X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fline-geometry.cpp;h=2e528f3afe5b555e64c459f02ef58e5d76a16836;hb=c559a44911579b77710f6698f1a064195da7c292;hp=5d8eca8a12197f2138f4dbdca8b215dd15b6296d;hpb=492de225e9b11f35d98b6b75efa58e115ee688fa;p=inkscape.git diff --git a/src/line-geometry.cpp b/src/line-geometry.cpp index 5d8eca8a1..2e528f3af 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 { @@ -26,14 +26,14 @@ namespace Box3D { * of the segment. Otherwise interpret it as the direction of the line. * FIXME: Think of a better way to distinguish between the two constructors of lines. */ -Line::Line(NR::Point const &start, NR::Point const &vec, bool is_endpoint) { +Line::Line(Geom::Point const &start, Geom::Point const &vec, bool is_endpoint) { pt = start; if (is_endpoint) v_dir = vec - start; else v_dir = vec; normal = v_dir.ccw(); - d0 = NR::dot(normal, pt); + d0 = Geom::dot(normal, pt); } Line::Line(Line const &line) { @@ -52,38 +52,38 @@ Line &Line::operator=(Line const &line) { return *this; } -NR::Maybe Line::intersect(Line const &line) { - NR::Coord denom = NR::dot(v_dir, line.normal); - NR::Maybe no_point = NR::Nothing(); +boost::optional Line::intersect(Line const &line) { + Geom::Coord denom = Geom::dot(v_dir, line.normal); + boost::optional no_point; if (fabs(denom) < 1e-6) return no_point; - NR::Coord lambda = (line.d0 - NR::dot(pt, line.normal)) / denom; + Geom::Coord lambda = (line.d0 - Geom::dot(pt, line.normal)) / denom; return pt + lambda * v_dir; } -void Line::set_direction(NR::Point const &dir) +void Line::set_direction(Geom::Point const &dir) { v_dir = dir; normal = v_dir.ccw(); - d0 = NR::dot(normal, pt); + d0 = Geom::dot(normal, pt); } -NR::Point Line::closest_to(NR::Point const &pt) +Geom::Point Line::closest_to(Geom::Point const &pt) { /* return the intersection of this line with a perpendicular line passing through pt */ - NR::Maybe result = this->intersect(Line(pt, (this->v_dir).ccw(), false)); - g_return_val_if_fail (result, NR::Point (0.0, 0.0)); + boost::optional result = this->intersect(Line(pt, (this->v_dir).ccw(), false)); + g_return_val_if_fail (result, Geom::Point (0.0, 0.0)); return *result; } -double Line::lambda (NR::Point const pt) +double Line::lambda (Geom::Point const pt) { - double sign = (NR::dot (pt - this->pt, this->v_dir) > 0) ? 1.0 : -1.0; - double lambda = sign * NR::L2 (pt - this->pt); + double sign = (Geom::dot (pt - this->pt, this->v_dir) > 0) ? 1.0 : -1.0; + double lambda = sign * Geom::L2 (pt - this->pt); // FIXME: It may speed things up (but how much?) if we assume that // pt lies on the line and thus skip the following test - NR::Point test = point_from_lambda (lambda); + Geom::Point test = point_from_lambda (lambda); if (!pts_coincide (pt, test)) { g_warning ("Point does not lie on line.\n"); return 0; @@ -91,13 +91,8 @@ 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) +std::pair coordinates (Geom::Point const &v1, Geom::Point const &v2, Geom::Point const &w) { double det = determinant (v1, v2);; if (fabs (det) < epsilon) { @@ -111,25 +106,25 @@ std::pair coordinates (NR::Point const &v1, NR::Point const &v2, } /* whether w lies inside the sector spanned by v1 and v2 */ -bool lies_in_sector (NR::Point const &v1, NR::Point const &v2, NR::Point const &w) +bool lies_in_sector (Geom::Point const &v1, Geom::Point const &v2, Geom::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 (Geom::dot (v1, v2) < 0); } return (coords.first >= 0 and coords.second >= 0); } -bool lies_in_quadrangle (NR::Point const &A, NR::Point const &B, NR::Point const &C, NR::Point const &D, NR::Point const &pt) +bool lies_in_quadrangle (Geom::Point const &A, Geom::Point const &B, Geom::Point const &C, Geom::Point const &D, Geom::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) +static double pos_angle (Geom::Point v, Geom::Point w) { - return fabs (NR::atan2 (v) - NR::atan2 (w)); + return fabs (Geom::atan2 (v) - Geom::atan2 (w)); } /* @@ -137,16 +132,16 @@ static double pos_angle (NR::Point v, NR::Point w) * starting at pt and going into direction dir. * If none of the sides is hit, it returns a pair containing two identical points. */ -std::pair -side_of_intersection (NR::Point const &A, NR::Point const &B, NR::Point const &C, NR::Point const &D, - NR::Point const &pt, NR::Point const &dir) +std::pair +side_of_intersection (Geom::Point const &A, Geom::Point const &B, Geom::Point const &C, Geom::Point const &D, + Geom::Point const &pt, Geom::Point const &dir) { - NR::Point dir_A (A - pt); - NR::Point dir_B (B - pt); - NR::Point dir_C (C - pt); - NR::Point dir_D (D - pt); + Geom::Point dir_A (A - pt); + Geom::Point dir_B (B - pt); + Geom::Point dir_C (C - pt); + Geom::Point dir_D (D - pt); - std::pair result; + std::pair result; double angle = -1; double tmp_angle; @@ -183,58 +178,24 @@ 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) +boost::optional 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); + Geom::Rect vb = desktop->get_display_area(); + /* remaining viewbox corners */ + Geom::Point ul (vb.min()[Geom::X], vb.max()[Geom::Y]); + Geom::Point lr (vb.max()[Geom::X], vb.min()[Geom::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 boost::optional(); } -} - -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) +void create_canvas_point(Geom::Point const &pos, double size, guint32 rgba) { SPDesktop *desktop = inkscape_active_desktop(); SPCanvasItem * canvas_pt = sp_canvas_item_new(sp_desktop_controls(desktop), SP_TYPE_CTRL, @@ -247,7 +208,7 @@ void create_canvas_point(NR::Point const &pos, double size, guint32 rgba) SP_CTRL(canvas_pt)->moveto(pos); } -void create_canvas_line(NR::Point const &p1, NR::Point const &p2, guint32 rgba) +void create_canvas_line(Geom::Point const &p1, Geom::Point const &p2, guint32 rgba) { SPDesktop *desktop = inkscape_active_desktop(); SPCanvasItem *line = sp_canvas_item_new(sp_desktop_controls(desktop), @@ -268,4 +229,4 @@ void create_canvas_line(NR::Point const &p1, NR::Point const &p2, guint32 rgba) fill-column:99 End: */ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :