From a220bfa759ea8f795685409ec20813bd5d0ed98a Mon Sep 17 00:00:00 2001 From: Rob Nadal Date: Fri, 18 Nov 2022 00:34:52 -0800 Subject: [PATCH] Bezier-rs: Remove unused legacy drawing components and structs (#853) * Removed unused legacy drawing components * Removed Point abstraction from frontend code * Code review fixes * Helper lambdas to functions Co-authored-by: Keavon Chambers --- website/other/bezier-rs-demos/src/App.vue | 26 +-- .../src/components/BezierDrawing.ts | 150 ----------------- .../src/components/BezierExample.vue | 2 +- .../src/components/Example.vue | 63 ------- .../src/components/ExamplePane.vue | 133 --------------- .../src/components/SliderExample.vue | 54 ------ .../bezier-rs-demos/src/utils/drawing.ts | 155 ------------------ .../bezier-rs-demos/src/utils/helpers.ts | 8 +- .../other/bezier-rs-demos/src/utils/types.ts | 31 +--- .../other/bezier-rs-demos/wasm/src/bezier.rs | 66 +++----- .../bezier-rs-demos/wasm/src/svg_drawing.rs | 19 ++- 11 files changed, 47 insertions(+), 660 deletions(-) delete mode 100644 website/other/bezier-rs-demos/src/components/BezierDrawing.ts delete mode 100644 website/other/bezier-rs-demos/src/components/Example.vue delete mode 100644 website/other/bezier-rs-demos/src/components/ExamplePane.vue delete mode 100644 website/other/bezier-rs-demos/src/components/SliderExample.vue delete mode 100644 website/other/bezier-rs-demos/src/utils/drawing.ts diff --git a/website/other/bezier-rs-demos/src/App.vue b/website/other/bezier-rs-demos/src/App.vue index d7baa7c20..7b4055f9e 100644 --- a/website/other/bezier-rs-demos/src/App.vue +++ b/website/other/bezier-rs-demos/src/App.vue @@ -6,17 +6,6 @@
- -
- -

Subpaths

@@ -28,10 +17,9 @@ import { defineComponent } from "vue"; import { WasmBezier } from "@/../wasm/pkg"; -import { BezierCurveType, ExampleOptions, Point, WasmBezierInstance, WasmSubpathInstance } from "@/utils/types"; +import { BezierCurveType, ExampleOptions, WasmBezierInstance, WasmSubpathInstance } from "@/utils/types"; import BezierExamplePane from "@/components/BezierExamplePane.vue"; -import ExamplePane from "@/components/ExamplePane.vue"; import SubpathExamplePane from "@/components/SubpathExamplePane.vue"; const tSliderOptions = { @@ -61,12 +49,11 @@ export default defineComponent({ { name: "Bezier Through Points", callback: (bezier: WasmBezierInstance, options: Record): string => { - const points: Point[] = JSON.parse(bezier.get_points()); - const formattedPoints: number[][] = points.map((p) => [p.x, p.y]); + const points = JSON.parse(bezier.get_points()); if (Object.values(options).length === 1) { - return WasmBezier.quadratic_through_points(formattedPoints, options.t); + return WasmBezier.quadratic_through_points(points, options.t); } - return WasmBezier.cubic_through_points(formattedPoints, options.t, options["midpoint separation"]); + return WasmBezier.cubic_through_points(points, options.t, options["midpoint separation"]); }, exampleOptions: { [BezierCurveType.Linear]: { @@ -233,8 +220,8 @@ export default defineComponent({ }, { name: "Project", - callback: (bezier: WasmBezierInstance, _: Record, mouseLocation: Point): string => - mouseLocation ? bezier.project(mouseLocation.x, mouseLocation.y) : bezier.to_svg(), + callback: (bezier: WasmBezierInstance, _: Record, mouseLocation?: [number, number]): string => + mouseLocation ? bezier.project(mouseLocation[0], mouseLocation[1]) : bezier.to_svg(), triggerOnMouseMove: true, }, { @@ -529,7 +516,6 @@ export default defineComponent({ }, components: { BezierExamplePane, - ExamplePane, SubpathExamplePane, }, }); diff --git a/website/other/bezier-rs-demos/src/components/BezierDrawing.ts b/website/other/bezier-rs-demos/src/components/BezierDrawing.ts deleted file mode 100644 index 700b15cf2..000000000 --- a/website/other/bezier-rs-demos/src/components/BezierDrawing.ts +++ /dev/null @@ -1,150 +0,0 @@ -import { COLORS, drawBezier, drawPoint, getContextFromCanvas, getPointSizeByIndex } from "@/utils/drawing"; -import { Callback, BezierPoint, BezierStyleConfig, Point, WasmBezierManipulatorKey, WasmBezierInstance } from "@/utils/types"; - -// Offset to increase selectable range, used to make points easier to grab -const FUDGE_FACTOR = 3; - -// Given the number of points in the curve, map the index of a point to the correct manipulator key -const MANIPULATOR_KEYS_FROM_BEZIER_TYPE: { [k: number]: WasmBezierManipulatorKey[] } = { - 2: ["set_start", "set_end"], - 3: ["set_start", "set_handle_start", "set_end"], - 4: ["set_start", "set_handle_start", "set_handle_end", "set_end"], -}; - -class BezierDrawing { - points: BezierPoint[]; - - canvas: HTMLCanvasElement; - - ctx: CanvasRenderingContext2D; - - dragIndex: number | null; - - bezier: WasmBezierInstance; - - callback: Callback; - - options: Record; - - createThroughPoints: boolean; - - constructor(bezier: WasmBezierInstance, callback: Callback, options: Record, createThroughPoints = false) { - this.bezier = bezier; - this.callback = callback; - this.options = options; - this.createThroughPoints = createThroughPoints; - const bezierPoints: Point[] = JSON.parse(bezier.get_points()); - this.points = bezierPoints.map((p, i, points) => ({ - x: p.x, - y: p.y, - r: getPointSizeByIndex(i, points.length), - selected: false, - manipulator: MANIPULATOR_KEYS_FROM_BEZIER_TYPE[points.length][i], - })); - - if (this.createThroughPoints && this.points.length === 4) { - // Use the first handler as the middle point - this.points = [this.points[0], this.points[1], this.points[3]]; - } - - const canvas = document.createElement("canvas"); - if (canvas === null) { - throw Error("Failed to create canvas"); - } - this.canvas = canvas; - - this.canvas.style.border = "solid 1px black"; - this.canvas.width = 200; - this.canvas.height = 200; - - this.ctx = getContextFromCanvas(this.canvas); - - this.dragIndex = null; // Index of the point being moved - - this.canvas.addEventListener("mousedown", (e) => this.mouseDownHandler(e)); - this.canvas.addEventListener("mousemove", (e) => this.mouseMoveHandler(e)); - this.canvas.addEventListener("mouseup", () => this.deselectPointHandler()); - this.updateBezier(); - } - - clearFigure(): void { - this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); - } - - mouseMoveHandler(evt: MouseEvent): void { - if (evt.buttons === 0) this.deselectPointHandler(); - - const mx = evt.offsetX; - const my = evt.offsetY; - - if (this.dragIndex !== null) { - const selectableRange = getPointSizeByIndex(this.dragIndex, this.points.length); - if (mx - selectableRange > 0 && my - selectableRange > 0 && mx + selectableRange < this.canvas.width && my + selectableRange < this.canvas.height) { - const selectedPoint = this.points[this.dragIndex]; - selectedPoint.x = mx; - selectedPoint.y = my; - this.bezier[selectedPoint.manipulator](selectedPoint.x, selectedPoint.y); - } - } - this.updateBezier({ x: mx, y: my }); - } - - mouseDownHandler(evt: MouseEvent): void { - const mx = evt.offsetX; - const my = evt.offsetY; - for (let i = 0; i < this.points.length; i += 1) { - const selectableRange = getPointSizeByIndex(i, this.points.length) + FUDGE_FACTOR; - if (Math.abs(mx - this.points[i].x) < selectableRange && Math.abs(my - this.points[i].y) < selectableRange) { - this.dragIndex = i; - break; - } - } - this.updateBezier(); - } - - deselectPointHandler(): void { - if (this.dragIndex !== undefined) { - this.dragIndex = null; - this.updateBezier(); - } - } - - updateBezier(mouseLocation?: Point, options: Record = {}): void { - this.clearFigure(); - if (Object.values(options).length !== 0) { - this.options = options; - } - this.clearFigure(); - - // For the create through points cases, we store a bezier where the handle is actually the point that the curve should pass through - // This is so that we can re-use the drag and drop logic, while simply drawing the desired bezier instead - const pointsToDraw = this.points; - - let styleConfig: Partial = { - handleLineStrokeColor: COLORS.INTERACTIVE.STROKE_2, - }; - let dragIndex = this.dragIndex; - if (this.createThroughPoints) { - if (this.dragIndex === 1) { - // Do not propagate dragIndex when the the non-endpoint is moved - dragIndex = null; - } else if (this.dragIndex === 2 && pointsToDraw.length === 4) { - // For the cubic case, we want to propagate the drag index when the end point is moved, but need to adjust the index - dragIndex = 3; - } - styleConfig = { handleLineStrokeColor: COLORS.NON_INTERACTIVE.STROKE_1, handleStrokeColor: COLORS.NON_INTERACTIVE.STROKE_1 }; - } - drawBezier(this.ctx, pointsToDraw, dragIndex, styleConfig); - if (this.createThroughPoints) { - // Draw the point that the curve was drawn through - drawPoint(this.ctx, this.points[1], getPointSizeByIndex(1, this.points.length), this.dragIndex === 1 ? COLORS.INTERACTIVE.SELECTED : COLORS.INTERACTIVE.STROKE_1); - } - this.callback(this.canvas, this.bezier, this.options, mouseLocation); - } - - getCanvas(): HTMLCanvasElement { - return this.canvas; - } -} - -export default BezierDrawing; diff --git a/website/other/bezier-rs-demos/src/components/BezierExample.vue b/website/other/bezier-rs-demos/src/components/BezierExample.vue index bb7e0eef7..536bc372c 100644 --- a/website/other/bezier-rs-demos/src/components/BezierExample.vue +++ b/website/other/bezier-rs-demos/src/components/BezierExample.vue @@ -86,7 +86,7 @@ export default defineComponent({ this.mutablePoints[this.activeIndex] = [mx, my]; this.bezierSVG = this.callback(this.bezier, this.sliderData); } else if (this.triggerOnMouseMove) { - this.bezierSVG = this.callback(this.bezier, this.sliderData, { x: mx, y: my }); + this.bezierSVG = this.callback(this.bezier, this.sliderData, [mx, my]); } }, getSliderValue: (sliderValue: number, sliderUnit?: string | string[]) => (Array.isArray(sliderUnit) ? sliderUnit[sliderValue] : sliderUnit), diff --git a/website/other/bezier-rs-demos/src/components/Example.vue b/website/other/bezier-rs-demos/src/components/Example.vue deleted file mode 100644 index 92e1ac69b..000000000 --- a/website/other/bezier-rs-demos/src/components/Example.vue +++ /dev/null @@ -1,63 +0,0 @@ - - - - - diff --git a/website/other/bezier-rs-demos/src/components/ExamplePane.vue b/website/other/bezier-rs-demos/src/components/ExamplePane.vue deleted file mode 100644 index 8b9195037..000000000 --- a/website/other/bezier-rs-demos/src/components/ExamplePane.vue +++ /dev/null @@ -1,133 +0,0 @@ - - - - - diff --git a/website/other/bezier-rs-demos/src/components/SliderExample.vue b/website/other/bezier-rs-demos/src/components/SliderExample.vue deleted file mode 100644 index a8d0c22e5..000000000 --- a/website/other/bezier-rs-demos/src/components/SliderExample.vue +++ /dev/null @@ -1,54 +0,0 @@ - - - - - diff --git a/website/other/bezier-rs-demos/src/utils/drawing.ts b/website/other/bezier-rs-demos/src/utils/drawing.ts deleted file mode 100644 index f433b423f..000000000 --- a/website/other/bezier-rs-demos/src/utils/drawing.ts +++ /dev/null @@ -1,155 +0,0 @@ -import { BezierStyleConfig, CircleSector, Point } from "@/utils/types"; - -const HANDLE_RADIUS_FACTOR = 2 / 3; -const DEFAULT_ENDPOINT_RADIUS = 5; - -export const COLORS = { - CANVAS: "white", - INTERACTIVE: { - STROKE_1: "black", - STROKE_2: "gray", - SELECTED: "blue", - }, - NON_INTERACTIVE: { - STROKE_1: "red", - STROKE_2: "orange", - }, -}; - -export const isIndexFirstOrLast = (index: number, arrayLength: number): boolean => index === 0 || index === arrayLength - 1; - -export const getPointSizeByIndex = (index: number, numPoints: number, radius = DEFAULT_ENDPOINT_RADIUS): number => (isIndexFirstOrLast(index, numPoints) ? radius : radius * HANDLE_RADIUS_FACTOR); - -export const getContextFromCanvas = (canvas: HTMLCanvasElement): CanvasRenderingContext2D => { - const ctx = canvas.getContext("2d"); - if (ctx === null) { - throw Error("Failed to fetch context"); - } - return ctx; -}; - -export const drawLine = (ctx: CanvasRenderingContext2D, point1: Point, point2: Point, strokeColor = COLORS.INTERACTIVE.STROKE_2, lineWidth = 1): void => { - ctx.strokeStyle = strokeColor; - ctx.lineWidth = lineWidth; - - ctx.beginPath(); - ctx.moveTo(point1.x, point1.y); - ctx.lineTo(point2.x, point2.y); - ctx.stroke(); -}; - -export const drawPoint = (ctx: CanvasRenderingContext2D, point: Point, radius: number, strokeColor = COLORS.INTERACTIVE.STROKE_1): void => { - // Outline the point - ctx.strokeStyle = strokeColor; - ctx.lineWidth = radius / 3; - ctx.beginPath(); - ctx.arc(point.x, point.y, radius, 0, 2 * Math.PI, false); - ctx.stroke(); - - // Fill the point (hiding any overlapping lines) - ctx.fillStyle = COLORS.CANVAS; - ctx.beginPath(); - ctx.arc(point.x, point.y, radius * HANDLE_RADIUS_FACTOR, 0, 2 * Math.PI, false); - ctx.fill(); -}; - -export const drawText = (ctx: CanvasRenderingContext2D, text: string, x: number, y: number, textColor = COLORS.INTERACTIVE.STROKE_1): void => { - ctx.fillStyle = textColor; - ctx.font = "16px Arial"; - ctx.fillText(text, x, y); -}; - -export const drawCurve = (ctx: CanvasRenderingContext2D, points: Point[], strokeColor = COLORS.INTERACTIVE.STROKE_1, lineWidth = 2): void => { - ctx.strokeStyle = strokeColor; - ctx.lineWidth = lineWidth; - - ctx.beginPath(); - ctx.moveTo(points[0].x, points[0].y); - if (points.length === 3) { - ctx.quadraticCurveTo(points[1].x, points[1].y, points[2].x, points[2].y); - } else { - ctx.bezierCurveTo(points[1].x, points[1].y, points[2].x, points[2].y, points[3].x, points[3].y); - } - ctx.stroke(); -}; - -export const drawCircle = (ctx: CanvasRenderingContext2D, point: Point, radius: number, strokeColor = COLORS.INTERACTIVE.STROKE_1): void => { - ctx.strokeStyle = strokeColor; - ctx.lineWidth = 1; - ctx.beginPath(); - ctx.arc(point.x, point.y, radius, 0, 2 * Math.PI, false); - ctx.stroke(); -}; - -export const drawCircleSector = (ctx: CanvasRenderingContext2D, circleSector: CircleSector, strokeColor = COLORS.INTERACTIVE.STROKE_1, fillColor = COLORS.NON_INTERACTIVE.STROKE_1): void => { - ctx.strokeStyle = strokeColor; - ctx.fillStyle = fillColor; - ctx.lineWidth = 2; - - const { center, radius, startAngle, endAngle } = circleSector; - ctx.beginPath(); - ctx.moveTo(center.x, center.y); - ctx.arc(center.x, center.y, radius, startAngle, endAngle); - ctx.lineTo(center.x, center.y); - ctx.closePath(); - ctx.fill(); -}; - -export const drawBezier = (ctx: CanvasRenderingContext2D, points: Point[], dragIndex: number | null = null, bezierStyleConfig: Partial = {}): void => { - const styleConfig: BezierStyleConfig = { - curveStrokeColor: COLORS.INTERACTIVE.STROKE_1, - handleStrokeColor: COLORS.INTERACTIVE.STROKE_1, - handleLineStrokeColor: COLORS.INTERACTIVE.STROKE_1, - radius: DEFAULT_ENDPOINT_RADIUS, - drawHandles: true, - ...bezierStyleConfig, - }; - // If the handle or handle line colors are not specified, use the same color as the rest of the curve - if (bezierStyleConfig.curveStrokeColor) { - if (!bezierStyleConfig.handleStrokeColor) { - styleConfig.handleStrokeColor = bezierStyleConfig.curveStrokeColor; - } - if (!bezierStyleConfig.handleLineStrokeColor) { - styleConfig.handleLineStrokeColor = bezierStyleConfig.curveStrokeColor; - } - } - // Points passed to drawBezier are interpreted as follows - // points[0] = start point - // points[1] = handle start - // points[2] = (optional) handle end - // points[3] = end point - const start = points[0]; - let end = null; - let handleStart = null; - let handleEnd = null; - if (points.length === 4) { - handleStart = points[1]; - handleEnd = points[2]; - end = points[3]; - } else if (points.length === 3) { - handleStart = points[1]; - handleEnd = handleStart; - end = points[2]; - } else { - handleStart = start; - handleEnd = points[1]; - end = handleEnd; - } - - if (points.length === 2) { - drawLine(ctx, start, end, styleConfig.curveStrokeColor, 2); - } else { - drawCurve(ctx, points, styleConfig.curveStrokeColor); - if (styleConfig.drawHandles) { - drawLine(ctx, start, handleStart, styleConfig.handleLineStrokeColor); - drawLine(ctx, end, handleEnd, styleConfig.handleLineStrokeColor); - } - } - - points.forEach((point, index) => { - if (styleConfig.drawHandles || isIndexFirstOrLast(index, points.length)) { - const strokeColor = isIndexFirstOrLast(index, points.length) ? styleConfig.curveStrokeColor : styleConfig.handleStrokeColor; - drawPoint(ctx, point, getPointSizeByIndex(index, points.length, styleConfig.radius), index === dragIndex ? COLORS.INTERACTIVE.SELECTED : strokeColor); - } - }); -}; diff --git a/website/other/bezier-rs-demos/src/utils/helpers.ts b/website/other/bezier-rs-demos/src/utils/helpers.ts index b3c65460a..939cba5b3 100644 --- a/website/other/bezier-rs-demos/src/utils/helpers.ts +++ b/website/other/bezier-rs-demos/src/utils/helpers.ts @@ -1,6 +1,6 @@ import { BezierCurveType, WasmBezierConstructorKey } from "@/utils/types"; -export const getCurveType = (numPoints: number): BezierCurveType => { +export function getCurveType(numPoints: number): BezierCurveType { switch (numPoints) { case 2: return BezierCurveType.Linear; @@ -11,9 +11,9 @@ export const getCurveType = (numPoints: number): BezierCurveType => { default: throw new Error("Invalid number of points for a bezier"); } -}; +} -export const getConstructorKey = (bezierCurveType: BezierCurveType): WasmBezierConstructorKey => { +export function getConstructorKey(bezierCurveType: BezierCurveType): WasmBezierConstructorKey { switch (bezierCurveType) { case BezierCurveType.Linear: return "new_linear"; @@ -24,4 +24,4 @@ export const getConstructorKey = (bezierCurveType: BezierCurveType): WasmBezierC default: throw new Error("Invalid value for a BezierCurveType"); } -}; +} diff --git a/website/other/bezier-rs-demos/src/utils/types.ts b/website/other/bezier-rs-demos/src/utils/types.ts index da90fbe3f..6acbef641 100644 --- a/website/other/bezier-rs-demos/src/utils/types.ts +++ b/website/other/bezier-rs-demos/src/utils/types.ts @@ -14,8 +14,7 @@ export enum BezierCurveType { Cubic = "Cubic", } -export type Callback = (canvas: HTMLCanvasElement, bezier: WasmBezierInstance, options: Record, mouseLocation?: Point) => void; -export type BezierCallback = (bezier: WasmBezierInstance, options: Record, mouseLocation?: Point) => string; +export type BezierCallback = (bezier: WasmBezierInstance, options: Record, mouseLocation?: [number, number]) => string; export type SubpathCallback = (subpath: WasmSubpathInstance) => string; export type ExampleOptions = { @@ -34,31 +33,3 @@ export type SliderOption = { variable: string; unit?: string | string[]; }; - -export type TemplateOption = { - sliders: SliderOption[]; -}; - -export type Point = { - x: number; - y: number; -}; - -export type BezierPoint = Point & { - manipulator: WasmBezierManipulatorKey; -}; - -export type BezierStyleConfig = { - curveStrokeColor: string; - handleStrokeColor: string; - handleLineStrokeColor: string; - radius: number; - drawHandles: boolean; -}; - -export type CircleSector = { - center: Point; - radius: number; - startAngle: number; - endAngle: number; -}; diff --git a/website/other/bezier-rs-demos/wasm/src/bezier.rs b/website/other/bezier-rs-demos/wasm/src/bezier.rs index 2d4421e3d..fde35dbbc 100644 --- a/website/other/bezier-rs-demos/wasm/src/bezier.rs +++ b/website/other/bezier-rs-demos/wasm/src/bezier.rs @@ -6,7 +6,7 @@ use wasm_bindgen::prelude::*; #[derive(Serialize, Deserialize)] struct CircleSector { - center: Point, + center: DVec2, radius: f64, #[serde(rename = "startAngle")] start_angle: f64, @@ -14,12 +14,6 @@ struct CircleSector { end_angle: f64, } -#[derive(Serialize, Deserialize)] -struct Point { - x: f64, - y: f64, -} - #[wasm_bindgen] pub enum WasmMaximizeArcs { Automatic, // 0 @@ -34,11 +28,6 @@ const SCALE_UNIT_VECTOR_FACTOR: f64 = 50.; #[derive(Clone)] pub struct WasmBezier(Bezier); -/// Convert a `DVec2` into a `Point`. -fn vec_to_point(p: &DVec2) -> Point { - Point { x: p.x, y: p.y } -} - /// Serialize some data and then convert it to a JsValue. fn to_js_value(data: T) -> JsValue { JsValue::from_serde(&serde_json::to_string(&data).unwrap()).unwrap() @@ -85,7 +74,7 @@ impl WasmBezier { HANDLE_ATTRIBUTES.to_string().replace(GRAY, RED), HANDLE_LINE_ATTRIBUTES.to_string().replace(GRAY, RED), ); - let through_point_circle = format!(r#""#, through_point.x, through_point.y, ANCHOR_ATTRIBUTES.to_string()); + let through_point_circle = format!(r#""#, through_point.x, through_point.y, ANCHOR_ATTRIBUTES); wrap_svg_tag(format!("{bezier_string}{through_point_circle}")) } @@ -118,10 +107,8 @@ impl WasmBezier { self.0.set_handle_end(DVec2::new(x, y)); } - /// The wrapped return type is `Vec`. pub fn get_points(&self) -> JsValue { - let points: Vec = self.0.get_points().map(|point| vec_to_point(&point)).collect(); - to_js_value(points) + to_js_value(self.0.get_points().collect::>()) } fn get_bezier_path(&self) -> String { @@ -145,25 +132,19 @@ impl WasmBezier { wrap_svg_tag(format!("{bezier}{}", draw_text(format!("Length: {:.2}", self.0.length(None)), TEXT_OFFSET_X, TEXT_OFFSET_Y, BLACK))) } - /// The wrapped return type is `Point`. - pub fn evaluate_value(&self, t: f64) -> JsValue { - let point: Point = vec_to_point(&self.0.evaluate(t)); - to_js_value(point) - } - pub fn evaluate(&self, t: f64) -> String { let bezier = self.get_bezier_path(); let point = &self.0.evaluate(t); - let content = format!("{bezier}{}", draw_circle(point.x, point.y, 4., RED, 1.5, WHITE)); + let content = format!("{bezier}{}", draw_circle(*point, 4., RED, 1.5, WHITE)); wrap_svg_tag(content) } pub fn compute_lookup_table(&self, steps: usize) -> String { let bezier = self.get_bezier_path(); - let table_values: Vec = self.0.compute_lookup_table(Some(steps)).iter().map(vec_to_point).collect(); + let table_values: Vec = self.0.compute_lookup_table(Some(steps)); let circles: String = table_values .iter() - .map(|point| draw_circle(point.x, point.y, 3., RED, 1.5, WHITE)) + .map(|point| draw_circle(*point, 3., RED, 1.5, WHITE)) .fold("".to_string(), |acc, circle| acc + &circle); let content = format!("{bezier}{circles}"); wrap_svg_tag(content) @@ -188,7 +169,6 @@ impl WasmBezier { wrap_svg_tag(content) } - /// The wrapped return type is `Point`. pub fn tangent(&self, t: f64) -> String { let bezier = self.get_bezier_path(); @@ -198,9 +178,9 @@ impl WasmBezier { let content = format!( "{bezier}{}{}{}", - draw_circle(intersection_point.x, intersection_point.y, 3., RED, 1., WHITE), + draw_circle(intersection_point, 3., RED, 1., WHITE), draw_line(intersection_point.x, intersection_point.y, tangent_end.x, tangent_end.y, RED, 1.), - draw_circle(tangent_end.x, tangent_end.y, 3., RED, 1., WHITE), + draw_circle(tangent_end, 3., RED, 1., WHITE), ); wrap_svg_tag(content) } @@ -215,8 +195,8 @@ impl WasmBezier { let content = format!( "{bezier}{}{}{}", draw_line(intersection_point.x, intersection_point.y, normal_end.x, normal_end.y, RED, 1.), - draw_circle(intersection_point.x, intersection_point.y, 3., RED, 1., WHITE), - draw_circle(normal_end.x, normal_end.y, 3., RED, 1., WHITE), + draw_circle(intersection_point, 3., RED, 1., WHITE), + draw_circle(normal_end, 3., RED, 1., WHITE), ); wrap_svg_tag(content) } @@ -231,10 +211,10 @@ impl WasmBezier { let content = format!( "{bezier}{}{}{}{}", - draw_circle(curvature_center.x, curvature_center.y, radius.abs(), RED, 1., NONE), + draw_circle(curvature_center, radius.abs(), RED, 1., NONE), draw_line(intersection_point.x, intersection_point.y, curvature_center.x, curvature_center.y, RED, 1.), - draw_circle(intersection_point.x, intersection_point.y, 3., RED, 1., WHITE), - draw_circle(curvature_center.x, curvature_center.y, 3., RED, 1., WHITE), + draw_circle(intersection_point, 3., RED, 1., WHITE), + draw_circle(curvature_center, 3., RED, 1., WHITE), ); wrap_svg_tag(content) } @@ -306,7 +286,7 @@ impl WasmBezier { .flat_map(|(t_value_list, color)| { t_value_list.iter().map(|&t_value| { let point = self.0.evaluate(t_value); - draw_circle(point.x, point.y, 3., color, 1.5, WHITE) + draw_circle(point, 3., color, 1.5, WHITE) }) }) .fold("".to_string(), |acc, circle| acc + &circle); @@ -341,7 +321,7 @@ impl WasmBezier { .iter() .map(|&t_value| { let point = self.0.evaluate(t_value); - draw_circle(point.x, point.y, 3., RED, 1.5, WHITE) + draw_circle(point, 3., RED, 1.5, WHITE) }) .fold("".to_string(), |acc, circle| acc + &circle); let content = format!("{bezier}{circles}"); @@ -362,7 +342,7 @@ impl WasmBezier { .iter() .enumerate() .map(|(index, point)| { - let circle = draw_circle(point.x, point.y, 3., &color_light, 1.5, WHITE); + let circle = draw_circle(*point, 3., &color_light, 1.5, WHITE); if index != 0 { let prev_point = points[index - 1]; let line = draw_line(prev_point.x, prev_point.y, point.x, point.y, &color_light, 1.5); @@ -385,7 +365,7 @@ impl WasmBezier { let rotated_bezier = self.0.rotate_about_point(angle, DVec2::new(pivot_x, pivot_y)); let mut rotated_bezier_svg = String::new(); rotated_bezier.to_svg(&mut rotated_bezier_svg, CURVE_ATTRIBUTES.to_string().replace(BLACK, RED), String::new(), String::new(), String::new()); - let pivot = draw_circle(pivot_x, pivot_y, 3., GRAY, 1.5, WHITE); + let pivot = draw_circle(DVec2::new(pivot_x, pivot_y), 3., GRAY, 1.5, WHITE); // Line between pivot and start point on curve let original_dashed_line_start = format!( @@ -434,7 +414,7 @@ impl WasmBezier { .iter() .map(|intersection_t| { let point = &self.0.evaluate(*intersection_t); - draw_circle(point.x, point.y, 4., RED, 1.5, WHITE) + draw_circle(*point, 4., RED, 1.5, WHITE) }) .fold(String::new(), |acc, item| format!("{acc}{item}")); wrap_svg_tag(format!("{bezier_curve_svg}{line_svg}{intersections_svg}")) @@ -454,7 +434,7 @@ impl WasmBezier { .iter() .map(|intersection_t| { let point = &self.0.evaluate(*intersection_t); - draw_circle(point.x, point.y, 4., RED, 1.5, WHITE) + draw_circle(*point, 4., RED, 1.5, WHITE) }) .fold(String::new(), |acc, item| format!("{acc}{item}")); wrap_svg_tag(format!("{bezier_curve_svg}{quadratic_svg}{intersections_svg}")) @@ -474,7 +454,7 @@ impl WasmBezier { .iter() .map(|intersection_t| { let point = &self.0.evaluate(*intersection_t); - draw_circle(point.x, point.y, 4., RED, 1.5, WHITE) + draw_circle(*point, 4., RED, 1.5, WHITE) }) .fold(String::new(), |acc, item| format!("{acc}{item}")); @@ -490,7 +470,7 @@ impl WasmBezier { .iter() .map(|intersection_t| { let point = &self.0.evaluate(intersection_t[0]); - draw_circle(point.x, point.y, 4., RED, 1.5, WHITE) + draw_circle(*point, 4., RED, 1.5, WHITE) }) .fold(bezier_curve_svg, |acc, item| format!("{acc}{item}")); @@ -577,7 +557,6 @@ impl WasmBezier { wrap_svg_tag(format!("{bezier_svg}{outline_svg}")) } - /// The wrapped return type is `Vec`. pub fn arcs(&self, error: f64, max_iterations: usize, maximize_arcs: WasmMaximizeArcs) -> String { let original_curve_svg = self.get_bezier_path(); @@ -591,8 +570,7 @@ impl WasmBezier { .enumerate() .map(|(idx, sector)| { draw_sector( - sector.center.x, - sector.center.y, + sector.center, sector.radius, -sector.start_angle, -sector.end_angle, diff --git a/website/other/bezier-rs-demos/wasm/src/svg_drawing.rs b/website/other/bezier-rs-demos/wasm/src/svg_drawing.rs index bf7a5992c..fdfd123b3 100644 --- a/website/other/bezier-rs-demos/wasm/src/svg_drawing.rs +++ b/website/other/bezier-rs-demos/wasm/src/svg_drawing.rs @@ -1,4 +1,5 @@ use bezier_rs::Bezier; +use glam::DVec2; use std::fmt::Write; // SVG drawing constants @@ -31,8 +32,11 @@ pub fn draw_text(text: String, x_pos: f64, y_pos: f64, fill: &str) -> String { } /// Helper function to create an SVG circle entity. -pub fn draw_circle(x_pos: f64, y_pos: f64, radius: f64, stroke: &str, stroke_width: f64, fill: &str) -> String { - format!(r#""#) +pub fn draw_circle(position: DVec2, radius: f64, stroke: &str, stroke_width: f64, fill: &str) -> String { + format!( + r#""#, + position.x, position.y + ) } /// Helper function to create an SVG circle entity. @@ -61,11 +65,14 @@ fn polar_to_cartesian(center_x: f64, center_y: f64, radius: f64, angle_in_rad: f } // Helper function to create an SVG drawing of a sector -pub fn draw_sector(center_x: f64, center_y: f64, radius: f64, start_angle: f64, end_angle: f64, stroke: &str, stroke_width: f64, fill: &str) -> String { - let [start_x, start_y] = polar_to_cartesian(center_x, center_y, radius, start_angle); - let [end_x, end_y] = polar_to_cartesian(center_x, center_y, radius, end_angle); +pub fn draw_sector(center: DVec2, radius: f64, start_angle: f64, end_angle: f64, stroke: &str, stroke_width: f64, fill: &str) -> String { + let [start_x, start_y] = polar_to_cartesian(center.x, center.y, radius, start_angle); + let [end_x, end_y] = polar_to_cartesian(center.x, center.y, radius, end_angle); // draw sector with fill color - let sector_svg = format!(r#""#); + let sector_svg = format!( + r#""#, + center.x, center.y + ); // draw arc with stroke color let arc_svg = format!(r#""#); format!("{sector_svg}{arc_svg}")