Skip to content

Instantly share code, notes, and snippets.

@dakcarto
Created March 6, 2014 01:15
Show Gist options
  • Save dakcarto/9380317 to your computer and use it in GitHub Desktop.
Save dakcarto/9380317 to your computer and use it in GitHub Desktop.
qgis issue 1219 combined patch
diff --git a/src/core/pal/layer.cpp b/src/core/pal/layer.cpp
index 28d0041..c0fec47 100644
--- a/src/core/pal/layer.cpp
+++ b/src/core/pal/layer.cpp
@@ -60,7 +60,7 @@ namespace pal
Layer::Layer( const char *lyrName, double min_scale, double max_scale, Arrangement arrangement, Units label_unit, double defaultPriority, bool obstacle, bool active, bool toLabel, Pal *pal, bool displayAll )
: pal( pal ), obstacle( obstacle ), active( active ),
- toLabel( toLabel ), displayAll( displayAll ), label_unit( label_unit ),
+ toLabel( toLabel ), displayAll( displayAll ), ignoreInvalidGeometries( true ), label_unit( label_unit ),
min_scale( min_scale ), max_scale( max_scale ),
arrangement( arrangement ), arrangementFlags( 0 ), mode( LabelPerFeature ), mergeLines( false )
{
@@ -157,7 +157,6 @@ namespace pal
this->arrangement = arrangement;
}
-
bool Layer::isObstacle()
{
return obstacle;
@@ -289,7 +288,8 @@ namespace pal
const GEOSGeometry* geom = simpleGeometries->pop_front();
// ignore invalid geometries (e.g. polygons with self-intersecting rings)
- if ( GEOSisValid( geom ) != 1 ) // 0=invalid, 1=valid, 2=exception
+ int geomvalid = GEOSisValid( geom ); // 0=invalid, 1=valid, 2=exception
+ if ( geomvalid == 2 || ( ignoreInvalidGeometries && geomvalid == 0 ) )
{
std::cerr << "ignoring invalid feature " << geom_id << std::endl;
continue;
diff --git a/src/core/pal/layer.h b/src/core/pal/layer.h
index c4518de..940262e 100644
--- a/src/core/pal/layer.h
+++ b/src/core/pal/layer.h
@@ -101,6 +101,7 @@ namespace pal
bool active;
bool toLabel;
bool displayAll;
+ bool ignoreInvalidGeometries;
Units label_unit;
@@ -183,6 +184,9 @@ namespace pal
unsigned long getArrangementFlags() const { return arrangementFlags; }
void setArrangementFlags( unsigned long flags ) { arrangementFlags = flags; }
+ bool getIgnoreInvalidGeometries() const { return ignoreInvalidGeometries; }
+ void setIgnoreInvalidGeometries( bool ignoreInvalid ) { ignoreInvalidGeometries = ignoreInvalid; }
+
/**
* \brief get units for label size
*/
diff --git a/src/core/qgsmaptopixelgeometrysimplifier.cpp b/src/core/qgsmaptopixelgeometrysimplifier.cpp
index 6c49e66..265e167 100644
--- a/src/core/qgsmaptopixelgeometrysimplifier.cpp
+++ b/src/core/qgsmaptopixelgeometrysimplifier.cpp
@@ -147,6 +147,11 @@ bool QgsMapToPixelSimplifier::simplifyWkbGeometry( int simplifyFlags, QGis::WkbT
bool hasZValue = QGis::wkbDimensions( wkbType ) == 3;
bool result = false;
+ // Save initial WKB settings to use when the simplification creates invalid geometries
+ unsigned char* sourcePrevWkb = sourceWkb;
+ unsigned char* targetPrevWkb = targetWkb;
+ size_t targetWkbPrevSize = targetWkbSize;
+
// Can replace the geometry by its BBOX ?
if (( simplifyFlags & QgsMapToPixelSimplifier::SimplifyEnvelope ) && ( envelope.xMaximum() - envelope.xMinimum() ) < map2pixelTol && ( envelope.yMaximum() - envelope.yMinimum() ) < map2pixelTol )
{
@@ -181,6 +186,11 @@ bool QgsMapToPixelSimplifier::simplifyWkbGeometry( int simplifyFlags, QGis::WkbT
{
double x, y, lastX = 0, lastY = 0;
+ double xmin = std::numeric_limits<double>::max();
+ double ymin = std::numeric_limits<double>::max();
+ double xmax = -std::numeric_limits<double>::max();
+ double ymax = -std::numeric_limits<double>::max();
+
int sizeOfDoubleX = sizeof( double );
int sizeOfDoubleY = QGis::wkbDimensions( wkbType ) == 3 /*hasZValue*/ ? 2 * sizeof( double ) : sizeof( double );
@@ -209,10 +219,21 @@ bool QgsMapToPixelSimplifier::simplifyWkbGeometry( int simplifyFlags, QGis::WkbT
memcpy( ptr, &y, sizeof( double ) ); lastY = y; ptr++;
numTargetPoints++;
}
+ if ( xmin > x ) xmin = x;
+ if ( ymin > y ) ymin = y;
+ if ( xmax < x ) xmax = x;
+ if ( ymax < y ) ymax = y;
}
targetWkb = wkb2 + 4;
// Fix the topology of the geometry
+ if ( numTargetPoints <= ( isaLinearRing ? 2 : 1 ) )
+ {
+ sourceWkb = sourcePrevWkb;
+ targetWkb = targetPrevWkb;
+ targetWkbSize = targetWkbPrevSize;
+ return generalizeWkbGeometry( wkbType, sourceWkb, sourceWkbSize, targetWkb, targetWkbSize, QgsRectangle( xmin, ymin, xmax, ymax ), writeHeader );
+ }
if ( isaLinearRing )
{
memcpy( &x, targetWkb + 0, sizeof( double ) );
diff --git a/src/core/qgspallabeling.cpp b/src/core/qgspallabeling.cpp
index 9fbfeb2..15ae51e 100644
--- a/src/core/qgspallabeling.cpp
+++ b/src/core/qgspallabeling.cpp
@@ -1840,6 +1840,12 @@ void QgsPalLayerSettings::registerFeature( QgsFeature& f, const QgsRenderContext
}
}
+ // fix invalid polygons
+ if ( QGis::singleType( QGis::flatType( geom->wkbType() ) ) == QGis::WKBPolygon && !geom->isGeosValid() )
+ {
+ geom->fromGeos( GEOSBuffer( geom->asGeos(), 0, 0 ) );
+ }
+
// CLIP the geometry if it is bigger than the extent
// don't clip if centroid is requested for whole feature
bool do_clip = false;
@@ -3276,6 +3282,9 @@ int QgsPalLabeling::prepareLayer( QgsVectorLayer* layer, QStringList& attrNames,
// set whether adjacent lines should be merged
l->setMergeConnectedLines( lyr.mergeLines );
+ // set whether invalid geometries (e.g. polygons with self-intersecting rings) should be processed
+ l->setIgnoreInvalidGeometries( false );
+
// set how to show upside-down labels
Layer::UpsideDownLabels upsdnlabels;
switch ( lyr.upsidedownLabels )
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment