From 80a38fd6ed41a1c70f1cc961df821932aafb6764 Mon Sep 17 00:00:00 2001 From: dvlierop2 Date: Sun, 12 Apr 2009 12:59:26 +0000 Subject: [PATCH] Use the line intersection routines in 2geom/line.h instead of the deprecated ones in 2geom/geom.h. (I know we're in a refactoring freeze, but this one I was already working on before this freeze was announced and it's quite safe IMHO. It's only a small change in 2geom's API and can hardly do any real harm. I will not refactor anything else until after the v0.47 release, promised!) --- src/2geom/geom.h | 4 +- src/box3d.cpp | 23 ++++++++-- src/display/canvas-axonomgrid.cpp | 44 ++++++++++++------- src/line-snapper.cpp | 34 +++++++-------- src/live_effects/lpe-line_segment.cpp | 12 ++--- src/snapped-line.cpp | 63 ++++++++++++++++----------- src/snapped-line.h | 2 + 7 files changed, 113 insertions(+), 69 deletions(-) diff --git a/src/2geom/geom.h b/src/2geom/geom.h index 4e7095372..9233696d7 100644 --- a/src/2geom/geom.h +++ b/src/2geom/geom.h @@ -57,7 +57,7 @@ intersector_ccw(const Geom::Point& p0, const Geom::Point& p1, /* intersectors */ -#if 1 +#if 0 // Use the new routines provided in line.h IntersectorKind @@ -76,7 +76,7 @@ line_twopoint_intersect(Geom::Point const &p00, Geom::Point const &p01, Geom::Point &result); #endif -#if 1 +#if 0 std::vector rect_line_intersect(Geom::Point const &E, Geom::Point const &F, Geom::Point const &p0, Geom::Point const &p1); diff --git a/src/box3d.cpp b/src/box3d.cpp index 34ce7a27f..5cffa66d9 100644 --- a/src/box3d.cpp +++ b/src/box3d.cpp @@ -31,7 +31,7 @@ #include "line-geometry.h" #include "persp3d-reference.h" #include "uri.h" -#include <2geom/geom.h> +#include <2geom/line.h> #include "sp-guide.h" #include "sp-namedview.h" #include "preferences.h" @@ -675,17 +675,32 @@ void box3d_corners_for_PLs (const SPBox3D * box, Proj::Axis axis, static bool box3d_half_line_crosses_joining_line (Geom::Point const &A, Geom::Point const &B, Geom::Point const &C, Geom::Point const &D) { - Geom::Point E; // the point of intersection Geom::Point n0 = (B - A).ccw(); double d0 = dot(n0,A); Geom::Point n1 = (D - C).ccw(); double d1 = dot(n1,C); - Geom::IntersectorKind intersects = Geom::line_intersection(n0, d0, n1, d1, E); - if (intersects == Geom::coincident || intersects == Geom::parallel) { + + Geom::Line lineAB(A,B); + Geom::Line lineCD(C,D); + + Geom::OptCrossing inters = Geom::OptCrossing(); // empty by default + try + { + inters = Geom::intersection(lineAB, lineCD); + } + catch (Geom::InfiniteSolutions e) + { + // We're probably dealing with parallel lines, so they don't really cross + return false; + } + + if (!inters) { return false; } + Geom::Point E = lineAB.pointAt((*inters).ta); // the point of intersection + if ((dot(C,n0) < d0) == (dot(D,n0) < d0)) { // C and D lie on the same side of the line AB return false; diff --git a/src/display/canvas-axonomgrid.cpp b/src/display/canvas-axonomgrid.cpp index 9c6126b7c..1a7c01c16 100644 --- a/src/display/canvas-axonomgrid.cpp +++ b/src/display/canvas-axonomgrid.cpp @@ -20,7 +20,7 @@ #include "sp-canvas-util.h" #include "canvas-axonomgrid.h" #include "util/mathfns.h" -#include "2geom/geom.h" +#include "2geom/line.h" #include "display-forward.h" #include @@ -713,33 +713,47 @@ CanvasAxonomGridSnapper::_getSnapLines(Geom::Point const &p) const double y_proj_along_x_max = Inkscape::Util::round_to_upper_multiple_plus(y_proj_along_x, scaled_spacing_v, grid->origin[Geom::Y]); double y_proj_along_x_min = Inkscape::Util::round_to_lower_multiple_plus(y_proj_along_x, scaled_spacing_v, grid->origin[Geom::Y]); + // Calculate the versor for the angled grid lines + Geom::Point vers_x = Geom::Point(1, -grid->tan_angle[X]); + Geom::Point vers_z = Geom::Point(1, grid->tan_angle[Z]); + // Calculate the normal for the angled grid lines - Geom::Point norm_x = Geom::rot90(Geom::Point(1, -grid->tan_angle[X])); - Geom::Point norm_z = Geom::rot90(Geom::Point(1, grid->tan_angle[Z])); + Geom::Point norm_x = Geom::rot90(vers_x); + Geom::Point norm_z = Geom::rot90(vers_z); - // The four angled grid lines form a parallellogram, enclosing the point - // One of the two vertical grid lines divides this parallellogram in two triangles + // The four angled grid lines form a parallelogram, enclosing the point + // One of the two vertical grid lines divides this parallelogram in two triangles // We will now try to find out in which half (i.e. triangle) our point is, and return // only the three grid lines defining that triangle // The vertical grid line is at the intersection of two angled grid lines. // Now go find that intersection! - Geom::Point result; - Geom::IntersectorKind is = Geom::line_intersection(norm_x, norm_x[Geom::Y]*y_proj_along_x_max, - norm_z, norm_z[Geom::Y]*y_proj_along_z_max, - result); - - // Determine which half of the parallellogram to use + Geom::Point p_x(0, y_proj_along_x_max); + Geom::Line line_x(p_x, p_x + vers_x); + Geom::Point p_z(0, y_proj_along_z_max); + Geom::Line line_z(p_z, p_z + vers_z); + + Geom::OptCrossing inters = Geom::OptCrossing(); // empty by default + try + { + inters = Geom::intersection(line_x, line_z); + } + catch (Geom::InfiniteSolutions e) + { + // We're probably dealing with parallel lines; this is useless! + return s; + } + + // Determine which half of the parallelogram to use bool use_left_half = true; bool use_right_half = true; - if (is == Geom::intersects) { - use_left_half = (p[Geom::X] - grid->origin[Geom::X]) < result[Geom::X]; + if (inters) { + Geom::Point inters_pt = line_x.pointAt((*inters).ta); + use_left_half = (p[Geom::X] - grid->origin[Geom::X]) < inters_pt[Geom::X]; use_right_half = !use_left_half; } - //std::cout << "intersection at " << result << " leads to use_left_half = " << use_left_half << " and use_right_half = " << use_right_half << std::endl; - // Return the three grid lines which define the triangle that encloses our point // If we didn't find an intersection above, all 6 grid lines will be returned if (use_left_half) { diff --git a/src/line-snapper.cpp b/src/line-snapper.cpp index f6a6be74e..73f46c0a2 100644 --- a/src/line-snapper.cpp +++ b/src/line-snapper.cpp @@ -11,7 +11,7 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include <2geom/geom.h> +#include <2geom/line.h> #include "line-snapper.h" #include "snapped-line.h" #include @@ -75,23 +75,23 @@ void Inkscape::LineSnapper::constrainedSnap(SnappedConstraints &sc, for (LineList::const_iterator i = lines.begin(); i != lines.end(); i++) { if (Geom::L2(c.getDirection()) > 0) { // Can't do a constrained snap without a constraint - /* Normal to the line we're trying to snap along */ - Geom::Point const n(Geom::rot90(Geom::unit_vector(c.getDirection()))); - - Geom::Point const point_on_line = c.hasPoint() ? c.getPoint() : p; - - /* Constant term of the line we're trying to snap along */ - Geom::Coord const q0 = dot(n, point_on_line); - /* Constant term of the grid or guide line */ - Geom::Coord const q1 = dot(i->first, i->second); - - /* Try to intersect this line with the target line */ - Geom::Point t_2geom(NR_HUGE, NR_HUGE); - Geom::IntersectorKind const k = Geom::line_intersection(n, q0, i->first, q1, t_2geom); - Geom::Point t(t_2geom); + Geom::Point const point_on_line = c.hasPoint() ? c.getPoint() : p; + Geom::Line line1(point_on_line, point_on_line + c.getDirection()); + Geom::Line line2(i->second, i->second + Geom::rot90(i->first)); + Geom::OptCrossing inters = Geom::OptCrossing(); // empty by default + try + { + inters = Geom::intersection(line1, line2); + } + catch (Geom::InfiniteSolutions e) + { + // We're probably dealing with parallel lines, so snapping doesn't make any sense here + continue; // jump to the next iterator in the for-loop + } - if (k == Geom::intersects) { - const Geom::Coord dist = Geom::L2(t - p); + if (inters) { + Geom::Point t = line1.pointAt((*inters).ta); + const Geom::Coord dist = Geom::L2(t - p); if (dist < getSnapperTolerance()) { // When doing a constrained snap, we're already at an intersection. // This snappoint is therefore fully constrained, so there's no need diff --git a/src/live_effects/lpe-line_segment.cpp b/src/live_effects/lpe-line_segment.cpp index 9a7d3cfbc..df5619002 100644 --- a/src/live_effects/lpe-line_segment.cpp +++ b/src/live_effects/lpe-line_segment.cpp @@ -53,29 +53,29 @@ LPELineSegment::doBeforeEffect (SPLPEItem *lpeitem) std::vector LPELineSegment::doEffect_path (std::vector const & path_in) { - using namespace Geom; std::vector output; A = initialPoint(path_in); B = finalPoint(path_in); - std::vector intersections = rect_line_intersect(bboxA, bboxB, A, B); + Geom::Rect dummyRect(bboxA, bboxB); + boost::optional intersection_segment = Geom::rect_line_intersect(dummyRect, Geom::Line(A, B)); - if (intersections.size() < 2) { + if (!intersection_segment) { g_print ("Possible error - no intersection with limiting bounding box.\n"); return path_in; } if (end_type == END_OPEN_INITIAL || end_type == END_OPEN_BOTH) { - A = intersections[0]; + A = (*intersection_segment).initialPoint(); } if (end_type == END_OPEN_FINAL || end_type == END_OPEN_BOTH) { - B = intersections[1]; + B = (*intersection_segment).finalPoint(); } Geom::Path path(A); - path.appendNew(B); + path.appendNew(B); output.push_back(path); diff --git a/src/snapped-line.cpp b/src/snapped-line.cpp index 27e024821..3ebbeaf70 100644 --- a/src/snapped-line.cpp +++ b/src/snapped-line.cpp @@ -9,7 +9,7 @@ */ #include "snapped-line.h" -#include <2geom/geom.h> +#include <2geom/line.h> Inkscape::SnappedLineSegment::SnappedLineSegment(Geom::Point const &snapped_point, Geom::Coord const &snapped_distance, SnapSourceType const &source, SnapTargetType const &target, Geom::Coord const &snapped_tolerance, bool const &always_snap, Geom::Point const &start_point_of_line, Geom::Point const &end_point_of_line) : _start_point_of_line(start_point_of_line), _end_point_of_line(end_point_of_line) @@ -49,16 +49,22 @@ Inkscape::SnappedLineSegment::~SnappedLineSegment() Inkscape::SnappedPoint Inkscape::SnappedLineSegment::intersect(SnappedLineSegment const &line) const { - Geom::Point intersection_2geom(NR_HUGE, NR_HUGE); - Geom::IntersectorKind result = segment_intersect(_start_point_of_line, _end_point_of_line, - line._start_point_of_line, line._end_point_of_line, - intersection_2geom); - Geom::Point intersection(intersection_2geom); - - if (result == Geom::intersects) { - /* If a snapper has been told to "always snap", then this one should be preferred + Geom::OptCrossing inters = Geom::OptCrossing(); // empty by default + try + { + inters = Geom::intersection(getLineSegment(), line.getLineSegment()); + } + catch (Geom::InfiniteSolutions e) + { + // We're probably dealing with parallel lines, so they don't really cross + inters = Geom::OptCrossing(); + } + + if (inters) { + Geom::Point inters_pt = getLineSegment().pointAt((*inters).ta); + /* If a snapper has been told to "always snap", then this one should be preferred * over the other, if that other one has not been told so. (The preferred snapper - * will be labelled "primary" below) + * will be labeled "primary" below) */ bool const c1 = this->getAlwaysSnap() && !line.getAlwaysSnap(); //do not use _tolerance directly! /* If neither or both have been told to "always snap", then cast a vote based on @@ -70,14 +76,14 @@ Inkscape::SnappedPoint Inkscape::SnappedLineSegment::intersect(SnappedLineSegmen bool const use_this_as_primary = c1 || c2; Inkscape::SnappedLineSegment const *primarySLS = use_this_as_primary ? this : &line; Inkscape::SnappedLineSegment const *secondarySLS = use_this_as_primary ? &line : this; - Geom::Coord primaryDist = use_this_as_primary ? Geom::L2(intersection_2geom - this->getPoint()) : Geom::L2(intersection_2geom - line.getPoint()); - Geom::Coord secondaryDist = use_this_as_primary ? Geom::L2(intersection_2geom - line.getPoint()) : Geom::L2(intersection_2geom - this->getPoint()); - return SnappedPoint(intersection, SNAPSOURCE_UNDEFINED, SNAPTARGET_PATH_INTERSECTION, primaryDist, primarySLS->getTolerance(), primarySLS->getAlwaysSnap(), true, true, + Geom::Coord primaryDist = use_this_as_primary ? Geom::L2(inters_pt - this->getPoint()) : Geom::L2(inters_pt - line.getPoint()); + Geom::Coord secondaryDist = use_this_as_primary ? Geom::L2(inters_pt - line.getPoint()) : Geom::L2(inters_pt - this->getPoint()); + return SnappedPoint(inters_pt, SNAPSOURCE_UNDEFINED, SNAPTARGET_PATH_INTERSECTION, primaryDist, primarySLS->getTolerance(), primarySLS->getAlwaysSnap(), true, true, secondaryDist, secondarySLS->getTolerance(), secondarySLS->getAlwaysSnap()); } // No intersection - return SnappedPoint(intersection, SNAPSOURCE_UNDEFINED, SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false, false, NR_HUGE, 0, false); + return SnappedPoint(Geom::Point(NR_HUGE, NR_HUGE), SNAPSOURCE_UNDEFINED, SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false, false, NR_HUGE, 0, false); }; @@ -123,13 +129,20 @@ Inkscape::SnappedPoint Inkscape::SnappedLine::intersect(SnappedLine const &line) // One could be a grid line, whereas the other could be a guide line // The point of intersection should be considered for snapping, but might be outside the snapping range - Geom::Point intersection_2geom(NR_HUGE, NR_HUGE); - Geom::IntersectorKind result = Geom::line_intersection(getNormal(), getConstTerm(), - line.getNormal(), line.getConstTerm(), intersection_2geom); - Geom::Point intersection(intersection_2geom); - - if (result == Geom::intersects) { - /* If a snapper has been told to "always snap", then this one should be preferred + Geom::OptCrossing inters = Geom::OptCrossing(); // empty by default + try + { + inters = Geom::intersection(getLine(), line.getLine()); + } + catch (Geom::InfiniteSolutions e) + { + // We're probably dealing with parallel lines, so they don't really cross + inters = Geom::OptCrossing(); + } + + if (inters) { + Geom::Point inters_pt = getLine().pointAt((*inters).ta); + /* If a snapper has been told to "always snap", then this one should be preferred * over the other, if that other one has not been told so. (The preferred snapper * will be labelled "primary" below) */ @@ -142,16 +155,16 @@ Inkscape::SnappedPoint Inkscape::SnappedLine::intersect(SnappedLine const &line) bool const use_this_as_primary = c1 || c2; Inkscape::SnappedLine const *primarySL = use_this_as_primary ? this : &line; Inkscape::SnappedLine const *secondarySL = use_this_as_primary ? &line : this; - Geom::Coord primaryDist = use_this_as_primary ? Geom::L2(intersection_2geom - this->getPoint()) : Geom::L2(intersection_2geom - line.getPoint()); - Geom::Coord secondaryDist = use_this_as_primary ? Geom::L2(intersection_2geom - line.getPoint()) : Geom::L2(intersection_2geom - this->getPoint()); - return SnappedPoint(intersection, Inkscape::SNAPSOURCE_UNDEFINED, Inkscape::SNAPTARGET_UNDEFINED, primaryDist, primarySL->getTolerance(), primarySL->getAlwaysSnap(), true, true, + Geom::Coord primaryDist = use_this_as_primary ? Geom::L2(inters_pt - this->getPoint()) : Geom::L2(inters_pt - line.getPoint()); + Geom::Coord secondaryDist = use_this_as_primary ? Geom::L2(inters_pt - line.getPoint()) : Geom::L2(inters_pt - this->getPoint()); + return SnappedPoint(inters_pt, Inkscape::SNAPSOURCE_UNDEFINED, Inkscape::SNAPTARGET_UNDEFINED, primaryDist, primarySL->getTolerance(), primarySL->getAlwaysSnap(), true, true, secondaryDist, secondarySL->getTolerance(), secondarySL->getAlwaysSnap()); // The type of the snap target is yet undefined, as we cannot tell whether // we're snapping to grid or the guide lines; must be set by on a higher level } // No intersection - return SnappedPoint(intersection, SNAPSOURCE_UNDEFINED, SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false, false, NR_HUGE, 0, false); + return SnappedPoint(Geom::Point(NR_HUGE, NR_HUGE), SNAPSOURCE_UNDEFINED, SNAPTARGET_UNDEFINED, NR_HUGE, 0, false, false, false, NR_HUGE, 0, false); } // search for the closest snapped line segment diff --git a/src/snapped-line.h b/src/snapped-line.h index 85bbf1caa..3dec432e7 100644 --- a/src/snapped-line.h +++ b/src/snapped-line.h @@ -26,6 +26,7 @@ public: SnappedLineSegment(Geom::Point const &snapped_point, Geom::Coord const &snapped_distance, SnapSourceType const &source, SnapTargetType const &target, Geom::Coord const &snapped_tolerance,bool const &always_snap, Geom::Point const &start_point_of_line, Geom::Point const &end_point_of_line); ~SnappedLineSegment(); Inkscape::SnappedPoint intersect(SnappedLineSegment const &line) const; //intersect with another SnappedLineSegment + Geom::LineSegment getLineSegment() const {return Geom::LineSegment(_start_point_of_line, _end_point_of_line);} private: Geom::Point _start_point_of_line; @@ -46,6 +47,7 @@ public: Geom::Point getNormal() const {return _normal_to_line;} // n = (nx, ny) Geom::Point getPointOnLine() const {return _point_on_line;} // p = (px, py) Geom::Coord getConstTerm() const {return dot(_normal_to_line, _point_on_line);} // c = n.p = nx*px + ny*py; + Geom::Line getLine() const {return Geom::Line(_point_on_line, _point_on_line + Geom::rot90(_normal_to_line));} private: Geom::Point _normal_to_line; -- 2.30.2