Skip to content

Commit

Permalink
feat(geom): update all shape types, add interfaces & ops, update tests
Browse files Browse the repository at this point in the history
  • Loading branch information
postspectacular committed Sep 29, 2018
1 parent 5c44ad9 commit 9c27c77
Show file tree
Hide file tree
Showing 10 changed files with 229 additions and 292 deletions.
6 changes: 3 additions & 3 deletions packages/geom/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@
"typescript": "^3.0.1"
},
"dependencies": {
"@thi.ng/api": "^4.1.1",
"@thi.ng/transducers": "^2.1.1",
"@thi.ng/vectors": "^1.1.0"
"@thi.ng/api": "^4.2.1",
"@thi.ng/transducers": "^2.1.6",
"@thi.ng/vectors": "^1.3.0"
},
"keywords": [
"ES6",
Expand Down
72 changes: 25 additions & 47 deletions packages/geom/src/circle2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,59 +2,41 @@ import { IObjectOf } from "@thi.ng/api/api";
import { normRange } from "@thi.ng/transducers/iter/norm-range";
import { Vec } from "@thi.ng/vectors/api";
import { mix1, PI, TAU } from "@thi.ng/vectors/math";
import {
addN2o,
set2,
setS2,
subN2o,
toCartesian2,
Vec2
} from "@thi.ng/vectors/vec2";

import { setS2, toCartesian2, Vec2 } from "@thi.ng/vectors/vec2";
import { Polygon2 } from "./poly2";

export class Circle2 {

buf: Vec;
offset: number;
attribs: any;
pos: Vec2;
r: number;
attribs: IObjectOf<any>;

constructor(buf: Vec, attribs?: IObjectOf<any>, offset = 0) {
this.buf = buf;
constructor(pos: Vec2, r = 1, attribs?: IObjectOf<any>) {
this.pos = pos;
this.r = r;
this.attribs = attribs;
this.offset = offset;
}

get pos() {
return new Vec2(this.buf, this.offset);
}

set pos(v: Readonly<Vec2>) {
set2(this.buf, v.buf, this.offset, v.i, 1, v.s);
}

get r() {
return this.buf[this.offset + 2];
}

set r(r: number) {
this.buf[this.offset + 2] = r;
}

verticesRaw(from: number,
verticesRaw(
from: number,
to: number,
res: number,
inclLast: boolean,
dest: Vec = [],
destOffset = 0,
cstride = 1,
estride = 2) {
estride = 2
) {

const buf = this.buf;
const o = this.offset;
const r = buf[o + 2];
const pos = this.pos.buf;
const po = this.pos.i;
const ps = this.pos.s;
const r = this.r;
for (let t of normRange(inclLast ? res - 1 : res, inclLast)) {
toCartesian2(setS2(dest, r, mix1(from, to, t), destOffset, cstride), buf, destOffset, o, cstride, 1);
toCartesian2(
setS2(dest, r, mix1(from, to, t), destOffset, cstride),
pos, destOffset, po, cstride, ps
);
destOffset += estride;
}
return dest;
Expand All @@ -65,32 +47,28 @@ export class Circle2 {
}

area() {
return PI * Math.pow(this.r, 2);
return PI * this.r * this.r;
}

circumference() {
return TAU * this.r;
}

bounds() {
const buf = this.buf;
return [
new Vec2(subN2o([], buf, buf[2], 0, this.offset)),
new Vec2(addN2o([], buf, buf[2], 0, this.offset))
Vec2.subN(this.pos, this.r),
Vec2.addN(this.pos, this.r)
];
}

toPolygon(res = 20) {
return new Polygon2(this.verticesRaw(0, TAU, res, false), res);
return new Polygon2(this.vertices(res));
}

toHiccup() {
return ["circle", this.attribs, this.pos, this.r];
}
}

export const circle2m = (buf: Vec, attribs?: IObjectOf<any>, offset?: number) =>
new Circle2(buf, attribs, offset);

export const circle2 = (pos: Readonly<Vec2>, r = 1, attribs?: IObjectOf<any>) =>
new Circle2([pos.x, pos.y, r], attribs, 0);
export const circle2 = (pos: Vec2, r = 1, attribs?: IObjectOf<any>) =>
new Circle2(pos, r, attribs);
43 changes: 34 additions & 9 deletions packages/geom/src/common.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,45 @@
import { peek } from "@thi.ng/transducers/func/peek";
import { wrap } from "@thi.ng/transducers/iter/wrap";
import { partition } from "@thi.ng/transducers/xform/partition";
import { ReadonlyVec, ReadonlyVecOp2 } from "@thi.ng/vectors/api";
import { IDistance } from "@thi.ng/vectors/api";
import { SampleableVector } from "./api";

export const arcLength = (dist: ReadonlyVecOp2<number>, buf: ReadonlyVec, num: number, offset: number, stride: number, closed = false) => {
num--;
export const arcLength = <T extends IDistance<T>>(pts: Readonly<T>[], closed = false) => {
const num = pts.length;
if (num < 2) return 0;
let i = pts[0];
let j = pts[1];
let res = 0;
for (let n = num, i = offset, j = i + stride; n > 0; n-- , i = j, j += stride) {
res += dist(buf, buf, i, j);
}
if (closed) {
res += dist(buf, buf, offset + num * stride, offset);
for (let k = 1; k < num; k++ , i = j, j = pts[k]) {
res += i.dist(j);
}
closed && (res += i.dist(pts[0]));
return res;
}

export const resample = () => { };
/**
* Re-samples given polyline at given uniform distance. Returns array of
* interpolated points (does not modify original).
*
* @param step sample distance
* @param pts
*/
export const sampleUniform = <T extends SampleableVector<T>>(pts: T[], step: number) => {
if (!pts.length) return [];
let prev = pts[0];
const res: T[] = [prev];
for (let i = 1, n = pts.length; i < n; prev = peek(res), i++) {
const p = pts[i];
let d = p.dist(prev);
while (d >= step) {
res.push(prev = prev.copy().mixN(p, step / d));
d -= step;
}
}
res.push(peek(pts));
return res;
};


export function edges<T>(vertices: T[], closed = false) {
return partition(2, 1, closed ? wrap(vertices, 1, false, true) : vertices);
Expand Down
134 changes: 48 additions & 86 deletions packages/geom/src/container2.ts
Original file line number Diff line number Diff line change
@@ -1,73 +1,63 @@
import { IObjectOf } from "@thi.ng/api/api";
import { illegalArgs } from "@thi.ng/errors/illegal-arguments";
import { Vec } from "@thi.ng/vectors/api";
import { transformVectors1 } from "@thi.ng/vectors/common";
import { Mat23, mulV23 } from "@thi.ng/vectors/mat23";
import {
add2,
max2,
min2,
mul2,
set2,
swap2,
Vec2
} from "@thi.ng/vectors/vec2";
import { Mat23 } from "@thi.ng/vectors/mat23";
import { Vec2, vec2 } from "@thi.ng/vectors/vec2";
import { IBounds } from "./api";

export class PointContainer2 {
export class PointContainer2 implements
IBounds<Vec2[]> {

buf: Vec;
length: number;
offset: number;
stride: number;
points: Vec2[];
attribs: IObjectOf<any>;

constructor(buf: Vec, num?: number, attribs?: IObjectOf<any>, offset = 0, stride = 2) {
this.buf = buf;
this.length = num != null ? num : buf.length / 2;
constructor(pts: Vec2[], attribs?: IObjectOf<any>) {
this.points = pts;
this.attribs = attribs;
this.offset = offset;
this.stride = stride;
}

*[Symbol.iterator]() {
yield* this.vertices();
}

vertices() {
return Vec2.mapBuffer(this.buf, this.length, this.offset, 1, this.stride);
}

get(i: number, safe = true) {
safe && this.ensureIndex(i);
return new Vec2(this.buf, this.offset + i * this.stride);
}

set(i: number, v: Readonly<Vec2>, safe = true) {
safe && this.ensureIndex(i);
set2(this.buf, v.buf, this.offset + i * this.stride, v.i, 1, v.s);
return this.points;
}

bounds() {
const s = this.stride;
const pts = this.buf;
const pts = this.points;
const min = Vec2.MAX.copy();
const max = Vec2.MIN.copy();
for (let n = this.length, i = this.offset; n > 0; n-- , i += s) {
min2(min.buf, pts, 0, i, 1, 1);
max2(max.buf, pts, 0, i, 1, 1);
for (let i = pts.length; --i >= 0;) {
const p = pts[i];
min.min(p);
max.max(p);
}
return [min, max];
}

width() {
const b = this.bounds();
return b[1].x - b[0].x;
}

height() {
const b = this.bounds();
return b[1].y - b[0].y;
}

depth() {
return 0;
}

centroid(c?: Vec2): Vec2 {
!this.length && illegalArgs("no points available");
!c && (c = Vec2.ZERO.copy());
const s = this.stride;
const pts = this.buf;
for (let n = this.length, i = this.offset; n > 0; n-- , i += s) {
add2(c.buf, pts, c.i, i, c.s, 1);
const pts = this.points;
const num = pts.length;
!num && illegalArgs("no points available");
!c && (c = vec2());
for (let i = num; --i >= 0;) {
c.add(pts[i]);
}
return c.divN(this.length);
return c.divN(num);
}

center(origin?: Readonly<Vec2>) {
Expand All @@ -76,58 +66,30 @@ export class PointContainer2 {
}

flip() {
const s = this.stride;
for (let i = 0, j = (this.length - 1) * s; i < j; i += s, j -= s) {
swap2(this.buf, this.buf, i, j);
}
this.points.reverse();
}

scale(v: Readonly<Vec2>) {
transformVectors1(
mul2,
this.buf,
v.buf,
this.length,
this.offset,
v.i,
1,
v.s,
this.stride
);
const pts = this.points;
for (let i = pts.length; --i >= 0;) {
pts[i].mul(v);
}
return this;
}

translate(v: Readonly<Vec2>) {
transformVectors1(
add2,
this.buf,
v.buf,
this.length,
this.offset,
v.i,
1,
v.s,
this.stride
);
const pts = this.points;
for (let i = pts.length; --i >= 0;) {
pts[i].add(v);
}
return this;
}

transform(mat: Readonly<Mat23>) {
transformVectors1(
mulV23,
this.buf,
mat.buf,
this.length,
this.offset,
mat.i,
1,
1,
this.stride
);
const pts = this.points;
for (let i = pts.length; --i >= 0;) {
mat.mulV(pts[i]);
}
return this;
}

protected ensureIndex(i: number) {
(i < 0 && i >= this.length) && illegalArgs(`index out of bounds: ${i}`);
}
}
Loading

0 comments on commit 9c27c77

Please sign in to comment.