Improve label positioning
Change-Id: I734f35f88d2e57fed4e9a49f780ad01c62c456bc
diff --git a/dev/js/src/match/relations.js b/dev/js/src/match/relations.js
index b1809a0..28a279b 100644
--- a/dev/js/src/match/relations.js
+++ b/dev/js/src/match/relations.js
@@ -6,23 +6,17 @@
return {
create : function (snippet) {
var obj = Object.create(this)._init(snippet);
- obj._tokens = ["Der", "alte", "Mann", "ging", "über", "die", "breite", "nasse", "Straße"];
+ obj._tokens = [];
obj._tokenElements = [];
- obj._arcs = [
+ obj._arcs = []
-
- /*
- * Start and end may be spans, i.e. arrays
- */
- { 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: [2,4], end: 5, label: "e" },
- { start: 4, end: [6,8], label: "f" },
- { start: [5,6], end: 7, label: "g" },
- ]
+ // Some configurations
obj.maxArc = 200; // maximum height of the bezier control point
+ obj.overlapDiff = 20;
+ obj.arcDiff = 15;
+ obj.anchorDiff = 6;
+ obj.anchorStart = 10;
+ obj.tokenSep = 30;
return obj;
},
@@ -49,7 +43,7 @@
var startPos = this._tokenElements[anchor.first].getBoundingClientRect().left;
var endPos = this._tokenElements[anchor.last].getBoundingClientRect().right;
- var y = (anchor.overlaps * -5) - 10;
+ var y = (anchor.overlaps * -1 * this.anchorDiff) - this.anchorStart; // - this.arcDiff;
var l = this._c('path');
l.setAttribute("d", "M " + startPos + " " + y + " L " + endPos + " " + y);
l.setAttribute("class", "anchor");
@@ -87,27 +81,53 @@
// Create arc
var middle = Math.abs(endPos - startPos) / 2;
- // 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 cHeight = this.arcDiff + arc.overlaps * this.overlapDiff + (middle / 2);
+
+ // Respect the maximum height
+ cHeight = cHeight < this.maxArc ? cHeight : this.maxArc;
var x = Math.min(startPos, endPos);
+
+ var controlY = (startY + endY - cHeight);
var arcE = "M "+ startPos + " " + startY +
- " C " + startPos + " " + (startY + endY - cHeight) +
- " " + endPos + " " + (startY + endY - cHeight) +
+ " C " + startPos + " " + controlY +
+ " " + endPos + " " + controlY +
" " + endPos + " " + endY;
p.setAttribute("d", arcE);
+ /*
+ * Calculate the top point of the arc for labeling using
+ * de Casteljau's algorithm, see e.g.
+ * http://blog.sklambert.com/finding-the-control-points-of-a-bezier-curve/
+ * of course simplified to symmetric arcs ...
+ */
+ // Interpolate one side of the control polygon
+ // var controlInterpY1 = (startY + controlY) / 2;
+ // var controlInterpY2 = (controlInterpY1 + controlY) / 2;
+ var middleY = (((startY + controlY) / 2) + controlY) / 2;
+
+ // WARNING!
+ // This won't respect span anchors, adjusting startY and endY!
+
if (arc.label !== undefined) {
var labelE = g.appendChild(this._c("text"));
labelE.setAttribute("x", x + middle);
- labelE.setAttribute("y", -1 * cHeight);
+ labelE.setAttribute("y", middleY + 3);
labelE.setAttribute("text-anchor", "middle");
labelE.appendChild(document.createTextNode(arc.label));
};
-
+
+ /*
+ var circle = this._c("circle");
+ circle.setAttribute("cx", x + middle);
+ circle.setAttribute("cy", middleY);
+ circle.setAttribute("r", 4);
+ circle.setAttribute("fill", "red");
+ g.appendChild(circle);
+ */
return g;
},
@@ -125,9 +145,17 @@
// Add a relation with a start, an end,
// a direction value and a label text
- addArc : function (arc) {
+ addRel : function (rel) {
+ this._arcs.push(rel);
+ return this;
},
+
+ addToken : function(token) {
+ this._tokens.push(token);
+ return this;
+ },
+
/*
* All arcs need to be sorted before shown,
* to avoid nesting.
@@ -227,7 +255,11 @@
this._tokenElements.push(tspan);
// Add whitespace!
- text.appendChild(document.createTextNode(" "));
+ // var whitespace = text.appendChild(document.createTextNode(" "));
+ var ws = text.appendChild(this._c("tspan"));
+ ws.appendChild(document.createTextNode(" "));
+ ws.setAttribute("class", "rel-ws");
+ ws.setAttribute("dx", this.tokenSep);
};
this.arcs = svg.appendChild(this._c("g"));