summaryrefslogtreecommitdiff
path: root/apps/web/src/lib/graphics/definitions/polygon.ts
diff options
context:
space:
mode:
authorMaze Winther <mazewinther@gmail.com>2026-04-20 11:31:17 +0200
committerMaze Winther <mazewinther@gmail.com>2026-04-20 11:31:17 +0200
commit3e89d2998588f8e35c524e523ba2ee853f0f6475 (patch)
tree57221f96c1259b3b07e3ddf8c1adefc502b9d8eb /apps/web/src/lib/graphics/definitions/polygon.ts
parent729d10592f4e802f91c555c309ff3ba4b119f843 (diff)
downloadopencut-3e89d2998588f8e35c524e523ba2ee853f0f6475.tar.gz
refactor: restructure files to their domains, new preview overlay system, and dep graph
Diffstat (limited to 'apps/web/src/lib/graphics/definitions/polygon.ts')
-rw-r--r--apps/web/src/lib/graphics/definitions/polygon.ts211
1 files changed, 0 insertions, 211 deletions
diff --git a/apps/web/src/lib/graphics/definitions/polygon.ts b/apps/web/src/lib/graphics/definitions/polygon.ts
deleted file mode 100644
index deecb6ff..00000000
--- a/apps/web/src/lib/graphics/definitions/polygon.ts
+++ /dev/null
@@ -1,211 +0,0 @@
-import type { ParamDefinition } from "@/lib/params";
-import { applyAlignedStroke } from "../stroke";
-import { STROKE_ALIGN_PARAM, type GraphicStrokeAlign } from "./shared";
-import type { GraphicDefinition } from "../types";
-
-interface Point {
- x: number;
- y: number;
-}
-
-interface PolygonParams {
- fill: string;
- stroke: string;
- strokeWidth: number;
- strokeAlign: GraphicStrokeAlign;
- sides: number;
- cornerRadius: number;
-}
-
-const POLYGON_PARAMS: ParamDefinition<keyof PolygonParams & string>[] = [
- {
- key: "fill",
- label: "Fill",
- type: "color",
- default: "#ffffff",
- },
- {
- key: "stroke",
- label: "Color",
- type: "color",
- default: "#000000",
- group: "stroke",
- },
- {
- key: "strokeWidth",
- label: "Width",
- type: "number",
- default: 0,
- min: 0,
- max: 64,
- step: 1,
- shortLabel: "W",
- group: "stroke",
- },
- STROKE_ALIGN_PARAM,
- {
- key: "sides",
- label: "Sides",
- type: "number",
- default: 5,
- min: 3,
- max: 12,
- step: 1,
- shortLabel: "S",
- },
- {
- key: "cornerRadius",
- label: "Corner radius",
- type: "number",
- default: 0,
- min: 0,
- max: 50,
- step: 1,
- shortLabel: "R",
- },
-];
-
-function buildPolygonVertices({
- centerX,
- centerY,
- radius,
- sides,
-}: {
- centerX: number;
- centerY: number;
- radius: number;
- sides: number;
-}): Point[] {
- return Array.from({ length: sides }, (_, index) => {
- const angle = -Math.PI / 2 + (index * Math.PI * 2) / sides;
- return {
- x: centerX + Math.cos(angle) * radius,
- y: centerY + Math.sin(angle) * radius,
- };
- });
-}
-
-function distance({ a, b }: { a: Point; b: Point }): number {
- return Math.hypot(a.x - b.x, a.y - b.y);
-}
-
-function normalize(point: Point): Point {
- const length = Math.hypot(point.x, point.y) || 1;
- return {
- x: point.x / length,
- y: point.y / length,
- };
-}
-
-function traceRoundedPolygonPath({
- path,
- vertices,
- radius,
-}: {
- path: Path2D;
- vertices: Point[];
- radius: number;
-}): void {
- if (vertices.length < 3) {
- return;
- }
-
- if (radius <= 0) {
- path.moveTo(vertices[0].x, vertices[0].y);
- for (let index = 1; index < vertices.length; index++) {
- path.lineTo(vertices[index].x, vertices[index].y);
- }
- path.closePath();
- return;
- }
-
- for (let index = 0; index < vertices.length; index++) {
- const previous = vertices[(index - 1 + vertices.length) % vertices.length];
- const current = vertices[index];
- const next = vertices[(index + 1) % vertices.length];
- const toPrevious = normalize({
- x: previous.x - current.x,
- y: previous.y - current.y,
- });
- const toNext = normalize({
- x: next.x - current.x,
- y: next.y - current.y,
- });
- const angle = Math.acos(
- Math.max(-1, Math.min(1, toPrevious.x * toNext.x + toPrevious.y * toNext.y)),
- );
- const maxOffset =
- Math.min(distance({ a: previous, b: current }), distance({ a: current, b: next })) / 2;
- const tangentOffset = Math.min(radius / Math.tan(angle / 2), maxOffset);
- const start = {
- x: current.x + toPrevious.x * tangentOffset,
- y: current.y + toPrevious.y * tangentOffset,
- };
- const end = {
- x: current.x + toNext.x * tangentOffset,
- y: current.y + toNext.y * tangentOffset,
- };
-
- if (index === 0) {
- path.moveTo(start.x, start.y);
- } else {
- path.lineTo(start.x, start.y);
- }
-
- path.arcTo(
- current.x,
- current.y,
- end.x,
- end.y,
- Math.min(radius, maxOffset),
- );
- }
-
- path.closePath();
-}
-
-export const polygonGraphicDefinition: GraphicDefinition = {
- id: "polygon",
- name: "Polygon",
- keywords: ["polygon", "triangle", "pentagon", "hexagon", "diamond"],
- params: POLYGON_PARAMS,
- render({ ctx, params, width, height }) {
- const fill = String(params.fill ?? "#ffffff");
- const stroke = String(params.stroke ?? "#000000");
- const strokeWidth = Math.max(0, Number(params.strokeWidth ?? 0));
- const strokeAlign = (params.strokeAlign ?? "center") as GraphicStrokeAlign;
- const sides = Math.max(3, Math.min(12, Math.round(Number(params.sides ?? 5))));
- const inset = strokeAlign === "center" ? strokeWidth / 2 : 0;
- const radius = Math.max(1, Math.min(width, height) / 2 - inset);
- const maxCornerRadius = radius * Math.sin(Math.PI / sides);
- const cornerRadiusPercent = Math.max(0, Number(params.cornerRadius ?? 0));
- const cornerRadius =
- maxCornerRadius * Math.min(cornerRadiusPercent, 50) / 50;
- const vertices = buildPolygonVertices({
- centerX: width / 2,
- centerY: height / 2,
- radius,
- sides,
- });
-
- ctx.clearRect(0, 0, width, height);
- const path = new Path2D();
- traceRoundedPolygonPath({
- path,
- vertices,
- radius: cornerRadius,
- });
- ctx.fillStyle = fill;
- ctx.fill(path);
-
- if (strokeWidth > 0) {
- applyAlignedStroke({
- ctx,
- path,
- strokeWidth,
- strokeAlign,
- strokeColor: stroke,
- });
- }
- },
-};