/// <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)); }
/// <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) { return(Other.MinDistance(this)); // bei der Linie ist es definiert } else if (Other is Circle2D) { double minDist = Curves2D.SimpleMinimumDistance(this, Other); // dort werden die Schnitt- Start- Endpunkte miteinander verrechnet // jetzt nur noch gucken, ob sich die beiden Kreise oder Bögen annähern Circle2D c = Other as Circle2D; double cdist = Geometry.Dist(c.center, center); if (cdist < Precision.eps) { return(minDist); // mit gleichen Mittelpunkten funktioniert } // das folgende nicht, aber der Abstand ist schon von SimpleMinimumDistance bestimmt // da dort auch die Fußpunkte verwendung finden if (cdist > c.radius + radius) { // Annäherung zweier nicht schneidenden Kreise GeoVector2D dir = c.center - center; // von hier zum anderen dir.Norm(); GeoPoint2D p1 = center + radius * dir; GeoPoint2D p2 = c.center + c.radius * dir.Opposite(); double pos1 = this.PositionOf(p1); double pos2 = c.PositionOf(p2); if (pos1 >= 0.0 && pos1 <= 1.0 && pos2 >= 0.0 && pos2 <= 1.0) { minDist = Math.Min(minDist, cdist - c.radius - radius); } } else if (radius - c.radius > cdist) { // Kreis c liegt innerhalb von diesem Kreis GeoVector2D dir = c.center - center; // von hier zum anderen dir.Norm(); GeoPoint2D p1 = center + radius * dir; GeoPoint2D p2 = c.center + c.radius * dir; double pos1 = this.PositionOf(p1); double pos2 = c.PositionOf(p2); if (pos1 >= 0.0 && pos1 <= 1.0 && pos2 >= 0.0 && pos2 <= 1.0) { minDist = Math.Min(minDist, Geometry.Dist(p1, p2)); } } else if (c.radius - radius > cdist) { // dieser Kreis liegt innerhalb von c GeoVector2D dir = center - c.center; dir.Norm(); GeoPoint2D p1 = c.center + c.radius * dir; GeoPoint2D p2 = center + radius * dir; double pos1 = c.PositionOf(p1); double pos2 = PositionOf(p2); if (pos1 >= 0.0 && pos1 <= 1.0 && pos2 >= 0.0 && pos2 <= 1.0) { minDist = Math.Min(minDist, Geometry.Dist(p1, p2)); } } return(minDist); } else { return(base.MinDistance(Other)); } }
/// <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)); } }