예제 #1
0
        /// <summary>
        /// Overrides <see cref="CADability.Curve2D.GeneralCurve2D.Copy (ICurve2D)"/>
        /// </summary>
        /// <param name="toCopyFrom"></param>
        public override void Copy(ICurve2D toCopyFrom)
        {
            Polyline2D c = toCopyFrom as Polyline2D;

            this.vertex = (GeoPoint2D[])c.vertex.Clone();
            UserData.CloneFrom(c.UserData);
        }
예제 #2
0
        /// <summary>
        /// Overrides <see cref="CADability.Curve2D.GeneralCurve2D.Clone ()"/>
        /// </summary>
        /// <returns></returns>
        public override ICurve2D Clone()
        {
            Polyline2D res = new Polyline2D(vertex);

            res.UserData.CloneFrom(this.UserData);
            return(res);
        }
예제 #3
0
        public override ICurve2D GetModified(ModOp2D m)
        {
            Polyline2D res = this.Clone() as Polyline2D;

            res.Modify(m);
            return(res);
        }
예제 #4
0
        /// <summary>
        /// Overrides <see cref="CADability.Curve2D.GeneralCurve2D.CloneReverse (bool)"/>
        /// </summary>
        /// <param name="reverse"></param>
        /// <returns></returns>
        public override ICurve2D CloneReverse(bool reverse)
        {
            Polyline2D res = (Polyline2D)this.Clone();

            if (reverse)
            {
                res.Reverse();
            }
            return(res);
        }
예제 #5
0
        /// <summary>
        /// Overrides <see cref="CADability.Curve2D.GeneralCurve2D.Trim (double, double)"/>
        /// </summary>
        /// <param name="StartPos"></param>
        /// <param name="EndPos"></param>
        /// <returns></returns>
        public override ICurve2D Trim(double StartPos, double EndPos)
        {
            if ((EndPos - StartPos) < (1.0 / vertex.Length))
            {
                if (Precision.IsEqual(PointAt(StartPos), PointAt(EndPos)))
                {
                    return(null);
                }
            }

            Polyline2D res = this.Clone() as Polyline2D;

            try
            {
                res.TrimOff(StartPos, EndPos);
                return(res);
            }
            catch (Polyline2DException)
            {   // ein zu kurzes Stück wird dort nicht akzeptiert
                return(null);
            }
        }
예제 #6
0
        /// <summary>
        /// Overrides <see cref="CADability.Curve2D.GeneralCurve2D.Intersect (ICurve2D)"/>
        /// </summary>
        /// <param name="IntersectWith"></param>
        /// <returns></returns>
        public override GeoPoint2DWithParameter[] Intersect(ICurve2D IntersectWith)
        {   // gesucht sind alle Schnittpunkte, also auch in der Verlängerung!
            Line2D l2d = IntersectWith as Line2D;

            if (l2d != null)
            {
                GeoPoint2D ip;
                if (Geometry.IntersectLL(startPoint, endPoint, l2d.StartPoint, l2d.EndPoint, out ip))
                {
                    double pos1 = this.PositionOf(ip);
                    double pos2 = l2d.PositionOf(ip);
                    GeoPoint2DWithParameter pwp = new GeoPoint2DWithParameter();
                    pwp.p    = ip;
                    pwp.par1 = pos1;
                    pwp.par2 = pos2;
                    return(new GeoPoint2DWithParameter[] { pwp });
                }
                else
                {
                    return(new GeoPoint2DWithParameter[0]);
                }
            }
            Circle2D c2d = IntersectWith as Circle2D;

            if (c2d != null)
            {
                GeoPoint2D[] isp = Geometry.IntersectLC(startPoint, endPoint, c2d.Center, c2d.Radius);
                GeoPoint2DWithParameter[] res = new GeoPoint2DWithParameter[isp.Length];
                for (int i = 0; i < isp.Length; ++i)
                {
                    res[i].p    = isp[i];
                    res[i].par1 = this.PositionOf(isp[i]);
                    res[i].par2 = c2d.PositionOf(isp[i]);
                }
                return(res);
            }
            Ellipse2D e2d = IntersectWith as Ellipse2D;

            if (e2d != null)
            {
                GeoPoint2D[] isp = Geometry.IntersectEL(e2d.center, e2d.majorAxis.Length, e2d.minorAxis.Length, e2d.majorAxis.Angle, startPoint, endPoint);
                GeoPoint2DWithParameter[] res = new GeoPoint2DWithParameter[isp.Length];
                for (int i = 0; i < isp.Length; ++i)
                {
                    res[i].p    = isp[i];
                    res[i].par1 = this.PositionOf(isp[i]);
                    res[i].par2 = e2d.PositionOf(isp[i]);
                }
                return(res);
            }
            Polyline2D p2d = IntersectWith as Polyline2D;

            if (p2d != null)
            {
                GeoPoint2DWithParameter[] res = p2d.Intersect(this); // sorum geht es
                for (int i = 0; i < res.Length; ++i)
                {
                    double t = res[i].par1;
                    res[i].par1 = res[i].par2;
                    res[i].par2 = t;
                }
                return(res);
            }
            Path2D pa2d = IntersectWith as Path2D;

            if (pa2d != null)
            {
                GeoPoint2DWithParameter[] res = pa2d.Intersect(this); // sorum geht es
                for (int i = 0; i < res.Length; ++i)
                {
                    double t = res[i].par1;
                    res[i].par1 = res[i].par2;
                    res[i].par2 = t;
                }
                return(res);
            }
            BSpline2D b2d = IntersectWith as BSpline2D;

            if (b2d != null)
            {
                GeoPoint2DWithParameter[] res = b2d.Intersect(this); // sorum geht es
                for (int i = 0; i < res.Length; ++i)
                {
                    double t = res[i].par1;
                    res[i].par1 = res[i].par2;
                    res[i].par2 = t;
                }
                return(res);
            }
            return(base.Intersect(IntersectWith));
        }
예제 #7
0
        public override ICurve2D GetFused(ICurve2D toFuseWith, double precision)
        {
            if (toFuseWith is Line2D)
            {
                toFuseWith = new Polyline2D(new GeoPoint2D[] { toFuseWith.StartPoint, toFuseWith.EndPoint });
            }
            if (toFuseWith is Polyline2D)
            {
                Polyline2D pl1, pl2;
                if (length < toFuseWith.Length)
                {
                    pl1 = toFuseWith.Clone() as Polyline2D; // 1. die längere
                    pl2 = this.Clone() as Polyline2D;
                }
                else
                {
                    pl1 = this.Clone() as Polyline2D;
                    pl2 = toFuseWith.Clone() as Polyline2D;
                }
                // die kürzere muss wenigstens start oder endpunkt auf der längeren haben
                double pos1       = pl1.PositionOf(pl2.StartPoint);
                double pos2       = pl1.PositionOf(pl2.EndPoint);
                bool   pos1inside = false;
                bool   pos2inside = false;
                if (pos1 >= 0.0 && pos1 <= 1.0)
                {   // Startpunkt liegt drauf
                    if (Math.Abs(pl1.Distance(pl2.StartPoint)) < precision)
                    {
                        pos1inside = true;
                    }
                }
                if (pos2 >= 0.0 && pos2 <= 1.0)
                {   // Startpunkt liegt drauf
                    if (Math.Abs(pl1.Distance(pl2.EndPoint)) < precision)
                    {
                        pos2inside = true;
                    }
                }
                GeoPoint2D split1 = GeoPoint2D.Origin, split2 = GeoPoint2D.Origin;
                bool       split = false;
                if (pos1inside && pos2inside)
                {
                    bool ok = true;
                    for (int i = 0; i < pl2.VertexCount; i++)
                    {
                        if (Math.Abs(pl1.Distance(pl2.vertex[i])) > precision)
                        {
                            ok = false;
                        }
                    }
                    if (ok)
                    {
                        return(pl1);    // die ist es bereits, und es ist ja auch ein clone
                    }
                    else
                    {
                        return(null); // zu großer Abstand
                    }
                }
                else if (pos2inside)
                {   // der Endpunkt von pl2 liegt innerhalb, der Startpunkt außerhalb
                    double p = pl2.PositionOf(pl1.StartPoint);
                    if (p >= 0.0 && p <= 1.0)
                    {
                        if (Math.Abs(pl2.Distance(pl1.StartPoint)) < precision)
                        {
                            // fängt an mit pl2, endet mid pl1, beide schon richtige Richtung
                            split1 = pl1.StartPoint;
                            split2 = pl2.EndPoint;
                            split  = true;
                            Polyline2D tmp = pl2;
                            pl2 = pl1;
                            pl1 = tmp;
                        }
                    }
                    if (!split)
                    {
                        p = pl2.PositionOf(pl1.EndPoint);
                        if (p >= 0.0 && p <= 1.0)
                        {
                            if (Math.Abs(pl2.Distance(pl1.EndPoint)) < precision)
                            {
                                // fängt an mit pl2, endet mid pl1, pl1 muss umgedreht werden
                                split1 = pl1.EndPoint;
                                split2 = pl2.EndPoint;
                                split  = true;
                                pl1.Reverse();
                                Polyline2D tmp = pl2;
                                pl2 = pl1;
                                pl1 = tmp;
                            }
                        }
                    }
                }
                else if (pos1inside)
                {   // der Startpunkt von pl2 liegt innerhalb, der Endpunkt außerhalb
                    double p = pl2.PositionOf(pl1.StartPoint);
                    if (p >= 0.0 && p <= 1.0)
                    {
                        if (Math.Abs(pl2.Distance(pl1.StartPoint)) < precision)
                        {
                            // fängt an mit pl1, endet mid pl2, pl1 falschrum
                            split1 = pl2.StartPoint;
                            split2 = pl1.StartPoint;
                            split  = true;
                            pl1.Reverse();
                        }
                    }
                    if (!split)
                    {
                        p = pl2.PositionOf(pl1.EndPoint);
                        if (p >= 0.0 && p <= 1.0)
                        {
                            if (Math.Abs(pl2.Distance(pl1.EndPoint)) < precision)
                            {
                                // fängt an mit pl1, endet mid pl2, beide richtigrum
                                split1 = pl2.StartPoint;
                                split2 = pl1.EndPoint;
                                split  = true;
                            }
                        }
                    }
                }
                if (split)
                {   // sie überlappen sich, das kann im Extramfall acuh einfach zusammenhängend sein
#if DEBUG
                    DebuggerContainer dc = new DebuggerContainer();
                    dc.Add(pl1, Color.Red, 1);
                    dc.Add(pl2, Color.Green, 2);
                    dc.Add(split1, Color.Red, 3);
                    dc.Add(split2, Color.Blue, 4);
#endif
                    // if (pl1.ConnectWith(pl2, precision)) return pl1; // damit ist das schon erledigt, sonst gibt es beim Splitten einen Fehler
                    // das macht Probleme bei zwei fast identischichen Polylines, die werden sonst in Gegenrichtung miteinander verbunden
                    ICurve2D[] spl1 = pl1.Split(pl1.PositionOf(split1));
                    ICurve2D[] spl2 = pl2.Split(pl2.PositionOf(split2));
                    // Der Anfang von spl1 und das Ende von spl2 sind die Endstücke, das Mittelteil ist doppelt und muss identisch sein
                    if (spl1.Length == 2 && spl2.Length == 2)
                    {
                        Polyline2D m1 = spl1[1] as Polyline2D;
                        Polyline2D m2 = spl2[0] as Polyline2D;
                        bool       ok = true;
                        for (int i = 0; i < m1.VertexCount; i++)
                        {
                            if (Math.Abs(m2.Distance(m1.vertex[i])) > precision)
                            {
                                ok = false;
                            }
                        }
                        if (!ok)
                        {
                            return(null);
                        }
                        List <GeoPoint2D> pnts = new List <GeoPoint2D>((spl1[0] as Polyline2D).Vertex);
                        for (int i = 1; i < m2.VertexCount; i++)
                        {
                            pnts.Add(m2.vertex[i]);
                        }
                        m2 = spl2[1] as Polyline2D;
                        for (int i = 1; i < m2.VertexCount; i++)
                        {
                            pnts.Add(m2.vertex[i]);
                        }
                        return(new Polyline2D(pnts.ToArray()));
                    }
                }
            }
            return(null);
        }
예제 #8
0
        /// <summary>
        /// Overrides <see cref="CADability.Curve2D.GeneralCurve2D.Split (double)"/>
        /// </summary>
        /// <param name="Position"></param>
        /// <returns></returns>
        public override ICurve2D[] Split(double Position)
        {
            int        ind       = -1;
            double     tot       = Length * Position;
            GeoPoint2D SplitHere = GeoPoint2D.Origin;

            for (int i = 1; i < vertex.Length; ++i)
            {
                double d = tot;
                tot -= Geometry.Dist(vertex[i - 1], vertex[i]);
                if (tot < 0.0)
                {
                    ind = i;
                    GeoVector2D dir = vertex[i] - vertex[i - 1];
                    dir.Length = d; // der letzte positive Rest
                    SplitHere  = vertex[i - 1] + dir;
                    break;
                }
            }
            if (ind < 0)
            {   // Schnitt am Endpunkt
                return(new ICurve2D[] { Clone() });
            }
            Polyline2D[] res = new Polyline2D[2];
            GeoPoint2D[] v1  = new GeoPoint2D[ind + 1];
            GeoPoint2D[] v2  = new GeoPoint2D[vertex.Length - ind + 1];
            for (int i = 0; i < ind; ++i)
            {
                v1[i] = vertex[i];
            }
            v1[ind] = SplitHere;
            v2[0]   = SplitHere;
            for (int i = ind; i < vertex.Length; ++i)
            {
                v2[i - ind + 1] = vertex[i];
            }
            Polyline2D pl1 = null, pl2 = null;

            try
            {
                pl1 = Polyline2D.MakePolyline2D(v1);
            }
            catch (Polyline2DException)
            {
                pl1 = null;
            }
            try
            {
                pl2 = Polyline2D.MakePolyline2D(v2);
            }
            catch (Polyline2DException)
            {
                pl2 = null;
            }
            if (pl1 == null && pl2 == null)
            {
                return(null);                            // sollte nicht vorkommen
            }
            if (pl1 == null)
            {
                return new ICurve2D[] { pl2 }
            }
            ;
            if (pl2 == null)
            {
                return new ICurve2D[] { pl1 }
            }
            ;
            return(new ICurve2D[] { pl1, pl2 });
        }
예제 #9
0
        internal bool Reduce(double precision)
        {
            // zuerst die Möglichkeit checken, dass die ganze Kurve in sich zurückgeht:
            int    splitat = -1;
            double maxBend = 0;

            for (int i = 2; i < vertex.Length; i++)
            {
                SweepAngle sw = new SweepAngle(vertex[i - 1] - vertex[i - 2], vertex[i] - vertex[i - 1]);
                if (Math.Abs(sw.Radian) > Math.PI - 0.1)
                {
                    if (Math.Abs(sw.Radian) > maxBend)
                    {
                        maxBend = Math.Abs(sw.Radian);
                        splitat = i - 1;
                    }
                }
            }
            if (splitat >= 0)
            {
                GeoPoint2D[] v1 = new GeoPoint2D[splitat + 1];
                GeoPoint2D[] v2 = new GeoPoint2D[vertex.Length - splitat];
                Array.Copy(vertex, v1, splitat + 1);
                Array.Copy(vertex, splitat, v2, 0, vertex.Length - splitat);
                Polyline2D pl1 = Polyline2D.MakePolyline2D(v1);
                Polyline2D pl2 = Polyline2D.MakePolyline2D(v2);
                if (pl1 != null && pl2 != null)
                {
                    ICurve2D fused = pl1.GetFused(pl2, precision);
                    if (fused != null && (fused as Polyline2D).VertexCount < vertex.Length)
                    {
                        this.SetVertices((fused as Polyline2D).Vertex);
                        return(Reduce(precision)); // sollte nicht rekursiv werden, es sei denn, es gibt mehrere Spitzkehren, dann ist es ja gut
                    }
                }
            }

            List <GeoPoint2D> vlist = new List <GeoPoint2D>();

            vlist.Add(vertex[0]);
            int  lastInserted = 0;
            bool reverts      = false;

            for (int i = 2; i < vertex.Length; i++)
            {
                bool inserted = true;
                while (inserted)
                {
                    inserted = false;
                    for (int j = lastInserted + 1; j < i; j++)
                    {
                        double lp = Geometry.LinePar(vertex[lastInserted], vertex[i], vertex[j]); // Problem: die Polyline geht in sich selbst zurück
                        if (Math.Abs(Geometry.DistPL(vertex[j], vertex[lastInserted], vertex[i])) > precision || lp < 0 || lp > 1)
                        {
                            if (lp < 0 || lp > 1)
                            {
                                reverts = true;
                            }
                            lastInserted = j;
                            vlist.Add(vertex[j]);
                            inserted = true;
                            break;
                        }
                    }
                }
            }
            vlist.Add(vertex[vertex.Length - 1]);
            if (reverts && vlist.Count >= 3)
            {                                                                                                         // versuche wenigstens am Anfang oder Ende die Situation, dass die Polyline in sich zurückgeht zu bereinigen
                double lp = Geometry.LinePar(vlist[vlist.Count - 3], vlist[vlist.Count - 2], vlist[vlist.Count - 1]); // der letzte Punkt im vorletzten Segment
                if (lp >= 0 && lp <= 1 && Math.Abs(Geometry.DistPL(vlist[vlist.Count - 1], vlist[vlist.Count - 2], vlist[vlist.Count - 3])) < precision)
                {
                    vlist.RemoveAt(vlist.Count - 1);
                }
                if (vlist.Count >= 3)
                {
                    lp = Geometry.LinePar(vlist[2], vlist[1], vlist[0]); // der letzte Punkt im vorletzten Segment
                    if (lp >= 0 && lp <= 1 && Math.Abs(Geometry.DistPL(vlist[0], vlist[1], vlist[2])) < precision)
                    {
                        vlist.RemoveAt(0);
                    }
                }
            }
            if (vlist.Count < vertex.Length)
            {
                SetVertices(vlist.ToArray());
                return(true);
            }
            return(false);
        }
예제 #10
0
        internal bool ConnectWith(Polyline2D polyline2D, double Precision)
        {
            double minDist = double.MaxValue;
            int    mode    = -1;
            double dist    = polyline2D.StartPoint | this.EndPoint;

            if (dist < minDist)
            {
                minDist = dist;
                mode    = 0;
            }
            dist = polyline2D.EndPoint | this.EndPoint;
            if (dist < minDist)
            {
                minDist = dist;
                mode    = 1;
            }
            dist = polyline2D.StartPoint | this.StartPoint;
            if (dist < minDist)
            {
                minDist = dist;
                mode    = 2;
            }
            dist = polyline2D.EndPoint | this.StartPoint;
            if (dist < minDist)
            {
                minDist = dist;
                mode    = 3;
            }
            if (minDist < Precision)
            {
                GeoPoint2D[] newvert;
                switch (mode)
                {
                case 0:
                    newvert = new GeoPoint2D[vertex.Length + polyline2D.VertexCount - 1];
                    Array.Copy(vertex, newvert, vertex.Length);
                    Array.Copy(polyline2D.vertex, 1, newvert, vertex.Length, polyline2D.VertexCount - 1);
                    vertex      = newvert;
                    this.length = -1;
                    return(true);

                case 1:
                    newvert = new GeoPoint2D[vertex.Length + polyline2D.VertexCount - 1];
                    Array.Copy(vertex, newvert, vertex.Length);
                    GeoPoint2D[] old = polyline2D.Vertex;     // das ist eine Kopie
                    Array.Reverse(old);
                    Array.Copy(old, 1, newvert, vertex.Length, polyline2D.VertexCount - 1);
                    vertex      = newvert;
                    this.length = -1;
                    return(true);

                case 2:
                    this.Reverse();
                    return(ConnectWith(polyline2D, Precision));

                case 3:
                    this.Reverse();
                    return(ConnectWith(polyline2D, Precision));
                }
            }
            //if ((polyline2D.StartPoint | vertex[vertex.Length - 1]) < Precision)
            //{
            //    GeoPoint2D[] newvert = new GeoPoint2D[vertex.Length + polyline2D.VertexCount - 1];
            //    Array.Copy(vertex, newvert, vertex.Length);
            //    Array.Copy(polyline2D.vertex, 1, newvert, vertex.Length, polyline2D.VertexCount - 1);
            //    vertex = newvert;
            //    this.length = -1;
            //    return true;
            //}
            //if ((polyline2D.EndPoint | vertex[vertex.Length - 1]) < Precision)
            //{
            //    GeoPoint2D[] newvert = new GeoPoint2D[vertex.Length + polyline2D.VertexCount - 1];
            //    Array.Copy(vertex, newvert, vertex.Length);
            //    GeoPoint2D[] old = polyline2D.Vertex; // das ist eine Kopie
            //    Array.Reverse(old);
            //    Array.Copy(old, 1, newvert, vertex.Length, polyline2D.VertexCount - 1);
            //    vertex = newvert;
            //    this.length = -1;
            //    return true;
            //}
            //// wenn die zuzufügende vornedran käme, dann halt umdrehen
            //if ((polyline2D.StartPoint | vertex[0]) < Precision)
            //{
            //    this.Reverse();
            //    return ConnectWith(polyline2D, Precision);
            //}
            //if ((polyline2D.EndPoint | vertex[0]) < Precision)
            //{
            //    this.Reverse();
            //    return ConnectWith(polyline2D, Precision);
            //}
            return(false);
        }