summaryrefslogtreecommitdiffstats
path: root/src/live_effects
diff options
context:
space:
mode:
authorJabier Arraiza Cenoz <jabier.arraiza@marker.es>2017-04-26 09:16:33 +0000
committerjabiertxof <info@marker.es>2017-04-26 09:16:33 +0000
commitb84137c431a7e236131f71a17f8f2c71e26c6162 (patch)
tree04cbe26ab83d5a7ddf1fde8d2da153cc9039306b /src/live_effects
parentAllow set and reset default values of LPE parameters (diff)
parentImprove 0.92 support for Clone Original LPE (diff)
downloadinkscape-b84137c431a7e236131f71a17f8f2c71e26c6162.tar.gz
inkscape-b84137c431a7e236131f71a17f8f2c71e26c6162.zip
Update to trunk
(bzr r15620.1.2)
Diffstat (limited to 'src/live_effects')
-rw-r--r--src/live_effects/lpe-clone-original.cpp39
-rw-r--r--src/live_effects/lpe-clone-original.h3
-rw-r--r--src/live_effects/lpe-copy_rotate.cpp281
-rw-r--r--src/live_effects/lpe-copy_rotate.h19
-rw-r--r--src/live_effects/parameter/point.cpp19
-rw-r--r--src/live_effects/parameter/point.h2
6 files changed, 168 insertions, 195 deletions
diff --git a/src/live_effects/lpe-clone-original.cpp b/src/live_effects/lpe-clone-original.cpp
index 74f93eddc..ae20b582a 100644
--- a/src/live_effects/lpe-clone-original.cpp
+++ b/src/live_effects/lpe-clone-original.cpp
@@ -20,8 +20,7 @@ namespace LivePathEffect {
LPECloneOriginal::LPECloneOriginal(LivePathEffectObject *lpeobject) :
Effect(lpeobject),
- linked_path("LEGACY FALLBACK", "LEGACY FALLBACK", "linkedpath", &wr, this),
- linked_item(_("Linked Item:"), _("Item from which to take the original data"), "linked_item", &wr, this),
+ linkeditem(_("Linked Item:"), _("Item from which to take the original data"), "linkeditem", &wr, this),
scale(_("Scale %"), _("Scale item %"), "scale", &wr, this, 100.0),
preserve_position(_("Preserve position"), _("Preserve position"), "preserve_position", &wr, this, false),
inverse(_("Inverse clone"), _("Use LPE item as origin"), "inverse", &wr, this, false),
@@ -37,8 +36,15 @@ LPECloneOriginal::LPECloneOriginal(LivePathEffectObject *lpeobject) :
expanded(false),
origin(Geom::Point(0,0))
{
- registerParameter(&linked_path);
- registerParameter(&linked_item);
+ //0.92 compatibility
+ const gchar * linkedpath = this->getRepr()->attribute("linkedpath");
+ if (linkedpath && strcmp(linkedpath, "") != 0){
+ this->getRepr()->setAttribute("linkeditem", linkedpath);
+ this->getRepr()->setAttribute("linkedpath", NULL);
+ this->getRepr()->setAttribute("transform", "false");
+ };
+
+ registerParameter(&linkeditem);
registerParameter(&scale);
registerParameter(&attributes);
registerParameter(&style_attributes);
@@ -208,19 +214,8 @@ LPECloneOriginal::cloneAttrbutes(SPObject *origin, SPObject *dest, bool live, co
void
LPECloneOriginal::doBeforeEffect (SPLPEItem const* lpeitem){
- if (linked_path.linksToPath()) { //Legacy staff
- Glib::ustring attributes_value("d");
- attributes.param_setValue(attributes_value);
- attributes.write_to_SVG();
- Glib::ustring style_attributes_value("");
- style_attributes.param_setValue(style_attributes_value);
- style_attributes.write_to_SVG();
- linked_item.param_readSVGValue(linked_path.param_getSVGValue());
- linked_path.param_readSVGValue("");
- }
-
- if (linked_item.linksToItem()) {
- linked_item.setInverse(inverse);
+ if (linkeditem.linksToItem()) {
+ linkeditem.setInverse(inverse);
if ( preserve_position_changed != preserve_position ) {
if (!preserve_position) {
sp_svg_transform_read(SP_ITEM(sp_lpe_item)->getAttribute("transform"), &preserve_affine);
@@ -262,8 +257,8 @@ LPECloneOriginal::doBeforeEffect (SPLPEItem const* lpeitem){
}
style_attr.append(Glib::ustring(style_attributes.param_getSVGValue()).append(","));
- SPItem * from = inverse ? SP_ITEM(sp_lpe_item) : SP_ITEM(linked_item.getObject());
- SPItem * to = !inverse ? SP_ITEM(sp_lpe_item) : SP_ITEM(linked_item.getObject());
+ SPItem * from = inverse ? SP_ITEM(sp_lpe_item) : SP_ITEM(linkeditem.getObject());
+ SPItem * to = !inverse ? SP_ITEM(sp_lpe_item) : SP_ITEM(linkeditem.getObject());
cloneAttrbutes(from, to, true, g_strdup(attr.c_str()), g_strdup(style_attr.c_str()), true);
Geom::OptRect bbox = from->geometricBounds();
if (bbox && preserve_position && origin != Geom::Point(0,0)) {
@@ -361,15 +356,15 @@ LPECloneOriginal::~LPECloneOriginal()
void
LPECloneOriginal::transform_multiply(Geom::Affine const& postmul, bool set)
{
- if (linked_item.linksToItem()) {
- linked_item.getObject()->requestModified(SP_OBJECT_MODIFIED_FLAG);
+ if (linkeditem.linksToItem()) {
+ linkeditem.getObject()->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
}
void
LPECloneOriginal::doEffect (SPCurve * curve)
{
- if (linked_item.linksToItem() && !inverse) {
+ if (linkeditem.linksToItem() && !inverse) {
SPShape * shape = getCurrentShape();
if(shape){
curve->set_pathvector(shape->getCurve()->get_pathvector());
diff --git a/src/live_effects/lpe-clone-original.h b/src/live_effects/lpe-clone-original.h
index e4328c169..9bab8553f 100644
--- a/src/live_effects/lpe-clone-original.h
+++ b/src/live_effects/lpe-clone-original.h
@@ -32,8 +32,7 @@ public:
void cloneAttrbutes(SPObject *origin, SPObject *dest, bool live, const char * attributes, const char * style_attributes, bool root);
private:
- OriginalPathParam linked_path;
- OriginalItemParam linked_item;
+ OriginalItemParam linkeditem;
ScalarParam scale;
BoolParam preserve_position;
BoolParam inverse;
diff --git a/src/live_effects/lpe-copy_rotate.cpp b/src/live_effects/lpe-copy_rotate.cpp
index a462c76a6..1fd0e466f 100644
--- a/src/live_effects/lpe-copy_rotate.cpp
+++ b/src/live_effects/lpe-copy_rotate.cpp
@@ -30,6 +30,14 @@
namespace Inkscape {
namespace LivePathEffect {
+static const Util::EnumData<RotateMethod> RotateMethodData[RM_END] = {
+ { RM_NORMAL, N_("Normal"), "normal" },
+ { RM_KALEIDOSCOPE, N_("Kaleidoscope"), "kaleidoskope" },
+ { RM_FUSE, N_("Fuse paths"), "fuse_paths" }
+};
+static const Util::EnumDataConverter<RotateMethod>
+RMConverter(RotateMethodData, RM_END);
+
bool
pointInTriangle(Geom::Point const &p, Geom::Point const &p1, Geom::Point const &p2, Geom::Point const &p3)
{
@@ -52,30 +60,37 @@ LPECopyRotate::LPECopyRotate(LivePathEffectObject *lpeobject) :
starting_angle(_("Starting angle"), _("Angle of the first copy"), "starting_angle", &wr, this, 0.0),
rotation_angle(_("Rotation angle"), _("Angle between two successive copies"), "rotation_angle", &wr, this, 60.0),
num_copies(_("Number of copies"), _("Number of copies of the original path"), "num_copies", &wr, this, 6),
- split_gap(_("Gap on split"), _("Gap on split"), "split_gap", &wr, this, -0.001),
+ gap(_("Gap"), _("Gap"), "gap", &wr, this, -0.0001),
copies_to_360(_("360º Copies"), _("No rotation angle, fixed to 360º"), "copies_to_360", &wr, this, true),
- fuse_paths(_("Kaleidoskope"), _("Kaleidoskope by helper line, use fill-rule: evenodd for best result"), "fuse_paths", &wr, this, false),
- join_paths(_("Join paths"), _("Join paths, use fill-rule: evenodd for best result"), "join_paths", &wr, this, false),
+ method(_("Method:"), _("Rotate methods"), "method", RMConverter, &wr, this, RM_NORMAL),
+ mirror_copies(_("Mirror copies"), _("Mirror between copies"), "mirror_copies", &wr, this, false),
split_items(_("Split elements"), _("Split elements, this allow gradients and other paints."), "split_items", &wr, this, false),
dist_angle_handle(100.0)
{
show_orig_path = true;
_provides_knotholder_entities = true;
+ //0.92 compatibility
+ if (this->getRepr()->attribute("fuse_paths") && strcmp(this->getRepr()->attribute("fuse_paths"), "true") == 0){
+ this->getRepr()->setAttribute("fuse_paths", NULL);
+ this->getRepr()->setAttribute("method", "kaleidoskope");
+ this->getRepr()->setAttribute("mirror_copies", "true");
+ };
// register all your parameters here, so Inkscape knows which parameters this effect has:
- registerParameter(&copies_to_360);
- registerParameter(&fuse_paths);
- registerParameter(&join_paths);
- registerParameter(&split_items);
+ registerParameter(&method);
+ registerParameter(&num_copies);
registerParameter(&starting_angle);
registerParameter(&starting_point);
registerParameter(&rotation_angle);
- registerParameter(&num_copies);
- registerParameter(&split_gap);
+ registerParameter(&gap);
registerParameter(&origin);
- split_gap.param_set_range(-999999.0, 999999.0);
- split_gap.param_set_increments(0.1, 0.1);
- split_gap.param_set_digits(5);
- num_copies.param_set_range(0, 999999);
+ registerParameter(&copies_to_360);
+ registerParameter(&mirror_copies);
+ registerParameter(&split_items);
+
+ gap.param_set_range(-99999.0, 99999.0);
+ gap.param_set_increments(0.1, 0.1);
+ gap.param_set_digits(5);
+ num_copies.param_set_range(1, 999999);
num_copies.param_make_integer(true);
apply_to_clippath_and_mask = true;
previous_num_copies = num_copies;
@@ -132,38 +147,21 @@ LPECopyRotate::doAfterEffect (SPLPEItem const* lpeitem)
counter++;
}
g_free(id);
- double diagonal = Geom::distance(Geom::Point(boundingbox_X.min(),boundingbox_Y.min()),Geom::Point(boundingbox_X.max(),boundingbox_Y.max()));
- Geom::Rect bbox(Geom::Point(boundingbox_X.min(),boundingbox_Y.min()),Geom::Point(boundingbox_X.max(),boundingbox_Y.max()));
- double size_divider = Geom::distance(origin,bbox) + (diagonal * 2);
- Geom::Point line_start = origin + dir * Geom::Rotate(-(Geom::rad_from_deg(starting_angle))) * size_divider;
- Geom::Point line_end = origin + dir * Geom::Rotate(-(Geom::rad_from_deg(rotation_angle + starting_angle))) * size_divider;
Geom::Affine m = Geom::Translate(-origin) * Geom::Rotate(-(Geom::rad_from_deg(starting_angle)));
- if (fuse_paths) {
- size_t rest = 0;
- for (size_t i = 1; i < num_copies; ++i) {
- Geom::Affine r = Geom::identity();
- Geom::Point dir = unit_vector((Geom::Point)origin - Geom::middle_point(line_start,line_end));
- if( rest%2 == 0) {
- r *= Geom::Rotate(Geom::Angle(dir)).inverse();
- r *= Geom::Scale(1, -1);
- r *= Geom::Rotate(Geom::Angle(dir));
- }
- Geom::Rotate rot(-(Geom::rad_from_deg(rotation_angle * i)));
- Geom::Affine t = m * r * rot * Geom::Rotate(Geom::rad_from_deg(starting_angle)) * Geom::Translate(origin);
- if( rest%2 == 0) {
- t = m * r * rot * Geom::Rotate(Geom::rad_from_deg(starting_angle)).inverse() * Geom::Translate(origin);
- }
- t *= sp_lpe_item->transform;
- toItem(t, i-1, reset);
- rest ++;
+ for (size_t i = 1; i < num_copies; ++i) {
+ Geom::Affine r = Geom::identity();
+ if( i%2 != 0 && mirror_copies) {
+ r *= Geom::Rotate(Geom::Angle(half_dir)).inverse();
+ r *= Geom::Scale(1, -1);
+ r *= Geom::Rotate(Geom::Angle(half_dir));
}
- } else {
- for (size_t i = 1; i < num_copies; ++i) {
- Geom::Rotate rot(-(Geom::rad_from_deg(rotation_angle * i)));
- Geom::Affine t = m * rot * Geom::Rotate(Geom::rad_from_deg(starting_angle)) * Geom::Translate(origin);
- t *= sp_lpe_item->transform;
- toItem(t, i - 1, reset);
+ Geom::Rotate rot(-(Geom::rad_from_deg(rotation_angle * i)));
+ Geom::Affine t = m * r * rot * Geom::Rotate(Geom::rad_from_deg(starting_angle)) * Geom::Translate(origin);
+ if( i%2 != 0 && mirror_copies) {
+ t = m * r * rot * Geom::Rotate(Geom::rad_from_deg(starting_angle)).inverse() * Geom::Translate(origin);
}
+ t *= sp_lpe_item->transform;
+ toItem(t, i-1, reset);
}
reset = false;
} else {
@@ -302,15 +300,6 @@ Gtk::Widget * LPECopyRotate::newWidget()
vbox->set_border_width(5);
vbox->set_homogeneous(false);
vbox->set_spacing(2);
- Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false,0));
- Gtk::VBox * vbox_expander = Gtk::manage( new Gtk::VBox(Effect::newWidget()) );
- vbox_expander->set_border_width(0);
- vbox_expander->set_spacing(2);
- Gtk::Button * reset_button = Gtk::manage(new Gtk::Button(Glib::ustring(_("Reset styles"))));
- reset_button->signal_clicked().connect(sigc::mem_fun (*this,&LPECopyRotate::resetStyles));
- reset_button->set_size_request(140,30);
- vbox->pack_start(*hbox, true,true,2);
- hbox->pack_start(*reset_button, false, false,2);
std::vector<Parameter *>::iterator it = param_vector.begin();
while (it != param_vector.end()) {
if ((*it)->widget_is_visible) {
@@ -332,6 +321,13 @@ Gtk::Widget * LPECopyRotate::newWidget()
++it;
}
+ Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false,0));
+ Gtk::Button * reset_button = Gtk::manage(new Gtk::Button(Glib::ustring(_("Reset styles"))));
+ reset_button->signal_clicked().connect(sigc::mem_fun (*this,&LPECopyRotate::resetStyles));
+ reset_button->set_size_request(110,20);
+ vbox->pack_start(*hbox, true,true,2);
+ hbox->pack_start(*reset_button, false, false,2);
+
if (show_default_widgets) {
Gtk::Label *default_label = Gtk::manage(new Gtk::Label(
Glib::ustring(_("<b>Defaults</b> set defaultable parameters")),
@@ -347,6 +343,7 @@ Gtk::Widget * LPECopyRotate::newWidget()
defaultBox->pack_start(*reset_default, true, true, 2);
vbox->pack_start(*defaultBox, true, true, 2);
}
+
return dynamic_cast<Gtk::Widget *>(vbox);
}
@@ -381,19 +378,24 @@ LPECopyRotate::doBeforeEffect (SPLPEItem const* lpeitem)
{
using namespace Geom;
original_bbox(lpeitem);
- if (copies_to_360) {
+ if (copies_to_360 && num_copies > 2) {
+ this->upd_params = true;
rotation_angle.param_set_value(360.0/(double)num_copies);
}
- if (fuse_paths && rotation_angle * num_copies > 360.1 && rotation_angle > 0) {
+
+ if ((method == RM_KALEIDOSCOPE || method == RM_FUSE) && rotation_angle * num_copies > 360.1 && rotation_angle > 0) {
+ this->upd_params = true;
num_copies.param_set_value(floor(360/rotation_angle));
}
- if (fuse_paths && copies_to_360) {
+ if ((method == RM_KALEIDOSCOPE || method == RM_FUSE) && mirror_copies && copies_to_360) {
+ this->upd_params = true;
num_copies.param_set_increments(2.0,10.0);
if ((int)num_copies%2 !=0) {
num_copies.param_set_value(num_copies+1);
rotation_angle.param_set_value(360.0/(double)num_copies);
}
} else {
+ this->upd_params = true;
num_copies.param_set_increments(1.0, 10.0);
}
@@ -406,7 +408,8 @@ LPECopyRotate::doBeforeEffect (SPLPEItem const* lpeitem)
// I first suspected the minus sign to be a bug in 2geom but it is
// likely due to SVG's choice of coordinate system orientation (max)
bool near = Geom::are_near(previous_start_point, (Geom::Point)starting_point, 0.01);
- if (!near) {
+ if (!near) {
+ this->upd_params = true;
starting_angle.param_set_value(deg_from_rad(-angle_between(dir, starting_point - origin)));
if (GDK_SHIFT_MASK) {
dist_angle_handle = L2(B - A);
@@ -420,11 +423,12 @@ LPECopyRotate::doBeforeEffect (SPLPEItem const* lpeitem)
start_pos = origin + dir * Rotate(-rad_from_deg(starting_angle)) * dist_angle_handle;
rot_pos = origin + dir * Rotate(-rad_from_deg(rotation_angle+starting_angle)) * dist_angle_handle;
near = Geom::are_near(start_pos, (Geom::Point)starting_point, 0.01);
- if (!near) {
+ if (!near) {
+ this->upd_params = true;
starting_point.param_setValue(start_pos, true);
}
previous_start_point = (Geom::Point)starting_point;
- if ( fuse_paths || copies_to_360 ) {
+ if ( method == RM_FUSE || copies_to_360 ) {
rot_pos = origin;
}
}
@@ -501,19 +505,21 @@ LPECopyRotate::setFusion(Geom::PathVector &path_on, Geom::Path divider, double s
}
Geom::PathVector tmp_path_helper;
Geom::Path append_path = original;
-
+ Geom::Point previous = original.finalPoint();
for (int i = 0; i < num_copies; ++i) {
Geom::Rotate rot(-Geom::rad_from_deg(rotation_angle * (i)));
Geom::Affine m = pre * rot * Geom::Translate(origin);
- if (i%2 != 0) {
- Geom::Point A = (Geom::Point)origin;
- Geom::Point B = origin + dir * Geom::Rotate(-Geom::rad_from_deg((rotation_angle*i)+starting_angle)) * size_divider;
- Geom::Line ls(A,B);
- m = Geom::reflection (ls.vector(), A);
+ if (i%2 != 0 && mirror_copies) {
+ Geom::Point point_a = (Geom::Point)origin;
+ Geom::Point point_b = origin + dir * Geom::Rotate(-Geom::rad_from_deg((rotation_angle*i)+starting_angle)) * size_divider;
+ Geom::Line ls(point_a, point_b);
+ m = Geom::reflection (ls.vector(), point_a);
+ append_path *= m;
} else {
append_path = original;
+ append_path *= m;
}
- append_path *= m;
+ previous = append_path.finalPoint();
if (tmp_path_helper.size() > 0) {
if (Geom::are_near(tmp_path_helper[tmp_path_helper.size()-1].finalPoint(), append_path.finalPoint())) {
Geom::Path tmp_append = append_path.reversed();
@@ -603,118 +609,83 @@ Geom::PathVector
LPECopyRotate::doEffect_path (Geom::PathVector const & path_in)
{
Geom::PathVector path_out;
- if (split_items && (fuse_paths || join_paths)) {
+ double diagonal = Geom::distance(Geom::Point(boundingbox_X.min(),boundingbox_Y.min()),Geom::Point(boundingbox_X.max(),boundingbox_Y.max()));
+ Geom::OptRect bbox = sp_lpe_item->geometricBounds();
+ size_divider = Geom::distance(origin,bbox) + (diagonal * 6);
+ Geom::Point line_start = origin + dir * Geom::Rotate(-(Geom::rad_from_deg(starting_angle))) * size_divider;
+ Geom::Point line_end = origin + dir * Geom::Rotate(-(Geom::rad_from_deg(rotation_angle + starting_angle))) * size_divider;
+ divider = Geom::Path(line_start);
+ divider.appendNew<Geom::LineSegment>((Geom::Point)origin);
+ divider.appendNew<Geom::LineSegment>(line_end);
+ divider.close();
+ half_dir = unit_vector(Geom::middle_point(line_start,line_end) - (Geom::Point)origin);
+ if (method == RM_KALEIDOSCOPE || method == RM_FUSE) {
+ if (method != RM_KALEIDOSCOPE) {
+ path_out = doEffect_path_post(path_in);
+ } else {
+ path_out = pathv_to_linear_and_cubic_beziers(path_in);
+ }
if (num_copies == 0) {
return path_out;
}
- path_out = pathv_to_linear_and_cubic_beziers(path_in);
- double diagonal = Geom::distance(Geom::Point(boundingbox_X.min(),boundingbox_Y.min()),Geom::Point(boundingbox_X.max(),boundingbox_Y.max()));
- Geom::OptRect bbox = sp_lpe_item->geometricBounds();
- double size_divider = Geom::distance(origin,bbox) + (diagonal * 2);
- Geom::Point line_start = origin + dir * Geom::Rotate(-(Geom::rad_from_deg(starting_angle))) * size_divider;
- Geom::Point line_end = origin + dir * Geom::Rotate(-(Geom::rad_from_deg(rotation_angle + starting_angle))) * size_divider;
- Geom::Path divider = Geom::Path(line_start);
- divider.appendNew<Geom::LineSegment>((Geom::Point)origin);
- divider.appendNew<Geom::LineSegment>(line_end);
- divider.close();
Geom::PathVector triangle;
triangle.push_back(divider);
Geom::PathIntersectionGraph *pig = new Geom::PathIntersectionGraph(triangle, path_out);
- if (pig && ! path_out.empty() && !triangle.empty()) {
- //TODO: Here can produce a crash because some knows problems in new boolops code
+ if (pig && !path_out.empty() && !triangle.empty()) {
path_out = pig->getIntersection();
}
- Geom::Affine r = Geom::identity();
- Geom::Point dir = unit_vector(Geom::middle_point(line_start,line_end) - (Geom::Point)origin);
- Geom::Point gap = dir * split_gap;
- path_out *= Geom::Translate(gap);
- } else {
- // default behavior
- for (unsigned int i=0; i < path_in.size(); i++) {
- Geom::Piecewise<Geom::D2<Geom::SBasis> > pwd2_in = path_in[i].toPwSb();
- Geom::Piecewise<Geom::D2<Geom::SBasis> > pwd2_out = doEffect_pwd2(pwd2_in);
- Geom::PathVector path = Geom::path_from_piecewise( pwd2_out, LPE_CONVERSION_TOLERANCE);
- // add the output path vector to the already accumulated vector:
- for (unsigned int j=0; j < path.size(); j++) {
- path_out.push_back(path[j]);
- }
+ path_out *= Geom::Translate(half_dir * gap);
+ if ( !split_items ) {
+ path_out *= Geom::Translate(half_dir * gap).inverse();
+ path_out = doEffect_path_post(path_out);
}
+ } else {
+ path_out = doEffect_path_post(path_in);
}
return pathv_to_linear_and_cubic_beziers(path_out);
}
-Geom::Piecewise<Geom::D2<Geom::SBasis> >
-LPECopyRotate::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in)
+Geom::PathVector
+LPECopyRotate::doEffect_path_post (Geom::PathVector const & path_in)
{
- using namespace Geom;
-
- if ((num_copies == 1 && !fuse_paths) || split_items) {
- return pwd2_in;
+ if ((split_items || num_copies == 1) && method != RM_FUSE && method != RM_KALEIDOSCOPE) {
+ return path_in;
}
- double diagonal = Geom::distance(Geom::Point(boundingbox_X.min(),boundingbox_Y.min()),Geom::Point(boundingbox_X.max(),boundingbox_Y.max()));
- Geom::Rect bbox(Geom::Point(boundingbox_X.min(),boundingbox_Y.min()),Geom::Point(boundingbox_X.max(),boundingbox_Y.max()));
- double size_divider = Geom::distance(origin,bbox) + (diagonal * 2);
- Geom::Point line_start = origin + dir * Rotate(-rad_from_deg(starting_angle)) * size_divider;
- Geom::Point line_end = origin + dir * Rotate(-rad_from_deg(rotation_angle + starting_angle)) * size_divider;
- //Note:: beter way to do this
- //Whith AppendNew have problems whith the crossing order
- Geom::Path divider = Geom::Path(line_start);
- divider.appendNew<Geom::LineSegment>((Geom::Point)origin);
- divider.appendNew<Geom::LineSegment>(line_end);
- Piecewise<D2<SBasis> > output;
- Affine pre = Translate(-origin) * Rotate(-rad_from_deg(starting_angle));
- PathVector const original_pathv = pathv_to_linear_and_cubic_beziers(path_from_piecewise(remove_short_cuts(pwd2_in, 0.1), 0.001));
- if (fuse_paths) {
- Geom::PathVector path_out;
- Geom::PathVector tmp_path;
- for (Geom::PathVector::const_iterator path_it = original_pathv.begin(); path_it != original_pathv.end(); ++path_it) {
- if (path_it->empty()) {
- continue;
- }
- bool end_open = false;
- if (path_it->closed()) {
- const Geom::Curve &closingline = path_it->back_closed();
- if (!are_near(closingline.initialPoint(), closingline.finalPoint())) {
- end_open = true;
- }
- }
- Geom::Path original = (Geom::Path)(*path_it);
- if (end_open && path_it->closed()) {
- original.close(false);
- original.appendNew<Geom::LineSegment>( original.initialPoint() );
- original.close(true);
- }
- tmp_path.push_back(original);
- setFusion(tmp_path, divider, size_divider);
- path_out.insert(path_out.end(), tmp_path.begin(), tmp_path.end());
- tmp_path.clear();
+ Geom::Affine pre = Geom::Translate(-origin) * Geom::Rotate(-Geom::rad_from_deg(starting_angle));
+ Geom::PathVector original_pathv = pathv_to_linear_and_cubic_beziers(path_in);
+ Geom::PathVector output_pv;
+ Geom::PathVector output;
+ for (int i = 0; i < num_copies; ++i) {
+ Geom::Rotate rot(-Geom::rad_from_deg(rotation_angle * i));
+ Geom::Affine r = Geom::identity();
+ if( i%2 != 0 && mirror_copies) {
+ r *= Geom::Rotate(Geom::Angle(half_dir)).inverse();
+ r *= Geom::Scale(1, -1);
+ r *= Geom::Rotate(Geom::Angle(half_dir));
}
- if (path_out.size()>0) {
- output = paths_to_pw(path_out);
+ Geom::Affine t = pre * r * rot * Geom::Rotate(Geom::rad_from_deg(starting_angle)) * Geom::Translate(origin);
+ if(mirror_copies && i%2 != 0) {
+ t = pre * r * rot * Geom::Rotate(Geom::rad_from_deg(starting_angle)).inverse() * Geom::Translate(origin);
}
- } else {
- Geom::PathVector output_pv;
- for (int i = 0; i < num_copies; ++i) {
- Rotate rot(-rad_from_deg(rotation_angle * i));
- Affine t = pre * rot * Translate(origin);
- if (join_paths) {
- Geom::PathVector join_pv = path_from_piecewise(pwd2_in * t , 0.01);
- Geom::PathIntersectionGraph *pig = new Geom::PathIntersectionGraph(output_pv, join_pv);
- if (pig) {
- if (!output_pv.empty()) {
- output_pv = pig->getUnion();
- } else {
- output_pv = join_pv;
- }
+ if (method == RM_FUSE || method == RM_KALEIDOSCOPE) {
+ Geom::PathVector join_pv = original_pathv * t;
+ join_pv *= Geom::Translate(half_dir * rot * gap);
+ Geom::PathIntersectionGraph *pig = new Geom::PathIntersectionGraph(output_pv, join_pv);
+ if (pig) {
+ if (!output_pv.empty()) {
+ output_pv = pig->getUnion();
+ } else {
+ output_pv = join_pv;
}
- } else {
- output.concat(pwd2_in * t);
}
+ } else {
+ output_pv = path_in * t;
+ output.insert(output.end(), output_pv.begin(), output_pv.end());
}
- if (join_paths) {
- output = paths_to_pw(output_pv);
- }
+ }
+ if (method == RM_FUSE || method == RM_KALEIDOSCOPE) {
+ output = output_pv;
}
return output;
}
diff --git a/src/live_effects/lpe-copy_rotate.h b/src/live_effects/lpe-copy_rotate.h
index dbec2e1c3..542a4e36e 100644
--- a/src/live_effects/lpe-copy_rotate.h
+++ b/src/live_effects/lpe-copy_rotate.h
@@ -15,6 +15,7 @@
*/
#include "live_effects/effect.h"
+#include "live_effects/parameter/enum.h"
#include "live_effects/parameter/parameter.h"
#include "live_effects/parameter/text.h"
#include "live_effects/parameter/point.h"
@@ -23,13 +24,20 @@
namespace Inkscape {
namespace LivePathEffect {
+enum RotateMethod {
+ RM_NORMAL,
+ RM_KALEIDOSCOPE,
+ RM_FUSE,
+ RM_END
+};
+
class LPECopyRotate : public Effect, GroupBBoxEffect {
public:
LPECopyRotate(LivePathEffectObject *lpeobject);
virtual ~LPECopyRotate();
virtual void doOnApply (SPLPEItem const* lpeitem);
virtual Geom::PathVector doEffect_path (Geom::PathVector const & path_in);
- virtual Geom::Piecewise<Geom::D2<Geom::SBasis> > doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in);
+ Geom::PathVector doEffect_path_post (Geom::PathVector const & path_in);
virtual void doBeforeEffect (SPLPEItem const* lpeitem);
virtual void doAfterEffect (SPLPEItem const* lpeitem);
virtual void setFusion(Geom::PathVector &path_in, Geom::Path divider, double sizeDivider);
@@ -51,18 +59,21 @@ private:
ScalarParam starting_angle;
ScalarParam rotation_angle;
ScalarParam num_copies;
- ScalarParam split_gap;
+ ScalarParam gap;
BoolParam copies_to_360;
- BoolParam fuse_paths;
- BoolParam join_paths;
+ EnumParam<RotateMethod> method;
+ BoolParam mirror_copies;
BoolParam split_items;
Geom::Point A;
Geom::Point B;
Geom::Point dir;
+ Geom::Point half_dir;
Geom::Point start_pos;
Geom::Point rot_pos;
Geom::Point previous_start_point;
double dist_angle_handle;
+ double size_divider;
+ Geom::Path divider;
double previous_num_copies;
bool reset;
SPObject * container;
diff --git a/src/live_effects/parameter/point.cpp b/src/live_effects/parameter/point.cpp
index 683cadc1f..561f1b34c 100644
--- a/src/live_effects/parameter/point.cpp
+++ b/src/live_effects/parameter/point.cpp
@@ -26,8 +26,7 @@ PointParam::PointParam( const Glib::ustring& label, const Glib::ustring& tip,
: Parameter(label, tip, key, wr, effect),
defvalue(default_value),
liveupdate(live_update),
- knoth(NULL),
- _pointwdg(NULL)
+ knoth(NULL)
{
knot_shape = SP_KNOT_SHAPE_DIAMOND;
knot_mode = SP_KNOT_MODE_XOR;
@@ -91,9 +90,7 @@ PointParam::param_setValue(Geom::Point newpoint, bool write)
if(knoth && liveupdate){
knoth->update_knots();
}
- if (_pointwdg) {
- _pointwdg->setValue( newpoint );
- }
+ param_effect->upd_params = true;
}
bool
@@ -129,7 +126,7 @@ PointParam::param_transform_multiply(Geom::Affine const& postmul, bool /*set*/)
Gtk::Widget *
PointParam::param_newWidget()
{
- _pointwdg = Gtk::manage(
+ Inkscape::UI::Widget::RegisteredTransformedPoint * pointwdg = Gtk::manage(
new Inkscape::UI::Widget::RegisteredTransformedPoint( param_label,
param_tooltip,
param_key,
@@ -138,13 +135,13 @@ PointParam::param_newWidget()
param_effect->getSPDoc() ) );
Geom::Affine transf = Geom::Scale(1, -1);
transf[5] = SP_ACTIVE_DOCUMENT->getHeight().value("px");
- _pointwdg->setTransform(transf);
- _pointwdg->setValue( *this );
- _pointwdg->clearProgrammatically();
- _pointwdg->set_undo_parameters(SP_VERB_DIALOG_LIVE_PATH_EFFECT, _("Change point parameter"));
+ pointwdg->setTransform(transf);
+ pointwdg->setValue( *this );
+ pointwdg->clearProgrammatically();
+ pointwdg->set_undo_parameters(SP_VERB_DIALOG_LIVE_PATH_EFFECT, _("Change point parameter"));
Gtk::HBox * hbox = Gtk::manage( new Gtk::HBox() );
- static_cast<Gtk::HBox*>(hbox)->pack_start(*_pointwdg, true, true);
+ static_cast<Gtk::HBox*>(hbox)->pack_start(*pointwdg, true, true);
static_cast<Gtk::HBox*>(hbox)->show_all_children();
param_effect->upd_params = false;
return dynamic_cast<Gtk::Widget *> (hbox);
diff --git a/src/live_effects/parameter/point.h b/src/live_effects/parameter/point.h
index a3797aea5..a5153ad80 100644
--- a/src/live_effects/parameter/point.h
+++ b/src/live_effects/parameter/point.h
@@ -44,6 +44,7 @@ public:
Geom::Point param_get_default() const;
void param_set_liveupdate(bool live_update);
void param_update_default(Geom::Point default_point);
+
virtual void param_update_default(const gchar * default_point);
virtual void param_transform_multiply(Geom::Affine const& /*postmul*/, bool /*set*/);
@@ -62,7 +63,6 @@ private:
SPKnotModeType knot_mode;
guint32 knot_color;
gchar *handle_tip;
- Inkscape::UI::Widget::RegisteredTransformedPoint * _pointwdg;
};