Feedback

Vom Polygonzug zum Rohr

Sprache: C#

Aus einer Liste, deren Punkte ein Polygonzug definieren, wird eine neue Liste von Punkten erstellt, die einfach der Methode Graphics.DrawLines(…) übergeben werden muss. Und schwupp wird ein Rohr gezeichnet :) Aufgerufen werden muss nur die Methode "GetTubePath".
internal static List<PointF> GetTubePath(List<PointF> Points, int move)
        {
            List<PointF> output = new List<PointF>();
            PointF p11, p12, p21, p22 = PointF.Empty, intercept;
            double ang1, ang2;
            Direction dir1, dir2;

            if (Points.Count == 2)
            {
                ang1 = AngelCalc(Points[0], Points[1]);
                dir1 = Forward(Points[0], Points[1]);
                p11 = MovePoint(Points[0], ang1 + (int)dir1, move);
                p22 = MovePoint(Points[1], ang1 + (int)dir1, move);

                output.Add(p11); 
            }
            else
            {
                for (int i = 0; i < Points.Count - 2; i++)
                {
                    ang1 = AngelCalc(Points[i], Points[i + 1]);
                    dir1 = Forward(Points[i], Points[i + 1]);
                    p11 = MovePoint(Points[i], ang1 + (int)dir1, move);
                    p12 = MovePoint(Points[i + 1], ang1 + (int)dir1, move);

                    ang2 = AngelCalc(Points[i + 1], Points[i + 2]);
                    dir2 = Forward(Points[i + 1], Points[i + 2]);
                    p21 = MovePoint(Points[i + 1], ang2 + (int)dir2, move);
                    p22 = MovePoint(Points[i + 2], ang2 + (int)dir2, move);

                    if (i == 0)
                        output.Add(p11);
                    else
                    {
                        intercept = GetIntersectPoint(p11, p12, p21, p22);
                        output.Add(intercept);
                    }
                }
            }
            output.Add(p22);
            output.AddRange(Points.Reverse<PointF>());
            output.Add(output[0]);
            return output;
        }

 internal static PointF MovePoint(PointF p, double α, int move)
        {
            PointF point = new PointF();
            point.X = p.X + (float)(Math.Cos(α * Math.PI / 180) * move);
            point.Y = p.Y + (float)(Math.Sin(α * Math.PI / 180) * move);
            return point;
        }
        

        internal enum Direction { Forward = 90, Backward = 270 }

        internal static Direction Forward(PointF p1, PointF p2)
        {
            if (p2.X > p1.X) return Direction.Forward;
            else return Direction.Backward;
        }

 internal static PointF GetIntersectPoint(PointF P1, PointF P2, PointF B1, PointF B2)
        {
            PointF intersect = new PointF();
            float numerator = -P1.Y + B1.Y - ((B1.X - P1.X) * (P2.Y - P1.Y) / (P2.X - P1.X)),

                  denominator = ((B2.X - B1.X) / (P2.X - P1.X)) * (P2.Y - P1.Y) - (B2.Y - B1.Y);

            float fraction = numerator / denominator ;
            intersect.X = B1.X + fraction * (B2.X - B1.X);
            intersect.Y = B1.Y + fraction * (B2.Y - B1.Y);
            return intersect;
        }

 internal static double AngelCalc(PointF P1, PointF P2)
        {
            if (P1.X > P2.X) return AngelCalc(P2, P1);

            float dy = P2.Y - P1.Y;
            float dx = P2.X - P1.X;

            if (dx == 0 && dy != 0)
            {
                if (P1.Y < P2.Y)
                    return 90f;
                else
                    return 270f;
            }
            if (dy == 0 && dx != 0)
            {
                if (P1.X < P2.X)
                    return 0f;
                else
                    return 180f;
            }
            double ang2 = Math.Atan((dy) / (dx)) * (180 / Math.PI);

            return ang2 ;
        }
internal static List<PointF> GetTubePath(List<PointF> Points, int move)
        {
            List<PointF> output = new List<PointF>();
            PointF p11, p12, p21, p22 = PointF.Empty, intercept;
            double ang1, ang2;
            Direction dir1, dir2;

            if (Points.Count == 2)
            {
                ang1 = AngelCalc(Points[0], Points[1]);
                dir1 = Forward(Points[0], Points[1]);
                p11 = MovePoint(Points[0], ang1 + (int)dir1, move);
                p22 = MovePoint(Points[1], ang1 + (int)dir1, move);

                output.Add(p11); 
            }
            else
            {
                for (int i = 0; i < Points.Count - 2; i++)
                {
                    ang1 = AngelCalc(Points[i], Points[i + 1]);
                    dir1 = Forward(Points[i], Points[i + 1]);
                    p11 = MovePoint(Points[i], ang1 + (int)dir1, move);
                    p12 = MovePoint(Points[i + 1], ang1 + (int)dir1, move);

                    ang2 = AngelCalc(Points[i + 1], Points[i + 2]);
                    dir2 = Forward(Points[i + 1], Points[i + 2]);
                    p21 = MovePoint(Points[i + 1], ang2 + (int)dir2, move);
                    p22 = MovePoint(Points[i + 2], ang2 + (int)dir2, move);

                    if (i == 0)
                        output.Add(p11);
                    else
                    {
                        intercept = GetIntersectPoint(p11, p12, p21, p22);
                        output.Add(intercept);
                    }
                }
            }
            output.Add(p22);
            output.AddRange(Points.Reverse<PointF>());
            output.Add(output[0]);
            return output;
        }

 internal static PointF MovePoint(PointF p, double α, int move)
        {
            PointF point = new PointF();
            point.X = p.X + (float)(Math.Cos(α * Math.PI / 180) * move);
            point.Y = p.Y + (float)(Math.Sin(α * Math.PI / 180) * move);
            return point;
        }
        

        internal enum Direction { Forward = 90, Backward = 270 }

        internal static Direction Forward(PointF p1, PointF p2)
        {
            if (p2.X > p1.X) return Direction.Forward;
            else return Direction.Backward;
        }

 internal static PointF GetIntersectPoint(PointF P1, PointF P2, PointF B1, PointF B2)
        {
            PointF intersect = new PointF();
            float numerator = -P1.Y + B1.Y - ((B1.X - P1.X) * (P2.Y - P1.Y) / (P2.X - P1.X)),

                  denominator = ((B2.X - B1.X) / (P2.X - P1.X)) * (P2.Y - P1.Y) - (B2.Y - B1.Y);

            float fraction = numerator / denominator ;
            intersect.X = B1.X + fraction * (B2.X - B1.X);
            intersect.Y = B1.Y + fraction * (B2.Y - B1.Y);
            return intersect;
        }

 internal static double AngelCalc(PointF P1, PointF P2)
        {
            if (P1.X > P2.X) return AngelCalc(P2, P1);

            float dy = P2.Y - P1.Y;
            float dx = P2.X - P1.X;

            if (dx == 0 && dy != 0)
            {
                if (P1.Y < P2.Y)
                    return 90f;
                else
                    return 270f;
            }
            if (dy == 0 && dx != 0)
            {
                if (P1.X < P2.X)
                    return 0f;
                else
                    return 180f;
            }
            double ang2 = Math.Atan((dy) / (dx)) * (180 / Math.PI);

            return ang2 ;
        }