diff options
| author | Jabier Arraiza Cenoz <jabier.arraiza@marker.es> | 2017-04-26 09:16:33 +0000 |
|---|---|---|
| committer | jabiertxof <info@marker.es> | 2017-04-26 09:16:33 +0000 |
| commit | b84137c431a7e236131f71a17f8f2c71e26c6162 (patch) | |
| tree | 04cbe26ab83d5a7ddf1fde8d2da153cc9039306b /src/live_effects | |
| parent | Allow set and reset default values of LPE parameters (diff) | |
| parent | Improve 0.92 support for Clone Original LPE (diff) | |
| download | inkscape-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.cpp | 39 | ||||
| -rw-r--r-- | src/live_effects/lpe-clone-original.h | 3 | ||||
| -rw-r--r-- | src/live_effects/lpe-copy_rotate.cpp | 281 | ||||
| -rw-r--r-- | src/live_effects/lpe-copy_rotate.h | 19 | ||||
| -rw-r--r-- | src/live_effects/parameter/point.cpp | 19 | ||||
| -rw-r--r-- | src/live_effects/parameter/point.h | 2 |
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; }; |
