roundabout,
created on Friday, 14 February 2025, 19:49:02 (1739562542),
received on Friday, 14 February 2025, 19:49:04 (1739562544)
Author identity: vlad <vlad.muntoiu@gmail.com>
77dfe671cfb18a5d8afb0c505ec7a5c7634382ec
static/picture-annotation.py
@@ -42,6 +42,8 @@ def make_shape_container():
shape = document.createElementNS("http://www.w3.org/2000/svg", "svg")
shape.setAttribute("width", "100%")
shape.setAttribute("height", "100%")
shape.setAttribute("viewBox", "0 0 1 1")
shape.setAttribute("preserveAspectRatio", "none")
shape.classList.add("shape-container")
return shape
@@ -79,10 +81,10 @@ def list_shapes():
if shape.tagName == "rect":
shape_dict["type"] = "bbox"
shape_dict["shape"] = {
"x": float(shape.getAttribute("x")) / image.naturalWidth,
"y": float(shape.getAttribute("y")) / image.naturalHeight,
"w": float(shape.getAttribute("width")) / image.naturalWidth,
"h": float(shape.getAttribute("height")) / image.naturalHeight
"x": float(shape.getAttribute("x")[:-1]) / 100,
"y": float(shape.getAttribute("y")[:-1]) / 100,
"w": float(shape.getAttribute("width")[:-1]) / 100,
"h": float(shape.getAttribute("height")[:-1]) / 100
}
elif shape.tagName == "polygon" or shape.tagName == "polyline":
if shape.tagName == "polygon":
@@ -96,16 +98,16 @@ def list_shapes():
x, y = point.split(",")
x, y = float(x), float(y)
json_points.append({
"x": x / image.naturalWidth,
"y": y / image.naturalHeight
"x": x,
"y": y
})
shape_dict["shape"] = json_points
elif shape.tagName == "circle" and shape.classList.contains("shape-point"):
shape_dict["type"] = "point"
shape_dict["shape"] = {
"x": float(shape.getAttribute("cx")) / image.naturalWidth,
"y": float(shape.getAttribute("cy")) / image.naturalHeight
"x": float(shape.getAttribute("cx")),
"y": float(shape.getAttribute("cy"))
}
else:
continue
@@ -123,10 +125,10 @@ def put_shapes(json_shapes):
if shape["type"] == "bbox":
rectangle = document.createElementNS("http://www.w3.org/2000/svg", "rect")
rectangle.setAttribute("x", str(shape["shape"]["x"] * image.naturalWidth))
rectangle.setAttribute("y", str(shape["shape"]["y"] * image.naturalHeight))
rectangle.setAttribute("width", str(shape["shape"]["w"] * image.naturalWidth))
rectangle.setAttribute("height", str(shape["shape"]["h"] * image.naturalHeight))
rectangle.setAttribute("x", str(shape["shape"]["x"]))
rectangle.setAttribute("y", str(shape["shape"]["y"]))
rectangle.setAttribute("width", str(shape["shape"]["w"]))
rectangle.setAttribute("height", str(shape["shape"]["h"]))
rectangle.setAttribute("fill", "none")
rectangle.setAttribute("data-object-type", shape["object"] or "")
rectangle.classList.add("shape-bbox")
@@ -135,7 +137,7 @@ def put_shapes(json_shapes):
elif shape["type"] == "polygon" or shape["type"] == "polyline":
polygon = document.createElementNS("http://www.w3.org/2000/svg", shape["type"])
points = " ".join(
[f"{point['x'] * image.naturalWidth},{point['y'] * image.naturalHeight}" for point in shape["shape"]])
[f"{point['x']},{point['y']}" for point in shape["shape"]])
polygon.setAttribute("points", points)
polygon.setAttribute("fill", "none")
polygon.setAttribute("data-object-type", shape["object"] or "")
@@ -144,8 +146,8 @@ def put_shapes(json_shapes):
new_shape.appendChild(polygon)
elif shape["type"] == "point":
point = document.createElementNS("http://www.w3.org/2000/svg", "circle")
point.setAttribute("cx", str(shape["shape"]["x"] * image.naturalWidth))
point.setAttribute("cy", str(shape["shape"]["y"] * image.naturalHeight))
point.setAttribute("cx", str(shape["shape"]["x"]))
point.setAttribute("cy", str(shape["shape"]["y"]))
point.setAttribute("r", "0")
point.classList.add("shape-point")
point.classList.add("shape")
@@ -278,24 +280,24 @@ async def focus_shape(shape):
object_list.style.display = "flex"
object_list_filter.focus()
object_list_filter.addEventListener("input", update_object_list_filter)
object_list.style.left = str(get_centre(shape)[0] / image.naturalWidth * 100) + "%"
object_list.style.top = str(get_centre(shape)[1] / image.naturalHeight * 100) + "%"
object_list.style.left = str(get_centre(shape)[0] * 100) + "%"
object_list.style.top = str(get_centre(shape)[1] * 100) + "%"
object_list.style.right = "auto"
object_list.style.bottom = "auto"
object_list.style.maxHeight = str(image.height - get_centre(shape)[1] / image.naturalHeight * image.height) + "px"
object_list.style.maxWidth = str(image.width - get_centre(shape)[0] / image.naturalWidth * image.width) + "px"
object_list.style.maxHeight = str(image.height * (1 - get_centre(shape)[1])) + "px"
object_list.style.maxWidth = str(image.width * (1 - get_centre(shape)[0])) + "px"
transform_origin = ["top", "left"]
if get_centre(shape)[0] / image.naturalWidth * image.width + object_list.offsetWidth > image.width:
if get_centre(shape)[0] * image.width + object_list.offsetWidth > image.width:
object_list.style.left = "auto"
object_list.style.right = str((image.naturalWidth - get_centre(shape)[0]) / image.naturalWidth * 100) + "%"
object_list.style.maxWidth = str(get_centre(shape)[0] / image.naturalWidth * image.width) + "px"
object_list.style.right = str((image.width - get_centre(shape)[0]) * 100) + "%"
object_list.style.maxWidth = str(get_centre(shape)[0] * image.width) + "px"
transform_origin[1] = "right"
if get_centre(shape)[1] / image.naturalHeight * image.height + object_list.offsetHeight > image.height:
if get_centre(shape)[1] / image.height * image.height + object_list.offsetHeight > image.height:
object_list.style.top = "auto"
object_list.style.bottom = str((image.naturalHeight - get_centre(shape)[1]) / image.naturalHeight * 100) + "%"
object_list.style.maxHeight = str(get_centre(shape)[1] / image.naturalHeight * image.height) + "px"
object_list.style.bottom = str((image.height - get_centre(shape)[1]) * 100) + "%"
object_list.style.maxHeight = str(get_centre(shape)[1] * image.height) + "px"
transform_origin[0] = "bottom"
object_list.style.transformOrigin = " ".join(transform_origin)
@@ -527,10 +529,10 @@ def make_bbox(event):
maxx = max(x0, x1)
maxy = max(y0, y1)
rectangle.setAttribute("x", str(minx * image.naturalWidth))
rectangle.setAttribute("y", str(miny * image.naturalHeight))
rectangle.setAttribute("width", str((maxx - minx) * image.naturalWidth))
rectangle.setAttribute("height", str((maxy - miny) * image.naturalHeight))
rectangle.setAttribute("x", str(minx))
rectangle.setAttribute("y", str(miny))
rectangle.setAttribute("width", str(maxx - minx))
rectangle.setAttribute("height", str(maxy - miny))
rectangle.setAttribute("fill", "none")
rectangle.setAttribute("data-object-type", "")
rectangle.classList.add("shape-bbox")
@@ -557,7 +559,7 @@ def make_polygon(event):
# Update the polygon
polygon.setAttribute("points", " ".join(
[f"{point[0] * image.naturalWidth},{point[1] * image.naturalHeight}" for point in
[f"{point[0]},{point[1]}" for point in
polygon_points]))
@@ -605,7 +607,7 @@ def backspace_polygon(event):
polygon_points.pop()
polygon = new_shape.children[0]
polygon.setAttribute("points", " ".join(
[f"{point[0] * image.naturalWidth},{point[1] * image.naturalHeight}" for point in
[f"{point[0] * 100}%,{point[1] * 100}%" for point in
polygon_points]))
@@ -672,8 +674,8 @@ def open_shape(event):
elif shape_type == "shape-point":
point = document.createElementNS("http://www.w3.org/2000/svg", "circle")
zone_rect = zone.getBoundingClientRect()
point.setAttribute("cx", str((event.clientX - zone_rect.left) / zone_rect.width * image.naturalWidth))
point.setAttribute("cy", str((event.clientY - zone_rect.top) / zone_rect.height * image.naturalHeight))
point.setAttribute("cx", str((event.clientX - zone_rect.left) / zone_rect.width))
point.setAttribute("cy", str((event.clientY - zone_rect.top) / zone_rect.height))
point.setAttribute("r", "0")
point.classList.add("shape-point")
point.classList.add("shape")
@@ -721,9 +723,6 @@ def update_transform():
svg.style.transformOrigin = "0 0"
svg.setAttribute("width", f"{100 * scale}%")
svg.setAttribute("height", f"{100 * scale}%")
for shape in svg.children:
shape.setAttribute("transform", f"scale({scale})")
shape.setAttribute("transform-origin", "0 0")
zoom_indicator.innerText = f"{scale:.3f}x"
static/style.css
@@ -140,7 +140,8 @@ iconify-icon {
stroke-width: 2px;
--shape-radius: 2px;
fill-opacity: 1;
r: 2;
r: 0.001;
vector-effect: non-scaling-stroke non-scaling-size;
transition: r 0.25s cubic-bezier(0.34, 1.56, 0.64, 1),
stroke-width 0.25s cubic-bezier(0.34, 1.56, 0.64, 1),
filter 0.25s cubic-bezier(0.61, 1, 0.88, 1);
@@ -155,8 +156,8 @@ iconify-icon {
.shape-point.selected {
fill-opacity: 1;
r: 6;
--shape-radius: 6px;
r: 0.001;
--shape-radius: 0.001;
stroke-width: 6px;
}
templates/gallery.html
@@ -1,10 +1,10 @@
{% extends "default.html" %}
{% import "small-annotation-display.html" as annotation_display %}
{% block nav_title %}{{ gallery.title }}{% endblock %}
{% block title %}Gallery {{ gallery.title }} | {{ site_name }}{% endblock %}
{% block content %}
<div id="picture-view">
<x-frame id="picture-actions">
<ul class="action-list">
@@ -51,33 +51,7 @@
{% for picture in gallery.pictures %}
<li>
<a href="/picture/{{ picture.resource.id }}">
<div class="annotation-zone">
<img src="/raw/picture/{{ picture.resource.id }}" alt="{{ picture.resource.title }}">
{% for region in picture.resource.regions %}
{% if region.json.type == "bbox" %}
<svg class="shape-container" viewBox="0 0 {{ picture.resource.width }} {{ picture.resource.height }}">
<rect x="{{ region.json.shape.x * picture.resource.width }}"
y="{{ region.json.shape.y * picture.resource.height }}"
width="{{ region.json.shape.w * picture.resource.width }}"
height="{{ region.json.shape.h * picture.resource.height }}"
fill="none" class="shape-bbox shape"
></rect>
</svg>
{% elif region.json.type == "polygon" %}
<svg class="shape-container" viewBox="0 0 {{ picture.resource.width }} {{ picture.resource.height }}">
<polygon points="{% for point in region.json.shape %}{{ point.x * picture.resource.width }},{{ point.y * picture.resource.height }} {% endfor %}" fill="none" class="shape-polygon shape"></polygon>
</svg>
{% elif region.json.type == "polyline" %}
<svg class="shape-container" viewBox="0 0 {{ picture.resource.width }} {{ picture.resource.height }}">
<polyline points="{% for point in region.json.shape %}{{ point.x * picture.resource.width }},{{ point.y * picture.resource.height }} {% endfor %}" fill="none" class="shape-polyline shape"></polyline>
</svg>
{% elif region.json.type == "point" %}
<svg class="shape-container" viewBox="0 0 {{ picture.resource.width }} {{ picture.resource.height }}">
<circle cx="{{ region.json.shape.x * picture.resource.width }}" cy="{{ region.json.shape.y * picture.resource.height }}" r="0" fill="none" class="shape-point shape"></circle>
</svg>
{% endif %}
{% endfor %}
</div>
{{ annotation_display.annotation_display(picture.resource) }}
<div class="list-detail">
{{ picture.resource.title }}
</div>
templates/graphical-query-pictures-results.html
@@ -1,4 +1,5 @@
{% extends "default.html" %}
{% import "small-annotation-display.html" as annotation_display %}
{% block nav_title %}Query results{% endblock %}
{% block title %}Picture query results | {{ site_name }}{% endblock %}
@@ -17,33 +18,7 @@
{% for resource in resources %}
<li>
<a href="/picture/{{ resource.id }}">
<div class="annotation-zone">
<img src="/raw/picture/{{ resource.id }}" alt="{{ resource.title }}">
{% for region in resource.regions %}
{% if region.json.type == "bbox" %}
<svg class="shape-container" viewBox="0 0 {{ resource.width }} {{ resource.height }}">
<rect x="{{ region.json.shape.x * resource.width }}"
y="{{ region.json.shape.y * resource.height }}"
width="{{ region.json.shape.w * resource.width }}"
height="{{ region.json.shape.h * resource.height }}"
fill="none" class="shape-bbox shape"
></rect>
</svg>
{% elif region.json.type == "polygon" %}
<svg class="shape-container" viewBox="0 0 {{ resource.width }} {{ resource.height }}">
<polygon points="{% for point in region.json.shape %}{{ point.x * resource.width }},{{ point.y * resource.height }} {% endfor %}" fill="none" class="shape-polygon shape"></polygon>
</svg>
{% elif region.json.type == "polyline" %}
<svg class="shape-container" viewBox="0 0 {{ resource.width }} {{ resource.height }}">
<polyline points="{% for point in region.json.shape %}{{ point.x * resource.width }},{{ point.y * resource.height }} {% endfor %}" fill="none" class="shape-polyline shape"></polyline>
</svg>
{% elif region.json.type == "point" %}
<svg class="shape-container" viewBox="0 0 {{ resource.width }} {{ resource.height }}">
<circle cx="{{ region.json.shape.x * resource.width }}" cy="{{ region.json.shape.y * resource.height }}" r="0" fill="none" class="shape-point shape"></circle>
</svg>
{% endif %}
{% endfor %}
</div>
{{ annotation_display.annotation_display(resource) }}
<div class="list-detail">
{{ resource.title }}
</div>
templates/home.html
@@ -1,4 +1,5 @@
{% extends "default.html" %}
{% import "small-annotation-display.html" as annotation_display %}
{% block nav_title %}Home{% endblock %}
{% block title %}Home | {{ site_name }}{% endblock %}
@@ -19,33 +20,7 @@
{% for resource in resources %}
<li>
<a href="/picture/{{ resource.id }}">
<div class="annotation-zone">
<img src="/raw/picture/{{ resource.id }}" alt="{{ resource.title }}">
{% for region in resource.regions %}
{% if region.json.type == "bbox" %}
<svg class="shape-container" viewBox="0 0 {{ resource.width }} {{ resource.height }}">
<rect x="{{ region.json.shape.x * resource.width }}"
y="{{ region.json.shape.y * resource.height }}"
width="{{ region.json.shape.w * resource.width }}"
height="{{ region.json.shape.h * resource.height }}"
fill="none" class="shape-bbox shape"
></rect>
</svg>
{% elif region.json.type == "polygon" %}
<svg class="shape-container" viewBox="0 0 {{ resource.width }} {{ resource.height }}">
<polygon points="{% for point in region.json.shape %}{{ point.x * resource.width }},{{ point.y * resource.height }} {% endfor %}" fill="none" class="shape-polygon shape"></polygon>
</svg>
{% elif region.json.type == "polyline" %}
<svg class="shape-container" viewBox="0 0 {{ resource.width }} {{ resource.height }}">
<polyline points="{% for point in region.json.shape %}{{ point.x * resource.width }},{{ point.y * resource.height }} {% endfor %}" fill="none" class="shape-polyline shape"></polyline>
</svg>
{% elif region.json.type == "point" %}
<svg class="shape-container" viewBox="0 0 {{ resource.width }} {{ resource.height }}">
<circle cx="{{ region.json.shape.x * resource.width }}" cy="{{ region.json.shape.y * resource.height }}" r="0" fill="none" class="shape-point shape"></circle>
</svg>
{% endif %}
{% endfor %}
</div>
{{ annotation_display.annotation_display(resource) }}
<div class="list-detail">
{{ resource.title }}
</div>
templates/object.html
@@ -1,4 +1,5 @@
{% extends "default.html" %}
{% import "small-annotation-display.html" as annotation_display %}
{% block nav_title %}{{ object.id }}{% endblock %}
{% block title %}Object {{ object.id }} | {{ site_name }}{% endblock %}
@@ -34,33 +35,7 @@
{% for resource in resources %}
<li>
<a href="/picture/{{ resource.id }}">
<div class="annotation-zone">
<img src="/raw/picture/{{ resource.id }}" alt="{{ resource.title }}">
{% for i in PictureRegion.query.filter_by(resource=resource, object=object) %}
{% if i.json.type == "bbox" %}
<svg class="shape-container" viewBox="0 0 {{ resource.width }} {{ resource.height }}">
<rect x="{{ i.json.shape.x * resource.width }}"
y="{{ i.json.shape.y * resource.height }}"
width="{{ i.json.shape.w * resource.width }}"
height="{{ i.json.shape.h * resource.height }}"
fill="none" class="shape-bbox shape"
></rect>
</svg>
{% elif i.json.type == "polygon" %}
<svg class="shape-container" viewBox="0 0 {{ resource.width }} {{ resource.height }}">
<polygon points="{% for point in i.json.shape %}{{ point.x * resource.width }},{{ point.y * resource.height }} {% endfor %}" fill="none" class="shape-polygon shape"></polygon>
</svg>
{% elif i.json.type == "polyline" %}
<svg class="shape-container" viewBox="0 0 {{ resource.width }} {{ resource.height }}">
<polyline points="{% for point in i.json.shape %}{{ point.x * resource.width }},{{ point.y * resource.height }} {% endfor %}" fill="none" class="shape-polyline shape"></polyline>
</svg>
{% elif i.json.type == "point" %}
<svg class="shape-container" viewBox="0 0 {{ resource.width }} {{ resource.height }}">
<circle cx="{{ i.json.shape.x * resource.width }}" cy="{{ i.json.shape.y * resource.height }}" r="0" fill="none" class="shape-point shape"></circle>
</svg>
{% endif %}
{% endfor %}
</div>
{{ annotation_display.annotation_display(resource) }}
<div class="list-detail">
{{ resource.title }}
</div>
templates/picture.html
@@ -1,4 +1,5 @@
{% extends "default.html" %}
{% import "small-annotation-display.html" as annotation_display %}
{% block nav_title %}{{ resource.title }}{% endblock %}
{% block title %}Picture {{ resource.title }} | {{ site_name }}{% endblock %}
@@ -87,19 +88,19 @@
<img id="annotation-image" src="/raw/picture/{{ resource.id }}" alt="{{ resource.title }}">
{% for region in resource.regions %}
{% if region.json.type == "bbox" %}
<svg class="shape-container-viewonly" viewBox="0 0 {{ size[0] }} {{ size[1] }}">
<rect x="{{ region.json.shape.x * size[0] }}"
y="{{ region.json.shape.y * size[1] }}"
width="{{ region.json.shape.w * size[0] }}"
height="{{ region.json.shape.h * size[1] }}"
<svg class="shape-container-viewonly" viewBox="0 0 1 1" preserveAspectRatio="none">
<rect x="{{ region.json.shape.x }}"
y="{{ region.json.shape.y }}"
width="{{ region.json.shape.w }}"
height="{{ region.json.shape.h }}"
fill="none" class="shape-bbox shape"
></rect>
{% set centre_x = region.json.shape.x + region.json.shape.w / 2 %}
{% set centre_y = region.json.shape.y + region.json.shape.h / 2 %}
</svg>
{% elif region.json.type == "polygon" %}
<svg class="shape-container-viewonly" viewBox="0 0 {{ size[0] }} {{ size[1] }}">
<polygon points="{% for point in region.json.shape %}{{ point.x * size[0] }},{{ point.y * size[1] }} {% endfor %}" fill="none" class="shape-polygon shape"></polygon>
<svg class="shape-container-viewonly" viewBox="0 0 1 1" preserveAspectRatio="none">
<polygon points="{% for point in region.json.shape %}{{ point.x }},{{ point.y }} {% endfor %}" fill="none" class="shape-polygon shape"></polygon>
{% set top = region.json.shape | sort(attribute='y') | last %}
{% set left = region.json.shape | sort(attribute='x') | first %}
{% set bottom = region.json.shape | sort(attribute='y') | first %}
@@ -108,15 +109,17 @@
{% set centre_y = (top.y + bottom.y) / 2 %}
</svg>
{% elif region.json.type == "polyline" %}
<svg class="shape-container-viewonly" viewBox="0 0 {{ size[0] }} {{ size[1] }}">
<polyline points="{% for point in region.json.shape %}{{ point.x * size[0] }},{{ point.y * size[1] }} {% endfor %}" fill="none" class="shape-polyline shape"></polyline>
<svg class="shape-container-viewonly" viewBox="0 0 1 1" preserveAspectRatio="none">
<polyline points="{% for point in region.json.shape %}{{ point.x }},{{ point.y }} {% endfor %}" fill="none" class="shape-polyline shape"></polyline>
{# Median point #}
{% set centre_x = region.json.shape | map(attribute="x") | median %}
{% set centre_y = region.json.shape | map(attribute="y") | median %}
</svg>
{% elif region.json.type == "point" %}
<svg class="shape-container-viewonly" viewBox="0 0 {{ size[0] }} {{ size[1] }}">
<circle cx="{{ region.json.shape.x * size[0] }}" cy="{{ region.json.shape.y * size[1] }}" r="0" fill="none" class="shape-point shape"></circle>
<svg class="shape-container-viewonly" viewBox="0 0 1 1" preserveAspectRatio="none">
<circle cx="{{ region.json.shape.x }}" cy="{{ region.json.shape.y }}" r="0" fill="none" class="shape-point shape"></circle>
{% set centre_x = region.json.shape.x %}
{% set centre_y = region.json.shape.y %}
</svg>
{% endif %}
{{ shape_label(centre_x, centre_y, region.object_id) }}
@@ -261,34 +264,7 @@
{% for copy in resource.copies %}
<li>
<a href="/picture/{{ copy.id }}">
<div class="annotation-zone">
<img src="/raw/picture/{{ copy.id }}" alt="{{ copy.title }}">
{% for region in copy.regions %}
{% if region.json.type == "bbox" %}
<svg class="shape-container" viewBox="0 0 {{ copy.width }} {{ copy.height }}">
<rect x="{{ region.json.shape.x * copy.width }}"
y="{{ region.json.shape.y * copy.height }}"
width="{{ region.json.shape.w * copy.width }}"
height="{{ region.json.shape.h * copy.height }}"
fill="none" class="shape-bbox shape"
></rect>
</svg>
{% elif region.json.type == "polygon" %}
<svg class="shape-container" viewBox="0 0 {{ copy.width }} {{ copy.height }}">
<polygon points="{% for point in region.json.shape %}{{ point.x * copy.width }},{{ point.y * copy.height }} {% endfor %}" fill="none" class="shape-polygon shape"></polygon>
</svg>
{% elif region.json.type == "polyline" %}
<svg class="shape-container" viewBox="0 0 {{ copy.width }} {{ copy.height }}">
<polyline points="{% for point in region.json.shape %}{{ point.x * copy.width }},{{ point.y * copy.height }} {% endfor %}" fill="none" class="shape-polyline shape"></polyline>
</svg>
{% elif region.json.type == "point" %}
<svg class="shape-container" viewBox="0 0 {{ copy.width }} {{ copy.height }}">
<circle cx="{{ region.json.shape.x * copy.width }}" cy="{{ region.json.shape.y * copy.height }}" r="0" fill="none" class="shape-point shape"></circle>
</svg>
{% endif %}
{% endfor %}
</div>
{{ annotation_display.annotation_display(copy) }}
<div class="list-detail">
{{ copy.title }}
</div>
templates/profile.html
@@ -1,4 +1,5 @@
{% extends "default.html" %}
{% import "small-annotation-display.html" as annotation_display %}
{% block nav_title %}{{ user.formatted_name }}{% endblock %}
{% block title %}{{ user.formatted_name }}'s profile | {{ site_name }}{% endblock %}
@@ -12,33 +13,7 @@
{% for resource in user.pictures %}
<li>
<a href="/picture/{{ resource.id }}">
<div class="annotation-zone">
<img src="/raw/picture/{{ resource.id }}" alt="{{ resource.title }}">
{% for region in resource.regions %}
{% if region.json.type == "bbox" %}
<svg class="shape-container" viewBox="0 0 {{ resource.width }} {{ resource.height }}">
<rect x="{{ region.json.shape.x * resource.width }}"
y="{{ region.json.shape.y * resource.height }}"
width="{{ region.json.shape.w * resource.width }}"
height="{{ region.json.shape.h * resource.height }}"
fill="none" class="shape-bbox shape"
></rect>
</svg>
{% elif region.json.type == "polygon" %}
<svg class="shape-container" viewBox="0 0 {{ resource.width }} {{ resource.height }}">
<polygon points="{% for point in region.json.shape %}{{ point.x * resource.width }},{{ point.y * resource.height }} {% endfor %}" fill="none" class="shape-polygon shape"></polygon>
</svg>
{% elif region.json.type == "polyline" %}
<svg class="shape-container" viewBox="0 0 {{ resource.width }} {{ resource.height }}">
<polyline points="{% for point in region.json.shape %}{{ point.x * resource.width }},{{ point.y * resource.height }} {% endfor %}" fill="none" class="shape-polyline shape"></polyline>
</svg>
{% elif region.json.type == "point" %}
<svg class="shape-container" viewBox="0 0 {{ resource.width }} {{ resource.height }}">
<circle cx="{{ region.json.shape.x * resource.width }}" cy="{{ region.json.shape.y * resource.height }}" r="0" fill="none" class="shape-point shape"></circle>
</svg>
{% endif %}
{% endfor %}
</div>
{{ annotation_display.annotation_display(resource) }}
<div class="list-detail">
{{ resource.title }}
</div>
templates/small-annotation-display.html
@@ -0,0 +1,29 @@
{% macro annotation_display(resource) %}
<div class="annotation-zone">
<img src="/raw/picture/{{ resource.id }}" alt="{{ resource.title }}">
{% for region in resource.regions %}
{% if region.json.type == "bbox" %}
<svg class="shape-container" viewBox="0 0 1 1" preserveAspectRatio="none">
<rect x="{{ region.json.shape.x }}"
y="{{ region.json.shape.y }}"
width="{{ region.json.shape.w }}"
height="{{ region.json.shape.h }}"
fill="none" class="shape-bbox shape"
></rect>
</svg>
{% elif region.json.type == "polygon" %}
<svg class="shape-container" viewBox="0 0 1 1" preserveAspectRatio="none">
<polygon points="{% for point in region.json.shape %}{{ point.x }},{{ point.y }} {% endfor %}" fill="none" class="shape-polygon shape"></polygon>
</svg>
{% elif region.json.type == "polyline" %}
<svg class="shape-container" viewBox="0 0 1 1" preserveAspectRatio="none">
<polyline points="{% for point in region.json.shape %}{{ point.x }},{{ point.y }} {% endfor %}" fill="none" class="shape-polyline shape"></polyline>
</svg>
{% elif region.json.type == "point" %}
<svg class="shape-container" viewBox="0 0 1 1" preserveAspectRatio="none">
<circle cx="{{ region.json.shape.x }}" cy="{{ region.json.shape.y }}" r="0" fill="none" class="shape-point shape"></circle>
</svg>
{% endif %}
{% endfor %}
</div>
{% endmacro %}