Add cubic bezier curve visual debug

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>
pull/8539/merge^2
Mark Tolmacs 2 months ago
parent 77ea537c69
commit 028c397c0a
No known key found for this signature in database

@ -12,9 +12,10 @@ import {
TrashIcon,
} from "../../packages/excalidraw/components/icons";
import { STORAGE_KEYS } from "../app_constants";
import type { Arc } from "../../packages/math";
import type { Arc, CubicBezier } from "../../packages/math";
import {
isArc,
isBezier,
isSegment,
type GlobalPoint,
type Segment,
@ -35,6 +36,28 @@ const renderLine = (
context.restore();
};
const renderCubicBezier = (
context: CanvasRenderingContext2D,
zoom: number,
{ start, control1, control2, end }: CubicBezier<GlobalPoint>,
color: string,
) => {
context.save();
context.strokeStyle = color;
context.beginPath();
context.moveTo(start[0] * zoom, start[1] * zoom);
context.bezierCurveTo(
control1[0] * zoom,
control1[1] * zoom,
control2[0] * zoom,
control2[1] * zoom,
end[0] * zoom,
end[1] * zoom,
);
context.stroke();
context.restore();
};
const renderArc = (
context: CanvasRenderingContext2D,
zoom: number,
@ -90,6 +113,16 @@ const render = (
el.color,
);
break;
case isBezier(el.data):
renderCubicBezier(
context,
appState.zoom.value,
el.data as CubicBezier<GlobalPoint>,
el.color,
);
break;
default:
throw new Error("Unknown element type");
}
});
};

@ -1,4 +1,4 @@
import type { Arc, Segment } from "../math";
import type { Arc, CubicBezier, Segment } from "../math";
import { isSegment, segment, pointFrom, type GlobalPoint } from "../math";
import { isBounds } from "./element/typeChecks";
import type { Bounds } from "./element/types";
@ -15,10 +15,24 @@ declare global {
export type DebugElement = {
color: string;
data: Segment<GlobalPoint> | Arc<GlobalPoint>;
data: Segment<GlobalPoint> | Arc<GlobalPoint> | CubicBezier<GlobalPoint>;
permanent: boolean;
};
export const debugDrawCubicBezier = (
c: CubicBezier<GlobalPoint>,
opts?: {
color?: string;
permanent?: boolean;
},
) => {
addToCurrentFrame({
color: opts?.color ?? "purple",
permanent: !!opts?.permanent,
data: c,
});
};
export const debugDrawArc = (
a: Arc<GlobalPoint>,
opts?: {

@ -1,5 +1,5 @@
import { pointFrom, pointRotateRads } from "./point";
import type { Curve, GenericPoint, Radians } from "./types";
import { isPoint, pointFrom, pointRotateRads } from "./point";
import type { CubicBezier, Curve, GenericPoint, Radians } from "./types";
/**
*
@ -221,3 +221,20 @@ const findClosestParameter = <Point extends GenericPoint>(
return closestT;
};
export const isBezier = <Point extends GenericPoint>(
c: unknown,
): c is CubicBezier<Point> => {
return (
c != null &&
typeof c === "object" &&
Object.hasOwn(c, "start") &&
Object.hasOwn(c, "end") &&
Object.hasOwn(c, "control1") &&
Object.hasOwn(c, "control2") &&
isPoint((c as CubicBezier<Point>).start) &&
isPoint((c as CubicBezier<Point>).end) &&
isPoint((c as CubicBezier<Point>).control1) &&
isPoint((c as CubicBezier<Point>).control2)
);
};

@ -132,9 +132,11 @@ export type Extent = {
_brand: "excalimath_extent";
};
// an ellipse is specified by its center, angle, and its major and minor axes
// but for the sake of simplicity, we've used halfWidth and halfHeight instead
// in replace of semi major and semi minor axes
/**
An ellipse is specified by its center, angle, and its major and minor axes
but for the sake of simplicity, we've used halfWidth and halfHeight instead
in replace of semi major and semi minor axes
*/
export type Ellipse<Point extends GenericPoint> = {
center: Point;
halfWidth: number;
@ -142,3 +144,14 @@ export type Ellipse<Point extends GenericPoint> = {
} & {
_brand: "excalimath_ellipse";
};
/**
* Represents a cubic bezier with 2 control points on the point space of your
* choosing.
*/
export type CubicBezier<P extends GenericPoint> = {
start: P;
end: P;
control1: P;
control2: P;
};

Loading…
Cancel
Save