1
/***************************************************************************
2
qgsvectorfilewriter.cpp
3
generic vector file writer
5
begin : Sat Jun 16 2004
6
copyright : (C) 2004 by Tim Sutton
7
email : tim at linfiniti.com
8
***************************************************************************/
10
/***************************************************************************
12
* This program is free software; you can redistribute it and/or modify *
13
* it under the terms of the GNU General Public License as published by *
14
* the Free Software Foundation; either version 2 of the License, or *
15
* (at your option) any later version. *
17
***************************************************************************/
18
/* $Id: qgsvectorfilewriter.cpp 5933 2006-10-09 02:45:38Z telwertowski $ */
19
#include "qgsvectorfilewriter.h"
26
// Includes for ogr shaprewriting
28
//#include "gdal_alg.h"
29
//#include "cpl_conv.h"
30
#include "ogr_srs_api.h"
32
#include <netinet/in.h>
35
QgsVectorFileWriter::QgsVectorFileWriter(QString theOutputFileName, QString fileEncoding, QgsVectorLayer * theVectorLayer)
37
std::cout << "QgsVectorFileWriter constructor called with " << theOutputFileName.toLocal8Bit().data() <<
38
" and vector layer : " << theVectorLayer->getLayerID().toLocal8Bit().data() << std::endl;
39
//const char *mOutputFormat = "ESRI Shapefile";
40
mOutputFormat = "ESRI Shapefile";
41
//const char *theOutputFileName = "ogrtest.shp";
42
mOutputFileName = theOutputFileName;
44
QTextCodec* ncodec=QTextCodec::codecForName(fileEncoding.toLocal8Bit().data());
52
qWarning("error finding QTextCodec in QgsVectorFileWriter ctor");
57
// We should retrieve the geometry type from the vector layer!
62
mInitialisedFlag = false;
66
QgsVectorFileWriter::QgsVectorFileWriter(QString theOutputFileName, QString fileEncoding, OGRwkbGeometryType theGeometryType)
68
std::cout << "QgsVectorFileWriter constructor called with " << theOutputFileName.toLocal8Bit().data() << " and no input vector layer " << std::endl;
69
mOutputFormat = "ESRI Shapefile"; //hard coded for now!
70
QTextCodec* ncodec=QTextCodec::codecForName(fileEncoding.toLocal8Bit().data());
78
qWarning("error finding QTextCodec in QgsVectorFileWriter ctor");
81
mOutputFileName = theOutputFileName;
82
mGeometryType = theGeometryType;
83
mInitialisedFlag = false;
86
QgsVectorFileWriter::~QgsVectorFileWriter()
88
OGR_DS_Destroy( mDataSourceHandle );
89
//GDALClose( hSrcDS );
92
bool QgsVectorFileWriter::initialise()
94
// Valid OGRwkbGeometryType as defined in ogr_core.h
95
// wkbUnknown = 0, /* non-standard */
96
// wkbPoint = 1, /* rest are standard WKB type codes */
100
// wkbMultiLineString = 5,
101
// wkbMultiPolygon = 6,
102
// wkbGeometryCollection = 7,
103
// wkbNone = 100, /* non-standard, for pure attribute records */
104
// wkbLinearRing = 101, /* non-standard, just for createGeometry() */
105
// wkbPoint25D = 0x80000001, /* 2.5D extensions as per 99-402 */
106
// wkbLineString25D = 0x80000002,
107
// wkbPolygon25D = 0x80000003,
108
// wkbMultiPoint25D = 0x80000004,
109
// wkbMultiLineString25D = 0x80000005,
110
// wkbMultiPolygon25D = 0x80000006,
111
// wkbGeometryCollection25D = 0x80000007
114
// The following stuff just sets up the shapefile - without writing any data to it!
118
mInitialisedFlag=false;
121
OGRSFDriverH myDriverHandle = OGRGetDriverByName( mOutputFormat.toLocal8Bit().data() );
123
if( myDriverHandle == NULL )
125
std::cout << "Unable to find format driver named " << mOutputFormat.toLocal8Bit().data() << std::endl;
129
// Filename needs to be UTF-8 for Mac but local8Bit otherwise
130
mDataSourceHandle = OGR_Dr_CreateDataSource( myDriverHandle, QFile::encodeName(mOutputFileName).constData(), NULL );
131
if( mDataSourceHandle == NULL )
133
std::cout << "Datasource handle is null! " << std::endl;
137
//define the spatial ref system
138
OGRSpatialReferenceH mySpatialReferenceSystemHandle = NULL;
139
QgsSpatialRefSys mySpatialRefSys;
140
mySpatialRefSys.validate();
142
QString myWKT = NULL;
143
if(mySpatialRefSys.toOgrSrs().exportToWkt(&WKT)==OGRERR_NONE)
146
qWarning("export to WKT successful****************************************************************************************************");
150
qWarning(("WKT is:WKT "+myWKT).toLocal8Bit().data());
156
qWarning("export to WKT failed*******************************************************************************************************3");
161
//sample below shows how to extract srs from a raster
162
// const char *myWKT = GDALGetProjectionRef( hBand );
165
if( !myWKT.isNull() && myWKT.length() != 0 )
167
mySpatialReferenceSystemHandle = OSRNewSpatialReference( myWKT.toLocal8Bit().data() );
169
//change 'contour' to something more useful!
171
qWarning(("mOutputFileName: "+mOutputFileName).toLocal8Bit().data());
175
QString outname=mOutputFileName.mid(mOutputFileName.findRev("\\")+1,mOutputFileName.length());
177
QString outname=mOutputFileName.mid(mOutputFileName.findRev("/")+1,mOutputFileName.length());
182
qWarning(("outname: "+outname).toLocal8Bit().data());
185
// Unsure if this will be a filename or not. Use custom encoding for now.
186
mLayerHandle = OGR_DS_CreateLayer( mDataSourceHandle, mEncoding->fromUnicode(outname),
187
mySpatialReferenceSystemHandle, mGeometryType, NULL );
189
if( mLayerHandle == NULL )
191
std::cout << "Error layer handle is null!" << std::endl;
196
std::cout << "File handle created!" << std::endl;
199
// Check and fall back on encoding.
200
if (mEncoding == NULL)
202
qWarning("Failed to initialize VectorFileWriter with encoding. Falling back on utf8");
203
mEncoding = QTextCodec::codecForName("utf8");
206
//let other methods know we have an initialised file
207
mInitialisedFlag=true;
211
bool QgsVectorFileWriter::createField(QString theName, OGRFieldType theType, int theWidthInt, int thePrecisionInt)
213
if (!mInitialisedFlag)
217
OGRFieldDefnH myFieldDefinitionHandle;
220
// OGRFieldType types as defined in ogr_core.h :
223
// OFTIntegerList = 1,
227
// OFTStringList = 5,
228
// OFTWideString = 6,
229
// OFTWideStringList = 7,
232
// XXX Is the layer encoding set here?
233
Q_ASSERT(mEncoding != NULL);
234
myFieldDefinitionHandle = OGR_Fld_Create( mEncoding->fromUnicode(theName), theType );
235
OGR_Fld_SetWidth( myFieldDefinitionHandle, theWidthInt );
237
// Set the precision where applicable!
242
//do nothing (has no precision to set)
245
//XXX Find out how this is used!!!!!!!
248
OGR_Fld_SetPrecision( myFieldDefinitionHandle, thePrecisionInt );
251
//XXX Find out how this is used!!!!!!!
256
//XXX Find out how this is used!!!!!!!
260
case OFTWideStringList:
261
//XXX Find out how this is used!!!!!!!
267
OGR_L_CreateField( mLayerHandle, myFieldDefinitionHandle, FALSE );
268
OGR_Fld_Destroy( myFieldDefinitionHandle );
273
bool QgsVectorFileWriter::writePoint(QgsPoint * thePoint)
275
bool returnvalue=true;
276
//check the output file has been initialised
277
if (!mInitialisedFlag)
279
std::cout << "Vector file writer not initialised yet. Initialise first before calling writePoint!" << std::endl;
282
//check the geomtry of the output file is compatible
283
if (mGeometryType != wkbPoint)
285
std::cout << "Vector file writer geometry type is not compatible with writePoint!" << std::endl;
289
OGRFeatureDefnH fdef=OGR_L_GetLayerDefn(mLayerHandle);
290
OGRFeatureH fhand= OGR_F_Create( fdef );
291
OGRGeometryH geometryh=OGR_G_CreateGeometry(wkbPoint);
292
OGR_G_AddPoint( geometryh, thePoint->x(), thePoint->y(), 0 );
294
if(OGR_F_SetGeometryDirectly(fhand, geometryh )!=OGRERR_NONE)
297
qWarning("Set geometry failed");
302
if(OGR_L_CreateFeature( mLayerHandle, fhand )!=OGRERR_NONE)
305
qWarning("Creation of the point failed");
310
if(OGR_L_SyncToDisk( mLayerHandle )!=OGRERR_NONE)
313
qWarning("Sync to disk failed");
317
OGR_F_Destroy( fhand );
321
bool QgsVectorFileWriter::writeLine(unsigned char* wkb, int size)
323
bool returnvalue=true;
325
int endianval = endian();
326
memcpy(&wkb[0],&endianval,1);
327
//check the output file has been initialised
328
if (!mInitialisedFlag)
330
std::cout << "Vector file writer not initialised yet. Initialise first before calling writePoint!" << std::endl;
333
//check the geomtry of the output file is compatible
334
if (mGeometryType != wkbLineString)
336
std::cout << "Vector file writer geometry type is not compatible with writePoint!" << std::endl;
340
OGRFeatureDefnH fdef=OGR_L_GetLayerDefn(mLayerHandle);
341
OGRFeatureH fhand= OGR_F_Create( fdef );
342
OGRGeometryH geometryh=OGR_G_CreateGeometry(wkbLineString);
344
if(OGR_G_ImportFromWkb(geometryh, wkb, size)!=OGRERR_NONE)
347
qWarning("wkb import failed");
352
if(OGR_F_SetGeometryDirectly(fhand, geometryh )!=OGRERR_NONE)
355
qWarning("Set geometry failed");
360
if(OGR_L_CreateFeature( mLayerHandle, fhand )!=OGRERR_NONE)
363
qWarning("Creation of the point failed");
368
if(OGR_L_SyncToDisk( mLayerHandle )!=OGRERR_NONE)
371
qWarning("Sync to disk failed");
375
OGR_F_Destroy( fhand );
379
bool QgsVectorFileWriter::writePolygon(unsigned char* wkb, int size)
381
bool returnvalue = true;
383
int endianval = endian();
384
memcpy(&wkb[0],&endianval,1);
385
//check the output file has been initialised
386
if (!mInitialisedFlag)
388
std::cout << "Vector file writer not initialised yet. Initialise first before calling writePoint!" << std::endl;
391
//check the geomtry of the output file is compatible
392
if (mGeometryType != wkbPolygon)
394
std::cout << "Vector file writer geometry type is not compatible with writePoint!" << std::endl;
398
OGRFeatureDefnH fdef=OGR_L_GetLayerDefn(mLayerHandle);
399
OGRFeatureH fhand= OGR_F_Create( fdef );
400
OGRGeometryH geometryh=OGR_G_CreateGeometry(wkbPolygon);
402
if(OGR_G_ImportFromWkb(geometryh, wkb, size)!=OGRERR_NONE)
405
qWarning("wkb import failed");
410
if(OGR_F_SetGeometryDirectly(fhand, geometryh )!=OGRERR_NONE)
413
qWarning("Set geometry failed");
418
if(OGR_L_CreateFeature( mLayerHandle, fhand )!=OGRERR_NONE)
421
qWarning("Creation of the point failed");
426
if(OGR_L_SyncToDisk( mLayerHandle )!=OGRERR_NONE)
429
qWarning("Sync to disk failed");
433
OGR_F_Destroy( fhand );
438
int QgsVectorFileWriter::endian()
443
// XXX why re-calculate this all the time? Why not just calculate this
444
// XXX once and return the value? For that matter, some machines have
445
// XXX endian.h, which stores the constant variable for local endian-ness.
446
if ( 23 == htons( 23 ) )
448
// if host byte order is same as network (big-endian) byte order, then
449
// this is a big-endian environment
453
// otherwise this must be little-endian