summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJabier Arraiza Cenoz <jabier.arraiza@marker.es>2015-02-08 15:40:25 +0000
committerJabiertxof <jtx@jtx.marker.es>2015-02-08 15:40:25 +0000
commit86891a9e442c81435c6d197cb09b3dc210643bc0 (patch)
tree4952411fd6e526907d4241e8965e93c4f185500a /src
parentrefactor of pointwise base (diff)
downloadinkscape-86891a9e442c81435c6d197cb09b3dc210643bc0.tar.gz
inkscape-86891a9e442c81435c6d197cb09b3dc210643bc0.zip
starting whith pointwise
(bzr r13645.1.7)
Diffstat (limited to 'src')
-rw-r--r--src/2geom/Makefile_insert3
-rw-r--r--src/2geom/pointwise.cpp6
-rw-r--r--src/2geom/pointwise.h16
-rw-r--r--src/2geom/satellite-enum.h2
-rw-r--r--src/2geom/satellite.h28
-rw-r--r--src/live_effects/CMakeLists.txt2
-rw-r--r--src/live_effects/lpe-fillet-chamfer.cpp585
-rw-r--r--src/live_effects/lpe-fillet-chamfer.h41
-rw-r--r--src/live_effects/parameter/Makefile_insert2
-rw-r--r--src/live_effects/parameter/array.cpp32
-rw-r--r--src/live_effects/parameter/array.h9
-rw-r--r--src/live_effects/parameter/pointwise.cpp104
-rw-r--r--src/live_effects/parameter/pointwise.h88
13 files changed, 295 insertions, 623 deletions
diff --git a/src/2geom/Makefile_insert b/src/2geom/Makefile_insert
index e77f413cb..2f23bc442 100644
--- a/src/2geom/Makefile_insert
+++ b/src/2geom/Makefile_insert
@@ -80,6 +80,8 @@
2geom/point.cpp \
2geom/point.h \
2geom/point-ops.h \
+ 2geom/pointwise.cpp \
+ 2geom/pointwise.h \
2geom/poly.cpp \
2geom/poly.h \
2geom/quadtree.cpp \
@@ -90,6 +92,7 @@
2geom/recursive-bezier-intersection.cpp \
2geom/region.cpp \
2geom/region.h \
+ 2geom/satellite.h \
2geom/sbasis-2d.cpp \
2geom/sbasis-2d.h \
2geom/sbasis.cpp \
diff --git a/src/2geom/pointwise.cpp b/src/2geom/pointwise.cpp
index ce3aa86f6..cd7f7914f 100644
--- a/src/2geom/pointwise.cpp
+++ b/src/2geom/pointwise.cpp
@@ -1,6 +1,8 @@
/*
- * pointwise.cpp - Pointwise function class
- *
+ * pointwise.cpp
+ * Authors:
+ * 2015 Jabier Arraiza Cenoz<jabier.arraiza@marker.es>
+ * Copyright 2015 authors
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
diff --git a/src/2geom/pointwise.h b/src/2geom/pointwise.h
index 33289f4f0..c0974f54c 100644
--- a/src/2geom/pointwise.h
+++ b/src/2geom/pointwise.h
@@ -3,10 +3,20 @@
* \brief Pointwise
*//*
* Authors:
+ * 2015 Jabier Arraiza Cenoz<jabier.arraiza@marker.es>
+ * Copyright 2015 authors
*
- * Copyright 2014 authors
- *
- *
+ * Pointwise maintains a set of "Satellite" positions along a curve/pathvector.
+ * The positions are specified as arc length distances along the curve or by
+ * time in the curve. Splicing operations automatically update the satellite
+ * positions to preserve the intent.
+ * The data is serialised to SVG using a specialiced pointwise LPE parameter to
+ * handle it in th future can be a inkscape based property to paths
+ * //all operations are O(1) per satellite, with the exception of .., .., and .., which
+ * //need to use binary search to find the locations.
+ * Anywhere a Piecewise is used, a Pointwise can be substituted, allowing
+ * existing algorithms to correctly update satellite positions.
+
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
diff --git a/src/2geom/satellite-enum.h b/src/2geom/satellite-enum.h
index 3872cf718..a71306bc9 100644
--- a/src/2geom/satellite-enum.h
+++ b/src/2geom/satellite-enum.h
@@ -20,7 +20,7 @@ enum SatelliteType {
INVERSE_CHAMFER,
INVALID_SATELLITE // This must be last (I made it such that it is not needed anymore I think..., Don't trust on it being last. - johan)
};
-
+std::map<gchar const *value, SatelliteType> SatelliteTypeMap = boost::map_list_of("FILLET", FILLET)("INVERSE_FILLET", INVERSE_FILLET)("CHAMFER",CHAMFER)("INVERSE_CHAMFER",INVERSE_CHAMFER)("INVALID_SATELLITE",INVALID_SATELLITE);
extern const Util::EnumData<SatelliteType> SATELLITETypeData[]; /// defined in satelite.cpp
extern const Util::EnumDataConverter<SateliteType> SATELLITETypeConverter; /// defined in sattelite.cpp
diff --git a/src/2geom/satellite.h b/src/2geom/satellite.h
index 8e570db4c..a18b08f27 100644
--- a/src/2geom/satellite.h
+++ b/src/2geom/satellite.h
@@ -3,8 +3,8 @@
* \brief Satellite
*//*
* Authors:
- *
- * Copyright 2014 authors
+ * 2015 Jabier Arraiza Cenoz<jabier.arraiza@marker.es>
+ * Copyright 2015 authors
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
@@ -129,16 +129,30 @@ class Satellite
return _time;
}
- double toTime(double A,D2<SBasis> curve) const
+ double time(D2<SBasis> curve) const
{
//todo make the process
return _time;
}
- double toSize(double A,D2<SBasis> curve) const
- {
- //todo make the process
- return _size;
+ void setPosition(Geom::Point p, D2<SBasis> curve){
+ _time = Geom::nearestPoint(p, curve);
+ if(!_isTime){
+ if (curve.degreesOfFreedom() != 2) {
+ Piecewise<D2<SBasis> > u;
+ u.push_cut(0);
+ u.push(curve, 1);
+ u = portion(u, 0, _time);
+ _size = length(u, 0.001) * -1;
+ } else {
+ lenghtPart = length(last_pwd2[index], EPSILON);
+ _size = (time * lenghtPart) * -1;
+ }
+ }
+ }
+
+ Geom::Point getPosition(D2<SBasis> curve){
+ return curve.pointAt(_time);
}
bool isDegenerate() const
diff --git a/src/live_effects/CMakeLists.txt b/src/live_effects/CMakeLists.txt
index c8a02c810..e171e99e3 100644
--- a/src/live_effects/CMakeLists.txt
+++ b/src/live_effects/CMakeLists.txt
@@ -63,6 +63,7 @@ set(live_effects_SRC
parameter/path-reference.cpp
parameter/point.cpp
parameter/powerstrokepointarray.cpp
+ parameter/pointwise.cpp
parameter/random.cpp
parameter/text.cpp
paramter/transformedpoint.cpp
@@ -139,6 +140,7 @@ set(live_effects_SRC
parameter/originalpatharray.h
parameter/point.h
parameter/powerstrokepointarray.h
+ parameter/pointwise.h
parameter/random.h
parameter/text.h
parameter/togglebutton.h
diff --git a/src/live_effects/lpe-fillet-chamfer.cpp b/src/live_effects/lpe-fillet-chamfer.cpp
index d2bdf2d8d..f4eb4f46e 100644
--- a/src/live_effects/lpe-fillet-chamfer.cpp
+++ b/src/live_effects/lpe-fillet-chamfer.cpp
@@ -13,23 +13,8 @@
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include "live_effects/lpe-fillet-chamfer.h"
-
-#include <2geom/sbasis-to-bezier.h>
-#include <2geom/svg-elliptical-arc.h>
-#include <2geom/line.h>
-#include "desktop.h"
-#include "display/curve.h"
-#include "helper/geom-nodetype.h"
-#include "helper/geom-curves.h"
-#include "helper/geom.h"
-
-#include "live_effects/parameter/filletchamferpointarray.h"
-
-// for programmatically updating knots
-#include "ui/tools-switch.h"
-#include <util/units.h>
+#include "live_effects/parameter/pointwise.h"
// TODO due to internal breakage in glibmm headers, this must be last:
#include <glibmm/i18n.h>
@@ -38,348 +23,23 @@ using namespace Geom;
namespace Inkscape {
namespace LivePathEffect {
-static const Util::EnumData<FilletMethod> FilletMethodData[FM_END] = {
- { FM_AUTO, N_("Auto"), "auto" },
- { FM_ARC, N_("Force arc"), "arc" },
- { FM_BEZIER, N_("Force bezier"), "bezier" }
-};
-static const Util::EnumDataConverter<FilletMethod>
-FMConverter(FilletMethodData, FM_END);
-
-const double tolerance = 0.001;
-const double gapHelper = 0.00001;
-
LPEFilletChamfer::LPEFilletChamfer(LivePathEffectObject *lpeobject) :
Effect(lpeobject),
- fillet_chamfer_values(_("Fillet point"), _("Fillet point"), "fillet_chamfer_values", &wr, this),
- hide_knots(_("Hide knots"), _("Hide knots"), "hide_knots", &wr, this, false),
- ignore_radius_0(_("Ignore 0 radius knots"), _("Ignore 0 radius knots"), "ignore_radius_0", &wr, this, false),
- only_selected(_("Change only selected nodes"), _("Change only selected nodes"), "only_selected", &wr, this, false),
- flexible(_("Flexible radius size (%)"), _("Flexible radius size (%)"), "flexible", &wr, this, false),
- use_knot_distance(_("Use knots distance instead radius"), _("Use knots distance instead radius"), "use_knot_distance", &wr, this, false),
- unit(_("Unit:"), _("Unit"), "unit", &wr, this),
- method(_("Method:"), _("Fillets methods"), "method", FMConverter, &wr, this, FM_AUTO),
- radius(_("Radius (unit or %):"), _("Radius, in unit or %"), "radius", &wr, this, 0.),
- chamfer_steps(_("Chamfer steps:"), _("Chamfer steps"), "chamfer_steps", &wr, this, 0),
-
- helper_size(_("Helper size with direction:"), _("Helper size with direction"), "helper_size", &wr, this, 0)
+ pointwise_values(_("Fillet point"), _("Fillet point"), "pointwise_values", &wr, this)
{
- registerParameter(&fillet_chamfer_values);
- registerParameter(&unit);
- registerParameter(&method);
- registerParameter(&radius);
- registerParameter(&chamfer_steps);
- registerParameter(&helper_size);
- registerParameter(&flexible);
- registerParameter(&use_knot_distance);
- registerParameter(&ignore_radius_0);
- registerParameter(&only_selected);
- registerParameter(&hide_knots);
-
- radius.param_set_range(0., infinity());
- radius.param_set_increments(1, 1);
- radius.param_set_digits(4);
- chamfer_steps.param_set_range(1, 999);
- chamfer_steps.param_set_increments(1, 1);
- chamfer_steps.param_set_digits(0);
- helper_size.param_set_range(0, infinity());
- helper_size.param_set_increments(5, 5);
- helper_size.param_set_digits(0);
- fillet_chamfer_values.set_chamfer_steps(3);
+ registerParameter(&pointwise_values);
}
LPEFilletChamfer::~LPEFilletChamfer() {}
-Gtk::Widget *LPEFilletChamfer::newWidget()
-{
- // use manage here, because after deletion of Effect object, others might
- // still be pointing to this widget.
- Gtk::VBox *vbox = Gtk::manage(new Gtk::VBox(Effect::newWidget()));
-
- vbox->set_border_width(5);
- vbox->set_homogeneous(false);
- vbox->set_spacing(2);
- std::vector<Parameter *>::iterator it = param_vector.begin();
- while (it != param_vector.end()) {
- if ((*it)->widget_is_visible) {
- Parameter *param = *it;
- Gtk::Widget *widg = param->param_newWidget();
- if (param->param_key == "radius") {
- Inkscape::UI::Widget::Scalar *widgRegistered = Gtk::manage(dynamic_cast<Inkscape::UI::Widget::Scalar *>(widg));
- widgRegistered->signal_value_changed().connect(sigc::mem_fun(*this, &LPEFilletChamfer::updateFillet));
- widg = widgRegistered;
- if (widg) {
- Gtk::HBox *scalarParameter = dynamic_cast<Gtk::HBox *>(widg);
- std::vector<Gtk::Widget *> childList = scalarParameter->get_children();
- Gtk::Entry *entryWidg = dynamic_cast<Gtk::Entry *>(childList[1]);
- entryWidg->set_width_chars(6);
- }
- } else if (param->param_key == "chamfer_steps") {
- Inkscape::UI::Widget::Scalar *widgRegistered = Gtk::manage(dynamic_cast<Inkscape::UI::Widget::Scalar *>(widg));
- widgRegistered->signal_value_changed().connect(sigc::mem_fun(*this, &LPEFilletChamfer::chamferSubdivisions));
- widg = widgRegistered;
- if (widg) {
- Gtk::HBox *scalarParameter = dynamic_cast<Gtk::HBox *>(widg);
- std::vector<Gtk::Widget *> childList = scalarParameter->get_children();
- Gtk::Entry *entryWidg = dynamic_cast<Gtk::Entry *>(childList[1]);
- entryWidg->set_width_chars(3);
- }
- } else if (param->param_key == "flexible") {
- Gtk::CheckButton *widgRegistered = Gtk::manage(dynamic_cast<Gtk::CheckButton *>(widg));
- widgRegistered->signal_clicked().connect(sigc::mem_fun(*this, &LPEFilletChamfer::toggleFlexFixed));
- } else if (param->param_key == "helper_size") {
- Inkscape::UI::Widget::Scalar *widgRegistered = Gtk::manage(dynamic_cast<Inkscape::UI::Widget::Scalar *>(widg));
- widgRegistered->signal_value_changed().connect(sigc::mem_fun(*this, &LPEFilletChamfer::refreshKnots));
- } else if (param->param_key == "hide_knots") {
- Gtk::CheckButton *widgRegistered = Gtk::manage(dynamic_cast<Gtk::CheckButton *>(widg));
- widgRegistered->signal_clicked().connect(sigc::mem_fun(*this, &LPEFilletChamfer::toggleHide));
- } else if (param->param_key == "only_selected") {
- Gtk::manage(widg);
- } else if (param->param_key == "ignore_radius_0") {
- Gtk::manage(widg);
- }
-
- Glib::ustring *tip = param->param_getTooltip();
- if (widg) {
- vbox->pack_start(*widg, true, true, 2);
- if (tip) {
- widg->set_tooltip_text(*tip);
- } else {
- widg->set_tooltip_text("");
- widg->set_has_tooltip(false);
- }
- }
- }
-
- ++it;
- }
- Gtk::HBox *filletContainer = Gtk::manage(new Gtk::HBox(true, 0));
- Gtk::Button *fillet = Gtk::manage(new Gtk::Button(Glib::ustring(_("Fillet"))));
- fillet->signal_clicked().connect(sigc::mem_fun(*this, &LPEFilletChamfer::fillet));
-
- filletContainer->pack_start(*fillet, true, true, 2);
- Gtk::Button *inverseFillet = Gtk::manage(new Gtk::Button(Glib::ustring(_("Inverse fillet"))));
- inverseFillet->signal_clicked().connect(sigc::mem_fun(*this, &LPEFilletChamfer::inverseFillet));
- filletContainer->pack_start(*inverseFillet, true, true, 2);
-
- Gtk::HBox *chamferContainer = Gtk::manage(new Gtk::HBox(true, 0));
- Gtk::Button *chamfer = Gtk::manage(new Gtk::Button(Glib::ustring(_("Chamfer"))));
- chamfer->signal_clicked().connect(sigc::mem_fun(*this, &LPEFilletChamfer::chamfer));
-
- chamferContainer->pack_start(*chamfer, true, true, 2);
- Gtk::Button *inverseChamfer = Gtk::manage(new Gtk::Button(Glib::ustring(_("Inverse chamfer"))));
- inverseChamfer->signal_clicked().connect(sigc::mem_fun(*this, &LPEFilletChamfer::inverseChamfer));
- chamferContainer->pack_start(*inverseChamfer, true, true, 2);
-
- vbox->pack_start(*filletContainer, true, true, 2);
- vbox->pack_start(*chamferContainer, true, true, 2);
-
- return vbox;
-}
-
-void LPEFilletChamfer::toggleHide()
-{
- std::vector<Point> filletChamferData = fillet_chamfer_values.data();
- std::vector<Geom::Point> result;
- for (std::vector<Point>::const_iterator point_it = filletChamferData.begin();
- point_it != filletChamferData.end(); ++point_it) {
- if (hide_knots) {
- result.push_back(Point((*point_it)[X], std::abs((*point_it)[Y]) * -1));
- } else {
- result.push_back(Point((*point_it)[X], std::abs((*point_it)[Y])));
- }
- }
- fillet_chamfer_values.param_set_and_write_new_value(result);
- refreshKnots();
-}
-
-void LPEFilletChamfer::toggleFlexFixed()
-{
- std::vector<Point> filletChamferData = fillet_chamfer_values.data();
- std::vector<Geom::Point> result;
- unsigned int i = 0;
- for (std::vector<Point>::const_iterator point_it = filletChamferData.begin();
- point_it != filletChamferData.end(); ++point_it) {
- if (flexible) {
- result.push_back(Point(fillet_chamfer_values.to_time(i, (*point_it)[X]),
- (*point_it)[Y]));
- } else {
- result.push_back(Point(fillet_chamfer_values.to_len(i, (*point_it)[X]),
- (*point_it)[Y]));
- }
- i++;
- }
- if (flexible) {
- radius.param_set_range(0., 100);
- radius.param_set_value(0);
- } else {
- radius.param_set_range(0., infinity());
- radius.param_set_value(0);
- }
- fillet_chamfer_values.param_set_and_write_new_value(result);
-}
-
-void LPEFilletChamfer::updateFillet()
-{
- double power = 0;
- if (!flexible) {
- power = Inkscape::Util::Quantity::convert(radius, unit.get_abbreviation(), *defaultUnit) * -1;
- } else {
- power = radius;
- }
- Piecewise<D2<SBasis> > const &pwd2 = fillet_chamfer_values.get_pwd2();
- doUpdateFillet(path_from_piecewise(pwd2, tolerance), power);
-}
-
-void LPEFilletChamfer::fillet()
-{
- Piecewise<D2<SBasis> > const &pwd2 = fillet_chamfer_values.get_pwd2();
- doChangeType(path_from_piecewise(pwd2, tolerance), 1);
-}
-
-void LPEFilletChamfer::inverseFillet()
-{
- Piecewise<D2<SBasis> > const &pwd2 = fillet_chamfer_values.get_pwd2();
- doChangeType(path_from_piecewise(pwd2, tolerance), 2);
-}
-
-void LPEFilletChamfer::chamferSubdivisions()
-{
- fillet_chamfer_values.set_chamfer_steps(chamfer_steps);
- Piecewise<D2<SBasis> > const &pwd2 = fillet_chamfer_values.get_pwd2();
- doChangeType(path_from_piecewise(pwd2, tolerance), chamfer_steps + 5000);
-}
-
-void LPEFilletChamfer::chamfer()
-{
- fillet_chamfer_values.set_chamfer_steps(chamfer_steps);
- Piecewise<D2<SBasis> > const &pwd2 = fillet_chamfer_values.get_pwd2();
- doChangeType(path_from_piecewise(pwd2, tolerance), chamfer_steps + 3000);
-}
-
-void LPEFilletChamfer::inverseChamfer()
-{
- fillet_chamfer_values.set_chamfer_steps(chamfer_steps);
- Piecewise<D2<SBasis> > const &pwd2 = fillet_chamfer_values.get_pwd2();
- doChangeType(path_from_piecewise(pwd2, tolerance), chamfer_steps + 4000);
-}
-
-void LPEFilletChamfer::refreshKnots()
-{
- Piecewise<D2<SBasis> > const &pwd2 = fillet_chamfer_values.get_pwd2();
- fillet_chamfer_values.recalculate_knots(pwd2);
- SPDesktop *desktop = SP_ACTIVE_DESKTOP;
- if (tools_isactive(desktop, TOOLS_NODES)) {
- tools_switch(desktop, TOOLS_SELECT);
- tools_switch(desktop, TOOLS_NODES);
- }
-}
-
-void LPEFilletChamfer::doUpdateFillet(std::vector<Geom::Path> const& original_pathv, double power)
-{
- std::vector<Point> filletChamferData = fillet_chamfer_values.data();
- std::vector<Geom::Point> result;
- std::vector<Geom::Path> original_pathv_processed = pathv_to_linear_and_cubic_beziers(original_pathv);
- int counter = 0;
- for (PathVector::const_iterator path_it = original_pathv_processed.begin();
- path_it != original_pathv_processed.end(); ++path_it) {
- if (path_it->empty())
- continue;
-
- Geom::Path::const_iterator curve_it1 = path_it->begin();
- Geom::Path::const_iterator curve_it2 = ++(path_it->begin());
- Geom::Path::const_iterator curve_endit = path_it->end_default();
- if (path_it->closed() && path_it->back_closed().isDegenerate()) {
- const Curve &closingline = path_it->back_closed();
- if (are_near(closingline.initialPoint(), closingline.finalPoint())) {
- curve_endit = path_it->end_open();
- }
- }
- double powerend = 0;
- while (curve_it1 != curve_endit) {
- powerend = power;
- if (power < 0 && !use_knot_distance) {
- powerend = fillet_chamfer_values.rad_to_len(counter,powerend);
- }
- if (power > 0) {
- powerend = counter + (power / 100);
- }
- if (ignore_radius_0 && (filletChamferData[counter][X] == 0 ||
- filletChamferData[counter][X] == counter)) {
- powerend = filletChamferData[counter][X];
- }
- if (filletChamferData[counter][Y] == 0) {
- powerend = filletChamferData[counter][X];
- }
- if (only_selected && !isNodePointSelected(curve_it1->initialPoint())) {
- powerend = filletChamferData[counter][X];
- }
- result.push_back(Point(powerend, filletChamferData[counter][Y]));
- ++curve_it1;
- ++curve_it2;
- counter++;
- }
- }
- fillet_chamfer_values.param_set_and_write_new_value(result);
-}
-
-void LPEFilletChamfer::doChangeType(std::vector<Geom::Path> const& original_pathv, int type)
-{
- std::vector<Point> filletChamferData = fillet_chamfer_values.data();
- std::vector<Geom::Point> result;
- std::vector<Geom::Path> original_pathv_processed = pathv_to_linear_and_cubic_beziers(original_pathv);
- int counter = 0;
- for (PathVector::const_iterator path_it = original_pathv_processed.begin(); path_it != original_pathv_processed.end(); ++path_it) {
- int pathCounter = 0;
- if (path_it->empty())
- continue;
-
- Geom::Path::const_iterator curve_it1 = path_it->begin();
- Geom::Path::const_iterator curve_it2 = ++(path_it->begin());
- Geom::Path::const_iterator curve_endit = path_it->end_default();
- if (path_it->closed() && path_it->back_closed().isDegenerate()) {
- const Curve &closingline = path_it->back_closed();
- if (are_near(closingline.initialPoint(), closingline.finalPoint())) {
- curve_endit = path_it->end_open();
- }
- }
- while (curve_it1 != curve_endit) {
- bool toggle = true;
- if (filletChamferData[counter][Y] == 0 ||
- (ignore_radius_0 && (filletChamferData[counter][X] == 0 ||
- filletChamferData[counter][X] == counter)) ||
- (only_selected && !isNodePointSelected(curve_it1->initialPoint()))) {
- toggle = false;
- }
- if (toggle) {
- if(type >= 5000){
- if(filletChamferData[counter][Y] >= 3000 && filletChamferData[counter][Y] < 4000){
- type = type - 2000;
- } else if (filletChamferData[counter][Y] >= 4000 && filletChamferData[counter][Y] < 5000){
- type = type - 1000;
- }
- }
- result.push_back(Point(filletChamferData[counter][X], type));
- } else {
- result.push_back(filletChamferData[counter]);
- }
- ++curve_it1;
- if (curve_it2 != curve_endit) {
- ++curve_it2;
- }
- counter++;
- pathCounter++;
- }
- }
- fillet_chamfer_values.param_set_and_write_new_value(result);
-}
void LPEFilletChamfer::doOnApply(SPLPEItem const *lpeItem)
{
- if (SP_IS_SHAPE(lpeItem)) {
- std::vector<Point> point;
- PathVector const &original_pathv = pathv_to_linear_and_cubic_beziers(SP_SHAPE(lpeItem)->_curve->get_pathvector());
- Piecewise<D2<SBasis> > pwd2_in = paths_to_pw(original_pathv);
+ SPShape * shape = dynamic_cast<SPshape *>(lpeItem);
+ if (shape) {
+ std::vector<std::pair<int,GeomSatellite> pointwise;
+ PathVector const &original_pathv = pathv_to_linear_and_cubic_beziers(shape->gerCurve->get_pathvector());
+ //Piecewise<D2<SBasis> > pwd2_in = paths_to_pw(original_pathv);
for (PathVector::const_iterator path_it = original_pathv.begin(); path_it != original_pathv.end(); ++path_it) {
if (path_it->empty())
continue;
@@ -401,25 +61,16 @@ void LPEFilletChamfer::doOnApply(SPLPEItem const *lpeItem)
}
int counter = 0;
while (curve_it1 != curve_endit) {
- std::pair<std::size_t, std::size_t> positions = fillet_chamfer_values.get_positions(counter, original_pathv);
+ Geom::Saltellite sat(FILLET, true, true, false, false, false, 0, 0.2);
+ std::pair<std::size_t, std::size_t> positions = pointwise_values.get_positions(counter, original_pathv);
Geom::NodeType nodetype;
if (positions.second == 0) {
- if (path_it->closed()) {
- Piecewise<D2<SBasis> > u;
- u.push_cut(0);
- u.push(pwd2_in[fillet_chamfer_values.last_index(counter, original_pathv)], 1);
- Geom::Curve const * A = path_from_piecewise(u, 0.1)[0][0].duplicate();
- nodetype = get_nodetype(*A, *curve_it1);
- } else {
- nodetype = NODE_NONE;
- }
+ nodetype = NODE_NONE;
} else {
nodetype = get_nodetype((*path_it)[counter - 1], *curve_it1);
}
if (nodetype == NODE_CUSP) {
- point.push_back(Point(0, 1));
- } else {
- point.push_back(Point(0, 0));
+ pointwise.push_back(std::pair<counter,sat>);
}
++curve_it1;
if (curve_it2 != curve_endit) {
@@ -428,222 +79,14 @@ void LPEFilletChamfer::doOnApply(SPLPEItem const *lpeItem)
counter++;
}
}
- fillet_chamfer_values.param_set_and_write_new_value(point);
+ pointwise_values.param_set_and_write_new_value(pointwise);
} else {
- g_warning("LPE Fillet can only be applied to shapes (not groups).");
+ g_warning("LPE Fillet/Chamfer can only be applied to shapes (not groups).");
SPLPEItem * item = const_cast<SPLPEItem*>(lpeItem);
item->removeCurrentPathEffect(false);
}
}
-void LPEFilletChamfer::doBeforeEffect(SPLPEItem const *lpeItem)
-{
- if (SP_IS_SHAPE(lpeItem)) {
- if(hide_knots){
- fillet_chamfer_values.set_helper_size(0);
- } else {
- fillet_chamfer_values.set_helper_size(helper_size);
- }
- fillet_chamfer_values.set_document_unit(defaultUnit);
- fillet_chamfer_values.set_use_distance(use_knot_distance);
- fillet_chamfer_values.set_unit(unit.get_abbreviation());
- SPCurve *c = SP_IS_PATH(lpeItem) ? static_cast<SPPath const *>(lpeItem)
- ->get_original_curve()
- : SP_SHAPE(lpeItem)->getCurve();
- std::vector<Point> filletChamferData = fillet_chamfer_values.data();
- if (!filletChamferData.empty() && getKnotsNumber(c) != (int)
- filletChamferData.size()) {
- PathVector const original_pathv = pathv_to_linear_and_cubic_beziers(c->get_pathvector());
- Piecewise<D2<SBasis> > pwd2_in = paths_to_pw(original_pathv);
- fillet_chamfer_values.recalculate_controlpoints_for_new_pwd2(pwd2_in);
- }
- } else {
- g_warning("LPE Fillet can only be applied to shapes (not groups).");
- }
-}
-
-int LPEFilletChamfer::getKnotsNumber(SPCurve const *c)
-{
- int nKnots = c->nodes_in_path();
- PathVector const pv = pathv_to_linear_and_cubic_beziers(c->get_pathvector());
- for (std::vector<Geom::Path>::const_iterator path_it = pv.begin();
- path_it != pv.end(); ++path_it) {
- if (!(*path_it).closed()) {
- nKnots--;
- }
- }
- return nKnots;
-}
-
-void
-LPEFilletChamfer::adjustForNewPath(std::vector<Geom::Path> const &path_in)
-{
- if (!path_in.empty()) {
- fillet_chamfer_values.recalculate_controlpoints_for_new_pwd2(pathv_to_linear_and_cubic_beziers(path_in)[0].toPwSb());
- }
-}
-
-std::vector<Geom::Path>
-LPEFilletChamfer::doEffect_path(std::vector<Geom::Path> const &path_in)
-{
- std::vector<Geom::Path> pathvector_out;
- Piecewise<D2<SBasis> > pwd2_in = paths_to_pw(pathv_to_linear_and_cubic_beziers(path_in));
- pwd2_in = remove_short_cuts(pwd2_in, .01);
- Piecewise<D2<SBasis> > der = derivative(pwd2_in);
- Piecewise<D2<SBasis> > n = rot90(unitVector(der));
- fillet_chamfer_values.set_pwd2(pwd2_in, n);
- std::vector<Point> filletChamferData = fillet_chamfer_values.data();
- unsigned int counter = 0;
- const double K = (4.0 / 3.0) * (sqrt(2.0) - 1.0);
- std::vector<Geom::Path> path_in_processed = pathv_to_linear_and_cubic_beziers(path_in);
- for (PathVector::const_iterator path_it = path_in_processed.begin();
- path_it != path_in_processed.end(); ++path_it) {
- if (path_it->empty())
- continue;
- Geom::Path path_out;
- Geom::Path::const_iterator curve_it1 = path_it->begin();
- Geom::Path::const_iterator curve_it2 = ++(path_it->begin());
- Geom::Path::const_iterator curve_endit = path_it->end_default();
- if (path_it->closed()) {
- const Geom::Curve &closingline = path_it->back_closed();
- // the closing line segment is always of type
- // Geom::LineSegment.
- if (are_near(closingline.initialPoint(), closingline.finalPoint())) {
- // closingline.isDegenerate() did not work, because it only checks for
- // *exact* zero length, which goes wrong for relative coordinates and
- // rounding errors...
- // the closing line segment has zero-length. So stop before that one!
- curve_endit = path_it->end_open();
- }
- }
- unsigned int counterCurves = 0;
- while (curve_it1 != curve_endit) {
- Curve *curve_it2Fixed = (*path_it->begin()).duplicate();
- if(!path_it->closed() || curve_it2 != curve_endit){
- curve_it2Fixed = (*curve_it2).duplicate();
- }
- bool last = curve_it2 == curve_endit;
- std::vector<double> times = fillet_chamfer_values.get_times(counter, path_in, last);
- Curve *knotCurve1 = curve_it1->portion(times[0], times[1]);
- if (counterCurves > 0) {
- knotCurve1->setInitial(path_out.finalPoint());
- } else {
- path_out.start((*curve_it1).pointAt(times[0]));
- }
- Curve *knotCurve2 = curve_it2Fixed->portion(times[2], 1);
- Point startArcPoint = knotCurve1->finalPoint();
- Point endArcPoint = curve_it2Fixed->pointAt(times[2]);
- double k1 = distance(startArcPoint, curve_it1->finalPoint()) * K;
- double k2 = distance(endArcPoint, curve_it1->finalPoint()) * K;
- Geom::CubicBezier const *cubic1 = dynamic_cast<Geom::CubicBezier const *>(&*knotCurve1);
- Ray ray1(startArcPoint, curve_it1->finalPoint());
- if (cubic1) {
- ray1.setPoints((*cubic1)[2], startArcPoint);
- }
- Point handle1 = Point::polar(ray1.angle(),k1) + startArcPoint;
- Geom::CubicBezier const *cubic2 =
- dynamic_cast<Geom::CubicBezier const *>(&*knotCurve2);
- Ray ray2(curve_it1->finalPoint(), endArcPoint);
- if (cubic2) {
- ray2.setPoints(endArcPoint, (*cubic2)[1]);
- }
- Point handle2 = endArcPoint - Point::polar(ray2.angle(),k2);
- bool ccwToggle = cross(curve_it1->finalPoint() - startArcPoint, endArcPoint - startArcPoint) < 0;
- double angle = angle_between(ray1, ray2, ccwToggle);
- double handleAngle = ray1.angle() - angle;
- if (ccwToggle) {
- handleAngle = ray1.angle() + angle;
- }
- Point inverseHandle1 = Point::polar(handleAngle,k1) + startArcPoint;
- handleAngle = ray2.angle() + angle;
- if (ccwToggle) {
- handleAngle = ray2.angle() - angle;
- }
- Point inverseHandle2 = endArcPoint - Point::polar(handleAngle,k2);
- //straigth lines arc based
- Line const x_line(Geom::Point(0,0),Geom::Point(1,0));
- Line const angled_line(startArcPoint,endArcPoint);
- double angleArc = Geom::angle_between( x_line,angled_line);
- double radius = Geom::distance(startArcPoint,middle_point(startArcPoint,endArcPoint))/sin(angle/2.0);
- Coord rx = radius;
- Coord ry = rx;
-
- if (times[1] != 1) {
- if (times[1] != gapHelper && times[1] != times[0] + gapHelper) {
- path_out.append(*knotCurve1);
- }
- int type = 0;
- if(path_it->closed() && last){
- type = std::abs(filletChamferData[counter - counterCurves][Y]);
- } else if (!path_it->closed() && last){
- //0
- } else {
- type = std::abs(filletChamferData[counter + 1][Y]);
- }
- if(are_near(middle_point(startArcPoint,endArcPoint),curve_it1->finalPoint(), 0.0001)){
- path_out.appendNew<Geom::LineSegment>(endArcPoint);
- } else if (type >= 3000 && type < 4000) {
- unsigned int chamferSubs = type-3000;
- Geom::Path path_chamfer;
- path_chamfer.start(path_out.finalPoint());
- if((is_straight_curve(*curve_it1) && is_straight_curve(*curve_it2Fixed) && method != FM_BEZIER )|| method == FM_ARC){
- path_chamfer.appendNew<SVGEllipticalArc>(rx, ry, angleArc, 0, ccwToggle, endArcPoint);
- } else {
- path_chamfer.appendNew<Geom::CubicBezier>(handle1, handle2, endArcPoint);
- }
- double chamfer_stepsTime = 1.0/chamferSubs;
- for(unsigned int i = 1; i < chamferSubs; i++){
- Geom::Point chamferStep = path_chamfer.pointAt(chamfer_stepsTime * i);
- path_out.appendNew<Geom::LineSegment>(chamferStep);
- }
- path_out.appendNew<Geom::LineSegment>(endArcPoint);
- } else if (type >= 4000 && type < 5000) {
- unsigned int chamferSubs = type-4000;
- Geom::Path path_chamfer;
- path_chamfer.start(path_out.finalPoint());
- if((is_straight_curve(*curve_it1) && is_straight_curve(*curve_it2Fixed) && method != FM_BEZIER )|| method == FM_ARC){
- ccwToggle = ccwToggle?0:1;
- path_chamfer.appendNew<SVGEllipticalArc>(rx, ry, angleArc, 0, ccwToggle, endArcPoint);
- }else{
- path_chamfer.appendNew<Geom::CubicBezier>(inverseHandle1, inverseHandle2, endArcPoint);
- }
- double chamfer_stepsTime = 1.0/chamferSubs;
- for(unsigned int i = 1; i < chamferSubs; i++){
- Geom::Point chamferStep = path_chamfer.pointAt(chamfer_stepsTime * i);
- path_out.appendNew<Geom::LineSegment>(chamferStep);
- }
- path_out.appendNew<Geom::LineSegment>(endArcPoint);
- } else if (type == 2) {
- if((is_straight_curve(*curve_it1) && is_straight_curve(*curve_it2Fixed) && method != FM_BEZIER )|| method == FM_ARC){
- ccwToggle = ccwToggle?0:1;
- path_out.appendNew<SVGEllipticalArc>(rx, ry, angleArc, 0, ccwToggle, endArcPoint);
- }else{
- path_out.appendNew<Geom::CubicBezier>(inverseHandle1, inverseHandle2, endArcPoint);
- }
- } else if (type == 1){
- if((is_straight_curve(*curve_it1) && is_straight_curve(*curve_it2Fixed) && method != FM_BEZIER )|| method == FM_ARC){
- path_out.appendNew<SVGEllipticalArc>(rx, ry, angleArc, 0, ccwToggle, endArcPoint);
- } else {
- path_out.appendNew<Geom::CubicBezier>(handle1, handle2, endArcPoint);
- }
- }
- } else {
- path_out.append(*knotCurve1);
- }
- if (path_it->closed() && last) {
- path_out.close();
- }
- ++curve_it1;
- if (curve_it2 != curve_endit) {
- ++curve_it2;
- }
- counter++;
- counterCurves++;
- }
- pathvector_out.push_back(path_out);
- }
- return pathvector_out;
-}
}; //namespace LivePathEffect
}; /* namespace Inkscape */
diff --git a/src/live_effects/lpe-fillet-chamfer.h b/src/live_effects/lpe-fillet-chamfer.h
index 0d6a1ff17..f4462d154 100644
--- a/src/live_effects/lpe-fillet-chamfer.h
+++ b/src/live_effects/lpe-fillet-chamfer.h
@@ -27,58 +27,23 @@
#include "live_effects/parameter/bool.h"
#include "live_effects/parameter/unit.h"
-#include "live_effects/parameter/filletchamferpointarray.h"
+#include "live_effects/parameter/pointwise.h"
#include "live_effects/effect.h"
namespace Inkscape {
namespace LivePathEffect {
-enum FilletMethod {
- FM_AUTO,
- FM_ARC,
- FM_BEZIER,
- FM_END
-};
class LPEFilletChamfer : public Effect {
public:
LPEFilletChamfer(LivePathEffectObject *lpeobject);
virtual ~LPEFilletChamfer();
- virtual std::vector<Geom::Path> doEffect_path(std::vector<Geom::Path> const &path_in);
-
virtual void doOnApply(SPLPEItem const *lpeItem);
- virtual void doBeforeEffect(SPLPEItem const *lpeItem);
- virtual void adjustForNewPath(std::vector<Geom::Path> const &path_in);
- virtual Gtk::Widget* newWidget();
-
- int getKnotsNumber(SPCurve const *c);
- void toggleHide();
- void toggleFlexFixed();
- void chamfer();
- void chamferSubdivisions();
- void inverseChamfer();
- void fillet();
- void inverseFillet();
- void updateFillet();
- void doUpdateFillet(std::vector<Geom::Path> const& original_pathv, double power);
- void doChangeType(std::vector<Geom::Path> const& original_pathv, int type);
- void refreshKnots();
-
- FilletChamferPointArrayParam fillet_chamfer_values;
-private:
+ PointwiseArrayParam pointwise_values;
- BoolParam hide_knots;
- BoolParam ignore_radius_0;
- BoolParam only_selected;
- BoolParam flexible;
- BoolParam use_knot_distance;
- UnitParam unit;
- EnumParam<FilletMethod> method;
- ScalarParam radius;
- ScalarParam chamfer_steps;
- ScalarParam helper_size;
+private:
LPEFilletChamfer(const LPEFilletChamfer &);
LPEFilletChamfer &operator=(const LPEFilletChamfer &);
diff --git a/src/live_effects/parameter/Makefile_insert b/src/live_effects/parameter/Makefile_insert
index f990f41c7..d78b1e22f 100644
--- a/src/live_effects/parameter/Makefile_insert
+++ b/src/live_effects/parameter/Makefile_insert
@@ -26,6 +26,8 @@ ink_common_sources += \
live_effects/parameter/powerstrokepointarray.h \
live_effects/parameter/filletchamferpointarray.cpp \
live_effects/parameter/filletchamferpointarray.h \
+ live_effects/parameter/pointwise.cpp \
+ live_effects/parameter/pointwise.h \
live_effects/parameter/text.cpp \
live_effects/parameter/text.h \
live_effects/parameter/transformedpoint.cpp \
diff --git a/src/live_effects/parameter/array.cpp b/src/live_effects/parameter/array.cpp
index 1b8f742da..bd2bf1870 100644
--- a/src/live_effects/parameter/array.cpp
+++ b/src/live_effects/parameter/array.cpp
@@ -48,6 +48,38 @@ ArrayParam<Geom::Point>::readsvg(const gchar * str)
}
return Geom::Point(Geom::infinity(),Geom::infinity());
}
+void
+sp_svg_satellite_read_d(gchar const *str, satellite *sat){
+ gchar ** strarray = g_strsplit(str, "*", 0);
+ if(strarray.size() != 6){
+ g_strfreev (strarray);
+ return NULL;
+ }
+ sat->setSatelliteType(SatelliteTypeMap[strarray[0]]);
+ sat->setActive(helperfns_read_bool(strarray[1], true));
+ sat->sethasMirror(helperfns_read_bool(strarray[2], false));
+ sat->setHidden(helperfns_read_bool(strarray[3], false));
+ sat->setHidden(helperfns_read_bool(strarray[3], false));
+ sat->setTime(sp_svg_number_read_d(strarray[4], 0.0));
+ sat->setSize(sp_svg_number_read_d(strarray[5], 0.0));
+ g_strfreev (strarray);
+}
+
+template <>
+std::pair<int, satellite>
+ArrayParam<Geom::Point>::readsvg(const gchar * str)
+{
+ gchar ** strarray = g_strsplit(str, ",", 2);
+ int index;
+ Geom::satellite sat = NULL;
+ unsigned int success = sp_svg_number_read_d(strarray[0], &index);
+ success += sp_svg_satellite_read_d(strarray[1], &sat);
+ g_strfreev (strarray);
+ if (success == 2) {
+ return std::pair<index, sat>;
+ }
+ return std::pair<Geom::infinity(),NULL>;
+}
} /* namespace LivePathEffect */
diff --git a/src/live_effects/parameter/array.h b/src/live_effects/parameter/array.h
index a600f0257..b93c7a617 100644
--- a/src/live_effects/parameter/array.h
+++ b/src/live_effects/parameter/array.h
@@ -93,7 +93,14 @@ protected:
// separate items with pipe symbol
str << " | ";
}
- str << vector[i];
+ std::pair<int,Geom::satellite> pointwiseElement = dynamic_cast<std::pair<int,Geom::satellite> ><(_vector[i]);
+ if(pointwiseElement){
+ str << vector[i].first;
+ str << " , ";
+ str << vector[i].second;
+ } else {
+ str << vector[i];
+ }
}
}
diff --git a/src/live_effects/parameter/pointwise.cpp b/src/live_effects/parameter/pointwise.cpp
new file mode 100644
index 000000000..ec83eb6c7
--- /dev/null
+++ b/src/live_effects/parameter/pointwise.cpp
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) Jabiertxo Arraiza Cenoz <jabier.arraiza@marker.es>
+ * Special thanks to Johan Engelen for the base of the effect -powerstroke-
+ * Also to ScislaC for point me to the idea
+ * Also su_v for his construvtive feedback and time
+ * and finaly to Liam P. White for his big help on coding, that save me a lot of
+ * hours
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "knotholder.h"
+
+// TODO due to internal breakage in glibmm headers,
+// this has to be included last.
+#include <glibmm/i18n.h>
+
+
+using namespace Geom;
+
+namespace Inkscape {
+
+namespace LivePathEffect {
+
+PointwiseParam::PointwiseParam(
+ const Glib::ustring &label, const Glib::ustring &tip,
+ const Glib::ustring &key, Inkscape::UI::Widget::Registry *wr,
+ Effect *effect)
+ : ArrayParam<Pointwise>(label, tip, key, wr, effect, 0)
+{
+ knot_shape = SP_KNOT_SHAPE_DIAMOND;
+ knot_mode = SP_KNOT_MODE_XOR;
+ knot_color = 0x00ff0000;
+}
+
+PointwiseParam::~PointwiseParam() {}
+
+Gtk::Widget *PointwiseParam::param_newWidget()
+{
+ return NULL;
+}
+
+void PointwiseParam::set_oncanvas_looks(SPKnotShapeType shape,
+ SPKnotModeType mode,
+ guint32 color)
+{
+ knot_shape = shape;
+ knot_mode = mode;
+ knot_color = color;
+}
+
+PointwiseParamKnotHolderEntity::
+PointwiseParamKnotHolderEntity(
+ PointwiseParam *p)
+ : _pparam(p) {}
+
+void PointwiseParamKnotHolderEntity::knot_set(Point const &p,
+ Point const &/*origin*/,
+ guint state)
+{
+ Geom::Point const s = snap_knot_position(p, state);
+ _pparam->_vector.at(_index).second.setPosition(s,_pparam->_pointwise.pwd2[_pparam->_vector.at(_index).first]);
+ sp_lpe_item_update_patheffect(SP_LPE_ITEM(item), false, false);
+}
+
+Point PointwiseParamKnotHolderEntity::knot_get() const
+{
+ Geom::Point const canvas_point = _pparam->_vector.at(_index).second.getPosition(_pparam->_pointwise.pwd2[_pparam->_vector.at(_index).first]);
+ _pparam->updateCanvasIndicators();
+ return canvas_point;
+}
+
+
+void PointwiseParam::addKnotHolderEntities(KnotHolder *knotholder,
+ SPDesktop *desktop,
+ SPItem *item)
+{
+ for (unsigned int i = 0; i < _pointwise.satellites.size(); ++i) {
+ const gchar *tip;
+ tip = _("<b>Fillet</b>: <b>Ctrl+Click</b> toggle type, "
+ "<b>Shift+Click</b> open dialog, "
+ "<b>Ctrl+Alt+Click</b> reset");
+ PointwiseParamKnotHolderEntity *e =
+ new PointwiseParamKnotHolderEntity(this, i);
+ e->create(desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN, _(tip),
+ knot_shape, knot_mode, knot_color);
+ knotholder->add(e);
+ }
+ updateCanvasIndicators();
+}
+
+} /* namespace LivePathEffect */
+
+} /* namespace Inkscape */
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/live_effects/parameter/pointwise.h b/src/live_effects/parameter/pointwise.h
new file mode 100644
index 000000000..59f1b4ff4
--- /dev/null
+++ b/src/live_effects/parameter/pointwise.h
@@ -0,0 +1,88 @@
+#ifndef INKSCAPE_LIVEPATHEFFECT_POINTWISE_H
+#define INKSCAPE_LIVEPATHEFFECT_POINTWISE_H
+
+/*
+ * Inkscape::LivePathEffectParameters
+ * Copyright (C) Jabiertxo Arraiza Cenoz <jabier.arraiza@marker.es>
+ * Special thanks to Johan Engelen for the base of the effect -powerstroke-
+ * Also to ScislaC for point me to the idea
+ * Also su_v for his construvtive feedback and time
+ * To Nathan Hurst for his review and help on refactor
+ * and finaly to Liam P. White for his big help on coding, that save me a lot of
+ * hours
+ *
+ *
+ * This parameter act as bridge from pointwise class to serialize it as a LPE
+ * parameter
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <glib.h>
+#include "knot-holder-entity.h"
+
+namespace Inkscape {
+
+namespace LivePathEffect {
+
+class PointwiseParamKnotHolderEntity;
+
+class PointwiseParam : public ArrayParam<Geom::Pointwise> {
+public:
+ PointwiseParam(const Glib::ustring &label,
+ const Glib::ustring &tip,
+ const Glib::ustring &key,
+ Inkscape::UI::Widget::Registry *wr,
+ Effect *effect);
+ virtual ~PointwiseParam();
+
+ virtual Gtk::Widget * param_newWidget() {
+ return NULL;
+ }
+
+ void set_oncanvas_looks(SPKnotShapeType shape, SPKnotModeType mode,
+ guint32 color);
+ virtual bool providesKnotHolderEntities() const {
+ return true;
+ }
+ friend class PointwiseParamKnotHolderEntity;
+
+protected:
+
+ StorageType readsvg(const gchar * str);
+
+private:
+ PointwiseParam(const PointwiseParam &);
+ PointwiseParam &operator=(const PointwiseParam &);
+
+ SPKnotShapeType knot_shape;
+ SPKnotModeType knot_mode;
+ guint32 knot_color;
+};
+
+class PointwiseParamKnotHolderEntity : public KnotHolderEntity {
+public:
+ PointwiseParamKnotHolderEntity(PointwiseParam *p,
+ unsigned int index);
+ virtual ~PointwiseParamKnotHolderEntity() {}
+
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin,
+ guint state);
+ virtual Geom::Point knot_get() const;
+
+ /*Checks whether the index falls within the size of the parameter's vector*/
+ bool valid_index(unsigned int index) const {
+ return (_pparam->_vector.size() > index);
+ }
+ ;
+
+private:
+ PointwiseParam *_pparam;
+ unsigned int _index;
+};
+
+} //namespace LivePathEffect
+
+} //namespace Inkscape
+
+#endif