diff --git a/packages/common/src/points.ts b/packages/common/src/points.ts index e8f988203..0d18a5cde 100644 --- a/packages/common/src/points.ts +++ b/packages/common/src/points.ts @@ -1,14 +1,9 @@ -import { - pointFromPair, - type GlobalPoint, - type LocalPoint, -} from "@excalidraw/math"; +import { type GenericPoint, pointFromPair } from "@excalidraw/math"; +import { pointFrom } from "@excalidraw/math"; import type { NullableGridSize } from "@excalidraw/excalidraw/types"; -export const getSizeFromPoints = ( - points: readonly (GlobalPoint | LocalPoint)[], -) => { +export const getSizeFromPoints = (points: readonly GenericPoint[]) => { const xs = points.map((point) => point[0]); const ys = points.map((point) => point[1]); return { @@ -18,7 +13,7 @@ export const getSizeFromPoints = ( }; /** @arg dimension, 0 for rescaling only x, 1 for y */ -export const rescalePoints = ( +export const rescalePoints = ( dimension: 0 | 1, newSize: number, points: readonly Point[], @@ -65,16 +60,16 @@ export const rescalePoints = ( }; // TODO: Rounding this point causes some shake when free drawing -export const getGridPoint = ( +export const getGridPoint = ( x: number, y: number, gridSize: NullableGridSize, -): [number, number] => { +): Point => { if (gridSize) { - return [ + return pointFrom( Math.round(x / gridSize) * gridSize, Math.round(y / gridSize) * gridSize, - ]; + ); } - return [x, y]; + return pointFrom(x, y); }; diff --git a/packages/element/src/collision.ts b/packages/element/src/collision.ts index 07b17bfde..c9d75d05d 100644 --- a/packages/element/src/collision.ts +++ b/packages/element/src/collision.ts @@ -19,9 +19,9 @@ import { isPointInShape, isPointOnShape } from "@excalidraw/utils/collision"; import { type GeometricShape, getPolygonShape } from "@excalidraw/utils/shape"; import type { + GenericPoint, GlobalPoint, LineSegment, - LocalPoint, Polygon, Radians, } from "@excalidraw/math"; @@ -72,7 +72,7 @@ export const shouldTestInside = (element: ExcalidrawElement) => { return isDraggableFromInside || isImageElement(element); }; -export type HitTestArgs = { +export type HitTestArgs = { x: number; y: number; element: ExcalidrawElement; @@ -81,7 +81,7 @@ export type HitTestArgs = { frameNameBound?: FrameNameBounds | null; }; -export const hitElementItself = ({ +export const hitElementItself = ({ x, y, element, @@ -127,9 +127,7 @@ export const hitElementBoundingBox = ( ); }; -export const hitElementBoundingBoxOnly = < - Point extends GlobalPoint | LocalPoint, ->( +export const hitElementBoundingBoxOnly = ( hitArgs: HitTestArgs, elementsMap: ElementsMap, ) => { @@ -145,7 +143,7 @@ export const hitElementBoundingBoxOnly = < ); }; -export const hitElementBoundText = ( +export const hitElementBoundText = ( x: number, y: number, textShape: GeometricShape | null, diff --git a/packages/element/src/elbowArrow.ts b/packages/element/src/elbowArrow.ts index a70e265bc..4461d1e9d 100644 --- a/packages/element/src/elbowArrow.ts +++ b/packages/element/src/elbowArrow.ts @@ -9,6 +9,7 @@ import { vectorCross, vectorFromPoint, vectorScale, + type GenericPoint, type GlobalPoint, type LocalPoint, } from "@excalidraw/math"; @@ -1642,7 +1643,7 @@ const pathTo = (start: Node, node: Node) => { return path; }; -const m_dist = (a: GlobalPoint | LocalPoint, b: GlobalPoint | LocalPoint) => +const m_dist = (a: GenericPoint, b: GenericPoint) => Math.abs(a[0] - b[0]) + Math.abs(a[1] - b[1]); /** @@ -2291,7 +2292,7 @@ const getHoveredElement = ( const gridAddressesEqual = (a: GridAddress, b: GridAddress): boolean => a[0] === b[0] && a[1] === b[1]; -export const validateElbowPoints =

( +export const validateElbowPoints =

( points: readonly P[], tolerance: number = DEDUP_TRESHOLD, ) => diff --git a/packages/element/src/heading.ts b/packages/element/src/heading.ts index 1e9ab3713..6e50d0dff 100644 --- a/packages/element/src/heading.ts +++ b/packages/element/src/heading.ts @@ -13,10 +13,10 @@ import { } from "@excalidraw/math"; import type { - LocalPoint, GlobalPoint, Triangle, Vector, + GenericPoint, } from "@excalidraw/math"; import { getCenterForBounds, type Bounds } from "./bounds"; @@ -43,12 +43,10 @@ export const vectorToHeading = (vec: Vector): Heading => { return HEADING_UP; }; -export const headingForPoint =

( - p: P, - o: P, -) => vectorToHeading(vectorFromPoint

(p, o)); +export const headingForPoint =

(p: P, o: P) => + vectorToHeading(vectorFromPoint

(p, o)); -export const headingForPointIsHorizontal =

( +export const headingForPointIsHorizontal =

( p: P, o: P, ) => headingIsHorizontal(headingForPoint

(p, o)); diff --git a/packages/element/src/resizeTest.ts b/packages/element/src/resizeTest.ts index 411dcf9a7..219265d36 100644 --- a/packages/element/src/resizeTest.ts +++ b/packages/element/src/resizeTest.ts @@ -7,7 +7,7 @@ import { import { SIDE_RESIZING_THRESHOLD } from "@excalidraw/common"; -import type { GlobalPoint, LineSegment, LocalPoint } from "@excalidraw/math"; +import type { GenericPoint, LineSegment } from "@excalidraw/math"; import type { AppState, Device, Zoom } from "@excalidraw/excalidraw/types"; @@ -43,7 +43,7 @@ const isInsideTransformHandle = ( y >= transformHandle[1] && y <= transformHandle[1] + transformHandle[3]; -export const resizeTest = ( +export const resizeTest = ( element: NonDeletedExcalidrawElement, elementsMap: ElementsMap, appState: AppState, @@ -152,9 +152,7 @@ export const getElementWithTransformHandleType = ( }, null as { element: NonDeletedExcalidrawElement; transformHandleType: MaybeTransformHandleType } | null); }; -export const getTransformHandleTypeFromCoords = < - Point extends GlobalPoint | LocalPoint, ->( +export const getTransformHandleTypeFromCoords = ( [x1, y1, x2, y2]: Bounds, scenePointerX: number, scenePointerY: number, @@ -271,7 +269,7 @@ export const getCursorForResizingElement = (resizingElement: { return cursor ? `${cursor}-resize` : ""; }; -const getSelectionBorders = ( +const getSelectionBorders = ( [x1, y1]: Point, [x2, y2]: Point, center: Point, diff --git a/packages/element/src/shapes.ts b/packages/element/src/shapes.ts index 96542c538..4ae2f87d3 100644 --- a/packages/element/src/shapes.ts +++ b/packages/element/src/shapes.ts @@ -13,8 +13,7 @@ import { pointFromPair, pointRotateRads, pointsEqual, - type GlobalPoint, - type LocalPoint, + type GenericPoint, } from "@excalidraw/math"; import { getClosedCurveShape, @@ -46,7 +45,7 @@ import type { * get the pure geometric shape of an excalidraw elementw * which is then used for hit detection */ -export const getElementShape = ( +export const getElementShape = ( element: ExcalidrawElement, elementsMap: ElementsMap, ): GeometricShape => { @@ -98,7 +97,7 @@ export const getElementShape = ( } }; -export const getBoundTextShape = ( +export const getBoundTextShape = ( element: ExcalidrawElement, elementsMap: ElementsMap, ): GeometricShape | null => { @@ -126,9 +125,7 @@ export const getBoundTextShape = ( return null; }; -export const getControlPointsForBezierCurve = < - P extends GlobalPoint | LocalPoint, ->( +export const getControlPointsForBezierCurve =

( element: NonDeleted, endPoint: P, ) => { @@ -170,7 +167,7 @@ export const getControlPointsForBezierCurve = < return controlPoints; }; -export const getBezierXY =

( +export const getBezierXY =

( p0: P, p1: P, p2: P, @@ -187,7 +184,7 @@ export const getBezierXY =

( return pointFrom(tx, ty); }; -const getPointsInBezierCurve =

( +const getPointsInBezierCurve =

( element: NonDeleted, endPoint: P, ) => { @@ -217,7 +214,7 @@ const getPointsInBezierCurve =

( return pointsOnCurve; }; -const getBezierCurveArcLengths =

( +const getBezierCurveArcLengths =

( element: NonDeleted, endPoint: P, ) => { @@ -236,7 +233,7 @@ const getBezierCurveArcLengths =

( return arcLengths; }; -export const getBezierCurveLength =

( +export const getBezierCurveLength =

( element: NonDeleted, endPoint: P, ) => { @@ -245,7 +242,7 @@ export const getBezierCurveLength =

( }; // This maps interval to actual interval t on the curve so that when t = 0.5, its actually the point at 50% of the length -export const mapIntervalToBezierT =

( +export const mapIntervalToBezierT =

( element: NonDeleted, endPoint: P, interval: number, // The interval between 0 to 1 for which you want to find the point on the curve, @@ -340,7 +337,7 @@ export const aabbForElement = ( return bounds; }; -export const pointInsideBounds =

( +export const pointInsideBounds =

( p: P, bounds: Bounds, ): boolean => diff --git a/packages/excalidraw/renderer/interactiveScene.ts b/packages/excalidraw/renderer/interactiveScene.ts index 3000c206c..8329c5e4a 100644 --- a/packages/excalidraw/renderer/interactiveScene.ts +++ b/packages/excalidraw/renderer/interactiveScene.ts @@ -2,8 +2,8 @@ import oc from "open-color"; import { pointFrom, type GlobalPoint, - type LocalPoint, type Radians, + type GenericPoint, } from "@excalidraw/math"; import { @@ -144,7 +144,7 @@ const renderLinearElementPointHighlight = ( context.restore(); }; -const highlightPoint = ( +const highlightPoint = ( point: Point, context: CanvasRenderingContext2D, appState: InteractiveCanvasAppState, @@ -211,7 +211,7 @@ const strokeDiamondWithRotation = ( context.restore(); }; -const renderSingleLinearPoint = ( +const renderSingleLinearPoint = ( context: CanvasRenderingContext2D, appState: InteractiveCanvasAppState, point: Point, diff --git a/packages/excalidraw/renderer/renderSnaps.ts b/packages/excalidraw/renderer/renderSnaps.ts index dd131f779..ade8a6b83 100644 --- a/packages/excalidraw/renderer/renderSnaps.ts +++ b/packages/excalidraw/renderer/renderSnaps.ts @@ -1,4 +1,4 @@ -import { pointFrom, type GlobalPoint, type LocalPoint } from "@excalidraw/math"; +import { pointFrom, type GenericPoint } from "@excalidraw/math"; import { THEME } from "@excalidraw/common"; @@ -88,7 +88,7 @@ const drawPointerSnapLine = ( } }; -const drawCross = ( +const drawCross = ( [x, y]: Point, appState: InteractiveCanvasAppState, context: CanvasRenderingContext2D, @@ -109,7 +109,7 @@ const drawCross = ( context.restore(); }; -const drawLine = ( +const drawLine = ( from: Point, to: Point, context: CanvasRenderingContext2D, @@ -120,7 +120,7 @@ const drawLine = ( context.stroke(); }; -const drawGapLine = ( +const drawGapLine = ( from: Point, to: Point, direction: "horizontal" | "vertical", diff --git a/packages/math/src/angle.ts b/packages/math/src/angle.ts index 353dc5dad..8dab50cac 100644 --- a/packages/math/src/angle.ts +++ b/packages/math/src/angle.ts @@ -1,12 +1,6 @@ import { PRECISION } from "./utils"; -import type { - Degrees, - GlobalPoint, - LocalPoint, - PolarCoords, - Radians, -} from "./types"; +import type { Degrees, GenericPoint, PolarCoords, Radians } from "./types"; // TODO: Simplify with modulo and fix for angles beyond 4*Math.PI and - 4*Math.PI export const normalizeRadians = (angle: Radians): Radians => { @@ -24,7 +18,7 @@ export const normalizeRadians = (angle: Radians): Radians => { * (x, y) for the center point 0,0 where the first number returned is the radius, * the second is the angle in radians. */ -export const cartesian2Polar =

([ +export const cartesian2Polar =

([ x, y, ]: P): PolarCoords => [ diff --git a/packages/math/src/curve.ts b/packages/math/src/curve.ts index a79fb43a1..06cd31d8e 100644 --- a/packages/math/src/curve.ts +++ b/packages/math/src/curve.ts @@ -3,7 +3,7 @@ import type { Bounds } from "@excalidraw/element/bounds"; import { isPoint, pointDistance, pointFrom } from "./point"; import { rectangle, rectangleIntersectLineSegment } from "./rectangle"; -import type { Curve, GlobalPoint, LineSegment, LocalPoint } from "./types"; +import type { Curve, GenericPoint, LineSegment } from "./types"; /** * @@ -13,7 +13,7 @@ import type { Curve, GlobalPoint, LineSegment, LocalPoint } from "./types"; * @param d * @returns */ -export function curve( +export function curve( a: Point, b: Point, c: Point, @@ -82,7 +82,7 @@ function solve( return [t0, s0]; } -const bezierEquation = ( +const bezierEquation = ( c: Curve, t: number, ) => @@ -100,9 +100,10 @@ const bezierEquation = ( /** * Computes the intersection between a cubic spline and a line segment. */ -export function curveIntersectLineSegment< - Point extends GlobalPoint | LocalPoint, ->(c: Curve, l: LineSegment): Point[] { +export function curveIntersectLineSegment( + c: Curve, + l: LineSegment, +): Point[] { // Optimize by doing a cheap bounding box check first const bounds = curveBounds(c); if ( @@ -188,7 +189,7 @@ export function curveIntersectLineSegment< * @param maxLevel * @returns */ -export function curveClosestPoint( +export function curveClosestPoint( c: Curve, p: Point, tolerance: number = 1e-3, @@ -245,7 +246,7 @@ export function curveClosestPoint( * @param c The curve to test * @param p The point to measure from */ -export function curvePointDistance( +export function curvePointDistance( c: Curve, p: Point, ) { @@ -261,9 +262,7 @@ export function curvePointDistance( /** * Determines if the parameter is a Curve */ -export function isCurve

( - v: unknown, -): v is Curve

{ +export function isCurve

(v: unknown): v is Curve

{ return ( Array.isArray(v) && v.length === 4 && @@ -274,9 +273,7 @@ export function isCurve

( ); } -function curveBounds( - c: Curve, -): Bounds { +function curveBounds(c: Curve): Bounds { const [P0, P1, P2, P3] = c; const x = [P0[0], P1[0], P2[0], P3[0]]; const y = [P0[1], P1[1], P2[1], P3[1]]; diff --git a/packages/math/src/ellipse.ts b/packages/math/src/ellipse.ts index 741a77df3..82af3a623 100644 --- a/packages/math/src/ellipse.ts +++ b/packages/math/src/ellipse.ts @@ -13,13 +13,7 @@ import { vectorScale, } from "./vector"; -import type { - Ellipse, - GlobalPoint, - Line, - LineSegment, - LocalPoint, -} from "./types"; +import type { Ellipse, GenericPoint, Line, LineSegment } from "./types"; /** * Construct an Ellipse object from the parameters @@ -30,7 +24,7 @@ import type { * @param halfHeight Half of the height of a non-slanted version of the ellipse * @returns The constructed Ellipse object */ -export function ellipse( +export function ellipse( center: Point, halfWidth: number, halfHeight: number, @@ -49,7 +43,7 @@ export function ellipse( * @param ellipse The ellipse to compare against * @returns TRUE if the point is inside or on the outline of the ellipse */ -export const ellipseIncludesPoint = ( +export const ellipseIncludesPoint = ( p: Point, ellipse: Ellipse, ) => { @@ -69,7 +63,7 @@ export const ellipseIncludesPoint = ( * @param threshold The distance to consider a point close enough to be "on" the outline * @returns TRUE if the point is on the ellise outline */ -export const ellipseTouchesPoint = ( +export const ellipseTouchesPoint = ( point: Point, ellipse: Ellipse, threshold = PRECISION, @@ -85,9 +79,7 @@ export const ellipseTouchesPoint = ( * @param ellipse The ellipse to calculate the distance to * @returns The eucledian distance */ -export const ellipseDistanceFromPoint = < - Point extends GlobalPoint | LocalPoint, ->( +export const ellipseDistanceFromPoint = ( p: Point, ellipse: Ellipse, ): number => { @@ -140,9 +132,10 @@ export const ellipseDistanceFromPoint = < * Calculate a maximum of two intercept points for a line going throug an * ellipse. */ -export function ellipseSegmentInterceptPoints< - Point extends GlobalPoint | LocalPoint, ->(e: Readonly>, s: Readonly>): Point[] { +export function ellipseSegmentInterceptPoints( + e: Readonly>, + s: Readonly>, +): Point[] { const rx = e.halfWidth; const ry = e.halfHeight; @@ -194,9 +187,7 @@ export function ellipseSegmentInterceptPoints< return intersections; } -export function ellipseLineIntersectionPoints< - Point extends GlobalPoint | LocalPoint, ->( +export function ellipseLineIntersectionPoints( { center, halfWidth, halfHeight }: Ellipse, [g, h]: Line, ): Point[] { diff --git a/packages/math/src/line.ts b/packages/math/src/line.ts index 889fa08ce..af3cd58c9 100644 --- a/packages/math/src/line.ts +++ b/packages/math/src/line.ts @@ -1,6 +1,6 @@ import { pointFrom } from "./point"; -import type { GlobalPoint, Line, LocalPoint } from "./types"; +import type { GenericPoint, Line } from "./types"; /** * Create a line from two points. @@ -8,7 +8,7 @@ import type { GlobalPoint, Line, LocalPoint } from "./types"; * @param points The two points lying on the line * @returns The line on which the points lie */ -export function line

(a: P, b: P): Line

{ +export function line

(a: P, b: P): Line

{ return [a, b] as Line

; } @@ -20,7 +20,7 @@ export function line

(a: P, b: P): Line

{ * @param b * @returns */ -export function linesIntersectAt( +export function linesIntersectAt( a: Line, b: Line, ): Point | null { diff --git a/packages/math/src/point.ts b/packages/math/src/point.ts index b6054a10a..db42a07a8 100644 --- a/packages/math/src/point.ts +++ b/packages/math/src/point.ts @@ -2,13 +2,7 @@ import { degreesToRadians } from "./angle"; import { PRECISION } from "./utils"; import { vectorFromPoint, vectorScale } from "./vector"; -import type { - LocalPoint, - GlobalPoint, - Radians, - Degrees, - Vector, -} from "./types"; +import type { Radians, Degrees, Vector, GenericPoint } from "./types"; /** * Create a properly typed Point instance from the X and Y coordinates. @@ -17,7 +11,7 @@ import type { * @param y The Y coordinate * @returns The branded and created point */ -export function pointFrom( +export function pointFrom( x: number, y: number, ): Point { @@ -30,7 +24,7 @@ export function pointFrom( * @param numberArray The number array to check and to convert to Point * @returns The point instance */ -export function pointFromArray( +export function pointFromArray( numberArray: number[], ): Point | undefined { return numberArray.length === 2 @@ -44,7 +38,7 @@ export function pointFromArray( * @param pair A number pair to convert to Point * @returns The point instance */ -export function pointFromPair( +export function pointFromPair( pair: [number, number], ): Point { return pair as Point; @@ -56,7 +50,7 @@ export function pointFromPair( * @param v The vector to convert * @returns The point the vector points at with origin 0,0 */ -export function pointFromVector

( +export function pointFromVector

( v: Vector, offset: P = pointFrom(0, 0), ): P { @@ -69,7 +63,7 @@ export function pointFromVector

( * @param p The value to attempt verification on * @returns TRUE if the provided value has the shape of a local or global point */ -export function isPoint(p: unknown): p is LocalPoint | GlobalPoint { +export function isPoint(p: unknown): p is GenericPoint { return ( Array.isArray(p) && p.length === 2 && @@ -88,7 +82,7 @@ export function isPoint(p: unknown): p is LocalPoint | GlobalPoint { * @param b Point The second point to compare * @returns TRUE if the points are sufficiently close to each other */ -export function pointsEqual( +export function pointsEqual( a: Point, b: Point, ): boolean { @@ -104,7 +98,7 @@ export function pointsEqual( * @param angle The radians to rotate the point by * @returns The rotated point */ -export function pointRotateRads( +export function pointRotateRads( [x, y]: Point, [cx, cy]: Point, angle: Radians, @@ -123,7 +117,7 @@ export function pointRotateRads( * @param angle The degree to rotate the point by * @returns The rotated point */ -export function pointRotateDegs( +export function pointRotateDegs( point: Point, center: Point, angle: Degrees, @@ -145,8 +139,8 @@ export function pointRotateDegs( */ // TODO 99% of use is translating between global and local coords, which need to be formalized export function pointTranslate< - From extends GlobalPoint | LocalPoint, - To extends GlobalPoint | LocalPoint, + From extends GenericPoint, + To extends GenericPoint, >(p: From, v: Vector = [0, 0] as Vector): To { return pointFrom(p[0] + v[0], p[1] + v[1]); } @@ -158,7 +152,7 @@ export function pointTranslate< * @param b The other point to create the middle point for * @returns The middle point */ -export function pointCenter

(a: P, b: P): P { +export function pointCenter

(a: P, b: P): P { return pointFrom((a[0] + b[0]) / 2, (a[1] + b[1]) / 2); } @@ -169,10 +163,7 @@ export function pointCenter

(a: P, b: P): P { * @param b Second point * @returns The euclidean distance between the two points. */ -export function pointDistance

( - a: P, - b: P, -): number { +export function pointDistance

(a: P, b: P): number { return Math.hypot(b[0] - a[0], b[1] - a[1]); } @@ -185,10 +176,7 @@ export function pointDistance

( * @param b Second point * @returns The euclidean distance between the two points. */ -export function pointDistanceSq

( - a: P, - b: P, -): number { +export function pointDistanceSq

(a: P, b: P): number { const xDiff = b[0] - a[0]; const yDiff = b[1] - a[1]; @@ -203,7 +191,7 @@ export function pointDistanceSq

( * @param multiplier The scaling factor * @returns */ -export const pointScaleFromOrigin =

( +export const pointScaleFromOrigin =

( p: P, mid: P, multiplier: number, @@ -218,7 +206,7 @@ export const pointScaleFromOrigin =

( * @param r The other point to compare against * @returns TRUE if q is indeed between p and r */ -export const isPointWithinBounds =

( +export const isPointWithinBounds =

( p: P, q: P, r: P, diff --git a/packages/math/src/polygon.ts b/packages/math/src/polygon.ts index a50d4e853..8f1671a54 100644 --- a/packages/math/src/polygon.ts +++ b/packages/math/src/polygon.ts @@ -2,21 +2,17 @@ import { pointsEqual } from "./point"; import { lineSegment, pointOnLineSegment } from "./segment"; import { PRECISION } from "./utils"; -import type { GlobalPoint, LocalPoint, Polygon } from "./types"; +import type { GenericPoint, Polygon } from "./types"; -export function polygon( - ...points: Point[] -) { +export function polygon(...points: Point[]) { return polygonClose(points) as Polygon; } -export function polygonFromPoints( - points: Point[], -) { +export function polygonFromPoints(points: Point[]) { return polygonClose(points) as Polygon; } -export const polygonIncludesPoint = ( +export const polygonIncludesPoint = ( point: Point, polygon: Polygon, ) => { @@ -69,7 +65,7 @@ export const polygonIncludesPointNonZero = ( return windingNumber !== 0; }; -export const pointOnPolygon = ( +export const pointOnPolygon = ( p: Point, poly: Polygon, threshold = PRECISION, @@ -86,16 +82,12 @@ export const pointOnPolygon = ( return on; }; -function polygonClose( - polygon: Point[], -) { +function polygonClose(polygon: Point[]) { return polygonIsClosed(polygon) ? polygon : ([...polygon, polygon[0]] as Polygon); } -function polygonIsClosed( - polygon: Point[], -) { +function polygonIsClosed(polygon: Point[]) { return pointsEqual(polygon[0], polygon[polygon.length - 1]); } diff --git a/packages/math/src/rectangle.ts b/packages/math/src/rectangle.ts index 394b5c2f8..0675fee7e 100644 --- a/packages/math/src/rectangle.ts +++ b/packages/math/src/rectangle.ts @@ -1,18 +1,19 @@ import { pointFrom } from "./point"; import { lineSegment, lineSegmentIntersectionPoints } from "./segment"; -import type { GlobalPoint, LineSegment, LocalPoint, Rectangle } from "./types"; +import type { GenericPoint, LineSegment, Rectangle } from "./types"; -export function rectangle

( +export function rectangle

( topLeft: P, bottomRight: P, ): Rectangle

{ return [topLeft, bottomRight] as Rectangle

; } -export function rectangleIntersectLineSegment< - Point extends LocalPoint | GlobalPoint, ->(r: Rectangle, l: LineSegment): Point[] { +export function rectangleIntersectLineSegment( + r: Rectangle, + l: LineSegment, +): Point[] { return [ lineSegment(r[0], pointFrom(r[1][0], r[0][1])), lineSegment(pointFrom(r[1][0], r[0][1]), r[1]), diff --git a/packages/math/src/segment.ts b/packages/math/src/segment.ts index dade79039..90a818126 100644 --- a/packages/math/src/segment.ts +++ b/packages/math/src/segment.ts @@ -14,7 +14,7 @@ import { vectorSubtract, } from "./vector"; -import type { GlobalPoint, LineSegment, LocalPoint, Radians } from "./types"; +import type { GenericPoint, LineSegment, Radians } from "./types"; /** * Create a line segment from two points. @@ -22,7 +22,7 @@ import type { GlobalPoint, LineSegment, LocalPoint, Radians } from "./types"; * @param points The two points delimiting the line segment on each end * @returns The line segment delineated by the points */ -export function lineSegment

( +export function lineSegment

( a: P, b: P, ): LineSegment

{ @@ -34,7 +34,7 @@ export function lineSegment

( * @param segment * @returns */ -export const isLineSegment = ( +export const isLineSegment = ( segment: unknown, ): segment is LineSegment => Array.isArray(segment) && @@ -51,7 +51,7 @@ export const isLineSegment = ( * @param origin * @returns */ -export const lineSegmentRotate = ( +export const lineSegmentRotate = ( l: LineSegment, angle: Radians, origin?: Point, @@ -66,7 +66,7 @@ export const lineSegmentRotate = ( * Calculates the point two line segments with a definite start and end point * intersect at. */ -export const segmentsIntersectAt = ( +export const segmentsIntersectAt = ( a: Readonly>, b: Readonly>, ): Point | null => { @@ -99,7 +99,7 @@ export const segmentsIntersectAt = ( return null; }; -export const pointOnLineSegment = ( +export const pointOnLineSegment = ( point: Point, line: LineSegment, threshold = PRECISION, @@ -113,7 +113,7 @@ export const pointOnLineSegment = ( return distance < threshold; }; -export const distanceToLineSegment = ( +export const distanceToLineSegment = ( point: Point, line: LineSegment, ) => { @@ -158,9 +158,7 @@ export const distanceToLineSegment = ( * @param s * @returns */ -export function lineSegmentIntersectionPoints< - Point extends GlobalPoint | LocalPoint, ->( +export function lineSegmentIntersectionPoints( l: LineSegment, s: LineSegment, threshold?: number, diff --git a/packages/math/src/triangle.ts b/packages/math/src/triangle.ts index bc74372b7..8e6144e83 100644 --- a/packages/math/src/triangle.ts +++ b/packages/math/src/triangle.ts @@ -1,4 +1,4 @@ -import type { GlobalPoint, LocalPoint, Triangle } from "./types"; +import type { GenericPoint, Triangle } from "./types"; // Types @@ -11,7 +11,7 @@ import type { GlobalPoint, LocalPoint, Triangle } from "./types"; * @param p The point to test whether is in the triangle * @returns TRUE if the point is inside of the triangle */ -export function triangleIncludesPoint

( +export function triangleIncludesPoint

( [a, b, c]: Triangle

, p: P, ): boolean { diff --git a/packages/math/src/vector.ts b/packages/math/src/vector.ts index 246722067..b9d214288 100644 --- a/packages/math/src/vector.ts +++ b/packages/math/src/vector.ts @@ -1,4 +1,4 @@ -import type { GlobalPoint, LocalPoint, Vector } from "./types"; +import type { GenericPoint, Vector } from "./types"; /** * Create a vector from the x and y coordiante elements. @@ -23,7 +23,7 @@ export function vector( * @param origin The origin point in a given coordiante system * @returns The created vector from the point and the origin */ -export function vectorFromPoint( +export function vectorFromPoint( p: Point, origin: Point = [0, 0] as Point, ): Vector { diff --git a/packages/utils/src/bbox.ts b/packages/utils/src/bbox.ts index a56128156..1fb96f656 100644 --- a/packages/utils/src/bbox.ts +++ b/packages/utils/src/bbox.ts @@ -1,17 +1,14 @@ import { vectorCross, vectorFromPoint, - type GlobalPoint, - type LocalPoint, + type GenericPoint, } from "@excalidraw/math"; import type { Bounds } from "@excalidraw/element/bounds"; -export type LineSegment

= [P, P]; +export type LineSegment

= [P, P]; -export function getBBox

( - line: LineSegment

, -): Bounds { +export function getBBox

(line: LineSegment

): Bounds { return [ Math.min(line[0][0], line[1][0]), Math.min(line[0][1], line[1][1]), @@ -26,10 +23,7 @@ export function doBBoxesIntersect(a: Bounds, b: Bounds) { const EPSILON = 0.000001; -export function isPointOnLine

( - l: LineSegment

, - p: P, -) { +export function isPointOnLine

(l: LineSegment

, p: P) { const p1 = vectorFromPoint(l[1], l[0]); const p2 = vectorFromPoint(p, l[0]); @@ -38,7 +32,7 @@ export function isPointOnLine

( return Math.abs(r) < EPSILON; } -export function isPointRightOfLine

( +export function isPointRightOfLine

( l: LineSegment

, p: P, ) { @@ -48,9 +42,10 @@ export function isPointRightOfLine

( return vectorCross(p1, p2) < 0; } -export function isLineSegmentTouchingOrCrossingLine< - P extends GlobalPoint | LocalPoint, ->(a: LineSegment

, b: LineSegment

) { +export function isLineSegmentTouchingOrCrossingLine

( + a: LineSegment

, + b: LineSegment

, +) { return ( isPointOnLine(a, b[0]) || isPointOnLine(a, b[1]) || @@ -61,7 +56,7 @@ export function isLineSegmentTouchingOrCrossingLine< } // https://martin-thoma.com/how-to-check-if-two-line-segments-intersect/ -export function doLineSegmentsIntersect

( +export function doLineSegmentsIntersect

( a: LineSegment

, b: LineSegment

, ) { diff --git a/packages/utils/src/collision.ts b/packages/utils/src/collision.ts index b7c155f66..207be9bee 100644 --- a/packages/utils/src/collision.ts +++ b/packages/utils/src/collision.ts @@ -5,19 +5,17 @@ import { pointOnLineSegment, pointOnPolygon, polygonFromPoints, - type GlobalPoint, - type LocalPoint, type Polygon, } from "@excalidraw/math"; -import type { Curve } from "@excalidraw/math"; +import type { Curve, GenericPoint } from "@excalidraw/math"; import { pointInEllipse, pointOnEllipse } from "./shape"; import type { Polycurve, Polyline, GeometricShape } from "./shape"; // check if the given point is considered on the given shape's border -export const isPointOnShape = ( +export const isPointOnShape = ( point: Point, shape: GeometricShape, tolerance = 0, @@ -43,7 +41,7 @@ export const isPointOnShape = ( }; // check if the given point is considered inside the element's border -export const isPointInShape = ( +export const isPointInShape = ( point: Point, shape: GeometricShape, ) => { @@ -69,14 +67,14 @@ export const isPointInShape = ( }; // check if the given element is in the given bounds -export const isPointInBounds = ( +export const isPointInBounds = ( point: Point, bounds: Polygon, ) => { return polygonIncludesPoint(point, bounds); }; -const pointOnPolycurve = ( +const pointOnPolycurve = ( point: Point, polycurve: Polycurve, tolerance: number, @@ -84,7 +82,7 @@ const pointOnPolycurve = ( return polycurve.some((curve) => pointOnCurve(point, curve, tolerance)); }; -const cubicBezierEquation = ( +const cubicBezierEquation = ( curve: Curve, ) => { const [p0, p1, p2, p3] = curve; @@ -96,7 +94,7 @@ const cubicBezierEquation = ( p0[idx] * Math.pow(t, 3); }; -const polyLineFromCurve = ( +const polyLineFromCurve = ( curve: Curve, segments = 10, ): Polyline => { @@ -118,7 +116,7 @@ const polyLineFromCurve = ( return lineSegments; }; -export const pointOnCurve = ( +export const pointOnCurve = ( point: Point, curve: Curve, threshold: number, @@ -126,7 +124,7 @@ export const pointOnCurve = ( return pointOnPolyline(point, polyLineFromCurve(curve), threshold); }; -export const pointOnPolyline = ( +export const pointOnPolyline = ( point: Point, polyline: Polyline, threshold = 10e-5, diff --git a/packages/utils/src/shape.ts b/packages/utils/src/shape.ts index b750c232e..1cc332e7f 100644 --- a/packages/utils/src/shape.ts +++ b/packages/utils/src/shape.ts @@ -30,8 +30,6 @@ import { vectorAdd, vectorFromPoint, vectorScale, - type GlobalPoint, - type LocalPoint, } from "@excalidraw/math"; import { getElementAbsoluteCoords } from "@excalidraw/element/bounds"; @@ -52,31 +50,36 @@ import type { ExcalidrawSelectionElement, ExcalidrawTextElement, } from "@excalidraw/element/types"; -import type { Curve, LineSegment, Polygon, Radians } from "@excalidraw/math"; +import type { + Curve, + GenericPoint, + LineSegment, + Polygon, + Radians, +} from "@excalidraw/math"; import type { Drawable, Op } from "roughjs/bin/core"; // a polyline (made up term here) is a line consisting of other line segments // this corresponds to a straight line element in the editor but it could also // be used to model other elements -export type Polyline = - LineSegment[]; +export type Polyline = LineSegment[]; // a polycurve is a curve consisting of ther curves, this corresponds to a complex // curve on the canvas -export type Polycurve = Curve[]; +export type Polycurve = Curve[]; // 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 = { +export type Ellipse = { center: Point; angle: Radians; halfWidth: number; halfHeight: number; }; -export type GeometricShape = +export type GeometricShape = | { type: "line"; data: LineSegment; @@ -113,7 +116,7 @@ type RectangularElement = | ExcalidrawSelectionElement; // polygon -export const getPolygonShape = ( +export const getPolygonShape = ( element: RectangularElement, ): GeometricShape => { const { angle, width, height, x, y } = element; @@ -148,7 +151,7 @@ export const getPolygonShape = ( }; // return the selection box for an element, possibly rotated as well -export const getSelectionBoxShape = ( +export const getSelectionBoxShape = ( element: ExcalidrawElement, elementsMap: ElementsMap, padding = 10, @@ -178,7 +181,7 @@ export const getSelectionBoxShape = ( }; // ellipse -export const getEllipseShape = ( +export const getEllipseShape = ( element: ExcalidrawEllipseElement, ): GeometricShape => { const { width, height, angle, x, y } = element; @@ -209,7 +212,7 @@ export const getCurvePathOps = (shape: Drawable): Op[] => { }; // linear -export const getCurveShape = ( +export const getCurveShape = ( roughShape: Drawable, startingPoint: Point = pointFrom(0, 0), angleInRadian: Radians, @@ -247,7 +250,7 @@ export const getCurveShape = ( }; }; -const polylineFromPoints = ( +const polylineFromPoints = ( points: Point[], ): Polyline => { let previousPoint: Point = points[0]; @@ -262,7 +265,7 @@ const polylineFromPoints = ( return polyline; }; -export const getFreedrawShape = ( +export const getFreedrawShape = ( element: ExcalidrawFreeDrawElement, center: Point, isClosed: boolean = false, @@ -293,7 +296,7 @@ export const getFreedrawShape = ( ) as GeometricShape; }; -export const getClosedCurveShape = ( +export const getClosedCurveShape = ( element: ExcalidrawLinearElement, roughShape: Drawable, startingPoint: Point = pointFrom(0, 0), @@ -359,9 +362,7 @@ export const getClosedCurveShape = ( * @returns An array of intersections */ // TODO: Replace with final rounded rectangle code -export const segmentIntersectRectangleElement = < - Point extends LocalPoint | GlobalPoint, ->( +export const segmentIntersectRectangleElement = ( element: ExcalidrawBindableElement, segment: LineSegment, gap: number = 0, @@ -399,7 +400,7 @@ export const segmentIntersectRectangleElement = < .filter((i): i is Point => !!i); }; -const distanceToEllipse = ( +const distanceToEllipse = ( p: Point, ellipse: Ellipse, ) => { @@ -456,7 +457,7 @@ const distanceToEllipse = ( ); }; -export const pointOnEllipse = ( +export const pointOnEllipse = ( point: Point, ellipse: Ellipse, threshold = PRECISION, @@ -464,7 +465,7 @@ export const pointOnEllipse = ( return distanceToEllipse(point, ellipse) <= threshold; }; -export const pointInEllipse = ( +export const pointInEllipse = ( p: Point, ellipse: Ellipse, ) => { @@ -486,7 +487,7 @@ export const pointInEllipse = ( ); }; -export const ellipseAxes = ( +export const ellipseAxes = ( ellipse: Ellipse, ) => { const widthGreaterThanHeight = ellipse.halfWidth > ellipse.halfHeight; @@ -504,7 +505,7 @@ export const ellipseAxes = ( }; }; -export const ellipseFocusToCenter = ( +export const ellipseFocusToCenter = ( ellipse: Ellipse, ) => { const { majorAxis, minorAxis } = ellipseAxes(ellipse); @@ -512,7 +513,7 @@ export const ellipseFocusToCenter = ( return Math.sqrt(majorAxis ** 2 - minorAxis ** 2); }; -export const ellipseExtremes = ( +export const ellipseExtremes = ( ellipse: Ellipse, ) => { const { center, angle } = ellipse;