Skip to content

Commit

Permalink
refactor(geom): remove obsolete/extracted internal ops, update publics
Browse files Browse the repository at this point in the history
  • Loading branch information
postspectacular committed Jan 23, 2019
1 parent cb2429c commit fb532b8
Show file tree
Hide file tree
Showing 59 changed files with 193 additions and 1,942 deletions.
9 changes: 9 additions & 0 deletions packages/geom/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,11 @@
"@thi.ng/geom-clip-convex": "^0.0.1",
"@thi.ng/geom-closest-point": "^0.0.1",
"@thi.ng/geom-isec": "^0.0.1",
"@thi.ng/geom-poly-utils": "^0.0.1",
"@thi.ng/geom-resample": "^0.0.1",
"@thi.ng/geom-splines": "^0.0.1",
"@thi.ng/geom-subdiv-curve": "^0.0.1",
"@thi.ng/geom-tessellate": "^0.0.1",
"@thi.ng/hiccup": "^3.0.1",
"@thi.ng/hiccup-svg": "^3.1.0",
"@thi.ng/math": "^1.0.1",
Expand All @@ -53,7 +56,13 @@
"@thi.ng/vectors": "^2.1.0"
},
"keywords": [
"2D",
"ES6",
"conversion",
"intersection",
"geometry",
"shapes",
"SVG",
"typescript"
],
"publishConfig": {
Expand Down
104 changes: 10 additions & 94 deletions packages/geom/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,15 @@ import { ICopy, IObjectOf, IToHiccup } from "@thi.ng/api";
import { isNumber } from "@thi.ng/checks";
import { equiv } from "@thi.ng/equiv";
import { illegalState } from "@thi.ng/errors";
import { pointAt as arcPointAt, pointAtTheta as arcPointAtTheta } from "@thi.ng/geom-arc";
import {
add2,
add3,
copyVectors,
maddN2,
ReadonlyVec,
set,
Vec
} from "@thi.ng/vectors";
import { arcPointAt, arcPointAtTheta } from "./internal/arc-point";
import { copyPoints } from "./internal/copy-points";

export const enum SegmentType {
MOVE,
Expand Down Expand Up @@ -52,23 +51,8 @@ export const enum Type {
RAY3,
}

export const enum IntersectionType {
NONE,
PARALLEL,
COINCIDENT,
COINCIDENT_NO_INTERSECT,
INTERSECT,
INTERSECT_OUTSIDE,
}

export const DEFAULT_SAMPLES = 20;

export type Attribs = IObjectOf<any>;

export type Tessellator = (points: Vec[]) => Vec[][];

export type VecPair = [Vec, Vec];

export interface IShape extends
ICopy<IShape> {

Expand All @@ -89,17 +73,6 @@ export interface IHiccupPathSegment {
toHiccupPathSegments(): any[];
}

export interface IntersectionResult {
type: IntersectionType;
}

export interface LineIntersection extends IntersectionResult {
isec?: Vec;
det?: number;
alpha?: number;
beta?: number;
}

export interface PathSegment {
type: SegmentType;
point?: Vec;
Expand All @@ -114,62 +87,6 @@ export interface PCLikeConstructor {
new(pts: Vec[], attribs: Attribs): PCLike;
}

export interface SamplingOpts {
/**
* Number of points to sample & return. Defaults to the implementing
* type's `DEFAULT_RES` if neither this nor `theta` option is given
* (see `ArcSamplingOpts`).
*/
num: number;
/**
* Approximate desired distance between sampled result points. If
* given, takes priority over the `num` option, but the latter MIGHT
* be used as part of the sampling process (implementation
* specific). Note: For circles this value is interpreted as arc
* length, not cartesian distance (error will be proportional to the
* given value relative to the circle's radius).
*/
dist: number;
/**
* Currently only used by these types:
*
* - Arc
* - Circle
*
* Defines the target angle between sampled points. If greater than
* the actual range of the arc, only the two end points will be
* returned at most. This option is used to derive a `num` value and
* takes priority if `num` is given as well.
*
* This option is useful to adapt the sampling based on angular
* resolution, rather than a fixed number of samples.
*/
theta: number;
/**
* If `true`, the shape's end point will be included in the result
* array. The default setting for open geometries is `true`, for
* closed ones `false`. This option has no influence on any internal
* resolution calculation.
*
* For open geometry this option is useful to when re-sampling paths
* of consecutive segments, where the end points of each segment
* coincide with the start points of the next segment. For all but
* the last segment, this option should be `false` and so can be
* used to avoid duplicate vertices in the concatenated result.
*
* When sampling closed shapes, enabling this option will include an
* extra point (start), i.e. if the `num` option was given, results
* in `num+1` points.
*/
last: boolean;
}

export interface SubdivKernel {
fn: (pts: ReadonlyVec[], i: number, nump: number) => Vec[];
iter?: (pts: ReadonlyVec[]) => Iterable<ReadonlyVec>;
size: number;
}

export abstract class APC implements
PCLike {

Expand Down Expand Up @@ -215,7 +132,6 @@ export class AABB implements
}
}


export class Arc implements
IHiccupShape,
IHiccupPathSegment {
Expand Down Expand Up @@ -341,7 +257,7 @@ export class Cubic extends APC implements
}

copy() {
return new Cubic(copyPoints(this.points), { ...this.attribs });
return new Cubic(copyVectors(this.points), { ...this.attribs });
}

toHiccup() {
Expand Down Expand Up @@ -430,7 +346,7 @@ export class Line extends APC implements
}

copy() {
return new Line(copyPoints(this.points), { ...this.attribs });
return new Line(copyVectors(this.points), { ...this.attribs });
}

toHiccup() {
Expand Down Expand Up @@ -511,7 +427,7 @@ export class Points extends APC implements
}

copy() {
return new Points(copyPoints(this.points), { ...this.attribs });
return new Points(copyVectors(this.points), { ...this.attribs });
}

toHiccup() {
Expand All @@ -527,7 +443,7 @@ export class Polygon extends APC implements
}

copy() {
return new Polygon(copyPoints(this.points), { ...this.attribs });
return new Polygon(copyVectors(this.points), { ...this.attribs });
}

toHiccup() {
Expand All @@ -544,7 +460,7 @@ export class Polyline extends APC implements
}

copy() {
return new Polyline(copyPoints(this.points), { ...this.attribs });
return new Polyline(copyVectors(this.points), { ...this.attribs });
}

toHiccup() {
Expand All @@ -568,7 +484,7 @@ export class Quad extends APC implements
}

copy() {
return new Quad(copyPoints(this.points), { ...this.attribs });
return new Quad(copyVectors(this.points), { ...this.attribs });
}

toHiccup() {
Expand All @@ -585,7 +501,7 @@ export class Quadratic extends APC implements
}

copy() {
return new Quadratic(copyPoints(this.points), { ...this.attribs });
return new Quadratic(copyVectors(this.points), { ...this.attribs });
}

toHiccup() {
Expand Down Expand Up @@ -694,7 +610,7 @@ export class Triangle extends APC implements
}

copy() {
return new Triangle(copyPoints(this.points), { ...this.attribs });
return new Triangle(copyVectors(this.points), { ...this.attribs });
}

toHiccup() {
Expand Down
94 changes: 17 additions & 77 deletions packages/geom/src/ctors/arc.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,7 @@
import { isNumber } from "@thi.ng/checks";
import { EPS, TAU } from "@thi.ng/math";
import {
abs2,
angleBetween2,
div2,
eqDelta2,
mulN2,
neg,
powN2,
ReadonlyVec,
sub2,
submN2,
Vec,
X2
} from "@thi.ng/vectors";
import { Arc } from "../api";
import { fromEndPoints } from "@thi.ng/geom-arc";
import { Vec, ReadonlyVec } from "@thi.ng/vectors";
import { Arc, Attribs } from "../api";

export const arc = (
pos: Vec,
Expand All @@ -26,71 +13,24 @@ export const arc = (
clockwise = false
) => new Arc(pos, isNumber(r) ? [r, r] : r, axis, start, end, xl, clockwise);

/**
* https://svgwg.org/svg2-draft/implnote.html#ArcConversionEndpointToCenter
*
* Returns undefined if `a` & `b` are equal or any `radii` component is
* zero.
*
* @param a start point
* @param b end point
* @param radii ellipse radii
* @param axisTheta in radians
* @param xl large arc flag
* @param cw clockwise flag
*/
export const arcFrom2Points = (
a: ReadonlyVec,
b: ReadonlyVec,
radii: ReadonlyVec,
axisTheta = 0,
axis = 0,
xl = false,
cw = false
cw = false,
attribs?: Attribs
) => {

const r = abs2([], radii);
if (eqDelta2(a, b) || r[0] < EPS || r[1] < EPS) {
return;
}
axisTheta %= TAU;
const d = submN2([], a, b, 0.5);
const c = Math.cos(axisTheta);
const s = Math.sin(axisTheta);
// transformed point
const tp = [
c * d[0] + s * d[1],
-s * d[0] + c * d[1]
];
const [tx2, ty2] = powN2([], tp, 2);
// ensure radii
const rc = tx2 / (r[0] * r[0]) + ty2 / (r[1] * r[1]);
rc > 1 && mulN2(r, r, Math.sqrt(rc));
const [rx, ry] = r;
const rx2 = rx * rx;
const ry2 = ry * ry;
// transformed center
const radicant = Math.max(0, (rx2 * ry2 - rx2 * ty2 - ry2 * tx2) / (rx2 * ty2 + ry2 * tx2));
const coeff = (xl !== cw ? 1 : -1) * Math.sqrt(radicant);
const tc = [
coeff * ((rx * tp[1]) / ry),
coeff * (-(ry * tp[0]) / rx)
];
// actual center
const center = [
c * tc[0] - s * tc[1] + (a[0] + b[0]) / 2,
s * tc[0] + c * tc[1] + (a[1] + b[1]) / 2
];
// transformed end points & angles
const ta = div2(null, sub2([], tp, tc), r);
const tb = div2(null, sub2(null, neg([], tp), tc), r);
const start = angleBetween2(X2, ta);
let sweep = angleBetween2(ta, tb);
if (!cw && sweep > 0) {
sweep -= TAU;
} else if (cw && sweep < 0) {
sweep += TAU;
}
sweep %= TAU;

return new Arc(center, r, axisTheta, start, start + sweep, xl, cw);
const res = fromEndPoints(a, b, radii, axis, xl, cw);
return new Arc(
res.center,
res.r,
res.axis,
res.start,
res.end,
res.xl,
res.cw,
attribs
);
};
4 changes: 2 additions & 2 deletions packages/geom/src/ctors/circle.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { circumCenter2 } from "@thi.ng/geom-poly-utils";
import {
dist,
mixN2,
Expand All @@ -6,7 +7,6 @@ import {
} from "@thi.ng/vectors";
import { Attribs, Circle } from "../api";
import { argsVN } from "../internal/args";
import { circumCenter } from "../internal/circumcenter";

export function circle(pos: Vec, r: number, attribs?: Attribs): Circle;
export function circle(pos: Vec, attribs?: Attribs): Circle;
Expand All @@ -22,6 +22,6 @@ export const circleFrom2Points =

export const circleFrom3Points =
(a: ReadonlyVec, b: ReadonlyVec, c: ReadonlyVec, attribs?: Attribs) => {
const o = circumCenter(a, b, c);
const o = circumCenter2(a, b, c);
return o ? new Circle(o, dist(a, o), attribs) : undefined;
};
Loading

0 comments on commit fb532b8

Please sign in to comment.