19#include <glibmm/i18n.h>
21#include <gtkmm/button.h>
22#include <gtkmm/label.h>
23#include <gtkmm/separator.h>
24#include <gtkmm/widget.h>
25#include <gsl/gsl_linalg.h>
51 horizontal_mirror(_(
"Mirror movements in horizontal"), _(
"Mirror movements in horizontal"),
"horizontal_mirror", &wr, this, false),
52 vertical_mirror(_(
"Mirror movements in vertical"), _(
"Mirror movements in vertical"),
"vertical_mirror", &wr, this, false),
53 overflow_perspective(_(
"Overflow perspective"), _(
"Overflow perspective"),
"overflow_perspective", &wr, this, false),
55 up_left_point(_(
"Top Left"), _(
"Top Left - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"),
"up_left_point", &wr, this),
56 up_right_point(_(
"Top Right"), _(
"Top Right - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"),
"up_right_point", &wr, this),
57 down_left_point(_(
"Down Left"), _(
"Down Left - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"),
"down_left_point", &wr, this),
58 down_right_point(_(
"Down Right"), _(
"Down Right - <b>Ctrl+Alt+Click</b>: reset, <b>Ctrl</b>: move along axes"),
"down_right_point", &wr, this)
86 if (points.size() != 3) {
87 g_warning(
"Incorrect number of points in pointInTriangle\n");
96 double denominator = (p1[
X] * (p2[
Y] - p3[
Y]) + p1[
Y] * (p3[
X] - p2[
X]) + p2[
X] * p3[
Y] - p2[
Y] * p3[
X]);
97 double t1 = (p[
X] * (p3[
Y] - p1[
Y]) + p[
Y] * (p1[
X] - p3[
X]) - p1[
X] * p3[
Y] + p1[
Y] * p3[
X]) / denominator;
98 double t2 = (p[
X] * (p2[
Y] - p1[
Y]) + p[
Y] * (p1[
X] - p2[
X]) - p1[
X] * p2[
Y] + p1[
Y] * p2[
X]) / -denominator;
101 return 0 <= t1 && t1 <= 1 && 0 <= t2 && t2 <= 1 && s <= 1;
106 double projmatrix[3][3];
110 std::vector<Geom::Point> source_handles(4);
115 double solmatrix[8][8] = {{0}};
116 double free_term[8] = {0};
117 double gslSolmatrix[64];
118 for(
unsigned int i = 0; i < 4; ++i) {
119 solmatrix[i][0] = source_handles[i][
X];
120 solmatrix[i][1] = source_handles[i][
Y];
122 solmatrix[i][6] = -
handles[i][
X] * source_handles[i][
X];
123 solmatrix[i][7] = -
handles[i][
X] * source_handles[i][
Y];
124 solmatrix[i+4][3] = source_handles[i][
X];
125 solmatrix[i+4][4] = source_handles[i][
Y];
126 solmatrix[i+4][5] = 1;
127 solmatrix[i+4][6] = -
handles[i][
Y] * source_handles[i][
X];
128 solmatrix[i+4][7] = -
handles[i][
Y] * source_handles[i][
Y];
133 for(
auto & i : solmatrix) {
141 gsl_matrix_view m = gsl_matrix_view_array (gslSolmatrix, 8, 8);
142 gsl_vector_view b = gsl_vector_view_array (free_term, 8);
143 gsl_vector *x = gsl_vector_alloc (8);
145 gsl_permutation * p = gsl_permutation_alloc (8);
146 gsl_linalg_LU_decomp (&m.matrix, p, &s);
147 gsl_linalg_LU_solve (&m.matrix, p, &b.vector, x);
149 for(
auto & i : projmatrix) {
150 for(
double & j : i) {
152 projmatrix[2][2] = 1.0;
155 j = gsl_vector_get(x, h);
159 gsl_permutation_free (p);
168 for (
const auto & path_it : original_pathv) {
176 if (path_it.closed()) {
177 const Geom::Curve &closingline = path_it.back_closed();
179 curve_endit = path_it.end_open();
187 while (curve_it1 != curve_endit) {
190 point_at1 = (*cubic)[1];
191 point_at2 = (*cubic)[2];
193 point_at1 = curve_it1->initialPoint();
194 point_at2 = curve_it1->finalPoint();
196 point_at3 = curve_it1->finalPoint();
214 if (path_it.closed()) {
218 curve.push_back(std::move(nCurve));
250 Geom::Coord((x*m[0][0] + y*m[0][1] + m[0][2])/(x*m[2][0]+y*m[2][1]+m[2][2])),
251 Geom::Coord((x*m[1][0] + y*m[1][1] + m[1][2])/(x*m[2][0]+y*m[2][1]+m[2][2])));
266 auto const vbox = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL, 6);
269 auto const hbox_up_handles = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL,0);
270 auto const hbox_down_handles = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL,0);
273 if (!param->widget_is_visible)
continue;
275 auto const widg = param->param_newWidget();
278 if (param->param_key ==
"up_left_point" ||
279 param->param_key ==
"up_right_point" ||
280 param->param_key ==
"down_left_point" ||
281 param->param_key ==
"down_right_point")
283 auto &point_hbox =
dynamic_cast<Gtk::Box &
>(*widg);
285 auto &point_hboxHBox =
dynamic_cast<Gtk::Box &
>(*child_list.at(0));
287 point_hboxHBox.remove(*child_list2.at(0));
289 if (param->param_key ==
"up_left_point") {
290 auto const handles = Gtk::make_managed<Gtk::Label>(Glib::ustring(_(
"Handles:")),Gtk::Align::START);
293 UI::pack_start(*hbox_up_handles, *Gtk::make_managed<Gtk::Separator>(Gtk::Orientation::VERTICAL),
295 }
else if (param->param_key ==
"up_right_point") {
297 }
else if (param->param_key ==
"down_left_point") {
299 UI::pack_start(*hbox_down_handles, *Gtk::make_managed<Gtk::Separator>(Gtk::Orientation::VERTICAL),
310 if (
auto const tip = param->param_getTooltip()) {
311 widg->set_tooltip_markup(*tip);
313 widg->set_tooltip_text({});
314 widg->set_has_tooltip(
false);
321 auto const reset_button = Gtk::make_managed<Gtk::Button>(_(
"_Clear"),
true);
322 reset_button->set_image_from_icon_name(
"edit-clear");
324 reset_button->set_size_request(140,30);
325 reset_button->set_halign(Gtk::Align::START);
341 double distance_middle = (distance_one + distance_two)/2;
343 distance_middle *= -1;
362 double distance_middle = (distance_one + distance_two)/2;
364 distance_middle *= -1;
379 g_warning(
"Couldn`t apply perspective/envelope to a element with geometric width or height equal 0 we add a temporary bounding box to allow handle");
401 "Perspective/Envelope LPE::doBeforeEffect - lpeobj with invalid parameter, the same value in 4 handles!");
434 if (position_a != 1 && move0) {
438 if (position_b == 1 && move0) {
442 if (position_c == 1 && move0) {
452 if (position_a != 1 && move1) {
456 if (position_b == 1 && move1) {
460 if (position_c == 1 && move1) {
470 if (position_a != 1 && move2) {
474 if (position_b == 1 && move2) {
478 if (position_c == 1 && move2) {
488 if (position_a != 1 && move3) {
492 if (position_b == 1 && move3) {
496 if (position_c == 1 && move3) {
563 hp_vec.emplace_back(std::move(
c));
3x3 matrix representing an affine transformation.
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.
constexpr C extent() const
constexpr C middle() const
Range of real numbers that is never empty.
Infinite line on a plane.
void setPoints(Point const &a, Point const &b)
Set a line based on two points it should pass through.
Coord nearestTime(Point const &p) const
Find a point on the line closest to the query point.
Point pointAt(Coord t) const
Sequence of contiguous curves, aka spline.
void start(Point const &p)
Two-dimensional point that doubles as a vector.
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
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
virtual void setDefaults()
~LPEPerspectiveEnvelope() override
void addCanvasIndicators(SPLPEItem const *, std::vector< Geom::PathVector > &hp_vec) override
Add possible canvas indicators (i.e., helperpaths other than the original path) to hp_vec This functi...
void resetDefaults(SPItem const *item) override
Sets all parameters to their default values and writes them to SVG.
virtual Geom::Point pointAtRatio(Geom::Coord ratio, Geom::Point A, Geom::Point B)
Gtk::Widget * newWidget() override
This creates a managed widget.
PointParam down_left_point
void doEffect(Geom::PathVector &curve) override
void doBeforeEffect(SPLPEItem const *lpeitem) override
Is performed each time before the effect is updated.
PointParam up_right_point
virtual void vertical(PointParam ¶mA, PointParam ¶mB, Geom::Line vert)
BoolParam vertical_mirror
void transform_multiply(Geom::Affine const &postmul, bool set) override
Overridden function to apply transforms for example to powerstroke, jointtype or tapperstroke.
PointParam down_right_point
std::vector< Geom::Point > handles
LPEPerspectiveEnvelope(LivePathEffectObject *lpeobject)
BoolParam overflow_perspective
virtual Geom::Point projectPoint(Geom::Point p)
BoolParam horizontal_mirror
virtual void horizontal(PointParam ¶mA, PointParam ¶mB, Geom::Line horiz)
EnumParam< unsigned > deform_type
void param_update_default(Geom::Point default_point)
void param_setValue(Geom::Point newpoint, bool write=false)
void param_set_default() final
void param_transform_multiply(Geom::Affine const &, bool set) final
Simplified management of enumerations of svg items with UI labels.
Base class for visual SVG elements.
bool pathEffectsEnabled() const
bool optimizeTransforms()
returns false when LPE write unoptimiced
void move_endpoints(Geom::PathVector &pathv, Geom::Point const &new_p0, Geom::Point const &new_p1)
Sets start of first path to new_p0, and end of first path to new_p1.
void closepath_current(Geom::Path &path)
Close path by setting the end point to the start point instead of adding a new lineto.
double Coord
Floating point type used to store coordinates.
Geom::PathVector pathv_to_linear_and_cubic_beziers(Geom::PathVector const &pathv)
Specific geometry functions for Inkscape, not provided my lib2geom.
LPE <perspective-envelope> implementation , see lpe-perspective-envelope.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)
std::optional< Crossing > OptCrossing
OptCrossing intersection(Ray const &r1, 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)
@ DEFORMATION_PERSPECTIVE
static const Util::EnumDataConverter< unsigned > DeformationTypeConverter(DeformationTypeData, sizeof(DeformationTypeData)/sizeof(*DeformationTypeData))
bool pointInTriangle(Geom::Point const &p, std::vector< Geom::Point > points)
static const Util::EnumData< unsigned > DeformationTypeData[]
std::vector< Gtk::Widget * > get_children(Gtk::Widget &widget)
Get a vector of the widgetʼs children, from get_first_child() through each get_next_sibling().
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.
Helpers for using Gtk::Boxes, encapsulating large changes between GTK3 & GTK4.
Base class for live path effect items.
Simplified management of enumerations of svg items with UI labels.