Mercurial > hg > digilib
changeset 1581:9b701efc0c14 measure-maps
measure plugin: work on info window
author | hertzhaft |
---|---|
date | Mon, 14 Nov 2016 01:37:20 +0100 |
parents | 97b7800578b8 |
children | |
files | webapp/src/main/webapp/jquery/jquery.digilib.measure.js |
diffstat | 1 files changed, 211 insertions(+), 200 deletions(-) [+] |
line wrap: on
line diff
--- a/webapp/src/main/webapp/jquery/jquery.digilib.measure.js Sun Nov 13 18:44:19 2016 +0100 +++ b/webapp/src/main/webapp/jquery/jquery.digilib.measure.js Mon Nov 14 01:37:20 2016 +0100 @@ -815,18 +815,80 @@ implementedShapes: ['Line', 'LineString', 'Proportion', 'Rect', 'Rectangle', 'Polygon', 'Circle', 'Intercolumnium', 'Oval', 'EllipseArc', 'Grid'], // all measuring shape types shapeInfo: { - Line: { name: 'line', display: 'length', }, - LineString: { name: 'linestring', display: 'length' }, - Proportion: { name: 'proportion', display: 'length' }, - Rectangle: { name: 'box', display: 'diagonal' }, - Rect: { name: 'rectangle', display: 'area' }, - Square: { name: 'square', display: 'length' }, - Polygon: { name: 'polygon', display: 'area' }, - Circle: { name: 'circle', display: 'radius' }, - Intercolumnium: { name: 'intercolumnium', display: 'distance' }, - Oval: { name: 'oval', display: 'distance' }, - EllipseArc: { name: 'ellipse', display: 'area' }, - Grid: { name: 'linegrid', display: 'spacing' } + Line: { name: 'line', labels: [ + { len1: 'length'}, + { angx: 'angle to x-axis'} + ]}, + LineString: { name: 'linestring', labels: [ + { len1: 'total length'}, + { seg: 'nr of segments'} + ]}, + Proportion: { name: 'proportion', labels: [ + { len1: 'first leg'}, + { len2: 'second leg'}, + { rat1: 'proportion'}, + { ang: 'contained angle'}, + { angx: 'angle to x-axis'} + ]}, + Rectangle: { name: 'box', labels: [ + { len1: 'side a'}, + { len2: 'side b'}, + { diag: 'diagonal'}, + { rat1: 'proportion'}, + { area: 'area'} + ]}, + Rect: { name: 'rectangle', labels: [ + { len1: 'side a'}, + { len2: 'side b'}, + { diag: 'diagonal'}, + { rat1: 'proportion'}, + { angx: 'angle to x-axis'}, + { area: 'area'} + ]}, + Square: { name: 'square', labels: [ + { len1: 'side'}, + { diag: 'diagonal'}, + { area: 'area'} + ]}, + Polygon: { name: 'polygon', labels: [ + { len1: 'circumference'}, + { area: 'area'} + ]}, + Circle: { name: 'circle', labels: [ + { rad1: 'radius'}, + { circ: 'circumference'}, + { area: 'area'} + ]}, + Intercolumnium: { name: 'intercolumnium', labels: [ + { len1: 'modulus'}, + { len2: 'interval'}, + { rat1: 'proportion'} + ]}, + Oval: { name: 'oval', labels: [ + { len1: 'long axis'}, + { len2: 'short axis'}, + { rad1: 'small radius'}, + { rad2: 'large radius'}, + { rat1: 'proportion'}, + { rat2: 'proportion of arcs'}, + { circ: 'circumference'}, + { area: 'area'}, + { angx: 'angle to x-axis'} + ]}, + EllipseArc: { name: 'ellipse', labels: [ + { len1: 'long axis'}, + { len2: 'short axis'}, + { rat1: 'proportion'}, + { dist: 'focus distance'}, + { circ: 'circumference'}, + { area: 'area'}, + { angx: 'angle to x-axis'} + ]}, + Grid: { name: 'linegrid', labels: [ + { len1: 'unit'}, + { area: 'area'}, + { angx: 'angle to x-axis'} + ]}, }, // currently selected shape type activeShapeType: 'Line', @@ -974,95 +1036,11 @@ _debug_shape('onRenderShape', shape); }; - // calculate the angle between three points (rectified) - var getRectifiedAngleY = function (data, shape, tip, v1) { - var coords = shape.geometry.coordinates; - var line = geom.line(coords[tip], coords[v1]); - var dist = fn.getDistance(data, - geom.position(coords[v1]), - geom.position(coords[v2]) - ); - return dist.rectified; - }; - - // calculate the angle between three points (rectified) - var getRectifiedAngle = function (data, shape, tip, v1, v2) { - var coords = shape.geometry.coordinates; - var line1 = geom.line(coords[tip], coords[v1]); - var line2 = geom.line(coords[tip], coords[v2]); - var dist = fn.getDistance(data, - geom.position(coords[v1]), - geom.position(coords[v2]) - ); - return dist.rectified; - }; - - // calculate the distance between two digilib coords (rectified) ### (needed?) - var getRectifiedDistance = function (data, shape, vtx1, vtx2) { - var coords = shape.geometry.coordinates; - var dist = fn.getDistance(data, - geom.position(coords[vtx1]), - geom.position(coords[vtx2]) - ); - return dist.rectified; - }; - - // convert a distance between 2 coordinates (indexed) into both units - // ### do we need this? - var convertDistance = function (data, shape, dist) { - return convertLength(data, getScreenDistance(data, shape, v1, v2)); - }; - - // calculate the distance between two vertices - var getScreenDistance = function (shape, v1, v2) { - var p = shape.properties.screenpos; - return p[v1].distance(p[v2]); - }; - - // calculate the angle of the line between two vertices - var getScreenAngle = function (shape, v1, v2) { - var p = shape.properties.screenpos; - return geom.line(p[v1], p[v2]).deg(); - }; - // get the vertex before the given one - var getPrecedingVertex = function(shape, vertex) { + var getPrecedingVertex = function(shape) { + var v = shape.properties.vtx; var props = shape.properties; - var vtx = vertex == null ? props.vtx : vertex; - return (vtx === 0) ? props.screenpos.length-1 : vtx-1; - }; - - // calculate the distance from one shape vertex to the one before it (in rectified digilib coords) - var getPrecedingVertexDistance = function(data, shape, v1) { - // [safely assume that the 'screenpos' and 'coords' arrays have equal length?] - if (v1 == null) { - v1 = shape.properties.vtx; - } - var v0 = getPrecedingVertex(shape, v1); - return getScreenDistance(shape, v0, v1); - }; - - // calculate the angle from one shape vertex to the one before it (in rectified digilib coords) - var getPrecedingVertexAngle = function(data, shape, v1) { - if (v1 == null) { - v1 = shape.properties.vtx; - } - var v0 = getPrecedingVertex(shape, v1); - return getScreenAngle(shape, v0, v1); - }; - - // calculate distance from current to preceding vertex (in rectified digilib coords) - var getRectifiedLength = function(data, shape) { - // var coords = shape.geometry.coordinates; - var total = 0; - if (shape.geometry.type === 'LineString') { // sum up distances - for (vtx = 1; vtx < shape.properties.screenpos.length; vtx++) { - total += getPrecedingVertexDistance(data, shape, vtx); - } - } else { - total = getPrecedingVertexDistance(data, shape); - } - return total; + return (v === 0) ? props.screenpos.length-1 : v-1; }; // are points ordered clockwise? @@ -1091,18 +1069,6 @@ return coords; }; - // calculate the area of a polygon (using digilib coords) - var getRectifiedArea = function(data, shape) { - var aspect = fn.getImgAspectRatio(data); - var coords = rectifyCoords(shape, aspect); - // formula for ellipse area - if (shape.geometry.type === 'Ellipse') { - return Math.abs((coords[0].x-coords[1].x) * (coords[0].y-coords[1].y) * Math.PI); - } - // algorithm for polygon area - return Math.abs(sumEdges(coords)/2); - }; - // recalculate factor after a new value was entered into input element "value1" var changeFactor = function(data) { var val = parseFloat(data.measureWidgets.value1.val()); @@ -1158,8 +1124,12 @@ // display info for shape var updateMeasuredValue = function(data, shape) { - data.lastMeasuredValue = getPrecedingVertexDistance(data, shape); - data.lastMeasuredAngle = getPrecedingVertexAngle(data, shape); + var props = shape.properties; + var screenpos = props.screenpos; + var thisPos = screenpos[props.vtx]; + var lastPos = screenpos[getPrecedingVertex(shape)]; + data.lastMeasuredValue = thisPos.distance(lastPos); + data.lastMeasuredAngle = thisPos.deg(lastPos); console.debug(shape, data.lastMeasuredValue, data.lastMeasuredAngle); updateUnits(data); }; @@ -1174,18 +1144,24 @@ var s = data.settings; var factor = data.measureFactor; var type = shape.geometry.type; - // var scaled = showArea(data, type) - // ? scaleArea(getRectifiedArea(data, shape), factor) - // : scaleValue(getRectifiedLength(data, shape), factor); - var scaled = scaleValue(getRectifiedLength(data, shape), factor); + var m = shape.properties.measures || {}; var name = s.shapeInfo[type].name; - var display = s.shapeInfo[type].display; - var l = convertLength(data, scaled); - var html = '<div class="head">'+name+'</div>' - +'<div><em>'+display+'</em>: ' - +fn.cropFloat(l[0], 2)+' '+l[2]+' = ' - +fn.cropFloat(l[1], 2)+' '+l[3] - +'</div>'; + var labels = s.shapeInfo[type].labels; + // var l = convertLength(data, scaled); + var htmlLine = function (item, i) { + var key = Object.keys(item)[0]; + var label = item[key]; + var value = m[key]; + return value + ? '<div><em>'+label+'</em>: ' + +fn.cropFloat(value, 2) + // +fn.cropFloat(l[0], 2)+' '+l[2]+' = ' + // +fn.cropFloat(l[1], 2)+' '+l[3] + +'</div>' + : ''; + }; + var lines = $.map(labels, htmlLine); + var html = '<div class="head">'+name+'</div>'+lines.join(''); return html; }; @@ -1237,10 +1213,10 @@ var vtx = props.vtx; if (screenpos == null || vtx == null) { return; } + var factor = data.measureFactor; + var thisPos = screenpos[vtx]; var lastPos = screenpos[getPrecedingVertex(shape)]; - // shape.geometry.coordinates[vtx] = data.imgTrafo.invtransform(thisPos); // ### needed? just work with screenpos? - var factor = data.measureFactor; - var screenDist = getPrecedingVertexDistance(data, shape); + var screenDist = thisPos.distance(lastPos); var unitDist = scaleValue(screenDist, factor); var roundDist = Math.round(unitDist); // round to the nearest integer if (roundDist === 0) { @@ -1331,18 +1307,18 @@ var $u2 = widgets.unit2; var section = data.settings.units.sections; var addOptions = function(i, item) { - var $opt = $('<option class="dl-section" disabled="disabled">'+ item.name +'</option>'); + var $opt = $('<option class="dl-section" disabled="disabled">'+ item.name +'</option>'); + $u1.append($opt); + $u2.append($opt.clone()); + var unit = item.units; + var addOption = function(i, item) { + var $opt = $('<option class="dl-units" value="'+ item.factor + '">'+ item.name + '</option>'); + $opt.data('unit', item); $u1.append($opt); $u2.append($opt.clone()); - var unit = item.units; - var addOption = function(i, item) { - var $opt = $('<option class="dl-units" value="'+ item.factor + '">'+ item.name + '</option>'); - $opt.data('unit', item); - $u1.append($opt); - $u2.append($opt.clone()); - }; - $.each(unit, addOption); }; + $.each(unit, addOption); + }; $.each(section, addOptions); $u1.children(':not(:disabled)')[data.settings.unitFrom].selected = true; $u2.children(':not(:disabled)')[data.settings.unitTo].selected = true; @@ -1386,7 +1362,7 @@ }; var createInfoDiv = function() { - var options = { id: CSS+'info', class: 'dl-keep '+CSS+'info' }; + var options = { id: CSS+'info', 'class': 'dl-keep '+CSS+'info' }; return $('<div>', options); }; @@ -1490,36 +1466,35 @@ console.error("No SVG factory found: jquery.digilib.vector not loaded?"); return; } - factory['Proportion'] = { + // algorithm for polygon area: Math.abs(sumEdges(coords)/2); + factory['Proportion'] = { setup: function (data, shape) { shape.properties.maxvtx = 3; }, svg: function (shape) { - var $s = factory['LineString'].svg(shape); - var p = shape.properties.screenpos; - var len1 = p[1].distance(p[0]); - var len2 = p[1].distance(p[2]); - var ang = null; - var angy = null; - props.measures = { - len1: len1, - len2: len2, - rat1: len1 / len2, - rat2: len2 / len1, - ang: ang, - angy: angy - }; + var props = shape.properties; + var $s = factory['LineString'].svg(shape); + var lplace = $s.place; + $s.place = function () { + lplace.call($s) + var p = props.screenpos; + if (p.length > 2) { // p[2] is the mouse pointer + var len1 = p[1].distance(p[0]); + var len2 = p[1].distance(p[2]); + var ang1 = p[1].deg(p[0]); + var ang2 = p[1].deg(p[2]); + var ang = Math.abs(ang1 - ang2); + props.measures = { + len1: len1, + len2: len2, + rat: len1 / len2, + inv: len2 / len1, + ang: ang, + angx: ang1 + }; + } + }; return $s; - }, - info: function (data, shape) { - return [ - { len1: 'leg a'}, - { len2: 'leg b'}, - { rat1: 'ratio a/b'}, - { rat2: 'ratio b/a'}, - { ang: 'contained angle'}, - { angy: 'angle y-axis - leg a'}, - ]; } }; factory['Intercolumnium'] = { @@ -1530,25 +1505,30 @@ var props = shape.properties; var guideClass = CSS+'guide'; var $s = factory['LineString'].svg(shape); - var place = $s.place; + shape.$interactor = $s; var $c1 = $(fn.svgElement('circle', {'id': shape.id + '-circ1', 'class': guideClass })); var $c2 = $(fn.svgElement('circle', {'id': shape.id + '-circ2', 'class': guideClass })); var $g = $(fn.svgElement('g', {'id': shape.id + '-intercolumnium'})); $g.append($s).append($c1).append($c2); $g.place = function () { - var p = props.screenpos; - var vtx = props.vtx; - place.call($s); // place the linestring - if (p.length > 2) { // p[2] is the mouse pointer - var m1 = p[1].mid(p[2]); - var line = geom.line(m1, p[1]); - var m2 = p[0].copy().add(line.vector()); - var rad = line.length(); - $c1.attr({cx: m1.x, cy: m1.y, r: rad}); - $c2.attr({cx: m2.x, cy: m2.y, r: rad}); + $s.place(); // place the linestring + var p = props.screenpos; + if (p.length > 2) { // p[2] is the mouse pointer + var m1 = p[1].mid(p[2]); + var line = geom.line(m1, p[1]); + var m2 = p[0].copy().add(line.vector()); + var rad = line.length(); + $c1.attr({cx: m1.x, cy: m1.y, r: rad}); + $c2.attr({cx: m2.x, cy: m2.y, r: rad}); + var diam = rad * 2; + var inter = p[0].distance(p[1]); + props.measures = { + len1: diam, + len2: inter, + rat: diam / inter + }; } - } - shape.$interactor = $s; + }; return $g; } }; @@ -1572,6 +1552,18 @@ shape.geometry.coordinates[2] = trafo.invtransform(p[2]).toArray(); props.p2 = p2; props.p3 = p3; // save other points + var len1 = line1.length(); + var len2 = p[0].distance(p3); + var diag = p[0].distance(p2); + var ang = line1.deg(); + props.measures = { + len1: len1, + len2: len2, + rat: len1 / len2, + diag: diag, + area: len1 * len2, + angx: ang + }; } this.attr({points: [p[0], p[1], p2, p3].join(" ")}); }; @@ -1591,20 +1583,20 @@ var constrClass = CSS+'constr'; props['stroke-width'] = styles.guide['stroke-width']; // draw a rectangle in guides style var $s = factory['Rect'].svg(shape); - var place = $s.place; var sweep = sumEdges(rectifyCoords(shape, 1)) > 0 ? '1' : '0'; $s.attr({class: guideClass}); var $g = $(fn.svgElement('g', {'id': shape.id + '-oval'})); - var $c1 = $(fn.svgElement('circle', {id: shape.id + '-circ1', class: guideClass })); - var $c2 = $(fn.svgElement('circle', {id: shape.id + '-circ2', class: guideClass })); - var $p1 = $(fn.svgElement('path', {id: shape.id + '-lines', class: guideClass })); - var $p2 = $(fn.svgElement('path', {id: shape.id + '-constr', class: constrClass })); + var $c1 = $(fn.svgElement('circle', {id: shape.id + '-circ1', 'class': guideClass })); + var $c2 = $(fn.svgElement('circle', {id: shape.id + '-circ2', 'class': guideClass })); + var $p1 = $(fn.svgElement('path', {id: shape.id + '-lines', 'class': guideClass })); + var $p2 = $(fn.svgElement('path', {id: shape.id + '-constr', 'class': constrClass })); props['stroke-width'] = styles.shape['stroke-width']; // draw the oval in shape style var $arc = $(fn.svgElement('path', fn.svgAttr(data, shape))); $g.append($s).append($c1).append($c2).append($p1).append($p2).append($arc); + shape.$interactor = $arc; $g.place = function () { + $s.place(); // place the framing rectangle (polygon) var p = props.screenpos; - place.call($s); // place the framing rectangle (polygon) if (p.length > 3) { // p[3] is the mouse pointer var side0 = geom.line(p[0], p[1]); // the sides var side1 = geom.line(p[1], props.p2); // use 'Rect' points @@ -1663,13 +1655,20 @@ }); p[3] = handle; shape.geometry.coordinates[3] = trafo.invtransform(handle).toArray(); - props.measures = { rad1: rad1, rad2: rad2, axis1: axis1.length(), axis2: axis2.length() }; // use for info - // area: (r² * phi) + (R² * (pi - phi)) - ((axis1 - 2r) * dist(m3, mid(axis1))) - // length of the periphery parts: q1 = r * phi, q2 = R * (pi - phi) - // circumference: 2 * (q1 + q2); + var len1 = axis1.length(); + var len2 = axis2.length(); + props.measures = { + rad1: rad1, + rad2: rad2, + len1: len1, + len2: len2, + rat1: len1 / len2 + // area: (r² * phi) + (R² * (pi - phi)) - ((axis1 - 2r) * dist(m3, mid(axis1))) + // length of the periphery parts: q1 = r * phi, q2 = R * (pi - phi) + // circumference: 2 * (q1 + q2); + }; } }; - shape.$interactor = $arc; return $g; } }; @@ -1687,27 +1686,27 @@ var shapeClass = CSS+'shape'; props['stroke-width'] = styles.guide['stroke-width']; // draw a rectangle in guides style var $s = factory['Rect'].svg(shape); - var place = $s.place; $s.attr({class: guideClass}); props['stroke-width'] = styles.shape['stroke-width']; // draw the ellipse in shape style var $arc = $(fn.svgElement('path', fn.svgAttr(data, shape))); - var $p = $(fn.svgElement('path', {id: shape.id + '-constr', class: guideClass })); - var $c1 = $(fn.svgElement('circle', {'id': shape.id + '-circ1', 'class': handleClass })); - var $c2 = $(fn.svgElement('circle', {'id': shape.id + '-circ2', 'class': handleClass })); + var $p = $(fn.svgElement('path', {id: shape.id + '-constr', 'class': guideClass })); + var $c1 = $(fn.svgElement('circle', {id: shape.id + '-circ1', 'class': handleClass })); + var $c2 = $(fn.svgElement('circle', {id: shape.id + '-circ2', 'class': handleClass })); var $g = $(fn.svgElement('g', {'id': shape.id + '-ellpisearc'})); $g.append($s).append($arc).append($p).append($c1).append($c2); + shape.$interactor = $arc; $g.place = function () { + $s.place(); // place the framing rectangle (polygon) var p = props.screenpos; - place.call($s); // place the framing rectangle (polygon) if (p.length > 2) { // p[3] is the mouse pointer var side0 = geom.line(p[0], p[1]); // the sides var mid0 = side0.mid(); // the midpoints of the sides - var axis1 = side0.parallel(p[2]); // short axis - var axis2 = geom.line(mid0, p[2]); // long axis - var m = axis2.mid(); + var axis1 = geom.line(mid0, p[2]); // long axis + var axis2 = side0.parallel(p[2]); // short axis + var m = axis1.mid(); var rad1 = m.distance(mid0); var rad2 = mid0.distance(p[0]); - var angle = axis2.deg(); + var angle = axis1.deg(); var e = Math.sqrt(Math.abs(rad1*rad1 - rad2*rad2)); // distance of focus to m if (rad1 > rad2) { var f1 = geom.line(m, mid0).scale(e/rad1).point(); @@ -1727,10 +1726,18 @@ ' A'+rad1+' '+rad2+' '+angle+' 1 1 '+p[2]+ ' A'+rad1+' '+rad2+' '+angle+' 1 1 '+mid0 }); - props.measures = { rad1: rad1, rad2: rad2, axis1: axis1.length(), axis2: axis2.length() }; // use for info + var len1 = axis1.length(); + var len2 = axis2.length(); + props.measures = { + angx: angle, + len1: len1, + len2: len2, + rat1: len1 / len2, + dist: e * 2, + area: len1 * len2 * Math.PI + }; } }; - shape.$interactor = $arc; return $g; } }; @@ -1740,7 +1747,7 @@ }, svg: function (shape) { var $s = factory['Line'].svg(shape); - var place = $s.place; + shape.$interactor = $s; var gridID = shape.id + '-grid'; var props = shape.properties; var $g = $(fn.svgElement('g', {id: shape.id + '-g'})); @@ -1750,7 +1757,7 @@ var $r = $(fn.svgElement('rect', {id: shape.id + '-rect', stroke: props.stroke, fill: 'url(#'+gridID+')'})); $g.append($defs.append($pat.append($path))).append($r).append($s); $g.place = function () { - place.call($s); + $s.place(); var p = props.screenpos; var d = p[0].distance(p[1]); var angle = fn.cropFloat(p[0].deg(p[1])); @@ -1761,8 +1768,12 @@ var transform = 'rotate('+angle+' '+p[0].x+' '+p[0].y+')'; $r.attr({x:x, y:y, height:d*scale, width:d*scale, transform:transform}); $pat.attr({patternTransform:transform}); + props.measures = { + angx: angle, + len1: d, + area: d * d + }; }; - shape.$interactor = $s; return $g; } };