mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-15 00:04:00 -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*/
|
@return 0 in case of success*/
|
||||||
int translate(double dx, double dy);
|
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
|
/**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.
|
between geometry and splitLine, only the first one is considered.
|
||||||
@param splitLine the line that splits the geometry
|
@param splitLine the line that splits the geometry
|
||||||
@param newGeometrys OUT: list of new geometries that have been created with the split
|
@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, \
|
@param topological true if topological editing is enabled
|
||||||
1 if line intersects multiple times but only one split could be done, \
|
@topologyTestPoints OUT: points that need to be tested for topological completeness in the dataset
|
||||||
2 if intersection too complicated to proceed (several polygon intersections), \ \
|
@return 0 in case of success, 1 if geometry has not been split, error else*/
|
||||||
else other error*/
|
int splitGeometry(const QList<QgsPoint>& splitLine, QList<QgsGeometry*>& newGeometries, bool topological, QList<QgsPoint>& topologyTestPoints);
|
||||||
int splitGeometry(const QList<QgsPoint>& splitLine, QList<QgsGeometry*>& newGeometries);
|
|
||||||
|
|
||||||
/**Changes this geometry such that it does not intersect the other geometry
|
/**Changes this geometry such that it does not intersect the other geometry
|
||||||
@param other geometry that should not be intersect
|
@param other geometry that should not be intersect
|
||||||
|
@ -3119,7 +3119,7 @@ int QgsGeometry::transform( QgsCoordinateTransform& ct )
|
|||||||
return 0;
|
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;
|
int returnCode = 0;
|
||||||
|
|
||||||
@ -3156,7 +3156,16 @@ int QgsGeometry::splitGeometry( const QList<QgsPoint>& splitLine, QList<QgsGeome
|
|||||||
return 1;
|
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 )
|
if ( vectorType() == QGis::Line )
|
||||||
{
|
{
|
||||||
returnCode = splitLinearGeometry( splitLineGeos, newGeometries );
|
returnCode = splitLinearGeometry( splitLineGeos, newGeometries );
|
||||||
@ -4885,6 +4894,64 @@ int QgsGeometry::splitPolygonGeometry( GEOSGeometry* splitLine, QList<QgsGeometr
|
|||||||
return 0;
|
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
|
GEOSGeometry *QgsGeometry::nodeGeometries( const GEOSGeometry *splitLine, GEOSGeometry *geom ) const
|
||||||
{
|
{
|
||||||
if ( !splitLine || !geom )
|
if ( !splitLine || !geom )
|
||||||
|
@ -242,8 +242,10 @@ class CORE_EXPORT QgsGeometry
|
|||||||
between geometry and splitLine, only the first one is considered.
|
between geometry and splitLine, only the first one is considered.
|
||||||
@param splitLine the line that splits the geometry
|
@param splitLine the line that splits the geometry
|
||||||
@param newGeometrys OUT: list of new geometries that have been created with the split
|
@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*/
|
@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
|
/**Changes this geometry such that it does not intersect the other geometry
|
||||||
@param other geometry that should not be intersect
|
@param other geometry that should not be intersect
|
||||||
@ -398,12 +400,13 @@ class CORE_EXPORT QgsGeometry
|
|||||||
@splitLine the line that splits the feature
|
@splitLine the line that splits the feature
|
||||||
@newGeometry new geometry if splitting was successful
|
@newGeometry new geometry if splitting was successful
|
||||||
@return 0 in case of success, 1 if geometry has not been split, error else*/
|
@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
|
/**Splits polygon/multipolygon geometries
|
||||||
@return 0 in case of success, 1 if geometry has not been split, error else*/
|
@return 0 in case of success, 1 if geometry has not been split, error else*/
|
||||||
int splitPolygonGeometry( GEOSGeometry *splitLine, QList<QgsGeometry*>& newGeometries );
|
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
|
/**Finds out the points that need to be tested for topological correctnes if this geometry will be split
|
||||||
and afterVertex are the same*/
|
@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
|
/**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*/
|
@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 )
|
for ( ; select_it != featureList.end(); ++select_it )
|
||||||
{
|
{
|
||||||
QList<QgsGeometry*> newGeometries;
|
QList<QgsGeometry*> newGeometries;
|
||||||
|
QList<QgsPoint> topologyTestPoints;
|
||||||
QgsGeometry* newGeometry = 0;
|
QgsGeometry* newGeometry = 0;
|
||||||
splitFunctionReturn = select_it->geometry()->splitGeometry( splitLine, newGeometries );
|
splitFunctionReturn = select_it->geometry()->splitGeometry( splitLine, newGeometries, topologicalEditing, topologyTestPoints);
|
||||||
if ( splitFunctionReturn == 0 )
|
if ( splitFunctionReturn == 0 )
|
||||||
{
|
{
|
||||||
//change this geometry
|
//change this geometry
|
||||||
@ -1737,18 +1738,17 @@ int QgsVectorLayer::splitFeatures( const QList<QgsPoint>& splitLine, bool topolo
|
|||||||
newFeature.setGeometry( newGeometry );
|
newFeature.setGeometry( newGeometry );
|
||||||
newFeature.setAttributeMap( select_it->attributeMap() );
|
newFeature.setAttributeMap( select_it->attributeMap() );
|
||||||
newFeatures.append( newFeature );
|
newFeatures.append( newFeature );
|
||||||
if ( topologicalEditing ) //add topological points for new feature
|
|
||||||
{
|
|
||||||
addTopologicalPoints( newGeometry );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
setModified( true, true );
|
|
||||||
|
|
||||||
//add topological points for this geometry if necessary
|
setModified( true, true );
|
||||||
if ( topologicalEditing )
|
if(topologicalEditing)
|
||||||
{
|
{
|
||||||
addTopologicalPoints( select_it->geometry() );
|
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
|
else if ( splitFunctionReturn > 1 ) //1 means no split but also no error
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user