pktools  2.6.7
Processing Kernel for geospatial data
pkeditogr.cc
1 /**********************************************************************
2 pkeditogr.cc: program to edit (rename fields) ogr fil
3 Copyright (C) 2008-2014 Pieter Kempeneers
4 
5 This file is part of pktools
6 
7 pktools is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11 
12 pktools is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with pktools. If not, see <http://www.gnu.org/licenses/>.
19 ***********************************************************************/
20 #include <assert.h>
21 #include <map>
22 #include "base/Optionpk.h"
23 #include "imageclasses/ImgReaderOgr.h"
24 #include "imageclasses/ImgWriterOgr.h"
25 #include "imageclasses/ImgReaderGdal.h"
26 #include "imageclasses/ImgWriterGdal.h"
27 
28 using namespace std;
29 
30 int main(int argc, char *argv[])
31 {
32  Optionpk<string> input_opt("i", "input", "Input vector file");
33  Optionpk<string> output_opt("o", "output", "Output vector file");
34  Optionpk<string> ogrformat_opt("f", "f", "Output OGR file format","ESRI Shapefile");
35  Optionpk<string> selectField_opt("select", "select", "select field (combined with like opt)");
36  //selectField can also be done via ogr2ogr using the -select option
37  Optionpk<string> like_opt("like", "like", "substring(s) to be found in select field. If multiple substrings are provided, feature will be selected if one of them is found (stringent option must be false)");
38  Optionpk<bool> stringent_opt("st", "stringent", "string in like option must exactly match to select feature)",false);
39  // Optionpk<string> field_opt("as_field", "_field", "output field names (number must exactly match input fields)");
40  //renaming fields can also be done via ogr2ogr using the -sql option:
41  //ogr2ogr outdataset indataset -sql "SELECT src_field1 AS dst_field1, src_field2 AS dst_field2 FROM sourcelayer"
42  Optionpk<long int> setfeature_opt("sf", "sf", "id of feature(s) to set (start from 0)");
43  Optionpk<string> setname_opt("sn", "sn", "name(s) of field(s) to set");
44  Optionpk<string> setvalue_opt("sv", "sv", "value(s) of field(s) to set");
45  Optionpk<string> addname_opt("an", "an", "name(s) of field(s) to add (number must exactly match field types)");
46  Optionpk<string> addtype_opt("at", "at", "type(s) of field(s) to add (number must exactly match fieldnames to add", "Real");
47  Optionpk<string> addvalue_opt("av", "av", "value(s) of field(s) to add");
48  Optionpk<short> verbose_opt("v", "verbose", "verbose", 0);
49 
50  bool doProcess;//stop process when program was invoked with help option (-h --help)
51  try{
52  doProcess=input_opt.retrieveOption(argc,argv);
53  output_opt.retrieveOption(argc,argv);
54  ogrformat_opt.retrieveOption(argc,argv);
55  selectField_opt.retrieveOption(argc,argv);
56  like_opt.retrieveOption(argc,argv);
57  stringent_opt.retrieveOption(argc,argv);
58  // field_opt.retrieveOption(argc,argv);
59  addname_opt.retrieveOption(argc,argv);
60  addtype_opt.retrieveOption(argc,argv);
61  addvalue_opt.retrieveOption(argc,argv);
62  setfeature_opt.retrieveOption(argc,argv);
63  setname_opt.retrieveOption(argc,argv);
64  setvalue_opt.retrieveOption(argc,argv);
65  verbose_opt.retrieveOption(argc,argv);
66  }
67  catch(string predefinedString){
68  std::cout << predefinedString << std::endl;
69  exit(0);
70  }
71  if(!doProcess){
72  std::cout << "short option -h shows basic options only, use long option --help to show all options" << std::endl;
73  exit(0);//help was invoked, stop processing
74  }
75  if(input_opt.empty()){
76  std::cerr << "No input file provided (use option -i). Use --help for help information";
77  exit(0);//help was invoked, stop processing
78  }
79  if(output_opt.empty()){
80  std::cerr << "No output file provided (use option -o). Use --help for help information";
81  exit(0);//help was invoked, stop processing
82  }
83  if(verbose_opt[0])
84  cout << "opening " << input_opt[0] << " for reading " << endl;
85  ImgReaderOgr ogrReader(input_opt[0]);
86  if(verbose_opt[0])
87  cout << "opening " << output_opt[0] << " for writing " << endl;
88 
89  OGRFieldType fieldType[addtype_opt.size()];
90  int ogr_typecount=11;//hard coded for now!
91  for(int it=0;it<addtype_opt.size();++it){
92  for(int iType = 0; iType < ogr_typecount; ++iType){
93  if( OGRFieldDefn::GetFieldTypeName((OGRFieldType)iType) != NULL
94  && EQUAL(OGRFieldDefn::GetFieldTypeName((OGRFieldType)iType),
95  addtype_opt[it].c_str()))
96  fieldType[it]=(OGRFieldType) iType;
97  }
98  if(verbose_opt[0]>1)
99  std::cout << std::endl << "field type is: " << OGRFieldDefn::GetFieldTypeName(fieldType[it]) << std::endl;
100  }
101 
102  //start reading features from the layer
103  // if(field_opt.size())
104  // assert(field_opt.size()==ogrReader.getFieldCount());
105  unsigned long int ifeature=0;
106  if(verbose_opt[0])
107  cout << "going through features" << endl << flush;
108 
109  ImgWriterOgr ogrWriter(output_opt[0],ogrformat_opt[0]);
110 
111  //support multiple layers
112  int nlayer=ogrReader.getLayerCount();
113  if(verbose_opt[0])
114  std::cout << "number of layers: " << nlayer << endl;
115 
116  for(int ilayer=0;ilayer<nlayer;++ilayer){
117  OGRLayer *readLayer=ogrReader.getLayer(ilayer);
118  if(verbose_opt[0])
119  cout << "reset reading" << endl;
120  readLayer->ResetReading();
121 
122  OGRLayer *writeLayer=ogrWriter.createLayer(output_opt[0],ogrReader.getProjection(),ogrReader.getGeometryType(ilayer),NULL);
123  std::vector<OGRFieldDefn*> readFields;
124  std::vector<OGRFieldDefn*> writeFields;
125  ogrReader.getFields(readFields,ilayer);
126  writeFields=readFields;
127  try{
128  for(int ifield=0;ifield<readFields.size();++ifield){
129  // if(field_opt.size()>ifield)
130  // writeFields[ifield]->SetName(field_opt[ifield].c_str());
131  if(verbose_opt[0])
132  std::cout << readFields[ifield]->GetNameRef() << " -> " << writeFields[ifield]->GetNameRef() << std::endl;
133  if(writeLayer->CreateField(writeFields[ifield]) != OGRERR_NONE ){
134  ostringstream es;
135  // if(field_opt.size()>ifield)
136  // es << "Creating field " << field_opt[ifield] << " failed";
137  // else
138  es << "Creating field " << readFields[ifield] << " failed";
139  string errorString=es.str();
140  throw(errorString);
141  }
142  }
143  }
144  catch(string errorString){
145  std::cerr << errorString << std::endl;
146  exit(1);
147  }
148  if(verbose_opt[0])
149  std::cout << "add " << addname_opt.size() << " fields" << std::endl;
150  if(addname_opt.size()){
151  assert(addname_opt.size()==addtype_opt.size());
152  while(addvalue_opt.size()<addname_opt.size())
153  addvalue_opt.push_back(addvalue_opt.back());
154  }
155  for(int iname=0;iname<addname_opt.size();++iname){
156  if(verbose_opt[0])
157  std::cout << addname_opt[iname] << " " << std::endl;
158  ogrWriter.createField(addname_opt[iname],fieldType[iname]);
159  }
160  if(verbose_opt[0]){
161  std::cout << std::endl;
162  std::cout << addname_opt.size() << " fields created" << std::endl;
163  }
164  const char* pszMessage;
165  void* pProgressArg=NULL;
166  GDALProgressFunc pfnProgress=GDALTermProgress;
167  double progress=0;
168  OGRFeature *poFeature;
169  unsigned long int nfeature=ogrReader.getFeatureCount(ilayer);
170  while((poFeature = ogrReader.getLayer(ilayer)->GetNextFeature()) != NULL ){
171  if(verbose_opt[0])
172  std::cout << "feature " << ifeature << std::endl;
173  ++ifeature;
174  bool doSelect;
175  if(like_opt.empty())
176  doSelect=true;
177  else{
178  assert(selectField_opt.size());
179  int fieldIndex=poFeature->GetFieldIndex(selectField_opt[0].c_str());
180  string fieldValue=poFeature->GetFieldAsString(fieldIndex);
181  if(stringent_opt[0]){
182  if(fieldValue==like_opt[0])
183  doSelect=true;
184  else
185  doSelect=false;
186  }
187  else{
188  doSelect=false;
189  for(int ilike=0;ilike<like_opt.size();++ilike){
190  if(fieldValue.find(like_opt[ilike])!=std::string::npos){
191  if(verbose_opt[0])
192  std::cout << "found " << like_opt[ilike] << " in " << fieldValue << std::endl;
193  doSelect=true;
194  break;
195  }
196  }
197  }
198  }
199  if(!doSelect){
200  if(verbose_opt[0])
201  std::cout << "string not found in feature " << ifeature << std::endl;
202  continue;
203  }
204  OGRFeature *poDstFeature = NULL;
205  poDstFeature=ogrWriter.createFeature(ilayer);
206  if( poDstFeature->SetFrom( poFeature, TRUE ) != OGRERR_NONE ){
207  const char* fmt;
208  string errorString="Unable to translate feature %d from layer %s.\n";
209  fmt=errorString.c_str();
210  CPLError( CE_Failure, CPLE_AppDefined,
211  fmt,
212  poFeature->GetFID(), ogrWriter.getLayerName().c_str() );
213  OGRFeature::DestroyFeature( poFeature );
214  OGRFeature::DestroyFeature( poDstFeature );
215  }
216  long int fid=poFeature->GetFID();
217  poDstFeature->SetFID( poFeature->GetFID() );
218  for(int ifeature=0;ifeature<setfeature_opt.size();++ifeature){
219  if(fid==setfeature_opt[ifeature]){
220  switch(poDstFeature->GetFieldDefnRef(fid)->GetType()){
221  case(OFTReal):
222  poDstFeature->SetField(setname_opt[ifeature].c_str(),string2type<float>(setvalue_opt[ifeature]));
223  break;
224  case(OFTInteger):
225  poDstFeature->SetField(setname_opt[ifeature].c_str(),string2type<int>(setvalue_opt[ifeature]));
226  break;
227  case(OFTString):
228  poDstFeature->SetField(setname_opt[ifeature].c_str(),setvalue_opt[ifeature].c_str());
229  break;
230  default:
231  std::cerr << "Error: field type not supported" << std::endl;
232  exit(1);
233  break;
234  }
235  }
236  }
237 
238  //set default values for new fields
239  if(verbose_opt[0])
240  std::cout << "set default values for new fields in feature " << ifeature << std::endl;
241  for(int iname=0;iname<addname_opt.size();++iname){
242  switch(fieldType[iname]){
243  case(OFTReal):
244  if(verbose_opt[0])
245  std::cout << "set field " << addname_opt[iname] << " to default " << string2type<float>(addvalue_opt[iname]) << std::endl;
246  poDstFeature->SetField(addname_opt[iname].c_str(),string2type<float>(addvalue_opt[iname]));
247  break;
248  case(OFTInteger):
249  if(verbose_opt[0])
250  std::cout << "set field " << addname_opt[iname] << " to default " << string2type<int>(addvalue_opt[iname]) << std::endl;
251  poDstFeature->SetField(addname_opt[iname].c_str(),string2type<int>(addvalue_opt[iname]));
252  break;
253  case(OFTString):
254  if(verbose_opt[0])
255  std::cout << "set field " << addname_opt[iname] << " to default " << addvalue_opt[iname] << std::endl;
256  poDstFeature->SetField(addname_opt[iname].c_str(),addvalue_opt[iname].c_str());
257  break;
258  default:
259  std::cerr << "Error: field type not supported" << std::endl;
260  exit(1);
261  break;
262  }
263  }
264  CPLErrorReset();
265  if(verbose_opt[0])
266  std::cout << "create feature" << std::endl;
267  if(ogrWriter.createFeature( poDstFeature,ilayer ) != OGRERR_NONE){
268  const char* fmt;
269  string errorString="Unable to translate feature %d from layer %s.\n";
270  fmt=errorString.c_str();
271  CPLError( CE_Failure, CPLE_AppDefined,
272  fmt,
273  poFeature->GetFID(), ogrWriter.getLayerName().c_str() );
274  OGRFeature::DestroyFeature( poDstFeature );
275  }
276  OGRFeature::DestroyFeature( poFeature );
277  OGRFeature::DestroyFeature( poDstFeature );
278  progress=static_cast<float>(ifeature+1)/nfeature;
279  pfnProgress(progress,pszMessage,pProgressArg);
280  }
281  }
282  if(verbose_opt[0])
283  std::cout << "replaced " << ifeature << " features" << std::endl;
284  ogrReader.close();
285  ogrWriter.close();
286 }
STL namespace.