ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof/**
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof * @file
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof * Roughen LPE implementation. Creates roughen paths.
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof */
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof/* Authors:
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof * Jabier Arraiza Cenoz <jabier.arraiza@marker.es>
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof *
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof * Thanks to all people involved specialy to Josh Andler for the idea and to the
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof * original extensions authors.
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof *
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof * Copyright (C) 2014 Authors
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof *
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof * Released under GNU GPL, read the file 'COPYING' for more information
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof */
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof#include <gtkmm.h>
81db7808fbee540434bcc6c7198579b95a6a2d88Jabiertxof#include "desktop.h"
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof#include "live_effects/lpe-roughen.h"
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof#include "display/curve.h"
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof#include "live_effects/parameter/parameter.h"
3ab4e87511c6a42f29370bf22a9afcf759ca1d0dJabiertxof#include <boost/functional/hash.hpp>
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof#include "helper/geom.h"
cf6881c70132c81dc201e7af86da7da64c91e048Jabiertxof#include "sp-item-group.h"
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof#include <glibmm/i18n.h>
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof#include <cmath>
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxofnamespace Inkscape {
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxofnamespace LivePathEffect {
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxofstatic const Util::EnumData<DivisionMethod> DivisionMethodData[DM_END] = {
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof { DM_SEGMENTS, N_("By number of segments"), "segments" },
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof { DM_SIZE, N_("By max. segment size"), "size" }
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof};
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxofstatic const Util::EnumDataConverter<DivisionMethod>
ccbee7d45f91658e83a602a9a28ee26162a261f9JabiertxofDMConverter(DivisionMethodData, DM_END);
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof
a7e81150b867e54cf50d331e30bb88f5676248c6Jabiertxofstatic const Util::EnumData<HandlesMethod> HandlesMethodData[HM_END] = {
a7e81150b867e54cf50d331e30bb88f5676248c6Jabiertxof { HM_ALONG_NODES, N_("Along nodes"), "along" },
a7e81150b867e54cf50d331e30bb88f5676248c6Jabiertxof { HM_RAND, N_("Rand"), "rand" },
a7e81150b867e54cf50d331e30bb88f5676248c6Jabiertxof { HM_RETRACT, N_("Retract"), "retract" },
a7e81150b867e54cf50d331e30bb88f5676248c6Jabiertxof { HM_SMOOTH, N_("Smooth"), "smooth" }
a7e81150b867e54cf50d331e30bb88f5676248c6Jabiertxof};
a7e81150b867e54cf50d331e30bb88f5676248c6Jabiertxofstatic const Util::EnumDataConverter<HandlesMethod>
a7e81150b867e54cf50d331e30bb88f5676248c6JabiertxofHMConverter(HandlesMethodData, HM_END);
a7e81150b867e54cf50d331e30bb88f5676248c6Jabiertxof
60db347ea19e568bd09c35a0248a9f78d7931ca0JabiertxofLPERoughen::LPERoughen(LivePathEffectObject *lpeobject)
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof : Effect(lpeobject),
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof // initialise your parameters here:
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof method(_("Method"), _("Division method"), "method", DMConverter, &wr,
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof this, DM_SEGMENTS),
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof max_segment_size(_("Max. segment size"), _("Max. segment size"),
a7e81150b867e54cf50d331e30bb88f5676248c6Jabiertxof "max_segment_size", &wr, this, 10),
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof segments(_("Number of segments"), _("Number of segments"), "segments",
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof &wr, this, 2),
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof displace_x(_("Max. displacement in X"), _("Max. displacement in X"),
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof "displace_x", &wr, this, 10.),
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof displace_y(_("Max. displacement in Y"), _("Max. displacement in Y"),
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof "displace_y", &wr, this, 10.),
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof global_randomize(_("Global randomize"), _("Global randomize"),
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof "global_randomize", &wr, this, 1.),
a7e81150b867e54cf50d331e30bb88f5676248c6Jabiertxof handles(_("Handles"), _("Handles options"), "handles", HMConverter, &wr,
a7e81150b867e54cf50d331e30bb88f5676248c6Jabiertxof this, HM_ALONG_NODES),
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof shift_nodes(_("Shift nodes"), _("Shift nodes"), "shift_nodes", &wr, this,
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof true),
b04cfe75120fc5d17a8d2f24ca44e8e456cb74d5Yuri Chornoivan fixed_displacement(_("Fixed displacement"), _("Fixed displacement, 1/3 of segment length"),
3ab4e87511c6a42f29370bf22a9afcf759ca1d0dJabiertxof "fixed_displacement", &wr, this, false),
90536c2550e30d32a103d11bff4bb61ad00812aejabiertxof spray_tool_friendly(_("Spray Tool friendly"), _("For use with spray tool in copy mode"),
3ab4e87511c6a42f29370bf22a9afcf759ca1d0dJabiertxof "spray_tool_friendly", &wr, this, false)
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof{
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof registerParameter(&method);
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof registerParameter(&max_segment_size);
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof registerParameter(&segments);
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof registerParameter(&displace_x);
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof registerParameter(&displace_y);
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof registerParameter(&global_randomize);
a7e81150b867e54cf50d331e30bb88f5676248c6Jabiertxof registerParameter(&handles);
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof registerParameter(&shift_nodes);
9d766cc272a22da6d0de4ebf6896da731b6c45c0jabiertxof registerParameter(&fixed_displacement);
3ab4e87511c6a42f29370bf22a9afcf759ca1d0dJabiertxof registerParameter(&spray_tool_friendly);
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof displace_x.param_set_range(0., Geom::infinity());
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof displace_y.param_set_range(0., Geom::infinity());
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof global_randomize.param_set_range(0., Geom::infinity());
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof max_segment_size.param_set_range(0., Geom::infinity());
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof max_segment_size.param_set_increments(1, 1);
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof max_segment_size.param_set_digits(1);
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof segments.param_set_range(1, Geom::infinity());
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof segments.param_set_increments(1, 1);
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof segments.param_set_digits(0);
a7e81150b867e54cf50d331e30bb88f5676248c6Jabiertxof seed = 0;
b8d3bf3a76982b925ccacab389e190adbfa1f3b1jabiertxof apply_to_clippath_and_mask = true;
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof}
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof
60db347ea19e568bd09c35a0248a9f78d7931ca0JabiertxofLPERoughen::~LPERoughen() {}
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof
2ce2003d5713154f99c32af18fb904a1af109031Jabiertxofvoid LPERoughen::doBeforeEffect(SPLPEItem const *lpeitem)
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof{
610985fe6a87b78eebcd60309f673221a406f238jabiertxof if(spray_tool_friendly && seed == 0 && SP_OBJECT(lpeitem)->getId()){
a7e81150b867e54cf50d331e30bb88f5676248c6Jabiertxof std::string id_item(SP_OBJECT(lpeitem)->getId());
a7e81150b867e54cf50d331e30bb88f5676248c6Jabiertxof long seed = static_cast<long>(boost::hash_value(id_item));
a7e81150b867e54cf50d331e30bb88f5676248c6Jabiertxof global_randomize.param_set_value(global_randomize.get_value(), seed);
a7e81150b867e54cf50d331e30bb88f5676248c6Jabiertxof }
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof displace_x.resetRandomizer();
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof displace_y.resetRandomizer();
a7e81150b867e54cf50d331e30bb88f5676248c6Jabiertxof global_randomize.resetRandomizer();
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof srand(1);
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof}
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof
ccbee7d45f91658e83a602a9a28ee26162a261f9JabiertxofGtk::Widget *LPERoughen::newWidget()
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof{
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof Gtk::VBox *vbox = Gtk::manage(new Gtk::VBox(Effect::newWidget()));
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof vbox->set_border_width(5);
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof vbox->set_homogeneous(false);
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof vbox->set_spacing(2);
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof std::vector<Parameter *>::iterator it = param_vector.begin();
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof while (it != param_vector.end()) {
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof if ((*it)->widget_is_visible) {
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof Parameter *param = *it;
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof Gtk::Widget *widg = dynamic_cast<Gtk::Widget *>(param->param_newWidget());
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof if (param->param_key == "method") {
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof Gtk::Label *method_label = Gtk::manage(new Gtk::Label(
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof Glib::ustring(_("<b>Add nodes</b> Subdivide each segment")),
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof Gtk::ALIGN_START));
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof method_label->set_use_markup(true);
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof vbox->pack_start(*method_label, false, false, 2);
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof vbox->pack_start(*Gtk::manage(new Gtk::HSeparator()),
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof Gtk::PACK_EXPAND_WIDGET);
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof }
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof if (param->param_key == "displace_x") {
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof Gtk::Label *displace_x_label = Gtk::manage(new Gtk::Label(
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof Glib::ustring(_("<b>Jitter nodes</b> Move nodes/handles")),
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof Gtk::ALIGN_START));
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof displace_x_label->set_use_markup(true);
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof vbox->pack_start(*displace_x_label, false, false, 2);
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof vbox->pack_start(*Gtk::manage(new Gtk::HSeparator()),
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof Gtk::PACK_EXPAND_WIDGET);
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof }
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof if (param->param_key == "global_randomize") {
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof Gtk::Label *global_rand = Gtk::manage(new Gtk::Label(
de641d2613f4eea940ba6eb6c52ea9bcda516ba2Jabiertxof Glib::ustring(_("<b>Extra roughen</b> Add a extra layer of rough")),
721286d6ce40a27fcd8b9483667a43ed09023b17Jabiertxof Gtk::ALIGN_START));
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof global_rand->set_use_markup(true);
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof vbox->pack_start(*global_rand, false, false, 2);
721286d6ce40a27fcd8b9483667a43ed09023b17Jabiertxof vbox->pack_start(*Gtk::manage(new Gtk::HSeparator()),
721286d6ce40a27fcd8b9483667a43ed09023b17Jabiertxof Gtk::PACK_EXPAND_WIDGET);
721286d6ce40a27fcd8b9483667a43ed09023b17Jabiertxof }
a7e81150b867e54cf50d331e30bb88f5676248c6Jabiertxof if (param->param_key == "handles") {
3ab4e87511c6a42f29370bf22a9afcf759ca1d0dJabiertxof Gtk::Label *options = Gtk::manage(new Gtk::Label(
3ab4e87511c6a42f29370bf22a9afcf759ca1d0dJabiertxof Glib::ustring(_("<b>Options</b> Modify options to rough")),
3ab4e87511c6a42f29370bf22a9afcf759ca1d0dJabiertxof Gtk::ALIGN_START));
3ab4e87511c6a42f29370bf22a9afcf759ca1d0dJabiertxof options->set_use_markup(true);
3ab4e87511c6a42f29370bf22a9afcf759ca1d0dJabiertxof vbox->pack_start(*options, false, false, 2);
3ab4e87511c6a42f29370bf22a9afcf759ca1d0dJabiertxof vbox->pack_start(*Gtk::manage(new Gtk::HSeparator()),
3ab4e87511c6a42f29370bf22a9afcf759ca1d0dJabiertxof Gtk::PACK_EXPAND_WIDGET);
3ab4e87511c6a42f29370bf22a9afcf759ca1d0dJabiertxof }
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof Glib::ustring *tip = param->param_getTooltip();
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof if (widg) {
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof vbox->pack_start(*widg, true, true, 2);
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof if (tip) {
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof widg->set_tooltip_text(*tip);
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof } else {
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof widg->set_tooltip_text("");
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof widg->set_has_tooltip(false);
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof }
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof }
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof }
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof ++it;
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof }
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof return dynamic_cast<Gtk::Widget *>(vbox);
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof}
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxofdouble LPERoughen::sign(double random_number)
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof{
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof if (rand() % 100 < 49) {
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof random_number *= -1.;
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof }
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof return random_number;
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof}
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof
c2e7008ce6d44e568eb899040b80336e3465882eJabiertxofGeom::Point LPERoughen::randomize(double max_lenght, bool is_node)
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof{
c2e7008ce6d44e568eb899040b80336e3465882eJabiertxof double factor = 1.0/3.0;
c2e7008ce6d44e568eb899040b80336e3465882eJabiertxof if(is_node){
c2e7008ce6d44e568eb899040b80336e3465882eJabiertxof factor = 1.0;
f7b72f99da76cd720b0a07868fc5dbf28b856d85Jabiertxof }
c2e7008ce6d44e568eb899040b80336e3465882eJabiertxof double displace_x_parsed = displace_x * global_randomize * factor;
c2e7008ce6d44e568eb899040b80336e3465882eJabiertxof double displace_y_parsed = displace_y * global_randomize * factor;
c2e7008ce6d44e568eb899040b80336e3465882eJabiertxof Geom::Point output = Geom::Point(sign(displace_x_parsed), sign(displace_y_parsed));
9d766cc272a22da6d0de4ebf6896da731b6c45c0jabiertxof if( fixed_displacement ){
9d766cc272a22da6d0de4ebf6896da731b6c45c0jabiertxof Geom::Ray ray(Geom::Point(0,0),output);
9d766cc272a22da6d0de4ebf6896da731b6c45c0jabiertxof output = Geom::Point::polar(ray.angle(), max_lenght);
9d766cc272a22da6d0de4ebf6896da731b6c45c0jabiertxof }
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof return output;
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof}
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxofvoid LPERoughen::doEffect(SPCurve *curve)
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof{
8fbc43f88a5488f54a1b99fcc08e340c7c1edf32jabiertxof Geom::PathVector const original_pathv = pathv_to_linear_and_cubic_beziers(curve->get_pathvector());
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof curve->reset();
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof for (Geom::PathVector::const_iterator path_it = original_pathv.begin();
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof path_it != original_pathv.end(); ++path_it) {
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof if (path_it->empty())
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof continue;
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof Geom::Path::const_iterator curve_it1 = path_it->begin();
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof Geom::Path::const_iterator curve_it2 = ++(path_it->begin());
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof Geom::Path::const_iterator curve_endit = path_it->end_default();
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof SPCurve *nCurve = new SPCurve();
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof Geom::Point prev(0, 0);
a7e81150b867e54cf50d331e30bb88f5676248c6Jabiertxof Geom::Point last_move(0, 0);
9d766cc272a22da6d0de4ebf6896da731b6c45c0jabiertxof nCurve->moveto(curve_it1->initialPoint());
90536c2550e30d32a103d11bff4bb61ad00812aejabiertxof if (path_it->closed()) {
90536c2550e30d32a103d11bff4bb61ad00812aejabiertxof const Geom::Curve &closingline = path_it->back_closed();
90536c2550e30d32a103d11bff4bb61ad00812aejabiertxof // the closing line segment is always of type
90536c2550e30d32a103d11bff4bb61ad00812aejabiertxof // Geom::LineSegment.
90536c2550e30d32a103d11bff4bb61ad00812aejabiertxof if (are_near(closingline.initialPoint(), closingline.finalPoint())) {
90536c2550e30d32a103d11bff4bb61ad00812aejabiertxof // closingline.isDegenerate() did not work, because it only checks for
90536c2550e30d32a103d11bff4bb61ad00812aejabiertxof // *exact* zero length, which goes wrong for relative coordinates and
90536c2550e30d32a103d11bff4bb61ad00812aejabiertxof // rounding errors...
90536c2550e30d32a103d11bff4bb61ad00812aejabiertxof // the closing line segment has zero-length. So stop before that one!
90536c2550e30d32a103d11bff4bb61ad00812aejabiertxof curve_endit = path_it->end_open();
90536c2550e30d32a103d11bff4bb61ad00812aejabiertxof }
90536c2550e30d32a103d11bff4bb61ad00812aejabiertxof }
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof while (curve_it1 != curve_endit) {
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof Geom::CubicBezier const *cubic = NULL;
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it1);
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof if (cubic) {
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof nCurve->curveto((*cubic)[1] + last_move, (*cubic)[2], curve_it1->finalPoint());
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof } else {
8fbc43f88a5488f54a1b99fcc08e340c7c1edf32jabiertxof nCurve->lineto(curve_it1->finalPoint());
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof }
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof last_move = Geom::Point(0, 0);
0b159142b0b5738b20883b411fe8233657cf8b4fJabiertxof double length = curve_it1->length(0.001);
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof std::size_t splits = 0;
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof if (method == DM_SEGMENTS) {
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof splits = segments;
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof } else {
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof splits = ceil(length / max_segment_size);
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof }
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof Geom::Curve const * original = nCurve->last_segment()->duplicate() ;
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof for (unsigned int t = 1; t <= splits; t++) {
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof if(t == splits && splits != 1){
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof continue;
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof }
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof SPCurve const * tmp;
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof if (splits == 1) {
a7e81150b867e54cf50d331e30bb88f5676248c6Jabiertxof tmp = jitter(nCurve->last_segment(), prev, last_move);
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof } else {
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof bool last = false;
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof if(t == splits-1){
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof last = true;
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof }
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof double time = Geom::nearest_time(original->pointAt((1. / (double)splits) * t), *nCurve->last_segment());
a7e81150b867e54cf50d331e30bb88f5676248c6Jabiertxof tmp = addNodesAndJitter(nCurve->last_segment(), prev, last_move, time, last);
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof }
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof if (nCurve->get_segment_count() > 1) {
9d766cc272a22da6d0de4ebf6896da731b6c45c0jabiertxof nCurve->backspace();
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof nCurve->append_continuous(tmp, 0.001);
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof } else {
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof nCurve = tmp->copy();
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof }
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof delete tmp;
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof }
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof ++curve_it1;
8fbc43f88a5488f54a1b99fcc08e340c7c1edf32jabiertxof ++curve_it2;
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof }
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof if (path_it->closed()) {
a7e81150b867e54cf50d331e30bb88f5676248c6Jabiertxof if(handles == HM_SMOOTH && curve_it1 == curve_endit){
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof SPCurve *out = new SPCurve();
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof nCurve = nCurve->create_reverse();
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof Geom::CubicBezier const *cubic_start = dynamic_cast<Geom::CubicBezier const *>(nCurve->first_segment());
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof Geom::CubicBezier const *cubic = dynamic_cast<Geom::CubicBezier const *>(nCurve->last_segment());
9d766cc272a22da6d0de4ebf6896da731b6c45c0jabiertxof Geom::Point oposite = nCurve->first_segment()->pointAt(1.0/3.0);
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof if(cubic_start){
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof Geom::Ray ray((*cubic_start)[1], (*cubic_start)[0]);
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof double dist = Geom::distance((*cubic_start)[1], (*cubic_start)[0]);
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof oposite = Geom::Point::polar(ray.angle(),dist) + (*cubic_start)[0];
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof }
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof if(cubic){
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof out->moveto((*cubic)[0]);
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof out->curveto((*cubic)[1], oposite, (*cubic)[3]);
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof } else {
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof out->moveto(nCurve->last_segment()->initialPoint());
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof out->curveto(nCurve->last_segment()->initialPoint(), oposite, nCurve->last_segment()->finalPoint());
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof }
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof nCurve->backspace();
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof nCurve->append_continuous(out, 0.001);
9d766cc272a22da6d0de4ebf6896da731b6c45c0jabiertxof nCurve = nCurve->create_reverse();
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof }
a7e81150b867e54cf50d331e30bb88f5676248c6Jabiertxof if(handles == HM_ALONG_NODES && curve_it1 == curve_endit){
a7e81150b867e54cf50d331e30bb88f5676248c6Jabiertxof SPCurve *out = new SPCurve();
a7e81150b867e54cf50d331e30bb88f5676248c6Jabiertxof nCurve = nCurve->create_reverse();
a7e81150b867e54cf50d331e30bb88f5676248c6Jabiertxof Geom::CubicBezier const *cubic = dynamic_cast<Geom::CubicBezier const *>(nCurve->last_segment());
a7e81150b867e54cf50d331e30bb88f5676248c6Jabiertxof if(cubic){
a7e81150b867e54cf50d331e30bb88f5676248c6Jabiertxof out->moveto((*cubic)[0]);
5b08636b45863e8af3f4c0d22a9235d565f2139ejabiertxof out->curveto((*cubic)[1], (*cubic)[2] - ((*cubic)[3] - nCurve->first_segment()->initialPoint()) , (*cubic)[3]);
a7e81150b867e54cf50d331e30bb88f5676248c6Jabiertxof nCurve->backspace();
a7e81150b867e54cf50d331e30bb88f5676248c6Jabiertxof nCurve->append_continuous(out, 0.001);
a7e81150b867e54cf50d331e30bb88f5676248c6Jabiertxof }
a7e81150b867e54cf50d331e30bb88f5676248c6Jabiertxof nCurve = nCurve->create_reverse();
a7e81150b867e54cf50d331e30bb88f5676248c6Jabiertxof }
9d766cc272a22da6d0de4ebf6896da731b6c45c0jabiertxof nCurve->move_endpoints(nCurve->last_segment()->finalPoint(), nCurve->last_segment()->finalPoint());
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof nCurve->closepath_current();
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof }
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof curve->append(nCurve, false);
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof nCurve->reset();
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof delete nCurve;
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof }
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof}
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof
a7e81150b867e54cf50d331e30bb88f5676248c6JabiertxofSPCurve const * LPERoughen::addNodesAndJitter(Geom::Curve const * A, Geom::Point &prev, Geom::Point &last_move, double t, bool last)
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof{
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof SPCurve *out = new SPCurve();
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof Geom::CubicBezier const *cubic = dynamic_cast<Geom::CubicBezier const *>(&*A);
9d766cc272a22da6d0de4ebf6896da731b6c45c0jabiertxof double max_lenght = Geom::distance(A->initialPoint(),A->pointAt(t)) / 3.0;
9d766cc272a22da6d0de4ebf6896da731b6c45c0jabiertxof Geom::Point point_a1(0, 0);
9d766cc272a22da6d0de4ebf6896da731b6c45c0jabiertxof Geom::Point point_a2(0, 0);
9d766cc272a22da6d0de4ebf6896da731b6c45c0jabiertxof Geom::Point point_a3(0, 0);
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof Geom::Point point_b1(0, 0);
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof Geom::Point point_b2(0, 0);
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof Geom::Point point_b3(0, 0);
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof if (shift_nodes) {
c2e7008ce6d44e568eb899040b80336e3465882eJabiertxof point_a3 = randomize(max_lenght, true);
9d766cc272a22da6d0de4ebf6896da731b6c45c0jabiertxof if(last){
c2e7008ce6d44e568eb899040b80336e3465882eJabiertxof point_b3 = randomize(max_lenght, true);
9d766cc272a22da6d0de4ebf6896da731b6c45c0jabiertxof }
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof }
a7e81150b867e54cf50d331e30bb88f5676248c6Jabiertxof if (handles == HM_RAND || handles == HM_SMOOTH) {
9d766cc272a22da6d0de4ebf6896da731b6c45c0jabiertxof point_a1 = randomize(max_lenght);
9d766cc272a22da6d0de4ebf6896da731b6c45c0jabiertxof point_a2 = randomize(max_lenght);
9d766cc272a22da6d0de4ebf6896da731b6c45c0jabiertxof point_b1 = randomize(max_lenght);
9d766cc272a22da6d0de4ebf6896da731b6c45c0jabiertxof if(last){
9d766cc272a22da6d0de4ebf6896da731b6c45c0jabiertxof point_b2 = randomize(max_lenght);
9d766cc272a22da6d0de4ebf6896da731b6c45c0jabiertxof }
9d766cc272a22da6d0de4ebf6896da731b6c45c0jabiertxof } else {
9d766cc272a22da6d0de4ebf6896da731b6c45c0jabiertxof point_a2 = point_a3;
9d766cc272a22da6d0de4ebf6896da731b6c45c0jabiertxof point_b1 = point_a3;
9d766cc272a22da6d0de4ebf6896da731b6c45c0jabiertxof if(last){
9d766cc272a22da6d0de4ebf6896da731b6c45c0jabiertxof point_b2 = point_b3;
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof }
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof }
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof if(handles == HM_SMOOTH){
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof if(cubic) {
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof std::pair<Geom::CubicBezier, Geom::CubicBezier> div = cubic->subdivide(t);
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof std::vector<Geom::Point> seg1 = div.first.controlPoints(),
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof seg2 = div.second.controlPoints();
7d52c19411e2bb66373fcf808bb2481165b31c26Jabiertxof Geom::Ray ray(seg1[3] + point_a3, seg2[1] + point_a3);
7d52c19411e2bb66373fcf808bb2481165b31c26Jabiertxof double lenght = max_lenght;
7d52c19411e2bb66373fcf808bb2481165b31c26Jabiertxof if(!fixed_displacement ){
7d52c19411e2bb66373fcf808bb2481165b31c26Jabiertxof lenght = Geom::distance(seg1[3] + point_a3, seg2[1] + point_a3);
7d52c19411e2bb66373fcf808bb2481165b31c26Jabiertxof }
7d52c19411e2bb66373fcf808bb2481165b31c26Jabiertxof point_b1 = seg1[3] + point_a3 + Geom::Point::polar(ray.angle() , lenght);
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof point_b2 = seg2[2];
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof point_b3 = seg2[3] + point_b3;
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof point_a3 = seg1[3] + point_a3;
7d52c19411e2bb66373fcf808bb2481165b31c26Jabiertxof ray.setPoints(prev,A->initialPoint());
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof point_a1 = A->initialPoint() + Geom::Point::polar(ray.angle(), max_lenght);
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof if(prev == Geom::Point(0,0)){
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof point_a1 = randomize(max_lenght);
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof }
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof if(last){
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof Geom::Path b2(point_b3);
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof b2.appendNew<Geom::LineSegment>(point_a3);
7d52c19411e2bb66373fcf808bb2481165b31c26Jabiertxof lenght = max_lenght;
7d52c19411e2bb66373fcf808bb2481165b31c26Jabiertxof ray.setPoints(point_b3, point_b2);
7d52c19411e2bb66373fcf808bb2481165b31c26Jabiertxof if(!fixed_displacement ){
7d52c19411e2bb66373fcf808bb2481165b31c26Jabiertxof lenght = Geom::distance(b2.pointAt(1.0/3.0), point_b3);
7d52c19411e2bb66373fcf808bb2481165b31c26Jabiertxof }
7d52c19411e2bb66373fcf808bb2481165b31c26Jabiertxof point_b2 = point_b3 + Geom::Point::polar(ray.angle() , lenght);
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof }
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof ray.setPoints(point_b1, point_a3);
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof point_a2 = point_a3 + Geom::Point::polar(ray.angle(), max_lenght);
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof if(last){
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof prev = point_b2;
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof } else {
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof prev = point_a2;
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof }
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof out->moveto(seg1[0]);
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof out->curveto(point_a1,point_a2,point_a3);
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof out->curveto(point_b1, point_b2, point_b3);
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof } else {
7d52c19411e2bb66373fcf808bb2481165b31c26Jabiertxof Geom::Ray ray(A->pointAt(t) + point_a3, A->pointAt(t + (t / 3)));
7d52c19411e2bb66373fcf808bb2481165b31c26Jabiertxof double lenght = max_lenght;
7d52c19411e2bb66373fcf808bb2481165b31c26Jabiertxof if(!fixed_displacement ){
7d52c19411e2bb66373fcf808bb2481165b31c26Jabiertxof lenght = Geom::distance(A->pointAt(t) + point_a3, A->pointAt(t + (t / 3)));
7d52c19411e2bb66373fcf808bb2481165b31c26Jabiertxof }
7d52c19411e2bb66373fcf808bb2481165b31c26Jabiertxof point_b1 = A->pointAt(t) + point_a3 + Geom::Point::polar(ray.angle() , lenght);
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof point_b2 = A->pointAt(t +((t / 3) * 2));
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof point_b3 = A->finalPoint() + point_b3;
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof point_a3 = A->pointAt(t) + point_a3;
7d52c19411e2bb66373fcf808bb2481165b31c26Jabiertxof ray.setPoints(prev,A->initialPoint());
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof point_a1 = A->initialPoint() + Geom::Point::polar(ray.angle(), max_lenght);
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof if(prev == Geom::Point(0,0)){
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof point_a1 = randomize(max_lenght);
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof }
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof if(last){
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof Geom::Path b2(point_b3);
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof b2.appendNew<Geom::LineSegment>(point_a3);
7d52c19411e2bb66373fcf808bb2481165b31c26Jabiertxof lenght = max_lenght;
7d52c19411e2bb66373fcf808bb2481165b31c26Jabiertxof ray.setPoints(point_b3, point_b2);
7d52c19411e2bb66373fcf808bb2481165b31c26Jabiertxof if(!fixed_displacement ){
7d52c19411e2bb66373fcf808bb2481165b31c26Jabiertxof lenght = Geom::distance(b2.pointAt(1.0/3.0), point_b3);
7d52c19411e2bb66373fcf808bb2481165b31c26Jabiertxof }
7d52c19411e2bb66373fcf808bb2481165b31c26Jabiertxof point_b2 = point_b3 + Geom::Point::polar(ray.angle() , lenght);
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof }
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof ray.setPoints(point_b1, point_a3);
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof point_a2 = point_a3 + Geom::Point::polar(ray.angle(), max_lenght);
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof if(last){
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof prev = point_b2;
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof } else {
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof prev = point_a2;
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof }
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof out->moveto(A->initialPoint());
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof out->curveto(point_a1,point_a2,point_a3);
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof out->curveto(point_b1, point_b2, point_b3);
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof }
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof } else if(handles == HM_RETRACT){
8fbc43f88a5488f54a1b99fcc08e340c7c1edf32jabiertxof out->moveto(A->initialPoint());
8fbc43f88a5488f54a1b99fcc08e340c7c1edf32jabiertxof out->lineto(A->pointAt(t) + point_a3);
8fbc43f88a5488f54a1b99fcc08e340c7c1edf32jabiertxof if(cubic && !last){
8fbc43f88a5488f54a1b99fcc08e340c7c1edf32jabiertxof std::pair<Geom::CubicBezier, Geom::CubicBezier> div = cubic->subdivide(t);
8fbc43f88a5488f54a1b99fcc08e340c7c1edf32jabiertxof std::vector<Geom::Point> seg2 = div.second.controlPoints();
8fbc43f88a5488f54a1b99fcc08e340c7c1edf32jabiertxof out->curveto(seg2[1], seg2[2], seg2[3]);
8fbc43f88a5488f54a1b99fcc08e340c7c1edf32jabiertxof } else {
8fbc43f88a5488f54a1b99fcc08e340c7c1edf32jabiertxof out->lineto(A->finalPoint() + point_b3);
8fbc43f88a5488f54a1b99fcc08e340c7c1edf32jabiertxof }
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof } else if(handles == HM_ALONG_NODES){
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof if (cubic) {
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof std::pair<Geom::CubicBezier, Geom::CubicBezier> div = cubic->subdivide(t);
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof std::vector<Geom::Point> seg1 = div.first.controlPoints(),
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof seg2 = div.second.controlPoints();
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof out->moveto(seg1[0]);
a7e81150b867e54cf50d331e30bb88f5676248c6Jabiertxof out->curveto(seg1[1] + last_move, seg1[2] + point_a3, seg1[3] + point_a3);
a7e81150b867e54cf50d331e30bb88f5676248c6Jabiertxof last_move = point_a3;
a7e81150b867e54cf50d331e30bb88f5676248c6Jabiertxof if(last){
a7e81150b867e54cf50d331e30bb88f5676248c6Jabiertxof last_move = point_b3;
a7e81150b867e54cf50d331e30bb88f5676248c6Jabiertxof }
a7e81150b867e54cf50d331e30bb88f5676248c6Jabiertxof out->curveto(seg2[1] + point_a3, seg2[2] + point_b3, seg2[3] + point_b3);
a7e81150b867e54cf50d331e30bb88f5676248c6Jabiertxof } else {
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof out->moveto(A->initialPoint());
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof out->lineto(A->pointAt(t) + point_a3);
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof out->lineto(A->finalPoint() + point_b3);
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof }
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof } else if(handles == HM_RAND) {
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof if (cubic) {
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof std::pair<Geom::CubicBezier, Geom::CubicBezier> div = cubic->subdivide(t);
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof std::vector<Geom::Point> seg1 = div.first.controlPoints(),
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof seg2 = div.second.controlPoints();
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof out->moveto(seg1[0]);
a7e81150b867e54cf50d331e30bb88f5676248c6Jabiertxof out->curveto(seg1[1] + point_a1, seg1[2] + point_a2 + point_a3, seg1[3] + point_a3);
a7e81150b867e54cf50d331e30bb88f5676248c6Jabiertxof out->curveto(seg2[1] + point_a3 + point_b1, seg2[2] + point_b2 + point_b3, seg2[3] + point_b3);
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof } else {
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof out->moveto(A->initialPoint());
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof out->lineto(A->pointAt(t) + point_a3);
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof out->lineto(A->finalPoint() + point_b3);
a7e81150b867e54cf50d331e30bb88f5676248c6Jabiertxof }
dbe3e7dacd7d4490ef69cc21314dc718b4706ae5jabiertxof }
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof return out;
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof}
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof
a7e81150b867e54cf50d331e30bb88f5676248c6JabiertxofSPCurve *LPERoughen::jitter(Geom::Curve const * A, Geom::Point &prev, Geom::Point &last_move)
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof{
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof SPCurve *out = new SPCurve();
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof Geom::CubicBezier const *cubic = dynamic_cast<Geom::CubicBezier const *>(&*A);
9d766cc272a22da6d0de4ebf6896da731b6c45c0jabiertxof double max_lenght = Geom::distance(A->initialPoint(),A->finalPoint()) / 3.0;
9d766cc272a22da6d0de4ebf6896da731b6c45c0jabiertxof Geom::Point point_a1(0, 0);
9d766cc272a22da6d0de4ebf6896da731b6c45c0jabiertxof Geom::Point point_a2(0, 0);
9d766cc272a22da6d0de4ebf6896da731b6c45c0jabiertxof Geom::Point point_a3(0, 0);
163aa8601274792f2afe8e24a061fed96b7a6599Jabiertxof if (shift_nodes) {
7d52c19411e2bb66373fcf808bb2481165b31c26Jabiertxof point_a3 = randomize(max_lenght, true);
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof }
a7e81150b867e54cf50d331e30bb88f5676248c6Jabiertxof if (handles == HM_RAND || handles == HM_SMOOTH) {
9d766cc272a22da6d0de4ebf6896da731b6c45c0jabiertxof point_a1 = randomize(max_lenght);
9d766cc272a22da6d0de4ebf6896da731b6c45c0jabiertxof point_a2 = randomize(max_lenght);
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof }
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof if(handles == HM_SMOOTH) {
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof if (cubic) {
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof Geom::Ray ray(prev,A->initialPoint());
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof point_a1 = Geom::Point::polar(ray.angle(), max_lenght);
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof if(prev == Geom::Point(0,0)){
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof point_a1 = A->pointAt(1.0/3.0) + randomize(max_lenght);
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof }
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof ray.setPoints((*cubic)[3] + point_a3, (*cubic)[2] + point_a3);
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof point_a2 = randomize(max_lenght, ray.angle());
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof prev = (*cubic)[2] + point_a2;
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof out->moveto((*cubic)[0]);
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof out->curveto((*cubic)[0] + point_a1, (*cubic)[2] + point_a2 + point_a3, (*cubic)[3] + point_a3);
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof } else {
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof Geom::Ray ray(prev,A->initialPoint());
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof point_a1 = Geom::Point::polar(ray.angle(), max_lenght);
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof if(prev==Geom::Point(0,0)){
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof point_a1 = A->pointAt(1.0/3.0) + randomize(max_lenght);
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof }
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof ray.setPoints(A->finalPoint() + point_a3, A->pointAt((1.0/3.0) * 2) + point_a3);
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof point_a2 = randomize(max_lenght, ray.angle());
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof prev = A->pointAt((1.0/3.0) * 2) + point_a2 + point_a3;
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof out->moveto(A->initialPoint());
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof out->curveto(A->initialPoint() + point_a1, A->pointAt((1.0/3.0) * 2) + point_a2 + point_a3, A->finalPoint() + point_a3);
9d766cc272a22da6d0de4ebf6896da731b6c45c0jabiertxof }
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof } else if(handles == HM_RETRACT){
9d766cc272a22da6d0de4ebf6896da731b6c45c0jabiertxof out->moveto(A->initialPoint());
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof out->lineto(A->finalPoint() + point_a3);
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof } else if (handles == HM_ALONG_NODES) {
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof if(cubic){
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof out->moveto((*cubic)[0]);
a7e81150b867e54cf50d331e30bb88f5676248c6Jabiertxof out->curveto((*cubic)[1] + last_move, (*cubic)[2] + point_a3, (*cubic)[3] + point_a3);
a7e81150b867e54cf50d331e30bb88f5676248c6Jabiertxof last_move = point_a3;
a7e81150b867e54cf50d331e30bb88f5676248c6Jabiertxof } else {
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof out->moveto(A->initialPoint());
cd37beb25860ded72c3a03f3f32dbb27047ce644Jabiertxof out->lineto(A->finalPoint() + point_a3);
a7e81150b867e54cf50d331e30bb88f5676248c6Jabiertxof }
a7e81150b867e54cf50d331e30bb88f5676248c6Jabiertxof } else if (handles == HM_RAND) {
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof out->moveto(A->initialPoint());
8fbc43f88a5488f54a1b99fcc08e340c7c1edf32jabiertxof out->curveto(A->pointAt(0.3333) + point_a1, A->pointAt(0.6666) + point_a2 + point_a3,
9d766cc272a22da6d0de4ebf6896da731b6c45c0jabiertxof A->finalPoint() + point_a3);
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof }
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof return out;
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof}
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof
163aa8601274792f2afe8e24a061fed96b7a6599JabiertxofGeom::Point LPERoughen::tPoint(Geom::Point A, Geom::Point B, double t)
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof{
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof using Geom::X;
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof using Geom::Y;
ccbee7d45f91658e83a602a9a28ee26162a261f9Jabiertxof return Geom::Point(A[X] + t * (B[X] - A[X]), A[Y] + t * (B[Y] - A[Y]));
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof}
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof}; //namespace LivePathEffect
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof}; /* namespace Inkscape */
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof/*
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof Local Variables:
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof mode:c++
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof c-file-style:"stroustrup"
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof indent-tabs-mode:nil
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof fill-column:99
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof End:
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof*/
60db347ea19e568bd09c35a0248a9f78d7931ca0Jabiertxof// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :