mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-14 00:07:35 -04:00
Fix for problem where splitting was slow for large polygons and with topological editing enabled (bug #1161)
git-svn-id: http://svn.osgeo.org/qgis/trunk@9351 c8812cc2-4d05-0410-92ff-de0c093fc19c
This commit is contained in:
parent
6cc1f3d3a0
commit
6506e6d176
@ -192,15 +192,14 @@ not disjoint with existing polygons of the feature*/
|
||||
@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.
|
||||
/**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);
|
||||
@param topological true if topological editing is enabled
|
||||
@topologyTestPoints OUT: points that need to be tested for topological completeness in the dataset
|
||||
@return 0 in case of success, 1 if geometry has not been split, error else*/
|
||||
int splitGeometry(const QList<QgsPoint>& splitLine, QList<QgsGeometry*>& newGeometries, bool topological, QList<QgsPoint>& topologyTestPoints);
|
||||
|
||||
/**Changes this geometry such that it does not intersect the other geometry
|
||||
@param other geometry that should not be intersect
|
||||
|
@ -3119,7 +3119,7 @@ int QgsGeometry::transform( QgsCoordinateTransform& ct )
|
||||
return 0;
|
||||
}
|
||||
|
||||
int QgsGeometry::splitGeometry( const QList<QgsPoint>& splitLine, QList<QgsGeometry*>& newGeometries )
|
||||
int QgsGeometry::splitGeometry( const QList<QgsPoint>& splitLine, QList<QgsGeometry*>& newGeometries, bool topological, QList<QgsPoint>& topologyTestPoints )
|
||||
{
|
||||
int returnCode = 0;
|
||||
|
||||
@ -3156,7 +3156,16 @@ int QgsGeometry::splitGeometry( const QList<QgsPoint>& splitLine, QList<QgsGeome
|
||||
return 1;
|
||||
}
|
||||
|
||||
//for line/multiline: call splitLinearGeometry
|
||||
if(topological)
|
||||
{
|
||||
//find out candidate points for topological corrections
|
||||
if(topologicalTestPointsSplit(splitLineGeos, topologyTestPoints) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
//call split function depending on geometry type
|
||||
if ( vectorType() == QGis::Line )
|
||||
{
|
||||
returnCode = splitLinearGeometry( splitLineGeos, newGeometries );
|
||||
@ -4885,6 +4894,64 @@ int QgsGeometry::splitPolygonGeometry( GEOSGeometry* splitLine, QList<QgsGeometr
|
||||
return 0;
|
||||
}
|
||||
|
||||
int QgsGeometry::topologicalTestPointsSplit( const GEOSGeometry* splitLine, QList<QgsPoint>& testPoints) const
|
||||
{
|
||||
//Find out the intersection points between splitLineGeos and this geometry.
|
||||
//These points need to be tested for topological correctness by the calling function
|
||||
//if topological editing is enabled
|
||||
|
||||
testPoints.clear();
|
||||
GEOSGeometry* intersectionGeom = GEOSIntersection(mGeos, splitLine);
|
||||
if(intersectionGeom == NULL)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool simple = false;
|
||||
int nIntersectGeoms = 1;
|
||||
if(GEOSGeomTypeId(intersectionGeom) == (GEOS_LINESTRING) || GEOSGeomTypeId(intersectionGeom) == (GEOS_POINT))
|
||||
{
|
||||
simple = true;
|
||||
}
|
||||
|
||||
if(!simple)
|
||||
{
|
||||
nIntersectGeoms = GEOSGetNumGeometries(intersectionGeom);
|
||||
}
|
||||
|
||||
for(int i = 0; i < nIntersectGeoms; ++i)
|
||||
{
|
||||
GEOSGeometry* currentIntersectGeom;
|
||||
if(simple)
|
||||
{
|
||||
currentIntersectGeom = intersectionGeom;
|
||||
}
|
||||
else
|
||||
{
|
||||
currentIntersectGeom = GEOSGetGeometryN(intersectionGeom, i);
|
||||
}
|
||||
|
||||
GEOSCoordSequence* lineSequence = GEOSGeom_getCoordSeq(currentIntersectGeom);
|
||||
unsigned int sequenceSize = 0;
|
||||
double x, y;
|
||||
if(GEOSCoordSeq_getSize(lineSequence, &sequenceSize) != 0)
|
||||
{
|
||||
for(int i = 0; i < sequenceSize; ++i)
|
||||
{
|
||||
if(GEOSCoordSeq_getX(lineSequence, i, &x) != 0)
|
||||
{
|
||||
if(GEOSCoordSeq_getY(lineSequence, i, &y) != 0)
|
||||
{
|
||||
testPoints.push_back(QgsPoint(x, y));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
GEOSGeom_destroy(intersectionGeom);
|
||||
return 0;
|
||||
}
|
||||
|
||||
GEOSGeometry *QgsGeometry::nodeGeometries( const GEOSGeometry *splitLine, GEOSGeometry *geom ) const
|
||||
{
|
||||
if ( !splitLine || !geom )
|
||||
|
@ -242,8 +242,10 @@ class CORE_EXPORT QgsGeometry
|
||||
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
|
||||
@param topological true if topological editing is enabled
|
||||
@topologyTestPoints OUT: points that need to be tested for topological completeness in the dataset
|
||||
@return 0 in case of success, 1 if geometry has not been split, error else*/
|
||||
int splitGeometry( const QList<QgsPoint>& splitLine, QList<QgsGeometry*>& newGeometries );
|
||||
int splitGeometry( const QList<QgsPoint>& splitLine, QList<QgsGeometry*>& newGeometries, bool topological, QList<QgsPoint>& topologyTestPoints);
|
||||
|
||||
/**Changes this geometry such that it does not intersect the other geometry
|
||||
@param other geometry that should not be intersect
|
||||
@ -398,12 +400,13 @@ class CORE_EXPORT QgsGeometry
|
||||
@splitLine the line that splits the feature
|
||||
@newGeometry new geometry if splitting was successful
|
||||
@return 0 in case of success, 1 if geometry has not been split, error else*/
|
||||
int splitLinearGeometry( GEOSGeometry *splitLine, QList<QgsGeometry*>& newGeometries );
|
||||
int splitLinearGeometry( GEOSGeometry *splitLine, QList<QgsGeometry*>& newGeometries);
|
||||
/**Splits polygon/multipolygon geometries
|
||||
@return 0 in case of success, 1 if geometry has not been split, error else*/
|
||||
int splitPolygonGeometry( GEOSGeometry *splitLine, QList<QgsGeometry*>& newGeometries );
|
||||
/**Finds the vertices next to point where the line is split. If it is split at a vertex, beforeVertex
|
||||
and afterVertex are the same*/
|
||||
/**Finds out the points that need to be tested for topological correctnes if this geometry will be split
|
||||
@return 0 in case of success*/
|
||||
int topologicalTestPointsSplit( const GEOSGeometry* splitLine, QList<QgsPoint>& testPoints) const;
|
||||
|
||||
/**Nodes together a split line and a (multi-) polygon geometry in a multilinestring
|
||||
@return the noded multiline geometry or 0 in case of error. The calling function takes ownership of the node geometry*/
|
||||
|
@ -1722,8 +1722,9 @@ int QgsVectorLayer::splitFeatures( const QList<QgsPoint>& splitLine, bool topolo
|
||||
for ( ; select_it != featureList.end(); ++select_it )
|
||||
{
|
||||
QList<QgsGeometry*> newGeometries;
|
||||
QList<QgsPoint> topologyTestPoints;
|
||||
QgsGeometry* newGeometry = 0;
|
||||
splitFunctionReturn = select_it->geometry()->splitGeometry( splitLine, newGeometries );
|
||||
splitFunctionReturn = select_it->geometry()->splitGeometry( splitLine, newGeometries, topologicalEditing, topologyTestPoints);
|
||||
if ( splitFunctionReturn == 0 )
|
||||
{
|
||||
//change this geometry
|
||||
@ -1737,18 +1738,17 @@ int QgsVectorLayer::splitFeatures( const QList<QgsPoint>& splitLine, bool topolo
|
||||
newFeature.setGeometry( newGeometry );
|
||||
newFeature.setAttributeMap( select_it->attributeMap() );
|
||||
newFeatures.append( newFeature );
|
||||
if ( topologicalEditing ) //add topological points for new feature
|
||||
{
|
||||
addTopologicalPoints( newGeometry );
|
||||
}
|
||||
}
|
||||
setModified( true, true );
|
||||
|
||||
//add topological points for this geometry if necessary
|
||||
if ( topologicalEditing )
|
||||
{
|
||||
addTopologicalPoints( select_it->geometry() );
|
||||
}
|
||||
setModified( true, true );
|
||||
if(topologicalEditing)
|
||||
{
|
||||
QList<QgsPoint>::const_iterator topol_it = topologyTestPoints.constBegin();
|
||||
for(; topol_it != topologyTestPoints.constEnd(); ++topol_it)
|
||||
{
|
||||
addTopologicalPoints(*topol_it);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( splitFunctionReturn > 1 ) //1 means no split but also no error
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user