Navigation Menu

Skip to content

Commit

Permalink
Make marker line angle calculation more robust against duplicated ver…
Browse files Browse the repository at this point in the history
…tices
  • Loading branch information
mhugent committed Jul 11, 2013
1 parent 9486e9f commit 646db83
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 46 deletions.
122 changes: 76 additions & 46 deletions src/core/symbology-ng/qgslinesymbollayerv2.cpp
Expand Up @@ -694,7 +694,6 @@ void QgsMarkerLineSymbolLayerV2::renderPolylineVertex( const QPolygonF& points,
QgsRenderContext& rc = context.renderContext();

double origAngle = mMarker->angle();
double angle;
int i, maxCount;
bool isRing = false;

Expand All @@ -718,66 +717,97 @@ void QgsMarkerLineSymbolLayerV2::renderPolylineVertex( const QPolygonF& points,

for ( ; i < maxCount; ++i )
{
const QPointF& pt = points[i];

if ( isRing && placement == Vertex && i == points.count() - 1 )
{
continue; // don't draw the last marker - it has been drawn already
}
// rotate marker (if desired)
if ( mRotateMarker )
{
if ( i == 0 )
double angle = markerAngle( points, isRing, i );
mMarker->setAngle( origAngle + angle * 180 / M_PI );
}

mMarker->renderPoint( points.at( i ), context.feature(), rc, -1, context.selected() );
}

// restore original rotation
mMarker->setAngle( origAngle );
}

double QgsMarkerLineSymbolLayerV2::markerAngle( const QPolygonF& points, bool isRing, int vertex )
{
double angle = 0;
const QPointF& pt = points[vertex];

if ( isRing || ( vertex > 0 && vertex < points.count() - 1 ) )
{
int prevIndex = vertex - 1;
int nextIndex = vertex + 1;

if ( isRing && ( vertex == 0 || vertex == points.count() - 1 ) )
{
prevIndex = points.count() - 2;
nextIndex = 1;
}

QPointF prevPoint, nextPoint;
while ( prevIndex >= 0 )
{
prevPoint = points[ prevIndex ];
if ( prevPoint != pt )
{
break;
}
--prevIndex;
}

while ( nextIndex < points.count() )
{
nextPoint = points[ nextIndex ];
if ( nextPoint != pt )
{
if ( !isRing )
break;
}
++nextIndex;
}

if ( prevIndex >= 0 && nextIndex < points.count() )
{
angle = _averageAngle( prevPoint, pt, nextPoint );
}
}
else //no ring and vertex is at start / at end
{
if ( vertex == 0 )
{
while ( vertex < points.size() - 1 )
{
const QPointF& nextPt = points[vertex+1];
if ( pt != nextPt )
{
// use first segment's angle
const QPointF& nextPt = points[i+1];
if ( pt == nextPt )
continue;
angle = MyLine( pt, nextPt ).angle();
return angle;
}
else
{
// closed ring: use average angle between first and last segment
const QPointF& prevPt = points[points.count() - 2];
const QPointF& nextPt = points[1];
if ( prevPt == pt || nextPt == pt )
continue;

angle = _averageAngle( prevPt, pt, nextPt );
}
++vertex;
}
else if ( i == points.count() - 1 )
}
else
{
// use last segment's angle
while ( vertex >= 1 ) //in case of duplicated vertices, take the next suitable one
{
if ( !isRing )
const QPointF& prevPt = points[vertex-1];
if ( pt != prevPt )
{
// use last segment's angle
const QPointF& prevPt = points[i-1];
if ( pt == prevPt )
continue;
angle = MyLine( prevPt, pt ).angle();
return angle;
}
else
{
// don't draw the last marker - it has been drawn already
continue;
}
}
else
{
// use average angle
const QPointF& prevPt = points[i-1];
const QPointF& nextPt = points[i+1];
if ( prevPt == pt || nextPt == pt )
continue;

angle = _averageAngle( prevPt, pt, nextPt );
--vertex;
}
mMarker->setAngle( origAngle + angle * 180 / M_PI );
}

mMarker->renderPoint( points.at( i ), context.feature(), rc, -1, context.selected() );
}

// restore original rotation
mMarker->setAngle( origAngle );
return angle;
}

void QgsMarkerLineSymbolLayerV2::renderPolylineCentral( const QPolygonF& points, QgsSymbolV2RenderContext& context )
Expand Down
1 change: 1 addition & 0 deletions src/core/symbology-ng/qgslinesymbollayerv2.h
Expand Up @@ -189,6 +189,7 @@ class CORE_EXPORT QgsMarkerLineSymbolLayerV2 : public QgsLineSymbolLayerV2
void renderPolylineInterval( const QPolygonF& points, QgsSymbolV2RenderContext& context );
void renderPolylineVertex( const QPolygonF& points, QgsSymbolV2RenderContext& context, Placement placement = Vertex );
void renderPolylineCentral( const QPolygonF& points, QgsSymbolV2RenderContext& context );
double markerAngle( const QPolygonF& points, bool isRing, int vertex );

bool mRotateMarker;
double mInterval;
Expand Down

0 comments on commit 646db83

Please sign in to comment.