public static EllipseArc2D Create(GeoPoint2D center, GeoVector2D majorAxis, GeoVector2D minorAxis, GeoPoint2D startPoint, GeoPoint2D endPoint, bool counterClock) { // bestimme die beiden Winkel GeoVector2D majAx; GeoVector2D minAx; GeoPoint2D left, right, bottom, top; Geometry.PrincipalAxis(center, majorAxis, minorAxis, out majAx, out minAx, out left, out right, out bottom, out top, false); ModOp2D toUnit = ModOp2D.Fit(new GeoPoint2D[] { center, center + majAx, center + minAx }, new GeoPoint2D[] { GeoPoint2D.Origin, GeoPoint2D.Origin + GeoVector2D.XAxis, GeoPoint2D.Origin + GeoVector2D.YAxis }, true); GeoPoint2D p = toUnit * startPoint; double sa = p.ToVector().Angle.Radian; p = toUnit * endPoint; double ea = p.ToVector().Angle.Radian; double sw; if (counterClock) { sw = ea - sa; if (sw <= 0.0) { sw += Math.PI * 2.0; // geändert auf <= bzw. >=, da sonst aus Vollkreisen Leerkreise werden } } else { sw = ea - sa; if (sw >= 0.0) { sw -= Math.PI * 2.0; } } return(new EllipseArc2D(center, majAx, minAx, sa, sw, left, right, bottom, top)); }
public override ICurve2D GetProjectedCurve(ICurve curve, double precision) { if (curve is Line line) { // this must be a line through the apex, otherwise there are no lines on the cone // if it is an extremely small line not through the apex, the result will also be a line, which // in reverse projection will give a very short ellipse return(new Line2D(PositionOf(line.StartPoint), PositionOf(line.EndPoint))); } else if (curve is Ellipse elli) { if (elli.IsCircle) { GeoPoint2D sp2d = PositionOf(elli.StartPoint); if (elli.IsArc) { } else { Arc2D a2d = new Arc2D(GeoPoint2D.Origin, sp2d.ToVector().Length, sp2d, sp2d, true); GeoVector sdir = a2d.StartDirection.x * UDirection(sp2d) + a2d.StartDirection.y * VDirection(sp2d); if (sdir * elli.StartDirection < 0) { a2d.counterClock = false; } return(a2d); } } else { // this is a intersection with a plane. GeoPoint2D[] fp2d = new GeoPoint2D[5]; double n = 5.0; if (elli.IsArc) { n = 4.0; } for (int i = 0; i < 5; i++) { fp2d[i] = PositionOf(elli.PointAt(i / n)); } Ellipse2D elli2d = Ellipse2D.FromFivePoints(fp2d, !elli.IsArc); // returns both full ellipse and ellipse arc if (elli2d != null) { return(elli2d); } } } return(base.GetProjectedCurve(curve, precision)); }
public override ICurve2D[] GetTangentCurves(GeoVector direction, double umin, double umax, double vmin, double vmax) { if (Precision.SameDirection(direction, zAxis, false)) { return(new ICurve2D[] { }); } GeoPoint2D uv = PositionOf(location + (direction ^ zAxis)); GeoVector2D dir2d = uv.ToVector(); dir2d.Length = xAxis.Length * 1.1; Line2D l2d = new Line2D(GeoPoint2D.Origin - dir2d, GeoPoint2D.Origin + dir2d); double[] parts = Clip(l2d); List <ICurve2D> res = new List <ICurve2D>(2); for (int i = 0; i < parts.Length; i += 2) { res.Add(l2d.Trim(parts[i], parts[i + 1])); } return(res.ToArray()); }
public override ICurve2D[] GetTangentCurves(GeoVector direction, double umin, double umax, double vmin, double vmax) { if (Precision.SameDirection(direction, zAxis, false)) { return(new ICurve2D[0]); } GeoPoint2D uv = PositionOf(location + zAxis + (direction ^ zAxis)); GeoVector2D dir2d = uv.ToVector(); dir2d.Length = Math.Max(Math.Max(Math.Abs(umax), Math.Abs(umin)), Math.Max(Math.Abs(vmax), Math.Abs(vmin))) * 1.1; ClipRect clr = new ClipRect(umin, umax, vmin, vmax); GeoPoint2D sp = GeoPoint2D.Origin - dir2d; GeoPoint2D ep = GeoPoint2D.Origin + dir2d; if (clr.ClipLine(ref sp, ref ep)) { return new ICurve2D[] { new Line2D(sp, ep) } } ; else { return(new ICurve2D[0]); } }
/// <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)); }