The Birdfont Source Code


All Repositories / birdfont.git / commitdiff – RSS feed

Remove backup files

These changes was commited to the Birdfont repository Sat, 09 May 2015 17:14:17 +0000.

Contributing

Send patches or pull requests to johan.mattsson.m@gmail.com.
Clone this repository: git clone https://github.com/johanmattssonm/birdfont.git
[Sat, 09 May 2015 17:14:17 +0000]

Updated Files

libbirdgems/FitCubic.vala~
libbirdgems/fit_cubic.c~
diff --git libbirdgems/FitCubic.vala~(deleted)
--- a/libbirdgems/FitCubic.vala~ +++ /dev/null @@ -1,4 +1,1 @@ - class FitCubic { - - }
diff --git libbirdgems/fit_cubic.c~(deleted)
--- a/libbirdgems/fit_cubic.c~ +++ /dev/null @@ -1,602 +1,1 @@ - /* - An Algorithm for Automatically Fitting Digitized Curves - by Philip J. Schneider - from "Graphics Gems", Academic Press, 1990 - Adapted to BirdFont by Johan Mattsson 2015 - */ - - /* - * EULA: The Graphics Gems code is copyright-protected. In other words, - * you cannot claim the text of the code as your own and resell it. - * Using the code is permitted in any program, product, or library, - * non-commercial or commercial. Giving credit is not required, though - * is a nice gesture. The code comes as-is, and if there are any flaws - * or problems with any Gems code, nobody involved with Gems - authors, - * editors, publishers, or webmasters - are to be held responsible. - * Basically, don't be a jerk, and remember that anything free comes - * with no guarantee. - */ - - /* fit_cubic.c */ - /* Piecewise cubic fitting code */ - - #include "GraphicsGems.h" - #include <stdio.h> - #include <malloc.h> - #include <math.h> - #include <stdio.h> - - typedef Point2 *BezierCurve; - - /* Forward declarations */ - void FitCurve(); - static void FitCubic(); - static double *Reparameterize(); - static double NewtonRaphsonRootFind(); - static Point2 BezierII(); - static double B0(), B1(), B2(), B3(); - static Vector2 ComputeLeftTangent(); - static Vector2 ComputeRightTangent(); - static Vector2 ComputeCenterTangent(); - static double ComputeMaxError(); - static double *ChordLengthParameterize(); - static BezierCurve GenerateBezier(); - static Vector2 V2AddII(); - static Vector2 V2ScaleIII(); - static Vector2 V2SubII(); - - #define MAXPOINTS 1000 /* The most points you can have */ - - int simplified_path_buffer_size = 0; - int simplified_path_size = 0; - double* simplified_path = NULL; - - /** Generates an a bezier path and returns the length of the output array. */ - int fit_bezier_curve_to_line (lines, lines_size, error, bezier_path) - double* lines, - int lines_size, - double error, - double** bezier_path /** generated Bezier curves */ - { - int i, j, n; - Point2* points - int npoints; - - npoints = lines_size / 2; - bezier_path = NULL; - - if (lines_size % 2 != 0) { - printf ("Odd number of coordinates."); - return 0; - } - - if (lines == NULL || lines_size == 0) { - printf ("No lines."); - return 0; - } - - if (simplified_path != NULL) { - printf ("Path simplification is alreading running."); - return 0; - } - - points = malloc (npoints * sizeof (Point2)); - - j = 0; - for (i = 0; i <= npoints; i++) { - points[i].x = lines[j]; - points[i].y = lines[j + 1]; - j += 2; - } - - simplified_path = malloc (4 * npoints * sizeof (double)); - simplified_path_buffer_size = 4 * npoints; - - FitCurve(points, n, error); - free (points); - - bezier_path = simplified_path; - simplified_path = NULL; - - return simplified_path_size; - } - - DrawBezierCurve(int n, Point2* curve) - { - int i; - - if (simplified_path_size + 4 > simplified_path_buffer_size) { - printf ("Out of memmory\n"); - return; - } - - if (n != 3) { - printf ("Expecting three points\n"); - } - - i = simplified_path_size; - - simplified_path[i++] = curve[0].x; - simplified_path[i++] = curve[0].y; - simplified_path[i++] = curve[1].x; - simplified_path[i++] = curve[1].y; - simplified_path[i++] = curve[2].x; - simplified_path[i++] = curve[2].y; - simplified_path[i++] = curve[3].x; - simplified_path[i++] = curve[3].y; - - simplified_path_size = i; - } - - /* - * FitCurve : - * Fit a Bezier curve to a set of digitized points - */ - void FitCurve(d, nPts, error) - Point2 *d; /* Array of digitized points */ - int nPts; /* Number of digitized points */ - double error; /* User-defined error squared */ - { - Vector2 tHat1, tHat2; /* Unit tangent vectors at endpoints */ - - tHat1 = ComputeLeftTangent(d, 0); - tHat2 = ComputeRightTangent(d, nPts - 1); - FitCubic(d, 0, nPts - 1, tHat1, tHat2, error); - } - - /* - * FitCubic : - * Fit a Bezier curve to a (sub)set of digitized points - */ - static void FitCubic(d, first, last, tHat1, tHat2, error) - Point2 *d; /* Array of digitized points */ - int first, last; /* Indices of first and last pts in region */ - Vector2 tHat1, tHat2; /* Unit tangent vectors at endpoints */ - double error; /* User-defined error squared */ - { - BezierCurve bezCurve; /*Control points of fitted Bezier curve*/ - double *u; /* Parameter values for point */ - double *uPrime; /* Improved parameter values */ - double maxError; /* Maximum fitting error */ - int splitPoint; /* Point to split point set at */ - int nPts; /* Number of points in subset */ - double iterationError; /*Error below which you try iterating */ - int maxIterations = 4; /* Max times to try iterating */ - Vector2 tHatCenter; /* Unit tangent vector at splitPoint */ - int i; - - iterationError = error * error; - nPts = last - first + 1; - - /* Use heuristic if region only has two points in it */ - if (nPts == 2) { - double dist = V2DistanceBetween2Points(&d[last], &d[first]) / 3.0; - - bezCurve = (Point2 *)malloc(4 * sizeof(Point2)); - bezCurve[0] = d[first]; - bezCurve[3] = d[last]; - V2Add(&bezCurve[0], V2Scale(&tHat1, dist), &bezCurve[1]); - V2Add(&bezCurve[3], V2Scale(&tHat2, dist), &bezCurve[2]); - DrawBezierCurve(3, bezCurve); - free((void *)bezCurve); - return; - } - - /* Parameterize points, and attempt to fit curve */ - u = ChordLengthParameterize(d, first, last); - bezCurve = GenerateBezier(d, first, last, u, tHat1, tHat2); - - /* Find max deviation of points to fitted curve */ - maxError = ComputeMaxError(d, first, last, bezCurve, u, &splitPoint); - if (maxError < error) { - DrawBezierCurve(3, bezCurve); - free((void *)u); - free((void *)bezCurve); - return; - } - - - /* If error not too large, try some reparameterization */ - /* and iteration */ - if (maxError < iterationError) { - for (i = 0; i < maxIterations; i++) { - uPrime = Reparameterize(d, first, last, u, bezCurve); - free((void *)bezCurve); - bezCurve = GenerateBezier(d, first, last, uPrime, tHat1, tHat2); - maxError = ComputeMaxError(d, first, last, - bezCurve, uPrime, &splitPoint); - if (maxError < error) { - DrawBezierCurve(3, bezCurve); - free((void *)u); - free((void *)bezCurve); - free((void *)uPrime); - return; - } - free((void *)u); - u = uPrime; - } - } - - /* Fitting failed -- split at max error point and fit recursively */ - free((void *)u); - free((void *)bezCurve); - tHatCenter = ComputeCenterTangent(d, splitPoint); - FitCubic(d, first, splitPoint, tHat1, tHatCenter, error); - V2Negate(&tHatCenter); - FitCubic(d, splitPoint, last, tHatCenter, tHat2, error); - } - - - /* - * GenerateBezier : - * Use least-squares method to find Bezier control points for region. - * - */ - static BezierCurve GenerateBezier(d, first, last, uPrime, tHat1, tHat2) - Point2 *d; /* Array of digitized points */ - int first, last; /* Indices defining region */ - double *uPrime; /* Parameter values for region */ - Vector2 tHat1, tHat2; /* Unit tangents at endpoints */ - { - int i; - Vector2 A[MAXPOINTS][2]; /* Precomputed rhs for eqn */ - int nPts; /* Number of pts in sub-curve */ - double C[2][2]; /* Matrix C */ - double X[2]; /* Matrix X */ - double det_C0_C1, /* Determinants of matrices */ - det_C0_X, - det_X_C1; - double alpha_l, /* Alpha values, left and right */ - alpha_r; - Vector2 tmp; /* Utility variable */ - BezierCurve bezCurve; /* RETURN bezier curve ctl pts */ - - bezCurve = (Point2 *)malloc(4 * sizeof(Point2)); - nPts = last - first + 1; - - - /* Compute the A's */ - for (i = 0; i < nPts; i++) { - Vector2 v1, v2; - v1 = tHat1; - v2 = tHat2; - V2Scale(&v1, B1(uPrime[i])); - V2Scale(&v2, B2(uPrime[i])); - A[i][0] = v1; - A[i][1] = v2; - } - - /* Create the C and X matrices */ - C[0][0] = 0.0; - C[0][1] = 0.0; - C[1][0] = 0.0; - C[1][1] = 0.0; - X[0] = 0.0; - X[1] = 0.0; - - for (i = 0; i < nPts; i++) { - C[0][0] += V2Dot(&A[i][0], &A[i][0]); - C[0][1] += V2Dot(&A[i][0], &A[i][1]); - /* C[1][0] += V2Dot(&A[i][0], &A[i][1]);*/ - C[1][0] = C[0][1]; - C[1][1] += V2Dot(&A[i][1], &A[i][1]); - - tmp = V2SubII(d[first + i], - V2AddII( - V2ScaleIII(d[first], B0(uPrime[i])), - V2AddII( - V2ScaleIII(d[first], B1(uPrime[i])), - V2AddII( - V2ScaleIII(d[last], B2(uPrime[i])), - V2ScaleIII(d[last], B3(uPrime[i])))))); - - - X[0] += V2Dot(&A[i][0], &tmp); - X[1] += V2Dot(&A[i][1], &tmp); - } - - /* Compute the determinants of C and X */ - det_C0_C1 = C[0][0] * C[1][1] - C[1][0] * C[0][1]; - det_C0_X = C[0][0] * X[1] - C[1][0] * X[0]; - det_X_C1 = X[0] * C[1][1] - X[1] * C[0][1]; - - /* Finally, derive alpha values */ - alpha_l = (det_C0_C1 == 0) ? 0.0 : det_X_C1 / det_C0_C1; - alpha_r = (det_C0_C1 == 0) ? 0.0 : det_C0_X / det_C0_C1; - - /* If alpha negative, use the Wu/Barsky heuristic (see text) */ - /* (if alpha is 0, you get coincident control points that lead to - * divide by zero in any subsequent NewtonRaphsonRootFind() call. */ - double segLength = V2DistanceBetween2Points(&d[last], &d[first]); - double epsilon = 1.0e-6 * segLength; - if (alpha_l < epsilon || alpha_r < epsilon) - { - /* fall back on standard (probably inaccurate) formula, and subdivide further if needed. */ - double dist = segLength / 3.0; - bezCurve[0] = d[first]; - bezCurve[3] = d[last]; - V2Add(&bezCurve[0], V2Scale(&tHat1, dist), &bezCurve[1]); - V2Add(&bezCurve[3], V2Scale(&tHat2, dist), &bezCurve[2]); - return (bezCurve); - } - - /* First and last control points of the Bezier curve are */ - /* positioned exactly at the first and last data points */ - /* Control points 1 and 2 are positioned an alpha distance out */ - /* on the tangent vectors, left and right, respectively */ - bezCurve[0] = d[first]; - bezCurve[3] = d[last]; - V2Add(&bezCurve[0], V2Scale(&tHat1, alpha_l), &bezCurve[1]); - V2Add(&bezCurve[3], V2Scale(&tHat2, alpha_r), &bezCurve[2]); - return (bezCurve); - } - - - /* - * Reparameterize: - * Given set of points and their parameterization, try to find - * a better parameterization. - * - */ - static double *Reparameterize(d, first, last, u, bezCurve) - Point2 *d; /* Array of digitized points */ - int first, last; /* Indices defining region */ - double *u; /* Current parameter values */ - BezierCurve bezCurve; /* Current fitted curve */ - { - int nPts = last-first+1; - int i; - double *uPrime; /* New parameter values */ - - uPrime = (double *)malloc(nPts * sizeof(double)); - for (i = first; i <= last; i++) { - uPrime[i-first] = NewtonRaphsonRootFind(bezCurve, d[i], u[i- - first]); - } - return (uPrime); - } - - - - /* - * NewtonRaphsonRootFind : - * Use Newton-Raphson iteration to find better root. - */ - static double NewtonRaphsonRootFind(Q, P, u) - BezierCurve Q; /* Current fitted curve */ - Point2 P; /* Digitized point */ - double u; /* Parameter value for "P" */ - { - double numerator, denominator; - Point2 Q1[3], Q2[2]; /* Q' and Q'' */ - Point2 Q_u, Q1_u, Q2_u; /*u evaluated at Q, Q', & Q'' */ - double uPrime; /* Improved u */ - int i; - - /* Compute Q(u) */ - Q_u = BezierII(3, Q, u); - - /* Generate control vertices for Q' */ - for (i = 0; i <= 2; i++) { - Q1[i].x = (Q[i+1].x - Q[i].x) * 3.0; - Q1[i].y = (Q[i+1].y - Q[i].y) * 3.0; - } - - /* Generate control vertices for Q'' */ - for (i = 0; i <= 1; i++) { - Q2[i].x = (Q1[i+1].x - Q1[i].x) * 2.0; - Q2[i].y = (Q1[i+1].y - Q1[i].y) * 2.0; - } - - /* Compute Q'(u) and Q''(u) */ - Q1_u = BezierII(2, Q1, u); - Q2_u = BezierII(1, Q2, u); - - /* Compute f(u)/f'(u) */ - numerator = (Q_u.x - P.x) * (Q1_u.x) + (Q_u.y - P.y) * (Q1_u.y); - denominator = (Q1_u.x) * (Q1_u.x) + (Q1_u.y) * (Q1_u.y) + - (Q_u.x - P.x) * (Q2_u.x) + (Q_u.y - P.y) * (Q2_u.y); - if (denominator == 0.0f) return u; - - /* u = u - f(u)/f'(u) */ - uPrime = u - (numerator/denominator); - return (uPrime); - } - - - - /* - * Bezier : - * Evaluate a Bezier curve at a particular parameter value - * - */ - static Point2 BezierII(degree, V, t) - int degree; /* The degree of the bezier curve */ - Point2 *V; /* Array of control points */ - double t; /* Parametric value to find point for */ - { - int i, j; - Point2 Q; /* Point on curve at parameter t */ - Point2 *Vtemp; /* Local copy of control points */ - - /* Copy array */ - Vtemp = (Point2 *)malloc((unsigned)((degree+1) - * sizeof (Point2))); - for (i = 0; i <= degree; i++) { - Vtemp[i] = V[i]; - } - - /* Triangle computation */ - for (i = 1; i <= degree; i++) { - for (j = 0; j <= degree-i; j++) { - Vtemp[j].x = (1.0 - t) * Vtemp[j].x + t * Vtemp[j+1].x; - Vtemp[j].y = (1.0 - t) * Vtemp[j].y + t * Vtemp[j+1].y; - } - } - - Q = Vtemp[0]; - free((void *)Vtemp); - return Q; - } - - - /* - * B0, B1, B2, B3 : - * Bezier multipliers - */ - static double B0(u) - double u; - { - double tmp = 1.0 - u; - return (tmp * tmp * tmp); - } - - - static double B1(u) - double u; - { - double tmp = 1.0 - u; - return (3 * u * (tmp * tmp)); - } - - static double B2(u) - double u; - { - double tmp = 1.0 - u; - return (3 * u * u * tmp); - } - - static double B3(u) - double u; - { - return (u * u * u); - } - - - - /* - * ComputeLeftTangent, ComputeRightTangent, ComputeCenterTangent : - *Approximate unit tangents at endpoints and "center" of digitized curve - */ - static Vector2 ComputeLeftTangent(d, end) - Point2 *d; /* Digitized points*/ - int end; /* Index to "left" end of region */ - { - Vector2 tHat1; - tHat1 = V2SubII(d[end+1], d[end]); - tHat1 = *V2Normalize(&tHat1); - return tHat1; - } - - static Vector2 ComputeRightTangent(d, end) - Point2 *d; /* Digitized points */ - int end; /* Index to "right" end of region */ - { - Vector2 tHat2; - tHat2 = V2SubII(d[end-1], d[end]); - tHat2 = *V2Normalize(&tHat2); - return tHat2; - } - - - static Vector2 ComputeCenterTangent(d, center) - Point2 *d; /* Digitized points */ - int center; /* Index to point inside region */ - { - Vector2 V1, V2, tHatCenter; - - V1 = V2SubII(d[center-1], d[center]); - V2 = V2SubII(d[center], d[center+1]); - tHatCenter.x = (V1.x + V2.x)/2.0; - tHatCenter.y = (V1.y + V2.y)/2.0; - tHatCenter = *V2Normalize(&tHatCenter); - return tHatCenter; - } - - - /* - * ChordLengthParameterize : - * Assign parameter values to digitized points - * using relative distances between points. - */ - static double *ChordLengthParameterize(d, first, last) - Point2 *d; /* Array of digitized points */ - int first, last; /* Indices defining region */ - { - int i; - double *u; /* Parameterization */ - - u = (double *)malloc((unsigned)(last-first+1) * sizeof(double)); - - u[0] = 0.0; - for (i = first+1; i <= last; i++) { - u[i-first] = u[i-first-1] + - V2DistanceBetween2Points(&d[i], &d[i-1]); - } - - for (i = first + 1; i <= last; i++) { - u[i-first] = u[i-first] / u[last-first]; - } - - return(u); - } - - - - - /* - * ComputeMaxError : - * Find the maximum squared distance of digitized points - * to fitted curve. - */ - static double ComputeMaxError(d, first, last, bezCurve, u, splitPoint) - Point2 *d; /* Array of digitized points */ - int first, last; /* Indices defining region */ - BezierCurve bezCurve; /* Fitted Bezier curve */ - double *u; /* Parameterization of points */ - int *splitPoint; /* Point of maximum error */ - { - int i; - double maxDist; /* Maximum error */ - double dist; /* Current error */ - Point2 P; /* Point on curve */ - Vector2 v; /* Vector from point to curve */ - - *splitPoint = (last - first + 1)/2; - maxDist = 0.0; - for (i = first + 1; i < last; i++) { - P = BezierII(3, bezCurve, u[i-first]); - v = V2SubII(P, d[i]); - dist = V2SquaredLength(&v); - if (dist >= maxDist) { - maxDist = dist; - *splitPoint = i; - } - } - return (maxDist); - } - static Vector2 V2AddII(a, b) - Vector2 a, b; - { - Vector2 c; - c.x = a.x + b.x; c.y = a.y + b.y; - return (c); - } - static Vector2 V2ScaleIII(v, s) - Vector2 v; - double s; - { - Vector2 result; - result.x = v.x * s; result.y = v.y * s; - return (result); - } - - static Vector2 V2SubII(a, b) - Vector2 a, b; - { - Vector2 c; - c.x = a.x - b.x; c.y = a.y - b.y; - return (c); - } -