Beispiel #1
0
 public Arc2D(GeoPoint2D center, double radius, GeoPoint2D StartPoint, GeoPoint2D EndPoint, bool counterclock)
     : base(center, radius)
 {
     start = new Angle(StartPoint, center);
     sweep = new SweepAngle(StartPoint - center, EndPoint - center);
     // sweep ist zwischen -pi und +pi, also der Bogen ist maximal ein Halbkreis.
     // counterclock gibt aber die Richtung vor, deshalb ggf. umdrehen
     if ((StartPoint | EndPoint) < radius * 1e-10)
     {
         if (counterclock)
         {
             sweep = SweepAngle.Full;
         }
         else
         {
             sweep = SweepAngle.FullReverse;
         }
     }
     if (counterclock && sweep <= 0.0)
     {
         sweep += 2.0 * Math.PI;
     }
     if (!counterclock && sweep >= 0.0)
     {
         sweep -= 2.0 * Math.PI;
     }
 }
Beispiel #2
0
 /// <summary>
 /// Constructor required by deserialization
 /// </summary>
 /// <param name="info">SerializationInfo</param>
 /// <param name="context">StreamingContext</param>
 protected HatchStyleLines(SerializationInfo info, StreamingContext context)
     : base(info, context)
 {
     lineDistance = (double)info.GetValue("LineDistance", typeof(double));
     lineAngle    = (Angle)info.GetValue("LineAngle", typeof(Angle));
     colorDef     = ColorDef.Read("ColorDef", info, context);
     lineWidth    = LineWidth.Read("LineWidth", info, context);
     linePattern  = LinePattern.Read("LinePattern", info, context);
     try
     {
         marginOffset = (double)info.GetValue("MarginOffset", typeof(double));
     }
     catch (SerializationException)
     {
         marginOffset = 0.0;
     }
     try
     {
         number    = (int)info.GetValue("NumberOffset", typeof(int));
         offset    = (double)info.GetValue("Offset", typeof(double)); // warum ist das double?
         alternate = (bool)info.GetValue("Alternate", typeof(bool));
     }
     catch (SerializationException)
     {
         number    = 1;
         offset    = SweepAngle.ToLeft;
         alternate = false;
     }
 }
Beispiel #3
0
 private void RotateWithPlanes()
 {
     // get rotation axis from the two planes
     if (src.Intersect(trg, out GeoPoint loc, out GeoVector dir))
     {
         // set to original position
         for (int i = 0; i < block.Count; ++i)
         {
             block.Child(i).CopyGeometry(originals[i]);
         }
         Plane       perp = new Plane(loc, dir); // plane perpendicular to rotation axis
         GeoVector2D from = perp.Project(dir ^ src.Normal);
         GeoVector2D to   = perp.Project(dir ^ trg.Normal);
         SweepAngle  sw   = new SweepAngle(from, to);
         rotationAngle = sw;
         rotAngleInput.ForceValue(rotationAngle);
         ModOp     m0 = ModOp.Rotate(loc, dir, sw);
         ModOp     m1 = ModOp.Rotate(loc, -dir, sw);
         GeoVector n0 = m0 * src.Normal;
         GeoVector n1 = m1 * src.Normal;
         ModOp     m; // not sure, which rotation is better
         if (Math.Abs(n0 * trg.Normal) > Math.Abs(n1 * trg.Normal))
         {
             m          = ModOp.Rotate(loc, dir, sw + GetOffset());
             axisVector = dir;
         }
         else
         {
             m          = ModOp.Rotate(loc, -dir, sw + GetOffset());
             axisVector = -dir;
         }
         block.Modify(m);
         base.BasePoint = loc;
     }
 }
Beispiel #4
0
        /// <summary>
        /// Overrides <see cref="CADability.Curve2D.GeneralCurve2D.Copy (ICurve2D)"/>
        /// </summary>
        /// <param name="toCopyFrom"></param>
        public override void Copy(ICurve2D toCopyFrom)
        {
            Arc2D c = toCopyFrom as Arc2D;

            start = c.start;
            sweep = c.sweep;
            base.Copy(toCopyFrom);
        }
Beispiel #5
0
 internal void Close()
 {
     if (sweep > 0)
     {
         sweep = Math.PI * 2.0;
     }
     else
     {
         sweep = -Math.PI * 2.0;
     }
 }
Beispiel #6
0
 private EntityObject ExportEllipse(GeoObject.Ellipse elli)
 {
     netDxf.Entities.EntityObject entity = null;
     if (elli.IsArc)
     {
         Plane dxfPlane;
         if (elli.CounterClockWise)
         {
             dxfPlane = Import.Plane(Vector3(elli.Center), Vector3(elli.Plane.Normal));
         }
         else
         {
             dxfPlane = Import.Plane(Vector3(elli.Center), Vector3(-elli.Plane.Normal));
         }
         if (elli.IsCircle)
         {
             GeoObject.Ellipse aligned = GeoObject.Ellipse.Construct();
             aligned.SetArcPlaneCenterStartEndPoint(dxfPlane, dxfPlane.Project(elli.Center), dxfPlane.Project(elli.StartPoint), dxfPlane.Project(elli.EndPoint), dxfPlane, true);
             entity        = new netDxf.Entities.Arc(Vector3(aligned.Center), aligned.Radius, aligned.StartParameter / Math.PI * 180, (aligned.StartParameter + aligned.SweepParameter) / Math.PI * 180);
             entity.Normal = Vector3(dxfPlane.Normal);
         }
         else
         {
             netDxf.Entities.Ellipse expelli = new netDxf.Entities.Ellipse(Vector3(elli.Center), 2 * elli.MajorRadius, 2 * elli.MinorRadius);
             entity        = expelli;
             entity.Normal = Vector3(elli.Plane.Normal);
             Plane       cdbplane = elli.Plane;
             GeoVector2D dir      = dxfPlane.Project(cdbplane.DirectionX);
             SweepAngle  rot      = new SweepAngle(GeoVector2D.XAxis, dir);
             expelli.Rotation = rot.Degree;
             SetEllipseParameters(expelli, elli.StartParameter, elli.StartParameter + elli.SweepParameter);
         }
     }
     else
     {
         if (elli.IsCircle)
         {
             entity        = new netDxf.Entities.Circle(Vector3(elli.Center), elli.Radius);
             entity.Normal = Vector3(elli.Plane.Normal);
         }
         else
         {
             netDxf.Entities.Ellipse expelli = new netDxf.Entities.Ellipse(Vector3(elli.Center), 2 * elli.MajorRadius, 2 * elli.MinorRadius);
             entity        = expelli;
             entity.Normal = Vector3(elli.Plane.Normal);
             Plane       dxfplane = Import.Plane(expelli.Center, expelli.Normal); // this plane is not correct, it has to be rotated
             Plane       cdbplane = elli.Plane;
             GeoVector2D dir      = dxfplane.Project(cdbplane.DirectionX);
             SweepAngle  rot      = new SweepAngle(GeoVector2D.XAxis, dir);
             expelli.Rotation = rot.Degree;
         }
     }
     return(entity);
 }
Beispiel #7
0
 internal void Close()
 {   // maybe this is wrong, see MakeFullEllipse
     if (sweep > 0)
     {
         sweep = Math.PI * 2.0;
     }
     else
     {
         sweep = -Math.PI * 2.0;
     }
     RecalcQuadrant();
 }
Beispiel #8
0
        /// <summary>
        /// Overrides <see cref="CADability.Curve2D.GeneralCurve2D.Trim (double, double)"/>
        /// </summary>
        /// <param name="StartPos"></param>
        /// <param name="EndPos"></param>
        /// <returns></returns>
        public override ICurve2D Trim(double StartPos, double EndPos)
        {
            Angle      st = startPar + StartPos * sweepPar;
            Angle      en = startPar + EndPos * sweepPar;
            SweepAngle sw = new SweepAngle(st, en, sweepPar > 0.0);

            if (StartPos == 0.0 && EndPos == 1.0)
            {
                sw = sweepPar;
            }
            return(new EllipseArc2D(center, majorAxis, minorAxis, st, sw, left, right, bottom, top));
        }
Beispiel #9
0
 internal override void Init(Project pr)
 {
     lineDistance = 1.0;
     lineAngle    = Angle.A45;
     marginOffset = 0.0;
     number       = 1;
     offset       = SweepAngle.ToLeft;
     alternate    = false;
     lineWidth    = pr.LineWidthList.Current;
     linePattern  = pr.LinePatternList.Current;
     colorDef     = pr.ColorList.Current;
 }
Beispiel #10
0
 private void OnSetEndPoint(GeoPoint p)
 {
     endPoint = p;
     if (startPointInput.Fixed)
     {
         rotAngleInput.Fixed = true; // damit die Aktion nach dem Endpunkt aufhört
         SweepAngle swAngle = new SweepAngle((GeoVector2D)(base.ActiveDrawingPlane.Project(startPoint) - base.ActiveDrawingPlane.Project(refPoint)), base.ActiveDrawingPlane.Project(endPoint) - base.ActiveDrawingPlane.Project(refPoint));
         ModOp      m       = ModOp.Rotate(base.BasePoint, axisVector, new SweepAngle(swAngle - rotationAngle) + GetOffset());
         rotationAngle = swAngle.Radian;
         block.Modify(m);
         feedBackEllipse.SetArcPlaneCenterStartEndPoint(ActiveDrawingPlane, ActiveDrawingPlane.Project(BasePoint), ActiveDrawingPlane.Project(startPoint), ActiveDrawingPlane.Project(endPoint), ActiveDrawingPlane, swAngle.Radian > 0.0);
     }
 }
        private void OnSetStartAngle(Angle a)
        {
            double     endParameter = ellipse.StartParameter + ellipse.SweepParameter;
            SweepAngle sa           = new SweepAngle(a, new Angle(endParameter), ellipse.SweepParameter > 0.0);

            using (Frame.Project.Undo.UndoFrame)
            {
                ellipse.StartParameter = a.Radian;
                if (ellipse.IsArc)
                {
                    ellipse.SweepParameter = sa.Radian;
                }
            }
        }
Beispiel #12
0
        /// <summary>
        /// Overrides <see cref="CADability.Curve2D.GeneralCurve2D.Copy (ICurve2D)"/>
        /// </summary>
        /// <param name="toCopyFrom"></param>
        public override void Copy(ICurve2D toCopyFrom)
        {
            EllipseArc2D c = toCopyFrom as EllipseArc2D;

            start        = c.start;
            sweep        = c.sweep;
            startPar     = c.startPar;
            sweepPar     = c.sweepPar;
            startPoint   = c.startPoint;
            endPoint     = c.endPoint;
            startQuad    = c.startQuad;
            endQuad      = c.endQuad;
            crossingZero = c.crossingZero;
            base.Copy(toCopyFrom);
        }
Beispiel #13
0
 /// <summary>
 /// Constructor required by deserialization
 /// </summary>
 /// <param name="info">SerializationInfo</param>
 /// <param name="context">StreamingContext</param>
 protected Arc2D(SerializationInfo info, StreamingContext context)
     : base(info, context)
 {
     start = (Angle)info.GetValue("Start", typeof(Angle));
     sweep = (SweepAngle)info.GetValue("Sweep", typeof(SweepAngle));
 }
 public override int GetHashCode()
 {
     unchecked
     {
         return((Location.GetHashCode() * 397) ^ (RadiusX.GetHashCode() * 397) ^ (RadiusY.GetHashCode() * 397) ^ (StartAngle.GetHashCode() * 397) ^ SweepAngle.GetHashCode());
     }
 }
 /// <summary></summary>
 /// <returns></returns>
 public override string ToString()
 {
     return(ToString("Center=" + Center.ToString("0.00") + ", StartAngle=" + StartAngle.ToString("0.0") + ", SweepAngle=" + SweepAngle.ToString("0.0")));
 }
Beispiel #16
0
        internal bool Reduce(double precision)
        {
            // zuerst die Möglichkeit checken, dass die ganze Kurve in sich zurückgeht:
            int    splitat = -1;
            double maxBend = 0;

            for (int i = 2; i < vertex.Length; i++)
            {
                SweepAngle sw = new SweepAngle(vertex[i - 1] - vertex[i - 2], vertex[i] - vertex[i - 1]);
                if (Math.Abs(sw.Radian) > Math.PI - 0.1)
                {
                    if (Math.Abs(sw.Radian) > maxBend)
                    {
                        maxBend = Math.Abs(sw.Radian);
                        splitat = i - 1;
                    }
                }
            }
            if (splitat >= 0)
            {
                GeoPoint2D[] v1 = new GeoPoint2D[splitat + 1];
                GeoPoint2D[] v2 = new GeoPoint2D[vertex.Length - splitat];
                Array.Copy(vertex, v1, splitat + 1);
                Array.Copy(vertex, splitat, v2, 0, vertex.Length - splitat);
                Polyline2D pl1 = Polyline2D.MakePolyline2D(v1);
                Polyline2D pl2 = Polyline2D.MakePolyline2D(v2);
                if (pl1 != null && pl2 != null)
                {
                    ICurve2D fused = pl1.GetFused(pl2, precision);
                    if (fused != null && (fused as Polyline2D).VertexCount < vertex.Length)
                    {
                        this.SetVertices((fused as Polyline2D).Vertex);
                        return(Reduce(precision)); // sollte nicht rekursiv werden, es sei denn, es gibt mehrere Spitzkehren, dann ist es ja gut
                    }
                }
            }

            List <GeoPoint2D> vlist = new List <GeoPoint2D>();

            vlist.Add(vertex[0]);
            int  lastInserted = 0;
            bool reverts      = false;

            for (int i = 2; i < vertex.Length; i++)
            {
                bool inserted = true;
                while (inserted)
                {
                    inserted = false;
                    for (int j = lastInserted + 1; j < i; j++)
                    {
                        double lp = Geometry.LinePar(vertex[lastInserted], vertex[i], vertex[j]); // Problem: die Polyline geht in sich selbst zurück
                        if (Math.Abs(Geometry.DistPL(vertex[j], vertex[lastInserted], vertex[i])) > precision || lp < 0 || lp > 1)
                        {
                            if (lp < 0 || lp > 1)
                            {
                                reverts = true;
                            }
                            lastInserted = j;
                            vlist.Add(vertex[j]);
                            inserted = true;
                            break;
                        }
                    }
                }
            }
            vlist.Add(vertex[vertex.Length - 1]);
            if (reverts && vlist.Count >= 3)
            {                                                                                                         // versuche wenigstens am Anfang oder Ende die Situation, dass die Polyline in sich zurückgeht zu bereinigen
                double lp = Geometry.LinePar(vlist[vlist.Count - 3], vlist[vlist.Count - 2], vlist[vlist.Count - 1]); // der letzte Punkt im vorletzten Segment
                if (lp >= 0 && lp <= 1 && Math.Abs(Geometry.DistPL(vlist[vlist.Count - 1], vlist[vlist.Count - 2], vlist[vlist.Count - 3])) < precision)
                {
                    vlist.RemoveAt(vlist.Count - 1);
                }
                if (vlist.Count >= 3)
                {
                    lp = Geometry.LinePar(vlist[2], vlist[1], vlist[0]); // der letzte Punkt im vorletzten Segment
                    if (lp >= 0 && lp <= 1 && Math.Abs(Geometry.DistPL(vlist[0], vlist[1], vlist[2])) < precision)
                    {
                        vlist.RemoveAt(0);
                    }
                }
            }
            if (vlist.Count < vertex.Length)
            {
                SetVertices(vlist.ToArray());
                return(true);
            }
            return(false);
        }
Beispiel #17
0
        private bool crossingZero; // geht über die X-Achse

        private void RecalcQuadrant()
        {
            // Berechnung von start und sweep, wird benötigt für die GDI Darstellung
            Angle       MajorAngle  = majorAxis.Angle;
            double      s           = Math.Sin(MajorAngle);
            double      c           = Math.Cos(MajorAngle);
            ModOp2D     toCenter    = new ModOp2D(c, s, (-c * center.x - s * center.y), -s, c, (s * center.x - c * center.y));
            GeoVector2D startVector = toCenter * startPoint - GeoPoint2D.Origin;
            GeoVector2D endVector   = toCenter * endPoint - GeoPoint2D.Origin;

            start = startVector.Angle;
            sweep = new SweepAngle(start, endVector.Angle, sweepPar > 0.0);
            if (sweep == 0.0)
            {
                if (sweepPar > 0.0)
                {
                    sweep = Math.PI * 2.0;
                }
                if (sweepPar < 0.0)
                {
                    sweep = -Math.PI * 2.0;
                }
            }

            // Berechnung der betroffenen Quadranten
            startQuad = endQuad = -1;
            if (startPoint.IsLeftOf(top, right))
            {
                startQuad = 0;
            }
            else if (startPoint.IsLeftOf(left, top))
            {
                startQuad = 1;
            }
            else if (startPoint.IsLeftOf(bottom, left))
            {
                startQuad = 2;
            }
            else if (startPoint.IsLeftOf(right, bottom))
            {
                startQuad = 3;
            }
            if (startQuad == -1)
            {   // der Startpunkt muss auf einer Ecke liegen
                double dmin, d;
                dmin = Geometry.Dist(startPoint, right); startQuad = 0;
                d    = Geometry.Dist(startPoint, top);
                if (d < dmin)
                {
                    startQuad = 1; dmin = d;
                }
                d = Geometry.Dist(startPoint, left);
                if (d < dmin)
                {
                    startQuad = 2; dmin = d;
                }
                if (Geometry.Dist(startPoint, bottom) < dmin)
                {
                    startQuad = 3;
                }
            }

            if (endPoint.IsLeftOf(top, right))
            {
                endQuad = 0;
            }
            else if (endPoint.IsLeftOf(left, top))
            {
                endQuad = 1;
            }
            else if (endPoint.IsLeftOf(bottom, left))
            {
                endQuad = 2;
            }
            else if (endPoint.IsLeftOf(right, bottom))
            {
                endQuad = 3;
            }
            if (endQuad == -1)
            {
                double dmin, d;
                dmin = Geometry.Dist(endPoint, right); endQuad = 0;
                d    = Geometry.Dist(endPoint, top);
                if (d < dmin)
                {
                    endQuad = 1; dmin = d;
                }
                d = Geometry.Dist(endPoint, left);
                if (d < dmin)
                {
                    endQuad = 2; dmin = d;
                }
                if (Geometry.Dist(endPoint, bottom) < dmin)
                {
                    endQuad = 3;
                }
            }
            if ((sweepPar > 0.0) == (GeoVector2D.Orientation(majorAxis, minorAxis) > 0))
            {
                //				crossingZero = right.IsLeftOf(endPoint,startPoint);
                //				if (Precision.IsEqual(right,endPoint) && endQuad==0) crossingZero = true;
                //				if (Precision.IsEqual(right,startPoint) && startQuad==3) crossingZero = true;
                crossingZero = (endQuad < startQuad);
                if (endQuad == startQuad)
                {
                    crossingZero = sweepPar > Math.PI;
                }
            }
            else
            {
                //				crossingZero = right.IsLeftOf(startPoint,endPoint);
                crossingZero = (startQuad < endQuad);
                if (endQuad == startQuad)
                {
                    crossingZero = sweepPar < -Math.PI;
                }
            }
        }
Beispiel #18
0
        public override void OnMouseMove(MouseEventArgs e, IView vw)
        {
            if (e.Button != MouseButtons.Left)
            {
                return;
            }
            if (modelView == null)
            {
                return;
            }
            int HOffset = e.X - lastPanPosition.X;
            int VOffset = e.Y - lastPanPosition.Y;

            if (VOffset != 0 || HOffset != 0)
            {
                Projection Projection = vw.Projection;
                lastPanPosition = new Point(e.X, e.Y);
                GeoVector haxis = Projection.InverseProjection * GeoVector.XAxis;
                GeoVector vaxis = Projection.InverseProjection * GeoVector.YAxis;
                ModOp     mh    = ModOp.Rotate(vaxis, SweepAngle.Deg(HOffset / 5.0));
                ModOp     mv    = ModOp.Rotate(haxis, SweepAngle.Deg(VOffset / 5.0));

                ModOp project = Projection.UnscaledProjection * mv * mh;
                // jetzt noch die Z-Achse einrichten. Die kann senkrecht nach oben oder unten
                // zeigen. Wenn die Z-Achse genau auf den Betrachter zeigt oder genau von ihm weg,
                // dann wird keine Anpassung vorgenommen, weils sonst zu sehr wackelt
                GeoVector z = project * GeoVector.ZAxis;
                if (modelView.ZAxisUp)
                {
                    const double mindeg = 0.05; // nur etwas aufrichten, aber in jedem Durchlauf
                    if (z.y < -0.1)
                    {                           // Z-Achse soll nach unten zeigen
                        Angle a = new Angle(-GeoVector2D.YAxis, new GeoVector2D(z.x, z.y));
                        if (a.Radian > mindeg)
                        {
                            a.Radian = mindeg;
                        }
                        if (a.Radian < -mindeg)
                        {
                            a.Radian = -mindeg;
                        }
                        if (z.x < 0)
                        {
                            project = project * ModOp.Rotate(vaxis ^ haxis, -a.Radian);
                        }
                        else
                        {
                            project = project * ModOp.Rotate(vaxis ^ haxis, a.Radian);
                        }
                        z = project * GeoVector.ZAxis;
                    }
                    else if (z.y > 0.1)
                    {
                        Angle a = new Angle(GeoVector2D.YAxis, new GeoVector2D(z.x, z.y));
                        if (a.Radian > mindeg)
                        {
                            a.Radian = mindeg;
                        }
                        if (a.Radian < -mindeg)
                        {
                            a.Radian = -mindeg;
                        }
                        if (z.x < 0)
                        {
                            project = project * ModOp.Rotate(vaxis ^ haxis, a.Radian);
                        }
                        else
                        {
                            project = project * ModOp.Rotate(vaxis ^ haxis, -a.Radian);
                        }
                        z = project * GeoVector.ZAxis;
                    }
                }
                // Fixpunkt bestimmen
                Point clcenter = vw.Canvas.ClientRectangle.Location;
                clcenter.X += vw.Canvas.ClientRectangle.Width / 2;
                clcenter.Y += vw.Canvas.ClientRectangle.Height / 2;
                // ium Folgenden ist Temporary auf true zu setzen und ein Mechanismus zu finden
                // wie der QuadTree von ProjektedModel berechnet werden soll
                //GeoVector newDirection = mv * mh * Projection.Direction;
                //GeoVector oldDirection = Projection.Direction;
                //GeoVector perp = oldDirection ^ newDirection;

                GeoPoint fixpoint;
                //if (Settings.GlobalSettings.ContainsSetting("ViewFixPoint"))
                if (modelView != null && modelView.FixPointValid)
                {
                    //fixpoint = (GeoPoint)Settings.GlobalSettings.GetValue("ViewFixPoint");
                    fixpoint = modelView.FixPoint;
                }
                else
                {
                    fixpoint = Projection.UnProject(clcenter);
                }
                modelView.SetViewDirection(project, fixpoint, true);
                if (Math.Abs(HOffset) > Math.Abs(VOffset))
                {
                    if (HOffset > 0)
                    {
                        vw.Canvas.Cursor = "PanEast";
                    }
                    else
                    {
                        vw.Canvas.Cursor = "PanWest";
                    }
                }
                else
                {
                    if (HOffset > 0)
                    {
                        vw.Canvas.Cursor = "PanSouth";
                    }
                    else
                    {
                        vw.Canvas.Cursor = "PanNorth";
                    }
                }
                modelView.projectedModelNeedsRecalc = false;
            }
        }
Beispiel #19
0
 /// <summary>
 /// Overrides <see cref="CADability.Curve2D.GeneralCurve2D.Reverse ()"/>
 /// </summary>
 public override void Reverse()
 {
     start = start + sweep;
     sweep = -sweep;
 }
Beispiel #20
0
        /// <summary>
        /// Constructs a non periodic spherical surface with <paramref name="center"/> and <paramref name="radius"/>. The z-axis will be oriented
        /// so that the "south pole" falls into an unused part of the sphere. The edges are <paramref name="orientedCurves"/> bound the sphere
        /// so that when you walk along the curve (<paramref name="outwardOriented"/>==true: on the outside, false: on the inside of the sphere), the
        /// used surfaces is on the left side of the curve. The curves must all be connected and define one or more closed loops on the surface.
        /// </summary>
        /// <param name="center"></param>
        /// <param name="radius"></param>
        /// <param name="outwardOriented">true: the center is on the inside, false: the center is on the outside of the surface</param>
        /// <param name="orientedCurves"></param>
        public SphericalSurfaceNP(GeoPoint center, double radius, bool outwardOriented, ICurve[] orientedCurves)
        {   // find all intersection points of the curves with a plane through the center
            // the points must be on a circle (because the curves are on the sphere) and alternating enter and leave the used surface.
            // we look for the biggest part outside the surface and use its center as the south pole
            for (int ii = 0; ii < 2; ii++)
            {   // if the first loop doesn't find a solution, run with different points again
                // exactly 3 arcs, which define an octant of the sphere can make a problem
                for (int i = 0; i < orientedCurves.Length; i++)
                {
                    double pos = 0.45;
                    if (ii == 1)
                    {
                        pos = 0.55;
                    }
                    GeoPoint  p    = orientedCurves[i].PointAt(pos); // not exactly in the middle to avoid special cases
                    GeoVector dir  = orientedCurves[i].DirectionAt(pos);
                    GeoVector xdir = p - center;
                    Plane     pln;
                    if (outwardOriented)
                    {
                        pln = new Plane(center, xdir, dir ^ xdir);
                    }
                    else
                    {
                        pln = new Plane(center, xdir, xdir ^ dir);
                    }
                    if (ii == 1)
                    {
                        pln.Modify(ModOp.Rotate(center, xdir, SweepAngle.Deg(5))); // slightly rotate to not go exactly through a vertex
                    }
                    double[] pi = orientedCurves[i].GetPlaneIntersection(pln);
                    SortedDictionary <double, bool> positions = new SortedDictionary <double, bool>();
                    bool ok = false;
                    for (int j = 0; j < pi.Length; j++)
                    {
                        GeoPoint2D pi2d = pln.Project(orientedCurves[i].PointAt(pi[j]));
                        double     a    = Math.Atan2(pi2d.y, pi2d.x);
                        if (Math.Abs(pi[j] - pos) < 1e-6)
                        {
                            ok = true;
                            a  = 0.0;
                        }
                        if (positions.ContainsKey(a))
                        {
                            ok = false;
                            break;
                        }
                        else
                        {
                            positions[a] = outwardOriented ^ (pln.ToLocal(orientedCurves[i].DirectionAt(pi[j])).z > 0);
                        }
                    }
                    if (ok)
                    {
                        for (int k = 0; k < orientedCurves.Length; k++)
                        {
                            if (k == i)
                            {
                                continue;
                            }
                            pi = orientedCurves[k].GetPlaneIntersection(pln);
                            for (int j = 0; j < pi.Length; j++)
                            {
                                GeoPoint2D pi2d = pln.Project(orientedCurves[k].PointAt(pi[j]));
                                double     a    = Math.Atan2(pi2d.y, pi2d.x);
                                if (a < 0)
                                {
                                    a += Math.PI * 2.0;
                                }
                                if (positions.ContainsKey(a))
                                {
                                    ok = false;
                                    break;
                                }
                                else
                                {
                                    positions[a] = outwardOriented ^ (pln.ToLocal(orientedCurves[k].DirectionAt(pi[j])).z > 0);
                                }
                            }
                            if (!ok)
                            {
                                break;      // two identical intersection points
                            }
                        }
                    }
                    if (ok)
                    {
                        double lastPos = -1;
                        bool   lastEnter = false;
                        double sp = 0, d = double.MinValue;
                        foreach (KeyValuePair <double, bool> position in positions)
                        {
                            if (lastPos >= 0)
                            {
                                if (position.Value == lastEnter)
                                {
                                    ok = false; // must be alternating
                                    break;
                                }
                                if (position.Value && position.Key - lastPos > d)
                                {
                                    d  = position.Key - lastPos;
                                    sp = lastPos;
                                }
                            }
                            lastPos   = position.Key;
                            lastEnter = position.Value;
                        }
                        GeoPoint2D soutPole2d = new GeoPoint2D(radius * Math.Cos(sp + d / 2), radius * Math.Sin(sp + d / 2));
                        if (ok && d > double.MinValue)
                        {
                            this.center = center;
                            zAxis       = center - pln.ToGlobal(soutPole2d);
                            zAxis.ArbitraryNormals(out xAxis, out yAxis);
                            if (!outwardOriented)
                            {
                                xAxis = -xAxis;
                            }
                            xAxis.Length = zAxis.Length;
                            yAxis.Length = zAxis.Length;
                        }
                        else
                        {
                            ok = false;
                        }
                    }
#if DEBUG
                    // GeoObjectList dbg = DebugGrid;
#endif
                    if (ok)
                    {
                        return;
                    }
                }
            }
        }
Beispiel #21
0
        public string ToString(string format, IFormatProvider formatProvider)
        {
            if (this == null)
            {
                return(nameof(Ellipse2D));
            }
            var sep = ((formatProvider as CultureInfo) ?? CultureInfo.InvariantCulture).GetNumericListSeparator();

            return($"{nameof(EllipticalArc2D)}({nameof(X)}: {X.ToString(format, formatProvider)}{sep} {nameof(Y)}: {Y.ToString(format, formatProvider)}{sep} {nameof(RadiusA)}: {RadiusA.ToString(format, formatProvider)}{sep} {nameof(RadiusB)}: {RadiusB.ToString(format, formatProvider)}{sep} {nameof(Angle)}: {Angle.ToString(format, formatProvider)}{sep} {nameof(StartAngle)}: {StartAngle.ToString(format, formatProvider)}{sep} {nameof(SweepAngle)}: {SweepAngle.ToString(format, formatProvider)})");
        }
Beispiel #22
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
     }
 }
        private void OnSetEndAngle(Angle a)
        {
            SweepAngle sa = new SweepAngle(new Angle(ellipse.StartParameter), a, ellipse.SweepParameter > 0.0);

            ellipse.SweepParameter = sa.Radian;
        }
Beispiel #24
0
 /// <summary>
 /// Constructs a circular arc in 2D.
 /// </summary>
 /// <param name="center">Center of the arc</param>
 /// <param name="radius">Radius of the Arc</param>
 /// <param name="start">Startangle of the arc (x-axis is 0)</param>
 /// <param name="sweep">Sweepangle of the arc -2*pi&lt;=s&lt;=2*pi</param>
 public Arc2D(GeoPoint2D center, double radius, Angle start, SweepAngle sweep)
     : base(center, radius)
 {
     this.start = start;
     this.sweep = sweep;
 }
Beispiel #25
0
        private void OnSetEndAngle(Angle a)
        {
            SweepAngle sa = new SweepAngle(new Angle(circle.StartParameter), a, circle.SweepParameter > 0.0);

            circle.SweepParameter = sa.Radian;
        }