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));
        }
Beispiel #2
0
        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));
        }