예제 #1
0
        /// <summary>
        /// Overrides <see cref="CADability.Curve2D.GeneralCurve2D.Clone ()"/>
        /// </summary>
        /// <returns></returns>
        public override ICurve2D Clone()
        {
            Arc2D res = new Arc2D(Center, Radius, start, sweep);

            res.UserData.CloneFrom(this.UserData);
            return(res);
        }
예제 #2
0
        /// <summary>
        /// Overrides <see cref="CADability.Curve2D.GeneralCurve2D.Copy (ICurve2D)"/>
        /// </summary>
        /// <param name="toCopyFrom"></param>
        public override void Copy(ICurve2D toCopyFrom)
        {
            Arc2D c = toCopyFrom as Arc2D;

            start = c.start;
            sweep = c.sweep;
            base.Copy(toCopyFrom);
        }
예제 #3
0
        /// <summary>
        /// Overrides <see cref="CADability.Curve2D.GeneralCurve2D.GetModified (ModOp2D)"/>
        /// </summary>
        /// <param name="m"></param>
        /// <returns></returns>
        public override ICurve2D GetModified(ModOp2D m)
        {
            // es ist wichtig hier zu überschreiben, die Basisfunktionalität macht aus einem 360°
            // Kreisbogen einen Kreis und der Anfangspunkt geht verloren. Diese Information ist aber
            // für die Edges wichtig.
            if (m.IsIsogonal)
            {
                bool cc = sweep > 0.0;
                if (m.Determinant < 0.0)
                {
                    cc = !cc;
                }
                Arc2D res = new Arc2D(m * Center, m.Factor * Radius, m * StartPoint, m * EndPoint, cc);
                if (m.Determinant < 0.0)
                {
                    res.sweep = -sweep; // das schaltet die Fälle aus, wo Unsicherheit zwischen 0 und 360° besteht
                }
                else
                {
                    res.sweep = sweep;
                }
                return(res);
            }
            else
            {
                //double sw = sweep;
                //if (m.Determinant < 0.0) sw = -sw;
                GeoVector2D majorAxis;
                GeoVector2D minorAxis;
                GeoPoint2D  left, right, bottom, top;
                bool        cc = sweep > 0.0;
                if (m.Determinant < 0.0)
                {
                    cc = !cc;
                }
                majorAxis = m * (Radius * GeoVector2D.XAxis);
                minorAxis = m * (Radius * GeoVector2D.YAxis);
                if (Math.Abs(majorAxis.Length - minorAxis.Length) < (majorAxis.Length + minorAxis.Length) * 1e-6)
                {
                    return(new Arc2D(m * Center, Math.Abs(m.Determinant * Radius), m * StartPoint, m * EndPoint, cc));
                }
                Geometry.PrincipalAxis(m * Center, m * (Radius * GeoVector2D.XAxis), m * (Radius * GeoVector2D.YAxis), out majorAxis, out minorAxis, out left, out right, out bottom, out top, false);
                // geändert wg. Fehler in IsIsogonal Fall, noch nicht getestet
                return(EllipseArc2D.Create(m * Center, majorAxis, minorAxis, m * StartPoint, m * EndPoint, cc));

                //if (m.Determinant < 0.0)
                //{
                //    return new EllipseArc2D(m * Center, m * (Radius * GeoVector2D.XAxis), m * (Radius * GeoVector2D.YAxis), start + sweep, sw, left, right, bottom, top);
                //}
                //else
                //{
                //    return new EllipseArc2D(m * Center, m * (Radius * GeoVector2D.XAxis), m * (Radius * GeoVector2D.YAxis), start, sw, left, right, bottom, top);
                //}
            }
        }
예제 #4
0
        /// <summary>
        /// Overrides <see cref="CADability.Curve2D.GeneralCurve2D.CloneReverse (bool)"/>
        /// </summary>
        /// <param name="reverse"></param>
        /// <returns></returns>
        public override ICurve2D CloneReverse(bool reverse)
        {
            ICurve2D res;

            if (reverse)
            {
                res = new Arc2D(Center, Radius, start + sweep, -sweep);
            }
            else
            {
                res = Clone();
            }
            res.UserData.CloneFrom(this.UserData);
            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)
        {
            //bool reversed = false;
            //if (StartPos>EndPos)
            //{
            //    double tmp = StartPos;
            //    StartPos = EndPos;
            //    EndPos = tmp;
            //    reversed = true;
            //}
            Arc2D res = new Arc2D(Center, Radius, start, sweep);
            Angle st  = start + StartPos * sweep;
            Angle end = start + EndPos * sweep;

            res.sweep = new SweepAngle(st, end, (sweep > 0.0) ^ (StartPos > EndPos));
            res.start = st;
            return(res);
        }
예제 #6
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 (StartPos < EndPos)
     {
         Arc2D res;
         if (counterClock)
         {
             res = new Arc2D(center, radius, Angle.A0, SweepAngle.Full);
         }
         else
         {
             res = new Arc2D(center, radius, Angle.A0, SweepAngle.FullReverse);
         }
         return(res.Trim(StartPos, EndPos));
     }
     else
     {
         return(new Arc2D(center, radius, PointAt(StartPos), PointAt(EndPos), counterClock));
     }
 }
예제 #7
0
        /// <summary>
        /// Overrides <see cref="CADability.Curve2D.GeneralCurve2D.Parallel (double, bool, double, double)"/>
        /// </summary>
        /// <param name="Dist"></param>
        /// <param name="approxSpline"></param>
        /// <param name="precision"></param>
        /// <param name="roundAngle"></param>
        /// <returns></returns>
        public override ICurve2D Parallel(double Dist, bool approxSpline, double precision, double roundAngle)
        {
            Arc2D  res;
            double newRadius;   // Abstand nach rechts im Sinne der Richtung des Bogens

            if (sweep > 0.0)
            {
                newRadius = Radius + Dist;
            }
            else
            {
                newRadius = Radius - Dist;
            }
            if (newRadius > 0.0)
            {
                res = new Arc2D(Center, newRadius, start, sweep);
            }
            else
            {
                res = new Arc2D(Center, -newRadius, start + SweepAngle.Opposite, sweep);
            }
            res.UserData.CloneFrom(this.UserData);
            return(res);
        }
예제 #8
0
 /// <summary>
 /// Overrides <see cref="CADability.Curve2D.GeneralCurve2D.MinDistance (ICurve2D)"/>
 /// </summary>
 /// <param name="Other"></param>
 /// <returns></returns>
 public override double MinDistance(ICurve2D Other)
 {
     if (Other is Line2D)
     {
         Line2D l = Other as Line2D;
         // schneller Vorabtest auf Schnitt: (noch nicht getestet)
         double f1 = (startPoint.x - endPoint.x) * (l.endPoint.y - endPoint.y) - (startPoint.y - endPoint.y) * (l.endPoint.x - endPoint.x);
         double f2 = (startPoint.x - endPoint.x) * (l.startPoint.y - endPoint.y) - (startPoint.y - endPoint.y) * (l.startPoint.x - endPoint.x);
         if (f1 * f2 < 0.0)
         {   // verschiedenes Vorzeichen
             double f3 = (l.startPoint.x - l.endPoint.x) * (endPoint.y - l.endPoint.y) - (l.startPoint.y - l.endPoint.y) * (endPoint.x - l.endPoint.x);
             double f4 = (l.startPoint.x - l.endPoint.x) * (startPoint.y - l.endPoint.y) - (l.startPoint.y - l.endPoint.y) * (startPoint.x - l.endPoint.x);
             if (f3 * f4 < 0.0)
             {
                 return(0.0);               // echter Schnittpunkt
             }
         }
         double minDist = double.MaxValue;
         double dx1     = endPoint.x - startPoint.x;
         double dy1     = endPoint.y - startPoint.y;
         bool   DoDx1   = Math.Abs(dx1) > Math.Abs(dy1);
         double dx2     = l.endPoint.x - l.startPoint.x;
         double dy2     = l.endPoint.y - l.startPoint.y;
         bool   DoDx2   = Math.Abs(dx2) > Math.Abs(dy2);
         double d;
         // Berechnung der Fußpunktabstände, wenn sie auf die andere Linie treffen
         GeoPoint2D p = Geometry.DropPL(l.startPoint, startPoint, endPoint);
         if (DoDx1)
         {
             d = (p.x - startPoint.x) / dx1;
         }
         else
         {
             d = (p.y - startPoint.y) / dy1;
         }
         if (d >= 0.0 && d <= 1.0)
         {
             minDist = Math.Min(minDist, Geometry.Dist(p, l.startPoint));
         }
         p = Geometry.DropPL(l.endPoint, startPoint, endPoint);
         if (DoDx1)
         {
             d = (p.x - startPoint.x) / dx1;
         }
         else
         {
             d = (p.y - startPoint.y) / dy1;
         }
         if (d >= 0.0 && d <= 1.0)
         {
             minDist = Math.Min(minDist, Geometry.Dist(p, l.endPoint));
         }
         p = Geometry.DropPL(startPoint, l.startPoint, l.endPoint);
         if (DoDx2)
         {
             d = (p.x - l.startPoint.x) / dx2;
         }
         else
         {
             d = (p.y - l.startPoint.y) / dy2;
         }
         if (d >= 0.0 && d <= 1.0)
         {
             minDist = Math.Min(minDist, Geometry.Dist(p, startPoint));
         }
         p = Geometry.DropPL(endPoint, l.startPoint, l.endPoint);
         if (DoDx2)
         {
             d = (p.x - l.startPoint.x) / dx2;
         }
         else
         {
             d = (p.y - l.startPoint.y) / dy2;
         }
         if (d >= 0.0 && d <= 1.0)
         {
             minDist = Math.Min(minDist, Geometry.Dist(p, endPoint));
         }
         if (minDist == double.MaxValue)
         {   // kein Fußpunkt auf der anderen Linie: die gegenseitigen Start/Endpunkt
             // Abstände verwenden
             minDist = Math.Min(minDist, Geometry.Dist(l.startPoint, endPoint));
             minDist = Math.Min(minDist, Geometry.Dist(l.endPoint, endPoint));
             minDist = Math.Min(minDist, Geometry.Dist(l.startPoint, startPoint));
             minDist = Math.Min(minDist, Geometry.Dist(l.endPoint, startPoint));
         }
         return(minDist);
     }
     else if (Other is Arc2D)
     {
         double       minDist = Curves2D.SimpleMinimumDistance(this, Other);
         Arc2D        a       = Other as Arc2D;
         GeoPoint2D[] fp      = PerpendicularFoot(a.Center);
         for (int i = 0; i < fp.Length; ++i)
         {
             GeoPoint2D p   = fp[i];
             double     pos = PositionOf(p);
             if (pos >= 0.0 && pos <= 1.0)
             {
                 pos = a.PositionOf(p);
                 if (pos >= 0.0 && pos <= 1.0)
                 {
                     double d = Geometry.Dist(p, a.Center);
                     if (d > a.Radius)
                     {
                         minDist = Math.Min(minDist, d - a.Radius);
                     }
                 }
             }
         }
         return(minDist);
     }
     else if (Other is Circle2D)
     {
         double       minDist = Curves2D.SimpleMinimumDistance(this, Other);
         Circle2D     c       = Other as Circle2D;
         GeoPoint2D[] fp      = PerpendicularFoot(c.Center);
         for (int i = 0; i < fp.Length; ++i)
         {
             GeoPoint2D p   = fp[i];
             double     pos = PositionOf(p);
             if (pos >= 0.0 && pos <= 1.0)
             {
                 double d = Geometry.Dist(p, c.Center);
                 if (d > c.Radius)
                 {
                     minDist = Math.Min(minDist, d - c.Radius);
                 }
             }
         }
         return(minDist);
     }
     else
     {
         return(base.MinDistance(Other));
     }
 }
예제 #9
0
        /// <summary>
        /// Overrides <see cref="CADability.Curve2D.GeneralCurve2D.GetFused (ICurve2D, double)"/>
        /// </summary>
        /// <param name="toFuseWith"></param>
        /// <param name="precision"></param>
        /// <returns></returns>
        public override ICurve2D GetFused(ICurve2D toFuseWith, double precision)
        {
            if (toFuseWith is Circle2D && !(toFuseWith is Arc2D))
            {
                return(toFuseWith.GetFused(this, precision));
            }
            if (toFuseWith is Arc2D)
            {
                Arc2D a2d = (toFuseWith as Arc2D);
                if ((Center | a2d.Center) + Math.Abs(Radius - a2d.Radius) < precision)
                {   // beides zusammen kleiner als precision, vielleich beim Bogen zu streng
                    Arc2D a1, a2;
                    if (this.Length > toFuseWith.Length)
                    {
                        a1 = this;
                        a2 = toFuseWith as Arc2D;
                    }
                    else
                    {
                        a1 = toFuseWith as Arc2D;
                        a2 = this;
                    }
                    if (a1.sweep * a2.sweep < 0.0)
                    {
                        a2 = (Arc2D)a2.CloneReverse(true); // war a2.Reverse();, man darf aber nicht eines der beteiligten Objekte ändern
                    }
                    // a1 ist länger als a2. Wenn es verschmelzen soll, dann muss der Start- oder der Endpunkt von a2
                    // innerhalb von a1 liegen

                    // Mittelpunkt und radius ist ja schon getestet
                    double pos1 = a1.PositionOf(a2.StartPoint, true); // vor dem Anfang oder auf dem Bogen
                    double pos2 = a1.PositionOf(a2.EndPoint, false);  // nach dem Ende oder auf dem Bogen
                    // System.Diagnostics.Trace.WriteLine("pos1, pos2: " + pos1.ToString() + ", " + pos2.ToString());
                    double eps = precision / a1.Length;
                    if (Math.Abs(pos1 - 1.0) < eps && Math.Abs(pos2) < eps)
                    {   // geht von Ende bis Anfang: Sonderfall: ergibt Vollkreis
                        double full;
                        if (a1.sweep > 0.0)
                        {
                            full = Math.PI * 2.0;
                        }
                        else
                        {
                            full = -Math.PI * 2.0;
                        }
                        Arc2D res = new Arc2D(Center / a2d.Center, (Radius + a2d.Radius) / 2.0, a1.start, full);
                        return(res);
                    }
                    else if (pos1 > -eps && pos1 < 1 + eps)
                    {   // also pos 2 geht evtl über diesen hinaus
                        GeoPoint2D sp  = a1.StartPoint;
                        GeoPoint2D ep  = a1.PointAt(Math.Max(pos2, 1.0));
                        Arc2D      res = new Arc2D(Center / a2d.Center, (Radius + a2d.Radius) / 2.0, sp, ep, a1.sweep > 0.0);
                        return(res);
                    }
                    else if (pos2 > -eps && pos2 < 1 + eps)
                    {
                        GeoPoint2D sp  = a1.PointAt(Math.Min(0.0, pos1));
                        GeoPoint2D ep  = a1.EndPoint;
                        Arc2D      res = new Arc2D(Center / a2d.Center, (Radius + a2d.Radius) / 2.0, sp, ep, a1.sweep > 0.0);
                        return(res);
                    }
                    else
                    {
                        return(null);
                    }
                }
            }
            return(null);
        }