diff --git a/src/math/shapes.js b/src/math/shapes.js index b7951961e6..77848554e3 100644 --- a/src/math/shapes.js +++ b/src/math/shapes.js @@ -254,8 +254,30 @@ dwv.math.Line = function(begin, end) parseInt( (begin.getX()+end.getX()) / 2, 10 ), parseInt( (begin.getY()+end.getY()) / 2, 10 ) ); }; + /** + * Get the slope of the line. + * @method getSlope + * @return {Number} The slope of the line. + */ + this.getSlope = function() + { + return (end.getY() - begin.getY()) / (end.getX() - begin.getX()); + }; }; // Line class +/** + * Get the angle between two lines. + * @param line0 The first line. + * @param line1 The second line. + */ +dwv.math.getAngle = function (line0, line1) +{ + var s0 = line0.getSlope(); + var s1 = line1.getSlope(); + var angle = Math.atan( Math.abs( (s0 - s1) / (1 + s0*s1) ) ) * 180 / Math.PI; + return angle; +}; + /** * Rectangle shape. * @class Rectangle diff --git a/src/tools/draw.js b/src/tools/draw.js index ae56826af3..c065c4b190 100644 --- a/src/tools/draw.js +++ b/src/tools/draw.js @@ -553,7 +553,15 @@ dwv.tool.Draw = function (app) // command name based on shape type var cmdName = "shape"; if ( shape instanceof Kinetic.Line ) { - cmdName = "line"; + if ( shape.points.length == 2 ) { + cmdName = "line"; + } + else if ( shape.points.length == 3 ) { + cmdName = "protractor"; + } + else { + cmdName = "roi"; + } } else if ( shape instanceof Kinetic.Rect ) { cmdName = "rectangle"; diff --git a/src/tools/editor.js b/src/tools/editor.js index ec95d335c0..2d676bc19e 100644 --- a/src/tools/editor.js +++ b/src/tools/editor.js @@ -179,15 +179,24 @@ dwv.tool.ShapeEditor = function () // add shape specific anchors to the shape group if ( shape instanceof Kinetic.Line ) { var points = shape.points(); - if ( points.length === 4 ) { - updateFunction = dwv.tool.UpdateLine; + if ( points.length === 4 || points.length === 6) { // add shape offset - var lineBeginX = points[0] + shape.x(); - var lineBeginY = points[1] + shape.y(); - var lineEndX = points[2] + shape.x(); - var lineEndY = points[3] + shape.y(); - addAnchor(group, lineBeginX, lineBeginY, 'begin'); - addAnchor(group, lineEndX, lineEndY, 'end'); + var p0x = points[0] + shape.x(); + var p0y = points[1] + shape.y(); + var p1x = points[2] + shape.x(); + var p1y = points[3] + shape.y(); + addAnchor(group, p0x, p0y, 'begin'); + if ( points.length === 4 ) { + updateFunction = dwv.tool.UpdateLine; + addAnchor(group, p1x, p1y, 'end'); + } + else { + updateFunction = dwv.tool.UpdateProtractor; + addAnchor(group, p1x, p1y, 'mid'); + var p2x = points[4] + shape.x(); + var p2y = points[5] + shape.y(); + addAnchor(group, p2x, p2y, 'end'); + } } else { updateFunction = dwv.tool.UpdateRoi; @@ -294,7 +303,15 @@ dwv.tool.ShapeEditor = function () // command name based on shape type var cmdName = "shape"; if ( shape instanceof Kinetic.Line ) { - cmdName = "line"; + if ( shape.points.length == 2 ) { + cmdName = "line"; + } + else if ( shape.points.length == 3 ) { + cmdName = "protractor"; + } + else { + cmdName = "roi"; + } } else if ( shape instanceof Kinetic.Rect ) { cmdName = "rectangle"; diff --git a/src/tools/protractor.js b/src/tools/protractor.js new file mode 100644 index 0000000000..fbce3d4c12 --- /dev/null +++ b/src/tools/protractor.js @@ -0,0 +1,152 @@ +/** + * Tool module. + * @module tool + */ +var dwv = dwv || {}; +dwv.tool = dwv.tool || {}; +var Kinetic = Kinetic || {}; + +/** + * Protractor factory. + * @class ProtractorFactory + * @namespace dwv.tool + * @constructor + */ +dwv.tool.ProtractorFactory = function () +{ + /** + * Get the number of points needed to build the shape. + * @method getNPoints + * @return {Number} The number of points. + */ + this.getNPoints = function () { return 3; }; + /** + * Get the timeout between point storage. + * @method getTimeout + * @return {Number} The timeout in milliseconds. + */ + this.getTimeout = function () { return 500; }; +}; + +/** + * Create a protractor shape to be displayed. + * @method ProtractorCreator + * @static + * @param {Array} points The points from which to extract the protractor. + * @param {Object} style The drawing style. + * @param {Object} image The associated image. + */ +dwv.tool.ProtractorFactory.prototype.create = function (points, style/*, image*/) +{ + // physical shape + var line0 = new dwv.math.Line(points[0], points[1]); + // points stored the kineticjs way + var pointsArray = []; + for( var i = 0; i < points.length; ++i ) + { + pointsArray.push( points[i].getX() ); + pointsArray.push( points[i].getY() ); + } + // shape + var kline = new Kinetic.Line({ + points: pointsArray, + stroke: style.getLineColor(), + strokeWidth: 2, + name: "shape" + }); + + var ktext; + if ( points.length == 3 ) { + var line1 = new dwv.math.Line(points[1], points[2]); + // quantification + var quant = dwv.math.getAngle(line0, line1); + var str = quant.toPrecision(4) + " deg"; + ktext = new Kinetic.Text({ + x: line0.getEnd().getX(), + y: line0.getEnd().getY() - 15, + text: str, + fontSize: style.getFontSize(), + fontFamily: "Verdana", + fill: style.getLineColor(), + name: "text" + }); + } + else { + ktext = new Kinetic.Text({ + x: 0, + y: 0, + text: "", + fontSize: style.getFontSize(), + fontFamily: "Verdana", + fill: style.getLineColor(), + name: "text" + }); + } + // return shape + return {"shape": kline, "text": ktext}; +}; + +/** + * Update a protractor shape. + * @method UpdateProtractor + * @static + * @param {Object} kline The protractor shape to update. + * @param {Object} anchor The active anchor. + * @param {Object} image The associated image. + */ +dwv.tool.UpdateProtractor = function (kline, anchor/*, image*/) +{ + // parent group + var group = anchor.getParent(); + // find special points + var begin = group.getChildren( function (node){ + return node.id() === 'begin'; + })[0]; + var mid = group.getChildren( function (node){ + return node.id() === 'mid'; + })[0]; + var end = group.getChildren( function (node){ + return node.id() === 'end'; + })[0]; + // update special points + switch ( anchor.id() ) { + case 'begin': + begin.x( anchor.x() ); + begin.y( anchor.y() ); + break; + case 'mid': + mid.x( anchor.x() ); + mid.y( anchor.y() ); + break; + case 'end': + end.x( anchor.x() ); + end.y( anchor.y() ); + break; + } + // update shape and compensate for possible drag + // note: shape.position() and shape.size() won't work... + var bx = begin.x() - kline.x(); + var by = begin.y() - kline.y(); + var mx = mid.x() - kline.x(); + var my = mid.y() - kline.y(); + var ex = end.x() - kline.x(); + var ey = end.y() - kline.y(); + kline.points( [bx,by,mx,my,ex,ey] ); + // update text + var ktext = group.getChildren(function(node){ + return node.name() === 'text'; + })[0]; + if ( ktext ) { + // update quantification + var p2d0 = new dwv.math.Point2D(begin.x(), begin.y()); + var p2d1 = new dwv.math.Point2D(mid.x(), mid.y()); + var p2d2 = new dwv.math.Point2D(end.x(), end.y()); + var line0 = new dwv.math.Line(p2d0, p2d1); + var line1 = new dwv.math.Line(p2d1, p2d2); + var quant = dwv.math.getAngle( line0, line1 ); + var str = quant.toPrecision(4) + " deg"; + var textPos = { 'x': line0.getEnd().getX(), 'y': line0.getEnd().getY() - 15 }; + ktext.position( textPos ); + ktext.text(str); + } +}; diff --git a/viewers/mobile/applauncher.js b/viewers/mobile/applauncher.js index d4dc45a548..534c0fa44f 100644 --- a/viewers/mobile/applauncher.js +++ b/viewers/mobile/applauncher.js @@ -40,6 +40,7 @@ $(document).ready( function() // Add shapes to the shape list for the draw tool dwv.tool.shapes = {}; dwv.tool.shapes.line = dwv.tool.LineFactory; + dwv.tool.shapes.protractor = dwv.tool.ProtractorFactory; dwv.tool.shapes.rectangle = dwv.tool.RectangleFactory; dwv.tool.shapes.roi = dwv.tool.RoiFactory; dwv.tool.shapes.ellipse = dwv.tool.EllipseFactory; diff --git a/viewers/mobile/index.html b/viewers/mobile/index.html index 4fe1a8c410..991564e8d9 100644 --- a/viewers/mobile/index.html +++ b/viewers/mobile/index.html @@ -66,6 +66,7 @@ + diff --git a/viewers/static/applauncher.js b/viewers/static/applauncher.js index a105d8e371..5a89466075 100644 --- a/viewers/static/applauncher.js +++ b/viewers/static/applauncher.js @@ -65,6 +65,7 @@ $(document).ready( function() // Add shapes to the shape list for the draw tool dwv.tool.shapes = {}; dwv.tool.shapes.line = dwv.tool.LineFactory; + dwv.tool.shapes.protractor = dwv.tool.ProtractorFactory; dwv.tool.shapes.rectangle = dwv.tool.RectangleFactory; dwv.tool.shapes.roi = dwv.tool.RoiFactory; dwv.tool.shapes.ellipse = dwv.tool.EllipseFactory; diff --git a/viewers/static/index.html b/viewers/static/index.html index f1cf3ad10e..cf2b9320fa 100644 --- a/viewers/static/index.html +++ b/viewers/static/index.html @@ -60,6 +60,7 @@ +