public static Matrix GetMatrixFromTransform(GeneralTransform generalTransform)
        {
            Transform transform = generalTransform as Transform;

            if (transform != null)
            {
                return(transform.Value);
            }
            GeneralTransformGroup generalTransformGroup = generalTransform as GeneralTransformGroup;

            if (generalTransformGroup != null)
            {
                Matrix identity = Matrix.Identity;
                foreach (GeneralTransform generalTransform1 in generalTransformGroup.Children)
                {
                    identity *= VectorUtilities.GetMatrixFromTransform(generalTransform1);
                }
                return(identity);
            }
            if (generalTransform == null)
            {
                throw new InvalidOperationException(StringTable.GeneralTransformIsNotAffineException);
            }
            return(Matrix.Identity);
        }
Exemple #2
0
        private void SetupCollinearHandlesConstraint(int index, bool enforceConstraint)
        {
            PathFigureEditor pathFigureEditor = new PathFigureEditor(this.figure);

            if (!pathFigureEditor.HasDownstreamBezierHandleNeighbor(index) || !pathFigureEditor.HasUpstreamBezierHandleNeighbor(index))
            {
                return;
            }
            Point  point = pathFigureEditor.GetPoint(index);
            Vector a     = pathFigureEditor.GetPoint(index - 1) - point;
            Vector b     = pathFigureEditor.GetPoint(index + 1) - point;

            if (!enforceConstraint || VectorUtilities.HaveOppositeDirections(a, b))
            {
                return;
            }
            double length1 = a.Length;
            double length2 = b.Length;

            if (length1 > length2)
            {
                a.Normalize();
                b = -a * length2;
                pathFigureEditor.SetPoint(index + 1, point + b);
            }
            else
            {
                b.Normalize();
                Vector vector = -b * length1;
                pathFigureEditor.SetPoint(index - 1, point - vector);
            }
        }
 private static void DoCubicMidpointSubdivision(Point[] controlPoints, uint depth, double inverseErrorTolerance, List <Point> resultPolyline)
 {
     Point[] controlPoints1 = new Point[4]
     {
         controlPoints[0],
         controlPoints[1],
         controlPoints[2],
         controlPoints[3]
     };
     Point[] controlPoints2 = new Point[4];
     controlPoints2[3] = controlPoints1[3];
     controlPoints1[3] = VectorUtilities.Midpoint(controlPoints1[3], controlPoints1[2]);
     controlPoints1[2] = VectorUtilities.Midpoint(controlPoints1[2], controlPoints1[1]);
     controlPoints1[1] = VectorUtilities.Midpoint(controlPoints1[1], controlPoints1[0]);
     controlPoints2[2] = controlPoints1[3];
     controlPoints1[3] = VectorUtilities.Midpoint(controlPoints1[3], controlPoints1[2]);
     controlPoints1[2] = VectorUtilities.Midpoint(controlPoints1[2], controlPoints1[1]);
     controlPoints2[1] = controlPoints1[3];
     controlPoints1[3] = VectorUtilities.Midpoint(controlPoints1[3], controlPoints1[2]);
     controlPoints2[0] = controlPoints1[3];
     --depth;
     if (depth > 0U)
     {
         BezierCurveFlattener.DoCubicMidpointSubdivision(controlPoints1, depth, inverseErrorTolerance, resultPolyline);
         resultPolyline.Add(controlPoints2[0]);
         BezierCurveFlattener.DoCubicMidpointSubdivision(controlPoints2, depth, inverseErrorTolerance, resultPolyline);
     }
     else
     {
         BezierCurveFlattener.DoCubicForwardDifferencing(controlPoints1, inverseErrorTolerance, resultPolyline);
         resultPolyline.Add(controlPoints2[0]);
         BezierCurveFlattener.DoCubicForwardDifferencing(controlPoints2, inverseErrorTolerance, resultPolyline);
     }
 }
        internal static bool ArePolylinesClose(List <Point> p, double[] lengthP, int firstP, int lastP, List <Point> q, double[] lengthQ, int firstQ, int lastQ, double distanceTolerance, ref int firstBadVertexInQ)
        {
            double num1   = distanceTolerance * distanceTolerance;
            int    index1 = firstP;
            double num2   = lengthP[firstP];
            double num3   = lengthQ[firstQ];

            for (int index2 = firstQ + 1; index2 < lastQ; ++index2)
            {
                while (index1 <= lastP && lengthQ[index2] - num3 > lengthP[index1] - num2)
                {
                    ++index1;
                }
                if (index1 > lastP)
                {
                    for (int index3 = index2; index3 < lastQ; ++index3)
                    {
                        if (VectorUtilities.SquaredDistance(p[lastP], q[index3]) > num1)
                        {
                            firstBadVertexInQ = index3;
                            return(false);
                        }
                    }
                    return(true);
                }
                Vector vector = (p[index1] - p[index1 - 1]) * ((lengthQ[index2] - num3 - lengthP[index1 - 1] + num2) / (lengthP[index1] - lengthP[index1 - 1]));
                if (VectorUtilities.SquaredDistance(p[index1 - 1] + vector, q[index2]) > num1)
                {
                    firstBadVertexInQ = index2;
                    return(false);
                }
            }
            return(true);
        }
 public static void FlattenQuadratic(Point[] controlPoints, double errorTolerance, List <Point> resultPolyline, bool connect)
 {
     BezierCurveFlattener.FlattenCubic(new Point[4]
     {
         controlPoints[0],
         VectorUtilities.WeightedAverage(controlPoints[0], controlPoints[1], 2.0 / 3.0),
         VectorUtilities.WeightedAverage(controlPoints[1], controlPoints[2], 1.0 / 3.0),
         controlPoints[2]
     }, errorTolerance, resultPolyline, connect);
 }
        public static bool IsCloseSegmentDegenerate(PathFigure figure)
        {
            if (figure.Segments.Count == 0)
            {
                return(false);
            }
            Point lastPoint = PathSegmentUtilities.GetLastPoint(figure.Segments[figure.Segments.Count - 1]);

            return(VectorUtilities.ArePathPointsVeryClose(PathFigureUtilities.FirstPoint(figure), lastPoint));
        }
        public void Add(Point pt, long time)
        {
            if (this.current.points.Count > 0 && VectorUtilities.ArePathPointsVeryClose(this.current.points[this.current.points.Count - 1], pt))
            {
                return;
            }
            this.current.points.Add(pt);
            int count = this.current.points.Count;

            if (count >= 3)
            {
                this.current.endTangent.X = 0.0;
                this.current.endTangent.Y = 0.0;
                for (int index = Math.Max(0, count - 6); index < count - 1; ++index)
                {
                    this.current.endTangent += (this.current.points[count - 1] - this.current.points[index]) / (double)(count - 1 - Math.Max(0, count - 6));
                }
                if (this.IsSamplePointACorner(this.current.points[count - 3], this.current.points[count - 2], this.current.points[count - 1], Math.Cos(2.0 * Math.PI * (this.cornerTolerance / 360.0))))
                {
                    this.current.points.RemoveAt(this.current.points.Count - 1);
                    this.current.endTangent = new Vector(0.0, 0.0);
                    this.FitSegments(new PathGeometryEditor(this.path), this.current);
                    this.current.cornerSegment = true;
                    this.current.prevBezier    = (IncrementalFitter.IncrementalFittingData)null;
                    this.current.points.Clear();
                    this.current.points.Add(pt);
                }
            }
            if (this.current.points.Count < 4)
            {
                return;
            }
            Point[] bezierFit1 = this.ComputeBezierFit(this.current);
            if (this.ComputeMaxError(this.current.points, bezierFit1) <= this.curveTolerance)
            {
                return;
            }
            if (this.current.prevBezier != null)
            {
                PathGeometryEditor pathGeometryEditor = new PathGeometryEditor(this.path);
                Point[]            bezierFit2         = this.ComputeBezierFit(this.current.prevBezier);
                if (PathGeometryUtilities.IsEmpty(pathGeometryEditor.PathGeometry))
                {
                    pathGeometryEditor.StartFigure(bezierFit2[0]);
                }
                pathGeometryEditor.AppendCubicBezier(bezierFit2[1], bezierFit2[2], bezierFit2[3]);
            }
            this.current.prevBezier            = (IncrementalFitter.IncrementalFittingData) this.current.Clone();
            this.current.prevBezier.prevBezier = (IncrementalFitter.IncrementalFittingData)null;
            this.current.cornerSegment         = false;
            this.current.startTangent          = bezierFit1[2] - bezierFit1[3];
            this.current.startTangent.Normalize();
            this.current.points.Clear();
            this.current.points.Add(pt);
        }
        private Point[] ComputeFitWithEndTangent(List <Point> points, Vector tangent)
        {
            if (points.Count < 4)
            {
                return(new Point[4]);
            }
            double[] parameterization = this.ComputeParameterization(points);
            Point[]  pointArray       = new Point[4];
            pointArray[3] = points[0];
            pointArray[0] = points[points.Count - 1];
            double num1 = 0.0;
            double num2 = 0.0;
            double num3 = 0.0;
            double num4 = 0.0;
            double num5 = 0.0;
            double num6 = 0.0;
            double num7 = 0.0;

            for (int index = 1; index < parameterization.Length - 1; ++index)
            {
                double num8  = 1.0 - parameterization[index];
                double num9  = num8 * num8 * num8;
                double num10 = 3.0 * num8 * num8 * parameterization[index];
                double num11 = 3.0 * num8 * parameterization[index] * parameterization[index];
                double num12 = parameterization[index] * parameterization[index] * parameterization[index];
                num1 += num11 * num11;
                num4 += num10 * num10;
                num2 += num11 * num10;
                num3 += num10 * num11;
                num5 += ((points[index].X - pointArray[0].X * (num12 + num11) - pointArray[3].X * num9) * tangent.X + (points[index].Y - pointArray[0].Y * (num12 + num11) - pointArray[3].Y * num9) * tangent.Y) * num11;
                num6 += (points[index].X - pointArray[0].X * (num12 + num11) - pointArray[3].X * num9) * num10;
                num7 += (points[index].Y - pointArray[0].Y * (num12 + num11) - pointArray[3].Y * num9) * num10;
            }
            double num13 = num1 * VectorUtilities.Dot(tangent, tangent);
            double num14 = num2 * tangent.X;
            double num15 = num3 * tangent.Y;
            double num16 = num13 - num15 * (num15 / num4) - num14 * (num14 / num4);
            double num17 = (num5 - num7 * (num15 / num4) - num6 * (num14 / num4)) / num16;
            double num18 = (num6 - num17 * num14) / num4;
            double num19 = (num7 - num17 * num15) / num4;

            pointArray[2].X = pointArray[0].X + tangent.X * num17;
            pointArray[2].Y = pointArray[0].Y + tangent.Y * num17;
            pointArray[1].X = num18;
            pointArray[1].Y = num19;
            pointArray[0]   = points[0];
            pointArray[3]   = points[points.Count - 1];
            return(pointArray);
        }
        private Point[] ComputeFitWithTwoTangents(List <Point> points, Vector start, Vector end)
        {
            if (points.Count < 4)
            {
                return(new Point[4]);
            }
            double[] parameterization = this.ComputeParameterization(points);
            Point[]  pointArray       = new Point[4];
            pointArray[0] = points[0];
            pointArray[3] = points[points.Count - 1];
            double num1;
            double num2;

            if (Math.Abs(start.X) == Math.Abs(end.X) && Math.Abs(start.Y) == Math.Abs(end.Y))
            {
                num1 = 1.0 / 3.0;
                num2 = 2.0 / 3.0;
            }
            else
            {
                double num3 = 0.0;
                double num4 = 0.0;
                double num5 = 0.0;
                double num6 = 0.0;
                double num7 = 0.0;
                for (int index = 1; index < parameterization.Length - 1; ++index)
                {
                    double num8  = 1.0 - parameterization[index];
                    double num9  = num8 * num8 * num8;
                    double num10 = 3.0 * num8 * num8 * parameterization[index];
                    double num11 = 3.0 * num8 * parameterization[index] * parameterization[index];
                    double num12 = parameterization[index] * parameterization[index] * parameterization[index];
                    num3 += VectorUtilities.Dot(start, start) * num10 * num10;
                    num4 += VectorUtilities.Dot(start, end) * num10 * num11;
                    num5 += VectorUtilities.Dot(end, end) * num11 * num11;
                    num6 += ((points[index].X - pointArray[0].X * (num9 + num10) - pointArray[3].X * (num11 + num12)) * start.X + (points[index].Y - pointArray[0].Y * (num9 + num10) - pointArray[3].Y * (num11 + num12)) * start.Y) * num10;
                    num7 += ((points[index].X - pointArray[0].X * (num9 + num10) - pointArray[3].X * (num11 + num12)) * end.X + (points[index].Y - pointArray[0].Y * (num9 + num10) - pointArray[3].Y * (num11 + num12)) * end.Y) * num11;
                }
                double num13 = num3 * num5 - num4 * num4;
                num1 = (num6 * num5 - num7 * num4) / num13;
                num2 = (num7 * num3 - num6 * num4) / num13;
            }
            pointArray[1].X = pointArray[0].X + start.X * num1;
            pointArray[1].Y = pointArray[0].Y + start.Y * num1;
            pointArray[2].X = pointArray[3].X + end.X * num2;
            pointArray[2].Y = pointArray[3].Y + end.Y * num2;
            return(pointArray);
        }
        private double[] ComputeParameterization(List <Point> points)
        {
            double[] numArray = new double[points.Count];
            numArray[0] = 0.0;
            for (int index = 1; index < points.Count; ++index)
            {
                numArray[index] = numArray[index - 1] + VectorUtilities.Distance(points[index - 1], points[index]);
            }
            double num = numArray[numArray.Length - 1];

            for (int index = 0; index < numArray.Length; ++index)
            {
                numArray[index] /= num;
            }
            return(numArray);
        }
        public static bool CompareAlgorithmsOnChordMonotoneCubic(Point[] controlPoints, double errorTolerance)
        {
            if (!BezierCurveFlattener.IsCubicChordMonotone(controlPoints, errorTolerance * errorTolerance))
            {
                return(false);
            }
            List <Point> list1 = new List <Point>(16);
            List <Point> list2 = new List <Point>(16);

            list1.Add(controlPoints[0]);
            list2.Add(controlPoints[0]);
            double x     = controlPoints[3].X - controlPoints[2].X + controlPoints[1].X - controlPoints[0].X;
            double y     = controlPoints[3].Y - controlPoints[2].Y + controlPoints[1].Y - controlPoints[0].Y;
            double num   = 1.0 / errorTolerance;
            uint   depth = BezierCurveFlattener.Log8UnsignedInt32((uint)(FloatingPointArithmetic.Hypotenuse(x, y) * num + 0.5));

            if (depth > 0U)
            {
                --depth;
            }
            if (depth > 0U)
            {
                BezierCurveFlattener.DoCubicMidpointSubdivision(controlPoints, depth, 0.75 * num, list1);
            }
            else
            {
                BezierCurveFlattener.DoCubicForwardDifferencing(controlPoints, 0.75 * num, list1);
            }
            BezierCurveFlattener.AdaptiveForwardDifferencingCubicFlattener differencingCubicFlattener = new BezierCurveFlattener.AdaptiveForwardDifferencingCubicFlattener(controlPoints, errorTolerance, errorTolerance, false);
            Point p = new Point();

            while (differencingCubicFlattener.Next(ref p))
            {
                list2.Add(p);
            }
            list1.Add(controlPoints[3]);
            list2.Add(controlPoints[3]);
            double[] cumulatedChordLength1 = VectorUtilities.GetCumulatedChordLength(list1, 0, list1.Count - 1);
            double[] cumulatedChordLength2 = VectorUtilities.GetCumulatedChordLength(list2, 0, list2.Count - 1);
            int      firstBadVertexInQ     = 0;

            return(VectorUtilities.ArePolylinesClose(list1, cumulatedChordLength1, 0, list1.Count - 1, list2, cumulatedChordLength2, 0, list2.Count - 1, errorTolerance, ref firstBadVertexInQ));
        }
        private bool IsSamplePointACorner(Point start, Point corner, Point end, double cosThreshold)
        {
            Vector a   = corner - start;
            Vector b   = end - corner;
            double num = VectorUtilities.Dot(a, b);

            if (num >= 0.0)
            {
                if (cosThreshold <= 0.0)
                {
                    return(false);
                }
                return(num * num < cosThreshold * cosThreshold * a.LengthSquared * b.LengthSquared);
            }
            if (cosThreshold >= 0.0)
            {
                return(true);
            }
            return(num * num > cosThreshold * cosThreshold * a.LengthSquared * b.LengthSquared);
        }
        private double ComputeMaxError(List <Point> points, Point[] bezier)
        {
            double num1 = 0.0;

            if (bezier == null)
            {
                return(double.MaxValue);
            }
            double[] parameterization = this.ComputeParameterization(points);
            for (int index = 0; index < points.Count; ++index)
            {
                Vector vector = this.EvaluateBezier(bezier, parameterization[index]) - points[index];
                double num2   = VectorUtilities.Dot(vector, vector);
                if (num2 >= num1)
                {
                    num1 = num2;
                }
            }
            return(num1);
        }
Exemple #14
0
        private bool IsSamplePointACorner(int i, double cosThreshold)
        {
            Vector a   = this.sample[i] - this.sample[i - 1];
            Vector b   = this.sample[i + 1] - this.sample[i];
            double num = VectorUtilities.Dot(a, b);

            if (num >= 0.0)
            {
                if (cosThreshold <= 0.0)
                {
                    return(false);
                }
                return(num * num < cosThreshold * cosThreshold * a.LengthSquared * b.LengthSquared);
            }
            if (cosThreshold >= 0.0)
            {
                return(true);
            }
            return(num * num > cosThreshold * cosThreshold * a.LengthSquared * b.LengthSquared);
        }
        private static bool IsCubicChordMonotone(Point[] controlPoints, double squaredTolerance)
        {
            double num1 = VectorUtilities.SquaredDistance(controlPoints[0], controlPoints[3]);

            if (num1 <= squaredTolerance)
            {
                return(false);
            }
            Vector a    = controlPoints[3] - controlPoints[0];
            Vector b1   = controlPoints[1] - controlPoints[0];
            double num2 = VectorUtilities.Dot(a, b1);

            if (num2 < 0.0 || num2 > num1)
            {
                return(false);
            }
            Vector b2   = controlPoints[2] - controlPoints[0];
            double num3 = VectorUtilities.Dot(a, b2);

            return(num3 >= 0.0 && num3 <= num1 && num2 <= num3);
        }
Exemple #16
0
        public static double[] GetCumulatedChordLength(List <Point> points, int firstIndex, int lastIndex)
        {
            if (firstIndex > lastIndex || firstIndex < 0 || (lastIndex < 0 || firstIndex >= points.Count) || lastIndex >= points.Count)
            {
                throw new ArgumentException("The specified indices are invalid.");
            }
            double[] numArray = new double[lastIndex - firstIndex + 1];
            double   num      = 0.0;

            numArray[0] = num;
            int index1 = firstIndex + 1;
            int index2 = 1;

            while (index1 <= lastIndex)
            {
                num += VectorUtilities.Distance(points[index1 - 1], points[index1]);
                numArray[index2] = num;
                ++index1;
                ++index2;
            }
            return(numArray);
        }
        private static void DoCubicMidpointSubdivision(Point[] controlPoints, uint depth, double leftParameter, double rightParameter, double inverseErrorTolerance, List <Point> resultPolyline, List <double> resultParameters)
        {
            Point[] controlPoints1 = new Point[4]
            {
                controlPoints[0],
                controlPoints[1],
                controlPoints[2],
                controlPoints[3]
            };
            Point[] controlPoints2 = new Point[4];
            controlPoints2[3] = controlPoints1[3];
            controlPoints1[3] = VectorUtilities.Midpoint(controlPoints1[3], controlPoints1[2]);
            controlPoints1[2] = VectorUtilities.Midpoint(controlPoints1[2], controlPoints1[1]);
            controlPoints1[1] = VectorUtilities.Midpoint(controlPoints1[1], controlPoints1[0]);
            controlPoints2[2] = controlPoints1[3];
            controlPoints1[3] = VectorUtilities.Midpoint(controlPoints1[3], controlPoints1[2]);
            controlPoints1[2] = VectorUtilities.Midpoint(controlPoints1[2], controlPoints1[1]);
            controlPoints2[1] = controlPoints1[3];
            controlPoints1[3] = VectorUtilities.Midpoint(controlPoints1[3], controlPoints1[2]);
            controlPoints2[0] = controlPoints1[3];
            --depth;
            double num = (leftParameter + rightParameter) * 0.5;

            if (depth > 0U)
            {
                BezierCurveFlattener.DoCubicMidpointSubdivision(controlPoints1, depth, leftParameter, num, inverseErrorTolerance, resultPolyline, resultParameters);
                resultPolyline.Add(controlPoints2[0]);
                resultParameters.Add(num);
                BezierCurveFlattener.DoCubicMidpointSubdivision(controlPoints2, depth, num, rightParameter, inverseErrorTolerance, resultPolyline, resultParameters);
            }
            else
            {
                BezierCurveFlattener.DoCubicForwardDifferencing(controlPoints1, leftParameter, num, inverseErrorTolerance, resultPolyline, resultParameters);
                resultPolyline.Add(controlPoints2[0]);
                resultParameters.Add(num);
                BezierCurveFlattener.DoCubicForwardDifferencing(controlPoints2, num, rightParameter, inverseErrorTolerance, resultPolyline, resultParameters);
            }
        }
Exemple #18
0
        public static bool ComputeClosestPointOnTransformedLineSegment(Point point, Point a, Point b, Matrix matrix, double toleranceSquared, out double resultParameter, out Point resultPoint, out double resultDistanceSquared)
        {
            Vector a1            = (b - a) * matrix;
            Vector b1            = point - a * matrix;
            double lengthSquared = a1.LengthSquared;

            resultParameter = lengthSquared < FloatingPointArithmetic.SquaredDistanceTolerance ? 0.0 : VectorUtilities.Dot(a1, b1) / lengthSquared;
            if (resultParameter <= 0.0)
            {
                resultParameter = 0.0;
                resultPoint     = a;
            }
            else if (resultParameter >= 1.0)
            {
                resultParameter = 1.0;
                resultPoint     = b;
            }
            else
            {
                resultPoint = VectorUtilities.WeightedAverage(a, b, resultParameter);
            }
            resultDistanceSquared = (resultPoint * matrix - point).LengthSquared;
            return(resultDistanceSquared <= toleranceSquared);
        }
Exemple #19
0
        private void OpenFit2DFromTo(int first, Vector unitTangentFirst, int last, Vector unitTangentLast, bool onlyCubics)
        {
            int length = last - first + 1;
            int num1   = length - 1;
            PathFigureEditor pathFigureEditor = new PathFigureEditor(this.figure);

            if (length == 2)
            {
                if (onlyCubics)
                {
                    double num2 = VectorUtilities.Distance(this.sample[first], this.sample[last]) / 3.0;
                    Point  p1   = this.sample[first] + unitTangentFirst * num2;
                    Point  p2   = this.sample[last] - unitTangentLast * num2;
                    pathFigureEditor.CubicCurveTo(p1, p2, this.sample[last]);
                }
                else
                {
                    pathFigureEditor.LineTo(this.sample[last]);
                }
            }
            else if (length == 3)
            {
                int    index1  = first + 1;
                Vector vector1 = this.sample[first] - this.sample[index1];
                Vector vector2 = this.sample[last] - this.sample[index1];
                Vector vector3 = vector1;
                vector3.Normalize();
                Vector vector4 = vector2;
                vector4.Normalize();
                Vector vector5 = vector3 + vector4;
                Vector vector6;
                if (VectorUtilities.IsZero(vector5))
                {
                    vector6 = this.sample[last] - this.sample[first];
                    vector6.Normalize();
                }
                else
                {
                    vector6 = VectorUtilities.UnitNormal(vector5);
                }
                if (VectorUtilities.Dot(vector6, this.sample[last] - this.sample[first]) < 0.0)
                {
                    vector6 *= -1.0;
                }
                this.OpenFit2DFromTo(first, unitTangentFirst, index1, vector6, onlyCubics);
                int index2 = PathFigureUtilities.PointCount(this.figure) - 1;
                this.OpenFit2DFromTo(index1, vector6, last, unitTangentLast, onlyCubics);
                this.SetupCollinearHandlesConstraint(index2, onlyCubics);
            }
            else
            {
                double[][] numArray1 = new double[length][];
                for (int index = 0; index < length; ++index)
                {
                    numArray1[index] = new double[4];
                }
                double   num2      = 1.0 / (this.chordLength[last] - this.chordLength[first]);
                double[] numArray2 = new double[length];
                for (int index = 0; index <= num1; ++index)
                {
                    numArray2[index] = (this.chordLength[first + index] - this.chordLength[first]) * num2;
                }
                double[] numArray3 = new double[4];
                numArray3[0] = 1.0;
                for (int index1 = 0; index1 <= num1; ++index1)
                {
                    numArray3[1] = 1.0 - numArray2[index1];
                    for (int index2 = 2; index2 <= 3; ++index2)
                    {
                        numArray3[index2] = numArray3[index2 - 1] * numArray3[1];
                    }
                    numArray1[index1][0] = numArray3[3];
                    double num3   = numArray2[index1];
                    int    index3 = 1;
                    while (index3 <= 3)
                    {
                        numArray1[index1][index3] = (double)BezierCurveFitter.pascalTriangle[3][index3] * num3 * numArray3[3 - index3];
                        ++index3;
                        num3 *= numArray2[index1];
                    }
                }
                double[][] numArray4 = new double[4][];
                for (int index = 0; index < 4; ++index)
                {
                    numArray4[index] = new double[4];
                }
                for (int index1 = 0; index1 <= 3; ++index1)
                {
                    for (int index2 = 0; index2 <= index1; ++index2)
                    {
                        for (int index3 = 0; index3 <= num1; ++index3)
                        {
                            numArray4[index1][index2] += numArray1[index3][index2] * numArray1[index3][index1];
                        }
                        if (index1 != index2)
                        {
                            numArray4[index2][index1] = numArray4[index1][index2];
                        }
                    }
                }
                double[][] m = new double[2][]
                {
                    new double[2]
                    {
                        numArray4[1][1],
                        numArray4[1][2] * VectorUtilities.Dot(unitTangentFirst, unitTangentLast)
                    },
                    new double[2]
                    {
                        numArray4[1][2],
                        numArray4[2][2]
                    }
                };
                double[] v           = new double[2];
                Vector[] vectorArray = new Vector[4];
                for (int index1 = 0; index1 < 4; ++index1)
                {
                    for (int index2 = 0; index2 <= num1; ++index2)
                    {
                        vectorArray[index1].X += numArray1[index2][index1] * this.sample[index2 + first].X;
                        vectorArray[index1].Y += numArray1[index2][index1] * this.sample[index2 + first].Y;
                    }
                }
                Vector vector1 = new Vector(this.sample[first].X, this.sample[first].Y);
                Vector vector2 = new Vector(this.sample[last].X, this.sample[last].Y);
                Vector b1      = (numArray4[1][0] + numArray4[1][1]) * vector1 + (numArray4[1][2] + numArray4[1][3]) * vector2 - vectorArray[1];
                v[0] = -VectorUtilities.Dot(unitTangentFirst, b1);
                Vector b2 = (numArray4[2][0] + numArray4[2][1]) * vector1 + (numArray4[2][2] + numArray4[2][3]) * vector2 - vectorArray[2];
                v[1] = -VectorUtilities.Dot(unitTangentLast, b2);
                bool flag = BezierCurveFitter.Solve2By2LinearSystem(m, v);
                int  firstBadVertexInQ = 0;
                if (flag && v[0] > 0.0 && v[1] < 0.0)
                {
                    Point[] controlPoints = new Point[4];
                    controlPoints[0] = this.sample[first];
                    controlPoints[1] = controlPoints[0] + v[0] * unitTangentFirst;
                    controlPoints[3] = this.sample[last];
                    controlPoints[2] = controlPoints[3] + v[1] * unitTangentLast;
                    List <Point> list = new List <Point>(128);
                    BezierCurveFlattener.FlattenCubic(controlPoints, this.distanceTolerance, list, false);
                    double[] cumulatedChordLength = VectorUtilities.GetCumulatedChordLength(list, 0, list.Count - 1);
                    if (VectorUtilities.ArePolylinesClose(list, cumulatedChordLength, 0, list.Count - 1, this.sample, this.chordLength, first, last, this.distanceTolerance, ref firstBadVertexInQ))
                    {
                        pathFigureEditor.CubicCurveTo(controlPoints[1], controlPoints[2], controlPoints[3]);
                        return;
                    }
                }
                int    num4 = (first + last) / 2;
                Vector tangentVectorAtSplit = this.GetUnitTangentVectorAtSplit(num4);
                this.OpenFit2DFromTo(first, unitTangentFirst, num4, tangentVectorAtSplit, onlyCubics);
                int index4 = PathFigureUtilities.PointCount(this.figure) - 1;
                this.OpenFit2DFromTo(num4, tangentVectorAtSplit, last, unitTangentLast, onlyCubics);
                this.SetupCollinearHandlesConstraint(index4, onlyCubics);
            }
        }
Exemple #20
0
        public PathGeometry OpenFit(List <Point> input, bool inputMayContainRepeats, double cornerThreshold, double distanceTolerance, bool onlyCubics, bool enforceStartTangent, Vector startTangent, bool enforceEndTangent, Vector endTangent)
        {
            if (cornerThreshold <= 0.0 || cornerThreshold >= Math.PI)
            {
                throw new ArgumentOutOfRangeException("cornerThreshold", (object)cornerThreshold, "Corner threshold must be strictly between zero and Pi.");
            }
            if (distanceTolerance <= 0.0)
            {
                throw new ArgumentOutOfRangeException("distanceTolerance", (object)distanceTolerance, "Distance tolerance must be strictly greater than zero.");
            }
            this.enforceStartTangent = enforceStartTangent;
            this.enforceEndTangent   = enforceEndTangent;
            if (this.enforceStartTangent && startTangent.LengthSquared < FloatingPointArithmetic.SquaredDistanceTolerance && (this.enforceEndTangent && endTangent.LengthSquared < FloatingPointArithmetic.SquaredDistanceTolerance))
            {
                throw new ArgumentException(ExceptionStringTable.CannotEnforceZeroLengthTangents);
            }
            if (this.enforceEndTangent)
            {
                endTangent.Normalize();
                this.endTangent = endTangent;
            }
            if (this.enforceStartTangent)
            {
                startTangent.Normalize();
                this.startTangent = startTangent;
            }
            this.sample = input;
            if (inputMayContainRepeats && input.Count > 1)
            {
                this.sample = new List <Point>(input.Count);
                this.sample.Add(input[0]);
                for (int index = 1; index < input.Count; ++index)
                {
                    if (!VectorUtilities.ArePathPointsVeryClose(input[index], input[index - 1]))
                    {
                        this.sample.Add(input[index]);
                    }
                }
            }
            PathGeometry       path = new PathGeometry();
            PathGeometryEditor pathGeometryEditor = new PathGeometryEditor(path);

            if (this.sample.Count > 0)
            {
                pathGeometryEditor.StartFigure(this.sample[0]);
                this.figure = path.Figures[0];
            }
            PathFigureEditor pathFigureEditor = new PathFigureEditor(this.figure);

            if (this.sample.Count == 2)
            {
                if (VectorUtilities.Distance(this.sample[0], this.sample[1]) >= distanceTolerance)
                {
                    if (onlyCubics)
                    {
                        pathFigureEditor.LinearCubicCurveTo(this.sample[1]);
                    }
                    else
                    {
                        pathFigureEditor.LineTo(this.sample[1]);
                    }
                }
            }
            else if (this.sample.Count > 2)
            {
                int lastIndex = this.sample.Count - 1;
                this.chordLength       = VectorUtilities.GetCumulatedChordLength(this.sample, 0, lastIndex);
                this.distanceTolerance = distanceTolerance;
                double cosThreshold = Math.Cos(cornerThreshold);
                int    num          = 0;
                int    index        = 1;
                while (true)
                {
                    while (index >= lastIndex || this.IsSamplePointACorner(index, cosThreshold))
                    {
                        if (index == num + 1)
                        {
                            if (onlyCubics)
                            {
                                pathFigureEditor.LinearCubicCurveTo(this.sample[index]);
                            }
                            else
                            {
                                pathFigureEditor.LineTo(this.sample[index]);
                            }
                        }
                        else
                        {
                            this.OpenFit2DFromTo(num, this.GetUnitTangentVectorFirst(num), index, this.GetUnitTangentVectorLast(index), onlyCubics);
                        }
                        num = index;
                        ++index;
                        if (num >= lastIndex)
                        {
                            goto label_33;
                        }
                    }
                    ++index;
                }
            }
label_33:
            return(path);
        }
Exemple #21
0
 public static bool ComputeClosestPointOnLineSegment(Point point, Point a, Point b, double toleranceSquared, out double resultParameter, out Point resultPoint, out double resultDistanceSquared)
 {
     return(VectorUtilities.ComputeClosestPointOnTransformedLineSegment(point, a, b, Matrix.Identity, toleranceSquared, out resultParameter, out resultPoint, out resultDistanceSquared));
 }
        private static void DoCubicForwardDifferencing(Point[] controlPoints, double leftParameter, double rightParameter, double inverseErrorTolerance, List <Point> resultPolyline, List <double> resultParameters)
        {
            double num1   = controlPoints[1].X - controlPoints[0].X;
            double num2   = controlPoints[1].Y - controlPoints[0].Y;
            double num3   = controlPoints[2].X - controlPoints[1].X;
            double num4   = controlPoints[2].Y - controlPoints[1].Y;
            double num5   = controlPoints[3].X - controlPoints[2].X;
            double num6   = controlPoints[3].Y - controlPoints[2].Y;
            double num7   = num3 - num1;
            double num8   = num4 - num2;
            double num9   = num5 - num3;
            double num10  = num6 - num4;
            double num11  = num9 - num7;
            double num12  = num10 - num8;
            Vector vector = controlPoints[3] - controlPoints[0];
            double length = vector.Length;
            double num13  = length < FloatingPointArithmetic.DistanceTolerance ? Math.Max(0.0, Math.Max(VectorUtilities.Distance(controlPoints[1], controlPoints[0]), VectorUtilities.Distance(controlPoints[2], controlPoints[0]))) : Math.Max(0.0, Math.Max(Math.Abs((num7 * vector.Y - num8 * vector.X) / length), Math.Abs((num9 * vector.Y - num10 * vector.X) / length)));
            uint   num14  = 0U;

            if (num13 > 0.0)
            {
                double d = num13 * inverseErrorTolerance;
                num14 = d < (double)int.MaxValue ? BezierCurveFlattener.Log4UnsignedInt32((uint)(d + 0.5)) : BezierCurveFlattener.Log4Double(d);
            }
            int    exp1  = -(int)num14;
            int    exp2  = exp1 + exp1;
            int    exp3  = exp2 + exp1;
            double num15 = FloatingPointArithmetic.DoubleFromMantissaAndExponent(3.0 * num7, exp2);
            double num16 = FloatingPointArithmetic.DoubleFromMantissaAndExponent(3.0 * num8, exp2);
            double num17 = FloatingPointArithmetic.DoubleFromMantissaAndExponent(6.0 * num11, exp3);
            double num18 = FloatingPointArithmetic.DoubleFromMantissaAndExponent(6.0 * num12, exp3);
            double num19 = FloatingPointArithmetic.DoubleFromMantissaAndExponent(3.0 * num1, exp1) + num15 + 1.0 / 6.0 * num17;
            double num20 = FloatingPointArithmetic.DoubleFromMantissaAndExponent(3.0 * num2, exp1) + num16 + 1.0 / 6.0 * num18;
            double num21 = 2.0 * num15 + num17;
            double num22 = 2.0 * num16 + num18;
            double x     = controlPoints[0].X;
            double y     = controlPoints[0].Y;
            Point  point = new Point(0.0, 0.0);
            int    num23 = 1 << (int)num14;
            double num24 = num23 > 0 ? (rightParameter - leftParameter) / (double)num23 : 0.0;
            double num25 = leftParameter;

            for (int index = 1; index < num23; ++index)
            {
                x      += num19;
                y      += num20;
                point.X = x;
                point.Y = y;
                resultPolyline.Add(point);
                num25 += num24;
                resultParameters.Add(num25);
                num19 += num21;
                num20 += num22;
                num21 += num17;
                num22 += num18;
            }
        }