英文:
Find distance between 2D point and line segment start point
问题
这似乎是一个简单的问题,但我在代数方面不擅长。
我正在尝试找到点与沿着线段的角度平行的线段起点之间的距离。我将使用这个距离来插值沿着该线的一个值。
我还需要知道点在线的外部时的情况。
这是我的代码尝试,使用了three.js的Vector2D,但它的行为不如预期。
const lineStartOrig = lineStart.clone()
const lineLength = lineStart.distanceTo(lineEnd)
const dotDiff = point2D.sub(lineStart).dot(lineEnd) / lineEnd.dot(lineEnd)
const pointIntersect = dummyLineStart.add(lineEnd)
.multiplyScalar(dotDiff)
.clamp(lineStartOrig, lineEnd)
const value = pointIntersect.distanceTo(lineStartOrig) / lineLength
英文:
This feels like a simple problem but I am bad at algebra.
I'm trying to find the distance between a point and the start of a line segment at an angle parallel to the segment. I will use the distance to interpolate a value along the line.
I also need to know when the points are outside of the line.
A code example would be appreciated, this is my attempt so far using threejs Vector2D but it isn't behaving as expected.
const lineStartOrig = lineStart.clone()
const lineLength = lineStart.distanceTo(lineEnd)
const dotDiff = point2D.sub(lineStart).dot(lineEnd) / lineEnd.dot(lineEnd)
const pointIntersect = dummyLineStart.add(lineEnd)
.multiplyScalar(dotDiff)
.clamp(lineStartOrig, lineEnd)
const value = pointIntersect.distanceTo(lineStartOrig) / lineLength
答案1
得分: 1
以下是要翻译的代码部分:
要计算两个向量和一个测试点C之间的角度:
float calcAngle(QVector2D& A, QVector2D& B, QVector2D& C)
{
QVector2D v1 = B - A;
QVector2D v2 = C - A;
float v1DotV2 = QVector2D::dotProduct(v1, v2);
float magV1TimesMagV2 = v1.length()* v2.length();
float cosTheta = v1DotV2/magV1TimesMagV2;
float theta = qRadiansToDegrees(acosf(cosTheta));
qInfo() << "Theta " << theta;
return theta;
}
要获取距离和交点,这是我认为楼主在寻找的:
float calcDistAlongParallelLineAndIntersectPoint(const QVector2D& A, const QVector2D& B, const QVector2D& C, QVector2D& intersectPoint)
{
QVector2D v1 = B - A;
QVector2D v2 = C - A;
float v1DotV2 = QVector2D::dotProduct(v1, v2);
float magV1TimesMagV2 = v1.length()* v2.length();
float cosTheta = v1DotV2/magV1TimesMagV2;
float dist = v2.length() * cosTheta;
QVector2D intersectingPoint = C - v1*(dist/v1.length());
intersectPoint.setX(intersectingPoint.x());
intersectPoint.setY(intersectingPoint.y());
return dist;
}
对于一些随机点的简单检查如下:
英文:
In case it's useful to anyone, I used the following functions (unfortunately not in .js, but should illustrate the idea)
To calc angle between two vectors and a test point C:
float calcAngle(QVector2D& A, QVector2D& B, QVector2D& C)
{
QVector2D v1 = B - A;
QVector2D v2 = C - A;
float v1DotV2 = QVector2D::dotProduct(v1, v2);
float magV1TimesMagV2 = v1.length()* v2.length();
float cosTheta = v1DotV2/magV1TimesMagV2;
float theta = qRadiansToDegrees(acosf(cosTheta));
qInfo() << "Theta " << theta;
return theta;
}
To get the distance and intersect point which I think the OP is after:
float calcDistAlongParallelLineAndIntersectPoint(const QVector2D& A, const QVector2D& B, const QVector2D& C, QVector2D& intersectPoint)
{
QVector2D v1 = B - A;
QVector2D v2 = C - A;
float v1DotV2 = QVector2D::dotProduct(v1, v2);
float magV1TimesMagV2 = v1.length()* v2.length();
float cosTheta = v1DotV2/magV1TimesMagV2;
float dist = v2.length() * cosTheta;
QVector2D intersectingPoint = C - v1*(dist/v1.length());
intersectPoint.setX(intersectingPoint.x());
intersectPoint.setY(intersectingPoint.y());
return dist;
}
答案2
得分: 0
我采用了稍微不同的方法,但Gremto的答案帮助了很多,并正确回答了问题,所以我将其标记为解决方案。
我使用了一个渐变函数来解决这个问题,我在这里找到了它:https://www.shadertoy.com/view/lscGDr
这是GLSL的版本,但这里是我使用three.js的Vector2的ts版本:
interface Line2D {
x1: number,
x2: number,
y1: number,
y2: number
}
const dummyLineStart = new Vector2(0, 0)
const dummyLineEnd = new Vector2(0, 0)
const dummyPoint = new Vector2(0, 0)
const dummyLineEndTranslated = new Vector2(0, 0)
// 提供一个在0和1之间的插值值,取决于点相对于一条线的平行位置
// 在线的起始点之前的点将返回1
function interpolatePointValueAlongLine(
line: Line2D,
pointX: number,
pointY: number
) {
// 使用可重用的向量以防止在每次调用时重新初始化类
dummyLineStart.set(line.x1, line.y1)
dummyLineEnd.set(line.x2, line.y2)
dummyPoint.set(pointX, pointY)
// 代码来自:https://www.shadertoy.com/view/lscGDr
dummyLineEndTranslated.set(line.x2, line.y2)
.sub(dummyLineStart)
return dummyPoint.sub(dummyLineStart)
.dot(dummyLineEndTranslated) /
dummyLineEndTranslated.dot(dummyLineEndTranslated)
}
英文:
I went in a slightly different direction but Gremto's answer helped a lot and correctly answered the question so I'm marking that as the solution.
I solved the problem using a gradient function that I found here: https://www.shadertoy.com/view/lscGDr
It's in GLSL but here's my ts version using three.js's Vector2
interface Line2D {
x1: number,
x2: number,
y1: number,
y2: number
}
const dummyLineStart = new Vector2(0, 0)
const dummyLineEnd = new Vector2(0, 0)
const dummyPoint = new Vector2(0, 0)
const dummyLineEndTranslated = new Vector2(0, 0)
//provides an interpolation value between 0 and 1 for a point depending on its
relative parallel position to a line
//points before the start of the line will return 1
function interpolatePointValueAlongLine(
line: Line2D,
pointX: number,
pointY: number
) {
//use reusable vecs to prevent reinitialising class every call
dummyLineStart.set(line.x1, line.y1)
dummyLineEnd.set(line.x2, line.y2)
dummyPoint.set(pointX, pointY)
//code from: https://www.shadertoy.com/view/lscGDr
dummyLineEndTranslated.set(line.x2, line.y2)
.sub(dummyLineStart)
return dummyPoint.sub(dummyLineStart)
.dot(dummyLineEndTranslated) /
dummyLineEndTranslated.dot(dummyLineEndTranslated)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论