Example #1
0
static spiro_seg *
setup_path(const spiro_cp *src, int n)
{
    int n_seg = src[0].ty == '{' ? n - 1 : n;
    spiro_seg *r = (spiro_seg *)malloc((n_seg + 1) * sizeof(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].ty = src[i].ty;
	r[i].ks[0] = 0.;
	r[i].ks[1] = 0.;
	r[i].ks[2] = 0.;
	r[i].ks[3] = 0.;
    }
    r[n_seg].x = src[n_seg % n].x;
    r[n_seg].y = src[n_seg % n].y;
    r[n_seg].ty = src[n_seg % n].ty;

    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;
	r[i].seg_ch = hypot(dx, dy);
	r[i].seg_th = atan2(dy, dx);
    }

    ilast = n_seg - 1;
    for (i = 0; i < n_seg; i++) {
	if (r[i].ty == '{' || r[i].ty == '}' || r[i].ty == 'v')
	    r[i].bend_th = 0.;
	else
	    r[i].bend_th = mod_2pi(r[i].seg_th - r[ilast].seg_th);
	ilast = i;
    }
    return r;
}
Example #2
0
static double
spiro_iter(spiro_seg *s, bandmat *m, int *perm, double *v, int n, int nmat)
{
    int cyclic, i, j, jthl, jthr, jk0l, jk0r, jk1l, jk1r, jk2l, jk2r, jinc, jj, k, n_invert;
    char ty0, ty1;
    double dk, norm, th;
    double ends[2][4];
    double derivs[4][2][4];

    cyclic = s[0].ty != '{' && s[0].ty != 'v';

    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')
	jj = nmat - 2;
    else if (s[0].ty == 'c')
	jj = nmat - 1;
    else
	jj = 0;
    for (i = 0; i < n; i++) {
	ty0 = s[i].ty;
	ty1 = s[i + 1].ty;
	jinc = compute_jinc(ty0, ty1);
	th = s[i].bend_th;
	jthl = jk0l = jk1l = jk2l = -1;
	jthr = jk0r = jk1r = jk2r = -1;

	compute_pderivs(&s[i], ends, derivs, jinc);

	/* constraints crossing left */
	if (ty0 == 'o' || ty0 == 'c' || ty0 == '[' || ty0 == ']' || \
	    ty0 == 'a' || ty0 == 'h') {
	    jthl = jj++;
	    jj %= nmat;
	    jk0l = jj++;
	    if (ty0 == 'o') {
		jj %= nmat;
		jk1l = jj++;
		jk2l = jj++;
	    }
	}

	/* constraints on left */
	if ((ty0 == '[' || ty0 == 'v' || ty0 == '{' || ty0 == 'c' || \
	     ty0 == 'a') && jinc == 4) {
	    if (ty0 != 'c')
		jk1l = jj++;
	    jk2l = jj++;
	}

	/* constraints on right */
	if ((ty1 == ']' || ty1 == 'v' || ty1 == '}' || ty1 == 'c' || \
	     ty1 == 'h') && jinc == 4) {
	    if (ty1 != 'c')
		jk1r = jj++;
	    jk2r = jj++;
	}

	/* constraints crossing right */
	if (ty1 == 'o' || ty1 == 'c' || ty1 == '[' || ty1 == ']' || \
	    ty1 == 'a' || ty1 == 'h') {
	    jthr = jj;
	    jk0r = (jj + 1) % nmat;
	    if (ty1 == 'o') {
		jk1r = (jj + 2) % nmat;
		jk2r = (jj + 3) % nmat;
	    }
	}

	add_mat_line(m, v, derivs[0][0], th - ends[0][0], 1, j, jthl, jinc, nmat);
	add_mat_line(m, v, derivs[1][0], ends[0][1], -1, j, jk0l, jinc, nmat);
	add_mat_line(m, v, derivs[2][0], ends[0][2], -1, j, jk1l, jinc, nmat);
	add_mat_line(m, v, derivs[3][0], ends[0][3], -1, j, jk2l, jinc, nmat);
	add_mat_line(m, v, derivs[0][1], -ends[1][0], 1, j, jthr, jinc, nmat);
	add_mat_line(m, v, derivs[1][1], -ends[1][1], 1, j, jk0r, jinc, nmat);
	add_mat_line(m, v, derivs[2][1], -ends[1][2], 1, j, jk1r, jinc, nmat);
	add_mat_line(m, v, derivs[3][1], -ends[1][3], 1, j, jk2r, jinc, nmat);
	if (jthl >= 0)
	    v[jthl] = mod_2pi(v[jthl]);
	if (jthr >= 0)
	    v[jthr] = mod_2pi(v[jthr]);
	j += jinc;
    }
    if (cyclic) {
	memcpy(m + nmat, m, sizeof(bandmat) * nmat);
	memcpy(m + 2 * nmat, m, sizeof(bandmat) * nmat);
	memcpy(v + nmat, v, sizeof(double) * nmat);
	memcpy(v + 2 * nmat, v, sizeof(double) * nmat);
	n_invert = 3 * nmat;
	j = nmat;
#ifdef VERBOSE
	printf("cyclic\n");
#endif
    } else {
	n_invert = nmat;
	j = 0;
    }

#ifdef VERBOSE
    for (i = 0; i < n; i++) {
	for (k = 0; k < 11; k++)
	    printf(" %2.4f", m[i].a[k]);
	printf(": %2.4f\n", v[i]);
    }
    printf("---\n");
#endif
    bandec11(m, perm, n_invert);
    banbks11(m, perm, v, n_invert);
    norm = 0.;
    for (i = 0; i < n; i++) {
	jinc = compute_jinc(s[i].ty, s[i + 1].ty);

	for (k = 0; k < jinc; k++) {
	    dk = v[j++];

#ifdef VERBOSE
	    printf("s[%d].ks[%d] += %f\n", i, k, dk);
#endif
	    s[i].ks[k] += dk;
	    norm += dk * dk;
	}
        s[i].ks[0] = 2.0 * mod_2pi(s[i].ks[0]/2.0);
    }
    return norm;
}
Example #3
0
static spiro_seg *
setup_path0(const spiro_cp *src, double *dm, int n)
{
    int i, ilast, n_seg;
    double dx, dy;
    double xmin, xmax, ymin, ymax;
    spiro_seg *r;

    if (src[0].ty == 'h' || src[n - 1].ty == 'a') { /* pair */
#ifdef VERBOSE
	fprintf(stderr, "ERROR: LibSpiro: cannot use cp type 'h' as start, or 'a' as end.\n");
#endif
	return 0;
    }

#ifdef CHECK_INPUT_FINITENESS
    /* Verify that input values are within realistic limits */
    for (i = 0; i < n; i++) {
	if (IS_FINITE(src[i].x)==0 || IS_FINITE(src[i].y)==0) {
#ifdef VERBOSE
	    fprintf(stderr, "ERROR: LibSpiro: #%d={'%c',%g,%g} is not finite.\n", \
		    i, src[i].ty, src[i].x, src[i].y);
#endif
	    return 0;
	}
    }
#endif

    n_seg = src[0].ty == '{' ? n - 1 : n;
    r = (spiro_seg *)malloc((n_seg + 1) * sizeof(spiro_seg));
    if (r==NULL) return 0;

    if (dm[0] < 0.9) {
	/* for math to be scalable fit it within -0.5..+0.5 */
	xmin = xmax = src[0].x; ymin = ymax = src[0].y;
	for (i = 0; i < n_seg; i++) {
	    if (src[i].ty != 'z' && src[i].ty != 'h') {
		if (src[i].x < xmin) xmin = src[i].x; else
		if (src[i].x > xmax) xmax = src[i].x;
		if (src[i].y < ymin) ymin = src[i].y; else
		if (src[i].y > ymax) ymax = src[i].y;
	    }
	}
	dm[1] /* xoff */ = (xmin + xmax) / 2; xmax -= xmin;
	dm[2] /* yoff */ = (ymin + ymax) / 2; ymax -= ymin;
	dm[0] /* scale */ = fabs((fabs(xmax) >= fabs(ymax)) ? xmax : ymax);
	if (xmax >= ymax) dm[0] = xmax; else dm[0] = ymax;
	dm[0] /* scale */ /= 500.; /* ~ backwards compatible */
	/* set_dm_to_1(dm); testing */
    }
#ifdef VERBOSE
	printf("scale=%g, x_offset=%g, y_offset=%g\n", dm[0], dm[1], dm[2]);
#endif
//    }

    for (i = 0; i < n_seg; i++) {
	r[i].x = (src[i].x - dm[1]) / dm[0];
	r[i].y = (src[i].y - dm[2]) / dm[0];
	r[i].ty = src[i].ty;
	r[i].ks[0] = 0.;
	r[i].ks[1] = 0.;
	r[i].ks[2] = 0.;
	r[i].ks[3] = 0.;
    }
    r[n_seg].x = (src[n_seg % n].x - dm[1]) / dm[0];
    r[n_seg].y = (src[n_seg % n].y - dm[2]) / dm[0];
    r[n_seg].ty = src[n_seg % n].ty;

    for (i = 0; i < n_seg; i++) {
	if (r[i].ty == 'h' || (i == n_seg-1 && i > 0 && r[i].ty == '}' && r[i - 1].ty == 'a')) {
	    /* behave like a disconnected pair of '[' & ']' */
	    /* point 'a' holds vector to old 'h' and now we */
	    /* change x,y here to be the same as point 'a'. */
	    /* curve fitting is based on vectors and angles */
	    /* but final curves will be based on x,y points */
	    r[i].x = r[i - 1].x;
	    r[i].y = r[i - 1].y;
	}
	dx = r[i + 1].x - r[i].x;
	dy = r[i + 1].y - r[i].y;
#ifndef CHECK_INPUT_FINITENESS
	r[i].seg_ch = hypot(dx, dy);
#else
	if (IS_FINITE(dx)==0 || IS_FINITE(dy)==0 || \
	    IS_FINITE((r[i].seg_ch = hypot(dx, dy)))==0) {
#ifdef VERBOSE
	    fprintf(stderr, "ERROR: LibSpiro: #%d={'%c',%g,%g} hypot error.\n", \
		    i, src[i].ty, src[i].x, src[i].y);
#endif
	    free(r);
	    return 0;
	}
#endif
	r[i].seg_th = atan2(dy, dx);
    }

    ilast = n_seg - 1;
    for (i = 0; i < n_seg; i++) {
	if (r[i].ty == '{' || r[i].ty == '}' || r[i].ty == 'v')
	    r[i].bend_th = 0.;
	else
	    r[i].bend_th = mod_2pi(r[i].seg_th - r[ilast].seg_th);
	ilast = i;
#ifdef VERBOSE
	printf("input #%d={'%c',%g=>%g,%g=>%g}, hypot=%g, atan2=%g, bend_th=%g\n", \
		    i, src[i].ty, src[i].x, r[i].x, src[i].y, r[i].y, r[i].seg_ch, r[i].seg_th, r[i].bend_th);
#endif
    }
#ifdef VERBOSE
    if (n_seg < n)
	printf("input #%d={'%c',%g=>%g,%g=>%g}\n", i, src[i].ty, src[i].x, r[i].x, src[i].y, r[i].y);
#endif
    return r;
}
Example #4
0
static spiro_seg *
setup_path(const spiro_cp *src, int n)
{
    int i, ilast, n_seg;
    double dx, dy;
    spiro_seg *r;

#ifdef CHECK_INPUT_FINITENESS
    /* Verify that input values are within realistic limits */
    for (i = 0; i < n; i++) {
	if (IS_FINITE(src[i].x)==0 || IS_FINITE(src[i].y)==0) {
#ifdef VERBOSE
	    fprintf(stderr, "ERROR: LibSpiro: #%d={'%c',%g,%g} is not finite.\n", \
		    i, src[i].ty, src[i].x, src[i].y);
#endif
	    return 0;
	}
    }
#endif

    n_seg = src[0].ty == '{' ? n - 1 : n;
    r = (spiro_seg *)malloc((n_seg + 1) * sizeof(spiro_seg));
    if ( r==NULL ) return 0;

    for (i = 0; i < n_seg; i++) {
	r[i].x = src[i].x;
	r[i].y = src[i].y;
	r[i].ty = src[i].ty;
	r[i].ks[0] = 0.;
	r[i].ks[1] = 0.;
	r[i].ks[2] = 0.;
	r[i].ks[3] = 0.;
    }
    r[n_seg].x = src[n_seg % n].x;
    r[n_seg].y = src[n_seg % n].y;
    r[n_seg].ty = src[n_seg % n].ty;

    for (i = 0; i < n_seg; i++) {
	dx = r[i + 1].x - r[i].x;
	dy = r[i + 1].y - r[i].y;
#ifndef CHECK_INPUT_FINITENESS
	r[i].seg_ch = hypot(dx, dy);
#else
	if (IS_FINITE(dx)==0 || IS_FINITE(dy)==0 || \
	    IS_FINITE((r[i].seg_ch = hypot(dx, dy)))==0) {
#ifdef VERBOSE
	    fprintf(stderr, "ERROR: LibSpiro: #%d={'%c',%g,%g} hypot error.\n", \
		    i, src[i].ty, r[i].x, r[i].y);
#endif
	    free(r);
	    return 0;
	}
#endif
	r[i].seg_th = atan2(dy, dx);
    }

    ilast = n_seg - 1;
    for (i = 0; i < n_seg; i++) {
	if (r[i].ty == '{' || r[i].ty == '}' || r[i].ty == 'v')
	    r[i].bend_th = 0.;
	else
	    r[i].bend_th = mod_2pi(r[i].seg_th - r[ilast].seg_th);
	ilast = i;
#ifdef VERBOSE
	printf("input #%d={'%c',%g,%g}, hypot=%g, atan2=%g, bend_th=%g\n", \
		    i, src[i].ty, r[i].x, r[i].y, r[i]. seg_th, r[i].seg_th, r[i].bend_th);
#endif
    }
#ifdef VERBOSE
    if (n_seg < n)
	printf("input #%d={'%c',%g,%g}\n", i, src[i].ty, r[i].x, r[i].y);
#endif
    return r;
}