/// <summary> /// Returns the parameters of the intersection points of curve1 with curve2. /// Parameters are with respect to curve1. The two curves must reside in a common plane. /// </summary> /// <param name="curve1">First curve for intersection</param> /// <param name="curve2">Second curve for intersection</param> /// <param name="onlyInside">if true, only intersction point that are actually on the curves are returned /// otherwise also intersection points on the extension of ther curves are returned</param> /// <returns>Parameters for the intersection points</returns> public static double[] Intersect(ICurve curve1, ICurve curve2, bool onlyInside) { ArrayList res = new ArrayList(); if (GetCommonPlane(curve1, curve2, out Plane pl)) { ICurve2D c12d = curve1.GetProjectedCurve(pl); ICurve2D c22d = curve2.GetProjectedCurve(pl); GeoPoint2DWithParameter[] pp = c12d.Intersect(c22d); for (int i = 0; i < pp.Length; ++i) { if (!onlyInside || (c12d.IsParameterOnCurve(pp[i].par1) && c22d.IsParameterOnCurve(pp[i].par2))) { // double pos = curve1.PositionOf(pl.ToGlobal(c12d.PointAt(pp[i].par1))); // geht z.Z. davon aus, dass die Parametrierung im 2d und 3d gleich läuft, ansonsten mit obiger Zeile res.Add(pp[i].par1); } } } return((double[])(res.ToArray(typeof(double)))); }
private bool showCutOff() { // nur wenn beide Kurven gültig sind base.ActiveObject = null; base.FeedBack.ClearSelected(); if ((iCurve1 != null) && (iCurve2 != null) && (iCurve1 != iCurve2)) { Plane pl; // nur bei gemeisamer Ebene if (Curves.GetCommonPlane(iCurve1, iCurve2, out pl)) { if (composedSplit) { if (iCurveComposedSplit != null) { owner = (iCurveComposedSplit as IGeoObject).Owner; // owner merken für löschen und Einfügen } else { owner = ownerCreated; } } // owner = (iCurveComposedSplit as IGeoObject).Owner; // owner merken für löschen und Einfügen else { owner = (iCurve1 as IGeoObject).Owner; // owner merken für löschen und Einfügen } pl.Align(base.ActiveDrawingPlane, false); // Winkel anpassen ICurve2D curve1_2D = iCurve1.GetProjectedCurve(pl); // die 2D-Kurven if (curve1_2D is Path2D) { (curve1_2D as Path2D).Flatten(); } ICurve2D curve2_2D = iCurve2.GetProjectedCurve(pl); if (curve2_2D is Path2D) { (curve2_2D as Path2D).Flatten(); } ICurve newCurve = iCurve1.Clone(); // neue Kurve bis zum Schnittpunkt // hier die Schnittpunkte bestimmen und den cutPoint auf den nächsten Schnittpunt setzen GeoPoint2DWithParameter cutPoint; if (Curves2D.NearestPoint(curve1_2D.Intersect(curve2_2D), pl.Project(objectPoint), out cutPoint)) // fasen war möglich { GeoVector2D v1 = curve1_2D.DirectionAt(cutPoint.par1); // die Richtung im Schnittpunkt if (cutPoint.par1 > 0.5) { v1 = v1.Opposite(); // evtl rumdrehen, falls am Ende } v1.Norm(); GeoVector2D v2 = curve2_2D.DirectionAt(cutPoint.par2); // die Richtung im Schnittpunkt if (cutPoint.par2 > 0.5) { v2 = v2.Opposite(); // evtl rumdrehen, falls am Ende } v2.Norm(); GeoVector2D v = (v1 + v2); // Winkelhalbierende if (Precision.IsNullVector(pl.ToGlobal(v))) { return(false); } v.Norm(); v = cutOffLen * v; // Winkelhalbierende mit Fas-Abstand GeoPoint2D dirPoint = cutPoint.p + v; // wird unten auch als Auswahlpunkt für die Richtung genutzt Line2D line2D = new Line2D(dirPoint, cutPoint.p); // Linie vorbesetzen, Punkte eigentlich egal if ((methodSelect == 0) || (methodSelect == 1)) { // 0: Länge cutOffLen = Seitenlänge Kurve1 1: Länge cutOffLen = Fasenlänge double sideLength; if (methodSelect == 1) // Länge cutOffLen = Fasenlänge // Geometrie, Pythagoras, bekannt Seite=cutOffLen, Winkel 1 = cutOffAng, Winkel 2 = Winkel der Kurven im Schnittpunkt { sideLength = cutOffLen * (Math.Cos(cutOffAng.Radian) + (Math.Sin(cutOffAng.Radian) / Math.Tan(Math.Abs(new SweepAngle(v1, v2).Radian)))); } else { sideLength = cutOffLen; } // neue Kurve bis zum Schnittpunkt synthetisieren, dazu: Schnittpunkt finden des Abschnitts mit der iCurve1 Ellipse arcTmp = Ellipse.Construct(); arcTmp.SetCirclePlaneCenterRadius(pl, pl.ToGlobal(cutPoint.p), sideLength); ICurve2D curveArc_2D = (arcTmp as ICurve).GetProjectedCurve(pl); // die 2D-Kurve GeoPoint2DWithParameter cutArc; GeoPoint2D startPoint; if (Curves2D.NearestPoint(curve1_2D.Intersect(curveArc_2D), dirPoint, out cutArc)) // war möglich { startPoint = cutArc.p; } else { return(false); } /* * double parCut; * * // neue Kurve bis zum Schnittpunkt synthetisieren: * if (cutPoint.par1 <= 0.5) * { * newCurve.Trim(cutPoint.par1,1.0); * parCut = (sideLength)/newCurve.Length; // der Parameter des Fasenpunktes * } * else * { * newCurve.Trim(0.0,cutPoint.par1); * parCut = (newCurve.Length-sideLength)/newCurve.Length; // der Parameter des Fasenpunktes * } * GeoPoint2D startPoint = pl.Project(newCurve.PointAt(parCut)); * GeoVector2D vc = curve1_2D.DirectionAt(parCut); // die Richtung im Schnittpunkt */ GeoVector2D vc = curve1_2D.DirectionAt(curve1_2D.PositionOf(startPoint)); // die Richtung im Schnittpunkt if (cutPoint.par1 <= 0.5) { vc = vc.Opposite(); // evtl rumdrehen, falls am Ende } if (Geometry.OnLeftSide(dirPoint, startPoint, vc)) // Richtung festlegen für Winkeloffset { vc.Angle = vc.Angle + new SweepAngle(cutOffAng); } else { vc.Angle = vc.Angle - new SweepAngle(cutOffAng); } // Hilfslinie im Fasabstand, im Offsetwinkel line2D = new Line2D(startPoint, startPoint + vc); } if (methodSelect == 2) // Länge cutOffLen = Winkelhalbierendenlänge { v.Angle = v.Angle + new SweepAngle(cutOffAng); // Winkelhalbierendenwinkel + Offset // Hilfslinie im Fasabstand, senkrecht auf der Winkelhalbierenden v line2D = new Line2D(dirPoint, dirPoint + v.ToLeft()); } GeoPoint2DWithParameter cutPoint1; GeoPoint2DWithParameter cutPoint2; // schnittpunkte der Hilfslinie mit den beiden Kurven if (Curves2D.NearestPoint(curve1_2D.Intersect(line2D as ICurve2D), cutPoint.p + v, out cutPoint1)) { if (Curves2D.NearestPoint(curve2_2D.Intersect(line2D as ICurve2D), cutPoint.p + v, out cutPoint2)) { // da isse, die Fas-Linie, nur, wenn die Punkte echt auf der Kurve bis zum Schnittpunkt liegen: bool onCurve1, onCurve2; // Berechnung, ob die Kurven realen Schnittpunkt haben // if ((cutPoint.par1 <= 1.0001) & (cutPoint.par1 >= -0.0001) & (cutPoint.par2 <= 1.0001) & (cutPoint.par2 >= -0.0001)) if (curve1_2D.IsParameterOnCurve(cutPoint.par1) & curve2_2D.IsParameterOnCurve(cutPoint.par2)) { onCurve1 = (cutPoint1.par1 > 0.0) & (cutPoint1.par1 < 1.0); onCurve2 = (cutPoint2.par1 > 0.0) & (cutPoint2.par1 < 1.0); } else { if (cutPoint.par1 > 0.5) { onCurve1 = (cutPoint1.par1 > 0.0) & (cutPoint1.par1 < 100); } // im Quasi-Parallelfall stehen in par1 riesige Werte else { onCurve1 = (cutPoint1.par1 < 1.0) & (cutPoint1.par1 > -100); } if (cutPoint.par2 > 0.5) { onCurve2 = (cutPoint2.par1 > 0.0) & (cutPoint2.par1 < 100); } else { onCurve2 = (cutPoint2.par1 < 1.0) & (cutPoint2.par1 > -100); } } if (onCurve1 && onCurve2) { line.SetTwoPoints(pl.ToGlobal(cutPoint1.p), pl.ToGlobal(cutPoint2.p)); // Fasenlänge vorgegeben, aber mit obiger Berechnung falsch, da dort Linien vorausgesetzt werden if ((methodSelect == 1) && (Math.Abs(line.Length - cutOffLen) > Precision.eps)) { // jetzt mit Iteration annähern double parInd = 0.5; double parIndDelta = 0.25; for (int i = 0; i < 49; ++i) // 48 Schritte müssen reichen, par kann zwischen 0 und 1 liegen { GeoPoint2D startPoint = pl.Project(newCurve.PointAt(parInd)); GeoVector2D vc = curve1_2D.DirectionAt(parInd); // die Richtung im Schnittpunkt if (cutPoint.par1 <= 0.5) { vc = vc.Opposite(); // evtl rumdrehen, falls am Ende } if (Geometry.OnLeftSide(dirPoint, startPoint, vc)) // Richtung festlegen für Winkeloffset { vc.Angle = vc.Angle + new SweepAngle(cutOffAng); } else { vc.Angle = vc.Angle - new SweepAngle(cutOffAng); } // Hilfslinie im Fasabstand, im Offsetwinkel line2D = new Line2D(startPoint, startPoint + vc); if (Curves2D.NearestPoint(curve1_2D.Intersect(line2D as ICurve2D), cutPoint.p + v, out cutPoint1)) { if (Curves2D.NearestPoint(curve2_2D.Intersect(line2D as ICurve2D), cutPoint.p + v, out cutPoint2)) { // da isse, die Fas-Linie, nur, wenn die Punkte echt auf der Kurvr liegen: if (cutPoint.par1 > 0.5) { onCurve1 = (cutPoint1.par1 > 0.0) & (cutPoint1.par1 < 100); } // im Quasi-Parallelfall stehen in par1 riesige Werte else { onCurve1 = (cutPoint1.par1 < 1.0) & (cutPoint1.par1 > -100); } if (cutPoint.par2 > 0.5) { onCurve2 = (cutPoint2.par1 > 0.0) & (cutPoint2.par1 < 100); } else { onCurve2 = (cutPoint2.par1 < 1.0) & (cutPoint2.par1 > -100); } if (onCurve1 && onCurve2) { line.SetTwoPoints(pl.ToGlobal(cutPoint1.p), pl.ToGlobal(cutPoint2.p)); if ((Math.Abs(line.Length - cutOffLen) < Precision.eps)) // gefunden und raus { break; } else { if (line.Length < cutOffLen) { // Fase ist zu klein: Parameter parInd vergrößern parInd = parInd + parIndDelta; parIndDelta = parIndDelta / 2.0; // delta halbieren (Bisection!!) continue; // nächster Schritt in der For-Schleife } } } } } // alle anderen Fälle: // Fase ist zu gross: Parameter parInd verkleinern parInd = parInd - parIndDelta; parIndDelta = parIndDelta / 2.0; // delta halbieren (Bisection!!) } // for schleife Iteration } // Ende Iteration line.CopyAttributes(iCurve1 as IGeoObject); base.ActiveObject = line; // merken base.FeedBack.AddSelected(line); // darstellen return(true); } } } } } } return(false); }