spiro.cpp revision 0a148d5e34b0d9ebac29a68a9ec02d6d43d0eb8c
/*
ppedit - A pattern plate editor for Spiro splines.
Copyright (C) 2007 Raph Levien
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
/* C implementation of third-order polynomial spirals. */
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include "bezctx_intf.h"
#include "spiro.h"
struct spiro_seg_s {
double x;
double y;
char ty;
double bend_th;
double ks[4];
double seg_ch;
double seg_th;
double l;
};
typedef struct {
double a[11]; /* band-diagonal matrix */
} bandmat;
#ifndef M_PI
#endif
int n = 4;
#ifndef ORDER
#define ORDER 12
#endif
/* Integrate polynomial spiral curve over range -.5 .. .5. */
void
{
#if 0
int n = 1024;
#endif
double x, y;
double ds = 1. / n;
int i;
x = 0;
y = 0;
for (i = 0; i < n; i++) {
#if ORDER > 2
double u, v;
if (n == 1) {
} else {
}
#endif
{
#if ORDER == 4
u = 24 - km0_2;
v = km1;
#endif
#if ORDER == 6
#endif
#if ORDER == 8
u = 1;
v = 0;
#endif
#if ORDER == 10
u = 1;
v = 0;
#endif
#if ORDER == 12
u = 1;
v = 0;
#endif
#if ORDER == 14
double t6_12 = t4_4 * t2_8 + t4_5 * t2_7 + t4_6 * t2_6 + t4_7 * t2_5 + t4_8 * t2_4 + t4_9 * t2_3 + t4_10 * t2_2;
u = 1;
v = 0;
v -= (1./480) * t3_4 + (1./2688) * t3_6 + (1./13824) * t3_8 + (1./67584) * t3_10 + (1./319488) * t3_12;
u += (1./1920) * t4_4 + (1./10752) * t4_6 + (1./55296) * t4_8 + (1./270336) * t4_10 + (1./1.27795e+06) * t4_12;
u -= (1./322560) * t6_6 + (1./1.65888e+06) * t6_8 + (1./8.11008e+06) * t6_10 + (1./3.83386e+07) * t6_12;
#endif
#if ORDER == 16
double t6_12 = t4_4 * t2_8 + t4_5 * t2_7 + t4_6 * t2_6 + t4_7 * t2_5 + t4_8 * t2_4 + t4_9 * t2_3 + t4_10 * t2_2;
double t6_13 = t4_5 * t2_8 + t4_6 * t2_7 + t4_7 * t2_6 + t4_8 * t2_5 + t4_9 * t2_4 + t4_10 * t2_3 + t4_11 * t2_2;
double t6_14 = t4_6 * t2_8 + t4_7 * t2_7 + t4_8 * t2_6 + t4_9 * t2_5 + t4_10 * t2_4 + t4_11 * t2_3 + t4_12 * t2_2;
double t8_14 = t6_6 * t2_8 + t6_7 * t2_7 + t6_8 * t2_6 + t6_9 * t2_5 + t6_10 * t2_4 + t6_11 * t2_3 + t6_12 * t2_2;
u = 1;
u += 1./1920 * t4_4 + 1./10752 * t4_6 + 1./55296 * t4_8 + 1./270336 * t4_10 + 1./1277952 * t4_12 + 1./5898240 * t4_14;
u -= 1./322560 * t6_6 + 1./1658880 * t6_8 + 1./8110080 * t6_10 + 1./38338560 * t6_12 + 1./176947200 * t6_14;
u += 1./92897280 * t8_8 + 1./454164480 * t8_10 + 4.6577500191e-10 * t8_12 + 1.0091791708e-10 * t8_14;
u -= 4.6674583324e-17 * t14_14;
v = 0;
v += 1./53760 * t5_6 + 1./276480 * t5_8 + 1./1351680 * t5_10 + 1./6389760 * t5_12 + 1./29491200 * t5_14;
v += 6.5344416654e-16 * t13_14;
#endif
}
if (n == 1) {
#if ORDER == 2
x = 1;
y = 0;
#else
x = u;
y = v;
#endif
} else {
#if ORDER == 2
x += cth;
y += sth;
#else
#endif
s += ds;
}
}
#else
#endif
}
static double
{
double xy[2];
l2 = l * l;
return l;
}
static void
int jinc)
{
double recip_d = 2e6;
double try_ks[4];
int i, j, k;
for (i = 0; i < jinc; i++) {
for (j = 0; j < 4; j++)
for (k = 0; k < 2; k++)
for (j = 0; j < 4; j++)
}
}
static double
{
}
static spiro_seg *
{
int i;
int ilast;
for (i = 0; i < n_seg; i++) {
r[i].x = src[i].x;
r[i].y = src[i].y;
r[i].ks[0] = 0.;
r[i].ks[1] = 0.;
r[i].ks[2] = 0.;
r[i].ks[3] = 0.;
}
for (i = 0; i < n_seg; i++) {
double dx = r[i + 1].x - r[i].x;
double dy = r[i + 1].y - r[i].y;
}
for (i = 0; i < n_seg; i++) {
r[i].bend_th = 0.;
else
ilast = i;
}
return r;
}
static void
{
int i, j, k;
int l;
/* pack top triangle to the left. */
for (i = 0; i < 5; i++) {
for (j = 0; j < i + 6; j++)
m[i].a[j] = m[i].a[j + 5 - i];
for (; j < 11; j++)
m[i].a[j] = 0.;
}
l = 5;
for (k = 0; k < n; k++) {
int pivot = k;
double pivot_val = m[k].a[0];
double pivot_scale;
l = l < n ? l + 1 : n;
for (j = k + 1; j < l; j++)
pivot_val = m[j].a[0];
pivot = j;
}
if (pivot != k) {
for (j = 0; j < 11; j++) {
double tmp = m[k].a[j];
m[k].a[j] = m[pivot].a[j];
}
}
for (i = k + 1; i < l; i++) {
double x = m[i].a[0] * pivot_scale;
m[k].al[i - k - 1] = x;
for (j = 1; j < 11; j++)
m[i].a[j - 1] = m[i].a[j] - x * m[k].a[j];
m[i].a[10] = 0.;
}
}
}
static void
{
int i, k, l;
/* forward substitution */
l = 5;
for (k = 0; k < n; k++) {
i = perm[k];
if (i != k) {
double tmp = v[k];
v[k] = v[i];
v[i] = tmp;
}
if (l < n) l++;
for (i = k + 1; i < l; i++)
v[i] -= m[k].al[i - k - 1] * v[k];
}
/* back substitution */
l = 1;
for (i = n - 1; i >= 0; i--) {
double x = v[i];
for (k = 1; k < l; k++)
x -= m[i].a[k] * v[k + i];
v[i] = x / m[i].a[0];
if (l < 11) l++;
}
}
{
return 4;
return 2;
return 1;
else
return 0;
}
{
int i;
int n = 0;
for (i = 0; i < nseg; i++)
return n;
}
static void
add_mat_line(bandmat *m, double *v,
int nmat)
{
int k;
if (jj >= 0) {
if (nmat < 6) {
} else if (nmat == 6) {
}
#ifdef VERBOSE
#endif
v[jj] += x;
for (k = 0; k < jinc; k++)
}
}
static double
{
int i, j, jj;
double norm;
int n_invert;
for (i = 0; i < nmat; i++) {
v[i] = 0.;
for (j = 0; j < 11; j++)
m[i].a[j] = 0.;
for (j = 0; j < 5; j++)
m[i].al[j] = 0.;
}
j = 0;
if (s[0].ty == 'o')
else if (s[0].ty == 'c')
else
jj = 0;
for (i = 0; i < n; i++) {
/* constraints crossing left */
}
if (ty0 == 'o') {
}
/* constraints on left */
jinc == 4) {
if (ty0 != 'c')
}
/* constraints on right */
jinc == 4) {
if (ty1 != 'c')
}
/* constraints crossing right */
}
if (ty1 == 'o') {
}
if (jthl >= 0)
if (jthr >= 0)
j += jinc;
}
if (cyclic) {
j = nmat;
} else {
j = 0;
}
#ifdef VERBOSE
for (i = 0; i < n; i++) {
int k;
for (k = 0; k < 11; k++)
printf(" %2.4f", m[i].a[k]);
printf(": %2.4f\n", v[i]);
}
printf("---\n");
#endif
norm = 0.;
for (i = 0; i < n; i++) {
int k;
for (k = 0; k < jinc; k++) {
double dk = v[j++];
#ifdef VERBOSE
#endif
}
}
return norm;
}
int
{
bandmat *m;
double *v;
int *perm;
double norm;
int i;
if (nmat == 0)
return 0;
n_alloc *= 3;
if (n_alloc < 5)
n_alloc = 5;
for (i = 0; i < 10; i++) {
#ifdef VERBOSE
#endif
if (norm < 1e-12) break;
}
free(m);
free(v);
return 0;
}
static void
{
if (!bend > 1e-8) {
} else {
double xy[2];
} else {
/* subdivide */
double ksub[4];
double thsub;
double xysub[2];
}
}
}
{
if (nseg > 1)
solve_spiro(s, nseg);
return s;
}
void
free_spiro(spiro_seg *s)
{
free(s);
}
void
{
int i;
for (i = 0; i < nsegs; i++) {
double x0 = s[i].x;
double y0 = s[i].y;
double x1 = s[i + 1].x;
double y1 = s[i + 1].y;
if (i == 0)
bezctx_mark_knot(bc, i);
}
}
double
get_knot_th(const spiro_seg *s, int i)
{
if (i == 0) {
} else {
}
}
#ifdef UNIT_TEST
#include <stdio.h>
static double
get_time (void)
{
}
int
test_integ(void) {
double xy[2];
double xynom[2];
int i, j;
int nsubdiv;
for (i = 0; i < nsubdiv; i++) {
double err;
n = 1 << i;
for (j = 0; j < n_iter; j++)
#if 0
printf("n = %d: integ(%g %g %g %g) = %g %g, ch = %g, th = %g\n", n,
#endif
}
return 0;
}
void
{
if (bend < 1e-8) {
} else {
double xy[2];
if (bend < 1.) {
printf("%g %g %g %g %g %g curveto\n",
} else {
/* subdivide */
double ksub[4];
double thsub;
double xysub[2];
}
}
}
void
{
int i;
for (i = 0; i < nsegs; i++) {
if (i == 0)
printf("%% ks = [ %g %g %g %g ]\n",
}
printf("stroke\n");
}
int
test_curve(void)
{
{334, 117, 'v'},
{305, 176, 'v'},
{212, 142, 'c'},
{159, 171, 'c'},
{224, 237, 'c'},
{347, 335, 'c'},
{202, 467, 'c'},
{81, 429, 'v'},
{114, 368, 'v'},
{201, 402, 'c'},
{276, 369, 'c'},
{218, 308, 'c'},
{91, 211, 'c'},
{124, 111, 'c'},
{229, 82, 'c'}
};
int i;
n = 1;
for (i = 0; i < 1000; i++) {
}
printf("100 800 translate 1 -1 scale 1 setlinewidth\n");
printf("showpage\n");
return 0;
}
{
return test_curve();
}
#endif