1 /*************************************************************************** 2 qgslinesymbollayer.h 3 --------------------- 4 begin : November 2009 5 copyright : (C) 2009 by Martin Dobias 6 email : wonder dot sk at gmail dot com 7 *************************************************************************** 8 * * 9 * This program is free software; you can redistribute it and/or modify * 10 * it under the terms of the GNU General Public License as published by * 11 * the Free Software Foundation; either version 2 of the License, or * 12 * (at your option) any later version. * 13 * * 14 ***************************************************************************/ 15 16 #ifndef QGSLINESYMBOLLAYER_H 17 #define QGSLINESYMBOLLAYER_H 18 19 #include "qgis_core.h" 20 #include "qgis.h" 21 #include "qgssymbollayer.h" 22 23 #include <QPen> 24 #include <QVector> 25 26 class QgsExpression; 27 class QgsMarkerSymbol; 28 class QgsLineSymbol; 29 30 #define DEFAULT_SIMPLELINE_COLOR QColor(35,35,35) 31 #define DEFAULT_SIMPLELINE_WIDTH DEFAULT_LINE_WIDTH 32 #define DEFAULT_SIMPLELINE_PENSTYLE Qt::SolidLine 33 #define DEFAULT_SIMPLELINE_JOINSTYLE Qt::BevelJoin 34 #define DEFAULT_SIMPLELINE_CAPSTYLE Qt::SquareCap 35 36 /** 37 * \ingroup core 38 * \class QgsSimpleLineSymbolLayer 39 * \brief A simple line symbol layer, which renders lines using a line in a variety of styles (e.g. solid, dotted, dashed). 40 */ 41 class CORE_EXPORT QgsSimpleLineSymbolLayer : public QgsLineSymbolLayer 42 { 43 public: 44 45 /** 46 * Constructor for QgsSimpleLineSymbolLayer. Creates a simple line 47 * symbol in the specified \a color, \a width (in millimeters) 48 * and \a penStyle. 49 */ 50 QgsSimpleLineSymbolLayer( const QColor &color = DEFAULT_SIMPLELINE_COLOR, 51 double width = DEFAULT_SIMPLELINE_WIDTH, 52 Qt::PenStyle penStyle = DEFAULT_SIMPLELINE_PENSTYLE ); 53 54 ~QgsSimpleLineSymbolLayer() override; 55 56 // static stuff 57 58 /** 59 * Creates a new QgsSimpleLineSymbolLayer, using the settings 60 * serialized in the \a properties map (corresponding to the output from 61 * QgsSimpleLineSymbolLayer::properties() ). 62 */ 63 static QgsSymbolLayer *create( const QVariantMap &properties = QVariantMap() ) SIP_FACTORY; 64 65 /** 66 * Creates a new QgsSimpleLineSymbolLayer from an SLD XML DOM \a element. 67 */ 68 static QgsSymbolLayer *createFromSld( QDomElement &element ) SIP_FACTORY; 69 70 QString layerType() const override; 71 void startRender( QgsSymbolRenderContext &context ) override; 72 void stopRender( QgsSymbolRenderContext &context ) override; 73 void renderPolyline( const QPolygonF &points, QgsSymbolRenderContext &context ) override; 74 //overridden so that clip path can be set when using draw inside polygon option 75 void renderPolygonStroke( const QPolygonF &points, const QVector<QPolygonF> *rings, QgsSymbolRenderContext &context ) override; 76 QVariantMap properties() const override; 77 QgsSimpleLineSymbolLayer *clone() const override SIP_FACTORY; 78 void toSld( QDomDocument &doc, QDomElement &element, const QVariantMap &props ) const override; 79 QString ogrFeatureStyle( double mmScaleFactor, double mapUnitScaleFactor ) const override; 80 void setOutputUnit( QgsUnitTypes::RenderUnit unit ) override; 81 QgsUnitTypes::RenderUnit outputUnit() const override; 82 bool usesMapUnits() const override; 83 void setMapUnitScale( const QgsMapUnitScale &scale ) override; 84 QgsMapUnitScale mapUnitScale() const override; 85 double estimateMaxBleed( const QgsRenderContext &context ) const override; 86 QVector<qreal> dxfCustomDashPattern( QgsUnitTypes::RenderUnit &unit ) const override; 87 Qt::PenStyle dxfPenStyle() const override; 88 double dxfWidth( const QgsDxfExport &e, QgsSymbolRenderContext &context ) const override; 89 double dxfOffset( const QgsDxfExport &e, QgsSymbolRenderContext &context ) const override; 90 QColor dxfColor( QgsSymbolRenderContext &context ) const override; 91 bool canCauseArtifactsBetweenAdjacentTiles() const override; 92 93 /** 94 * Returns the pen style used to render the line (e.g. solid, dashed, etc). 95 * 96 * \see setPenStyle() 97 */ penStyle()98 Qt::PenStyle penStyle() const { return mPenStyle; } 99 100 /** 101 * Sets the pen \a style used to render the line (e.g. solid, dashed, etc). 102 * 103 * \see penStyle() 104 */ setPenStyle(Qt::PenStyle style)105 void setPenStyle( Qt::PenStyle style ) { mPenStyle = style; } 106 107 /** 108 * Returns the pen join style used to render the line (e.g. miter, bevel, round, etc). 109 * 110 * \see setPenJoinStyle() 111 */ penJoinStyle()112 Qt::PenJoinStyle penJoinStyle() const { return mPenJoinStyle; } 113 114 /** 115 * Sets the pen join \a style used to render the line (e.g. miter, bevel, round, etc). 116 * 117 * \see penJoinStyle() 118 */ setPenJoinStyle(Qt::PenJoinStyle style)119 void setPenJoinStyle( Qt::PenJoinStyle style ) { mPenJoinStyle = style; } 120 121 /** 122 * Returns the pen cap style used to render the line (e.g. flat, square, round, etc). 123 * 124 * \see setPenCapStyle() 125 */ penCapStyle()126 Qt::PenCapStyle penCapStyle() const { return mPenCapStyle; } 127 128 /** 129 * Sets the pen cap \a style used to render the line (e.g. flat, square, round, etc). 130 * 131 * \see penCapStyle() 132 */ setPenCapStyle(Qt::PenCapStyle style)133 void setPenCapStyle( Qt::PenCapStyle style ) { mPenCapStyle = style; } 134 135 /** 136 * Returns TRUE if the line uses a custom dash pattern. 137 * \see setUseCustomDashPattern() 138 * \see customDashPatternUnit() 139 * \see customDashVector() 140 */ useCustomDashPattern()141 bool useCustomDashPattern() const { return mUseCustomDashPattern; } 142 143 /** 144 * Sets whether the line uses a custom dash pattern. 145 * \see useCustomDashPattern() 146 * \see setCustomDashPatternUnit() 147 * \see setCustomDashVector() 148 */ setUseCustomDashPattern(bool b)149 void setUseCustomDashPattern( bool b ) { mUseCustomDashPattern = b; } 150 151 /** 152 * Sets the \a unit for lengths used in the custom dash pattern. 153 * \see customDashPatternUnit() 154 */ setCustomDashPatternUnit(QgsUnitTypes::RenderUnit unit)155 void setCustomDashPatternUnit( QgsUnitTypes::RenderUnit unit ) { mCustomDashPatternUnit = unit; } 156 157 /** 158 * Returns the units for lengths used in the custom dash pattern. 159 * \see setCustomDashPatternUnit() 160 */ customDashPatternUnit()161 QgsUnitTypes::RenderUnit customDashPatternUnit() const { return mCustomDashPatternUnit; } 162 163 /** 164 * Returns the map unit scale for lengths used in the custom dash pattern. 165 * \see setCustomDashPatternMapUnitScale() 166 */ customDashPatternMapUnitScale()167 const QgsMapUnitScale &customDashPatternMapUnitScale() const { return mCustomDashPatternMapUnitScale; } 168 169 /** 170 * Sets the map unit \a scale for lengths used in the custom dash pattern. 171 * \see customDashPatternMapUnitScale() 172 */ setCustomDashPatternMapUnitScale(const QgsMapUnitScale & scale)173 void setCustomDashPatternMapUnitScale( const QgsMapUnitScale &scale ) { mCustomDashPatternMapUnitScale = scale; } 174 175 /** 176 * Returns the custom dash vector, which is the pattern of alternating drawn/skipped lengths 177 * used while rendering a custom dash pattern. 178 * 179 * Units for the vector are specified by customDashPatternUnit() 180 * 181 * This setting is only used when useCustomDashPattern() returns TRUE. 182 * 183 * \see setCustomDashVector() 184 * \see customDashPatternUnit() 185 * \see useCustomDashPattern() 186 */ customDashVector()187 QVector<qreal> customDashVector() const { return mCustomDashVector; } 188 189 /** 190 * Sets the custom dash \a vector, which is the pattern of alternating drawn/skipped lengths 191 * used while rendering a custom dash pattern. 192 * 193 * Units for the vector are specified by customDashPatternUnit() 194 * 195 * This setting is only used when useCustomDashPattern() returns TRUE. 196 * 197 * \see customDashVector() 198 * \see setCustomDashPatternUnit() 199 * \see setUseCustomDashPattern() 200 */ setCustomDashVector(const QVector<qreal> & vector)201 void setCustomDashVector( const QVector<qreal> &vector ) { mCustomDashVector = vector; } 202 203 /** 204 * Returns the dash pattern offset, which dictates how far along the dash pattern 205 * the pattern should start rendering at. 206 * 207 * Offset units can be retrieved by calling dashPatternOffsetUnit(). 208 * 209 * \see setDashPatternOffset() 210 * \see dashPatternOffsetUnit() 211 * \see dashPatternOffsetMapUnitScale() 212 * 213 * \since QGIS 3.16 214 */ dashPatternOffset()215 double dashPatternOffset() const { return mDashPatternOffset; } 216 217 /** 218 * Sets the dash pattern \a offset, which dictates how far along the dash pattern 219 * the pattern should start rendering at. 220 * 221 * Offset units are set via setDashPatternOffsetUnit(). 222 * 223 * \see dashPatternOffset() 224 * \see setDashPatternOffsetUnit() 225 * \see setDashPatternOffsetMapUnitScale() 226 * 227 * \since QGIS 3.16 228 */ setDashPatternOffset(double offset)229 void setDashPatternOffset( double offset ) { mDashPatternOffset = offset; } 230 231 /** 232 * Sets the \a unit for the dash pattern offset. 233 * 234 * \see dashPatternOffsetUnit() 235 * \see setDashPatternOffset() 236 * \see setDashPatternOffsetMapUnitScale() 237 * 238 * \since QGIS 3.16 239 */ setDashPatternOffsetUnit(QgsUnitTypes::RenderUnit unit)240 void setDashPatternOffsetUnit( QgsUnitTypes::RenderUnit unit ) { mDashPatternOffsetUnit = unit; } 241 242 /** 243 * Returns the units for the dash pattern offset. 244 * 245 * \see setDashPatternOffsetUnit() 246 * \see dashPatternOffset() 247 * \see dashPatternOffsetMapUnitScale() 248 * 249 * \since QGIS 3.16 250 */ dashPatternOffsetUnit()251 QgsUnitTypes::RenderUnit dashPatternOffsetUnit() const { return mDashPatternOffsetUnit; } 252 253 /** 254 * Returns the map unit scale for the dash pattern offset value. 255 * 256 * \see setDashPatternOffsetMapUnitScale() 257 * \see dashPatternOffsetUnit() 258 * \see dashPatternOffset() 259 * 260 * \since QGIS 3.16 261 */ dashPatternOffsetMapUnitScale()262 const QgsMapUnitScale &dashPatternOffsetMapUnitScale() const { return mDashPatternOffsetMapUnitScale; } 263 264 /** 265 * Sets the map unit \a scale for the dash pattern offset. 266 * 267 * \see dashPatternOffsetMapUnitScale() 268 * \see setDashPatternOffset() 269 * \see setDashPatternOffsetUnit() 270 * 271 * \since QGIS 3.16 272 */ setDashPatternOffsetMapUnitScale(const QgsMapUnitScale & scale)273 void setDashPatternOffsetMapUnitScale( const QgsMapUnitScale &scale ) { mDashPatternOffsetMapUnitScale = scale; } 274 275 /** 276 * Returns the trim distance for the start of the line, which dictates a length 277 * from the start of the line at which the actual rendering should start. 278 * 279 * Trim units can be retrieved by calling trimDistanceStartUnit(). 280 * 281 * \see setTrimDistanceStart() 282 * \see trimDistanceEnd() 283 * \see trimDistanceStartUnit() 284 * \see trimDistanceStartMapUnitScale() 285 * 286 * \since QGIS 3.20 287 */ trimDistanceStart()288 double trimDistanceStart() const { return mTrimDistanceStart; } 289 290 /** 291 * Sets the trim \a distance for the start of the line, which dictates a length 292 * from the start of the line at which the actual rendering should start. 293 * 294 * Trim units can be set by calling setTrimDistanceStartUnit(). 295 * 296 * \see trimDistanceStart() 297 * \see setTrimDistanceEnd() 298 * \see setTrimDistanceStartUnit() 299 * \see setTrimDistanceStartMapUnitScale() 300 * 301 * \since QGIS 3.20 302 */ setTrimDistanceStart(double distance)303 void setTrimDistanceStart( double distance ) { mTrimDistanceStart = distance; } 304 305 /** 306 * Sets the \a unit for the trim distance for the start of the line. 307 * 308 * \see trimDistanceStartUnit() 309 * \see setTrimDistanceEndUnit() 310 * \see setTrimDistanceStart() 311 * \see setTrimDistanceStartMapUnitScale() 312 * 313 * \since QGIS 3.20 314 */ setTrimDistanceStartUnit(QgsUnitTypes::RenderUnit unit)315 void setTrimDistanceStartUnit( QgsUnitTypes::RenderUnit unit ) { mTrimDistanceStartUnit = unit; } 316 317 /** 318 * Returns the unit for the trim distance for the start of the line. 319 * 320 * \see setTrimDistanceStartUnit() 321 * \see trimDistanceEndUnit() 322 * \see trimDistanceStart() 323 * \see trimDistanceStartMapUnitScale() 324 * 325 * \since QGIS 3.20 326 */ trimDistanceStartUnit()327 QgsUnitTypes::RenderUnit trimDistanceStartUnit() const { return mTrimDistanceStartUnit; } 328 329 /** 330 * Returns the map unit scale for the trim distance for the start of the line. 331 * 332 * \see setTrimDistanceStartMapUnitScale() 333 * \see trimDistanceEndMapUnitScale() 334 * \see trimDistanceStart() 335 * \see trimDistanceStartUnit() 336 * 337 * \since QGIS 3.20 338 */ trimDistanceStartMapUnitScale()339 const QgsMapUnitScale &trimDistanceStartMapUnitScale() const { return mTrimDistanceStartMapUnitScale; } 340 341 /** 342 * Sets the map unit \a scale for the trim distance for the start of the line. 343 * 344 * \see trimDistanceStartMapUnitScale() 345 * \see setTrimDistanceEndMapUnitScale() 346 * \see setTrimDistanceStart() 347 * \see setTrimDistanceStartUnit() 348 * 349 * \since QGIS 3.20 350 */ setTrimDistanceStartMapUnitScale(const QgsMapUnitScale & scale)351 void setTrimDistanceStartMapUnitScale( const QgsMapUnitScale &scale ) { mTrimDistanceStartMapUnitScale = scale; } 352 353 /** 354 * Returns the trim distance for the end of the line, which dictates a length 355 * from the end of the line at which the actual rendering should end. 356 * 357 * Trim units can be retrieved by calling trimDistanceEndUnit(). 358 * 359 * \see setTrimDistanceEnd() 360 * \see trimDistanceStart() 361 * \see trimDistanceEndUnit() 362 * \see trimDistanceEndMapUnitScale() 363 * 364 * \since QGIS 3.20 365 */ trimDistanceEnd()366 double trimDistanceEnd() const { return mTrimDistanceEnd; } 367 368 /** 369 * Sets the trim \a distance for the end of the line, which dictates a length 370 * from the end of the line at which the actual rendering should end. 371 * 372 * Trim units can be set by calling setTrimDistanceEndUnit(). 373 * 374 * \see trimDistanceEnd() 375 * \see setTrimDistanceStart() 376 * \see setTrimDistanceEndUnit() 377 * \see setTrimDistanceEndMapUnitScale() 378 * 379 * \since QGIS 3.20 380 */ setTrimDistanceEnd(double distance)381 void setTrimDistanceEnd( double distance ) { mTrimDistanceEnd = distance; } 382 383 /** 384 * Sets the \a unit for the trim distance for the end of the line. 385 * 386 * \see trimDistanceEndUnit() 387 * \see setTrimDistanceStartUnit() 388 * \see setTrimDistanceEnd() 389 * \see setTrimDistanceEndMapUnitScale() 390 * 391 * \since QGIS 3.20 392 */ setTrimDistanceEndUnit(QgsUnitTypes::RenderUnit unit)393 void setTrimDistanceEndUnit( QgsUnitTypes::RenderUnit unit ) { mTrimDistanceEndUnit = unit; } 394 395 /** 396 * Returns the unit for the trim distance for the end of the line. 397 * 398 * \see setTrimDistanceEndUnit() 399 * \see trimDistanceStartUnit() 400 * \see trimDistanceEnd() 401 * \see trimDistanceEndMapUnitScale() 402 * 403 * \since QGIS 3.20 404 */ trimDistanceEndUnit()405 QgsUnitTypes::RenderUnit trimDistanceEndUnit() const { return mTrimDistanceEndUnit; } 406 407 /** 408 * Returns the map unit scale for the trim distance for the end of the line. 409 * 410 * \see setTrimDistanceEndMapUnitScale() 411 * \see trimDistanceStartMapUnitScale() 412 * \see trimDistanceEnd() 413 * \see trimDistanceEndUnit() 414 * 415 * \since QGIS 3.20 416 */ trimDistanceEndMapUnitScale()417 const QgsMapUnitScale &trimDistanceEndMapUnitScale() const { return mTrimDistanceEndMapUnitScale; } 418 419 /** 420 * Sets the map unit \a scale for the trim distance for the end of the line. 421 * 422 * \see trimDistanceEndMapUnitScale() 423 * \see setTrimDistanceStartMapUnitScale() 424 * \see setTrimDistanceEnd() 425 * \see setTrimDistanceEndUnit() 426 * 427 * \since QGIS 3.20 428 */ setTrimDistanceEndMapUnitScale(const QgsMapUnitScale & scale)429 void setTrimDistanceEndMapUnitScale( const QgsMapUnitScale &scale ) { mTrimDistanceEndMapUnitScale = scale; } 430 431 /** 432 * Returns TRUE if the line should only be drawn inside polygons, and any portion 433 * of the line which falls outside the polygon should be clipped away. 434 * 435 * This setting only has an effect when the line symbol is being 436 * used to render polygon rings. 437 * 438 * \see setDrawInsidePolygon() 439 */ drawInsidePolygon()440 bool drawInsidePolygon() const { return mDrawInsidePolygon; } 441 442 /** 443 * Sets whether the line should only be drawn inside polygons, and any portion 444 * of the line which falls outside the polygon should be clipped away. 445 * 446 * This setting only has an effect when the line symbol is being 447 * used to render polygon rings. 448 * 449 * \see drawInsidePolygon() 450 */ setDrawInsidePolygon(bool drawInsidePolygon)451 void setDrawInsidePolygon( bool drawInsidePolygon ) { mDrawInsidePolygon = drawInsidePolygon; } 452 453 /** 454 * Returns TRUE if dash patterns should be aligned to the start and end of lines, by 455 * applying subtle tweaks to the pattern sizing in order to ensure that the end of 456 * a line is represented by a complete dash element. 457 * 458 * \see setAlignDashPattern() 459 * \see tweakDashPatternOnCorners() 460 * \since QGIS 3.16 461 */ 462 bool alignDashPattern() const; 463 464 /** 465 * Sets whether dash patterns should be aligned to the start and end of lines, by 466 * applying subtle tweaks to the pattern sizing in order to ensure that the end of 467 * a line is represented by a complete dash element. 468 * 469 * \see alignDashPattern() 470 * \see setTweakDashPatternOnCorners() 471 * \since QGIS 3.16 472 */ 473 void setAlignDashPattern( bool enabled ); 474 475 /** 476 * Returns TRUE if dash patterns tweaks should be applied on sharp corners, to ensure 477 * that a double-length dash is drawn running into and out of the corner. 478 * 479 * \note This setting is only applied if alignDashPattern() is TRUE. 480 * 481 * \see setTweakDashPatternOnCorners() 482 * \see alignDashPattern() 483 * \since QGIS 3.16 484 */ 485 bool tweakDashPatternOnCorners() const; 486 487 /** 488 * Sets whether dash patterns tweaks should be applied on sharp corners, to ensure 489 * that a double-length dash is drawn running into and out of the corner. 490 * 491 * \note This setting is only applied if alignDashPattern() is TRUE. 492 * 493 * \see tweakDashPatternOnCorners() 494 * \see setAlignDashPattern() 495 * \since QGIS 3.16 496 */ 497 void setTweakDashPatternOnCorners( bool enabled ); 498 499 private: 500 501 Qt::PenStyle mPenStyle = Qt::SolidLine; 502 Qt::PenJoinStyle mPenJoinStyle = DEFAULT_SIMPLELINE_JOINSTYLE; 503 Qt::PenCapStyle mPenCapStyle = DEFAULT_SIMPLELINE_CAPSTYLE; 504 QPen mPen; 505 QPen mSelPen; 506 507 bool mUseCustomDashPattern = false; 508 QgsUnitTypes::RenderUnit mCustomDashPatternUnit = QgsUnitTypes::RenderMillimeters; 509 QgsMapUnitScale mCustomDashPatternMapUnitScale; 510 511 double mDashPatternOffset = 0; 512 QgsUnitTypes::RenderUnit mDashPatternOffsetUnit = QgsUnitTypes::RenderMillimeters; 513 QgsMapUnitScale mDashPatternOffsetMapUnitScale; 514 515 double mTrimDistanceStart = 0; 516 QgsUnitTypes::RenderUnit mTrimDistanceStartUnit = QgsUnitTypes::RenderMillimeters; 517 QgsMapUnitScale mTrimDistanceStartMapUnitScale; 518 519 double mTrimDistanceEnd = 0; 520 QgsUnitTypes::RenderUnit mTrimDistanceEndUnit = QgsUnitTypes::RenderMillimeters; 521 QgsMapUnitScale mTrimDistanceEndMapUnitScale; 522 523 //! Vector with an even number of entries for the 524 QVector<qreal> mCustomDashVector; 525 526 bool mAlignDashPattern = false; 527 bool mPatternCartographicTweakOnSharpCorners = false; 528 529 bool mDrawInsidePolygon = false; 530 531 //helper functions for data defined symbology 532 void applyDataDefinedSymbology( QgsSymbolRenderContext &context, QPen &pen, QPen &selPen, double &offset ); 533 void drawPathWithDashPatternTweaks( QPainter *painter, const QPolygonF &points, QPen pen ) const; 534 }; 535 536 ///////// 537 538 #define DEFAULT_MARKERLINE_ROTATE true 539 #define DEFAULT_MARKERLINE_INTERVAL 3 540 541 /** 542 * \ingroup core 543 * \class QgsTemplatedLineSymbolLayerBase 544 * 545 * \brief Base class for templated line symbols, e.g. line symbols which draw markers or hash 546 * lines at intervals along the line feature. 547 * 548 * \since QGIS 3.8 549 */ 550 class CORE_EXPORT QgsTemplatedLineSymbolLayerBase : public QgsLineSymbolLayer 551 { 552 public: 553 554 /** 555 * Defines how/where the templated symbol should be placed on the line. 556 */ 557 enum Placement 558 { 559 Interval, //!< Place symbols at regular intervals 560 Vertex, //!< Place symbols on every vertex in the line 561 LastVertex, //!< Place symbols on the last vertex in the line 562 FirstVertex, //!< Place symbols on the first vertex in the line 563 CentralPoint, //!< Place symbols at the mid point of the line 564 CurvePoint, //!< Place symbols at every virtual curve point in the line (used when rendering curved geometry types only) 565 SegmentCenter, //!< Place symbols at the center of every line segment 566 }; 567 568 /** 569 * Constructor for QgsTemplatedLineSymbolLayerBase. Creates a template 570 * line placed at the specified \a interval (in millimeters). 571 * 572 * The \a rotateSymbol argument specifies whether individual symbols 573 * should be rotated to match the line segment alignment. 574 */ 575 QgsTemplatedLineSymbolLayerBase( bool rotateSymbol = true, 576 double interval = 3 ); 577 578 ~QgsTemplatedLineSymbolLayerBase() override; 579 580 /** 581 * Returns TRUE if the repeating symbols be rotated to match their line segment orientation. 582 * \see setRotateSymbols() 583 */ rotateSymbols()584 bool rotateSymbols() const { return mRotateSymbols; } 585 586 /** 587 * Sets whether the repeating symbols should be rotated to match their line segment orientation. 588 * \see rotateSymbols() 589 */ setRotateSymbols(bool rotate)590 void setRotateSymbols( bool rotate ) { mRotateSymbols = rotate; } 591 592 /** 593 * Returns the interval between individual symbols. Units are specified through intervalUnits(). 594 * \see setInterval() 595 * \see intervalUnit() 596 */ interval()597 double interval() const { return mInterval; } 598 599 /** 600 * Sets the interval between individual symbols. 601 * \param interval interval size. Units are specified through setIntervalUnit() 602 * \see interval() 603 * \see setIntervalUnit() 604 */ setInterval(double interval)605 void setInterval( double interval ) { mInterval = interval; } 606 607 /** 608 * Sets the units for the interval between symbols. 609 * \param unit interval units 610 * \see intervalUnit() 611 * \see setInterval() 612 */ setIntervalUnit(QgsUnitTypes::RenderUnit unit)613 void setIntervalUnit( QgsUnitTypes::RenderUnit unit ) { mIntervalUnit = unit; } 614 615 /** 616 * Returns the units for the interval between symbols. 617 * \see setIntervalUnit() 618 * \see interval() 619 */ intervalUnit()620 QgsUnitTypes::RenderUnit intervalUnit() const { return mIntervalUnit; } 621 622 /** 623 * Sets the map unit \a scale for the interval between symbols. 624 * \see intervalMapUnitScale() 625 * \see setIntervalUnit() 626 * \see setInterval() 627 */ setIntervalMapUnitScale(const QgsMapUnitScale & scale)628 void setIntervalMapUnitScale( const QgsMapUnitScale &scale ) { mIntervalMapUnitScale = scale; } 629 630 /** 631 * Returns the map unit scale for the interval between symbols. 632 * \see setIntervalMapUnitScale() 633 * \see intervalUnit() 634 * \see interval() 635 */ intervalMapUnitScale()636 const QgsMapUnitScale &intervalMapUnitScale() const { return mIntervalMapUnitScale; } 637 638 /** 639 * Returns the placement of the symbols. 640 * \see setPlacement() 641 */ placement()642 Placement placement() const { return mPlacement; } 643 644 /** 645 * Sets the \a placement of the symbols. 646 * \see placement() 647 */ setPlacement(Placement placement)648 void setPlacement( Placement placement ) { mPlacement = placement; } 649 650 /** 651 * Returns the offset along the line for the symbol placement. For Interval placements, this is the distance 652 * between the start of the line and the first symbol. For FirstVertex and LastVertex placements, this is the 653 * distance between the symbol and the start of the line or the end of the line respectively. 654 * This setting has no effect for Vertex or CentralPoint placements. 655 * \returns The offset along the line. The unit for the offset is retrievable via offsetAlongLineUnit. 656 * \see setOffsetAlongLine() 657 * \see offsetAlongLineUnit() 658 * \see placement() 659 */ offsetAlongLine()660 double offsetAlongLine() const { return mOffsetAlongLine; } 661 662 /** 663 * Sets the the offset along the line for the symbol placement. For Interval placements, this is the distance 664 * between the start of the line and the first symbol. For FirstVertex and LastVertex placements, this is the 665 * distance between the symbol and the start of the line or the end of the line respectively. 666 * This setting has no effect for Vertex or CentralPoint placements. 667 * \param offsetAlongLine Distance to offset markers along the line. The offset 668 * unit is set via setOffsetAlongLineUnit. 669 * \see offsetAlongLine() 670 * \see setOffsetAlongLineUnit() 671 * \see setPlacement() 672 */ setOffsetAlongLine(double offsetAlongLine)673 void setOffsetAlongLine( double offsetAlongLine ) { mOffsetAlongLine = offsetAlongLine; } 674 675 /** 676 * Returns the unit used for calculating the offset along line for symbols. 677 * \returns Offset along line unit type. 678 * \see setOffsetAlongLineUnit() 679 * \see offsetAlongLine() 680 */ offsetAlongLineUnit()681 QgsUnitTypes::RenderUnit offsetAlongLineUnit() const { return mOffsetAlongLineUnit; } 682 683 /** 684 * Sets the unit used for calculating the offset along line for symbols. 685 * \param unit Offset along line unit type. 686 * \see offsetAlongLineUnit() 687 * \see setOffsetAlongLine() 688 */ setOffsetAlongLineUnit(QgsUnitTypes::RenderUnit unit)689 void setOffsetAlongLineUnit( QgsUnitTypes::RenderUnit unit ) { mOffsetAlongLineUnit = unit; } 690 691 /** 692 * Returns the map unit scale used for calculating the offset in map units along line for symbols. 693 * \see setOffsetAlongLineMapUnitScale() 694 */ offsetAlongLineMapUnitScale()695 const QgsMapUnitScale &offsetAlongLineMapUnitScale() const { return mOffsetAlongLineMapUnitScale; } 696 697 /** 698 * Sets the map unit \a scale used for calculating the offset in map units along line for symbols. 699 * \see offsetAlongLineMapUnitScale() 700 */ setOffsetAlongLineMapUnitScale(const QgsMapUnitScale & scale)701 void setOffsetAlongLineMapUnitScale( const QgsMapUnitScale &scale ) { mOffsetAlongLineMapUnitScale = scale; } 702 703 /** 704 * Returns the length of line over which the line's direction is averaged when 705 * calculating individual symbol angles. Longer lengths smooth out angles from jagged lines to a greater extent. 706 * 707 * Units are retrieved through averageAngleUnit() 708 * 709 * \see setAverageAngleLength() 710 * \see averageAngleUnit() 711 * \see averageAngleMapUnitScale() 712 */ averageAngleLength()713 double averageAngleLength() const { return mAverageAngleLength; } 714 715 /** 716 * Sets the \a length of line over which the line's direction is averaged when 717 * calculating individual symbol angles. Longer lengths smooth out angles from jagged lines to a greater extent. 718 * 719 * Units are set through setAverageAngleUnit() 720 * 721 * \see averageAngleLength() 722 * \see setAverageAngleUnit() 723 * \see setAverageAngleMapUnitScale() 724 */ setAverageAngleLength(double length)725 void setAverageAngleLength( double length ) { mAverageAngleLength = length; } 726 727 /** 728 * Sets the \a unit for the length over which the line's direction is averaged when 729 * calculating individual symbol angles. 730 * 731 * \see averageAngleUnit() 732 * \see setAverageAngleLength() 733 * \see setAverageAngleMapUnitScale() 734 */ setAverageAngleUnit(QgsUnitTypes::RenderUnit unit)735 void setAverageAngleUnit( QgsUnitTypes::RenderUnit unit ) { mAverageAngleLengthUnit = unit; } 736 737 /** 738 * Returns the unit for the length over which the line's direction is averaged when 739 * calculating individual symbol angles. 740 * 741 * \see setAverageAngleUnit() 742 * \see averageAngleLength() 743 * \see averageAngleMapUnitScale() 744 */ averageAngleUnit()745 QgsUnitTypes::RenderUnit averageAngleUnit() const { return mAverageAngleLengthUnit; } 746 747 /** 748 * Sets the map unit \a scale for the length over which the line's direction is averaged when 749 * calculating individual symbol angles. 750 * 751 * \see averageAngleMapUnitScale() 752 * \see setAverageAngleLength() 753 * \see setAverageAngleUnit() 754 */ setAverageAngleMapUnitScale(const QgsMapUnitScale & scale)755 void setAverageAngleMapUnitScale( const QgsMapUnitScale &scale ) { mAverageAngleLengthMapUnitScale = scale; } 756 757 /** 758 * Returns the map unit scale for the length over which the line's direction is averaged when 759 * calculating individual symbol angles. 760 * 761 * \see setAverageAngleMapUnitScale() 762 * \see averageAngleLength() 763 * \see averageAngleUnit() 764 */ averageAngleMapUnitScale()765 const QgsMapUnitScale &averageAngleMapUnitScale() const { return mAverageAngleLengthMapUnitScale; } 766 767 void renderPolyline( const QPolygonF &points, QgsSymbolRenderContext &context ) override; 768 void renderPolygonStroke( const QPolygonF &points, const QVector<QPolygonF> *rings, QgsSymbolRenderContext &context ) FINAL; 769 QgsUnitTypes::RenderUnit outputUnit() const FINAL; 770 void setMapUnitScale( const QgsMapUnitScale &scale ) FINAL; 771 QgsMapUnitScale mapUnitScale() const FINAL; 772 QVariantMap properties() const override; 773 bool canCauseArtifactsBetweenAdjacentTiles() const override; 774 775 protected: 776 777 /** 778 * Sets the line \a angle modification for the symbol's angle. This angle is added to 779 * the symbol's rotation and data defined rotation before rendering the symbol, and 780 * is used for orienting symbols to match the line's angle. 781 * \param angle Angle in degrees, valid values are between 0 and 360 782 */ 783 virtual void setSymbolLineAngle( double angle ) = 0; 784 785 /** 786 * Returns the symbol's current angle, in degrees clockwise. 787 */ 788 virtual double symbolAngle() const = 0; 789 790 /** 791 * Sets the symbol's \a angle, in degrees clockwise. 792 */ 793 virtual void setSymbolAngle( double angle ) = 0; 794 795 /** 796 * Renders the templated symbol at the specified \a point, using the given render \a context. 797 * 798 * The \a feature argument is used to pass the feature currently being rendered (when available). 799 * 800 * If only a single symbol layer from the symbol should be rendered, it should be specified 801 * in the \a layer argument. A \a layer of -1 indicates that all symbol layers should be 802 * rendered. 803 * 804 * If \a selected is TRUE then the symbol will be drawn using the "selected feature" 805 * style and colors instead of the symbol's normal style. 806 */ 807 virtual void renderSymbol( const QPointF &point, const QgsFeature *feature, QgsRenderContext &context, int layer = -1, bool selected = false ) = 0; 808 809 /** 810 * Copies all common properties of this layer to another templated symbol layer. 811 */ 812 void copyTemplateSymbolProperties( QgsTemplatedLineSymbolLayerBase *destLayer ) const; 813 814 /** 815 * Sets all common symbol properties in the \a destLayer, using the settings 816 * serialized in the \a properties map. 817 */ 818 static void setCommonProperties( QgsTemplatedLineSymbolLayerBase *destLayer, const QVariantMap &properties ); 819 820 private: 821 822 void renderPolylineInterval( const QPolygonF &points, QgsSymbolRenderContext &context, double averageAngleOver ); 823 void renderPolylineVertex( const QPolygonF &points, QgsSymbolRenderContext &context, QgsTemplatedLineSymbolLayerBase::Placement placement = QgsTemplatedLineSymbolLayerBase::Vertex ); 824 void renderPolylineCentral( const QPolygonF &points, QgsSymbolRenderContext &context, double averageAngleOver ); 825 double markerAngle( const QPolygonF &points, bool isRing, int vertex ); 826 827 /** 828 * Renders a symbol by offsetting a vertex along the line by a specified distance. 829 * \param points vertices making up the line 830 * \param vertex vertex number to begin offset at 831 * \param distance distance to offset from vertex. If distance is positive, offset is calculated 832 * moving forward along the line. If distance is negative, offset is calculated moving backward 833 * along the line's vertices. 834 * \param context render context 835 * \see setoffsetAlongLine 836 * \see setOffsetAlongLineUnit 837 */ 838 void renderOffsetVertexAlongLine( const QPolygonF &points, int vertex, double distance, QgsSymbolRenderContext &context ); 839 840 841 static void collectOffsetPoints( const QVector< QPointF> &points, 842 QVector< QPointF> &dest, double intervalPainterUnits, double initialOffset, double initialLag = 0, 843 int numberPointsRequired = -1 ); 844 845 bool mRotateSymbols = true; 846 double mInterval = 3; 847 QgsUnitTypes::RenderUnit mIntervalUnit = QgsUnitTypes::RenderMillimeters; 848 QgsMapUnitScale mIntervalMapUnitScale; 849 Placement mPlacement = Interval; 850 double mOffsetAlongLine = 0; //distance to offset along line before marker is drawn 851 QgsUnitTypes::RenderUnit mOffsetAlongLineUnit = QgsUnitTypes::RenderMillimeters; //unit for offset along line 852 QgsMapUnitScale mOffsetAlongLineMapUnitScale; 853 double mAverageAngleLength = 4; 854 QgsUnitTypes::RenderUnit mAverageAngleLengthUnit = QgsUnitTypes::RenderMillimeters; 855 QgsMapUnitScale mAverageAngleLengthMapUnitScale; 856 857 friend class TestQgsMarkerLineSymbol; 858 859 }; 860 861 /** 862 * \ingroup core 863 * \class QgsMarkerLineSymbolLayer 864 * \brief Line symbol layer type which draws repeating marker symbols along a line feature. 865 */ 866 class CORE_EXPORT QgsMarkerLineSymbolLayer : public QgsTemplatedLineSymbolLayerBase 867 { 868 public: 869 870 /** 871 * Constructor for QgsMarkerLineSymbolLayer. Creates a marker line 872 * with a default marker symbol, placed at the specified \a interval (in millimeters). 873 * 874 * The \a rotateMarker argument specifies whether individual marker symbols 875 * should be rotated to match the line segment alignment. 876 */ 877 QgsMarkerLineSymbolLayer( bool rotateMarker = DEFAULT_MARKERLINE_ROTATE, 878 double interval = DEFAULT_MARKERLINE_INTERVAL ); 879 880 ~QgsMarkerLineSymbolLayer() override; 881 882 // static stuff 883 884 /** 885 * Creates a new QgsMarkerLineSymbolLayer, using the settings 886 * serialized in the \a properties map (corresponding to the output from 887 * QgsMarkerLineSymbolLayer::properties() ). 888 */ 889 static QgsSymbolLayer *create( const QVariantMap &properties = QVariantMap() ) SIP_FACTORY; 890 891 /** 892 * Creates a new QgsMarkerLineSymbolLayer from an SLD XML DOM \a element. 893 */ 894 static QgsSymbolLayer *createFromSld( QDomElement &element ) SIP_FACTORY; 895 896 // implemented from base classes 897 898 QString layerType() const override; 899 void startRender( QgsSymbolRenderContext &context ) override; 900 void stopRender( QgsSymbolRenderContext &context ) override; 901 QgsMarkerLineSymbolLayer *clone() const override SIP_FACTORY; 902 void toSld( QDomDocument &doc, QDomElement &element, const QVariantMap &props ) const override; 903 void setColor( const QColor &color ) override; 904 QColor color() const override; 905 QgsSymbol *subSymbol() override; 906 bool setSubSymbol( QgsSymbol *symbol SIP_TRANSFER ) override; 907 void setWidth( double width ) override; 908 double width() const override; 909 double width( const QgsRenderContext &context ) const override; 910 double estimateMaxBleed( const QgsRenderContext &context ) const override; 911 void setOutputUnit( QgsUnitTypes::RenderUnit unit ) override; 912 bool usesMapUnits() const override; 913 QSet<QString> usedAttributes( const QgsRenderContext &context ) const override; 914 bool hasDataDefinedProperties() const override; 915 void setDataDefinedProperty( QgsSymbolLayer::Property key, const QgsProperty &property ) override; 916 917 /** 918 * Shall the marker be rotated. 919 * 920 * \returns TRUE if the marker should be rotated. 921 * \deprecated Use rotateSymbols() instead. 922 */ rotateMarker()923 Q_DECL_DEPRECATED bool rotateMarker() const SIP_DEPRECATED { return rotateSymbols(); } 924 925 /** 926 * Shall the marker be rotated. 927 * \deprecated Use setRotateSymbols() instead. 928 */ setRotateMarker(bool rotate)929 Q_DECL_DEPRECATED void setRotateMarker( bool rotate ) SIP_DEPRECATED { setRotateSymbols( rotate ); } 930 931 void renderPolyline( const QPolygonF &points, QgsSymbolRenderContext &context ) override; 932 933 protected: 934 935 std::unique_ptr< QgsMarkerSymbol > mMarker; 936 937 void setSymbolLineAngle( double angle ) override; 938 double symbolAngle() const override; 939 void setSymbolAngle( double angle ) override; 940 void renderSymbol( const QPointF &point, const QgsFeature *feature, QgsRenderContext &context, int layer = -1, bool selected = false ) override; 941 942 private: 943 944 #ifdef SIP_RUN 945 QgsMarkerLineSymbolLayer( const QgsMarkerLineSymbolLayer &other ); 946 #endif 947 948 949 }; 950 951 952 /** 953 * \ingroup core 954 * \class QgsHashedLineSymbolLayer 955 * 956 * \brief Line symbol layer type which draws repeating line sections along a line feature. 957 * 958 * \since QGIS 3.8 959 */ 960 class CORE_EXPORT QgsHashedLineSymbolLayer : public QgsTemplatedLineSymbolLayerBase 961 { 962 public: 963 964 /** 965 * Constructor for QgsHashedLineSymbolLayer. Creates a line 966 * with a default hash symbol, placed at the specified \a interval (in millimeters). 967 * 968 * The \a rotateSymbol argument specifies whether individual hash symbols 969 * should be rotated to match the line segment alignment. 970 */ 971 QgsHashedLineSymbolLayer( bool rotateSymbol = true, 972 double interval = 3 ); 973 974 ~QgsHashedLineSymbolLayer() override; 975 976 /** 977 * Creates a new QgsHashedLineSymbolLayer, using the settings 978 * serialized in the \a properties map (corresponding to the output from 979 * QgsHashedLineSymbolLayer::properties() ). 980 */ 981 static QgsSymbolLayer *create( const QVariantMap &properties = QVariantMap() ) SIP_FACTORY; 982 983 QString layerType() const override; 984 void startRender( QgsSymbolRenderContext &context ) override; 985 void stopRender( QgsSymbolRenderContext &context ) override; 986 QVariantMap properties() const override; 987 QgsHashedLineSymbolLayer *clone() const override SIP_FACTORY; 988 void setColor( const QColor &color ) override; 989 QColor color() const override; 990 QgsSymbol *subSymbol() override; 991 bool setSubSymbol( QgsSymbol *symbol SIP_TRANSFER ) override; 992 void setWidth( double width ) override; 993 double width() const override; 994 double width( const QgsRenderContext &context ) const override; 995 double estimateMaxBleed( const QgsRenderContext &context ) const override; 996 void setOutputUnit( QgsUnitTypes::RenderUnit unit ) override; 997 QSet<QString> usedAttributes( const QgsRenderContext &context ) const override; 998 bool hasDataDefinedProperties() const override; 999 void setDataDefinedProperty( QgsSymbolLayer::Property key, const QgsProperty &property ) override; 1000 bool usesMapUnits() const override; 1001 1002 /** 1003 * Returns the angle to use when drawing the hashed lines sections, in degrees clockwise. 1004 * 1005 * \see setHashAngle() 1006 */ 1007 double hashAngle() const; 1008 1009 /** 1010 * Sets the \a angle to use when drawing the hashed lines sections, in degrees clockwise. 1011 * 1012 * \see hashAngle() 1013 */ 1014 void setHashAngle( double angle ); 1015 1016 /** 1017 * Returns the length of hash symbols. Units are specified through hashLengthUnits(). 1018 * \see setHashLength() 1019 * \see hashLengthUnit() 1020 */ hashLength()1021 double hashLength() const { return mHashLength; } 1022 1023 /** 1024 * Sets the \a length of hash symbols. Units are specified through setHashLengthUnit() 1025 * \see hashLength() 1026 * \see setHashLengthUnit() 1027 */ setHashLength(double length)1028 void setHashLength( double length ) { mHashLength = length; } 1029 1030 /** 1031 * Sets the \a unit for the length of hash symbols. 1032 * \see hashLengthUnit() 1033 * \see setHashLength() 1034 */ setHashLengthUnit(QgsUnitTypes::RenderUnit unit)1035 void setHashLengthUnit( QgsUnitTypes::RenderUnit unit ) { mHashLengthUnit = unit; } 1036 1037 /** 1038 * Returns the units for the length of hash symbols. 1039 * \see setHashLengthUnit() 1040 * \see hashLength() 1041 */ hashLengthUnit()1042 QgsUnitTypes::RenderUnit hashLengthUnit() const { return mHashLengthUnit; } 1043 1044 /** 1045 * Sets the map unit \a scale for the hash length. 1046 * \see hashLengthMapUnitScale() 1047 * \see setHashLengthUnit() 1048 * \see setHashLength() 1049 */ setHashLengthMapUnitScale(const QgsMapUnitScale & scale)1050 void setHashLengthMapUnitScale( const QgsMapUnitScale &scale ) { mHashLengthMapUnitScale = scale; } 1051 1052 /** 1053 * Returns the map unit scale for the hash length. 1054 * \see setHashLengthMapUnitScale() 1055 * \see hashLengthUnit() 1056 * \see hashLength() 1057 */ hashLengthMapUnitScale()1058 const QgsMapUnitScale &hashLengthMapUnitScale() const { return mHashLengthMapUnitScale; } 1059 1060 void renderPolyline( const QPolygonF &points, QgsSymbolRenderContext &context ) override; 1061 1062 protected: 1063 1064 void setSymbolLineAngle( double angle ) override; 1065 double symbolAngle() const override; 1066 void setSymbolAngle( double angle ) override; 1067 void renderSymbol( const QPointF &point, const QgsFeature *feature, QgsRenderContext &context, int layer = -1, bool selected = false ) override; 1068 1069 private: 1070 #ifdef SIP_RUN 1071 QgsHashedLineSymbolLayer( const QgsHashedLineSymbolLayer &other ); 1072 #endif 1073 1074 std::unique_ptr< QgsLineSymbol > mHashSymbol; 1075 1076 double mSymbolLineAngle = 0; 1077 double mSymbolAngle = 0; 1078 1079 double mHashAngle = 0; 1080 double mHashLength = 3; 1081 QgsUnitTypes::RenderUnit mHashLengthUnit = QgsUnitTypes::RenderMillimeters; 1082 QgsMapUnitScale mHashLengthMapUnitScale; 1083 1084 }; 1085 1086 #endif 1087 1088 1089