Skip to content

Commit

Permalink
feat: Allow inner vertex of a line snap to the center of a shape
Browse files Browse the repository at this point in the history
- There's no reason to not to
  • Loading branch information
miyanokomiya committed Apr 24, 2024
1 parent 076c44e commit dd8c549
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 21 deletions.
44 changes: 33 additions & 11 deletions src/composables/lineSnapping.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,19 @@ import { TextShape } from "../shapes/text";

describe("newLineSnapping", () => {
describe("testConnection", () => {
test("should return connection result", () => {
const snappableShapes = [
createShape<RectangleShape>(getCommonStruct, "rectangle", { id: "a", width: 100, height: 100 }),
createShape<RectangleShape>(getCommonStruct, "rectangle", {
id: "b",
p: { x: 150, y: 0 },
width: 100,
height: 100,
}),
];
const movingLine = createShape<LineShape>(getCommonStruct, "line", { id: "a", q: { x: 100, y: 100 } });
const snappableShapes = [
createShape<RectangleShape>(getCommonStruct, "rectangle", { id: "a", width: 100, height: 100 }),
createShape<RectangleShape>(getCommonStruct, "rectangle", {
id: "b",
p: { x: 150, y: 0 },
width: 100,
height: 100,
}),
createShape<RectangleShape>(getCommonStruct, "rectangle", { id: "a", width: 100, height: 100 }),
];

test("should return connection result: End vertex", () => {
const movingLine = createShape<LineShape>(getCommonStruct, "line", { id: "line", q: { x: 100, y: 100 } });
const target = newLineSnapping({ snappableShapes, getShapeStruct: getCommonStruct, movingLine, movingIndex: 1 });
expect(target.testConnection({ x: -20, y: 10 }, 1)).toEqual(undefined);

Expand Down Expand Up @@ -68,6 +70,12 @@ describe("newLineSnapping", () => {
p: { x: 160, y: 100 },
});

// Snapped to the center of a shape
expect(target.testConnection({ x: 49, y: 51 }, 1)).toEqual({
connection: { id: "a", rate: { x: 0.5, y: 0.5 } },
p: { x: 50, y: 50 },
});

// Self snapped & Outline snapped
expect(target.testConnection({ x: 160, y: -5 }, 1)).toEqual({
connection: { id: "b", rate: { x: 0, y: 0 } },
Expand All @@ -81,6 +89,20 @@ describe("newLineSnapping", () => {
});
});

test("should return connection result: Inner vertex", () => {
const movingLine = createShape<LineShape>(getCommonStruct, "line", {
id: "line",
body: [{ p: { x: 100, y: 0 } }],
q: { x: 200, y: 100 },
});
const target = newLineSnapping({ snappableShapes, getShapeStruct: getCommonStruct, movingLine, movingIndex: 1 });
// Snapped to the center of a shape
expect(target.testConnection({ x: 49, y: 51 }, 1)).toEqual({
connection: { id: "a", rate: { x: 0.5, y: 0.5 } },
p: { x: 50, y: 50 },
});
});

test("should regard grid lines when self snapping happens", () => {
const movingLine = createShape<LineShape>(getCommonStruct, "line", { id: "a", q: { x: 100, y: 50 } });
const target = newLineSnapping({
Expand Down
17 changes: 7 additions & 10 deletions src/composables/lineSnapping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ export type ConnectionResult = { connection?: ConnectionPoint; p: IVec2; guidLin
export function newLineSnapping(option: Option) {
const reversedSnappableShapes = option.snappableShapes.concat().reverse();
const vertices = option.movingLine ? getLinePath(option.movingLine) : [];
const isEndVertex = option.movingIndex === 0 || option.movingIndex === vertices.length - 1;
const adjacentVertices =
vertices.length === 0 || option.movingIndex === undefined
? []
Expand Down Expand Up @@ -126,15 +125,13 @@ export function newLineSnapping(option: Option) {
// If there's no intersection, seek the closest outline point.
const p = intersection ?? getClosestOutline(option.getShapeStruct, shape, point, threshold);
if (!p) {
if (isEndVertex) {
const rect = shapeComposite.getWrapperRect(shape);
const c = getRectCenter(rect);
const d = getDistance(c, point);
if (d < threshold) {
outline = { p: c, d, shape };
selfSnapped = undefined;
return true;
}
const rect = shapeComposite.getWrapperRect(shape);
const c = getRectCenter(rect);
const d = getDistance(c, point);
if (d < threshold) {
outline = { p: c, d, shape };
selfSnapped = undefined;
return true;
}
return;
}
Expand Down

0 comments on commit dd8c549

Please sign in to comment.