示例#1
0
static int
sp_spiral_snappoints (SPItem *item, NRPointF *p, int size)
{
#if 0
	/* fixme: (Lauris) */
	SPSpiral *spiral;
	ArtPoint * p, p1, p2, p3;
	gdouble affine[6];
	
	spiral = SP_SPIRAL(item);
	
	sp_spiral_get_xy (spiral, 0.0, &p1);
	sp_spiral_get_xy (spiral, spiral->t0, &p2);
	sp_spiral_get_xy (spiral, 1.0, &p3);
	
	sp_item_i2d_affine (item, affine);
	
	p = g_new (ArtPoint,1);
	art_affine_point (p, &p1, affine);
	points = g_slist_append (points, p);
	
	p = g_new (ArtPoint,1);
	art_affine_point (p, &p2, affine);
	points = g_slist_append (points, p);
	
	p = g_new (ArtPoint,1);
	art_affine_point (p, &p3, affine);
	points = g_slist_append (points, p);
#else
	if (((SPItemClass *) parent_class)->snappoints)
		return ((SPItemClass *) parent_class)->snappoints (item, p, size);
#endif
	
	return 0;
}
示例#2
0
Geom::Point
SpiralKnotHolderEntityOuter::knot_get() const
{
    SPSpiral const *spiral = SP_SPIRAL(item);

    return spiral->getXY(1.0);
}
示例#3
0
static SPRepr *
sp_spiral_write (SPObject *object, SPRepr *repr, guint flags)
{
	SPSpiral *spiral;
	char *d;

	spiral = SP_SPIRAL (object);

	if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) {
		repr = sp_repr_new ("path");
	}

	if (flags & SP_OBJECT_WRITE_EXT) {
		/* Fixme: we may replace these attributes by
		 * sodipodi:spiral="cx cy exp revo rad arg t0"
		 */
		sp_repr_set_attr (repr, "sodipodi:type", "spiral");
		sp_repr_set_double_attribute (repr, "sodipodi:cx", spiral->cx);
		sp_repr_set_double_attribute (repr, "sodipodi:cy", spiral->cy);
		sp_repr_set_double_attribute (repr, "sodipodi:expansion", spiral->exp);
		sp_repr_set_double_attribute (repr, "sodipodi:revolution", spiral->revo);
		sp_repr_set_double_attribute (repr, "sodipodi:radius", spiral->rad);
		sp_repr_set_double_attribute (repr, "sodipodi:argument", spiral->arg);
		sp_repr_set_double_attribute (repr, "sodipodi:t0", spiral->t0);
	}

	d = sp_svg_write_path (((SPShape *) spiral)->curve->bpath);
	sp_repr_set_attr (repr, "d", d);
	g_free (d);

	if (((SPObjectClass *) (parent_class))->write)
		((SPObjectClass *) (parent_class))->write (object, repr, flags | SP_SHAPE_WRITE_PATH);

	return repr;
}
示例#4
0
void
SpiralKnotHolderEntityInner::knot_click(guint state)
{
    SPSpiral *spiral = SP_SPIRAL(item);

    if (state & GDK_MOD1_MASK) {
        spiral->exp = 1;
        (static_cast<SPObject *>(spiral))->updateRepr();
    } else if (state & GDK_SHIFT_MASK) {
        spiral->t0 = 0;
        (static_cast<SPObject *>(spiral))->updateRepr();
    }
}
示例#5
0
/*
 * set attributes via inner (t=t0) knot point:
 *   [default] increase/decrease inner point
 *   [shift]   increase/decrease inner and outer arg synchronizely
 *   [control] constrain inner arg to round per PI/4
 */
void
SpiralKnotHolderEntityInner::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;

    gdouble   moved_y = p[Geom::Y] - origin[Geom::Y];

    if (state & GDK_MOD1_MASK) {
        // adjust divergence by vertical drag, relative to rad
        if (spiral->rad > 0) {
            double exp_delta = 0.1*moved_y/(spiral->rad); // arbitrary multiplier to slow it down
            spiral->exp += exp_delta;
            if (spiral->exp < 1e-3)
                spiral->exp = 1e-3;
        }
    } else {
        // roll/unroll from inside
        gdouble   arg_t0;
        spiral->getPolar(spiral->t0, NULL, &arg_t0);

        gdouble   arg_tmp = atan2(dy, dx) - arg_t0;
        gdouble   arg_t0_new = arg_tmp - floor((arg_tmp+M_PI)/(2.0*M_PI))*2.0*M_PI + arg_t0;
        spiral->t0 = (arg_t0_new - spiral->arg) / (2.0*M_PI*spiral->revo);

        /* round inner arg per PI/snaps, if CTRL is pressed */
        if ( ( state & GDK_CONTROL_MASK )
                && ( fabs(spiral->revo) > SP_EPSILON_2 )
                && ( snaps != 0 ) ) {
            gdouble arg = 2.0*M_PI*spiral->revo*spiral->t0 + spiral->arg;
            spiral->t0 = (sp_round(arg, M_PI/snaps) - spiral->arg)/(2.0*M_PI*spiral->revo);
        }

        spiral->t0 = CLAMP(spiral->t0, 0.0, 0.999);
    }

    (static_cast<SPObject *>(spiral))->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
}
示例#6
0
static void
sp_spiral_finish(SPSpiralContext *sc)
{
    sc->_message_context->clear();

    if (sc->item != NULL) {
        SPDesktop *desktop = SP_EVENT_CONTEXT(sc)->desktop;
        SPSpiral  *spiral = SP_SPIRAL(sc->item);

        sp_shape_set_shape(SP_SHAPE(spiral));
        SP_OBJECT(spiral)->updateRepr(SP_OBJECT_WRITE_EXT);

        sp_canvas_end_forced_full_redraws(desktop->canvas);

        sp_desktop_selection(desktop)->set(sc->item);
        sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_SPIRAL, 
                         _("Create spiral"));

        sc->item = NULL;
    }
}
示例#7
0
static void
sp_spiral_set_shape (SPShape *shape)
{
	SPSpiral *spiral;
	NRPointF darray[SAMPLE_SIZE + 1];
	NRPointF hat1, hat2;
	int i;
	double tstep, t;
	double dstep, d;
	SPCurve *c;

	spiral = SP_SPIRAL(shape);

	sp_object_request_modified (SP_OBJECT (spiral), SP_OBJECT_MODIFIED_FLAG);

#if 0
	if (spiral->rad < SP_EPSILON) return;
#endif
	
	c = sp_curve_new ();
	
#ifdef SPIRAL_VERBOSE
	g_print ("ex=%g, revo=%g, rad=%g, arg=%g, t0=%g\n",
		 spiral->cx,
		 spiral->cy,
		 spiral->exp,
		 spiral->revo,
		 spiral->rad,
		 spiral->arg,
		 spiral->t0);
#endif
	
	tstep = SAMPLE_STEP/spiral->revo;
	dstep = tstep/(SAMPLE_SIZE - 1.0);

	if (spiral->t0 - dstep >= 0.0) {
		for (d = spiral->t0 - dstep, i = 0; i <= 2; d += dstep, i++)
			sp_spiral_get_xy (spiral, d, &darray[i]);

		sp_darray_center_tangent (darray, 1, &hat1);
		hat1.x = - hat1.x;
		hat1.y = - hat1.y;
	} else {
		for (d = spiral->t0, i = 1; i <= 2; d += dstep, i++)
			sp_spiral_get_xy (spiral, d, &darray[i]);

		sp_darray_left_tangent (darray, 1, 2, &hat1);
	}

	sp_curve_moveto (c, darray[1].x, darray[1].y);

	for (t = spiral->t0; t < (1.0-tstep); t += tstep)
	{
		sp_spiral_fit_and_draw (spiral, c, dstep, darray, &hat1, &hat2, t);

		hat1.x = - hat2.x;
		hat1.y = - hat2.y;
	}
	if ((1.0 - t) > SP_EPSILON)
		sp_spiral_fit_and_draw (spiral, c, (1.0 - t)/(SAMPLE_SIZE - 1.0),
					darray, &hat1, &hat2, t);
  
	sp_shape_set_curve_insync ((SPShape *) spiral, c, TRUE);
	sp_curve_unref (c);
}
示例#8
0
static void
sp_spiral_set (SPObject *object, unsigned int key, const gchar *value)
{
	SPSpiral *spiral;
	SPShape  *shape;
	gulong unit;

	spiral = SP_SPIRAL (object);
	shape  = SP_SHAPE (object);

	/* fixme: we should really collect updates */
	switch (key) {
	case SP_ATTR_SODIPODI_CX:
		if (!sp_svg_length_read_lff (value, &unit, NULL, &spiral->cx) ||
		    (unit == SP_SVG_UNIT_EM) ||
		    (unit == SP_SVG_UNIT_EX) ||
		    (unit == SP_SVG_UNIT_PERCENT)) {
			spiral->cx = 0.0;
		}
		sp_object_request_update (object, SP_OBJECT_MODIFIED_FLAG);
		break;
	case SP_ATTR_SODIPODI_CY:
		if (!sp_svg_length_read_lff (value, &unit, NULL, &spiral->cy) ||
		    (unit == SP_SVG_UNIT_EM) ||
		    (unit == SP_SVG_UNIT_EX) ||
		    (unit == SP_SVG_UNIT_PERCENT)) {
			spiral->cy = 0.0;
		}
		sp_object_request_update (object, SP_OBJECT_MODIFIED_FLAG);
		break;
	case SP_ATTR_SODIPODI_EXPANSION:
		if (value) {
			spiral->exp = atof (value);
			spiral->exp = CLAMP (spiral->exp, 0.0, 1000.0);
		} else {
			spiral->exp = 1.0;
		}
		sp_object_request_update (object, SP_OBJECT_MODIFIED_FLAG);
		break;
	case SP_ATTR_SODIPODI_REVOLUTION:
		if (value) {
			spiral->revo = atof (value);
			spiral->revo = CLAMP (spiral->revo, 0.05, 20.0);
		} else {
			spiral->revo = 3.0;
		}
		sp_object_request_update (object, SP_OBJECT_MODIFIED_FLAG);
		break;
	case SP_ATTR_SODIPODI_RADIUS:
		if (!sp_svg_length_read_lff (value, &unit, NULL, &spiral->rad) ||
		    (unit != SP_SVG_UNIT_EM) ||
		    (unit != SP_SVG_UNIT_EX) ||
		    (unit != SP_SVG_UNIT_PERCENT)) {
			spiral->rad = MAX (spiral->rad, 0.001);
		}
		sp_object_request_update (object, SP_OBJECT_MODIFIED_FLAG);
		break;
	case SP_ATTR_SODIPODI_ARGUMENT:
		if (value) {
			spiral->arg = atof (value);
		} else {
			spiral->arg = 0.0;
		}
		sp_object_request_update (object, SP_OBJECT_MODIFIED_FLAG);
		break;
	case SP_ATTR_SODIPODI_T0:
		if (value) {
			spiral->t0 = atof (value);
			spiral->t0 = CLAMP (spiral->t0, -1.0, 0.999);
		} else {
			spiral->t0 = 0.0;
		}
		sp_object_request_update (object, SP_OBJECT_MODIFIED_FLAG);
		break;
	default:
		if (((SPObjectClass *) parent_class)->set)
			((SPObjectClass *) parent_class)->set (object, key, value);
		break;
	}
}
示例#9
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);
}
示例#10
0
static void
sp_spiral_drag(SPSpiralContext *sc, Geom::Point p, guint state)
{
    SPDesktop *desktop = SP_EVENT_CONTEXT(sc)->desktop;

    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
    int const snaps = prefs->getInt("/options/rotationsnapsperpi/value", 12);

    if (!sc->item) {

        if (Inkscape::have_viable_layer(desktop, sc->_message_context) == false) {
            return;
        }

        /* Create object */
        Inkscape::XML::Document *xml_doc = sp_document_repr_doc(SP_EVENT_CONTEXT_DOCUMENT(sc));
        Inkscape::XML::Node *repr = xml_doc->createElement("svg:path");
        repr->setAttribute("sodipodi:type", "spiral");

        /* Set style */
        sp_desktop_apply_style_tool(desktop, repr, "/tools/shapes/spiral", false);

        sc->item = (SPItem *) desktop->currentLayer()->appendChildRepr(repr);
        Inkscape::GC::release(repr);
        sc->item->transform = sp_item_i2doc_affine(SP_ITEM(desktop->currentLayer())).inverse();
        sc->item->updateRepr();

        sp_canvas_force_full_redraw_after_interruptions(desktop->canvas, 5);
    }

    SnapManager &m = desktop->namedview->snap_manager;
    m.setup(desktop, true, sc->item);
    Geom::Point pt2g = to_2geom(p);
    m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, pt2g);

    Geom::Point const p0 = to_2geom(sp_desktop_dt2doc_xy_point(desktop, sc->center));
    Geom::Point const p1 = to_2geom(sp_desktop_dt2doc_xy_point(desktop, from_2geom(pt2g)));        
    
    SPSpiral *spiral = SP_SPIRAL(sc->item);

    Geom::Point const delta = p1 - p0;
    gdouble const rad = Geom::L2(delta);

    gdouble arg = Geom::atan2(delta) - 2.0*M_PI*spiral->revo;

    if (state & GDK_CONTROL_MASK) {
        arg = sp_round(arg, M_PI/snaps);
    }

    /* Fixme: these parameters should be got from dialog box */
    sp_spiral_position_set(spiral, p0[Geom::X], p0[Geom::Y],
                           /*expansion*/ sc->exp,
                           /*revolution*/ sc->revo,
                           rad, arg,
                           /*t0*/ sc->t0);

    /* status text */
    GString *rads = SP_PX_TO_METRIC_STRING(rad, desktop->namedview->getDefaultMetric());
    sc->_message_context->setF(Inkscape::IMMEDIATE_MESSAGE,
                               _("<b>Spiral</b>: radius %s, angle %5g&#176;; with <b>Ctrl</b> to snap angle"),
                               rads->str, sp_round((arg + 2.0*M_PI*spiral->revo)*180/M_PI, 0.0001));
    g_string_free(rads, FALSE);
}