天天看点

给出轨迹折线的中间线,求出轨迹(绘制平行线)

给出轨迹折线的中间线,求出轨迹(绘制平行线)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DrawRoadAnd.Control
{
    using System.Windows;
    using Point2D = System.Windows.Point;
    public class DrawParallelLines
    {        
        private static void GetParallelLine(Point2D inSPos, Point2D inEPos, double inWidth, bool IsLeft, out Point2D outSPos, out Point2D outEPos)
        {
            Vector v1 = new Vector(inEPos.X - inSPos.X, inEPos.Y - inSPos.Y);
            v1.Normalize();
            Vector n1 = new Vector(-v1.Y, v1.X);
            
            if (IsLeft == false)
                n1 = -n1;
            n1 *= inWidth;
            outSPos = inSPos + n1;
            outEPos = inEPos + n1;
        }

        /// <summary>
        /// 计算两条直线的交点
        /// </summary>
        /// <param name="SLine1">L1的点1坐标</param>
        /// <param name="ELine1">L1的点2坐标</param>
        /// <param name="SLine2">L2的点1坐标</param>
        /// <param name="ELine2">L2的点2坐标</param>
        /// <returns></returns>
        private static Point2D GetIntersection(Point2D SLine1, Point2D ELine1, Point2D SLine2, Point2D ELine2)
        {
            /*
             * L1,L2都存在斜率的情况:
             * 直线方程L1: ( y - y1 ) / ( y2 - y1 ) = ( x - x1 ) / ( x2 - x1 ) 
             * => y = [ ( y2 - y1 ) / ( x2 - x1 ) ]( x - x1 ) + y1
             * 令 a = ( y2 - y1 ) / ( x2 - x1 )
             * 有 y = a * x - a * x1 + y1   .........1
             * 直线方程L2: ( y - y3 ) / ( y4 - y3 ) = ( x - x3 ) / ( x4 - x3 )
             * 令 b = ( y4 - y3 ) / ( x4 - x3 )
             * 有 y = b * x - b * x3 + y3 ..........2
             * 
             * 如果 a = b,则两直线平等,否则, 联解方程 1,2,得:
             * x = ( a * x1 - b * x3 - y1 + y3 ) / ( a - b )
             * y = a * x - a * x1 + y1
             * 
             * L1存在斜率, L2平行Y轴的情况:
             * x = x3
             * y = a * x3 - a * x1 + y1
             * 
             * L1 平行Y轴,L2存在斜率的情况:
             * x = x1
             * y = b * x - b * x3 + y3
             * 
             * L1与L2都平行Y轴的情况:
             * 如果 x1 = x3,那么L1与L2重合,否则平等
             * 
            */
            double a = 0, b = 0;
            int state = 0;
            if (SLine1.X != ELine1.X)
            {
                a = (ELine1.Y - SLine1.Y) / (ELine1.X - SLine1.X);
                state |= 1;
            }
            if (SLine2.X != ELine2.X)
            {
                b = (ELine2.Y - SLine2.Y) / (ELine2.X - SLine2.X);
                state |= 2;
            }
            switch (state)
            {
                case 0: //L1与L2都平行Y轴
                    {
                        if (SLine1.X == SLine2.X)
                        {
                            //throw new Exception("两条直线互相重合,且平行于Y轴,无法计算交点。");
                            return new Point2D(0, 0);
                        }
                        else
                        {
                            //throw new Exception("两条直线互相平行,且平行于Y轴,无法计算交点。");
                            return new Point2D(0, 0);
                        }
                    }
                case 1: //L1存在斜率, L2平行Y轴
                    {
                        double x = SLine2.X;
                        double y = (SLine1.X - x) * (-a) + SLine1.Y;
                        return new Point2D(x, y);
                    }
                case 2: //L1 平行Y轴,L2存在斜率
                    {
                        double x = SLine1.X;
                        //网上有相似代码的,这一处是错误的。你可以对比case 1 的逻辑 进行分析
                        //源code:lineSecondStar * x + lineSecondStar * lineSecondStar.X + p3.Y;
                        double y = (SLine2.X - x) * (-b) + SLine2.Y;
                        return new Point2D(x, y);
                    }
                case 3: //L1,L2都存在斜率
                    {
                        if (a == b)
                        {
                            // throw new Exception("两条直线平行或重合,无法计算交点。");
                            return new Point2D(0, 0);
                        }
                        double x = (a * SLine1.X - b * SLine2.X - SLine1.Y + SLine2.Y) / (a - b);
                        double y = a * x - a * SLine1.X + SLine1.Y;
                        return new Point2D(x, y);
                    }
            }
            return new Point2D(0, 0);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="inLines"></param>
        /// <param name="width"></param>
        /// <param name="IsLeft"></param>
        /// <returns></returns>
        public static List<Point2D> GetParallelLines(List<Point2D> inLines, double width, bool IsLeft)
        {
            List<Point2D> tempPoints = new List<Point2D>();
            for (int i = 0; i < inLines.Count - 1; i++)
            {
                Point2D p1, p2, p3, p4;
                
                if (tempPoints.Count == 0)
                {
                    GetParallelLine(inLines[0], inLines[1], width, IsLeft, out p1, out p2);
                    tempPoints.Add(p1); tempPoints.Add(p2);
                    continue;
                }
                if (inLines[i].X == inLines[i + 1].X && inLines[i].Y == inLines[i + 1].Y)
                {
                    continue;
                }
                GetParallelLine(inLines[i], inLines[i+1], width, IsLeft, out p3, out p4);                
                Point2D IntersectPoint = GetIntersection(tempPoints[tempPoints.Count - 2], tempPoints[tempPoints.Count - 1], p3, p4);
                tempPoints.RemoveAt(tempPoints.Count - 1);
                tempPoints.Add(IntersectPoint);
                tempPoints.Add(p4);
            }
            return tempPoints;
        }
    }
}