public override ICurve2D GetProjectedCurve(ICurve curve, double precision) { #if DEBUG if (id == 135 || id == 414) { } #endif if (curve is Line line) { // this must be a line parallel to the axis, otherwise there are no lines on the cylinder // if it is an extremely small line not parallel to the axis, 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) { // the ellipse must be above the projection center of the 2d system // otherwise it is probably a hyperbola GeoPoint p1 = Geometry.DropPL(elli.Center + elli.MajorAxis, location, zAxis); GeoPoint p2 = Geometry.DropPL(elli.Center - elli.MajorAxis, location, zAxis); double pos1 = Geometry.LinePar(location - zAxis, zAxis, p1); double pos2 = Geometry.LinePar(location - zAxis, zAxis, p2); if (pos1 < 0 || pos2 < 0) { return(base.GetProjectedCurve(curve, precision)); } double d = Geometry.DistPL(elli.Center, location, zAxis); double prec = (elli.MajorRadius + elli.MinorRadius) * 1e-6; // FromFivePoints for this case GeoPoint2D[] fp2d = new GeoPoint2D[5]; double n = 5.0; if (elli.IsArc) { n = 4; } 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) { if (elli.IsArc) { double spar = elli2d.PositionOf(PositionOf(elli.StartPoint)); double epar = elli2d.PositionOf(PositionOf(elli.EndPoint)); EllipseArc2D elliarc2d = elli2d.Trim(spar, epar) as EllipseArc2D; // there must be a more sophisticated way to calculate the orientation and which part to use, but the following works: double pm = elliarc2d.PositionOf(PositionOf(elli.PointAt(0.5))); if (pm < 0 || pm > 1) { elliarc2d = elliarc2d.GetComplement(); } pm = elliarc2d.PositionOf(PositionOf(elli.PointAt(0.1))); if (pm > 0.5) { elliarc2d.Reverse(); } return(elliarc2d); } else { // get the correct orientation double pos = elli2d.PositionOf(PositionOf(elli.PointAt(0.1))); if (pos > 0.5) { elli2d.Reverse(); } return(elli2d); } } } return(base.GetProjectedCurve(curve, precision)); }
public override ICurve2D GetProjectedCurve(ICurve curve, double precision) { ICurve2D dbg = base.GetProjectedCurve(curve, precision); if (curve is Ellipse elli) { // a circle on the surface is projected to an ellipse in the uv plane GeoPoint2D[] positions = new GeoPoint2D[5]; for (int i = 0; i < 5; i++) { positions[i] = PositionOf(elli.PointAtParam(i * Math.PI * 2.0 / 6.0)); } Ellipse2D elli2d = Ellipse2D.FromFivePoints(positions, true); double prec = precision; if (prec == 0) { prec = Precision.eps; } if (elli2d == null) { BoundingRect ext = new BoundingRect(positions); GaussNewtonMinimizer.Ellipse2DFit(new ToIArray <GeoPoint2D>(positions), ext.GetCenter(), ext.Size / 2.0, ext.Size / 3.0, 0.0, prec, out elli2d); } else { GaussNewtonMinimizer.Ellipse2DFit(new ToIArray <GeoPoint2D>(positions), elli2d.center, elli2d.majrad, elli2d.minrad, elli2d.majorAxis.Angle, prec, out elli2d); } //GeoPoint2D center = PositionOf(elli.Center); //GeoPoint2D maj = PositionOf(elli.Center + elli.MajorAxis); //GeoPoint2D min = PositionOf(elli.Center + elli.MinorAxis); //Geometry.PrincipalAxis(maj - center, min - center, out GeoVector2D majorAxis, out GeoVector2D minorAxis); //Ellipse2D elli2d = new Ellipse2D(center, maj - center, min - center); if (elli2d == null) { return(base.GetProjectedCurve(curve, precision)); } if (elli.IsArc) { double sp = elli2d.PositionOf(PositionOf(elli.StartPoint)); double ep = elli2d.PositionOf(PositionOf(elli.EndPoint)); EllipseArc2D elliarc2d = elli2d.Trim(sp, ep) as EllipseArc2D; // there must be a more sophisticated way to calculate the orientation and which part to use, but the following works: double pm = elliarc2d.PositionOf(PositionOf(elli.PointAt(0.5))); if (pm < 0 || pm > 1) { elliarc2d = elliarc2d.GetComplement(); } pm = elliarc2d.PositionOf(PositionOf(elli.PointAt(0.1))); if (pm > 0.5) { elliarc2d.Reverse(); } return(elliarc2d); } else { // get the correct orientation double pos = elli2d.PositionOf(PositionOf(elli.PointAt(0.1))); if (pos > 0.5) { elli2d.Reverse(); } return(elli2d); } } return(base.GetProjectedCurve(curve, precision)); }