Skip to content

Commit

Permalink
Consider curve geometries unsegmentized in line marker renderer
Browse files Browse the repository at this point in the history
  • Loading branch information
mhugent committed Sep 1, 2015
1 parent 5b97c03 commit a5a963c
Show file tree
Hide file tree
Showing 7 changed files with 142 additions and 51 deletions.
1 change: 1 addition & 0 deletions src/core/qgsrendercontext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ QgsRenderContext::QgsRenderContext()
, mLabelingEngine( NULL )
, mShowSelection( true )
, mUseRenderingOptimization( true )
, mGeometry( 0 )
{
mVectorSimplifyMethod.setSimplifyHints( QgsVectorSimplifyMethod::NoSimplification );
}
Expand Down
7 changes: 7 additions & 0 deletions src/core/qgsrendercontext.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

class QPainter;

class QgsAbstractGeometryV2;
class QgsLabelingEngineInterface;
class QgsMapSettings;

Expand Down Expand Up @@ -140,6 +141,9 @@ class CORE_EXPORT QgsRenderContext
*/
const QgsExpressionContext& expressionContext() const { return mExpressionContext; }

const QgsAbstractGeometryV2* geometry() const { return mGeometry; }
void setGeometry( const QgsAbstractGeometryV2* geometry ) { mGeometry = geometry; }

private:

/** Painter for rendering operations*/
Expand Down Expand Up @@ -190,6 +194,9 @@ class CORE_EXPORT QgsRenderContext

/** Expression context */
QgsExpressionContext mExpressionContext;

/** Pointer to the (unsegmentized) geometry*/
const QgsAbstractGeometryV2* mGeometry;
};

#endif
60 changes: 58 additions & 2 deletions src/core/symbology-ng/qgslinesymbollayerv2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
***************************************************************************/

#include "qgslinesymbollayerv2.h"
#include "qgscurvev2.h"
#include "qgscurvepolygonv2.h"
#include "qgsdxfexport.h"
#include "qgssymbollayerv2utils.h"
#include "qgsexpression.h"
Expand Down Expand Up @@ -751,6 +753,8 @@ QgsSymbolLayerV2* QgsMarkerLineSymbolLayerV2::create( const QgsStringMap& props
x->setPlacement( FirstVertex );
else if ( props["placement"] == "centralpoint" )
x->setPlacement( CentralPoint );
else if ( props["placement"] == "curvepoint" )
x->setPlacement( CurvePoint );
else
x->setPlacement( Interval );
}
Expand Down Expand Up @@ -827,6 +831,10 @@ void QgsMarkerLineSymbolLayerV2::renderPolyline( const QPolygonF& points, QgsSym
{
placement = CentralPoint;
}
else if ( placementString.compare( "curvepoint", Qt::CaseInsensitive ) == 0 )
{
placement = CurvePoint;
}
else
{
placement = Interval;
Expand All @@ -845,6 +853,7 @@ void QgsMarkerLineSymbolLayerV2::renderPolyline( const QPolygonF& points, QgsSym
}
else
{
context.renderContext().setGeometry( 0 ); //always use segmented geometry with offset
QList<QPolygonF> mline = ::offsetLine( points, offset * QgsSymbolLayerV2Utils::lineWidthScaleFactor( context.renderContext(), mOffsetUnit, mOffsetMapUnitScale ), context.feature() ? context.feature()->constGeometry()->type() : QGis::Line );

for ( int part = 0; part < mline.count(); ++part )
Expand All @@ -863,12 +872,24 @@ void QgsMarkerLineSymbolLayerV2::renderPolyline( const QPolygonF& points, QgsSym

void QgsMarkerLineSymbolLayerV2::renderPolygonOutline( const QPolygonF& points, QList<QPolygonF>* rings, QgsSymbolV2RenderContext& context )
{
const QgsCurvePolygonV2* curvePolygon = dynamic_cast<const QgsCurvePolygonV2*>( context.renderContext().geometry() );

if ( curvePolygon )
{
context.renderContext().setGeometry( curvePolygon->exteriorRing() );
}
renderPolyline( points, context );
if ( rings )
{
mOffset = -mOffset; // invert the offset for rings!
foreach ( const QPolygonF& ring, *rings )
renderPolyline( ring, context );
for ( int i = 0; i < rings->size(); ++i )
{
if ( curvePolygon )
{
context.renderContext().setGeometry( curvePolygon->interiorRing( i ) );
}
renderPolyline( rings->at( i ), context );
}
mOffset = -mOffset;
}
}
Expand Down Expand Up @@ -978,6 +999,39 @@ void QgsMarkerLineSymbolLayerV2::renderPolylineVertex( const QPolygonF& points,
offsetAlongLine *= QgsSymbolLayerV2Utils::lineWidthScaleFactor( rc, mOffsetAlongLineUnit, mOffsetAlongLineMapUnitScale );
}

if ( !mRotateMarker && offsetAlongLine == 0 && context.renderContext().geometry()
&& context.renderContext().geometry()->hasCurvedSegments() && ( placement == Vertex || placement == CurvePoint ) )
{
const QgsCoordinateTransform* ct = context.renderContext().coordinateTransform();
const QgsMapToPixel& mtp = context.renderContext().mapToPixel();

QgsVertexId vId;
QgsPointV2 vPoint;
double z;
QPointF mapPoint;
while ( context.renderContext().geometry()->nextVertex( vId, vPoint ) )
{
if (( placement == Vertex && vId.type == QgsVertexId::SegmentVertex )
|| ( placement == CurvePoint && vId.type == QgsVertexId::CurveVertex ) )
{
//transform
mapPoint.setX( vPoint.x() ); mapPoint.setY( vPoint.y() ); z = vPoint.z();
mtp.transformInPlace( mapPoint.rx(), mapPoint.ry() );
if ( ct )
{
ct->transformInPlace( mapPoint.rx(), mapPoint.ry(), z );
}

if ( mRotateMarker )
{
//todo: function to calculate angle...
}
mMarker->renderPoint( mapPoint, context.feature(), rc, -1, context.selected() );
}
}
return;
}

if ( placement == FirstVertex )
{
i = 0;
Expand Down Expand Up @@ -1230,6 +1284,8 @@ QgsStringMap QgsMarkerLineSymbolLayerV2::properties() const
map["placement"] = "firstvertex";
else if ( mPlacement == CentralPoint )
map["placement"] = "centralpoint";
else if ( mPlacement == CurvePoint )
map["placement"] = "curvepoint";
else
map["placement"] = "interval";

Expand Down
3 changes: 2 additions & 1 deletion src/core/symbology-ng/qgslinesymbollayerv2.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,8 @@ class CORE_EXPORT QgsMarkerLineSymbolLayerV2 : public QgsLineSymbolLayerV2
Vertex,
LastVertex,
FirstVertex,
CentralPoint
CentralPoint,
CurvePoint
};

// static stuff
Expand Down
14 changes: 14 additions & 0 deletions src/core/symbology-ng/qgsrendererv2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "qgsrendercontext.h"
#include "qgsclipper.h"
#include "qgsgeometry.h"
#include "qgsgeometrycollectionv2.h"
#include "qgsfeature.h"
#include "qgslogger.h"
#include "qgsvectorlayer.h"
Expand Down Expand Up @@ -288,6 +289,7 @@ void QgsFeatureRendererV2::renderFeatureWithSymbol( QgsFeature& feature, QgsSymb

const QgsGeometry* segmentizedGeometry = geom;
bool deleteSegmentizedGeometry = false;
context.setGeometry( geom->geometry() );

//convert curve types to normal point/line/polygon ones
switch ( QgsWKBTypes::flatType( geom->geometry()->wkbType() ) )
Expand Down Expand Up @@ -387,8 +389,14 @@ void QgsFeatureRendererV2::renderFeatureWithSymbol( QgsFeature& feature, QgsSymb
const unsigned char* ptr = wkbPtr;
QPolygonF pts;

const QgsGeometryCollectionV2* geomCollection = dynamic_cast<const QgsGeometryCollectionV2*>( geom->geometry() );

for ( unsigned int i = 0; i < num; ++i )
{
if ( geomCollection )
{
context.setGeometry( geomCollection->geometryN( i ) );
}
ptr = QgsConstWkbPtr( _getLineString( pts, context, ptr, symbol->clipFeaturesToExtent() ) );
(( QgsLineSymbolV2* )symbol )->renderPolyline( pts, &feature, context, layer, selected );
}
Expand All @@ -411,8 +419,14 @@ void QgsFeatureRendererV2::renderFeatureWithSymbol( QgsFeature& feature, QgsSymb
QPolygonF pts;
QList<QPolygonF> holes;

const QgsGeometryCollectionV2* geomCollection = dynamic_cast<const QgsGeometryCollectionV2*>( geom->geometry() );

for ( unsigned int i = 0; i < num; ++i )
{
if ( geomCollection )
{
context.setGeometry( geomCollection->geometryN( i ) );
}
ptr = _getPolygon( pts, holes, context, ptr, symbol->clipFeaturesToExtent() );
(( QgsFillSymbolV2* )symbol )->renderPolygon( pts, ( holes.count() ? &holes : NULL ), &feature, context, layer, selected );
}
Expand Down
57 changes: 31 additions & 26 deletions src/gui/symbology-ng/qgssymbollayerv2widget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1343,6 +1343,7 @@ QgsMarkerLineSymbolLayerV2Widget::QgsMarkerLineSymbolLayerV2Widget( const QgsVec
connect( radVertexLast, SIGNAL( clicked() ), this, SLOT( setPlacement() ) );
connect( radVertexFirst, SIGNAL( clicked() ), this, SLOT( setPlacement() ) );
connect( radCentralPoint, SIGNAL( clicked() ), this, SLOT( setPlacement() ) );
connect( radCurvePoint, SIGNAL( clicked() ), this, SLOT( setPlacement() ) );
}

void QgsMarkerLineSymbolLayerV2Widget::setSymbolLayer( QgsSymbolLayerV2* layer )
Expand Down Expand Up @@ -1374,6 +1375,8 @@ void QgsMarkerLineSymbolLayerV2Widget::setSymbolLayer( QgsSymbolLayerV2* layer )
radVertexLast->setChecked( true );
else if ( mLayer->placement() == QgsMarkerLineSymbolLayerV2::CentralPoint )
radCentralPoint->setChecked( true );
else if ( mLayer->placement() == QgsMarkerLineSymbolLayerV2::CurvePoint )
radCurvePoint->setChecked( true );
else
radVertexFirst->setChecked( true );

Expand Down Expand Up @@ -1442,6 +1445,8 @@ void QgsMarkerLineSymbolLayerV2Widget::setPlacement()
mLayer->setPlacement( QgsMarkerLineSymbolLayerV2::LastVertex );
else if ( radVertexFirst->isChecked() )
mLayer->setPlacement( QgsMarkerLineSymbolLayerV2::FirstVertex );
else if ( radCurvePoint->isChecked() )
mLayer->setPlacement( QgsMarkerLineSymbolLayerV2::CurvePoint );
else
mLayer->setPlacement( QgsMarkerLineSymbolLayerV2::CentralPoint );

Expand Down Expand Up @@ -1544,47 +1549,47 @@ class QgsSvgListModel : public QAbstractListModel
{
Q_UNUSED( parent );
return mSvgFiles.count();
}
}

QVariant data( const QModelIndex & index, int role = Qt::DisplayRole ) const override
{
QString entry = mSvgFiles.at( index.row() );

if ( role == Qt::DecorationRole ) // icon
{
QPixmap pixmap;
if ( !QPixmapCache::find( entry, pixmap ) )
{
QPixmap pixmap;
if ( !QPixmapCache::find( entry, pixmap ) )
{
// render SVG file
QColor fill, outline;
double outlineWidth;
bool fillParam, outlineParam, outlineWidthParam;
QgsSvgCache::instance()->containsParams( entry, fillParam, fill, outlineParam, outline, outlineWidthParam, outlineWidth );

bool fitsInCache; // should always fit in cache at these sizes (i.e. under 559 px ^ 2, or half cache size)
const QImage& img = QgsSvgCache::instance()->svgAsImage( entry, 30.0, fill, outline, outlineWidth, 3.5 /*appr. 88 dpi*/, 1.0, fitsInCache );
pixmap = QPixmap::fromImage( img );
QPixmapCache::insert( entry, pixmap );
}

return pixmap;
}
else if ( role == Qt::UserRole || role == Qt::ToolTipRole )
{
return entry;
// render SVG file
QColor fill, outline;
double outlineWidth;
bool fillParam, outlineParam, outlineWidthParam;
QgsSvgCache::instance()->containsParams( entry, fillParam, fill, outlineParam, outline, outlineWidthParam, outlineWidth );

bool fitsInCache; // should always fit in cache at these sizes (i.e. under 559 px ^ 2, or half cache size)
const QImage& img = QgsSvgCache::instance()->svgAsImage( entry, 30.0, fill, outline, outlineWidth, 3.5 /*appr. 88 dpi*/, 1.0, fitsInCache );
pixmap = QPixmap::fromImage( img );
QPixmapCache::insert( entry, pixmap );
}

return QVariant();
return pixmap;
}
else if ( role == Qt::UserRole || role == Qt::ToolTipRole )
{
return entry;
}

protected:
QStringList mSvgFiles;
return QVariant();
}

protected:
QStringList mSvgFiles;
};

class QgsSvgGroupsModel : public QStandardItemModel
{
public:
QgsSvgGroupsModel( QObject* parent ) : QStandardItemModel( parent )
public:
QgsSvgGroupsModel( QObject* parent ) : QStandardItemModel( parent )
{
QStringList svgPaths = QgsApplication::svgPaths();
QStandardItem *parentItem = invisibleRootItem();
Expand Down
51 changes: 29 additions & 22 deletions src/ui/symbollayer/widget_markerline.ui
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,14 @@
<string>Marker placement</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="5" column="1">
<item row="1" column="1">
<widget class="QRadioButton" name="radVertex">
<property name="text">
<string>on every vertex</string>
</property>
</widget>
</item>
<item row="6" column="1">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
Expand Down Expand Up @@ -85,27 +92,6 @@
</item>
</layout>
</item>
<item row="4" column="1">
<widget class="QRadioButton" name="radCentralPoint">
<property name="text">
<string>on central point</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QRadioButton" name="radVertex">
<property name="text">
<string>on every vertex</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QRadioButton" name="radVertexLast">
<property name="text">
<string>on last vertex only</string>
</property>
</widget>
</item>
<item row="0" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
Expand Down Expand Up @@ -176,6 +162,27 @@
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QRadioButton" name="radVertexLast">
<property name="text">
<string>on last vertex only</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QRadioButton" name="radCentralPoint">
<property name="text">
<string>on central point</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QRadioButton" name="radCurvePoint">
<property name="text">
<string>on every curve point</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
Expand Down

0 comments on commit a5a963c

Please sign in to comment.