// SPDX-License-Identifier: GPL-2.0-or-later /** * @file * Inspired by Hofstadter's 'Goedel Escher Bach', chapter V. */ /* Authors: * Johan Engelen * * Copyright (C) 2007-2009 Authors * * Released under GNU GPL v2+, read the file 'COPYING' for more information. */ #include "live_effects/lpe-recursiveskeleton.h" #include <2geom/bezier-to-sbasis.h> // TODO due to internal breakage in glibmm headers, this must be last: #include namespace Inkscape { namespace LivePathEffect { LPERecursiveSkeleton::LPERecursiveSkeleton(LivePathEffectObject *lpeobject) : Effect(lpeobject), iterations(_("Iterations:"), _("recursivity"), "iterations", &wr, this, 2) { show_orig_path = true; concatenate_before_pwd2 = true; iterations.param_make_integer(true); iterations.param_set_range(1, 15); registerParameter(&iterations); } LPERecursiveSkeleton::~LPERecursiveSkeleton() = default; Geom::Piecewise > LPERecursiveSkeleton::doEffect_pwd2 (Geom::Piecewise > const & pwd2_in) { using namespace Geom; Piecewise > output; double prop_scale = 1.0; D2 > patternd2 = make_cuts_independent(pwd2_in); Piecewise x0 = false /*vertical_pattern.get_value()*/ ? Piecewise(patternd2[1]) : Piecewise(patternd2[0]); Piecewise y0 = false /*vertical_pattern.get_value()*/ ? Piecewise(patternd2[0]) : Piecewise(patternd2[1]); OptInterval pattBndsX = bounds_exact(x0); OptInterval pattBndsY = bounds_exact(y0); if ( !pattBndsX || !pattBndsY) { return pwd2_in; } x0 -= pattBndsX->min(); y0 -= pattBndsY->middle(); double noffset = 0;//normal_offset; double toffset = 0;//tang_offset; if (false /*prop_units.get_value()*/){ noffset *= pattBndsY->extent(); toffset *= pattBndsX->extent(); } y0+=noffset; output = pwd2_in; for (int i = 0; i < iterations; ++i) { std::vector > > skeleton = split_at_discontinuities(output); output.clear(); for (auto path_i : skeleton){ Piecewise x = x0; Piecewise y = y0; Piecewise > uskeleton = arc_length_parametrization(path_i,2,.1); uskeleton = remove_short_cuts(uskeleton,.01); Piecewise > n = rot90(derivative(uskeleton)); n = force_continuity(remove_short_cuts(n,.1)); double scaling = (uskeleton.domain().extent() - toffset)/pattBndsX->extent(); // TODO investigate why pattWidth is not being used: // - Doesn't appear to have been used anywhere in bzr history (Alex V: 2013-03-16) // double pattWidth = pattBndsX->extent() * scaling; if (scaling != 1.0) { x*=scaling; } if ( true /*scale_y_rel.get_value()*/ ) { y*=(scaling*prop_scale); } else { if (prop_scale != 1.0) y *= prop_scale; } x += toffset; output.concat(compose(uskeleton,x)+y*compose(n,x)); } } return output; } } //namespace LivePathEffect } /* namespace Inkscape */ /* Local Variables: mode:c++ c-file-style:"stroustrup" c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) indent-tabs-mode:nil fill-column:99 End: */ // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :