Beispiel #1
0
        /// <summary>
        /// Approximate the given Bezier curve as lines and arcs.
        /// </summary>
        internal static IPrimitive[] AsSimplePrimitives(PrimitiveBezier bezier)
        {
            var simplePrimitives = new List <IPrimitive>();
            var intervals        = new Queue <Tuple <double, double, int> >();

            intervals.Enqueue(Tuple.Create(0.0, 1.0, 0));
            while (intervals.Count > 0)
            {
                var interval          = intervals.Dequeue();
                var intervalStart     = interval.Item1;
                var intervalEnd       = interval.Item2;
                var currentSplitCount = interval.Item3;
                var intervalSpread    = intervalEnd - intervalStart;
                var intervalMid       = intervalStart + (intervalSpread * 0.5);
                var pStart            = bezier.ComputeParameterizedPoint(intervalStart);
                var pMid               = bezier.ComputeParameterizedPoint(intervalMid);
                var pEnd               = bezier.ComputeParameterizedPoint(intervalEnd);
                var intervalLine       = new PrimitiveLine(pStart, pEnd);
                var candidatePrimitive = intervalLine.IsPointOnPrimitive(pMid, MathHelper.BezierEpsilon)
                    ? (IPrimitive)intervalLine
                    : PrimitiveEllipse.ThreePointArc(pStart, pMid, pEnd, idealNormal: Vector.ZAxis);
                candidatePrimitive = candidatePrimitive ?? intervalLine; // ensure it has a value

                var intervalFirstQuarter = intervalStart + (intervalSpread * 0.25);
                var intervalThirdQuarter = intervalStart + (intervalSpread * 0.75);
                var pFirstQuarter        = bezier.ComputeParameterizedPoint(intervalFirstQuarter);
                var pThirdQuarter        = bezier.ComputeParameterizedPoint(intervalThirdQuarter);
                if (currentSplitCount >= MaximumPrimitiveSplitCount ||
                    (candidatePrimitive.IsPointOnPrimitive(pFirstQuarter, MathHelper.BezierEpsilon) &&
                     candidatePrimitive.IsPointOnPrimitive(pThirdQuarter, MathHelper.BezierEpsilon)))
                {
                    simplePrimitives.Add(candidatePrimitive);
                }
                else
                {
                    intervals.Enqueue(Tuple.Create(intervalStart, intervalMid, currentSplitCount + 1));
                    intervals.Enqueue(Tuple.Create(intervalMid, intervalEnd, currentSplitCount + 1));
                }
            }

            return(simplePrimitives.ToArray());
        }
Beispiel #2
0
        /// <summary>
        /// Creates a circle that passes through the three specified points.  Null if the points are co-linear
        /// </summary>
        /// <param name="a">The first point.</param>
        /// <param name="b">The second point.</param>
        /// <param name="c">The third point.</param>
        /// <param name="idealNormal">The ideal normal to normalize to if specified.</param>
        /// <returns>The resultant circle or null.</returns>
        public static PrimitiveEllipse ThreePointCircle(Point a, Point b, Point c, Optional <Vector> idealNormal = default(Optional <Vector>))
        {
            var v1 = a - b;
            var v2 = c - b;

            var normal = v1.Cross(v2);

            if (normal.IsZeroVector)
            {
                return(null);
            }

            normal = normal.Normalize();

            var m1 = v1.Cross(normal);
            var m2 = v2.Cross(normal);

            var b1a = (a + b) / 2.0;
            var b2a = (c + b) / 2.0;

            var b1 = new PrimitiveLine(b1a, b1a + m1);
            var b2 = new PrimitiveLine(b2a, b2a + m2);

            var center = b1.IntersectionPoint(b2, false);

            if (center == null)
            {
                return(null);
            }

            if (idealNormal.HasValue && idealNormal.Value == normal * -1.0)
            {
                normal = idealNormal.Value;
            }

            return(new PrimitiveEllipse(center.GetValueOrDefault(), (a - center.GetValueOrDefault()).Length, normal));
        }