Skip to content

Commit

Permalink
In Vertex editing, when doing a mousedown to choose which geometry to
Browse files Browse the repository at this point in the history
edit, the closest geometry will be selected (not just the first within
snapping range), 

AND then the closest vertex *on that geometry* will be
selected.  

This disambiguates between the same vertex shared amongst
multiple geometries.


git-svn-id: http://svn.osgeo.org/qgis/trunk@5550 c8812cc2-4d05-0410-92ff-de0c093fc19c
  • Loading branch information
morb_au committed Jun 27, 2006
1 parent c59ea1d commit 36b0a6c
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 24 deletions.
24 changes: 24 additions & 0 deletions src/core/qgsgeometry.cpp
Expand Up @@ -1316,6 +1316,30 @@ bool QgsGeometry::vertexAt(double &x, double &y,
}


double QgsGeometry::sqrDistToVertexAt(QgsPoint& point,
QgsGeometryVertexIndex& atVertex) const
{
double x;
double y;

if (vertexAt(x, y, atVertex))
{
#ifdef QGISDEBUG
std::cout << "QgsGeometry::sqrDistToVertexAt: Exiting with distance to " << x << " " << y << "." << std::endl;
#endif
return point.sqrDist(x, y);
}
else
{
#ifdef QGISDEBUG
std::cout << "QgsGeometry::sqrDistToVertexAt: Exiting with std::numeric_limits<double>::max()." << std::endl;
#endif
// probably safest to bail out with a very large number
return std::numeric_limits<double>::max();
}
}


QgsPoint QgsGeometry::closestVertexWithContext(QgsPoint& point,
QgsGeometryVertexIndex& atVertex,
double& sqrDist)
Expand Down
9 changes: 9 additions & 0 deletions src/core/qgsgeometry.h
Expand Up @@ -133,6 +133,15 @@ class QgsGeometry {
*/
bool vertexAt(double &x, double &y, QgsGeometryVertexIndex atVertex) const;

/**
Returns the squared cartesian distance between the given point
to the given vertex index (vertex at the given position number,
ring and item (first number is index 0))
*/
double sqrDistToVertexAt(QgsPoint& point,
QgsGeometryVertexIndex& atVertex) const;

/**
Returns, in atVertex, the closest vertex in this geometry to the given point.
The squared cartesian distance is also returned in sqrDist.
Expand Down
94 changes: 79 additions & 15 deletions src/gui/qgsmaptoolvertexedit.cpp
Expand Up @@ -101,8 +101,9 @@ void QgsMapToolVertexEdit::canvasPressEvent(QMouseEvent * e)
//Find nearest segment of the selected line, move that node to the mouse location
if (!snapSegmentWithContext(point))
{
QMessageBox::warning(0, "Error", "Could not snap vertex. Have you set the tolerance?",
QMessageBox::Ok, Qt::NoButton);
QMessageBox::warning(0, "Error",
QObject::tr("Could not snap segment. Have you set the tolerance in Settings > Project Properties > General?"),
QMessageBox::Ok, Qt::NoButton);
return;
}

Expand Down Expand Up @@ -130,15 +131,32 @@ void QgsMapToolVertexEdit::canvasPressEvent(QMouseEvent * e)
#endif

// Find the closest line segment to the mouse position
// Then set up the rubber band to its endpoints
// Then find the closest vertex on that line segment
// Then set up the rubber band to its adjoining vertexes

//Find nearest segment of the selected line, move that node to the mouse location
if (!snapVertexWithContext(point))
{
QMessageBox::warning(0, "Error", "Could not snap vertex. Have you set the tolerance?",
QMessageBox::Ok, Qt::NoButton);
return;
}
QgsPoint snapPoint;

snapPoint = point;
if (!snapSegmentWithContext(snapPoint))
{
QMessageBox::warning(0, "Error",
QObject::tr("Could not snap segment. Have you set the tolerance in Settings > Project Properties > General?"),
QMessageBox::Ok, Qt::NoButton);
return;
}

snapPoint = point;
if (!snapVertexOfSnappedSegment(snapPoint))
{
QMessageBox::warning(0, "Error",
QObject::tr("Could not snap vertex. Have you set the tolerance in Settings > Project Properties > General?"),
QMessageBox::Ok, Qt::NoButton);
return;
}

#ifdef QGISDEBUG
qWarning("Creating rubber band for moveVertex");
#endif

index = mSnappedAtVertex;
createRubberBand();
Expand Down Expand Up @@ -178,8 +196,9 @@ void QgsMapToolVertexEdit::canvasPressEvent(QMouseEvent * e)
// TODO: Find nearest segment of the selected line, move that node to the mouse location
if (!snapVertexWithContext(point))
{
QMessageBox::warning(0, "Error", "Could not snap vertex. Have you set the tolerance?",
QMessageBox::Ok, Qt::NoButton);
QMessageBox::warning(0, "Error",
QObject::tr("Could not snap vertex. Have you set the tolerance in Settings > Project Properties > General?"),
QMessageBox::Ok, Qt::NoButton);
return;
}

Expand Down Expand Up @@ -216,14 +235,15 @@ bool QgsMapToolVertexEdit::snapSegmentWithContext(QgsPoint& point)
if (!vlayer->snapSegmentWithContext(point, beforeVertex, atFeatureId, atGeometry, tolerance()))
{
mSnappedAtFeatureId = -1;
QMessageBox::warning(0, "Error", "Could not snap segment. Have you set the tolerance?",
QMessageBox::Ok, Qt::NoButton);
QMessageBox::warning(0, "Error",
QObject::tr("Could not snap segment. Have you set the tolerance in Settings > Project Properties > General?"),
QMessageBox::Ok, Qt::NoButton);
return FALSE;
}
else
{
#ifdef QGISDEBUG
std::cout << "QgsMapToolVertexEdit: Snapped to segment fid " << atFeatureId << "." << std::endl;
std::cout << "QgsMapToolVertexEdit::snapSegmentWithContext: Snapped to segment fid " << atFeatureId << "." << std::endl;
#endif

// Save where we snapped to
Expand Down Expand Up @@ -266,6 +286,50 @@ bool QgsMapToolVertexEdit::snapVertexWithContext(QgsPoint& point)
}
}

bool QgsMapToolVertexEdit::snapVertexOfSnappedSegment(QgsPoint& point)
{
double twoBeforeVertexSqrDist;
double beforeVertexSqrDist;

// Set up the "other side" of the snapped-to segment
QgsGeometryVertexIndex snappedTwoBeforeVertex(mSnappedBeforeVertex);
snappedTwoBeforeVertex.decrement_back();

#ifdef QGISDEBUG
std::cout << "QgsMapToolVertexEdit::snapVertexOfSnappedSegment: Choice of "
<< snappedTwoBeforeVertex.toString().toLocal8Bit().data() << " or "
<< mSnappedBeforeVertex.toString().toLocal8Bit().data() << "." << std::endl;
#endif


twoBeforeVertexSqrDist = mSnappedAtGeometry.sqrDistToVertexAt(point, snappedTwoBeforeVertex);
beforeVertexSqrDist = mSnappedAtGeometry.sqrDistToVertexAt(point, mSnappedBeforeVertex);

#ifdef QGISDEBUG
std::cout << "QgsMapToolVertexEdit::snapVertexOfSnappedSegment: Choice of "
<< twoBeforeVertexSqrDist << " or "
<< beforeVertexSqrDist << "." << std::endl;
#endif


// See which of the two verticies is closer (i.e. smaller squared distance)
if (twoBeforeVertexSqrDist < beforeVertexSqrDist)
{
mSnappedAtVertex = snappedTwoBeforeVertex;
}
else
{
mSnappedAtVertex = mSnappedBeforeVertex;
}

#ifdef QGISDEBUG
std::cout << "QgsMapToolVertexEdit::snapVertexOfSnappedSegment: Chose "
<< mSnappedAtVertex.toString().toLocal8Bit().data() << "." << std::endl;
#endif

return TRUE;
}

bool QgsMapToolVertexEdit::snapVertex(QgsPoint& point, int exclFeatureId, int exclVertexNr)
{
QgsVectorLayer* vlayer = dynamic_cast<QgsVectorLayer*>(mCanvas->currentLayer());
Expand Down
19 changes: 17 additions & 2 deletions src/gui/qgsmaptoolvertexedit.h
Expand Up @@ -69,12 +69,27 @@ class QgsMapToolVertexEdit : public QgsMapTool
/**Searches the closest point within the project tolerance and setx mSnappedAtFeatureId and mSnappedAtVertex*/
bool snapVertexWithContext(QgsPoint& point);

/** Searches the closest vertex of "geometry" to the given "point"
This is useful when selecting a vertex to move, as the selection process is a two step process:
1. Select the closest line segment to the mouse pointer.
- snapSegmentWithContext()
2. Select the closest vertex on (1).
- snapVertexOfSnappedSegement()
Step 1 is needed to disambiguate between two geometries sharing the same vertex.
*/
bool snapVertexOfSnappedSegment(QgsPoint& point);

/**Snaps a point (without setting mSnappedAtFeatureId and mSnappedAtVertex). Does not snap to the specified vertex,
because during dragging, a vertex should not be snapped to itself*/
bool snapVertex(QgsPoint& point, int exclFeatureId, int exclVertexNr);



bool snapSegmentWithContext(QgsPoint& point);



//! The snapped-to segment before this vertex number (identifying the vertex that is being moved)
QgsGeometryVertexIndex mSnappedAtVertex;

Expand Down
7 changes: 2 additions & 5 deletions src/gui/qgsvectorlayer.cpp
Expand Up @@ -2990,8 +2990,6 @@ QgsGeometry& snappedGeometry, double tolerance)
snappedFeatureId = feature->featureId();
snappedGeometry = *(feature->geometry());
segmentFound = true;
delete feature;
return true;
}
delete feature;
}
Expand All @@ -3018,7 +3016,6 @@ QgsGeometry& snappedGeometry, double tolerance)
snappedFeatureId = (*iter)->featureId();
snappedGeometry = *((*iter)->geometry());
segmentFound = true;
return true;
}
}

Expand All @@ -3034,10 +3031,10 @@ QgsGeometry& snappedGeometry, double tolerance)
snappedFeatureId = it->first;
snappedGeometry = it->second;
segmentFound = true;
return true;
}
}
return false;

return segmentFound;
}


Expand Down
5 changes: 3 additions & 2 deletions src/gui/qgsvectorlayer.h
Expand Up @@ -380,7 +380,8 @@ public slots:
If there is no point within this tolerance, point is left unchanged.
@param tolerance The snapping tolerance
@return true if the position of point has been changed, and false otherwise */
bool snapPoint(QgsPoint& point, double tolerance);
bool snapPoint(QgsPoint& point,
double tolerance);

/**Snaps a point to the closest vertex if there is one within the snapping tolerance
@param atVertex Set to a vertex index of the snapped-to vertex
Expand All @@ -401,7 +402,7 @@ public slots:
QgsGeometry& snappedGeometry,
double tolerance);

/**Snaps a point to the closest line segment if there is one within the snapping tolerance (mSnappingTolerance)
/**Snaps a point to the closest line segment if there is one within the snapping tolerance ("tolerance")
@param beforeVertex Set to a value where the snapped-to segment is before this vertex index
@param snappedFeatureId Set to the feature ID that where the snapped-to segment belongs to.
@param snappedGeometry Set to the geometry that the snapped-to segment belongs to.
Expand Down

0 comments on commit 36b0a6c

Please sign in to comment.