adding in path geometry for the add point +
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { describe, it, expect } from 'vitest'
|
||||
import { buildWaypointPath, distToSegment, findInsertIndex, getWaypointLabelPosition, snap45, snap45both } from '../waypointUtils'
|
||||
import { buildWaypointPath, distToSegment, findInsertIndex, getAddWaypointHandlePosition, getWaypointLabelPosition, snap45, snap45both } from '../waypointUtils'
|
||||
|
||||
describe('buildWaypointPath — bezier (default)', () => {
|
||||
it('builds a catmull-rom curve with no waypoints (start = end clamp)', () => {
|
||||
@@ -192,3 +192,16 @@ describe('getWaypointLabelPosition', () => {
|
||||
expect(point).toEqual({ x: 10, y: 20 })
|
||||
})
|
||||
})
|
||||
|
||||
describe('getAddWaypointHandlePosition', () => {
|
||||
it('places bezier add handle on the rendered curved segment', () => {
|
||||
const point = getAddWaypointHandlePosition(0, 0, [{ x: 50, y: 100 }], 100, 0, 0, 'bezier')
|
||||
expect(point.x).toBeCloseTo(21.875, 3)
|
||||
expect(point.y).toBeCloseTo(56.25, 3)
|
||||
})
|
||||
|
||||
it('keeps smooth add handle at straight segment midpoint', () => {
|
||||
const point = getAddWaypointHandlePosition(0, 0, [{ x: 50, y: 0 }, { x: 50, y: 100 }], 100, 100, 1, 'smooth')
|
||||
expect(point).toEqual({ x: 50, y: 50 })
|
||||
})
|
||||
})
|
||||
|
||||
@@ -13,7 +13,7 @@ import type { EdgeData, EdgeType, Waypoint } from '@/types'
|
||||
import { useThemeStore } from '@/stores/themeStore'
|
||||
import { useCanvasStore } from '@/stores/canvasStore'
|
||||
import { THEMES } from '@/utils/themes'
|
||||
import { buildWaypointPath, getWaypointLabelPosition, snap45, snap45both } from './waypointUtils'
|
||||
import { buildWaypointPath, getAddWaypointHandlePosition, getWaypointLabelPosition, snap45, snap45both } from './waypointUtils'
|
||||
|
||||
const VLAN_COLORS = ['#00d4ff', '#a855f7', '#39d353', '#ff6e00', '#e3b341', '#f85149']
|
||||
|
||||
@@ -161,9 +161,9 @@ function segmentMidpoints(
|
||||
const isSmooth = pathStyle === 'smooth'
|
||||
|
||||
return pts.slice(0, -1).map((a, i) => {
|
||||
const b = pts[i + 1]
|
||||
let mx = (a.x + b.x) / 2
|
||||
const my = (a.y + b.y) / 2
|
||||
const base = getAddWaypointHandlePosition(sourceX, sourceY, waypoints, targetX, targetY, i, pathStyle)
|
||||
let mx = base.x
|
||||
const my = base.y
|
||||
|
||||
// For smooth style with no existing waypoints, bias the single + handle onto
|
||||
// the source handle axis so clicking it creates a perpendicular exit.
|
||||
|
||||
@@ -238,6 +238,50 @@ export function getWaypointLabelPosition(
|
||||
return lastSegment.pointAt(1)
|
||||
}
|
||||
|
||||
function getBezierSegmentPoint(
|
||||
pts: Waypoint[],
|
||||
insertIndex: number,
|
||||
t: number,
|
||||
): Waypoint {
|
||||
const i = Math.max(0, Math.min(insertIndex, pts.length - 2))
|
||||
const p0 = pts[Math.max(i - 1, 0)]
|
||||
const p1 = pts[i]
|
||||
const p2 = pts[i + 1]
|
||||
const p3 = pts[Math.min(i + 2, pts.length - 1)]
|
||||
const cp1 = {
|
||||
x: p1.x + (p2.x - p0.x) / 6,
|
||||
y: p1.y + (p2.y - p0.y) / 6,
|
||||
}
|
||||
const cp2 = {
|
||||
x: p2.x - (p3.x - p1.x) / 6,
|
||||
y: p2.y - (p3.y - p1.y) / 6,
|
||||
}
|
||||
|
||||
return interpolateCubic(p1, cp1, cp2, p2, t)
|
||||
}
|
||||
|
||||
export function getAddWaypointHandlePosition(
|
||||
sourceX: number, sourceY: number,
|
||||
waypoints: Waypoint[],
|
||||
targetX: number, targetY: number,
|
||||
insertIndex: number,
|
||||
pathStyle: string = 'bezier',
|
||||
): Waypoint {
|
||||
const pts = [{ x: sourceX, y: sourceY }, ...waypoints, { x: targetX, y: targetY }]
|
||||
|
||||
if (pts.length < 2) return { x: sourceX, y: sourceY }
|
||||
|
||||
if (pathStyle !== 'smooth') {
|
||||
return getBezierSegmentPoint(pts, insertIndex, 0.5)
|
||||
}
|
||||
|
||||
const i = Math.max(0, Math.min(insertIndex, pts.length - 2))
|
||||
return {
|
||||
x: (pts[i].x + pts[i + 1].x) / 2,
|
||||
y: (pts[i].y + pts[i + 1].y) / 2,
|
||||
}
|
||||
}
|
||||
|
||||
// ── 45° snapping ──────────────────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user