double QgsTolerance::computeMapUnitPerPixel( QgsMapLayer* layer, const QgsMapSettings& mapSettings ) { if ( ! mapSettings.hasCrsTransformEnabled() ) { // if the on-the-fly projections are not enabled, layer units pre pixel are the same as map units per pixel return mapSettings.mapUnitsPerPixel(); } // the layer is projected. Find out how many pixels are in one map unit - either horizontal and vertical direction // this check might not work correctly in some cases // (on a large area the pixels projected around "0,0" can have different properties from the actual point) QgsPoint p1 = toLayerCoordinates( layer, mapSettings, QPoint( 0, 1 ) ); QgsPoint p2 = toLayerCoordinates( layer, mapSettings, QPoint( 0, 2 ) ); QgsPoint p3 = toLayerCoordinates( layer, mapSettings, QPoint( 1, 0 ) ); QgsPoint p4 = toLayerCoordinates( layer, mapSettings, QPoint( 2, 0 ) ); double x = p1.sqrDist( p2 ); double y = p3.sqrDist( p4 ); if ( x > y ) { return sqrt( x ); } else { return sqrt( y ); } }
// return ratio [mu/lu] between map units and layer units // this is of course only an approximation double _ratioMU2LU( const QgsMapSettings& mapSettings, QgsMapLayer* layer ) { double distMU = mapSettings.mapUnitsPerPixel(); QgsPoint ptMapCenterMU = mapSettings.visibleExtent().center(); QgsPoint ptMapCenterRightMU( ptMapCenterMU.x() + distMU, ptMapCenterMU.y() ); QgsPoint ptMapCenterLU = mapSettings.mapToLayerCoordinates( layer, ptMapCenterMU ); QgsPoint ptMapCenterRightLU = mapSettings.mapToLayerCoordinates( layer, ptMapCenterRightMU ); double distLU = sqrt( ptMapCenterLU.sqrDist( ptMapCenterRightLU ) ); double ratio = distMU / distLU; return ratio; }
double QgsTolerance::toleranceInProjectUnits( double tolerance, QgsMapLayer* layer, const QgsMapSettings& mapSettings, QgsTolerance::UnitType units ) { // converts to map units if ( units == ProjectUnits ) return tolerance; else if ( units == Pixels ) return tolerance * mapSettings.mapUnitsPerPixel(); else // units == LayerUnits { // [mu] = [lu] * [mu/lu] return tolerance * _ratioMU2LU( mapSettings, layer ); } }
int QgsDecorationGrid::yGridLines( const QgsMapSettings &mapSettings, QList< QPair< qreal, QLineF > > &lines ) const { // prepare vertical lines lines.clear(); if ( mGridIntervalX <= 0.0 ) { return 1; } const QgsMapToPixel &m2p = mapSettings.mapToPixel(); // draw nothing if the distance between grid lines would be less than 1px // otherwise the grid lines would completely cover the whole map //if ( mapBoundingRect.height() / mGridIntervalY >= p->device()->height() ) if ( mGridIntervalX / mapSettings.mapUnitsPerPixel() < 1 ) return 1; const QPolygonF &canvasPoly = canvasPolygon( mapSettings ); const QPolygonF &mapPolygon = canvasExtent( mapSettings ); QLineF lineSouth( mapPolygon[3], mapPolygon[2] ); QLineF lineNorth( mapPolygon[0], mapPolygon[1] ); double len = lineSouth.length(); Q_ASSERT( std::fabs( len - lineNorth.length() ) < 1e-6 ); // no shear const QRectF &mapBoundingRect = mapPolygon.boundingRect(); double roundCorrection = mapBoundingRect.left() > 0 ? 1.0 : 0.0; double dist = static_cast< int >( ( mapBoundingRect.left() - mGridOffsetX ) / mGridIntervalX + roundCorrection ) * mGridIntervalX + mGridOffsetX; dist = dist - mapBoundingRect.left(); while ( dist < len ) { double t = dist / len; QPointF p0( lineNorth.pointAt( t ) ); QPointF p1( lineSouth.pointAt( t ) ); QLineF line( p0, p1 ); clipByRect( line, canvasPoly ); line = QLineF( m2p.transform( QgsPointXY( line.pointAt( 0 ) ) ).toQPointF(), m2p.transform( QgsPointXY( line.pointAt( 1 ) ) ).toQPointF() ); lines.push_back( qMakePair( p0.x(), line ) ); dist += mGridIntervalX; } return 0; }