~ubuntu-branches/ubuntu/trusty/qgis/trusty

« back to all changes in this revision

Viewing changes to src/gui/qgsvectorfilewriter.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Johan Van de Wauw
  • Date: 2010-07-11 20:23:24 UTC
  • mfrom: (3.1.4 squeeze)
  • Revision ID: james.westby@ubuntu.com-20100711202324-5ktghxa7hracohmr
Tags: 1.4.0+12730-3ubuntu1
* Merge from Debian unstable (LP: #540941).
* Fix compilation issues with QT 4.7
* Add build-depends on libqt4-webkit-dev 

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/***************************************************************************
2
 
                          qgsvectorfilewriter.cpp  
3
 
                          generic vector file writer 
4
 
                             -------------------
5
 
    begin                : Sat Jun 16 2004
6
 
    copyright            : (C) 2004 by Tim Sutton
7
 
    email                : tim at linfiniti.com
8
 
 ***************************************************************************/
9
 
 
10
 
/***************************************************************************
11
 
 *                                                                         *
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.                                   *
16
 
 *                                                                         *
17
 
 ***************************************************************************/
18
 
/* $Id: qgsvectorfilewriter.cpp 5933 2006-10-09 02:45:38Z telwertowski $ */
19
 
#include "qgsvectorfilewriter.h"
20
 
 
21
 
#include <iostream>
22
 
#include <QFile>
23
 
#include <QString>
24
 
#include <QTextCodec>
25
 
 
26
 
// Includes for ogr shaprewriting
27
 
//#include "gdal.h"
28
 
//#include "gdal_alg.h"
29
 
//#include "cpl_conv.h"
30
 
#include "ogr_srs_api.h"
31
 
#ifndef WIN32
32
 
#include <netinet/in.h>
33
 
#endif
34
 
 
35
 
QgsVectorFileWriter::QgsVectorFileWriter(QString theOutputFileName, QString fileEncoding, QgsVectorLayer * theVectorLayer)
36
 
{
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;
43
 
 
44
 
  QTextCodec* ncodec=QTextCodec::codecForName(fileEncoding.toLocal8Bit().data());
45
 
  if(ncodec)
46
 
    {
47
 
      mEncoding=ncodec;
48
 
    }
49
 
  else
50
 
    {
51
 
#ifdef QGISDEBUG
52
 
      qWarning("error finding QTextCodec in QgsVectorFileWriter ctor");
53
 
#endif
54
 
    }
55
 
 
56
 
  //
57
 
  // We should retrieve the geometry type from the vector layer!
58
 
  //
59
 
 
60
 
 
61
 
 
62
 
  mInitialisedFlag = false;
63
 
  
64
 
}
65
 
 
66
 
QgsVectorFileWriter::QgsVectorFileWriter(QString theOutputFileName, QString fileEncoding, OGRwkbGeometryType theGeometryType)
67
 
{
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());
71
 
  if(ncodec)
72
 
    {
73
 
      mEncoding=ncodec;
74
 
    }
75
 
  else
76
 
    {
77
 
#ifdef QGISDEBUG
78
 
      qWarning("error finding QTextCodec in QgsVectorFileWriter ctor");
79
 
#endif
80
 
    }
81
 
  mOutputFileName = theOutputFileName; 
82
 
  mGeometryType = theGeometryType;
83
 
  mInitialisedFlag = false;
84
 
}
85
 
 
86
 
QgsVectorFileWriter::~QgsVectorFileWriter()
87
 
{
88
 
  OGR_DS_Destroy( mDataSourceHandle );
89
 
  //GDALClose( hSrcDS );
90
 
}
91
 
 
92
 
bool QgsVectorFileWriter::initialise()
93
 
{
94
 
  // Valid OGRwkbGeometryType as defined in ogr_core.h
95
 
  //    wkbUnknown = 0,             /* non-standard */
96
 
  //    wkbPoint = 1,               /* rest are standard WKB type codes */
97
 
  //    wkbLineString = 2,
98
 
  //    wkbPolygon = 3,
99
 
  //    wkbMultiPoint = 4,
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
112
 
 
113
 
  //
114
 
  // The following stuff just sets up the shapefile - without writing any data to it!
115
 
  //
116
 
 
117
 
  //assume failure
118
 
  mInitialisedFlag=false; 
119
 
  
120
 
  OGRRegisterAll();
121
 
  OGRSFDriverH myDriverHandle = OGRGetDriverByName( mOutputFormat.toLocal8Bit().data() );
122
 
 
123
 
  if( myDriverHandle == NULL )
124
 
  {
125
 
    std::cout << "Unable to find format driver named " << mOutputFormat.toLocal8Bit().data() << std::endl;
126
 
    return false;
127
 
  }
128
 
 
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 )
132
 
  {
133
 
    std::cout << "Datasource handle is null! " << std::endl;
134
 
    return false;
135
 
  }
136
 
 
137
 
  //define the spatial ref system
138
 
  OGRSpatialReferenceH mySpatialReferenceSystemHandle = NULL;
139
 
  QgsSpatialRefSys mySpatialRefSys;
140
 
  mySpatialRefSys.validate();
141
 
  char* WKT;
142
 
  QString myWKT = NULL;
143
 
  if(mySpatialRefSys.toOgrSrs().exportToWkt(&WKT)==OGRERR_NONE)
144
 
  {
145
 
#ifdef QGISDEBUG
146
 
      qWarning("export to WKT successful****************************************************************************************************");
147
 
#endif
148
 
      myWKT=WKT;
149
 
#ifdef QGISDEBUG
150
 
      qWarning(("WKT is:WKT "+myWKT).toLocal8Bit().data());
151
 
#endif    
152
 
  }
153
 
  else
154
 
  {
155
 
#ifdef QGISDEBUG
156
 
      qWarning("export to WKT failed*******************************************************************************************************3");
157
 
#endif      
158
 
  }
159
 
 
160
 
 
161
 
  //sample below shows how to extract srs from a raster
162
 
  //    const char *myWKT = GDALGetProjectionRef( hBand );
163
 
 
164
 
 
165
 
  if( !myWKT.isNull()  &&  myWKT.length() != 0 )
166
 
  {
167
 
    mySpatialReferenceSystemHandle = OSRNewSpatialReference( myWKT.toLocal8Bit().data() );
168
 
  }
169
 
  //change 'contour' to something more useful!
170
 
#ifdef QGISDEBUG
171
 
  qWarning(("mOutputFileName: "+mOutputFileName).toLocal8Bit().data());
172
 
#endif //QGISDEBUG
173
 
 
174
 
#ifdef WIN32 
175
 
  QString outname=mOutputFileName.mid(mOutputFileName.findRev("\\")+1,mOutputFileName.length());
176
 
#else
177
 
  QString outname=mOutputFileName.mid(mOutputFileName.findRev("/")+1,mOutputFileName.length());
178
 
#endif
179
 
  
180
 
 
181
 
#ifdef QGISDEBUG
182
 
  qWarning(("outname: "+outname).toLocal8Bit().data());
183
 
#endif //QGISDEBUG
184
 
 
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 );
188
 
  
189
 
  if( mLayerHandle == NULL )
190
 
  {
191
 
    std::cout << "Error layer handle is null!" << std::endl;
192
 
    return false;
193
 
  }
194
 
  else
195
 
  {
196
 
    std::cout << "File handle created!" << std::endl;
197
 
  }
198
 
 
199
 
  // Check and fall back on encoding.
200
 
  if (mEncoding == NULL)
201
 
  {
202
 
    qWarning("Failed to initialize VectorFileWriter with encoding. Falling back on utf8");
203
 
    mEncoding = QTextCodec::codecForName("utf8");
204
 
    Q_ASSERT(mEncoding);
205
 
  }
206
 
  //let other methods know we have an initialised file
207
 
  mInitialisedFlag=true; 
208
 
  return true;
209
 
}
210
 
 
211
 
bool QgsVectorFileWriter::createField(QString theName, OGRFieldType theType, int theWidthInt, int thePrecisionInt)
212
 
{
213
 
  if (!mInitialisedFlag)
214
 
  {
215
 
    return false;
216
 
  }
217
 
  OGRFieldDefnH myFieldDefinitionHandle;
218
 
 
219
 
  //
220
 
  // OGRFieldType types as defined in  ogr_core.h :
221
 
  // 
222
 
  //        OFTInteger = 0,
223
 
  //        OFTIntegerList = 1,
224
 
  //        OFTReal = 2,
225
 
  //        OFTRealList = 3,
226
 
  //        OFTString = 4,
227
 
  //        OFTStringList = 5,
228
 
  //        OFTWideString = 6,
229
 
  //        OFTWideStringList = 7,
230
 
  //        OFTBinary = 8
231
 
  //
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 );
236
 
  //
237
 
  // Set the precision where applicable!
238
 
  //
239
 
  switch (theType)
240
 
  {
241
 
      case OFTInteger:
242
 
          //do nothing  (has no precision to set)
243
 
        break;
244
 
      case OFTIntegerList:
245
 
          //XXX Find out how this is used!!!!!!!
246
 
          break;
247
 
      case OFTReal:
248
 
          OGR_Fld_SetPrecision( myFieldDefinitionHandle, thePrecisionInt );
249
 
          break;
250
 
      case OFTRealList:
251
 
          //XXX Find out how this is used!!!!!!!
252
 
          break;
253
 
      case OFTString:
254
 
          break;
255
 
      case OFTStringList:
256
 
          //XXX Find out how this is used!!!!!!!
257
 
          break;
258
 
      case OFTWideString:
259
 
          break;
260
 
      case OFTWideStringList:
261
 
          //XXX Find out how this is used!!!!!!!
262
 
          break;
263
 
      case OFTBinary:
264
 
          break;
265
 
  }
266
 
 
267
 
  OGR_L_CreateField( mLayerHandle, myFieldDefinitionHandle, FALSE );
268
 
  OGR_Fld_Destroy( myFieldDefinitionHandle );
269
 
  
270
 
  return true;
271
 
}
272
 
 
273
 
bool QgsVectorFileWriter::writePoint(QgsPoint * thePoint)
274
 
{
275
 
    bool returnvalue=true;
276
 
    //check the output file has been initialised
277
 
    if (!mInitialisedFlag)
278
 
    {
279
 
        std::cout << "Vector file writer not initialised yet. Initialise first before calling writePoint!" << std::endl;
280
 
        return false;
281
 
    }
282
 
    //check the geomtry of the output file is compatible
283
 
    if (mGeometryType != wkbPoint)
284
 
    {
285
 
        std::cout << "Vector file writer geometry type is not compatible with writePoint!" << std::endl;
286
 
        return false;
287
 
    }
288
 
    
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 );
293
 
    
294
 
    if(OGR_F_SetGeometryDirectly(fhand, geometryh )!=OGRERR_NONE)
295
 
    {
296
 
#ifdef QGISDEBUG
297
 
        qWarning("Set geometry failed");
298
 
#endif
299
 
        returnvalue=false;
300
 
    }
301
 
    
302
 
    if(OGR_L_CreateFeature( mLayerHandle, fhand )!=OGRERR_NONE)
303
 
    {
304
 
#ifdef QGISDEBUG
305
 
        qWarning("Creation of the point failed");
306
 
#endif  
307
 
        returnvalue=false;
308
 
    }
309
 
    
310
 
    if(OGR_L_SyncToDisk( mLayerHandle )!=OGRERR_NONE)
311
 
    {
312
 
#ifdef QGISDEBUG
313
 
        qWarning("Sync to disk failed");
314
 
#endif 
315
 
        returnvalue=false;
316
 
    }
317
 
    OGR_F_Destroy( fhand );  
318
 
    return returnvalue;
319
 
}
320
 
 
321
 
bool QgsVectorFileWriter::writeLine(unsigned char* wkb, int size)
322
 
{
323
 
    bool returnvalue=true;
324
 
    //add endianness
325
 
    int endianval = endian();
326
 
    memcpy(&wkb[0],&endianval,1);
327
 
    //check the output file has been initialised
328
 
    if (!mInitialisedFlag)
329
 
    {
330
 
        std::cout << "Vector file writer not initialised yet. Initialise first before calling writePoint!" << std::endl;
331
 
        return false;
332
 
    }
333
 
    //check the geomtry of the output file is compatible
334
 
    if (mGeometryType != wkbLineString)
335
 
    {
336
 
        std::cout << "Vector file writer geometry type is not compatible with writePoint!" << std::endl;
337
 
        return false;
338
 
    }
339
 
 
340
 
    OGRFeatureDefnH fdef=OGR_L_GetLayerDefn(mLayerHandle);
341
 
    OGRFeatureH fhand= OGR_F_Create( fdef );
342
 
    OGRGeometryH geometryh=OGR_G_CreateGeometry(wkbLineString);
343
 
    
344
 
    if(OGR_G_ImportFromWkb(geometryh, wkb, size)!=OGRERR_NONE)
345
 
    {
346
 
#ifdef QGISDEBUG
347
 
        qWarning("wkb import failed");
348
 
#endif
349
 
        returnvalue=false;
350
 
    }
351
 
 
352
 
    if(OGR_F_SetGeometryDirectly(fhand, geometryh )!=OGRERR_NONE)
353
 
    {
354
 
#ifdef QGISDEBUG
355
 
        qWarning("Set geometry failed");
356
 
#endif
357
 
        returnvalue=false;
358
 
    }
359
 
 
360
 
    if(OGR_L_CreateFeature( mLayerHandle, fhand )!=OGRERR_NONE)
361
 
    {
362
 
#ifdef QGISDEBUG
363
 
        qWarning("Creation of the point failed");
364
 
#endif    
365
 
        returnvalue=false;
366
 
    }
367
 
    
368
 
    if(OGR_L_SyncToDisk( mLayerHandle )!=OGRERR_NONE)
369
 
    {
370
 
#ifdef QGISDEBUG
371
 
        qWarning("Sync to disk failed");
372
 
#endif 
373
 
        returnvalue=false;
374
 
    }
375
 
    OGR_F_Destroy( fhand );  
376
 
    return returnvalue;
377
 
}
378
 
 
379
 
bool QgsVectorFileWriter::writePolygon(unsigned char* wkb, int size)
380
 
{
381
 
    bool returnvalue = true;
382
 
    //add endianness
383
 
    int endianval = endian();
384
 
    memcpy(&wkb[0],&endianval,1);
385
 
    //check the output file has been initialised
386
 
    if (!mInitialisedFlag)
387
 
    {
388
 
        std::cout << "Vector file writer not initialised yet. Initialise first before calling writePoint!" << std::endl;
389
 
        return false;
390
 
    }
391
 
    //check the geomtry of the output file is compatible
392
 
    if (mGeometryType != wkbPolygon)
393
 
    {
394
 
        std::cout << "Vector file writer geometry type is not compatible with writePoint!" << std::endl;
395
 
        return false;
396
 
    }
397
 
 
398
 
    OGRFeatureDefnH fdef=OGR_L_GetLayerDefn(mLayerHandle);
399
 
    OGRFeatureH fhand= OGR_F_Create( fdef );
400
 
    OGRGeometryH geometryh=OGR_G_CreateGeometry(wkbPolygon);
401
 
    
402
 
    if(OGR_G_ImportFromWkb(geometryh, wkb, size)!=OGRERR_NONE)
403
 
    {
404
 
#ifdef QGISDEBUG
405
 
        qWarning("wkb import failed");
406
 
#endif
407
 
        returnvalue = false;
408
 
    }
409
 
 
410
 
    if(OGR_F_SetGeometryDirectly(fhand, geometryh )!=OGRERR_NONE)
411
 
    {
412
 
#ifdef QGISDEBUG
413
 
        qWarning("Set geometry failed");
414
 
#endif
415
 
        returnvalue = false;
416
 
    }
417
 
 
418
 
    if(OGR_L_CreateFeature( mLayerHandle, fhand )!=OGRERR_NONE)
419
 
    {
420
 
#ifdef QGISDEBUG
421
 
        qWarning("Creation of the point failed");
422
 
#endif      
423
 
        returnvalue = false;
424
 
    }
425
 
    
426
 
    if(OGR_L_SyncToDisk( mLayerHandle )!=OGRERR_NONE)
427
 
    {
428
 
#ifdef QGISDEBUG
429
 
        qWarning("Sync to disk failed");
430
 
#endif 
431
 
        returnvalue = false;
432
 
    }
433
 
    OGR_F_Destroy( fhand );  
434
 
    return true;
435
 
    
436
 
}
437
 
 
438
 
int QgsVectorFileWriter::endian()
439
 
{
440
 
#ifdef WIN32
441
 
  return NDR;
442
 
#else
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 ) )
447
 
    {
448
 
        // if host byte order is same as network (big-endian) byte order, then
449
 
        // this is a big-endian environment
450
 
        return XDR;
451
 
    }
452
 
    
453
 
    // otherwise this must be little-endian
454
 
 
455
 
    return NDR;
456
 
#endif
457
 
}