如何检测一条线上/周围的点(有一些偏移)

时间:2014-02-11 07:07:55

标签: math geometry 2d graphic

从A点到B点画一条线。让d偏移。让C指向要测试。

我将使用偏移量对该线进行一种命中测试。

如何围绕具有给定偏移的线进行命中测试。

Ex:A =(10,10),B(30,30),偏移= 2.选择C作为任意点。请参阅链接中的图片。

http://s10.postimg.org/6by2dzvax/reference.png

请帮帮我。

提前致谢。

4 个答案:

答案 0 :(得分:0)

查找C的偏移量 例如dx1和dy1。如果dy1 / dx1 = dy / dx,则你的C击中该线。 对于段,您还应检查是否dx1< dx或dy1< DY

答案 1 :(得分:0)

换句话说,您要检查该点C是否位于特定矩形内,尺寸为2*d|A-B|+2*d
您需要将该行表示为u*x+v*y+w=0,这可以通过

来完成
u = A.y-B.y
v = B.x-A.x
w = A.x*B.y - A.y * B.x

然后C与该行的(签名)距离为

d = (u*C.x + v*C.y +w) / sqrt( u*u+v*v)

您将abs(d)与偏移量进行比较。

下一步是检查C在线方向上的位置。为此,您将正交线u2*x+v2*y+w2=0

一起考虑
u2 = v
v2 = -u
w2 = -u2*(A.x+B.x)/2 - v2*(A.y+B.y)/2

和距离

d2 = (u2 * C.x + v2 * C.y + w2 ) / sqrt( u2*u2+v2*v2 )

必须将此距离与线的长度+偏移量进行比较:

abs(d2) < |A-B| / 2 + offset

答案 2 :(得分:0)

一个方便的技巧是旋转和平移平面,使得AB段映射到段(0, 0)-(0, L)(就像在图像上一样),L是段长度。

如果将相同的变换应用于C,那么在矩形中测试包含是一件非常简单的事情。

有用的转换由:

给出
x = ((X - XA).(XB - XA) + (Y - YA).(YB - YA)) / L
y = ((X - XA).(YB - YA) - (Y - YA).(XB - XA)) / L

答案 3 :(得分:0)

也许您可以使用此功能来计算点到线的最短距离。如果距离是&lt; = offset,则该点击中该线。

    private double pointDistanceToLine(PointF line1, PointF line2, PointF pt) 
    { 
        var isValid = false;

        PointF r = new PointF(); 
        if (line1.Y == line2.Y && line1.X == line2.X) 
            line1.Y -= 0.00001f;

        double U = ((pt.Y - line1.Y ) * (line2.Y - line1.Y )) + ((pt.X - line1.X) * (line2.X - line1.X));

        double Udenom = Math.Pow(line2.Y - line1.Y , 2) + Math.Pow(line2.X - line1.X, 2);

        U /= Udenom;

        r.Y = (float)(line1.Y + (U * (line2.Y - line1.Y ))); r.X = (float)(line1.X + (U * (line2.X - line1.X)));

        double minX, maxX, minY , maxY ;

        minX = Math.Min(line1.Y , line2.Y ); 
        maxX = Math.Max(line1.Y , line2.Y );

        minY = Math.Min(line1.X, line2.X); 
        maxY = Math.Max(line1.X, line2.X);

        isValid = (r.Y >= minX && r.Y <= maxX) && (r.X >= minY && r.X <= maxY );

        //return isValid ? r : null; 
        if (isValid) 
        { 
            double result = Math.Pow((pt.X - r.X), 2) + Math.Pow((pt.Y - r.Y), 2); 
            result = Math.Sqrt(result); 
            return result; 
        } 
        else { 
            double result1 = Math.Pow((pt.X - line1.X), 2) + Math.Pow((pt.Y - line1.Y), 2); 
            result1 = Math.Sqrt(result1); 
            double result2 = Math.Pow((pt.X - line2.X), 2) + Math.Pow((pt.Y - line2.Y), 2); 
            result2 = Math.Sqrt(result2);

            return Math.Min(result1, result2); 
        } 
    }