pktools  2.6.7
Processing Kernel for geospatial data
pkreclassogr.cc
1 /**********************************************************************
2 pkreclassogr.cc: program to replace field values of attributes in vector dataset
3 Copyright (C) 2008-2017 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 /******************************************************************************/
59 using namespace std;
60 
61 int main(int argc, char *argv[])
62 {
63  Optionpk<string> input_opt("i", "input", "Input vector dataset");
64  Optionpk<string> output_opt("o", "output", "Output file");
65  Optionpk<int> nodata_opt("nodata", "nodata", "nodata value to put in vector dataset if not valid (0)", 0);
66  Optionpk<string> code_opt("code", "code", "Recode text file (2 columns: from to)");
67  Optionpk<string> class_opt("c", "class", "list of classes to reclass (in combination with reclass option)");
68  Optionpk<string> reclass_opt("r", "reclass", "list of recoded classes (in combination with class option)");
69  Optionpk<string> fieldname_opt("n", "fname", "field name of the shape file to be replaced", "label");
70  Optionpk<short> verbose_opt("v", "verbose", "verbose", 0);
71 
72  bool doProcess;//stop process when program was invoked with help option (-h --help)
73  try{
74  doProcess=input_opt.retrieveOption(argc,argv);
75  nodata_opt.retrieveOption(argc,argv);
76  code_opt.retrieveOption(argc,argv);
77  class_opt.retrieveOption(argc,argv);
78  reclass_opt.retrieveOption(argc,argv);
79  output_opt.retrieveOption(argc,argv);
80  fieldname_opt.retrieveOption(argc,argv);
81  verbose_opt.retrieveOption(argc,argv);
82  }
83  catch(string predefinedString){
84  std::cout << predefinedString << std::endl;
85  exit(0);
86  }
87  if(!doProcess){
88  cout << endl;
89  cout << "Usage: pkreclassogr -i input [-c from -r to]* -o output" << endl;
90  cout << endl;
91  std::cout << "short option -h shows basic options only, use long option --help to show all options" << std::endl;
92  exit(0);//help was invoked, stop processing
93  }
94 
95  if(input_opt.empty()){
96  std::cerr << "No input file provided (use option -i). Use --help for help information" << std::endl;
97  exit(0);
98  }
99  if(output_opt.empty()){
100  std::cerr << "No output file provided (use option -o). Use --help for help information" << std::endl;
101  exit(0);
102  }
103 
104  // vector<short> bandVector;
105  map<string,string> codemapString;//map with codes: codemapString[theKey(from)]=theValue(to)
106  map<double,double> codemap;//map with codes: codemap[theKey(from)]=theValue(to)
107  if(code_opt.size()){
108  if(verbose_opt[0])
109  cout << "opening code text file " << code_opt[0] << endl;
110  ifstream codefile;
111  codefile.open(code_opt[0].c_str());
112  string theKey;
113  string theValue;
114  while(codefile>>theKey){
115  codefile >> theValue;
116  codemapString[theKey]=theValue;
117  codemap[string2type<double>(theKey)]=string2type<double>(theValue);
118  }
119  codefile.close();
120  }
121  else{//use combination of class_opt and reclass_opt
122  assert(class_opt.size()==reclass_opt.size());
123  for(int iclass=0;iclass<class_opt.size();++iclass){
124  codemapString[class_opt[iclass]]=reclass_opt[iclass];
125  codemap[string2type<double>(class_opt[iclass])]=string2type<double>(reclass_opt[iclass]);
126  }
127  }
128  assert(codemapString.size());
129  assert(codemap.size());
130  //if verbose true, print the codes to screen
131  if(verbose_opt[0]){
132  map<string,string>::iterator mit;
133  cout << codemapString.size() << " codes used: " << endl;
134  for(mit=codemapString.begin();mit!=codemapString.end();++mit)
135  cout << (*mit).first << " " << (*mit).second << endl;
136  }
137  bool refIsRaster=false;
138  ImgReaderOgr ogrReader;
139  try{
140  ogrReader.open(input_opt[0]);
141  }
142  catch(string errorString){
143  refIsRaster=true;
144  }
145  if(!refIsRaster){
146  if(verbose_opt[0])
147  cout << "opening " << input_opt[0] << " for reading " << endl;
148  // ImgReaderOgr ogrReader(input_opt[0]);
149  if(verbose_opt[0])
150  cout << "opening " << output_opt[0] << " for writing " << endl;
151  ImgWriterOgr ogrWriter(output_opt[0],ogrReader);
152  if(verbose_opt[0])
153  cout << "copied layer from " << input_opt[0] << endl << flush;
154  OGRFeatureDefn *poFDefn = ogrWriter.getLayer()->GetLayerDefn();
155  //start reading features from the layer
156  if(verbose_opt[0])
157  cout << "reset reading" << endl;
158  ogrReader.getLayer()->ResetReading();
159  unsigned long int ifeature=0;
160  if(verbose_opt[0])
161  cout << "going through features" << endl << flush;
162  while(true){
163  // while( (poFeature = ogrWriter.getLayer()->GetNextFeature()) != NULL ){
164  OGRFeature *poFeature;
165  poFeature=ogrReader.getLayer()->GetNextFeature();
166  if(poFeature== NULL)
167  break;
168  OGRFeatureDefn *poFDefn = ogrWriter.getLayer()->GetLayerDefn();
169  string featurename;
170  for(int iField=0;iField<poFDefn->GetFieldCount();++iField){
171  OGRFieldDefn *poFieldDefn = poFDefn->GetFieldDefn(iField);
172  string fieldname=poFieldDefn->GetNameRef();
173  if(fieldname==fieldname_opt[0]){
174  string fromClass=poFeature->GetFieldAsString(iField);
175  string toClass=fromClass;
176  if(codemapString.find(fromClass)!=codemapString.end())
177  toClass=codemapString[fromClass];
178  poFeature->SetField(iField,toClass.c_str());
179  if(verbose_opt[0])
180  cout << "feature " << ifeature << ": " << fromClass << "->" << poFeature->GetFieldAsInteger(iField) << endl << flush;
181  // cout << "feature " << ifeature << ": " << fromClass << "->" << toClass << endl << flush;
182  }
183  }
184  //do not forget to actually write feature to file!!!
185  ogrWriter.createFeature(poFeature);
186  OGRFeature::DestroyFeature( poFeature );
187  ++ifeature;
188  }
189  if(verbose_opt[0])
190  cout << "replaced " << ifeature << " features" << endl;
191  ogrReader.close();
192  ogrWriter.close();
193  }
194 }
STL namespace.