@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,1056 @@
1
+ import * as g from '../g/index.mjs';
2
+
3
+ const Directions = {
4
+ AUTO: 'auto',
5
+ LEFT: 'left',
6
+ RIGHT: 'right',
7
+ TOP: 'top',
8
+ BOTTOM: 'bottom',
9
+ ANCHOR_SIDE: 'anchor-side',
10
+ MAGNET_SIDE: 'magnet-side'
11
+ };
12
+
13
+ const DEFINED_DIRECTIONS = [Directions.LEFT, Directions.RIGHT, Directions.TOP, Directions.BOTTOM];
14
+
15
+ const OPPOSITE_DIRECTIONS = {
16
+ [Directions.LEFT]: Directions.RIGHT,
17
+ [Directions.RIGHT]: Directions.LEFT,
18
+ [Directions.TOP]: Directions.BOTTOM,
19
+ [Directions.BOTTOM]: Directions.TOP
20
+ };
21
+
22
+ const VERTICAL_DIRECTIONS = [Directions.TOP, Directions.BOTTOM];
23
+
24
+ const ANGLE_DIRECTION_MAP = {
25
+ 0: Directions.RIGHT,
26
+ 180: Directions.LEFT,
27
+ 270: Directions.TOP,
28
+ 90: Directions.BOTTOM
29
+ };
30
+
31
+ function getSegmentAngle(line) {
32
+ // TODO: the angle() method is general and therefore unnecessarily heavy for orthogonal links
33
+ return line.angle();
34
+ }
35
+
36
+ function simplifyPoints(points) {
37
+ // TODO: use own more efficient implementation (filter points that do not change direction).
38
+ // To simplify segments that are almost aligned (start and end points differ by e.g. 0.5px), use a threshold of 1.
39
+ return new g.Polyline(points).simplify({ threshold: 1 }).points;
40
+ }
41
+
42
+ function resolveSides(source, target) {
43
+ const { point: sourcePoint, x0: sx0, y0: sy0, view: sourceView, bbox: sourceBBox, direction: sourceDirection } = source;
44
+ const { point: targetPoint, x0: tx0, y0: ty0, view: targetView, bbox: targetBBox, direction: targetDirection } = target;
45
+
46
+ let sourceSide;
47
+
48
+ if (!sourceView) {
49
+ const sourceLinkAnchorBBox = new g.Rect(sx0, sy0, 0, 0);
50
+ sourceSide = DEFINED_DIRECTIONS.includes(sourceDirection) ? sourceDirection : sourceLinkAnchorBBox.sideNearestToPoint(targetPoint);
51
+ } else if (sourceView.model.isLink()) {
52
+ sourceSide = getDirectionForLinkConnection(targetPoint, sourcePoint, sourceView);
53
+ } else if (sourceDirection === Directions.ANCHOR_SIDE) {
54
+ sourceSide = sourceBBox.sideNearestToPoint(sourcePoint);
55
+ } else if (sourceDirection === Directions.MAGNET_SIDE) {
56
+ sourceSide = sourceView.model.getBBox().sideNearestToPoint(sourcePoint);
57
+ } else {
58
+ sourceSide = sourceDirection;
59
+ }
60
+
61
+ let targetSide;
62
+
63
+ if (!targetView) {
64
+ const targetLinkAnchorBBox = new g.Rect(tx0, ty0, 0, 0);
65
+ targetSide = DEFINED_DIRECTIONS.includes(targetDirection) ? targetDirection : targetLinkAnchorBBox.sideNearestToPoint(sourcePoint);
66
+ } else if (targetView.model.isLink()) {
67
+ targetSide = getDirectionForLinkConnection(sourcePoint, targetPoint, targetView);
68
+ } else if (targetDirection === Directions.ANCHOR_SIDE) {
69
+ targetSide = targetBBox.sideNearestToPoint(targetPoint);
70
+ } else if (targetDirection === Directions.MAGNET_SIDE) {
71
+ targetSide = targetView.model.getBBox().sideNearestToPoint(targetPoint);
72
+ } else {
73
+ targetSide = targetDirection;
74
+ }
75
+
76
+ return [sourceSide, targetSide];
77
+ }
78
+
79
+ function resolveForTopSourceSide(source, target, nextInLine) {
80
+ const { x0: sx0, y0: sy0, width, height, point: anchor, margin } = source;
81
+ const sx1 = sx0 + width;
82
+ const sy1 = sy0 + height;
83
+ const smx0 = sx0 - margin;
84
+ const smx1 = sx1 + margin;
85
+ const smy0 = sy0 - margin;
86
+
87
+ const { x: ax } = anchor;
88
+ const { x0: tx, y0: ty } = target;
89
+
90
+ if (tx === ax && ty < sy0) return Directions.BOTTOM;
91
+ if (tx < ax && ty < smy0) return Directions.RIGHT;
92
+ if (tx > ax && ty < smy0) return Directions.LEFT;
93
+ if (tx < smx0 && ty >= sy0) return Directions.TOP;
94
+ if (tx > smx1 && ty >= sy0) return Directions.TOP;
95
+ if (tx >= smx0 && tx <= ax && ty > sy1) {
96
+ if (nextInLine.point.x < tx) {
97
+ return Directions.RIGHT;
98
+ }
99
+
100
+ return Directions.LEFT;
101
+ }
102
+ if (tx <= smx1 && tx >= ax && ty > sy1) {
103
+ if (nextInLine.point.x < tx) {
104
+ return Directions.RIGHT;
105
+ }
106
+
107
+ return Directions.LEFT;
108
+ }
109
+
110
+ return Directions.TOP;
111
+ }
112
+
113
+ function resolveForBottomSourceSide(source, target, nextInLine) {
114
+ const { x0: sx0, y0: sy0, width, height, point: anchor, margin } = source;
115
+ const sx1 = sx0 + width;
116
+ const sy1 = sy0 + height;
117
+ const smx0 = sx0 - margin;
118
+ const smx1 = sx1 + margin;
119
+ const smy1 = sy1 + margin;
120
+
121
+ const { x: ax } = anchor;
122
+ const { x0: tx, y0: ty } = target;
123
+
124
+ if (tx === ax && ty > sy1) return Directions.TOP;
125
+ if (tx < ax && ty > smy1) return Directions.RIGHT;
126
+ if (tx > ax && ty > smy1) return Directions.LEFT;
127
+ if (tx < smx0 && ty <= sy1) return Directions.BOTTOM;
128
+ if (tx > smx1 && ty <= sy1) return Directions.BOTTOM;
129
+ if (tx >= smx0 && tx <= ax && ty < sy0) {
130
+ if (nextInLine.point.x < tx) {
131
+ return Directions.RIGHT;
132
+ }
133
+
134
+ return Directions.LEFT;
135
+ }
136
+ if (tx <= smx1 && tx >= ax && ty < sy0) {
137
+ if (nextInLine.point.x < tx) {
138
+ return Directions.RIGHT;
139
+ }
140
+
141
+ return Directions.LEFT;
142
+ }
143
+
144
+ return Directions.BOTTOM;
145
+ }
146
+
147
+ function resolveForLeftSourceSide(source, target, nextInLine) {
148
+ const { y0: sy0, x0: sx0, width, height, point: anchor, margin } = source;
149
+ const sx1 = sx0 + width;
150
+ const sy1 = sy0 + height;
151
+ const smx0 = sx0 - margin;
152
+ const smy0 = sy0 - margin;
153
+ const smy1 = sy1 + margin;
154
+
155
+ const { x: ax, y: ay } = anchor;
156
+ const { x0: tx, y0: ty } = target;
157
+
158
+ if (tx < ax && ty === ay) return Directions.RIGHT;
159
+ if (tx <= smx0 && ty < ay) return Directions.BOTTOM;
160
+ if (tx <= smx0 && ty > ay) return Directions.TOP;
161
+ if (tx >= sx0 && ty <= smy0) return Directions.LEFT;
162
+ if (tx >= sx0 && ty >= smy1) return Directions.LEFT;
163
+ if (tx > sx1 && ty >= smy0 && ty <= ay) {
164
+ if (nextInLine.point.y < ty) {
165
+ return Directions.BOTTOM;
166
+ }
167
+
168
+ return Directions.TOP;
169
+ }
170
+ if (tx > sx1 && ty <= smy1 && ty >= ay) {
171
+ if (nextInLine.point.y < ty) {
172
+ return Directions.BOTTOM;
173
+ }
174
+
175
+ return Directions.TOP;
176
+ }
177
+
178
+ return Directions.LEFT;
179
+ }
180
+
181
+ function resolveForRightSourceSide(source, target, nextInLine) {
182
+ const { y0: sy0, x0: sx0, width, height, point: anchor, margin } = source;
183
+ const sx1 = sx0 + width;
184
+ const sy1 = sy0 + height;
185
+ const smx1 = sx1 + margin;
186
+ const smy0 = sy0 - margin;
187
+ const smy1 = sy1 + margin;
188
+
189
+ const { x: ax, y: ay } = anchor;
190
+ const { x0: tx, y0: ty } = target;
191
+
192
+ if (tx > ax && ty === ay) return Directions.LEFT;
193
+ if (tx >= smx1 && ty < ay) return Directions.BOTTOM;
194
+ if (tx >= smx1 && ty > ay) return Directions.TOP;
195
+ if (tx <= sx1 && ty <= smy0) return Directions.RIGHT;
196
+ if (tx <= sx1 && ty >= smy1) return Directions.RIGHT;
197
+ if (tx < sx0 && ty >= smy0 && ty <= ay) {
198
+ if (nextInLine.point.y < ty) {
199
+ return Directions.BOTTOM;
200
+ }
201
+
202
+ return Directions.TOP;
203
+ }
204
+ if (tx < sx0 && ty <= smy1 && ty >= ay) {
205
+ if (nextInLine.point.y < ty) {
206
+ return Directions.BOTTOM;
207
+ }
208
+
209
+ return Directions.TOP;
210
+ }
211
+
212
+ return Directions.RIGHT;
213
+ }
214
+
215
+ function resolveInitialDirection(source, target, nextInLine) {
216
+ const [sourceSide] = resolveSides(source, target);
217
+
218
+ switch (sourceSide) {
219
+ case Directions.TOP:
220
+ return resolveForTopSourceSide(source, target, nextInLine);
221
+ case Directions.RIGHT:
222
+ return resolveForRightSourceSide(source, target, nextInLine);
223
+ case Directions.BOTTOM:
224
+ return resolveForBottomSourceSide(source, target, nextInLine);
225
+ case Directions.LEFT:
226
+ return resolveForLeftSourceSide(source, target, nextInLine);
227
+ }
228
+ }
229
+
230
+ function getDirectionForLinkConnection(linkOrigin, connectionPoint, linkView) {
231
+ const tangent = linkView.getTangentAtLength(linkView.getClosestPointLength(connectionPoint));
232
+ const roundedAngle = Math.round(getSegmentAngle(tangent) / 90) * 90;
233
+
234
+ if (roundedAngle % 180 === 0 && linkOrigin.y === connectionPoint.y) {
235
+ return linkOrigin.x < connectionPoint.x ? Directions.LEFT : Directions.RIGHT;
236
+ } else if (linkOrigin.x === connectionPoint.x) {
237
+ return linkOrigin.y < connectionPoint.y ? Directions.TOP : Directions.BOTTOM;
238
+ }
239
+
240
+ switch (roundedAngle) {
241
+ case 0:
242
+ case 180:
243
+ case 360:
244
+ return linkOrigin.y < connectionPoint.y ? Directions.TOP : Directions.BOTTOM;
245
+ case 90:
246
+ case 270:
247
+ return linkOrigin.x < connectionPoint.x ? Directions.LEFT : Directions.RIGHT;
248
+ }
249
+ }
250
+
251
+ function pointDataFromAnchor(view, point, bbox, direction, isPort, fallBackAnchor, margin) {
252
+ if (direction === Directions.AUTO) {
253
+ direction = isPort ? Directions.MAGNET_SIDE : Directions.ANCHOR_SIDE;
254
+ }
255
+
256
+ const isElement = view && view.model.isElement();
257
+
258
+ const {
259
+ x: x0,
260
+ y: y0,
261
+ width = 0,
262
+ height = 0
263
+ } = isElement ? g.Rect.fromRectUnion(bbox, view.model.getBBox()) : fallBackAnchor;
264
+
265
+ return {
266
+ point,
267
+ x0,
268
+ y0,
269
+ view,
270
+ bbox,
271
+ width,
272
+ height,
273
+ direction,
274
+ margin: isElement ? margin : 0
275
+ };
276
+ }
277
+
278
+ function pointDataFromVertex({ x, y }) {
279
+ const point = new g.Point(x, y);
280
+
281
+ return {
282
+ point,
283
+ x0: point.x,
284
+ y0: point.y,
285
+ view: null,
286
+ bbox: new g.Rect(x, y, 0, 0),
287
+ width: 0,
288
+ height: 0,
289
+ direction: null,
290
+ margin: 0
291
+ };
292
+ }
293
+
294
+ function getOutsidePoint(side, pointData, margin) {
295
+ const outsidePoint = pointData.point.clone();
296
+
297
+ const { x0, y0, width, height } = pointData;
298
+
299
+ switch (side) {
300
+ case 'left':
301
+ outsidePoint.x = x0 - margin;
302
+ break;
303
+ case 'right':
304
+ outsidePoint.x = x0 + width + margin;
305
+ break;
306
+ case 'top':
307
+ outsidePoint.y = y0 - margin;
308
+ break;
309
+ case 'bottom':
310
+ outsidePoint.y = y0 + height + margin;
311
+ break;
312
+ }
313
+
314
+ return outsidePoint;
315
+ }
316
+
317
+ function routeBetweenPoints(source, target) {
318
+ const { point: sourcePoint, x0: sx0, y0: sy0, view: sourceView, width: sourceWidth, height: sourceHeight, margin: sourceMargin } = source;
319
+ const { point: targetPoint, x0: tx0, y0: ty0, width: targetWidth, height: targetHeight, margin: targetMargin } = target;
320
+
321
+ const tx1 = tx0 + targetWidth;
322
+ const ty1 = ty0 + targetHeight;
323
+ const sx1 = sx0 + sourceWidth;
324
+ const sy1 = sy0 + sourceHeight;
325
+
326
+ const isSourceEl = sourceView && sourceView.model.isElement();
327
+
328
+ // Key coordinates including the margin
329
+ const smx0 = sx0 - sourceMargin;
330
+ const smx1 = sx1 + sourceMargin;
331
+ const smy0 = sy0 - sourceMargin;
332
+ const smy1 = sy1 + sourceMargin;
333
+
334
+ const tmx0 = tx0 - targetMargin;
335
+ const tmx1 = tx1 + targetMargin;
336
+ const tmy0 = ty0 - targetMargin;
337
+ const tmy1 = ty1 + targetMargin;
338
+
339
+ const [sourceSide, targetSide] = resolveSides(source, target);
340
+
341
+ const sourceOutsidePoint = getOutsidePoint(sourceSide, { point: sourcePoint, x0: sx0, y0: sy0, width: sourceWidth, height: sourceHeight }, sourceMargin);
342
+ const targetOutsidePoint = getOutsidePoint(targetSide, { point: targetPoint, x0: tx0, y0: ty0, width: targetWidth, height: targetHeight }, targetMargin);
343
+
344
+ const { x: sox, y: soy } = sourceOutsidePoint;
345
+ const { x: tox, y: toy } = targetOutsidePoint;
346
+ const tcx = (tx0 + tx1) / 2;
347
+ const tcy = (ty0 + ty1) / 2;
348
+ const scx = (sx0 + sx1) / 2;
349
+ const scy = (sy0 + sy1) / 2;
350
+ const middleOfVerticalSides = (scx < tcx ? (sx1 + tx0) : (tx1 + sx0)) / 2;
351
+ const middleOfHorizontalSides = (scy < tcy ? (sy1 + ty0) : (ty1 + sy0)) / 2;
352
+
353
+ if (sourceSide === 'left' && targetSide === 'right') {
354
+ if (smx0 <= tmx1) {
355
+ let y = middleOfHorizontalSides;
356
+ if (sx1 <= tx0) {
357
+ if (ty1 >= smy0 && toy < soy) {
358
+ y = Math.min(tmy0, smy0);
359
+ } else if (ty0 <= smy1 && toy >= soy) {
360
+ y = Math.max(tmy1, smy1);
361
+ }
362
+ }
363
+ return [
364
+ { x: sox, y: soy },
365
+ { x: sox, y },
366
+ { x: tox, y },
367
+ { x: tox, y: toy }
368
+ ];
369
+ }
370
+
371
+ const x = (sox + tox) / 2;
372
+ return [
373
+ { x, y: soy },
374
+ { x, y: toy }
375
+ ];
376
+ } else if (sourceSide === 'right' && targetSide === 'left') {
377
+ if (smx1 >= tmx0) {
378
+ let y = middleOfHorizontalSides;
379
+ if (sox > tx1) {
380
+ if (ty1 >= smy0 && toy < soy) {
381
+ y = Math.min(tmy0, smy0);
382
+ } else if (ty0 <= smy1 && toy >= soy) {
383
+ y = Math.max(tmy1, smy1);
384
+ }
385
+ }
386
+
387
+ return [
388
+ { x: sox, y: soy },
389
+ { x: sox, y },
390
+ { x: tox, y },
391
+ { x: tox, y: toy }
392
+ ];
393
+ }
394
+
395
+ const x = (sox + tox) / 2;
396
+ return [
397
+ { x, y: soy },
398
+ { x, y: toy }
399
+ ];
400
+ } else if (sourceSide === 'top' && targetSide === 'bottom') {
401
+ if (soy < toy) {
402
+ let x = middleOfVerticalSides;
403
+ let y = soy;
404
+
405
+ if (soy < ty0) {
406
+ if (tx1 >= smx0 && tox < sox) {
407
+ x = Math.min(tmx0, smx0);
408
+ } else if (tx0 <= smx1 && tox >= sox) {
409
+ x = Math.max(tmx1, smx1);
410
+ }
411
+ }
412
+
413
+ return [
414
+ { x: sox, y },
415
+ { x, y },
416
+ { x, y: toy },
417
+ { x: tox, y: toy }
418
+ ];
419
+ }
420
+ const y = (soy + toy) / 2;
421
+ return [
422
+ { x: sox, y },
423
+ { x: tox, y }
424
+ ];
425
+ } else if (sourceSide === 'bottom' && targetSide === 'top') {
426
+ if (soy - sourceMargin > toy) {
427
+ let x = middleOfVerticalSides;
428
+ let y = soy;
429
+
430
+ if (soy > ty1) {
431
+ if (tx1 >= smx0 && tox < sox) {
432
+ x = Math.min(tmx0, smx0);
433
+ } else if (tx0 <= smx1 && tox >= sox) {
434
+ x = Math.max(tmx1, smx1);
435
+ }
436
+ }
437
+
438
+ return [
439
+ { x: sox, y },
440
+ { x, y },
441
+ { x, y: toy },
442
+ { x: tox, y: toy }
443
+ ];
444
+ }
445
+ const y = (soy + toy) / 2;
446
+ return [
447
+ { x: sox, y },
448
+ { x: tox, y }
449
+ ];
450
+ } else if (sourceSide === 'top' && targetSide === 'top') {
451
+ let x;
452
+ let y1 = Math.min((sy1 + ty0) / 2, toy);
453
+ let y2 = Math.min((sy0 + ty1) / 2, soy);
454
+
455
+ if (toy < soy) {
456
+ if (sox >= tmx1 || sox <= tmx0) {
457
+ return [
458
+ { x: sox, y: Math.min(soy, toy) },
459
+ { x: tox, y: Math.min(soy, toy) }
460
+ ];
461
+ } else if (tox > sox) {
462
+ x = Math.min(sox, tmx0);
463
+ } else {
464
+ x = Math.max(sox, tmx1);
465
+ }
466
+ } else {
467
+ if (tox >= smx1 || tox <= smx0) {
468
+ return [
469
+ { x: sox, y: Math.min(soy, toy) },
470
+ { x: tox, y: Math.min(soy, toy) }
471
+ ];
472
+ } else if (tox >= sox) {
473
+ x = Math.max(tox, smx1);
474
+ } else {
475
+ x = Math.min(tox, smx0);
476
+ }
477
+ }
478
+
479
+ return [
480
+ { x: sox, y: y2 },
481
+ { x, y: y2 },
482
+ { x, y: y1 },
483
+ { x: tox, y: y1 }
484
+ ];
485
+ } else if (sourceSide === 'bottom' && targetSide === 'bottom') {
486
+ let x;
487
+ let y1 = Math.max((sy0 + ty1) / 2, toy);
488
+ let y2 = Math.max((sy1 + ty0) / 2, soy);
489
+
490
+ if (toy > soy) {
491
+ if (sox >= tmx1 || sox <= tmx0) {
492
+ return [
493
+ { x: sox, y: Math.max(soy, toy) },
494
+ { x: tox, y: Math.max(soy, toy) }
495
+ ];
496
+ } else if (tox > sox) {
497
+ x = Math.min(sox, tmx0);
498
+ } else {
499
+ x = Math.max(sox, tmx1);
500
+ }
501
+ } else {
502
+ if (tox >= smx1 || tox <= smx0) {
503
+ return [
504
+ { x: sox, y: Math.max(soy, toy) },
505
+ { x: tox, y: Math.max(soy, toy) }
506
+ ];
507
+ } else if (tox >= sox) {
508
+ x = Math.max(tox, smx1);
509
+ } else {
510
+ x = Math.min(tox, smx0);
511
+ }
512
+ }
513
+
514
+ return [
515
+ { x: sox, y: y2 },
516
+ { x, y: y2 },
517
+ { x, y: y1 },
518
+ { x: tox, y: y1 }
519
+ ];
520
+ } else if (sourceSide === 'left' && targetSide === 'left') {
521
+ let y;
522
+ let x1 = Math.min((sx1 + tx0) / 2, tox);
523
+ let x2 = Math.min((sx0 + tx1) / 2, sox);
524
+
525
+ if (tox > sox) {
526
+ if (toy <= soy) {
527
+ y = Math.min(smy0, toy);
528
+ } else {
529
+ y = Math.max(smy1, toy);
530
+ }
531
+ } else {
532
+ if (toy >= soy) {
533
+ y = Math.min(tmy0, soy);
534
+ } else {
535
+ y = Math.max(tmy1, soy);
536
+ }
537
+ }
538
+
539
+ return [
540
+ { x: x2, y: soy },
541
+ { x: x2, y },
542
+ { x: x1, y },
543
+ { x: x1, y: toy }
544
+ ];
545
+ } else if (sourceSide === 'right' && targetSide === 'right') {
546
+ let y;
547
+ let x1 = Math.max((sx0 + tx1) / 2, tox);
548
+ let x2 = Math.max((sx1 + tx0) / 2, sox);
549
+
550
+ if (tox < sox) {
551
+ if (toy <= soy) {
552
+ y = Math.min(smy0, toy);
553
+ } else {
554
+ y = Math.max(smy1, toy);
555
+ }
556
+ } else {
557
+ if (toy >= soy) {
558
+ y = Math.min(tmy0, soy);
559
+ } else {
560
+ y = Math.max(tmy1, soy);
561
+ }
562
+ }
563
+
564
+ return [
565
+ { x: x2, y: soy },
566
+ { x: x2, y },
567
+ { x: x1, y },
568
+ { x: x1, y: toy }
569
+ ];
570
+ } else if (sourceSide === 'top' && targetSide === 'right') {
571
+ if (soy > toy) {
572
+ if (sox < tox) {
573
+ let y = middleOfHorizontalSides;
574
+
575
+ if ((y > tcy || !isSourceEl) && y < tmy1 && sox < tx0) {
576
+ y = tmy0;
577
+ }
578
+ return [
579
+ { x: sox, y },
580
+ { x: tox, y },
581
+ { x: tox, y: toy }
582
+ ];
583
+ }
584
+
585
+ return [{ x: sox, y: toy }];
586
+ }
587
+
588
+ const x = Math.max(middleOfVerticalSides, tmx1);
589
+
590
+ if (tox < sox && toy > sy0 && toy < sy1) {
591
+ return [
592
+ { x: sox, y: soy },
593
+ { x: x, y: soy },
594
+ { x: x, y: toy }
595
+ ];
596
+ }
597
+
598
+ if ((x > smx0 && toy > sy0) || tx0 > sx1) {
599
+ const y = Math.min(sy0 - sourceMargin, ty0 - targetMargin);
600
+ const x = Math.max(sx1 + sourceMargin, tx1 + targetMargin);
601
+ return [
602
+ { x: sox, y },
603
+ { x, y },
604
+ { x, y: toy }
605
+ ];
606
+ }
607
+
608
+ return [
609
+ { x: sox, y: soy },
610
+ { x: Math.max(x, tox), y: soy },
611
+ { x: Math.max(x, tox), y: toy }
612
+ ];
613
+ } else if (sourceSide === 'top' && targetSide === 'left') {
614
+ if (soy > toy) {
615
+ if (sox > tox) {
616
+ let y = middleOfHorizontalSides;
617
+
618
+ if ((y > tcy || !isSourceEl) && y < tmy1 && sox > tx1) {
619
+ y = tmy0;
620
+ }
621
+ return [
622
+ { x: sox, y },
623
+ { x: tox, y },
624
+ { x: tox, y: toy }
625
+ ];
626
+ }
627
+ return [{ x: sox, y: toy }];
628
+ }
629
+
630
+ const x = Math.min(tmx0, middleOfVerticalSides);
631
+
632
+ if (sox < tox && sy1 >= toy) {
633
+ return [
634
+ { x: sox, y: soy },
635
+ { x, y: soy },
636
+ { x, y: toy }];
637
+ }
638
+
639
+ if (x < smx1 && soy < ty1) {
640
+ const y = Math.min(smy0, tmy0);
641
+ const x = Math.min(smx0, tmx0);
642
+ return [
643
+ { x: sox, y },
644
+ { x, y },
645
+ { x, y: toy }
646
+ ];
647
+ }
648
+ return [
649
+ { x: sox, y: soy },
650
+ { x, y: soy },
651
+ { x, y: toy }
652
+ ];
653
+ } else if (sourceSide === 'bottom' && targetSide === 'right') {
654
+ if (soy < toy) {
655
+ if (sox < tox) {
656
+ let y = middleOfHorizontalSides;
657
+
658
+ if ((y < tcy || !isSourceEl) && y > tmy0 && sox < tx0) {
659
+ y = tmy1;
660
+ }
661
+ return [
662
+ { x: sox, y },
663
+ { x: tox, y },
664
+ { x: tox, y: toy }
665
+ ];
666
+ }
667
+ return [{ x: sox, y: toy }];
668
+ } else {
669
+ if (sx0 < tox) {
670
+ const y = Math.max(smy1, tmy1);
671
+ const x = Math.max(smx1, tmx1);
672
+ return [
673
+ { x: sox, y },
674
+ { x, y },
675
+ { x, y: toy }
676
+ ];
677
+ }
678
+ }
679
+
680
+ const x = middleOfVerticalSides;
681
+
682
+ return [
683
+ { x: sox, y: soy },
684
+ { x, y: soy },
685
+ { x, y: toy }
686
+ ];
687
+ } else if (sourceSide === 'bottom' && targetSide === 'left') {
688
+ if (soy < toy) {
689
+ if (sox > tox) {
690
+ let y = middleOfHorizontalSides;
691
+
692
+ if ((y < tcy || !isSourceEl) && y > tmy0 && sox > tx1) {
693
+ y = tmy1;
694
+ }
695
+ return [
696
+ { x: sox, y },
697
+ { x: tox, y },
698
+ { x: tox, y: toy }
699
+ ];
700
+ }
701
+ return [{ x: sox, y: toy }];
702
+ } else {
703
+ if (sx1 > tox) {
704
+ const y = Math.max(smy1, tmy1);
705
+ const x = Math.min(smx0, tmx0);
706
+ return [
707
+ { x: sox, y },
708
+ { x, y },
709
+ { x, y: toy }
710
+ ];
711
+ }
712
+ }
713
+
714
+ const x = middleOfVerticalSides;
715
+
716
+ return [
717
+ { x: sox, y: soy },
718
+ { x, y: soy },
719
+ { x, y: toy }
720
+ ];
721
+ }
722
+ else if (sourceSide === 'left' && targetSide === 'bottom') {
723
+ if (sox >= tox && soy >= tmy1) {
724
+ return [{ x: tox, y: soy }];
725
+ }
726
+
727
+ if (sox >= tx1 && soy < toy) {
728
+ const x = middleOfVerticalSides;
729
+
730
+ return [
731
+ { x, y: soy },
732
+ { x, y: toy },
733
+ { x: tox, y: toy }
734
+ ];
735
+ }
736
+
737
+ if (tox < sx1 && ty1 <= sy0) {
738
+ const y = middleOfHorizontalSides;
739
+
740
+ return [
741
+ { x: sox, y: soy },
742
+ { x: sox, y },
743
+ { x: tox, y }
744
+ ];
745
+ }
746
+
747
+ const x = Math.min(tmx0, sox);
748
+ const y = Math.max(smy1, tmy1);
749
+
750
+ return [
751
+ { x, y: soy },
752
+ { x, y },
753
+ { x: tox, y }
754
+ ];
755
+ } else if (sourceSide === 'left' && targetSide === 'top') {
756
+ if (sox > tox && soy < tmy0) {
757
+ return [{ x: tox, y: soy }];
758
+ }
759
+
760
+ if (sox >= tx1) {
761
+ if (soy > toy) {
762
+ const x = middleOfVerticalSides;
763
+
764
+ return [
765
+ { x, y: soy },
766
+ { x, y: toy },
767
+ { x: tox, y: toy }
768
+ ];
769
+ }
770
+ }
771
+
772
+ if (tox <= sx1 && toy > soy) {
773
+ const y = middleOfHorizontalSides;
774
+
775
+ return [
776
+ { x: sox, y: soy },
777
+ { x: sox, y },
778
+ { x: tox, y },
779
+ ];
780
+ }
781
+
782
+ const x = toy < soy ? Math.min(smx0, tmx0) : smx0;
783
+ const y = Math.min(smy0, tmy0);
784
+
785
+ return [
786
+ { x, y: soy },
787
+ { x, y },
788
+ { x: tox, y }
789
+ ];
790
+
791
+ } else if (sourceSide === 'right' && targetSide === 'top') {
792
+ if (sox <= tox && soy < tmy0) {
793
+ return [{ x: tox, y: soy }];
794
+ }
795
+
796
+ if (sx1 < tx0 && soy > toy) {
797
+ let x = middleOfVerticalSides;
798
+
799
+ return [
800
+ { x, y: soy },
801
+ { x, y: toy },
802
+ { x: tox, y: toy }
803
+ ];
804
+ }
805
+
806
+ if (tox < sox && ty0 > sy1) {
807
+ const y = middleOfHorizontalSides;
808
+
809
+ return [
810
+ { x: sox, y: soy },
811
+ { x: sox, y },
812
+ { x: tox, y }
813
+ ];
814
+ }
815
+
816
+ const x = Math.max(smx1, tmx1);
817
+ const y = Math.min(smy0, tmy0);
818
+
819
+ return [
820
+ { x, y: soy },
821
+ { x, y },
822
+ { x: tox, y }
823
+ ];
824
+ } else if (sourceSide === 'right' && targetSide === 'bottom') {
825
+ if (sox <= tox && soy >= tmy1) {
826
+ return [{ x: tox, y: soy }];
827
+ }
828
+
829
+ if (sox <= tmx0 && soy < toy) {
830
+ const x = middleOfVerticalSides;
831
+
832
+ return [
833
+ { x, y: soy },
834
+ { x, y: toy },
835
+ { x: tox, y: toy }
836
+ ];
837
+ }
838
+
839
+ if (tox > sx0 && ty1 < sy0) {
840
+ const y = middleOfHorizontalSides;
841
+
842
+ return [
843
+ { x: sox, y: soy },
844
+ { x: sox, y },
845
+ { x: tox, y }
846
+ ];
847
+ }
848
+
849
+ const x = Math.max(tmx1, sox);
850
+ const y = Math.max(smy1, tmy1);
851
+
852
+ return [
853
+ { x, y: soy },
854
+ { x, y },
855
+ { x: tox, y }
856
+ ];
857
+ }
858
+ }
859
+
860
+ function rightAngleRouter(vertices, opt, linkView) {
861
+ const { sourceDirection = Directions.AUTO, targetDirection = Directions.AUTO } = opt;
862
+ const margin = opt.margin || 20;
863
+ const useVertices = opt.useVertices || false;
864
+
865
+ const isSourcePort = !!linkView.model.source().port;
866
+ const sourcePoint = pointDataFromAnchor(linkView.sourceView, linkView.sourceAnchor, linkView.sourceBBox, sourceDirection, isSourcePort, linkView.sourceAnchor, margin);
867
+
868
+ const isTargetPort = !!linkView.model.target().port;
869
+ const targetPoint = pointDataFromAnchor(linkView.targetView, linkView.targetAnchor, linkView.targetBBox, targetDirection, isTargetPort, linkView.targetAnchor, margin);
870
+
871
+ let resultVertices = [];
872
+
873
+ if (!useVertices || vertices.length === 0) {
874
+ return simplifyPoints(routeBetweenPoints(sourcePoint, targetPoint));
875
+ }
876
+
877
+ const verticesData = vertices.map((v) => pointDataFromVertex(v));
878
+ const [firstVertex] = verticesData;
879
+
880
+ if (sourcePoint.view && sourcePoint.view.model.isElement() && sourcePoint.view.model.getBBox().inflate(margin).containsPoint(firstVertex.point)) {
881
+ const [fromDirection] = resolveSides(sourcePoint, firstVertex);
882
+ const toDirection = fromDirection;
883
+ const dummySource = pointDataFromVertex(sourcePoint.point);
884
+ // Points do not usually have margin. Here we create a point with a margin.
885
+ dummySource.margin = margin;
886
+ dummySource.direction = fromDirection;
887
+ firstVertex.direction = toDirection;
888
+
889
+ resultVertices.push(...routeBetweenPoints(dummySource, firstVertex), firstVertex.point);
890
+ } else {
891
+ // The first point responsible for the initial direction of the route
892
+ const next = verticesData[1] || targetPoint;
893
+ const direction = resolveInitialDirection(sourcePoint, firstVertex, next);
894
+ firstVertex.direction = direction;
895
+
896
+ resultVertices.push(...routeBetweenPoints(sourcePoint, firstVertex), firstVertex.point);
897
+ }
898
+
899
+ for (let i = 0; i < verticesData.length - 1; i++) {
900
+ const from = verticesData[i];
901
+ const to = verticesData[i + 1];
902
+
903
+ const segment = new g.Line(from.point, to.point);
904
+ const segmentAngle = getSegmentAngle(segment);
905
+ if (segmentAngle % 90 === 0) {
906
+ // Since the segment is horizontal or vertical, we can skip the routing and just connect them with a straight line
907
+ const toDirection = ANGLE_DIRECTION_MAP[segmentAngle];
908
+ const accessDirection = OPPOSITE_DIRECTIONS[toDirection];
909
+
910
+ if (toDirection !== from.direction) {
911
+ resultVertices.push(from.point, to.point);
912
+ to.direction = accessDirection;
913
+ } else {
914
+ const angle = g.normalizeAngle(segmentAngle - 90);
915
+
916
+ let dx = 0;
917
+ let dy = 0;
918
+
919
+ if (angle === 90) {
920
+ dy = -margin;
921
+ } else if (angle === 180) {
922
+ dx = -margin;
923
+ } else if (angle === 270) {
924
+ dy = margin;
925
+ } else if (angle === 0) {
926
+ dx = margin;
927
+ }
928
+
929
+ const p1 = { x: from.point.x + dx, y: from.point.y + dy };
930
+ const p2 = { x: to.point.x + dx, y: to.point.y + dy };
931
+
932
+ const segment2 = new g.Line(to.point, p2);
933
+ to.direction = ANGLE_DIRECTION_MAP[getSegmentAngle(segment2)];
934
+
935
+ // Constructing a loop
936
+ resultVertices.push(from.point, p1, p2, to.point);
937
+ }
938
+
939
+ continue;
940
+ }
941
+
942
+ const [fromDirection, toDirection] = resolveDirection(from, to);
943
+
944
+ from.direction = fromDirection;
945
+ to.direction = toDirection;
946
+
947
+ resultVertices.push(...routeBetweenPoints(from, to), to.point);
948
+ }
949
+
950
+ const lastVertex = verticesData[verticesData.length - 1];
951
+
952
+ if (targetPoint.view && targetPoint.view.model.isElement()) {
953
+ if (targetPoint.view.model.getBBox().inflate(margin).containsPoint(lastVertex.point)) {
954
+ const [fromDirection] = resolveDirection(lastVertex, targetPoint);
955
+ const dummyTarget = pointDataFromVertex(targetPoint.point);
956
+ const [, toDirection] = resolveSides(lastVertex, targetPoint);
957
+ // we are creating a point that has a margin
958
+ dummyTarget.margin = margin;
959
+ dummyTarget.direction = toDirection;
960
+ lastVertex.direction = fromDirection;
961
+
962
+ resultVertices.push(...routeBetweenPoints(lastVertex, dummyTarget));
963
+ } else {
964
+ // the last point of `simplified` array is the last defined vertex
965
+ // grab the penultimate point and construct a line segment from it to the last vertex
966
+ // this will ensure that the last segment continues in a straight line
967
+
968
+ const simplified = simplifyPoints(resultVertices);
969
+ const segment = new g.Line(simplified[simplified.length - 2], lastVertex.point);
970
+ const definedDirection = ANGLE_DIRECTION_MAP[Math.round(getSegmentAngle(segment))];
971
+ lastVertex.direction = definedDirection;
972
+
973
+ let lastSegmentRoute = routeBetweenPoints(lastVertex, targetPoint);
974
+ const [p1, p2] = simplifyPoints([...lastSegmentRoute, targetPoint.point]);
975
+
976
+ const lastSegment = new g.Line(p1, p2);
977
+ const roundedLastSegmentAngle = Math.round(getSegmentAngle(lastSegment));
978
+ const lastSegmentDirection = ANGLE_DIRECTION_MAP[roundedLastSegmentAngle];
979
+
980
+ if (lastSegmentDirection !== definedDirection && definedDirection === OPPOSITE_DIRECTIONS[lastSegmentDirection]) {
981
+ lastVertex.margin = margin;
982
+ lastSegmentRoute = routeBetweenPoints(lastVertex, targetPoint);
983
+ }
984
+
985
+ resultVertices.push(...lastSegmentRoute);
986
+ }
987
+ } else {
988
+ // since the target is only a point we can apply the same logic as if we connected two verticesData
989
+ const [vertexDirection] = resolveDirection(lastVertex, targetPoint);
990
+ lastVertex.direction = vertexDirection;
991
+
992
+ resultVertices.push(...routeBetweenPoints(lastVertex, targetPoint));
993
+ }
994
+
995
+ return simplifyPoints(resultVertices);
996
+ }
997
+
998
+ function resolveDirection(from, to) {
999
+ const accessDirection = from.direction;
1000
+ const isDirectionVertical = VERTICAL_DIRECTIONS.includes(accessDirection);
1001
+
1002
+ let sourceDirection = from.direction;
1003
+ let targetDirection = to.direction;
1004
+
1005
+ if (isDirectionVertical) {
1006
+ const isToAbove = from.point.y > to.point.y;
1007
+ const dx = to.point.x - from.point.x;
1008
+
1009
+ if (accessDirection === Directions.BOTTOM) {
1010
+ // If isToAbove === false and we need figure out if to go left or right
1011
+ sourceDirection = isToAbove ? OPPOSITE_DIRECTIONS[accessDirection] : dx >= 0 ? Directions.RIGHT : Directions.LEFT;
1012
+
1013
+ if (dx > 0) {
1014
+ targetDirection = isToAbove ? Directions.LEFT : Directions.TOP;
1015
+ } else if (dx < 0) {
1016
+ targetDirection = isToAbove ? Directions.RIGHT : Directions.TOP;
1017
+ }
1018
+ } else {
1019
+ // If isToAbove === true and we need figure out if to go left or right
1020
+ sourceDirection = isToAbove ? dx >= 0 ? Directions.RIGHT : Directions.LEFT : OPPOSITE_DIRECTIONS[accessDirection];
1021
+
1022
+ if (dx > 0) {
1023
+ targetDirection = isToAbove ? Directions.BOTTOM : Directions.LEFT;
1024
+ } else if (dx < 0) {
1025
+ targetDirection = isToAbove ? Directions.BOTTOM : Directions.RIGHT;
1026
+ }
1027
+ }
1028
+ } else {
1029
+ const isToLeft = from.point.x > to.point.x;
1030
+ const dy = to.point.y - from.point.y;
1031
+
1032
+ if (accessDirection === Directions.RIGHT) {
1033
+ sourceDirection = isToLeft ? OPPOSITE_DIRECTIONS[accessDirection] : dy >= 0 ? Directions.BOTTOM : Directions.TOP;
1034
+
1035
+ if (dy > 0) {
1036
+ targetDirection = isToLeft ? Directions.TOP : Directions.LEFT;
1037
+ } else if (dy < 0) {
1038
+ targetDirection = isToLeft ? Directions.BOTTOM : Directions.LEFT;
1039
+ }
1040
+ } else {
1041
+ sourceDirection = isToLeft ? dy >= 0 ? Directions.BOTTOM : Directions.TOP : OPPOSITE_DIRECTIONS[accessDirection];
1042
+
1043
+ if (dy > 0) {
1044
+ targetDirection = isToLeft ? Directions.RIGHT : Directions.TOP;
1045
+ } else if (dy < 0) {
1046
+ targetDirection = isToLeft ? Directions.RIGHT : Directions.BOTTOM;
1047
+ }
1048
+ }
1049
+ }
1050
+
1051
+ return [sourceDirection, targetDirection];
1052
+ }
1053
+
1054
+ rightAngleRouter.Directions = Directions;
1055
+
1056
+ export const rightAngle = rightAngleRouter;