summaryrefslogtreecommitdiffstats
path: root/src/live_effects
diff options
context:
space:
mode:
authorJabier Arraiza <jabier.arraiza@marker.es>2019-09-28 08:07:20 +0000
committerJabier Arraiza <jabier.arraiza@marker.es>2019-09-28 15:40:01 +0000
commita63e35e6176130eb13f8c26f50b20c6d5d2fca4e (patch)
tree1419cc3d677a54025c2f65d5caccf663e07c6e05 /src/live_effects
parentFinal fix issue pointed by Mc from https://twitter.com/geekeish/status/117498... (diff)
downloadinkscape-a63e35e6176130eb13f8c26f50b20c6d5d2fca4e.tar.gz
inkscape-a63e35e6176130eb13f8c26f50b20c6d5d2fca4e.zip
Fix issue https://gitlab.com/inkscape/inkscape/issues/246 LPE Perspective/Envelope: Perspective Overflow doesn't work
Diffstat (limited to 'src/live_effects')
-rw-r--r--src/live_effects/lpe-perspective-envelope.cpp261
1 files changed, 141 insertions, 120 deletions
diff --git a/src/live_effects/lpe-perspective-envelope.cpp b/src/live_effects/lpe-perspective-envelope.cpp
index 39db3d8c6..70ca6899c 100644
--- a/src/live_effects/lpe-perspective-envelope.cpp
+++ b/src/live_effects/lpe-perspective-envelope.cpp
@@ -67,120 +67,32 @@ LPEPerspectiveEnvelope::LPEPerspectiveEnvelope(LivePathEffectObject *lpeobject)
LPEPerspectiveEnvelope::~LPEPerspectiveEnvelope()
= default;
-void LPEPerspectiveEnvelope::doEffect(SPCurve *curve)
+bool pointInTriangle(Geom::Point const &p, std::vector<Geom::Point> points)
{
+ if (points.size() != 3) {
+ g_warning("Incorrect number of points in pointInTriangle\n");
+ return false;
+ }
+ Geom::Point p1 = points[0];
+ Geom::Point p2 = points[1];
+ Geom::Point p3 = points[2];
+ // http://totologic.blogspot.com.es/2014/01/accurate-point-in-triangle-test.html
using Geom::X;
using Geom::Y;
- if(are_near(up_left_point, up_right_point) &&
- are_near(up_right_point, down_left_point) &&
- are_near(down_left_point, down_right_point)) {
- g_warning("Perspective/Envelope LPE::doBeforeEffect - lpeobj with invalid parameter, the same value in 4 handles!");
- resetGrid();
- return;
- }
+ double denominator = (p1[X] * (p2[Y] - p3[Y]) + p1[Y] * (p3[X] - p2[X]) + p2[X] * p3[Y] - p2[Y] * p3[X]);
+ double t1 = (p[X] * (p3[Y] - p1[Y]) + p[Y] * (p1[X] - p3[X]) - p1[X] * p3[Y] + p1[Y] * p3[X]) / denominator;
+ double t2 = (p[X] * (p2[Y] - p1[Y]) + p[Y] * (p1[X] - p2[X]) - p1[X] * p2[Y] + p1[Y] * p2[X]) / -denominator;
+ double s = t1 + t2;
+
+ return 0 <= t1 && t1 <= 1 && 0 <= t2 && t2 <= 1 && s <= 1;
+}
+
+void LPEPerspectiveEnvelope::doEffect(SPCurve *curve)
+{
double projmatrix[3][3];
if(deform_type == DEFORMATION_PERSPECTIVE) {
- if (!overflow_perspective && handles.size() == 4) {
- bool move0 = false;
- if (handles[0] != down_left_point) {
- move0 = true;
- }
- bool move1 = false;
- if (handles[1] != up_left_point) {
- move1 = true;
- }
- bool move2 = false;
- if (handles[2] != up_right_point) {
- move2 = true;
- }
- bool move3 = false;
- if (handles[3] != down_right_point) {
- move3 = true;
- }
- handles.resize(4);
- handles[0] = down_left_point;
- handles[1] = up_left_point;
- handles[2] = up_right_point;
- handles[3] = down_right_point;
- Geom::Line line_a(handles[3],handles[1]);
- Geom::Line line_b(handles[1],handles[2]);
- Geom::Line line_c(handles[2],handles[3]);
- int position_a = Geom::sgn(Geom::cross(handles[3] - handles[1], handles[0] - handles[1]));
- int position_b = Geom::sgn(Geom::cross(handles[1] - handles[2], handles[0] - handles[2]));
- int position_c = Geom::sgn(Geom::cross(handles[2] - handles[3], handles[0] - handles[3]));
- if (position_a != 1 && move0) {
- Geom::Point point_a = line_a.pointAt(line_a.nearestTime(handles[0]));
- down_left_point.param_setValue(point_a);
- }
- if (position_b == 1 && move0) {
- Geom::Point point_b = line_b.pointAt(line_b.nearestTime(handles[0]));
- down_left_point.param_setValue(point_b);
- }
- if (position_c == 1 && move0) {
- Geom::Point point_c = line_c.pointAt(line_c.nearestTime(handles[0]));
- down_left_point.param_setValue(point_c);
- }
- line_a.setPoints(handles[0],handles[2]);
- line_b.setPoints(handles[2],handles[3]);
- line_c.setPoints(handles[3],handles[0]);
- position_a = Geom::sgn(Geom::cross(handles[0] - handles[2], handles[1] - handles[2]));
- position_b = Geom::sgn(Geom::cross(handles[2] - handles[3], handles[1] - handles[3]));
- position_c = Geom::sgn(Geom::cross(handles[3] - handles[0], handles[1] - handles[0]));
- if (position_a != 1 && move1) {
- Geom::Point point_a = line_a.pointAt(line_a.nearestTime(handles[1]));
- up_left_point.param_setValue(point_a);
- }
- if (position_b == 1 && move1) {
- Geom::Point point_b = line_b.pointAt(line_b.nearestTime(handles[1]));
- up_left_point.param_setValue(point_b);
- }
- if (position_c == 1 && move1) {
- Geom::Point point_c = line_c.pointAt(line_c.nearestTime(handles[1]));
- up_left_point.param_setValue(point_c);
- }
- line_a.setPoints(handles[1],handles[3]);
- line_b.setPoints(handles[3],handles[0]);
- line_c.setPoints(handles[0],handles[1]);
- position_a = Geom::sgn(Geom::cross(handles[1] - handles[3], handles[2] - handles[3]));
- position_b = Geom::sgn(Geom::cross(handles[3] - handles[0], handles[2] - handles[0]));
- position_c = Geom::sgn(Geom::cross(handles[0] - handles[1], handles[2] - handles[1]));
- if (position_a != 1 && move2) {
- Geom::Point point_a = line_a.pointAt(line_a.nearestTime(handles[2]));
- up_right_point.param_setValue(point_a);
- }
- if (position_b == 1 && move2) {
- Geom::Point point_b = line_b.pointAt(line_b.nearestTime(handles[2]));
- up_right_point.param_setValue(point_b);
- }
- if (position_c == 1 && move2) {
- Geom::Point point_c = line_c.pointAt(line_c.nearestTime(handles[2]));
- up_right_point.param_setValue(point_c);
- }
- line_a.setPoints(handles[2],handles[0]);
- line_b.setPoints(handles[0],handles[1]);
- line_c.setPoints(handles[1],handles[2]);
- position_a = Geom::sgn(Geom::cross(handles[2] - handles[0], handles[3] - handles[0]));
- position_b = Geom::sgn(Geom::cross(handles[0] - handles[1], handles[3] - handles[1]));
- position_c = Geom::sgn(Geom::cross(handles[1] - handles[2], handles[3] - handles[2]));
- if (position_a != 1 && move3) {
- Geom::Point point_a = line_a.pointAt(line_a.nearestTime(handles[3]));
- down_right_point.param_setValue(point_a);
- }
- if (position_b == 1 && move3) {
- Geom::Point point_b = line_b.pointAt(line_b.nearestTime(handles[3]));
- down_right_point.param_setValue(point_b);
- }
- if (position_c == 1 && move3) {
- Geom::Point point_c = line_c.pointAt(line_c.nearestTime(handles[3]));
- down_right_point.param_setValue(point_c);
- }
- } else {
- handles.resize(4);
- handles[0] = down_left_point;
- handles[1] = up_left_point;
- handles[2] = up_right_point;
- handles[3] = down_right_point;
- }
+ using Geom::X;
+ using Geom::Y;
std::vector<Geom::Point> source_handles(4);
source_handles[0] = Geom::Point(boundingbox_X.min(), boundingbox_Y.max());
source_handles[1] = Geom::Point(boundingbox_X.min(), boundingbox_Y.min());
@@ -246,18 +158,16 @@ void LPEPerspectiveEnvelope::doEffect(SPCurve *curve)
//Itreadores
SPCurve *nCurve = new SPCurve();
Geom::Path::const_iterator curve_it1 = path_it.begin();
- Geom::Path::const_iterator curve_it2 = ++(path_it.begin());
Geom::Path::const_iterator curve_endit = path_it.end_default();
if (path_it.closed()) {
- const Geom::Curve &closingline =
- path_it.back_closed();
+ const Geom::Curve &closingline = path_it.back_closed();
if (are_near(closingline.initialPoint(), closingline.finalPoint())) {
curve_endit = path_it.end_open();
}
}
if(deform_type == DEFORMATION_PERSPECTIVE) {
- nCurve->moveto(projectPoint(curve_it1->initialPoint(),projmatrix));
+ nCurve->moveto(projectPoint(curve_it1->initialPoint(), projmatrix));
} else {
nCurve->moveto(projectPoint(curve_it1->initialPoint()));
}
@@ -272,19 +182,20 @@ void LPEPerspectiveEnvelope::doEffect(SPCurve *curve)
}
point_at3 = curve_it1->finalPoint();
if(deform_type == DEFORMATION_PERSPECTIVE) {
- point_at1 = projectPoint(point_at1,projmatrix);
- point_at2 = projectPoint(point_at2,projmatrix);
- point_at3 = projectPoint(point_at3,projmatrix);
+ point_at1 = projectPoint(point_at1, projmatrix);
+ point_at2 = projectPoint(point_at2, projmatrix);
+ point_at3 = projectPoint(point_at3, projmatrix);
} else {
point_at1 = projectPoint(point_at1);
point_at2 = projectPoint(point_at2);
point_at3 = projectPoint(point_at3);
}
- nCurve->curveto(point_at1, point_at2, point_at3);
- ++curve_it1;
- if(curve_it2 != curve_endit) {
- ++curve_it2;
+ if (cubic) {
+ nCurve->curveto(point_at1, point_at2, point_at3);
+ } else {
+ nCurve->lineto(point_at3);
}
+ ++curve_it1;
}
//y cerramos la curva
if (path_it.closed()) {
@@ -477,6 +388,116 @@ LPEPerspectiveEnvelope::doBeforeEffect (SPLPEItem const* lpeitem)
horizontal(up_right_point, down_right_point,horiz);
}
setDefaults();
+ if (are_near(up_left_point, up_right_point) && are_near(up_right_point, down_left_point) &&
+ are_near(down_left_point, down_right_point)) {
+ g_warning(
+ "Perspective/Envelope LPE::doBeforeEffect - lpeobj with invalid parameter, the same value in 4 handles!");
+ resetGrid();
+ return;
+ }
+ if (deform_type == DEFORMATION_PERSPECTIVE) {
+ if (!overflow_perspective && handles.size() == 4) {
+ bool move0 = false;
+ if (handles[0] != down_left_point) {
+ move0 = true;
+ }
+ bool move1 = false;
+ if (handles[1] != up_left_point) {
+ move1 = true;
+ }
+ bool move2 = false;
+ if (handles[2] != up_right_point) {
+ move2 = true;
+ }
+ bool move3 = false;
+ if (handles[3] != down_right_point) {
+ move3 = true;
+ }
+ handles.resize(4);
+ handles[0] = down_left_point;
+ handles[1] = up_left_point;
+ handles[2] = up_right_point;
+ handles[3] = down_right_point;
+ Geom::Line line_a(handles[3], handles[1]);
+ Geom::Line line_b(handles[1], handles[2]);
+ Geom::Line line_c(handles[2], handles[3]);
+ int position_a = Geom::sgn(Geom::cross(handles[3] - handles[1], handles[0] - handles[1]));
+ int position_b = Geom::sgn(Geom::cross(handles[1] - handles[2], handles[0] - handles[2]));
+ int position_c = Geom::sgn(Geom::cross(handles[2] - handles[3], handles[0] - handles[3]));
+ if (position_a != 1 && move0) {
+ Geom::Point point_a = line_a.pointAt(line_a.nearestTime(handles[0]));
+ down_left_point.param_setValue(point_a, true);
+ }
+ if (position_b == 1 && move0) {
+ Geom::Point point_b = line_b.pointAt(line_b.nearestTime(handles[0]));
+ down_left_point.param_setValue(point_b, true);
+ }
+ if (position_c == 1 && move0) {
+ Geom::Point point_c = line_c.pointAt(line_c.nearestTime(handles[0]));
+ down_left_point.param_setValue(point_c, true);
+ }
+ line_a.setPoints(handles[0], handles[2]);
+ line_b.setPoints(handles[2], handles[3]);
+ line_c.setPoints(handles[3], handles[0]);
+ position_a = Geom::sgn(Geom::cross(handles[0] - handles[2], handles[1] - handles[2]));
+ position_b = Geom::sgn(Geom::cross(handles[2] - handles[3], handles[1] - handles[3]));
+ position_c = Geom::sgn(Geom::cross(handles[3] - handles[0], handles[1] - handles[0]));
+ if (position_a != 1 && move1) {
+ Geom::Point point_a = line_a.pointAt(line_a.nearestTime(handles[1]));
+ up_left_point.param_setValue(point_a, true);
+ }
+ if (position_b == 1 && move1) {
+ Geom::Point point_b = line_b.pointAt(line_b.nearestTime(handles[1]));
+ up_left_point.param_setValue(point_b, true);
+ }
+ if (position_c == 1 && move1) {
+ Geom::Point point_c = line_c.pointAt(line_c.nearestTime(handles[1]));
+ up_left_point.param_setValue(point_c, true);
+ }
+ line_a.setPoints(handles[1], handles[3]);
+ line_b.setPoints(handles[3], handles[0]);
+ line_c.setPoints(handles[0], handles[1]);
+ position_a = Geom::sgn(Geom::cross(handles[1] - handles[3], handles[2] - handles[3]));
+ position_b = Geom::sgn(Geom::cross(handles[3] - handles[0], handles[2] - handles[0]));
+ position_c = Geom::sgn(Geom::cross(handles[0] - handles[1], handles[2] - handles[1]));
+ if (position_a != 1 && move2) {
+ Geom::Point point_a = line_a.pointAt(line_a.nearestTime(handles[2]));
+ up_right_point.param_setValue(point_a, true);
+ }
+ if (position_b == 1 && move2) {
+ Geom::Point point_b = line_b.pointAt(line_b.nearestTime(handles[2]));
+ up_right_point.param_setValue(point_b, true);
+ }
+ if (position_c == 1 && move2) {
+ Geom::Point point_c = line_c.pointAt(line_c.nearestTime(handles[2]));
+ up_right_point.param_setValue(point_c, true);
+ }
+ line_a.setPoints(handles[2], handles[0]);
+ line_b.setPoints(handles[0], handles[1]);
+ line_c.setPoints(handles[1], handles[2]);
+ position_a = Geom::sgn(Geom::cross(handles[2] - handles[0], handles[3] - handles[0]));
+ position_b = Geom::sgn(Geom::cross(handles[0] - handles[1], handles[3] - handles[1]));
+ position_c = Geom::sgn(Geom::cross(handles[1] - handles[2], handles[3] - handles[2]));
+ if (position_a != 1 && move3) {
+ Geom::Point point_a = line_a.pointAt(line_a.nearestTime(handles[3]));
+ down_right_point.param_setValue(point_a, true);
+ }
+ if (position_b == 1 && move3) {
+ Geom::Point point_b = line_b.pointAt(line_b.nearestTime(handles[3]));
+ down_right_point.param_setValue(point_b, true);
+ }
+ if (position_c == 1 && move3) {
+ Geom::Point point_c = line_c.pointAt(line_c.nearestTime(handles[3]));
+ down_right_point.param_setValue(point_c, true);
+ }
+ } else {
+ handles.resize(4);
+ handles[0] = down_left_point;
+ handles[1] = up_left_point;
+ handles[2] = up_right_point;
+ handles[3] = down_right_point;
+ }
+ }
}
void