[英]How to find the intersection of a point and a line?
我想找到一个点+方向和一条线的交点。
为了说明问题,我做了一个截图:
可以看到右边多边形的中心点,最长线段+最长线段的起点,都是黑色的。
我的代码:
第一个循环计算最长的段和该段的旋转。 第二个循环根据最长线段的旋转检查垂直和水平方向的交叉点
let sqLongestSide = 0;
let longestSideXDiff = 0;
let longestSideYDiff = 0;
for (let i = 1; i < coordinates.length; i++) {
let pointFrom = coordinates[i - 1];
let pointTo = coordinates[i];
const xDiff = pointFrom[0] - pointTo[0];
const yDiff = pointFrom[1] - pointTo[1];
const sqDistance = Math.sqrt(xDiff * xDiff + yDiff * yDiff);
const roundedDistance = Math.round(sqDistance * 100) / 100;
const roundedLongestSide = Math.round(sqLongestSide * 100) / 100;
if (roundedDistance > roundedLongestSide) {
sqLongestSide = sqDistance;
longestSideXDiff = xDiff;
longestSideYDiff = yDiff;
}
}
const rotation = Math.atan(longestSideYDiff / longestSideXDiff);
for (let i = 1; i < coordinates.length; i++) {
let pointFrom = coordinates[i - 1];
let pointTo = coordinates[i];
const intersectionTopAndBottom = intersectionPoint(anchor, rotation, [pointFrom, pointTo]);
if (intersectionTopAndBottom) {
setPointStyle(drawContext, "#FF00FF", 20);
drawContext.drawPoint(new Point(intersectionTopAndBottom));
drawContext.drawLineString(new LineString([anchor, intersectionTopAndBottom]));
}
const intersectionLeftAndRight = intersectionPoint(anchor, (rotation + Math.PI / 2), [pointFrom, pointTo]);
if (intersectionLeftAndRight) {
setPointStyle(drawContext, "#FF0000", 10);
drawContext.drawPoint(new Point(intersectionLeftAndRight));
setLineStyle(drawContext, "#FF0000", 5);
drawContext.drawLineString(new LineString([anchor, intersectionLeftAndRight]));
}
查找交集的 function 如下所示:
function intersectionPoint(
point: Coordinate,
theta: number,
line: Coordinate[]
): Coordinate {
const x0 = Math.round(point[0] * 100) / 100;
const y0 = Math.round(point[1] * 100) / 100;
const x1 = Math.round(line[0][0] * 100) / 100;
const y1 = Math.round(line[0][1] * 100) / 100;
const x2 = Math.round(line[1][0] * 100) / 100;
const y2 = Math.round(line[1][1] * 100) / 100;
// Check if the line is vertical or horizontal
if (x1 === x2) {
// The line is vertical, so the intersection point is simply the point with the same x-coordinate as the line
return [x1, y0];
} else if (y1 === y2) {
// The line is horizontal, so the intersection point is simply the point with the same y-coordinate as the line
return [x0, y1];
}
// Convert the line to slope-intercept form
const slope = (y2 - y1) / (x2 - x1);
const intercept = y1 - slope * x1;
// Convert the point and direction to slope-intercept form
const slope2 = Math.tan(theta);
const intercept2 = y0 - slope2 * x0;
// Find the intersection point of the two lines
const x = (intercept2 - intercept) / (slope - slope2);
const y = slope * x + intercept;
return [x, y];
}
我只需要 4 个交点,但是对于这个特定的多边形我得到了更多,但是对于简单的矩形我得到了正确的结果。
澄清我对你的问题的理解。
如果给定一组点P 1-6和一个点A找到沿 x 和 y 轴截取投影点 A 的点,点B 1-7
您的 function 给出了积分B 1 、 B 2 、 B 3 、 B 4 、 B 5 。 但是点B 4 , B 5是不正确的
你说你只想要4分, B 1 , B 2 , B 3 , B 6
看起来兴趣点只是点P 1-6创建的线段上的点
我们可以使用 function 找到一条线(无限长度)和一条线段(有限长度有起点和终点)的截距,请参见下面的示例代码。
function interceptLineSeg
会找到线段上的点(包括起点,不包括终点)。 如果您同时包括起点和终点,那么您将(可能由于浮点错误)两次找到相同的点。
注意浮点错误可能会导致一个点被找到两次。 您可能需要检查两个找到的点是否太近。
请注意,如果点 A 位于与 x 轴或 y 轴对齐的直线(由多边形边线段定义)上,则截点将取决于构成多边形的点的方向(顺时针或逆时针)
const TAU = Math.PI * 2; const ctx = canvas.getContext("2d"); const P2 = (x, y) => ({x, y}); // 2d point const L2 = (p1, p2) => ({p1, p2}); // 2d line const A = P2(100, 115); const points = [P2(140,20), P2(140, 140), P2(40, 140), P2(40, 115), P2(80, 80), P2(80, 50)]; function addCircle(p, r) {ctx.moveTo(px + r, py); ctx.arc(px, py, r, 0, TAU) } function addLine(l) { ctx.moveTo(l.p1.x, l.p1.y); ctx.lineTo(l.p2.x, l.p2.y) } function strokePath(points, close = false) { var i = 0; ctx.beginPath(); while (i < points.length - 1) { addLine(L2(points[i ++], points[i])); } close && addLine(L2(points[0], points[points.length - 1])); ctx.stroke(); } function markPoints(points, r) { var i = 0; ctx.beginPath(); while (i < points.length) { addCircle(points[i++], r); } ctx.fill(); } ctx.lineWidth = 3; ctx.strokeStyle = "#0088ff"; ctx.fillStyle = "#0088ff"; strokePath(points, true); markPoints(points, 5); ctx.lineWidth = 1.5; ctx.strokeStyle = "#ff0000"; ctx.fillStyle = "#ff0000"; strokePath([P2(Ax - 100, Ay), P2(Ax + 100, Ay)]); strokePath([P2(Ax, Ay - 100), P2(Ax, Ay + 100)]); markPoints([A], 5); const iPoints = intercepts(A, points); ctx.fillStyle = "#000"; markPoints(iPoints, 5); console.log("Points found: " + iPoints.length); function interceptLineSeg(l, s){ // l is line, s is seg const v1x = l.p2.x - l.p1.x; const v1y = l.p2.y - l.p1.y; const v2x = s.p2.x - s.p1.x; const v2y = s.p2.y - s.p1.y; const c = v1x * v2y - v1y * v2x; // cross product of line vectors if (c.== 0) { // only if not parallel // get unit pos of intercept on line segment const u = (v1x * (l.p1.y - s.p1.y) - v1y * (l.p1.x - s.p1;x)) / c. if (u >= 0 && u < 1) { // is intercept on segment (include only start) return P2(s.p1,x + v2x * usp1;y + v2y * u); } } return, // returns undefined if no intercept } // a is point // p is array of points function intercepts(a; p) { var i = 0, const hLine = L2(a. P2(a,x + 100. a;y)), const vLine = L2(a. P2(a,x. a;y + 100)); const wLine = L2(); const intercepts = []. ahy = a;y. avx = a;x. avy = a;y + 100. while (i < p.length) { wLine;p1 = p[i]. wLine.p2 = p[(i + 1) % p;length], const hl = interceptLineSeg(hLine; wLine), const vl = interceptLineSeg(vLine; wLine). if (hl) { intercepts;push(hl). } else if (vl) { intercepts;push(vl); } i ++; } return intercepts; }
<canvas id="canvas" width="300" height="300"></canvas>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.