포인트가 특정 줄에 속하는지 어떻게 알 수 있습니까?
문제
포인트가 특정 줄에 속하는지 어떻게 알 수 있습니까?
가능하면 예제에 감사합니다.
해결책
가장 간단한 형태로 좌표를 선 방정식에 연결하고 평등을 확인하십시오.
주어진:
Point p (X=4, Y=5)
Line l (Slope=1, YIntersect=1)
X와 Y를 연결합니다.
Y = Slope * X + YIntersect
=> 5 = 1 * 4 + 1
=> 5 = 5
그렇습니다. 요점은 줄에 있습니다.
라인이 (x1, y1), (x2, y2) 형태로 표시되면 다음과 같이 기울기를 계산할 수 있습니다.
Slope = (y1 - y2) / (x1-x2)
그런 다음 y-intersect를 가져옵니다.
YIntersect = - Slope * X1 + Y1;
편집 : y-intersect를 수정했습니다 (x1 / y1입니다 ...)
당신은 그것을 확인해야합니다 x1 - x2
아니다 0
. 그것이 있다면, 포인트가 줄에 있는지 확인하는 것은 포인트의 y 값이 어느 쪽인지 확인하는 간단한 문제입니다. x1
또는 x2
. 또한 포인트의 X가 'x1'또는 'x2'가 아닌지 확인하십시오.
다른 팁
방금 드로잉 응용 프로그램 에서이 점검을 사용한 이후 몇 가지 추가 요구 사항을 처리하는 기능을 작성했습니다.
- 퍼지 - 함수는 라인을 클릭하여 선을 선택하는 데 사용되므로 오류의 공간이 있어야합니다.
- 선은 끝점과 시작점, 무한 선이 없습니다.
- 직선 수직 및 수평선을 처리해야합니다.
private const double SELECTION_FUZZINESS = 3;
internal override bool ContainsPoint(Point point)
{
LineGeometry lineGeo = geometry as LineGeometry;
Point leftPoint;
Point rightPoint;
// Normalize start/end to left right to make the offset calc simpler.
if (lineGeo.StartPoint.X <= lineGeo.EndPoint.X)
{
leftPoint = lineGeo.StartPoint;
rightPoint = lineGeo.EndPoint;
}
else
{
leftPoint = lineGeo.EndPoint;
rightPoint = lineGeo.StartPoint;
}
// If point is out of bounds, no need to do further checks.
if (point.X + SELECTION_FUZZINESS < leftPoint.X || rightPoint.X < point.X - SELECTION_FUZZINESS)
return false;
else if (point.Y + SELECTION_FUZZINESS < Math.Min(leftPoint.Y, rightPoint.Y) || Math.Max(leftPoint.Y, rightPoint.Y) < point.Y - SELECTION_FUZZINESS)
return false;
double deltaX = rightPoint.X - leftPoint.X;
double deltaY = rightPoint.Y - leftPoint.Y;
// If the line is straight, the earlier boundary check is enough to determine that the point is on the line.
// Also prevents division by zero exceptions.
if (deltaX == 0 || deltaY == 0)
return true;
double slope = deltaY / deltaX;
double offset = leftPoint.Y - leftPoint.X * slope;
double calculatedY = point.X * slope + offset;
// Check calculated Y matches the points Y coord with some easing.
bool lineContains = point.Y - SELECTION_FUZZINESS <= calculatedY && calculatedY <= point.Y + SELECTION_FUZZINESS;
return lineContains;
}
포인트 r = (rx, ry)가 줄 연결점 p = (px, py) 및 q = (qx, qy)에 있는지 여부를 결정하는 가장 좋은 방법은 매트릭스의 결정 요인을 확인하는 것입니다.
{{qx - px, qy - py}, {rx - px, ry - py}},
즉 (QX -PX) * (RY -PY) - (QY -PY) * (RX -PX)는 0에 가깝습니다.이 솔루션은 게시 된 다른 것보다 몇 가지 관련 이점이 있습니다. 첫째, 수직선에 대한 특별한 경우는 필요하지 않습니다. 둘째, 나누지 않고 (일반적으로 느린 작동), 셋째, 라인이 거의 수직 일 때 잘못된 부동 소수점 동작을 유발하지는 않습니다.
라인에 두 가지 점이 주어졌습니다 L0
그리고 L1
그리고 테스트 요점 P
.
(L1 - L0) * (P - L0)
n = (P - L0) - --------------------- (L1 - L0)
(L1 - L0) * (L1 - L0)
벡터의 표준 n
요점의 거리입니다 P
라인에서 L0
그리고 L1
. 이 거리가 0이거나 작은 경우 (반올림 오류의 경우) 점은 선 위에 있습니다.
상징물 *
도트 제품을 나타냅니다.
예시
P = (5, 5)
L0 = (0, 10)
L1 = (20, -10)
L1 - L0 = (20, -20)
P - L0 = (5, -5)
(20, -20) * (5, -5)
n = (5, -5) - --------------------- (20, -20)
(20, -20) * (20, -20)
200
= (5, -5) - --- (20, -20)
800
= (5, -5) - (5, -5)
= (0, 0)
패트릭 맥도날드 씨는 거의 정답을 썼고 이것이 그의 대답의 수정이라고 생각합니다.
public bool IsOnLine(Point endPoint1, Point endPoint2, Point checkPoint)
{
return (((double)checkPoint.Y - endPoint1.Y)) / ((double)(checkPoint.X - endPoint1.X))
== ((double)(endPoint2.Y - endPoint1.Y)) / ((double)(endPoint2.X - endPoint1.X));
}
물론 다른 많은 정답이 특히 많지만 조쉬 씨는 이것이 가장 좋은 것으로 나타났습니다.
Evryone에 감사드립니다.
y = m * x + c
이것은 선의 방정식입니다. X & Y는 코디네스입니다. 각 라인은 기울기 (m)와 y 축 (c)과 교차하는 곳으로 특징 지어집니다.
따라서 라인의 M & C가 주어지면, 지점 (x1, y1)이 방정식이 x = x1 및 y = y1에 대한 방정식을 확인하여 줄에 있는지 확인할 수 있습니다.
엔드 포인트로 정의 된 선이있는 경우
PointF pt1, pt2;
그리고 당신은 당신이 확인하고 싶은 지점이 있습니다
PointF checkPoint;
그런 다음 함수를 다음과 같이 정의 할 수 있습니다.
bool IsOnLine(PointF endPoint1, PointF endPoint2, PointF checkPoint)
{
return (checkPoint.Y - endPoint1.Y) / (endPoint2.Y - endPoint1.Y)
== (checkPoint.X - endPoint1.X) / (endPoint2.X - endPoint1.X);
}
다음과 같이 부릅니다.
if (IsOnLine(pt1, pt2, checkPoint) {
// Is on line
}
그래도 Zero의 분할을 확인해야합니다.
2D 라인은 일반적으로 두 변수 X와 Y의 방정식을 사용하여 표시됩니다. 여기에는 잘 알려진 방정식이 있습니다.
이제 GDI+ 라인이 (0,0)에서 (100, 100)에서 그려져 있다고 상상해보십시오. M = (0-100)/(0-100) = 1이므로 라인의 방정식은 y-0 = 1입니다. *(x-0) => y = x
이제 우리는 문제의 라인에 대한 방정식을 가지고 있기 때문에 포인트 가이 줄에 속하는지 테스트하기 쉽습니다. 주어진 점 (x3, y3)은 x = x3 및 y = y3을 대체 할 때 라인 방정식을 만족하면이 라인에 속합니다. 예를 들어, 점 (10, 10)은 10 = 10 이후이 줄에 속하지만 (10,12)는 12! = 10 이후이 줄에 속하지 않습니다.
참고 : 수직선의 경우 기울기 (m)의 값은 무한하지만이 특수한 경우에는 직접 x = c 인 수직선의 방정식을 사용할 수 있습니다. 여기서 c = x1 = x2.
비록 이것이 이것이 가장 효율적인 방법인지 확실하지 않습니다. 더 많은 시간이있을 때 더 효율적인 방법을 찾아 보겠습니다.
도움이 되었기를 바랍니다.
라인의 방정식은 다음과 같습니다.
y = mx + c
그래서이 방정식을 만족 시키면 포인트 (A, B) 가이 줄에 있습니다. b = ma + c
더 구체적 일 수 있습니까?
어떤 프로그래밍 언어에 대해 이야기하고 있습니까?
어떤 환경에 대해 이야기하고 있습니까?
당신은 어떤 "라인"에 대해 이야기하고 있습니까? 텍스트? 어떤 요점? 화면에 XY?
대안으로 slope/y-intercept
방법, 나는이 접근법을 사용하여 선택했다 Math.Atan2
:
// as an extension method
public static bool Intersects(this Vector2 v, LineSegment s) {
// check from line segment start perspective
var reference = Math.Atan2(s.Start.Y - s.End.Y, s.Start.X - s.End.X);
var aTanTest = Math.Atan2(s.Start.Y - v.Y, s.Start.X - v.X);
// check from line segment end perspective
if (reference == aTanTest) {
reference = Math.Atan2(s.End.Y - s.Start.Y, s.End.X - s.Start.X);
aTanTest = Math.Atan2(s.End.Y - v.Y, s.End.X - v.X);
}
return reference == aTanTest;
}
첫 번째 수표 reference
라인 세그먼트의 시작점에서 엔드 포인트까지 ArcTan을 결정합니다. 그런 다음 시작점 관점에서 ArcTan을 벡터로 결정합니다. v
.
이러한 값이 동일하면 엔드 포인트의 관점에서 확인합니다.
단순하고 손잡이 수평, 수직 및 그 사이의 모든 내용.