Gitlab CSE Unil

Commit 610a025d authored by M. Chardon's avatar M. Chardon
Browse files

arrowgeo ok

parent 27305445
......@@ -46,7 +46,8 @@ define([
"tools/drawinggeo",
"tools/linesgeo",
"tools/ellipsegeo",
"tools/rectanglegeo"
"tools/rectanglegeo",
"tools/arrowgeo"
],
function(_, Signal){
// ----- Locale variables -----------------------------
......
define(["paper", "tools/Shape.class","adim/category"], function (paper,Shape, Category) {
// ----- Const ----------------------------------------
var TOOL_TYPE = 'arrowgeo';
var _ro = false;
// ----- Local variables ------------------------------
// Events
var _events = {
annotationAdded: null,
annotationSelected: null,
annotationChanged: null
};
// Properties
var defaultProperties = {
comment: "",
category: "cat_geo_1",
fill: true
};
var _transparent = new paper.Color([0,0,0,0]);
// ----- Serialization ---------------------------------
function exportJSON(param) {
var fromPt = this.data.from;
var toPt = this.data.to;
var json = this.exportJSON({asString:false});
try {
json[1][1].data.from = [this.data.from.x, this.data.from.y];
json[1][1].data.to = [this.data.to.x, this.data.to.y];
} catch(e) {
console.error(e);
}
return (param && param.asString) ? JSON.stringify(json) : json;
}
function importJSON(itemDef, layer, listening) {
var item = itemDef[1][1];
var symbolItem = itemDef[0][1][item.symbol][1][1];
var isFill = symbolItem.fillColor && (symbolItem.fillColor.length < 3 || symbolItem.fillColor[3] !== 0);
var opacity = parseFloat(item.opacity) || 1;
var curLayer = paper.project.activeLayer;
layer.activate();
if (item.data.from.length > 2)
item.data.from = item.data.from.splice(1);
if (item.data.to.length > 2)
item.data.to = item.data.to.splice(1);
var newArrow = createNewArrow({
from: new paper.Point(item.data.from),
prop: item.data.prop,
scale: item.data.scale || {h:1, v:1}
}, listening);
newArrow.opacity = opacity;
_setColor.call(newArrow, newArrow.data.getColor());
_setFill.call(newArrow, newArrow.data.prop.fill, newArrow.data.getColorBgD());
_setStrokeWidth.call(newArrow, symbolItem.strokeWidth);
drawArrow(newArrow, {
from: newArrow.data.from,
to: new paper.Point(item.data.to)
});
curLayer.activate();
return newArrow;
}
// ----- Item -----------------------------------------
var _arrowSymbol,
_arrowLeftMostPt,
_arrowHeadLeftMostPt,
_arrowRightMostPt,
_arrowMinLength;
function initArrowSymbol() {
if (_arrowSymbol)
return;
var defPath = new paper.Path({
segments: [
[0, -5],
[0 , 5],
new paper.Segment([20, 5]),
[10, 30],
new paper.Segment([50, 0]),
[10, -30],
new paper.Segment([20, -5])
],
strokeJoin: 'round',
strokeScaling: false,
closed: true
});
_arrowLeftMostPt = 1;
_arrowHeadLeftMostPt = 3;
_arrowRightMostPt = 4;
_arrowMinLength = defPath.segments[_arrowHeadLeftMostPt].point.x - defPath.segments[_arrowLeftMostPt].point.x;
_arrowSymbol = new paper.Symbol(defPath);
defPath.remove();
}
function _hitArrowHead(point, arrowItem) {
arrowItem = arrowItem || this;
var a = arrowItem.symbol.definition.segments[2].point.x,
b = arrowItem.symbol.definition.segments[_arrowRightMostPt].point.x,
c = arrowItem.globalToLocal(point).x;
return ((c - a) / (b - a)) > 0.1;
}
function _minArrowLength(length, arrowItem) {
arrowItem = arrowItem || this;
length = length || (
arrowItem.symbol.definition.segments[_arrowRightMostPt].point.x - arrowItem.symbol.definition.segments[_arrowLeftMostPt].point.x
);
var b = (arrowItem.symbol.definition.segments[_arrowRightMostPt].point.x - arrowItem.symbol.definition.segments[_arrowHeadLeftMostPt].point.x);
return (length - b) < _arrowMinLength;
}
/**
* Create a new Arrow item.
* If '''eventListening''' is false, won't listen to mouse or keyboard event,
* any other value is considered as true, including undefined
*
* @param params
* @param eventListening
* @returns {M.PlacedSymbol}
*/
function createNewArrow(params, eventListening) {
var newArrow, width, from ,to, scale;
initArrowSymbol();
newArrow = new paper.PlacedSymbol(_arrowSymbol.clone());
width = newArrow.symbol.definition.bounds.width;
from = new paper.Point(params.from);
to = new paper.Point([from.x + width, from.y]);
scale = params.scale || {h:1, v:1};
// Extend tool's item properties with default values
params.prop = (typeof params.prop === 'object') ? params.prop : {};
for (var p in defaultProperties) {
if (!params.prop.hasOwnProperty(p))
params.prop[p] = defaultProperties[p];
}
newArrow.pivot = [-width/2, 0];
drawArrow(newArrow, {from: from, to: to});
_scaleArrow.call(newArrow, scale);
console.log(params.prop.fill +' - '+_getColorBg(params.prop.category) +" - "+_getColor(params.prop.category));
_setFill.call(newArrow, params.prop.fill, _getColorBg(params.prop.category));
_setColor.call(newArrow, _getColor(params.prop.category));
_setStrokeWidth.call(newArrow, paper.project.currentStyle.strokeWidth);
newArrow.data = {
tId: "a" + newArrow._id,
type: TOOL_TYPE,
prop: params.prop,
from: from,
to: to,
scale: scale,
// Handlers
setColor: _setColor,
getColor: _getColorD,
setFill: _setFill,
getFill: _getFill,
setStrokeWidth: _setStrokeWidth,
getStrokeWidth: _getStrokeWidth,
setCategory: _setCategory,
getColorBgD: _getColorBgD,
// Mouse drag
setDragMode: setDragMode,
itemMouseDrag: itemMouseDrag
};
if (eventListening !== false) {
newArrow.onMouseDown = itemMouseDown;
newArrow.onMouseUp = itemMouseUp;
newArrow.onPropertyChange = itemPropertyChange;
}
return newArrow;
}
function _updateDataPos() {
this.data.from = this.position;
this.data.to = this.data.from.add(new paper.Point({
length: this.symbol.definition.bounds.width,
angle: this.rotation
}));
}
function _scaleArrow(scale) {
var w = _arrowSymbol.definition.bounds.width;
this.symbol.definition.scale(scale.h, scale.v, [-w/2,0]);
if (!this.data.scale)
this.data.scale = {h:1, v:1};
this.data.scale.h *= scale.h;
this.data.scale.v *= scale.v;
_updateDataPos.call(this);
}
// ===== Attributes setters and getters =====
// this represent the arrow instance
function _setColor(color) {
this.symbol.definition.strokeColor = color;
/*if (this.symbol.definition.fillColor.alpha > 0) {
this.symbol.definition.fillColor = color;
}*/
}
function _getColorD() {
//return this.symbol.definition.strokeColor;
if (this.prop){
var category = Category.getCategory(this.prop.category),
color = (category && category.color) || "#000000";
return color;
} else {
return "#000000";
}
}
function _setFill(isFill, color) {
if (isFill) {
this.symbol.definition.fillColor = color;
} else {
this.symbol.definition.fillColor = _transparent;
}
}
function _getFill() {
//return this.symbol.definition.fillColor.alpha > 0;
return _getColorBgD();
}
function _setStrokeWidth(width) {
this.symbol.definition.strokeWidth = width;
}
function _getStrokeWidth() {
return this.symbol.definition.strokeWidth;
}
var DRAG_MODES = {
FULL_DRAG: 1,
DRAG_TO: 2,
DRAG_FROM: 3,
DRAG_HANDLE: 4
};
var _dragMode = null;
var _dragOpts = {};
var _dragModified = false; // this is set to true if a drag event changed the item and need to emmit a change event
function setDragMode(mode, opts) {
if (! mode in DRAG_MODES) {
_dragMode = null;
_dragOpts = {};
_dragModified = false;
} else {
_dragMode = DRAG_MODES[mode];
_dragOpts = opts;
}
}
function itemMouseDown(event) {
if (!this.selected) return;
if (_ro) return;
_dragMode = DRAG_MODES.FULL_DRAG;
var toPt = this.data.to;
var fromPt = this.data.from;
// if (toPt.getDistance(event.point) < 20) {
if (_hitArrowHead.call(this, event.point)) {
setDragMode('DRAG_TO', {
delta: toPt.subtract(event.point)
});
}
else if (fromPt.getDistance(event.point) < 30) {
setDragMode('DRAG_FROM', {
delta: fromPt.subtract(event.point)
});
}
this.attach('mousedrag', itemMouseDrag);
}
function itemMouseDrag(event) {
if (_ro) return;
_dragModified = true;
var param = {
from: this.data.from,
to: this.data.to
};
switch(_dragMode) {
case DRAG_MODES.FULL_DRAG:
this.translate(event.delta);
_updateDataPos.call(this);
break;
case DRAG_MODES.DRAG_TO:
param.to = _dragOpts.delta ? event.point.add(_dragOpts.delta) : event.point;
delete(param.from);
drawArrow(this, param);
break;
case DRAG_MODES.DRAG_FROM:
param.from = _dragOpts.delta ? event.point.add(_dragOpts.delta) : event.point;
delete(param.to);
drawArrow(this, param);
break;
case DRAG_MODES.DRAG_HANDLE:
if (_dragOpts.nameParts[1] !== 'right') {
_dragModified = false;
} else {
// projection of the mouse point on the axe of the arrow. relative vector (centered at the origin)
var p = event.point.subtract(param.from).project(param.to.subtract(param.from));
var h_fact = p.length / this.symbol.definition.bounds.width;
var v_fact = (event.event.shiftKey) ? h_fact :
event.point.subtract(p.add(param.from)).length / this.symbol.definition.bounds.height * 2;
_scaleArrow.call(this, {h:h_fact, v:v_fact});
}
break;
default:
_dragModified = false;
break;
}
}
function itemMouseUp(event) {
this.detach('mousedrag', itemMouseDrag);
_updateDataPos.call(this);
_dragMode = null;
if (_dragModified) {
_events.annotationChanged.dispatch(this);
}
_dragModified = false;
}
function itemPropertyChange(property, value) {
if (property === 'category') {
_setCategory.call(this, value);
if (this.data.prop.fill) {
_setColor.call(this, _getColor(value));
_setFill.call(this, true, _getColorBg(value));
}else{
_setColor.call(this, _getColor(value));
}
paper.view.draw();
} else if (property === 'fill') {
_setFill.call(this, value, _getColorBg(this.data.prop.category));
paper.view.draw();
}
}
// ===== Drawing functions
function drawArrow(instance, params) {
var vect, angle, curWidth, deltaWidth, movingPt = "";
if (!params.from) {
params.from = instance.data.from;
movingPt = "to";
}
if (!params.to) {
params.to = instance.data.to;
movingPt = "from";
}
vect = params.to.subtract(params.from);
angle = vect.angle;
curWidth = instance.symbol.definition.bounds.width;
deltaWidth = vect.length - curWidth;
// Check if min length will be reached
if (_minArrowLength.call(instance, curWidth + deltaWidth)) {
// nullify the length change
deltaWidth = 0;
if (movingPt === "from") {
// Calculate the new target point from the end of the arrow, the desired angle and the current width
params.from = params.to.subtract(new paper.Point({length: curWidth, angle: angle}));
}
}
// Apply rotation and shift of the position
instance.rotation = angle;
instance.position = params.from;
// Modify the length of the arrow, not scaling it
if (deltaWidth !== 0) {
for (var idx = 2, s; s = instance.symbol.definition.segments[idx]; idx++) {
s.point.x += deltaWidth;
}
}
// store new values in data
instance.data.from = params.from;
instance.data.to = params.to;
}
// ----- Utilities ------------------------------------
function _getAnnotationFromItem(item) {
if (item.data && item.data.type === TOOL_TYPE) {
return item;
} else if (item.parent) {
return _getAnnotationFromItem(item.parent);
} else {
return null;
}
}
function _hitOnArrowTest(point) {
var hitResult, hitArrow;
// Check if hit on a selected arrow or on its bounds
hitResult = paper.project.activeLayer.hitTest(point,{
tolerance: 7,
fill: true,
stroke: true,
segments: true,
handles: true,
ends: true,
bounds: true,
selected: true
});
// If nothing found, check if hit on a not yet selected arrow
if (!hitResult) {
hitResult = paper.project.activeLayer.hitTest(point, {
fill: true,
stroke: true
});
}
if (!hitResult || !hitResult.item) {
return false;
} else {
hitArrow = _getAnnotationFromItem(hitResult.item);
if (!hitArrow)
return false;
hitArrow.selected = true;
if (hitResult.type === 'bounds') {
var p = hitResult.name.split('-');
if (p[1] === 'right') {
setDragMode('DRAG_HANDLE', {
nameStr: hitResult.name,
nameParts: hitResult.name.split('-'),
item: hitArrow
});
}
}
}
return true;
}
// ----- Functions ------------------------------------
function _setCategory(catId) {
defaultProperties.category = catId;
}
function _getColor(catId) {
var category = Category.getCategory(catId),
color = (category && category.color) || "#000000";
return color;
}
function _getColorBg(catId) {
var category = Category.getCategory(catId),
color = (category && category.colorbg) || "#000000";
return color;
}
function _getColorBgD() {
if (this.prop){
var category = Category.getCategory(this.prop.category),
color = (category && category.colorbg) || "#000000";
return color;
} else {
return "#000000";
}
}
// ----- Tool -----------------------------------------
var _create = false;
var _startPoint = null;
var _creatingArrow = null;
var toolDef = {
onMouseDown: function(event) {
if (_ro) return;
var hitAnnot;
_create = false;
_creatingArrow = null;
if (!_hitOnArrowTest(event.point)) {
paper.project.deselectAll();
_events.annotationSelected.dispatch(null);
// lets create a new arrow
_create = true;
_startPoint = event.point;
_creatingArrow = createNewArrow({from: _startPoint}, true);
_creatingArrow.visible = false;
}
},
onMouseDrag: function(event) {
if (_ro) return;
if (_create && _creatingArrow) {
drawArrow(_creatingArrow, {from: _startPoint, to:event.point});
_creatingArrow.visible = true;
}
else if (_dragMode === DRAG_MODES.DRAG_HANDLE && _dragOpts.item) {
itemMouseDrag.call(_dragOpts.item, event);
}
},
onMouseUp: function(event) {
setDragMode(null);
if (_create && _creatingArrow) {
_events.annotationAdded.dispatch(_creatingArrow);
_create = false;
_creatingArrow.selected = true;
_creatingArrow.visible = true;
_creatingArrow = null;
}
}
};
function _setRo(ro) {
if (ro !== _ro)
_ro = ro;
return _ro;
}
// ----- Returned Module ------------------------------
return {
name: TOOL_TYPE,
tool: new paper.Tool(toolDef),
setRo: _setRo,
registerEvent: function(eventName, evt) { _events[eventName] = evt; },
exportJSON: exportJSON,
importJSON: importJSON,
listeners: {
}
};
});
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment