Skip to content

Commit

Permalink
fix: Hide angle-adjust controls for shape having coordinate angles
Browse files Browse the repository at this point in the history
  • Loading branch information
miyanokomiya committed Jan 23, 2025
1 parent 6dead76 commit 6829fe9
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 11 deletions.
26 changes: 22 additions & 4 deletions src/composables/shapeHandlers/multipleSelectedHandler.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { describe, test, expect } from "vitest";
import { newMultipleSelectedHandler } from "./multipleSelectedHandler";
import { getIsCoordinateAngleFn, newMultipleSelectedHandler } from "./multipleSelectedHandler";
import { newShapeComposite } from "../shapeComposite";
import { createShape, getCommonStruct } from "../../shapes";
import { RectangleShape } from "../../shapes/rectangle";
Expand All @@ -19,14 +19,14 @@ describe("hitTest", () => {
p: { x: 0, y: 10 },
width: 10,
height: 10,
rotation: Math.PI / 2,
rotation: Math.PI / 3,
});
const c = createShape<RectangleShape>(getCommonStruct, "rectangle", {
id: "c",
p: { x: 0, y: 20 },
width: 10,
height: 10,
rotation: Math.PI / 2,
rotation: Math.PI / 3,
});
const d = createShape<RectangleShape>(getCommonStruct, "rectangle", {
id: "d",
Expand Down Expand Up @@ -63,7 +63,7 @@ describe("hitTest", () => {
const target1 = newMultipleSelectedHandler({
getShapeComposite: () => shapeComposite,
targetIds: shapes.map((s) => s.id),
rotation: Math.PI / 2,
rotation: Math.PI / 3,
});
expect(target1.hitTest({ x: 5, y: 4 }, 1)).toEqual({
type: "rotation",
Expand Down Expand Up @@ -105,3 +105,21 @@ describe("hitTest", () => {
expect(target0.hitTest({ x: 5, y: 5 }, 1)?.info[0]).toBe("a");
});
});

describe("getIsCoordinateAngleFn", () => {
test("should return true when the angle is coordinate", () => {
const fn1 = getIsCoordinateAngleFn(0);
expect(fn1(Math.PI / 3)).toBe(false);
expect(fn1(Math.PI / 2)).toBe(true);
expect(fn1(Math.PI)).toBe(true);
expect(fn1(Math.PI * 1.5)).toBe(true);
expect(fn1(Math.PI * 2)).toBe(true);

const fn2 = getIsCoordinateAngleFn(Math.PI / 3);
expect(fn2((Math.PI / 3) * 0.5)).toBe(false);
expect(fn2((Math.PI / 3) * 1.5)).toBe(false);
expect(fn2(Math.PI / 3 + Math.PI / 2)).toBe(true);
expect(fn2(Math.PI / 3 + Math.PI)).toBe(true);
expect(fn2(Math.PI / 3 + (Math.PI * 3) / 2)).toBe(true);
});
});
28 changes: 21 additions & 7 deletions src/composables/shapeHandlers/multipleSelectedHandler.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { IVec2, MINVALUE, getDistance, getRectCenter } from "okageo";
import { IVec2, getDistance, getRectCenter } from "okageo";
import { ShapeComposite } from "../shapeComposite";
import { defineShapeHandler } from "./core";
import { applyFillStyle } from "../../utils/fillStyle";
import { TAU } from "../../utils/geometry";
import { StyleScheme } from "../../models";
import { isSameValue, TAU } from "../../utils/geometry";
import { Shape, StyleScheme } from "../../models";
import { isLineShape } from "../../shapes/line";
import { CanvasCTX } from "../../utils/types";

Expand All @@ -24,10 +24,11 @@ interface Option {

export const newMultipleSelectedHandler = defineShapeHandler<HitResult, Option>((option) => {
const shapeComposite = option.getShapeComposite();
const rotationAnchorInfoList: RotationAnchorInfo[] = option.targetIds
.map((id) => shapeComposite.shapeMap[id])
.filter((s) => !isLineShape(s) && Math.abs(s.rotation - option.rotation) > MINVALUE)
.map((s) => [s.id, s.rotation, getRectCenter(shapeComposite.getWrapperRect(s))]);

const rotationAnchorInfoList: RotationAnchorInfo[] = getIncoordinateAngledShapes(
option.targetIds.map((id) => shapeComposite.shapeMap[id]),
option.rotation,
).map((s) => [s.id, s.rotation, getRectCenter(shapeComposite.getWrapperRect(s))]);

function hitTest(p: IVec2, scale: number): HitResult | undefined {
const threshold = ANCHOR_SIZE * scale;
Expand Down Expand Up @@ -62,3 +63,16 @@ export const newMultipleSelectedHandler = defineShapeHandler<HitResult, Option>(
};
});
export type MultipleSelectedHandler = ReturnType<typeof newMultipleSelectedHandler>;

function getIncoordinateAngledShapes(shapes: Shape[], origin: number) {
const checkFn = getIsCoordinateAngleFn(origin);
return shapes.filter((s) => !isLineShape(s) && !checkFn(s.rotation));
}

export function getIsCoordinateAngleFn(origin: number): (r: number) => boolean {
return (r) => {
const cos = Math.cos(r - origin);
const sin = Math.sin(r - origin);
return isSameValue(Math.abs(cos * sin), 0);
};
}

0 comments on commit 6829fe9

Please sign in to comment.