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); }
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); }
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); }
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); } }
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); }
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); } }
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); }
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; } }