@leafer-in/linker 2.3.1 → 2.3.3

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.
@@ -1,4 +1,4 @@
1
- import { LineData, AroundHelper, PointHelper, Direction9, BoundsHelper, decorateLeafAttr, attr, doBoundsType, doStrokeType, PathCommandDataHelper, dataProcessor, pathType, registerUI, Line, BoundsEvent, LeafHelper, isString, isObject, Plugin, registerPointsCurve } from "@leafer-ui/draw";
1
+ import { LineData, AroundHelper, PointHelper, Direction9, BoundsHelper, decorateLeafAttr, attr, doBoundsType, doStrokeType, PathCommandDataHelper, dataProcessor, boundsType, pathType, registerUI, Line, BoundsEvent, LeafHelper, isString, isObject, Plugin, registerPointsCurve } from "@leafer-ui/draw";
2
2
 
3
3
  import { PointHelper as PointHelper$1, PathCommandMap } from "@leafer-ui/core";
4
4
 
@@ -19,7 +19,7 @@ class LinkerData extends LineData {
19
19
  }
20
20
  }
21
21
 
22
- const {directionData: directionData} = AroundHelper;
22
+ const {directionData: directionData$1} = AroundHelper;
23
23
 
24
24
  const directionNames = [ "top-left", "top", "top-right", "right", "bottom-right", "bottom", "bottom-left", "left", "center" ];
25
25
 
@@ -135,8 +135,8 @@ function getPointDirection(boxPoint, bounds, eight) {
135
135
  const {width: width, height: height} = bounds;
136
136
  const hitRadiusX = width / 4;
137
137
  const hitRadiusY = height / 4;
138
- for (let i = 0; i < directionData.length; i++) {
139
- const unit = directionData[i];
138
+ for (let i = 0; i < directionData$1.length; i++) {
139
+ const unit = directionData$1[i];
140
140
  const px = unit.x * width;
141
141
  const py = unit.y * height;
142
142
  const dx = boxPoint.x - px;
@@ -181,7 +181,386 @@ function linkerPointType(defaultValue) {
181
181
  }));
182
182
  }
183
183
 
184
- const {moveTo: moveTo, bezierCurveTo: bezierCurveTo, drawPoints: drawPoints$1} = PathCommandDataHelper;
184
+ const {directionData: directionData} = AroundHelper;
185
+
186
+ const {moveTo: moveTo$1, lineTo: lineTo$1} = PathCommandDataHelper;
187
+
188
+ const POLYLINE_X = 0, POLYLINE_Y = 1;
189
+
190
+ const POLYLINE_EPSILON = .001;
191
+
192
+ const POLYLINE_MIN_SEGMENT = 4;
193
+
194
+ const POLYLINE_TURN_WEIGHT = 1.5;
195
+
196
+ function getPolylineDirectionIndex(direction) {
197
+ switch (direction) {
198
+ case "top-left":
199
+ return 0;
200
+
201
+ case "top":
202
+ return 1;
203
+
204
+ case "top-right":
205
+ return 2;
206
+
207
+ case "right":
208
+ return 3;
209
+
210
+ case "bottom-right":
211
+ return 4;
212
+
213
+ case "bottom":
214
+ return 5;
215
+
216
+ case "bottom-left":
217
+ return 6;
218
+
219
+ case "left":
220
+ return 7;
221
+
222
+ default:
223
+ return 8;
224
+ }
225
+ }
226
+
227
+ function getPolylinePorts(direction, point, target, bounds, targetBounds, ports) {
228
+ const data = directionData[getPolylineDirectionIndex(direction)];
229
+ const dx = Math.sign(data.x - .5), dy = Math.sign(data.y - .5);
230
+ const cx = bounds ? bounds.x + bounds.width / 2 : point.x;
231
+ const cy = bounds ? bounds.y + bounds.height / 2 : point.y;
232
+ const tx = targetBounds ? targetBounds.x + targetBounds.width / 2 : target.x;
233
+ const ty = targetBounds ? targetBounds.y + targetBounds.height / 2 : target.y;
234
+ const deltaX = tx - cx, deltaY = ty - cy;
235
+ const xSign = dx || (deltaX >= 0 ? 1 : -1);
236
+ const ySign = dy || (deltaY >= 0 ? 1 : -1);
237
+ const xPort = POLYLINE_X * 2 + (xSign > 0 ? 1 : 0);
238
+ const yPort = POLYLINE_Y * 2 + (ySign > 0 ? 1 : 0);
239
+ if (dx && !dy) {
240
+ ports[0] = xPort;
241
+ return 1;
242
+ }
243
+ if (dy && !dx) {
244
+ ports[0] = yPort;
245
+ return 1;
246
+ }
247
+ if (Math.abs(deltaX) >= Math.abs(deltaY)) {
248
+ ports[0] = xPort;
249
+ ports[1] = yPort;
250
+ } else {
251
+ ports[0] = yPort;
252
+ ports[1] = xPort;
253
+ }
254
+ return 2;
255
+ }
256
+
257
+ function getPolylineExit(point, bounds, port, clearance, result) {
258
+ const axis = port >> 1, sign = port & 1 ? 1 : -1;
259
+ if (axis === POLYLINE_X) {
260
+ const boundary = bounds ? sign > 0 ? bounds.x + bounds.width : bounds.x : point.x;
261
+ result[0] = boundary + sign * clearance;
262
+ result[1] = point.y;
263
+ } else {
264
+ const boundary = bounds ? sign > 0 ? bounds.y + bounds.height : bounds.y : point.y;
265
+ result[0] = point.x;
266
+ result[1] = boundary + sign * clearance;
267
+ }
268
+ }
269
+
270
+ function isPolylinePointBlocked(x, y, bounds, clearance) {
271
+ if (!bounds) return false;
272
+ const left = bounds.x - clearance, right = bounds.x + bounds.width + clearance;
273
+ const top = bounds.y - clearance, bottom = bounds.y + bounds.height + clearance;
274
+ return x > left + POLYLINE_EPSILON && x < right - POLYLINE_EPSILON && y > top + POLYLINE_EPSILON && y < bottom - POLYLINE_EPSILON;
275
+ }
276
+
277
+ function isPolylineSegmentBlocked(x1, y1, x2, y2, bounds, clearance) {
278
+ if (!bounds) return false;
279
+ const left = bounds.x - clearance, right = bounds.x + bounds.width + clearance;
280
+ const top = bounds.y - clearance, bottom = bounds.y + bounds.height + clearance;
281
+ if (Math.abs(y1 - y2) <= POLYLINE_EPSILON) {
282
+ return y1 > top + POLYLINE_EPSILON && y1 < bottom - POLYLINE_EPSILON && Math.max(Math.min(x1, x2), left + POLYLINE_EPSILON) < Math.min(Math.max(x1, x2), right - POLYLINE_EPSILON);
283
+ }
284
+ if (Math.abs(x1 - x2) <= POLYLINE_EPSILON) {
285
+ return x1 > left + POLYLINE_EPSILON && x1 < right - POLYLINE_EPSILON && Math.max(Math.min(y1, y2), top + POLYLINE_EPSILON) < Math.min(Math.max(y1, y2), bottom - POLYLINE_EPSILON);
286
+ }
287
+ return true;
288
+ }
289
+
290
+ function addPolylineBoundsCoordinates(xs, ys, bounds, clearance, margin) {
291
+ if (!bounds) return;
292
+ const left = bounds.x - clearance, right = bounds.x + bounds.width + clearance;
293
+ const top = bounds.y - clearance, bottom = bounds.y + bounds.height + clearance;
294
+ xs.push(left, right, left - margin, right + margin);
295
+ ys.push(top, bottom, top - margin, bottom + margin);
296
+ }
297
+
298
+ function sortPolylineCoordinates(values) {
299
+ values.sort((a, b) => a - b);
300
+ let write = 0;
301
+ for (let i = 0; i < values.length; i++) {
302
+ if (!write || Math.abs(values[i] - values[write - 1]) > POLYLINE_EPSILON) values[write++] = values[i];
303
+ }
304
+ values.length = write;
305
+ }
306
+
307
+ function getPolylineCoordinateIndex(values, value) {
308
+ for (let i = 0; i < values.length; i++) {
309
+ if (Math.abs(values[i] - value) <= POLYLINE_EPSILON) return i;
310
+ }
311
+ return -1;
312
+ }
313
+
314
+ function getPolylineMidpointAxis(startPort, endPort, sx, sy, ex, ey) {
315
+ const startAxis = startPort >> 1, endAxis = endPort >> 1;
316
+ const startSign = startPort & 1 ? 1 : -1, endSign = endPort & 1 ? 1 : -1;
317
+ if (startAxis === endAxis && startSign === -endSign) return startAxis;
318
+ return Math.abs(ex - sx) >= Math.abs(ey - sy) ? POLYLINE_X : POLYLINE_Y;
319
+ }
320
+
321
+ function getPolylineMidpointRoute(result, startPoint, endPoint, sx, sy, ex, ey, midpointAxis, startBounds, endBounds, clearance) {
322
+ const midpointX = (sx + ex) / 2, midpointY = (sy + ey) / 2;
323
+ result.length = 0;
324
+ result.push(startPoint.x, startPoint.y, sx, sy);
325
+ if (midpointAxis === POLYLINE_X) {
326
+ result.push(midpointX, sy, midpointX, ey);
327
+ } else {
328
+ result.push(sx, midpointY, ex, midpointY);
329
+ }
330
+ result.push(ex, ey, endPoint.x, endPoint.y);
331
+ for (let i = 4; i < result.length - 2; i += 2) {
332
+ const x1 = result[i - 2], y1 = result[i - 1];
333
+ const x2 = result[i], y2 = result[i + 1];
334
+ if (isPolylineSegmentBlocked(x1, y1, x2, y2, startBounds, clearance) || isPolylineSegmentBlocked(x1, y1, x2, y2, endBounds, clearance)) return Infinity;
335
+ }
336
+ return getPolylineScore(result, clearance);
337
+ }
338
+
339
+ function getPolylineRoute(result, startPoint, endPoint, startPort, endPort, startBounds, endBounds, clearance) {
340
+ const startExit = [], endExit = [];
341
+ getPolylineExit(startPoint, startBounds, startPort, clearance, startExit);
342
+ getPolylineExit(endPoint, endBounds, endPort, clearance, endExit);
343
+ const sx = startExit[0], sy = startExit[1], ex = endExit[0], ey = endExit[1];
344
+ const startAxis = startPort >> 1, endAxis = endPort >> 1;
345
+ const startSign = startPort & 1 ? 1 : -1, endSign = endPort & 1 ? 1 : -1;
346
+ const startStub = Math.abs(sx - startPoint.x) + Math.abs(sy - startPoint.y);
347
+ const endStub = Math.abs(ex - endPoint.x) + Math.abs(ey - endPoint.y);
348
+ if (isPolylineSegmentBlocked(startPoint.x, startPoint.y, sx, sy, endBounds, clearance) || isPolylineSegmentBlocked(endPoint.x, endPoint.y, ex, ey, startBounds, clearance)) return Infinity;
349
+ const midpointAxis = getPolylineMidpointAxis(startPort, endPort, sx, sy, ex, ey);
350
+ const midpointScore = getPolylineMidpointRoute(result, startPoint, endPoint, sx, sy, ex, ey, midpointAxis, startBounds, endBounds, clearance);
351
+ if (midpointScore < Infinity) return midpointScore;
352
+ const margin = Math.max(clearance, POLYLINE_MIN_SEGMENT) * 2;
353
+ const xs = [ sx, ex, (sx + ex) / 2 ], ys = [ sy, ey, (sy + ey) / 2 ];
354
+ addPolylineBoundsCoordinates(xs, ys, startBounds, clearance, margin);
355
+ addPolylineBoundsCoordinates(xs, ys, endBounds, clearance, margin);
356
+ let minX = Math.min(...xs), maxX = Math.max(...xs);
357
+ let minY = Math.min(...ys), maxY = Math.max(...ys);
358
+ xs.push(minX - margin * 2, maxX + margin * 2);
359
+ ys.push(minY - margin * 2, maxY + margin * 2);
360
+ sortPolylineCoordinates(xs);
361
+ sortPolylineCoordinates(ys);
362
+ const nx = xs.length, ny = ys.length;
363
+ const startXIndex = getPolylineCoordinateIndex(xs, sx), startYIndex = getPolylineCoordinateIndex(ys, sy);
364
+ const endXIndex = getPolylineCoordinateIndex(xs, ex), endYIndex = getPolylineCoordinateIndex(ys, ey);
365
+ if (startXIndex < 0 || startYIndex < 0 || endXIndex < 0 || endYIndex < 0) return Infinity;
366
+ const startNode = startYIndex * nx + startXIndex, endNode = endYIndex * nx + endXIndex;
367
+ const total = nx * ny * 3;
368
+ const distance = new Float64Array(total), previous = new Int32Array(total), visited = new Uint8Array(total);
369
+ distance.fill(Infinity);
370
+ previous.fill(-1);
371
+ const startState = startNode * 3;
372
+ distance[startState] = 0;
373
+ const turnCost = Math.max(POLYLINE_MIN_SEGMENT, clearance * POLYLINE_TURN_WEIGHT);
374
+ let currentState = -1, currentNode = -1, currentAxis = 0;
375
+ let currentX = 0, currentY = 0, currentDistance = 0;
376
+ const relax = (nextXIndex, nextYIndex, axis, sign) => {
377
+ const nextX = xs[nextXIndex], nextY = ys[nextYIndex];
378
+ const nextNode = nextYIndex * nx + nextXIndex;
379
+ if (isPolylinePointBlocked(nextX, nextY, startBounds, clearance) || isPolylinePointBlocked(nextX, nextY, endBounds, clearance)) return;
380
+ if (isPolylineSegmentBlocked(currentX, currentY, nextX, nextY, startBounds, clearance) || isPolylineSegmentBlocked(currentX, currentY, nextX, nextY, endBounds, clearance)) return;
381
+ if (currentState === startState) {
382
+ if (axis === startAxis + 1) {
383
+ if (sign !== startSign) return;
384
+ } else if (startStub <= POLYLINE_EPSILON) return;
385
+ }
386
+ if (nextNode === endNode) {
387
+ if (axis === endAxis + 1) {
388
+ if (sign !== -endSign) return;
389
+ } else if (endStub <= POLYLINE_EPSILON) return;
390
+ }
391
+ const nextState = nextNode * 3 + axis;
392
+ if (visited[nextState]) return;
393
+ const segmentLength = Math.abs(nextX - currentX) + Math.abs(nextY - currentY);
394
+ let cost = currentDistance + segmentLength;
395
+ if (currentAxis && currentAxis !== axis) {
396
+ cost += turnCost;
397
+ const turnCoordinate = currentAxis === POLYLINE_X + 1 ? currentX : currentY;
398
+ const preferredCoordinate = midpointAxis === POLYLINE_X ? (sx + ex) / 2 : (sy + ey) / 2;
399
+ if (Math.abs(turnCoordinate - preferredCoordinate) > POLYLINE_EPSILON) cost += turnCost * 2;
400
+ }
401
+ if (cost < distance[nextState]) {
402
+ distance[nextState] = cost;
403
+ previous[nextState] = currentState;
404
+ }
405
+ };
406
+ let bestState = -1;
407
+ for (let iteration = 0; iteration < total; iteration++) {
408
+ let minDistance = Infinity, state = -1;
409
+ for (let i = 0; i < total; i++) {
410
+ if (!visited[i] && distance[i] < minDistance) {
411
+ minDistance = distance[i];
412
+ state = i;
413
+ }
414
+ }
415
+ if (state < 0) break;
416
+ currentState = state;
417
+ currentNode = Math.floor(state / 3);
418
+ currentAxis = state % 3;
419
+ currentDistance = minDistance;
420
+ visited[state] = 1;
421
+ if (currentNode === endNode) {
422
+ bestState = state;
423
+ break;
424
+ }
425
+ const xIndex = currentNode % nx, yIndex = Math.floor(currentNode / nx);
426
+ currentX = xs[xIndex];
427
+ currentY = ys[yIndex];
428
+ if (xIndex > 0) relax(xIndex - 1, yIndex, POLYLINE_X + 1, -1);
429
+ if (xIndex < nx - 1) relax(xIndex + 1, yIndex, POLYLINE_X + 1, 1);
430
+ if (yIndex > 0) relax(xIndex, yIndex - 1, POLYLINE_Y + 1, -1);
431
+ if (yIndex < ny - 1) relax(xIndex, yIndex + 1, POLYLINE_Y + 1, 1);
432
+ }
433
+ if (bestState < 0) return Infinity;
434
+ const reverse = [];
435
+ let state = bestState;
436
+ while (state >= 0) {
437
+ const node = Math.floor(state / 3);
438
+ reverse.push(xs[node % nx], ys[Math.floor(node / nx)]);
439
+ if (state === startState) break;
440
+ state = previous[state];
441
+ }
442
+ if (state !== startState) return Infinity;
443
+ result.length = 0;
444
+ result.push(startPoint.x, startPoint.y, sx, sy);
445
+ for (let i = reverse.length - 4; i >= 0; i -= 2) result.push(reverse[i], reverse[i + 1]);
446
+ result.push(endPoint.x, endPoint.y);
447
+ return distance[bestState] + startStub + endStub;
448
+ }
449
+
450
+ function appendPolylinePoint(points, x, y) {
451
+ const length = points.length;
452
+ if (length >= 2 && Math.abs(points[length - 2] - x) <= POLYLINE_EPSILON && Math.abs(points[length - 1] - y) <= POLYLINE_EPSILON) return;
453
+ points.push(x, y);
454
+ }
455
+
456
+ function appendPolylineOrthogonal(points, x1, y1, x2, y2, firstAxis = POLYLINE_X) {
457
+ if (Math.abs(x1 - x2) > POLYLINE_EPSILON && Math.abs(y1 - y2) > POLYLINE_EPSILON) {
458
+ if (firstAxis === POLYLINE_X) {
459
+ const midX = (x1 + x2) / 2;
460
+ appendPolylinePoint(points, midX, y1);
461
+ appendPolylinePoint(points, midX, y2);
462
+ } else {
463
+ const midY = (y1 + y2) / 2;
464
+ appendPolylinePoint(points, x1, midY);
465
+ appendPolylinePoint(points, x2, midY);
466
+ }
467
+ }
468
+ appendPolylinePoint(points, x2, y2);
469
+ }
470
+
471
+ function getPolylineEditPath(result, startPoint, endPoint, startPort, endPort, startBounds, endBounds, points, clearance) {
472
+ if (points.length % 2) return Infinity;
473
+ for (let i = 0; i < points.length; i++) if (!Number.isFinite(points[i])) return Infinity;
474
+ const startExit = [], endExit = [];
475
+ getPolylineExit(startPoint, startBounds, startPort, clearance, startExit);
476
+ getPolylineExit(endPoint, endBounds, endPort, clearance, endExit);
477
+ const sx = startExit[0], sy = startExit[1], ex = endExit[0], ey = endExit[1];
478
+ if (isPolylineSegmentBlocked(startPoint.x, startPoint.y, sx, sy, endBounds, clearance) || isPolylineSegmentBlocked(endPoint.x, endPoint.y, ex, ey, startBounds, clearance)) return Infinity;
479
+ result.length = 0;
480
+ appendPolylinePoint(result, startPoint.x, startPoint.y);
481
+ appendPolylinePoint(result, sx, sy);
482
+ let x = sx, y = sy;
483
+ for (let i = 0; i < points.length; i += 2) {
484
+ const nx = points[i], ny = points[i + 1];
485
+ appendPolylineOrthogonal(result, x, y, nx, ny, i === 0 && clearance === 0 ? startPort >> 1 : POLYLINE_X);
486
+ x = nx;
487
+ y = ny;
488
+ }
489
+ const endAxis = endPort >> 1;
490
+ if (Math.abs(x - ex) > POLYLINE_EPSILON && Math.abs(y - ey) > POLYLINE_EPSILON) {
491
+ if (endAxis === POLYLINE_X) appendPolylinePoint(result, x, ey); else appendPolylinePoint(result, ex, y);
492
+ }
493
+ appendPolylinePoint(result, ex, ey);
494
+ appendPolylinePoint(result, endPoint.x, endPoint.y);
495
+ return getPolylineScore(result, clearance);
496
+ }
497
+
498
+ function getPolylineScore(points, clearance) {
499
+ let length = 0, turns = 0, previousAxis = -1;
500
+ for (let i = 2; i < points.length; i += 2) {
501
+ const dx = points[i] - points[i - 2], dy = points[i + 1] - points[i - 1];
502
+ if (Math.abs(dx) <= POLYLINE_EPSILON && Math.abs(dy) <= POLYLINE_EPSILON) continue;
503
+ const axis = Math.abs(dx) > POLYLINE_EPSILON ? POLYLINE_X : POLYLINE_Y;
504
+ length += Math.abs(dx) + Math.abs(dy);
505
+ if (previousAxis !== -1 && previousAxis !== axis) turns++;
506
+ previousAxis = axis;
507
+ }
508
+ return length + turns * Math.max(clearance, POLYLINE_MIN_SEGMENT) * POLYLINE_TURN_WEIGHT;
509
+ }
510
+
511
+ function simplifyPolyline(points) {
512
+ let write = 2;
513
+ for (let read = 2; read < points.length; read += 2) {
514
+ const x = points[read], y = points[read + 1];
515
+ const px = points[write - 2], py = points[write - 1];
516
+ if (Math.abs(x - px) <= POLYLINE_EPSILON && Math.abs(y - py) <= POLYLINE_EPSILON) continue;
517
+ if (write >= 4) {
518
+ const ax = points[write - 4], ay = points[write - 3];
519
+ const horizontal = Math.abs(ay - py) <= POLYLINE_EPSILON && Math.abs(py - y) <= POLYLINE_EPSILON && (px - ax) * (x - px) >= 0;
520
+ const vertical = Math.abs(ax - px) <= POLYLINE_EPSILON && Math.abs(px - x) <= POLYLINE_EPSILON && (py - ay) * (y - py) >= 0;
521
+ if (horizontal || vertical) {
522
+ points[write - 2] = x;
523
+ points[write - 1] = y;
524
+ continue;
525
+ }
526
+ }
527
+ points[write++] = x;
528
+ points[write++] = y;
529
+ }
530
+ points.length = write;
531
+ }
532
+
533
+ function drawPolyline(path, startPoint, endPoint, startDirection, endDirection, startBounds, endBounds, clearance = 8, points) {
534
+ if (!Number.isFinite(startPoint.x) || !Number.isFinite(startPoint.y) || !Number.isFinite(endPoint.x) || !Number.isFinite(endPoint.y)) return false;
535
+ if (startBounds && (!Number.isFinite(startBounds.x) || !Number.isFinite(startBounds.y) || !Number.isFinite(startBounds.width) || !Number.isFinite(startBounds.height) || startBounds.width < 0 || startBounds.height < 0)) return false;
536
+ if (endBounds && (!Number.isFinite(endBounds.x) || !Number.isFinite(endBounds.y) || !Number.isFinite(endBounds.width) || !Number.isFinite(endBounds.height) || endBounds.width < 0 || endBounds.height < 0)) return false;
537
+ clearance = Number.isFinite(clearance) ? Math.max(0, clearance) : 8;
538
+ const startPorts = [], endPorts = [];
539
+ const startCount = getPolylinePorts(startDirection, startPoint, endPoint, startBounds, endBounds, startPorts);
540
+ const endCount = getPolylinePorts(endDirection, endPoint, startPoint, endBounds, startBounds, endPorts);
541
+ const candidate = [], best = [];
542
+ let bestScore = Infinity;
543
+ for (let pass = 0; pass < 2 && bestScore === Infinity; pass++) {
544
+ const currentClearance = pass === 0 ? clearance : 0;
545
+ for (let i = 0; i < startCount; i++) {
546
+ for (let j = 0; j < endCount; j++) {
547
+ const score = points !== undefined ? getPolylineEditPath(candidate, startPoint, endPoint, startPorts[i], endPorts[j], startBounds, endBounds, points, currentClearance) : getPolylineRoute(candidate, startPoint, endPoint, startPorts[i], endPorts[j], startBounds, endBounds, currentClearance);
548
+ if (score < bestScore) {
549
+ bestScore = score;
550
+ best.length = 0;
551
+ for (let k = 0; k < candidate.length; k++) best.push(candidate[k]);
552
+ }
553
+ }
554
+ }
555
+ }
556
+ if (!best.length) return false;
557
+ if (points === undefined) simplifyPolyline(best);
558
+ moveTo$1(path, best[0], best[1]);
559
+ for (let i = 2; i < best.length; i += 2) lineTo$1(path, best[i], best[i + 1]);
560
+ return true;
561
+ }
562
+
563
+ const {moveTo: moveTo, lineTo: lineTo, bezierCurveTo: bezierCurveTo, drawPoints: drawPoints$1} = PathCommandDataHelper;
185
564
 
186
565
  const {isEmpty: isEmpty, getPoint: getPoint} = BoundsHelper;
187
566
 
@@ -274,7 +653,7 @@ let Linker = class Linker extends Line {
274
653
  }
275
654
  }
276
655
  updateLinkerPoint(type) {
277
- const {startPoint: startPoint, endPoint: endPoint} = this;
656
+ const {startPoint: startPoint, endPoint: endPoint, lineType: lineType} = this;
278
657
  const nowPoint = type === "end" ? endPoint : startPoint;
279
658
  if (nowPoint) {
280
659
  const data = {};
@@ -299,6 +678,7 @@ let Linker = class Linker extends Line {
299
678
  if (isEmpty(boxBounds)) LeafHelper.updateBounds(ui);
300
679
  p = getPoint(boxBounds, point, true);
301
680
  ui.getWorldPointByBox(p, this, false, true);
681
+ if (lineType === "polyline") data.bounds = ui.getBounds("box", this.parent);
302
682
  }
303
683
  } else {
304
684
  if (isObject(point)) p = point;
@@ -324,56 +704,69 @@ let Linker = class Linker extends Line {
324
704
  }
325
705
  const startPoint = startData.point, endPoint = endData.point;
326
706
  const startDirection = startData.direction, endDirection = endData.direction;
327
- const half = {
328
- x: abs((startPoint.x - endPoint.x) / 2),
329
- y: abs((startPoint.y - endPoint.y) / 2)
330
- };
331
707
  const arrowWidth = this.__.strokeWidth * 8;
332
- let minCtrl;
333
- if (this.__.__useArrow) {
334
- const ratio = min(getDistance(startPoint, endPoint) / (arrowWidth * 25), 1);
335
- minCtrl = max(arrowWidth * ratio * 12, arrowWidth * 3);
336
- } else {
337
- minCtrl = arrowWidth * 2;
338
- }
339
- if (endDirection) {
340
- if (isOppositeDirection(startDirection, endDirection) && startDirection === getDirectionForFromPoint(startPoint, endPoint)) {
708
+ switch (data.lineType) {
709
+ case "straight":
710
+ moveTo(path, startPoint.x, startPoint.y);
711
+ lineTo(path, endPoint.x, endPoint.y);
712
+ break;
713
+
714
+ case "polyline":
715
+ drawPolyline(path, startPoint, endPoint, startDirection, endDirection, startData.bounds, endData.bounds, arrowWidth, hasPoints && PointHelper.toNumberPoints(data.points));
716
+ break;
717
+
718
+ case "curve":
719
+ default:
720
+ const half = {
721
+ x: abs((startPoint.x - endPoint.x) / 2),
722
+ y: abs((startPoint.y - endPoint.y) / 2)
723
+ };
724
+ let minCtrl;
725
+ if (this.__.__useArrow) {
726
+ const ratio = min(getDistance(startPoint, endPoint) / (arrowWidth * 25), 1);
727
+ minCtrl = max(arrowWidth * ratio * 12, arrowWidth * 3);
728
+ } else {
341
729
  minCtrl = arrowWidth * 2;
342
730
  }
343
- }
344
- half.x = max(minCtrl, half.x);
345
- half.y = max(minCtrl, half.y);
346
- if (hasPoints) {
347
- minCtrl *= .6;
348
- const points = PointHelper.toNumberPoints(data.points);
349
- drawPoints$1(path, [ startPoint.x, startPoint.y, ...points, endPoint.x, endPoint.y ], data.curve, false, data);
350
- if (startDirection) {
351
- const handleX = path[4];
352
- const handleY = path[5];
353
- half.x = max(minCtrl, abs(handleX - startPoint.x));
354
- half.y = max(minCtrl, abs(handleY - startPoint.y));
355
- const startCtrlPoint = getCtrlPoint(this, startNode, startPoint, startDirection, half);
356
- path[4] = startCtrlPoint.x;
357
- path[5] = startCtrlPoint.y;
358
- }
359
- const len = path.length;
360
731
  if (endDirection) {
361
- const handleX = path[len - 4];
362
- const handleY = path[len - 3];
363
- half.x = max(minCtrl, abs(handleX - endPoint.x));
364
- half.y = max(minCtrl, abs(handleY - endPoint.y));
365
- const endCtrlPoint = getCtrlPoint(this, endNode, endPoint, endDirection, half);
366
- path[len - 4] = endCtrlPoint.x;
367
- path[len - 3] = endCtrlPoint.y;
732
+ if (isOppositeDirection(startDirection, endDirection) && startDirection === getDirectionForFromPoint(startPoint, endPoint)) {
733
+ minCtrl = arrowWidth * 2;
734
+ }
735
+ }
736
+ half.x = max(minCtrl, half.x);
737
+ half.y = max(minCtrl, half.y);
738
+ if (hasPoints) {
739
+ minCtrl *= .6;
740
+ const points = PointHelper.toNumberPoints(data.points);
741
+ drawPoints$1(path, [ startPoint.x, startPoint.y, ...points, endPoint.x, endPoint.y ], data.curve, false, data);
742
+ if (startDirection) {
743
+ const handleX = path[4];
744
+ const handleY = path[5];
745
+ half.x = max(minCtrl, abs(handleX - startPoint.x));
746
+ half.y = max(minCtrl, abs(handleY - startPoint.y));
747
+ const startCtrlPoint = getCtrlPoint(this, startNode, startPoint, startDirection, half);
748
+ path[4] = startCtrlPoint.x;
749
+ path[5] = startCtrlPoint.y;
750
+ }
751
+ const len = path.length;
752
+ if (endDirection) {
753
+ const handleX = path[len - 4];
754
+ const handleY = path[len - 3];
755
+ half.x = max(minCtrl, abs(handleX - endPoint.x));
756
+ half.y = max(minCtrl, abs(handleY - endPoint.y));
757
+ const endCtrlPoint = getCtrlPoint(this, endNode, endPoint, endDirection, half);
758
+ path[len - 4] = endCtrlPoint.x;
759
+ path[len - 3] = endCtrlPoint.y;
760
+ } else {
761
+ path[len - 4] = endPoint.x;
762
+ path[len - 3] = endPoint.y;
763
+ }
368
764
  } else {
369
- path[len - 4] = endPoint.x;
370
- path[len - 3] = endPoint.y;
765
+ const startCtrlPoint = startDirection ? getCtrlPoint(this, startNode, startPoint, startDirection, half) : startPoint;
766
+ const endCtrlPoint = endDirection ? getCtrlPoint(this, endNode, endPoint, endDirection, half) : endPoint;
767
+ moveTo(path, startPoint.x, startPoint.y);
768
+ bezierCurveTo(path, startCtrlPoint.x, startCtrlPoint.y, endCtrlPoint.x, endCtrlPoint.y, endPoint.x, endPoint.y);
371
769
  }
372
- } else {
373
- const startCtrlPoint = startDirection ? getCtrlPoint(this, startNode, startPoint, startDirection, half) : startPoint;
374
- const endCtrlPoint = endDirection ? getCtrlPoint(this, endNode, endPoint, endDirection, half) : endPoint;
375
- moveTo(path, startPoint.x, startPoint.y);
376
- bezierCurveTo(path, startCtrlPoint.x, startCtrlPoint.y, endCtrlPoint.x, endCtrlPoint.y, endPoint.x, endPoint.y);
377
770
  }
378
771
  }
379
772
  createStartPoint(worldPoint, node, options) {
@@ -443,6 +836,8 @@ let Linker = class Linker extends Line {
443
836
 
444
837
  __decorate([ dataProcessor(LinkerData) ], Linker.prototype, "__", void 0);
445
838
 
839
+ __decorate([ boundsType("curve") ], Linker.prototype, "lineType", void 0);
840
+
446
841
  __decorate([ linkerPointType() ], Linker.prototype, "startPoint", void 0);
447
842
 
448
843
  __decorate([ linkerPointType() ], Linker.prototype, "endPoint", void 0);
@@ -1,2 +1,2 @@
1
- import{LineData as t,AroundHelper as e,PointHelper as n,Direction9 as o,BoundsHelper as i,decorateLeafAttr as r,attr as s,doBoundsType as a,doStrokeType as d,PathCommandDataHelper as h,dataProcessor as c,pathType as u,registerUI as l,Line as p,BoundsEvent as f,LeafHelper as y,isString as g,isObject as x,Plugin as P,registerPointsCurve as k}from"@leafer-ui/draw";import{PointHelper as b,PathCommandMap as L}from"@leafer-ui/core";function N(t,e,n,o){var i,r=arguments.length,s=r<3?e:null===o?o=Object.getOwnPropertyDescriptor(e,n):o;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(t,e,n,o);else for(var a=t.length-1;a>=0;a--)(i=t[a])&&(s=(r<3?i(s):r>3?i(e,n,s):i(e,n))||s);return r>3&&s&&Object.defineProperty(e,n,s),s}"function"==typeof SuppressedError&&SuppressedError;class m extends t{get __usePathBox(){return this.path||this.__pathInputed}}const{directionData:C}=e,M=["top-left","top","top-right","right","bottom-right","bottom","bottom-left","left","center"],_={getCtrlPoint(t,e,n,o,i,r){let s;switch(e&&(n=e.getBoxPoint(n,t)),o){case"left":case"top-left":case"bottom-left":s={x:n.x-i.x,y:n.y};break;case"top":s={x:n.x,y:n.y-i.y};break;case"right":case"top-right":case"bottom-right":s={x:n.x+i.x,y:n.y};break;case"bottom":s={x:n.x,y:n.y+i.y};break;default:s={x:n.x,y:n.y}}return r&&(r=r/180*Math.PI,s={x:(s.x-n.x)*Math.cos(r)-(s.y-n.y)*Math.sin(r)+n.x,y:(s.x-n.x)*Math.sin(r)+(s.y-n.y)*Math.cos(r)+n.y}),e&&e.getWorldPointByBox(s,t,void 0,!0),s},isOppositeDirection(t,e){switch(t){case"left":return"right"==e;case"top":return"bottom"==e;case"right":return"left"==e;case"bottom":return"top"==e;case"center":return"center"==e;default:return!1}},getDirectionForFromPoint(t,e){const n=t.x-e.x,o=t.y-e.y;let i,r=180*Math.atan2(o,n)/Math.PI;return r<0&&(r=360+r),i=r>315||r<45?"left":r>45&&r<135?"top":r>135&&r<225?"right":"bottom",i},getRotateDirection(t,e,n=8){let i=o[t];return i=(i+Math.round(e/(360/n)))%n,i<0&&(i+=n),M[i]},getDirection:function(t,e,n){const{width:o,height:r}=e,s=i.getPoint(e,"center",!0),a=t.x-s.x,d=t.y-s.y;if(!n&&Math.abs(a)<o/4&&Math.abs(d)<r/4)return"center";const h=Math.abs(a)*r,c=Math.abs(d)*o;if(h>c)return a>0?"right":"left";return d>0?"bottom":"top"},getPointDirection:function(t,e,n){const{width:o,height:i}=e,r=o/4,s=i/4;for(let e=0;e<C.length;e++){const a=C[e],d=a.x*o,h=a.y*i,c=t.x-d,u=t.y-h;if(Math.abs(c)<=r&&Math.abs(u)<=s){if(!n)return M[e];if("center"!==M[e])return M[e]}}return},autoRotatePoint(t,e,o){const{rotation:i,scaleX:r,scaleY:s}=o,a=r*s<0;(i||a)&&n.rotate(t,a?-i:i,e)}};function D(t){return r(t,t=>s({set(e){if(this.__setAttr(t,e)){const t=this.__layout;t.linkerChanged||(a(this),d(this),t.linkerChanged=!0)}}}))}const{moveTo:B,bezierCurveTo:v,drawPoints:w}=h,{isEmpty:E,getPoint:R}=i,{getDistance:O}=n,{getCtrlPoint:S,getDirectionForFromPoint:W,isOppositeDirection:q}=_,{max:I,min:j,abs:F}=Math;let z=class extends p{get __tag(){return"Linker"}constructor(t){super(t),this.onStartNodeChange=this.onStartNodeChange.bind(this),this.onEndNodeChange=this.onEndNodeChange.bind(this)}__updatePath(){const t=this.__layout,{startNode:e,endNode:n}=this;t.linkerChanged&&(this.updateLinkerNode("start"),this.updateLinkerNode("end"),this.updateLinkerPoint("start"),this.updateLinkerPoint("end"),e!==this.startNode&&this.listenLinkerNode(this.startNode,e,"start"),n!==this.endNode&&this.listenLinkerNode(this.endNode,n,"end"),t.linkerChanged=!1),this.updateLinkerPath()}listenLinkerNode(t,e,n){if(e){e.off(f.WORLD,"end"===n?this.onEndNodeChange:this.onStartNodeChange);const t="end"===n?e.endLinker:e.startLinker;if(t){const e=t.indexOf(this);e>-1&&t.splice(e,1)}}if(t){t.on(f.WORLD,"end"===n?this.onEndNodeChange:this.onStartNodeChange);("end"===n?t.endLinker||(t.endLinker=[]):t.startLinker||(t.startLinker=[])).push(this)}}onStartNodeChange(){this.onLinkerNodeChange("start")}onEndNodeChange(){this.onLinkerNodeChange("end")}onLinkerNodeChange(t){if(this.leaferIsCreated){const{layouter:t,zoomLayer:e}=this.leafer;if(t.__updatedList.has(e))return;t.addExtra(this,!0)}const{startData:e,endData:n}=this;"start"==t?(this.updateLinkerPoint("start"),n&&n.auto&&this.updateLinkerPoint("end")):(e&&e.auto&&this.updateLinkerPoint("start"),this.updateLinkerPoint("end")),this.__layout.boxChange(),y.updateBounds(this)}updateLinkerNode(t){const{startPoint:e,endPoint:n}=this,o="end"===t?n:e;if(o){const{id:e}=o,n=e&&(g(e)?this.app.findId(e):e);"end"===t?this.endNode=n:this.startNode=n}}getLinkerNodeCenter(t){const{startPoint:e,endPoint:n,startNode:o,endNode:i,startData:r,endData:s}=this,a="end"===t?i:o,d="end"===t?s||n:r||e;if(a){const{worldRenderBounds:t}=a;return E(t)&&y.updateBounds(a),R(a.worldRenderBounds,"center")}return d&&x(d.point)&&this.getWorldPointByLocal(d.point)}updateLinkerPoint(t){const{startPoint:e,endPoint:o}=this,i="end"===t?o:e;if(i){const e={},{id:o,offset:r}=i;let{direction:s,point:a}=i;if("center"===s||!s&&o&&!a){const n=this.getLinkerNodeCenter("start"),o=this.getLinkerNodeCenter("end"),i="end"===t?o:n,r="end"===t?n:o;i&&r&&(s=W(i,r)),e.auto=!0}!s&&g(a)&&(s=a),e.direction=s;const d="end"===t?this.endNode:this.startNode;let h;if(d){if(a||(a=s),a){const{boxBounds:t}=d;E(t)&&y.updateBounds(d),h=R(t,a,!0),d.getWorldPointByBox(h,this,!1,!0)}}else x(a)&&(h=a);if(h&&r){const t=Object.assign({},r);r.x||(t.x=0),r.y||(t.y=0),d&&d.getWorldPoint(t,this,!0,!0),n.move(h,t)}e.point=h,"end"===t?this.endData=h&&e:this.startData=h&&e}}updateLinkerPath(){const t=this.__,e=t.path=[],o=t.points&&t.points.length,{startData:i,endData:r,startNode:s,endNode:a}=this;if(!i||!r)return;const d=i.point,h=r.point,c=i.direction,u=r.direction,l={x:F((d.x-h.x)/2),y:F((d.y-h.y)/2)},p=8*this.__.strokeWidth;let f;if(this.__.__useArrow){const t=j(O(d,h)/(25*p),1);f=I(p*t*12,3*p)}else f=2*p;if(u&&q(c,u)&&c===W(d,h)&&(f=2*p),l.x=I(f,l.x),l.y=I(f,l.y),o){f*=.6;const o=n.toNumberPoints(t.points);if(w(e,[d.x,d.y,...o,h.x,h.y],t.curve,!1,t),c){const t=e[4],n=e[5];l.x=I(f,F(t-d.x)),l.y=I(f,F(n-d.y));const o=S(this,s,d,c,l);e[4]=o.x,e[5]=o.y}const i=e.length;if(u){const t=e[i-4],n=e[i-3];l.x=I(f,F(t-h.x)),l.y=I(f,F(n-h.y));const o=S(this,a,h,u,l);e[i-4]=o.x,e[i-3]=o.y}else e[i-4]=h.x,e[i-3]=h.y}else{const t=c?S(this,s,d,c,l):d,n=u?S(this,a,h,u,l):h;B(e,d.x,d.y),v(e,t.x,t.y,n.x,n.y,h.x,h.y)}}createStartPoint(t,e,n){const o=this.createLinkerPoint(t,e,n);return this.startPoint=o,o}createEndPoint(t,e,n){const o=this.createLinkerPoint(t,e,n);return this.endPoint=o,o}createLinkerPoint(t,e,n){const o={};if(e&&e.id){const r=e.getBoxPoint(t),{boxBounds:s}=e,a=n&&n.mode,d="edge"===a||!a,h="four"===a,c="free"===a;if(!("auto"===a))if(h)o.point=_.getDirection(r,s,h);else if(o.direction=_.getDirection(r,s,d),o.point=_.getPointDirection(r,s,d)||o.direction,o.point===o.direction&&delete o.direction,c||d){const t=i.getPoint(s,o.point),e=r.x-t.x,a=r.y-t.y,h=n&&n.snapRadius||10;if(Math.abs(e)>h||Math.abs(a)>h){const t=o.offset={x:Math.abs(e)>h?e:0,y:Math.abs(a)>h?a:0};if(d&&(t.x||t.y))switch(o.direction||o.point){case"top":case"bottom":t.y=0;break;case"right":case"left":t.x=0;break;default:t.x>t.y?t.y=0:t.x=0}}}o.id=e.id}else o.point=this.getLocalPoint(t);return o}};N([c(m)],z.prototype,"__",void 0),N([D()],z.prototype,"startPoint",void 0),N([D()],z.prototype,"endPoint",void 0),N([u({type:"C",value:.5})],z.prototype,"curve",void 0),z=N([l()],z);const{toNumberPoints:A}=b,{M:T,L:H,C:X,Z:Y}=L;P.add("linker"),k("C",function(t,e,n,o){const i=A(e),r=i.length>>1;if(r<2)return;if(t.push(T,i[0],i[1]),!n||r<3){for(let e=1;e<r;e++)t.push(H,i[2*e],i[2*e+1]);return void(o&&t.push(Y))}let s=!0===n?.5:n;s<0?s=0:s>1&&(s=1);const a=o?r:r-1;let d=i[0],h=i[1];{const t=i[2]-i[0],e=i[3]-i[1],n=Math.sqrt(t*t+e*e);n&&(d=i[0]+t/n*n*s,h=i[1]+e/n*n*s)}for(let e=0;e<a;e++){const n=e+1===r?0:e+1,o=i[2*n],a=i[2*n+1],c=0===n?r-1:n-1,u=n+1===r?0:n+1;let l=i[2*c]-o,p=i[2*c+1]-a,f=i[2*u]-o,y=i[2*u+1]-a;const g=Math.sqrt(l*l+p*p),x=Math.sqrt(f*f+y*y);let P=o,k=a,b=o,L=a;if(g||x){let t=0,e=0;g&&(t+=l/g,e+=p/g),x&&(t+=f/x,e+=y/x);let n=Math.sqrt(t*t+e*e);n||(x?(t=f/x,e=y/x):(t=l/g,e=p/g),n=1),t/=n,e/=n;let i=-e,r=t;x&&i*f+r*y<0&&(i=-i,r=-r);let d=0;g&&x&&(d=(l*f+p*y)/(g*x),d>1?d=1:d<-1&&(d=-1));let h=Math.sqrt(Math.sqrt(Math.max(0,1-d*d)));h<.15&&(h=.15);let c=g*s*h,u=x*s*h;const N=.5*Math.min(g||x,x||g);c>N&&(c=N),u>N&&(u=N),P=o-i*c,k=a-r*c,b=o+i*u,L=a+r*u}t.push(X,d,h,P,k,o,a),d=b,h=L}o&&t.push(Y)});export{z as Linker,m as LinkerData};
1
+ import{LineData as t,AroundHelper as e,PointHelper as n,Direction9 as i,BoundsHelper as o,decorateLeafAttr as r,attr as s,doBoundsType as a,doStrokeType as h,PathCommandDataHelper as c,dataProcessor as u,boundsType as d,pathType as f,registerUI as l,Line as p,BoundsEvent as y,LeafHelper as x,isString as g,isObject as b,Plugin as M,registerPointsCurve as m}from"@leafer-ui/draw";import{PointHelper as N,PathCommandMap as P}from"@leafer-ui/core";function k(t,e,n,i){var o,r=arguments.length,s=r<3?e:null===i?i=Object.getOwnPropertyDescriptor(e,n):i;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)s=Reflect.decorate(t,e,n,i);else for(var a=t.length-1;a>=0;a--)(o=t[a])&&(s=(r<3?o(s):r>3?o(e,n,s):o(e,n))||s);return r>3&&s&&Object.defineProperty(e,n,s),s}"function"==typeof SuppressedError&&SuppressedError;class L extends t{get __usePathBox(){return this.path||this.__pathInputed}}const{directionData:C}=e,_=["top-left","top","top-right","right","bottom-right","bottom","bottom-left","left","center"],w={getCtrlPoint(t,e,n,i,o,r){let s;switch(e&&(n=e.getBoxPoint(n,t)),i){case"left":case"top-left":case"bottom-left":s={x:n.x-o.x,y:n.y};break;case"top":s={x:n.x,y:n.y-o.y};break;case"right":case"top-right":case"bottom-right":s={x:n.x+o.x,y:n.y};break;case"bottom":s={x:n.x,y:n.y+o.y};break;default:s={x:n.x,y:n.y}}return r&&(r=r/180*Math.PI,s={x:(s.x-n.x)*Math.cos(r)-(s.y-n.y)*Math.sin(r)+n.x,y:(s.x-n.x)*Math.sin(r)+(s.y-n.y)*Math.cos(r)+n.y}),e&&e.getWorldPointByBox(s,t,void 0,!0),s},isOppositeDirection(t,e){switch(t){case"left":return"right"==e;case"top":return"bottom"==e;case"right":return"left"==e;case"bottom":return"top"==e;case"center":return"center"==e;default:return!1}},getDirectionForFromPoint(t,e){const n=t.x-e.x,i=t.y-e.y;let o,r=180*Math.atan2(i,n)/Math.PI;return r<0&&(r=360+r),o=r>315||r<45?"left":r>45&&r<135?"top":r>135&&r<225?"right":"bottom",o},getRotateDirection(t,e,n=8){let o=i[t];return o=(o+Math.round(e/(360/n)))%n,o<0&&(o+=n),_[o]},getDirection:function(t,e,n){const{width:i,height:r}=e,s=o.getPoint(e,"center",!0),a=t.x-s.x,h=t.y-s.y;if(!n&&Math.abs(a)<i/4&&Math.abs(h)<r/4)return"center";const c=Math.abs(a)*r,u=Math.abs(h)*i;if(c>u)return a>0?"right":"left";return h>0?"bottom":"top"},getPointDirection:function(t,e,n){const{width:i,height:o}=e,r=i/4,s=o/4;for(let e=0;e<C.length;e++){const a=C[e],h=a.x*i,c=a.y*o,u=t.x-h,d=t.y-c;if(Math.abs(u)<=r&&Math.abs(d)<=s){if(!n)return _[e];if("center"!==_[e])return _[e]}}return},autoRotatePoint(t,e,i){const{rotation:o,scaleX:r,scaleY:s}=i,a=r*s<0;(o||a)&&n.rotate(t,a?-o:o,e)}};function D(t){return r(t,t=>s({set(e){if(this.__setAttr(t,e)){const t=this.__layout;t.linkerChanged||(a(this),h(this),t.linkerChanged=!0)}}}))}const{directionData:v}=e,{moveTo:F,lineTo:B}=c,E=.001;function R(t,e,n,i,o,r){const s=v[function(t){switch(t){case"top-left":return 0;case"top":return 1;case"top-right":return 2;case"right":return 3;case"bottom-right":return 4;case"bottom":return 5;case"bottom-left":return 6;case"left":return 7;default:return 8}}(t)],a=Math.sign(s.x-.5),h=Math.sign(s.y-.5),c=i?i.x+i.width/2:e.x,u=i?i.y+i.height/2:e.y,d=(o?o.x+o.width/2:n.x)-c,f=(o?o.y+o.height/2:n.y)-u,l=0+((a||(d>=0?1:-1))>0?1:0),p=2+((h||(f>=0?1:-1))>0?1:0);return a&&!h?(r[0]=l,1):h&&!a?(r[0]=p,1):(Math.abs(d)>=Math.abs(f)?(r[0]=l,r[1]=p):(r[0]=p,r[1]=l),2)}function O(t,e,n,i,o){const r=1&n?1:-1;if(0===n>>1){const n=e?r>0?e.x+e.width:e.x:t.x;o[0]=n+r*i,o[1]=t.y}else{const n=e?r>0?e.y+e.height:e.y:t.y;o[0]=t.x,o[1]=n+r*i}}function S(t,e,n,i){if(!n)return!1;const o=n.x-i,r=n.x+n.width+i,s=n.y-i,a=n.y+n.height+i;return t>o+E&&t<r-E&&e>s+E&&e<a-E}function T(t,e,n,i,o,r){if(!o)return!1;const s=o.x-r,a=o.x+o.width+r,h=o.y-r,c=o.y+o.height+r;return Math.abs(e-i)<=E?e>h+E&&e<c-E&&Math.max(Math.min(t,n),s+E)<Math.min(Math.max(t,n),a-E):!(Math.abs(t-n)<=E)||t>s+E&&t<a-E&&Math.max(Math.min(e,i),h+E)<Math.min(Math.max(e,i),c-E)}function W(t,e,n,i,o){if(!n)return;const r=n.x-i,s=n.x+n.width+i,a=n.y-i,h=n.y+n.height+i;t.push(r,s,r-o,s+o),e.push(a,h,a-o,h+o)}function q(t){t.sort((t,e)=>t-e);let e=0;for(let n=0;n<t.length;n++)(!e||Math.abs(t[n]-t[e-1])>E)&&(t[e++]=t[n]);t.length=e}function I(t,e){for(let n=0;n<t.length;n++)if(Math.abs(t[n]-e)<=E)return n;return-1}function A(t,e,n,i,o,r,s,a){const h=[],c=[];O(e,r,i,a,h),O(n,s,o,a,c);const u=h[0],d=h[1],f=c[0],l=c[1],p=i>>1,y=o>>1,x=1&i?1:-1,g=1&o?1:-1,b=Math.abs(u-e.x)+Math.abs(d-e.y),M=Math.abs(f-n.x)+Math.abs(l-n.y);if(T(e.x,e.y,u,d,s,a)||T(n.x,n.y,f,l,r,a))return 1/0;const m=function(t,e,n,i,o,r){const s=t>>1;return s===e>>1&&(1&t?1:-1)==-(1&e?1:-1)?s:Math.abs(o-n)>=Math.abs(r-i)?0:1}(i,o,u,d,f,l),N=function(t,e,n,i,o,r,s,a,h,c,u){const d=(i+r)/2,f=(o+s)/2;t.length=0,t.push(e.x,e.y,i,o),0===a?t.push(d,o,d,s):t.push(i,f,r,f),t.push(r,s,n.x,n.y);for(let e=4;e<t.length-2;e+=2){const n=t[e-2],i=t[e-1],o=t[e],r=t[e+1];if(T(n,i,o,r,h,u)||T(n,i,o,r,c,u))return 1/0}return U(t,u)}(t,e,n,u,d,f,l,m,r,s,a);if(N<1/0)return N;const P=2*Math.max(a,4),k=[u,f,(u+f)/2],L=[d,l,(d+l)/2];W(k,L,r,a,P),W(k,L,s,a,P);let C=Math.min(...k),_=Math.max(...k),w=Math.min(...L),D=Math.max(...L);k.push(C-2*P,_+2*P),L.push(w-2*P,D+2*P),q(k),q(L);const v=k.length,F=L.length,B=I(k,u),R=I(L,d),A=I(k,f),j=I(L,l);if(B<0||R<0||A<0||j<0)return 1/0;const z=R*v+B,H=j*v+A,X=v*F*3,Y=new Float64Array(X),Z=new Int32Array(X),G=new Uint8Array(X);Y.fill(1/0),Z.fill(-1);const J=3*z;Y[J]=0;const K=Math.max(4,1.5*a);let Q=-1,V=-1,$=0,tt=0,et=0,nt=0;const it=(t,e,n,i)=>{const o=k[t],h=L[e],c=e*v+t;if(S(o,h,r,a)||S(o,h,s,a))return;if(T(tt,et,o,h,r,a)||T(tt,et,o,h,s,a))return;if(Q===J)if(n===p+1){if(i!==x)return}else if(b<=E)return;if(c===H)if(n===y+1){if(i!==-g)return}else if(M<=E)return;const N=3*c+n;if(G[N])return;const P=Math.abs(o-tt)+Math.abs(h-et);let C=nt+P;if($&&$!==n){C+=K;const t=1===$?tt:et,e=0===m?(u+f)/2:(d+l)/2;Math.abs(t-e)>E&&(C+=2*K)}C<Y[N]&&(Y[N]=C,Z[N]=Q)};let ot=-1;for(let t=0;t<X;t++){let t=1/0,e=-1;for(let n=0;n<X;n++)!G[n]&&Y[n]<t&&(t=Y[n],e=n);if(e<0)break;if(Q=e,V=Math.floor(e/3),$=e%3,nt=t,G[e]=1,V===H){ot=e;break}const n=V%v,i=Math.floor(V/v);tt=k[n],et=L[i],n>0&&it(n-1,i,1,-1),n<v-1&&it(n+1,i,1,1),i>0&&it(n,i-1,2,-1),i<F-1&&it(n,i+1,2,1)}if(ot<0)return 1/0;const rt=[];let st=ot;for(;st>=0;){const t=Math.floor(st/3);if(rt.push(k[t%v],L[Math.floor(t/v)]),st===J)break;st=Z[st]}if(st!==J)return 1/0;t.length=0,t.push(e.x,e.y,u,d);for(let e=rt.length-4;e>=0;e-=2)t.push(rt[e],rt[e+1]);return t.push(n.x,n.y),Y[ot]+b+M}function j(t,e,n){const i=t.length;i>=2&&Math.abs(t[i-2]-e)<=E&&Math.abs(t[i-1]-n)<=E||t.push(e,n)}function z(t,e,n,i,o,r=0){if(Math.abs(e-i)>E&&Math.abs(n-o)>E)if(0===r){const r=(e+i)/2;j(t,r,n),j(t,r,o)}else{const r=(n+o)/2;j(t,e,r),j(t,i,r)}j(t,i,o)}function H(t,e,n,i,o,r,s,a,h){if(a.length%2)return 1/0;for(let t=0;t<a.length;t++)if(!Number.isFinite(a[t]))return 1/0;const c=[],u=[];O(e,r,i,h,c),O(n,s,o,h,u);const d=c[0],f=c[1],l=u[0],p=u[1];if(T(e.x,e.y,d,f,s,h)||T(n.x,n.y,l,p,r,h))return 1/0;t.length=0,j(t,e.x,e.y),j(t,d,f);let y=d,x=f;for(let e=0;e<a.length;e+=2){const n=a[e],o=a[e+1];z(t,y,x,n,o,0===e&&0===h?i>>1:0),y=n,x=o}const g=o>>1;return Math.abs(y-l)>E&&Math.abs(x-p)>E&&(0===g?j(t,y,p):j(t,l,x)),j(t,l,p),j(t,n.x,n.y),U(t,h)}function U(t,e){let n=0,i=0,o=-1;for(let e=2;e<t.length;e+=2){const r=t[e]-t[e-2],s=t[e+1]-t[e-1];if(Math.abs(r)<=E&&Math.abs(s)<=E)continue;const a=Math.abs(r)>E?0:1;n+=Math.abs(r)+Math.abs(s),-1!==o&&o!==a&&i++,o=a}return n+i*Math.max(e,4)*1.5}function X(t,e,n,i,o,r,s,a=8,h){if(!(Number.isFinite(e.x)&&Number.isFinite(e.y)&&Number.isFinite(n.x)&&Number.isFinite(n.y)))return!1;if(r&&(!Number.isFinite(r.x)||!Number.isFinite(r.y)||!Number.isFinite(r.width)||!Number.isFinite(r.height)||r.width<0||r.height<0))return!1;if(s&&(!Number.isFinite(s.x)||!Number.isFinite(s.y)||!Number.isFinite(s.width)||!Number.isFinite(s.height)||s.width<0||s.height<0))return!1;a=Number.isFinite(a)?Math.max(0,a):8;const c=[],u=[],d=R(i,e,n,r,s,c),f=R(o,n,e,s,r,u),l=[],p=[];let y=1/0;for(let t=0;t<2&&y===1/0;t++){const i=0===t?a:0;for(let t=0;t<d;t++)for(let o=0;o<f;o++){const a=void 0!==h?H(l,e,n,c[t],u[o],r,s,h,i):A(l,e,n,c[t],u[o],r,s,i);if(a<y){y=a,p.length=0;for(let t=0;t<l.length;t++)p.push(l[t])}}}if(!p.length)return!1;void 0===h&&function(t){let e=2;for(let n=2;n<t.length;n+=2){const i=t[n],o=t[n+1],r=t[e-2],s=t[e-1];if(!(Math.abs(i-r)<=E&&Math.abs(o-s)<=E)){if(e>=4){const n=t[e-4],a=t[e-3],h=Math.abs(a-s)<=E&&Math.abs(s-o)<=E&&(r-n)*(i-r)>=0,c=Math.abs(n-r)<=E&&Math.abs(r-i)<=E&&(s-a)*(o-s)>=0;if(h||c){t[e-2]=i,t[e-1]=o;continue}}t[e++]=i,t[e++]=o}}t.length=e}(p),F(t,p[0],p[1]);for(let e=2;e<p.length;e+=2)B(t,p[e],p[e+1]);return!0}const{moveTo:Y,lineTo:Z,bezierCurveTo:G,drawPoints:J}=c,{isEmpty:K,getPoint:Q}=o,{getDistance:V}=n,{getCtrlPoint:$,getDirectionForFromPoint:tt,isOppositeDirection:et}=w,{max:nt,min:it,abs:ot}=Math;let rt=class extends p{get __tag(){return"Linker"}constructor(t){super(t),this.onStartNodeChange=this.onStartNodeChange.bind(this),this.onEndNodeChange=this.onEndNodeChange.bind(this)}__updatePath(){const t=this.__layout,{startNode:e,endNode:n}=this;t.linkerChanged&&(this.updateLinkerNode("start"),this.updateLinkerNode("end"),this.updateLinkerPoint("start"),this.updateLinkerPoint("end"),e!==this.startNode&&this.listenLinkerNode(this.startNode,e,"start"),n!==this.endNode&&this.listenLinkerNode(this.endNode,n,"end"),t.linkerChanged=!1),this.updateLinkerPath()}listenLinkerNode(t,e,n){if(e){e.off(y.WORLD,"end"===n?this.onEndNodeChange:this.onStartNodeChange);const t="end"===n?e.endLinker:e.startLinker;if(t){const e=t.indexOf(this);e>-1&&t.splice(e,1)}}if(t){t.on(y.WORLD,"end"===n?this.onEndNodeChange:this.onStartNodeChange);("end"===n?t.endLinker||(t.endLinker=[]):t.startLinker||(t.startLinker=[])).push(this)}}onStartNodeChange(){this.onLinkerNodeChange("start")}onEndNodeChange(){this.onLinkerNodeChange("end")}onLinkerNodeChange(t){if(this.leaferIsCreated){const{layouter:t,zoomLayer:e}=this.leafer;if(t.__updatedList.has(e))return;t.addExtra(this,!0)}const{startData:e,endData:n}=this;"start"==t?(this.updateLinkerPoint("start"),n&&n.auto&&this.updateLinkerPoint("end")):(e&&e.auto&&this.updateLinkerPoint("start"),this.updateLinkerPoint("end")),this.__layout.boxChange(),x.updateBounds(this)}updateLinkerNode(t){const{startPoint:e,endPoint:n}=this,i="end"===t?n:e;if(i){const{id:e}=i,n=e&&(g(e)?this.app.findId(e):e);"end"===t?this.endNode=n:this.startNode=n}}getLinkerNodeCenter(t){const{startPoint:e,endPoint:n,startNode:i,endNode:o,startData:r,endData:s}=this,a="end"===t?o:i,h="end"===t?s||n:r||e;if(a){const{worldRenderBounds:t}=a;return K(t)&&x.updateBounds(a),Q(a.worldRenderBounds,"center")}return h&&b(h.point)&&this.getWorldPointByLocal(h.point)}updateLinkerPoint(t){const{startPoint:e,endPoint:i,lineType:o}=this,r="end"===t?i:e;if(r){const e={},{id:i,offset:s}=r;let{direction:a,point:h}=r;if("center"===a||!a&&i&&!h){const n=this.getLinkerNodeCenter("start"),i=this.getLinkerNodeCenter("end"),o="end"===t?i:n,r="end"===t?n:i;o&&r&&(a=tt(o,r)),e.auto=!0}!a&&g(h)&&(a=h),e.direction=a;const c="end"===t?this.endNode:this.startNode;let u;if(c){if(h||(h=a),h){const{boxBounds:t}=c;K(t)&&x.updateBounds(c),u=Q(t,h,!0),c.getWorldPointByBox(u,this,!1,!0),"polyline"===o&&(e.bounds=c.getBounds("box",this.parent))}}else b(h)&&(u=h);if(u&&s){const t=Object.assign({},s);s.x||(t.x=0),s.y||(t.y=0),c&&c.getWorldPoint(t,this,!0,!0),n.move(u,t)}e.point=u,"end"===t?this.endData=u&&e:this.startData=u&&e}}updateLinkerPath(){const t=this.__,e=t.path=[],i=t.points&&t.points.length,{startData:o,endData:r,startNode:s,endNode:a}=this;if(!o||!r)return;const h=o.point,c=r.point,u=o.direction,d=r.direction,f=8*this.__.strokeWidth;switch(t.lineType){case"straight":Y(e,h.x,h.y),Z(e,c.x,c.y);break;case"polyline":X(e,h,c,u,d,o.bounds,r.bounds,f,i&&n.toNumberPoints(t.points));break;default:const l={x:ot((h.x-c.x)/2),y:ot((h.y-c.y)/2)};let p;if(this.__.__useArrow){const t=it(V(h,c)/(25*f),1);p=nt(f*t*12,3*f)}else p=2*f;if(d&&et(u,d)&&u===tt(h,c)&&(p=2*f),l.x=nt(p,l.x),l.y=nt(p,l.y),i){p*=.6;const i=n.toNumberPoints(t.points);if(J(e,[h.x,h.y,...i,c.x,c.y],t.curve,!1,t),u){const t=e[4],n=e[5];l.x=nt(p,ot(t-h.x)),l.y=nt(p,ot(n-h.y));const i=$(this,s,h,u,l);e[4]=i.x,e[5]=i.y}const o=e.length;if(d){const t=e[o-4],n=e[o-3];l.x=nt(p,ot(t-c.x)),l.y=nt(p,ot(n-c.y));const i=$(this,a,c,d,l);e[o-4]=i.x,e[o-3]=i.y}else e[o-4]=c.x,e[o-3]=c.y}else{const t=u?$(this,s,h,u,l):h,n=d?$(this,a,c,d,l):c;Y(e,h.x,h.y),G(e,t.x,t.y,n.x,n.y,c.x,c.y)}}}createStartPoint(t,e,n){const i=this.createLinkerPoint(t,e,n);return this.startPoint=i,i}createEndPoint(t,e,n){const i=this.createLinkerPoint(t,e,n);return this.endPoint=i,i}createLinkerPoint(t,e,n){const i={};if(e&&e.id){const r=e.getBoxPoint(t),{boxBounds:s}=e,a=n&&n.mode,h="edge"===a||!a,c="four"===a,u="free"===a;if(!("auto"===a))if(c)i.point=w.getDirection(r,s,c);else if(i.direction=w.getDirection(r,s,h),i.point=w.getPointDirection(r,s,h)||i.direction,i.point===i.direction&&delete i.direction,u||h){const t=o.getPoint(s,i.point),e=r.x-t.x,a=r.y-t.y,c=n&&n.snapRadius||10;if(Math.abs(e)>c||Math.abs(a)>c){const t=i.offset={x:Math.abs(e)>c?e:0,y:Math.abs(a)>c?a:0};if(h&&(t.x||t.y))switch(i.direction||i.point){case"top":case"bottom":t.y=0;break;case"right":case"left":t.x=0;break;default:t.x>t.y?t.y=0:t.x=0}}}i.id=e.id}else i.point=this.getLocalPoint(t);return i}};k([u(L)],rt.prototype,"__",void 0),k([d("curve")],rt.prototype,"lineType",void 0),k([D()],rt.prototype,"startPoint",void 0),k([D()],rt.prototype,"endPoint",void 0),k([f({type:"C",value:.5})],rt.prototype,"curve",void 0),rt=k([l()],rt);const{toNumberPoints:st}=N,{M:at,L:ht,C:ct,Z:ut}=P;M.add("linker"),m("C",function(t,e,n,i){const o=st(e),r=o.length>>1;if(r<2)return;if(t.push(at,o[0],o[1]),!n||r<3){for(let e=1;e<r;e++)t.push(ht,o[2*e],o[2*e+1]);return void(i&&t.push(ut))}let s=!0===n?.5:n;s<0?s=0:s>1&&(s=1);const a=i?r:r-1;let h=o[0],c=o[1];{const t=o[2]-o[0],e=o[3]-o[1],n=Math.sqrt(t*t+e*e);n&&(h=o[0]+t/n*n*s,c=o[1]+e/n*n*s)}for(let e=0;e<a;e++){const n=e+1===r?0:e+1,i=o[2*n],a=o[2*n+1],u=0===n?r-1:n-1,d=n+1===r?0:n+1;let f=o[2*u]-i,l=o[2*u+1]-a,p=o[2*d]-i,y=o[2*d+1]-a;const x=Math.sqrt(f*f+l*l),g=Math.sqrt(p*p+y*y);let b=i,M=a,m=i,N=a;if(x||g){let t=0,e=0;x&&(t+=f/x,e+=l/x),g&&(t+=p/g,e+=y/g);let n=Math.sqrt(t*t+e*e);n||(g?(t=p/g,e=y/g):(t=f/x,e=l/x),n=1),t/=n,e/=n;let o=-e,r=t;g&&o*p+r*y<0&&(o=-o,r=-r);let h=0;x&&g&&(h=(f*p+l*y)/(x*g),h>1?h=1:h<-1&&(h=-1));let c=Math.sqrt(Math.sqrt(Math.max(0,1-h*h)));c<.15&&(c=.15);let u=x*s*c,d=g*s*c;const P=.5*Math.min(x||g,g||x);u>P&&(u=P),d>P&&(d=P),b=i-o*u,M=a-r*u,m=i+o*d,N=a+r*d}t.push(ct,h,c,b,M,i,a),h=m,c=N}i&&t.push(ut)});export{rt as Linker,L as LinkerData};
2
2
  //# sourceMappingURL=linker.esm.min.js.map