@@ -2878,14 +2878,35 @@ int QgsGeometry::splitGeometry( const QList<QgsPoint>& splitLine, QList<QgsGeome
28782878 return 7 ;
28792879
28802880 // make sure splitLine is valid
2881- if ( splitLine.size () < 2 )
2881+ if ( splitLine.size () < 1 )
28822882 return 1 ;
28832883
2884+ // Treat the special case of a single point to split a line without geos
2885+ if ( splitLine.size () == 1 )
2886+ {
2887+ // A point cannot split a polygon
2888+ if ( type () == QGis::Polygon )
2889+ return 1 ;
2890+ // return splitLinearGeometryAtPoint( splitLine[0], newGeometries );
2891+ }
2892+
28842893 newGeometries.clear ();
28852894
28862895 try
28872896 {
2888- GEOSGeometry *splitLineGeos = createGeosLineString ( splitLine.toVector () );
2897+ GEOSGeometry* splitLineGeos;
2898+ if ( splitLine.size () > 1 )
2899+ {
2900+ splitLineGeos = createGeosLineString ( splitLine.toVector () );
2901+ }
2902+ else if ( splitLine.size () == 1 )
2903+ {
2904+ splitLineGeos = createGeosPoint ( splitLine.at ( 0 ) );
2905+ }
2906+ else
2907+ {
2908+ return 1 ;
2909+ }
28892910 if ( !GEOSisValid ( splitLineGeos ) || !GEOSisSimple ( splitLineGeos ) )
28902911 {
28912912 GEOSGeom_destroy ( splitLineGeos );
@@ -4549,6 +4570,105 @@ void QgsGeometry::transformVertex( QgsWkbPtr &wkbPtr, const QgsCoordinateTransfo
45494570
45504571}
45514572
4573+ GEOSGeometry* QgsGeometry::linePointDifference ( GEOSGeometry* GEOSsplitPoint )
4574+ {
4575+ int type = GEOSGeomTypeId ( mGeos );
4576+ QgsMultiPolyline multiLine;
4577+
4578+ if ( type == GEOS_MULTILINESTRING )
4579+ multiLine = asMultiPolyline ();
4580+ else if ( type == GEOS_LINESTRING )
4581+ multiLine = QgsMultiPolyline () << asPolyline ();
4582+ else
4583+ return 0 ;
4584+
4585+ QgsPoint splitPoint = fromGeosGeom ( GEOSsplitPoint )->asPoint ();
4586+
4587+ QgsPoint p1, p2;
4588+ QgsGeometry* g;
4589+ QgsMultiPolyline lines;
4590+ QgsPolyline line;
4591+ QgsPolyline newline;
4592+
4593+ // For each part
4594+ for ( int i = 0 ; i < multiLine.size () ; ++i )
4595+ {
4596+ line = multiLine[i];
4597+ // For each segment
4598+ newline = QgsPolyline ();
4599+ for ( int j = 1 ; j < line.size () ; ++j )
4600+ {
4601+ p1 = line[j-1 ];
4602+ p2 = line[j];
4603+ g = QgsGeometry::fromPolyline ( QgsPolyline () << p1 << p2 );
4604+ QgsDebugMsg ( g->exportToWkt () );
4605+ QgsDebugMsg ( splitPoint.toString () );
4606+
4607+ newline.append ( p1 );
4608+
4609+ double x1 = p1.x ();
4610+ double y1 = p1.y ();
4611+ double x2 = p2.x ();
4612+ double y2 = p2.y ();
4613+ double xt = splitPoint.x ();
4614+ double yt = splitPoint.y ();
4615+ double k;
4616+ double diff;
4617+ if ( x2 == x1 )
4618+ {
4619+ if ( y2 == y1 )
4620+ {
4621+ k = -1 ;
4622+ diff = 1e50 ;
4623+ }
4624+ else
4625+ {
4626+ k = ( yt - y1 ) / ( y2 - y1 );
4627+ diff = k * ( x2 - x1 ) - ( xt - x1 );
4628+ }
4629+ }
4630+ else
4631+ {
4632+ k = ( xt - x1 ) / ( x2 - x1 );
4633+ diff = k * ( y2 - y1 ) - ( yt - y1 );
4634+ }
4635+ if ( abs ( diff ) < 1e-7 )
4636+ {
4637+ if ( k == 0 )
4638+ {
4639+ lines.append ( newline );
4640+ newline = QgsPolyline ();
4641+ newline.append ( p1 );
4642+ }
4643+ if ( k == 1 )
4644+ {
4645+ newline.append ( p2 );
4646+ lines.append ( newline );
4647+ newline = QgsPolyline ();
4648+ }
4649+ if ( k > 0 && k < 1 )
4650+ {
4651+ newline.append ( splitPoint );
4652+ lines.append ( newline );
4653+ newline = QgsPolyline ();
4654+ newline.append ( splitPoint );
4655+ }
4656+ if ( k < 0 || k > 1 )
4657+ {
4658+ // Nothing happens, we are on the line but not the segment
4659+ }
4660+ }
4661+ }
4662+ newline.append ( line.last () );
4663+ lines.append ( newline );
4664+ }
4665+ QgsGeometry* splitLines = fromMultiPolyline ( lines );
4666+ GEOSGeometry* splitGeom = GEOSGeom_clone ( splitLines->asGeos () );
4667+
4668+ return splitGeom;
4669+
4670+ }
4671+
45524672int QgsGeometry::splitLinearGeometry ( GEOSGeometry *splitLine, QList<QgsGeometry*>& newGeometries )
45534673{
45544674 if ( !splitLine )
@@ -4560,16 +4680,25 @@ int QgsGeometry::splitLinearGeometry( GEOSGeometry *splitLine, QList<QgsGeometry
45604680 if ( !mGeos )
45614681 return 5 ;
45624682
4563- // first test if linestring intersects geometry. If not, return straight away
4564- if ( !GEOSIntersects ( splitLine, mGeos ) )
4565- return 1 ;
45664683
45674684 // check that split line has no linear intersection
45684685 int linearIntersect = GEOSRelatePattern ( mGeos , splitLine, " 1********" );
45694686 if ( linearIntersect > 0 )
45704687 return 3 ;
45714688
4572- GEOSGeometry* splitGeom = GEOSDifference ( mGeos , splitLine );
4689+ int splitGeomType = GEOSGeomTypeId ( splitLine );
4690+ // first test if linestring intersects geometry. If not, return straight away
4691+ if ( splitGeomType == GEOS_LINESTRING && !GEOSIntersects ( splitLine, mGeos ) )
4692+ return 1 ;
4693+ GEOSGeometry* splitGeom;
4694+ if ( splitGeomType == GEOS_LINESTRING )
4695+ {
4696+ splitGeom = GEOSDifference ( mGeos , splitLine );
4697+ }
4698+ else
4699+ {
4700+ splitGeom = linePointDifference ( splitLine );
4701+ }
45734702 QVector<GEOSGeometry*> lineGeoms;
45744703
45754704 int splitType = GEOSGeomTypeId ( splitGeom );
0 commit comments