Skip to content

Instantly share code, notes, and snippets.

@croraf
Last active October 26, 2020 23:00
Show Gist options
  • Save croraf/ae9a861729a5221970b87927b4c1acb6 to your computer and use it in GitHub Desktop.
Save croraf/ae9a861729a5221970b87927b4c1acb6 to your computer and use it in GitHub Desktop.
Polygon 2
const calculateDistance = (point1, point2) => {
return Math.sqrt((point2.x - point1.x) ** 2 + (point2.y - point1.y) ** 2);
}
/**
* Polygon is oriented positively, that is when traveling on it its interior is always to the left
* @param {*} polygon
* @param {*} pointP
*/
const calculateClosestPointWithinPolygon = (polygon, pointP) => {
let minDistance;
let finalClosestPoint;
for (let i = 0; i < polygon.length; i++) {
const side = [
polygon[i],
polygon[(i + 1) % polygon.length],
];
const y2 = side[1].y;
const x2 = side[1].x;
const y1 = side[0].y;
const x1 = side[0].x;
const y0 = pointP.y;
const x0 = pointP.x;
const sideAsVector = {
point: polygon[i],
vector: { x: x2 - x1, y: y2 - y1 }
};
const sideLenght = calculateDistance(side[0], side[1]);
const pointPAsVector = {
point: polygon[i],
vector: { x: x0 - x1, y: y0 - y1 }
};
const scalarProduct = (
sideAsVector.vector.x * pointPAsVector.vector.x + sideAsVector.vector.y * pointPAsVector.vector.y
)
/ sideLenght;
console.log('sideAsVector:', sideAsVector);
console.log('sideLenght:', sideLenght);
console.log('pointPAsVector:', pointPAsVector);
console.log('scalarProduct:', scalarProduct);
let closestPoint;
let distance;
if (scalarProduct > sideLenght) {
// orthogonal projection is not within the side
// closest point is the second side's point
closestPoint = side[1];
distance = calculateDistance(side[1], pointP);
console.log('second point');
} else if (scalarProduct < 0) {
// orthogonal projection is not within the side
// closest point is the first side's point
closestPoint = side[0];
distance = calculateDistance(side[0], pointP);
console.log('first point');
} else {
//orthogonal projection is within the side,
// it is the closest point
const orthogonalProjectionPoint = {
x: sideAsVector.point.x + sideAsVector.vector.x * scalarProduct / sideLenght,
y: sideAsVector.point.y + sideAsVector.vector.y * scalarProduct / sideLenght,
};
closestPoint = orthogonalProjectionPoint;
distance = calculateDistance(orthogonalProjectionPoint, pointP);
console.log('orthogonal projection point');
}
console.log('distance:', distance);
console.log('closestPoint:', closestPoint);
console.log('--------------------',);
if (minDistance === undefined || distance < minDistance) {
// take the minimal of the figures for all sides
minDistance = distance;
finalClosestPoint = closestPoint;
}
}
return finalClosestPoint;
// it only remains to see if the point is withing the polygon.
}
const polygon = [{ x: 0, y: 0 }, { x: 100, y: 0 }, { x: 100, y: 100 }, { x: 0, y: 100 }];
const pointP = { x: 150, y: 50 };
const result = calculateClosestPointWithinPolygon(polygon, pointP);
console.log(result);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment