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