12#include <glibmm/i18n.h>
36namespace LivePathEffect {
115 if (mirror ==
true) {
119 for (
size_t i = 0; i <
_vector.size(); ++i) {
120 for (
size_t j = 0; j <
_vector[i].size(); ++j) {
122 (!
_vector[i][j].has_mirror && mirror ==
true) ||
127 (!pathv[i].closed() && j == 0) ||
133 bool overflow =
false;
134 double size_out =
_vector[i][j].arcDistance(*curve_in);
135 double length_out = curve_in->
length();
136 gint previous_index =
138 if (j == 0 && pathv[i].closed()) {
141 if ( previous_index < 0 ) {
147 pos =
_vector[i][j].time(size_out,
true, *curve_in);
148 if (length_out < size_out) {
152 pos =
_vector[i][j].time(*curve_in);
153 if (length_in < size_out) {
157 if (pos <= 0 || pos >= 1) {
174 hp_vec.push_back(
_hp);
181 if (prefs->
getBool(
"/options/transform/rectcorners",
true)) {
184 if (!j.is_time && j.amount > 0) {
199 for (
size_t i = 0; i <
_vector.size(); ++i) {
200 for (
size_t j = 0; j <
_vector[i].size(); ++j) {
201 if (!
_vector[i][j].has_mirror && mirror) {
205 if (mirror && i == 0 && j == 0) {
208 using namespace Geom;
213 tip = _(
"<b>Chamfer</b>: <b>Ctrl+Click</b> toggles type, "
214 "<b>Shift+Click</b> open dialog, "
215 "<b>Ctrl+Alt+Click</b> reset");
217 tip = _(
"<b>Inverse Chamfer</b>: <b>Ctrl+Click</b> toggles type, "
218 "<b>Shift+Click</b> open dialog, "
219 "<b>Ctrl+Alt+Click</b> reset");
221 tip = _(
"<b>Inverse Fillet</b>: <b>Ctrl+Click</b> toggles type, "
222 "<b>Shift+Click</b> open dialog, "
223 "<b>Ctrl+Alt+Click</b> reset");
225 tip = _(
"<b>Fillet</b>: <b>Ctrl+Click</b> toggles type, "
226 "<b>Shift+Click</b> open dialog, "
227 "<b>Ctrl+Alt+Click</b> reset");
246 for (
size_t i = 0; i < nodesatellites.size(); ++i) {
247 for (
size_t j = 0; j < nodesatellites[i].size(); ++j) {
251 _vector[i][j].setSelected(
true);
253 _vector[i][j].setSelected(
false);
277 bool is_mirror =
false;
279 if (
_index >= total_nodesatellites) {
284 size_t satelite_index = index_data.first;
285 size_t subsatelite_index = index_data.second;
287 if (!
valid_index(satelite_index, subsatelite_index)) {
292 if (nodesatellite.
hidden ||
293 (!pathv[satelite_index].closed() &&
294 (subsatelite_index == 0 ||
300 gint previous_index = subsatelite_index - 1;
301 if (subsatelite_index == 0 && pathv[satelite_index].closed()) {
304 if ( previous_index < 0 ) {
307 Geom::Curve const &curve_in = pathv[satelite_index][previous_index];
314 if ((normal_time == 0 && !is_mirror) ||
315 (mirror_time == 1 && is_mirror) ||
319 }
else if (distance_mirror < distance_normal) {
320 double time_start = 0;
322 time_start = nodesatellites[satelite_index][previous_index].time(curve_in);
323 if (time_start > mirror_time) {
324 mirror_time = time_start;
329 amount =
timeAtArcLength(amount, pathv[satelite_index][subsatelite_index]);
334 nodesatellite.
amount = amount;
336 nodesatellite.
setPosition(s, pathv[satelite_index][subsatelite_index]);
341 _pparam->
_vector[satelite_index][subsatelite_index] = nodesatellite;
375 bool is_mirror =
false;
377 if (
_index >= total_nodesatellites) {
382 size_t satelite_index = index_data.first;
383 size_t subsatelite_index = index_data.second;
384 if (!
valid_index(satelite_index, subsatelite_index)) {
389 if (nodesatellite.
hidden ||
390 (!pathv[satelite_index].closed() &&
391 (subsatelite_index == 0 || subsatelite_index ==
count_path_nodes(pathv[satelite_index]) -
398 gint previous_index = subsatelite_index - 1;
399 if (subsatelite_index == 0 && pathv[satelite_index].closed()) {
402 if (previous_index < 0 || subsatelite_index > pathv[satelite_index].size_open()) {
405 auto const &ssat_path = pathv[satelite_index][subsatelite_index];
406 auto const &prev_path = pathv[satelite_index][previous_index ];
407 Geom::Curve const &curve_in = pathv[satelite_index][previous_index];
414 double t = nodesatellite.
time(s,
true, curve_in);
421 double time_start = 0;
424 if (time_start > t) {
427 tmp_point = (curve_in).pointAt(t);
431 segment = segment.
portion(0,t);
432 segment *= itemtransform;
438 double angle = ray.
angle();
442 segment.
append(ssat_path);
444 segment *= itemtransform;
454 angle = ray2.
angle() + Geom::rad_from_deg(180);
455 contracted = ssat_path.pointAt(0.1);
462 angle -= Geom::rad_from_deg(180);
465 angle += Geom::rad_from_deg(180);
474 if (nodesatellite.
amount == 0) {
478 tmp_point = contracted;
501 bool is_mirror =
false;
503 if (
_index >= total_nodesatellites) {
508 size_t satelite_index = index_data.first;
509 size_t subsatelite_index = index_data.second;
510 if (!
valid_index(satelite_index, subsatelite_index)) {
514 if (!pathv[satelite_index].closed() &&
515 (subsatelite_index == 0 ||
521 if (state & GDK_CONTROL_MASK) {
522 if (state & GDK_ALT_MASK) {
526 using namespace Geom;
542 _pparam->
_vector[satelite_index][subsatelite_index].nodesatellite_type = type;
546 tip = _(
"<b>Chamfer</b>: <b>Ctrl+Click</b> toggles type, "
547 "<b>Shift+Click</b> open dialog, "
548 "<b>Ctrl+Alt+Click</b> resets");
550 tip = _(
"<b>Inverse Chamfer</b>: <b>Ctrl+Click</b> toggles type, "
551 "<b>Shift+Click</b> open dialog, "
552 "<b>Ctrl+Alt+Click</b> resets");
554 tip = _(
"<b>Inverse Fillet</b>: <b>Ctrl+Click</b> toggles type, "
555 "<b>Shift+Click</b> open dialog, "
556 "<b>Ctrl+Alt+Click</b> resets");
558 tip = _(
"<b>Fillet</b>: <b>Ctrl+Click</b> toggles type, "
559 "<b>Shift+Click</b> open dialog, "
560 "<b>Ctrl+Alt+Click</b> resets");
565 }
else if (state & GDK_SHIFT_MASK) {
566 double amount =
_pparam->
_vector[satelite_index][subsatelite_index].amount;
567 gint previous_index = subsatelite_index - 1;
568 if (subsatelite_index == 0 && pathv[satelite_index].closed()) {
571 if ( previous_index < 0 ) {
575 amount =
_pparam->
_vector[satelite_index][subsatelite_index].lenToRad(
576 amount, pathv[satelite_index][previous_index], pathv[satelite_index][subsatelite_index],
582 aprox = ((d2_in)[0].degreesOfFreedom() != 2 ||
583 d2_out[0].degreesOfFreedom() != 2) &&
599 bool is_mirror =
false;
601 if (
_index >= total_nodesatellites) {
606 size_t satelite_index = index_data.first;
607 size_t subsatelite_index = index_data.second;
608 if (!
valid_index(satelite_index, subsatelite_index)) {
612 if (nodesatellite.
hidden ||
613 (!pathv[satelite_index].closed() &&
614 (subsatelite_index == 0 ||
620 double amount = nodesatellite.
amount;
621 double max_amount = amount;
623 gint previous_index = subsatelite_index - 1;
624 if (subsatelite_index == 0 && pathv[satelite_index].closed()) {
627 if ( previous_index < 0 ) {
630 amount =
_pparam->
_vector[satelite_index][subsatelite_index].radToLen(
631 amount, pathv[satelite_index][previous_index], pathv[satelite_index][subsatelite_index]);
632 if (max_amount > 0 && amount == 0) {
633 amount =
_pparam->
_vector[satelite_index][subsatelite_index].amount;
636 nodesatellite.
amount = amount;
637 _pparam->
_vector[satelite_index][subsatelite_index] = nodesatellite;
3x3 matrix representing an affine transformation.
Coord expansionX() const
Calculates the amount of x-scaling imparted by the Affine.
Coord expansionY() const
Calculates the amount of y-scaling imparted by the Affine.
Bezier curve with compile-time specified order.
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.
virtual Coord length(Coord tolerance=0.01) const
Compute the arc length of this curve.
virtual Point pointAt(Coord t) const
Evaluate the curve at a specified time value.
Adaptor that creates 2D functions from 1D ones.
Point pointAt(Coord t) const
Curve const & curveAt(Coord t, Coord *rest=NULL) const
void clear()
Remove all paths from the vector.
bool empty() const
Check whether the vector contains any paths.
Sequence of contiguous curves, aka spline.
Point finalPoint() const
Get the last point in the path.
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.
Two-dimensional point that doubles as a vector.
Straight ray from a specific point to infinity.
void setPoints(Point const &a, Point const &b)
void param_set_and_write_new_value(std::vector< std::vector< NodeSatellite > > const &new_vector)
void param_setValue(std::vector< std::vector< NodeSatellite > > const &new_vector)
std::vector< std::vector< NodeSatellite > > _vector
bool isNodePointSelected(Geom::Point const &nodePoint) const
void makeUndoDone(Glib::ustring message)
void knot_set_offset(NodeSatellite)
FilletChamferKnotHolderEntity(NodeSatelliteArrayParam *p, size_t index)
void knot_ungrabbed(Geom::Point const &p, Geom::Point const &origin, guint state) override
Geom::Point knot_get() const override
void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state) override
void knot_click(guint state) override
bool valid_index(size_t index, size_t subindex) const
Checks whether the index falls within the size of the parameter's vector.
NodeSatelliteArrayParam * _pparam
void set_oncanvas_looks(Inkscape::CanvasItemCtrlShape shape, uint32_t color)
void addKnotHolderEntities(KnotHolder *knotholder, SPItem *item) override
void setGlobalKnotHide(bool global_knot_hide)
friend class FilletChamferKnotHolderEntity
void setEffectType(EffectType et)
void addCanvasIndicators(SPLPEItem const *lpeitem, std::vector< Geom::PathVector > &hp_vec) override
void setCurrentZoom(double current_zoom)
void updateAmmount(double amount)
Inkscape::CanvasItemCtrlShape _knot_shape
void setPathVectorNodeSatellites(PathVectorNodeSatellites *pathVectorNodeSatellites, bool write=true)
void param_transform_multiply(Geom::Affine const &postmul, bool) override
PathVectorNodeSatellites * _last_pathvector_nodesatellites
NodeSatelliteArrayParam(const Glib::ustring &label, const Glib::ustring &tip, const Glib::ustring &key, Inkscape::UI::Widget::Registry *wr, Effect *effect)
void setUseDistance(bool use_knot_distance)
virtual void updateCanvasIndicators()
virtual void param_widget_is_visible(bool is_visible)
Preference storage class.
bool getBool(Glib::ustring const &pref_path, bool def=false)
Retrieve a Boolean value.
static Preferences * get()
Access the singleton Preferences object.
static void showDialog(SPDesktop *desktop, double amount, LivePathEffect::FilletChamferKnotHolderEntity *knot, bool use_distance, bool approx_radius, NodeSatellite nodesatellite)
void set_item(SPItem *item)
std::unique_ptr< KnotHolder > lpeknotholder
Geom::Point snap_knot_position(Geom::Point const &p, unsigned state)
void create(SPDesktop *desktop, SPItem *item, KnotHolder *parent, Inkscape::CanvasItemCtrlType type=Inkscape::CANVAS_ITEM_CTRL_TYPE_DEFAULT, Glib::ustring const &name="unknown", char const *tip="", uint32_t color=0xffffff00)
KnotHolder * parent_holder
void knot_ungrabbed_handler(SPKnot *knot, unsigned int state)
void add(KnotHolderEntity *e)
NodeSatellite a per node holder of data.
Geom::Point getPosition(Geom::Curve const &curve_in, bool inverse=false) const
Get the point position of the nodesatellite.
double arcDistance(Geom::Curve const &curve_in) const
Get the length of the nodesatellite in curve_in.
double time(Geom::Curve const &curve_in, bool inverse=false) const
Get the time position of the nodesatellite in curve_in.
void setPosition(Geom::Point const p, Geom::Curve const &curve_in, bool inverse=false)
Set the position of the nodesatellite from a given point P.
PathVectorNodeSatellites a class to manage nodesatellites in a pathvector.
Geom::PathVector getPathVector() const
NodeSatellites getNodeSatellites()
std::pair< size_t, size_t > getIndexData(size_t index)
size_t getTotalNodeSatellites()
To do: update description of desktop.
Inkscape::UI::Tools::ToolBase * getTool() const
Base class for visual SVG elements.
void setSize(Inkscape::HandleSize size)
CanvasItemPtr< Inkscape::CanvasItemCtrl > ctrl
Our CanvasItemCtrl.
void hide()
Hide knot on its canvas.
void show()
Show knot on its canvas.
void setTip(Glib::ustring &&tip)
void updateCtrl()
Update knot's control state.
double timeAtArcLength(double const A, Geom::Curve const &curve_in)
Calculate the time in curve_in with a size of A.
double arcLengthAt(double const A, Geom::Curve const &curve_in)
Calculate the size in curve_in with a point at A.
std::vector< std::vector< NodeSatellite > > NodeSatellites
constexpr Coord infinity()
Get a value representing infinity.
size_t count_path_nodes(Geom::Path const &path)
Specific geometry functions for Inkscape, not provided my lib2geom.
Various utility functions.
Coord nearest_time(Point const &p, Curve const &c)
bool path_direction(Path const &p)
This function should only be applied to simple paths (regions), as otherwise a boolean winding direct...
Angle distance(Angle const &a, Angle const &b)
double angle_between(Line const &l1, Line const &l2)
Piecewise< SBasis > cross(Piecewise< D2< SBasis > > const &a, Piecewise< D2< SBasis > > const &b)
bool are_near(Affine const &a1, Affine const &a2, Coord eps=EPSILON)
Helper class to stream background task notifications as a series of messages.
@ CANVAS_ITEM_CTRL_TYPE_POINTER
@ CANVAS_ITEM_CTRL_TYPE_MOVE
@ CANVAS_ITEM_CTRL_TYPE_LPE
static cairo_user_data_key_t key
Singleton class to access the preferences file in a convenient way.
Inkscape::ShapeEditor This is a container class which contains a knotholder for shapes.
void sp_lpe_item_update_patheffect(SPLPEItem *lpeitem, bool wholetree, bool write, bool with_satellites)
Calls any registered handlers for the update_patheffect action.
Base class for live path effect items.