Exemplo n.º 1
0
        public static Point[] GetInterestingPoints(this PrimitiveEllipse ellipse, int maxSeg)
        {
            var startAngleDeg = ellipse.StartAngle;
            var endAngleDeg   = ellipse.EndAngle;

            if (endAngleDeg < startAngleDeg)
            {
                endAngleDeg += MathHelper.ThreeSixty;
            }
            var startAngleRad = startAngleDeg * MathHelper.DegreesToRadians;
            var endAngleRad   = endAngleDeg * MathHelper.DegreesToRadians;

            if (endAngleRad < startAngleRad)
            {
                endAngleRad += MathHelper.TwoPI;
            }
            var    vertexCount = (int)Math.Ceiling((endAngleDeg - startAngleDeg) / MathHelper.ThreeSixty * maxSeg);
            var    points      = new Point[vertexCount + 1];
            var    angleDelta  = MathHelper.ThreeSixty / maxSeg * MathHelper.DegreesToRadians;
            var    trans       = ellipse.FromUnitCircle;
            double angle;
            int    i;

            for (angle = startAngleRad, i = 0; i < vertexCount; angle += angleDelta, i++)
            {
                points[i] = trans.Transform(new Point(Math.Cos(angle), Math.Sin(angle), 0.0));
            }

            points[i] = trans.Transform(new Point(Math.Cos(angle), Math.Sin(angle), 0.0));
            return(points);
        }
Exemplo n.º 2
0
        public static IEnumerable <Point> IntersectionPoints(this PrimitiveEllipse ellipse, PrimitivePoint point, bool withinBounds = true)
        {
            var fromUnit    = ellipse.FromUnitCircle;
            var toUnit      = fromUnit.Inverse();
            var pointOnUnit = (Vector)toUnit.Transform(point.Location);

            if (MathHelper.CloseTo(pointOnUnit.LengthSquared, 1.0))
            {
                if (!withinBounds)
                {
                    return new Point[] { point.Location }
                }
                ;                                          // always a match
                else
                {
                    var pointAngle = pointOnUnit.ToAngle();

                    if (ellipse.IsAngleContained(pointAngle))
                    {
                        return new Point[] { point.Location }
                    }
                    ;
                    else
                    {
                        return(new Point[0]);
                    }
                }
            }
            else
            {
                // wrong distance
                return(new Point[0]);
            }
        }
Exemplo n.º 3
0
        public static Point GetPoint(this PrimitiveEllipse ellipse, double angle)
        {
            var pointUnit        = new Point(Math.Cos(angle * MathHelper.DegreesToRadians), Math.Sin(angle * MathHelper.DegreesToRadians), 0.0);
            var pointTransformed = ellipse.FromUnitCircle.Transform(pointUnit);

            return(pointTransformed);
        }
Exemplo n.º 4
0
        public static IEnumerable <Point> IntersectionPoints(this PrimitiveEllipse ellipse, IPrimitive primitive, bool withinBounds = true)
        {
            IEnumerable <Point> result;

            switch (primitive.Kind)
            {
            case PrimitiveKind.Ellipse:
                result = ellipse.IntersectionPoints((PrimitiveEllipse)primitive, withinBounds);
                break;

            case PrimitiveKind.Line:
                result = ((PrimitiveLine)primitive).IntersectionPoints(ellipse, withinBounds);
                break;

            case PrimitiveKind.Point:
                result = ellipse.IntersectionPoints((PrimitivePoint)primitive, withinBounds);
                break;

            case PrimitiveKind.Text:
                result = Enumerable.Empty <Point>();
                break;

            default:
                Debug.Assert(false, "Unsupported primitive type");
                result = Enumerable.Empty <Point>();
                break;
            }

            return(result);
        }
Exemplo n.º 5
0
        public Circle(PrimitiveEllipse ellipse, object tag = null)
            : base(ellipse.Color, tag)
        {
            if (!ellipse.IsCircle)
            {
                throw new ArgumentException($"{nameof(PrimitiveEllipse)} was not a circle");
            }

            _primitive  = ellipse;
            _primitives = new[] { _primitive };
            Radius      = ellipse.MajorAxis.Length;

            var right     = Vector.RightVectorFromNormal(Normal);
            var points    = TransformedPoints(Center, Normal, right, Radius, Radius, 0, 90, 180, 270);
            var quadrant1 = points[0];
            var quadrant2 = points[1];
            var quadrant3 = points[2];
            var quadrant4 = points[3];

            _snapPoints = new SnapPoint[]
            {
                new CenterPoint(Center),
                new QuadrantPoint(quadrant1),
                new QuadrantPoint(quadrant2),
                new QuadrantPoint(quadrant3),
                new QuadrantPoint(quadrant4)
            };
            BoundingBox = BoundingBox.FromPoints(points);
        }
Exemplo n.º 6
0
Arquivo: Arc.cs Projeto: nbright/BCad
        public Arc(PrimitiveEllipse arc, object tag = null)
            : base(arc.Color, tag)
        {
            if (arc.MinorAxisRatio != 1.0)
            {
                throw new ArgumentException($"{nameof(PrimitiveEllipse)} is not circular");
            }

            _primitive  = arc;
            _primitives = new[] { _primitive };
            Radius      = arc.MajorAxis.Length;

            var right    = Vector.RightVectorFromNormal(Normal);
            var midAngle = (StartAngle + EndAngle) / 2.0;

            if (StartAngle > EndAngle)
            {
                midAngle -= 180.0;
            }
            var points = Circle.TransformedPoints(Center, Normal, right, Radius, Radius, StartAngle, EndAngle, midAngle);

            EndPoint1 = points[0];
            EndPoint2 = points[1];
            MidPoint  = points[2];

            _snapPoints = new SnapPoint[]
            {
                new CenterPoint(Center),
                new EndPoint(EndPoint1),
                new EndPoint(EndPoint2),
                new MidPoint(MidPoint)
            };
            BoundingBox = BoundingBox.FromPoints(Circle.TransformedPoints(Center, Normal, right, Radius, Radius, 0, 90, 180, 270));
        }
Exemplo n.º 7
0
        public static double GetAngle(this PrimitiveEllipse ellipse, Point point)
        {
            var transform           = ellipse.FromUnitCircle.Inverse();
            var pointFromUnitCircle = transform.Transform(point);
            var angle = Math.Atan2(pointFromUnitCircle.Y, pointFromUnitCircle.X) * MathHelper.RadiansToDegrees;

            return(angle.CorrectAngleDegrees());
        }
Exemplo n.º 8
0
        private static bool IsPointOnPrimitive(this PrimitiveEllipse el, Point point)
        {
            var unitPoint = el.FromUnitCircle.Inverse().Transform(point);

            return(MathHelper.CloseTo(0.0, unitPoint.Z) && // on the XY plane
                   MathHelper.CloseTo(1.0, ((Vector)unitPoint).LengthSquared) && // on the unit circle
                   el.IsAngleContained(Math.Atan2(unitPoint.Y, unitPoint.X) * MathHelper.RadiansToDegrees)); // within angle bounds
        }
Exemplo n.º 9
0
        public void EllipseAngleContainmentTest()
        {
            var el = new PrimitiveEllipse(Point.Origin, 1.0, 90.0, 360.0, Vector.ZAxis);

            Assert.True(el.IsAngleContained(90.0));
            Assert.True(el.IsAngleContained(180.0));
            Assert.True(el.IsAngleContained(270.0));
            Assert.True(el.IsAngleContained(360.0));
            Assert.False(el.IsAngleContained(45.0));
        }
Exemplo n.º 10
0
        public static PrimitiveEllipse Project(PrimitiveEllipse ellipse, Matrix4 transform)
        {
            // brute-force the endpoints
            var fromUnit    = Matrix4.CreateScale(1.0, 1.0, 0.0) * transform * ellipse.FromUnitCircle;
            var center      = transform.Transform(ellipse.Center);
            var minPoint    = fromUnit.Transform(new Point(MathHelper.COS[0], MathHelper.SIN[0], 0));
            var maxPoint    = minPoint;
            var minDistance = (minPoint - center).LengthSquared;
            var maxDistance = minDistance;

            for (int i = 1; i < 360; i++)
            {
                var next = fromUnit.Transform(new Point(MathHelper.COS[i], MathHelper.SIN[i], 0));
                var dist = (next - center).LengthSquared;
                if (dist < minDistance)
                {
                    minPoint    = next;
                    minDistance = dist;
                }

                if (dist > maxDistance)
                {
                    maxPoint    = next;
                    maxDistance = dist;
                }
            }

            var majorAxis      = maxPoint - center;
            var minorAxisRatio = Math.Sqrt(minDistance) / Math.Sqrt(maxDistance);
            var startAngle     = ellipse.StartAngle;
            var endAngle       = ellipse.EndAngle;

            // projection looks like a circle
            if (Math.Abs(maxDistance - minDistance) < MathHelper.Epsilon * 1000) // TODO: need a better way to do this
            {
                majorAxis      = new Vector(majorAxis.Length, 0.0, 0.0);         // right vector
                minorAxisRatio = 1.0;
            }

            // correct start/end angles
            if (!ellipse.IsClosed)
            {
                var tempEllipse = new PrimitiveEllipse(center, majorAxis, Vector.ZAxis, minorAxisRatio, 0.0, MathHelper.ThreeSixty, ellipse.Color);
                var majorAngle  = majorAxis.ToAngle();
                var startPoint  = transform.Transform(ellipse.StartPoint());
                var endPoint    = transform.Transform(ellipse.EndPoint());
                var toUnit      = tempEllipse.FromUnitCircle.Inverse();
                var startUnit   = (Vector)toUnit.Transform(startPoint);
                var endUnit     = (Vector)toUnit.Transform(endPoint);
                startAngle = (startUnit.ToAngle() - majorAngle).CorrectAngleDegrees();
                endAngle   = (endUnit.ToAngle() - majorAngle).CorrectAngleDegrees();
            }

            return(new PrimitiveEllipse(center, majorAxis, Vector.ZAxis, minorAxisRatio, startAngle, endAngle, ellipse.Color));
        }
Exemplo n.º 11
0
        public async Task <bool> Execute(IWorkspace workspace, object arg)
        {
            var first = await workspace.InputService.GetPoint(new UserDirective("First point"));

            if (!first.Cancel && first.HasValue)
            {
                var second = await workspace.InputService.GetPoint(new UserDirective("Second point"), (p) =>
                {
                    return(new[]
                    {
                        new PrimitiveLine(first.Value, p)
                    });
                });

                if (!second.Cancel && second.HasValue)
                {
                    var third = await workspace.InputService.GetPoint(new UserDirective("Third point"), (p) =>
                    {
                        var a = PrimitiveEllipse.ThreePointArc(first.Value, second.Value, p, workspace.DrawingPlane.Normal);
                        if (a == null)
                        {
                            return(new IPrimitive[0]);
                        }
                        else
                        {
                            return(new IPrimitive[]
                            {
                                a,
                                new PrimitivePoint(first.Value),
                                new PrimitivePoint(second.Value)
                            });
                        }
                    });

                    if (!third.Cancel && third.HasValue)
                    {
                        var primitiveArc = PrimitiveEllipse.ThreePointArc(first.Value, second.Value, third.Value, workspace.DrawingPlane.Normal);
                        if (primitiveArc != null)
                        {
                            var arc = new Arc(
                                primitiveArc.Center,
                                primitiveArc.MajorAxis.Length,
                                primitiveArc.StartAngle,
                                primitiveArc.EndAngle,
                                primitiveArc.Normal);
                            workspace.AddToCurrentLayer(arc);
                            return(true);
                        }
                    }
                }
            }

            return(false);
        }
Exemplo n.º 12
0
 public static IPrimitive PrimitiveFromPointAndVertex(Point lastPoint, Vertex nextVertex)
 {
     if (nextVertex.IsLine)
     {
         return(new PrimitiveLine(lastPoint, nextVertex.Location));
     }
     else
     {
         return(PrimitiveEllipse.ArcFromPointsAndIncludedAngle(lastPoint, nextVertex.Location, nextVertex.IncludedAngle, nextVertex.Direction));
     }
 }
Exemplo n.º 13
0
 public static IPrimitive PrimitiveFromVertices(Vertex last, Vertex next)
 {
     if (last.IsLine)
     {
         return(new PrimitiveLine(last.Location, next.Location));
     }
     else
     {
         return(PrimitiveEllipse.ArcFromPointsAndIncludedAngle(last.Location, next.Location, last.IncludedAngle, last.Direction));
     }
 }
Exemplo n.º 14
0
        private static void TestThreePointArcNormal(Point a, Point b, Point c, Vector idealNormal, Point expectedCenter, double expectedRadius, double expectedStartAngle, double expectedEndAngle)
        {
            var arc = PrimitiveEllipse.ThreePointArc(a, b, c, idealNormal);

            AssertClose(idealNormal, arc.Normal);
            AssertClose(expectedCenter, arc.Center);
            AssertClose(1.0, arc.MinorAxisRatio);
            AssertClose(expectedRadius, arc.MajorAxis.Length);
            AssertClose(expectedStartAngle, arc.StartAngle);
            AssertClose(expectedEndAngle, arc.EndAngle);
        }
Exemplo n.º 15
0
        public void ThreePointCircleTest()
        {
            var a    = new Point(0, 0, 0);
            var b    = new Point(0, 2, 0);
            var c    = new Point(1, 1, 0);
            var circ = PrimitiveEllipse.ThreePointCircle(a, b, c);

            Assert.NotNull(circ);
            Assert.Equal(new Point(0, 1, 0), circ.Center);
            Assert.Equal(Vector.XAxis, circ.MajorAxis);
            Assert.Equal(Vector.ZAxis, circ.Normal);
        }
Exemplo n.º 16
0
        public void EllipseGetPointTest()
        {
            var el = new PrimitiveEllipse(Point.Origin, 1.0, 0.0, 180.0, Vector.ZAxis);

            Assert.True(el.StartPoint().CloseTo(new Point(1.0, 0.0, 0.0)));
            Assert.True(el.EndPoint().CloseTo(new Point(-1.0, 0.0, 0.0)));
            Assert.True(el.GetPoint(90.0).CloseTo(new Point(0.0, 1.0, 0.0)));

            el = new PrimitiveEllipse(new Point(1.0, 1.0, 0.0), 1.0, 0.0, 180.0, Vector.ZAxis);
            Assert.True(el.StartPoint().CloseTo(new Point(2.0, 1.0, 0.0)));
            Assert.True(el.EndPoint().CloseTo(new Point(0.0, 1.0, 0.0)));
            Assert.True(el.GetPoint(90.0).CloseTo(new Point(1.0, 2.0, 0.0)));
        }
Exemplo n.º 17
0
        public Ellipse(PrimitiveEllipse ellipse, object tag = null)
            : base(ellipse.Color, tag)
        {
            _primitive  = ellipse;
            _primitives = new[] { _primitive };

            var majorLength = MajorAxis.Length;
            var points      = Circle.TransformedPoints(Center, Normal, MajorAxis, majorLength, majorLength * MinorAxisRatio, 0, 90, 180, 270, StartAngle, EndAngle, (StartAngle + EndAngle) / 2.0);
            var quadrant1   = points[0];
            var quadrant2   = points[1];
            var quadrant3   = points[2];
            var quadrant4   = points[3];
            var endPoint1   = points[4];
            var endPoint2   = points[5];
            var midPoint    = points[6];

            var snaps = new List <SnapPoint>();

            snaps.Add(new CenterPoint(Center));
            if (StartAngle == 0.0 && EndAngle == 360.0)
            {
                // treat it like a circle
                snaps.Add(new QuadrantPoint(quadrant1));
                snaps.Add(new QuadrantPoint(quadrant2));
                snaps.Add(new QuadrantPoint(quadrant3));
                snaps.Add(new QuadrantPoint(quadrant4));
            }
            else
            {
                // treat it like an arc
                snaps.Add(new EndPoint(endPoint1));
                snaps.Add(new EndPoint(endPoint2));
                snaps.Add(new MidPoint(midPoint));
            }

            if (MinorAxisRatio != 1.0)
            {
                // a true ellipse with two distinct foci
                var majorNormalized = MajorAxis.Normalize();
                var minorLength     = majorLength * MinorAxisRatio;
                var focusDistance   = Math.Sqrt((majorLength * majorLength) - (minorLength * minorLength));
                var focus1          = (Point)((majorNormalized * focusDistance) + Center);
                var focus2          = (Point)((majorNormalized * -focusDistance) + Center);
                snaps.Add(new FocusPoint(focus1));
                snaps.Add(new FocusPoint(focus2));
            }

            _snapPoints = snaps.ToArray();
            BoundingBox = BoundingBox.FromPoints(quadrant1, quadrant2, quadrant3, quadrant4);
        }
Exemplo n.º 18
0
        public async Task <bool> Execute(IWorkspace workspace, object arg)
        {
            var drawingPlane = workspace.DrawingPlane;
            var center       = await workspace.InputService.GetPoint(new UserDirective("Center"));

            if (!center.Cancel && center.HasValue)
            {
                var majorEnd = await workspace.InputService.GetPoint(new UserDirective("Major axis endpoint"), p =>
                {
                    return(new[]
                    {
                        new PrimitiveLine(center.Value, p)
                    });
                });

                var majorPrimitive  = new PrimitiveLine(center.Value, majorEnd.Value);
                var majorAxis       = majorEnd.Value - center.Value;
                var majorAxisLength = majorAxis.Length;
                if (!majorEnd.Cancel && majorEnd.HasValue)
                {
                    var minorEnd = await workspace.InputService.GetPoint(new UserDirective("Minor axis endpoint"), lastPoint : center.Value, onCursorMove : p =>
                    {
                        var tempMinorAxis      = p - center.Value;
                        var tempMinorAxisRatio = tempMinorAxis.Length / majorAxisLength;
                        var el = new PrimitiveEllipse(center.Value, majorAxis, drawingPlane.Normal, tempMinorAxisRatio, 0.0, 360.0);
                        return(new IPrimitive[]
                        {
                            majorPrimitive,                     // major axis line
                            new PrimitiveLine(center.Value, p), // minor axis line
                            el                                  // the ellipse
                        });
                    });

                    if (!minorEnd.Cancel && minorEnd.HasValue)
                    {
                        var minorAxis      = minorEnd.Value - center.Value;
                        var minorAxisRatio = minorAxis.Length / majorAxisLength;
                        if (!minorEnd.Cancel && minorEnd.HasValue)
                        {
                            var el = new Ellipse(center.Value, majorAxis, minorAxisRatio, 0.0, 360.0, drawingPlane.Normal);
                            workspace.AddToCurrentLayer(el);
                            return(true);
                        }
                    }
                }
            }

            return(false);
        }
Exemplo n.º 19
0
        private static Entity ToEntity(StepEdge edge)
        {
            switch (edge.ItemType)
            {
            case StepItemType.EdgeCurve:
            {
                var edgeCurve = (StepEdgeCurve)edge;
                if (edgeCurve.EdgeGeometry is StepCircle)
                {
                    var circle = (StepCircle)edgeCurve.EdgeGeometry;
                    var center = circle.Position.Location;
                    var normal = ToVector(circle.Position.RefDirection);
                    normal = Vector.ZAxis;
                    var primitiveCircle = new PrimitiveEllipse(ToPoint(center), circle.Radius, normal);
                    var toUnit          = primitiveCircle.FromUnitCircle.Inverse();
                    var startPoint      = toUnit.Transform(ToPoint((StepVertexPoint)edgeCurve.EdgeStart));
                    var endPoint        = toUnit.Transform(ToPoint((StepVertexPoint)edgeCurve.EdgeEnd));
                    var startAngle      = Math.Atan2(startPoint.Y, startPoint.X).CorrectAngleRadians() * MathHelper.RadiansToDegrees;
                    var endAngle        = Math.Atan2(endPoint.Y, endPoint.X).CorrectAngleRadians() * MathHelper.RadiansToDegrees;
                    return(new Arc(primitiveCircle.Center, circle.Radius, startAngle, endAngle, primitiveCircle.Normal));
                }
                else if (edgeCurve.EdgeGeometry is StepLine)
                {
                    var  stepLine = (StepLine)edgeCurve.EdgeGeometry;
                    Line line;
                    if (edgeCurve.EdgeStart == null || edgeCurve.EdgeEnd == null)
                    {
                        // use auto values
                        line = ToLine(stepLine);
                    }
                    else
                    {
                        // use explicit values
                        var p1 = ToPoint((StepVertexPoint)edgeCurve.EdgeStart);
                        var p2 = ToPoint((StepVertexPoint)edgeCurve.EdgeEnd);
                        line = new Line(p1, p2);
                    }

                    return(line);
                }

                break;
            }
            }

            return(null);
        }
Exemplo n.º 20
0
        public void TrimSplineOnLineTest2()
        {
            //      _______|_              _______|
            //     /       | \            /       | \
            //    /        |  \          /        |
            //   |         |   |o       |         |
            //   |         |   |   =>   |         |   |
            //    \        |  /          \        |  /
            //     \       | /            \       | /
            //      -------|-              -------|_
            var sqrt2over2   = Math.Sqrt(2.0) / 2.0;
            var unitCircle   = new PrimitiveEllipse(Point.Origin, 1.0, Vector.ZAxis);
            var circleSpline = Spline.FromBeziers(unitCircle.AsBezierCurves());
            var trimLine     = new Line(new Point(sqrt2over2, -1.0, 0.0), new Point(sqrt2over2, 1.0, 0.0));

            // 45-90 degrees
            var q1trimBezier = new PrimitiveBezier(
                new Point(0.70696813418525, 0.70696813418525, 0.0),
                new Point(0.525957512247, 0.8879787561235, 0.0),
                new Point(0.275957512247, 1.0, 0.0),
                new Point(0.0, 1.0, 0.0));

            // 270-315 degrees
            var q4trimBezier = new PrimitiveBezier(
                new Point(0.0, -1.0, 0.0),
                new Point(0.275957512247, -1.0, 0.0),
                new Point(0.525957512247, -0.8879787561235, 0.0),
                new Point(0.70696813418525, -0.70696813418525, 0.0));

            var selectionPoint = new Point(Math.Cos(1.0 * MathHelper.DegreesToRadians), Math.Sin(1.0 * MathHelper.DegreesToRadians), 0.0); // one degree up

            var resultSpline = Spline.FromBeziers(new[]
            {
                new PrimitiveBezier(new Point(1.0, 0.0, 0.0), new Point(1.0, -0.551915024494, 0.0), new Point(0.551915024494, -1.0, 0.0), new Point(0.0, -1.0, 0.0)),
                new PrimitiveBezier(new Point(0.0, 1.0, 0.0), new Point(0.27602797672647056, 1.0, 0.0), new Point(0.5260851832511362, 0.8879215406024443, 0.0), new Point(0.7071067813752437, 0.7068294600060859, 0.0)),
            });

            DoTrim(
                existingEntities: new[] { trimLine },
                entityToTrim: circleSpline,
                selectionPoint: selectionPoint,
                expectTrim: true,
                expectedAdded: new[] { resultSpline });
        }
Exemplo n.º 21
0
        public static bool IsAngleContained(this PrimitiveEllipse ellipse, double angle)
        {
            angle = angle.CorrectAngleDegrees();
            var startAngle = ellipse.StartAngle;
            var endAngle   = ellipse.EndAngle;

            if (endAngle < startAngle)
            {
                // we pass zero.  angle should either be [startAngle, 360.0] or [0.0, endAngle]
                return(MathHelper.Between(startAngle, 360.0, angle) ||
                       MathHelper.Between(0.0, endAngle, angle));
            }
            else
            {
                // we're within normal bounds
                return(MathHelper.Between(startAngle, endAngle, angle) ||
                       MathHelper.Between(startAngle, endAngle, angle + 360.0));
            }
        }
Exemplo n.º 22
0
        public static Entity ToArc(this IgesCircularArc arc)
        {
            var center     = TransformPoint(arc, arc.ProperCenter);
            var startPoint = TransformPoint(arc, arc.ProperStartPoint);
            var endPoint   = TransformPoint(arc, arc.ProperEndPoint);

            // all points have the same Z-value, so the normal will be the transformed Z-axis vector
            var igesNormal = TransformPoint(arc, IgesVector.ZAxis);
            var normal     = new Vector(igesNormal.X, igesNormal.Y, igesNormal.Z).Normalize();

            // find radius from start/end points
            var startVector = startPoint - center;
            var endVector   = endPoint - center;
            var startRadius = startVector.Length;
            var endRadius   = endVector.Length;
            // these should be very close, if not identical, but not necessarily
            var radius = (startRadius + endRadius) / 2;

            // if start/end points are the same, it's a circle.  otherwise it's an arc
            if (startPoint.CloseTo(endPoint))
            {
                return(new Circle(center, radius, normal, GetColor(arc), arc));
            }
            else
            {
                // project back to unit circle to find start/end angles
                var primitiveCircle = new PrimitiveEllipse(center, radius, normal);
                var fromUnit        = primitiveCircle.FromUnitCircle;
                Debug.Assert(AreAllValuesValid(fromUnit));
                var toUnit = fromUnit.Inverse();
                Debug.Assert(AreAllValuesValid(toUnit));
                var startUnit  = toUnit.Transform(startPoint);
                var endUnit    = toUnit.Transform(endPoint);
                var startAngle = ((Vector)startUnit).ToAngle();
                var endAngle   = ((Vector)endUnit).ToAngle();
                return(new Arc(center, radius, startAngle, endAngle, normal, GetColor(arc), arc));
            }
        }
Exemplo n.º 23
0
        public void ArcsFromPointsAndRadiusTest1()
        {
            // given the points (0, 1) and (0, -1) and an included angle of 90 degrees, the possible centers for the arcs
            // here are (1, 0) and (-1, 0) and a radius of sqrt(2)
            var p1            = new Point(0, 1, 0);
            var p2            = new Point(0, -1, 0);
            var includedAngle = 90.0;

            var sqrt2 = Math.Sqrt(2.0);

            var arc1 = PrimitiveEllipse.ArcFromPointsAndIncludedAngle(p1, p2, includedAngle, VertexDirection.Clockwise);

            AssertClose(new Point(-1, 0, 0), arc1.Center);
            AssertClose(sqrt2, arc1.MajorAxis.Length);
            AssertClose(315.0, arc1.StartAngle);
            AssertClose(45.0, arc1.EndAngle);

            var arc2 = PrimitiveEllipse.ArcFromPointsAndIncludedAngle(p1, p2, includedAngle, VertexDirection.CounterClockwise);

            AssertClose(new Point(1, 0, 0), arc2.Center);
            AssertClose(sqrt2, arc2.MajorAxis.Length);
            AssertClose(135.0, arc2.StartAngle);
            AssertClose(225.0, arc2.EndAngle);
        }
Exemplo n.º 24
0
        /// <summary>
        /// Using algorithm as described at http://www.ceometric.com/support/examples/v-ellipse-projection-using-rytz-construction.html
        /// </summary>
        public static ProjectedCircle FromConjugateDiameters(Circle originalCircle, Layer originalLayer, Point center, Point majorAxisConjugate, Point minorAxisConjugate)
        {
            // re-map to shorter variables
            var m = center;
            var p = majorAxisConjugate;
            var q = minorAxisConjugate;

            // PM must be longer than QM.  Swap if necessary.
            var pm = p - m;
            var qm = q - m;

            if (pm.LengthSquared > qm.LengthSquared)
            {
                var temp = p;
                p  = q;
                q  = temp;
                pm = p - m;
                qm = q - m;
            }

            // if axes are already orthoganal, no transform is needed
            if (MathHelper.CloseTo(0.0, pm.Dot(qm)))
            {
                return(new ProjectedCircle(originalCircle, originalLayer, m, qm.Length, pm.Length, 0.0));
            }

            // find the plane containing the projected ellipse
            var plane = Plane.From3Points(m, p, q);

            // rotate P by 90 degrees around the normal
            var rotationMatrix = Matrix4.Identity;

            rotationMatrix.RotateAt(new Quaternion(plane.Normal, 90.0), m);
            var rotp = rotationMatrix.Transform(p);

            // the angle between (rotp-M) and (Q-M) should be less than 90 degrees.  mirror if not
            if (Vector.AngleBetween(rotp - m, qm) > 90.0)
            {
                rotp = ((rotp - m) * -1.0) + m;
            }

            // construct the rytz circle
            // the center is the midpoint of the edge from rotp to Q
            // the radius is the distance from M to the center
            // the normal is the normal of the plane
            var rc   = (rotp + q) / 2.0;
            var rytz = new PrimitiveEllipse(rc, (m - rc).Length, plane.Normal);

            // intersect the rytz circle with a line passing through the center and Q
            var intersectingLine   = new PrimitiveLine(rc, q);
            var intersectingPoints = intersectingLine.IntersectionPoints(rytz, false).ToList();

            if (intersectingPoints.Count != 2)
            {
                return(null);
            }
            var da = (q - intersectingPoints[0]).Length;
            var db = (q - intersectingPoints[1]).Length;

            if (da < db)
            {
                // da must be large than db
                var temp = da;
                da = db;
                db = temp;
            }

            // get main axes
            var a = intersectingPoints[0] - m;
            var b = intersectingPoints[1] - m;

            if (b.LengthSquared > a.LengthSquared)
            {
                var temp = a;
                a = b;
                b = temp;
            }

            // return the new ellipse
            return(new ProjectedCircle(originalCircle, originalLayer, m, da, db, a.ToAngle() * -1.0));
        }
Exemplo n.º 25
0
        public static IEnumerable <Point> IntersectionPoints(this PrimitiveLine line, PrimitiveEllipse ellipse, bool withinSegment = true)
        {
            var empty = Enumerable.Empty <Point>();

            var l0 = line.P1;
            var l  = line.P2 - line.P1;
            var p0 = ellipse.Center;
            var n  = ellipse.Normal;

            var right     = ellipse.MajorAxis.Normalize();
            var up        = ellipse.Normal.Cross(right).Normalize();
            var radiusX   = ellipse.MajorAxis.Length;
            var radiusY   = radiusX * ellipse.MinorAxisRatio;
            var transform = ellipse.FromUnitCircle;
            var inverse   = transform.Inverse();

            var denom = l.Dot(n);
            var num   = (p0 - l0).Dot(n);

            var flatPoints = new List <Point>();

            if (Math.Abs(denom) < MathHelper.Epsilon)
            {
                // plane either contains the line entirely or is parallel
                if (Math.Abs(num) < MathHelper.Epsilon)
                {
                    // parallel.  normalize the plane and find the intersection
                    var flatLine = line.Transform(inverse);
                    // the ellipse is now centered at the origin with a radius of 1.
                    // find the intersection points then reproject
                    var dv     = flatLine.P2 - flatLine.P1;
                    var dx     = dv.X;
                    var dy     = dv.Y;
                    var dr2    = dx * dx + dy * dy;
                    var D      = flatLine.P1.X * flatLine.P2.Y - flatLine.P2.X * flatLine.P1.Y;
                    var det    = dr2 - D * D;
                    var points = new List <Point>();
                    if (det < 0.0 || Math.Abs(dr2) < MathHelper.Epsilon)
                    {
                        // no intersection or line is too short
                    }
                    else if (Math.Abs(det) < MathHelper.Epsilon)
                    {
                        // 1 point
                        var x = (D * dy) / dr2;
                        var y = (-D * dx) / dr2;
                        points.Add(new Point(x, y, 0.0));
                    }
                    else
                    {
                        // 2 points
                        var sgn  = dy < 0.0 ? -1.0 : 1.0;
                        var det2 = Math.Sqrt(det);
                        points.Add(
                            new Point(
                                (D * dy + sgn * dx * det2) / dr2,
                                (-D * dx + Math.Abs(dy) * det2) / dr2,
                                0.0));
                        points.Add(
                            new Point(
                                (D * dy - sgn * dx * det2) / dr2,
                                (-D * dx - Math.Abs(dy) * det2) / dr2,
                                0.0));
                    }

                    // ensure the points are within appropriate bounds
                    if (withinSegment)
                    {
                        // line test
                        points = points.Where(p =>
                                              MathHelper.Between(flatLine.P1.X, flatLine.P2.X, p.X) &&
                                              MathHelper.Between(flatLine.P1.Y, flatLine.P2.Y, p.Y)).ToList();

                        // circle test
                        points = points.Where(p => ellipse.IsAngleContained(((Vector)p).ToAngle())).ToList();
                    }

                    return(points.Select(p => (Point)transform.Transform(p)));
                }
            }
            else
            {
                // otherwise line and plane intersect in only 1 point, p
                var d = num / denom;
                var p = (Point)(l * d + l0);

                // verify within the line segment
                if (withinSegment && !MathHelper.Between(0.0, 1.0, d))
                {
                    return(empty);
                }

                // p is the point of intersection.  verify if on transformed unit circle
                var unitVector = (Vector)inverse.Transform(p);
                if (Math.Abs(unitVector.Length - 1.0) < MathHelper.Epsilon)
                {
                    // point is on the unit circle
                    if (withinSegment)
                    {
                        // verify within the angles specified
                        var angle = Math.Atan2(unitVector.Y, unitVector.X) * MathHelper.RadiansToDegrees;
                        if (MathHelper.Between(ellipse.StartAngle, ellipse.EndAngle, angle.CorrectAngleDegrees()))
                        {
                            return(new[] { p });
                        }
                    }
                    else
                    {
                        return(new[] { p });
                    }
                }
            }

            // point is not on unit circle
            return(empty);
        }
Exemplo n.º 26
0
        public static IEnumerable <Point> IntersectionPoints(this PrimitiveEllipse first, PrimitiveEllipse second, bool withinBounds = true)
        {
            var empty = Enumerable.Empty <Point>();
            IEnumerable <Point> results;

            // planes either intersect in a line or are parallel
            var lineVector = first.Normal.Cross(second.Normal);

            if (lineVector.IsZeroVector)
            {
                // parallel or the same plane
                if ((first.Center == second.Center) ||
                    Math.Abs((second.Center - first.Center).Dot(first.Normal)) < MathHelper.Epsilon)
                {
                    // if they share a point or second.Center is on the first plane, they are the same plane
                    // project second back to a unit circle and find intersection points
                    var fromUnit = first.FromUnitCircle;
                    var toUnit   = fromUnit.Inverse();

                    // transform second ellipse to be on the unit circle's plane
                    var           secondCenter   = toUnit.Transform(second.Center);
                    var           secondMajorEnd = toUnit.Transform(second.Center + second.MajorAxis);
                    var           secondMinorEnd = toUnit.Transform(second.Center + (second.Normal.Cross(second.MajorAxis).Normalize() * second.MajorAxis.Length * second.MinorAxisRatio));
                    RoundedDouble a = (secondMajorEnd - secondCenter).Length;
                    RoundedDouble b = (secondMinorEnd - secondCenter).Length;

                    if (a == b)
                    {
                        // if second ellipse is a circle we can absolutely solve for the intersection points
                        // rotate to place the center of the second circle on the x-axis
                        var angle           = ((Vector)secondCenter).ToAngle();
                        var rotation        = Matrix4.RotateAboutZ(angle);
                        var returnTransform = fromUnit * Matrix4.RotateAboutZ(-angle);
                        var newSecondCenter = rotation.Transform(secondCenter);
                        var secondRadius    = a;

                        if (Math.Abs(newSecondCenter.X) > secondRadius + 1.0)
                        {
                            // no points of intersection
                            results = empty;
                        }
                        else
                        {
                            // 2 points of intersection
                            var x = (secondRadius * secondRadius - newSecondCenter.X * newSecondCenter.X - 1.0)
                                    / (-2.0 * newSecondCenter.X);
                            var y = Math.Sqrt(1.0 - x * x);
                            results = new[]
                            {
                                new Point(x, y, 0),
                                new Point(x, -y, 0)
                            };
                        }

                        results = results.Distinct().Select(p => returnTransform.Transform(p));
                    }
                    else
                    {
                        // rotate about the origin to make the major axis align with the x-axis
                        var angle       = (secondMajorEnd - secondCenter).ToAngle();
                        var rotation    = Matrix4.RotateAboutZ(angle);
                        var finalCenter = rotation.Transform(secondCenter);
                        fromUnit = fromUnit * Matrix4.RotateAboutZ(-angle);
                        toUnit   = fromUnit.Inverse();

                        if (a < b)
                        {
                            // rotate to ensure a > b
                            fromUnit    = fromUnit * Matrix4.RotateAboutZ(90);
                            toUnit      = fromUnit.Inverse();
                            finalCenter = Matrix4.RotateAboutZ(-90).Transform(finalCenter);

                            // and swap a and b
                            var temp = a;
                            a = b;
                            b = temp;
                        }

                        RoundedDouble h  = finalCenter.X;
                        RoundedDouble k  = finalCenter.Y;
                        var           h2 = h * h;
                        var           k2 = k * k;
                        var           a2 = a * a;
                        var           b2 = b * b;
                        var           a4 = a2 * a2;
                        var           b4 = b2 * b2;

                        // RoundedDouble is used to ensure all operations are rounded to a certain precision
                        if (Math.Abs(h) < MathHelper.Epsilon)
                        {
                            // ellipse x = 0; wide
                            // find x values
                            var A = a2 - a2 * b2 + a2 * k2 - ((2 * a4 * k2) / (a2 - b2));
                            var B = (2 * a2 * k * Math.Sqrt(b2 * (-a2 + a4 + b2 - a2 * b2 + a2 * k2))) / (a2 - b2);
                            var C = (RoundedDouble)Math.Sqrt(a2 - b2);

                            var x1 = -Math.Sqrt(A + B) / C;
                            var x2 = (RoundedDouble)(-x1);
                            var x3 = -Math.Sqrt(A - B) / C;
                            var x4 = (RoundedDouble)(-x3);

                            // find y values
                            var D = a2 * k;
                            var E = Math.Sqrt(-a2 * b2 + a4 * b2 + b4 - a2 * b4 + a2 * b2 * k2);
                            var F = a2 - b2;

                            var y1 = (D - E) / F;
                            var y2 = (D + E) / F;

                            results = new[] {
                                new Point(x1, y1, 0),
                                new Point(x2, y1, 0),
                                new Point(x3, y2, 0),
                                new Point(x4, y2, 0)
                            };
                        }
                        else if (Math.Abs(k) < MathHelper.Epsilon)
                        {
                            // ellipse y = 0; wide
                            // find x values
                            var A = -b2 * h;
                            var B = Math.Sqrt(a4 - a2 * b2 - a4 * b2 + a2 * b4 + a2 * b2 * h2);
                            var C = a2 - b2;

                            var x1 = (A - B) / C;
                            var x2 = (A + B) / C;

                            // find y values
                            var D = -b2 + a2 * b2 - b2 * h2 - ((2 * b4 * h2) / (a2 - b2));
                            var E = (2 * b2 * h * Math.Sqrt(a2 * (a2 - b2 - a2 * b2 + b4 + b2 * h2))) / (a2 - b2);
                            var F = (RoundedDouble)Math.Sqrt(a2 - b2);

                            var y1 = -Math.Sqrt(D - E) / F;
                            var y2 = (RoundedDouble)(-y1);
                            var y3 = -Math.Sqrt(D + E) / F;
                            var y4 = (RoundedDouble)(-y3);

                            results = new[] {
                                new Point(x1, y1, 0),
                                new Point(x1, y2, 0),
                                new Point(x2, y3, 0),
                                new Point(x2, y4, 0)
                            };
                        }
                        else
                        {
                            // brute-force approximate intersections
                            results = BruteForceEllipseWithUnitCircle(finalCenter, a, b);
                        }

                        results = results
                                  .Where(p => !(double.IsNaN(p.X) || double.IsNaN(p.Y) || double.IsNaN(p.Z)))
                                  .Where(p => !(double.IsInfinity(p.X) || double.IsInfinity(p.Y) || double.IsInfinity(p.Z)))
                                  .Distinct()
                                  .Select(p => fromUnit.Transform(p))
                                  .Select(p => new Point((RoundedDouble)p.X, (RoundedDouble)p.Y, (RoundedDouble)p.Z));
                    }
                }
                else
                {
                    // parallel with no intersections
                    results = empty;
                }
            }
            else
            {
                // intersection was a line
                // find a common point to complete the line then intersect that line with the circles
                double x = 0, y = 0, z = 0;
                var    n = first.Normal;
                var    m = second.Normal;
                var    q = first.Center;
                var    r = second.Center;
                if (Math.Abs(lineVector.X) >= MathHelper.Epsilon)
                {
                    x = 0.0;
                    y = (-m.Z * n.X * q.X - m.Z * n.Y * q.Y - m.Z * n.Z * q.Z + m.X * n.Z * r.X + m.Y * n.Z * r.Y + m.Z * n.Z * r.Z)
                        / (-m.Z * n.Y + m.Y * n.Z);
                    z = (-m.Y * n.X * q.X - m.Y * n.Y * q.Y - m.Y * n.Z * q.Z + m.X * n.Y * r.X + m.Y * n.Y * r.Y + m.Z * n.Y * r.Z)
                        / (-m.Z * n.Y + m.Y * n.Z);
                }
                else if (Math.Abs(lineVector.Y) >= MathHelper.Epsilon)
                {
                    x = (-m.Z * n.X * q.X - m.Z * n.Y * q.Y - m.Z * n.Z * q.Z + m.X * n.Z * r.X + m.Y * n.Z * r.Y + m.Z * n.Z * r.Z)
                        / (-m.Z * n.X + m.X * n.Z);
                    y = 0.0;
                    z = (-m.X * n.X * q.X - m.X * n.Y * q.Y - m.X * n.Z * q.Z + m.X * n.X * r.X + m.Y * n.X * r.Y + m.Z * n.X * r.Z)
                        / (-m.Z * n.X + m.X * n.Z);
                }
                else if (Math.Abs(lineVector.Z) >= MathHelper.Epsilon)
                {
                    x = (-m.Y * n.X * q.X - m.Y * n.Y * q.Y - m.Y * n.Z * q.Z + m.X * n.Y * r.X + m.Y * n.Y * r.Y + m.Z * n.Y * r.Z)
                        / (m.Y * n.X - m.X * n.Y);
                    y = (-m.X * n.X * q.X - m.X * n.Y * q.Y - m.X * n.Z * q.Z + m.X * n.X * r.X + m.Y * n.X * r.Y + m.Z * n.X * r.Z)
                        / (m.Y * n.X - m.X * n.Y);
                    z = 0.0;
                }
                else
                {
                    Debug.Assert(false, "zero-vector shouldn't get here");
                }

                var point              = new Point(x, y, z);
                var other              = point + lineVector;
                var intersectionLine   = new PrimitiveLine(point, other);
                var firstIntersections = intersectionLine.IntersectionPoints(first, false)
                                         .Select(p => new Point((RoundedDouble)p.X, (RoundedDouble)p.Y, (RoundedDouble)p.Z));
                var secondIntersections = intersectionLine.IntersectionPoints(second, false)
                                          .Select(p => new Point((RoundedDouble)p.X, (RoundedDouble)p.Y, (RoundedDouble)p.Z));
                results = firstIntersections
                          .Union(secondIntersections)
                          .Distinct();
            }

            // verify points are in angle bounds
            if (withinBounds)
            {
                var toFirstUnit  = first.FromUnitCircle.Inverse();
                var toSecondUnit = second.FromUnitCircle.Inverse();
                results = from res in results
                          // verify point is within first ellipse's angles
                          let trans1                       = toFirstUnit.Transform(res)
                                                  let ang1 = ((Vector)trans1).ToAngle()
                                                             where first.IsAngleContained(ang1)
                                                             // and same for second
                                                             let trans2                       = toSecondUnit.Transform(res)
                                                                                     let ang2 = ((Vector)trans2).ToAngle()
                                                                                                where second.IsAngleContained(ang2)
                                                                                                select res;
            }

            return(results);
        }
Exemplo n.º 27
0
        public async Task <bool> Execute(IWorkspace workspace, object arg)
        {
            Entity circle       = null;
            var    drawingPlane = workspace.DrawingPlane;

            var cen = await workspace.InputService.GetPoint(new UserDirective("Select center, [ttr], or [th]ree-point", "ttr", "th"));

            if (cen.Cancel)
            {
                return(false);
            }
            if (cen.HasValue)
            {
                var mode = CircleMode.Radius;
                while (circle == null)
                {
                    switch (mode)
                    {
                    case CircleMode.Radius:
                    {
                        var rad = await workspace.InputService.GetPoint(new UserDirective("Enter radius or [d]iameter/[i]sometric", "d", "i"), (p) =>
                            {
                                return(new IPrimitive[]
                                {
                                    new PrimitiveLine(cen.Value, p),
                                    new PrimitiveEllipse(cen.Value, (p - cen.Value).Length, drawingPlane.Normal)
                                });
                            });

                        if (rad.Cancel)
                        {
                            return(false);
                        }
                        if (rad.HasValue)
                        {
                            circle = new Circle(cen.Value, (rad.Value - cen.Value).Length, drawingPlane.Normal);
                        }
                        else         // switch modes
                        {
                            if (rad.Directive == null)
                            {
                                return(false);
                            }

                            switch (rad.Directive)
                            {
                            case "d":
                                mode = CircleMode.Diameter;
                                break;

                            case "i":
                                mode = CircleMode.Isometric;
                                break;
                            }
                        }

                        break;
                    }

                    case CircleMode.Diameter:
                    {
                        var dia = await workspace.InputService.GetPoint(new UserDirective("Enter diameter or [r]adius/[i]sometric", "r", "i"), (p) =>
                            {
                                return(new IPrimitive[]
                                {
                                    new PrimitiveLine(cen.Value, p),
                                    new PrimitiveEllipse(cen.Value, (p - cen.Value).Length, drawingPlane.Normal)
                                });
                            });

                        if (dia.Cancel)
                        {
                            return(false);
                        }
                        if (dia.HasValue)
                        {
                            circle = new Circle(cen.Value, (dia.Value - cen.Value).Length * 0.5, drawingPlane.Normal);
                        }
                        else         // switch modes
                        {
                            if (dia.Directive == null)
                            {
                                return(false);
                            }

                            switch (dia.Directive)
                            {
                            case "r":
                                mode = CircleMode.Radius;
                                break;

                            case "i":
                                mode = CircleMode.Isometric;
                                break;
                            }
                        }

                        break;
                    }

                    case CircleMode.Isometric:
                    {
                        var isoRad = await workspace.InputService.GetPoint(new UserDirective("Enter isometric-radius or [r]adius/[d]iameter", "r", "d"), (p) =>
                            {
                                return(new IPrimitive[]
                                {
                                    new PrimitiveLine(cen.Value, p),
                                    new PrimitiveEllipse(cen.Value,
                                                         Vector.SixtyDegrees * (p - cen.Value).Length *MathHelper.SqrtThreeHalves,
                                                         drawingPlane.Normal,
                                                         IsoMinorRatio,
                                                         0.0,
                                                         360.0)
                                });
                            });

                        if (isoRad.Cancel)
                        {
                            return(false);
                        }
                        if (isoRad.HasValue)
                        {
                            circle = new Ellipse(cen.Value,
                                                 Vector.SixtyDegrees * (isoRad.Value - cen.Value).Length * MathHelper.SqrtThreeHalves,
                                                 IsoMinorRatio,
                                                 0.0,
                                                 360.0,
                                                 drawingPlane.Normal);
                        }
                        else         // switch modes
                        {
                            if (isoRad.Directive == null)
                            {
                                return(false);
                            }

                            switch (isoRad.Directive)
                            {
                            case "r":
                                mode = CircleMode.Radius;
                                break;

                            case "d":
                                mode = CircleMode.Diameter;
                                break;
                            }
                        }

                        break;
                    }
                    }
                }
            }
            else
            {
                switch (cen.Directive)
                {
                case "ttr":
                    var firstEntity = await workspace.InputService.GetEntity(new UserDirective("First entity"));

                    if (firstEntity.Cancel || !firstEntity.HasValue)
                    {
                        break;
                    }
                    var secondEntity = await workspace.InputService.GetEntity(new UserDirective("Second entity"));

                    if (secondEntity.Cancel || !secondEntity.HasValue)
                    {
                        break;
                    }
                    var radius = await workspace.InputService.GetDistance();

                    var ellipse = EditUtilities.Ttr(drawingPlane, firstEntity.Value, secondEntity.Value, radius.Value);
                    if (ellipse != null)
                    {
                        circle = ellipse.ToEntity();
                    }
                    break;

                case "2":
                    break;

                case "th":
                    var first = await workspace.InputService.GetPoint(new UserDirective("First point"));

                    if (first.Cancel || !first.HasValue)
                    {
                        break;
                    }
                    var second = await workspace.InputService.GetPoint(new UserDirective("Second point"), p =>
                                                                       new[]
                    {
                        new PrimitiveLine(first.Value, p)
                    });

                    if (second.Cancel || !second.HasValue)
                    {
                        break;
                    }
                    var third = await workspace.InputService.GetPoint(new UserDirective("Third point"), p =>
                    {
                        var c = PrimitiveEllipse.ThreePointCircle(first.Value, second.Value, p);
                        if (c == null)
                        {
                            return new IPrimitive[]
                            {
                                new PrimitiveLine(first.Value, second.Value),
                                new PrimitiveLine(second.Value, p),
                                new PrimitiveLine(p, first.Value)
                            }
                        }
                        ;
                        else
                        {
                            return new IPrimitive[]
                            {
                                new PrimitiveLine(first.Value, second.Value),
                                new PrimitiveLine(second.Value, p),
                                new PrimitiveLine(p, first.Value),
                                c
                            }
                        };
                    });

                    if (third.Cancel || !third.HasValue)
                    {
                        break;
                    }
                    var circ = PrimitiveEllipse.ThreePointCircle(first.Value, second.Value, third.Value);
                    if (circ != null)
                    {
                        circle = new Circle(circ.Center, circ.MajorAxis.Length, circ.Normal);
                    }
                    break;
                }
            }

            if (circle != null)
            {
                workspace.AddToCurrentLayer(circle);
            }

            return(true);
        }
Exemplo n.º 28
0
        private Shape CreatePrimitiveEllipse(PrimitiveEllipse ellipse, CadColor?color)
        {
            // rendering zero-radius ellipses (and arcs/circles) can cause the WPF layout engine to throw
            if (ellipse.MajorAxis.LengthSquared == 0.0)
            {
                return(null);
            }

            // find axis endpoints
            var projected = ProjectionHelper.Project(ellipse, PlaneProjection);
            var radiusX   = projected.MajorAxis.Length;
            var radiusY   = radiusX * projected.MinorAxisRatio;

            Shape shape;

            if (projected.StartAngle == 0.0 && projected.EndAngle == 360.0)
            {
                // full circle
                shape = new Shapes.Ellipse()
                {
                    Width = radiusX * 2.0, Height = radiusY * 2.0
                };
                shape.RenderTransform = new RotateTransform()
                {
                    Angle   = Math.Atan2(projected.MajorAxis.Y, projected.MajorAxis.X) * MathHelper.RadiansToDegrees,
                    CenterX = radiusX,
                    CenterY = radiusY
                };
                Canvas.SetLeft(shape, projected.Center.X - radiusX);
                Canvas.SetTop(shape, projected.Center.Y - radiusY);
            }
            else
            {
                // arc
                var endAngle = ellipse.EndAngle;
                if (endAngle < ellipse.StartAngle)
                {
                    endAngle += 360.0;
                }
                var startPoint = projected.StartPoint();
                var endPoint   = projected.EndPoint();
                shape = new Path()
                {
                    Data = new GeometryGroup()
                    {
                        Children = new GeometryCollection()
                        {
                            new PathGeometry()
                            {
                                Figures = new PathFigureCollection()
                                {
                                    new PathFigure()
                                    {
                                        StartPoint = new DisplayPoint(startPoint.X, startPoint.Y),
                                        Segments   = new PathSegmentCollection()
                                        {
                                            new ArcSegment()
                                            {
                                                IsLargeArc     = (endAngle - ellipse.StartAngle) > 180.0,
                                                Point          = new DisplayPoint(endPoint.X, endPoint.Y),
                                                SweepDirection = SweepDirection.Clockwise,
                                                RotationAngle  = Math.Atan2(projected.MajorAxis.Y, projected.MajorAxis.X) * MathHelper.RadiansToDegrees,
                                                Size           = new DisplaySize(radiusX, radiusY)
                                            }
                                        }
                                    },
                                }
                            }
                        }
                    }
                };
            }

            SetThicknessBinding(shape);
            SetColor(shape, color);
            return(shape);
        }
Exemplo n.º 29
0
        public static IPrimitive Offset(Plane drawingPlane, IPrimitive primitive, Point offsetDirection, double offsetDistance)
        {
            if (!drawingPlane.Contains(offsetDirection))
            {
                return(null);
            }

            IPrimitive result;

            switch (primitive.Kind)
            {
            case PrimitiveKind.Ellipse:
                var el          = (PrimitiveEllipse)primitive;
                var projection  = el.FromUnitCircle.Inverse();
                var isInside    = projection.Transform((Vector)offsetDirection).LengthSquared <= 1.0;
                var majorLength = el.MajorAxis.Length;
                if (isInside && (offsetDistance > majorLength * el.MinorAxisRatio) ||
                    (offsetDistance >= majorLength))
                {
                    result = null;
                }
                else
                {
                    Vector newMajor;
                    if (isInside)
                    {
                        newMajor = el.MajorAxis.Normalize() * (majorLength - offsetDistance);
                    }
                    else
                    {
                        newMajor = el.MajorAxis.Normalize() * (majorLength + offsetDistance);
                    }
                    result = new PrimitiveEllipse(
                        center: el.Center,
                        majorAxis: newMajor,
                        normal: el.Normal,
                        minorAxisRatio: el.MinorAxisRatio,
                        startAngle: el.StartAngle,
                        endAngle: el.EndAngle,
                        color: el.Color);
                }
                break;

            case PrimitiveKind.Line:
                // find what side the offset occured on and move both end points
                var line = (PrimitiveLine)primitive;
                // normalize to XY plane
                var picked        = drawingPlane.ToXYPlane(offsetDirection);
                var p1            = drawingPlane.ToXYPlane(line.P1);
                var p2            = drawingPlane.ToXYPlane(line.P2);
                var pline         = new PrimitiveLine(p1, p2);
                var perpendicular = new PrimitiveLine(picked, pline.PerpendicularSlope());
                var intersection  = pline.IntersectionPoint(perpendicular, false);
                if (intersection.HasValue && intersection.Value != picked)
                {
                    var offsetVector = (picked - intersection.Value).Normalize() * offsetDistance;
                    offsetVector = drawingPlane.FromXYPlane(offsetVector);
                    result       = new PrimitiveLine(
                        p1: line.P1 + offsetVector,
                        p2: line.P2 + offsetVector,
                        color: line.Color);
                }
                else
                {
                    // the selected point was directly on the line
                    result = null;
                }
                break;

            case PrimitiveKind.Point:
                var point             = (PrimitivePoint)primitive;
                var pointOffsetVector = (offsetDirection - point.Location).Normalize() * offsetDistance;
                result = new PrimitivePoint(point.Location + pointOffsetVector, point.Color);
                break;

            case PrimitiveKind.Text:
                result = null;
                break;

            default:
                throw new ArgumentException("primitive.Kind");
            }

            return(result);
        }
Exemplo n.º 30
0
 public static IEnumerable <Point> GetProjectedVerticies(this PrimitiveEllipse ellipse, Matrix4 transformationMatrix, int maxSeg)
 {
     return(ellipse.GetInterestingPoints(maxSeg)
            .Select(p => transformationMatrix.Transform(p)));
 }