/// <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 Ellipse2D && !(toFuseWith is EllipseArc2D)) { return(toFuseWith.GetFused(this, precision)); } if (toFuseWith is EllipseArc2D) { EllipseArc2D a2d = (toFuseWith as EllipseArc2D); // hier wird vorausgesetzt, dass majrad>minrad immer gilt. Stimmt das? if ((Center | a2d.Center) + Math.Abs(majrad - a2d.majrad) + Math.Abs(minrad - a2d.minrad) < precision) { // alle zusammen kleiner als precision, vielleich beim Bogen zu streng // weitere Bedingung: Achsen müssen übereinstimmen. // dazu müsste man bei vertauschten Richtungen noch mehr Grips reinstecken... EllipseArc2D a1, a2; if (Math.Abs(this.sweepPar) > Math.Abs(a2d.sweepPar)) { a1 = this; a2 = a2d; } else { a1 = a2d; a2 = this; } if (a1.sweepPar * a2.sweepPar < 0.0) { a2.Reverse(); } // 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); // vor dem Anfang oder auf dem Bogen double pos2 = a1.PositionOf(a2.EndPoint); // nach dem Ende oder auf dem Bogen // System.Diagnostics.Trace.WriteLine("pos1, pos2: " + pos1.ToString() + ", " + pos2.ToString()); bool pos1ok = a1.IsParameterOnCurve(pos1); bool pos2ok = a1.IsParameterOnCurve(pos2); if (pos1ok && pos2ok) { // beide Punkte sind drauf return(a1.Clone()); } else if (pos1ok) { return(Create(a1.center, a1.majorAxis, a1.minorAxis, a1.startPoint, a2.endPoint, a1.sweepPar > 0.0)); } else if (pos2ok) { return(Create(a1.center, a1.majorAxis, a1.minorAxis, a2.startPoint, a1.endPoint, a1.sweepPar > 0.0)); } } } return(null); }
/// <summary> /// Tries to combine two curves. crv1 and crv2 must be correct oriented and the endpoint of crv1 mut be the start-point of crv2 /// </summary> /// <param name="crv1"></param> /// <param name="crv2"></param> /// <returns>the combined curve or null, if not possible</returns> public static ICurve Combine(ICurve crv1, ICurve crv2, double precision) { if (crv1 == null || crv2 == null) { return(null); } if ((crv1.EndPoint | crv2.StartPoint) > precision) { return(null); } if (crv1 is InterpolatedDualSurfaceCurve ip1 && crv2 is InterpolatedDualSurfaceCurve ip2) { if ((ip1.Surface1.SameGeometry(ip1.Domain1, ip2.Surface1, ip2.Domain1, precision, out _) && ip1.Surface2.SameGeometry(ip1.Domain2, ip2.Surface2, ip2.Domain2, precision, out _)) || (ip1.Surface1.SameGeometry(ip1.Domain1, ip2.Surface2, ip2.Domain2, precision, out _) && ip1.Surface2.SameGeometry(ip1.Domain2, ip2.Surface1, ip2.Domain1, precision, out _))) { List <GeoPoint> basepoints = new List <GeoPoint>(); basepoints.AddRange(ip1.BasePoints); basepoints.RemoveAt(basepoints.Count - 1); basepoints.AddRange(ip2.BasePoints); return(new InterpolatedDualSurfaceCurve(ip1.Surface1, ip1.Domain1, ip1.Surface2, ip1.Domain2, basepoints)); // the domains are too small, but this is not a problem } } if (GetCommonPlane(crv1, crv2, out Plane pln)) { ICurve2D e2d1 = crv1.GetProjectedCurve(pln); ICurve2D e2d2 = crv2.GetProjectedCurve(pln); ICurve2D fused = e2d1.GetFused(e2d2, precision); if (fused != null) { return(fused.MakeGeoObject(pln) as ICurve); } } else if (crv1 is Line && crv2 is Line) { Line res = Line.Construct(); res.SetTwoPoints(crv1.StartPoint, crv2.EndPoint); return(res); } // non planar BSplines should be implemented return(null); }
/// <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); }