-
-
Notifications
You must be signed in to change notification settings - Fork 153
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(geom-clip-line): add clipLinePoly(), update deps
- Loading branch information
1 parent
6958280
commit e096efd
Showing
4 changed files
with
143 additions
and
114 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
}; |