12 changes: 12 additions & 0 deletions src/app/qgsoptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@

#define CPL_SUPRESS_CPLUSPLUS
#include <gdal.h>
#include <geos_c.h>

/**
* \class QgsOptions - Set user options and preferences
* Constructor
Expand Down Expand Up @@ -392,6 +394,14 @@ QgsOptions::QgsOptions( QWidget *parent, Qt::WFlags fl ) :
mMarkerStyleComboBox->addItem( tr( "Cross" ) );
mMarkerStyleComboBox->addItem( tr( "None" ) );

mValidateGeometries->clear();
mValidateGeometries->addItem( tr( "Off" ) );
mValidateGeometries->addItem( tr( "QGIS" ) );
#if defined(GEOS_VERSION_MAJOR) && defined(GEOS_VERSION_MINOR) && \
( (GEOS_VERSION_MAJOR==3 && GEOS_VERSION_MINOR>=3) || GEOS_VERSION_MAJOR>3)
mValidateGeometries->addItem( tr( "GEOS" ) );
#endif

QString markerStyle = settings.value( "/qgis/digitizing/marker_style", "Cross" ).toString();
if ( markerStyle == "SemiTransparentCircle" )
{
Expand All @@ -409,6 +419,7 @@ QgsOptions::QgsOptions( QWidget *parent, Qt::WFlags fl ) :

chkReuseLastValues->setChecked( settings.value( "/qgis/digitizing/reuseLastValues", false ).toBool() );
chkDisableAttributeValuesDlg->setChecked( settings.value( "/qgis/digitizing/disable_enter_attribute_values_dialog", false ).toBool() );
mValidateGeometries->setCurrentIndex( settings.value( "/qgis/digitizing/validate_geometries", 1 ).toInt() );

#ifdef Q_WS_MAC //MH: disable incremental update on Mac for now to avoid problems with resizing
groupBox_5->setEnabled( false );
Expand Down Expand Up @@ -757,6 +768,7 @@ void QgsOptions::saveOptions()

settings.setValue( "/qgis/digitizing/reuseLastValues", chkReuseLastValues->isChecked() );
settings.setValue( "/qgis/digitizing/disable_enter_attribute_values_dialog", chkDisableAttributeValuesDlg->isChecked() );
settings.setValue( "/qgis/digitizing/validate_geometries", mValidateGeometries->currentIndex() );

//
// Locale settings
Expand Down
2 changes: 2 additions & 0 deletions src/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ SET(QGIS_CORE_SRCS
qgsfeature.cpp
qgsfield.cpp
qgsgeometry.cpp
qgsgeometryvalidator.cpp
qgshttptransaction.cpp
qgslabel.cpp
qgslabelattributes.cpp
Expand Down Expand Up @@ -249,6 +250,7 @@ SET(QGIS_CORE_MOC_HDRS
qgsrasterdataprovider.h
qgsnetworkaccessmanager.h
qgsvectordataprovider.h
qgsgeometryvalidator.h

composer/qgsaddremoveitemcommand.h
composer/qgscomposerlegend.h
Expand Down
3 changes: 3 additions & 0 deletions src/core/qgsapplication.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "qgsmaplayerregistry.h"
#include "qgsproviderregistry.h"
#include "qgsexception.h"
#include "qgsgeometry.h"

#include <QDir>
#include <QFileOpenEvent>
Expand Down Expand Up @@ -72,6 +73,8 @@ QgsApplication::QgsApplication( int & argc, char ** argv, bool GUIenabled, QStri
}
void QgsApplication::init( QString customConfigPath )
{
qRegisterMetaType<QgsGeometry::Error>( "QgsGeometry::Error" );

// check if QGIS is run from build directory (not the install directory)
QDir appDir( applicationDirPath() );
if ( appDir.exists( "source_path.txt" ) )
Expand Down
49 changes: 14 additions & 35 deletions src/core/qgscoordinatereferencesystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ QgsCoordinateReferenceSystem& QgsCoordinateReferenceSystem::operator=( const Qgs
mAuthId = srs.mAuthId;
mIsValidFlag = srs.mIsValidFlag;
mValidationHint = srs.mValidationHint;
mWkt = srs.mWkt;
if ( mIsValidFlag )
{
OSRDestroySpatialReference( mCRS );
Expand Down Expand Up @@ -217,6 +218,7 @@ bool QgsCoordinateReferenceSystem::loadFromDb( QString db, QString expression, Q
{
QgsDebugMsgLevel( "load CRS from " + db + " where " + expression + " is " + value, 3 );
mIsValidFlag = false;
mWkt.clear();

QFileInfo myInfo( db );
if ( !myInfo.exists() )
Expand Down Expand Up @@ -292,6 +294,7 @@ bool QgsCoordinateReferenceSystem::loadFromDb( QString db, QString expression, Q
bool QgsCoordinateReferenceSystem::createFromWkt( QString theWkt )
{
mIsValidFlag = false;
mWkt.clear();

if ( theWkt.isEmpty() )
{
Expand Down Expand Up @@ -369,6 +372,7 @@ bool QgsCoordinateReferenceSystem::createFromProj4( const QString theProj4String
//
QgsDebugMsg( "proj4: " + theProj4String );
mIsValidFlag = false;
mWkt.clear();

QRegExp myProjRegExp( "\\+proj=(\\S+)" );
int myStart = myProjRegExp.indexIn( theProj4String );
Expand Down Expand Up @@ -565,7 +569,6 @@ bool QgsCoordinateReferenceSystem::createFromProj4( const QString theProj4String
}
}


return mIsValidFlag;
}

Expand Down Expand Up @@ -785,6 +788,7 @@ void QgsCoordinateReferenceSystem::setProj4String( QString theProj4String )
OSRDestroySpatialReference( mCRS );
mCRS = OSRNewSpatialReference( NULL );
mIsValidFlag = OSRImportFromProj4( mCRS, theProj4String.toLatin1().constData() ) == OGRERR_NONE;
mWkt.clear();
setMapUnits();

#if defined(QGISDEBUG) && QGISDEBUG>=3
Expand Down Expand Up @@ -977,33 +981,7 @@ long QgsCoordinateReferenceSystem::findMatchingProj()

bool QgsCoordinateReferenceSystem::operator==( const QgsCoordinateReferenceSystem &theSrs )
{
if ( !mIsValidFlag || !theSrs.mIsValidFlag )
{
return false;
}
char *thisStr;
char *otherStr;

// OSRIsSame is not relaibel when it comes to comparing +towgs84 parameters
// Use string compare on WKT instead.
if (( OSRExportToWkt( mCRS, &thisStr ) == OGRERR_NONE ) )
{
if ( OSRExportToWkt( theSrs.mCRS, &otherStr ) == OGRERR_NONE )
{
QgsDebugMsgLevel( QString( "Comparing " ) + thisStr, 3 );
QgsDebugMsgLevel( QString( " with " ) + otherStr, 3 );
if ( !strcmp( thisStr, otherStr ) )
{
QgsDebugMsgLevel( QString( "MATCHED!" ) + otherStr, 3 );
CPLFree( thisStr );
CPLFree( otherStr );
return true;
}
CPLFree( otherStr );
}
CPLFree( thisStr );
}
return false;
return mIsValidFlag && theSrs.mIsValidFlag && toWkt() == theSrs.toWkt();
}

bool QgsCoordinateReferenceSystem::operator!=( const QgsCoordinateReferenceSystem &theSrs )
Expand All @@ -1020,15 +998,16 @@ bool QgsCoordinateReferenceSystem::equals( QString theProj4String )

QString QgsCoordinateReferenceSystem::toWkt() const
{
QString myWkt;
char* Wkt;
if ( OSRExportToWkt( mCRS, &Wkt ) == OGRERR_NONE )
if ( mWkt.isEmpty() )
{
myWkt = Wkt;
OGRFree( Wkt );
char *wkt;
if ( OSRExportToWkt( mCRS, &wkt ) == OGRERR_NONE )
{
mWkt = wkt;
OGRFree( wkt );
}
}

return myWkt;
return mWkt;
}

bool QgsCoordinateReferenceSystem::readXML( QDomNode & theNode )
Expand Down
1 change: 1 addition & 0 deletions src/core/qgscoordinatereferencesystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,7 @@ class CORE_EXPORT QgsCoordinateReferenceSystem
bool loadFromDb( QString db, QString expression, QString value );

QString mValidationHint;
mutable QString mWkt;

static CUSTOM_CRS_VALIDATION mCustomSrsValidation;
};
Expand Down
311 changes: 14 additions & 297 deletions src/core/qgsgeometry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ email : morb at ozemail dot com dot au
#include "qgsmaplayerregistry.h"
#include "qgsvectorlayer.h"
#include "qgsproject.h"
#include "qgsmessagelog.h"
#include "qgsgeometryvalidator.h"

#define DEFAULT_QUADRANT_SEGMENTS 8

Expand Down Expand Up @@ -181,19 +183,19 @@ static GEOSGeometry *cloneGeosGeom( const GEOSGeometry *geom )
#endif

QgsGeometry::QgsGeometry()
: mGeometry( 0 ),
mGeometrySize( 0 ),
mGeos( 0 ),
mDirtyWkb( false ),
mDirtyGeos( false )
: mGeometry( 0 )
, mGeometrySize( 0 )
, mGeos( 0 )
, mDirtyWkb( false )
, mDirtyGeos( false )
{
}

QgsGeometry::QgsGeometry( QgsGeometry const & rhs )
: mGeometry( 0 ),
mGeometrySize( rhs.mGeometrySize ),
mDirtyWkb( rhs.mDirtyWkb ),
mDirtyGeos( rhs.mDirtyGeos )
: mGeometry( 0 )
, mGeometrySize( rhs.mGeometrySize )
, mDirtyWkb( rhs.mDirtyWkb )
, mDirtyGeos( rhs.mDirtyGeos )
{
if ( mGeometrySize && rhs.mGeometry )
{
Expand Down Expand Up @@ -6399,296 +6401,11 @@ int QgsGeometry::avoidIntersections()
return returnValue;
}

//
// distance of point q from line through p in direction v
// return >0 => q lies left of the line
// <0 => q lies right of the line
//
static double distLine2Point( QgsPoint p, QgsVector v, QgsPoint q )
{
if ( v.length() == 0 )
{
throw QgsException( QObject::tr( "invalid line" ) );
}

return ( v.x()*( q.y() - p.y() ) - v.y()*( q.x() - p.x() ) ) / v.length();
}

static bool intersectLines( QgsPoint p, QgsVector v, QgsPoint q, QgsVector w, QgsPoint &s )
{
double d = v.y() * w.x() - v.x() * w.y();

if ( d == 0 )
return false;

double dx = q.x() - p.x();
double dy = q.y() - p.y();
double k = ( dy * w.x() - dx * w.y() ) / d;

s = p + v * k;

return true;
}

bool pointInRing( const QgsPolyline &ring, const QgsPoint &p )
{
bool inside = false;
int j = ring.size() - 1;

for ( int i = 0; i < ring.size(); i++ )
{
if ( ring[i].x() == p.x() && ring[i].y() == p.y() )
return true;

if (( ring[i].y() < p.y() && ring[j].y() >= p.y() ) ||
( ring[j].y() < p.y() && ring[i].y() >= p.y() ) )
{
if ( ring[i].x() + ( p.y() - ring[i].y() ) / ( ring[j].y() - ring[i].y() )*( ring[j].x() - ring[i].x() ) <= p.x() )
inside = !inside;
}

j = i;
}

return inside;
}

static bool ringInRing( const QgsPolyline &inside, const QgsPolyline &outside )
{
for ( int i = 0; i < inside.size(); i++ )
{
if ( !pointInRing( outside, inside[i] ) )
return false;
}

return true;
}

void QgsGeometry::checkRingIntersections( QList<Error> &errors,
int p0, int i0, const QgsPolyline &ring0,
int p1, int i1, const QgsPolyline &ring1 )
{
for ( int i = 0; i < ring0.size() - 1; i++ )
{
QgsVector v = ring0[i+1] - ring0[i];

for ( int j = 0; j < ring1.size() - 1; j++ )
{
QgsVector w = ring1[j+1] - ring1[j];

QgsPoint s;
if ( intersectLines( ring0[i], v, ring1[j], w, s ) )
{
double d = -distLine2Point( ring0[i], v.perpVector(), s );

if ( d >= 0 && d <= v.length() )
{
d = -distLine2Point( ring1[j], w.perpVector(), s );
if ( d >= 0 && d <= w.length() )
{
QString msg = QObject::tr( "segment %1 of ring %2 of polygon %3 intersects segment %4 of ring %5 of polygon %6 at %7" )
.arg( i0 ).arg( i ).arg( p0 )
.arg( i1 ).arg( j ).arg( p1 )
.arg( s.toString() );
QgsDebugMsg( msg );
errors << Error( msg, s );
if ( errors.size() > 100 )
{
QString msg = QObject::tr( "stopping validation after more than 100 errors" );
QgsDebugMsg( msg );
errors << Error( msg );
return;
}
}
}
}
}
}
}

void QgsGeometry::validatePolyline( QList<Error> &errors, int i, QgsPolyline line, bool ring )
{
if ( ring )
{
if ( line.size() < 3 )
{
QString msg = QObject::tr( "ring %1 with less than three points" ).arg( i );
QgsDebugMsg( msg );
errors << Error( msg );
return;
}

if ( line[0] != line[ line.size()-1 ] )
{
QString msg = QObject::tr( "ring %1 not closed" ).arg( i );
QgsDebugMsg( msg );
errors << Error( msg );
return;
}
}
else if ( line.size() < 2 )
{
QString msg = QObject::tr( "line %1 with less than two points" ).arg( i );
QgsDebugMsg( msg );
errors << Error( msg );
return;
}

int j = 0;
while ( j < line.size() - 1 )
{
int n = 0;
while ( j < line.size() - 1 && line[j] == line[j+1] )
{
line.remove( j );
n++;
}

if ( n > 0 )
{
QString msg = QObject::tr( "line %1 contains %n duplicate node(s) at %2", "number of duplicate nodes", n ).arg( i ).arg( j );
QgsDebugMsg( msg );
errors << Error( msg, line[j] );
}

j++;
}

for ( j = 0; j < line.size() - 3; j++ )
{
QgsVector v = line[j+1] - line[j];
double vl = v.length();

int n = ( j == 0 && ring ) ? line.size() - 2 : line.size() - 1;

for ( int k = j + 2; k < n; k++ )
{
QgsVector w = line[k+1] - line[k];

QgsPoint s;
if ( !intersectLines( line[j], v, line[k], w, s ) )
continue;

double d = -distLine2Point( line[j], v.perpVector(), s );
if ( d < 0 || d > vl )
continue;

d = -distLine2Point( line[k], w.perpVector(), s );
if ( d < 0 || d > w.length() )
continue;

QString msg = QObject::tr( "segments %1 and %2 of line %3 intersect at %4" ).arg( j ).arg( k ).arg( i ).arg( s.toString() );
QgsDebugMsg( msg );
errors << Error( msg, s );
if ( errors.size() > 100 )
{
QString msg = QObject::tr( "stopping validation after more than 100 errors" );
QgsDebugMsg( msg );
errors << Error( msg );
return;
}
}
}
}

void QgsGeometry::validatePolygon( QList<Error> &errors, int idx, const QgsPolygon &polygon )
{
// check if holes are inside polygon
for ( int i = 1; i < polygon.size(); i++ )
{
if ( !ringInRing( polygon[i], polygon[0] ) )
{
QString msg = QObject::tr( "ring %1 of polygon %2 not in exterior ring" ).arg( i ).arg( idx );
QgsDebugMsg( msg );
errors << Error( msg );
}
}

// check holes for intersections
for ( int i = 1; i < polygon.size(); i++ )
{
for ( int j = i + 1; j < polygon.size(); j++ )
{
checkRingIntersections( errors, idx, i, polygon[i], idx, j, polygon[j] );
}
}

// check if rings are self-intersecting
for ( int i = 0; i < polygon.size(); i++ )
{
validatePolyline( errors, i, polygon[i], true );
}
}

void QgsGeometry::validateGeometry( QList<Error> &errors )
{
errors.clear();

switch ( wkbType() )
{
case QGis::WKBPoint:
case QGis::WKBPoint25D:
case QGis::WKBMultiPoint:
case QGis::WKBMultiPoint25D:
break;

case QGis::WKBLineString:
case QGis::WKBLineString25D:
validatePolyline( errors, 0, asPolyline() );
break;

case QGis::WKBMultiLineString:
case QGis::WKBMultiLineString25D:
{
QgsMultiPolyline mp = asMultiPolyline();
for ( int i = 0; i < mp.size(); i++ )
validatePolyline( errors, i, mp[i] );
}
break;

case QGis::WKBPolygon:
case QGis::WKBPolygon25D:
{
validatePolygon( errors, 0, asPolygon() );
}
break;

case QGis::WKBMultiPolygon:
case QGis::WKBMultiPolygon25D:
{
QgsMultiPolygon mp = asMultiPolygon();
for ( int i = 0; i < mp.size(); i++ )
{
validatePolygon( errors, i, mp[i] );
}

for ( int i = 0; i < mp.size(); i++ )
{
for ( int j = i + 1; j < mp.size(); j++ )
{
if ( ringInRing( mp[i][0], mp[j][0] ) )
{
errors << Error( QObject::tr( "polygon %1 inside polygon %2" ).arg( i ).arg( j ) );
}
else if ( ringInRing( mp[j][0], mp[i][0] ) )
{
errors << Error( QObject::tr( "polygon %1 inside polygon %2" ).arg( j ).arg( i ) );
}
else
{
checkRingIntersections( errors, i, 0, mp[i][0], j, 0, mp[j][0] );
}
}
}
}
break;

case QGis::WKBNoGeometry:
case QGis::WKBUnknown:
QgsDebugMsg( QObject::tr( "Unknown geometry type" ) );
errors << Error( QObject::tr( "Unknown geometry type" ) );
break;
}
QgsGeometryValidator *gv = new QgsGeometryValidator( this, &errors );
gv->start();
delete gv;
}

bool QgsGeometry::isGeosValid()
Expand Down
9 changes: 1 addition & 8 deletions src/core/qgsgeometry.h
Original file line number Diff line number Diff line change
Expand Up @@ -415,13 +415,13 @@ class CORE_EXPORT QgsGeometry
*/
int avoidIntersections();


class Error
{
QString message;
QgsPoint location;
bool hasLocation;
public:
Error() : message( "none" ), hasLocation( false ) {}
Error( QString m ) : message( m ), hasLocation( false ) {}
Error( QString m, QgsPoint p ) : message( m ), location( p ), hasLocation( true ) {}

Expand All @@ -435,9 +435,6 @@ class CORE_EXPORT QgsGeometry
**/
void validateGeometry( QList<Error> &errors );

static void validatePolyline( QList<Error> &errors, int i, QgsPolyline polyline, bool ring = false );
static void validatePolygon( QList<Error> &errors, int i, const QgsPolygon &polygon );

private:
// Private variables

Expand Down Expand Up @@ -566,10 +563,6 @@ class CORE_EXPORT QgsGeometry
/** return polygon from wkb */
QgsPolygon asPolygon( unsigned char*& ptr, bool hasZValue );

static void checkRingIntersections( QList<Error> &errors,
int p0, int i0, const QgsPolyline &ring0,
int p1, int i1, const QgsPolyline &ring1 );

static bool geosRelOp( char( *op )( const GEOSGeometry*, const GEOSGeometry * ),
QgsGeometry *a, QgsGeometry *b );

Expand Down
400 changes: 400 additions & 0 deletions src/core/qgsgeometryvalidator.cpp

Large diffs are not rendered by default.

60 changes: 60 additions & 0 deletions src/core/qgsgeometryvalidator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/***************************************************************************
qgsgeometryvalidator.h - geometry validation thread
-------------------------------------------------------------------
Date : 03.01.2012
Copyright : (C) 2012 by Juergen E. Fischer
email : jef at norbit dot de
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#ifndef QGSGEOMETRYVALIDATOR_H
#define QGSGEOMETRYVALIDATOR_H

#include <QThread>
#include "qgsgeometry.h"

class QgsGeometryValidator : public QThread
{
Q_OBJECT;

public:
//! Constructor
QgsGeometryValidator( QgsGeometry *g, QList<QgsGeometry::Error> *errors = 0 );
~QgsGeometryValidator();

void run();
void stop();

/** Validate geometry and produce a list of geometry errors
* @note added in 1.9
**/
static void validateGeometry( QgsGeometry *g, QList<QgsGeometry::Error> &errors );

signals:
void errorFound( QgsGeometry::Error );

public slots:
void addError( QgsGeometry::Error );

private:
void validatePolyline( int i, QgsPolyline polyline, bool ring = false );
void validatePolygon( int i, const QgsPolygon &polygon );
void checkRingIntersections( int p0, int i0, const QgsPolyline &ring0, int p1, int i1, const QgsPolyline &ring1 );
double distLine2Point( QgsPoint p, QgsVector v, QgsPoint q );
bool intersectLines( QgsPoint p, QgsVector v, QgsPoint q, QgsVector w, QgsPoint &s );
bool ringInRing( const QgsPolyline &inside, const QgsPolyline &outside );
bool pointInRing( const QgsPolyline &ring, const QgsPoint &p );

QgsGeometry mG;
QList<QgsGeometry::Error> *mErrors;
bool mStop;
int mErrorCount;
}; // class QgsGeometryValidator

#endif
43 changes: 26 additions & 17 deletions src/core/qgsmaprenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ QgsMapRenderer::QgsMapRenderer()
{
mScaleCalculator = new QgsScaleCalculator;
mDistArea = new QgsDistanceArea;
mCachedTrForLayer = 0;
mCachedTr = 0;

mDrawing = false;
mOverview = false;
Expand All @@ -67,6 +69,7 @@ QgsMapRenderer::~QgsMapRenderer()
delete mDistArea;
delete mDestCRS;
delete mLabelingEngine;
delete mCachedTr;
}


Expand Down Expand Up @@ -702,8 +705,6 @@ bool QgsMapRenderer::splitLayersExtent( QgsMapLayer* layer, QgsRectangle& extent
{
try
{
QgsCoordinateTransform tr( layer->crs(), *mDestCRS );

#ifdef QGISDEBUG
// QgsLogger::debug<QgsRectangle>("Getting extent of canvas in layers CS. Canvas is ", extent, __FILE__, __FUNCTION__, __LINE__);
#endif
Expand All @@ -714,17 +715,17 @@ bool QgsMapRenderer::splitLayersExtent( QgsMapLayer* layer, QgsRectangle& extent
// extent separately.
static const double splitCoord = 180.0;

if ( tr.sourceCrs().geographicFlag() )
if ( mCachedTr->sourceCrs().geographicFlag() )
{
// Note: ll = lower left point
// and ur = upper right point
QgsPoint ll = tr.transform( extent.xMinimum(), extent.yMinimum(),
QgsCoordinateTransform::ReverseTransform );
QgsPoint ll = tr( layer )->transform( extent.xMinimum(), extent.yMinimum(),
QgsCoordinateTransform::ReverseTransform );

QgsPoint ur = tr.transform( extent.xMaximum(), extent.yMaximum(),
QgsCoordinateTransform::ReverseTransform );
QgsPoint ur = tr( layer )->transform( extent.xMaximum(), extent.yMaximum(),
QgsCoordinateTransform::ReverseTransform );

extent = tr.transformBoundingBox( extent, QgsCoordinateTransform::ReverseTransform );
extent = tr( layer )->transformBoundingBox( extent, QgsCoordinateTransform::ReverseTransform );

if ( ll.x() > ur.x() )
{
Expand All @@ -736,7 +737,7 @@ bool QgsMapRenderer::splitLayersExtent( QgsMapLayer* layer, QgsRectangle& extent
}
else // can't cross 180
{
extent = tr.transformBoundingBox( extent, QgsCoordinateTransform::ReverseTransform );
extent = tr( layer )->transformBoundingBox( extent, QgsCoordinateTransform::ReverseTransform );
}
}
catch ( QgsCsException &cse )
Expand All @@ -757,8 +758,7 @@ QgsRectangle QgsMapRenderer::layerExtentToOutputExtent( QgsMapLayer* theLayer, Q
{
try
{
QgsCoordinateTransform tr( theLayer->crs(), *mDestCRS );
extent = tr.transformBoundingBox( extent );
extent = tr( theLayer )->transformBoundingBox( extent );
}
catch ( QgsCsException &cse )
{
Expand All @@ -780,8 +780,7 @@ QgsPoint QgsMapRenderer::layerToMapCoordinates( QgsMapLayer* theLayer, QgsPoint
{
try
{
QgsCoordinateTransform tr( theLayer->crs(), *mDestCRS );
point = tr.transform( point, QgsCoordinateTransform::ForwardTransform );
point = tr( theLayer )->transform( point, QgsCoordinateTransform::ForwardTransform );
}
catch ( QgsCsException &cse )
{
Expand All @@ -802,8 +801,7 @@ QgsPoint QgsMapRenderer::mapToLayerCoordinates( QgsMapLayer* theLayer, QgsPoint
{
try
{
QgsCoordinateTransform tr( theLayer->crs(), *mDestCRS );
point = tr.transform( point, QgsCoordinateTransform::ReverseTransform );
point = tr( theLayer )->transform( point, QgsCoordinateTransform::ReverseTransform );
}
catch ( QgsCsException &cse )
{
Expand All @@ -824,8 +822,7 @@ QgsRectangle QgsMapRenderer::mapToLayerCoordinates( QgsMapLayer* theLayer, QgsRe
{
try
{
QgsCoordinateTransform tr( theLayer->crs(), *mDestCRS );
rect = tr.transform( rect, QgsCoordinateTransform::ReverseTransform );
rect = tr( theLayer )->transform( rect, QgsCoordinateTransform::ReverseTransform );
}
catch ( QgsCsException &cse )
{
Expand Down Expand Up @@ -1103,4 +1100,16 @@ void QgsMapRenderer::setLabelingEngine( QgsLabelingEngineInterface* iface )
mLabelingEngine = iface;
}

QgsCoordinateTransform *QgsMapRenderer::tr( QgsMapLayer *layer )
{
if ( mCachedTrForLayer != layer )
{
delete mCachedTr;
mCachedTr = new QgsCoordinateTransform( layer->crs(), *mDestCRS );
mCachedTrForLayer = layer;
}

return mCachedTr;
}

bool QgsMapRenderer::mDrawing = false;
7 changes: 5 additions & 2 deletions src/core/qgsmaprenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -268,8 +268,6 @@ class CORE_EXPORT QgsMapRenderer : public QObject
@note this method was added in version 1.1*/
QgsOverlayObjectPositionManager* overlayManagerFromSettings();

protected:

//! indicates drawing in progress
static bool mDrawing;

Expand Down Expand Up @@ -323,6 +321,11 @@ class CORE_EXPORT QgsMapRenderer : public QObject

//! Locks rendering loop for concurrent draws
QMutex mRenderMutex;

private:
QgsCoordinateTransform *tr( QgsMapLayer *layer );
QgsCoordinateTransform *mCachedTr;
QgsMapLayer *mCachedTrForLayer;
};

#endif
Expand Down
1 change: 0 additions & 1 deletion src/core/qgspoint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,6 @@ QString QgsPoint::toDegreesMinutesSeconds( int thePrecision ) const
return rep;
}


QString QgsPoint::wellKnownText() const
{
return QString( "POINT(%1 %2)" ).arg( QString::number( m_x, 'f', 18 ) ).arg( QString::number( m_y, 'f', 18 ) );
Expand Down
6 changes: 3 additions & 3 deletions src/plugins/coordinate_capture/coordinatecapture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,9 @@ static const QgisPlugin::PLUGINTYPE sPluginType = QgisPlugin::UI;
* an interface object that provides access to exposed functions in QGIS.
* @param theQGisInterface - Pointer to the QGIS interface object
*/
CoordinateCapture::CoordinateCapture( QgisInterface * theQgisInterface ):
QgisPlugin( sName, sDescription, sPluginVersion, sPluginType ),
mQGisIface( theQgisInterface )
CoordinateCapture::CoordinateCapture( QgisInterface * theQgisInterface )
: QgisPlugin( sName, sDescription, sPluginVersion, sPluginType )
, mQGisIface( theQgisInterface )
{
}

Expand Down
3 changes: 2 additions & 1 deletion src/plugins/gps_importer/qgsgpsplugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ QgsGPSPlugin::~QgsGPSPlugin()
void QgsGPSPlugin::initGui()
{
// add an action to the toolbar
mQActionPointer = new QAction( QIcon(), tr( "&Gps Tools" ), this );
mQActionPointer = new QAction( QIcon(), tr( "&GPS Tools" ), this );
mCreateGPXAction = new QAction( QIcon(), tr( "&Create new GPX layer" ), this );
setCurrentTheme( "" );

Expand Down Expand Up @@ -202,6 +202,7 @@ void QgsGPSPlugin::drawVectorLayer( QString thePathNameQString,
void QgsGPSPlugin::unload()
{
// remove the GUI
mQGisInterface->layerToolBar()->addAction( mQActionPointer );
mQGisInterface->removePluginMenu( tr( "&Gps" ), mQActionPointer );
mQGisInterface->removePluginMenu( tr( "&Gps" ), mCreateGPXAction );
mQGisInterface->removeToolBarIcon( mQActionPointer );
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/gps_importer/qgsgpsplugingui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ void QgsGPSPluginGui::on_buttonBox_rejected()

void QgsGPSPluginGui::on_pbnGPXSelectFile_clicked()
{
QgsLogger::debug( " Gps File Importer::pbnGPXSelectFile_clicked() " );
QgsLogger::debug( " GPS File Importer::pbnGPXSelectFile_clicked() " );
QString myFileTypeQString;
QString myFilterString = tr( "GPS eXchange format (*.gpx)" );
QSettings settings;
Expand Down
29 changes: 19 additions & 10 deletions src/ui/qgsoptionsbase.ui
Original file line number Diff line number Diff line change
Expand Up @@ -1436,33 +1436,43 @@
<item row="3" column="0">
<widget class="QGroupBox" name="mEnterAttributeValuesGroupBox">
<property name="title">
<string>Enter attribute values</string>
<string>Other settings</string>
</property>
<layout class="QHBoxLayout">
<item>
<widget class="QCheckBox" name="chkReuseLastValues">
<layout class="QGridLayout" name="gridLayout_26">
<item row="0" column="0" colspan="2">
<widget class="QCheckBox" name="chkDisableAttributeValuesDlg">
<property name="text">
<string>Reuse last entered attribute values</string>
<string>Suppress attributes pop-up windows after each created feature</string>
</property>
<property name="tristate">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="chkDisableAttributeValuesDlg">
<item row="1" column="0" colspan="2">
<widget class="QCheckBox" name="chkReuseLastValues">
<property name="text">
<string>Suppress attributes pop-up windows after each created feature</string>
<string>Reuse last entered attribute values</string>
</property>
<property name="tristate">
<bool>false</bool>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="mValidateGeometries"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_19">
<property name="text">
<string>Validate geometries</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="4" column="0">
<item row="5" column="0">
<spacer>
<property name="orientation">
<enum>Qt::Vertical</enum>
Expand Down Expand Up @@ -2067,7 +2077,6 @@
<tabstop>mMarkerStyleComboBox</tabstop>
<tabstop>mMarkerSizeSpinBox</tabstop>
<tabstop>chkReuseLastValues</tabstop>
<tabstop>chkDisableAttributeValuesDlg</tabstop>
<tabstop>scrollArea_6</tabstop>
<tabstop>pbnSelectOtfProjection</tabstop>
<tabstop>leProjectGlobalCrs</tabstop>
Expand Down