Skip to content

Commit

Permalink
#9480: New option for CentroidFillSymbolLayerV2 to force centroid ins…
Browse files Browse the repository at this point in the history
…ide of polygons
  • Loading branch information
ahuarte47 committed May 27, 2014
1 parent cbee3d3 commit 72b3d3f
Show file tree
Hide file tree
Showing 7 changed files with 101 additions and 10 deletions.
23 changes: 15 additions & 8 deletions src/core/symbology-ng/qgsfillsymbollayerv2.cpp
Expand Up @@ -3166,7 +3166,7 @@ QSet<QString> QgsPointPatternFillSymbolLayer::usedAttributes() const
//////////////


QgsCentroidFillSymbolLayerV2::QgsCentroidFillSymbolLayerV2(): mMarker( NULL )
QgsCentroidFillSymbolLayerV2::QgsCentroidFillSymbolLayerV2(): mMarker( NULL ), mPointOnSurface( false )
{
setSubSymbol( new QgsMarkerSymbolV2() );
}
Expand All @@ -3178,8 +3178,12 @@ QgsCentroidFillSymbolLayerV2::~QgsCentroidFillSymbolLayerV2()

QgsSymbolLayerV2* QgsCentroidFillSymbolLayerV2::create( const QgsStringMap& properties )
{
Q_UNUSED( properties );
return new QgsCentroidFillSymbolLayerV2();
QgsCentroidFillSymbolLayerV2* sl = new QgsCentroidFillSymbolLayerV2();

if ( properties.contains( "point_on_surface" ) )
sl->setPointOnSurface( properties["point_on_surface"].toInt() != 0 );

return sl;
}

QString QgsCentroidFillSymbolLayerV2::layerType() const
Expand Down Expand Up @@ -3208,13 +3212,15 @@ void QgsCentroidFillSymbolLayerV2::renderPolygon( const QPolygonF& points, QList
{
Q_UNUSED( rings );

QPointF centroid = QgsSymbolLayerV2Utils::polygonCentroid( points );
QPointF centroid = mPointOnSurface ? QgsSymbolLayerV2Utils::polygonPointOnSurface( points ) : QgsSymbolLayerV2Utils::polygonCentroid( points );
mMarker->renderPoint( centroid, context.feature(), context.renderContext(), -1, context.selected() );
}

QgsStringMap QgsCentroidFillSymbolLayerV2::properties() const
{
return QgsStringMap();
QgsStringMap map;
map["point_on_surface"] = QString::number( mPointOnSurface );
return map;
}

QgsSymbolLayerV2* QgsCentroidFillSymbolLayerV2::clone() const
Expand All @@ -3223,6 +3229,7 @@ QgsSymbolLayerV2* QgsCentroidFillSymbolLayerV2::clone() const
x->mAngle = mAngle;
x->mColor = mColor;
x->setSubSymbol( mMarker->clone() );
x->setPointOnSurface( mPointOnSurface );
return x;
}

Expand All @@ -3246,9 +3253,9 @@ QgsSymbolLayerV2* QgsCentroidFillSymbolLayerV2::createFromSld( QDomElement &elem
layers.append( l );
QgsMarkerSymbolV2 *marker = new QgsMarkerSymbolV2( layers );

QgsCentroidFillSymbolLayerV2* x = new QgsCentroidFillSymbolLayerV2();
x->setSubSymbol( marker );
return x;
QgsCentroidFillSymbolLayerV2* sl = new QgsCentroidFillSymbolLayerV2();
sl->setSubSymbol( marker );
return sl;
}


Expand Down
4 changes: 4 additions & 0 deletions src/core/symbology-ng/qgsfillsymbollayerv2.h
Expand Up @@ -904,8 +904,12 @@ class CORE_EXPORT QgsCentroidFillSymbolLayerV2 : public QgsFillSymbolLayerV2

virtual QSet<QString> usedAttributes() const;

void setPointOnSurface( bool pointOnSurface ) { mPointOnSurface = pointOnSurface; }
bool pointOnSurface() const { return mPointOnSurface; }

protected:
QgsMarkerSymbolV2* mMarker;
bool mPointOnSurface;
};

#endif
Expand Down
56 changes: 56 additions & 0 deletions src/core/symbology-ng/qgssymbollayerv2utils.cpp
Expand Up @@ -3179,6 +3179,62 @@ QPointF QgsSymbolLayerV2Utils::polygonCentroid( const QPolygonF& points )
return QPointF( cx, cy );
}

QPointF QgsSymbolLayerV2Utils::polygonPointOnSurface( const QPolygonF& points )
{
QPointF centroid = QgsSymbolLayerV2Utils::polygonCentroid( points );

// check if centroid inside in polygon
if ( !QgsSymbolLayerV2Utils::pointInPolygon( points, centroid ) )
{
unsigned int i, pointCount = points.count();

QgsPolyline polyline( pointCount );
for ( i = 0; i < pointCount; ++i ) polyline[i] = QgsPoint( points[i].x(), points[i].y() );

QgsGeometry* geom = QgsGeometry::fromPolygon( QgsPolygon() << polyline );
if ( geom )
{
QgsGeometry* pointOnSurfaceGeom = geom->pointOnSurface();

if ( pointOnSurfaceGeom )
{
QgsPoint point = pointOnSurfaceGeom->asPoint();
delete pointOnSurfaceGeom;
delete geom;

return QPointF( point.x(), point.y() );
}
delete geom;
}
}
return centroid;
}

bool QgsSymbolLayerV2Utils::pointInPolygon( const QPolygonF &points, const QPointF &point )
{
bool inside = false;

double x = point.x();
double y = point.y();

for ( int i = 0, j = points.count() - 1; i < points.count(); i++ )
{
const QPointF& p1 = points[i];
const QPointF& p2 = points[j];

if ( p1.x() == x && p1.y() == y )
return true;

if ( ( p1.y() < y && p2.y() >= y ) || ( p2.y() < y && p1.y() >= y ) )
{
if ( p1.x() + ( y - p1.y() ) / ( p2.y() - p1.y() )*( p2.x() - p1.x() ) <= x )
inside = !inside;
}

j = i;
}
return inside;
}

QgsExpression* QgsSymbolLayerV2Utils::fieldOrExpressionToExpression( const QString& fieldOrExpression )
{
Expand Down
6 changes: 6 additions & 0 deletions src/core/symbology-ng/qgssymbollayerv2utils.h
Expand Up @@ -287,6 +287,12 @@ class CORE_EXPORT QgsSymbolLayerV2Utils
//! Calculate the centroid point of a QPolygonF
static QPointF polygonCentroid( const QPolygonF& points );

//! Calculate a point within of a QPolygonF
static QPointF polygonPointOnSurface( const QPolygonF& points );

//! Calculate whether a point is within of a QPolygonF
static bool pointInPolygon( const QPolygonF &points, const QPointF &point );

/** Return a new valid expression instance for given field or expression string.
* If the input is not a valid expression, it is assumed that it is a field name and gets properly quoted.
* If the string is empty, returns null pointer.
Expand Down
12 changes: 10 additions & 2 deletions src/gui/symbology-ng/qgssymbollayerv2widget.cpp
Expand Up @@ -2794,12 +2794,20 @@ void QgsCentroidFillSymbolLayerV2Widget::setSymbolLayer( QgsSymbolLayerV2* layer

// layer type is correct, we can do the cast
mLayer = static_cast<QgsCentroidFillSymbolLayerV2*>( layer );

// set values
mDrawInsideCheckBox->blockSignals( true );
mDrawInsideCheckBox->setChecked( mLayer->pointOnSurface() );
mDrawInsideCheckBox->blockSignals( false );
}

QgsSymbolLayerV2* QgsCentroidFillSymbolLayerV2Widget::symbolLayer()
{
return mLayer;
}



void QgsCentroidFillSymbolLayerV2Widget::on_mDrawInsideCheckBox_stateChanged( int state )
{
mLayer->setPointOnSurface( state == Qt::Checked );
emit changed();
}
3 changes: 3 additions & 0 deletions src/gui/symbology-ng/qgssymbollayerv2widget.h
Expand Up @@ -482,6 +482,9 @@ class GUI_EXPORT QgsCentroidFillSymbolLayerV2Widget : public QgsSymbolLayerV2Wid
virtual void setSymbolLayer( QgsSymbolLayerV2* layer );
virtual QgsSymbolLayerV2* symbolLayer();

public slots:
void on_mDrawInsideCheckBox_stateChanged( int state );

protected:
QgsCentroidFillSymbolLayerV2* mLayer;
};
Expand Down
7 changes: 7 additions & 0 deletions src/ui/symbollayer/widget_centroidfill.ui
Expand Up @@ -16,6 +16,13 @@
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QCheckBox" name="mDrawInsideCheckBox">
<property name="text">
<string>Force point inside polygon</string>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation">
Expand Down

0 comments on commit 72b3d3f

Please sign in to comment.