@leafer-in/linker 2.3.2 → 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.
@@ -0,0 +1,456 @@
1
+ import { IDirection, IPointData, IBoundsData } from '@leafer-ui/interface'
2
+ import { AroundHelper, PathCommandDataHelper } from '@leafer-ui/draw'
3
+
4
+ const { directionData } = AroundHelper
5
+ const { moveTo, lineTo } = PathCommandDataHelper
6
+
7
+ const POLYLINE_X = 0, POLYLINE_Y = 1
8
+ const POLYLINE_EPSILON = 0.001
9
+ const POLYLINE_MIN_SEGMENT = 4
10
+ const POLYLINE_TURN_WEIGHT = 1.5
11
+
12
+ function getPolylineDirectionIndex(direction: IDirection): number {
13
+ switch (direction) {
14
+ case 'top-left': return 0
15
+ case 'top': return 1
16
+ case 'top-right': return 2
17
+ case 'right': return 3
18
+ case 'bottom-right': return 4
19
+ case 'bottom': return 5
20
+ case 'bottom-left': return 6
21
+ case 'left': return 7
22
+ default: return 8
23
+ }
24
+ }
25
+
26
+ function getPolylinePorts(direction: IDirection, point: IPointData, target: IPointData, bounds: IBoundsData | undefined, targetBounds: IBoundsData | undefined, ports: number[]): number {
27
+ const data = directionData[getPolylineDirectionIndex(direction)]
28
+ const dx = Math.sign(data.x - 0.5), dy = Math.sign(data.y - 0.5)
29
+ const cx = bounds ? bounds.x + bounds.width / 2 : point.x
30
+ const cy = bounds ? bounds.y + bounds.height / 2 : point.y
31
+ const tx = targetBounds ? targetBounds.x + targetBounds.width / 2 : target.x
32
+ const ty = targetBounds ? targetBounds.y + targetBounds.height / 2 : target.y
33
+ const deltaX = tx - cx, deltaY = ty - cy
34
+ const xSign = dx || (deltaX >= 0 ? 1 : -1)
35
+ const ySign = dy || (deltaY >= 0 ? 1 : -1)
36
+ const xPort = POLYLINE_X * 2 + (xSign > 0 ? 1 : 0)
37
+ const yPort = POLYLINE_Y * 2 + (ySign > 0 ? 1 : 0)
38
+
39
+ if (dx && !dy) {
40
+ ports[0] = xPort
41
+ return 1
42
+ }
43
+
44
+ if (dy && !dx) {
45
+ ports[0] = yPort
46
+ return 1
47
+ }
48
+
49
+ if (Math.abs(deltaX) >= Math.abs(deltaY)) {
50
+ ports[0] = xPort
51
+ ports[1] = yPort
52
+ } else {
53
+ ports[0] = yPort
54
+ ports[1] = xPort
55
+ }
56
+
57
+ return 2
58
+ }
59
+
60
+ function getPolylineExit(point: IPointData, bounds: IBoundsData | undefined, port: number, clearance: number, result: number[]): void {
61
+ const axis = port >> 1, sign = port & 1 ? 1 : -1
62
+
63
+ if (axis === POLYLINE_X) {
64
+ const boundary = bounds ? sign > 0 ? bounds.x + bounds.width : bounds.x : point.x
65
+ result[0] = boundary + sign * clearance
66
+ result[1] = point.y
67
+ } else {
68
+ const boundary = bounds ? sign > 0 ? bounds.y + bounds.height : bounds.y : point.y
69
+ result[0] = point.x
70
+ result[1] = boundary + sign * clearance
71
+ }
72
+ }
73
+
74
+ function isPolylinePointBlocked(x: number, y: number, bounds: IBoundsData | undefined, clearance: number): boolean {
75
+ if (!bounds) return false
76
+ const left = bounds.x - clearance, right = bounds.x + bounds.width + clearance
77
+ const top = bounds.y - clearance, bottom = bounds.y + bounds.height + clearance
78
+ return x > left + POLYLINE_EPSILON && x < right - POLYLINE_EPSILON && y > top + POLYLINE_EPSILON && y < bottom - POLYLINE_EPSILON
79
+ }
80
+
81
+ function isPolylineSegmentBlocked(x1: number, y1: number, x2: number, y2: number, bounds: IBoundsData | undefined, clearance: number): boolean {
82
+ if (!bounds) return false
83
+ const left = bounds.x - clearance, right = bounds.x + bounds.width + clearance
84
+ const top = bounds.y - clearance, bottom = bounds.y + bounds.height + clearance
85
+
86
+ if (Math.abs(y1 - y2) <= POLYLINE_EPSILON) {
87
+ return y1 > top + POLYLINE_EPSILON && y1 < bottom - POLYLINE_EPSILON &&
88
+ Math.max(Math.min(x1, x2), left + POLYLINE_EPSILON) < Math.min(Math.max(x1, x2), right - POLYLINE_EPSILON)
89
+ }
90
+
91
+ if (Math.abs(x1 - x2) <= POLYLINE_EPSILON) {
92
+ return x1 > left + POLYLINE_EPSILON && x1 < right - POLYLINE_EPSILON &&
93
+ Math.max(Math.min(y1, y2), top + POLYLINE_EPSILON) < Math.min(Math.max(y1, y2), bottom - POLYLINE_EPSILON)
94
+ }
95
+
96
+ return true
97
+ }
98
+
99
+ function addPolylineBoundsCoordinates(xs: number[], ys: number[], bounds: IBoundsData | undefined, clearance: number, margin: number): void {
100
+ if (!bounds) return
101
+ const left = bounds.x - clearance, right = bounds.x + bounds.width + clearance
102
+ const top = bounds.y - clearance, bottom = bounds.y + bounds.height + clearance
103
+ xs.push(left, right, left - margin, right + margin)
104
+ ys.push(top, bottom, top - margin, bottom + margin)
105
+ }
106
+
107
+ function sortPolylineCoordinates(values: number[]): void {
108
+ values.sort((a, b) => a - b)
109
+ let write = 0
110
+
111
+ for (let i = 0; i < values.length; i++) {
112
+ if (!write || Math.abs(values[i] - values[write - 1]) > POLYLINE_EPSILON) values[write++] = values[i]
113
+ }
114
+
115
+ values.length = write
116
+ }
117
+
118
+ function getPolylineCoordinateIndex(values: number[], value: number): number {
119
+ for (let i = 0; i < values.length; i++) {
120
+ if (Math.abs(values[i] - value) <= POLYLINE_EPSILON) return i
121
+ }
122
+ return -1
123
+ }
124
+
125
+ // 根据两端连接方向确定中点转折轴
126
+ function getPolylineMidpointAxis(startPort: number, endPort: number, sx: number, sy: number, ex: number, ey: number): number {
127
+ const startAxis = startPort >> 1, endAxis = endPort >> 1
128
+ const startSign = startPort & 1 ? 1 : -1, endSign = endPort & 1 ? 1 : -1
129
+
130
+ if (startAxis === endAxis && startSign === -endSign) return startAxis
131
+ return Math.abs(ex - sx) >= Math.abs(ey - sy) ? POLYLINE_X : POLYLINE_Y
132
+ }
133
+
134
+ // 检查中点优先路径
135
+ function getPolylineMidpointRoute(result: number[], startPoint: IPointData, endPoint: IPointData, sx: number, sy: number, ex: number, ey: number, midpointAxis: number, startBounds: IBoundsData | undefined, endBounds: IBoundsData | undefined, clearance: number): number {
136
+ const midpointX = (sx + ex) / 2, midpointY = (sy + ey) / 2
137
+ result.length = 0
138
+ result.push(startPoint.x, startPoint.y, sx, sy)
139
+
140
+ if (midpointAxis === POLYLINE_X) {
141
+ result.push(midpointX, sy, midpointX, ey)
142
+ } else {
143
+ result.push(sx, midpointY, ex, midpointY)
144
+ }
145
+
146
+ result.push(ex, ey, endPoint.x, endPoint.y)
147
+
148
+ // 只检查两端出口之间的路径,起终点连接段允许进入自身元素
149
+ for (let i = 4; i < result.length - 2; i += 2) {
150
+ const x1 = result[i - 2], y1 = result[i - 1]
151
+ const x2 = result[i], y2 = result[i + 1]
152
+
153
+ if (isPolylineSegmentBlocked(x1, y1, x2, y2, startBounds, clearance) ||
154
+ isPolylineSegmentBlocked(x1, y1, x2, y2, endBounds, clearance)) return Infinity
155
+ }
156
+
157
+ return getPolylineScore(result, clearance)
158
+ }
159
+
160
+ function getPolylineRoute(result: number[], startPoint: IPointData, endPoint: IPointData, startPort: number, endPort: number, startBounds: IBoundsData | undefined, endBounds: IBoundsData | undefined, clearance: number): number {
161
+ const startExit: number[] = [], endExit: number[] = []
162
+ getPolylineExit(startPoint, startBounds, startPort, clearance, startExit)
163
+ getPolylineExit(endPoint, endBounds, endPort, clearance, endExit)
164
+
165
+ const sx = startExit[0], sy = startExit[1], ex = endExit[0], ey = endExit[1]
166
+ const startAxis = startPort >> 1, endAxis = endPort >> 1
167
+ const startSign = startPort & 1 ? 1 : -1, endSign = endPort & 1 ? 1 : -1
168
+ const startStub = Math.abs(sx - startPoint.x) + Math.abs(sy - startPoint.y)
169
+ const endStub = Math.abs(ex - endPoint.x) + Math.abs(ey - endPoint.y)
170
+
171
+ if (isPolylineSegmentBlocked(startPoint.x, startPoint.y, sx, sy, endBounds, clearance) ||
172
+ isPolylineSegmentBlocked(endPoint.x, endPoint.y, ex, ey, startBounds, clearance)) return Infinity
173
+
174
+ const midpointAxis = getPolylineMidpointAxis(startPort, endPort, sx, sy, ex, ey)
175
+
176
+ // 第一优先级:只要中点路径不受阻,就直接采用
177
+ const midpointScore = getPolylineMidpointRoute(result, startPoint, endPoint, sx, sy, ex, ey, midpointAxis, startBounds, endBounds, clearance)
178
+ if (midpointScore < Infinity) return midpointScore
179
+
180
+ // 第二优先级:中点路径受阻,使用网格寻路绕行
181
+ const margin = Math.max(clearance, POLYLINE_MIN_SEGMENT) * 2
182
+ const xs: number[] = [sx, ex, (sx + ex) / 2], ys: number[] = [sy, ey, (sy + ey) / 2]
183
+
184
+ addPolylineBoundsCoordinates(xs, ys, startBounds, clearance, margin)
185
+ addPolylineBoundsCoordinates(xs, ys, endBounds, clearance, margin)
186
+
187
+ let minX = Math.min(...xs), maxX = Math.max(...xs)
188
+ let minY = Math.min(...ys), maxY = Math.max(...ys)
189
+ xs.push(minX - margin * 2, maxX + margin * 2)
190
+ ys.push(minY - margin * 2, maxY + margin * 2)
191
+
192
+ sortPolylineCoordinates(xs)
193
+ sortPolylineCoordinates(ys)
194
+
195
+ const nx = xs.length, ny = ys.length
196
+ const startXIndex = getPolylineCoordinateIndex(xs, sx), startYIndex = getPolylineCoordinateIndex(ys, sy)
197
+ const endXIndex = getPolylineCoordinateIndex(xs, ex), endYIndex = getPolylineCoordinateIndex(ys, ey)
198
+
199
+ if (startXIndex < 0 || startYIndex < 0 || endXIndex < 0 || endYIndex < 0) return Infinity
200
+
201
+ const startNode = startYIndex * nx + startXIndex, endNode = endYIndex * nx + endXIndex
202
+ const total = nx * ny * 3
203
+ const distance = new Float64Array(total), previous = new Int32Array(total), visited = new Uint8Array(total)
204
+
205
+ distance.fill(Infinity)
206
+ previous.fill(-1)
207
+
208
+ const startState = startNode * 3
209
+ distance[startState] = 0
210
+
211
+ const turnCost = Math.max(POLYLINE_MIN_SEGMENT, clearance * POLYLINE_TURN_WEIGHT)
212
+ let currentState = -1, currentNode = -1, currentAxis = 0
213
+ let currentX = 0, currentY = 0, currentDistance = 0
214
+
215
+ const relax = (nextXIndex: number, nextYIndex: number, axis: number, sign: number): void => {
216
+ const nextX = xs[nextXIndex], nextY = ys[nextYIndex]
217
+ const nextNode = nextYIndex * nx + nextXIndex
218
+
219
+ if (isPolylinePointBlocked(nextX, nextY, startBounds, clearance) ||
220
+ isPolylinePointBlocked(nextX, nextY, endBounds, clearance)) return
221
+
222
+ if (isPolylineSegmentBlocked(currentX, currentY, nextX, nextY, startBounds, clearance) ||
223
+ isPolylineSegmentBlocked(currentX, currentY, nextX, nextY, endBounds, clearance)) return
224
+
225
+ if (currentState === startState) {
226
+ if (axis === startAxis + 1) {
227
+ if (sign !== startSign) return
228
+ } else if (startStub <= POLYLINE_EPSILON) return
229
+ }
230
+
231
+ if (nextNode === endNode) {
232
+ if (axis === endAxis + 1) {
233
+ if (sign !== -endSign) return
234
+ } else if (endStub <= POLYLINE_EPSILON) return
235
+ }
236
+
237
+ const nextState = nextNode * 3 + axis
238
+ if (visited[nextState]) return
239
+
240
+ const segmentLength = Math.abs(nextX - currentX) + Math.abs(nextY - currentY)
241
+ let cost = currentDistance + segmentLength
242
+
243
+ if (currentAxis && currentAxis !== axis) {
244
+ cost += turnCost
245
+ const turnCoordinate = currentAxis === POLYLINE_X + 1 ? currentX : currentY
246
+ const preferredCoordinate = midpointAxis === POLYLINE_X ? (sx + ex) / 2 : (sy + ey) / 2
247
+ if (Math.abs(turnCoordinate - preferredCoordinate) > POLYLINE_EPSILON) cost += turnCost * 2
248
+ }
249
+
250
+ if (cost < distance[nextState]) {
251
+ distance[nextState] = cost
252
+ previous[nextState] = currentState
253
+ }
254
+ }
255
+
256
+ let bestState = -1
257
+
258
+ for (let iteration = 0; iteration < total; iteration++) {
259
+ let minDistance = Infinity, state = -1
260
+
261
+ for (let i = 0; i < total; i++) {
262
+ if (!visited[i] && distance[i] < minDistance) {
263
+ minDistance = distance[i]
264
+ state = i
265
+ }
266
+ }
267
+
268
+ if (state < 0) break
269
+
270
+ currentState = state
271
+ currentNode = Math.floor(state / 3)
272
+ currentAxis = state % 3
273
+ currentDistance = minDistance
274
+ visited[state] = 1
275
+
276
+ if (currentNode === endNode) {
277
+ bestState = state
278
+ break
279
+ }
280
+
281
+ const xIndex = currentNode % nx, yIndex = Math.floor(currentNode / nx)
282
+ currentX = xs[xIndex]
283
+ currentY = ys[yIndex]
284
+
285
+ if (xIndex > 0) relax(xIndex - 1, yIndex, POLYLINE_X + 1, -1)
286
+ if (xIndex < nx - 1) relax(xIndex + 1, yIndex, POLYLINE_X + 1, 1)
287
+ if (yIndex > 0) relax(xIndex, yIndex - 1, POLYLINE_Y + 1, -1)
288
+ if (yIndex < ny - 1) relax(xIndex, yIndex + 1, POLYLINE_Y + 1, 1)
289
+ }
290
+
291
+ if (bestState < 0) return Infinity
292
+
293
+ const reverse: number[] = []
294
+ let state = bestState
295
+
296
+ while (state >= 0) {
297
+ const node = Math.floor(state / 3)
298
+ reverse.push(xs[node % nx], ys[Math.floor(node / nx)])
299
+ if (state === startState) break
300
+ state = previous[state]
301
+ }
302
+
303
+ if (state !== startState) return Infinity
304
+
305
+ result.length = 0
306
+ result.push(startPoint.x, startPoint.y, sx, sy)
307
+
308
+ for (let i = reverse.length - 4; i >= 0; i -= 2) result.push(reverse[i], reverse[i + 1])
309
+
310
+ result.push(endPoint.x, endPoint.y)
311
+ return distance[bestState] + startStub + endStub
312
+ }
313
+
314
+ function appendPolylinePoint(points: number[], x: number, y: number): void {
315
+ const length = points.length
316
+ if (length >= 2 && Math.abs(points[length - 2] - x) <= POLYLINE_EPSILON && Math.abs(points[length - 1] - y) <= POLYLINE_EPSILON) return
317
+ points.push(x, y)
318
+ }
319
+
320
+ function appendPolylineOrthogonal(points: number[], x1: number, y1: number, x2: number, y2: number, firstAxis = POLYLINE_X): void {
321
+ if (Math.abs(x1 - x2) > POLYLINE_EPSILON && Math.abs(y1 - y2) > POLYLINE_EPSILON) {
322
+ if (firstAxis === POLYLINE_X) {
323
+ const midX = (x1 + x2) / 2
324
+ appendPolylinePoint(points, midX, y1)
325
+ appendPolylinePoint(points, midX, y2)
326
+ } else {
327
+ const midY = (y1 + y2) / 2
328
+ appendPolylinePoint(points, x1, midY)
329
+ appendPolylinePoint(points, x2, midY)
330
+ }
331
+ }
332
+ appendPolylinePoint(points, x2, y2)
333
+ }
334
+
335
+ function getPolylineEditPath(result: number[], startPoint: IPointData, endPoint: IPointData, startPort: number, endPort: number, startBounds: IBoundsData | undefined, endBounds: IBoundsData | undefined, points: number[], clearance: number): number {
336
+ if (points.length % 2) return Infinity
337
+ for (let i = 0; i < points.length; i++) if (!Number.isFinite(points[i])) return Infinity
338
+
339
+ const startExit: number[] = [], endExit: number[] = []
340
+ getPolylineExit(startPoint, startBounds, startPort, clearance, startExit)
341
+ getPolylineExit(endPoint, endBounds, endPort, clearance, endExit)
342
+
343
+ const sx = startExit[0], sy = startExit[1], ex = endExit[0], ey = endExit[1]
344
+
345
+ if (isPolylineSegmentBlocked(startPoint.x, startPoint.y, sx, sy, endBounds, clearance) ||
346
+ isPolylineSegmentBlocked(endPoint.x, endPoint.y, ex, ey, startBounds, clearance)) return Infinity
347
+
348
+ result.length = 0
349
+ appendPolylinePoint(result, startPoint.x, startPoint.y)
350
+ appendPolylinePoint(result, sx, sy)
351
+
352
+ let x = sx, y = sy
353
+
354
+ for (let i = 0; i < points.length; i += 2) {
355
+ const nx = points[i], ny = points[i + 1]
356
+ appendPolylineOrthogonal(result, x, y, nx, ny, i === 0 && clearance === 0 ? startPort >> 1 : POLYLINE_X)
357
+ x = nx
358
+ y = ny
359
+ }
360
+
361
+ const endAxis = endPort >> 1
362
+
363
+ if (Math.abs(x - ex) > POLYLINE_EPSILON && Math.abs(y - ey) > POLYLINE_EPSILON) {
364
+ if (endAxis === POLYLINE_X) appendPolylinePoint(result, x, ey)
365
+ else appendPolylinePoint(result, ex, y)
366
+ }
367
+
368
+ appendPolylinePoint(result, ex, ey)
369
+ appendPolylinePoint(result, endPoint.x, endPoint.y)
370
+ return getPolylineScore(result, clearance)
371
+ }
372
+
373
+ function getPolylineScore(points: number[], clearance: number): number {
374
+ let length = 0, turns = 0, previousAxis = -1
375
+
376
+ for (let i = 2; i < points.length; i += 2) {
377
+ const dx = points[i] - points[i - 2], dy = points[i + 1] - points[i - 1]
378
+ if (Math.abs(dx) <= POLYLINE_EPSILON && Math.abs(dy) <= POLYLINE_EPSILON) continue
379
+
380
+ const axis = Math.abs(dx) > POLYLINE_EPSILON ? POLYLINE_X : POLYLINE_Y
381
+ length += Math.abs(dx) + Math.abs(dy)
382
+ if (previousAxis !== -1 && previousAxis !== axis) turns++
383
+ previousAxis = axis
384
+ }
385
+
386
+ return length + turns * Math.max(clearance, POLYLINE_MIN_SEGMENT) * POLYLINE_TURN_WEIGHT
387
+ }
388
+
389
+ function simplifyPolyline(points: number[]): void {
390
+ let write = 2
391
+
392
+ for (let read = 2; read < points.length; read += 2) {
393
+ const x = points[read], y = points[read + 1]
394
+ const px = points[write - 2], py = points[write - 1]
395
+
396
+ if (Math.abs(x - px) <= POLYLINE_EPSILON && Math.abs(y - py) <= POLYLINE_EPSILON) continue
397
+
398
+ if (write >= 4) {
399
+ const ax = points[write - 4], ay = points[write - 3]
400
+ const horizontal = Math.abs(ay - py) <= POLYLINE_EPSILON && Math.abs(py - y) <= POLYLINE_EPSILON && (px - ax) * (x - px) >= 0
401
+ const vertical = Math.abs(ax - px) <= POLYLINE_EPSILON && Math.abs(px - x) <= POLYLINE_EPSILON && (py - ay) * (y - py) >= 0
402
+
403
+ if (horizontal || vertical) {
404
+ points[write - 2] = x
405
+ points[write - 1] = y
406
+ continue
407
+ }
408
+ }
409
+
410
+ points[write++] = x
411
+ points[write++] = y
412
+ }
413
+
414
+ points.length = write
415
+ }
416
+
417
+ export function drawPolyline(path: number[], startPoint: IPointData, endPoint: IPointData, startDirection: IDirection, endDirection: IDirection, startBounds?: IBoundsData, endBounds?: IBoundsData, clearance = 8, points?: number[]): boolean {
418
+ if (!Number.isFinite(startPoint.x) || !Number.isFinite(startPoint.y) || !Number.isFinite(endPoint.x) || !Number.isFinite(endPoint.y)) return false
419
+
420
+ 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
421
+ 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
422
+
423
+ clearance = Number.isFinite(clearance) ? Math.max(0, clearance) : 8
424
+
425
+ const startPorts: number[] = [], endPorts: number[] = []
426
+ const startCount = getPolylinePorts(startDirection, startPoint, endPoint, startBounds, endBounds, startPorts)
427
+ const endCount = getPolylinePorts(endDirection, endPoint, startPoint, endBounds, startBounds, endPorts)
428
+ const candidate: number[] = [], best: number[] = []
429
+
430
+ let bestScore = Infinity
431
+
432
+ for (let pass = 0; pass < 2 && bestScore === Infinity; pass++) {
433
+ const currentClearance = pass === 0 ? clearance : 0
434
+
435
+ for (let i = 0; i < startCount; i++) {
436
+ for (let j = 0; j < endCount; j++) {
437
+ const score = points !== undefined
438
+ ? getPolylineEditPath(candidate, startPoint, endPoint, startPorts[i], endPorts[j], startBounds, endBounds, points, currentClearance)
439
+ : getPolylineRoute(candidate, startPoint, endPoint, startPorts[i], endPorts[j], startBounds, endBounds, currentClearance)
440
+
441
+ if (score < bestScore) {
442
+ bestScore = score
443
+ best.length = 0
444
+ for (let k = 0; k < candidate.length; k++) best.push(candidate[k])
445
+ }
446
+ }
447
+ }
448
+ }
449
+
450
+ if (!best.length) return false
451
+ if (points === undefined) simplifyPolyline(best)
452
+
453
+ moveTo(path, best[0], best[1])
454
+ for (let i = 2; i < best.length; i += 2) lineTo(path, best[i], best[i + 1])
455
+ return true
456
+ }
package/types/index.d.ts CHANGED
@@ -1,9 +1,10 @@
1
- import { ILinker, ILinkerData, ILinkerPointData, IPointsCurve, IUI, ILinkerComputedPointData, ILinkerInputData, ILinkerPointType, IPointData, ILeaf, ILinkerPointOptions } from '@leafer-ui/interface';
1
+ import { ILinker, ILinkerData, ILineType, ILinkerPointData, IPointsCurve, IUI, ILinkerComputedPointData, ILinkerInputData, ILinkerPointType, IPointData, ILeaf, ILinkerPointOptions } from '@leafer-ui/interface';
2
2
  import { Line, LineData } from '@leafer-ui/draw';
3
3
 
4
4
  declare class Linker extends Line implements ILinker {
5
5
  get __tag(): string;
6
6
  __: ILinkerData;
7
+ lineType?: ILineType;
7
8
  startPoint?: ILinkerPointData;
8
9
  endPoint?: ILinkerPointData;
9
10
  curve?: IPointsCurve;