17 #include "qgsdxfexport.h"
26 #include <QDomDocument>
27 #include <QDomElement>
33 mUseCustomDashPattern( false ), mCustomDashPatternUnit(
QgsSymbolV2::MM ), mDrawInsidePolygon( false )
64 if ( props.contains(
"color" ) )
66 if ( props.contains(
"width" ) )
67 width = props[
"width"].toDouble();
68 if ( props.contains(
"penstyle" ) )
73 if ( props.contains(
"width_unit" ) )
75 if ( props.contains(
"offset" ) )
76 l->
setOffset( props[
"offset"].toDouble() );
77 if ( props.contains(
"offset_unit" ) )
79 if ( props.contains(
"joinstyle" ) )
81 if ( props.contains(
"capstyle" ) )
84 if ( props.contains(
"use_custom_dash" ) )
88 if ( props.contains(
"customdash" ) )
92 if ( props.contains(
"customdash_unit" ) )
97 if ( props.contains(
"draw_inside_polygon" ) )
103 if ( props.contains(
"color_expression" ) )
105 if ( props.contains(
"width_expression" ) )
107 if ( props.contains(
"offset_expression" ) )
109 if ( props.contains(
"customdash_expression" ) )
111 if ( props.contains(
"joinstyle_expression" ) )
113 if ( props.contains(
"capstyle_expression" ) )
128 penColor.setAlphaF(
mColor.alphaF() * context.
alpha() );
129 mPen.setColor( penColor );
131 mPen.setWidthF( scaledWidth );
134 mPen.setStyle( Qt::CustomDashLine );
137 double dashWidthDiv = scaledWidth;
139 QStringList versionSplit = QString( qVersion() ).split(
"." );
140 if ( versionSplit.size() > 1
141 && versionSplit.at( 1 ).toInt() >= 8
146 QVector<qreal> scaledVector;
153 mPen.setDashPattern( scaledVector );
165 selColor.setAlphaF( context.
alpha() );
193 p->setRenderHint( QPainter::Antialiasing,
false );
194 p->drawPolyline( points );
195 p->setRenderHint( QPainter::Antialiasing,
true );
203 QPainterPath clipPath;
204 clipPath.addPolygon( points );
205 p->setClipPath( clipPath, Qt::IntersectClip );
210 p->drawPolyline( points );
215 p->drawPolyline( ::
offsetLine( points, scaledOffset ) );
229 map[
"width"] = QString::number(
mWidth );
234 map[
"offset"] = QString::number(
mOffset );
265 QDomElement symbolizerElem = doc.createElement(
"se:LineSymbolizer" );
266 if ( !props.value(
"uom",
"" ).isEmpty() )
267 symbolizerElem.setAttribute(
"uom", props.value(
"uom",
"" ) );
268 element.appendChild( symbolizerElem );
274 QDomElement strokeElem = doc.createElement(
"se:Stroke" );
275 symbolizerElem.appendChild( strokeElem );
284 QDomElement perpOffsetElem = doc.createElement(
"se:PerpendicularOffset" );
285 perpOffsetElem.appendChild( doc.createTextNode( QString::number(
mOffset ) ) );
286 symbolizerElem.appendChild( perpOffsetElem );
309 QDomElement strokeElem = element.firstChildElement(
"Stroke" );
310 if ( strokeElem.isNull() )
322 &penJoinStyle, &penCapStyle,
323 &customDashVector ) )
327 QDomElement perpOffsetElem = element.firstChildElement(
"PerpendicularOffset" );
328 if ( !perpOffsetElem.isNull() )
331 double d = perpOffsetElem.firstChild().nodeValue().toDouble( &ok );
348 double scaledWidth = 0;
350 if ( strokeWidthExpression )
352 scaledWidth = strokeWidthExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toDouble()
354 pen.setWidthF( scaledWidth );
355 selPen.setWidthF( scaledWidth );
360 pen.setWidthF( scaledWidth );
361 selPen.setWidthF( scaledWidth );
366 if ( strokeColorExpression )
374 if ( lineOffsetExpression )
376 offset = lineOffsetExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toDouble();
381 if ( dashPatternExpression )
383 QVector<qreal> dashVector;
384 QStringList dashList = dashPatternExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toString().split(
";" );
385 QStringList::const_iterator dashIt = dashList.constBegin();
386 for ( ; dashIt != dashList.constEnd(); ++dashIt )
390 pen.setDashPattern( dashVector );
395 if ( joinStyleExpression )
397 QString joinStyleString = joinStyleExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toString();
403 if ( capStyleExpression )
405 QString capStyleString = capStyleExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toString();
438 if ( strokeWidthExpression )
440 width = strokeWidthExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toDouble() * e.mapUnitScaleFactor( e.symbologyScaleDenominator(),
widthUnit(), e.mapUnits() );
447 return width * e.mapUnitScaleFactor( e.symbologyScaleDenominator(),
widthUnit(), e.mapUnits() );
453 if ( strokeColorExpression )
472 if ( p1.x() == p2.x() )
481 mT = float( p2.y() - p1.y() ) / ( p2.x() - p1.x() );
486 double x = ( p2.x() - p1.x() );
487 double y = ( p2.y() - p1.y() );
488 mLength = sqrt( x * x + y * y );
505 return (
mIncreasing ? QPointF( 0, interval ) : QPointF( 0, -interval ) );
507 double alpha = atan(
mT );
508 double dx = cos( alpha ) * interval;
509 double dy = sin( alpha ) * interval;
510 return (
mIncreasing ? QPointF( dx, dy ) : QPointF( -dx, -dy ) );
546 if ( props.contains(
"interval" ) )
547 interval = props[
"interval"].toDouble();
548 if ( props.contains(
"rotate" ) )
549 rotate = ( props[
"rotate"] ==
"1" );
552 if ( props.contains(
"offset" ) )
554 x->
setOffset( props[
"offset"].toDouble() );
556 if ( props.contains(
"offset_unit" ) )
560 if ( props.contains(
"interval_unit" ) )
565 if ( props.contains(
"placement" ) )
567 if ( props[
"placement"] ==
"vertex" )
569 else if ( props[
"placement"] ==
"lastvertex" )
571 else if ( props[
"placement"] ==
"firstvertex" )
573 else if ( props[
"placement"] ==
"centralpoint" )
580 if ( props.contains(
"interval_expression" ) )
584 if ( props.contains(
"offset_expression" ) )
588 if ( props.contains(
"placement_expression" ) )
634 if ( offsetExpression )
636 offset = offsetExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toDouble();
641 if ( placementExpression )
643 QString placementString = placementExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toString();
644 if ( placementString.compare(
"vertex", Qt::CaseInsensitive ) == 0 )
648 else if ( placementString.compare(
"lastvertex", Qt::CaseInsensitive ) == 0 )
652 else if ( placementString.compare(
"firstvertex", Qt::CaseInsensitive ) == 0 )
656 else if ( placementString.compare(
"centerpoint", Qt::CaseInsensitive ) == 0 )
689 if ( points.isEmpty() )
692 QPointF lastPt = points[0];
693 double lengthLeft = 0;
701 if ( intervalExpression )
703 interval = intervalExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toDouble();
712 for (
int i = 1; i < points.count(); ++i )
714 const QPointF& pt = points[i];
725 double c = 1 - lengthLeft / painterUnitInterval;
743 while ( lengthLeft > painterUnitInterval )
747 lengthLeft -= painterUnitInterval;
760 static double _averageAngle(
const QPointF& prevPt,
const QPointF& pt,
const QPointF& nextPt )
765 double unitX = cos( a1 ) + cos( a2 ), unitY = sin( a1 ) + sin( a2 );
767 return atan2( unitY, unitX );
772 if ( points.isEmpty() )
788 i = points.count() - 1;
789 maxCount = points.count();
794 maxCount = points.count();
795 if ( points.first() == points.last() )
799 for ( ; i < maxCount; ++i )
801 if ( isRing && placement ==
Vertex && i == points.count() - 1 )
822 const QPointF& pt = points[vertex];
824 if ( isRing || ( vertex > 0 && vertex < points.count() - 1 ) )
826 int prevIndex = vertex - 1;
827 int nextIndex = vertex + 1;
829 if ( isRing && ( vertex == 0 || vertex == points.count() - 1 ) )
831 prevIndex = points.count() - 2;
835 QPointF prevPoint, nextPoint;
836 while ( prevIndex >= 0 )
838 prevPoint = points[ prevIndex ];
839 if ( prevPoint != pt )
846 while ( nextIndex < points.count() )
848 nextPoint = points[ nextIndex ];
849 if ( nextPoint != pt )
856 if ( prevIndex >= 0 && nextIndex < points.count() )
865 while ( vertex < points.size() - 1 )
867 const QPointF& nextPt = points[vertex+1];
879 while ( vertex >= 1 )
881 const QPointF& prevPt = points[vertex-1];
896 if ( points.size() > 0 )
900 QPolygonF::const_iterator it = points.constBegin();
902 for ( ++it; it != points.constEnd(); ++it )
904 length += sqrt(( last.x() - it->x() ) * ( last.x() - it->x() ) +
905 ( last.y() - it->y() ) * ( last.y() - it->y() ) );
910 it = points.constBegin();
912 qreal last_at = 0, next_at = 0;
915 for ( ++it; it != points.constEnd(); ++it )
918 next_at += sqrt(( last.x() - it->x() ) * ( last.x() - it->x() ) +
919 ( last.y() - it->y() ) * ( last.y() - it->y() ) );
920 if ( next_at >= length / 2 )
929 qreal k = ( length * 0.5 - last_at ) / ( next_at - last_at );
930 QPointF pt = last + ( next - last ) * k;
947 map[
"interval"] = QString::number(
mInterval );
948 map[
"offset"] = QString::number(
mOffset );
952 map[
"placement"] =
"vertex";
954 map[
"placement"] =
"lastvertex";
956 map[
"placement"] =
"firstvertex";
958 map[
"placement"] =
"centralpoint";
960 map[
"placement"] =
"interval";
1001 QDomElement symbolizerElem = doc.createElement(
"se:LineSymbolizer" );
1002 if ( !props.value(
"uom",
"" ).isEmpty() )
1003 symbolizerElem.setAttribute(
"uom", props.value(
"uom",
"" ) );
1004 element.appendChild( symbolizerElem );
1038 QDomElement strokeElem = doc.createElement(
"se:Stroke" );
1039 symbolizerElem.appendChild( strokeElem );
1042 QDomElement graphicStrokeElem = doc.createElement(
"se:GraphicStroke" );
1043 strokeElem.appendChild( graphicStrokeElem );
1049 graphicStrokeElem.appendChild( doc.createComment( QString(
"MarkerSymbolLayerV2 expected, %1 found. Skip it." ).arg( markerLayer->
layerType() ) ) );
1056 if ( !gap.isEmpty() )
1058 QDomElement gapElem = doc.createElement(
"se:Gap" );
1060 graphicStrokeElem.appendChild( gapElem );
1065 QDomElement perpOffsetElem = doc.createElement(
"se:PerpendicularOffset" );
1066 perpOffsetElem.appendChild( doc.createTextNode( QString::number(
mOffset ) ) );
1067 symbolizerElem.appendChild( perpOffsetElem );
1076 QDomElement strokeElem = element.firstChildElement(
"Stroke" );
1077 if ( strokeElem.isNull() )
1080 QDomElement graphicStrokeElem = strokeElem.firstChildElement(
"GraphicStroke" );
1081 if ( graphicStrokeElem.isNull() )
1089 for ( QgsStringMap::iterator it = vendorOptions.begin(); it != vendorOptions.end(); ++it )
1091 if ( it.key() ==
"placement" )
1093 if ( it.value() ==
"points" ) placement =
Vertex;
1094 else if ( it.value() ==
"firstPoint" ) placement =
FirstVertex;
1095 else if ( it.value() ==
"lastPoint" ) placement =
LastVertex;
1096 else if ( it.value() ==
"centralPoint" ) placement =
CentralPoint;
1098 else if ( it.value() ==
"rotateMarker" )
1100 rotateMarker = it.value() ==
"0";
1118 QDomElement gapElem = graphicStrokeElem.firstChildElement(
"Gap" );
1119 if ( !gapElem.isNull() )
1122 double d = gapElem.firstChild().nodeValue().toDouble( &ok );
1128 QDomElement perpOffsetElem = graphicStrokeElem.firstChildElement(
"PerpendicularOffset" );
1129 if ( !perpOffsetElem.isNull() )
1132 double d = perpOffsetElem.firstChild().nodeValue().toDouble( &ok );