2013-03-05 51 views
4

我一直在试图弄清楚这一点现在一段定义的..投影线的一个点得到2分

要解决的问题..

说我有3点..

P1 ---------- P2, and P3 can be anywhere around P1 and P2 

什么是计算公式,以便P3插入到P1和P2之间的线上?

我需要计算新的X中的公式,P3上P1和P2之间的界线落在Y坐标..

我的代码到目前为止..

 public Point lerp(Point P0, Point P1, Point P) 
     { 
      double y1 = P0.Y + (P1.Y - P0.Y) * ((P.X - P0.X)/(P1.X - P0.X)); 
      double x1 = P.X; 

      double y2 = P.Y; 
      double x2 = P0.X + (P1.X - P0.X) * ((P.Y - P0.Y)/(P1.Y - P0.Y)); 

      return new Point((x1 + x2)/2, (y1 + y2)/2); 
     } 

而我参考.. http://en.wikipedia.org/wiki/Linear_interpolation

上面的代码得到它接近,但其微客...

下面是转换的JavaScript代码来自Corey Ogburn

 public Point _pointOnLine(Point pt1, Point pt2, Point pt) 
     { 
      bool isValid = false; 

      var r = new Point(0, 0); 
      if (pt1.Y == pt2.Y && pt1.X == pt2.X) { pt1.Y -= 0.00001; } 

      var U = ((pt.Y - pt1.Y) * (pt2.Y - pt1.Y)) + ((pt.X - pt1.X) * (pt2.X - pt1.X)); 

      var Udenom = Math.Pow(pt2.Y - pt1.Y, 2) + Math.Pow(pt2.X - pt1.X, 2); 

      U /= Udenom; 

      r.Y = pt1.Y + (U * (pt2.Y - pt1.Y)); 
      r.X = pt1.X + (U * (pt2.X - pt1.X)); 

      double minx, maxx, miny, maxy; 

      minx = Math.Min(pt1.Y, pt2.Y); 
      maxx = Math.Max(pt1.Y, pt2.Y); 

      miny = Math.Min(pt1.X, pt2.X); 
      maxy = Math.Max(pt1.X, pt2.X); 

      isValid = (r.Y >= minx && r.Y <= maxx) && (r.X >= miny && r.X <= maxy); 

      return isValid ? r : new Point(); 
     } 
+1

嗯......你的意思'P3'是一些任意点(可能_not_就行了),并投上找到该行的一个点?就像投下阴影一样?所以考虑到投影点'P4',你可以从'P1P2'绘制一条垂直线并且它会碰到'P3'? – 2013-03-05 19:26:26

+0

是的,这正是我想要做的。 – 2013-03-05 19:29:00

+0

我已更改标题以匹配您的评论 - 随时恢复。 – 2013-03-05 19:33:37

回答

4

下面是我们在工作中使用的一些javascript代码(一家GIS公司)在用户想要分割线的情况下找出鼠标在一条线上的最近点添加一个顶点。应该很容易移动到C#:

function _pointOnLine(line1, line2, pt) { 
    var isValid = false; 

    var r = new Microsoft.Maps.Location(0, 0); 
    if (line1.latitude == line2.latitude && line1.longitude == line2.longitude) line1.latitude -= 0.00001; 

    var U = ((pt.latitude - line1.latitude) * (line2.latitude - line1.latitude)) + ((pt.longitude - line1.longitude) * (line2.longitude - line1.longitude)); 

    var Udenom = Math.pow(line2.latitude - line1.latitude, 2) + Math.pow(line2.longitude - line1.longitude, 2); 

    U /= Udenom; 

    r.latitude = line1.latitude + (U * (line2.latitude - line1.latitude)); 
    r.longitude = line1.longitude + (U * (line2.longitude - line1.longitude)); 

    var minx, maxx, miny, maxy; 

    minx = Math.min(line1.latitude, line2.latitude); 
    maxx = Math.max(line1.latitude, line2.latitude); 

    miny = Math.min(line1.longitude, line2.longitude); 
    maxy = Math.max(line1.longitude, line2.longitude); 

    isValid = (r.latitude >= minx && r.latitude <= maxx) && (r.longitude >= miny && r.longitude <= maxy); 

    return isValid ? r : null; 
} 

line1是用经纬度来表示该行的终点之一,相当于你的P1点。 line2是另一个端点:P2。 pt是你的P3。这将返回P3垂直通过的线上的点。如果P3通过线的任一端,则这将返回null,这意味着两个端点中的一个是最接近P3的点。

为清楚:

enter image description here

+0

听起来就像我需要的..去转换它,并给它一个镜头..谢谢 – 2013-03-05 20:02:52

+0

这工作..真棒..谢谢:) – 2013-03-05 20:10:55

3

问题是你Point对X和Y有整数值,所以你在做整数除法。尝试将您的值转换为floatdouble,进行计算,然后将其返回给整数。

注意,当你这样做: (P1.Y - P0.Y)*((PX - P0.X)/(P1.X - P0.X)) 你actualy失去了,因为精度5/2的结果是2,而不是2.5,但是当你的值是实数时,5.0/2.0确实是2.5。

你应该试试这个:

double y1 = P0.Y + (double)(P1.Y - P0.Y) * ((double)(P.X - P0.X)/(double)(P1.X - P0.X)); 
double x1 = P.X; //these two are implicit casts 

double y2 = P.Y; 
double x2 = P0.X + (double)(P1.X - P0.X) * ((double)(P.Y - P0.Y)/(double)(P1.Y - P0.Y)); 

return new Point((x1 + x2)/2.0, (y1 + y2)/2.0); //put 2.0 for any case even though x1+x2 is `double` 

而且,那么你是从双为int转换,数字的小数部分被自动切断,例如3.87会变成3比你的最后一行应该是更精确的,如果你可以使用这个:

return new Point((x1 + x2)/2.0 + 0.5, (y1 + y2)/2.0 + 0.5); 

这将有效地舍入double值到更接近的整数值。

编辑:

但如果你只是想找到两个点之间的连线P3点,比它更容易使用这种方法:

public Point lerp(Point P0, Point P1) 
{ 
     double x = ((double)P0.X + P1.X)/2.0; 

     double y = (double)P0.Y + (double)(P1.Y - P0.Y) * ((double)(x - P0.X)/(double)(P1.X - P0.X)); 
     return new Point(x + 0.5, y + 0.5); 
} 
+0

我试过了,基本上结果是一模一样的.. – 2013-03-05 19:38:53

+0

谢谢,这绝对有帮助..但也许不是我正在寻找的答案..我会在记住一个更好的公式时记住这一点。 。 – 2013-03-05 19:44:28

+0

@ChrisFazzio检查编辑的答案。 MU和Real刚刚开始,所以我会关闭:-D – 2013-03-05 19:49:27