Last active
April 4, 2016 21:32
-
-
Save ivmartel/1bd4205d8a30be94e556c9160761a967 to your computer and use it in GitHub Desktop.
Fixed sized rectangle
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// namespaces | |
var dwv = dwv || {}; | |
/** @namespace */ | |
dwv.tool = dwv.tool || {}; | |
//external | |
var Kinetic = Kinetic || {}; | |
/** | |
* Draw group command. | |
* @constructor | |
*/ | |
dwv.tool.DrawGroupCommand = function (group, name, layer) | |
{ | |
/** | |
* Get the command name. | |
* @return {String} The command name. | |
*/ | |
this.getName = function () { return "Draw-"+name; }; | |
/** | |
* Execute the command. | |
*/ | |
this.execute = function () { | |
// add the group to the layer | |
layer.add(group); | |
// draw | |
layer.draw(); | |
// callback | |
this.onExecute({'type': 'draw-create', 'id': group.id()}); | |
}; | |
/** | |
* Undo the command. | |
*/ | |
this.undo = function () { | |
// remove the group from the parent layer | |
group.remove(); | |
// draw | |
layer.draw(); | |
// callback | |
this.onUndo({'type': 'draw-delete', 'id': group.id()}); | |
}; | |
}; // DrawGroupCommand class | |
/** | |
* Handle an execute event. | |
* @param {Object} event The execute event with type and id. | |
*/ | |
dwv.tool.DrawGroupCommand.prototype.onExecute = function (/*event*/) | |
{ | |
// default does nothing. | |
}; | |
/** | |
* Handle an undo event. | |
* @param {Object} event The undo event with type and id. | |
*/ | |
dwv.tool.DrawGroupCommand.prototype.onUndo = function (/*event*/) | |
{ | |
// default does nothing. | |
}; | |
/** | |
* Move group command. | |
* @constructor | |
*/ | |
dwv.tool.MoveGroupCommand = function (group, name, translation, layer) | |
{ | |
/** | |
* Get the command name. | |
* @return {String} The command name. | |
*/ | |
this.getName = function () { return "Move-"+name; }; | |
/** | |
* Execute the command. | |
*/ | |
this.execute = function () { | |
// translate all children of group | |
group.getChildren().each( function (shape) { | |
shape.x( shape.x() + translation.x ); | |
shape.y( shape.y() + translation.y ); | |
}); | |
// draw | |
layer.draw(); | |
// callback | |
this.onExecute({'type': 'draw-move', 'id': group.id()}); | |
}; | |
/** | |
* Undo the command. | |
*/ | |
this.undo = function () { | |
// invert translate all children of group | |
group.getChildren().each( function (shape) { | |
shape.x( shape.x() - translation.x ); | |
shape.y( shape.y() - translation.y ); | |
}); | |
// draw | |
layer.draw(); | |
// callback | |
this.onUndo({'type': 'draw-move', 'id': group.id()}); | |
}; | |
}; // MoveGroupCommand class | |
/** | |
* Handle an execute event. | |
* @param {Object} event The execute event with type and id. | |
*/ | |
dwv.tool.MoveGroupCommand.prototype.onExecute = function (/*event*/) | |
{ | |
// default does nothing. | |
}; | |
/** | |
* Handle an undo event. | |
* @param {Object} event The undo event with type and id. | |
*/ | |
dwv.tool.MoveGroupCommand.prototype.onUndo = function (/*event*/) | |
{ | |
// default does nothing. | |
}; | |
/** | |
* Change group command. | |
* @constructor | |
*/ | |
dwv.tool.ChangeGroupCommand = function (name, func, startAnchor, endAnchor, layer, image) | |
{ | |
/** | |
* Get the command name. | |
* @return {String} The command name. | |
*/ | |
this.getName = function () { return "Change-"+name; }; | |
/** | |
* Execute the command. | |
*/ | |
this.execute = function () { | |
// change shape | |
func( endAnchor, image ); | |
// draw | |
layer.draw(); | |
// callback | |
this.onExecute({'type': 'draw-change'}); | |
}; | |
/** | |
* Undo the command. | |
*/ | |
this.undo = function () { | |
// invert change shape | |
func( startAnchor, image ); | |
// draw | |
layer.draw(); | |
// callback | |
this.onUndo({'type': 'draw-change'}); | |
}; | |
}; // ChangeGroupCommand class | |
/** | |
* Handle an execute event. | |
* @param {Object} event The execute event with type and id. | |
*/ | |
dwv.tool.ChangeGroupCommand.prototype.onExecute = function (/*event*/) | |
{ | |
// default does nothing. | |
}; | |
/** | |
* Handle an undo event. | |
* @param {Object} event The undo event with type and id. | |
*/ | |
dwv.tool.ChangeGroupCommand.prototype.onUndo = function (/*event*/) | |
{ | |
// default does nothing. | |
}; | |
/** | |
* Delete group command. | |
* @constructor | |
*/ | |
dwv.tool.DeleteGroupCommand = function (group, name, layer) | |
{ | |
/** | |
* Get the command name. | |
* @return {String} The command name. | |
*/ | |
this.getName = function () { return "Delete-"+name; }; | |
/** | |
* Execute the command. | |
*/ | |
this.execute = function () { | |
// remove the group from the parent layer | |
group.remove(); | |
// draw | |
layer.draw(); | |
// callback | |
this.onExecute({'type': 'draw-delete', 'id': group.id()}); | |
}; | |
/** | |
* Undo the command. | |
*/ | |
this.undo = function () { | |
// add the group to the layer | |
layer.add(group); | |
// draw | |
layer.draw(); | |
// callback | |
this.onUndo({'type': 'draw-create', 'id': group.id()}); | |
}; | |
}; // DeleteGroupCommand class | |
/** | |
* Handle an execute event. | |
* @param {Object} event The execute event with type and id. | |
*/ | |
dwv.tool.DeleteGroupCommand.prototype.onExecute = function (/*event*/) | |
{ | |
// default does nothing. | |
}; | |
/** | |
* Handle an undo event. | |
* @param {Object} event The undo event with type and id. | |
*/ | |
dwv.tool.DeleteGroupCommand.prototype.onUndo = function (/*event*/) | |
{ | |
// default does nothing. | |
}; | |
/** | |
* Drawing tool. | |
* @constructor | |
* @param {Object} app The associated application. | |
*/ | |
dwv.tool.Draw = function (app, shapeFactoryList) | |
{ | |
/** | |
* Closure to self: to be used by event handlers. | |
* @private | |
* @type WindowLevel | |
*/ | |
var self = this; | |
/** | |
* Draw GUI. | |
* @type Object | |
*/ | |
var gui = null; | |
/** | |
* Interaction start flag. | |
* @private | |
* @type Boolean | |
*/ | |
var started = false; | |
/** | |
* Shape factory list | |
* @type Object | |
*/ | |
this.shapeFactoryList = shapeFactoryList; | |
/** | |
* Draw command. | |
* @private | |
* @type Object | |
*/ | |
var command = null; | |
/** | |
* Current shape group. | |
* @private | |
* @type Object | |
*/ | |
var shapeGroup = null; | |
/** | |
* Shape name. | |
* @type String | |
*/ | |
this.shapeName = 0; | |
/** | |
* List of points. | |
* @private | |
* @type Array | |
*/ | |
var points = []; | |
/** | |
* Last selected point. | |
* @private | |
* @type Object | |
*/ | |
var lastPoint = null; | |
/** | |
* Shape editor. | |
* @private | |
* @type Object | |
*/ | |
var shapeEditor = new dwv.tool.ShapeEditor(app); | |
// associate the event listeners of the editor | |
// with those of the draw tool | |
shapeEditor.setDrawEventCallback(fireEvent); | |
/** | |
* Trash draw: a cross. | |
* @private | |
* @type Object | |
*/ | |
var trash = new Kinetic.Group(); | |
// first line of the cross | |
var trashLine1 = new Kinetic.Line({ | |
points: [-10, -10, 10, 10 ], | |
stroke: 'red', | |
}); | |
// second line of the cross | |
var trashLine2 = new Kinetic.Line({ | |
points: [10, -10, -10, 10 ], | |
stroke: 'red' | |
}); | |
trash.add(trashLine1); | |
trash.add(trashLine2); | |
// listeners | |
var listeners = {}; | |
/** | |
* The associated draw layer. | |
* @private | |
* @type Object | |
*/ | |
var drawLayer = null; | |
/** | |
* Handle mouse down event. | |
* @param {Object} event The mouse down event. | |
*/ | |
this.mousedown = function(event){ | |
// determine if the click happened in an existing shape | |
var stage = app.getDrawStage(); | |
var kshape = stage.getIntersection({ | |
x: event._xs, | |
y: event._ys | |
}); | |
if ( kshape ) { | |
var group = kshape.getParent(); | |
var selectedShape = group.find(".shape")[0]; | |
// reset editor if click on other shape | |
// (and avoid anchors mouse down) | |
if ( selectedShape && selectedShape !== shapeEditor.getShape() ) { | |
shapeEditor.disable(); | |
shapeEditor.setShape(selectedShape); | |
shapeEditor.setImage(app.getImage()); | |
shapeEditor.enable(); | |
} | |
} | |
else { | |
// disable edition | |
shapeEditor.disable(); | |
shapeEditor.setShape(null); | |
shapeEditor.setImage(null); | |
// start storing points | |
started = true; | |
// clear array | |
points = []; | |
// store point | |
lastPoint = new dwv.math.Point2D(event._x, event._y); | |
points.push(lastPoint); | |
} | |
}; | |
/** | |
* Handle mouse move event. | |
* @param {Object} event The mouse move event. | |
*/ | |
this.mousemove = function(event){ | |
if (!started) | |
{ | |
return; | |
} | |
if ( Math.abs( event._x - lastPoint.getX() ) > 0 || | |
Math.abs( event._y - lastPoint.getY() ) > 0 ) | |
{ | |
// current point | |
lastPoint = new dwv.math.Point2D(event._x, event._y); | |
// clear last added point from the list (but not the first one) | |
if ( points.length != 1 ) { | |
points.pop(); | |
} | |
// add current one to the list | |
points.push( lastPoint ); | |
// allow for anchor points | |
var factory = new self.shapeFactoryList[self.shapeName](); | |
if( points.length < factory.getNPoints() ) { | |
clearTimeout(this.timer); | |
this.timer = setTimeout( function () { | |
points.push( lastPoint ); | |
}, factory.getTimeout() ); | |
} | |
// remove previous draw | |
if ( shapeGroup ) { | |
shapeGroup.destroy(); | |
} | |
// create shape group | |
shapeGroup = factory.create(points, app.getStyle(), app.getImage()); | |
// do not listen during creation | |
var shape = shapeGroup.getChildren( function (node) { | |
return node.name() === 'shape'; | |
})[0]; | |
shape.listening(false); | |
drawLayer.hitGraphEnabled(false); | |
// draw shape command | |
command = new dwv.tool.DrawGroupCommand(shapeGroup, self.shapeName, drawLayer); | |
// draw | |
command.execute(); | |
} | |
}; | |
/** | |
* Handle mouse up event. | |
* @param {Object} event The mouse up event. | |
*/ | |
this.mouseup = function (/*event*/){ | |
// check it the factory has its NPoints | |
var factory = new self.shapeFactoryList[self.shapeName](); | |
if (started && points.length >= factory.getNPoints() ) | |
{ | |
// reset shape group | |
if ( shapeGroup ) { | |
shapeGroup.destroy(); | |
} | |
// create final shape | |
//var factory = new self.shapeFactoryList[self.shapeName](); | |
var group = factory.create(points, app.getStyle(), app.getImage()); | |
group.id( dwv.math.guid() ); | |
// re-activate layer | |
drawLayer.hitGraphEnabled(true); | |
// draw shape command | |
command = new dwv.tool.DrawGroupCommand(group, self.shapeName, drawLayer); | |
command.onExecute = fireEvent; | |
command.onUndo = fireEvent; | |
// execute it | |
command.execute(); | |
// save it in undo stack | |
app.addToUndoStack(command); | |
// set shape on | |
var shape = group.getChildren( function (node) { | |
return node.name() === 'shape'; | |
})[0]; | |
self.setShapeOn( shape ); | |
} | |
// reset flag | |
started = false; | |
}; | |
/** | |
* Handle mouse out event. | |
* @param {Object} event The mouse out event. | |
*/ | |
this.mouseout = function(event){ | |
self.mouseup(event); | |
}; | |
/** | |
* Handle touch start event. | |
* @param {Object} event The touch start event. | |
*/ | |
this.touchstart = function(event){ | |
self.mousedown(event); | |
}; | |
/** | |
* Handle touch move event. | |
* @param {Object} event The touch move event. | |
*/ | |
this.touchmove = function(event){ | |
self.mousemove(event); | |
}; | |
/** | |
* Handle touch end event. | |
* @param {Object} event The touch end event. | |
*/ | |
this.touchend = function(event){ | |
self.mouseup(event); | |
}; | |
/** | |
* Handle key down event. | |
* @param {Object} event The key down event. | |
*/ | |
this.keydown = function(event){ | |
app.onKeydown(event); | |
}; | |
/** | |
* Setup the tool GUI. | |
*/ | |
this.setup = function () | |
{ | |
gui = new dwv.gui.Draw(app); | |
gui.setup(this.shapeFactoryList); | |
}; | |
/** | |
* Enable the tool. | |
* @param {Boolean} flag The flag to enable or not. | |
*/ | |
this.display = function ( flag ){ | |
if ( gui ) { | |
gui.display( flag ); | |
} | |
// reset shape display properties | |
shapeEditor.disable(); | |
shapeEditor.setShape(null); | |
shapeEditor.setImage(null); | |
document.body.style.cursor = 'default'; | |
// make layer listen or not to events | |
app.getDrawStage().listening( flag ); | |
drawLayer = app.getDrawLayer(); | |
drawLayer.listening( flag ); | |
drawLayer.hitGraphEnabled( flag ); | |
// get the list of shapes | |
var groups = drawLayer.getChildren(); | |
var shapes = []; | |
var fshape = function (node) { | |
return node.name() === 'shape'; | |
}; | |
for ( var i = 0; i < groups.length; ++i ) { | |
// should only be one shape per group | |
shapes.push( groups[i].getChildren(fshape)[0] ); | |
} | |
// set shape display properties | |
if ( flag ) { | |
app.addLayerListeners( app.getDrawStage().getContent() ); | |
shapes.forEach( function (shape){ self.setShapeOn( shape ); }); | |
} | |
else { | |
app.removeLayerListeners( app.getDrawStage().getContent() ); | |
shapes.forEach( function (shape){ setShapeOff( shape ); }); | |
} | |
// draw | |
drawLayer.draw(); | |
}; | |
/** | |
* Set shape off properties. | |
* @param {Object} shape The shape to set off. | |
*/ | |
function setShapeOff( shape ) { | |
// mouse styling | |
shape.off('mouseover'); | |
shape.off('mouseout'); | |
// drag | |
shape.draggable(false); | |
shape.off('dragstart'); | |
shape.off('dragmove'); | |
shape.off('dragend'); | |
} | |
/** | |
* Get the real position from an event. | |
*/ | |
function getRealPosition( index ) { | |
var stage = app.getDrawStage(); | |
return { 'x': stage.offset().x + index.x / stage.scale().x, | |
'y': stage.offset().y + index.y / stage.scale().y }; | |
} | |
/** | |
* Set shape on properties. | |
* @param {Object} shape The shape to set on. | |
*/ | |
this.setShapeOn = function ( shape ) { | |
// mouse over styling | |
shape.on('mouseover', function () { | |
document.body.style.cursor = 'pointer'; | |
}); | |
// mouse out styling | |
shape.on('mouseout', function () { | |
document.body.style.cursor = 'default'; | |
}); | |
// make it draggable | |
shape.draggable(true); | |
var dragStartPos = null; | |
var dragLastPos = null; | |
// command name based on shape type | |
var cmdName = "shape"; | |
if ( shape instanceof Kinetic.Line ) { | |
if ( shape.points().length == 4 ) { | |
cmdName = "line"; | |
} | |
else if ( shape.points().length == 6 ) { | |
cmdName = "protractor"; | |
} | |
else { | |
cmdName = "roi"; | |
} | |
} | |
else if ( shape instanceof Kinetic.Rect ) { | |
cmdName = "rectangle"; | |
} | |
else if ( shape instanceof Kinetic.Ellipse ) { | |
cmdName = "ellipse"; | |
} | |
// shape colour | |
var colour = shape.stroke(); | |
// drag start event handling | |
shape.on('dragstart', function (event) { | |
// save start position | |
var offset = dwv.html.getEventOffset( event.evt )[0]; | |
dragStartPos = getRealPosition( offset ); | |
// display trash | |
var stage = app.getDrawStage(); | |
var scale = stage.scale(); | |
var invscale = {'x': 1/scale.x, 'y': 1/scale.y}; | |
trash.x( stage.offset().x + ( 256 / scale.x ) ); | |
trash.y( stage.offset().y + ( 20 / scale.y ) ); | |
trash.scale( invscale ); | |
drawLayer.add( trash ); | |
// deactivate anchors to avoid events on null shape | |
shapeEditor.setAnchorsActive(false); | |
// draw | |
drawLayer.draw(); | |
}); | |
// drag move event handling | |
shape.on('dragmove', function (event) { | |
var offset = dwv.html.getEventOffset( event.evt )[0]; | |
var pos = getRealPosition( offset ); | |
var translation; | |
if ( dragLastPos ) { | |
translation = {'x': pos.x - dragLastPos.x, | |
'y': pos.y - dragLastPos.y}; | |
} | |
else { | |
translation = {'x': pos.x - dragStartPos.x, | |
'y': pos.y - dragStartPos.y}; | |
} | |
dragLastPos = pos; | |
// highlight trash when on it | |
if ( Math.abs( pos.x - trash.x() ) < 10 && | |
Math.abs( pos.y - trash.y() ) < 10 ) { | |
trash.getChildren().each( function (tshape){ tshape.stroke('orange'); }); | |
shape.stroke('red'); | |
} | |
else { | |
trash.getChildren().each( function (tshape){ tshape.stroke('red'); }); | |
shape.stroke(colour); | |
} | |
// update group but not 'this' shape | |
var group = this.getParent(); | |
group.getChildren().each( function (shape) { | |
if ( shape === this ) { | |
return; | |
} | |
shape.x( shape.x() + translation.x ); | |
shape.y( shape.y() + translation.y ); | |
}); | |
// reset anchors | |
shapeEditor.resetAnchors(); | |
// draw | |
drawLayer.draw(); | |
}); | |
// drag end event handling | |
shape.on('dragend', function (/*event*/) { | |
var pos = dragLastPos; | |
dragLastPos = null; | |
// delete case | |
if ( Math.abs( pos.x - trash.x() ) < 10 && | |
Math.abs( pos.y - trash.y() ) < 10 ) { | |
// compensate for the drag translation | |
var delTranslation = {'x': pos.x - dragStartPos.x, | |
'y': pos.y - dragStartPos.y}; | |
var group = this.getParent(); | |
group.getChildren().each( function (shape) { | |
shape.x( shape.x() - delTranslation.x ); | |
shape.y( shape.y() - delTranslation.y ); | |
}); | |
// restore colour | |
shape.stroke(colour); | |
// disable editor | |
shapeEditor.disable(); | |
shapeEditor.setShape(null); | |
shapeEditor.setImage(null); | |
document.body.style.cursor = 'default'; | |
// delete command | |
var delcmd = new dwv.tool.DeleteGroupCommand(this.getParent(), cmdName, drawLayer); | |
delcmd.onExecute = fireEvent; | |
delcmd.onUndo = fireEvent; | |
delcmd.execute(); | |
app.addToUndoStack(delcmd); | |
} | |
else { | |
// save drag move | |
var translation = {'x': pos.x - dragStartPos.x, | |
'y': pos.y - dragStartPos.y}; | |
if ( translation.x !== 0 || translation.y !== 0 ) { | |
var mvcmd = new dwv.tool.MoveGroupCommand(this.getParent(), cmdName, translation, drawLayer); | |
mvcmd.onExecute = fireEvent; | |
mvcmd.onUndo = fireEvent; | |
app.addToUndoStack(mvcmd); | |
// the move is handled by kinetic, trigger an event manually | |
fireEvent({'type': 'draw-move'}); | |
} | |
// reset anchors | |
shapeEditor.setAnchorsActive(true); | |
shapeEditor.resetAnchors(); | |
} | |
// remove trash | |
trash.remove(); | |
// draw | |
drawLayer.draw(); | |
}); | |
}; | |
/** | |
* Initialise the tool. | |
*/ | |
this.init = function() { | |
// set the default to the first in the list | |
var shapeName = 0; | |
for( var key in this.shapeFactoryList ){ | |
shapeName = key; | |
break; | |
} | |
this.setShapeName(shapeName); | |
// init gui | |
if ( gui ) { | |
// same for colour | |
this.setLineColour(gui.getColours()[0]); | |
// init html | |
gui.initialise(); | |
} | |
return true; | |
}; | |
/** | |
* Add an event listener on the app. | |
* @param {String} type The event type. | |
* @param {Object} listener The method associated with the provided event type. | |
*/ | |
this.addEventListener = function (type, listener) | |
{ | |
if ( typeof listeners[type] === "undefined" ) { | |
listeners[type] = []; | |
} | |
listeners[type].push(listener); | |
}; | |
/** | |
* Remove an event listener from the app. | |
* @param {String} type The event type. | |
* @param {Object} listener The method associated with the provided event type. | |
*/ | |
this.removeEventListener = function (type, listener) | |
{ | |
if( typeof listeners[type] === "undefined" ) { | |
return; | |
} | |
for ( var i = 0; i < listeners[type].length; ++i ) | |
{ | |
if ( listeners[type][i] === listener ) { | |
listeners[type].splice(i,1); | |
} | |
} | |
}; | |
/** | |
* Set the line colour of the drawing. | |
* @param {String} colour The colour to set. | |
*/ | |
this.setLineColour = function (colour) | |
{ | |
app.getStyle().setLineColour(colour); | |
}; | |
// Private Methods ----------------------------------------------------------- | |
/** | |
* Fire an event: call all associated listeners. | |
* @param {Object} event The event to fire. | |
*/ | |
function fireEvent (event) | |
{ | |
if ( typeof listeners[event.type] === "undefined" ) { | |
return; | |
} | |
for ( var i=0; i < listeners[event.type].length; ++i ) | |
{ | |
listeners[event.type][i](event); | |
} | |
} | |
}; // Draw class | |
/** | |
* Help for this tool. | |
* @return {Object} The help content. | |
*/ | |
dwv.tool.Draw.prototype.getHelp = function() | |
{ | |
return { | |
'title': "Draw", | |
'brief': "Allows to draw shapes on the image. " + | |
"Choose the shape and its colour from the drop down menus. Once created, shapes " + | |
"can be edited by selecting them. Anchors will appear and allow specific shape edition. " + | |
"Drag the shape on the top red cross to delete it. All actions are undoable. ", | |
'mouse': { | |
'mouse_drag': "A single mouse drag draws the desired shape.", | |
}, | |
'touch': { | |
'touch_drag': "A single touch drag draws the desired shape.", | |
} | |
}; | |
}; | |
/** | |
* Set the shape name of the drawing. | |
* @param {String} name The name of the shape. | |
*/ | |
dwv.tool.Draw.prototype.setShapeName = function(name) | |
{ | |
// check if we have it | |
if( !this.hasShape(name) ) | |
{ | |
throw new Error("Unknown shape: '" + name + "'"); | |
} | |
this.shapeName = name; | |
}; | |
/** | |
* Check if the shape is in the shape list. | |
* @param {String} name The name of the shape. | |
*/ | |
dwv.tool.Draw.prototype.hasShape = function(name) { | |
return this.shapeFactoryList[name]; | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// namespaces | |
var dwv = dwv || {}; | |
dwv.tool = dwv.tool || {}; | |
//external | |
var Kinetic = Kinetic || {}; | |
/** | |
* Rectangle factory. | |
* @constructor | |
*/ | |
dwv.tool.RectangleFactory = function () | |
{ | |
/** | |
* Get the number of points needed to build the shape. | |
* @return {Number} The number of points. | |
*/ | |
this.getNPoints = function () { return 1; }; | |
/** | |
* Get the timeout between point storage. | |
* @return {Number} The timeout in milliseconds. | |
*/ | |
this.getTimeout = function () { return 0; }; | |
}; | |
/** | |
* Create a rectangle shape to be displayed. | |
* @param {Array} points The points from which to extract the rectangle. | |
* @param {Object} style The drawing style. | |
* @param {Object} image The associated image. | |
*/ | |
dwv.tool.RectangleFactory.prototype.create = function (points, style, image) | |
{ | |
// physical shape: rectangle centered in points[0] | |
var p0 = new dwv.math.Point2D(points[0].getX() - 25, points[0].getY() - 25); | |
var p1 = new dwv.math.Point2D(points[0].getX() + 25, points[0].getY() + 25); | |
var rectangle = new dwv.math.Rectangle(p0, p1); | |
// draw shape | |
var kshape = new Kinetic.Rect({ | |
x: rectangle.getBegin().getX(), | |
y: rectangle.getBegin().getY(), | |
width: rectangle.getWidth(), | |
height: rectangle.getHeight(), | |
stroke: style.getLineColour(), | |
strokeWidth: style.getScaledStrokeWidth(), | |
name: "shape" | |
}); | |
// quantification | |
var quant = image.quantifyRect( rectangle ); | |
var cm2 = quant.surface / 100; | |
var str = cm2.toPrecision(4) + " cm2"; | |
// quantification text | |
var ktext = new Kinetic.Text({ | |
x: rectangle.getBegin().getX(), | |
y: rectangle.getEnd().getY() + 10, | |
text: str, | |
fontSize: style.getScaledFontSize(), | |
fontFamily: style.getFontFamily(), | |
fill: style.getLineColour(), | |
name: "text" | |
}); | |
// return group | |
var group = new Kinetic.Group(); | |
group.name("rectangle-group"); | |
group.add(kshape); | |
group.add(ktext); | |
return group; | |
}; | |
/** | |
* Update a rectangle shape. | |
* @param {Object} anchor The active anchor. | |
* @param {Object} image The associated image. | |
*/ | |
dwv.tool.UpdateRect = function (anchor, image) | |
{ | |
// parent group | |
var group = anchor.getParent(); | |
// associated shape | |
var krect = group.getChildren( function (node) { | |
return node.name() === 'shape'; | |
})[0]; | |
// associated text | |
var ktext = group.getChildren( function (node) { | |
return node.name() === 'text'; | |
})[0]; | |
// find special points | |
var topLeft = group.getChildren( function (node) { | |
return node.id() === 'topLeft'; | |
})[0]; | |
var topRight = group.getChildren( function (node) { | |
return node.id() === 'topRight'; | |
})[0]; | |
var bottomRight = group.getChildren( function (node) { | |
return node.id() === 'bottomRight'; | |
})[0]; | |
var bottomLeft = group.getChildren( function (node) { | |
return node.id() === 'bottomLeft'; | |
})[0]; | |
// update 'self' (undo case) and special points | |
switch ( anchor.id() ) { | |
case 'topLeft': | |
topLeft.x( anchor.x() ); | |
topLeft.y( anchor.y() ); | |
topRight.y( anchor.y() ); | |
bottomLeft.x( anchor.x() ); | |
break; | |
case 'topRight': | |
topRight.x( anchor.x() ); | |
topRight.y( anchor.y() ); | |
topLeft.y( anchor.y() ); | |
bottomRight.x( anchor.x() ); | |
break; | |
case 'bottomRight': | |
bottomRight.x( anchor.x() ); | |
bottomRight.y( anchor.y() ); | |
bottomLeft.y( anchor.y() ); | |
topRight.x( anchor.x() ); | |
break; | |
case 'bottomLeft': | |
bottomLeft.x( anchor.x() ); | |
bottomLeft.y( anchor.y() ); | |
bottomRight.y( anchor.y() ); | |
topLeft.x( anchor.x() ); | |
break; | |
default : | |
console.error('Unhandled anchor id: '+anchor.id()); | |
break; | |
} | |
// update shape | |
krect.position(topLeft.position()); | |
var width = topRight.x() - topLeft.x(); | |
var height = bottomLeft.y() - topLeft.y(); | |
if ( width && height ) { | |
krect.size({'width': width, 'height': height}); | |
} | |
// update text | |
var p2d0 = new dwv.math.Point2D(topLeft.x(), topLeft.y()); | |
var p2d1 = new dwv.math.Point2D(bottomRight.x(), bottomRight.y()); | |
var rect = new dwv.math.Rectangle(p2d0, p2d1); | |
var quant = image.quantifyRect( rect ); | |
var cm2 = quant.surface / 100; | |
var str = cm2.toPrecision(4) + " cm2"; | |
var textPos = { 'x': rect.getBegin().getX(), 'y': rect.getEnd().getY() + 10 }; | |
ktext.position(textPos); | |
ktext.text(str); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Modifs compared to current head: