public override IDualSurfaceCurve[] GetPlaneIntersection(PlaneSurface pl, double umin, double umax, double vmin, double vmax, double precision)
        {
            if (Precision.IsPerpendicular(pl.Normal, zAxis, false))
            {
                // two lines along the cylinder axis
                Plane               lower = new Plane(location, zAxis);
                GeoPoint2D          sp2d  = lower.Project(pl.Location);
                GeoVector2D         dir2d = lower.Project(pl.Normal).ToLeft();
                GeoPoint2D[]        ips   = Geometry.IntersectLC(sp2d, dir2d, GeoPoint2D.Origin, xAxis.Length);
                IDualSurfaceCurve[] res   = new IDualSurfaceCurve[ips.Length];
                for (int i = 0; i < ips.Length; i++)
                {
                    GeoPoint p   = lower.ToGlobal(ips[i]);
                    Line     l3d = Line.TwoPoints(p, p + zAxis);
                    res[i] = new DualSurfaceCurve(l3d, this, new Line2D(this.PositionOf(l3d.StartPoint), this.PositionOf(l3d.EndPoint)), pl, new Line2D(pl.PositionOf(l3d.StartPoint), pl.PositionOf(l3d.EndPoint)));
                }
                return(res);
            }
            else
            {
                // an ellipse
                GeoPoint2D[] cnts = pl.GetLineIntersection(location, zAxis);
                if (cnts.Length == 1)
                {   // there must be exactly one intersection
                    GeoPoint  cnt       = pl.PointAt(cnts[0]);
                    GeoVector minorAxis = pl.Normal ^ zAxis;
                    minorAxis.Length = xAxis.Length;
                    GeoVector majorAxis = minorAxis ^ pl.Normal;
                    Polynom   impl      = GetImplicitPolynomial();
                    Polynom   toSolve   = impl.Substitute(new Polynom(majorAxis.x, "u", cnt.x, ""), new Polynom(majorAxis.y, "u", cnt.y, ""), new Polynom(majorAxis.z, "u", cnt.z, ""));
                    double[]  roots     = toSolve.Roots();
                    // there must be two roots
                    majorAxis = roots[0] * majorAxis;

                    Ellipse elli = Ellipse.Construct();
                    elli.SetEllipseCenterAxis(cnt, majorAxis, minorAxis);

                    GeoPoint2D[] fpnts = new GeoPoint2D[5];
                    for (int i = 0; i < 5; i++)
                    {
                        fpnts[i] = PositionOf(elli.PointAt(i / 6.0));
                    }
                    Ellipse2D e2d = Ellipse2D.FromFivePoints(fpnts); // there should be a better way to calculate the 2d ellipse, but the following is wrong:
                    // Ellipse2D e2d = new Ellipse2D(GeoPoint2D.Origin, PositionOf(cnt + majorAxis).ToVector(), PositionOf(cnt + minorAxis).ToVector());
                    // and principal axis doesn't yield the correct result either
                    // Geometry.PrincipalAxis(PositionOf(cnt + majorAxis).ToVector(), PositionOf(cnt + minorAxis).ToVector(), out GeoVector2D maj, out GeoVector2D min);
                    return(new IDualSurfaceCurve[] { new DualSurfaceCurve(elli, this, e2d, pl, pl.GetProjectedCurve(elli, 0.0)) });
                }
            }
            return(new IDualSurfaceCurve[0]);
        }
 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 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));
        }
Exemple #4
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));
        }