Vector 复制距离为d的路径的数学方法

Vector 复制距离为d的路径的数学方法,vector,path,copy,geometry,trigonometry,Vector,Path,Copy,Geometry,Trigonometry,我有一个关于复制路径所涉及的数学问题。 假设我有一条路径: 除了那条黑色的外,我还要一份这条路的精确副本。我编写了一个小型C#程序,用于计算两点之间的角度。根据角度,会添加到X或Y值的偏移。 这是一种工作,这是结果: 正如你所看到的,它并没有那么漂亮。 现在,我真正的问题是:什么是正确的数学 希望有人能给我一个答案,因为我在这个问题上有点纠结。 当做 萨沙 代码: void绘图(列出点) { Graphics g=pictureBox.CreateGraphics(); g、 清晰(颜色:白

我有一个关于复制路径所涉及的数学问题。 假设我有一条路径:

除了那条黑色的外,我还要一份这条路的精确副本。我编写了一个小型C#程序,用于计算两点之间的角度。根据角度,会添加到X或Y值的偏移。 这是一种工作,这是结果:

正如你所看到的,它并没有那么漂亮。 现在,我真正的问题是:什么是正确的数学

希望有人能给我一个答案,因为我在这个问题上有点纠结。 当做 萨沙

代码:

void绘图(列出点)
{
Graphics g=pictureBox.CreateGraphics();
g、 清晰(颜色:白色);
对于(int i=0;i=135)
{
点2.Add(新点(点[i].X-偏移量,点[i].Y));
}
如果(角度<135和角度>=90)
{
if(点[i].Y<点[i+1].Y)
{
点2.Add(新点(点[i].X-OFFSET/2,点[i].Y+OFFSET));
}
其他的
{
}                   
}
如果(角度<90和角度>=45)
{
if(点[i].Y<点[i+1].Y)
{
点2.Add(新点(点[i].X-偏移量,点[i].Y));
}
其他的
{
点2.Add(新点(点[i].X+偏移量,点[i].Y));
}
}
如果(角度<45和角度>=0)
{
if(点[i].Y<点[i+1].Y)
{
点2.Add(新点(点[i].X-偏移量,点[i].Y));
}
其他的
{
点2.Add(新点(点[i].X+偏移量,点[i].Y));
}
}
如果(角度<360和角度>=315)
{
if(点[i].Y<点[i+1].Y)
{
点2.Add(新点(点[i].X+偏移量,点[i].Y));
}
其他的
{
点2.Add(新点(点[i].X+10,点[i].Y-偏移));
}
}
如果(角度<315和角度>=270)
{
点2.Add(新点(点[i].X,点[i].Y-偏移量));
}
如果(角度<270和角度>=225)
{                    
if(点[i].Y<点[i+1].Y)
{
点2.Add(新点(点[i].X-OFFSET/2,点[i].Y-OFFSET));
}
其他的
{
}
}
如果(角度<225和角度>=180)
{
if(点[i].X<点[i+1].X)
{
点2.Add(新点(点[i].X,点[i].Y-偏移量));
}
其他的
{
如果(点[i].Y<点[i+1].Y)//\
{
点2.Add(新点(点[i].X-偏移量,点[i].Y));
}
其他的
{
}
}
}
}
对于(int i=0;i

我想如果我减小角度(从45度步进到30度),我可以预测结果,但一定有更好的解决方案。

我想解决这个问题的一个方法是将其分成线对(即:三个点)

找到一对中每条线的平行线(距离d)。然后找出这些平行线相交的位置,以确定新线上某个点的位置

在非常粗略的psuedo代码中:

points a, b, c
distance d

lineab = findLineParallelTo(line(a,b), d)
linebc = findLineParallelTo(line(b,c), d)

return intersect(lineab, linebc)

我想解决这个问题的一种方法是把它分成几对线(即:三个点)

找到一对中每条线的平行线(距离d)。然后找出这些平行线相交的位置,以确定新线上某个点的位置

在非常粗略的psuedo代码中:

points a, b, c
distance d

lineab = findLineParallelTo(line(a,b), d)
linebc = findLineParallelTo(line(b,c), d)

return intersect(lineab, linebc)

我从@Jack实现了解决方案,效果非常好:

public class Line
{
    public PointF P { get; private set; }
    public PointF Q { get; private set; }

    public float Pitch
    {
        get; private set;
    }

    public Line()
    {

    }

    public Line(float px, float py, float qx, float qy) : this(new PointF(px, py), new PointF(qx, qy))
    {

    }

    public Line(PointF p, PointF q)
    {
        P = p;
        Q = q;
    }

    #region Methods

    /// <summary>
    /// http://stackoverflow.com/questions/2825412/draw-a-parallel-line
    /// </summary>
    public Line FindParallelLine(float distance)
    {
        float length = (float)Math.Sqrt((P.X - Q.X) * (P.X - Q.X) + (P.Y - Q.Y) * (P.Y - Q.Y));

        // This is the second line
        float px = P.X + distance * (Q.Y - P.Y) / length;
        float qx = Q.X + distance * (Q.Y - P.Y) / length;
        float py = P.Y + distance * (P.X - Q.X) / length;
        float qy = Q.Y + distance * (P.X - Q.X) / length;

        return new Line(px, py, qx, qy);
    }        

    public override string ToString()
    {
        return string.Format("P({0}|{1}), Q({2}|{3}) - Pitch: {4}", P.X, P.Y, Q.X, Q.Y, Pitch);
    }

    #endregion
}

private PointF FindIntersection(Line a, Line b)
    {
        PointF A = a.P;
        PointF B = a.Q;
        PointF C = b.P;
        PointF D = b.Q;

        float dy1 = B.Y - A.Y;
        float dx1 = B.X - A.X;
        float dy2 = D.Y - C.Y;
        float dx2 = D.X - C.X;            

        // Check whether the two line parallel.
        if (dy1 * dx2 == dy2 * dx1)
        {
            return PointF.Empty;
        }
        else
        {
            float x = ((C.Y - A.Y) * dx1 * dx2 + dy1 * dx2 * A.X - dy2 * dx1 * C.X) / (dy1 * dx2 - dy2 * dx1);
            float y = A.Y + (dy1 / dx1) * (x - A.X);
            return new PointF(x, y);
        }
    }

    private PointF FindIntersection(PointF a, PointF b, PointF c, float distance)
    {
        Line line1 = new Line(a, b);
        Line line2 = new Line(b, c);

        Line parallel = line1.FindParallelLine(distance);
        Line parallel2 = line2.FindParallelLine(distance);

        return FindIntersection(parallel, parallel2);
    }

    private List<PointF> FindIntersections(PointF[] points, float distance)
    {
        List<PointF> intersections = new List<PointF>();

        for (int i = 0; i < points.Length - 2; i++)
        {
            PointF intersection = FindIntersection(points[i], points[i + 1], points[i + 2], distance);
            if (!intersection.IsEmpty && !double.IsNaN(intersection.X) && !double.IsNaN(intersection.Y))
            {
                intersections.Add(intersection);
            }                
        }

        return intersections;
    }

    private PointF GetFirstPoint(PointF[] points, float distance)
    {
        Line parallel = new Line(points[0], points[1]).FindParallelLine(distance);
        return parallel.P;
    }

    private PointF GetLastPoint(PointF[] points, float distance)
    {
        Line parallel = new Line(points[points.Length - 2], points[points.Length - 1]).FindParallelLine(distance);
        return parallel.Q;
    }
公共类行
{
公共点f P{get;私有集;}
公共点f Q{get;私有集;}
公众浮球
{
获得;私人设置;
}
公共电话线()
{
}
公共行(float px,float py,float qx,float qy):这个(新点f(px,py),新点f(qx,qy))
{
}
公共线路(点F p、点F q)
{
P=P;
Q=Q;
}
#区域方法
/// 
/// http://stackoverflow.com/questions/2825412/draw-a-parallel-line
/// 
公用线路FindParalleline(浮动距离)
{
浮点长度=(浮点)数学Sqrt((P.X-Q.X)*(P.X-Q.X)+(P.Y-Q.Y)*(P.Y-Q.Y));
//这是第二行
浮动px=P.X+距离*(Q.Y-P.Y)/长度;
浮动qx=Q.X+距离*(Q.Y-P.Y)/长度;
浮动py=P.Y+距离*(P.X-Q.X)/长度;
浮动qy=Q.Y+距离*(P.X-Q.X)/长度;
返回新行(px、py、qx、qy);
}        
公共重写字符串ToString()
{
返回string.Format(“P({0}{1})、Q({2}{3})-音高:{4}”、P.X、P.Y、Q.X、Q.Y、音高);
}
#端区
}
专用点F FindIntersection(a行、b行)
{
点F A=A.P;
点F B=a.Q;
点F C=b.P;
点F D=b.Q;
浮动dy1=B.Y-A.Y;
浮点数dx1=B.X-
OFFSET = float.Parse(textBox1.Text);
        List<PointF> points = new List<PointF>();
        points.Add(new PointF(200, 180));
        points.Add(new PointF(160, 160));
        points.Add(new PointF(100, 160));
        points.Add(new PointF(60, 140));
        points.Add(new PointF(40, 100));
        points.Add(new PointF(80, 60));
        points.Add(new PointF(140, 100));
        points.Add(new PointF(180, 140));
        points.Add(new PointF(220, 80));

        List<PointF> intersections = FindIntersections(points.ToArray(), OFFSET);
        intersections.Insert(0, GetFirstPoint(points.ToArray(), OFFSET));
        intersections.Add(GetLastPoint(points.ToArray(), OFFSET));

        Graphics g = pictureBox.CreateGraphics();
        g.Clear(Color.White);

        g.DrawLines(Pens.Black, points.ToArray());
        // Connect the intersection points.
        g.DrawLines(Pens.Red, intersections.ToArray());