#include <math.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "spiro-config.h"
#ifdef DO_TIME_DAY
#include <sys/time.h>
#else
#include <sys/timeb.h>
#endif
#include "spiroentrypoints.h"
#include "bezctx.h"
#ifdef DO_CALL_TESTM
#ifdef HAVE_PTHREADS
#include <pthread.h>
#endif
#endif
static double get_time (void) {
#ifdef DO_TIME_DAY
struct timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_sec + 1e-6 * tv.tv_usec;
#else
struct timeb tb;
ftime(&tb);
return tb.time + 1e-3 * tb.millitm;
#endif
}
#ifndef DO_CALL_TESTM
typedef struct {
double b, ch, th;
} rs_check_vals;
rs_check_vals verify_rs0[] = {
{0.000000, 65.741920, 2.027641},
{0.000000, 99.020200, -2.791096},
{-0.851164, 60.415230, 2.640925},
{-1.847893, 92.633687, 0.793032},
{-0.120277, 157.267288, 0.672755},
{1.730337, 196.084166, 2.403091},
{1.042797, 126.826653, -2.837297},
{0.000000, 69.354164, -1.074902},
{0.000000, 93.407708, 0.372554},
{-0.787061, 81.939002, -0.414507},
{-1.916483, 84.172442, -2.330990},
{-0.158341, 159.806133, -2.489331},
{1.237282, 105.304321, -1.252049},
{0.982576, 108.931171, -0.269473},
{0.591223, 110.679718, 0.321751}
};
rs_check_vals verify_rs1[] = {
{0.000000, 697.685459, -0.287750},
{-1.608688, 243.813453, -1.896438},
{-1.770739, 173.404152, 2.616009},
{0.937994, 157.178243, -2.729182},
{1.881365, 136.029409, -0.847817}
};
rs_check_vals verify_rs2[] = {
{0.000000, 108.115679, -0.046263},
{-0.926114, 79.881162, -0.972377},
{1.844174, 90.138782, 0.871797}
};
rs_check_vals verify_rs4[] = {
{-1.570796, 141.421356, 0.785398},
{-1.570796, 141.421356, -0.785398},
{-1.570796, 141.421356, -2.356194}
};
rs_check_vals verify_rs5[] = {
{0.000000, 141.421356, 0.785398},
{0.000000, 141.421356, 0.785398},
{-0.785398, 100.000000, 0.000000},
{-0.463648, 111.803399, -0.463648},
{-2.214297, 111.803399, -2.677945},
{-0.463648, 100.000000, 3.141593},
{0.785398, 70.710678, -2.356194},
{0.000000, 70.710678, -2.356194},
{0.000000, 141.421356, -2.356194},
{0.321751, 111.803399, -2.034444},
{-0.076772, 58.309519, -2.111216}
};
rs_check_vals verify_rs7[] = {
{-0.950547, 50.990195, 0.197396},
{-1.534449, 215.870331, -1.337053},
{-0.233743, 50.000000, -1.570796},
{-0.484478, 214.709106, -2.055274},
{-0.986650, 50.249378, -3.041924},
{-1.228091, 210.237960, 2.013171},
{-0.342706, 50.249378, 1.670465},
{-0.522523, 219.317122, 1.147942}
};
rs_check_vals verify_rs8[] = {
{-0.950547, 50.990195, 0.197396},
{-1.534449, 215.870331, -1.337053},
{-0.233743, 50.000000, -1.570796},
{-0.484478, 214.709106, -2.055274},
{-0.986650, 50.249378, -3.041924},
{-1.228091, 210.237960, 2.013171},
{-0.342706, 50.249378, 1.670465}
};
rs_check_vals verify_rs9[] = {
{-1.570796, 141.421356, 0.785398},
{-1.570796, 141.421356, -0.785398},
{-1.570796, 141.421356, -2.356194},
{-1.570796, 141.421356, 2.356194}
};
#define TEST_10_11 1
rs_check_vals verify_rs10[] = {
#ifndef TEST_10_11
{-0.233743, 50.000000, -1.570796},
{-0.484478, 214.709106, -2.055274},
{-0.986650, 50.249378, -3.041924},
{-1.228091, 210.237960, 2.013171},
{-0.342706, 50.249378, 1.670465},
{-0.522523, 219.317122, 1.147942},
{-0.950547, 50.990195, 0.197396},
{-1.534449, 215.870331, -1.337053}
#else
{-0.256151, 50.000000, -1.570796},
{-0.484478, 214.709106, -2.055274},
{-0.986650, 50.249378, -3.041924},
{-1.228091, 210.237960, 2.013171},
{-0.342706, 50.249378, 1.670465},
{-0.522523, 219.317, 1.14794},
{-0.950547, 50.990195, 0.197396},
{-1.512041, 217.082933, -1.314645}
#endif
};
rs_check_vals verify_rs11[] = {
#ifndef TEST_10_11
{-0.233743, 50.000000, -1.570796},
{-0.484478, 214.709106, -2.055274},
{-0.986650, 50.249378, -3.041924},
{-1.228091, 210.237960, 2.013171},
{-0.342706, 50.249378, 1.670465},
{-0.522523, 219.317122, 1.147942},
{-0.950547, 50.990195, 0.197396},
{-1.534449, 215.870331, -1.337053}
#else
{-0.256151, 50.000000, -1.570796},
{-0.484478, 214.709106, -2.055274},
{-0.986650, 50.249378, -3.041924},
{-1.228091, 210.237960, 2.013171},
{-0.342706, 50.249378, 1.670465},
{-0.522523, 219.317122, 1.147942},
{-0.950547, 50.990195, 0.197396},
{-1.512041, 217.0829933, -1.314645}
#endif
};
rs_check_vals verify_rs13[] = {
{ 0.000000, 50.000000, -1.570796},
{-0.484478, 214.709106, -2.055274},
{-0.986650, 50.249378, -3.041924},
{-1.228091, 210.237960, 2.013171},
{-0.342706, 50.249378, 1.670465},
{-0.522523, 219.317122, 1.147942},
{-0.950547, 50.990195, 0.197396},
{-1.534449, 215.870331, -1.337053}
};
rs_check_vals verify_rs14[] = {
{-1.570796, 141.421356e10, 0.785398},
{-1.570796, 141.421356e10, -0.785398},
{-1.570796, 141.421356e10, -2.356194},
{-1.570796, 141.421356e10, 2.356194}
};
rs_check_vals verify_rs15[] = {
{-1.570796, 141.421356e-42, 0.785398},
{-1.570796, 141.421356e-42, -0.785398},
{-1.570796, 141.421356e-42, -2.356194},
{-1.570796, 141.421356e-42, 2.356194}
};
#endif
void load_test_curve(spiro_cp *spiro, int *nextknot, int c) {
spiro_cp path0[] = {
{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'},
{0, 0, 'z'}
};
int knot0[] = {
1, 1, 3, 3, 2, 3, 1, 1, 1, 3, 3, 2, 2, 2, 1, 1
};
spiro_cp path1[] = {
{ 80, 738, '{'},
{749, 540, 'o'},
{671, 309, 'o'},
{521, 396, 'o'},
{377, 333, 'o'},
{467, 231, '}'}
};
int knot1[] = {
3, 4, 2, 3, 2, 0
};
spiro_cp path2[] = {
{233, 143, '{'},
{341, 138, 'o'},
{386, 72, 'o'},
{444, 141, '}'}
};
int knot2[] = {
2, 1, 9, 0
};
spiro_cp path3[] = {
{233, 144, '{'},
{341, 138, 'o'},
{386, 72, 'o'},
{443, 141, 'o'},
{467, 231, 'o'},
{377, 333, '}'}
};
int knot3[] = {
2, 1, 9, 1, 1, 0
};
spiro_cp path4[] = {
{-100, 0, SPIRO_G4},
{ 0, 100, SPIRO_G4},
{ 100, 0, SPIRO_G4},
{ 0, -100, SPIRO_G4}
};
int knot4[] = {
2, 2, 2, 0
};
spiro_cp path5[] = {
{ 0, 0, '{'},
{100, 100, 'c'},
{200, 200, '['},
{300, 200, ']'},
{400, 150, 'c'},
{300, 100, '['},
{200, 100, ']'},
{150, 50, 'c'},
{100, 0, '['},
{ 0,-100, ']'},
{-50,-200, 'c'},
{-80,-250, '}'}
};
int knot5[] = {
1, 4, 1, 3, 3, 1, 4, 2, 1, 2, 1, 0
};
spiro_cp path6[] = {
{ 0, 0, '{'},
{100, 100, 'c'},
{200, 200, 'a'},
{300, 200, 'h'},
{300, 150, 'c'},
{200, 100, 'a'},
{100, 100, 'h'},
{150, 50, 'c'},
{100, 0, 'a'},
{ 0,-100, 'h'},
{ 50,-100, 'c'},
{ 20,-150, '}'}
};
int knot6[] = {
1, 4, 3, 3, 4, 2, 2, 1, 0, 0, 0, 0
};
spiro_cp path7[] = {
{ 0, 200, 'o'},
{ 50, 210, 'o'},
{100, 0, 'a'},
{100, -50, 'h'},
{ 0,-190, 'a'},
{-50,-195, 'h'},
{-90, 0, 'a'},
{-95, 50, 'h'},
{ 0, 0, 'z'}
};
int knot7[] = {
1, 1, 5, 5, 6, 3, 0, 0, 0
};
spiro_cp path10[] = {
#ifndef TEST_10_11
{100, 0, 'a'},
{100, -50, 'h'},
{ 0,-190, 'a'},
{-50,-195, 'h'},
{-90, 0, 'a'},
{-95, 50, 'h'},
{ 0, 200, 'o'},
{ 50, 210, 'o'}
#else
{100, 0, '['},
{100, -50, ']'},
{ 0,-240, 'a'},
{-50,-245, 'h'},
{-90, -50, '['},
{-95, 0, ']'},
{ -5, 200, 'o'},
{ 45, 210, 'o'}
#endif
};
int knot10[] = {
5, 6, 3, 1, 1, 5, 0, 0
};
spiro_cp path13[] = {
{100, 0, '{'},
{100, -50, 'h'},
{ 0,-190, 'a'},
{-50,-195, 'h'},
{-90, 0, 'a'},
{-95, 50, 'h'},
{ 0, 200, 'o'},
{ 50, 210, '}'}
};
int knot13[] = {
5, 6, 3, 1, 1, 5, 0, 0
};
spiro_cp path14[] = {
{-100e10, 0, SPIRO_G4},
{ 0, 100e10, SPIRO_G4},
{ 100e10, 0, SPIRO_G4},
{ 0, -100e10, SPIRO_G4}
};
spiro_cp path15[] = {
{-100e-42, 0, SPIRO_G4},
{ 0, 100e-42, SPIRO_G4},
{ 100e-42, 0, SPIRO_G4},
{ 0, -100e-42, SPIRO_G4}
};
int i;
if ( c==0 ) for (i = 0; i < 16; i++) {
spiro[i].x = path0[i].x;
spiro[i].y = path0[i].y;
spiro[i].ty = path0[i].ty;
nextknot[i] = knot0[i];
} else if ( c==1 ) for (i = 0; i < 6; i++) {
spiro[i].x = path1[i].x;
spiro[i].y = path1[i].y;
spiro[i].ty = path1[i].ty;
nextknot[i] = knot1[i];
} else if ( c==2 ) for (i = 0; i < 4; i++) {
spiro[i].x = path2[i].x;
spiro[i].y = path2[i].y;
spiro[i].ty = path2[i].ty;
nextknot[i] = knot2[i];
} else if ( c==3 ) for (i = 0; i < 6; i++) {
spiro[i].x = path3[i].x;
spiro[i].y = path3[i].y;
spiro[i].ty = path3[i].ty;
nextknot[i] = knot3[i];
} else if ( c==4 ) for (i = 0; i < 4; i++) {
spiro[i].x = path4[i].x;
spiro[i].y = path4[i].y;
spiro[i].ty = path4[i].ty;
nextknot[i] = knot4[i];
} else if ( c==5 ) for (i = 0; i < 12; i++) {
spiro[i].x = path5[i].x;
spiro[i].y = path5[i].y;
spiro[i].ty = path5[i].ty;
nextknot[i] = knot5[i];
} else if ( c==6 ) for (i = 0; i < 12; i++) {
spiro[i].x = path6[i].x;
spiro[i].y = path6[i].y;
spiro[i].ty = path6[i].ty;
nextknot[i] = knot6[i];
} else if ( c==7 || c==8 || c==21 ) for (i = 0; i < 8; i++) {
spiro[i].x = path7[i].x;
spiro[i].y = path7[i].y;
spiro[i].ty = path7[i].ty;
nextknot[i] = knot7[i];
} else if ( c==9 ) for (i = 0; i < 4; i++) {
spiro[i].x = path4[i].x;
spiro[i].y = path4[i].y;
spiro[i].ty = path4[i].ty;
nextknot[i] = knot4[i];
} else if ( c==10 || c==11 ) for (i = 0; i < 8; i++) {
spiro[i].x = path10[i].x;
spiro[i].y = path10[i].y;
spiro[i].ty = path10[i].ty;
nextknot[i] = knot10[i];
} else if ( c==12 ) for (i = 0; i < 9; i++) {
spiro[i].x = path7[i].x;
spiro[i].y = path7[i].y;
spiro[i].ty = path7[i].ty;
nextknot[i] = knot7[i];
} else if ( c==13 ) for (i = 0; i < 8; i++) {
spiro[i].x = path13[i].x;
spiro[i].y = path13[i].y;
spiro[i].ty = path13[i].ty;
nextknot[i] = knot13[i];
} else if ( c==14 ) for (i = 0; i < 4; i++) {
spiro[i].x = path14[i].x;
spiro[i].y = path14[i].y;
spiro[i].ty = path14[i].ty;
nextknot[i] = knot4[i];
} else if ( c==15 ) for (i = 0; i < 4; i++) {
spiro[i].x = path15[i].x;
spiro[i].y = path15[i].y;
spiro[i].ty = path15[i].ty;
nextknot[i] = knot4[i];
} else if ( c==16 ) for (i = 0; i < 4; i++) {
spiro[i].x = path4[i].x;
spiro[i].y = path4[i].y;
spiro[i].ty = path4[i].ty;
nextknot[i] = knot4[i];
} else if ( c==17 ) for (i = 0; i < 4; i++) {
spiro[i].x = path4[i].x;
spiro[i].y = path4[i].y;
spiro[i].ty = path4[i].ty;
nextknot[i] = knot4[i];
} else if ( c==18 ) for (i = 0; i < 4; i++) {
spiro[i].x = path2[i].x;
spiro[i].y = path2[i].y;
spiro[i].ty = path2[i].ty;
nextknot[i] = knot2[i];
} else if ( c==19 ) for (i = 0; i < 16; i++) {
spiro[i].x = path0[i].x;
spiro[i].y = path0[i].y;
spiro[i].ty = path0[i].ty;
nextknot[i] = knot0[i];
} else if ( c==20 || c==22) for (i = 0; i < 9; i++) {
spiro[i].x = path7[i].x;
spiro[i].y = path7[i].y;
spiro[i].ty = path7[i].ty;
} else if ( c==23 ) for (i = 0; i < 12; i++) {
spiro[i].x = path5[i].x;
spiro[i].y = path5[i].y;
spiro[i].ty = path5[i].ty;
} else if ( c==24 ) for (i = 0; i < 16; i++) {
spiro[i].x = path0[i].x;
spiro[i].y = path0[i].y;
spiro[i].ty = path0[i].ty;
nextknot[i] = knot0[i];
}
}
int cl[] = {16, 6, 4, 6, 4, 12, 12, 8, 8, 4, 8, 8, 8, 8, 4, 4, 4, 4, 4, 16,
8, 8, 9, 12, 16};
int ck[] = {16, 6, 4, 6, 4, 12, 9, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 16,
4, 4, 4, 12, 16};
int co[] = {1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1,
1, 0, 1, 0, 1};
#ifndef DO_CALL_TESTM
void test_moveto(bezctx *bc, double x, double y, int is_open) {
printf("test_moveto(%g,%g)_%d\n",x,y,is_open);
}
void test_lineto(bezctx *bc, double x, double y) {
printf("test_lineto(%g,%g)\n",x,y);
}
void test_quadto(bezctx *bc, double x1, double y1, double x2, double y2) {
printf("test_quadto(%g,%g, %g,%g)\n",x1,y1,x2,y2);
}
void test_curveto(bezctx *bc, double x1, double y1, double x2, double y2,
double x3, double y3) {
printf("test_curveto(%g,%g, %g,%g, %g,%g)\n",x1,y1,x2,y2,x3,y3);
}
void test_mark_knot(bezctx *bc, int knot_idx) {
printf("test_mark_knot()_%d\n",knot_idx);
}
bezctx *new_bezctx_test(void) {
bezctx *result = malloc(1*sizeof(bezctx));
result->moveto = test_moveto;
result->lineto = test_lineto;
result->quadto = test_quadto;
result->curveto = test_curveto;
result->mark_knot = test_mark_knot;
return result;
}
int test_curve(int c) {
spiro_cp spiro[16];
int nextknot[17];
double d[6];
spiro_seg *segs = NULL;
bezctx *bc;
rs_check_vals *rsp;
int i,j,done;
load_test_curve(spiro,nextknot,c);
d[0] = 1.; d[1] = d[2] = 0.;
#if defined(DO_CALL_TEST20)
printf("---\ntesting spiroreverse() using data=path%d[].\n",c);
if ( (spiroreverse(spiro,cl[c])) ) {
fprintf(stderr,"error with spiroreverse() using data=path%d[].\n",c);
return -1;
}
for (i=0; i < cl[c]; i++) {
printf(" reversed %d: ty=%c, x=%g, y=%g\n", i,spiro[i].ty,spiro[i].x,spiro[i].y);
}
#else
#if defined(DO_CALL_TEST14) || defined(DO_CALL_TEST15) || defined(DO_CALL_TEST16) || defined(DO_CALL_TEST17) || defined(DO_CALL_TEST18) || defined(DO_CALL_TEST19)
#if defined(DO_CALL_TEST16) || defined(DO_CALL_TEST17) || defined(DO_CALL_TEST18) || defined(DO_CALL_TEST19)
d[0] = -1.;
printf("---\ntesting run_spiro0(q) using data=path%d[].\n",c);
if ( (segs=run_spiro0(spiro,d,SPIRO_ARC_MAYBE,cl[c]))==0 ) {
fprintf(stderr,"error with run_spiro0(q) using data=path%d[].\n",c);
return -1;
}
#else
d[0] = -1.;
printf("---\ntesting run_spiro0() using data=path%d[].\n",c);
if ( (segs=run_spiro0(spiro,d,0,cl[c]))==0 ) {
fprintf(stderr,"error with run_spiro0() using data=path%d[].\n",c);
return -1;
}
#endif
#else
printf("---\ntesting run_spiro() using data=path%d[].\n",c);
if ( (segs=run_spiro(spiro,cl[c]))==0 ) {
fprintf(stderr,"error with run_spiro() using data=path%d[].\n",c);
return -1;
}
#endif
if ( c==0 ) rsp = verify_rs0;
else if ( c==1 ) rsp = verify_rs1;
else if ( c==2 ) rsp = verify_rs2;
else if ( c==4 ) rsp = verify_rs4;
else if ( c==5 ) rsp = verify_rs5;
else if ( c==6 ) rsp = verify_rs5;
else if ( c==7 ) rsp = verify_rs7;
else if ( c==8 ) rsp = verify_rs8;
else if ( c==9 ) rsp = verify_rs9;
else if ( c==10 ) rsp = verify_rs10;
else if ( c==11 ) rsp = verify_rs11;
else if ( c==12 ) rsp = verify_rs7;
else if ( c==13 ) rsp = verify_rs13;
else if ( c==14 ) rsp = verify_rs14;
else if ( c==15 ) rsp = verify_rs15;
else if ( c==16 ) rsp = verify_rs4;
else if ( c==17 ) rsp = verify_rs4;
else if ( c==18 ) rsp = verify_rs2;
else rsp = verify_rs0;
for (i=j=0; i < cl[c]-1; i++,j++) {
if ( spiro[i].ty == 'h' ) {
--j;
printf("curve %d ctrl %d t=%c x=%f y=%f (handle)\n", \
c,j,segs[i].ty,spiro[i].x,spiro[i].y);
}
printf("curve %d line %d t=%c x=%f y=%f bend=%f ch=%f th=%f ",c,j, \
segs[i].ty,segs[i].x,segs[i].y,segs[i].bend_th,segs[i].seg_ch,segs[i].seg_th);
if ( (segs[i].ty != spiro[i].ty) ||
#if defined(DO_CALL_TEST14) || defined(DO_CALL_TEST15) || defined(DO_CALL_TEST16) || defined(DO_CALL_TEST17) || defined(DO_CALL_TEST18) || defined(DO_CALL_TEST19)
#if defined(DO_CALL_TEST14) || defined(DO_CALL_TEST16) || defined(DO_CALL_TEST17) || defined(DO_CALL_TEST18) || defined(DO_CALL_TEST19)
(fabs((segs[i].x * d[0] + d[1]) - spiro[i].x) > 1e5) ||
(fabs((segs[i].y * d[0] + d[2]) - spiro[i].y) > 1e5) ||
(fabs(segs[i].seg_ch * d[0] - rsp[i].ch) > 1e5) ||
#else
(fabs((segs[i].x * d[0] + d[1]) - spiro[i].x) > 1e-47) ||
(fabs((segs[i].y * d[0] + d[2]) - spiro[i].y) > 1e-47) ||
(fabs(segs[i].seg_ch * d[0] - rsp[i].ch) > 1e-47) ||
#endif
#else
#if !defined(DO_CALL_TEST6) && !defined(DO_CALL_TEST7) && !defined(DO_CALL_TEST8) && !defined(DO_CALL_TEST10) && !defined(DO_CALL_TEST11) && !defined(DO_CALL_TEST12) && !defined(DO_CALL_TEST13)
(fabs(segs[i].x - spiro[i].x) > 1e-5) ||
(fabs(segs[i].y - spiro[i].y) > 1e-5) ||
#endif
(fabs(segs[i].seg_ch - rsp[i].ch) > 1e-5) ||
#endif
(fabs(segs[i].bend_th - rsp[i].b) > 1e-5) ||
(fabs(segs[i].seg_th - rsp[i].th) > 1e-5) ) {
printf("FAIL\n");
fprintf(stderr,"Error found with run_spiro() data. Results are not the same.\n");
fprintf(stderr,"expected line %d t=%c x=%f y=%f bend=%f ch=%f th=%f\n", j, \
spiro[i].ty,spiro[i].x,spiro[i].y,rsp[i].b,rsp[i].ch,rsp[i].th);
free(segs);
return -2;
} else
printf("PASS\n");
}
printf("curve %d ",c);
if ( spiro[i].ty == '}' || spiro[i].ty == 'z' )
printf("stop %d t=%c x=%f y=%f\n",j,segs[i].ty,segs[i].x,segs[i].y);
else
printf("line %d t=%c x=%f y=%f bend=%f ch=%f th=%f\n", j,segs[i].ty, \
segs[i].x,segs[i].y,segs[i].bend_th,segs[i].seg_ch,segs[i].seg_th);
printf("---\ntesting spiro_to_bpath() using data from run_spiro(data=path%d[],len=%d).\n",c,cl[c]);
bc = new_bezctx_test();
#if defined(DO_CALL_TEST14) || defined(DO_CALL_TEST15) || defined(DO_CALL_TEST16) || defined(DO_CALL_TEST17) || defined(DO_CALL_TEST18) || defined(DO_CALL_TEST19)
#if defined(DO_CALL_TEST16) || defined(DO_CALL_TEST17) || defined(DO_CALL_TEST18) || defined(DO_CALL_TEST19)
spiro_to_bpath0(spiro,segs,d,SPIRO_ARC_MAYBE,cl[c],bc);
#else
spiro_to_bpath0(spiro,segs,d,0,cl[c],bc);
#endif
#else
spiro_to_bpath(segs,cl[c],bc);
#endif
free(segs);
#endif
#if !defined(DO_CALL_TEST20)
#if defined(DO_CALL_TEST14) || defined(DO_CALL_TEST15) || defined(DO_CALL_TEST16) || defined(DO_CALL_TEST17) || defined(DO_CALL_TEST18) || defined(DO_CALL_TEST19)
#if defined(DO_CALL_TEST14) || defined(DO_CALL_TEST15) || defined(DO_CALL_TEST16) || defined(DO_CALL_TEST17)
printf("---\ntesting SpiroCPsToBezier2() using data=path%d[].\n",c);
if ( SpiroCPsToBezier2(spiro,cl[c],SPIRO_ARC_MAYBE,co[c],bc)!=1 ) {
fprintf(stderr,"error with SpiroCPsToBezier2() using data=path%d[].\n",c);
return -7;
}
#endif
#if defined(DO_CALL_TEST18) || defined(DO_CALL_TEST19)
printf("---\ntesting TaggedSpiroCPsToBezier2() using data=path%d[].\n",c);
if ( TaggedSpiroCPsToBezier2(spiro,SPIRO_ARC_MAYBE,bc)!=1 ) {
fprintf(stderr,"error with TaggedSpiroCPsToBezier2() using data=path%d[].\n",c);
return -8;
}
#endif
#else
#if !defined(DO_CALL_TEST4) && !defined(DO_CALL_TEST6) && !defined(DO_CALL_TEST7) && !defined(DO_CALL_TEST8) && !defined(DO_CALL_TEST9) && !defined(DO_CALL_TEST10) && !defined(DO_CALL_TEST11)
printf("---\ntesting TaggedSpiroCPsToBezier0() using data=path%d[].\n",c);
if ( TaggedSpiroCPsToBezier0(spiro,bc)!=1 ) {
fprintf(stderr,"error with TaggedSpiroCPsToBezier0() using data=path%d[].\n",c);
return -3;
}
#endif
#if !defined(DO_CALL_TEST12)
printf("---\ntesting SpiroCPsToBezier0() using data=path%d[].\n",c);
if ( SpiroCPsToBezier0(spiro,cl[c],co[c],bc)!=1 ) {
fprintf(stderr,"error with SpiroCPsToBezier0() using data=path%d[].\n",c);
return -4;
}
#endif
#if !defined(DO_CALL_TEST4) && !defined(DO_CALL_TEST6) && !defined(DO_CALL_TEST7) && !defined(DO_CALL_TEST8) && !defined(DO_CALL_TEST9) && !defined(DO_CALL_TEST10) && !defined(DO_CALL_TEST11)
printf("---\ntesting TaggedSpiroCPsToBezier1() using data=path%d[].\n",c);
TaggedSpiroCPsToBezier1(spiro,bc,&done);
if ( done!=1 ) {
fprintf(stderr,"error with TaggedSpiroCPsToBezier1() using data=path%d[].\n",c);
return -5;
}
#endif
#if !defined(DO_CALL_TEST12)
printf("---\ntesting SpiroCPsToBezier1() using data=path%d[].\n",c);
SpiroCPsToBezier1(spiro,cl[c],co[c],bc,&done);
if ( done!=1 ) {
fprintf(stderr,"error with SpiroCPsToBezier1() using data=path%d[].\n",c);
return -6;
}
#if defined(DO_CALL_TEST13)
printf("---\ntesting SpiroCPsToBezier2() using data=path%d[].\n",c);
if ( SpiroCPsToBezier2(spiro,cl[c],SPIRO_INCLUDE_LAST_KNOT,co[c],bc)!=1 ) {
fprintf(stderr,"error with SpiroCPsToBezier2() using data=path%d[].\n",c);
return -6;
}
#endif
#else
printf("---\ntesting SpiroCPsToBezier2() using data=path%d[].\n",c);
if ( SpiroCPsToBezier2(spiro,cl[c],SPIRO_INCLUDE_LAST_KNOT,co[c],bc)!=1 ) {
fprintf(stderr,"error with SpiroCPsToBezier2() using data=path%d[].\n",c);
return -6;
}
printf("---\ntesting TaggedSpiroCPsToBezier2() using data=path%d[].\n",c);
if ( TaggedSpiroCPsToBezier2(spiro,SPIRO_INCLUDE_LAST_KNOT,bc)!=1 ) {
fprintf(stderr,"error with TaggedSpiroCPsToBezier2() using data=path%d[].\n",c);
return -6;
}
#endif
#endif
#else
bc = new_bezctx_test();
if (c == 20 || c == 21) {
printf("---\ntesting SpiroCPsToBezier2(reverse) using data=path%d[].\n",c);
if ( SpiroCPsToBezier2(spiro,cl[c],SPIRO_REVERSE_SRC,co[c],bc)!=1 ) {
fprintf(stderr,"error with SpiroCPsToBezier2(reverse) using data=path%d[].\n",c);
return -9;
}
} else {
printf("---\ntesting TaggedSpiroCPsToBezier2(reverse) using data=path%d[].\n",c);
if ( TaggedSpiroCPsToBezier2(spiro,SPIRO_REVERSE_SRC,bc)!=1 ) {
fprintf(stderr,"error with TaggedSpiroCPsToBezier2(reverse) using data=path%d[].\n",c);
return -10;
}
if (c == 24) {
printf("---\ntesting TaggedSpiroCPsToBezier2(reverse) using data=path%d[].\n",c);
if ( TaggedSpiroCPsToBezier2(spiro,SPIRO_REVERSE_SRC|SPIRO_INCLUDE_LAST_KNOT,bc)!=1 ) {
fprintf(stderr,"error with TaggedSpiroCPsToBezier2(reverse) using data=path%d[].\n",c);
return -10;
}
}
}
#endif
free(bc);
return 0;
}
#endif
#ifdef DO_CALL_TESTM
#ifdef HAVE_PTHREADS
typedef struct {
spiro_cp *spiro;
bezctx *bc;
int ret;
} pthread_pcurve;
void *test_a_curve(void *pdata) {
pthread_pcurve *data = (pthread_pcurve*)pdata;
data->ret = TaggedSpiroCPsToBezier2(data->spiro,0,data->bc);
return 0;
}
#endif
typedef struct {
double x1,y1,x2,y2,x3,y3;
char ty;
} my_curve_data;
typedef struct {
bezctx base;
my_curve_data *my_curve;
int len;
int is_open;
int c_id;
} test_bezctx;
#define S_RESULTS 50
void test_s_moveto(bezctx *z, double x, double y, int is_open) {
test_bezctx *p = (test_bezctx*)z;
int i;
if ( (i=p->len) < S_RESULTS ) {
#ifdef VERBOSE
printf("test_s_moveto(%g,%g)_%d [%d]%d\n",x,y,is_open,p->c_id,i);
#endif
p->is_open = is_open;
p->my_curve[i].x1 = x;
p->my_curve[i].y1 = y;
p->my_curve[p->len++].ty = 'm';
}
}
void test_s_lineto(bezctx *z, double x, double y) {
test_bezctx *p = (test_bezctx*)z;
int i;
if ( (i=p->len) < S_RESULTS ) {
#ifdef VERBOSE
printf("test_s_lineto(%g,%g) [%d]%d\n",x,y,p->c_id,i);
#endif
p->my_curve[i].x1 = x;
p->my_curve[i].y1 = y;
p->my_curve[p->len++].ty = 'l';
}
}
void test_s_quadto(bezctx *z, double x1, double y1, double x2, double y2) {
test_bezctx *p = (test_bezctx*)z;
int i;
if ( (i=p->len) < S_RESULTS ) {
#ifdef VERBOSE
printf("test_s_quadto(%g,%g, %g,%g) [%d]%d\n",x1,y1,x2,y2,p->c_id,i);
#endif
p->my_curve[i].x1 = x1;
p->my_curve[i].y1 = y1;
p->my_curve[i].x2 = x2;
p->my_curve[i].y2 = y2;
p->my_curve[p->len++].ty = 'q';
}
}
void test_s_curveto(bezctx *z, double x1, double y1, double x2, double y2,
double x3, double y3) {
test_bezctx *p = (test_bezctx*)z;
int i;
if ( (i=p->len) < S_RESULTS ) {
#ifdef VERBOSE
printf("test_s_curveto(%g,%g, %g,%g, %g,%g) [%d]%d\n",x1,y1,x2,y2,x3,y3,p->c_id,i);
#endif
p->my_curve[i].x1 = x1;
p->my_curve[i].y1 = y1;
p->my_curve[i].x2 = x2;
p->my_curve[i].y2 = y2;
p->my_curve[i].x3 = x3;
p->my_curve[i].y3 = y3;
p->my_curve[p->len++].ty = 'c';
}
}
void test_s_mark_knot(bezctx *z, int knot_idx) {
test_bezctx *p = (test_bezctx*)z;
if ( p->len < S_RESULTS )
#ifdef VERBOSE
printf("test_s_mark_knot()_%d [%d]%d\n",knot_idx,p->c_id,p->len);
#endif
p->my_curve[p->len++].ty = 'k';
}
int test_multi_curves(void) {
spiro_cp **spiro = NULL;
spiro_cp *temp;
int *pk, **nextknot = NULL;
int *scl = NULL;
test_bezctx **bc;
int i, j, k, l, ret;
double x, y;
char ty;
#define S_TESTS S_TESTP*5
#ifdef HAVE_PTHREADS
pthread_attr_t tattr;
pthread_t curve_test[S_TESTS];
pthread_pcurve pdata[S_TESTS];
printf("---\nMulti-thread testing of libspiro.\n");
#else
printf("---\nSequential tests of libspiro.\n");
#endif
ret = -1;
if ( (bc=(test_bezctx**)calloc(S_TESTS,sizeof(test_bezctx*)))==NULL )
goto test_multi_curves_exit;
for (i=0; i < S_TESTS; i++) {
if ( (bc[i]=(test_bezctx*)malloc(sizeof(test_bezctx)))==NULL )
goto test_multi_curves_exit;
bc[i]->base.moveto = test_s_moveto;
bc[i]->base.lineto = test_s_lineto;
bc[i]->base.quadto = test_s_quadto;
bc[i]->base.curveto = test_s_curveto;
bc[i]->base.mark_knot = test_s_mark_knot;
if ( (bc[i]->my_curve=(my_curve_data*)calloc(S_RESULTS,sizeof(my_curve_data)))==NULL )
goto test_multi_curves_exit;
bc[i]->len = 0;
bc[i]->is_open = 0;
bc[i]->c_id = i;
}
if ( (scl=(int*)malloc(S_TESTS*sizeof(int)))==NULL || \
(spiro=(spiro_cp**)calloc(S_TESTS,sizeof(spiro_cp*)))==NULL || \
(nextknot=(int**)calloc(S_TESTS,sizeof(int*)))==NULL )
goto test_multi_curves_exit;
for (i=0; i < S_TESTS; ) {
if ( (spiro[i]=malloc(cl[0]*sizeof(spiro_cp)))==NULL || \
(nextknot[i]=calloc(cl[0],sizeof(int)))==NULL )
goto test_multi_curves_exit;
load_test_curve(spiro[i],nextknot[i],0);
scl[i++]=cl[0];
if ( (spiro[i]=malloc(cl[1]*sizeof(spiro_cp)))==NULL || \
(nextknot[i]=calloc(cl[1],sizeof(int)))==NULL )
goto test_multi_curves_exit;
load_test_curve(spiro[i],nextknot[i],1);
scl[i++]=cl[1];
if ( (spiro[i]=malloc(cl[2]*sizeof(spiro_cp)))==NULL || \
(nextknot[i]=calloc(cl[2],sizeof(int)))==NULL )
goto test_multi_curves_exit;
load_test_curve(spiro[i],nextknot[i],2);
scl[i++]=cl[2];
if ( (spiro[i]=malloc(cl[5]*sizeof(spiro_cp)))==NULL || \
(nextknot[i]=calloc(cl[5],sizeof(int)))==NULL )
goto test_multi_curves_exit;
load_test_curve(spiro[i],nextknot[i],5);
scl[i++]=cl[5];
if ( (spiro[i]=malloc(cl[6]*sizeof(spiro_cp)))==NULL || \
(nextknot[i]=calloc(cl[6],sizeof(int)))==NULL )
goto test_multi_curves_exit;
load_test_curve(spiro[i],nextknot[i],6);
scl[i++]=cl[6];
}
for (i=0; i < S_TESTS; i++) {
temp = spiro[i];
for (j=0; j < scl[i]; j++) {
if ( i&1 ) {
temp[j].x = temp[j].x * (i/S_TESTS+1) + i;
temp[j].y = temp[j].y * (i/S_TESTS+1) + i;
} else {
temp[j].x *= (i+1); temp[j].x += i*1000. - 5000.;
temp[j].y *= (i+1); temp[j].y += i*3000. - 9000.;
}
}
}
--ret;
#ifdef HAVE_PTHREADS
for (i=0; i < S_TESTS; i++) {
pdata[i].spiro = spiro[i];
pdata[i].bc = (bezctx*)(bc[i]);
pdata[i].ret = i;
}
j=0;
for (k=0; k < S_TESTS;) {
pthread_attr_init(&tattr);
pthread_attr_setdetachstate(&tattr,PTHREAD_CREATE_JOINABLE);
for (i=k; i < S_TESTS-1; i++) {
if ( pthread_create(&curve_test[i],&tattr,test_a_curve,(void *)&pdata[i]) ) {
if ( i-k < 20 ) {
printf("bad pthread_create[%d]\n",i);
j=-1;
}
break;
}
}
pthread_attr_destroy(&tattr);
if ( j!=-1 ) {
pdata[i].ret = TaggedSpiroCPsToBezier2(pdata[i].spiro,0,pdata[i].bc);
printf("running simultaneous threads[%d..%d]\n",k,i);
}
l=i;
while (--i >= k)
if ( pthread_join(curve_test[i],NULL) ) {
fprintf(stderr,"bad pthread_join[%d]\n",i);
j=-1;
}
k=++l;
if (j) goto test_multi_curves_exit;
}
for (i=0; i < S_TESTS; i++)
if ( pdata[i].ret!=1 ) {
ret=ret-i;
fprintf(stderr,"error %d with TaggedSpiroCPsToBezier2() using data=%d.\n",ret,i);
goto test_multi_curves_exit;
}
#else
for (i=0; i < S_TESTS; i++) {
if ( TaggedSpiroCPsToBezier0(spiro[i],(bezctx*)(bc[i]))!=1 ) {
ret=ret-i;
fprintf(stderr,"error %d with TaggedSpiroCPsToBezier0() using data=%d.\n",ret,i);
goto test_multi_curves_exit;
}
}
#endif
ret=ret-S_TESTS;
for (i=0; i < S_TESTS; i++) {
temp = spiro[i];
pk = nextknot[i];
k=0;
#ifdef VERBOSE
printf("test[%d], input spiro[0..%d], output bc->my_curve[0..%d]\n", \
i, scl[i]-1, bc[i]->len-1);
#endif
for (j=l=0; j < scl[i] && temp[j].ty!='z'; j++,l++) {
if (temp[j].ty=='h') {
#ifdef VERBOSE
printf(" s[%d][ty=%c x=%g y=%g] is handle 'h' to anchor 'a'.\n", \
l-1,temp[j].ty,temp[j].x,temp[j].y);
#endif
--l;
} else {
ty = bc[i]->my_curve[k].ty;
x = bc[i]->my_curve[k].x1;
y = bc[i]->my_curve[k].y1;
if ( ty=='q' ) {
x = bc[i]->my_curve[k].x2;
y = bc[i]->my_curve[k].y2;
}
if ( ty=='c' ) {
x = bc[i]->my_curve[k].x3;
y = bc[i]->my_curve[k].y3;
}
#ifdef VERBOSE
printf(" s[%d][ty=%c x=%g y=%g], pk=%d mc[%d][x=%g y=%g]\n", \
l,temp[j].ty,temp[j].x,temp[j].y,pk[j],k,x,y);
#endif
if ( (fabs(temp[j].x - x) > 1e-5) || (fabs(temp[j].y - y) > 1e-5) ) {
if ( j == scl[i]-2 && temp[j+1].ty=='z' )
;
else {
ret=ret-i;
fprintf(stderr,"error %d with test_multi_curves() using data %d\n",ret,i);
goto test_multi_curves_exit;
}
}
k += pk[l]+1;
}
}
}
#ifdef HAVE_PTHREADS
printf("Multi-thread testing of libspiro passed.\n");
#else
printf("Sequential tests of libspiro passed.\n");
#endif
ret = 0;
test_multi_curves_exit:
if ( nextknot!=NULL ) for (i=0; i < S_TESTS; i++) free(nextknot[i]);
if ( spiro!=NULL ) for (i=0; i < S_TESTS; i++) free(spiro[i]);
free(nextknot); free(spiro); free(scl);
if ( bc!=NULL ) for (i=0; i < S_TESTS; i++) {
free(bc[i]->my_curve); free(bc[i]);
}
free(bc);
return ret;
}
#endif
int main(int argc, char **argv) {
double st, en;
int ret;
st = get_time();
#ifdef DO_CALL_TEST0
ret=test_curve(0);
#endif
#ifdef DO_CALL_TEST1
ret=test_curve(1);
#endif
#ifdef DO_CALL_TEST2
ret=test_curve(2);
#endif
#ifdef DO_CALL_TEST3
if ( (ret=test_curve(3)==0) )
ret = -1 ;
else
ret = 0;
#endif
#ifdef DO_CALL_TEST4
ret=test_curve(4);
#endif
#ifdef DO_CALL_TEST5
ret=test_curve(5);
#endif
#ifdef DO_CALL_TEST6
ret=test_curve(6);
#endif
#ifdef DO_CALL_TEST7
ret=test_curve(7);
#endif
#ifdef DO_CALL_TEST8
ret=test_curve(8);
#endif
#ifdef DO_CALL_TEST9
ret=test_curve(9);
#endif
#ifdef DO_CALL_TEST10
ret=test_curve(10);
ret = 0;
#endif
#ifdef DO_CALL_TEST11
ret=test_curve(11);
ret = 0;
#endif
#ifdef DO_CALL_TEST12
ret=test_curve(12);
#endif
#ifdef DO_CALL_TEST13
ret=test_curve(13);
#endif
#ifdef DO_CALL_TEST14
ret=test_curve(14);
#endif
#ifdef DO_CALL_TEST15
ret=test_curve(15);
#endif
#ifdef DO_CALL_TEST16
ret=test_curve(16);
#endif
#ifdef DO_CALL_TEST17
ret=test_curve(17);
#endif
#ifdef DO_CALL_TEST18
ret=test_curve(18);
#endif
#ifdef DO_CALL_TEST19
ret=test_curve(19);
#endif
#ifdef DO_CALL_TEST20
if ( (ret=test_curve(20))==0 )
if ( (ret=test_curve(21))==0 )
if ( (ret=test_curve(22))==0 )
if ( (ret=test_curve(23))==0 )
ret=test_curve(24);
#endif
#ifdef DO_CALL_TESTM
ret=test_multi_curves();
#endif
en = get_time();
printf("time %g\n", (en - st));
return ret;
}