/// <summary> /// Overrides <see cref="CADability.GeoObject.ISurfaceImpl.PositionOf (GeoPoint)"/> /// </summary> /// <param name="p"></param> /// <returns></returns> public override GeoPoint2D PositionOf(GeoPoint p) { if (basisCurve.GetPlanarState() == PlanarState.Planar) { Plane cp = basisCurve.GetPlane(); // ICurve2D c2d = basisCurve.GetProjectedCurve(cp); wird nicht benötigt if (Precision.IsPerpendicular(cp.Normal, direction, false)) { } else { GeoPoint pp = cp.Intersect(p, direction); // direction darf natürlich nicht in der Ebene der Kurve liegen double u = basisCurve.PositionOf(pp); double v = Geometry.LinePar(basisCurve.PointAt(u), direction, p); #if DEBUG //GeoPoint2D dbg1 = base.PositionOf(p); //GeoPoint2D dbg2 = new GeoPoint2D(curveStartParameter + u * (curveEndParameter - curveStartParameter), v); //if ((dbg1 | dbg2) > 1e-6) //{ // throw new ApplicationException("error in SurfaceOfLinearExtrusion.PositionOf"); //} #endif return(new GeoPoint2D(curveStartParameter + u * (curveEndParameter - curveStartParameter), v)); } } Plane pl = new Plane(basisCurve.StartPoint, direction); ICurve2D projected = basisCurve.GetProjectedCurve(pl); double uu = projected.PositionOf(pl.Project(p)); // assuming the projected curve and the basisCurve have the same parameter space (which is true for NURBS) GeoPoint start = basisCurve.PointAt(uu); double vv = Geometry.LinePar(start, direction, p); return(new GeoPoint2D(uu, vv)); // GeoPoint2D res = base.PositionOf(p); // return res; }
private double OnCalculateDist(GeoPoint MousePosition) { if (theBaseCurve != null) { Plane pln; if (theBaseCurve.GetPlanarState() == PlanarState.Planar) { pln = theBaseCurve.GetPlane(); } else { pln = base.ActiveDrawingPlane; } ICurve2D c2d = theBaseCurve.GetProjectedCurve(pln); GeoPoint2D p2d = pln.Project(MousePosition); GeoPoint2D[] fp = c2d.PerpendicularFoot(p2d); int ind = -1; double mind = double.MaxValue; GeoVector2D dir = GeoVector2D.XAxis; // muss halt initialisiert sein for (int i = 0; i < fp.Length; ++i) { double d = Geometry.Dist(p2d, fp[i]); if (d < mind) { mind = d; ind = i; double pos = c2d.PositionOf(fp[i]); dir = c2d.DirectionAt(pos); } } if (ind >= 0) { if (Geometry.OnLeftSide(p2d, fp[ind], dir)) { return(-mind); } else { return(mind); } } } return(0.0); }
private bool showRound() { // jetzt werden die Rundparameter bestimmt base.ActiveObject = null; base.FeedBack.ClearSelected(); if ((iCurve1 != null) && (iCurve2 != null) && (iCurve1 != iCurve2)) { Plane pl; 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; } } else { owner = (iCurve1 as IGeoObject).Owner; // owner merken für löschen und Einfügen } // owner = (iCurve1 as IGeoObject).Owner; // owner merken für löschen und Einfügen bool rndPos = false; // Runden möglich double distCP; // Entfernung Pickpunkt - Schnittpunkte GeoPoint2D arcP1 = new GeoPoint2D(0.0, 0.0); GeoPoint2D arcP2 = new GeoPoint2D(0.0, 0.0); GeoPoint2D arcCenter = new GeoPoint2D(0.0, 0.0); 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(); } // hier die Schnittpunkte bestimmen und den cutPoint auf den nächsten Schnittpunt setzen GeoPoint2DWithParameter cutPoint; rndPos = Curves2D.NearestPoint(curve1_2D.Intersect(curve2_2D), pl.Project(objectPoint), out cutPoint); if (rndPos) // runden war möglich { arcCenter = cutPoint.p; double locmin1, locmin2; // Parametergrenzen vorbesetzen für den Fall: Realer Schnittpunkt locmin1 = 0.0; // Parametergrenzen vorbesetzen für den Fall: Realer Schnittpunkt locmin2 = 0.0; // Parametergrenzen vorbesetzen für den Fall: Realer Schnittpunkt double locmax1, locmax2; // Parametergrenzen vorbesetzen für den Fall: Realer Schnittpunkt locmax1 = 1.0; locmax2 = 1.0; double locPar; // für den Fall: virtueller Schnittpunkt die Parametergrenzen anpassen locPar = curve1_2D.PositionOf(cutPoint.p); // position des Schnittpunktes auf der Kurve1 //if ( locPar > 0.5) locmax1 = locPar; //else locmin1 = locPar; if (locPar > 1.0) { locmax1 = locPar; } if (locPar < 0.0) { locmin1 = locPar; } locPar = curve2_2D.PositionOf(cutPoint.p); // position des Schnittpunktes auf der Kurve2 if (locPar > 1.0) { locmax2 = locPar; } if (locPar < 0.0) { locmin2 = locPar; } //if (locPar > 0.5) locmax2 = locPar; //else locmin2 = locPar; // Kreis synthetisieren arc.SetArcPlaneCenterRadius(pl, pl.ToGlobal(arcCenter), roundRad); ICurve2D curveArc_2D = (arc as ICurve).GetProjectedCurve(pl); // Schnittpunkte Kreisbogen mit Kurve 1 GeoPoint2DWithParameter[] cutPoints = curve1_2D.Intersect(curveArc_2D); distCP = double.MaxValue; for (int i = 0; i < cutPoints.Length; ++i) // Schleife über alle Schnittpunkte { // nur der Schnittpunkt innerhalb der Kurve if ((cutPoints[i].par1 > locmin1) & (cutPoints[i].par1 < locmax1)) { double distLoc = Geometry.Dist(cutPoints[i].p, pl.Project(objectPoint)); if (distLoc < distCP) { distCP = distLoc; arcP1 = cutPoints[i].p; // Schnittpunkt schonmal merken } //arcP1 = cutPoints[i].p; //break; } } // Schnittpunkte Kreisbogen mit Kurve 2 cutPoints = curve2_2D.Intersect(curveArc_2D); distCP = double.MaxValue; for (int i = 0; i < cutPoints.Length; ++i) // Schleife über alle Schnittpunkte { // nur der Schnittpunkt innerhalb der Kurve if ((cutPoints[i].par1 > locmin2) & (cutPoints[i].par1 < locmax2)) { double distLoc = Geometry.Dist(cutPoints[i].p, pl.Project(objectPoint)); if (distLoc < distCP) { distCP = distLoc; arcP2 = cutPoints[i].p; // Schnittpunkt schonmal merken } // arcP2 = cutPoints[i].p; // break; } } if (!Precision.IsEqual(arcP1, arcP2)) // runden war möglich { // Mittelwert zwischen dem Kurven // roundRadCalc = (Math.Abs(curve1_2D.Distance(pl.Project(radiusPoint))) + Math.Abs(curve2_2D.Distance(pl.Project(radiusPoint)))) / 2.0; // objectPoint = pl.ToGlobal(cutPoint.p); // merken für onDone, als Entscheidungskriterium arc.SetArcPlaneCenterStartEndPoint(base.ActiveDrawingPlane, arcCenter, arcP1, arcP2, pl, false); Ellipse arc1 = Ellipse.Construct(); arc1.SetArcPlaneCenterStartEndPoint(base.ActiveDrawingPlane, arcCenter, arcP1, arcP2, pl, true); if (Math.Abs(arc.SweepParameter) > Math.Abs(arc1.SweepParameter)) // es ist immer der kleinere Bogen! { arc = arc1; } arc.CopyAttributes(iCurve1 as IGeoObject); base.ActiveObject = arc; // merken base.FeedBack.AddSelected(arc); // darstellen return(true); } } } } // roundObject.HitCursor = CursorTable.GetCursor("RoundIn.cur"); return(false); }
private bool showLine() { ArrayList usableCurves = new ArrayList(); // lokales Array, das die gültigen Kurven sammelt double mindist = double.MaxValue; for (int i = 0; i < perpCurves.Length; ++i) { Plane pl; if (Curves.GetCommonPlane(startPoint, perpCurves[i], out pl)) { ICurve2D l2D = perpCurves[i].GetProjectedCurve(pl); if (l2D is Path2D) { (l2D as Path2D).Flatten(); } GeoPoint2D[] perpPoints = l2D.PerpendicularFoot(pl.Project(startPoint)); if (perpPoints.Length > 0) { // eine gültige Kurve ist gefunden usableCurves.Add(perpCurves[i]); for (int j = 0; j < perpPoints.Length; ++j) { // double dist = Geometry.Dist(perpPoints[j],pl.Project(startPoint)); double dist = Geometry.Dist(perpPoints[j], pl.Project(objectPoint)); if (dist < mindist) { mindist = dist; selected = usableCurves.Count - 1; // merken, welche Kurve die aktuell benutzte ist endPoint = perpPoints[j]; } } } else { // beim Kreis oder Bogen vom Mittelpunkt aus gilt jeder Punkt if (l2D is Circle2D) { if (Precision.IsEqual((l2D as Circle2D).Center, pl.Project(startPoint))) { GeoPoint2D pp = l2D.PointAt(l2D.PositionOf(pl.Project(objectPoint))); double dist = Geometry.Dist(pp, pl.Project(objectPoint)); if (dist < mindist) { mindist = dist; selected = usableCurves.Count - 1; // merken, welche Kurve die aktuell benutzte ist endPoint = pp; } } } } } if (mindist < double.MaxValue) { line.SetTwoPoints(startPoint, pl.ToGlobal(endPoint)); perpCurves = (ICurve[])usableCurves.ToArray(typeof(ICurve)); // perpCurves wird mit den gültigen überschrieben und unten zur Anzeige zurückgegeben an den Sender base.ShowActiveObject = true; return(true); } } line.SetTwoPoints(startPoint, objectPoint); base.ShowActiveObject = true; return(false); }
private void AddSplittedFace(Face face) { List <ICurve> edgeCurves = new List <ICurve>(); List <ICurve2D> curves2d = new List <ICurve2D>(); #if DEBUG Vertex[] vtx = face.Vertices; bool[] outside = new bool[vtx.Length]; Polyline pln = Polyline.Construct(); for (int i = 0; i < vtx.Length; i++) { outside[i] = outsideVertices.Contains(vtx[i]); pln.AddPoint(vtx[i].Position); } DebuggerContainer dc = new DebuggerContainer(); #endif Edge[] edges = face.AllEdges; // sollte keine Löcher haben for (int i = 0; i < edges.Length; i++) { List <double> positions; if (splitedEdges.TryGetValue(edges[i], out positions)) { List <double> pos = new List <double>(positions); pos.Add(0.0); pos.Add(1.0); pos.Sort(); int startj; Vertex startVertex; ICurve2D c2d = edges[i].Curve2D(face); #if DEBUG dc.Add(c2d, System.Drawing.Color.Red, i); #endif if ((face.Surface.PointAt(c2d.StartPoint) | edges[i].Vertex1.Position) < (face.Surface.PointAt(c2d.StartPoint) | edges[i].Vertex2.Position)) { startVertex = edges[i].Vertex1; } else { startVertex = edges[i].Vertex2; // die Kurve geht andersrum als die Kante, also Kantenschnittpunkte umdrehen pos.Reverse(); } if (outsideVertices.Contains(startVertex)) { startj = 1; } else { startj = 0; } for (int j = startj; j < pos.Count - 1; j += 2) { double pos1 = c2d.PositionOf(face.Surface.PositionOf(edges[i].Curve3D.PointAt(pos[j]))); double pos2 = c2d.PositionOf(face.Surface.PositionOf(edges[i].Curve3D.PointAt(pos[j + 1]))); if (pos2 < pos1) { double tmp = pos1; pos1 = pos2; pos2 = tmp; } ICurve2D trimmed = c2d.Trim(pos1, pos2); curves2d.Add(trimmed); #if DEBUG dc.Add(trimmed, System.Drawing.Color.Blue, i); #endif } } else { if (!outsideVertices.Contains(edges[i].Vertex1)) { #if DEBUG dc.Add(edges[i].Curve2D(face), System.Drawing.Color.Green, i); #endif curves2d.Add(edges[i].Curve2D(face)); } } } List <ICurve2D> lc2d; if (all2DCurves.TryGetValue(face, out lc2d)) { for (int i = 0; i < lc2d.Count; i++) { #if DEBUG dc.Add(lc2d[i], System.Drawing.Color.HotPink, i); #endif // die folgende Kurve mit Start- und Endpunkt anpassen, denn sie ist evtl ungenau... curves2d.Add(lc2d[i]); } } // alle zuletzt hinzugefügten Kurven magnetisch einschnappen lassen for (int i = all2DCurves.Count - lc2d.Count; i < all2DCurves.Count; i++) { AddAndAdjust2DCurve(curves2d, i); } // eigentlich wäre mehr Information vorhanden, als dass man diese Kurven völlig neu sortieren müsste // aber so ist es nun mal einfacher ICurve2D[] acsd = new ICurve2D[curves2d.Count]; for (int i = 0; i < acsd.Length; i++) { acsd[i] = curves2d[i].Clone(); } Reduce2D r2d = new Reduce2D(); r2d.Add(acsd); r2d.OutputMode = Reduce2D.Mode.Paths; ICurve2D[] red = r2d.Reduced; if (red.Length == 1) { Border bdr = new Border(red[0]); SimpleShape ss = new SimpleShape(bdr); Face splitted = Face.MakeFace(face.Surface, ss); resultingFaces.Add(splitted); } //CompoundShape cs = CompoundShape.CreateFromList(acsd, Precision.eps); //if (cs != null && cs.SimpleShapes.Length == 1) //{ // SimpleShape ss = cs.SimpleShapes[0]; // Face splitted = Face.MakeFace(face.Surface, ss); // resultingFaces.Add(splitted); //} //else //{ //} }
/// <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) { GeoPoint2DWithParameter[] res = l2d.Intersect(this); // die Linie kanns // aber noch die Rollen vertauschen for (int i = 0; i < res.Length; ++i) { // par1 und par2 vertauschen double tmp = res[i].par1; res[i].par1 = res[i].par2; res[i].par2 = tmp; } return(res); } else if (IntersectWith is Circle2D) // geht auch für Arc2D { GeoPoint2D[] ip = Geometry.IntersectEC(center, majrad, minrad, majorAxis.Angle, (IntersectWith as Circle2D).Center, (IntersectWith as Circle2D).Radius); GeoPoint2DWithParameter[] res = new GeoPoint2DWithParameter[ip.Length]; double error = 0.0; for (int i = 0; i < ip.Length; ++i) { GeoPoint2D p0 = toUnitCircle * ip[i]; error += Math.Abs(1.0 - p0.ToVector().Length); error += Math.Abs(1.0 - (ip[i] | (IntersectWith as Circle2D).Center) / (IntersectWith as Circle2D).Radius); res[i].p = ip[i]; res[i].par1 = PositionOf(ip[i]); res[i].par2 = IntersectWith.PositionOf(ip[i]); // liefert auch für Arc2D den richtigen Wert } if (error < 1e-7) // auf Radius 1 normierter fehler { // wenn nicht, dann unten mit dreiecksschnitten lösen return(res); } } else if (IntersectWith is Ellipse2D) // geht auch für EllipseArc2D { Ellipse2D elli = (IntersectWith as Ellipse2D); Ellipse2D ellinorm = this.GetModified(elli.toUnitCircle) as Ellipse2D; GeoPoint2D[] ip = Geometry.IntersectEC(ellinorm.center, ellinorm.majrad, ellinorm.minrad, ellinorm.majorAxis.Angle, elli.toUnitCircle * elli.center, 1.0); GeoPoint2DWithParameter[] res = new GeoPoint2DWithParameter[ip.Length]; for (int i = 0; i < ip.Length; ++i) { res[i].p = elli.fromUnitCircle * ip[i]; res[i].par1 = PositionOf(res[i].p); res[i].par2 = IntersectWith.PositionOf(res[i].p); } for (int i = 0; i < res.Length; i++) { RefineIntersectionPoint(this, elli, ref res[i]); } if (((ellinorm.Center | GeoPoint2D.Origin) < Precision.eps) && res.Length == 0) { // gleicher Mittelpunkt und keine Lösung, könnte zusammenhängender Bogen zweier identischen Ellipsen sein bool connected = false; GeoPoint2D p = GeoPoint2D.Origin; double par0 = 0.0; double par1 = 0.0; if ((this.EndPoint | elli.StartPoint) < Precision.eps) { p = this.EndPoint; par0 = 1.0; par1 = 0.0; connected = true; } if ((this.EndPoint | elli.EndPoint) < Precision.eps) { p = this.EndPoint; par0 = 1.0; par1 = 1.0; connected = true; } if ((this.StartPoint | elli.StartPoint) < Precision.eps) { p = this.StartPoint; par0 = 0.0; par1 = 0.0; connected = true; } if ((this.StartPoint | elli.EndPoint) < Precision.eps) { p = this.StartPoint; par0 = 0.0; par1 = 1.0; connected = true; } if (connected) { res = new GeoPoint2DWithParameter[1]; res[0] = new GeoPoint2DWithParameter(p, par0, par1); } } return(res); } // auch wenn die Ellipsenschnittpunkte schlecht waren return(base.Intersect(IntersectWith)); }
private bool showCutOff() { // nur wenn beide Kurven gültig sind if ((iCurve1 != null) && (iCurve2 != null) && (iCurve1 != iCurve2)) { Plane pl; // nur bei gemeisamer Ebene if (Curves.GetCommonPlane(iCurve1, iCurve2, out pl)) { // !!! // 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)) // runden 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 sythetisieren: * if (cutPoint.par1 <= 0.5) * { * newCurve.StartPoint = iCurve1.PointAt(cutPoint.par1); * parCut = (sideLength)/newCurve.Length; // der Parameter des Fasenpunktes * } * else * { * newCurve.EndPoint = iCurve1.PointAt(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; 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 line = Line.Construct(); 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 objectPoint = pl.ToGlobal(cutPoint.p); if (iCurve1.PositionOf(objectPoint) > 0.5) // am oberen Ende geklickt { iCurve1.Trim(0.0, iCurve1.PositionOf(line.StartPoint)); } else { iCurve1.Trim(iCurve1.PositionOf(line.StartPoint), 1.0); } if (iCurve2.PositionOf(objectPoint) > 0.5) // am oberen Ende geklickt { iCurve2.Trim(0.0, iCurve2.PositionOf(line.EndPoint)); objectPoint = iCurve2.StartPoint; } else { iCurve2.Trim(iCurve2.PositionOf(line.EndPoint), 1.0); objectPoint = iCurve2.EndPoint; } (line as IGeoObject).CopyAttributes(iCurve1 as IGeoObject); // objectPoint = pl.ToGlobal(cutPoint2.p); blk.Add(iCurve1 as IGeoObject); blk.Add(line); // base.FeedBack.AddSelected(iCurve1 as IGeoObject);// darstellen // base.FeedBack.AddSelected(line);// darstellen iCurve1 = iCurve2; // getrimmte Curve2 als Grundlage zur nächsten Berechnung return(true); } } } } } blk.Add(iCurve1 as IGeoObject); // unveränderte 1. Kurve zufügen, da kein Fasen möglich // base.FeedBack.AddSelected(iCurve1 as IGeoObject);// darstellen iCurve1 = iCurve2; // unveränderte Curve2 als Grundlage zur nächsten Berechnung } // base.ActiveObject = null; return(false); }
private bool showObject() { base.FeedBack.ClearSelected(); base.ActiveObject = null; double[] cutPlace; ICurve2D c2d = iCurve.GetProjectedCurve(CurrentMouseView.Projection.ProjectionPlane); GeoPoint2D op2d = CurrentMouseView.Projection.ProjectUnscaled(objectPoint); lowerEnd = (c2d.PositionOf(op2d) < 0.5); // im 2D überprüfen, in 3D ist objectPoint möglicherweise weit von iCurve entfernt // bool lowerEnd = (iCurve.PositionOf(objectPoint)< 0.5); ProjectedModel.IntersectionMode cutMode; bool realCut; if (lowerEnd) { cutMode = ProjectedModel.IntersectionMode.StartExtension; } else { cutMode = ProjectedModel.IntersectionMode.EndExtension; } // if (expandSourceObject.Fixed) ICurve[] targetCurves = null; if (sourceCurve != null) { cutPlace = Curves.Intersect(iCurve, sourceCurve, false); } else { cutPlace = base.Frame.ActiveView.ProjectedModel.GetIntersectionParameters(iCurve, cutMode, out targetCurves); } if (cutPlace.Length > 0) { realCut = false; for (int i = 0; i < cutPlace.Length; ++i) { if (distToCurve.Length == 0) { if (cutPlace[i] < -1e-8 || cutPlace[i] > 1 + 1e-8) // Endpunkte nicht mit berücksichtigen //if (!((Math.Abs(cutPlace[i]) < 1e-8) || (Math.Abs(cutPlace[i] - 1) < 1e-8))) { realCut = true; break; } } else { //if (cutPlace[i] < 1e-8 || cutPlace[i] > 1 - 1e-8) // Endpunkte mit berücksichtigen { realCut = true; break; } } } if (realCut) { int k = -1; if (lowerEnd) { param = double.MinValue; } else { param = double.MaxValue; } double eps; // wenn distToCurve gesetzt ist, dann bleibt ein exakt getrimmtes am Ende gültig, ansonsten wird die nächste Querkurve verwendet if (distToCurve.Length == 0) { eps = 1e-8; } else { if (sourceCurve != null && sourceCurve.Length > 0) // eine Zielkurve wurde angewählt. Schnitte dürfen jetzt vor dem Ende von iCurve sein //eps = -Math.Abs(distToCurve.Length) / sourceCurve.Length; { eps = -1.0; // egal, Hauptsache auf der Kurve } else { eps = -1e-8; } } for (int i = 0; i < cutPlace.Length; ++i) { if (lowerEnd) { // verlängern nach hinten, der größte Wert, der kleiner Null und ungleich quasi Null if ((cutPlace[i] > param) && (cutPlace[i] < 0.0 - eps)) { param = cutPlace[i]; k = i; } } else { // verlängern nach vorne, der kleinste Wert, der größer 1.0 und ungleich quasi 1.0 if ((cutPlace[i] < param) && (cutPlace[i] > 1.0 + eps)) { param = cutPlace[i]; k = i; } } } if (k >= 0) // was gefunden { newCurve = iCurve.Clone(); if (distToCurve.Length != 0.0) { // zusätzlich länger oder kürzer machen ICurve targetCurve = sourceCurve; if (targetCurves != null) { targetCurve = targetCurves[k]; } Plane pl; if (Curves.GetCommonPlane(iCurve, targetCurve, out pl)) { // muss der Fall sein ICurve2D targetCurve2d = targetCurve.GetProjectedCurve(pl); ICurve2D parl1 = targetCurve2d.Parallel(-distToCurve.Length, true, Precision.eps, 0.0); ICurve2D parl2 = targetCurve2d.Parallel(distToCurve.Length, true, Precision.eps, 0.0); ICurve2D newCurve2d = newCurve.GetProjectedCurve(pl); // im 2d verlängern if (lowerEnd) { newCurve2d.StartPoint = newCurve2d.PointAt(param); } else { newCurve2d.EndPoint = newCurve2d.PointAt(param); } if (lowerEnd) { // jetzt nur den Vorwärtsfall betrachten newCurve2d.Reverse(); } // betrachte beide Parallelen, wir kennen die Richtungen nicht GeoPoint2DWithParameter[] gp1 = newCurve2d.Intersect(parl1); GeoPoint2DWithParameter[] gp2 = newCurve2d.Intersect(parl2); double bestPar; if (distToCurve.Length > 0) { // Kurve muss kürzer werden bestPar = 0.0; for (int i = 0; i < gp1.Length; i++) { if (gp1[i].par2 >= 0 && gp1[i].par2 <= 1 && gp1[i].par1 <1 && gp1[i].par1> bestPar) { bestPar = gp1[i].par1; } } for (int i = 0; i < gp2.Length; i++) { if (gp2[i].par2 >= 0 && gp2[i].par2 <= 1 && gp2[i].par1 <1 && gp2[i].par1> bestPar) { bestPar = gp2[i].par1; } } } else { bestPar = double.MaxValue; for (int i = 0; i < gp1.Length; i++) { if (gp1[i].par2 >= 0 && gp1[i].par2 <= 1 && gp1[i].par1 > 1 && gp1[i].par1 < bestPar) { bestPar = gp1[i].par1; } } for (int i = 0; i < gp2.Length; i++) { if (gp2[i].par2 >= 0 && gp2[i].par2 <= 1 && gp2[i].par1 > 1 && gp2[i].par1 < bestPar) { bestPar = gp2[i].par1; } } } // den gefundenen Punkt auf die Kurve setzen if (bestPar > 0 && bestPar < double.MaxValue) { GeoPoint pp = pl.ToGlobal(newCurve2d.PointAt(bestPar)); param = iCurve.PositionOf(pp); // param ist das eigentliche Ergebnis, welches bei onDone verwendet wird if (lowerEnd) { newCurve.StartPoint = pp; } else { newCurve.EndPoint = pp; } } } } else { if (lowerEnd) { newCurve.StartPoint = iCurve.PointAt(param); } else { newCurve.EndPoint = iCurve.PointAt(param); } } (newCurve as IGeoObject).CopyAttributes(iCurve as IGeoObject); //Color backColor = base.Frame.GetColorSetting("Colors.Feedback", Color.DarkGray); //if (newCurve is IColorDef) // (newCurve as IColorDef).ColorDef = new ColorDef("", backColor); base.ActiveObject = (newCurve as IGeoObject); base.FeedBack.AddSelected(newCurve as IGeoObject);// letzte Linie einfügen return(true); } } } param = 0.0; return(false); }
private bool showRound() { // jetzt werden die Rundparameter bestimmt Plane pl; try { if (Curves.GetCommonPlane(iCurve1, iCurve2, out pl)) { bool rndPos = false; // Runden möglich GeoPoint2D arcP1 = new GeoPoint2D(0.0, 0.0); GeoPoint2D arcP2 = new GeoPoint2D(0.0, 0.0); GeoPoint2D arcP1Loc = new GeoPoint2D(0.0, 0.0); GeoPoint2D arcP2Loc = new GeoPoint2D(0.0, 0.0); GeoPoint2D arcCenter = new GeoPoint2D(0.0, 0.0); 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(); } // ist beim menrfachrunden nicht nötig!! // hier die Schnittpunkte bestimmen und den ObjectPoint auf den nächsten Schnittpunt setzen // GeoPoint2DWithParameter[] intersectPoints = curve1_2D.Intersect(curve2_2D); // GeoPoint2D objectPoint2D = new GeoPoint2D(0.0,0.0); // double distS = double.MaxValue; // Entfernung des Pickpunkts zu den Schnittpunkten // for (int i=0; i< intersectPoints.Length; ++i) // macht hier wenig Sinn, schadet aber auch nicht // { // macht hier wenig Sinn, schadet aber auch nicht, Kompatibilität zum einfachrunden // double distLoc = Geometry.dist(intersectPoints[i].p,pl.Project(objectPoint)); // if (distLoc < distS) // { // distS = distLoc; // objectPoint2D = intersectPoints[i].p; // Pickpunkt merken // } // } // statt der Berechnung oben: Auswahlpunkt ist der gemeinsame Punkt der beiden Kurven!! GeoPoint2D objectPoint2D = curve1_2D.EndPoint; double locmin1, locmin2; // Parametergrenzen vorbesetzen für den Fall: Realer Schnittpunkt locmin1 = 0.0; // Parametergrenzen vorbesetzen für den Fall: Realer Schnittpunkt locmin2 = 0.0; // Parametergrenzen vorbesetzen für den Fall: Realer Schnittpunkt double locmax1, locmax2; // Parametergrenzen vorbesetzen für den Fall: Realer Schnittpunkt locmax1 = 1.0; locmax2 = 1.0; // bei mehfachrunden nicht nötig, da alle aneinanderhängen, also nur reale Schnittpunkte! // double locPar; // für den Fall: virtueller Schnittpunkt die Parametergrenzen anpassen // locPar = curve1_2D.PositionOf(objectPoint2D); // position des Schnittpunktes auf der Kurve1 // if ( locPar > 1.0) locmax1 = locPar; // if ( locPar < 0.0) locmin1 = locPar; // locPar = curve2_2D.PositionOf(objectPoint2D); // position des Schnittpunktes auf der Kurve2 // if ( locPar > 1.0) locmax2 = locPar; // if ( locPar < 0.0) locmin2 = locPar; // die Parallelen links und rechts der 2 Kurven ICurve2D P1L1 = curve1_2D.Parallel(roundRad, false, 0.0, 0.0); ICurve2D P1L2 = curve1_2D.Parallel(-roundRad, false, 0.0, 0.0); ICurve2D P2L1 = curve2_2D.Parallel(roundRad, false, 0.0, 0.0); ICurve2D P2L2 = curve2_2D.Parallel(-roundRad, false, 0.0, 0.0); // nun alle mit allen schneiden und Schnittpunkte (=evtl. Mittelpunkte des Bogens) merken ArrayList centers = new ArrayList(); centers.AddRange(P1L1.Intersect(P2L1)); centers.AddRange(P1L1.Intersect(P2L2)); centers.AddRange(P1L2.Intersect(P2L1)); centers.AddRange(P1L2.Intersect(P2L2)); GeoPoint2DWithParameter[] centerPoints = (GeoPoint2DWithParameter[])centers.ToArray(typeof(GeoPoint2DWithParameter)); GeoPoint2D[] perpP; // Lotfusspunkte double loc; // location des schnittpunktes der parallelen auf der Kurve double distCP; // Entfernung von der Ecke für Fusspunkte double distCS = double.MaxValue; // Entfernung von der Ecke für Schnittpunkte bool ok1, ok2; // der gesuchte Schnittpunkt hat einen realen Lotfusspunkt auf beiden Kurven und den Abstand roundRad von diesen for (int i = 0; i < centerPoints.Length; ++i) // Schleife über alle Schnittpunkte { ok1 = false; ok2 = false; perpP = curve1_2D.PerpendicularFoot(centerPoints[i].p); // Lotpunkt(e) Kurve 1 distCP = double.MaxValue; for (int j = 0; j < perpP.Length; ++j) // Schleife über alle Lotpunkte Kurve 1 { loc = curve1_2D.PositionOf(perpP[j]); // der Parameter des j. Lotpunktes auf Kurve1 // der Parameter muss innerhalb der Kurve sein und der Abstand = roundRad if ((loc >= locmin1) & (loc <= locmax1) & (Math.Abs(Geometry.Dist(perpP[j], centerPoints[i].p) - roundRad) < Precision.eps)) { double distLoc = Geometry.Dist(perpP[j], objectPoint2D); if (distLoc < distCP) { distCP = distLoc; arcP1Loc = perpP[j]; // Lotpunkt schonmal merken } ok1 = true; } } if (ok1) // also was gefunden oben, jetzt dasselbe mit Kurve 2 { perpP = curve2_2D.PerpendicularFoot(centerPoints[i].p); // Lotpunkt(e) Kurve 2 distCP = double.MaxValue; for (int j = 0; j < perpP.Length; ++j) // Schleife über alle Lotpunkte Kurve 2 { loc = curve2_2D.PositionOf(perpP[j]); // der Parameter des j. Lotpunktes auf Kurve2 // der Parameter muss innerhalb der Kurve sein und der Abstand = roundRad if ((loc >= locmin2) & (loc <= locmax2) & (Math.Abs(Geometry.Dist(perpP[j], centerPoints[i].p) - roundRad) < Precision.eps)) { double distLoc = Geometry.Dist(perpP[j], objectPoint2D); if (distLoc < distCP) { distCP = distLoc; arcP2Loc = perpP[j]; // Lotpunkt schonmal merken } ok2 = true; } } } if (ok2) { // falls mehrere Schnittpunkte alle Bedingungen erfüllen: Den nächsten nehmen! double distLoc = Geometry.Dist(centerPoints[i].p, objectPoint2D); if (distLoc < distCS) { distCS = distLoc; // jetzt merken arcCenter = centerPoints[i].p; arcP1 = arcP1Loc; arcP2 = arcP2Loc; rndPos = true; } } } if (rndPos && !Precision.IsEqual(arcP1, arcP2)) // runden war möglich { // Mittelwert zwischen dem Kurven // roundRadCalc = (Math.Abs(curve1_2D.Distance(pl.Project(radiusPoint))) + Math.Abs(curve2_2D.Distance(pl.Project(radiusPoint)))) / 2.0; objectPoint = pl.ToGlobal(objectPoint2D); // merken als Entscheidungskriterium, ist hier immer der Schnittpunkt Ellipse arc = Ellipse.Construct(); Ellipse arc1 = Ellipse.Construct(); arc.SetArcPlaneCenterStartEndPoint(base.ActiveDrawingPlane, arcCenter, arcP1, arcP2, pl, false); arc1.SetArcPlaneCenterStartEndPoint(base.ActiveDrawingPlane, arcCenter, arcP1, arcP2, pl, true); if (Math.Abs(arc.SweepParameter) > Math.Abs(arc1.SweepParameter)) // es ist immer der kleinere Bogen! { arc = arc1; } arc.CopyAttributes(iCurve1 as IGeoObject); if (iCurve1.PositionOf(objectPoint) > 0.5) { iCurve1.Trim(0.0, iCurve1.PositionOf(arc.StartPoint)); } else { iCurve1.Trim(iCurve1.PositionOf(arc.StartPoint), 1.0); } if (iCurve2.PositionOf(objectPoint) > 0.5) { iCurve2.Trim(0.0, iCurve2.PositionOf(arc.EndPoint)); } else { iCurve2.Trim(iCurve2.PositionOf(arc.EndPoint), 1.0); } if (iCurve1.Length > Precision.eps) { blk.Add(iCurve1 as IGeoObject); // base.FeedBack.AddSelected(iCurve1 as IGeoObject); // darstellen } blk.Add(arc); // base.FeedBack.AddSelected(arc); // darstellen iCurve1 = iCurve2; // getrimmte Curve2 als Grundlage zur nächsten Berechnung return(true); } } } catch (ApplicationException e) { return(false); } blk.Add(iCurve1 as IGeoObject); // unveränderte 1. Kurve zufügen, da kein Runden möglich // base.FeedBack.AddSelected(iCurve1 as IGeoObject); // darstellen iCurve1 = iCurve2; // unveränderte Curve2 als Grundlage zur nächsten Berechnung return(false); }