/// <summary> /// Overrides <see cref="CADability.Curve2D.GeneralCurve2D.Copy (ICurve2D)"/> /// </summary> /// <param name="toCopyFrom"></param> public override void Copy(ICurve2D toCopyFrom) { Polyline2D c = toCopyFrom as Polyline2D; this.vertex = (GeoPoint2D[])c.vertex.Clone(); UserData.CloneFrom(c.UserData); }
/// <summary> /// Overrides <see cref="CADability.Curve2D.GeneralCurve2D.Clone ()"/> /// </summary> /// <returns></returns> public override ICurve2D Clone() { Polyline2D res = new Polyline2D(vertex); res.UserData.CloneFrom(this.UserData); return(res); }
public override ICurve2D GetModified(ModOp2D m) { Polyline2D res = this.Clone() as Polyline2D; res.Modify(m); return(res); }
/// <summary> /// Overrides <see cref="CADability.Curve2D.GeneralCurve2D.CloneReverse (bool)"/> /// </summary> /// <param name="reverse"></param> /// <returns></returns> public override ICurve2D CloneReverse(bool reverse) { Polyline2D res = (Polyline2D)this.Clone(); if (reverse) { res.Reverse(); } 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 ((EndPos - StartPos) < (1.0 / vertex.Length)) { if (Precision.IsEqual(PointAt(StartPos), PointAt(EndPos))) { return(null); } } Polyline2D res = this.Clone() as Polyline2D; try { res.TrimOff(StartPos, EndPos); return(res); } catch (Polyline2DException) { // ein zu kurzes Stück wird dort nicht akzeptiert return(null); } }
/// <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) { GeoPoint2D ip; if (Geometry.IntersectLL(startPoint, endPoint, l2d.StartPoint, l2d.EndPoint, out ip)) { double pos1 = this.PositionOf(ip); double pos2 = l2d.PositionOf(ip); GeoPoint2DWithParameter pwp = new GeoPoint2DWithParameter(); pwp.p = ip; pwp.par1 = pos1; pwp.par2 = pos2; return(new GeoPoint2DWithParameter[] { pwp }); } else { return(new GeoPoint2DWithParameter[0]); } } Circle2D c2d = IntersectWith as Circle2D; if (c2d != null) { GeoPoint2D[] isp = Geometry.IntersectLC(startPoint, endPoint, c2d.Center, c2d.Radius); GeoPoint2DWithParameter[] res = new GeoPoint2DWithParameter[isp.Length]; for (int i = 0; i < isp.Length; ++i) { res[i].p = isp[i]; res[i].par1 = this.PositionOf(isp[i]); res[i].par2 = c2d.PositionOf(isp[i]); } return(res); } Ellipse2D e2d = IntersectWith as Ellipse2D; if (e2d != null) { GeoPoint2D[] isp = Geometry.IntersectEL(e2d.center, e2d.majorAxis.Length, e2d.minorAxis.Length, e2d.majorAxis.Angle, startPoint, endPoint); GeoPoint2DWithParameter[] res = new GeoPoint2DWithParameter[isp.Length]; for (int i = 0; i < isp.Length; ++i) { res[i].p = isp[i]; res[i].par1 = this.PositionOf(isp[i]); res[i].par2 = e2d.PositionOf(isp[i]); } return(res); } Polyline2D p2d = IntersectWith as Polyline2D; if (p2d != null) { GeoPoint2DWithParameter[] res = p2d.Intersect(this); // sorum geht es for (int i = 0; i < res.Length; ++i) { double t = res[i].par1; res[i].par1 = res[i].par2; res[i].par2 = t; } return(res); } Path2D pa2d = IntersectWith as Path2D; if (pa2d != null) { GeoPoint2DWithParameter[] res = pa2d.Intersect(this); // sorum geht es for (int i = 0; i < res.Length; ++i) { double t = res[i].par1; res[i].par1 = res[i].par2; res[i].par2 = t; } return(res); } BSpline2D b2d = IntersectWith as BSpline2D; if (b2d != null) { GeoPoint2DWithParameter[] res = b2d.Intersect(this); // sorum geht es for (int i = 0; i < res.Length; ++i) { double t = res[i].par1; res[i].par1 = res[i].par2; res[i].par2 = t; } return(res); } return(base.Intersect(IntersectWith)); }
public override ICurve2D GetFused(ICurve2D toFuseWith, double precision) { if (toFuseWith is Line2D) { toFuseWith = new Polyline2D(new GeoPoint2D[] { toFuseWith.StartPoint, toFuseWith.EndPoint }); } if (toFuseWith is Polyline2D) { Polyline2D pl1, pl2; if (length < toFuseWith.Length) { pl1 = toFuseWith.Clone() as Polyline2D; // 1. die längere pl2 = this.Clone() as Polyline2D; } else { pl1 = this.Clone() as Polyline2D; pl2 = toFuseWith.Clone() as Polyline2D; } // die kürzere muss wenigstens start oder endpunkt auf der längeren haben double pos1 = pl1.PositionOf(pl2.StartPoint); double pos2 = pl1.PositionOf(pl2.EndPoint); bool pos1inside = false; bool pos2inside = false; if (pos1 >= 0.0 && pos1 <= 1.0) { // Startpunkt liegt drauf if (Math.Abs(pl1.Distance(pl2.StartPoint)) < precision) { pos1inside = true; } } if (pos2 >= 0.0 && pos2 <= 1.0) { // Startpunkt liegt drauf if (Math.Abs(pl1.Distance(pl2.EndPoint)) < precision) { pos2inside = true; } } GeoPoint2D split1 = GeoPoint2D.Origin, split2 = GeoPoint2D.Origin; bool split = false; if (pos1inside && pos2inside) { bool ok = true; for (int i = 0; i < pl2.VertexCount; i++) { if (Math.Abs(pl1.Distance(pl2.vertex[i])) > precision) { ok = false; } } if (ok) { return(pl1); // die ist es bereits, und es ist ja auch ein clone } else { return(null); // zu großer Abstand } } else if (pos2inside) { // der Endpunkt von pl2 liegt innerhalb, der Startpunkt außerhalb double p = pl2.PositionOf(pl1.StartPoint); if (p >= 0.0 && p <= 1.0) { if (Math.Abs(pl2.Distance(pl1.StartPoint)) < precision) { // fängt an mit pl2, endet mid pl1, beide schon richtige Richtung split1 = pl1.StartPoint; split2 = pl2.EndPoint; split = true; Polyline2D tmp = pl2; pl2 = pl1; pl1 = tmp; } } if (!split) { p = pl2.PositionOf(pl1.EndPoint); if (p >= 0.0 && p <= 1.0) { if (Math.Abs(pl2.Distance(pl1.EndPoint)) < precision) { // fängt an mit pl2, endet mid pl1, pl1 muss umgedreht werden split1 = pl1.EndPoint; split2 = pl2.EndPoint; split = true; pl1.Reverse(); Polyline2D tmp = pl2; pl2 = pl1; pl1 = tmp; } } } } else if (pos1inside) { // der Startpunkt von pl2 liegt innerhalb, der Endpunkt außerhalb double p = pl2.PositionOf(pl1.StartPoint); if (p >= 0.0 && p <= 1.0) { if (Math.Abs(pl2.Distance(pl1.StartPoint)) < precision) { // fängt an mit pl1, endet mid pl2, pl1 falschrum split1 = pl2.StartPoint; split2 = pl1.StartPoint; split = true; pl1.Reverse(); } } if (!split) { p = pl2.PositionOf(pl1.EndPoint); if (p >= 0.0 && p <= 1.0) { if (Math.Abs(pl2.Distance(pl1.EndPoint)) < precision) { // fängt an mit pl1, endet mid pl2, beide richtigrum split1 = pl2.StartPoint; split2 = pl1.EndPoint; split = true; } } } } if (split) { // sie überlappen sich, das kann im Extramfall acuh einfach zusammenhängend sein #if DEBUG DebuggerContainer dc = new DebuggerContainer(); dc.Add(pl1, Color.Red, 1); dc.Add(pl2, Color.Green, 2); dc.Add(split1, Color.Red, 3); dc.Add(split2, Color.Blue, 4); #endif // if (pl1.ConnectWith(pl2, precision)) return pl1; // damit ist das schon erledigt, sonst gibt es beim Splitten einen Fehler // das macht Probleme bei zwei fast identischichen Polylines, die werden sonst in Gegenrichtung miteinander verbunden ICurve2D[] spl1 = pl1.Split(pl1.PositionOf(split1)); ICurve2D[] spl2 = pl2.Split(pl2.PositionOf(split2)); // Der Anfang von spl1 und das Ende von spl2 sind die Endstücke, das Mittelteil ist doppelt und muss identisch sein if (spl1.Length == 2 && spl2.Length == 2) { Polyline2D m1 = spl1[1] as Polyline2D; Polyline2D m2 = spl2[0] as Polyline2D; bool ok = true; for (int i = 0; i < m1.VertexCount; i++) { if (Math.Abs(m2.Distance(m1.vertex[i])) > precision) { ok = false; } } if (!ok) { return(null); } List <GeoPoint2D> pnts = new List <GeoPoint2D>((spl1[0] as Polyline2D).Vertex); for (int i = 1; i < m2.VertexCount; i++) { pnts.Add(m2.vertex[i]); } m2 = spl2[1] as Polyline2D; for (int i = 1; i < m2.VertexCount; i++) { pnts.Add(m2.vertex[i]); } return(new Polyline2D(pnts.ToArray())); } } } return(null); }
/// <summary> /// Overrides <see cref="CADability.Curve2D.GeneralCurve2D.Split (double)"/> /// </summary> /// <param name="Position"></param> /// <returns></returns> public override ICurve2D[] Split(double Position) { int ind = -1; double tot = Length * Position; GeoPoint2D SplitHere = GeoPoint2D.Origin; for (int i = 1; i < vertex.Length; ++i) { double d = tot; tot -= Geometry.Dist(vertex[i - 1], vertex[i]); if (tot < 0.0) { ind = i; GeoVector2D dir = vertex[i] - vertex[i - 1]; dir.Length = d; // der letzte positive Rest SplitHere = vertex[i - 1] + dir; break; } } if (ind < 0) { // Schnitt am Endpunkt return(new ICurve2D[] { Clone() }); } Polyline2D[] res = new Polyline2D[2]; GeoPoint2D[] v1 = new GeoPoint2D[ind + 1]; GeoPoint2D[] v2 = new GeoPoint2D[vertex.Length - ind + 1]; for (int i = 0; i < ind; ++i) { v1[i] = vertex[i]; } v1[ind] = SplitHere; v2[0] = SplitHere; for (int i = ind; i < vertex.Length; ++i) { v2[i - ind + 1] = vertex[i]; } Polyline2D pl1 = null, pl2 = null; try { pl1 = Polyline2D.MakePolyline2D(v1); } catch (Polyline2DException) { pl1 = null; } try { pl2 = Polyline2D.MakePolyline2D(v2); } catch (Polyline2DException) { pl2 = null; } if (pl1 == null && pl2 == null) { return(null); // sollte nicht vorkommen } if (pl1 == null) { return new ICurve2D[] { pl2 } } ; if (pl2 == null) { return new ICurve2D[] { pl1 } } ; return(new ICurve2D[] { pl1, pl2 }); }
internal bool Reduce(double precision) { // zuerst die Möglichkeit checken, dass die ganze Kurve in sich zurückgeht: int splitat = -1; double maxBend = 0; for (int i = 2; i < vertex.Length; i++) { SweepAngle sw = new SweepAngle(vertex[i - 1] - vertex[i - 2], vertex[i] - vertex[i - 1]); if (Math.Abs(sw.Radian) > Math.PI - 0.1) { if (Math.Abs(sw.Radian) > maxBend) { maxBend = Math.Abs(sw.Radian); splitat = i - 1; } } } if (splitat >= 0) { GeoPoint2D[] v1 = new GeoPoint2D[splitat + 1]; GeoPoint2D[] v2 = new GeoPoint2D[vertex.Length - splitat]; Array.Copy(vertex, v1, splitat + 1); Array.Copy(vertex, splitat, v2, 0, vertex.Length - splitat); Polyline2D pl1 = Polyline2D.MakePolyline2D(v1); Polyline2D pl2 = Polyline2D.MakePolyline2D(v2); if (pl1 != null && pl2 != null) { ICurve2D fused = pl1.GetFused(pl2, precision); if (fused != null && (fused as Polyline2D).VertexCount < vertex.Length) { this.SetVertices((fused as Polyline2D).Vertex); return(Reduce(precision)); // sollte nicht rekursiv werden, es sei denn, es gibt mehrere Spitzkehren, dann ist es ja gut } } } List <GeoPoint2D> vlist = new List <GeoPoint2D>(); vlist.Add(vertex[0]); int lastInserted = 0; bool reverts = false; for (int i = 2; i < vertex.Length; i++) { bool inserted = true; while (inserted) { inserted = false; for (int j = lastInserted + 1; j < i; j++) { double lp = Geometry.LinePar(vertex[lastInserted], vertex[i], vertex[j]); // Problem: die Polyline geht in sich selbst zurück if (Math.Abs(Geometry.DistPL(vertex[j], vertex[lastInserted], vertex[i])) > precision || lp < 0 || lp > 1) { if (lp < 0 || lp > 1) { reverts = true; } lastInserted = j; vlist.Add(vertex[j]); inserted = true; break; } } } } vlist.Add(vertex[vertex.Length - 1]); if (reverts && vlist.Count >= 3) { // versuche wenigstens am Anfang oder Ende die Situation, dass die Polyline in sich zurückgeht zu bereinigen double lp = Geometry.LinePar(vlist[vlist.Count - 3], vlist[vlist.Count - 2], vlist[vlist.Count - 1]); // der letzte Punkt im vorletzten Segment if (lp >= 0 && lp <= 1 && Math.Abs(Geometry.DistPL(vlist[vlist.Count - 1], vlist[vlist.Count - 2], vlist[vlist.Count - 3])) < precision) { vlist.RemoveAt(vlist.Count - 1); } if (vlist.Count >= 3) { lp = Geometry.LinePar(vlist[2], vlist[1], vlist[0]); // der letzte Punkt im vorletzten Segment if (lp >= 0 && lp <= 1 && Math.Abs(Geometry.DistPL(vlist[0], vlist[1], vlist[2])) < precision) { vlist.RemoveAt(0); } } } if (vlist.Count < vertex.Length) { SetVertices(vlist.ToArray()); return(true); } return(false); }
internal bool ConnectWith(Polyline2D polyline2D, double Precision) { double minDist = double.MaxValue; int mode = -1; double dist = polyline2D.StartPoint | this.EndPoint; if (dist < minDist) { minDist = dist; mode = 0; } dist = polyline2D.EndPoint | this.EndPoint; if (dist < minDist) { minDist = dist; mode = 1; } dist = polyline2D.StartPoint | this.StartPoint; if (dist < minDist) { minDist = dist; mode = 2; } dist = polyline2D.EndPoint | this.StartPoint; if (dist < minDist) { minDist = dist; mode = 3; } if (minDist < Precision) { GeoPoint2D[] newvert; switch (mode) { case 0: newvert = new GeoPoint2D[vertex.Length + polyline2D.VertexCount - 1]; Array.Copy(vertex, newvert, vertex.Length); Array.Copy(polyline2D.vertex, 1, newvert, vertex.Length, polyline2D.VertexCount - 1); vertex = newvert; this.length = -1; return(true); case 1: newvert = new GeoPoint2D[vertex.Length + polyline2D.VertexCount - 1]; Array.Copy(vertex, newvert, vertex.Length); GeoPoint2D[] old = polyline2D.Vertex; // das ist eine Kopie Array.Reverse(old); Array.Copy(old, 1, newvert, vertex.Length, polyline2D.VertexCount - 1); vertex = newvert; this.length = -1; return(true); case 2: this.Reverse(); return(ConnectWith(polyline2D, Precision)); case 3: this.Reverse(); return(ConnectWith(polyline2D, Precision)); } } //if ((polyline2D.StartPoint | vertex[vertex.Length - 1]) < Precision) //{ // GeoPoint2D[] newvert = new GeoPoint2D[vertex.Length + polyline2D.VertexCount - 1]; // Array.Copy(vertex, newvert, vertex.Length); // Array.Copy(polyline2D.vertex, 1, newvert, vertex.Length, polyline2D.VertexCount - 1); // vertex = newvert; // this.length = -1; // return true; //} //if ((polyline2D.EndPoint | vertex[vertex.Length - 1]) < Precision) //{ // GeoPoint2D[] newvert = new GeoPoint2D[vertex.Length + polyline2D.VertexCount - 1]; // Array.Copy(vertex, newvert, vertex.Length); // GeoPoint2D[] old = polyline2D.Vertex; // das ist eine Kopie // Array.Reverse(old); // Array.Copy(old, 1, newvert, vertex.Length, polyline2D.VertexCount - 1); // vertex = newvert; // this.length = -1; // return true; //} //// wenn die zuzufügende vornedran käme, dann halt umdrehen //if ((polyline2D.StartPoint | vertex[0]) < Precision) //{ // this.Reverse(); // return ConnectWith(polyline2D, Precision); //} //if ((polyline2D.EndPoint | vertex[0]) < Precision) //{ // this.Reverse(); // return ConnectWith(polyline2D, Precision); //} return(false); }