Пример #1
0
void bezctx_ink_lineto(bezctx *bc, double x, double y)
{
    bezctx_ink *bi = (bezctx_ink *) bc;
    if ( IS_FINITE(x) && IS_FINITE(y) ) {
        bi->curve->lineto(x, y);
    }
#ifdef SPIRO_SHOW_INFINITE_COORDINATE_CALLS
    else {
        g_message("lpe lineto not finite");
    }
#endif
}
Пример #2
0
void bezctx_ink_curveto(bezctx *bc, double x1, double y1, double x2, double y2,
		    double x3, double y3)
{
    bezctx_ink *bi = (bezctx_ink *) bc;
    if ( IS_FINITE(x1) && IS_FINITE(y1) && IS_FINITE(x2) && IS_FINITE(y2) ) {
        bi->curve->curveto(x1, y1, x2, y2, x3, y3);
    }
#ifdef SPIRO_SHOW_INFINITE_COORDINATE_CALLS
    else {
        g_message("lpe curveto not finite");
    }
#endif
}
Пример #3
0
void bezctx_ink_quadto(bezctx *bc, double xm, double ym, double x3, double y3)
{
    bezctx_ink *bi = (bezctx_ink *) bc;

    if ( IS_FINITE(xm) && IS_FINITE(ym) && IS_FINITE(x3) && IS_FINITE(y3) ) {
        bi->curve->quadto(xm, ym, x3, y3);
    }
#ifdef SPIRO_SHOW_INFINITE_COORDINATE_CALLS
    else {
        g_message("lpe quadto not finite");
    }
#endif
}
Пример #4
0
static int
check_finiteness(spiro_seg * segs, int num_segs)
{
/* Check if all values are "finite", return true=0, else return fail=-1 */
    int i, j;
    for (i = 0; i < num_segs; ++i)
	for (j = 0; j < 4; ++j)
	    if ( IS_FINITE( segs[i].ks[j])==0 ) return -1;
    return 0;
}
Пример #5
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;
}
Пример #6
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;
}
Пример #7
0
/*
 * set attributes via outer (t=1) knot point:
 *   [default] increase/decrease revolution factor
 *   [control] constrain inner arg to round per PI/4
 */
void
SpiralKnotHolderEntityOuter::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state)
{
    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
    int snaps = prefs->getInt("/options/rotationsnapsperpi/value", 12);

    SPSpiral *spiral = SP_SPIRAL(item);

    gdouble  dx = p[Geom::X] - spiral->cx;
    gdouble  dy = p[Geom::Y] - spiral->cy;

    if (state & GDK_SHIFT_MASK) { // rotate without roll/unroll
        spiral->arg = atan2(dy, dx) - 2.0*M_PI*spiral->revo;
        if (!(state & GDK_MOD1_MASK)) {
            // if alt not pressed, change also rad; otherwise it is locked
            spiral->rad = MAX(hypot(dx, dy), 0.001);
        }
        if ( ( state & GDK_CONTROL_MASK )
                && snaps ) {
            spiral->arg = sp_round(spiral->arg, M_PI/snaps);
        }
    } else { // roll/unroll
        // arg of the spiral outer end
        double arg_1;
        spiral->getPolar(1, NULL, &arg_1);

        // its fractional part after the whole turns are subtracted
        double arg_r = arg_1 - sp_round(arg_1, 2.0*M_PI);

        // arg of the mouse point relative to spiral center
        double mouse_angle = atan2(dy, dx);
        if (mouse_angle < 0)
            mouse_angle += 2*M_PI;

        // snap if ctrl
        if ( ( state & GDK_CONTROL_MASK ) && snaps ) {
            mouse_angle = sp_round(mouse_angle, M_PI/snaps);
        }

        // by how much we want to rotate the outer point
        double diff = mouse_angle - arg_r;
        if (diff > M_PI)
            diff -= 2*M_PI;
        else if (diff < -M_PI)
            diff += 2*M_PI;

        // calculate the new rad;
        // the value of t corresponding to the angle arg_1 + diff:
        double t_temp = ((arg_1 + diff) - spiral->arg)/(2*M_PI*spiral->revo);
        // the rad at that t:
        double rad_new = 0;
        if (t_temp > spiral->t0)
            spiral->getPolar(t_temp, &rad_new, NULL);

        // change the revo (converting diff from radians to the number of turns)
        spiral->revo += diff/(2*M_PI);
        if (spiral->revo < 1e-3)
            spiral->revo = 1e-3;

        // if alt not pressed and the values are sane, change the rad
        if (!(state & GDK_MOD1_MASK) && rad_new > 1e-3 && rad_new/spiral->rad < 2) {
            // adjust t0 too so that the inner point stays unmoved
            double r0;
            spiral->getPolar(spiral->t0, &r0, NULL);
            spiral->rad = rad_new;
            spiral->t0 = pow(r0 / spiral->rad, 1.0/spiral->exp);
        }
        if (!IS_FINITE(spiral->t0)) spiral->t0 = 0.0;
        spiral->t0 = CLAMP(spiral->t0, 0.0, 0.999);
    }

    (static_cast<SPObject *>(spiral))->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
}