Avoid overlaps in relation visualization
Change-Id: I69b0c297a3160b50f4c4cdf163f0966cdeef539d
diff --git a/dev/js/src/match/relations.js b/dev/js/src/match/relations.js
index 77d05ec..040a674 100644
--- a/dev/js/src/match/relations.js
+++ b/dev/js/src/match/relations.js
@@ -6,11 +6,16 @@
return {
create : function (snippet) {
var obj = Object.create(this)._init(snippet);
- obj._tokens = ["Das", "ist", "ja", "toll"];
+ obj._tokens = ["0", "1", "2", "3", "4", "5", "6", "7", "8"];
obj._tokenElements = [];
obj._arcs = [
- { start: 1, end: 3, label: "small" },
- { start: 3, end: 0, label: "large" }
+ { start: 0, end: 1, label: "a" },
+ { start: 0, end: 1, label: "b" },
+ { start: 1, end: 2, label: "c" },
+ { start: 0, end: 2, label: "d" },
+ { start: 1, end: 5, label: "e" },
+ { start: 4, end: 8, label: "f" },
+ { start: 6, end: 7, label: "g" },
]
obj.maxArc = 200; // maximum height of the bezier control point
return obj;
@@ -37,10 +42,10 @@
// Create an arc with a label
// Potentially needs a height parameter for stacks
- _createArc : function (start, end, label) {
+ _drawArc : function (arc) {
- var startPos = this._tokenPoint(this._tokenElements[start]);
- var endPos = this._tokenPoint(this._tokenElements[end]);
+ var startPos = this._tokenPoint(this._tokenElements[arc.first]);
+ var endPos = this._tokenPoint(this._tokenElements[arc.last]);
var y = 0;
var g = this._c("g");
@@ -49,22 +54,24 @@
// Create arc
var middle = Math.abs(endPos - startPos) / 2;
- var cHeight = middle < this.maxArc ? middle : this.maxArc;
+ // var cHeight = middle < this.maxArc ? middle : this.maxArc;
+ // TODO: take the number of tokens into account!
+ var cHeight = 10 + arc.overlaps * 12 + (middle / 2);
var x = Math.min(startPos, endPos);
- var arc = "M "+ startPos + " " + y +
+ var arcE = "M "+ startPos + " " + y +
" C " + startPos + " " + (y-cHeight) +
" " + endPos + " " + (y-cHeight) +
" " + endPos + " " + y;
- p.setAttribute("d", arc);
+ p.setAttribute("d", arcE);
- if (label !== undefined) {
+ if (arc.label !== undefined) {
var labelE = g.appendChild(this._c("text"));
labelE.setAttribute("x", x + middle);
- labelE.setAttribute("y", -1 * cHeight + 10);
+ labelE.setAttribute("y", -1 * cHeight);
labelE.setAttribute("text-anchor", "middle");
- labelE.appendChild(document.createTextNode(label));
+ labelE.appendChild(document.createTextNode(arc.label));
};
return g;
@@ -84,7 +91,7 @@
// Add a relation with a start, an end,
// a direction value and a label text
- addArc : function (start, end, direction, label) {
+ addArc : function (arc) {
},
/*
@@ -101,6 +108,73 @@
// -> found: Add +1 to the level of the (lpos)
// c) If the new tag is smaller than the previous element,
// reorder
+
+ // Normalize start and end
+ var sortedArcs = this._arcs.map(function (v) {
+ if (v.start < v.end) {
+ v.first = v.start;
+ v.last = v.end;
+ v.length = v.end - v.start;
+ }
+ else {
+ v.first = v.end;
+ v.last = v.start;
+ v.length = v.start - v.end;
+ };
+ return v;
+ });
+
+ // Sort based on length
+ sortedArcs.sort(function (a, b) {
+ if (a.length < b.length)
+ return -1;
+ else
+ return 1;
+ });
+
+ var arcStack = [];
+
+ // Iterate over all arc definitions
+ for (var i = 0; i < sortedArcs.length; i++) {
+ var currentArc = sortedArcs[i];
+
+ // Check the stack order
+ var overlaps = 0;
+
+ for (var j = (arcStack.length - 1); j >= 0; j--) {
+ var checkArc = arcStack[j];
+
+ // (a..(b..b)..a)
+ if (currentArc.first <= checkArc.first && currentArc.last >= checkArc.last) {
+ overlaps = checkArc.overlaps + 1;
+ break;
+ }
+
+ // (a..(b..a)..b)
+ else if (currentArc.first < checkArc.first && currentArc.last > checkArc.first) {
+ overlaps = checkArc.overlaps + (currentArc.length == checkArc.length ? 0 : 1);
+ }
+
+ // (b..(a..b)..a)
+ else if (currentArc.first < checkArc.last && currentArc.last > checkArc.last) {
+ overlaps = checkArc.overlaps + (currentArc.length == checkArc.length ? 0 : 1);
+ };
+ };
+
+ // Set overlaps
+ currentArc.overlaps = overlaps;
+
+ arcStack.push(currentArc);
+
+ // Although it is already sorted,
+ // the new item has to be put at the correct place
+ // TODO: Use something like splice() instead
+ arcStack.sort(function (a,b) {
+ b.overlaps - a.overlaps
+ });
+ };
+
+ return arcStack;
},
show : function () {
@@ -134,7 +208,7 @@
"transform",
"translate(0," + textBox.y +")"
);
-
+
/*
* TODO:
* Before creating the arcs, the height of the arc
@@ -142,9 +216,9 @@
* That means, the arcs need to be presorted, so massively
* overlapping arcs are taken first.
*/
- for (var i in this._arcs) {
- var arc = this._arcs[i];
- this.arcs.appendChild(this._createArc(arc.start, arc.end, arc.label));
+ var sortedArcs = this._sortArcs();
+ for (var i in sortedArcs) {
+ this.arcs.appendChild(this._drawArc(sortedArcs[i]));
};
}
}