@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,452 @@
1
+ import * as util from '../util/index.mjs';
2
+ import * as g from '../g/index.mjs';
3
+
4
+ // default size of jump if not specified in options
5
+ var JUMP_SIZE = 5;
6
+
7
+ // available jump types
8
+ // first one taken as default
9
+ var JUMP_TYPES = ['arc', 'gap', 'cubic'];
10
+
11
+ // default radius
12
+ var RADIUS = 0;
13
+
14
+ // takes care of math. error for case when jump is too close to end of line
15
+ var CLOSE_PROXIMITY_PADDING = 1;
16
+
17
+ // list of connector types not to jump over.
18
+ var IGNORED_CONNECTORS = ['smooth'];
19
+
20
+ // internal constants for round segment
21
+ var _13 = 1 / 3;
22
+ var _23 = 2 / 3;
23
+
24
+ function sortPointsAscending(p1, p2) {
25
+
26
+ let { x: x1, y: y1 } = p1;
27
+ let { x: x2, y: y2 } = p2;
28
+
29
+ if (x1 > x2) {
30
+
31
+ let swap = x1;
32
+ x1 = x2;
33
+ x2 = swap;
34
+
35
+ swap = y1;
36
+ y1 = y2;
37
+ y2 = swap;
38
+ }
39
+
40
+ if (y1 > y2) {
41
+ let swap = x1;
42
+ x1 = x2;
43
+ x2 = swap;
44
+
45
+ swap = y1;
46
+ y1 = y2;
47
+ y2 = swap;
48
+ }
49
+
50
+ return [new g.Point(x1, y1), new g.Point(x2, y2)];
51
+ }
52
+
53
+ function overlapExists(line1, line2) {
54
+
55
+ const [{ x: x1, y: y1 }, { x: x2, y: y2 }] = sortPointsAscending(line1.start, line1.end);
56
+ const [{ x: x3, y: y3 }, { x: x4, y: y4 }] = sortPointsAscending(line2.start, line2.end);
57
+
58
+ const xMatch = x1 <= x4 && x3 <= x2;
59
+ const yMatch = y1 <= y4 && y3 <= y2;
60
+
61
+ return xMatch && yMatch;
62
+ }
63
+
64
+ /**
65
+ * Transform start/end and route into series of lines
66
+ * @param {g.point} sourcePoint start point
67
+ * @param {g.point} targetPoint end point
68
+ * @param {g.point[]} route optional list of route
69
+ * @return {g.line[]} [description]
70
+ */
71
+ function createLines(sourcePoint, targetPoint, route) {
72
+ // make a flattened array of all points
73
+ var points = [].concat(sourcePoint, route, targetPoint);
74
+ return points.reduce(function(resultLines, point, idx) {
75
+ // if there is a next point, make a line with it
76
+ var nextPoint = points[idx + 1];
77
+ if (nextPoint != null) {
78
+ resultLines[idx] = g.line(point, nextPoint);
79
+ }
80
+ return resultLines;
81
+ }, []);
82
+ }
83
+
84
+ function setupUpdating(jumpOverLinkView) {
85
+ var paper = jumpOverLinkView.paper;
86
+ var updateList = paper._jumpOverUpdateList;
87
+
88
+ // first time setup for this paper
89
+ if (updateList == null) {
90
+ updateList = paper._jumpOverUpdateList = [];
91
+ var graph = paper.model;
92
+ graph.on('batch:stop', function() {
93
+ if (this.hasActiveBatch()) return;
94
+ updateJumpOver(paper);
95
+ });
96
+ graph.on('reset', function() {
97
+ updateList = paper._jumpOverUpdateList = [];
98
+ });
99
+ }
100
+
101
+ // add this link to a list so it can be updated when some other link is updated
102
+ if (updateList.indexOf(jumpOverLinkView) < 0) {
103
+ updateList.push(jumpOverLinkView);
104
+
105
+ // watch for change of connector type or removal of link itself
106
+ // to remove the link from a list of jump over connectors
107
+ jumpOverLinkView.listenToOnce(jumpOverLinkView.model, 'change:connector remove', function() {
108
+ updateList.splice(updateList.indexOf(jumpOverLinkView), 1);
109
+ });
110
+ }
111
+ }
112
+
113
+ /**
114
+ * Handler for a batch:stop event to force
115
+ * update of all registered links with jump over connector
116
+ * @param {object} batchEvent optional object with info about batch
117
+ */
118
+ function updateJumpOver(paper) {
119
+ var updateList = paper._jumpOverUpdateList;
120
+ for (var i = 0; i < updateList.length; i++) {
121
+ const linkView = updateList[i];
122
+ const updateFlag = linkView.getFlag(linkView.constructor.Flags.CONNECTOR);
123
+ linkView.requestUpdate(updateFlag);
124
+ }
125
+ }
126
+
127
+ /**
128
+ * Utility function to collect all intersection points of a single
129
+ * line against group of other lines.
130
+ * @param {g.line} line where to find points
131
+ * @param {g.line[]} crossCheckLines lines to cross
132
+ * @return {g.point[]} list of intersection points
133
+ */
134
+ function findLineIntersections(line, crossCheckLines) {
135
+ return util.toArray(crossCheckLines).reduce(function(res, crossCheckLine) {
136
+ var intersection = line.intersection(crossCheckLine);
137
+ if (intersection) {
138
+ res.push(intersection);
139
+ }
140
+ return res;
141
+ }, []);
142
+ }
143
+
144
+ /**
145
+ * Sorting function for list of points by their distance.
146
+ * @param {g.point} p1 first point
147
+ * @param {g.point} p2 second point
148
+ * @return {number} squared distance between points
149
+ */
150
+ function sortPoints(p1, p2) {
151
+ return g.line(p1, p2).squaredLength();
152
+ }
153
+
154
+ /**
155
+ * Split input line into multiple based on intersection points.
156
+ * @param {g.line} line input line to split
157
+ * @param {g.point[]} intersections points where to split the line
158
+ * @param {number} jumpSize the size of jump arc (length empty spot on a line)
159
+ * @return {g.line[]} list of lines being split
160
+ */
161
+ function createJumps(line, intersections, jumpSize) {
162
+ return intersections.reduce(function(resultLines, point, idx) {
163
+ // skipping points that were merged with the previous line
164
+ // to make bigger arc over multiple lines that are close to each other
165
+ if (point.skip === true) {
166
+ return resultLines;
167
+ }
168
+
169
+ // always grab the last line from buffer and modify it
170
+ var lastLine = resultLines.pop() || line;
171
+
172
+ // calculate start and end of jump by moving by a given size of jump
173
+ var jumpStart = g.point(point).move(lastLine.start, -(jumpSize));
174
+ var jumpEnd = g.point(point).move(lastLine.start, +(jumpSize));
175
+
176
+ // now try to look at the next intersection point
177
+ var nextPoint = intersections[idx + 1];
178
+ if (nextPoint != null) {
179
+ var distance = jumpEnd.distance(nextPoint);
180
+ if (distance <= jumpSize) {
181
+ // next point is close enough, move the jump end by this
182
+ // difference and mark the next point to be skipped
183
+ jumpEnd = nextPoint.move(lastLine.start, distance);
184
+ nextPoint.skip = true;
185
+ }
186
+ } else {
187
+ // this block is inside of `else` as an optimization so the distance is
188
+ // not calculated when we know there are no other intersection points
189
+ var endDistance = jumpStart.distance(lastLine.end);
190
+ // if the end is too close to possible jump, draw remaining line instead of a jump
191
+ if (endDistance < jumpSize * 2 + CLOSE_PROXIMITY_PADDING) {
192
+ resultLines.push(lastLine);
193
+ return resultLines;
194
+ }
195
+ }
196
+
197
+ var startDistance = jumpEnd.distance(lastLine.start);
198
+ if (startDistance < jumpSize * 2 + CLOSE_PROXIMITY_PADDING) {
199
+ // if the start of line is too close to jump, draw that line instead of a jump
200
+ resultLines.push(lastLine);
201
+ return resultLines;
202
+ }
203
+
204
+ // finally create a jump line
205
+ var jumpLine = g.line(jumpStart, jumpEnd);
206
+ // it's just simple line but with a `isJump` property
207
+ jumpLine.isJump = true;
208
+
209
+ resultLines.push(
210
+ g.line(lastLine.start, jumpStart),
211
+ jumpLine,
212
+ g.line(jumpEnd, lastLine.end)
213
+ );
214
+ return resultLines;
215
+ }, []);
216
+ }
217
+
218
+ /**
219
+ * Assemble `D` attribute of a SVG path by iterating given lines.
220
+ * @param {g.line[]} lines source lines to use
221
+ * @param {number} jumpSize the size of jump arc (length empty spot on a line)
222
+ * @param {number} radius the radius
223
+ * @return {string}
224
+ */
225
+ function buildPath(lines, jumpSize, jumpType, radius) {
226
+
227
+ var path = new g.Path();
228
+ var segment;
229
+
230
+ // first move to the start of a first line
231
+ segment = g.Path.createSegment('M', lines[0].start);
232
+ path.appendSegment(segment);
233
+
234
+ // make a paths from lines
235
+ util.toArray(lines).forEach(function(line, index) {
236
+
237
+ if (line.isJump) {
238
+ var angle, diff;
239
+
240
+ var control1, control2;
241
+
242
+ if (jumpType === 'arc') { // approximates semicircle with 2 curves
243
+ angle = -90;
244
+ // determine rotation of arc based on difference between points
245
+ diff = line.start.difference(line.end);
246
+ // make sure the arc always points up (or right)
247
+ var xAxisRotate = Number((diff.x < 0) || (diff.x === 0 && diff.y < 0));
248
+ if (xAxisRotate) angle += 180;
249
+
250
+ var midpoint = line.midpoint();
251
+ var centerLine = new g.Line(midpoint, line.end).rotate(midpoint, angle);
252
+
253
+ var halfLine;
254
+
255
+ // first half
256
+ halfLine = new g.Line(line.start, midpoint);
257
+
258
+ control1 = halfLine.pointAt(2 / 3).rotate(line.start, angle);
259
+ control2 = centerLine.pointAt(1 / 3).rotate(centerLine.end, -angle);
260
+
261
+ segment = g.Path.createSegment('C', control1, control2, centerLine.end);
262
+ path.appendSegment(segment);
263
+
264
+ // second half
265
+ halfLine = new g.Line(midpoint, line.end);
266
+
267
+ control1 = centerLine.pointAt(1 / 3).rotate(centerLine.end, angle);
268
+ control2 = halfLine.pointAt(1 / 3).rotate(line.end, -angle);
269
+
270
+ segment = g.Path.createSegment('C', control1, control2, line.end);
271
+ path.appendSegment(segment);
272
+
273
+ } else if (jumpType === 'gap') {
274
+ segment = g.Path.createSegment('M', line.end);
275
+ path.appendSegment(segment);
276
+
277
+ } else if (jumpType === 'cubic') { // approximates semicircle with 1 curve
278
+ angle = line.start.theta(line.end);
279
+
280
+ var xOffset = jumpSize * 0.6;
281
+ var yOffset = jumpSize * 1.35;
282
+
283
+ // determine rotation of arc based on difference between points
284
+ diff = line.start.difference(line.end);
285
+ // make sure the arc always points up (or right)
286
+ xAxisRotate = Number((diff.x < 0) || (diff.x === 0 && diff.y < 0));
287
+ if (xAxisRotate) yOffset *= -1;
288
+
289
+ control1 = g.Point(line.start.x + xOffset, line.start.y + yOffset).rotate(line.start, angle);
290
+ control2 = g.Point(line.end.x - xOffset, line.end.y + yOffset).rotate(line.end, angle);
291
+
292
+ segment = g.Path.createSegment('C', control1, control2, line.end);
293
+ path.appendSegment(segment);
294
+ }
295
+
296
+ } else {
297
+ var nextLine = lines[index + 1];
298
+ if (radius == 0 || !nextLine || nextLine.isJump) {
299
+ segment = g.Path.createSegment('L', line.end);
300
+ path.appendSegment(segment);
301
+ } else {
302
+ buildRoundedSegment(radius, path, line.end, line.start, nextLine.end);
303
+ }
304
+ }
305
+ });
306
+
307
+ return path;
308
+ }
309
+
310
+ function buildRoundedSegment(offset, path, curr, prev, next) {
311
+ var prevDistance = curr.distance(prev) / 2;
312
+ var nextDistance = curr.distance(next) / 2;
313
+
314
+ var startMove = -Math.min(offset, prevDistance);
315
+ var endMove = -Math.min(offset, nextDistance);
316
+
317
+ var roundedStart = curr.clone().move(prev, startMove).round();
318
+ var roundedEnd = curr.clone().move(next, endMove).round();
319
+
320
+ var control1 = new g.Point((_13 * roundedStart.x) + (_23 * curr.x), (_23 * curr.y) + (_13 * roundedStart.y));
321
+ var control2 = new g.Point((_13 * roundedEnd.x) + (_23 * curr.x), (_23 * curr.y) + (_13 * roundedEnd.y));
322
+
323
+ var segment;
324
+ segment = g.Path.createSegment('L', roundedStart);
325
+ path.appendSegment(segment);
326
+
327
+ segment = g.Path.createSegment('C', control1, control2, roundedEnd);
328
+ path.appendSegment(segment);
329
+ }
330
+
331
+ /**
332
+ * Actual connector function that will be run on every update.
333
+ * @param {g.point} sourcePoint start point of this link
334
+ * @param {g.point} targetPoint end point of this link
335
+ * @param {g.point[]} route of this link
336
+ * @param {object} opt options
337
+ * @property {number} size optional size of a jump arc
338
+ * @return {string} created `D` attribute of SVG path
339
+ */
340
+ export const jumpover = function(sourcePoint, targetPoint, route, opt) { // eslint-disable-line max-params
341
+
342
+ setupUpdating(this);
343
+
344
+ var raw = opt.raw;
345
+ var jumpSize = opt.size || JUMP_SIZE;
346
+ var jumpType = opt.jump && ('' + opt.jump).toLowerCase();
347
+ var radius = opt.radius || RADIUS;
348
+ var ignoreConnectors = opt.ignoreConnectors || IGNORED_CONNECTORS;
349
+
350
+ // grab the first jump type as a default if specified one is invalid
351
+ if (JUMP_TYPES.indexOf(jumpType) === -1) {
352
+ jumpType = JUMP_TYPES[0];
353
+ }
354
+
355
+ var paper = this.paper;
356
+ var graph = paper.model;
357
+ var allLinks = graph.getLinks();
358
+
359
+ // there is just one link, draw it directly
360
+ if (allLinks.length === 1) {
361
+ return buildPath(
362
+ createLines(sourcePoint, targetPoint, route),
363
+ jumpSize, jumpType, radius
364
+ );
365
+ }
366
+
367
+ var thisModel = this.model;
368
+ var thisIndex = allLinks.indexOf(thisModel);
369
+ var defaultConnector = paper.options.defaultConnector || {};
370
+
371
+ // not all links are meant to be jumped over.
372
+ var links = allLinks.filter(function(link, idx) {
373
+
374
+ var connector = link.get('connector') || defaultConnector;
375
+
376
+ // avoid jumping over links with connector type listed in `ignored connectors`.
377
+ if (util.toArray(ignoreConnectors).includes(connector.name)) {
378
+ return false;
379
+ }
380
+ // filter out links that are above this one and have the same connector type
381
+ // otherwise there would double hoops for each intersection
382
+ if (idx > thisIndex) {
383
+ return connector.name !== 'jumpover';
384
+ }
385
+ return true;
386
+ });
387
+
388
+ // find views for all links
389
+ var linkViews = links.map(function(link) {
390
+ return paper.findViewByModel(link);
391
+ });
392
+
393
+ // create lines for this link
394
+ var thisLines = createLines(
395
+ sourcePoint,
396
+ targetPoint,
397
+ route
398
+ );
399
+
400
+ // create lines for all other links
401
+ var linkLines = linkViews.map(function(linkView) {
402
+ if (linkView == null) {
403
+ return [];
404
+ }
405
+ if (linkView === this) {
406
+ return thisLines;
407
+ }
408
+ return createLines(
409
+ linkView.sourcePoint,
410
+ linkView.targetPoint,
411
+ linkView.route
412
+ );
413
+ }, this);
414
+
415
+ // transform lines for this link by splitting with jump lines at
416
+ // points of intersection with other links
417
+ var jumpingLines = thisLines.reduce(function(resultLines, thisLine) {
418
+ // iterate all links and grab the intersections with this line
419
+ // these are then sorted by distance so the line can be split more easily
420
+ var intersections = links.reduce(function(res, link, i) {
421
+ // don't intersection with itself
422
+ if (link !== thisModel) {
423
+
424
+ const linkLinesToTest = linkLines[i].slice();
425
+ const overlapIndex = linkLinesToTest.findIndex((line) => overlapExists(thisLine, line));
426
+
427
+ // Overlap occurs and the end point of one segment lies on thisLine
428
+ if (overlapIndex > -1 && thisLine.containsPoint(linkLinesToTest[overlapIndex].end)) {
429
+ // Remove the next segment because there will never be a jump
430
+ linkLinesToTest.splice(overlapIndex + 1, 1);
431
+ }
432
+ const lineIntersections = findLineIntersections(thisLine, linkLinesToTest);
433
+ res.push.apply(res, lineIntersections);
434
+ }
435
+ return res;
436
+ }, []).sort(function(a, b) {
437
+ return sortPoints(thisLine.start, a) - sortPoints(thisLine.start, b);
438
+ });
439
+
440
+ if (intersections.length > 0) {
441
+ // split the line based on found intersection points
442
+ resultLines.push.apply(resultLines, createJumps(thisLine, intersections, jumpSize));
443
+ } else {
444
+ // without any intersection the line goes uninterrupted
445
+ resultLines.push(thisLine);
446
+ }
447
+ return resultLines;
448
+ }, []);
449
+
450
+ var path = buildPath(jumpingLines, jumpSize, jumpType, radius);
451
+ return (raw) ? path : path.serialize();
452
+ };
@@ -0,0 +1,12 @@
1
+ import { straight } from './straight.mjs';
2
+
3
+ export const normal = function(sourcePoint, targetPoint, route = [], opt = {}) {
4
+
5
+ const { raw } = opt;
6
+ const localOpt = {
7
+ cornerType: 'point',
8
+ raw
9
+ };
10
+
11
+ return straight(sourcePoint, targetPoint, route, localOpt);
12
+ };
@@ -0,0 +1,17 @@
1
+ import { straight } from './straight.mjs';
2
+
3
+ const CORNER_RADIUS = 10;
4
+ const PRECISION = 0;
5
+
6
+ export const rounded = function(sourcePoint, targetPoint, route = [], opt = {}) {
7
+
8
+ const { radius = CORNER_RADIUS, raw } = opt;
9
+ const localOpt = {
10
+ cornerType: 'cubic',
11
+ cornerRadius: radius,
12
+ precision: PRECISION,
13
+ raw
14
+ };
15
+
16
+ return straight(sourcePoint, targetPoint, route, localOpt);
17
+ };
@@ -0,0 +1,44 @@
1
+ import * as g from '../g/index.mjs';
2
+
3
+ export const smooth = function(sourcePoint, targetPoint, route, opt) {
4
+
5
+ var raw = opt && opt.raw;
6
+ var path;
7
+
8
+ if (route && route.length !== 0) {
9
+
10
+ var points = [sourcePoint].concat(route).concat([targetPoint]);
11
+ var curves = g.Curve.throughPoints(points);
12
+
13
+ path = new g.Path(curves);
14
+
15
+ } else {
16
+ // if we have no route, use a default cubic bezier curve
17
+ // cubic bezier requires two control points
18
+ // the control points have `x` midway between source and target
19
+ // this produces an S-like curve
20
+
21
+ path = new g.Path();
22
+
23
+ var segment;
24
+
25
+ segment = g.Path.createSegment('M', sourcePoint);
26
+ path.appendSegment(segment);
27
+
28
+ if ((Math.abs(sourcePoint.x - targetPoint.x)) >= (Math.abs(sourcePoint.y - targetPoint.y))) {
29
+ var controlPointX = (sourcePoint.x + targetPoint.x) / 2;
30
+
31
+ segment = g.Path.createSegment('C', controlPointX, sourcePoint.y, controlPointX, targetPoint.y, targetPoint.x, targetPoint.y);
32
+ path.appendSegment(segment);
33
+
34
+ } else {
35
+ var controlPointY = (sourcePoint.y + targetPoint.y) / 2;
36
+
37
+ segment = g.Path.createSegment('C', sourcePoint.x, controlPointY, targetPoint.x, controlPointY, targetPoint.x, targetPoint.y);
38
+ path.appendSegment(segment);
39
+
40
+ }
41
+ }
42
+
43
+ return (raw) ? path : path.serialize();
44
+ };
@@ -0,0 +1,110 @@
1
+ import * as g from '../g/index.mjs';
2
+
3
+ const CornerTypes = {
4
+ POINT: 'point',
5
+ CUBIC: 'cubic',
6
+ LINE: 'line',
7
+ GAP: 'gap'
8
+ };
9
+
10
+ const DEFINED_CORNER_TYPES = Object.values(CornerTypes);
11
+
12
+ const CORNER_RADIUS = 10;
13
+ const PRECISION = 1;
14
+
15
+ export const straight = function(sourcePoint, targetPoint, routePoints = [], opt = {}) {
16
+
17
+ const {
18
+ cornerType = CornerTypes.POINT,
19
+ cornerRadius = CORNER_RADIUS,
20
+ cornerPreserveAspectRatio = false,
21
+ precision = PRECISION,
22
+ raw = false
23
+ } = opt;
24
+
25
+ if (DEFINED_CORNER_TYPES.indexOf(cornerType) === -1) {
26
+ // unknown `cornerType` provided => error
27
+ throw new Error('Invalid `cornerType` provided to `straight` connector.');
28
+ }
29
+
30
+ let path;
31
+
32
+ if ((cornerType === CornerTypes.POINT) || !cornerRadius) {
33
+ // default option => normal connector
34
+ // simply connect all points with straight lines
35
+ const points = [sourcePoint].concat(routePoints).concat([targetPoint]);
36
+ const polyline = new g.Polyline(points);
37
+ path = new g.Path(polyline);
38
+
39
+ } else {
40
+ // `cornerType` is not unknown and not 'point' (default) => must be one of other valid types
41
+ path = new g.Path();
42
+
43
+ // add initial gap segment = to source point
44
+ path.appendSegment(g.Path.createSegment('M', sourcePoint));
45
+
46
+ let nextDistance;
47
+ const routePointsLength = routePoints.length;
48
+ for (let i = 0; i < routePointsLength; i++) {
49
+
50
+ const curr = new g.Point(routePoints[i]);
51
+ const prev = (routePoints[i - 1] || sourcePoint);
52
+ const next = (routePoints[i + 1] || targetPoint);
53
+ const prevDistance = (nextDistance || (curr.distance(prev) / 2)); // try to re-use previously-computed `nextDistance`
54
+ nextDistance = (curr.distance(next) / 2);
55
+
56
+ let startMove, endMove;
57
+ if (!cornerPreserveAspectRatio) {
58
+ // `startMove` and `endMove` may be different
59
+ // (this happens when next or previous path point is closer than `2 * cornerRadius`)
60
+ startMove = -Math.min(cornerRadius, prevDistance);
61
+ endMove = -Math.min(cornerRadius, nextDistance);
62
+ } else {
63
+ // force `startMove` and `endMove` to be the same
64
+ startMove = endMove = -Math.min(cornerRadius, prevDistance, nextDistance);
65
+ }
66
+
67
+ // to find `cornerStart` and `cornerEnd`, the logic is as follows (using `cornerStart` as example):
68
+ // - find a point lying on the line `prev - startMove` such that...
69
+ // - ...the point lies `abs(startMove)` distance away from `curr`...
70
+ // - ...and its coordinates are rounded to whole numbers
71
+ const cornerStart = curr.clone().move(prev, startMove).round(precision);
72
+ const cornerEnd = curr.clone().move(next, endMove).round(precision);
73
+
74
+ // add in-between straight segment = from previous route point to corner start point
75
+ // (may have zero length)
76
+ path.appendSegment(g.Path.createSegment('L', cornerStart));
77
+
78
+ // add corner segment = from corner start point to corner end point
79
+ switch (cornerType) {
80
+ case CornerTypes.CUBIC: {
81
+ // corner is rounded
82
+ const _13 = (1 / 3);
83
+ const _23 = (2 / 3);
84
+ const control1 = new g.Point((_13 * cornerStart.x) + (_23 * curr.x), (_23 * curr.y) + (_13 * cornerStart.y));
85
+ const control2 = new g.Point((_13 * cornerEnd.x) + (_23 * curr.x), (_23 * curr.y) + (_13 * cornerEnd.y));
86
+ path.appendSegment(g.Path.createSegment('C', control1, control2, cornerEnd));
87
+ break;
88
+ }
89
+ case CornerTypes.LINE: {
90
+ // corner has bevel
91
+ path.appendSegment(g.Path.createSegment('L', cornerEnd));
92
+ break;
93
+ }
94
+ case CornerTypes.GAP: {
95
+ // corner has empty space
96
+ path.appendSegment(g.Path.createSegment('M', cornerEnd));
97
+ break;
98
+ }
99
+ // default: no segment is created
100
+ }
101
+ }
102
+
103
+ // add final straight segment = from last corner end point to target point
104
+ // (= or from start point to end point, if there are no route points)
105
+ // (may have zero length)
106
+ path.appendSegment(g.Path.createSegment('L', targetPoint));
107
+ }
108
+
109
+ return ((raw) ? path : path.serialize());
110
+ };