32  return QStringLiteral( 
"texture" );
 
 
   37  std::unique_ptr< QgsTiledSceneTextureRenderer > res = std::make_unique< QgsTiledSceneTextureRenderer >();
 
   38  res->setFillSymbol( mFillSymbol->clone() );
 
 
   47  std::unique_ptr< QgsTiledSceneTextureRenderer > r = std::make_unique< QgsTiledSceneTextureRenderer >();
 
   49    const QDomElement fillSymbolElem = element.firstChildElement( QStringLiteral( 
"fillSymbol" ) );
 
   50    if ( !fillSymbolElem.isNull() )
 
   52      const QDomElement symbolElem = fillSymbolElem.firstChildElement( QStringLiteral( 
"symbol" ) );
 
   53      std::unique_ptr< QgsFillSymbol > 
fillSymbol( QgsSymbolLayerUtils::loadSymbol<QgsFillSymbol>( symbolElem, context ) );
 
   59  r->restoreCommonProperties( element, context );
 
 
   66  QVariantMap properties;
 
   67  properties.insert( QStringLiteral( 
"color" ), QStringLiteral( 
"224,224,224" ) );
 
   68  properties.insert( QStringLiteral( 
"style" ), QStringLiteral( 
"solid" ) );
 
   69  properties.insert( QStringLiteral( 
"style_border" ), QStringLiteral( 
"solid" ) );
 
   70  properties.insert( QStringLiteral( 
"color_border" ), QStringLiteral( 
"124,124,124" ) );
 
   71  properties.insert( QStringLiteral( 
"width_border" ), QStringLiteral( 
"0.1" ) );
 
   72  properties.insert( QStringLiteral( 
"joinstyle" ), QStringLiteral( 
"round" ) );
 
 
   79  return mFillSymbol.get();
 
 
   84  mFillSymbol.reset( symbol );
 
 
   89  QDomElement rendererElem = doc.createElement( QStringLiteral( 
"renderer" ) );
 
   91  rendererElem.setAttribute( QStringLiteral( 
"type" ), QStringLiteral( 
"texture" ) );
 
   94    QDomElement fillSymbolElem = doc.createElement( QStringLiteral( 
"fillSymbol" ) );
 
   99    fillSymbolElem.appendChild( symbolElement );
 
  100    rendererElem.appendChild( fillSymbolElem );
 
 
  122    mFillSymbol->renderPolygon( triangle, 
nullptr, 
nullptr, context.
renderContext() );
 
  132  context.
textureCoordinates( textureX1, textureY1, textureX2, textureY2, textureX3, textureY3 );
 
  135  painter->setPen( Qt::NoPen );
 
  137  auto unitNormal = []( 
const QPointF p1, 
const QPointF p2 )
 
  139    const float dx = p2.x() - p1.x();
 
  140    const float dy = p2.y() - p1.y();
 
  141    QPointF n( -dy, dx );
 
  142    const double length = std::sqrt( n.x() * n.x() + n.y() * n.y() );
 
  143    return QPointF( n.x() / length, n.y() / length );
 
  146  auto intersect = []( 
const QPointF p1, 
const QPointF p2, 
const QPointF q1, 
const QPointF q2 )
 
  148    const double a1 = p2.y() - p1.y();
 
  149    const double b1 = p1.x() - p2.x();
 
  150    const double c1 = a1 * p1.x() + b1 * p1.y();
 
  152    const double a2 = q2.y() - q1.y();
 
  153    const double b2 = q1.x() - q2.x();
 
  154    const double c2 = a2 * q1.x() + b2 * q1.y();
 
  156    const double det = a1 * b2 - a2 * b1;
 
  164      return QPointF( ( b2 * c1 - b1 * c2 ) / det,
 
  165                      ( a1 * c2 - a2 * c1 ) / det );
 
  169  auto smallestAngleInTriangle = []( 
const QPolygonF & triangle )
 
  171    const QPointF p1 = triangle.at( 0 );
 
  172    const QPointF p2 = triangle.at( 1 );
 
  173    const QPointF p3 = triangle.at( 2 );
 
  175    const QPointF v1 = p2 - p1;
 
  176    const QPointF v2 = p3 - p2;
 
  177    const QPointF v3 = p1 - p3;
 
  179    const double a = std::sqrt( v1.x() * v1.x() + v1.y() * v1.y() );
 
  180    const double b = std::sqrt( v2.x() * v2.x() + v2.y() * v2.y() );
 
  181    const double c = std::sqrt( v3.x() * v3.x() + v3.y() * v3.y() );
 
  185               std::acos( ( b * b + 
c * 
c - a * a )  / ( 2 * b * 
c ) ),
 
  186               std::acos( ( a * a + 
c * 
c - b * b )  / ( 2 * a * 
c ) ) ),
 
  187             std::acos( ( a * a + b * b - 
c * 
c )  / ( 2 * a * b ) )
 
  191  auto growTriangle = [&unitNormal, &intersect]( 
const QPolygonF & triangle, 
float pixels )
 
  193    QPair< QPointF, QPointF > offsetEdges[3];
 
  194    for ( 
int i = 0; i < 3; ++i )
 
  196      const QPointF p1 = triangle.at( i );
 
  197      const QPointF p2 = triangle.at( i + 1 );
 
  198      const QPointF n = unitNormal( p1, p2 );
 
  200      const QPointF offsetP1( p1.x() + n.x() * pixels, p1.y() + n.y() * pixels );
 
  201      const QPointF offsetP2( p2.x() + n.x() * pixels, p2.y() + n.y() * pixels );
 
  203      offsetEdges[i] = { offsetP1, offsetP2 };
 
  210    static double constexpr MAX_TRIANGLE_GROW_PIXELS_SQUARED = 3 * 3;
 
  211    for ( 
int i = 0; i < 3; ++i )
 
  213      const auto &edge1 = offsetEdges[i];
 
  214      const auto &edge2 = offsetEdges[i == 0 ? 2 : ( i - 1 )];
 
  216      const QPointF vertex = intersect( edge1.first, edge1.second, edge2.first, edge2.second );
 
  217      if ( vertex.isNull() )
 
  220      const QPointF originalPoint = triangle.at( i );
 
  223      double delta = std::pow( vertex.x() - originalPoint.x(), 2 ) + std::pow( vertex.y() - originalPoint.y(), 2 );
 
  224      if ( delta > MAX_TRIANGLE_GROW_PIXELS_SQUARED )
 
  226        double dx = ( vertex.x() - originalPoint.x() ) * MAX_TRIANGLE_GROW_PIXELS_SQUARED / delta;
 
  227        double dy = ( vertex.y() - originalPoint.y() ) * MAX_TRIANGLE_GROW_PIXELS_SQUARED / delta;
 
  228        result << triangle.at( i ) + QPointF( dx, dy );
 
  233    result << result.at( 0 );
 
  239  const double minAngle = smallestAngleInTriangle( triangle ) * 180 / M_PI;
 
  240  if ( std::isnan( minAngle ) || minAngle < 0.1 )
 
  248    growTriangle( triangle, 1 ),
 
  250    textureX1, textureY1,
 
  251    textureX2, textureY2,
 
 
@ RequiresTextures
Renderer requires textures.
@ ForceRasterRender
Layer should always be rendered as a raster image.
@ RendersTriangles
Renderer can render triangle primitives.
A fill symbol type, for rendering Polygon and MultiPolygon geometries.
static QgsFillSymbol * createSimple(const QVariantMap &properties)
Create a fill symbol with one symbol layer: SimpleFill with specified properties.
static bool drawTriangleUsingTexture(QPainter *painter, const QPolygonF &triangle, const QImage &textureImage, float textureX1, float textureY1, float textureX2, float textureY2, float textureX3, float textureY3)
Draws a triangle onto a painter using a mapped texture image.
The class is used as a container of context for various read/write operations on other objects.
QPainter * painter()
Returns the destination QPainter for the render operation.
static QDomElement saveSymbol(const QString &symbolName, const QgsSymbol *symbol, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a symbol definition to XML.
Encapsulates the render context for a 2D tiled scene rendering operation.
void textureCoordinates(float &textureX1, float &textureY1, float &textureX2, float &textureY2, float &textureX3, float &textureY3) const
Returns the current texture coordinates.
QgsRenderContext & renderContext()
Returns a reference to the context's render context.
QImage textureImage() const
Returns the current texture image.
Abstract base class for 2d tiled scene renderers.
void saveCommonProperties(QDomElement &element, const QgsReadWriteContext &context) const
Saves common renderer properties (such as point size and screen error) to the specified DOM element.
virtual void stopRender(QgsTiledSceneRenderContext &context)
Must be called when a render cycle has finished, to allow the renderer to clean up.
virtual void startRender(QgsTiledSceneRenderContext &context)
Must be called when a new render cycle is started.
void copyCommonProperties(QgsTiledSceneRenderer *destination) const
Copies common tiled scene renderer properties (such as screen error) to the destination renderer.
void startRender(QgsTiledSceneRenderContext &context) override
Must be called when a new render cycle is started.
QDomElement save(QDomDocument &doc, const QgsReadWriteContext &context) const override
Saves the renderer configuration to an XML element.
static QgsFillSymbol * createDefaultFillSymbol()
Returns a copy of the default fill symbol used to render triangles without textures.
QgsTiledSceneTextureRenderer()
Constructor for QgsTiledSceneTextureRenderer.
QgsFillSymbol * fillSymbol() const
Returns the fill symbol used to render triangles without textures.
void renderLine(QgsTiledSceneRenderContext &context, const QPolygonF &line) override
Renders a line.
QgsTiledSceneRenderer * clone() const override
Create a deep copy of this renderer.
void setFillSymbol(QgsFillSymbol *symbol)
Sets the fill symbol used to render triangles without textures.
QString type() const override
Returns the identifier of the renderer type.
static QgsTiledSceneRenderer * create(QDomElement &element, const QgsReadWriteContext &context)
Creates a textured renderer from an XML element.
void stopRender(QgsTiledSceneRenderContext &context) override
Must be called when a render cycle has finished, to allow the renderer to clean up.
~QgsTiledSceneTextureRenderer()
void renderTriangle(QgsTiledSceneRenderContext &context, const QPolygonF &triangle) override
Renders a triangle.
Qgis::TiledSceneRendererFlags flags() const override
Returns flags which control how the renderer behaves.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)