Skip to content

Instantly share code, notes, and snippets.

@lostPixels
Created May 22, 2022 01:10
Show Gist options
  • Save lostPixels/890150664c5f80bb52be62b72d2be5d8 to your computer and use it in GitHub Desktop.
Save lostPixels/890150664c5f80bb52be62b72d2be5d8 to your computer and use it in GitHub Desktop.
window.intersectionCount = 0;
function trimLine(polyline, polygon){
if (!polyline.length){
return {true:[],false:[]};
}
let zero = segmentIntersectPoly(...polyline[0],polyline[0][0]+Math.E,polyline[0][1]+PI,polygon,true).length % 2 != 0;
let out = {
'true' :[[]],
'false':[[]],
}
let io = zero;
let hasIsect = false;
for (let i = 0; i < polyline.length; i++){
let a= polyline[i];
let b= polyline[i+1];
out[io][out[io].length-1].push(a);
if (!b) break;
let isects = segmentIntersectPoly(...a,...b,polygon,false);
if(!hasIsect && isects) {
hasIsect = true;
}
for (let j = 0; j < isects.length; j++){
out[io][out[io].length-1].push(isects[j].xy);
io = !io;
out[io].push([isects[j].xy]);
}
}
out.true = out.true.filter(x=>x.length);
out.false = out.false.filter(x=>x.length);
if(!hasIsect) {
return [];
}
return out.true;
}
function segmentIntersectPoly(x0,y0,x1,y1,poly,is_ray=false){
let n = poly.length;
let isects = [];
for (let i = 0; i < poly.length; i++){
let a = poly[i];
let b = poly[(i+1)%n];
let xx = segmentIntersects(x0,y0,x1,y1,...a,...b,is_ray);
if (xx){
isects.push(xx);
}
}
isects.sort((a,b)=>a.t-b.t);
return isects;
}
function segmentIntersects(p0x, p0y, p1x, p1y, q0x, q0y, q1x, q1y, is_ray = false) {
let d0x = p1x - p0x;
let d0y = p1y - p0y;
let d1x = q1x - q0x;
let d1y = q1y - q0y;
let vc = d0x * d1y - d0y * d1x;
if (vc == 0) {
return null;
}
let vcn = vc * vc;
let q0x_p0x = q0x - p0x;
let q0y_p0y = q0y - p0y;
let vc_vcn = vc / vcn;
let t = (q0x_p0x * d1y - q0y_p0y * d1x) * vc_vcn;
let s = (q0x_p0x * d0y - q0y_p0y * d0x) * vc_vcn;
if (0 <= t && (is_ray || t < 1) && 0 <= s && s < 1) {
let ret = {t, s, side: null, other: null, xy: null};
ret.xy = [p1x * t + p0x * (1 - t), p1y * t + p0y * (1 - t)];
ret.side = pointInside(p0x, p0y, p1x, p1y, q0x, q0y) < 0 ? 1 : -1;
return ret;
}
window.intersectionCount++;
return null;
}
function pointInside(x, y, x0, y0, x1, y1) {
let dx = x1 - x0;
let dy = y1 - y0;
let e = (x - x0) * dy - (y - y0) * dx;
return e;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment