From 896855de3f9c31506d6431e539a4db8f8129f90c Mon Sep 17 00:00:00 2001 From: Karsten Schmidt Date: Sat, 1 Dec 2018 22:06:33 +0000 Subject: [PATCH] feat(geom): re-add arcLength() impls, update imports --- packages/geom2/src/api.ts | 9 ++++-- packages/geom2/src/circle.ts | 30 ++++++++++-------- packages/geom2/src/ellipse.ts | 34 +++++++++++++-------- packages/geom2/src/internal/arc-length.ts | 15 +++++++++ packages/geom2/src/line.ts | 19 +++++++----- packages/geom2/src/polygon.ts | 34 ++++++++++++--------- packages/geom2/src/polyline.ts | 6 ++++ packages/geom2/src/quad.ts | 2 ++ packages/geom2/src/rect.ts | 37 +++++++++++++---------- packages/geom2/src/triangle.ts | 2 ++ 10 files changed, 124 insertions(+), 64 deletions(-) create mode 100644 packages/geom2/src/internal/arc-length.ts diff --git a/packages/geom2/src/api.ts b/packages/geom2/src/api.ts index c0d6e1a4f7..cc30721665 100644 --- a/packages/geom2/src/api.ts +++ b/packages/geom2/src/api.ts @@ -7,6 +7,7 @@ import { import { DEFAULT, defmulti, + MultiFn1, MultiFn1O, MultiFn2O } from "@thi.ng/defmulti"; @@ -16,14 +17,14 @@ import { ReadonlyMat } from "@thi.ng/matrices/api"; import { add } from "@thi.ng/vectors3/add"; import { ReadonlyVec, Vec } from "@thi.ng/vectors3/api"; import { copy } from "@thi.ng/vectors3/copy"; +import { max } from "@thi.ng/vectors3/max"; +import { min } from "@thi.ng/vectors3/min"; import { mixN } from "@thi.ng/vectors3/mixn"; import { mul } from "@thi.ng/vectors3/mul"; -import { min } from "@thi.ng/vectors3/min"; -import { max } from "@thi.ng/vectors3/max"; import { neg } from "@thi.ng/vectors3/neg"; -import { sub } from "@thi.ng/vectors3/sub"; import { perpendicularLeft2 } from "@thi.ng/vectors3/perpendicular"; import { rotateZ } from "@thi.ng/vectors3/rotate"; +import { sub } from "@thi.ng/vectors3/sub"; import { subdivKernel3 } from "./internal/subdiv-curve"; import { warpPoints } from "./internal/warp"; @@ -209,6 +210,8 @@ export type VecPair = [Vec, Vec]; const dispatch = (x: IShape) => x.type; +export const arcLength: MultiFn1 = defmulti(dispatch); + export const area: MultiFn1O = defmulti(dispatch); area.add(DEFAULT, () => 0); diff --git a/packages/geom2/src/circle.ts b/packages/geom2/src/circle.ts index 7338c98c24..4639a7efdb 100644 --- a/packages/geom2/src/circle.ts +++ b/packages/geom2/src/circle.ts @@ -13,27 +13,28 @@ import { mulN2 } from "@thi.ng/vectors3/muln"; import { normalize } from "@thi.ng/vectors3/normalize"; import { sub2 } from "@thi.ng/vectors3/sub"; import { subN2 } from "@thi.ng/vectors3/subn"; -import { circumCenter } from "./internal/circumcenter"; -import "./polygon"; import { - perimeter, + arcLength, area, + Attribs, bounds, + center, centroid, Circle2, - Type, - Attribs, - Rect2, - vertices, + classifyPoint, + closestPoint, DEFAULT_SAMPLES, + perimeter, pointAt, pointInside, - classifyPoint, - closestPoint, - translate, - center, + Rect2, SamplingOpts, + translate, + Type, + vertices } from "./api"; +import { circumCenter } from "./internal/circumcenter"; +import "./polygon"; export function circle(pos: Vec, r = 1, attribs?: Attribs): Circle2 { return new Circle2(pos, r, attribs); @@ -56,8 +57,13 @@ implementations( null, + arcLength, + (circle: Circle2) => + TAU * circle.r, + area, - (circle: Circle2) => PI * circle.r * circle.r, + (circle: Circle2) => + PI * circle.r * circle.r, bounds, (circle: Circle2) => diff --git a/packages/geom2/src/ellipse.ts b/packages/geom2/src/ellipse.ts index 7a69538c08..8241f8e9a6 100644 --- a/packages/geom2/src/ellipse.ts +++ b/packages/geom2/src/ellipse.ts @@ -8,25 +8,26 @@ import { copy } from "@thi.ng/vectors3/copy"; import { madd2 } from "@thi.ng/vectors3/madd"; import { mulN2 } from "@thi.ng/vectors3/muln"; import { sub2 } from "@thi.ng/vectors3/sub"; -import "./polygon"; import { - perimeter, + arcLength, area, + asPolygon, + Attribs, bounds, + center, centroid, - Ellipse2, - Type, - Attribs, - Rect2, - vertices, - Polygon2, - asPolygon, DEFAULT_SAMPLES, + Ellipse2, + perimeter, pointAt, - center, - translate, + Polygon2, + Rect2, SamplingOpts, + translate, + Type, + vertices } from "./api"; +import "./polygon"; export function ellipse(pos: Vec, r = [1, 1], attribs?: Attribs): Ellipse2 { return new Ellipse2(pos, r, attribs); @@ -37,8 +38,17 @@ implementations( null, + arcLength, + (ellipse: Ellipse2) => { + const [a, b] = ellipse.r; + // Ramanujan approximation + // https://www.mathsisfun.com/geometry/ellipse-perimeter.html + return PI * ((3 * (a + b)) - Math.sqrt((3 * a + b) * (3 * b + a))); + }, + area, - (ellipse: Ellipse2) => PI * ellipse.r[0] * ellipse.r[1], + (ellipse: Ellipse2) => + PI * ellipse.r[0] * ellipse.r[1], asPolygon, (ellipse: Ellipse2, opts) => diff --git a/packages/geom2/src/internal/arc-length.ts b/packages/geom2/src/internal/arc-length.ts new file mode 100644 index 0000000000..a5536bf54e --- /dev/null +++ b/packages/geom2/src/internal/arc-length.ts @@ -0,0 +1,15 @@ +import { ReadonlyVec } from "@thi.ng/vectors3/api"; +import { dist } from "@thi.ng/vectors3/dist"; + +export const arcLength = (pts: ReadonlyVec[], closed = false) => { + const num = pts.length; + if (num < 2) return 0; + let res = 0; + let p = pts[0]; + let q = pts[1]; + for (let i = 1; i < num; i++ , p = q, q = pts[i]) { + res += dist(p, q); + } + closed && (res += dist(p, pts[0])); + return res; +}; diff --git a/packages/geom2/src/line.ts b/packages/geom2/src/line.ts index 285e6f4e34..588db06647 100644 --- a/packages/geom2/src/line.ts +++ b/packages/geom2/src/line.ts @@ -4,12 +4,8 @@ import { ReadonlyVec, Vec } from "@thi.ng/vectors3/api"; import { dist } from "@thi.ng/vectors3/dist"; import { mixN } from "@thi.ng/vectors3/mixn"; import { sub } from "@thi.ng/vectors3/sub"; -import { direction } from "./internal/direction"; -import { intersectLines2 } from "./internal/line-intersection"; -import { offsetLine } from "./internal/offset"; -import { transformPoints } from "./internal/transform"; -import "./polygon"; import { + arcLength, asCubic, asPolyline, Attribs, @@ -24,13 +20,18 @@ import { Polygon2, Polyline2, Rect2, + resample, tangentAt, transform, Type, VecPair, - vertices, - resample, + vertices } from "./api"; +import { direction } from "./internal/direction"; +import { intersectLines2 } from "./internal/line-intersection"; +import { offsetLine } from "./internal/offset"; +import { transformPoints } from "./internal/transform"; +import "./polygon"; export function line(a: Vec, b: Vec, attribs?: Attribs) { return new Line2([a, b], attribs); @@ -52,6 +53,10 @@ implementations( ], }, + arcLength, + (line: Line2) => + dist(line.a, line.b), + asCubic, (line: Line2) => [Cubic2.fromLine(line.a, line.b, { ...line.attribs })], diff --git a/packages/geom2/src/polygon.ts b/packages/geom2/src/polygon.ts index 318fbf54d1..010ed29586 100644 --- a/packages/geom2/src/polygon.ts +++ b/packages/geom2/src/polygon.ts @@ -16,20 +16,10 @@ import { add2 } from "@thi.ng/vectors3/add"; import { ReadonlyVec, Vec } from "@thi.ng/vectors3/api"; import { cartesian2 } from "@thi.ng/vectors3/cartesian"; import { signedArea2 } from "@thi.ng/vectors3/signed-area"; -import "./container2"; -import { centerOfWeight2 } from "./internal/centroid"; -import { edges as _edges } from "./internal/edges"; -import { booleanOp } from "./internal/greiner-hormann"; -import { offset as _offset } from "./internal/offset"; -import { perimeter as _perimeter } from "./internal/perimeter"; -import { pointInside as _pointInside, polygonArea } from "./internal/polygon"; -import { Sampler } from "./internal/sampler"; -import { subdivideCurve } from "./internal/subdiv-curve"; -import { sutherlandHodgeman } from "./internal/sutherland-hodgeman"; -import { transformPoints } from "./internal/transform"; -import { tessellatePoints } from "./tessellate"; import { + arcLength, area, + asPolygon, Attribs, bounds, centroid, @@ -59,10 +49,22 @@ import { translate, Type, union, - vertices, - asPolygon, + vertices } from "./api"; +import "./container2"; +import { centerOfWeight2 } from "./internal/centroid"; +import { edges as _edges } from "./internal/edges"; +import { booleanOp } from "./internal/greiner-hormann"; +import { offset as _offset } from "./internal/offset"; +import { perimeter as _perimeter } from "./internal/perimeter"; +import { pointInside as _pointInside, polygonArea } from "./internal/polygon"; +import { Sampler } from "./internal/sampler"; +import { subdivideCurve } from "./internal/subdiv-curve"; +import { sutherlandHodgeman } from "./internal/sutherland-hodgeman"; +import { transformPoints } from "./internal/transform"; +import { tessellatePoints } from "./tessellate"; import { douglasPeucker2 } from "./internal/douglas–peucker"; +import { arcLength as _arcLength } from "./internal/arc-length"; export function polygon(points: Vec[], attribs?: Attribs): Polygon2 { return new Polygon2(points, attribs); @@ -118,6 +120,10 @@ implementations( ] }, + arcLength, + (poly: Polygon2) => + _arcLength(poly.points, true), + area, (poly: Polygon2, signed = true) => { const area = polygonArea(poly.points); diff --git a/packages/geom2/src/polyline.ts b/packages/geom2/src/polyline.ts index 1b11933cc7..f18d2ebad1 100644 --- a/packages/geom2/src/polyline.ts +++ b/packages/geom2/src/polyline.ts @@ -5,6 +5,7 @@ import { map } from "@thi.ng/transducers/xform/map"; import { add2 } from "@thi.ng/vectors3/add"; import { ReadonlyVec, Vec } from "@thi.ng/vectors3/api"; import { + arcLength, asCubic, Attribs, bounds, @@ -30,6 +31,7 @@ import { vertices } from "./api"; import "./container2"; +import { arcLength as _arcLength } from "./internal/arc-length"; import { centroid as _centroid } from "./internal/centroid"; import { edges as _edges } from "./internal/edges"; import { offset as _offset } from "./internal/offset"; @@ -55,6 +57,10 @@ implementations( ], }, + arcLength, + (poly: Polygon2) => + _arcLength(poly.points), + asCubic, (line: Polyline2) => map((e) => Cubic2.fromLine(...e), _edges(line.points)), diff --git a/packages/geom2/src/quad.ts b/packages/geom2/src/quad.ts index f5f2705df1..8e34f977e7 100644 --- a/packages/geom2/src/quad.ts +++ b/packages/geom2/src/quad.ts @@ -4,6 +4,7 @@ import { add2 } from "@thi.ng/vectors3/add"; import { ReadonlyVec, Vec } from "@thi.ng/vectors3/api"; import { mixBilinear2 } from "@thi.ng/vectors3/mix-bilinear"; import { + arcLength, area, Attribs, bounds, @@ -39,6 +40,7 @@ implementations( flip, ], [Type.POLYGON2]: [ + arcLength, area, centroid, clipConvex, diff --git a/packages/geom2/src/rect.ts b/packages/geom2/src/rect.ts index 0809247408..f44b9b0b14 100644 --- a/packages/geom2/src/rect.ts +++ b/packages/geom2/src/rect.ts @@ -7,40 +7,41 @@ import { div2 } from "@thi.ng/vectors3/div"; import { madd2 } from "@thi.ng/vectors3/madd"; import { maddN2 } from "@thi.ng/vectors3/maddn"; import { sub } from "@thi.ng/vectors3/sub"; -import { unionBounds } from "./internal/bounds"; -import { edges as _edges } from "./internal/edges"; -import { booleanOp } from "./internal/greiner-hormann"; -import { Sampler } from "./internal/sampler"; -import { sutherlandHodgeman } from "./internal/sutherland-hodgeman"; -import { transformPoints } from "./internal/transform"; -import "./polygon"; -import { tessellatePoints } from "./tessellate"; import { + arcLength, area, Attribs, bounds, centroid, clipConvex, ClipMode, + edges, IShape, mapPoint, perimeter, + pointAt, + pointInside, Polygon2, Rect2, + resample, + SamplingOpts, tessellate, Tessellator, + transform, + translate, Type, union, unmapPoint, - vertices, - transform, - SamplingOpts, - edges, - translate, - resample, - pointAt, - pointInside, + vertices } from "./api"; +import { unionBounds } from "./internal/bounds"; +import { edges as _edges } from "./internal/edges"; +import { booleanOp } from "./internal/greiner-hormann"; +import { Sampler } from "./internal/sampler"; +import { sutherlandHodgeman } from "./internal/sutherland-hodgeman"; +import { transformPoints } from "./internal/transform"; +import "./polygon"; +import { tessellatePoints } from "./tessellate"; export function rect(pos: Vec, size: Vec, attribs?: Attribs) { return new Rect2(pos, size, attribs); @@ -58,6 +59,10 @@ implementations( ] }, + arcLength, + (rect: Rect2) => + 2 * (rect.size[0] * rect.size[1]), + area, (rect: Rect2) => rect.size[0] * rect.size[1], diff --git a/packages/geom2/src/triangle.ts b/packages/geom2/src/triangle.ts index f442c733d9..d48ea690c4 100644 --- a/packages/geom2/src/triangle.ts +++ b/packages/geom2/src/triangle.ts @@ -11,6 +11,7 @@ import { perpendicularLeft2 } from "@thi.ng/vectors3/perpendicular"; import { signedArea2 } from "@thi.ng/vectors3/signed-area"; import { sub } from "@thi.ng/vectors3/sub"; import { + arcLength, area, Attribs, bounds, @@ -50,6 +51,7 @@ implementations( bounds, ], [Type.POLYGON2]: [ + arcLength, clipConvex, edges, perimeter,