我想找到一个点+方向和一条直线的交点。
- 点位于多边形的中心,线是多边形的边。
- 方向是多边形最长线段的弧度旋转。
为了说明我的问题,我做了一个截图:
image of the current state
你可以看到中心点,右边多边形的最长线段+最长线段的起点,都是黑色的。
- 紫色和红色的点是我的算法找到的交点。
- 底部和右侧的交叉点是正确的,但在左侧它找到了2个交叉点,其中一个是正确的。
- 顶部交点未到达多边形的边。
- 紫色的点应该是顶部和底部的交点
- 较小的红点应位于多边形的左侧和右侧,因为您可以看到它们部分混合在一起。
我的代码:
第一个循环计算最长线段和该线段的旋转。第二个循环根据最长线段的旋转检查垂直和水平方向上的相交
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 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个交叉点,但得到更多的这个特定的多边形,但简单的矩形,我得到正确的结果。
编辑:
只是为了弄清楚。我需要对射线应用一个旋转。这是在第一个循环中计算的最长线段的旋转。
@Blindman67你的解决方案给了我正确的结果为第一个多边形,我只需要交叉"十字"旋转。如下图:
correct
该算法给出以下结果:
not correct
1条答案
按热度按时间vql8enpb1#
澄清
澄清我对你问题的理解。
如果给定一组点P1 - 6和一个点A,则沿x和y轴查找与投影点A相交的点,即点B1 - 7
您的函数给出了点B1、B2、B3、B4、B5。但点B4、B5不正确
你说你只想要4分,B1,B2,B3,B6
溶液
看起来感兴趣点只是由点P1 - 6创建的线段上的点
我们可以使用一个函数来找到一条直线(无限长)和一条线段(有限长有一个起点和终点)的截距。
示例代码
函数
interceptLineSeg
将找到线段上的点(包括起点,不包括终点)。如果同时包括起点和终点,则会(可能由于浮点错误)找到两次相同的点。