Skip to content

Commit

Permalink
feat(geom-clip-line): add clipLinePoly(), update deps
Browse files Browse the repository at this point in the history
  • Loading branch information
postspectacular committed Jun 20, 2020
1 parent 6958280 commit e096efd
Show file tree
Hide file tree
Showing 4 changed files with 143 additions and 114 deletions.
1 change: 1 addition & 0 deletions packages/geom-clip-line/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
"typescript": "^3.9.2"
},
"dependencies": {
"@thi.ng/geom-isec": "^0.4.21",
"@thi.ng/vectors": "^4.4.4",
"tslib": "^1.12.0"
},
Expand Down
26 changes: 26 additions & 0 deletions packages/geom-clip-line/src/clip-poly.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { intersectRayPolylineAll } from "@thi.ng/geom-isec";
import { direction, ReadonlyVec, Vec } from "@thi.ng/vectors";

/**
* Computes all intersection points of the infinite line defined by `a`,
* `b` with the given polygon. Returns an array of segments where the
* line is inside the polygon.
*
* @param a
* @param b
* @param pts
*/
export const clipLinePoly = (
a: ReadonlyVec,
b: ReadonlyVec,
pts: ReadonlyVec[]
) => {
const isecs = intersectRayPolylineAll(a, direction([], a, b), pts, true)
.isec;
if (!isecs) return;
const segments: Vec[][] = [];
for (let i = 0; i < isecs.length; i += 2) {
segments.push([<Vec>isecs[i], <Vec>isecs[i + 1]]);
}
return segments;
};
116 changes: 2 additions & 114 deletions packages/geom-clip-line/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,114 +1,2 @@
import type { Vec, ReadonlyVec } from "@thi.ng/vectors";

/**
* Performs Liang-Barsky clipping of the line segment with endpoints
* `a`, `b` against the clipping rect defined by `min` and `max`. The
* optional `ca` and `cb` vectors can be given to store the result
* (clipped points). If omitted creates new vectors. Returns a tuple of
* `[ca, cb, a, b]`, where the latter two values represent the
* normalized distances of the clipped points relative to original given
* line segment. Returns `undefined` iff the line lies completely
* outside the rect.
*
* - {@link https://en.wikipedia.org/wiki/Liang%E2%80%93Barsky_algorithm}
* - {@link https://github.com/thi-ng/c-thing/blob/develop/src/geom/clip/liangbarsky.c}
*
* @param a - line endpoint
* @param b - line endpoint
* @param min - bbox min
* @param max - bbox max
* @param ca - result A
* @param cb - result B
*/
export const liangBarsky2 = (
a: ReadonlyVec,
b: ReadonlyVec,
min: ReadonlyVec,
max: ReadonlyVec,
ca: Vec = [],
cb: Vec = []
): [Vec, Vec, number, number] | undefined => {
const res = liangBarsky2Raw(
a[0],
a[1],
b[0],
b[1],
min[0],
min[1],
max[0],
max[1]
);
if (!res) return;

ca[0] = res[0];
ca[1] = res[1];
cb[0] = res[2];
cb[1] = res[3];

return [ca, cb, res[4], res[5]];
};

/**
* Same as {@link liangBarsky2} but for non-vector arguments.
*
* @param ax
* @param ay
* @param bx
* @param by
* @param minx
* @param miny
* @param maxx
* @param maxy
*/
export const liangBarsky2Raw = (
ax: number,
ay: number,
bx: number,
by: number,
minx: number,
miny: number,
maxx: number,
maxy: number
): [number, number, number, number, number, number] | undefined => {
const dx = bx - ax;
const dy = by - ay;
let alpha = 0;
let beta = 1;

const clip = (p: number, q: number) => {
if (p < 0) {
const r = q / p;
if (r > beta) {
return false;
}
if (r > alpha) {
alpha = r;
}
} else if (p > 0) {
const r = q / p;
if (r < alpha) {
return false;
}
if (r < beta) {
beta = r;
}
} else if (q < 0) {
return false;
}
return true;
};

return clip(-dx, ax - minx) &&
clip(dx, maxx - ax) &&
clip(-dy, ay - miny) &&
clip(dy, maxy - ay)
? [
alpha * dx + ax,
alpha * dy + ay,
beta * dx + ax,
beta * dy + ay,
alpha,
beta,
]
: undefined;
};
export * from "./clip-poly";
export * from "./liang-barsky";
114 changes: 114 additions & 0 deletions packages/geom-clip-line/src/liang-barsky.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import type { Vec, ReadonlyVec } from "@thi.ng/vectors";

/**
* Performs Liang-Barsky clipping of the line segment with endpoints
* `a`, `b` against the clipping rect defined by `min` and `max`. The
* optional `ca` and `cb` vectors can be given to store the result
* (clipped points). If omitted creates new vectors. Returns a tuple of
* `[ca, cb, a, b]`, where the latter two values represent the
* normalized distances of the clipped points relative to original given
* line segment. Returns `undefined` iff the line lies completely
* outside the rect.
*
* - {@link https://en.wikipedia.org/wiki/Liang%E2%80%93Barsky_algorithm}
* - {@link https://github.com/thi-ng/c-thing/blob/develop/src/geom/clip/liangbarsky.c}
*
* @param a - line endpoint
* @param b - line endpoint
* @param min - bbox min
* @param max - bbox max
* @param ca - result A
* @param cb - result B
*/
export const liangBarsky2 = (
a: ReadonlyVec,
b: ReadonlyVec,
min: ReadonlyVec,
max: ReadonlyVec,
ca: Vec = [],
cb: Vec = []
): [Vec, Vec, number, number] | undefined => {
const res = liangBarsky2Raw(
a[0],
a[1],
b[0],
b[1],
min[0],
min[1],
max[0],
max[1]
);
if (!res) return;

ca[0] = res[0];
ca[1] = res[1];
cb[0] = res[2];
cb[1] = res[3];

return [ca, cb, res[4], res[5]];
};

/**
* Same as {@link liangBarsky2} but for non-vector arguments.
*
* @param ax
* @param ay
* @param bx
* @param by
* @param minx
* @param miny
* @param maxx
* @param maxy
*/
export const liangBarsky2Raw = (
ax: number,
ay: number,
bx: number,
by: number,
minx: number,
miny: number,
maxx: number,
maxy: number
): [number, number, number, number, number, number] | undefined => {
const dx = bx - ax;
const dy = by - ay;
let alpha = 0;
let beta = 1;

const clip = (p: number, q: number) => {
if (p < 0) {
const r = q / p;
if (r > beta) {
return false;
}
if (r > alpha) {
alpha = r;
}
} else if (p > 0) {
const r = q / p;
if (r < alpha) {
return false;
}
if (r < beta) {
beta = r;
}
} else if (q < 0) {
return false;
}
return true;
};

return clip(-dx, ax - minx) &&
clip(dx, maxx - ax) &&
clip(-dy, ay - miny) &&
clip(dy, maxy - ay)
? [
alpha * dx + ax,
alpha * dy + ay,
beta * dx + ax,
beta * dy + ay,
alpha,
beta,
]
: undefined;
};

0 comments on commit e096efd

Please sign in to comment.