Skip to content

Commit 0d0f5a6

Browse files
author
timlinux
committed
zoomToActiveLayer instead of zoomActiveLayer. Also applied patch from Magnus Homann to correct issue where save as shapefile does not allow using CRS of project projection.
git-svn-id: http://svn.osgeo.org/qgis/trunk/qgis@9334 c8812cc2-4d05-0410-92ff-de0c093fc19c
1 parent 10e2cb1 commit 0d0f5a6

12 files changed

+245
-7
lines changed

python/core/qgsvectorfilewriter.sip

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ public:
2828
static WriterError writeAsShapefile(QgsVectorLayer* layer,
2929
const QString& shapefileName,
3030
const QString& fileEncoding,
31+
const QgsCoordinateReferenceSystem*,
3132
bool onlySelected = FALSE);
3233

3334

python/gui/qgisinterface.sip

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ class QgisInterface : QObject
3333
//! Zoom to previous view extent
3434
virtual void zoomToPrevious()=0;
3535
//! Zoome to extent of the active layer
36-
virtual void zoomActiveLayer()=0;
36+
virtual void zoomToActiveLayer()=0;
3737

3838
//! Add a vector layer
3939
virtual QgsVectorLayer* addVectorLayer(QString vectorLayerPath, QString baseName, QString providerKey)=0;

src/app/legend/qgslegendlayerfile.cpp

+33-1
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,12 @@
2424
#include "qgslegendlayer.h"
2525
#include "qgslegendlayerfile.h"
2626
#include "qgsmaplayer.h"
27+
#include "qgsmaprenderer.h"
2728
#include "qgsrasterlayer.h"
2829
#include "qgsvectorfilewriter.h"
2930
#include "qgsvectorlayer.h"
3031
#include "qgsvectordataprovider.h"
32+
#include "qgsgenericprojectionselector.h"
3133

3234
// attribute table
3335
#include "qgsattributetable.h"
@@ -225,6 +227,8 @@ void QgsLegendLayerFile::saveSelectionAsShapefile()
225227

226228
void QgsLegendLayerFile::saveAsShapefileGeneral( bool saveOnlySelection )
227229
{
230+
QgsCoordinateReferenceSystem destCRS;
231+
228232
if ( mLyr.layer()->type() != QgsMapLayer::VECTOR )
229233
return;
230234

@@ -264,6 +268,33 @@ void QgsLegendLayerFile::saveAsShapefileGeneral( bool saveOnlySelection )
264268
shapefileName += ".shp";
265269
}
266270

271+
destCRS = vlayer->srs();
272+
// Find out if we have projections enabled or not
273+
if ( QgisApp::instance()->mapCanvas()->mapRenderer()->projectionsEnabled() )
274+
{
275+
destCRS = QgisApp::instance()->mapCanvas()->mapRenderer()->destinationSrs();
276+
}
277+
278+
QgsGenericProjectionSelector * mySelector = new QgsGenericProjectionSelector();
279+
mySelector->setSelectedCrsId( destCRS.srsid() );
280+
mySelector->setMessage(tr("Select the coordinate reference system for the saved shapefile.") +
281+
tr("The data points will be transformed from the layer coordinate reference system."));
282+
283+
if ( mySelector->exec() )
284+
{
285+
QgsCoordinateReferenceSystem srs( mySelector->selectedCrsId(), QgsCoordinateReferenceSystem::QGIS_CRSID );
286+
destCRS = srs;
287+
// destCRS->createFromId(mySelector->selectedCrsId(), QgsCoordinateReferenceSystem::QGIS_CRSID)
288+
}
289+
else
290+
{
291+
// Aborted CS selection, don't save.
292+
delete mySelector;
293+
return;
294+
}
295+
296+
delete mySelector;
297+
267298
// overwrite the file - user will already have been prompted
268299
// to verify they want to overwrite by the file dialog above
269300
if ( QFile::exists( shapefileName ) )
@@ -273,11 +304,12 @@ void QgsLegendLayerFile::saveAsShapefileGeneral( bool saveOnlySelection )
273304
return;
274305
}
275306
}
307+
276308
// ok if the file existed it should be deleted now so we can continue...
277309
QApplication::setOverrideCursor( Qt::WaitCursor );
278310

279311
QgsVectorFileWriter::WriterError error;
280-
error = QgsVectorFileWriter::writeAsShapefile( vlayer, shapefileName, encoding, saveOnlySelection );
312+
error = QgsVectorFileWriter::writeAsShapefile( vlayer, shapefileName, encoding, &destCRS, saveOnlySelection );
281313

282314
QApplication::restoreOverrideCursor();
283315

src/app/qgisappinterface.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ void QgisAppInterface::zoomToPrevious()
5252
qgis->zoomToPrevious();
5353
}
5454

55-
void QgisAppInterface::zoomActiveLayer()
55+
void QgisAppInterface::zoomToActiveLayer()
5656
{
5757
qgis->zoomToLayerExtent();
5858
}

src/app/qgisappinterface.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ class QgisAppInterface : public QgisInterface
4848
//! Zoom map to previous extent
4949
void zoomToPrevious();
5050
//! Zoom to active layer
51-
void zoomActiveLayer();
51+
void zoomToActiveLayer();
5252

5353
//! Add a vector layer
5454
QgsVectorLayer* addVectorLayer( QString vectorLayerPath, QString baseName, QString providerKey );

src/core/qgsgeometry.cpp

+151
Original file line numberDiff line numberDiff line change
@@ -2993,6 +2993,132 @@ int QgsGeometry::translate( double dx, double dy )
29932993
return 0;
29942994
}
29952995

2996+
int QgsGeometry::transform( QgsCoordinateTransform& ct )
2997+
{
2998+
if ( mDirtyWkb )
2999+
{
3000+
exportGeosToWkb();
3001+
}
3002+
3003+
if ( !mGeometry )
3004+
{
3005+
QgsDebugMsg( "WKB geometry not available!" );
3006+
return 1;
3007+
}
3008+
3009+
QGis::WKBTYPE wkbType;
3010+
memcpy( &wkbType, &( mGeometry[1] ), sizeof( int ) );
3011+
bool hasZValue = false;
3012+
int wkbPosition = 5;
3013+
3014+
switch ( wkbType )
3015+
{
3016+
case QGis::WKBPoint25D:
3017+
case QGis::WKBPoint:
3018+
{
3019+
transformVertex( wkbPosition, ct, hasZValue );
3020+
}
3021+
break;
3022+
3023+
case QGis::WKBLineString25D:
3024+
hasZValue = true;
3025+
case QGis::WKBLineString:
3026+
{
3027+
int* npoints = ( int* )( &mGeometry[wkbPosition] );
3028+
wkbPosition += sizeof( int );
3029+
for ( int index = 0;index < *npoints;++index )
3030+
{
3031+
transformVertex( wkbPosition, ct, hasZValue );
3032+
}
3033+
break;
3034+
}
3035+
3036+
case QGis::WKBPolygon25D:
3037+
hasZValue = true;
3038+
case QGis::WKBPolygon:
3039+
{
3040+
int* nrings = ( int* )( &( mGeometry[wkbPosition] ) );
3041+
wkbPosition += sizeof( int );
3042+
int* npoints;
3043+
3044+
for ( int index = 0;index < *nrings;++index )
3045+
{
3046+
npoints = ( int* )( &( mGeometry[wkbPosition] ) );
3047+
wkbPosition += sizeof( int );
3048+
for ( int index2 = 0;index2 < *npoints;++index2 )
3049+
{
3050+
transformVertex( wkbPosition, ct, hasZValue );
3051+
}
3052+
}
3053+
break;
3054+
}
3055+
3056+
case QGis::WKBMultiPoint25D:
3057+
hasZValue = true;
3058+
case QGis::WKBMultiPoint:
3059+
{
3060+
int* npoints = ( int* )( &( mGeometry[wkbPosition] ) );
3061+
wkbPosition += sizeof( int );
3062+
for ( int index = 0;index < *npoints;++index )
3063+
{
3064+
wkbPosition += ( sizeof( int ) + 1 );
3065+
transformVertex( wkbPosition, ct, hasZValue );
3066+
}
3067+
break;
3068+
}
3069+
3070+
case QGis::WKBMultiLineString25D:
3071+
hasZValue = true;
3072+
case QGis::WKBMultiLineString:
3073+
{
3074+
int* nlines = ( int* )( &( mGeometry[wkbPosition] ) );
3075+
int* npoints = 0;
3076+
wkbPosition += sizeof( int );
3077+
for ( int index = 0;index < *nlines;++index )
3078+
{
3079+
wkbPosition += ( sizeof( int ) + 1 );
3080+
npoints = ( int* )( &( mGeometry[wkbPosition] ) );
3081+
wkbPosition += sizeof( int );
3082+
for ( int index2 = 0; index2 < *npoints; ++index2 )
3083+
{
3084+
transformVertex( wkbPosition, ct, hasZValue );
3085+
}
3086+
}
3087+
break;
3088+
}
3089+
3090+
case QGis::WKBMultiPolygon25D:
3091+
hasZValue = true;
3092+
case QGis::WKBMultiPolygon:
3093+
{
3094+
int* npolys = ( int* )( &( mGeometry[wkbPosition] ) );
3095+
int* nrings;
3096+
int* npoints;
3097+
wkbPosition += sizeof( int );
3098+
for ( int index = 0;index < *npolys;++index )
3099+
{
3100+
wkbPosition += ( 1 + sizeof( int ) ); //skip endian and polygon type
3101+
nrings = ( int* )( &( mGeometry[wkbPosition] ) );
3102+
wkbPosition += sizeof( int );
3103+
for ( int index2 = 0;index2 < *nrings;++index2 )
3104+
{
3105+
npoints = ( int* )( &( mGeometry[wkbPosition] ) );
3106+
wkbPosition += sizeof( int );
3107+
for ( int index3 = 0;index3 < *npoints;++index3 )
3108+
{
3109+
transformVertex( wkbPosition, ct, hasZValue );
3110+
}
3111+
}
3112+
}
3113+
}
3114+
3115+
default:
3116+
break;
3117+
}
3118+
mDirtyGeos = true;
3119+
return 0;
3120+
}
3121+
29963122
int QgsGeometry::splitGeometry( const QList<QgsPoint>& splitLine, QList<QgsGeometry*>& newGeometries )
29973123
{
29983124
int returnCode = 0;
@@ -4569,6 +4695,31 @@ void QgsGeometry::translateVertex( int& wkbPosition, double dx, double dy, bool
45694695
}
45704696
}
45714697

4698+
void QgsGeometry::transformVertex( int& wkbPosition, QgsCoordinateTransform& ct, bool hasZValue )
4699+
{
4700+
double x, y, z;
4701+
4702+
4703+
x = *(( double * )( &( mGeometry[wkbPosition] ) ) );
4704+
y = *(( double * )( &( mGeometry[wkbPosition + sizeof( double )] ) ) );
4705+
z = 0.0; // Ignore Z for now.
4706+
4707+
ct.transformInPlace( x, y, z);
4708+
4709+
// new x-coordinate
4710+
memcpy( &( mGeometry[wkbPosition] ), &x, sizeof( double ) );
4711+
wkbPosition += sizeof( double );
4712+
4713+
// new y-coordinate
4714+
memcpy( &( mGeometry[wkbPosition] ), &y, sizeof( double ) );
4715+
wkbPosition += sizeof( double );
4716+
4717+
if ( hasZValue )
4718+
{
4719+
wkbPosition += sizeof( double );
4720+
}
4721+
}
4722+
45724723
int QgsGeometry::splitLinearGeometry( GEOSGeometry *splitLine, QList<QgsGeometry*>& newGeometries )
45734724
{
45744725
if ( !splitLine )

src/core/qgsgeometry.h

+12
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ email : morb at ozemail dot com dot au
3030
#endif
3131

3232
#include "qgspoint.h"
33+
#include "qgscoordinatetransform.h"
3334

3435
/** polyline is represented as a vector of points */
3536
typedef QVector<QgsPoint> QgsPolyline;
@@ -233,6 +234,10 @@ class CORE_EXPORT QgsGeometry
233234
@return 0 in case of success*/
234235
int translate( double dx, double dy );
235236

237+
/**Transform this geometry as described by CoordinateTranasform ct
238+
@return 0 in case of success*/
239+
int transform( QgsCoordinateTransform& ct );
240+
236241
/**Splits this geometry according to a given line. Note that the geometry is only splitted once. If there are several intersections
237242
between geometry and splitLine, only the first one is considered.
238243
@param splitLine the line that splits the geometry
@@ -380,6 +385,13 @@ class CORE_EXPORT QgsGeometry
380385
@param hasZValue 25D type?*/
381386
void translateVertex( int& wkbPosition, double dx, double dy, bool hasZValue );
382387

388+
/**Transforms a single vertex by ct.
389+
@param ptr pointer to the wkb fragment containing the vertex
390+
@param wkbPosition position in wkb array. Is increased automatically by the function
391+
@param ct the QgsCoordinateTransform
392+
@param hasZValue 25D type?*/
393+
void transformVertex( int& wkbPosition, QgsCoordinateTransform& ct, bool hasZValue );
394+
383395
//helper functions for geometry splitting
384396

385397
/**Splits line/multiline geometries

src/core/qgsvectorfilewriter.cpp

+39-1
Original file line numberDiff line numberDiff line change
@@ -294,18 +294,36 @@ QgsVectorFileWriter::WriterError
294294
QgsVectorFileWriter::writeAsShapefile( QgsVectorLayer* layer,
295295
const QString& shapefileName,
296296
const QString& fileEncoding,
297+
const QgsCoordinateReferenceSystem* destCRS,
297298
bool onlySelected )
298299
{
299300

301+
const QgsCoordinateReferenceSystem* outputCRS;
302+
QgsCoordinateTransform* ct;
303+
300304
QgsVectorDataProvider* provider = layer->dataProvider();
305+
int shallTransform = false;
301306

307+
if ( destCRS && destCRS->isValid() )
308+
{
309+
// This means we should transform
310+
outputCRS = destCRS;
311+
shallTransform = true;
312+
} else {
313+
// This means we shouldn't transform, use source CRS as output (if defined)
314+
outputCRS = &layer->srs();
315+
}
302316
QgsVectorFileWriter* writer = new QgsVectorFileWriter( shapefileName,
303-
fileEncoding, provider->fields(), provider->geometryType(), &layer->srs() );
317+
fileEncoding, provider->fields(), provider->geometryType(), outputCRS );
304318

305319
// check whether file creation was successful
306320
WriterError err = writer->hasError();
307321
if ( err != NoError )
308322
{
323+
if (ct != NULL)
324+
{
325+
delete ct;
326+
}
309327
delete writer;
310328
return err;
311329
}
@@ -317,17 +335,37 @@ QgsVectorFileWriter::writeAsShapefile( QgsVectorLayer* layer,
317335

318336
const QgsFeatureIds& ids = layer->selectedFeaturesIds();
319337

338+
// Create our transform
339+
if (destCRS)
340+
{
341+
ct = new QgsCoordinateTransform(layer->srs(), *destCRS);
342+
}
343+
344+
// Check for failure
345+
if (ct == NULL)
346+
{
347+
shallTransform = false;
348+
}
349+
320350
// write all features
321351
while ( provider->getNextFeature( fet ) )
322352
{
323353
if ( onlySelected && !ids.contains( fet.featureId() ) )
324354
continue;
325355

356+
if ( shallTransform )
357+
{
358+
fet.geometry()->transform(*ct);
359+
}
326360
writer->addFeature( fet );
327361
}
328362

329363
delete writer;
330364

365+
if (shallTransform)
366+
{
367+
delete ct;
368+
}
331369
return NoError;
332370
}
333371

src/core/qgsvectorfilewriter.h

+1
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ class CORE_EXPORT QgsVectorFileWriter
5555
static WriterError writeAsShapefile( QgsVectorLayer* layer,
5656
const QString& shapefileName,
5757
const QString& fileEncoding,
58+
const QgsCoordinateReferenceSystem *destCRS,
5859
bool onlySelected = FALSE );
5960

6061

src/core/qgsvectorlayer.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -3301,7 +3301,8 @@ void QgsVectorLayer::drawFeature( QPainter* p,
33013301
transformPoint( x, y, theMapToPixelTransform, ct );
33023302
//QPointF pt(x - (marker->width()/2), y - (marker->height()/2));
33033303
//QPointF pt(x/markerScaleFactor - (marker->width()/2), y/markerScaleFactor - (marker->height()/2));
3304-
QPointF pt( x, y );
3304+
QPointF pt( x*rasterScaleFactor - ( marker->width() / 2 ), y*rasterScaleFactor - ( marker->height() / 2 ) );
3305+
//QPointF pt( x, y );
33053306

33063307
#if defined(Q_WS_X11)
33073308
// Work around a +/- 32768 limitation on coordinates in X11

0 commit comments

Comments
 (0)