feat: Implement interactive wire rendering with segment-based dragging and selection using new `WireRenderer` component and `wireSegments` utilities.
parent
2277389ea5
commit
fef33cc9be
|
|
@ -296,6 +296,15 @@ export const WireRenderer: React.FC<WireRendererProps> = ({ wire, isSelected })
|
||||||
onClick={handleWireClick}
|
onClick={handleWireClick}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{/* Background erasing path for visual crossing effect */}
|
||||||
|
<path
|
||||||
|
d={path}
|
||||||
|
stroke="#1a1a1a"
|
||||||
|
strokeWidth={isSelected ? '7' : '6'}
|
||||||
|
fill="none"
|
||||||
|
style={{ pointerEvents: 'none' }}
|
||||||
|
/>
|
||||||
|
|
||||||
{/* Visible wire path */}
|
{/* Visible wire path */}
|
||||||
<path
|
<path
|
||||||
d={path}
|
d={path}
|
||||||
|
|
|
||||||
|
|
@ -158,20 +158,46 @@ export function updateOrthogonalPointsForSegmentDrag(
|
||||||
offset: number
|
offset: number
|
||||||
): Array<{ x: number; y: number }> {
|
): Array<{ x: number; y: number }> {
|
||||||
const newPoints = orthoPoints.map((p) => ({ ...p }));
|
const newPoints = orthoPoints.map((p) => ({ ...p }));
|
||||||
|
|
||||||
const { startIndex, endIndex, orientation } = segment;
|
const { startIndex, endIndex, orientation } = segment;
|
||||||
|
|
||||||
|
let newStart = { ...newPoints[startIndex] };
|
||||||
|
let newEnd = { ...newPoints[endIndex] };
|
||||||
|
|
||||||
if (orientation === 'horizontal') {
|
if (orientation === 'horizontal') {
|
||||||
// Move horizontal segment up/down (change Y)
|
newStart.y += offset;
|
||||||
newPoints[startIndex].y += offset;
|
newEnd.y += offset;
|
||||||
newPoints[endIndex].y += offset;
|
|
||||||
} else {
|
} else {
|
||||||
// Move vertical segment left/right (change X)
|
newStart.x += offset;
|
||||||
newPoints[startIndex].x += offset;
|
newEnd.x += offset;
|
||||||
newPoints[endIndex].x += offset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return newPoints;
|
const resultPoints: Array<{ x: number; y: number }> = [];
|
||||||
|
|
||||||
|
// Add points before the dragged segment
|
||||||
|
for (let i = 0; i < startIndex; i++) {
|
||||||
|
resultPoints.push(newPoints[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If dragging the first segment, inject the original start pin to act as a stub anchor
|
||||||
|
if (startIndex === 0 && offset !== 0) {
|
||||||
|
resultPoints.push({ ...newPoints[0] });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the dragged segment's end points
|
||||||
|
resultPoints.push(newStart);
|
||||||
|
resultPoints.push(newEnd);
|
||||||
|
|
||||||
|
// If dragging the last segment, inject the original end pin to act as a stub anchor
|
||||||
|
if (endIndex === newPoints.length - 1 && offset !== 0) {
|
||||||
|
resultPoints.push({ ...newPoints[newPoints.length - 1] });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add points after the dragged segment
|
||||||
|
for (let i = endIndex + 1; i < newPoints.length; i++) {
|
||||||
|
resultPoints.push(newPoints[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return resultPoints;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -183,8 +209,8 @@ export function updateOrthogonalPointsForSegmentDrag(
|
||||||
*/
|
*/
|
||||||
export function orthogonalPointsToControlPoints(
|
export function orthogonalPointsToControlPoints(
|
||||||
orthoPoints: Array<{ x: number; y: number }>,
|
orthoPoints: Array<{ x: number; y: number }>,
|
||||||
start: { x: number; y: number },
|
_start: { x: number; y: number },
|
||||||
end: { x: number; y: number }
|
_end: { x: number; y: number }
|
||||||
): WireControlPoint[] {
|
): WireControlPoint[] {
|
||||||
if (orthoPoints.length < 2) {
|
if (orthoPoints.length < 2) {
|
||||||
return [];
|
return [];
|
||||||
|
|
@ -197,10 +223,6 @@ export function orthogonalPointsToControlPoints(
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use actual orthoPoints for prev/next comparison (not start/end parameters)
|
|
||||||
const actualStart = orthoPoints[0];
|
|
||||||
const actualEnd = orthoPoints[orthoPoints.length - 1];
|
|
||||||
|
|
||||||
// Keep only corner points (where direction changes)
|
// Keep only corner points (where direction changes)
|
||||||
const controlPoints: WireControlPoint[] = [];
|
const controlPoints: WireControlPoint[] = [];
|
||||||
|
|
||||||
|
|
@ -211,9 +233,14 @@ export function orthogonalPointsToControlPoints(
|
||||||
const next = orthoPoints[i + 2]; // Next point in orthoPoints
|
const next = orthoPoints[i + 2]; // Next point in orthoPoints
|
||||||
|
|
||||||
// Check if current point is a corner (changes direction)
|
// Check if current point is a corner (changes direction)
|
||||||
const isCorner =
|
// We use a cross product check to tolerate slight non-90-degree angles during drag
|
||||||
(prev.x === current.x && current.y === next.y) ||
|
const dx1 = current.x - prev.x;
|
||||||
(prev.y === current.y && current.x === next.x);
|
const dy1 = current.y - prev.y;
|
||||||
|
const dx2 = next.x - current.x;
|
||||||
|
const dy2 = next.y - current.y;
|
||||||
|
|
||||||
|
// Cross product magnitude. If > 0.1, the path bends here.
|
||||||
|
const isCorner = Math.abs(dx1 * dy2 - dy1 * dx2) > 0.1;
|
||||||
|
|
||||||
if (isCorner) {
|
if (isCorner) {
|
||||||
controlPoints.push({
|
controlPoints.push({
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue