/// <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); }
/// <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); }
/// <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); //} } }
/// <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); }
/// <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); }
/// <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)); } }
/// <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); }
/// <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)); } }
/// <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); }