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() );
189 QPainterPath clipPath;
190 clipPath.addPolygon( points );
195 QList<QPolygonF>::const_iterator it = rings->constBegin();
196 for ( ; it != rings->constEnd(); ++it )
198 QPolygonF ring = *it;
199 clipPath.addPolygon( ring );
204 p->setClipPath( clipPath, Qt::IntersectClip );
210 foreach (
const QPolygonF& ring, *rings )
238 p->setRenderHint( QPainter::Antialiasing,
false );
239 p->drawPolyline( points );
240 p->setRenderHint( QPainter::Antialiasing,
true );
246 p->drawPolyline( points );
251 p->drawPolyline( ::
offsetLine( points, scaledOffset ) );
259 map[
"width"] = QString::number(
mWidth );
264 map[
"offset"] = QString::number(
mOffset );
295 QDomElement symbolizerElem = doc.createElement(
"se:LineSymbolizer" );
296 if ( !props.value(
"uom",
"" ).isEmpty() )
297 symbolizerElem.setAttribute(
"uom", props.value(
"uom",
"" ) );
298 element.appendChild( symbolizerElem );
304 QDomElement strokeElem = doc.createElement(
"se:Stroke" );
305 symbolizerElem.appendChild( strokeElem );
314 QDomElement perpOffsetElem = doc.createElement(
"se:PerpendicularOffset" );
315 perpOffsetElem.appendChild( doc.createTextNode( QString::number(
mOffset ) ) );
316 symbolizerElem.appendChild( perpOffsetElem );
339 QDomElement strokeElem = element.firstChildElement(
"Stroke" );
340 if ( strokeElem.isNull() )
352 &penJoinStyle, &penCapStyle,
353 &customDashVector ) )
357 QDomElement perpOffsetElem = element.firstChildElement(
"PerpendicularOffset" );
358 if ( !perpOffsetElem.isNull() )
361 double d = perpOffsetElem.firstChild().nodeValue().toDouble( &ok );
378 double scaledWidth = 0;
380 if ( strokeWidthExpression )
382 scaledWidth = strokeWidthExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toDouble()
384 pen.setWidthF( scaledWidth );
385 selPen.setWidthF( scaledWidth );
390 pen.setWidthF( scaledWidth );
391 selPen.setWidthF( scaledWidth );
396 if ( strokeColorExpression )
404 if ( lineOffsetExpression )
406 offset = lineOffsetExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toDouble();
411 if ( dashPatternExpression )
413 QVector<qreal> dashVector;
414 QStringList dashList = dashPatternExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toString().split(
";" );
415 QStringList::const_iterator dashIt = dashList.constBegin();
416 for ( ; dashIt != dashList.constEnd(); ++dashIt )
420 pen.setDashPattern( dashVector );
425 if ( joinStyleExpression )
427 QString joinStyleString = joinStyleExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toString();
433 if ( capStyleExpression )
435 QString capStyleString = capStyleExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toString();
468 if ( strokeWidthExpression )
470 width = strokeWidthExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toDouble() * e.mapUnitScaleFactor( e.symbologyScaleDenominator(),
widthUnit(), e.mapUnits() );
477 return width * e.mapUnitScaleFactor( e.symbologyScaleDenominator(),
widthUnit(), e.mapUnits() );
483 if ( strokeColorExpression )
502 if ( p1.x() == p2.x() )
511 mT = float( p2.y() - p1.y() ) / ( p2.x() - p1.x() );
516 double x = ( p2.x() - p1.x() );
517 double y = ( p2.y() - p1.y() );
518 mLength = sqrt( x * x + y * y );
535 return (
mIncreasing ? QPointF( 0, interval ) : QPointF( 0, -interval ) );
537 double alpha = atan(
mT );
538 double dx = cos( alpha ) * interval;
539 double dy = sin( alpha ) * interval;
540 return (
mIncreasing ? QPointF( dx, dy ) : QPointF( -dx, -dy ) );
576 if ( props.contains(
"interval" ) )
577 interval = props[
"interval"].toDouble();
578 if ( props.contains(
"rotate" ) )
579 rotate = ( props[
"rotate"] ==
"1" );
582 if ( props.contains(
"offset" ) )
584 x->
setOffset( props[
"offset"].toDouble() );
586 if ( props.contains(
"offset_unit" ) )
590 if ( props.contains(
"interval_unit" ) )
595 if ( props.contains(
"placement" ) )
597 if ( props[
"placement"] ==
"vertex" )
599 else if ( props[
"placement"] ==
"lastvertex" )
601 else if ( props[
"placement"] ==
"firstvertex" )
603 else if ( props[
"placement"] ==
"centralpoint" )
610 if ( props.contains(
"interval_expression" ) )
614 if ( props.contains(
"offset_expression" ) )
618 if ( props.contains(
"placement_expression" ) )
664 if ( offsetExpression )
666 offset = offsetExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toDouble();
671 if ( placementExpression )
673 QString placementString = placementExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toString();
674 if ( placementString.compare(
"vertex", Qt::CaseInsensitive ) == 0 )
678 else if ( placementString.compare(
"lastvertex", Qt::CaseInsensitive ) == 0 )
682 else if ( placementString.compare(
"firstvertex", Qt::CaseInsensitive ) == 0 )
686 else if ( placementString.compare(
"centerpoint", Qt::CaseInsensitive ) == 0 )
719 if ( points.isEmpty() )
722 QPointF lastPt = points[0];
723 double lengthLeft = 0;
731 if ( intervalExpression )
733 interval = intervalExpression->
evaluate( const_cast<QgsFeature*>( context.
feature() ) ).toDouble();
742 for (
int i = 1; i < points.count(); ++i )
744 const QPointF& pt = points[i];
755 double c = 1 - lengthLeft / painterUnitInterval;
773 while ( lengthLeft > painterUnitInterval )
777 lengthLeft -= painterUnitInterval;
790 static double _averageAngle(
const QPointF& prevPt,
const QPointF& pt,
const QPointF& nextPt )
795 double unitX = cos( a1 ) + cos( a2 ), unitY = sin( a1 ) + sin( a2 );
797 return atan2( unitY, unitX );
802 if ( points.isEmpty() )
818 i = points.count() - 1;
819 maxCount = points.count();
824 maxCount = points.count();
825 if ( points.first() == points.last() )
829 for ( ; i < maxCount; ++i )
831 if ( isRing && placement ==
Vertex && i == points.count() - 1 )
852 const QPointF& pt = points[vertex];
854 if ( isRing || ( vertex > 0 && vertex < points.count() - 1 ) )
856 int prevIndex = vertex - 1;
857 int nextIndex = vertex + 1;
859 if ( isRing && ( vertex == 0 || vertex == points.count() - 1 ) )
861 prevIndex = points.count() - 2;
865 QPointF prevPoint, nextPoint;
866 while ( prevIndex >= 0 )
868 prevPoint = points[ prevIndex ];
869 if ( prevPoint != pt )
876 while ( nextIndex < points.count() )
878 nextPoint = points[ nextIndex ];
879 if ( nextPoint != pt )
886 if ( prevIndex >= 0 && nextIndex < points.count() )
895 while ( vertex < points.size() - 1 )
897 const QPointF& nextPt = points[vertex+1];
909 while ( vertex >= 1 )
911 const QPointF& prevPt = points[vertex-1];
926 if ( points.size() > 0 )
930 QPolygonF::const_iterator it = points.constBegin();
932 for ( ++it; it != points.constEnd(); ++it )
934 length += sqrt(( last.x() - it->x() ) * ( last.x() - it->x() ) +
935 ( last.y() - it->y() ) * ( last.y() - it->y() ) );
940 it = points.constBegin();
942 qreal last_at = 0, next_at = 0;
945 for ( ++it; it != points.constEnd(); ++it )
948 next_at += sqrt(( last.x() - it->x() ) * ( last.x() - it->x() ) +
949 ( last.y() - it->y() ) * ( last.y() - it->y() ) );
950 if ( next_at >= length / 2 )
959 qreal k = ( length * 0.5 - last_at ) / ( next_at - last_at );
960 QPointF pt = last + ( next - last ) * k;
977 map[
"interval"] = QString::number(
mInterval );
978 map[
"offset"] = QString::number(
mOffset );
982 map[
"placement"] =
"vertex";
984 map[
"placement"] =
"lastvertex";
986 map[
"placement"] =
"firstvertex";
988 map[
"placement"] =
"centralpoint";
990 map[
"placement"] =
"interval";
1031 QDomElement symbolizerElem = doc.createElement(
"se:LineSymbolizer" );
1032 if ( !props.value(
"uom",
"" ).isEmpty() )
1033 symbolizerElem.setAttribute(
"uom", props.value(
"uom",
"" ) );
1034 element.appendChild( symbolizerElem );
1068 QDomElement strokeElem = doc.createElement(
"se:Stroke" );
1069 symbolizerElem.appendChild( strokeElem );
1072 QDomElement graphicStrokeElem = doc.createElement(
"se:GraphicStroke" );
1073 strokeElem.appendChild( graphicStrokeElem );
1079 graphicStrokeElem.appendChild( doc.createComment( QString(
"MarkerSymbolLayerV2 expected, %1 found. Skip it." ).arg( markerLayer->
layerType() ) ) );
1086 if ( !gap.isEmpty() )
1088 QDomElement gapElem = doc.createElement(
"se:Gap" );
1090 graphicStrokeElem.appendChild( gapElem );
1095 QDomElement perpOffsetElem = doc.createElement(
"se:PerpendicularOffset" );
1096 perpOffsetElem.appendChild( doc.createTextNode( QString::number(
mOffset ) ) );
1097 symbolizerElem.appendChild( perpOffsetElem );
1106 QDomElement strokeElem = element.firstChildElement(
"Stroke" );
1107 if ( strokeElem.isNull() )
1110 QDomElement graphicStrokeElem = strokeElem.firstChildElement(
"GraphicStroke" );
1111 if ( graphicStrokeElem.isNull() )
1119 for ( QgsStringMap::iterator it = vendorOptions.begin(); it != vendorOptions.end(); ++it )
1121 if ( it.key() ==
"placement" )
1123 if ( it.value() ==
"points" ) placement =
Vertex;
1124 else if ( it.value() ==
"firstPoint" ) placement =
FirstVertex;
1125 else if ( it.value() ==
"lastPoint" ) placement =
LastVertex;
1126 else if ( it.value() ==
"centralPoint" ) placement =
CentralPoint;
1128 else if ( it.value() ==
"rotateMarker" )
1130 rotateMarker = it.value() ==
"0";
1148 QDomElement gapElem = graphicStrokeElem.firstChildElement(
"Gap" );
1149 if ( !gapElem.isNull() )
1152 double d = gapElem.firstChild().nodeValue().toDouble( &ok );
1158 QDomElement perpOffsetElem = graphicStrokeElem.firstChildElement(
"PerpendicularOffset" );
1159 if ( !perpOffsetElem.isNull() )
1162 double d = perpOffsetElem.firstChild().nodeValue().toDouble( &ok );
static double _averageAngle(const QPointF &prevPt, const QPointF &pt, const QPointF &nextPt)
void setIntervalUnit(QgsSymbolV2::OutputUnit unit)
static QString encodeOutputUnit(QgsSymbolV2::OutputUnit unit)
void renderPolygonOutline(const QPolygonF &points, QList< QPolygonF > *rings, QgsSymbolV2RenderContext &context)
double estimateMaxBleed() const
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape...
Class for parsing and evaluation of expressions (formerly called "search strings").
#define DEFAULT_SIMPLELINE_PENSTYLE
void startRender(QgsSymbolV2RenderContext &context)
#define DEFAULT_MARKERLINE_ROTATE
float threshold() const
Gets the simplification threshold of the vector layer managed.
virtual double width() const
double markerAngle(const QPolygonF &points, bool isRing, int vertex)
#define DEFAULT_MARKERLINE_INTERVAL
QVariant evaluate(const QgsFeature *f=NULL)
Evaluate the feature and return the result.
QColor selectionColor() const
Added in QGIS v2.0.
QgsSymbolV2 * subSymbol()
void setCustomDashPatternUnit(QgsSymbolV2::OutputUnit unit)
double rendererScale() const
static QgsStringMap getVendorOptionList(QDomElement &element)
const QgsVectorSimplifyMethod & simplifyMethod() const
Returns the simplification settings for fast rendering of features.
void setUseCustomDashPattern(bool b)
static QVector< qreal > decodeRealVector(const QString &s)
void renderPolylineInterval(const QPolygonF &points, QgsSymbolV2RenderContext &context)
QVector< qreal > customDashVector() const
void setPenJoinStyle(Qt::PenJoinStyle style)
void setOffsetUnit(QgsSymbolV2::OutputUnit unit)
QgsSymbolV2::OutputUnit outputUnit() const
QgsSymbolV2::OutputUnit outputUnit() const
static QDomElement createVendorOptionElement(QDomDocument &doc, QString name, QString value)
Qt::PenCapStyle mPenCapStyle
static QColor decodeColor(QString str)
QgsSymbolLayerV2 * clone() const
static const bool selectionIsOpaque
bool setSubSymbol(QgsSymbolV2 *symbol)
QVector< qreal > dxfCustomDashPattern(QgsSymbolV2::OutputUnit &unit) const
void renderPolyline(const QPolygonF &points, QgsSymbolV2RenderContext &context)
QString layerType() const
QMap< QString, QString > QgsStringMap
QString layerType() const
bool qgsDoubleNear(double a, double b, double epsilon=4 *DBL_EPSILON)
Qt::PenStyle penStyle() const
void setWidthUnit(QgsSymbolV2::OutputUnit unit)
static QString encodeColor(QColor color)
void setInterval(double interval)
virtual QgsExpression * expression(const QString &property) const
QgsSymbolV2::OutputUnit mOffsetUnit
qreal alpha() const
Get alpha transparency 1 for opaque, 0 for invisible.
bool mUseCustomDashPattern
void setDrawInsidePolygon(bool drawInsidePolygon)
static QString encodePenStyle(Qt::PenStyle style)
QPointF diffForInterval(double interval)
virtual void prepareExpressions(const QgsVectorLayer *vl, double scale=-1.0)
void setColor(const QColor &color)
QgsSymbolV2::OutputUnit mIntervalUnit
virtual void writeSldMarker(QDomDocument &doc, QDomElement &element, QgsStringMap props) const
static QgsSymbolLayerV2 * createMarkerLayerFromSld(QDomElement &element)
QgsStringMap properties() const
bool simplifyDrawingCanbeApplied(const QgsRenderContext &renderContext, QgsVectorSimplifyMethod::SimplifyHint simplifyHint) const
Returns whether the VectorLayer can apply the specified simplification hint.
static QString ogrFeatureStylePen(double width, double mmScaleFactor, double mapUnitsScaleFactor, const QColor &c, Qt::PenJoinStyle joinStyle=Qt::MiterJoin, Qt::PenCapStyle capStyle=Qt::FlatCap, double offset=0.0, const QVector< qreal > *dashPattern=0)
Create ogr feature style string for pen.
const QgsFeature * feature() const
The geometries can be rendered with 'AntiAliasing' disabled because of it is '1-pixel size'...
Qt::PenJoinStyle mPenJoinStyle
static Qt::PenCapStyle decodePenCapStyle(QString str)
static QgsSymbolLayerV2 * create(const QgsStringMap &properties=QgsStringMap())
static Qt::PenStyle decodePenStyle(QString str)
QgsSymbolV2::OutputUnit mWidthUnit
static bool createFunctionElement(QDomDocument &doc, QDomElement &element, QString function)
QVector< qreal > mCustomDashVector
Vector with an even number of entries for the.
#define DEFAULT_SIMPLELINE_WIDTH
static QString encodePenJoinStyle(Qt::PenJoinStyle style)
static QgsSymbolLayerV2 * createFromSld(QDomElement &element)
void setAngle(double angle)
bool rotateMarker() const
#define DEFAULT_SIMPLELINE_CAPSTYLE
#define DEFAULT_SIMPLELINE_JOINSTYLE
void setOutputUnit(QgsSymbolV2::OutputUnit unit)
void setSize(double size)
double rasterScaleFactor() const
void startRender(QgsSymbolV2RenderContext &context)
virtual QColor color() const
QString ogrFeatureStyle(double mmScaleFactor, double mapUnitScaleFactor) const
void setOffset(double offset)
void renderPoint(const QPointF &point, const QgsFeature *f, QgsRenderContext &context, int layer=-1, bool selected=false)
QgsStringMap properties() const
void setPenCapStyle(Qt::PenCapStyle style)
void setCustomDashVector(const QVector< qreal > &vector)
static QgsSymbolLayerV2 * create(const QgsStringMap &properties=QgsStringMap())
QgsMarkerSymbolV2 * mMarker
double ANALYSIS_EXPORT angle(Point3D *p1, Point3D *p2, Point3D *p3, Point3D *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
void setOffset(double offset)
virtual void setWidth(double width)
void setColor(const QColor &color)
static QString encodeRealVector(const QVector< qreal > &v)
QgsSymbolV2::OutputUnit mCustomDashPatternUnit
virtual QString layerType() const =0
void renderPolyline(const QPolygonF &points, QgsSymbolV2RenderContext &context)
QgsSymbolLayerV2 * clone() const
~QgsMarkerLineSymbolLayerV2()
static QgsSymbolLayerV2 * createFromSld(QDomElement &element)
void applyDataDefinedSymbology(QgsSymbolV2RenderContext &context, QPen &pen, QPen &selPen, double &offset)
static void lineToSld(QDomDocument &doc, QDomElement &element, Qt::PenStyle penStyle, QColor color, double width=-1, const Qt::PenJoinStyle *penJoinStyle=0, const Qt::PenCapStyle *penCapStyle=0, const QVector< qreal > *customDashPattern=0, double dashOffset=0.0)
#define DEFAULT_SIMPLELINE_COLOR
static void createGeometryElement(QDomDocument &doc, QDomElement &element, QString geomFunc)
Contains information about the context of a rendering operation.
void stopRender(QgsRenderContext &context)
QgsSimpleLineSymbolLayerV2(QColor color=DEFAULT_SIMPLELINE_COLOR, double width=DEFAULT_SIMPLELINE_WIDTH, Qt::PenStyle penStyle=DEFAULT_SIMPLELINE_PENSTYLE)
void stopRender(QgsSymbolV2RenderContext &context)
void setPlacement(Placement p)
void toSld(QDomDocument &doc, QDomElement &element, QgsStringMap props) const
virtual QgsSymbolV2 * clone() const
QList< QgsSymbolLayerV2 * > QgsSymbolLayerV2List
virtual double width() const
double dxfWidth(const QgsDxfExport &e, const QgsSymbolV2RenderContext &context) const
QgsRenderContext & renderContext()
void startRender(QgsRenderContext &context, const QgsVectorLayer *layer=0)
double estimateMaxBleed() const
Returns the estimated maximum distance which the layer style will bleed outside the drawn shape...
static double lineWidthScaleFactor(const QgsRenderContext &c, QgsSymbolV2::OutputUnit u)
Returns the line width scale factor depending on the unit and the paint device.
void setRenderHints(int hints)
static Qt::PenJoinStyle decodePenJoinStyle(QString str)
void setOutputUnit(QgsSymbolV2::OutputUnit unit)
MyLine(QPointF p1, QPointF p2)
Placement placement() const
void toSld(QDomDocument &doc, QDomElement &element, QgsStringMap props) const
QgsSymbolV2::OutputUnit mOffsetUnit
QPolygonF offsetLine(QPolygonF polyline, double dist)
calculate line shifted by a specified distance
QgsSymbolLayerV2 * symbolLayer(int layer)
Qt::PenStyle dxfPenStyle() const
static bool lineFromSld(QDomElement &element, Qt::PenStyle &penStyle, QColor &color, double &width, Qt::PenJoinStyle *penJoinStyle=0, Qt::PenCapStyle *penCapStyle=0, QVector< qreal > *customDashPattern=0, double *dashOffset=0)
QgsMarkerLineSymbolLayerV2(bool rotateMarker=DEFAULT_MARKERLINE_ROTATE, double interval=DEFAULT_MARKERLINE_INTERVAL)
void saveDataDefinedProperties(QgsStringMap &stringMap) const
Saves data defined properties to string map.
void setOffsetUnit(QgsSymbolV2::OutputUnit unit)
void setAlpha(qreal alpha)
Set alpha transparency 1 for opaque, 0 for invisible.
void renderPolylineCentral(const QPolygonF &points, QgsSymbolV2RenderContext &context)
QColor dxfColor(const QgsSymbolV2RenderContext &context) const
static bool canbeGeneralizedByDeviceBoundingBox(const QgsRectangle &envelope, float mapToPixelTol=1.0f)
Returns whether the device-envelope can be replaced by its BBOX when is applied the specified toleran...
void stopRender(QgsSymbolV2RenderContext &context)
QgsSymbolV2::OutputUnit widthUnit() const
static QgsSymbolV2::OutputUnit decodeOutputUnit(QString str)
Qt::PenJoinStyle penJoinStyle() const
void renderPolylineVertex(const QPolygonF &points, QgsSymbolV2RenderContext &context, Placement placement=Vertex)
void copyDataDefinedProperties(QgsSymbolLayerV2 *destLayer) const
Copies data defined properties of this layer to another symbol layer.
Qt::PenCapStyle penCapStyle() const
const QgsVectorLayer * layer() const
static QString encodePenCapStyle(Qt::PenCapStyle style)
virtual void setDataDefinedProperty(const QString &property, const QString &expressionString)