【问题标题】:How can I calculate a point perpendicular to a point on another line, at a given distance, in C#?如何在 C# 中以给定距离计算垂直于另一条线上的点的点?
【发布时间】:2014-07-18 07:07:48
【问题描述】:

我有一个中点p1,用于沿着角度A创建一条线:

double startX = p1.X - lineHalfLength * Math.Cos(-A * Math.PI/180);
double endX = p1.X + lineHalfLength * Math.Cos(-A * Math.PI/180);

double startY = p1.Y - lineHalfLength * Math.Sin(-A * Math.PI/180);
double endY = p1.Y + lineHalfLength* Math.Sin(-A * Math.PI/180);

到目前为止一切顺利。

现在我需要创建一条与第一条平行的新线,距离 D 垂直。

一旦我确定了新线的中点 p2,我就可以创建线(与上面的逻辑相同),但是得到那个点是在逃避我,高中三角学太久以前了。这是我目前的尝试:

p2.X = p1.X + D * Math.Cos((A + 90) * Math.PI/180);
p2.Y = p1.Y + D * Math.Sin((A + 90) * Math.PI/180);

这几乎适用于 45 度,但仅此而已。

我在这里错过了什么?

【问题讨论】:

  • 一张照片会走很长一段路:)
  • 您在创建垂直线时遇到问题吗?或者您在使垂直线的长度正确时遇到问题?
  • X坐标不应该是D * Math.Cos吗?
  • 你真的应该开始用弧度工作

标签: c# math trigonometry vector-graphics


【解决方案1】:

您有正确的想法,将您使用的角度添加 90 度,但您使用的角度是从水平线的左侧顺时针测量的,而惯例是从水平线的右手侧逆时针测量.

按照通常的角度约定,我本来希望看到更像这样的代码来查找线端

double startX = p1.X - lineHalfLength * Math.Cos(A * Math.PI/180);
double endX = p1.X + lineHalfLength * Math.Cos(A * Math.PI/180);

double startY = p1.Y - lineHalfLength * Math.Sin(A * Math.PI/180);
double endY = p1.Y + lineHalfLength* Math.Sin(A * Math.PI/180);

在这种情况下,将 90 添加到 A 应该可以正常工作。

(注意cos(-x)=cos(x)sin(-x)=-sin(x)

保持您的角度约定,将您的代码包装到一个直线函数中,然后您可以将 90 度添加到您传递给您自己的函数的角度

void LineFromMidpoint(double A, Point p1, double dist, out Point p2, out Point p3)
{
    double startX = p1.X - dist * Math.Cos(-A * Math.PI/180);
    double endX = p1.X + dist * Math.Cos(-A * Math.PI/180);

    double startY = p1.Y - dist * Math.Sin(-A * Math.PI/180);
    double endY = p1.Y + dist* Math.Sin(-A * Math.PI/180);

    p2 = new Point {X=startX, Y=startY};
    p3 = new Point {X=endX, Y=endY};
}

调用一次得到原线的端点p2,再调用一次得到垂直线的端点p3,再调用两次得到平行线的端点p4, p5

void Main()
{
    Point p1 = new Point {X=10, Y=5};
    Point p2start, p2end;
    double A=15;
    double lineHalfLength = 10;
    LineFromMidpoint(A, p1, lineHalfLength, out p2start, out p2end);
    Console.WriteLine("p1={0}, p2={1}, p3={2}", p1, p2start, p2end);

    double B=A+90;
    double perpDist=2;
    Point p3firstMidpoint, p3secondMidpoint;
    LineFromMidpoint(B, p1, perpDist, out p3firstMidpoint, out p3secondMidpoint);
    Console.WriteLine("p3firstMidpoint={0}, p3secondMidpoint={1}",
        p3firstMidpoint, p3secondMidpoint);

    Point p4start, p4end;
    LineFromMidpoint(A, p3firstMidpoint, lineHalfLength, out p4start, out p4end);
    Console.WriteLine("p4start={0}, p4end={1}", p4start, p4end);

    Point p5start, p5end;
    LineFromMidpoint(A, p3secondMidpoint, lineHalfLength, out p5start, out p5end);
    Console.WriteLine("p5start={0}, p5end={1}", p5start, p5end);
}

绘制点结果

原线末端(黑色)、垂直线末端(红色)、平行线(蓝色和绿色)。

【讨论】:

  • 很好地使用 DRY,这似乎解决了所有奇怪的 +/-、sin/cos 等问题。
【解决方案2】:

这几乎适用于 45 度

这是因为SIN(45)COS(45) 相等,而您在X 计算中使用了错误的值:

p2.X = p1.X + D * Math.Cos((A + 90) * Math.PI/180);
p2.Y = p1.Y + D * Math.Sin((A + 90) * Math.PI/180);

【讨论】:

  • 已经试过了。对于角度 != 45,没有 sin/cos 的组合返回正确的结果。
  • 为我工作了 30 度角。您可以在问题中添加示例输入和预期输出。
  • 我能够得到 0-90 的答案,但距离很不稳定。我认为要使这个问题有意义,我需要将代码转换为生成 SVG 的 Javascript。
猜你喜欢
  • 1970-01-01
  • 2011-02-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-24
  • 2019-12-16
相关资源
最近更新 更多