18#include <gtkmm/widget.h>
43#include <glibmm/i18n.h>
46namespace LivePathEffect {
51 {
RM_FUSE, N_(
"Fuse paths"),
"fuse_paths" }
59 lpesatellites(_(
"lpesatellites"), _(
"Items satellites"),
"lpesatellites", &wr, this, false),
61 origin(_(
"Origin"), _(
"Adjust origin of the rotation"),
"origin", &wr, this, _(
"Adjust origin of the rotation")),
62 starting_point(_(
"Start point"), _(
"Starting point to define start angle"),
"starting_point", &wr, this, _(
"Adjust starting point to define start angle")),
63 starting_angle(_(
"Starting angle"), _(
"Angle of the first copy"),
"starting_angle", &wr, this, 0.0),
64 rotation_angle(_(
"Rotation angle"), _(
"Angle between two successive copies"),
"rotation_angle", &wr, this, 60.0),
65 num_copies(_(
"Number of copies"), _(
"Number of copies of the original path"),
"num_copies", &wr, this, 6),
66 gap(_(
"Gap"), _(
"Gap space between copies, use small negative gaps to fix some joins"),
"gap", &wr, this, -0.01),
67 copies_to_360(_(
"Distribute evenly"), _(
"Angle between copies is 360°/number of copies (ignores rotation angle setting)"),
"copies_to_360", &wr, this, true),
68 mirror_copies(_(
"Mirror copies"), _(
"Mirror between copies"),
"mirror_copies", &wr, this, false),
69 split_items(_(
"Split elements"), _(
"Split elements, so each can have its own style"),
"split_items", &wr, this, false),
70 link_styles(_(
"Link styles"), _(
"Link styles on split mode"),
"link_styles", &wr, this, false),
71 dist_angle_handle(100.0)
76 if (this->
getRepr()->attribute(
"fuse_paths") && strcmp(this->
getRepr()->attribute(
"fuse_paths"),
"true") == 0){
94 gap.
param_set_range(std::numeric_limits<double>::lowest(), std::numeric_limits<double>::max());
117 if (version <
"1.2") {
123 Glib::ustring
id = Glib::ustring(
"rotated-");
124 id += std::to_string(i);
156 if (lpereference && lpereference->isAttached() && lpereference.get()->getObject() !=
nullptr) {
171 if (lpereference && lpereference->isAttached()) {
172 auto copies = cast<SPItem>(lpereference->getObject());
175 copies->setHidden(
true);
176 }
else if (copies->isHidden()) {
177 copies->setHidden(
false);
185 bool forcewrite = write;
208 forcewrite = forcewrite || write;
212 if (forcewrite || !connected) {
233 for (
auto iter :
orig->style->properties()) {
235 auto key = iter->id();
237 const gchar *attr =
orig->getAttribute(iter->name().c_str());
253 if (is<SPGroup>(
orig) && is<SPGroup>(dest) && cast_unsafe<SPGroup>(
orig)->getItemCount() == cast_unsafe<SPGroup>(dest)->getItemCount()) {
257 std::vector< SPObject * > childs =
orig->childList(
true);
259 for (
auto &
child : childs) {
265 }
else if( is<SPGroup>(
orig) && is<SPGroup>(dest) && cast<SPGroup>(
orig)->getItemCount() != cast<SPGroup>(dest)->getItemCount()) {
270 if ( is<SPText>(
orig) && is<SPText>(dest) && cast<SPText>(
orig)->children.size() == cast<SPText>(dest)->children.size()) {
275 for (
auto &
child : cast<SPText>(
orig)->children) {
282 auto shape = cast<SPShape>(
orig);
283 auto path = cast<SPPath>(dest);
288 if (shape && !path) {
295 dest->
updateRepr(xml_doc, dest_node, SP_OBJECT_WRITE_ALL);
296 path = cast<SPPath>(dest);
298 path->setAttribute(
"d", str);
300 path->removeAttribute(
"d");
317 auto group = cast<SPGroup>(elemref);
325 std::vector<SPItem*>
const item_list = group->item_list();
327 for (
auto sub_item : item_list) {
331 previous = resultnode;
362 bool creation =
false;
397 auto const vbox = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 2);
400 std::vector<Parameter *>::iterator it =
param_vector.begin();
402 if ((*it)->widget_is_visible) {
410 widg->set_tooltip_markup(*tip);
412 widg->set_tooltip_text(
"");
413 widg->set_has_tooltip(
false);
428 using namespace Geom;
443 using namespace Geom;
483 if (!near_start_point && !
is_load) {
488 if (GDK_SHIFT_MASK) {
502 if (!near_start_point || !near_origin ||
split_items) {
514 double time_start = 0.0;
518 std::vector<double> crossed;
520 crossed.push_back(
c.ta);
522 std::sort(crossed.begin(), crossed.end());
523 for (
double time_end : crossed) {
524 if (time_start == time_end || time_end - time_start <
Geom::EPSILON) {
528 if (!portion_original.
empty()) {
537 portion_original.
clear();
538 time_start = time_end;
545 if (cs.size() > 0 && position == 1) {
547 if(!portion_original.
empty()){
551 if (tmp_path.
size() > 0 && tmp_path[0].
size() > 0 ) {
552 portion_original.
setFinal(tmp_path[0].initialPoint());
553 portion_original.
append(tmp_path[0]);
554 tmp_path[0] = portion_original;
559 portion_original.
clear();
562 if (cs.size()==0 && position == 1) {
611 for (
const auto & path_it : path_out) {
612 if (path_it.empty()) {
618 if (path_it.closed()) {
619 const Geom::Curve &closingline = path_it.back_closed();
627 curve_endit = path_it.end_open();
630 while (curve_it1 != curve_endit) {
631 if (!
Geom::are_near(curve_it1->initialPoint(), curve_it1->pointAt(0.5), 0.05)) {
633 res.
setFinal(curve_it1->initialPoint());
640 if (path_it.closed()) {
645 path_out = path_out_tmp;
684 if (!output_pv.
empty()) {
694 output_pv = path_in * t;
707 using namespace Geom;
715 hp_vec.push_back(pathv);
3x3 matrix representing an affine transformation.
Wrapper for angular values.
Abstract continuous curve on a plane defined on [0,1].
virtual Point initialPoint() const =0
Retrieve the start of the curve.
virtual Point finalPoint() const =0
Retrieve the end of the curve.
constexpr C middle() const
Axis-aligned rectangle that can be empty.
size_type size() const
Get the number of paths in the vector.
void push_back(Path const &path)
Append a path at the end.
bool empty() const
Check whether the vector contains any paths.
iterator insert(iterator pos, Path const &p)
Sequence of contiguous curves, aka spline.
Point finalPoint() const
Get the last point in the path.
void close(bool closed=true)
Set whether the path is closed.
bool empty() const
Check whether path is empty.
Point pointAt(Coord t) const
Get the point at the specified time value.
void clear()
Remove all curves from the path.
Path portion(Coord f, Coord t) const
void append(Curve *curve)
Add a new curve to the end of the path.
Point initialPoint() const
Get the first point in the path.
void setFinal(Point const &p)
void appendNew(Args &&... args)
Append a new curve to the path.
void start(Point const &p)
Two-dimensional point that doubles as a vector.
Rotation around the origin.
std::vector< StorageType > const & data() const
void param_setValue(bool newvalue)
std::vector< Parameter * > param_vector
void registerParameter(Parameter *param)
virtual void resetDefaults(SPItem const *item)
Sets all parameters to their default values and writes them to SVG.
bool apply_to_clippath_and_mask
virtual void processObjects(LPEAction lpe_action)
Inkscape::XML::Node * getRepr()
bool _provides_knotholder_entities
LivePathEffectObject * getLPEObj()
void original_bbox(SPLPEItem const *lpeitem, bool absolute=false, bool clip_mask=false, Geom::Affine base_transform=Geom::identity())
Geom::Interval boundingbox_Y
Geom::Interval boundingbox_X
void param_setValue(Glib::ustring newvalue, bool write=false)
Glib::ustring param_getSVGValue() const override
Geom::PathVector doEffect_path_post(Geom::PathVector const &path_in, FillRuleBool fillrule)
~LPECopyRotate() override
void cloneD(SPObject *orig, SPObject *dest)
void doOnApply(SPLPEItem const *lpeitem) override
Is performed a single time when the effect is freshly applied to a path.
EnumParam< RotateMethod > method
void toItem(Geom::Affine transform, size_t i, bool reset, bool &write)
Geom::Point previous_start_point
Gtk::Widget * newWidget() override
This creates a managed widget.
ScalarParam starting_angle
SatelliteArrayParam lpesatellites
void cloneStyle(SPObject *orig, SPObject *dest)
void doOnVisibilityToggled(SPLPEItem const *) override
LPECopyRotate(LivePathEffectObject *lpeobject)
void doAfterEffect(SPLPEItem const *lpeitem, SPCurve *curve) override
Is performed at the end of the LPE only one time per "lpeitem" in paths/shapes is called in middle of...
void resetDefaults(SPItem const *item) override
Sets all parameters to their default values and writes them to SVG.
void doBeforeEffect(SPLPEItem const *lpeitem) override
Is performed each time before the effect is updated.
void addCanvasIndicators(SPLPEItem const *lpeitem, std::vector< Geom::PathVector > &hp_vec) override
Add possible canvas indicators (i.e., helperpaths other than the original path) to hp_vec This functi...
Geom::PathVector doEffect_path(Geom::PathVector const &path_in) override
ScalarParam rotation_angle
double previous_num_copies
Inkscape::XML::Node * createPathBase(SPObject *elemref)
bool doOnOpen(SPLPEItem const *) override
Is performed on load document or revert If the item is fixed legacy return true.
Geom::Point previous_origin
PointParam starting_point
void doOnRemove(SPLPEItem const *) override
void split(Geom::PathVector &path_in, Geom::Path const ÷r)
Glib::ustring const * param_getTooltip() const
virtual void param_widget_is_visible(bool is_visible)
void connect_selection_changed()
virtual Gtk::Widget * param_newWidget()=0
void param_update_default(Geom::Point default_point)
void param_setValue(Geom::Point newpoint, bool write=false)
void link(SPObject *to, size_t pos=Glib::ustring::npos)
void param_set_digits(unsigned digits)
void param_set_range(double min, double max)
void param_set_increments(double step, double page)
void param_make_integer(bool yes=true)
void param_set_value(double val)
Simplified management of enumerations of svg items with UI labels.
Interface for refcounted XML nodes.
void setAttribute(Util::const_char_ptr key, Util::const_char_ptr value)
Change an attribute of this node.
virtual char const * attribute(char const *key) const =0
Get the string representation of a node's attribute.
void removeAttribute(Inkscape::Util::const_char_ptr key)
Remove an attribute of this node.
Wrapper around a Geom::PathVector object.
Typed SVG document implementation.
SPObject * getObjectById(std::string const &id) const
Inkscape::XML::Document * getReprDoc()
Our Inkscape::XML::Document.
Base class for visual SVG elements.
Geom::OptRect geometricBounds(Geom::Affine const &transform=Geom::identity()) const
Get item's geometric bounding box in this item's coordinate system.
SPObject is an abstract base class of all of the document nodes at the SVG document level.
void setAttributeOrRemoveIfEmpty(Inkscape::Util::const_char_ptr key, Inkscape::Util::const_char_ptr value)
void setAttribute(Inkscape::Util::const_char_ptr key, Inkscape::Util::const_char_ptr value)
char const * getId() const
Returns the objects current ID string.
SPStyle * style
Represents the style properties, whether from presentation attributes, the style attribute,...
Inkscape::XML::Node * updateRepr(unsigned int flags=SP_OBJECT_WRITE_EXT)
Updates the object's repr based on the object's state.
Inkscape::XML::Node * getRepr()
Returns the XML representation of tree.
char const * getAttribute(char const *name) const
SPObject * appendChildRepr(Inkscape::XML::Node *repr)
Append repr as child of this object.
SPObject * nthChild(unsigned index)
void addChild(Inkscape::XML::Node *child, Inkscape::XML::Node *prev=nullptr)
T< SPAttr::FILL_RULE, SPIEnum< SPWindRule > > fill_rule
fill-rule: 0 nonzero, 1 evenodd
constexpr Coord EPSILON
Default "acceptably small" value.
Geom::PathVector pathv_to_linear_and_cubic_beziers(Geom::PathVector const &pathv)
Specific geometry functions for Inkscape, not provided my lib2geom.
auto floor(Geom::Rect const &rect)
LPE <copy_rotate> implementation, see lpe-copy_rotate.cpp.
Various utility functions.
int sgn(const T &x)
Sign function - indicates the sign of a numeric type.
Angle distance(Angle const &a, Angle const &b)
double angle_between(Line const &l1, Line const &l2)
std::vector< Crossing > Crossings
Affine identity()
Create an identity matrix.
Crossings crossings(Curve const &a, Curve const &b)
Piecewise< SBasis > cross(Piecewise< D2< SBasis > > const &a, Piecewise< D2< SBasis > > const &b)
SBasis L2(D2< SBasis > const &a, unsigned k)
Point unit_vector(Point const &a)
bool are_near(Affine const &a1, Affine const &a2, Coord eps=EPSILON)
Point middle_point(LineSegment const &_segment)
static R & release(R &r)
Decrements the reference count of a anchored object.
static const Util::EnumDataConverter< RotateMethod > RMConverter(RotateMethodData, RM_END)
bool pointInTriangle(Geom::Point const &p, std::vector< Geom::Point > points)
static const Util::EnumData< RotateMethod > RotateMethodData[RM_END]
void pack_start(Gtk::Box &box, Gtk::Widget &child, bool const expand, bool const fill, unsigned const padding)
Adds child to box, packed with reference to the start of box.
Helper class to stream background task notifications as a series of messages.
static cairo_user_data_key_t key
Helpers for using Gtk::Boxes, encapsulating large changes between GTK3 & GTK4.
Geom::PathVector sp_pathvector_boolop(Geom::PathVector const &pathva, Geom::PathVector const &pathvb, BooleanOp bop, FillRule fra, FillRule frb)
Perform a boolean operation on two pathvectors.
Inkscape::SVG::PathString - builder for SVG path strings.
TODO: insert short description here.
Conversion between SBasis and Bezier basis polynomials.
SPCSSAttr - interface for CSS Attributes.
void sp_lpe_item_update_patheffect(SPLPEItem *lpeitem, bool wholetree, bool write, bool with_satellites)
Calls any registered handlers for the update_patheffect action.
Simplified management of enumerations of svg items with UI labels.
Interface for XML documents.
virtual Node * createElement(char const *name)=0
SPStyle - a style object for SPItem objects.
std::string sp_svg_transform_write(Geom::Affine const &transform)
static void sp_svg_write_path(Inkscape::SVG::PathString &str, Geom::Path const &p, bool normalize=false)