diff --git a/dist/examples/annotation-editor/index.html b/dist/examples/annotation-editor/index.html index 1be38ac3..7f891fcb 100644 --- a/dist/examples/annotation-editor/index.html +++ b/dist/examples/annotation-editor/index.html @@ -143,7 +143,7 @@

OpenLIME - Annotation Editor

} // Create an annotation layer and add it to the canvans - const anno = new OpenLIME.Layer(aOptions); + const anno = new OpenLIME.LayerAnnotation(aOptions); lime.addLayer('anno', anno); // If editorEnable, create a SVG annotation Editor diff --git a/src/BoundingBox.js b/src/BoundingBox.js index f745c819..b6fea2b2 100644 --- a/src/BoundingBox.js +++ b/src/BoundingBox.js @@ -139,7 +139,7 @@ class BoundingBox { * @returns {number} The center value. */ center() { - return [(this.xLow+this.xHigh)/2, (this.yLow+this.yHigh)/2]; + return { x: (this.xLow+this.xHigh)/2, y: (this.yLow+this.yHigh)/2 }; } /** diff --git a/src/Camera.js b/src/Camera.js index e60e4526..770f050c 100644 --- a/src/Camera.js +++ b/src/Camera.js @@ -290,7 +290,7 @@ class Camera { let c = box.center(); let z = Math.min(w / bw, h / bh); - this.setPosition(dt, -c[0], -c[1], z, 0); + this.setPosition(dt, -c.x, -c.y, z, 0); } /** diff --git a/src/EditorSvgAnnotation.js b/src/EditorSvgAnnotation.js index b2862dbb..2fdd904b 100644 --- a/src/EditorSvgAnnotation.js +++ b/src/EditorSvgAnnotation.js @@ -144,8 +144,11 @@ class EditorSvgAnnotation { updateCallback: null, deleteCallback: null }, options); - - layer.style += Object.entries(this.classes).map((g) => `[data-class=${g[0]}] { stroke:${g[1].style.stroke}; }`).join('\n'); + + layer.style += Object.entries(this.classes).map((g) => { + console.assert(g[1].hasOwnProperty('stroke'), "Classes needs a stroke property"); + return `[data-class=${g[0]}] { stroke:${g[1].stroke}; }`; + }).join('\n'); //at the moment is not really possible to unregister the events registered here. viewer.pointerManager.onEvent(this); document.addEventListener('keyup', (e) => this.keyUp(e), false); @@ -240,7 +243,7 @@ class EditorSvgAnnotation { edit.classList.remove('hidden'); let button = edit.querySelector('.openlime-select-button'); button.textContent = this.classes[anno.class].label; - button.style.background = this.classes[anno.class].style.stroke; + button.style.background = this.classes[anno.class].stroke; } /** @ignore */ @@ -279,7 +282,7 @@ class EditorSvgAnnotation {

@@ -324,7 +327,7 @@ class EditorSvgAnnotation { input.value = e.srcElement.getAttribute('data-class'); input.dispatchEvent(new Event('change')); - button.style.background = this.classes[input.value].style.stroke; + button.style.background = this.classes[input.value].stroke; button.textContent = e.srcElement.textContent; select.classList.toggle('active'); @@ -419,7 +422,7 @@ class EditorSvgAnnotation { anno.class = select.value || ''; let button = edit.querySelector('.openlime-select-button'); - button.style.background = this.classes[anno.class].style.stroke; + button.style.background = this.classes[anno.class].stroke; for (let e of this.annotation.elements) e.setAttribute('data-class', anno.class); @@ -759,11 +762,13 @@ class EditorSvgAnnotation { const p = {x:e.offsetX, y: e.offsetY}; const layerT = this.layer.transform; const useGL = false; - console.log(layerT); const layerbb = this.layer.boundingBox(); const layerSize = {w:layerbb.width(), h:layerbb.height()}; + //compute also size of an image pixel on screen and store in pixelSize. let pos = CoordinateSystem.fromCanvasHtmlToImage(p, this.viewer.camera, layerT, layerSize, useGL); - + p.x += 1; + let pos1 = CoordinateSystem.fromCanvasHtmlToImage(p, this.viewer.camera, layerT, layerSize, useGL); + pos.pixelSize = Math.abs(pos1.x - pos.x); return pos; } } @@ -886,7 +891,7 @@ class Line { for (let e of this.annotation.elements) { if (!e.points || e.points.length < 2) continue; - if (Line.distance(e.points[0], pos) * pos.z < 5) { + if (Line.distance(e.points[0], pos) / pos.pixelSize < 5) { e.points.reverse(); this.path = e; this.path.setAttribute('d', Line.svgPath(e.points)); @@ -956,7 +961,7 @@ class Line { adjust(pos) { let gap = Line.distanceToLast(this.path.points, pos); - if (gap * pos.z < 4) return false; + if (gap / pos.pixelSize < 4) return false; this.path.points.push(pos); @@ -984,7 +989,7 @@ class Line { static svgPath(points) { //return points.map((p, i) => `${(i == 0? "M" : "L")}${p.x} ${p.y}`).join(' '); - let tolerance = 1.5 / points[0].z; + let tolerance = 1.5 * points[0].pixelSize; let tmp = simplify(points, tolerance); let smoothed = smooth(tmp, 90, true); diff --git a/src/Layer.js b/src/Layer.js index ccfec3df..f4d892e2 100644 --- a/src/Layer.js +++ b/src/Layer.js @@ -207,7 +207,8 @@ class Layer { // Set signal to acknowledge change of bbox when it is known. Let this signal go up to canvas this.layout.addEvent('updateSize', () => { - this.shader.setTileSize(this.layout.getTileSize()); + if(this.shader) + this.shader.setTileSize(this.layout.getTileSize()); this.emit('updateSize'); }); } diff --git a/src/LayerAnnotation.js b/src/LayerAnnotation.js index 234b6b6f..2768f350 100644 --- a/src/LayerAnnotation.js +++ b/src/LayerAnnotation.js @@ -62,6 +62,7 @@ class LayerAnnotation extends Layer { //FIXME CustomData Object template {name: this.createAnnotationsList(); this.emit('update'); + this.status = 'ready'; this.emit('ready'); this.emit('loaded'); } diff --git a/src/LayerSvgAnnotation.js b/src/LayerSvgAnnotation.js index 3094177b..9baeab21 100644 --- a/src/LayerSvgAnnotation.js +++ b/src/LayerSvgAnnotation.js @@ -39,13 +39,13 @@ class LayerSvgAnnotation extends LayerAnnotation { svgGroup: null, onClick: null, //callback function classes: { - '': { style: { stroke: '#000' }, label: '' }, + '': { stroke: '#000', label: '' }, }, annotationUpdate: null }, options); super(options); for(const [key, value] of Object.entries(this.classes)) { - this.style += `[data-class=${key}] { ` + Object.entries(value.style).map( g => `${g[0]}: ${g[1]};`).join('\n') + '}'; + this.style += `[data-class=${key}] { ` + Object.entries(value).map( g => `${g[0]}: ${g[1]};`).join('\n') + '}'; } //this.createOverlaySVGElement(); //this.setLayout(this.layout); @@ -160,7 +160,7 @@ class LayerSvgAnnotation extends LayerAnnotation { if (typeof (this.annotations) == "string") return; //FIXME Is it right? Should we use this.status? const bBox = this.boundingBox(); - this.svgElement.setAttribute('viewBox', `${bBox.xLow} ${bBox.yLow} ${bBox.xHigh - bBox.xLow} ${bBox.yHigh - bBox.yLow}`); + //this.svgElement.setAttribute('viewBox', `${bBox.xLow} ${bBox.yLow} ${bBox.xHigh - bBox.xLow} ${bBox.yHigh - bBox.yLow}`); //find which annotations needs to be added to the ccanvas, some //indexing whould be used, for the moment we just iterate all of them. diff --git a/src/LayoutTiles.js b/src/LayoutTiles.js index 0b111602..9f1fbb07 100644 --- a/src/LayoutTiles.js +++ b/src/LayoutTiles.js @@ -291,7 +291,7 @@ class LayoutTiles extends Layout { } let c = box.center(); //sort tiles by distance to the center TODO: check it's correct! - tmp.sort(function (a, b) { return Math.abs(a.x - c[0]) + Math.abs(a.y - c[1]) - Math.abs(b.x - c[0]) - Math.abs(b.y - c[1]); }); + tmp.sort(function (a, b) { return Math.abs(a.x - c.x) + Math.abs(a.y - c.y) - Math.abs(b.x - c.x) - Math.abs(b.y - c.y); }); needed = needed.concat(tmp); } return needed; diff --git a/src/UIBasic.js b/src/UIBasic.js index e60f540a..6ea4c964 100644 --- a/src/UIBasic.js +++ b/src/UIBasic.js @@ -173,8 +173,12 @@ class UIBasic { }; if(modes.length > 1) layerEntry.list = modes; - if (layer.annotations) { + if (layer.annotations ) { + layerEntry.list = []; + //setTimeout(() => { layerEntry.list.push(layer.annotationsEntry()); + //this.updateMenu(); + //}, 1000); //TODO: this could be a convenience, creating an editor which can be //customized later using layer.editor. //if(layer.editable) diff --git a/src/index.js b/src/index.js index ee13d546..bf121a00 100644 --- a/src/index.js +++ b/src/index.js @@ -22,7 +22,7 @@ let lime = new Viewer('.openlime', { background: 'black', canvas: { preserveDraw //imageTest('google'); // image google deepzoom deepzoom1px zoomify iiif tarzoon itarzoom //flipTest(); //brdfTest(); -rtiTest('rbf'); +//rtiTest('rbf'); //tomeTest(); //testUIBasic(); @@ -32,7 +32,7 @@ rtiTest('rbf'); //testMedicalAnnotations(); -//testAnnotationEditor(); +testAnnotationEditor(); //testNeural(); @@ -64,18 +64,21 @@ function dstretchTest() { } function testAnnotationEditor() { + + + Skin.setUrl('skin/skin.svg'); let layer0 = new Layer({ label: 'Coin 10', layout: 'image', type:'rti', - url: 'assets/rti/hsh/info.json', + url: 'assets/rti/eloi/info.json', normals: false }); lime.canvas.addLayer('hsh', layer0); - + let layer1 = new LayerSvgAnnotation({ label: 'Annotations', - viewBox: "0 0 256 256", + layout: layer0.layout, style:` .openlime-annotation { pointer-events:all; opacity: 0.7; } .openlime-annotation:hover { cursor:pointer; opacity: 1.0; } @@ -94,26 +97,29 @@ function testAnnotationEditor() {

${annotation.description}

`; }, - annotations: 'assets/medical/PH1101-1.json', + annotations: 'assets/medical/test.json', editable: true, }); lime.canvas.addLayer('anno', layer1); //here the overlayelement created and attached to layer1 - Skin.setUrl('skin/skin.svg'); + + + let editor = new EditorSvgAnnotation(lime, layer1, { lime: lime, + classes: { + '': { stroke: '#000', label: '' }, + 'class1': { stroke: "#00FF00", label: "Vert" }, + 'class2': { stroke: '#707', label: '' }, + 'class3': { stroke: '#777', label: '' }, + 'class4': { stroke: '#070', label: '' }, + 'class5': { stroke: '#007', label: '' }, + 'class6': { stroke: '#077', label: '' }, + } + }); - let editor = new EditorSvgAnnotation(lime, layer1, { lime: lime }); - editor.classes = { - '': { color: '#000', label: '' }, - 'class1': { color: '#770', label: '' }, - 'class2': { color: '#707', label: '' }, - 'class3': { color: '#777', label: '' }, - 'class4': { color: '#070', label: '' }, - 'class5': { color: '#007', label: '' }, - 'class6': { color: '#077', label: '' }, - }; let ui = new UIBasic(lime); lime.camera.maxFixedZoom = 4; + ui.actions.help.display = true; ui.actions.help.html = "Help text could be here."; ui.actions.snapshot.display = true; @@ -123,7 +129,7 @@ function testAnnotationEditor() { editor.deleteCallback = (annotation) => { console.log("Deleted annotation: ", annotation); return true; }; editor.updateCallback = (annotation) => { console.log("Updated annotation: ", annotation); return true; }; - editor.multiple = true; + editor.multiple = true; } @@ -152,7 +158,6 @@ function testMedicalAnnotations() { infoTemplate: (annotation) => { return `

${annotation.class}

${annotation.description}

- `; }, annotations: 'assets/medical/PH1101-1.json', editable: true,