summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 6fa6358)
raw | patch | inline | side by side (parent: 6fa6358)
author | dvlierop2 <dvlierop2@users.sourceforge.net> | |
Sat, 8 Dec 2007 21:18:49 +0000 (21:18 +0000) | ||
committer | dvlierop2 <dvlierop2@users.sourceforge.net> | |
Sat, 8 Dec 2007 21:18:49 +0000 (21:18 +0000) |
index a74151523a55202f3cd3e60050f007706d18fe2c..e16e1fdf2db7fd11ea7f047602508eec664a5fa7 100644 (file)
#include "sp-canvas-util.h"
#include "canvas-axonomgrid.h"
#include "util/mathfns.h"
+#include "2geom/geom.h"
#include "display-forward.h"
#include <libnr/nr-pixops.h>
-
#include "canvas-grid.h"
#include "desktop-handles.h"
#include "helper/units.h"
}
/* This is to make sure we snap to only visible grid lines */
- double scaled_spacing = grid->spacing_ylines; // this is spacing of visible lines if screen pixels
+ double scaled_spacing_h = grid->spacing_ylines; // this is spacing of visible lines if screen pixels
+ double scaled_spacing_v = grid->lyw; // vertical
// convert screen pixels to px
// FIXME: after we switch to snapping dist in screen pixels, this will be unnecessary
if (SP_ACTIVE_DESKTOP) {
- scaled_spacing /= SP_ACTIVE_DESKTOP->current_zoom();
- }
-
- NR::Coord rounded;
- rounded = Inkscape::Util::round_to_nearest_multiple_plus(p[0], scaled_spacing, grid->origin[0]);
- s.push_back(std::make_pair(NR::Dim2(0), rounded));
- rounded = Inkscape::Util::round_to_lower_multiple_plus(p[0], scaled_spacing, grid->origin[0]);
- s.push_back(std::make_pair(NR::Dim2(0), rounded));
-
+ scaled_spacing_h /= SP_ACTIVE_DESKTOP->current_zoom();
+ scaled_spacing_v /= SP_ACTIVE_DESKTOP->current_zoom();
+ }
+
+ // In an axonometric grid, any point will be surrounded by 6 grid lines:
+ // - 2 vertical grid lines, one left and one right from the point
+ // - 2 angled z grid lines, one above and one below the point
+ // - 2 angled x grid lines, one above and one below the point
+
+ // Calculate the x coordinate of the vertical grid lines
+ NR::Coord x_max = Inkscape::Util::round_to_upper_multiple_plus(p[NR::X], scaled_spacing_h, grid->origin[NR::X]);
+ NR::Coord x_min = Inkscape::Util::round_to_lower_multiple_plus(p[NR::X], scaled_spacing_h, grid->origin[NR::X]);
+
+ // Calculate the y coordinate of the intersection of the angled grid lines with the y-axis
+ double y_proj_along_z = p[NR::Y] - grid->tan_angle[Z]*(p[NR::X] - grid->origin[NR::X]);
+ double y_proj_along_x = p[NR::Y] + grid->tan_angle[X]*(p[NR::X] - grid->origin[NR::X]);
+ double y_proj_along_z_max = Inkscape::Util::round_to_upper_multiple_plus(y_proj_along_z, scaled_spacing_v, grid->origin[NR::Y]);
+ double y_proj_along_z_min = Inkscape::Util::round_to_lower_multiple_plus(y_proj_along_z, scaled_spacing_v, grid->origin[NR::Y]);
+ double y_proj_along_x_max = Inkscape::Util::round_to_upper_multiple_plus(y_proj_along_x, scaled_spacing_v, grid->origin[NR::Y]);
+ double y_proj_along_x_min = Inkscape::Util::round_to_lower_multiple_plus(y_proj_along_x, scaled_spacing_v, grid->origin[NR::Y]);
+
+ // Calculate the normal for the angled grid lines
+ NR::Point norm_x = NR::rot90(NR::Point(1, -grid->tan_angle[X]));
+ NR::Point norm_z = NR::rot90(NR::Point(1, grid->tan_angle[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
+ // 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 = line_intersection(norm_x.to_2geom(), norm_x[NR::Y]*y_proj_along_x_max,
+ norm_z.to_2geom(), norm_z[NR::Y]*y_proj_along_z_max,
+ result);
+
+ // Determine which half of the parallellogram to use
+ bool use_left_half = true;
+ bool use_right_half = true;
+
+ if (is == Geom::intersects) {
+ use_left_half = (p[NR::X] - grid->origin[NR::X]) < result[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) {
+ s.push_back(std::make_pair(norm_z, NR::Point(grid->origin[NR::X], y_proj_along_z_max)));
+ s.push_back(std::make_pair(norm_x, NR::Point(grid->origin[NR::X], y_proj_along_x_min)));
+ s.push_back(std::make_pair(component_vectors[NR::X], NR::Point(x_max, 0)));
+ }
+
+ if (use_right_half) {
+ s.push_back(std::make_pair(norm_z, NR::Point(grid->origin[NR::X], y_proj_along_z_min)));
+ s.push_back(std::make_pair(norm_x, NR::Point(grid->origin[NR::X], y_proj_along_x_max)));
+ s.push_back(std::make_pair(component_vectors[NR::X], NR::Point(x_min, 0)));
+ }
+
return s;
}
index db4648ec08032fc7a1340bef2d609e903bb0b278..183b299d17a1b7314126ea926138a81f2d1c655a 100644 (file)
}
NR::Coord rounded;
+ NR::Point point_on_line;
+
rounded = Inkscape::Util::round_to_upper_multiple_plus(p[i], scaled_spacing, grid->origin[i]);
- s.push_back(std::make_pair(NR::Dim2(i), rounded));
+ point_on_line = i ? NR::Point(0, rounded) : NR::Point(rounded, 0);
+ s.push_back(std::make_pair(component_vectors[i], point_on_line));
+
rounded = Inkscape::Util::round_to_lower_multiple_plus(p[i], scaled_spacing, grid->origin[i]);
- s.push_back(std::make_pair(NR::Dim2(i), rounded));
+ point_on_line = i ? NR::Point(0, rounded) : NR::Point(rounded, 0);
+ s.push_back(std::make_pair(component_vectors[i], point_on_line));
}
return s;
diff --git a/src/guide-snapper.cpp b/src/guide-snapper.cpp
index a1df5f1cd339aa906888050d793cbbb4e2483c0a..0d7dffd0071472758f35f42a36bfb2862f723696 100644 (file)
--- a/src/guide-snapper.cpp
+++ b/src/guide-snapper.cpp
for (GSList const *l = _named_view->guides; l != NULL; l = l->next) {
SPGuide const *g = SP_GUIDE(l->data);
-
- /* We assume here that guides are horizontal or vertical */
- if (g->normal == component_vectors[NR::X]) {
- s.push_back(std::make_pair(NR::X, g->position));
- } else {
- s.push_back(std::make_pair(NR::Y, g->position));
- }
+ NR::Point point_on_line = (g->normal == component_vectors[NR::X]) ? NR::Point(g->position, 0) : NR::Point(0, g->position);
+ s.push_back(std::make_pair(g->normal, point_on_line));
}
return s;
diff --git a/src/line-snapper.cpp b/src/line-snapper.cpp
index be35ec2db930b1faaf717ecad13bb2f7d379853e..446ec73e73deab0c57eafa6545f2b9533597f350 100644 (file)
--- a/src/line-snapper.cpp
+++ b/src/line-snapper.cpp
+/**
+ * \file line-snapper.cpp
+ * \brief LineSnapper class.
+ *
+ * Authors:
+ * Diederik van Lierop <mail@diedenrezi.nl>
+ * And others...
+ *
+ * Copyright (C) 1999-2007 Authors
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
#include "libnr/nr-values.h"
#include "libnr/nr-point-fns.h"
#include <2geom/geom.h>
#include "line-snapper.h"
#include "snapped-line.cpp"
+#include <gtk/gtk.h>
Inkscape::LineSnapper::LineSnapper(SPNamedView const *nv, NR::Coord const d) : Snapper(nv, d)
{
Inkscape::Snapper::PointType const &t,
NR::Point const &p,
bool const &f,
- std::vector<NR::Point> &points_to_snap,
+ std::vector<NR::Point> &points_to_snap,
std::list<SPItem const *> const &it) const
{
- /* Snap along x (i.e. to vertical lines) */
- _doConstrainedSnap(sc, t, p, f, points_to_snap, component_vectors[NR::X], it);
- /* Snap along y (i.e. to horizontal lines) */
- _doConstrainedSnap(sc, t, p, f, points_to_snap, component_vectors[NR::Y], it);
+ Inkscape::SnappedPoint s = SnappedPoint(p, NR_HUGE);
+ /* Get the lines that we will try to snap to */
+ const LineList lines = _getSnapLines(p);
+
+ // std::cout << "snap point " << p << " to: " << std::endl;
+
+ for (LineList::const_iterator i = lines.begin(); i != lines.end(); i++) {
+ NR::Point const p1 = i->second; // point at guide/grid line
+ NR::Point const p2 = p1 + NR::rot90(i->first); // 2nd point at guide/grid line
+
+ // std::cout << " line through " << i->second << " with normal " << i->first;
+
+ g_assert(i->first != NR::Point(0,0)); // otherwise we'll have div. by zero because NR::L2(d2) = 0
+
+ // p_proj = projection of p on the grid/guide line running from p1 to p2
+ // p_proj = p1 + u (p2 - p1)
+ // calculate u according to "Minimum Distance between a Point and a Line"
+ // see http://local.wasp.uwa.edu.au/~pbourke/geometry/pointline/
+ NR::Point const d1(p-p1); // delta 1
+ NR::Point const d2(p2-p1); // delta 1
+ double const u = (d1[NR::X] * d2[NR::X] + d1[NR::Y] * d2[NR::Y]) / (NR::L2(d2) * NR::L2(d2));
+
+ NR::Point const p_proj(p1 + u*(p2-p1));
+ NR::Coord const dist = NR::L2(p_proj - p);
+ //Store any line that's within snapping range
+ if (dist < getDistance()) {
+ _addSnappedLine(sc, p_proj, dist, i->first, i->second);
+ // std::cout << " -> distance = " << dist;
+ }
+ // std::cout << std::endl;
+ }
}
void Inkscape::LineSnapper::_doConstrainedSnap(SnappedConstraints &sc,
NR::Point const point_on_line = c.hasPoint() ? c.getPoint() : p;
/* Constant term of the line we're trying to snap along */
- NR::Coord const q = dot(n, point_on_line);
+ NR::Coord const q0 = dot(n, point_on_line);
+ /* Constant term of the grid or guide line */
+ NR::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.to_2geom(), q, component_vectors[i->first].to_2geom(), i->second, t_2geom);
+ Geom::IntersectorKind const k = Geom::line_intersection(n.to_2geom(), q0, i->first.to_2geom(), q1, t_2geom);
NR::Point t(t_2geom);
if (k == Geom::intersects) {
//Store any line that's within snapping range
if (dist < getDistance()) {
_addSnappedLine(sc, t, dist, c.getDirection(), t);
- //SnappedLine dummy = SnappedLine(t, dist, c.getDirection(), t);
- //sc.infinite_lines.push_back(dummy);
}
}
}
diff --git a/src/line-snapper.h b/src/line-snapper.h
index 8c307da53be9fdd7ba77dc1387fdaa9967cf0963..6a1ff9016b105d140cb9d62af7213bc5d29fcb27 100644 (file)
--- a/src/line-snapper.h
+++ b/src/line-snapper.h
LineSnapper(SPNamedView const *nv, NR::Coord const d);
protected:
- typedef std::list<std::pair<NR::Dim2, NR::Coord> > LineList;
+ typedef std::list<std::pair<NR::Point, NR::Point> > LineList;
+ //first point is a vector normal to the line
+ //second point is a point on the line
private:
void _doFreeSnap(SnappedConstraints &sc,
- Inkscape::Snapper::PointType const &t,
- NR::Point const &p,
- bool const &first_point,
- std::vector<NR::Point> &points_to_snap,
- std::list<SPItem const *> const &it) const;
+ Inkscape::Snapper::PointType const &t,
+ NR::Point const &p,
+ bool const &first_point,
+ std::vector<NR::Point> &points_to_snap,
+ std::list<SPItem const *> const &it) const;
void _doConstrainedSnap(SnappedConstraints &sc,
- Inkscape::Snapper::PointType const &t,
- NR::Point const &p,
- bool const &first_point,
- std::vector<NR::Point> &points_to_snap,
- ConstraintLine const &c,
- std::list<SPItem const *> const &it) const;
+ Inkscape::Snapper::PointType const &t,
+ NR::Point const &p,
+ bool const &first_point,
+ std::vector<NR::Point> &points_to_snap,
+ ConstraintLine const &c,
+ std::list<SPItem const *> const &it) const;
/**
* \param p Point that we are trying to snap.
diff --git a/src/sp-namedview.cpp b/src/sp-namedview.cpp
index a9c6bbfd6d449b905a4ccc7caab97c86b90dae56..86da7a93a40f5634bc83fceca8d909ca99ec56ec 100644 (file)
--- a/src/sp-namedview.cpp
+++ b/src/sp-namedview.cpp
@@ -159,7 +159,7 @@ static void sp_namedview_build(SPObject *object, SPDocument *document, Inkscape:
sp_object_read_attr(object, "inkscape:snap-guide");
sp_object_read_attr(object, "inkscape:snap-center");
sp_object_read_attr(object, "inkscape:snap-intersection-grid-guide");
- sp_object_read_attr(object, "inkscape:snap-snap-intersection-line-segments");
+ sp_object_read_attr(object, "inkscape:snap-intersection-line-segments");
sp_object_read_attr(object, "inkscape:object-paths");
sp_object_read_attr(object, "inkscape:object-nodes");
sp_object_read_attr(object, "inkscape:bbox-paths");
@@ -374,7 +374,7 @@ static void sp_namedview_set(SPObject *object, unsigned int key, const gchar *va
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
break;
case SP_ATTR_INKSCAPE_SNAP_INTERS_GRIDGUIDE:
- nv->snap_manager.setSnapIntersectionGG(value ? sp_str_to_bool(value) : FALSE);
+ nv->snap_manager.setSnapIntersectionGG(value ? sp_str_to_bool(value) : TRUE);
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
break;
case SP_ATTR_INKSCAPE_SNAP_INTERS_LINESEGM: