@joint/core 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. package/LICENSE +376 -0
  2. package/README.md +49 -0
  3. package/dist/geometry.js +6486 -0
  4. package/dist/geometry.min.js +8 -0
  5. package/dist/joint.d.ts +5536 -0
  6. package/dist/joint.js +39629 -0
  7. package/dist/joint.min.js +8 -0
  8. package/dist/joint.nowrap.js +39626 -0
  9. package/dist/joint.nowrap.min.js +8 -0
  10. package/dist/vectorizer.js +9135 -0
  11. package/dist/vectorizer.min.js +8 -0
  12. package/dist/version.mjs +3 -0
  13. package/index.js +3 -0
  14. package/joint.mjs +27 -0
  15. package/package.json +192 -0
  16. package/src/V/annotation.mjs +0 -0
  17. package/src/V/index.mjs +2642 -0
  18. package/src/anchors/index.mjs +123 -0
  19. package/src/config/index.mjs +12 -0
  20. package/src/connectionPoints/index.mjs +202 -0
  21. package/src/connectionStrategies/index.mjs +73 -0
  22. package/src/connectors/curve.mjs +553 -0
  23. package/src/connectors/index.mjs +6 -0
  24. package/src/connectors/jumpover.mjs +452 -0
  25. package/src/connectors/normal.mjs +12 -0
  26. package/src/connectors/rounded.mjs +17 -0
  27. package/src/connectors/smooth.mjs +44 -0
  28. package/src/connectors/straight.mjs +110 -0
  29. package/src/dia/Cell.mjs +945 -0
  30. package/src/dia/CellView.mjs +1316 -0
  31. package/src/dia/Element.mjs +519 -0
  32. package/src/dia/ElementView.mjs +859 -0
  33. package/src/dia/Graph.mjs +1112 -0
  34. package/src/dia/HighlighterView.mjs +319 -0
  35. package/src/dia/Link.mjs +565 -0
  36. package/src/dia/LinkView.mjs +2207 -0
  37. package/src/dia/Paper.mjs +3171 -0
  38. package/src/dia/PaperLayer.mjs +75 -0
  39. package/src/dia/ToolView.mjs +69 -0
  40. package/src/dia/ToolsView.mjs +128 -0
  41. package/src/dia/attributes/calc.mjs +128 -0
  42. package/src/dia/attributes/connection.mjs +75 -0
  43. package/src/dia/attributes/defs.mjs +76 -0
  44. package/src/dia/attributes/eval.mjs +64 -0
  45. package/src/dia/attributes/index.mjs +69 -0
  46. package/src/dia/attributes/legacy.mjs +148 -0
  47. package/src/dia/attributes/offset.mjs +53 -0
  48. package/src/dia/attributes/props.mjs +30 -0
  49. package/src/dia/attributes/shape.mjs +92 -0
  50. package/src/dia/attributes/text.mjs +180 -0
  51. package/src/dia/index.mjs +13 -0
  52. package/src/dia/layers/GridLayer.mjs +176 -0
  53. package/src/dia/ports.mjs +874 -0
  54. package/src/elementTools/Control.mjs +153 -0
  55. package/src/elementTools/HoverConnect.mjs +37 -0
  56. package/src/elementTools/index.mjs +5 -0
  57. package/src/env/index.mjs +43 -0
  58. package/src/g/bezier.mjs +175 -0
  59. package/src/g/curve.mjs +956 -0
  60. package/src/g/ellipse.mjs +245 -0
  61. package/src/g/extend.mjs +64 -0
  62. package/src/g/geometry.helpers.mjs +58 -0
  63. package/src/g/index.mjs +17 -0
  64. package/src/g/intersection.mjs +511 -0
  65. package/src/g/line.bearing.mjs +30 -0
  66. package/src/g/line.length.mjs +5 -0
  67. package/src/g/line.mjs +356 -0
  68. package/src/g/line.squaredLength.mjs +10 -0
  69. package/src/g/path.mjs +2260 -0
  70. package/src/g/point.mjs +375 -0
  71. package/src/g/points.mjs +247 -0
  72. package/src/g/polygon.mjs +51 -0
  73. package/src/g/polyline.mjs +523 -0
  74. package/src/g/rect.mjs +556 -0
  75. package/src/g/types.mjs +10 -0
  76. package/src/highlighters/addClass.mjs +27 -0
  77. package/src/highlighters/index.mjs +5 -0
  78. package/src/highlighters/list.mjs +111 -0
  79. package/src/highlighters/mask.mjs +220 -0
  80. package/src/highlighters/opacity.mjs +17 -0
  81. package/src/highlighters/stroke.mjs +100 -0
  82. package/src/layout/index.mjs +4 -0
  83. package/src/layout/ports/port.mjs +188 -0
  84. package/src/layout/ports/portLabel.mjs +224 -0
  85. package/src/linkAnchors/index.mjs +76 -0
  86. package/src/linkTools/Anchor.mjs +235 -0
  87. package/src/linkTools/Arrowhead.mjs +103 -0
  88. package/src/linkTools/Boundary.mjs +48 -0
  89. package/src/linkTools/Button.mjs +121 -0
  90. package/src/linkTools/Connect.mjs +85 -0
  91. package/src/linkTools/HoverConnect.mjs +161 -0
  92. package/src/linkTools/Segments.mjs +393 -0
  93. package/src/linkTools/Vertices.mjs +253 -0
  94. package/src/linkTools/helpers.mjs +33 -0
  95. package/src/linkTools/index.mjs +8 -0
  96. package/src/mvc/Collection.mjs +560 -0
  97. package/src/mvc/Data.mjs +46 -0
  98. package/src/mvc/Dom/Dom.mjs +587 -0
  99. package/src/mvc/Dom/Event.mjs +130 -0
  100. package/src/mvc/Dom/animations.mjs +122 -0
  101. package/src/mvc/Dom/events.mjs +69 -0
  102. package/src/mvc/Dom/index.mjs +13 -0
  103. package/src/mvc/Dom/methods.mjs +392 -0
  104. package/src/mvc/Dom/props.mjs +77 -0
  105. package/src/mvc/Dom/vars.mjs +5 -0
  106. package/src/mvc/Events.mjs +337 -0
  107. package/src/mvc/Listener.mjs +33 -0
  108. package/src/mvc/Model.mjs +239 -0
  109. package/src/mvc/View.mjs +323 -0
  110. package/src/mvc/ViewBase.mjs +182 -0
  111. package/src/mvc/index.mjs +9 -0
  112. package/src/mvc/mvcUtils.mjs +90 -0
  113. package/src/polyfills/array.js +4 -0
  114. package/src/polyfills/base64.js +68 -0
  115. package/src/polyfills/index.mjs +5 -0
  116. package/src/polyfills/number.js +3 -0
  117. package/src/polyfills/string.js +3 -0
  118. package/src/polyfills/typedArray.js +47 -0
  119. package/src/routers/index.mjs +6 -0
  120. package/src/routers/manhattan.mjs +856 -0
  121. package/src/routers/metro.mjs +91 -0
  122. package/src/routers/normal.mjs +6 -0
  123. package/src/routers/oneSide.mjs +60 -0
  124. package/src/routers/orthogonal.mjs +323 -0
  125. package/src/routers/rightAngle.mjs +1056 -0
  126. package/src/shapes/index.mjs +3 -0
  127. package/src/shapes/standard.mjs +755 -0
  128. package/src/util/cloneCells.mjs +67 -0
  129. package/src/util/getRectPoint.mjs +65 -0
  130. package/src/util/index.mjs +5 -0
  131. package/src/util/svgTagTemplate.mjs +110 -0
  132. package/src/util/util.mjs +1754 -0
  133. package/src/util/utilHelpers.mjs +2402 -0
  134. package/src/util/wrappers.mjs +56 -0
  135. package/types/geometry.d.ts +815 -0
  136. package/types/index.d.ts +53 -0
  137. package/types/joint.d.ts +4391 -0
  138. package/types/joint.head.d.ts +12 -0
  139. package/types/vectorizer.d.ts +327 -0
@@ -0,0 +1,91 @@
1
+ import { manhattan } from './manhattan.mjs';
2
+ import * as util from '../util/index.mjs';
3
+ import * as g from '../g/index.mjs';
4
+
5
+ var config = {
6
+
7
+ maxAllowedDirectionChange: 45,
8
+
9
+ // cost of a diagonal step
10
+ diagonalCost: function() {
11
+
12
+ var step = this.step;
13
+ return Math.ceil(Math.sqrt(step * step << 1));
14
+ },
15
+
16
+ // an array of directions to find next points on the route
17
+ // different from start/end directions
18
+ directions: function() {
19
+
20
+ var step = this.step;
21
+ var cost = this.cost();
22
+ var diagonalCost = this.diagonalCost();
23
+
24
+ return [
25
+ { offsetX: step, offsetY: 0, cost: cost },
26
+ { offsetX: step, offsetY: step, cost: diagonalCost },
27
+ { offsetX: 0, offsetY: step, cost: cost },
28
+ { offsetX: -step, offsetY: step, cost: diagonalCost },
29
+ { offsetX: -step, offsetY: 0, cost: cost },
30
+ { offsetX: -step, offsetY: -step, cost: diagonalCost },
31
+ { offsetX: 0, offsetY: -step, cost: cost },
32
+ { offsetX: step, offsetY: -step, cost: diagonalCost }
33
+ ];
34
+ },
35
+
36
+ // a simple route used in situations when main routing method fails
37
+ // (exceed max number of loop iterations, inaccessible)
38
+ fallbackRoute: function(from, to, opt) {
39
+
40
+ // Find a route which breaks by 45 degrees ignoring all obstacles.
41
+
42
+ var theta = from.theta(to);
43
+
44
+ var route = [];
45
+
46
+ var a = { x: to.x, y: from.y };
47
+ var b = { x: from.x, y: to.y };
48
+
49
+ if (theta % 180 > 90) {
50
+ var t = a;
51
+ a = b;
52
+ b = t;
53
+ }
54
+
55
+ var p1 = (theta % 90) < 45 ? a : b;
56
+ var l1 = new g.Line(from, p1);
57
+
58
+ var alpha = 90 * Math.ceil(theta / 90);
59
+
60
+ var p2 = g.Point.fromPolar(l1.squaredLength(), g.toRad(alpha + 135), p1);
61
+ var l2 = new g.Line(to, p2);
62
+
63
+ var intersectionPoint = l1.intersection(l2);
64
+ var point = intersectionPoint ? intersectionPoint : to;
65
+
66
+ var directionFrom = intersectionPoint ? point : from;
67
+
68
+ var quadrant = 360 / opt.directions.length;
69
+ var angleTheta = directionFrom.theta(to);
70
+ var normalizedAngle = g.normalizeAngle(angleTheta + (quadrant / 2));
71
+ var directionAngle = quadrant * Math.floor(normalizedAngle / quadrant);
72
+
73
+ opt.previousDirectionAngle = directionAngle;
74
+
75
+ if (point) route.push(point.round());
76
+ route.push(to);
77
+
78
+ return route;
79
+ }
80
+ };
81
+
82
+ // public function
83
+ export const metro = function(vertices, opt, linkView) {
84
+
85
+ if (!util.isFunction(manhattan)) {
86
+ throw new Error('Metro requires the manhattan router.');
87
+ }
88
+
89
+ return manhattan(vertices, util.assign({}, config, opt), linkView);
90
+ };
91
+
@@ -0,0 +1,6 @@
1
+ // Does not make any changes to vertices.
2
+ // Returns the arguments that are passed to it, unchanged.
3
+ export const normal = function(vertices, opt, linkView) {
4
+
5
+ return vertices;
6
+ };
@@ -0,0 +1,60 @@
1
+ import * as util from '../util/index.mjs';
2
+
3
+ // Routes the link always to/from a certain side
4
+ //
5
+ // Arguments:
6
+ // padding ... gap between the element and the first vertex. :: Default 40.
7
+ // side ... 'left' | 'right' | 'top' | 'bottom' :: Default 'bottom'.
8
+ //
9
+ export const oneSide = function(vertices, opt, linkView) {
10
+
11
+ var side = opt.side || 'bottom';
12
+ var padding = util.normalizeSides(opt.padding || 40);
13
+
14
+ // LinkView contains cached source an target bboxes.
15
+ // Note that those are Geometry rectangle objects.
16
+ var sourceBBox = linkView.sourceBBox;
17
+ var targetBBox = linkView.targetBBox;
18
+ var sourcePoint = sourceBBox.center();
19
+ var targetPoint = targetBBox.center();
20
+
21
+ var coordinate, dimension, direction;
22
+
23
+ switch (side) {
24
+ case 'bottom':
25
+ direction = 1;
26
+ coordinate = 'y';
27
+ dimension = 'height';
28
+ break;
29
+ case 'top':
30
+ direction = -1;
31
+ coordinate = 'y';
32
+ dimension = 'height';
33
+ break;
34
+ case 'left':
35
+ direction = -1;
36
+ coordinate = 'x';
37
+ dimension = 'width';
38
+ break;
39
+ case 'right':
40
+ direction = 1;
41
+ coordinate = 'x';
42
+ dimension = 'width';
43
+ break;
44
+ default:
45
+ throw new Error('Router: invalid side');
46
+ }
47
+
48
+ // move the points from the center of the element to outside of it.
49
+ sourcePoint[coordinate] += direction * (sourceBBox[dimension] / 2 + padding[side]);
50
+ targetPoint[coordinate] += direction * (targetBBox[dimension] / 2 + padding[side]);
51
+
52
+ // make link orthogonal (at least the first and last vertex).
53
+ if ((direction * (sourcePoint[coordinate] - targetPoint[coordinate])) > 0) {
54
+ targetPoint[coordinate] = sourcePoint[coordinate];
55
+ } else {
56
+ sourcePoint[coordinate] = targetPoint[coordinate];
57
+ }
58
+
59
+ return [sourcePoint].concat(vertices, targetPoint);
60
+ };
@@ -0,0 +1,323 @@
1
+ import * as g from '../g/index.mjs';
2
+ import * as util from '../util/index.mjs';
3
+
4
+ // bearing -> opposite bearing
5
+ var opposites = {
6
+ N: 'S',
7
+ S: 'N',
8
+ E: 'W',
9
+ W: 'E'
10
+ };
11
+
12
+ // bearing -> radians
13
+ var radians = {
14
+ N: -Math.PI / 2 * 3,
15
+ S: -Math.PI / 2,
16
+ E: 0,
17
+ W: Math.PI
18
+ };
19
+
20
+ // HELPERS //
21
+
22
+ // returns a point `p` where lines p,p1 and p,p2 are perpendicular and p is not contained
23
+ // in the given box
24
+ function freeJoin(p1, p2, bbox) {
25
+
26
+ var p = new g.Point(p1.x, p2.y);
27
+ if (bbox.containsPoint(p)) p = new g.Point(p2.x, p1.y);
28
+ // kept for reference
29
+ // if (bbox.containsPoint(p)) p = null;
30
+
31
+ return p;
32
+ }
33
+
34
+ // returns either width or height of a bbox based on the given bearing
35
+ function getBBoxSize(bbox, bearing) {
36
+
37
+ return bbox[(bearing === 'W' || bearing === 'E') ? 'width' : 'height'];
38
+ }
39
+
40
+ // simple bearing method (calculates only orthogonal cardinals)
41
+ function getBearing(from, to) {
42
+
43
+ if (from.x === to.x) return (from.y > to.y) ? 'N' : 'S';
44
+ if (from.y === to.y) return (from.x > to.x) ? 'W' : 'E';
45
+ return null;
46
+ }
47
+
48
+ // transform point to a rect
49
+ function getPointBox(p) {
50
+
51
+ return new g.Rect(p.x, p.y, 0, 0);
52
+ }
53
+
54
+ function getPaddingBox(opt) {
55
+
56
+ // if both provided, opt.padding wins over opt.elementPadding
57
+ var sides = util.normalizeSides(opt.padding || opt.elementPadding || 20);
58
+
59
+ return {
60
+ x: -sides.left,
61
+ y: -sides.top,
62
+ width: sides.left + sides.right,
63
+ height: sides.top + sides.bottom
64
+ };
65
+ }
66
+
67
+ // return source bbox
68
+ function getSourceBBox(linkView, opt) {
69
+
70
+ return linkView.sourceBBox.clone().moveAndExpand(getPaddingBox(opt));
71
+ }
72
+
73
+ // return target bbox
74
+ function getTargetBBox(linkView, opt) {
75
+
76
+ return linkView.targetBBox.clone().moveAndExpand(getPaddingBox(opt));
77
+ }
78
+
79
+ // return source anchor
80
+ function getSourceAnchor(linkView, opt) {
81
+
82
+ if (linkView.sourceAnchor) return linkView.sourceAnchor;
83
+
84
+ // fallback: center of bbox
85
+ var sourceBBox = getSourceBBox(linkView, opt);
86
+ return sourceBBox.center();
87
+ }
88
+
89
+ // return target anchor
90
+ function getTargetAnchor(linkView, opt) {
91
+
92
+ if (linkView.targetAnchor) return linkView.targetAnchor;
93
+
94
+ // fallback: center of bbox
95
+ var targetBBox = getTargetBBox(linkView, opt);
96
+ return targetBBox.center(); // default
97
+ }
98
+
99
+ // PARTIAL ROUTERS //
100
+
101
+ function vertexVertex(from, to, bearing) {
102
+
103
+ var p1 = new g.Point(from.x, to.y);
104
+ var p2 = new g.Point(to.x, from.y);
105
+ var d1 = getBearing(from, p1);
106
+ var d2 = getBearing(from, p2);
107
+ var opposite = opposites[bearing];
108
+
109
+ var p = (d1 === bearing || (d1 !== opposite && (d2 === opposite || d2 !== bearing))) ? p1 : p2;
110
+
111
+ return { points: [p], direction: getBearing(p, to) };
112
+ }
113
+
114
+ function elementVertex(from, to, fromBBox) {
115
+
116
+ var p = freeJoin(from, to, fromBBox);
117
+
118
+ return { points: [p], direction: getBearing(p, to) };
119
+ }
120
+
121
+ function vertexElement(from, to, toBBox, bearing) {
122
+
123
+ var route = {};
124
+
125
+ var points = [new g.Point(from.x, to.y), new g.Point(to.x, from.y)];
126
+ var freePoints = points.filter(function(pt) {
127
+ return !toBBox.containsPoint(pt);
128
+ });
129
+ var freeBearingPoints = freePoints.filter(function(pt) {
130
+ return getBearing(pt, from) !== bearing;
131
+ });
132
+
133
+ var p;
134
+
135
+ if (freeBearingPoints.length > 0) {
136
+ // Try to pick a point which bears the same direction as the previous segment.
137
+
138
+ p = freeBearingPoints.filter(function(pt) {
139
+ return getBearing(from, pt) === bearing;
140
+ }).pop();
141
+ p = p || freeBearingPoints[0];
142
+
143
+ route.points = [p];
144
+ route.direction = getBearing(p, to);
145
+
146
+ } else {
147
+ // Here we found only points which are either contained in the element or they would create
148
+ // a link segment going in opposite direction from the previous one.
149
+ // We take the point inside element and move it outside the element in the direction the
150
+ // route is going. Now we can join this point with the current end (using freeJoin).
151
+
152
+ p = util.difference(points, freePoints)[0];
153
+
154
+ var p2 = (new g.Point(to)).move(p, -getBBoxSize(toBBox, bearing) / 2);
155
+ var p1 = freeJoin(p2, from, toBBox);
156
+
157
+ route.points = [p1, p2];
158
+ route.direction = getBearing(p2, to);
159
+ }
160
+
161
+ return route;
162
+ }
163
+
164
+ function elementElement(from, to, fromBBox, toBBox) {
165
+
166
+ var route = elementVertex(to, from, toBBox);
167
+ var p1 = route.points[0];
168
+
169
+ if (fromBBox.containsPoint(p1)) {
170
+
171
+ route = elementVertex(from, to, fromBBox);
172
+ var p2 = route.points[0];
173
+
174
+ if (toBBox.containsPoint(p2)) {
175
+
176
+ var fromBorder = (new g.Point(from)).move(p2, -getBBoxSize(fromBBox, getBearing(from, p2)) / 2);
177
+ var toBorder = (new g.Point(to)).move(p1, -getBBoxSize(toBBox, getBearing(to, p1)) / 2);
178
+ var mid = (new g.Line(fromBorder, toBorder)).midpoint();
179
+
180
+ var startRoute = elementVertex(from, mid, fromBBox);
181
+ var endRoute = vertexVertex(mid, to, startRoute.direction);
182
+
183
+ route.points = [startRoute.points[0], endRoute.points[0]];
184
+ route.direction = endRoute.direction;
185
+ }
186
+ }
187
+
188
+ return route;
189
+ }
190
+
191
+ // Finds route for situations where one element is inside the other.
192
+ // Typically the route is directed outside the outer element first and
193
+ // then back towards the inner element.
194
+ function insideElement(from, to, fromBBox, toBBox, bearing) {
195
+
196
+ var route = {};
197
+ var boundary = fromBBox.union(toBBox).inflate(1);
198
+
199
+ // start from the point which is closer to the boundary
200
+ var reversed = boundary.center().distance(to) > boundary.center().distance(from);
201
+ var start = reversed ? to : from;
202
+ var end = reversed ? from : to;
203
+
204
+ var p1, p2, p3;
205
+
206
+ if (bearing) {
207
+ // Points on circle with radius equals 'W + H` are always outside the rectangle
208
+ // with width W and height H if the center of that circle is the center of that rectangle.
209
+ p1 = g.Point.fromPolar(boundary.width + boundary.height, radians[bearing], start);
210
+ p1 = boundary.pointNearestToPoint(p1).move(p1, -1);
211
+
212
+ } else {
213
+ p1 = boundary.pointNearestToPoint(start).move(start, 1);
214
+ }
215
+
216
+ p2 = freeJoin(p1, end, boundary);
217
+
218
+ if (p1.round().equals(p2.round())) {
219
+ p2 = g.Point.fromPolar(boundary.width + boundary.height, g.toRad(p1.theta(start)) + Math.PI / 2, end);
220
+ p2 = boundary.pointNearestToPoint(p2).move(end, 1).round();
221
+ p3 = freeJoin(p1, p2, boundary);
222
+ route.points = reversed ? [p2, p3, p1] : [p1, p3, p2];
223
+
224
+ } else {
225
+ route.points = reversed ? [p2, p1] : [p1, p2];
226
+ }
227
+
228
+ route.direction = reversed ? getBearing(p1, to) : getBearing(p2, to);
229
+
230
+ return route;
231
+ }
232
+
233
+ // MAIN ROUTER //
234
+
235
+ // Return points through which a connection needs to be drawn in order to obtain an orthogonal link
236
+ // routing from source to target going through `vertices`.
237
+ export function orthogonal(vertices, opt, linkView) {
238
+
239
+ var sourceBBox = getSourceBBox(linkView, opt);
240
+ var targetBBox = getTargetBBox(linkView, opt);
241
+
242
+ var sourceAnchor = getSourceAnchor(linkView, opt);
243
+ var targetAnchor = getTargetAnchor(linkView, opt);
244
+
245
+ // if anchor lies outside of bbox, the bbox expands to include it
246
+ sourceBBox = sourceBBox.union(getPointBox(sourceAnchor));
247
+ targetBBox = targetBBox.union(getPointBox(targetAnchor));
248
+
249
+ vertices = util.toArray(vertices).map(g.Point);
250
+ vertices.unshift(sourceAnchor);
251
+ vertices.push(targetAnchor);
252
+
253
+ var bearing; // bearing of previous route segment
254
+
255
+ var orthogonalVertices = []; // the array of found orthogonal vertices to be returned
256
+ for (var i = 0, max = vertices.length - 1; i < max; i++) {
257
+
258
+ var route = null;
259
+
260
+ var from = vertices[i];
261
+ var to = vertices[i + 1];
262
+
263
+ var isOrthogonal = !!getBearing(from, to);
264
+
265
+ if (i === 0) { // source
266
+
267
+ if (i + 1 === max) { // route source -> target
268
+
269
+ // Expand one of the elements by 1px to detect situations when the two
270
+ // elements are positioned next to each other with no gap in between.
271
+ if (sourceBBox.intersect(targetBBox.clone().inflate(1))) {
272
+ route = insideElement(from, to, sourceBBox, targetBBox);
273
+
274
+ } else if (!isOrthogonal) {
275
+ route = elementElement(from, to, sourceBBox, targetBBox);
276
+ }
277
+
278
+ } else { // route source -> vertex
279
+
280
+ if (sourceBBox.containsPoint(to)) {
281
+ route = insideElement(from, to, sourceBBox, getPointBox(to).moveAndExpand(getPaddingBox(opt)));
282
+
283
+ } else if (!isOrthogonal) {
284
+ route = elementVertex(from, to, sourceBBox);
285
+ }
286
+ }
287
+
288
+ } else if (i + 1 === max) { // route vertex -> target
289
+
290
+ // prevent overlaps with previous line segment
291
+ var isOrthogonalLoop = isOrthogonal && getBearing(to, from) === bearing;
292
+
293
+ if (targetBBox.containsPoint(from) || isOrthogonalLoop) {
294
+ route = insideElement(from, to, getPointBox(from).moveAndExpand(getPaddingBox(opt)), targetBBox, bearing);
295
+
296
+ } else if (!isOrthogonal) {
297
+ route = vertexElement(from, to, targetBBox, bearing);
298
+ }
299
+
300
+ } else if (!isOrthogonal) { // route vertex -> vertex
301
+ route = vertexVertex(from, to, bearing);
302
+ }
303
+
304
+ // applicable to all routes:
305
+
306
+ // set bearing for next iteration
307
+ if (route) {
308
+ Array.prototype.push.apply(orthogonalVertices, route.points);
309
+ bearing = route.direction;
310
+
311
+ } else {
312
+ // orthogonal route and not looped
313
+ bearing = getBearing(from, to);
314
+ }
315
+
316
+ // push `to` point to identified orthogonal vertices array
317
+ if (i + 1 < max) {
318
+ orthogonalVertices.push(to);
319
+ }
320
+ }
321
+
322
+ return orthogonalVertices;
323
+ }