X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fline-geometry.cpp;h=d050ec458c266605d4142a65e09e4593080508f5;hb=ceb9b97a62780ab7aef6ec4c03f20d776368a112;hp=d7b5fb2ecd9bc66022916c2d7c8298f6c8c07a0e;hpb=5341d52bd89ffc1587300ac4210afb64661af05d;p=inkscape.git diff --git a/src/line-geometry.cpp b/src/line-geometry.cpp index d7b5fb2ec..d050ec458 100644 --- a/src/line-geometry.cpp +++ b/src/line-geometry.cpp @@ -13,11 +13,11 @@ #include "line-geometry.h" #include "inkscape.h" +#include "desktop.h" #include "desktop-style.h" #include "desktop-handles.h" #include "display/sp-canvas.h" #include "display/sodipodi-ctrl.h" -//#include "display/curve.cpp" namespace Box3D { @@ -54,7 +54,9 @@ Line &Line::operator=(Line const &line) { NR::Maybe Line::intersect(Line const &line) { NR::Coord denom = NR::dot(v_dir, line.normal); - g_return_val_if_fail(fabs(denom) > 1e-6, NR::Nothing()); + NR::Maybe no_point = NR::Nothing(); + if (fabs(denom) < 1e-6) + return no_point; NR::Coord lambda = (line.d0 - NR::dot(pt, line.normal)) / denom; return pt + lambda * v_dir; @@ -89,18 +91,13 @@ double Line::lambda (NR::Point const pt) return lambda; } -inline static double determinant (NR::Point const &a, NR::Point const &b) -{ - return (a[NR::X] * b[NR::Y] - a[NR::Y] * b[NR::X]); -} - /* The coordinates of w with respect to the basis {v1, v2} */ std::pair coordinates (NR::Point const &v1, NR::Point const &v2, NR::Point const &w) { double det = determinant (v1, v2);; if (fabs (det) < epsilon) { - g_warning ("Vectors do not form a basis.\n"); - return std::make_pair (0.0, 0.0); + // vectors are not linearly independent; we indicate this in the return value(s) + return std::make_pair (HUGE_VAL, HUGE_VAL); } double lambda1 = determinant (w, v2) / det; @@ -112,12 +109,22 @@ std::pair coordinates (NR::Point const &v1, NR::Point const &v2, bool lies_in_sector (NR::Point const &v1, NR::Point const &v2, NR::Point const &w) { std::pair coords = coordinates (v1, v2, w); + if (coords.first == HUGE_VAL) { + // catch the case that the vectors are not linearly independent + // FIXME: Can we assume that it's safe to return true if the vectors point in different directions? + return (NR::dot (v1, v2) < 0); + } return (coords.first >= 0 and coords.second >= 0); } -static double pos_angle (NR::Point A, NR::Point B) +bool lies_in_quadrangle (NR::Point const &A, NR::Point const &B, NR::Point const &C, NR::Point const &D, NR::Point const &pt) +{ + return (lies_in_sector (D - A, B - A, pt - A) && lies_in_sector (D - C, B - C, pt - C)); +} + +static double pos_angle (NR::Point v, NR::Point w) { - return fabs (NR::atan2 (A) - NR::atan2 (B)); + return fabs (NR::atan2 (v) - NR::atan2 (w)); } /* @@ -171,55 +178,21 @@ side_of_intersection (NR::Point const &A, NR::Point const &B, NR::Point const &C } } -double cross_ratio (NR::Point const &A, NR::Point const &B, NR::Point const &C, NR::Point const &D) -{ - Line line (A, D); - double lambda_A = line.lambda (A); - double lambda_B = line.lambda (B); - double lambda_C = line.lambda (C); - double lambda_D = line.lambda (D); - - if (fabs (lambda_D - lambda_A) < epsilon || fabs (lambda_C - lambda_B) < epsilon) { - // FIXME: What should we return if the cross ratio can't be computed? - return 0; - //return NR_HUGE; - } - return (((lambda_C - lambda_A) / (lambda_D - lambda_A)) * ((lambda_D - lambda_B) / (lambda_C - lambda_B))); -} - -double cross_ratio (VanishingPoint const &V, NR::Point const &B, NR::Point const &C, NR::Point const &D) +NR::Maybe Line::intersection_with_viewbox (SPDesktop *desktop) { - if (V.is_finite()) { - return cross_ratio (V.get_pos(), B, C, D); - } else { - Line line (B, D); - double lambda_B = line.lambda (B); - double lambda_C = line.lambda (C); - double lambda_D = line.lambda (D); - - if (fabs (lambda_C - lambda_B) < epsilon) { - // FIXME: What should we return if the cross ratio can't be computed? - return 0; - //return NR_HUGE; - } - return (lambda_D - lambda_B) / (lambda_C - lambda_B); + NR::Rect vb = desktop->get_display_area(); + /* remaining viewbox corners */ + NR::Point ul (vb.min()[NR::X], vb.max()[NR::Y]); + NR::Point lr (vb.max()[NR::X], vb.min()[NR::Y]); + + std::pair e = side_of_intersection (vb.min(), lr, vb.max(), ul, this->pt, this->v_dir); + if (e.first == e.second) { + // perspective line lies outside the canvas + return NR::Nothing(); } -} -NR::Point fourth_pt_with_given_cross_ratio (NR::Point const &A, NR::Point const &C, NR::Point const &D, double gamma) -{ - Line line (A, D); - double lambda_A = line.lambda (A); - double lambda_C = line.lambda (C); - double lambda_D = line.lambda (D); - - double beta = (lambda_C - lambda_A) / (lambda_D - lambda_A); - if (fabs (beta - gamma) < epsilon) { - // FIXME: How to handle the case when the point can't be computed? - // g_warning ("Cannot compute point with given cross ratio.\n"); - return NR::Point (0.0, 0.0); - } - return line.point_from_lambda ((beta * lambda_D - gamma * lambda_C) / (beta - gamma)); + Line line (e.first, e.second); + return this->intersect (line); } void create_canvas_point(NR::Point const &pos, double size, guint32 rgba)