diff --git a/src/sp-spiral.cpp b/src/sp-spiral.cpp
index 23233d04e1f8921e0a9d6750b1006a0c5504a62a..cfe02947a26af5276f16532be2bea8f2aafb06df 100644 (file)
--- a/src/sp-spiral.cpp
+++ b/src/sp-spiral.cpp
-#define __SP_SPIRAL_C__
-
/** \file
* <sodipodi:spiral> implementation
*/
/** \file
* <sodipodi:spiral> implementation
*/
* Authors:
* Mitsuru Oka <oka326@parkcity.ne.jp>
* Lauris Kaplinski <lauris@kaplinski.com>
* Authors:
* Mitsuru Oka <oka326@parkcity.ne.jp>
* Lauris Kaplinski <lauris@kaplinski.com>
+ * Abhishek Sharma
*
* Copyright (C) 1999-2002 Lauris Kaplinski
* Copyright (C) 2000-2001 Ximian, Inc.
*
* Copyright (C) 1999-2002 Lauris Kaplinski
* Copyright (C) 2000-2001 Ximian, Inc.
#include "svg/svg.h"
#include "attributes.h"
#include "svg/svg.h"
#include "attributes.h"
-#include "display/bezier-utils.h"
+#include <2geom/bezier-utils.h>
+#include <2geom/pathvector.h>
#include "display/curve.h"
#include <glibmm/i18n.h>
#include "xml/repr.h"
#include "display/curve.h"
#include <glibmm/i18n.h>
#include "xml/repr.h"
static void sp_spiral_update (SPObject *object, SPCtx *ctx, guint flags);
static gchar * sp_spiral_description (SPItem * item);
static void sp_spiral_update (SPObject *object, SPCtx *ctx, guint flags);
static gchar * sp_spiral_description (SPItem * item);
-static void sp_spiral_snappoints(SPItem const *item, SnapPointsIter p, Inkscape::SnapPreferences const *snapprefs);
+static void sp_spiral_snappoints(SPItem const *item, std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs);
static void sp_spiral_set_shape (SPShape *shape);
static void sp_spiral_update_patheffect (SPLPEItem *lpeitem, bool write);
static void sp_spiral_set_shape (SPShape *shape);
static void sp_spiral_update_patheffect (SPLPEItem *lpeitem, bool write);
GType
sp_spiral_get_type (void)
{
GType
sp_spiral_get_type (void)
{
- static GType spiral_type = 0;
-
- if (!spiral_type) {
- GTypeInfo spiral_info = {
- sizeof (SPSpiralClass),
- NULL, /* base_init */
- NULL, /* base_finalize */
- (GClassInitFunc) sp_spiral_class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (SPSpiral),
- 16, /* n_preallocs */
- (GInstanceInitFunc) sp_spiral_init,
- NULL, /* value_table */
- };
- spiral_type = g_type_register_static (SP_TYPE_SHAPE, "SPSpiral", &spiral_info, (GTypeFlags)0);
- }
- return spiral_type;
+ static GType spiral_type = 0;
+
+ if (!spiral_type) {
+ GTypeInfo spiral_info = {
+ sizeof (SPSpiralClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) sp_spiral_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (SPSpiral),
+ 16, /* n_preallocs */
+ (GInstanceInitFunc) sp_spiral_init,
+ NULL, /* value_table */
+ };
+ spiral_type = g_type_register_static (SP_TYPE_SHAPE, "SPSpiral", &spiral_info, (GTypeFlags)0);
+ }
+ return spiral_type;
}
/**
}
/**
static void
sp_spiral_class_init (SPSpiralClass *klass)
{
static void
sp_spiral_class_init (SPSpiralClass *klass)
{
- GObjectClass * gobject_class;
- SPObjectClass * sp_object_class;
- SPItemClass * item_class;
- SPLPEItemClass * lpe_item_class;
- SPShapeClass *shape_class;
+ GObjectClass * gobject_class;
+ SPObjectClass * sp_object_class;
+ SPItemClass * item_class;
+ SPLPEItemClass * lpe_item_class;
+ SPShapeClass *shape_class;
- gobject_class = (GObjectClass *) klass;
- sp_object_class = (SPObjectClass *) klass;
- item_class = (SPItemClass *) klass;
- lpe_item_class = (SPLPEItemClass *) klass;
- shape_class = (SPShapeClass *) klass;
+ gobject_class = (GObjectClass *) klass;
+ sp_object_class = (SPObjectClass *) klass;
+ item_class = (SPItemClass *) klass;
+ lpe_item_class = (SPLPEItemClass *) klass;
+ shape_class = (SPShapeClass *) klass;
- parent_class = (SPShapeClass *)g_type_class_ref (SP_TYPE_SHAPE);
+ parent_class = (SPShapeClass *)g_type_class_ref (SP_TYPE_SHAPE);
- sp_object_class->build = sp_spiral_build;
- sp_object_class->write = sp_spiral_write;
- sp_object_class->set = sp_spiral_set;
- sp_object_class->update = sp_spiral_update;
+ sp_object_class->build = sp_spiral_build;
+ sp_object_class->write = sp_spiral_write;
+ sp_object_class->set = sp_spiral_set;
+ sp_object_class->update = sp_spiral_update;
- item_class->description = sp_spiral_description;
- item_class->snappoints = sp_spiral_snappoints;
+ item_class->description = sp_spiral_description;
+ item_class->snappoints = sp_spiral_snappoints;
lpe_item_class->update_patheffect = sp_spiral_update_patheffect;
lpe_item_class->update_patheffect = sp_spiral_update_patheffect;
static void
sp_spiral_init (SPSpiral * spiral)
{
static void
sp_spiral_init (SPSpiral * spiral)
{
- spiral->cx = 0.0;
- spiral->cy = 0.0;
- spiral->exp = 1.0;
- spiral->revo = 3.0;
- spiral->rad = 1.0;
- spiral->arg = 0.0;
- spiral->t0 = 0.0;
+ spiral->cx = 0.0;
+ spiral->cy = 0.0;
+ spiral->exp = 1.0;
+ spiral->revo = 3.0;
+ spiral->rad = 1.0;
+ spiral->arg = 0.0;
+ spiral->t0 = 0.0;
}
/**
}
/**
static void
sp_spiral_build (SPObject * object, SPDocument * document, Inkscape::XML::Node * repr)
{
static void
sp_spiral_build (SPObject * object, SPDocument * document, Inkscape::XML::Node * repr)
{
- if (((SPObjectClass *) parent_class)->build)
- ((SPObjectClass *) parent_class)->build (object, document, repr);
-
- sp_object_read_attr (object, "sodipodi:cx");
- sp_object_read_attr (object, "sodipodi:cy");
- sp_object_read_attr (object, "sodipodi:expansion");
- sp_object_read_attr (object, "sodipodi:revolution");
- sp_object_read_attr (object, "sodipodi:radius");
- sp_object_read_attr (object, "sodipodi:argument");
- sp_object_read_attr (object, "sodipodi:t0");
+ if (((SPObjectClass *) parent_class)->build)
+ ((SPObjectClass *) parent_class)->build (object, document, repr);
+
+ object->readAttr( "sodipodi:cx" );
+ object->readAttr( "sodipodi:cy" );
+ object->readAttr( "sodipodi:expansion" );
+ object->readAttr( "sodipodi:revolution" );
+ object->readAttr( "sodipodi:radius" );
+ object->readAttr( "sodipodi:argument" );
+ object->readAttr( "sodipodi:t0" );
}
/**
}
/**
@@ -143,25 +143,25 @@ sp_spiral_build (SPObject * object, SPDocument * document, Inkscape::XML::Node *
static Inkscape::XML::Node *
sp_spiral_write (SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags)
{
static Inkscape::XML::Node *
sp_spiral_write (SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags)
{
- SPSpiral *spiral = SP_SPIRAL (object);
-
- if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) {
- repr = xml_doc->createElement("svg:path");
- }
-
- if (flags & SP_OBJECT_WRITE_EXT) {
- /* Fixme: we may replace these attributes by
- * sodipodi:spiral="cx cy exp revo rad arg t0"
- */
- repr->setAttribute("sodipodi:type", "spiral");
- sp_repr_set_svg_double(repr, "sodipodi:cx", spiral->cx);
- sp_repr_set_svg_double(repr, "sodipodi:cy", spiral->cy);
- sp_repr_set_svg_double(repr, "sodipodi:expansion", spiral->exp);
- sp_repr_set_svg_double(repr, "sodipodi:revolution", spiral->revo);
- sp_repr_set_svg_double(repr, "sodipodi:radius", spiral->rad);
- sp_repr_set_svg_double(repr, "sodipodi:argument", spiral->arg);
- sp_repr_set_svg_double(repr, "sodipodi:t0", spiral->t0);
- }
+ SPSpiral *spiral = SP_SPIRAL (object);
+
+ if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) {
+ repr = xml_doc->createElement("svg:path");
+ }
+
+ if (flags & SP_OBJECT_WRITE_EXT) {
+ /* Fixme: we may replace these attributes by
+ * sodipodi:spiral="cx cy exp revo rad arg t0"
+ */
+ repr->setAttribute("sodipodi:type", "spiral");
+ sp_repr_set_svg_double(repr, "sodipodi:cx", spiral->cx);
+ sp_repr_set_svg_double(repr, "sodipodi:cy", spiral->cy);
+ sp_repr_set_svg_double(repr, "sodipodi:expansion", spiral->exp);
+ sp_repr_set_svg_double(repr, "sodipodi:revolution", spiral->revo);
+ sp_repr_set_svg_double(repr, "sodipodi:radius", spiral->rad);
+ sp_repr_set_svg_double(repr, "sodipodi:argument", spiral->arg);
+ sp_repr_set_svg_double(repr, "sodipodi:t0", spiral->t0);
+ }
// make sure the curve is rebuilt with all up-to-date parameters
sp_spiral_set_shape ((SPShape *) spiral);
// make sure the curve is rebuilt with all up-to-date parameters
sp_spiral_set_shape ((SPShape *) spiral);
@@ -189,61 +189,61 @@ sp_spiral_write (SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::X
static void
sp_spiral_set (SPObject *object, unsigned int key, const gchar *value)
{
static void
sp_spiral_set (SPObject *object, unsigned int key, const gchar *value)
{
- SPSpiral *spiral;
- SPShape *shape;
-
- spiral = SP_SPIRAL (object);
- shape = SP_SHAPE (object);
-
- /// \todo fixme: we should really collect updates
- switch (key) {
- case SP_ATTR_SODIPODI_CX:
- if (!sp_svg_length_read_computed_absolute (value, &spiral->cx)) {
- spiral->cx = 0.0;
- }
- object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
- break;
- case SP_ATTR_SODIPODI_CY:
- if (!sp_svg_length_read_computed_absolute (value, &spiral->cy)) {
- spiral->cy = 0.0;
- }
- object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
- break;
- case SP_ATTR_SODIPODI_EXPANSION:
- if (value) {
- /** \todo
+ SPSpiral *spiral;
+ SPShape *shape;
+
+ spiral = SP_SPIRAL (object);
+ shape = SP_SHAPE (object);
+
+ /// \todo fixme: we should really collect updates
+ switch (key) {
+ case SP_ATTR_SODIPODI_CX:
+ if (!sp_svg_length_read_computed_absolute (value, &spiral->cx)) {
+ spiral->cx = 0.0;
+ }
+ object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ break;
+ case SP_ATTR_SODIPODI_CY:
+ if (!sp_svg_length_read_computed_absolute (value, &spiral->cy)) {
+ spiral->cy = 0.0;
+ }
+ object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ break;
+ case SP_ATTR_SODIPODI_EXPANSION:
+ if (value) {
+ /** \todo
* FIXME: check that value looks like a (finite)
* number. Create a routine that uses strtod, and
* accepts a default value (if strtod finds an error).
* N.B. atof/sscanf/strtod consider "nan" and "inf"
* to be valid numbers.
*/
* FIXME: check that value looks like a (finite)
* number. Create a routine that uses strtod, and
* accepts a default value (if strtod finds an error).
* N.B. atof/sscanf/strtod consider "nan" and "inf"
* to be valid numbers.
*/
- spiral->exp = g_ascii_strtod (value, NULL);
- spiral->exp = CLAMP (spiral->exp, 0.0, 1000.0);
- } else {
- spiral->exp = 1.0;
- }
- object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
- break;
- case SP_ATTR_SODIPODI_REVOLUTION:
- if (value) {
- spiral->revo = g_ascii_strtod (value, NULL);
- spiral->revo = CLAMP (spiral->revo, 0.05, 1024.0);
- } else {
- spiral->revo = 3.0;
- }
- object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
- break;
- case SP_ATTR_SODIPODI_RADIUS:
- if (!sp_svg_length_read_computed_absolute (value, &spiral->rad)) {
- spiral->rad = MAX (spiral->rad, 0.001);
- }
- object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
- break;
- case SP_ATTR_SODIPODI_ARGUMENT:
- if (value) {
- spiral->arg = g_ascii_strtod (value, NULL);
- /** \todo
+ spiral->exp = g_ascii_strtod (value, NULL);
+ spiral->exp = CLAMP (spiral->exp, 0.0, 1000.0);
+ } else {
+ spiral->exp = 1.0;
+ }
+ object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ break;
+ case SP_ATTR_SODIPODI_REVOLUTION:
+ if (value) {
+ spiral->revo = g_ascii_strtod (value, NULL);
+ spiral->revo = CLAMP (spiral->revo, 0.05, 1024.0);
+ } else {
+ spiral->revo = 3.0;
+ }
+ object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ break;
+ case SP_ATTR_SODIPODI_RADIUS:
+ if (!sp_svg_length_read_computed_absolute (value, &spiral->rad)) {
+ spiral->rad = MAX (spiral->rad, 0.001);
+ }
+ object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ break;
+ case SP_ATTR_SODIPODI_ARGUMENT:
+ if (value) {
+ spiral->arg = g_ascii_strtod (value, NULL);
+ /** \todo
* FIXME: We still need some bounds on arg, for
* numerical reasons. E.g., we don't want inf or NaN,
* nor near-infinite numbers. I'm inclined to take
* FIXME: We still need some bounds on arg, for
* numerical reasons. E.g., we don't want inf or NaN,
* nor near-infinite numbers. I'm inclined to take
* which use atan2 - revo*2*pi, which typically
* results in very negative arg.
*/
* which use atan2 - revo*2*pi, which typically
* results in very negative arg.
*/
- } else {
- spiral->arg = 0.0;
- }
- object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
- break;
- case SP_ATTR_SODIPODI_T0:
- if (value) {
- spiral->t0 = g_ascii_strtod (value, NULL);
- spiral->t0 = CLAMP (spiral->t0, 0.0, 0.999);
- /** \todo
+ } else {
+ spiral->arg = 0.0;
+ }
+ object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ break;
+ case SP_ATTR_SODIPODI_T0:
+ if (value) {
+ spiral->t0 = g_ascii_strtod (value, NULL);
+ spiral->t0 = CLAMP (spiral->t0, 0.0, 0.999);
+ /** \todo
* Have shared constants for the allowable bounds for
* attributes. There was a bug here where we used -1.0
* as the minimum (which leads to NaN via, e.g.,
* pow(-1.0, 0.5); see sp_spiral_get_xy for
* requirements.
*/
* Have shared constants for the allowable bounds for
* attributes. There was a bug here where we used -1.0
* as the minimum (which leads to NaN via, e.g.,
* pow(-1.0, 0.5); see sp_spiral_get_xy for
* requirements.
*/
- } else {
- spiral->t0 = 0.0;
- }
- object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
- break;
- default:
- if (((SPObjectClass *) parent_class)->set)
- ((SPObjectClass *) parent_class)->set (object, key, value);
- break;
- }
+ } else {
+ spiral->t0 = 0.0;
+ }
+ object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ break;
+ default:
+ if (((SPObjectClass *) parent_class)->set)
+ ((SPObjectClass *) parent_class)->set (object, key, value);
+ break;
+ }
}
/**
}
/**
static void
sp_spiral_update (SPObject *object, SPCtx *ctx, guint flags)
{
static void
sp_spiral_update (SPObject *object, SPCtx *ctx, guint flags)
{
- if (flags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG | SP_OBJECT_VIEWPORT_MODIFIED_FLAG)) {
- sp_shape_set_shape ((SPShape *) object);
- }
+ if (flags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG | SP_OBJECT_VIEWPORT_MODIFIED_FLAG)) {
+ ((SPShape *) object)->setShape ();
+ }
- if (((SPObjectClass *) parent_class)->update)
- ((SPObjectClass *) parent_class)->update (object, ctx, flags);
+ if (((SPObjectClass *) parent_class)->update)
+ ((SPObjectClass *) parent_class)->update (object, ctx, flags);
}
static void
}
static void
static gchar *
sp_spiral_description (SPItem * item)
{
static gchar *
sp_spiral_description (SPItem * item)
{
- // TRANSLATORS: since turn count isn't an integer, please adjust the
- // string as needed to deal with an localized plural forms.
- return g_strdup_printf (_("<b>Spiral</b> with %3f turns"), SP_SPIRAL(item)->revo);
+ // TRANSLATORS: since turn count isn't an integer, please adjust the
+ // string as needed to deal with an localized plural forms.
+ return g_strdup_printf (_("<b>Spiral</b> with %3f turns"), SP_SPIRAL(item)->revo);
}
}
**/
static void
sp_spiral_fit_and_draw (SPSpiral const *spiral,
**/
static void
sp_spiral_fit_and_draw (SPSpiral const *spiral,
- SPCurve *c,
- double dstep,
- Geom::Point darray[],
- Geom::Point const &hat1,
- Geom::Point &hat2,
- double *t)
+ SPCurve *c,
+ double dstep,
+ Geom::Point darray[],
+ Geom::Point const &hat1,
+ Geom::Point &hat2,
+ double *t)
{
#define BEZIER_SIZE 4
#define FITTING_MAX_BEZIERS 4
#define BEZIER_LENGTH (BEZIER_SIZE * FITTING_MAX_BEZIERS)
{
#define BEZIER_SIZE 4
#define FITTING_MAX_BEZIERS 4
#define BEZIER_LENGTH (BEZIER_SIZE * FITTING_MAX_BEZIERS)
- g_assert (dstep > 0);
- g_assert (is_unit_vector (hat1));
-
- Geom::Point bezier[BEZIER_LENGTH];
- double d;
- int depth, i;
-
- for (d = *t, i = 0; i <= SAMPLE_SIZE; d += dstep, i++) {
- darray[i] = sp_spiral_get_xy(spiral, d);
-
- /* Avoid useless adjacent dups. (Otherwise we can have all of darray filled with
- the same value, which upsets chord_length_parameterize.) */
- if ((i != 0)
- && (darray[i] == darray[i - 1])
- && (d < 1.0)) {
- i--;
- d += dstep;
- /** We mustn't increase dstep for subsequent values of
+ g_assert (dstep > 0);
+ g_assert (is_unit_vector (hat1));
+
+ Geom::Point bezier[BEZIER_LENGTH];
+ double d;
+ int depth, i;
+
+ for (d = *t, i = 0; i <= SAMPLE_SIZE; d += dstep, i++) {
+ darray[i] = sp_spiral_get_xy(spiral, d);
+
+ /* Avoid useless adjacent dups. (Otherwise we can have all of darray filled with
+ the same value, which upsets chord_length_parameterize.) */
+ if ((i != 0)
+ && (darray[i] == darray[i - 1])
+ && (d < 1.0)) {
+ i--;
+ d += dstep;
+ /** We mustn't increase dstep for subsequent values of
* i: for large spiral.exp values, rate of growth
* increases very rapidly.
*/
* i: for large spiral.exp values, rate of growth
* increases very rapidly.
*/
* value for next iteration to avoid the problem
* mentioned above.
*/
* value for next iteration to avoid the problem
* mentioned above.
*/
- }
- }
+ }
+ }
- double const next_t = d - 2 * dstep;
- /* == t + (SAMPLE_SIZE - 1) * dstep, in absence of dups. */
+ double const next_t = d - 2 * dstep;
+ /* == t + (SAMPLE_SIZE - 1) * dstep, in absence of dups. */
- hat2 = -sp_spiral_get_tangent (spiral, next_t);
+ hat2 = -sp_spiral_get_tangent (spiral, next_t);
- /** \todo
+ /** \todo
* We should use better algorithm to specify maximum error.
*/
* We should use better algorithm to specify maximum error.
*/
- depth = sp_bezier_fit_cubic_full (bezier, NULL, darray, SAMPLE_SIZE,
- hat1, hat2,
- SPIRAL_TOLERANCE*SPIRAL_TOLERANCE,
- FITTING_MAX_BEZIERS);
- g_assert(depth * BEZIER_SIZE <= gint(G_N_ELEMENTS(bezier)));
+ depth = Geom::bezier_fit_cubic_full (bezier, NULL, darray, SAMPLE_SIZE,
+ hat1, hat2,
+ SPIRAL_TOLERANCE*SPIRAL_TOLERANCE,
+ FITTING_MAX_BEZIERS);
+ g_assert(depth * BEZIER_SIZE <= gint(G_N_ELEMENTS(bezier)));
#ifdef SPIRAL_DEBUG
#ifdef SPIRAL_DEBUG
- if (*t == spiral->t0 || *t == 1.0)
- g_print ("[%s] depth=%d, dstep=%g, t0=%g, t=%g, arg=%g\n",
- debug_state, depth, dstep, spiral->t0, *t, spiral->arg);
+ if (*t == spiral->t0 || *t == 1.0)
+ g_print ("[%s] depth=%d, dstep=%g, t0=%g, t=%g, arg=%g\n",
+ debug_state, depth, dstep, spiral->t0, *t, spiral->arg);
#endif
#endif
- if (depth != -1) {
- for (i = 0; i < 4*depth; i += 4) {
- c->curveto(bezier[i + 1],
- bezier[i + 2],
- bezier[i + 3]);
- }
- } else {
+ if (depth != -1) {
+ for (i = 0; i < 4*depth; i += 4) {
+ c->curveto(bezier[i + 1],
+ bezier[i + 2],
+ bezier[i + 3]);
+ }
+ } else {
#ifdef SPIRAL_VERBOSE
#ifdef SPIRAL_VERBOSE
- g_print ("cant_fit_cubic: t=%g\n", *t);
+ g_print ("cant_fit_cubic: t=%g\n", *t);
#endif
#endif
- for (i = 1; i < SAMPLE_SIZE; i++)
- c->lineto(darray[i]);
- }
- *t = next_t;
- g_assert (is_unit_vector (hat2));
+ for (i = 1; i < SAMPLE_SIZE; i++)
+ c->lineto(darray[i]);
+ }
+ *t = next_t;
+ g_assert (is_unit_vector (hat2));
}
static void
sp_spiral_set_shape (SPShape *shape)
{
}
static void
sp_spiral_set_shape (SPShape *shape)
{
- Geom::Point darray[SAMPLE_SIZE + 1];
- double t;
+ SPSpiral *spiral = SP_SPIRAL(shape);
+
+ if (sp_lpe_item_has_broken_path_effect(SP_LPE_ITEM(shape))) {
+ g_warning ("The spiral shape has unknown LPE on it! Convert to path to make it editable preserving the appearance; editing it as spiral will remove the bad LPE");
+ if (SP_OBJECT_REPR(shape)->attribute("d")) {
+ // unconditionally read the curve from d, if any, to preserve appearance
+ Geom::PathVector pv = sp_svg_read_pathv(SP_OBJECT_REPR(shape)->attribute("d"));
+ SPCurve *cold = new SPCurve(pv);
+ shape->setCurveInsync( cold, TRUE);
+ cold->unref();
+ }
+ return;
+ }
- SPSpiral *spiral = SP_SPIRAL(shape);
+ Geom::Point darray[SAMPLE_SIZE + 1];
+ double t;
- SP_OBJECT (spiral)->requestModified(SP_OBJECT_MODIFIED_FLAG);
+ SP_OBJECT (spiral)->requestModified(SP_OBJECT_MODIFIED_FLAG);
+
+ SPCurve *c = new SPCurve ();
- SPCurve *c = new SPCurve ();
-
#ifdef SPIRAL_VERBOSE
#ifdef SPIRAL_VERBOSE
- g_print ("cx=%g, cy=%g, exp=%g, revo=%g, rad=%g, arg=%g, t0=%g\n",
- spiral->cx,
- spiral->cy,
- spiral->exp,
- spiral->revo,
- spiral->rad,
- spiral->arg,
- spiral->t0);
+ g_print ("cx=%g, cy=%g, exp=%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
#endif
- /* Initial moveto. */
- c->moveto(sp_spiral_get_xy(spiral, spiral->t0));
+ /* Initial moveto. */
+ c->moveto(sp_spiral_get_xy(spiral, spiral->t0));
- double const tstep = SAMPLE_STEP / spiral->revo;
- double const dstep = tstep / (SAMPLE_SIZE - 1);
+ double const tstep = SAMPLE_STEP / spiral->revo;
+ double const dstep = tstep / (SAMPLE_SIZE - 1);
- Geom::Point hat1 = sp_spiral_get_tangent (spiral, spiral->t0);
- Geom::Point hat2;
- for (t = spiral->t0; t < (1.0 - tstep);) {
- sp_spiral_fit_and_draw (spiral, c, dstep, darray, hat1, hat2, &t);
+ Geom::Point hat1 = sp_spiral_get_tangent (spiral, spiral->t0);
+ Geom::Point hat2;
+ for (t = spiral->t0; t < (1.0 - tstep);) {
+ sp_spiral_fit_and_draw (spiral, c, dstep, darray, hat1, hat2, &t);
- hat1 = -hat2;
- }
- if ((1.0 - t) > SP_EPSILON)
- sp_spiral_fit_and_draw (spiral, c, (1.0 - t)/(SAMPLE_SIZE - 1.0),
- darray, hat1, hat2, &t);
+ hat1 = -hat2;
+ }
+ if ((1.0 - t) > SP_EPSILON)
+ sp_spiral_fit_and_draw (spiral, c, (1.0 - t)/(SAMPLE_SIZE - 1.0),
+ darray, hat1, hat2, &t);
/* Reset the shape'scurve to the "original_curve"
* This is very important for LPEs to work properly! (the bbox might be recalculated depending on the curve in shape)*/
/* Reset the shape'scurve to the "original_curve"
* This is very important for LPEs to work properly! (the bbox might be recalculated depending on the curve in shape)*/
- sp_shape_set_curve_insync (shape, c, TRUE);
+ shape->setCurveInsync( c, TRUE);
if (sp_lpe_item_has_path_effect(SP_LPE_ITEM(shape)) && sp_lpe_item_path_effects_enabled(SP_LPE_ITEM(shape))) {
SPCurve *c_lpe = c->copy();
bool success = sp_lpe_item_perform_path_effect(SP_LPE_ITEM (shape), c_lpe);
if (success) {
if (sp_lpe_item_has_path_effect(SP_LPE_ITEM(shape)) && sp_lpe_item_path_effects_enabled(SP_LPE_ITEM(shape))) {
SPCurve *c_lpe = c->copy();
bool success = sp_lpe_item_perform_path_effect(SP_LPE_ITEM (shape), c_lpe);
if (success) {
- sp_shape_set_curve_insync (shape, c_lpe, TRUE);
+ shape->setCurveInsync( c_lpe, TRUE);
}
c_lpe->unref();
}
}
c_lpe->unref();
}
*/
void
sp_spiral_position_set (SPSpiral *spiral,
*/
void
sp_spiral_position_set (SPSpiral *spiral,
- gdouble cx,
- gdouble cy,
- gdouble exp,
- gdouble revo,
- gdouble rad,
- gdouble arg,
- gdouble t0)
+ gdouble cx,
+ gdouble cy,
+ gdouble exp,
+ gdouble revo,
+ gdouble rad,
+ gdouble arg,
+ gdouble t0)
{
{
- g_return_if_fail (spiral != NULL);
- g_return_if_fail (SP_IS_SPIRAL (spiral));
+ g_return_if_fail (spiral != NULL);
+ g_return_if_fail (SP_IS_SPIRAL (spiral));
- /** \todo
+ /** \todo
* Consider applying CLAMP or adding in-bounds assertions for
* some of these parameters.
*/
* Consider applying CLAMP or adding in-bounds assertions for
* some of these parameters.
*/
- spiral->cx = cx;
- spiral->cy = cy;
- spiral->exp = exp;
- spiral->revo = revo;
- spiral->rad = MAX (rad, 0.001);
- spiral->arg = arg;
- spiral->t0 = CLAMP(t0, 0.0, 0.999);
-
- ((SPObject *)spiral)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ spiral->cx = cx;
+ spiral->cy = cy;
+ spiral->exp = exp;
+ spiral->revo = revo;
+ spiral->rad = MAX (rad, 0.0);
+ spiral->arg = arg;
+ spiral->t0 = CLAMP(t0, 0.0, 0.999);
+
+ ((SPObject *)spiral)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
}
/**
* Virtual snappoints callback.
*/
}
/**
* Virtual snappoints callback.
*/
-static void sp_spiral_snappoints(SPItem const *item, SnapPointsIter p, Inkscape::SnapPreferences const *snapprefs)
+static void sp_spiral_snappoints(SPItem const *item, std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs)
{
{
- if (((SPItemClass *) parent_class)->snappoints) {
- ((SPItemClass *) parent_class)->snappoints (item, p, snapprefs);
- }
+ // We will determine the spiral's midpoint ourselves, instead of trusting on the base class
+ // Therefore setSnapObjectMidpoints() is set to false temporarily
+ Inkscape::SnapPreferences local_snapprefs = *snapprefs;
+ local_snapprefs.setSnapObjectMidpoints(false);
+
+ if (((SPItemClass *) parent_class)->snappoints) {
+ ((SPItemClass *) parent_class)->snappoints (item, p, &local_snapprefs);
+ }
+
+ // Help enforcing strict snapping, i.e. only return nodes when we're snapping nodes to nodes or a guide to nodes
+ if (!(snapprefs->getSnapModeNode() || snapprefs->getSnapModeGuide())) {
+ return;
+ }
+
+ if (snapprefs->getSnapObjectMidpoints()) {
+ Geom::Matrix const i2d (item->i2d_affine ());
+ SPSpiral *spiral = SP_SPIRAL(item);
+ p.push_back(Inkscape::SnapCandidatePoint(Geom::Point(spiral->cx, spiral->cy) * i2d, Inkscape::SNAPSOURCE_OBJECT_MIDPOINT, Inkscape::SNAPTARGET_OBJECT_MIDPOINT));
+ // This point is the start-point of the spiral, which is also returned when _snap_to_itemnode has been set
+ // in the object snapper. In that case we will get a duplicate!
+ }
}
/**
}
/**
@@ -520,19 +550,19 @@ static void sp_spiral_snappoints(SPItem const *item, SnapPointsIter p, Inkscape:
*/
Geom::Point sp_spiral_get_xy (SPSpiral const *spiral, gdouble t)
{
*/
Geom::Point sp_spiral_get_xy (SPSpiral const *spiral, gdouble t)
{
- g_assert (spiral != NULL);
- g_assert (SP_IS_SPIRAL(spiral));
- g_assert (spiral->exp >= 0.0);
- /* Otherwise we get NaN for t==0. */
- g_assert (spiral->exp <= 1000.0);
- /* Anything much more results in infinities. Even allowing 1000 is somewhat overkill. */
- g_assert (t >= 0.0);
- /* Any callers passing -ve t will have a bug for non-integral values of exp. */
-
- double const rad = spiral->rad * pow(t, (double) spiral->exp);
- double const arg = 2.0 * M_PI * spiral->revo * t + spiral->arg;
-
- return Geom::Point(rad * cos (arg) + spiral->cx,
+ g_assert (spiral != NULL);
+ g_assert (SP_IS_SPIRAL(spiral));
+ g_assert (spiral->exp >= 0.0);
+ /* Otherwise we get NaN for t==0. */
+ g_assert (spiral->exp <= 1000.0);
+ /* Anything much more results in infinities. Even allowing 1000 is somewhat overkill. */
+ g_assert (t >= 0.0);
+ /* Any callers passing -ve t will have a bug for non-integral values of exp. */
+
+ double const rad = spiral->rad * pow(t, (double) spiral->exp);
+ double const arg = 2.0 * M_PI * spiral->revo * t + spiral->arg;
+
+ return Geom::Point(rad * cos (arg) + spiral->cx,
rad * sin (arg) + spiral->cy);
}
rad * sin (arg) + spiral->cy);
}
static Geom::Point
sp_spiral_get_tangent (SPSpiral const *spiral, gdouble t)
{
static Geom::Point
sp_spiral_get_tangent (SPSpiral const *spiral, gdouble t)
{
- Geom::Point ret(1.0, 0.0);
- g_return_val_if_fail (( ( spiral != NULL )
- && SP_IS_SPIRAL(spiral) ),
- ret);
- g_assert (t >= 0.0);
- g_assert (spiral->exp >= 0.0);
- /* See above for comments on these assertions. */
-
- double const t_scaled = 2.0 * M_PI * spiral->revo * t;
- double const arg = t_scaled + spiral->arg;
- double const s = sin (arg);
- double const c = cos (arg);
-
- if (spiral->exp == 0.0) {
- ret = Geom::Point(-s, c);
- } else if (t_scaled == 0.0) {
- ret = Geom::Point(c, s);
- } else {
- Geom::Point unrotated(spiral->exp, t_scaled);
- double const s_len = L2 (unrotated);
- g_assert (s_len != 0);
- /** \todo
+ Geom::Point ret(1.0, 0.0);
+ g_return_val_if_fail (( ( spiral != NULL )
+ && SP_IS_SPIRAL(spiral) ),
+ ret);
+ g_assert (t >= 0.0);
+ g_assert (spiral->exp >= 0.0);
+ /* See above for comments on these assertions. */
+
+ double const t_scaled = 2.0 * M_PI * spiral->revo * t;
+ double const arg = t_scaled + spiral->arg;
+ double const s = sin (arg);
+ double const c = cos (arg);
+
+ if (spiral->exp == 0.0) {
+ ret = Geom::Point(-s, c);
+ } else if (t_scaled == 0.0) {
+ ret = Geom::Point(c, s);
+ } else {
+ Geom::Point unrotated(spiral->exp, t_scaled);
+ double const s_len = L2 (unrotated);
+ g_assert (s_len != 0);
+ /** \todo
* Check that this isn't being too hopeful of the hypot
* function. E.g. test with numbers around 2**-1070
* (denormalized numbers), preferably on a few different
* platforms. However, njh says that the usual implementation
* does handle both very big and very small numbers.
*/
* Check that this isn't being too hopeful of the hypot
* function. E.g. test with numbers around 2**-1070
* (denormalized numbers), preferably on a few different
* platforms. However, njh says that the usual implementation
* does handle both very big and very small numbers.
*/
- unrotated /= s_len;
+ unrotated /= s_len;
- /* ret = spiral->exp * (c, s) + t_scaled * (-s, c);
- alternatively ret = (spiral->exp, t_scaled) * (( c, s),
- (-s, c)).*/
- ret = Geom::Point(dot(unrotated, Geom::Point(c, -s)),
+ /* ret = spiral->exp * (c, s) + t_scaled * (-s, c);
+ alternatively ret = (spiral->exp, t_scaled) * (( c, s),
+ (-s, c)).*/
+ ret = Geom::Point(dot(unrotated, Geom::Point(c, -s)),
dot(unrotated, Geom::Point(s, c)));
dot(unrotated, Geom::Point(s, c)));
- /* ret should already be approximately normalized: the
- matrix ((c, -s), (s, c)) is orthogonal (it just
- rotates by arg), and unrotated has been normalized,
- so ret is already of unit length other than numerical
- error in the above matrix multiplication. */
+ /* ret should already be approximately normalized: the
+ matrix ((c, -s), (s, c)) is orthogonal (it just
+ rotates by arg), and unrotated has been normalized,
+ so ret is already of unit length other than numerical
+ error in the above matrix multiplication. */
- /** \todo
+ /** \todo
* I haven't checked how important it is for ret to be very
* near unit length; we could get rid of the below.
*/
* I haven't checked how important it is for ret to be very
* near unit length; we could get rid of the below.
*/
- ret.normalize();
- /* Proof that ret length is non-zero: see above. (Should be near 1.) */
- }
+ ret.normalize();
+ /* Proof that ret length is non-zero: see above. (Should be near 1.) */
+ }
- g_assert (is_unit_vector (ret));
- return ret;
+ g_assert (is_unit_vector (ret));
+ return ret;
}
/**
}
/**
void
sp_spiral_get_polar (SPSpiral const *spiral, gdouble t, gdouble *rad, gdouble *arg)
{
void
sp_spiral_get_polar (SPSpiral const *spiral, gdouble t, gdouble *rad, gdouble *arg)
{
- g_return_if_fail (spiral != NULL);
- g_return_if_fail (SP_IS_SPIRAL(spiral));
+ g_return_if_fail (spiral != NULL);
+ g_return_if_fail (SP_IS_SPIRAL(spiral));
- if (rad)
- *rad = spiral->rad * pow(t, (double) spiral->exp);
- if (arg)
- *arg = 2.0 * M_PI * spiral->revo * t + spiral->arg;
+ if (rad)
+ *rad = spiral->rad * pow(t, (double) spiral->exp);
+ if (arg)
+ *arg = 2.0 * M_PI * spiral->revo * t + spiral->arg;
}
/**
}
/**
@@ -624,19 +654,19 @@ sp_spiral_get_polar (SPSpiral const *spiral, gdouble t, gdouble *rad, gdouble *a
bool
sp_spiral_is_invalid (SPSpiral const *spiral)
{
bool
sp_spiral_is_invalid (SPSpiral const *spiral)
{
- gdouble rad;
-
- sp_spiral_get_polar (spiral, 0.0, &rad, NULL);
- if (rad < 0.0 || rad > SP_HUGE) {
- g_print ("rad(t=0)=%g\n", rad);
- return TRUE;
- }
- sp_spiral_get_polar (spiral, 1.0, &rad, NULL);
- if (rad < 0.0 || rad > SP_HUGE) {
- g_print ("rad(t=1)=%g\n", rad);
- return TRUE;
- }
- return FALSE;
+ gdouble rad;
+
+ sp_spiral_get_polar (spiral, 0.0, &rad, NULL);
+ if (rad < 0.0 || rad > SP_HUGE) {
+ g_print ("rad(t=0)=%g\n", rad);
+ return TRUE;
+ }
+ sp_spiral_get_polar (spiral, 1.0, &rad, NULL);
+ if (rad < 0.0 || rad > SP_HUGE) {
+ g_print ("rad(t=1)=%g\n", rad);
+ return TRUE;
+ }
+ return FALSE;
}
/*
}
/*
fill-column:99
End:
*/
fill-column:99
End:
*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :