Skip to content
Permalink
Browse files
Merge of advanced editing branch is now done
git-svn-id: http://svn.osgeo.org/qgis/trunk@7886 c8812cc2-4d05-0410-92ff-de0c093fc19c
  • Loading branch information
mhugent committed Jan 9, 2008
1 parent 026a061 commit 61ecb55810f5062336687527298a8df83b6823d0
@@ -301,7 +301,7 @@ class QgsGeometry
/**
Returns the squared cartesian distance between the given point
to the given vertex index*/
//double sqrDistToVertexAt(QgsPoint& point /In, int atVertex);
double sqrDistToVertexAt(QgsPoint& point /In, int atVertex);


/**
@@ -321,6 +321,35 @@ class QgsGeometry
*/
double closestSegmentWithContext(const QgsPoint& point, QgsPoint& minDistPoint /Out/, int& beforeVertex /Out/);

/**Adds a new ring to this geometry. This makes only sense for polygon and multipolygons.
@return 0 in case of success (ring added), 1 problem with geometry type, 2 ring not closed, \
3 ring is not valid geometry, 4 ring not disjoint with existing rings, 5 no polygon found which contained the ring*/
int addRing(const QList<QgsPoint>& ring);

/**Adds a new island polygon to a multipolygon feature
@return 0 in case of success, 1 if not a multipolygon, 2 if ring is not a valid geometry, 3 if new polygon ring \
not disjoint with existing polygons of the feature*/
int addIsland(const QList<QgsPoint>& ring);

/**Translate this geometry by dx, dy
@return 0 in case of success*/
int translate(double dx, double dy);

/**Splits this geometry according to a given line. Note that the geometry is only splitted once. If there are several intersections
between geometry and splitLine, only the first one is considered.
@param splitLine the line that splits the geometry
@param newGeometrys OUT: list of new geometries that have been created with the split
@return 0 in case of success, which means the geometry has been split in two parts, \
1 if line intersects multiple times but only one split could be done, \
2 if intersection too complicated to proceed (several polygon intersections), \ \
else other error*/
int splitGeometry(const QList<QgsPoint>& splitLine, QList<QgsGeometry*>& newGeometries);

/**Changes this geometry such that it does not intersect the other geometry
@param other geometry that should not be intersect
@return 0 in case of success*/
int difference(QgsGeometry* other);

/**Returns the bounding box of this feature*/
QgsRect boundingBox();

@@ -130,6 +130,14 @@ public:
*/
virtual QString subsetString();

/**Returns the features contained in the rectangle. Considers the changed, added, deleted and permanent features
@return 0 in case of success*/
int featuresInRectangle(const QgsRect& searchRect, QList<QgsFeature>& features, bool fetchGeometries = true, bool fetchAttributes = true);

/**Gets the feature at the given feature id. Considers the changed, added, deleted and permanent features
@return 0 in case of success*/
int getFeatureAtId(int featureId, QgsFeature& f, bool fetchGeometries = true, bool fetchAttributes = true);

/** Adds a feature
@param lastFeatureInBatch If True, will also go to the effort of e.g. updating the extents.
@return Irue in case of success and False in case of error
@@ -170,6 +178,47 @@ existing rings, 5 no feature found where ring can be inserted*/
6 if selected geometry not found*/
int addIsland(const QList<QgsPoint>& ring);

/**Translates feature by dx, dy
@param featureId id of the feature to translate
@param dx translation of x-coordinate
@param dy translation of y-coordinate
@return 0 in case of success*/
int translateFeature(int featureId, double dx, double dy);

/**Splits features cut by the given line
@param splitLine line that splits the layer features
@param topologicalEditing true if topological editing is enabled
@return 0 in case of success, 1 if several intersections but only 1 split done, \
2 if intersection too complex to be handled, else other error*/
int splitFeatures(const QList<QgsPoint>& splitLine, bool topologicalEditing = false);

/**Changes the specified geometry such that it has no intersections with other \
polygon (or multipolygon) geometries in this vector layer
@param geom geometry to modify
@return 0 in case of success*/
int removePolygonIntersections(QgsGeometry* geom);

/**Adds topological points for every vertex of the
geometry
@param geom the geometry where each vertex is added to segments of other features
Note: geom is not going to be modified by the function
@return 0 in case of success*/
int addTopologicalPoints(QgsGeometry* geom);

/**Adds a vertex to segments which intersect point p but don't
already have a vertex there. If a feature already has a vertex at position p,
no additional vertex is inserted. This method is usefull for topological
editing.
@param p position of the vertex
@return 0 in case of success*/
int addTopologicalPoints(const QgsPoint& p);

/**Inserts vertices to the snapped segments.
This is usefull for topological editing if snap to segment is enabled.
@param snapResults results collected from the snapping operation
@return 0 in case of success*/
int insertSegmentVerticesForSnap(const QList<QgsSnappingResult>& snapResults);

/** Set labels on */
void setLabelOn( bool on );

@@ -187,7 +236,7 @@ existing rings, 5 no feature found where ring can be inserted*/
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 /In, Out/, double tolerance);
bool snapPoint(QgsPoint& point, double tolerance);

/**Snaps to segment or vertex within given tolerance
@param startPoint point to snap (in layer coordinates)
@@ -196,8 +245,8 @@ existing rings, 5 no feature found where ring can be inserted*/
@param snap_to to segment / to vertex
@return 0 in case of success
*/
//int snapWithContext(const QgsPoint& startPoint, double snappingTolerance, QMultiMap<double, QgsSnappingResult>& snappingResults, \
// QgsSnapper::SNAP_TO snap_to);
int snapWithContext(const QgsPoint& startPoint, double snappingTolerance, QMultiMap<double, QgsSnappingResult>& snappingResults, \
QgsSnapper::SNAP_TO snap_to);

/**
Commits edited attributes. Depending on the feature id,
@@ -15,12 +15,25 @@ class QgsRubberBand: QgsMapCanvasItem
void reset(bool isPolygon = false);

void addPoint(const QgsPoint & p, int geometryIndex);

//!Removes the last point. Most usefull in connection with undo operations
void removeLastPoint(int geometryIndex = 0);

void movePoint(const QgsPoint & p, int geometryIndex);
void movePoint(int index, const QgsPoint& p, int geometryIndex);

int size() const;
const QList<QgsPoint>& getPoints() const;
const QgsPoint& getPoint(int index) const;
/**Sets this rubber band to the geometry of an existing feature.
This is usefull for feature highlighting.
@param geom the geometry object
@param layer the layer containing the feature (used for coord transformation)
@param render the maprender object (used for coord transformation)*/
void setToGeometry(QgsGeometry* geom, QgsVectorLayer& layer);

/**Adds translation to original coordinates (all in map coordinates)*/
void setTranslationOffset(double dx, double dy);

/**Returns count of vertices in all lists of mPoint*/
int numberOfVertices() const;

protected:
virtual void paint(QPainter* p);
@@ -428,13 +428,15 @@ void QgsMapToolAddFeature::canvasReleaseEvent(QMouseEvent * e)

if (QgsAttributeDialog::queryAttributes(fields, *f))
{
//add points to other features to keep topology up-to-date
int topologicalEditing = QgsProject::instance()->readNumEntry("Digitizing", "/TopologicalEditing", 0);
if(topologicalEditing)
if(vlayer->addFeature(*f))
{
addTopologicalPoints(mCaptureList);
//add points to other features to keep topology up-to-date
int topologicalEditing = QgsProject::instance()->readNumEntry("Digitizing", "/TopologicalEditing", 0);
if(topologicalEditing)
{
addTopologicalPoints(mCaptureList);
}
}
vlayer->addFeature(*f);
}
delete f;

@@ -79,13 +79,6 @@ void QgsMapToolAddIsland::canvasReleaseEvent(QMouseEvent * e)

//close polygon
mCaptureList.push_back(*mCaptureList.begin());

//add points to other features to keep topology up-to-date
int topologicalEditing = QgsProject::instance()->readNumEntry("Digitizing", "/TopologicalEditing", 0);
if(topologicalEditing)
{
addTopologicalPoints(mCaptureList);
}

int errorCode = vlayer->addIsland(mCaptureList);
QString errorMessage;
@@ -118,6 +111,15 @@ void QgsMapToolAddIsland::canvasReleaseEvent(QMouseEvent * e)
}
QMessageBox::critical(0, QObject::tr("Error, could not add island"), errorMessage);
}
else
{
//add points to other features to keep topology up-to-date
int topologicalEditing = QgsProject::instance()->readNumEntry("Digitizing", "/TopologicalEditing", 0);
if(topologicalEditing)
{
addTopologicalPoints(mCaptureList);
}
}

mCaptureList.clear();
mCanvas->refresh();
@@ -17,6 +17,7 @@

#include "qgsmaptooladdvertex.h"
#include "qgsmapcanvas.h"
#include "qgsproject.h"
#include "qgsrubberband.h"
#include "qgsvectorlayer.h"

@@ -54,6 +55,8 @@ void QgsMapToolAddVertex::canvasPressEvent(QMouseEvent * e)
//error
}



if(mRecentSnappingResults.size() > 0)
{
mRubberBand = createRubberBand();
@@ -63,6 +66,10 @@ void QgsMapToolAddVertex::canvasPressEvent(QMouseEvent * e)
mRubberBand->addPoint(firstResult.snappedVertex, false);
mRubberBand->addPoint(firstResult.afterVertex, true);
}
else
{
displaySnapToleranceWarning();
}
}

void QgsMapToolAddVertex::canvasReleaseEvent(QMouseEvent * e)
@@ -85,7 +92,12 @@ void QgsMapToolAddVertex::canvasReleaseEvent(QMouseEvent * e)
{
snappedPointMapCoord = snapPointFromResults(snapResults, e->pos());
snappedPointLayerCoord = toLayerCoords(vlayer, snappedPointMapCoord);
insertSegmentVerticesForSnap(snapResults, vlayer);

int topologicalEditing = QgsProject::instance()->readNumEntry("Digitizing", "/TopologicalEditing", 0);
if(topologicalEditing)
{
insertSegmentVerticesForSnap(snapResults, vlayer);
}

//and change the feature points
QList<QgsSnappingResult>::iterator sr_it = mRecentSnappingResults.begin();
@@ -79,7 +79,7 @@ class QgsMapToolCapture : public QgsMapToolEdit
/** rubber band for polylines and polygons */
QgsRubberBand* mRubberBand;

/** List to store the points of digitised lines and polygons */
/** List to store the points of digitised lines and polygons (in layer coordinates)*/
QList<QgsPoint> mCaptureList;

/**Adds a point to the rubber band (in map coordinates) and to the capture list (in layer coordinates)
@@ -56,6 +56,10 @@ void QgsMapToolDeleteVertex::canvasPressEvent(QMouseEvent * e)
mCross->setIconType(QgsVertexMarker::ICON_X);
mCross->setCenter(markerPoint);
}
else
{
displaySnapToleranceWarning();
}
}

void QgsMapToolDeleteVertex::canvasReleaseEvent(QMouseEvent * e)
@@ -43,32 +43,16 @@ int QgsMapToolEdit::insertSegmentVerticesForSnap(const QList<QgsSnappingResult>&
return 1;
}

//can only add segment vertices for other features if topological editing is enabled
//topological editing on?
int topologicalEditing = QgsProject::instance()->readNumEntry("Digitizing", "/TopologicalEditing", 0);
if(topologicalEditing == 0)
//transform snaping coordinates to layer crs first
QList<QgsSnappingResult> transformedSnapResults = snapResults;
QList<QgsSnappingResult>::iterator it = transformedSnapResults.begin();
for(; it != transformedSnapResults.constEnd(); ++it)
{
return 2;
QgsPoint layerPoint = toLayerCoords(editedLayer, it->snappedVertex);
it->snappedVertex = layerPoint;
}

QList<QgsSnappingResult>::const_iterator it = snapResults.constBegin();
for(; it != snapResults.constEnd(); ++it)
{
//snap to edited layer?
if(it->layer == editedLayer)
{
if(it->snappedVertexNr == -1) //segment snap
{
layerPoint = toLayerCoords(editedLayer, it->snappedVertex);
if(!editedLayer->insertVertexBefore(layerPoint.x(), layerPoint.y(), it->snappedAtGeometry, it->afterVertexNr))
{
returnval = 3;
}
}
}
}

return returnval;
return editedLayer->insertSegmentVerticesForSnap(transformedSnapResults);
}

QgsPoint QgsMapToolEdit::snapPointFromResults(const QList<QgsSnappingResult>& snapResults, const QPoint& screenCoords)
@@ -131,42 +115,9 @@ int QgsMapToolEdit::addTopologicalPoints(const QList<QgsPoint>& geom)
QList<QgsPoint>::const_iterator list_it = geom.constBegin();
for(; list_it != geom.constEnd(); ++list_it)
{
addTopologicalPoints(*list_it, vlayer);
vlayer->addTopologicalPoints(*list_it);
}

return 0;
}

int QgsMapToolEdit::addTopologicalPoints(const QgsPoint& p, QgsVectorLayer* vl)
{
if(!vl)
{
return 1;
}

QMultiMap<double, QgsSnappingResult> snapResults; //results from the snapper object
QList<QgsSnappingResult> filteredSnapResults; //we filter out the results that are on existing vertices

const double threshold = 0.00000001;

if(vl->snapWithContext(p, threshold, snapResults, QgsSnapper::SNAP_TO_SEGMENT) != 0)
{
return 2;
}

QMultiMap<double, QgsSnappingResult>::const_iterator snap_it = snapResults.constBegin();

for(; snap_it != snapResults.constEnd(); ++snap_it)
{
//check if there is already an existing vertex at the position of p
QgsPoint vertexPoint(p);
if(vl->snapPoint(vertexPoint, threshold))
{
continue;
}

filteredSnapResults.push_back(*snap_it);
}
insertSegmentVerticesForSnap(filteredSnapResults, vl);
return 0;
}
@@ -58,14 +58,9 @@ class QgsMapToolEdit: public QgsMapTool
QgsVectorLayer* currentVectorLayer();

/**Adds vertices to other features to keep topology up to date, e.g. to neighbouring polygons.
Note that geom must be a geometry that is not yet inserted into the layer.
@param geom a geometry that is to be inserted into the current vector layer
@param geom list of points (in layer coordinate system)
@return 0 in case of success*/
int addTopologicalPoints(const QList<QgsPoint>& geom);
/**Adds topological points for one vertex
@param p vertex in layer coordinates
@return 0 in case of success*/
int addTopologicalPoints(const QgsPoint& p, QgsVectorLayer* vl);
};

#endif
Loading

0 comments on commit 61ecb55

Please sign in to comment.