Пример #1
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));
        }
Пример #2
0
        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));
        }
Пример #3
0
 void IPaintTo3D.Arc(GeoPoint center, GeoVector majorAxis, GeoVector minorAxis, double startParameter, double sweepParameter)
 {
     try
     {
         GeoVector normal = majorAxis ^ minorAxis; // normale der Ebene des Bogens
         // wird der Bogen von vorne oder hinten betrachtet?
         // statt projection.Direction besser die Richtung zum Mittelpunkt (bei perspektivischer Projektion)
         double sc = projection.Direction.Normalized * normal.Normalized;
         if (Math.Abs(sc) < 1e-6)
         {                                                  // eine Linie
             GeoVector dir = normal ^ projection.Direction; // Richtung der Linie
             double    pmin, pmax;
             double    par = Geometry.LinePar(center, dir, center + Math.Cos(startParameter) * majorAxis + Math.Sin(startParameter) * minorAxis);
             pmin = pmax = par;
             par  = Geometry.LinePar(center, dir, center + Math.Cos(startParameter + sweepParameter) * majorAxis + Math.Sin(startParameter + sweepParameter) * minorAxis);
             if (par < pmin)
             {
                 pmin = par;
             }
             if (par > pmax)
             {
                 pmax = par;
             }
             // fehlt noch: jetzt noch die Achsenpunkt abprüfen...
             (this as IPaintTo3D).Polyline(new GeoPoint[] { center + pmin * dir, center + pmax * dir });
         }
         else
         {
             GeoPoint2D  center2d = projection.Project(center);
             GeoVector2D maj2D    = projection.Project(center + majorAxis) - center2d;
             GeoVector2D min2D    = projection.Project(center + minorAxis) - center2d;
             if (maj2D.IsNullVector() || min2D.IsNullVector())
             {   // eigentlich auch eine Linie
                 return;
             }
             GeoPoint2D sp           = center2d + Math.Cos(startParameter) * maj2D + Math.Sin(startParameter) * min2D;
             GeoPoint2D ep           = center2d + Math.Cos(startParameter + sweepParameter) * maj2D + Math.Sin(startParameter + sweepParameter) * min2D;
             bool       counterclock = sweepParameter > 0.0;
             //if (normal.z > 0.0) counterclock = !counterclock;
             EllipseArc2D ea2d = EllipseArc2D.Create(center2d, maj2D, min2D, sp, ep, counterclock);
             ea2d.MakePositivOriented();
             GeoVector2D prmaj2D, prmin2D;
             // Geometry.PrincipalAxis(maj2D, min2D, out prmaj2D, out prmin2D);
             prmaj2D = ea2d.MajorAxis;
             prmin2D = ea2d.MinorAxis;
             Angle rot = prmaj2D.Angle;
             //ModOp2D toHorizontal = ModOp2D.Rotate(center2d, -rot.Radian);
             ModOp2D    fromHorizontal = ModOp2D.Rotate(center2d, rot.Radian);
             SweepAngle swapar         = new SweepAngle(ea2d.StartPoint - center2d, ea2d.EndPoint - center2d);
             if (counterclock && swapar < 0)
             {
                 swapar += 360;
             }
             if (!counterclock && swapar > 0)
             {
                 swapar -= 360;
             }
             float swPar = (float)(ea2d.axisSweep / Math.PI * 180);
             float stPar = (float)(ea2d.axisStart / Math.PI * 180);
             if (sweepParameter >= Math.PI * 2.0 || sweepParameter <= -Math.PI * 2.0)
             {   // Notlösung wg. ERSACAD und wg. Nürnberger 5.12.13
                 swPar = 360.0f;
             }
             try
             {
                 Matrix r      = fromHorizontal.Matrix2D;
                 double maxRad = prmaj2D.Length;
                 double minRad = prmin2D.Length;
                 if ((maxRad + minRad) * Projection.WorldToDeviceFactor < 1)
                 {     // sonst gibt es ein out of memory exception
                     if (graphicsPath != null)
                     { // kann auch schräge Ellipsen zufügen mit Transformation
                         GraphicsPath tmpPath = new GraphicsPath();
                         tmpPath.AddLine((float)center2d.x, (float)center2d.y, (float)center2d.x, (float)center2d.y);
                         tmpPath.Transform(r);
                         graphicsPath.AddPath(tmpPath, true);
                     }
                     else
                     {
                         Pen drawPen = MakePen();
                         using (drawPen)
                         {
                             using (new Transform(graphics, r, false))
                             {   // wenigstens einen Pixel darstellen
                                 graphics.DrawLine(drawPen, (float)(center2d.x - 0.5), (float)center2d.y, (float)(center2d.x + 0.5), (float)center2d.y);
                             }
                         }
                     }
                 }
                 else
                 {
                     if (graphicsPath != null)
                     {   // kann auch schräge Ellipsen zufügen mit Transformation
                         GraphicsPath tmpPath = new GraphicsPath();
                         tmpPath.AddArc((float)(center2d.x - maxRad), (float)(center2d.y - minRad), (float)(2.0 * maxRad), (float)(2.0 * minRad), stPar, swPar);
                         tmpPath.Transform(r);
                         graphicsPath.AddPath(tmpPath, true);
                     }
                     else
                     {
                         Pen drawPen = MakePen();
                         using (drawPen)
                         {
                             using (new Transform(graphics, r, false))
                             {
                                 graphics.DrawArc(drawPen, (float)(center2d.x - maxRad), (float)(center2d.y - minRad), (float)(2.0 * maxRad), (float)(2.0 * minRad), stPar, swPar);
                             }
                         }
                     }
                 }
             }
             catch (ArgumentException)
             {
             }
             catch (ModOpException)
             {
             }
             catch (OutOfMemoryException)
             {
             }
         }
     }
     catch
     {   // damit es sicher durchläuft. z.B. eine Ellipse, bei der beide Achsen dieselbe Richtung haben, erzeugt eine ModOp Exception
     }
 }