Gitlab CSE Unil

Commit 67a9000e authored by M. Chardon's avatar M. Chardon
Browse files

ajout zone discordance

parent 3f0accab
......@@ -52,39 +52,68 @@ define([
* this area was created/edited, so we don't need to update the count for other area.
*/
function updateAreaIntersectionCount(annotation) {
// If annotation is not area or concordant stria, there is no need for computation
if (annotation && ['cmsarea', 'concordantstr'].indexOf(annotation.data.type) < 0)
return;
if (!userLayer) {
userLayer = view.getOrCreateUserLayer(config.user.id, config.user.full_name)
}
if (!userLayer) return;
var zones = userLayer.children.filter(function (a) {
return a.data.type && a.data.type === 'cmsarea';
});
var striae = userLayer.children.filter(function (a) {
return a.data.type && a.data.type === 'concordantstr';
});
// If the current selection is an area, keep it's current nbConcordances
var items = paper.project.getSelectedItems();
var selectedArea = (items.length === 1 && items[0].data.type === 'cmsarea') ? items[0] : null;
var selectedAreaCount = selectedArea ? selectedArea.data.prop.nbConcordances : null;
// If annotation is not area or concordant stria, there is no need for computation
if (annotation && ['cmsarea', 'concordantstr'].indexOf(annotation.data.type) >= 0) {
var zonesCms = userLayer.children.filter(function (a) {
return a.data.type && a.data.type === 'cmsarea';
});
var striaeCms = userLayer.children.filter(function (a) {
return a.data.type && a.data.type === 'concordantstr';
});
// If the current selection is an area, keep it's current nbConcordances
var items = paper.project.getSelectedItems();
var selectedArea = (items.length === 1 && items[0].data.type === 'cmsarea') ? items[0] : null;
var selectedAreaCount = selectedArea ? selectedArea.data.prop.nbConcordances : null;
var zone, nbInter, i, ii, nbStria = striaeCms.length;
for (i = 0; zone = zonesCms[i]; i++) {
nbInter = 0;
for (ii = 0; ii < nbStria; ii++) {
nbInter += Math.round(zone.getIntersections(striaeCms[ii]).length / 2);
}
zone.data.prop.nbConcordances = nbInter;
}
var zone, nbInter, i, ii, nbStria = striae.length;
for (i = 0; zone = zones[i]; i++) {
nbInter = 0;
for (ii = 0; ii < nbStria; ii++) {
nbInter += Math.round(zone.getIntersections(striae[ii]).length / 2);
if (selectedAreaCount !== null && selectedArea.data.prop.nbConcordances !== selectedAreaCount) {
ui.displayProperties(selectedArea);
}
zone.data.prop.nbConcordances = nbInter;
}
if (selectedAreaCount !== null && selectedArea.data.prop.nbConcordances !== selectedAreaCount) {
ui.displayProperties(selectedArea);
if (annotation && ['dcmsarea', 'discordantstr'].indexOf(annotation.data.type) >= 0) {
var zonesDcms = userLayer.children.filter(function (a) {
return a.data.type && a.data.type === 'dcmsarea';
});
var striaeDcms = userLayer.children.filter(function (a) {
return a.data.type && a.data.type === 'discordantstr';
});
// If the current selection is an area, keep it's current nbConcordances
var items = paper.project.getSelectedItems();
var selectedArea = (items.length === 1 && items[0].data.type === 'dcmsarea') ? items[0] : null;
var selectedAreaCount = selectedArea ? selectedArea.data.prop.nbDiscordances : null;
var zone, nbInter, i, ii, nbStria = striaeDcms.length;
for (i = 0; zone = zonesDcms[i]; i++) {
nbInter = 0;
for (ii = 0; ii < nbStria; ii++) {
nbInter += Math.round(zone.getIntersections(striaeDcms[ii]).length / 2);
}
zone.data.prop.nbDiscordances = nbInter;
}
if (selectedAreaCount !== null && selectedArea.data.prop.nbDiscordances !== selectedAreaCount) {
ui.displayProperties(selectedArea);
}
}
}
tools.events.annotationAdded.add(function (annotation) {
......@@ -103,6 +132,7 @@ define([
var concordantstrTool = tools.tools['concordantstr'];
var discordantstrTool = tools.tools['discordantstr'];
var cmsareaTool = tools.tools['cmsarea'];
var dcmsareaTool = tools.tools['dcmsarea'];
var cutPos = annotableData.envparam && annotableData.envparam.cimaf_cut_pos;
var cutMargin = annotableData.envparam && annotableData.envparam.cimaf_cut_margin;
......@@ -116,6 +146,8 @@ define([
discordantstrTool.listeners.onCutPositionChanged(cutPos);
cmsareaTool.listeners.onCutPositionChanged(cutPos);
cmsareaTool.listeners.onSetAreaWidth(cutMargin * 2);
dcmsareaTool.listeners.onCutPositionChanged(cutPos);
dcmsareaTool.listeners.onSetAreaWidth(cutMargin * 2);
});
}, 100);
......
......@@ -38,6 +38,7 @@ define([
"tools/concordantstr",
"tools/discordantstr",
"tools/cmsarea",
"tools/dcmsarea",
// ----- ANODATE tool
"tools/marker",
......
/**
* Copyright (C) 2019 Université de Lausanne, RISET,
* < http://www.unil.ch/riset/ >
* This file is part of AdIm.
* AdIm is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* AdIm is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* This copyright notice MUST APPEAR in all copies of the file.
*
* @AUTHOR: Marion Chardon <Marion.Chardon@unil.ch>
*
*/
define(["paper"], function (paper) {
// ----- Const ----------------------------------------
var TOOL_TYPE = 'dcmsarea';
// ----- Local variables ------------------------------
// Events
var _events = {
annotationAdded: null,
annotationSelected: null,
annotationChanged: null
};
//var activated = false;
var _cutPosition = 0;
var _areaWidth = 50;
var _aw = _areaWidth / 2;
var areaStyle = {
strokeWidth: 2,
fillColor: new paper.Color(.701960784, .901960784, 1, 0.66),
strokeColor: '#33bbff',
opacity: 0.5
};
var hitOptions = {
segments: true,
stroke: false,
fill: true,
tolerance: 20,
bounds: false,
handles: false
};
var _noop = function() {};
// ----- Listeners ------------------------------------
// ----- Functions -----------------------------------
function exportJSON(param) {
var json = this.exportJSON({asString:false});
if (!json[1].strokeColor) {
json[1].strokeWidth = 0;
}
delete(json[1].fontFamily);
delete(json[1].font);
delete(json[1].fontSize);
delete(json[1].leading);
return (param && param.asString) ? JSON.stringify(json) : json;
}
function importJSON(itemDef, layer, listening) {
var item = itemDef[1];
var curLayer = paper.project.activeLayer;
layer.activate();
var newArea = createNewZone({
from: item.segments[0][1],
to: item.segments[2][1],
prop: item.data.prop
});
curLayer.activate();
return newArea;
}
function _cutPositionChanged(newCutPosition) {
_cutPosition = newCutPosition;
}
function _setAreaWidth(width) {
_areaWidth = width;
_aw = _areaWidth / 2;
}
function onToolActivated(toolName) {
//activated = toolName === TOOL_TYPE;
}
var create = true;
var _startPoint = null;
var _drawingArea = null;
var terminateOnRelease = false;
var _editedArea = null,
_editedDirection = null;
var _areaChanged = false;
var defaultProperties = {
comment: ""
};
/***
* Create a new zone
* @param {object} o the parameters of the new zone
* @param {boolean} [noEventListening] Set to true to disable event listening on the item
* @returns {paper.Path|u}
*/
function createNewZone(o, noEventListening) {
var newArea = new paper.Path({
segments: [
[_cutPosition - _aw, o.from],
[_cutPosition + _aw, o.from],
[_cutPosition + _aw, o.to],
[_cutPosition - _aw, o.to]
],
closed: true,
style: areaStyle
});
// Extend stria properties with default values
o.prop = (typeof o.prop === 'object') ? o.prop : {};
for (var p in defaultProperties) {
if (!o.prop.hasOwnProperty(p))
o.prop[p] = defaultProperties[p];
}
newArea.data = {
tId: "a" + newArea._id,
type: TOOL_TYPE,
prop: o.prop,
setStrokeWidth: _noop,
// Mouse Event
itemMouseDrag: itemMouseDrag,
itemMouseUp: itemMouseUp
};
if (noEventListening !== true) {
newArea.onMouseDown = itemMouseDown;
newArea.onKeyDown = itemKeyDown;
newArea.onKeyUp = itemKeyUp;
}
return newArea;
}
/**
* Item (zone) event handler
* @param event
*/
function itemMouseDown(event) {
_editedDirection = null;
var hitItem = this;
hitItem.layer.activate();
paper.project.deselectAll();
hitItem.selected = true;
_events.annotationSelected.dispatch(hitItem);
_editedArea = hitItem;
// Determine the edited direction, if near the top, move the top
// if near the bottom, move the bottom, else translate
if (event.point.y - _editedArea.segments[0].point.y <= _aw) {
_editedDirection = 'up';
} else if (_editedArea.segments[2].point.y - event.point.y <= _aw) {
_editedDirection = 'down';
} else {
_editedDirection = null;
}
return false;
}
function itemMouseDrag(event) {
if (_editedDirection !== null) {
editArea(event);
} else if (_editedArea) {
dragArea(event);
}
}
function itemMouseUp(event) {
if (_editedArea && _areaChanged) {
_events.annotationChanged.dispatch([_editedArea]);
_areaChanged = false;
}
}
function itemKeyDown(event) {
var translateVector;
switch (event.key) {
case "up":
translateVector = [0, -1];
break;
case "down":
translateVector = [0, 1];
break;
}
if (translateVector) {
translateVector = new paper.Point(translateVector).multiply(
(paper.view.zoom < 4.5) ? 1 : 0.5
);
_editedArea = this;
this.translate(translateVector);
_areaChanged = true;
paper.view.draw();
}
}
function itemKeyUp(event) {
switch (event.key) {
case "up":
case "down":
if (_areaChanged) {
_events.annotationChanged.dispatch([_editedArea]);
_areaChanged = false;
}
break;
}
}
function cancelCreate() {
if (_drawingArea)
_drawingArea.remove();
_startPoint = null;
create = false;
_areaChanged = false;
}
function _terminateCreate() {
// Can be called
var dstPoint = _drawingArea ? _drawingArea.segments[3].point.clone() : null;
if (dstPoint) {
if (_drawingArea) {
_drawingArea.remove();
_drawingArea = null;
}
var newArea = createNewZone({from: _startPoint.y, to: dstPoint.y});
_events.annotationAdded.dispatch(newArea);
_areaChanged = false;
_startPoint = null;
create = false;
}
}
function drawArea(event) {
if (!_drawingArea) {
_drawingArea = new paper.Path({
segments: [
[_cutPosition - _aw, _startPoint.y],
[_cutPosition + _aw, _startPoint.y],
[_cutPosition + _aw, event.point.y],
[_cutPosition - _aw, event.point.y]
],
closed: true,
style: areaStyle,
dashArray: [10,5]
});
}
else {
_drawingArea.segments[2].point.y = event.point.y;
_drawingArea.segments[3].point.y = event.point.y;
}
}
/**
* Draw Stria while editing, the hit segment follow the mouse
* @param event
*/
function editArea(event) {
var i = _editedDirection === 'up' ? 0 : 2;
_editedArea.segments[i].point.y += event.delta.y;
_editedArea.segments[i+1].point.y += event.delta.y;
_areaChanged = true;
}
function dragArea(event) {
var delta = event.delta.clone();
delta.x = 0;
_editedArea.translate(delta);
_areaChanged = true;
}
// ----- Tool Def -------------------------------------
var toolDef = {
onMouseDown: function(event) {
if (_startPoint) {
// We are currently drawing an area, this mouse click will terminate the creation
// only if the drawing is not done by dragging the mouse
if (_drawingArea && !terminateOnRelease) {
_terminateCreate()
}
} else {
// The click MUST occur in the proximity of the cut, within the areaWidth
if (event.point.x < (_cutPosition - _aw - 5) || event.point.x > (_cutPosition + _aw + 5)) {
// outside of the active zone, deselect all and exit
paper.project.deselectAll();
_events.annotationSelected.dispatch(null);
return;
}
// The hit test is done along the cut, to ensure there are no zone overlap
var cutPoint = event.point.clone();
cutPoint.x = _cutPosition;
var hitResult = paper.project.activeLayer.hitTest(cutPoint, hitOptions);
var hitItem = null;
if (hitResult && hitResult.item.data && hitResult.item.data.type === TOOL_TYPE) {
hitItem = hitResult.item;
}
if (hitItem) {
// The click occurs on an existing zone (not an other item)
// Handled by the item itself
return false;
}
else {
// The click occurs along the cut, not an existing zone, create a new zone
_editedDirection = _editedArea = null;
paper.project.deselectAll();
_events.annotationSelected.dispatch(null);
if (!_startPoint) {
create = true;
if (_drawingArea)
_drawingArea.remove();
_drawingArea = null;
_startPoint = cutPoint;
terminateOnRelease = false;
}
}
}
},
onMouseDrag: function(event) {
if (create && _startPoint) {
terminateOnRelease = true;
drawArea(event);
} else if (_editedDirection !== null) {
editArea(event);
} else if (_editedArea) {
dragArea(event);
} else {
return false;
}
},
onMouseMove: function(event) {
if (create && _startPoint) {
drawArea(event);
}
},
onMouseUp: function(event) {
if (_startPoint) {
if (_drawingArea && terminateOnRelease) {
drawArea(event);
_terminateCreate()
}
} else if (_editedArea) {
_editedArea.data.itemMouseUp(event);
}
_editedDirection = _editedArea = null;
},
onKeyDown: function(event) {
switch (event.key) {
case "enter":
if (create)
_terminateCreate();
break;
case "escape":
if (create)
cancelCreate();
break;
case "up":
case"down":
var items = paper.project.getSelectedItems();
for (var i=0,item;item=items[i];i++){
if (item.data.type && typeof item.onKeyDown === 'function') {
item.onKeyDown(event);
break;
}
}
break;
}
},
onKeyUp: function(event) {
switch(event.key) {
case "up":
case"down":
var items = paper.project.getSelectedItems();
for (var i=0,item;item=items[i];i++){
if (item.data.type && typeof item.onKeyUp === 'function') {
item.onKeyUp(event);
break;
}
}
break;
}
}
};
// ----- Returned Module ------------------------------
return {
name: TOOL_TYPE,
tool: new paper.Tool(toolDef),
registerEvent: function(eventName, evt) { _events[eventName] = evt; },
exportJSON: exportJSON,
importJSON: importJSON,
listeners: {
onCutPositionChanged: _cutPositionChanged,
onSetAreaWidth: _setAreaWidth,
onToolActivated: onToolActivated
}
};
});
\ No newline at end of file
......@@ -1350,6 +1350,25 @@ define([
}
},
'nbDiscordances': {
el: "#prop-annot-nbdiscordance",
enable: function (status) {
status = (status !== void (0)) ? !!status : true;
if (!status) {
this.setValue("");
}
this.el.closest(".property-group").toggleClass("disabled", !status);
return this;
},
setValue: function (value) {
this.el.text(value);