Skip to content

Commit

Permalink
Linepattern
Browse files Browse the repository at this point in the history
  • Loading branch information
elpaso committed Jan 10, 2023
1 parent ddd010d commit 889a263
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 78 deletions.
Expand Up @@ -997,10 +997,10 @@ Evaluates a map of properties using the given ``context`` and returns a variant
.. versionadded:: 3.18
%End

static QSize tileSize( int width, int height, double &angleRad /In,Out/, const QSize maxSize = QSize() );
static QSize tileSize( int width, int height, double &angleRad /In,Out/ );
%Docstring
Calculate the minimum size in pixels of a symbol tile given the symbol ``width`` and ``height`` and the grid rotation ``angle`` in radians.
The method makes approximations in order to generate the smallest possible tile.
The method makes approximations and can modify ``angle`` in order to generate the smallest possible tile.

.. versionadded:: 3.30
%End
Expand Down
24 changes: 8 additions & 16 deletions src/core/symbology/qgsfillsymbollayer.cpp
Expand Up @@ -2642,14 +2642,15 @@ void QgsLinePatternFillSymbolLayer::stopFeatureRender( const QgsFeature &, QgsRe

QImage QgsLinePatternFillSymbolLayer::toTiledPattern() const
{
const double lineAngleRads { qDegreesToRadians( mLineAngle ) };
double distancePx = QgsSymbolLayerUtils::rescaleUom( mDistance, mDistanceUnit, {} );
// adjust tile size to generate a tile with seamless edges
const QSize size { static_cast<int>( distancePx / std::cos( lineAngleRads ) ), static_cast<int>( distancePx / std::sin( lineAngleRads ) ) };

if ( size.isEmpty() || size.width() > 512 || size.height() > 512 )
double lineAngleRads { qDegreesToRadians( mLineAngle ) };
double distancePx { QgsSymbolLayerUtils::rescaleUom( mDistance, mDistanceUnit, {} ) };

QSize size { static_cast<int>( distancePx ), static_cast<int>( distancePx ) };

if ( ! qgsDoubleNear( lineAngleRads, 0 ) )
{
return QImage( );
size = QSize( static_cast<int>( distancePx / std::sin( lineAngleRads ) ), static_cast<int>( distancePx / std::cos( lineAngleRads ) ) );
}

QPixmap pixmap( size );
Expand Down Expand Up @@ -4417,19 +4418,11 @@ QImage QgsPointPatternFillSymbolLayer::toTiledPattern() const

QSize size { static_cast<int>( distanceXPx ), static_cast<int>( distanceYPx ) };


if ( mAngle != 0 )
if ( ! qgsDoubleNear( angleRads, 0 ) )
{
size = QgsSymbolLayerUtils::tileSize( distanceXPx, distanceYPx, angleRads );
}

/*
if ( size.isEmpty() || size.width() > 512 || size.height() > 512 )
{
return QImage( );
}
*/

QPixmap pixmap( size );
pixmap.fill( Qt::transparent );
QPainter painter;
Expand All @@ -4444,7 +4437,6 @@ QImage QgsPointPatternFillSymbolLayer::toTiledPattern() const

std::unique_ptr< QgsPointPatternFillSymbolLayer > layerClone( clone() );

// !!!!!!!
layerClone->setAngle( qRadiansToDegrees( angleRads ) );

layerClone->drawPreviewIcon( symbolContext, pixmap.size() );
Expand Down
67 changes: 9 additions & 58 deletions src/core/symbology/qgssymbollayerutils.cpp
Expand Up @@ -5098,11 +5098,9 @@ QgsStringMap QgsSymbolLayerUtils::evaluatePropertiesMap( const QMap<QString, Qgs
return properties;
}

QSize QgsSymbolLayerUtils::tileSize( int width, int height, double &angleRad, const QSize maxSize )
QSize QgsSymbolLayerUtils::tileSize( int width, int height, double &angleRad )
{

const QSize maxSizeActual { ! maxSize.isValid() ? QSize( width * 10, height * 10 ) : maxSize };

struct rationalTangent
{
int a;
Expand Down Expand Up @@ -5154,61 +5152,14 @@ QSize QgsSymbolLayerUtils::tileSize( int width, int height, double &angleRad, co
}
}

bool asc { true };
int increment { 1 };
bool endTouched { false };
bool startTouched { false };

while ( !( startTouched && endTouched ) && rTanIdx >= 0 && rTanIdx < rationalTangents.count() )
{

rationalTangent bTan { rationalTangents.at( rTanIdx ) };
angleRad = bTan.angle;
const double k { bTan.b *height *width / std::cos( angleRad ) };
const int hcfH = std::gcd( bTan.a * height, bTan.b * width );
const int hcfW = std::gcd( bTan.b * height, bTan.a * width );
const double W1 = k / hcfW;
const double H1 = k / hcfH;

qDebug() << "TO TILE" << rTanIdx << qRadiansToDegrees( angleRad ) << angleRad << W1 << H1 << "K:" << k << hcfW << hcfH << bTan.a << bTan.b;

return QSize( W1, H1 );

if ( W1 <= maxSizeActual.width() && H1 <= maxSizeActual.height() )
{
return QSize( W1, H1 );
}
else
{
if ( rTanIdx == 0 )
{
startTouched = true;
rTanIdx = rTanIdx + increment;
continue;
}
else if ( rTanIdx == rationalTangents.count() - 1 )
{
endTouched = true;
rTanIdx = rTanIdx - increment;
continue;
}
const rationalTangent bTan { rationalTangents.at( rTanIdx ) };
angleRad = bTan.angle;
const double k { bTan.b *height *width / std::cos( angleRad ) };
const int hcfH { std::gcd( bTan.a * height, bTan.b * width ) };
const int hcfW { std::gcd( bTan.b * height, bTan.a * width ) };
const int W1 { static_cast<int>( std::round( k / hcfW ) ) };
const int H1 { static_cast<int>( std::round( k / hcfH ) ) };

if ( startTouched )
{
rTanIdx += 1;
}
else if ( endTouched )
{
rTanIdx -= 1;
}
else
{
rTanIdx = asc ? rTanIdx + increment : rTanIdx - increment;
asc = ! asc;
increment += 1;
}
}
}
return QSize( W1, H1 );

return QSize( );
}
4 changes: 2 additions & 2 deletions src/core/symbology/qgssymbollayerutils.h
Expand Up @@ -899,10 +899,10 @@ class CORE_EXPORT QgsSymbolLayerUtils

/**
* Calculate the minimum size in pixels of a symbol tile given the symbol \a width and \a height and the grid rotation \a angle in radians.
* The method makes approximations in order to generate the smallest possible tile.
* The method makes approximations and can modify \a angle in order to generate the smallest possible tile.
* \since QGIS 3.30
*/
static QSize tileSize( int width, int height, double &angleRad SIP_INOUT, const QSize maxSize = QSize() );
static QSize tileSize( int width, int height, double &angleRad SIP_INOUT );

///@cond PRIVATE
#ifndef SIP_RUN
Expand Down

0 comments on commit 889a263

Please sign in to comment.