Public
Edited
Jan 2
Importers
Insert cell
Insert cell
/**

resample the points in `pts` array at a `maxDist`

*/
resample = (pts, maxDst, closed=true) => {
const nps = [];
const len = closed ? pts.length : pts.length-1;
for (let i=0;i<len;i++){
const a = pts[i];
const b = pts[(i+1)%pts.length];
const dif = add(a, minus(b));
const d = Math.hypot(...dif);
const st =Math.round( d/maxDst);
// console.log(dif,st);
for(let j=0;j<st;j++) {
const t = j/st;
nps.push([a[0]+t*(b[0]-a[0]), a[1]+t*(b[1]-a[1])]);
}
}
if (!closed) nps.push(pts[pts.length-1])
return nps;
}
Insert cell
import { add, minus, dif, cross, addmN, mulN} from "@max-generis/vector-math"
Insert cell
intersect = ([slope, intercept], a, b) => {
const p = [0,intercept], r = dif(p,[-10000, -10000*slope + intercept]);
const q = a, s = dif(b,a), xrs = cross(r,s), qpr = cross(dif(q,p), r);

const t = cross(dif(q,p), s)/xrs;
const u = qpr/xrs;

return xrs ===0 && qpr === 0
? "collinear"
: xrs ===0 && qpr !== 0
? "parallel"
: 0<= u && u<= 1
? addmN(q, s, u)
: "notintersecting";
}
Insert cell
//
/**
* Calculates the distance from a point to a line segment.
*
* @param {Array} p - The point [x, y].
* @param {Array} seg - The segment represented as [[ax, ay], [bx, by]].
* @returns {number} - The shortest distance from the point to the segment.
*/
function distancePointToSegment(p, seg) {
const [px, py] = p;
const [[ax, ay], [bx, by]] = seg;
// Calculate the squared length of the segment
const dx = bx - ax;
const dy = by - ay;
const segmentLengthSquared = dx * dx + dy * dy;
// Calculate the projection of point p onto the segment
let t = ((px - ax) * dx + (py - ay) * dy) / segmentLengthSquared;
t = Math.max(0, Math.min(1, t)); // Clamp t to the range [0, 1]
// Find the closest point on the segment to point p
const closestX = ax + t * dx;
const closestY = ay + t * dy;
// Calculate the distance from point p to the closest point on the segment
const distanceX = px - closestX;
const distanceY = py - closestY;
return Math.sqrt(distanceX * distanceX + distanceY * distanceY);
}


Insert cell
distancePointToSegment([0,0], [[1,2], [1,1]])
Insert cell
rayIntersect = (p, r, a, b) => {
const q = a, s = dif(b,a), xrs = cross(r,s), qpr = cross(dif(q,p), r);

const t = cross(dif(q,p), s)/xrs;
const u = qpr/xrs;

return xrs ===0 && qpr === 0
? "collinear"
: xrs ===0 && qpr !== 0
? "parallel"
: 0<= u && u<= 1 && t>=0
? addmN(q, s, u)
: "notintersecting";
}
Insert cell
area = points => points.reduce((acc, p, i)=> acc + p[0]*points[(i+1)%points.length][1] - p[1]*points[(i+1)%points.length][0], 0)/2
Insert cell
centroid = points => {
let area = 0, cx=0, cy=0;
for (let i = 0;i<points.length;i++) {
const a = points[i][0]*points[(i+1)%points.length][1] - points[i][1]*points[(i+1)%points.length][0];
area += a;
cx += (points[i][0] + points[(i+1)%points.length][0])*a;
cy += (points[i][1] + points[(i+1)%points.length][1])*a;
}
return [cx/(3*area), cy/(3*area)]
}
Insert cell
resample(resample([[0,0], [1, 1]], 0.2, false), 0.2, false)
Insert cell
scalePoly = (poly, scale) => {
const c = centroid(poly);
const pp = poly.map(p => addmN(c, dif(p,c), scale));
return pp;
}
Insert cell

pointInPolygon = (point, polygon) => {
const x = point[0];
const y = point[1];
let inside = false;
for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
const xi = polygon[i][0];
const yi = polygon[i][1];
const xj = polygon[j][0];
const yj = polygon[j][1];
const intersect =
(yi > y) !== (yj > y) && x < ((xj - xi) * (y - yi)) / (yj - yi) + xi;
if (intersect) {
inside = !inside;
}
}
return inside;
}

Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more