Skip to content

Commit 646db83

Browse files
committedJul 11, 2013
Make marker line angle calculation more robust against duplicated vertices
1 parent 9486e9f commit 646db83

File tree

2 files changed

+77
-46
lines changed

2 files changed

+77
-46
lines changed
 

‎src/core/symbology-ng/qgslinesymbollayerv2.cpp

Lines changed: 76 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -694,7 +694,6 @@ void QgsMarkerLineSymbolLayerV2::renderPolylineVertex( const QPolygonF& points,
694694
QgsRenderContext& rc = context.renderContext();
695695

696696
double origAngle = mMarker->angle();
697-
double angle;
698697
int i, maxCount;
699698
bool isRing = false;
700699

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

719718
for ( ; i < maxCount; ++i )
720719
{
721-
const QPointF& pt = points[i];
722-
720+
if ( isRing && placement == Vertex && i == points.count() - 1 )
721+
{
722+
continue; // don't draw the last marker - it has been drawn already
723+
}
723724
// rotate marker (if desired)
724725
if ( mRotateMarker )
725726
{
726-
if ( i == 0 )
727+
double angle = markerAngle( points, isRing, i );
728+
mMarker->setAngle( origAngle + angle * 180 / M_PI );
729+
}
730+
731+
mMarker->renderPoint( points.at( i ), context.feature(), rc, -1, context.selected() );
732+
}
733+
734+
// restore original rotation
735+
mMarker->setAngle( origAngle );
736+
}
737+
738+
double QgsMarkerLineSymbolLayerV2::markerAngle( const QPolygonF& points, bool isRing, int vertex )
739+
{
740+
double angle = 0;
741+
const QPointF& pt = points[vertex];
742+
743+
if ( isRing || ( vertex > 0 && vertex < points.count() - 1 ) )
744+
{
745+
int prevIndex = vertex - 1;
746+
int nextIndex = vertex + 1;
747+
748+
if ( isRing && ( vertex == 0 || vertex == points.count() - 1 ) )
749+
{
750+
prevIndex = points.count() - 2;
751+
nextIndex = 1;
752+
}
753+
754+
QPointF prevPoint, nextPoint;
755+
while ( prevIndex >= 0 )
756+
{
757+
prevPoint = points[ prevIndex ];
758+
if ( prevPoint != pt )
759+
{
760+
break;
761+
}
762+
--prevIndex;
763+
}
764+
765+
while ( nextIndex < points.count() )
766+
{
767+
nextPoint = points[ nextIndex ];
768+
if ( nextPoint != pt )
727769
{
728-
if ( !isRing )
770+
break;
771+
}
772+
++nextIndex;
773+
}
774+
775+
if ( prevIndex >= 0 && nextIndex < points.count() )
776+
{
777+
angle = _averageAngle( prevPoint, pt, nextPoint );
778+
}
779+
}
780+
else //no ring and vertex is at start / at end
781+
{
782+
if ( vertex == 0 )
783+
{
784+
while ( vertex < points.size() - 1 )
785+
{
786+
const QPointF& nextPt = points[vertex+1];
787+
if ( pt != nextPt )
729788
{
730-
// use first segment's angle
731-
const QPointF& nextPt = points[i+1];
732-
if ( pt == nextPt )
733-
continue;
734789
angle = MyLine( pt, nextPt ).angle();
790+
return angle;
735791
}
736-
else
737-
{
738-
// closed ring: use average angle between first and last segment
739-
const QPointF& prevPt = points[points.count() - 2];
740-
const QPointF& nextPt = points[1];
741-
if ( prevPt == pt || nextPt == pt )
742-
continue;
743-
744-
angle = _averageAngle( prevPt, pt, nextPt );
745-
}
792+
++vertex;
746793
}
747-
else if ( i == points.count() - 1 )
794+
}
795+
else
796+
{
797+
// use last segment's angle
798+
while ( vertex >= 1 ) //in case of duplicated vertices, take the next suitable one
748799
{
749-
if ( !isRing )
800+
const QPointF& prevPt = points[vertex-1];
801+
if ( pt != prevPt )
750802
{
751-
// use last segment's angle
752-
const QPointF& prevPt = points[i-1];
753-
if ( pt == prevPt )
754-
continue;
755803
angle = MyLine( prevPt, pt ).angle();
804+
return angle;
756805
}
757-
else
758-
{
759-
// don't draw the last marker - it has been drawn already
760-
continue;
761-
}
762-
}
763-
else
764-
{
765-
// use average angle
766-
const QPointF& prevPt = points[i-1];
767-
const QPointF& nextPt = points[i+1];
768-
if ( prevPt == pt || nextPt == pt )
769-
continue;
770-
771-
angle = _averageAngle( prevPt, pt, nextPt );
806+
--vertex;
772807
}
773-
mMarker->setAngle( origAngle + angle * 180 / M_PI );
774808
}
775-
776-
mMarker->renderPoint( points.at( i ), context.feature(), rc, -1, context.selected() );
777809
}
778-
779-
// restore original rotation
780-
mMarker->setAngle( origAngle );
810+
return angle;
781811
}
782812

783813
void QgsMarkerLineSymbolLayerV2::renderPolylineCentral( const QPolygonF& points, QgsSymbolV2RenderContext& context )

‎src/core/symbology-ng/qgslinesymbollayerv2.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ class CORE_EXPORT QgsMarkerLineSymbolLayerV2 : public QgsLineSymbolLayerV2
189189
void renderPolylineInterval( const QPolygonF& points, QgsSymbolV2RenderContext& context );
190190
void renderPolylineVertex( const QPolygonF& points, QgsSymbolV2RenderContext& context, Placement placement = Vertex );
191191
void renderPolylineCentral( const QPolygonF& points, QgsSymbolV2RenderContext& context );
192+
double markerAngle( const QPolygonF& points, bool isRing, int vertex );
192193

193194
bool mRotateMarker;
194195
double mInterval;

0 commit comments

Comments
 (0)
Please sign in to comment.