int main(int argc, char **argv) { if (argc > 1) { Geom::PathVector originald = Geom::parse_svg_path(&*argv[1]); Geom::Piecewise<Geom::D2<Geom::SBasis> > originaldpwd2; for (unsigned int i=0; i < originald.size(); i++) { originaldpwd2.concat( originald[i].toPwSb() ); } Geom::PathVector pattern = Geom::parse_svg_path(&*argv[2]); Geom::Piecewise<Geom::D2<Geom::SBasis> > patternpwd2; for (unsigned int i=0; i < pattern.size(); i++) { patternpwd2.concat( pattern[i].toPwSb() ); } doEffect_pwd2(originaldpwd2, patternpwd2); } return 0; };
int main(int argc, char **argv) { if (argc > 1) { SVGPathTestPrinter sink; Geom::parse_svg_path(&*argv[1], sink); std::cout << "Try real pathsink:" << std::endl; Geom::PathVector testpath = Geom::parse_svg_path(&*argv[1]); std::cout << "Geom::PathVector length: " << testpath.size() << std::endl; if ( !testpath.empty() ) std::cout << "Path curves: " << testpath.front().size() << std::endl; std::cout << "success!" << std::endl; } return 0; };
/* * interpolate path_in[0] to path_in[1] */ Geom::PathVector LPEInterpolate::doEffect_path (Geom::PathVector const & path_in) { if ( (path_in.size() < 2) || (number_of_steps < 2)) { return path_in; } // Don't allow empty path parameter: if ( trajectory_path.get_pathvector().empty() ) { return path_in; } Geom::PathVector path_out; Geom::Piecewise<Geom::D2<Geom::SBasis> > pwd2_A = path_in[0].toPwSb(); Geom::Piecewise<Geom::D2<Geom::SBasis> > pwd2_B = path_in[1].toPwSb(); // Transform both paths to (0,0) midpoint, so they can easily be positioned along interpolate_path if (Geom::OptRect bounds = Geom::bounds_exact(pwd2_A)) { pwd2_A -= bounds->midpoint(); } if (Geom::OptRect bounds = Geom::bounds_exact(pwd2_B)) { pwd2_B -= bounds->midpoint(); } // Make sure both paths have the same number of segments and cuts at the same locations pwd2_B.setDomain(pwd2_A.domain()); Geom::Piecewise<Geom::D2<Geom::SBasis> > pA = Geom::partition(pwd2_A, pwd2_B.cuts); Geom::Piecewise<Geom::D2<Geom::SBasis> > pB = Geom::partition(pwd2_B, pwd2_A.cuts); Geom::Piecewise<Geom::D2<Geom::SBasis> > trajectory = trajectory_path.get_pathvector()[0].toPwSb(); if (equidistant_spacing) trajectory = Geom::arc_length_parametrization(trajectory); Geom::Interval trajectory_domain = trajectory.domain(); for (int i = 0; i < number_of_steps; ++i) { double fraction = i / (number_of_steps-1); Geom::Piecewise<Geom::D2<Geom::SBasis> > pResult = pA*(1-fraction) + pB*fraction; pResult += trajectory.valueAt(trajectory_domain.min() + fraction*trajectory_domain.extent()); Geom::PathVector pathv = Geom::path_from_piecewise(pResult, LPE_CONVERSION_TOLERANCE); path_out.push_back( pathv[0] ); } return path_out; }
void KnotHolderEntityAttachPt::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state) { using namespace Geom; LPETangentToCurve* lpe = dynamic_cast<LPETangentToCurve *>(_effect); Geom::Point const s = snap_knot_position(p, state); // FIXME: There must be a better way of converting the path's SPCurve* to pwd2. SPCurve *curve = SP_PATH(item)->get_curve_for_edit(); Geom::PathVector pathv = curve->get_pathvector(); Piecewise<D2<SBasis> > pwd2; for (unsigned int i=0; i < pathv.size(); i++) { pwd2.concat(pathv[i].toPwSb()); } double t0 = nearest_point(s, pwd2); lpe->t_attach.param_set_value(t0); // FIXME: this should not directly ask for updating the item. It should write to SVG, which triggers updating. sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), false, true); }
Geom::PathVector LPEMirrorSymmetry::doEffect_path (Geom::PathVector const & path_in) { // Don't allow empty path parameter: if ( reflection_line.get_pathvector().empty() ) { return path_in; } Geom::PathVector path_out; if (!discard_orig_path) { path_out = path_in; } Geom::PathVector mline(reflection_line.get_pathvector()); Geom::Point A(mline.front().initialPoint()); Geom::Point B(mline.back().finalPoint()); Geom::Affine m1(1.0, 0.0, 0.0, 1.0, A[0], A[1]); double hyp = Geom::distance(A, B); double c = (B[0] - A[0]) / hyp; // cos(alpha) double s = (B[1] - A[1]) / hyp; // sin(alpha) Geom::Affine m2(c, -s, s, c, 0.0, 0.0); Geom::Affine sca(1.0, 0.0, 0.0, -1.0, 0.0, 0.0); Geom::Affine m = m1.inverse() * m2; m = m * sca; m = m * m2.inverse(); m = m * m1; for (int i = 0; i < static_cast<int>(path_in.size()); ++i) { path_out.push_back(path_in[i] * m); } return path_out; }
static void spdc_check_for_and_apply_waiting_LPE(FreehandBase *dc, SPItem *item, SPCurve *curve) { using namespace Inkscape::LivePathEffect; Inkscape::Preferences *prefs = Inkscape::Preferences::get(); if (item && SP_IS_LPE_ITEM(item)) { bool simplify = prefs->getInt(tool_name(dc) + "/simplify", 0); if(simplify){ double tol = prefs->getDoubleLimited("/tools/freehand/pencil/tolerance", 10.0, 1.0, 100.0); tol = tol/(100.0*(102.0-tol)); std::ostringstream ss; ss << tol; spdc_apply_simplify(ss.str(), dc, item); sp_lpe_item_update_patheffect(SP_LPE_ITEM(item), false, false); } if (prefs->getInt(tool_name(dc) + "/freehand-mode", 0) == 1) { Effect::createAndApply(SPIRO, dc->desktop->doc(), item); } if (prefs->getInt(tool_name(dc) + "/freehand-mode", 0) == 2) { Effect::createAndApply(BSPLINE, dc->desktop->doc(), item); } SPShape *sp_shape = dynamic_cast<SPShape *>(item); if (sp_shape) { curve = sp_shape->getCurve(); } //Store the clipboard path to apply in the future without the use of clipboard static Geom::PathVector previous_shape_pathv; shapeType shape = (shapeType)prefs->getInt(tool_name(dc) + "/shape", 0); bool shape_applied = false; SPCSSAttr *css_item = sp_css_attr_from_object(item, SP_STYLE_FLAG_ALWAYS); const char *cstroke = sp_repr_css_property(css_item, "stroke", "none"); static SPItem *bend_item; #define SHAPE_LENGTH 10 #define SHAPE_HEIGHT 10 if(shape == LAST_APPLIED){ shape = previous_shape_type; if(shape == CLIPBOARD || shape == BEND_CLIPBOARD){ shape = LAST_APPLIED; } } switch (shape) { case NONE: // don't apply any shape break; case TRIANGLE_IN: { // "triangle in" std::vector<Geom::Point> points(1); points[0] = Geom::Point(0., SHAPE_HEIGHT/2); spdc_apply_powerstroke_shape(points, dc, item); shape_applied = true; break; } case TRIANGLE_OUT: { // "triangle out" guint curve_length = curve->get_segment_count(); std::vector<Geom::Point> points(1); points[0] = Geom::Point((double)curve_length, SHAPE_HEIGHT/2); spdc_apply_powerstroke_shape(points, dc, item); shape_applied = true; break; } case ELLIPSE: { // "ellipse" SPCurve *c = new SPCurve(); const double C1 = 0.552; c->moveto(0, SHAPE_HEIGHT/2); c->curveto(0, (1 - C1) * SHAPE_HEIGHT/2, (1 - C1) * SHAPE_LENGTH/2, 0, SHAPE_LENGTH/2, 0); c->curveto((1 + C1) * SHAPE_LENGTH/2, 0, SHAPE_LENGTH, (1 - C1) * SHAPE_HEIGHT/2, SHAPE_LENGTH, SHAPE_HEIGHT/2); c->curveto(SHAPE_LENGTH, (1 + C1) * SHAPE_HEIGHT/2, (1 + C1) * SHAPE_LENGTH/2, SHAPE_HEIGHT, SHAPE_LENGTH/2, SHAPE_HEIGHT); c->curveto((1 - C1) * SHAPE_LENGTH/2, SHAPE_HEIGHT, 0, (1 + C1) * SHAPE_HEIGHT/2, 0, SHAPE_HEIGHT/2); c->closepath(); spdc_paste_curve_as_freehand_shape(c->get_pathvector(), dc, item); c->unref(); shape_applied = true; break; } case CLIPBOARD: { // take shape from clipboard; Inkscape::UI::ClipboardManager *cm = Inkscape::UI::ClipboardManager::get(); if(cm->paste(SP_ACTIVE_DESKTOP,true) == true){ SPItem * pasted_clipboard = dc->selection->singleItem(); if(pasted_clipboard){ Inkscape::XML::Node *pasted_clipboard_root = pasted_clipboard->getRepr(); Inkscape::XML::Node *path = sp_repr_lookup_name(pasted_clipboard_root, "svg:path", -1); // unlimited search depth if ( path != NULL ) { gchar const *svgd = path->attribute("d"); dc->selection->remove(SP_OBJECT(pasted_clipboard)); previous_shape_pathv = sp_svg_read_pathv(svgd); previous_shape_pathv *= pasted_clipboard->transform; spdc_paste_curve_as_freehand_shape(previous_shape_pathv, dc, item); shape = CLIPBOARD; shape_applied = true; pasted_clipboard->deleteObject(); } else { shape = NONE; } } else { shape = NONE; } } else { shape = NONE; } break; } case BEND_CLIPBOARD: { Inkscape::UI::ClipboardManager *cm = Inkscape::UI::ClipboardManager::get(); if(cm->paste(SP_ACTIVE_DESKTOP,true) == true){ gchar const *svgd = item->getRepr()->attribute("d"); bend_item = dc->selection->singleItem(); if(bend_item){ bend_item->moveTo(item,false); bend_item->transform.setTranslation(Geom::Point()); spdc_apply_bend_shape(svgd, dc, bend_item); dc->selection->add(SP_OBJECT(bend_item)); shape = BEND_CLIPBOARD; } else { shape = NONE; } } else { shape = NONE; } break; } case LAST_APPLIED: { if(previous_shape_type == CLIPBOARD){ if(previous_shape_pathv.size() != 0){ spdc_paste_curve_as_freehand_shape(previous_shape_pathv, dc, item); shape_applied = true; shape = CLIPBOARD; } else{ shape = NONE; } } else { if(bend_item != NULL && bend_item->getRepr() != NULL){ gchar const *svgd = item->getRepr()->attribute("d"); dc->selection->add(SP_OBJECT(bend_item)); sp_selection_duplicate(dc->desktop); dc->selection->remove(SP_OBJECT(bend_item)); bend_item = dc->selection->singleItem(); if(bend_item){ bend_item->moveTo(item,false); Geom::Coord expansion_X = bend_item->transform.expansionX(); Geom::Coord expansion_Y = bend_item->transform.expansionY(); bend_item->transform = Geom::Affine(1,0,0,1,0,0); bend_item->transform.setExpansionX(expansion_X); bend_item->transform.setExpansionY(expansion_Y); spdc_apply_bend_shape(svgd, dc, bend_item); dc->selection->add(SP_OBJECT(bend_item)); shape = BEND_CLIPBOARD; } else { shape = NONE; } } else { shape = NONE; } } break; } default: break; } previous_shape_type = shape; if (shape_applied) { // apply original stroke color as fill and unset stroke; then return SPCSSAttr *css = sp_repr_css_attr_new(); if (!strcmp(cstroke, "none")){ sp_repr_css_set_property (css, "fill", "black"); } else { sp_repr_css_set_property (css, "fill", cstroke); } sp_repr_css_set_property (css, "stroke", "none"); sp_desktop_apply_css_recursive(item, css, true); sp_repr_css_attr_unref(css); return; } if (dc->waiting_LPE_type != INVALID_LPE) { Effect::createAndApply(dc->waiting_LPE_type, dc->desktop->doc(), item); dc->waiting_LPE_type = INVALID_LPE; if (SP_IS_LPETOOL_CONTEXT(dc)) { // since a geometric LPE was applied, we switch back to "inactive" mode lpetool_context_switch_mode(SP_LPETOOL_CONTEXT(dc), INVALID_LPE); } } if (SP_IS_PEN_CONTEXT(dc)) { SP_PEN_CONTEXT(dc)->setPolylineMode(); } } }