Socket
Socket
Sign inDemoInstall

@mathigon/euclid

Package Overview
Dependencies
Maintainers
1
Versions
48
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@mathigon/euclid - npm Package Compare versions

Comparing version 1.0.6 to 1.0.7

2

dist/angle.d.ts

@@ -32,2 +32,3 @@ import { Arc } from './arc';

at(): Point;
offset(): number;
contains(): boolean;

@@ -41,2 +42,3 @@ transform(m: TransformMatrix): Angle;

equals(_a: Angle): boolean;
toString(): string;
}

@@ -0,1 +1,2 @@

import { Circle } from './circle';
import { Line } from './line';

@@ -11,2 +12,3 @@ import { Point } from './point';

constructor(c: Point, start: Point, angle: number);
get circle(): Circle;
get radius(): number;

@@ -21,2 +23,3 @@ get end(): Point;

at(t: number): Point;
offset(p: Point): number;
contains(p: Point): boolean;

@@ -31,2 +34,3 @@ transform(m: TransformMatrix): this;

equals(): boolean;
toString(): string;
}

@@ -36,2 +40,3 @@ export declare class Sector extends Arc {

contains(p: Point): boolean;
toString(): string;
}

@@ -21,2 +21,3 @@ import { Arc } from './arc';

at(t: number): Point;
offset(p: Point): number;
contains(p: Point): boolean;

@@ -23,0 +24,0 @@ transform(m: TransformMatrix): Circle;

@@ -22,2 +22,3 @@ import { Line } from './line';

at(t: number): Point;
offset(p: Point): number;
contains(_p: Point): boolean;

@@ -31,2 +32,3 @@ transform(_m: TransformMatrix): this;

equals(): boolean;
toString(): string;
}

472

dist/index.cjs.js

@@ -41,2 +41,3 @@ var __defProp = Object.defineProperty;

Segment: () => Segment,
TWO_PI: () => TWO_PI,
Triangle: () => Triangle,

@@ -67,5 +68,11 @@ angleSize: () => angleSize,

// src/angle.ts
var import_fermat6 = require("@mathigon/fermat");
// src/arc.ts
var import_fermat5 = require("@mathigon/fermat");
// src/arc.ts
// src/circle.ts
var import_fermat4 = require("@mathigon/fermat");
// src/line.ts
var import_fermat3 = require("@mathigon/fermat");

@@ -84,2 +91,17 @@

}
function findClosest(p, items) {
let q = void 0;
let d = Infinity;
let index = -1;
for (const [i, e] of items.entries()) {
const q1 = e.project(p);
const d1 = Point.distance(p, q1);
if (d1 < d) {
q = q1;
d = d1;
index = i;
}
}
return q ? [q, index] : void 0;
}

@@ -236,3 +258,3 @@ // src/point.ts

toString() {
return `Point(x: ${this.x}, y: ${this.y})`;
return `point(${this.x},${this.y})`;
}

@@ -242,86 +264,3 @@ };

// src/arc.ts
var Arc = class {
constructor(c, start, angle) {
this.c = c;
this.start = start;
this.angle = angle;
this.type = "arc";
}
get radius() {
return Point.distance(this.c, this.start);
}
get end() {
return this.start.rotate(this.angle, this.c);
}
get startAngle() {
return rad(this.start, this.c);
}
contract(p) {
return new this.constructor(this.c, this.at(p / 2), this.angle * (1 - p));
}
get minor() {
if (this.angle <= Math.PI)
return this;
return new this.constructor(this.c, this.end, TWO_PI - this.angle);
}
get major() {
if (this.angle >= Math.PI)
return this;
return new this.constructor(this.c, this.end, TWO_PI - this.angle);
}
get center() {
return this.at(0.5);
}
project(p) {
const start = this.startAngle;
const end = start + this.angle;
let angle = rad(p, this.c);
if (end > TWO_PI && angle < end - TWO_PI)
angle += TWO_PI;
angle = (0, import_fermat3.clamp)(angle, start, end);
return this.c.shift(this.radius, 0).rotate(angle, this.c);
}
at(t) {
return this.start.rotate(this.angle * t, this.c);
}
contains(p) {
return p.equals(this.project(p));
}
transform(m) {
return new this.constructor(this.c.transform(m), this.start.transform(m), this.angle);
}
rotate(a, c = ORIGIN) {
if ((0, import_fermat3.nearlyEquals)(a, 0))
return this;
return new this.constructor(this.c.rotate(a, c), this.start.rotate(a, c), this.angle);
}
reflect(l) {
return new this.constructor(this.c.reflect(l), this.start.reflect(l), this.angle);
}
scale(sx, sy = sx) {
return new this.constructor(this.c.scale(sx, sy), this.start.scale(sx, sy), this.angle);
}
shift(x, y = x) {
return new this.constructor(this.c.shift(x, y), this.start.shift(x, y), this.angle);
}
translate(p) {
return this.shift(p.x, p.y);
}
equals() {
return false;
}
};
var Sector = class extends Arc {
constructor() {
super(...arguments);
this.type = "sector";
}
contains(p) {
return Point.distance(p, this.c) <= this.radius && new Angle(this.start, this.c, p).rad <= this.angle;
}
};
// src/line.ts
var import_fermat4 = require("@mathigon/fermat");
var Line = class {

@@ -386,3 +325,3 @@ constructor(p1, p2) {

const d = b.x * a.y - b.y * a.x;
return (0, import_fermat4.nearlyEquals)(d, 0, tolerance) ? 0 : Math.sign(d);
return (0, import_fermat3.nearlyEquals)(d, 0, tolerance) ? 0 : Math.sign(d);
}

@@ -399,3 +338,3 @@ contains(p, tolerance) {

rotate(a, c = ORIGIN) {
if ((0, import_fermat4.nearlyEquals)(a, 0))
if ((0, import_fermat3.nearlyEquals)(a, 0))
return this;

@@ -420,3 +359,3 @@ return new this.constructor(this.p1.rotate(a, c), this.p2.rotate(a, c));

toString() {
return `Line(p1: ${this.p1}, p2: ${this.p2})`;
return `line(${this.p1},${this.p2})`;
}

@@ -438,3 +377,3 @@ };

toString() {
return `Ray(p1: ${this.p1}, p2: ${this.p2})`;
return `ray(${this.p1},${this.p2})`;
}

@@ -452,6 +391,6 @@ };

return true;
if ((0, import_fermat4.nearlyEquals)(this.p1.x, this.p2.x, tolerance)) {
return (0, import_fermat4.isBetween)(p.y, this.p1.y, this.p2.y);
if ((0, import_fermat3.nearlyEquals)(this.p1.x, this.p2.x, tolerance)) {
return (0, import_fermat3.isBetween)(p.y, this.p1.y, this.p2.y);
} else {
return (0, import_fermat4.isBetween)(p.x, this.p1.x, this.p2.x);
return (0, import_fermat3.isBetween)(p.x, this.p1.x, this.p2.x);
}

@@ -465,3 +404,3 @@ }

const b = Point.difference(p, this.p1);
const q = (0, import_fermat4.clamp)(Point.dot(a, b) / this.lengthSquared, 0, 1);
const q = (0, import_fermat3.clamp)(Point.dot(a, b) / this.lengthSquared, 0, 1);
return Point.sum(this.p1, a.scale(q));

@@ -478,6 +417,171 @@ }

toString() {
return `Segment(p1: ${this.p1}, p2: ${this.p2})`;
return `segment(${this.p1},${this.p2})`;
}
};
// src/circle.ts
var Circle = class {
constructor(c = ORIGIN, r = 1) {
this.c = c;
this.r = r;
this.type = "circle";
}
get circumference() {
return TWO_PI * this.r;
}
get area() {
return Math.PI * this.r ** 2;
}
get arc() {
const start = this.c.shift(this.r, 0);
return new Arc(this.c, start, TWO_PI);
}
tangentAt(t) {
const p1 = this.at(t);
const p2 = this.c.rotate(Math.PI / 2, p1);
return new Line(p1, p2);
}
collision(r) {
const tX = this.c.x < r.p.x ? r.p.x : this.c.x > r.p.x + r.w ? r.p.x + r.w : this.c.x;
const tY = this.c.y < r.p.y ? r.p.y : this.c.y > r.p.y + r.h ? r.p.y + r.h : this.c.y;
const d = Point.distance(this.c, new Point(tX, tY));
return d <= this.r;
}
project(p) {
const proj = p.subtract(this.c).unitVector.scale(this.r);
return Point.sum(this.c, proj);
}
at(t) {
const a = TWO_PI * t;
return this.c.shift(this.r * Math.cos(a), this.r * Math.sin(a));
}
offset(p) {
return rad(p, this.c) / TWO_PI;
}
contains(p) {
return Point.distance(p, this.c) <= this.r;
}
transform(m) {
const scale = Math.abs(m[0][0]) + Math.abs(m[1][1]);
return new Circle(this.c.transform(m), this.r * scale / 2);
}
rotate(a, c = ORIGIN) {
if ((0, import_fermat4.nearlyEquals)(a, 0))
return this;
return new Circle(this.c.rotate(a, c), this.r);
}
reflect(l) {
return new Circle(this.c.reflect(l), this.r);
}
scale(sx, sy = sx) {
return new Circle(this.c.scale(sx, sy), this.r * (sx + sy) / 2);
}
shift(x, y = x) {
return new Circle(this.c.shift(x, y), this.r);
}
translate(p) {
return this.shift(p.x, p.y);
}
equals(other, tolerance) {
return (0, import_fermat4.nearlyEquals)(this.r, other.r, tolerance) && this.c.equals(other.c, tolerance);
}
toString() {
return `circle(${this.c},${this.r})`;
}
};
// src/arc.ts
var Arc = class {
constructor(c, start, angle) {
this.c = c;
this.start = start;
this.angle = angle;
this.type = "arc";
}
get circle() {
return new Circle(this.c, this.radius);
}
get radius() {
return Point.distance(this.c, this.start);
}
get end() {
return this.start.rotate(this.angle, this.c);
}
get startAngle() {
return rad(this.start, this.c);
}
contract(p) {
return new this.constructor(this.c, this.at(p / 2), this.angle * (1 - p));
}
get minor() {
if (this.angle <= Math.PI)
return this;
return new this.constructor(this.c, this.end, TWO_PI - this.angle);
}
get major() {
if (this.angle >= Math.PI)
return this;
return new this.constructor(this.c, this.end, TWO_PI - this.angle);
}
get center() {
return this.at(0.5);
}
project(p) {
const start = this.startAngle;
const end = start + this.angle;
let angle = rad(p, this.c);
if (end > TWO_PI && angle < end - TWO_PI)
angle += TWO_PI;
angle = (0, import_fermat5.clamp)(angle, start, end);
return this.c.shift(this.radius, 0).rotate(angle, this.c);
}
at(t) {
return this.start.rotate(this.angle * t, this.c);
}
offset(p) {
return new Angle(this.start, this.c, p).rad / this.angle;
}
contains(p) {
return p.equals(this.project(p));
}
transform(m) {
return new this.constructor(this.c.transform(m), this.start.transform(m), this.angle);
}
rotate(a, c = ORIGIN) {
if ((0, import_fermat5.nearlyEquals)(a, 0))
return this;
return new this.constructor(this.c.rotate(a, c), this.start.rotate(a, c), this.angle);
}
reflect(l) {
return new this.constructor(this.c.reflect(l), this.start.reflect(l), this.angle);
}
scale(sx, sy = sx) {
return new this.constructor(this.c.scale(sx, sy), this.start.scale(sx, sy), this.angle);
}
shift(x, y = x) {
return new this.constructor(this.c.shift(x, y), this.start.shift(x, y), this.angle);
}
translate(p) {
return this.shift(p.x, p.y);
}
equals() {
return false;
}
toString() {
return `arc(${this.c},${this.start},${this.angle})`;
}
};
var Sector = class extends Arc {
constructor() {
super(...arguments);
this.type = "sector";
}
contains(p) {
return Point.distance(p, this.c) <= this.radius && new Angle(this.start, this.c, p).rad <= this.angle;
}
toString() {
return `sector(${this.c},${this.start},${this.angle})`;
}
};
// src/angle.ts

@@ -519,3 +623,3 @@ var RAD_TO_DEG = 180 / Math.PI;

get isRight() {
return (0, import_fermat5.nearlyEquals)(this.rad, Math.PI / 2, Math.PI / 360);
return (0, import_fermat6.nearlyEquals)(this.rad, Math.PI / 2, Math.PI / 360);
}

@@ -548,2 +652,5 @@ get bisector() {

}
offset() {
return 0;
}
contains() {

@@ -556,3 +663,3 @@ return false;

rotate(a, c) {
if ((0, import_fermat5.nearlyEquals)(a, 0))
if ((0, import_fermat6.nearlyEquals)(a, 0))
return this;

@@ -576,2 +683,5 @@ return new Angle(this.a.rotate(a, c), this.b.rotate(a, c), this.c.rotate(a, c));

}
toString() {
return `angle(${this.a},${this.b},${this.c})`;
}
};

@@ -591,3 +701,3 @@

var import_core2 = require("@mathigon/core");
var import_fermat6 = require("@mathigon/fermat");
var import_fermat7 = require("@mathigon/fermat");
var PRECISION = 1e-6;

@@ -611,4 +721,4 @@ function pointAboveOrOnLine(pt, left, right) {

function pointsCompare(p1, p2) {
if ((0, import_fermat6.nearlyEquals)(p1.x, p2.x)) {
return (0, import_fermat6.nearlyEquals)(p1.y, p2.y) ? 0 : p1.y < p2.y ? -1 : 1;
if ((0, import_fermat7.nearlyEquals)(p1.x, p2.x)) {
return (0, import_fermat7.nearlyEquals)(p1.y, p2.y) ? 0 : p1.y < p2.y ? -1 : 1;
}

@@ -634,3 +744,3 @@ return p1.x < p2.x ? -1 : 1;

const axb = adx * bdy - ady * bdx;
if ((0, import_fermat6.nearlyEquals)(axb, 0))
if ((0, import_fermat7.nearlyEquals)(axb, 0))
return false;

@@ -1034,71 +1144,2 @@ const dx = a0.x - b0.x;

// src/circle.ts
var import_fermat7 = require("@mathigon/fermat");
var Circle = class {
constructor(c = ORIGIN, r = 1) {
this.c = c;
this.r = r;
this.type = "circle";
}
get circumference() {
return TWO_PI * this.r;
}
get area() {
return Math.PI * this.r ** 2;
}
get arc() {
const start = this.c.shift(this.r, 0);
return new Arc(this.c, start, TWO_PI);
}
tangentAt(t) {
const p1 = this.at(t);
const p2 = this.c.rotate(Math.PI / 2, p1);
return new Line(p1, p2);
}
collision(r) {
const tX = this.c.x < r.p.x ? r.p.x : this.c.x > r.p.x + r.w ? r.p.x + r.w : this.c.x;
const tY = this.c.y < r.p.y ? r.p.y : this.c.y > r.p.y + r.h ? r.p.y + r.h : this.c.y;
const d = Point.distance(this.c, new Point(tX, tY));
return d <= this.r;
}
project(p) {
const proj = p.subtract(this.c).unitVector.scale(this.r);
return Point.sum(this.c, proj);
}
at(t) {
const a = TWO_PI * t;
return this.c.shift(this.r * Math.cos(a), this.r * Math.sin(a));
}
contains(p) {
return Point.distance(p, this.c) <= this.r;
}
transform(m) {
const scale = Math.abs(m[0][0]) + Math.abs(m[1][1]);
return new Circle(this.c.transform(m), this.r * scale / 2);
}
rotate(a, c = ORIGIN) {
if ((0, import_fermat7.nearlyEquals)(a, 0))
return this;
return new Circle(this.c.rotate(a, c), this.r);
}
reflect(l) {
return new Circle(this.c.reflect(l), this.r);
}
scale(sx, sy = sx) {
return new Circle(this.c.scale(sx, sy), this.r * (sx + sy) / 2);
}
shift(x, y = x) {
return new Circle(this.c.shift(x, y), this.r);
}
translate(p) {
return this.shift(p.x, p.y);
}
equals(other, tolerance) {
return (0, import_fermat7.nearlyEquals)(this.r, other.r, tolerance) && this.c.equals(other.c, tolerance);
}
toString() {
return `Circle(c: ${this.c}, r: ${this.r})`;
}
};
// src/intersection.ts

@@ -1159,7 +1200,9 @@ var import_core3 = require("@mathigon/core");

function liesOnRay(r, p) {
if ((0, import_fermat8.nearlyEquals)(r.p1.x, r.p2.x)) {
if ((0, import_fermat8.nearlyEquals)(r.p1.x, r.p2.x))
return (p.y - r.p1.y) / (r.p2.y - r.p1.y) > 0;
}
return (p.x - r.p1.x) / (r.p2.x - r.p1.x) > 0;
}
function liesOnArc(a, p) {
return (0, import_fermat8.isBetween)(a.offset(p), 0, 1);
}
function lineLineIntersection(l1, l2) {

@@ -1217,17 +1260,20 @@ const d1x = l1.p1.x - l1.p2.x;

let results = [];
const a1 = isArc(a) ? a.circle : a;
const b1 = isArc(b) ? b.circle : b;
if (isLineLike(a) && isLineLike(b)) {
results = lineLineIntersection(a, b);
} else if (isLineLike(a) && isCircle(b)) {
results = lineCircleIntersection(a, b);
} else if (isCircle(a) && isLineLike(b)) {
results = lineCircleIntersection(b, a);
} else if (isCircle(a) && isCircle(b)) {
results = circleCircleIntersection(a, b);
} else if (isLineLike(a1) && isCircle(b1)) {
results = lineCircleIntersection(a1, b1);
} else if (isCircle(a1) && isLineLike(b1)) {
results = lineCircleIntersection(b1, a1);
} else if (isCircle(a1) && isCircle(b1)) {
results = circleCircleIntersection(a1, b1);
}
for (const x of [a, b]) {
if (x.type === "segment") {
if (isSegment(x))
results = results.filter((i) => liesOnSegment(x, i));
}
if (x.type === "ray")
if (isRay(x))
results = results.filter((i) => liesOnRay(x, i));
if (isArc(x))
results = results.filter((i) => liesOnArc(x, i));
}

@@ -1293,7 +1339,7 @@ return results;

get edges() {
const p = this.points;
const n = p.length;
const n = this.points.length;
const edges = [];
for (let i = 0; i < n; ++i)
edges.push(new Segment(p[i], p[(i + 1) % n]));
for (let i = 0; i < n; ++i) {
edges.push(new Segment(this.points[i], this.points[(i + 1) % n]));
}
return edges;

@@ -1391,17 +1437,27 @@ }

at(t) {
return Point.interpolateList([...this.points, this.points[0]], t);
}
project(p) {
let q = void 0;
let d = Infinity;
if (t < 0)
t += Math.floor(t);
const offset = t * this.circumference;
let cum = 0;
for (const e of this.edges) {
const q1 = e.project(p);
const d1 = Point.distance(p, q1);
if (d1 < d) {
q = q1;
d = d1;
}
const l = e.length;
if (cum + l > offset)
return e.at((offset - cum) / l);
cum += l;
}
return q || this.points[0];
return this.points[0];
}
offset(p) {
const edges = this.edges;
const proj = findClosest(p, this.edges) || [this.points[0], 0];
let offset = 0;
for (let i = 0; i < proj[1]; ++i)
offset += edges[i].length;
offset += edges[proj[1]].offset(p) * edges[proj[1]].length;
return offset / this.circumference;
}
project(p) {
const proj = findClosest(p, this.edges);
return proj ? proj[0] : this.points[0];
}
centerAt(on = ORIGIN) {

@@ -1447,2 +1503,5 @@ return this.translate(on.subtract(this.centroid));

}
toString() {
return `polygon(${this.points.join(",")})`;
}
};

@@ -1454,2 +1513,5 @@ var Polyline = class extends Polygon {

}
get circumference() {
return this.length;
}
get length() {

@@ -1469,2 +1531,5 @@ let length = 0;

}
toString() {
return `polyline(${this.points.join(",")})`;
}
};

@@ -1567,5 +1632,8 @@ var Triangle = class extends Polygon {

}
at(_t) {
return this.p;
at(t) {
return this.polygon.at(t);
}
offset(p) {
return this.polygon.offset(p);
}
transform(m) {

@@ -1595,3 +1663,3 @@ return this.polygon.transform(m);

toString() {
return `Rectangle(p: ${this.p}, w: ${this.w}, h: ${this.h})`;
return `rectangle(${this.p},${this.w},${this.h})`;
}

@@ -1863,2 +1931,5 @@ };

}
offset(p) {
return 0.5;
}
contains(_p) {

@@ -1888,4 +1959,7 @@ return false;

}
toString() {
return `ellipse(${this.c},${this.a},${this.b})`;
}
};
module.exports = __toCommonJS(src_exports);
//# sourceMappingURL=index.cjs.js.map

@@ -14,2 +14,2 @@ export * from './angle';

export * from './types';
export { GeoElement, GeoShape, rad, SimplePoint, TransformMatrix } from './utilities';
export { GeoElement, GeoShape, rad, SimplePoint, TransformMatrix, TWO_PI } from './utilities';
// src/angle.ts
import { nearlyEquals as nearlyEquals4 } from "@mathigon/fermat";
import { nearlyEquals as nearlyEquals5 } from "@mathigon/fermat";
// src/arc.ts
import { clamp as clamp2, nearlyEquals as nearlyEquals2 } from "@mathigon/fermat";
import { clamp as clamp3, nearlyEquals as nearlyEquals4 } from "@mathigon/fermat";
// src/circle.ts
import { nearlyEquals as nearlyEquals3 } from "@mathigon/fermat";
// src/line.ts
import { clamp as clamp2, isBetween, nearlyEquals as nearlyEquals2 } from "@mathigon/fermat";
// src/point.ts

@@ -18,2 +24,17 @@ import { total } from "@mathigon/core";

}
function findClosest(p, items) {
let q = void 0;
let d = Infinity;
let index = -1;
for (const [i, e] of items.entries()) {
const q1 = e.project(p);
const d1 = Point.distance(p, q1);
if (d1 < d) {
q = q1;
d = d1;
index = i;
}
}
return q ? [q, index] : void 0;
}

@@ -170,3 +191,3 @@ // src/point.ts

toString() {
return `Point(x: ${this.x}, y: ${this.y})`;
return `point(${this.x},${this.y})`;
}

@@ -176,86 +197,3 @@ };

// src/arc.ts
var Arc = class {
constructor(c, start, angle) {
this.c = c;
this.start = start;
this.angle = angle;
this.type = "arc";
}
get radius() {
return Point.distance(this.c, this.start);
}
get end() {
return this.start.rotate(this.angle, this.c);
}
get startAngle() {
return rad(this.start, this.c);
}
contract(p) {
return new this.constructor(this.c, this.at(p / 2), this.angle * (1 - p));
}
get minor() {
if (this.angle <= Math.PI)
return this;
return new this.constructor(this.c, this.end, TWO_PI - this.angle);
}
get major() {
if (this.angle >= Math.PI)
return this;
return new this.constructor(this.c, this.end, TWO_PI - this.angle);
}
get center() {
return this.at(0.5);
}
project(p) {
const start = this.startAngle;
const end = start + this.angle;
let angle = rad(p, this.c);
if (end > TWO_PI && angle < end - TWO_PI)
angle += TWO_PI;
angle = clamp2(angle, start, end);
return this.c.shift(this.radius, 0).rotate(angle, this.c);
}
at(t) {
return this.start.rotate(this.angle * t, this.c);
}
contains(p) {
return p.equals(this.project(p));
}
transform(m) {
return new this.constructor(this.c.transform(m), this.start.transform(m), this.angle);
}
rotate(a, c = ORIGIN) {
if (nearlyEquals2(a, 0))
return this;
return new this.constructor(this.c.rotate(a, c), this.start.rotate(a, c), this.angle);
}
reflect(l) {
return new this.constructor(this.c.reflect(l), this.start.reflect(l), this.angle);
}
scale(sx, sy = sx) {
return new this.constructor(this.c.scale(sx, sy), this.start.scale(sx, sy), this.angle);
}
shift(x, y = x) {
return new this.constructor(this.c.shift(x, y), this.start.shift(x, y), this.angle);
}
translate(p) {
return this.shift(p.x, p.y);
}
equals() {
return false;
}
};
var Sector = class extends Arc {
constructor() {
super(...arguments);
this.type = "sector";
}
contains(p) {
return Point.distance(p, this.c) <= this.radius && new Angle(this.start, this.c, p).rad <= this.angle;
}
};
// src/line.ts
import { clamp as clamp3, isBetween, nearlyEquals as nearlyEquals3 } from "@mathigon/fermat";
var Line = class {

@@ -320,3 +258,3 @@ constructor(p1, p2) {

const d = b.x * a.y - b.y * a.x;
return nearlyEquals3(d, 0, tolerance) ? 0 : Math.sign(d);
return nearlyEquals2(d, 0, tolerance) ? 0 : Math.sign(d);
}

@@ -333,3 +271,3 @@ contains(p, tolerance) {

rotate(a, c = ORIGIN) {
if (nearlyEquals3(a, 0))
if (nearlyEquals2(a, 0))
return this;

@@ -354,3 +292,3 @@ return new this.constructor(this.p1.rotate(a, c), this.p2.rotate(a, c));

toString() {
return `Line(p1: ${this.p1}, p2: ${this.p2})`;
return `line(${this.p1},${this.p2})`;
}

@@ -372,3 +310,3 @@ };

toString() {
return `Ray(p1: ${this.p1}, p2: ${this.p2})`;
return `ray(${this.p1},${this.p2})`;
}

@@ -386,3 +324,3 @@ };

return true;
if (nearlyEquals3(this.p1.x, this.p2.x, tolerance)) {
if (nearlyEquals2(this.p1.x, this.p2.x, tolerance)) {
return isBetween(p.y, this.p1.y, this.p2.y);

@@ -399,3 +337,3 @@ } else {

const b = Point.difference(p, this.p1);
const q = clamp3(Point.dot(a, b) / this.lengthSquared, 0, 1);
const q = clamp2(Point.dot(a, b) / this.lengthSquared, 0, 1);
return Point.sum(this.p1, a.scale(q));

@@ -412,6 +350,171 @@ }

toString() {
return `Segment(p1: ${this.p1}, p2: ${this.p2})`;
return `segment(${this.p1},${this.p2})`;
}
};
// src/circle.ts
var Circle = class {
constructor(c = ORIGIN, r = 1) {
this.c = c;
this.r = r;
this.type = "circle";
}
get circumference() {
return TWO_PI * this.r;
}
get area() {
return Math.PI * this.r ** 2;
}
get arc() {
const start = this.c.shift(this.r, 0);
return new Arc(this.c, start, TWO_PI);
}
tangentAt(t) {
const p1 = this.at(t);
const p2 = this.c.rotate(Math.PI / 2, p1);
return new Line(p1, p2);
}
collision(r) {
const tX = this.c.x < r.p.x ? r.p.x : this.c.x > r.p.x + r.w ? r.p.x + r.w : this.c.x;
const tY = this.c.y < r.p.y ? r.p.y : this.c.y > r.p.y + r.h ? r.p.y + r.h : this.c.y;
const d = Point.distance(this.c, new Point(tX, tY));
return d <= this.r;
}
project(p) {
const proj = p.subtract(this.c).unitVector.scale(this.r);
return Point.sum(this.c, proj);
}
at(t) {
const a = TWO_PI * t;
return this.c.shift(this.r * Math.cos(a), this.r * Math.sin(a));
}
offset(p) {
return rad(p, this.c) / TWO_PI;
}
contains(p) {
return Point.distance(p, this.c) <= this.r;
}
transform(m) {
const scale = Math.abs(m[0][0]) + Math.abs(m[1][1]);
return new Circle(this.c.transform(m), this.r * scale / 2);
}
rotate(a, c = ORIGIN) {
if (nearlyEquals3(a, 0))
return this;
return new Circle(this.c.rotate(a, c), this.r);
}
reflect(l) {
return new Circle(this.c.reflect(l), this.r);
}
scale(sx, sy = sx) {
return new Circle(this.c.scale(sx, sy), this.r * (sx + sy) / 2);
}
shift(x, y = x) {
return new Circle(this.c.shift(x, y), this.r);
}
translate(p) {
return this.shift(p.x, p.y);
}
equals(other, tolerance) {
return nearlyEquals3(this.r, other.r, tolerance) && this.c.equals(other.c, tolerance);
}
toString() {
return `circle(${this.c},${this.r})`;
}
};
// src/arc.ts
var Arc = class {
constructor(c, start, angle) {
this.c = c;
this.start = start;
this.angle = angle;
this.type = "arc";
}
get circle() {
return new Circle(this.c, this.radius);
}
get radius() {
return Point.distance(this.c, this.start);
}
get end() {
return this.start.rotate(this.angle, this.c);
}
get startAngle() {
return rad(this.start, this.c);
}
contract(p) {
return new this.constructor(this.c, this.at(p / 2), this.angle * (1 - p));
}
get minor() {
if (this.angle <= Math.PI)
return this;
return new this.constructor(this.c, this.end, TWO_PI - this.angle);
}
get major() {
if (this.angle >= Math.PI)
return this;
return new this.constructor(this.c, this.end, TWO_PI - this.angle);
}
get center() {
return this.at(0.5);
}
project(p) {
const start = this.startAngle;
const end = start + this.angle;
let angle = rad(p, this.c);
if (end > TWO_PI && angle < end - TWO_PI)
angle += TWO_PI;
angle = clamp3(angle, start, end);
return this.c.shift(this.radius, 0).rotate(angle, this.c);
}
at(t) {
return this.start.rotate(this.angle * t, this.c);
}
offset(p) {
return new Angle(this.start, this.c, p).rad / this.angle;
}
contains(p) {
return p.equals(this.project(p));
}
transform(m) {
return new this.constructor(this.c.transform(m), this.start.transform(m), this.angle);
}
rotate(a, c = ORIGIN) {
if (nearlyEquals4(a, 0))
return this;
return new this.constructor(this.c.rotate(a, c), this.start.rotate(a, c), this.angle);
}
reflect(l) {
return new this.constructor(this.c.reflect(l), this.start.reflect(l), this.angle);
}
scale(sx, sy = sx) {
return new this.constructor(this.c.scale(sx, sy), this.start.scale(sx, sy), this.angle);
}
shift(x, y = x) {
return new this.constructor(this.c.shift(x, y), this.start.shift(x, y), this.angle);
}
translate(p) {
return this.shift(p.x, p.y);
}
equals() {
return false;
}
toString() {
return `arc(${this.c},${this.start},${this.angle})`;
}
};
var Sector = class extends Arc {
constructor() {
super(...arguments);
this.type = "sector";
}
contains(p) {
return Point.distance(p, this.c) <= this.radius && new Angle(this.start, this.c, p).rad <= this.angle;
}
toString() {
return `sector(${this.c},${this.start},${this.angle})`;
}
};
// src/angle.ts

@@ -453,3 +556,3 @@ var RAD_TO_DEG = 180 / Math.PI;

get isRight() {
return nearlyEquals4(this.rad, Math.PI / 2, Math.PI / 360);
return nearlyEquals5(this.rad, Math.PI / 2, Math.PI / 360);
}

@@ -482,2 +585,5 @@ get bisector() {

}
offset() {
return 0;
}
contains() {

@@ -490,3 +596,3 @@ return false;

rotate(a, c) {
if (nearlyEquals4(a, 0))
if (nearlyEquals5(a, 0))
return this;

@@ -510,2 +616,5 @@ return new Angle(this.a.rotate(a, c), this.b.rotate(a, c), this.c.rotate(a, c));

}
toString() {
return `angle(${this.a},${this.b},${this.c})`;
}
};

@@ -525,3 +634,3 @@

import { last } from "@mathigon/core";
import { nearlyEquals as nearlyEquals5 } from "@mathigon/fermat";
import { nearlyEquals as nearlyEquals6 } from "@mathigon/fermat";
var PRECISION = 1e-6;

@@ -545,4 +654,4 @@ function pointAboveOrOnLine(pt, left, right) {

function pointsCompare(p1, p2) {
if (nearlyEquals5(p1.x, p2.x)) {
return nearlyEquals5(p1.y, p2.y) ? 0 : p1.y < p2.y ? -1 : 1;
if (nearlyEquals6(p1.x, p2.x)) {
return nearlyEquals6(p1.y, p2.y) ? 0 : p1.y < p2.y ? -1 : 1;
}

@@ -568,3 +677,3 @@ return p1.x < p2.x ? -1 : 1;

const axb = adx * bdy - ady * bdx;
if (nearlyEquals5(axb, 0))
if (nearlyEquals6(axb, 0))
return false;

@@ -968,71 +1077,2 @@ const dx = a0.x - b0.x;

// src/circle.ts
import { nearlyEquals as nearlyEquals6 } from "@mathigon/fermat";
var Circle = class {
constructor(c = ORIGIN, r = 1) {
this.c = c;
this.r = r;
this.type = "circle";
}
get circumference() {
return TWO_PI * this.r;
}
get area() {
return Math.PI * this.r ** 2;
}
get arc() {
const start = this.c.shift(this.r, 0);
return new Arc(this.c, start, TWO_PI);
}
tangentAt(t) {
const p1 = this.at(t);
const p2 = this.c.rotate(Math.PI / 2, p1);
return new Line(p1, p2);
}
collision(r) {
const tX = this.c.x < r.p.x ? r.p.x : this.c.x > r.p.x + r.w ? r.p.x + r.w : this.c.x;
const tY = this.c.y < r.p.y ? r.p.y : this.c.y > r.p.y + r.h ? r.p.y + r.h : this.c.y;
const d = Point.distance(this.c, new Point(tX, tY));
return d <= this.r;
}
project(p) {
const proj = p.subtract(this.c).unitVector.scale(this.r);
return Point.sum(this.c, proj);
}
at(t) {
const a = TWO_PI * t;
return this.c.shift(this.r * Math.cos(a), this.r * Math.sin(a));
}
contains(p) {
return Point.distance(p, this.c) <= this.r;
}
transform(m) {
const scale = Math.abs(m[0][0]) + Math.abs(m[1][1]);
return new Circle(this.c.transform(m), this.r * scale / 2);
}
rotate(a, c = ORIGIN) {
if (nearlyEquals6(a, 0))
return this;
return new Circle(this.c.rotate(a, c), this.r);
}
reflect(l) {
return new Circle(this.c.reflect(l), this.r);
}
scale(sx, sy = sx) {
return new Circle(this.c.scale(sx, sy), this.r * (sx + sy) / 2);
}
shift(x, y = x) {
return new Circle(this.c.shift(x, y), this.r);
}
translate(p) {
return this.shift(p.x, p.y);
}
equals(other, tolerance) {
return nearlyEquals6(this.r, other.r, tolerance) && this.c.equals(other.c, tolerance);
}
toString() {
return `Circle(c: ${this.c}, r: ${this.r})`;
}
};
// src/intersection.ts

@@ -1093,7 +1133,9 @@ import { flatten } from "@mathigon/core";

function liesOnRay(r, p) {
if (nearlyEquals7(r.p1.x, r.p2.x)) {
if (nearlyEquals7(r.p1.x, r.p2.x))
return (p.y - r.p1.y) / (r.p2.y - r.p1.y) > 0;
}
return (p.x - r.p1.x) / (r.p2.x - r.p1.x) > 0;
}
function liesOnArc(a, p) {
return isBetween2(a.offset(p), 0, 1);
}
function lineLineIntersection(l1, l2) {

@@ -1151,17 +1193,20 @@ const d1x = l1.p1.x - l1.p2.x;

let results = [];
const a1 = isArc(a) ? a.circle : a;
const b1 = isArc(b) ? b.circle : b;
if (isLineLike(a) && isLineLike(b)) {
results = lineLineIntersection(a, b);
} else if (isLineLike(a) && isCircle(b)) {
results = lineCircleIntersection(a, b);
} else if (isCircle(a) && isLineLike(b)) {
results = lineCircleIntersection(b, a);
} else if (isCircle(a) && isCircle(b)) {
results = circleCircleIntersection(a, b);
} else if (isLineLike(a1) && isCircle(b1)) {
results = lineCircleIntersection(a1, b1);
} else if (isCircle(a1) && isLineLike(b1)) {
results = lineCircleIntersection(b1, a1);
} else if (isCircle(a1) && isCircle(b1)) {
results = circleCircleIntersection(a1, b1);
}
for (const x of [a, b]) {
if (x.type === "segment") {
if (isSegment(x))
results = results.filter((i) => liesOnSegment(x, i));
}
if (x.type === "ray")
if (isRay(x))
results = results.filter((i) => liesOnRay(x, i));
if (isArc(x))
results = results.filter((i) => liesOnArc(x, i));
}

@@ -1227,7 +1272,7 @@ return results;

get edges() {
const p = this.points;
const n = p.length;
const n = this.points.length;
const edges = [];
for (let i = 0; i < n; ++i)
edges.push(new Segment(p[i], p[(i + 1) % n]));
for (let i = 0; i < n; ++i) {
edges.push(new Segment(this.points[i], this.points[(i + 1) % n]));
}
return edges;

@@ -1325,17 +1370,27 @@ }

at(t) {
return Point.interpolateList([...this.points, this.points[0]], t);
}
project(p) {
let q = void 0;
let d = Infinity;
if (t < 0)
t += Math.floor(t);
const offset = t * this.circumference;
let cum = 0;
for (const e of this.edges) {
const q1 = e.project(p);
const d1 = Point.distance(p, q1);
if (d1 < d) {
q = q1;
d = d1;
}
const l = e.length;
if (cum + l > offset)
return e.at((offset - cum) / l);
cum += l;
}
return q || this.points[0];
return this.points[0];
}
offset(p) {
const edges = this.edges;
const proj = findClosest(p, this.edges) || [this.points[0], 0];
let offset = 0;
for (let i = 0; i < proj[1]; ++i)
offset += edges[i].length;
offset += edges[proj[1]].offset(p) * edges[proj[1]].length;
return offset / this.circumference;
}
project(p) {
const proj = findClosest(p, this.edges);
return proj ? proj[0] : this.points[0];
}
centerAt(on = ORIGIN) {

@@ -1381,2 +1436,5 @@ return this.translate(on.subtract(this.centroid));

}
toString() {
return `polygon(${this.points.join(",")})`;
}
};

@@ -1388,2 +1446,5 @@ var Polyline = class extends Polygon {

}
get circumference() {
return this.length;
}
get length() {

@@ -1403,2 +1464,5 @@ let length = 0;

}
toString() {
return `polyline(${this.points.join(",")})`;
}
};

@@ -1501,5 +1565,8 @@ var Triangle = class extends Polygon {

}
at(_t) {
return this.p;
at(t) {
return this.polygon.at(t);
}
offset(p) {
return this.polygon.offset(p);
}
transform(m) {

@@ -1529,3 +1596,3 @@ return this.polygon.transform(m);

toString() {
return `Rectangle(p: ${this.p}, w: ${this.w}, h: ${this.h})`;
return `rectangle(${this.p},${this.w},${this.h})`;
}

@@ -1797,2 +1864,5 @@ };

}
offset(p) {
return 0.5;
}
contains(_p) {

@@ -1822,2 +1892,5 @@ return false;

}
toString() {
return `ellipse(${this.c},${this.a},${this.b})`;
}
};

@@ -1839,2 +1912,3 @@ export {

Segment,
TWO_PI,
Triangle,

@@ -1841,0 +1915,0 @@ angleSize,

@@ -38,2 +38,3 @@ import { Circle } from './circle';

at(t: number): Point;
offset(p: Point): number;
project(p: Point): Point;

@@ -50,2 +51,3 @@ /** Center this polygon on a given point or the origin */

equals(other: Polygon, tolerance?: number, oriented?: boolean): boolean;
toString(): string;
}

@@ -55,5 +57,7 @@ /** A polyline defined by its vertex points. */

readonly type = "polyline";
get circumference(): number;
get length(): number;
/** @returns {Segment[]} */
get edges(): Segment[];
toString(): string;
}

@@ -60,0 +64,0 @@ /** A triangle defined by its three vertices. */

@@ -28,6 +28,7 @@ import { Line } from './line';

project(p: SimplePoint): Point;
at(_t: number): Point;
at(t: number): Point;
offset(p: Point): number;
transform(m: TransformMatrix): Polygon;
/** Rotates this rectangle by a given angle (in radians), optionally around point `c`. */
rotate(a: number, c?: Point): this | Polygon;
rotate(a: number, c?: Point): Polygon | this;
reflect(l: Line): Polygon;

@@ -34,0 +35,0 @@ scale(sx: number, sy?: number): Rectangle;

@@ -17,2 +17,3 @@ import { Line } from './line';

equals(other: GeoElement, tolerance?: number, oriented?: boolean): boolean;
toString(): string;
}

@@ -23,2 +24,3 @@ export interface GeoShape extends GeoElement {

at(t: number): Point;
offset(p: Point): number;
rotate(angle: number, center?: SimplePoint): GeoShape;

@@ -32,1 +34,2 @@ reflect(l: Line): GeoShape;

export declare function rad(p: SimplePoint, c?: SimplePoint): number;
export declare function findClosest(p: Point, items: GeoShape[]): [Point, number] | undefined;
{
"name": "@mathigon/euclid",
"version": "1.0.6",
"version": "1.0.7",
"license": "MIT",

@@ -31,3 +31,3 @@ "homepage": "https://mathigon.io/euclid",

"dependencies": {
"@mathigon/core": "1.0.6",
"@mathigon/core": "1.0.7",
"@mathigon/fermat": "1.0.7"

@@ -34,0 +34,0 @@ },

@@ -103,2 +103,6 @@ // =============================================================================

offset() {
return 0;
}
contains() {

@@ -139,2 +143,6 @@ return false;

}
toString() {
return `angle(${this.a},${this.b},${this.c})`;
}
}

@@ -9,2 +9,3 @@ // =============================================================================

import {Angle} from './angle';
import {Circle} from './circle';
import {Line} from './line';

@@ -23,2 +24,6 @@ import {ORIGIN, Point} from './point';

get circle() {
return new Circle(this.c, this.radius);
}
get radius() {

@@ -71,2 +76,6 @@ return Point.distance(this.c, this.start);

offset(p: Point) {
return new Angle(this.start, this.c, p).rad / this.angle;
}
contains(p: Point) {

@@ -114,2 +123,6 @@ // TODO Is there a better way to do this?

}
toString() {
return `arc(${this.c},${this.start},${this.angle})`;
}
}

@@ -123,2 +136,6 @@

}
toString() {
return `sector(${this.c},${this.start},${this.angle})`;
}
}

@@ -12,3 +12,3 @@ // =============================================================================

import {Rectangle} from './rectangle';
import {GeoShape, TransformMatrix, TWO_PI} from './utilities';
import {GeoShape, rad, TransformMatrix, TWO_PI} from './utilities';

@@ -63,2 +63,6 @@

offset(p: Point) {
return rad(p, this.c) / TWO_PI;
}
contains(p: Point) {

@@ -101,4 +105,4 @@ return Point.distance(p, this.c) <= this.r;

toString() {
return `Circle(c: ${this.c}, r: ${this.r})`;
return `circle(${this.c},${this.r})`;
}
}

@@ -73,2 +73,7 @@ // =============================================================================

offset(p: Point) {
// TODO Implement
return 0.5;
}
contains(_p: Point) {

@@ -115,2 +120,6 @@ // TODO Implement

}
toString() {
return `ellipse(${this.c},${this.a},${this.b})`;
}
}

@@ -20,2 +20,2 @@ // =============================================================================

export * from './types';
export {GeoElement, GeoShape, rad, SimplePoint, TransformMatrix} from './utilities';
export {GeoElement, GeoShape, rad, SimplePoint, TransformMatrix, TWO_PI} from './utilities';

@@ -9,9 +9,13 @@ // =============================================================================

import {isBetween, nearlyEquals, square, subsets} from '@mathigon/fermat';
import {Arc} from './arc';
import {Circle} from './circle';
import {Line, Ray, Segment} from './line';
import {Point} from './point';
import {isCircle, isLineLike, isPolygonLike} from './types';
import {isArc, isCircle, isLineLike, isPolygonLike, isRay, isSegment} from './types';
import {GeoShape} from './utilities';
// -----------------------------------------------------------------------------
// Helper functions
function liesOnSegment(s: Segment, p: Point) {

@@ -23,8 +27,14 @@ if (nearlyEquals(s.p1.x, s.p2.x)) return isBetween(p.y, s.p1.y, s.p2.y);

function liesOnRay(r: Ray, p: Point) {
if (nearlyEquals(r.p1.x, r.p2.x)) {
return (p.y - r.p1.y) / (r.p2.y - r.p1.y) > 0;
}
if (nearlyEquals(r.p1.x, r.p2.x)) return (p.y - r.p1.y) / (r.p2.y - r.p1.y) > 0;
return (p.x - r.p1.x) / (r.p2.x - r.p1.x) > 0;
}
function liesOnArc(a: Arc, p: Point) {
return isBetween(a.offset(p), 0, 1);
}
// -----------------------------------------------------------------------------
// Foundations
function lineLineIntersection(l1: Line, l2: Line) {

@@ -96,22 +106,26 @@ const d1x = l1.p1.x - l1.p2.x;

/** Finds the intersection of two lines or circles. */
function simpleIntersection(a: Line|Circle, b: Line|Circle): Point[] {
// -----------------------------------------------------------------------------
// Exported functions
function simpleIntersection(a: Line|Circle|Arc, b: Line|Circle|Arc): Point[] {
let results: Point[] = [];
// TODO Handle Arcs and Rays
const a1 = isArc(a) ? a.circle : a;
const b1 = isArc(b) ? b.circle : b;
if (isLineLike(a) && isLineLike(b)) {
results = lineLineIntersection(a, b);
} else if (isLineLike(a) && isCircle(b)) {
results = lineCircleIntersection(a, b);
} else if (isCircle(a) && isLineLike(b)) {
results = lineCircleIntersection(b, a);
} else if (isCircle(a) && isCircle(b)) {
results = circleCircleIntersection(a, b);
} else if (isLineLike(a1) && isCircle(b1)) {
results = lineCircleIntersection(a1, b1);
} else if (isCircle(a1) && isLineLike(b1)) {
results = lineCircleIntersection(b1, a1);
} else if (isCircle(a1) && isCircle(b1)) {
results = circleCircleIntersection(a1, b1);
}
for (const x of [a, b]) {
if (x.type === 'segment') {
results = results.filter(i => liesOnSegment(x as Segment, i));
}
if (x.type === 'ray') results = results.filter(i => liesOnRay(x as Ray, i));
if (isSegment(x)) results = results.filter(i => liesOnSegment(x, i));
if (isRay(x)) results = results.filter(i => liesOnRay(x, i));
if (isArc(x)) results = results.filter(i => liesOnArc(x, i));
}

@@ -143,3 +157,3 @@

// TODO Handle arcs, sectors and angles!
return simpleIntersection(a as (Line|Circle), b as (Line|Circle));
return simpleIntersection(a as (Line|Circle|Arc), b as (Line|Circle|Arc));
}

@@ -154,3 +154,3 @@ // =============================================================================

toString() {
return `Line(p1: ${this.p1}, p2: ${this.p2})`;
return `line(${this.p1},${this.p2})`;
}

@@ -174,3 +174,3 @@ }

toString() {
return `Ray(p1: ${this.p1}, p2: ${this.p2})`;
return `ray(${this.p1},${this.p2})`;
}

@@ -219,4 +219,4 @@ }

toString() {
return `Segment(p1: ${this.p1}, p2: ${this.p2})`;
return `segment(${this.p1},${this.p2})`;
}
}

@@ -219,3 +219,3 @@ // =============================================================================

toString() {
return `Point(x: ${this.x}, y: ${this.y})`;
return `point(${this.x},${this.y})`;
}

@@ -222,0 +222,0 @@ }

@@ -14,3 +14,3 @@ // =============================================================================

import {ORIGIN, Point} from './point';
import {GeoShape, TransformMatrix, TWO_PI} from './utilities';
import {findClosest, GeoShape, TransformMatrix, TWO_PI} from './utilities';

@@ -70,7 +70,7 @@

get edges() {
const p = this.points;
const n = p.length;
const n = this.points.length;
const edges = [];
for (let i = 0; i < n; ++i) edges.push(new Segment(p[i], p[(i + 1) % n]));
for (let i = 0; i < n; ++i) {
edges.push(new Segment(this.points[i], this.points[(i + 1) % n]));
}
return edges;

@@ -199,21 +199,29 @@ }

at(t: number) {
return Point.interpolateList([...this.points, this.points[0]], t);
if (t < 0) t += Math.floor(t);
const offset = t * this.circumference;
let cum = 0;
for (const e of this.edges) {
const l = e.length;
if (cum + l > offset) return e.at((offset - cum) / l);
cum += l;
}
return this.points[0];
}
project(p: Point) {
let q: Point|undefined = undefined;
let d = Infinity;
offset(p: Point) {
const edges = this.edges;
const proj = findClosest(p, this.edges) || [this.points[0], 0] as const;
for (const e of this.edges) {
const q1 = e.project(p);
const d1 = Point.distance(p, q1);
if (d1 < d) {
q = q1;
d = d1;
}
}
let offset = 0;
for (let i = 0; i < proj[1]; ++i) offset += edges[i].length;
offset += edges[proj[1]].offset(p) * edges[proj[1]].length;
return q || this.points[0];
return offset / this.circumference;
}
project(p: Point) {
const proj = findClosest(p, this.edges);
return proj ? proj[0] : this.points[0];
}
/** Center this polygon on a given point or the origin */

@@ -271,2 +279,6 @@ centerAt(on = ORIGIN) {

}
toString() {
return `polygon(${this.points.join(',')})`;
}
}

@@ -279,2 +291,6 @@

get circumference() {
return this.length;
}
get length() {

@@ -296,2 +312,6 @@ let length = 0;

}
toString() {
return `polyline(${this.points.join(',')})`;
}
}

@@ -298,0 +318,0 @@

@@ -98,7 +98,10 @@ // =============================================================================

at(_t: number) {
// TODO Implement
return this.p;
at(t: number) {
return this.polygon.at(t);
}
offset(p: Point) {
return this.polygon.offset(p);
}
// ---------------------------------------------------------------------------

@@ -138,4 +141,4 @@

toString() {
return `Rectangle(p: ${this.p}, w: ${this.w}, h: ${this.h})`;
return `rectangle(${this.p},${this.w},${this.h})`;
}
}

@@ -25,2 +25,3 @@ // =============================================================================

equals(other: GeoElement, tolerance?: number, oriented?: boolean): boolean;
toString(): string;
}

@@ -32,2 +33,3 @@

at(t: number): Point;
offset(p: Point): number;

@@ -47,1 +49,20 @@ rotate(angle: number, center?: SimplePoint): GeoShape;

}
// TODO Merge this with findMin() in @mathigon/core
export function findClosest(p: Point, items: GeoShape[]): [Point, number]|undefined {
let q: Point|undefined = undefined;
let d = Infinity;
let index = -1;
for (const [i, e] of items.entries()) {
const q1 = e.project(p);
const d1 = Point.distance(p, q1);
if (d1 < d) {
q = q1;
d = d1;
index = i;
}
}
return q ? [q, index] : undefined;
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc