Subject: TTF to PS curve conversion (5/5)

From: "L.S.Ng" <[email-masked]>
Date: Sat, 28 May 1994 16:30:55 BST

/* Example: Splitting Long Bezier B-spline Curve */
/* Bezier B-Spline Approximation */
/* uses Borland BGI */

#include <stdio.h>
#include <stdlib.h>
#include <graphics.h>
#include <float.h>

#define oy 240

/* knot set for long quadratic Bezier curve */
double t[] = {0, 0, 0, 1, 2, 3, 4, 4, 4};
/* control points for long Bezier curve */
double y[] = { 0, 2, -2, 0, -1, 0};
double x[] = { 0, 1, 2, 3, 4, 5};

/* knot set for short quadratic Bezier curve */
double t2[] = {0,0,0,1,1,1};
/* arrays of control points for short quadratic Bezier curve */
double sx[3], sy[3];

/* knot set for (short) Cubic bezier curve */
double t3[] = {0,0,0,0,1,1,1,1};
/* arrays of control points for short cubic Bezier curve */
double cx[4], cy[4];

/* B-Spline basis/blending function */
double B(int i, int n, double x, double *t);
/* First derivative of B(x) */
double B1(int i, int n, double x, double *t);

/* Customised Divide function */
double DIV(double a, double b);

/* X coordinate of Bezier curve at (t) */
double X(int n, int m, double t, double *s, double *x);
/* Y coordinate of Bezier curve at (t) */
double Y(int n, int m, double t, double *s, double *y);
/* n = number of terms to sum, m = degree of Bezier curve
   s = knot set, y = array of control points */

main()
{   int gdrv=VGA, gmode=VGAHI, k, j;
    double i, xsum, ysum, axsum;

    initgraph(&gdrv, &gmode, "");

    /* Draw long quadratic Bezier curve */
    setcolor(0);
    for (i=3.9999; i>=0; i-=0.1) {
    lineto((int) (X(5,2,i,t,x)*100), (int) (oy-Y(5,2,i,t,y)*100));
    setcolor(14); /* yellow */
    }

    /* Draw control points of long Bezier curve */
    setcolor(0);
    for (k=0; k<=5; k++) {
    lineto ((int) (x[k]*100), (int) oy-(y[k]*100));
    if (k==0) setcolor(15); /* white */
    }

    /* Draw segments of short quadratic Bezier curve */
    for (k=0; k<=3; k++) {

    sx[0] = X(5,2,(double)k+.0001,t,x);
    sy[0] = Y(5,2,(double)k+.0001,t,y);
    sx[1] = x[k+1];
    sy[1] = y[k+1];
    sx[2] = X(5,2,(double)(k+.9999),t,x);
    sy[2] = Y(5,2,(double)(k+.9999),t,y);

    setcolor(0);
    for (i=0; i<=1; i+=0.05) {
    lineto((int) (X(2,2,i,t2,sx)*100), (int) (oy-Y(2,2,i,t2,sy)*100));
    setcolor(13); /* magenta */
    }

    /* Draw control points of short quadratic bezier curve */
    setcolor(0);
    for (j=0; j<=2; j++) {
    lineto ((int) (sx[j]*100), (int) oy-(sy[j]*100));
    setcolor(12); /* red */
    }

    cx[0] = sx[0];
    cy[0] = sy[0];
    cx[3] = sx[2];
    cy[3] = sy[2];
    cx[1] = (2*sx[1]+sx[0])/3;
    cy[1] = (2*sy[1]+sy[0])/3;
    cx[2] = (sx[2]+2*sx[1])/3;
    cy[2] = (sy[2]+2*sy[1])/3;

    setcolor(0);
    for (i=0.0001; i<=1; i+=0.05) {
    lineto((int) (X(3,3,i,t3,cx)*100), (int) (oy-Y(3,3,i,t3,cy)*100));
    setcolor(11); /* cyan */
    }

    /* Draw control points of short cubic bezier curve */
    setcolor(0);
    for (j=0; j<=3; j++) {
    lineto ((int) (cx[j]*100), (int) oy-(cy[j]*100));
    setcolor(10); /* green */
    }
    }

    /* Plot Gradient of Curve vs x coordinate */
    setcolor(0);
    for (i=0; i<=4; i+=0.1) {
    xsum = 0; ysum = 0; axsum = 0;
    for (k=0; k<=5; k++) {
        xsum += x[k]*B1(k, 2, i, t) ;
        ysum += y[k]*B1(k, 2, i, t) ;
        axsum += x[k]*B(k, 2, i, t) ;
        }
    lineto((int) (axsum*100), (int) (oy-DIV(ysum,xsum)*50));
    setcolor(9); /* blue */
    }

    /* Enter a dummy integer to finish */
    scanf("%d", &k);
    closegraph();

}

double B(int i, int n, double x, double *t)
{
     if (n==0) {
        if (x>= t[i] && x <= t[i+1]) return (double) 1;
        return (double) 0;
        }
     else return (double) DIV((x - t[i])*B(i, n-1, x, t), t[i+n] - t[i])
         + DIV((t[i+n+1] - x)*B(i+1, n-1, x, t), t[i+n+1] - t[i+1]);
}

double B1(int i, int n, double x, double *t)
{
     if (n == 1) return DIV( B(i,0,x,t), t[i+1]-t[i] )
                        - DIV( B(i+1,0,x,t), t[i+2]-t[i+1] );
     else return DIV(B(i,n-1,x,t)+(x-t[i])*B1(i,n-1,x,t) , t[i+n]-t[i])
     + DIV((t[i+n+1]-x)*B1(i+1,n-1,x,t)-B(i+1,n-1,x,t) , t[i+n+1]-t[i+1]);
}

double DIV(double a, double b)
{
     if (a==0 && b==0) return 0;
     if (a!=0 && b==0) return DBL_MAX;
     if (a > 1e4*b) return 1e4;
     return a/b;
}

double X(int n, int m, double t, double *s, double *x)
{
    double xsum=0, b;
    int i;

    for (i=0; i<=n; i++) {
    b = B(i, m, t, s);
    xsum += (double) x[i]*b;
    }

    return (double) xsum;
}

double Y(int n, int m, double t, double *s, double *y)
{
    double ysum=0;
    int i;

    for (i=0; i<=n; i++)
    ysum += (double) y[i]*B(i, m, t, s);

    return (double) ysum;
}