Commit 165d910
Remove backup files
Changed files (2)
Diff
deleted file mode 100644@@ -1,3 +0,0 @@-class FitCubic {--}deleted file mode 100644@@ -1,601 +0,0 @@-/*-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);-}-