pktools  2.6.3
Processing Kernel for geospatial data
pkextract.cc
1 /**********************************************************************
2 pkextract.cc: extract pixel values from raster image from a (vector or raster) sample
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 <math.h>
22 #include <stdlib.h>
23 #include <sstream>
24 #include <string>
25 #include <algorithm>
26 #include <ctime>
27 #include <vector>
28 #include "imageclasses/ImgReaderGdal.h"
29 #include "imageclasses/ImgWriterOgr.h"
30 #include "base/Optionpk.h"
31 #include "algorithms/StatFactory.h"
32 
33 #ifndef PI
34 #define PI 3.1415926535897932384626433832795
35 #endif
36 
37 namespace rule{
38  enum RULE_TYPE {point=0, mean=1, proportion=2, custom=3, min=4, max=5, mode=6, centroid=7, sum=8, median=9, stdev=10, percentile=11};
39 }
40 
41 using namespace std;
42 
43 int main(int argc, char *argv[])
44 {
45  Optionpk<string> image_opt("i", "input", "Raster input dataset containing band information");
46  Optionpk<string> sample_opt("s", "sample", "OGR vector dataset with features to be extracted from input data. Output will contain features with input band information included. Sample image can also be GDAL raster dataset.");
47  Optionpk<string> layer_opt("ln", "ln", "Layer name(s) in sample (leave empty to select all)");
48  Optionpk<unsigned int> random_opt("rand", "random", "Create simple random sample of points. Provide number of points to generate");
49  Optionpk<double> grid_opt("grid", "grid", "Create systematic grid of points. Provide cell grid size (in projected units, e.g,. m)");
50  Optionpk<string> output_opt("o", "output", "Output sample dataset");
51  Optionpk<int> class_opt("c", "class", "Class(es) to extract from input sample image. Leave empty to extract all valid data pixels from sample dataset. Make sure to set classes if rule is set to mode or proportion");
52  Optionpk<float> threshold_opt("t", "threshold", "Probability threshold for selecting samples (randomly). Provide probability in percentage (>0) or absolute (<0). Use a single threshold for vector sample datasets. If using raster land cover maps as a sample dataset, you can provide a threshold value for each class (e.g. -t 80 -t 60). Use value 100 to select all pixels for selected class(es)", 100);
53  Optionpk<double> percentile_opt("perc","perc","Percentile value used for rule percentile",95);
54  Optionpk<string> ogrformat_opt("f", "f", "Output sample dataset format","SQLite");
55  Optionpk<string> ftype_opt("ft", "ftype", "Field type (only Real or Integer)", "Real");
56  Optionpk<string> ltype_opt("lt", "ltype", "Label type: In16 or String", "Integer");
57  Optionpk<bool> polygon_opt("polygon", "polygon", "Create OGRPolygon as geometry instead of OGRPoint.", false);
58  Optionpk<int> band_opt("b", "band", "Band index(es) to extract (0 based). Leave empty to use all bands");
59  Optionpk<string> rule_opt("r", "rule", "Rule how to report image information per feature (only for vector sample). point (value at each point or at centroid if polygon), centroid, mean, stdev, median, proportion, min, max, mode, sum, percentile.", "centroid");
60  Optionpk<double> srcnodata_opt("srcnodata", "srcnodata", "Invalid value(s) for input image");
61  Optionpk<int> bndnodata_opt("bndnodata", "bndnodata", "Band(s) in input image to check if pixel is valid (used for srcnodata)", 0);
62  Optionpk<float> polythreshold_opt("tp", "thresholdPolygon", "(absolute) threshold for selecting samples in each polygon");
63  Optionpk<string> test_opt("test", "test", "Test sample dataset (use this option in combination with threshold<100 to create a training (output) and test set");
64  Optionpk<string> fieldname_opt("bn", "bname", "For single band input data, this extra attribute name will correspond to the raster values. For multi-band input data, multiple attributes with this prefix will be added (e.g. b0, b1, b2, etc.)", "b");
65  Optionpk<string> label_opt("cn", "cname", "Name of the class label in the output vector dataset", "label");
66  Optionpk<short> geo_opt("geo", "geo", "Use geo coordinates (set to 0 to use image coordinates)", 1);
67  Optionpk<short> down_opt("down", "down", "Down sampling factor (for raster sample datasets only). Can be used to create grid points", 1);
68  Optionpk<short> buffer_opt("buf", "buffer", "Buffer for calculating statistics for point features ");
69  Optionpk<bool> disc_opt("circ", "circular", "Use a circular disc kernel buffer (for vector point sample datasets only, use in combination with buffer option)", false);
70  Optionpk<short> verbose_opt("v", "verbose", "Verbose mode if > 0", 0,2);
71 
72  bndnodata_opt.setHide(1);
73  srcnodata_opt.setHide(1);
74  polythreshold_opt.setHide(1);
75  percentile_opt.setHide(1);
76  test_opt.setHide(1);
77  fieldname_opt.setHide(1);
78  label_opt.setHide(1);
79  geo_opt.setHide(1);
80  down_opt.setHide(1);
81  buffer_opt.setHide(1);
82  disc_opt.setHide(1);
83 
84  bool doProcess;//stop process when program was invoked with help option (-h --help)
85  try{
86  doProcess=image_opt.retrieveOption(argc,argv);
87  sample_opt.retrieveOption(argc,argv);
88  layer_opt.retrieveOption(argc,argv);
89  random_opt.retrieveOption(argc,argv);
90  grid_opt.retrieveOption(argc,argv);
91  output_opt.retrieveOption(argc,argv);
92  class_opt.retrieveOption(argc,argv);
93  threshold_opt.retrieveOption(argc,argv);
94  percentile_opt.retrieveOption(argc,argv);
95  ogrformat_opt.retrieveOption(argc,argv);
96  ftype_opt.retrieveOption(argc,argv);
97  ltype_opt.retrieveOption(argc,argv);
98  polygon_opt.retrieveOption(argc,argv);
99  band_opt.retrieveOption(argc,argv);
100  rule_opt.retrieveOption(argc,argv);
101  bndnodata_opt.retrieveOption(argc,argv);
102  srcnodata_opt.retrieveOption(argc,argv);
103  polythreshold_opt.retrieveOption(argc,argv);
104  test_opt.retrieveOption(argc,argv);
105  fieldname_opt.retrieveOption(argc,argv);
106  label_opt.retrieveOption(argc,argv);
107  geo_opt.retrieveOption(argc,argv);
108  down_opt.retrieveOption(argc,argv);
109  buffer_opt.retrieveOption(argc,argv);
110  disc_opt.retrieveOption(argc,argv);
111  // rbox_opt.retrieveOption(argc,argv);
112  // cbox_opt.retrieveOption(argc,argv);
113  verbose_opt.retrieveOption(argc,argv);
114  }
115  catch(string predefinedString){
116  std::cout << predefinedString << std::endl;
117  exit(0);
118  }
119  if(!doProcess){
120  cout << endl;
121  cout << "Usage: pkextract -i input [-s sample | -rand number | -grid size] -o output" << endl;
122  cout << endl;
123  std::cout << "short option -h shows basic options only, use long option --help to show all options" << std::endl;
124  exit(0);//help was invoked, stop processing
125  }
126 
127  std::map<std::string, rule::RULE_TYPE> ruleMap;
128  //initialize ruleMap
129  ruleMap["point"]=rule::point;
130  ruleMap["centroid"]=rule::centroid;
131  ruleMap["mean"]=rule::mean;
132  ruleMap["stdev"]=rule::stdev;
133  ruleMap["median"]=rule::median;
134  ruleMap["proportion"]=rule::proportion;
135  ruleMap["min"]=rule::min;
136  ruleMap["max"]=rule::max;
137  ruleMap["custom"]=rule::custom;
138  ruleMap["mode"]=rule::mode;
139  ruleMap["sum"]=rule::sum;
140  ruleMap["percentile"]=rule::percentile;
141 
142  if(srcnodata_opt.size()){
143  while(srcnodata_opt.size()<bndnodata_opt.size())
144  srcnodata_opt.push_back(srcnodata_opt[0]);
145  while(bndnodata_opt.size()<srcnodata_opt.size())
146  bndnodata_opt.push_back(bndnodata_opt[0]);
147  }
148 
149  if(verbose_opt[0])
150  std::cout << class_opt << std::endl;
152  stat.setNoDataValues(srcnodata_opt);
153  Vector2d<unsigned int> posdata;
154  unsigned long int nsample=0;
155  unsigned long int ntotalvalid=0;
156  unsigned long int ntotalinvalid=0;
157  vector<unsigned long int> nvalid(class_opt.size());
158  vector<unsigned long int> ninvalid(class_opt.size());
159  for(int it=0;it<nvalid.size();++it){
160  nvalid[it]=0;
161  ninvalid[it]=0;
162  }
163 
164  ImgReaderGdal imgReader;
165  if(image_opt.empty()){
166  std::cerr << "No image dataset provided (use option -i). Use --help for help information";
167  exit(0);
168  }
169  if(output_opt.empty()){
170  std::cerr << "No output dataset provided (use option -o). Use --help for help information";
171  exit(0);
172  }
173  try{
174  imgReader.open(image_opt[0]);
175  }
176  catch(std::string errorstring){
177  std::cout << errorstring << std::endl;
178  exit(0);
179  }
180 
181  int nband=(band_opt.size()) ? band_opt.size() : imgReader.nrOfBand();
182 
183  if(fieldname_opt.size()<nband){
184  std::string bandString=fieldname_opt[0];
185  fieldname_opt.clear();
186  fieldname_opt.resize(nband);
187  for(int iband=0;iband<nband;++iband){
188  int theBand=(band_opt.size()) ? band_opt[iband] : iband;
189  ostringstream fs;
190  fs << bandString << theBand;
191  fieldname_opt[iband]=fs.str();
192  }
193  }
194 
195  if(verbose_opt[0])
196  std::cout << fieldname_opt << std::endl;
197 
198  if(verbose_opt[0]>1)
199  std::cout << "Number of bands in input image: " << imgReader.nrOfBand() << std::endl;
200 
201  OGRFieldType fieldType;
202  OGRFieldType labelType;
203  int ogr_typecount=11;//hard coded for now!
204  if(verbose_opt[0]>1)
205  std::cout << "field and label types can be: ";
206  for(int iType = 0; iType < ogr_typecount; ++iType){
207  if(verbose_opt[0]>1)
208  std::cout << " " << OGRFieldDefn::GetFieldTypeName((OGRFieldType)iType);
209  if( OGRFieldDefn::GetFieldTypeName((OGRFieldType)iType) != NULL
210  && EQUAL(OGRFieldDefn::GetFieldTypeName((OGRFieldType)iType),
211  ftype_opt[0].c_str()))
212  fieldType=(OGRFieldType) iType;
213  if( OGRFieldDefn::GetFieldTypeName((OGRFieldType)iType) != NULL
214  && EQUAL(OGRFieldDefn::GetFieldTypeName((OGRFieldType)iType),
215  ltype_opt[0].c_str()))
216  labelType=(OGRFieldType) iType;
217  }
218  switch( fieldType ){
219  case OFTInteger:
220  case OFTReal:
221  case OFTRealList:
222  case OFTString:
223  if(verbose_opt[0]>1)
224  std::cout << std::endl << "field type is: " << OGRFieldDefn::GetFieldTypeName(fieldType) << std::endl;
225  break;
226  default:
227  cerr << "field type " << OGRFieldDefn::GetFieldTypeName(fieldType) << " not supported" << std::endl;
228  exit(0);
229  break;
230  }
231  switch( labelType ){
232  case OFTInteger:
233  case OFTReal:
234  case OFTRealList:
235  case OFTString:
236  if(verbose_opt[0]>1)
237  std::cout << std::endl << "label type is: " << OGRFieldDefn::GetFieldTypeName(labelType) << std::endl;
238  break;
239  default:
240  cerr << "label type " << OGRFieldDefn::GetFieldTypeName(labelType) << " not supported" << std::endl;
241  exit(0);
242  break;
243  }
244 
245  const char* pszMessage;
246  void* pProgressArg=NULL;
247  GDALProgressFunc pfnProgress=GDALTermProgress;
248  double progress=0;
249  srand(time(NULL));
250 
251  bool sampleIsRaster=false;
252  bool sampleIsVirtual=false;
253 
254  ImgReaderOgr sampleReaderOgr;
255  ImgWriterOgr sampleWriterOgr;
256 
257  if(sample_opt.size()){
258  try{
259  sampleReaderOgr.open(sample_opt[0]);
260  }
261  catch(string errorString){
262  sampleIsRaster=true;
263  }
264  }
265  else{
266  try{
267  sampleWriterOgr.open("/vsimem/virtual",ogrformat_opt[0]);
268  }
269  catch(string errorString){
270  cerr << errorString << endl;
271  }
272  char **papszOptions=NULL;
273  sampleWriterOgr.createLayer("points", imgReader.getProjection(), wkbPoint, papszOptions);
274  sampleIsVirtual=true;
275 
276  // string fieldName="label";
277  // string fieldValue="class";
278  // sampleWriterOgr.createField(fieldName,OFTString);
279  if(random_opt.size()){
280  //create simple random sampling within boundary
281  OGRPoint pt;
282  double ulx,uly,lrx,lry;
283  imgReader.getBoundingBox(ulx,uly,lrx,lry);
284  for(unsigned int ipoint=1;ipoint<=random_opt[0];++ipoint){
285  OGRFeature *pointFeature;
286  pointFeature=sampleWriterOgr.createFeature();
287  // pointFeature->SetField(fieldName.c_str(),fieldValue.c_str());
288  double theX=ulx+static_cast<double>(rand())/(RAND_MAX)*(lrx-ulx);
289  double theY=uly-static_cast<double>(rand())/(RAND_MAX)*(uly-lry);
290  pt.setX(theX);
291  pt.setY(theY);
292  pointFeature->SetGeometry( &pt );
293  if(sampleWriterOgr.createFeature(pointFeature) != OGRERR_NONE ){
294  cerr << "Failed to create feature in shapefile" << endl;
295  exit( 1 );
296  }
297  OGRFeature::DestroyFeature(pointFeature);
298  }
299  }
300  else if(grid_opt.size()){
301  //create systematic grid of points
302  OGRPoint pt;
303  double ulx,uly,lrx,lry;
304  imgReader.getBoundingBox(ulx,uly,lrx,lry);
305  unsigned int ipoint=0;
306  for(double theY=uly-grid_opt[0]/2;theY>lry;theY-=grid_opt[0]){
307  for(double theX=ulx+grid_opt[0]/2;theX<lrx;theX+=grid_opt[0]){
308  if(verbose_opt[0]>1)
309  cout << "position: " << theX << " " << theY << endl;
310  OGRFeature *pointFeature;
311  pointFeature=sampleWriterOgr.createFeature();
312  // pointFeature->SetField(fieldName.c_str(),fieldValue.c_str());
313  pt.setX(theX);
314  pt.setY(theY);
315  pointFeature->SetGeometry( &pt );
316  if(sampleWriterOgr.createFeature(pointFeature) != OGRERR_NONE ){
317  cerr << "Failed to create feature in shapefile" << endl;
318  exit( 1 );
319  }
320  OGRFeature::DestroyFeature(pointFeature);
321  }
322  }
323  }
324  else{
325  std::cerr << "No sample dataset provided (use option -s). Use --help for help information";
326  exit(0);
327  }
328  try{
329  sampleWriterOgr.close();
330  sampleReaderOgr.open("/vsimem/virtual");
331  }
332  catch(string errorString){
333  cerr << errorString << endl;
334  }
335  }
336 
337  if(sampleIsRaster){
338  if(class_opt.empty()){
339  // std::cout << "Warning: no classes selected, if a classes must be extracted, set to -1 for all classes using option -c -1" << std::endl;
340  ImgReaderGdal classReader;
341  ImgWriterOgr ogrWriter;
342  assert(sample_opt.size());
343  classReader.open(sample_opt[0]);
344  // vector<int> classBuffer(classReader.nrOfCol());
345  vector<double> classBuffer(classReader.nrOfCol());
346  Vector2d<double> imgBuffer(nband);//[band][col]
347  vector<double> sample(2+nband);//x,y,band values
348  Vector2d<double> writeBuffer;
349  // vector<int> writeBufferClass;
350  vector<double> writeBufferClass;
351  vector<int> selectedClass;
352  Vector2d<double> selectedBuffer;
353  double oldimgrow=-1;
354  int irow=0;
355  int icol=0;
356  if(verbose_opt[0]>1)
357  std::cout << "extracting sample from image..." << std::endl;
358  progress=0;
359  pfnProgress(progress,pszMessage,pProgressArg);
360  for(irow=0;irow<classReader.nrOfRow();++irow){
361  if(irow%down_opt[0])
362  continue;
363  // classReader.readData(classBuffer,GDT_Int32,irow);
364  classReader.readData(classBuffer,GDT_Float64,irow);
365  double x,y;//geo coordinates
366  double iimg,jimg;//image coordinates in img image
367  for(icol=0;icol<classReader.nrOfCol();++icol){
368  if(icol%down_opt[0])
369  continue;
370  // int theClass=0;
371  double theClass=classBuffer[icol];
372  // int processClass=-1;
373  int processClass=0;
374  // if(class_opt[0]<0){//process every class except 0
375  // if(classBuffer[icol]){
376  // processClass=0;
377  // theClass=classBuffer[icol];
378  // }
379  // }
380  // else{
381  // for(int iclass=0;iclass<class_opt.size();++iclass){
382  // if(classBuffer[icol]==class_opt[iclass]){
383  // processClass=iclass;
384  // theClass=class_opt[iclass];
385  // }
386  // }
387  // }
388  // if(processClass>=0){
389  bool valid=true;
390  if(valid){
391  if(geo_opt[0]){
392  classReader.image2geo(icol,irow,x,y);
393  sample[0]=x;
394  sample[1]=y;
395  if(verbose_opt[0]>1){
396  std::cout.precision(12);
397  std::cout << theClass << " " << x << " " << y << std::endl;
398  }
399  //find col in img
400  imgReader.geo2image(x,y,iimg,jimg);
401  //nearest neighbour
402  jimg=static_cast<int>(jimg);
403  iimg=static_cast<int>(iimg);
404  if(static_cast<int>(iimg)<0||static_cast<int>(iimg)>=imgReader.nrOfCol())
405  continue;
406  }
407  else{
408  iimg=icol;
409  jimg=irow;
410  sample[0]=iimg;
411  sample[1]=jimg;
412  }
413  if(static_cast<int>(jimg)<0||static_cast<int>(jimg)>=imgReader.nrOfRow())
414  continue;
415 
416  bool valid=true;
417 
418  if(static_cast<int>(jimg)!=static_cast<int>(oldimgrow)){
419  assert(imgBuffer.size()==nband);
420  for(int iband=0;iband<nband;++iband){
421  int theBand=(band_opt.size()) ? band_opt[iband] : iband;
422  imgReader.readData(imgBuffer[iband],GDT_Float64,static_cast<int>(jimg),theBand);
423  assert(imgBuffer[iband].size()==imgReader.nrOfCol());
424  if(srcnodata_opt.size()){
425  vector<int>::const_iterator bndit=bndnodata_opt.begin();
426  vector<double>::const_iterator srcit=srcnodata_opt.begin();
427  while(bndit!=bndnodata_opt.end()&&srcit!=srcnodata_opt.end()){
428  if((*bndit==theBand)&&(*srcit==imgBuffer[iband][static_cast<int>(iimg)])){
429  valid=false;
430  break;
431  }
432  else{
433  ++bndit;
434  ++srcit;
435  }
436  }
437  }
438  }
439  oldimgrow=jimg;
440  }
441 
442  if(valid){
443  for(int iband=0;iband<imgBuffer.size();++iband){
444  if(imgBuffer[iband].size()!=imgReader.nrOfCol()){
445  std::cout << "Error in band " << iband << ": " << imgBuffer[iband].size() << "!=" << imgReader.nrOfCol() << std::endl;
446  assert(imgBuffer[iband].size()==imgReader.nrOfCol());
447  }
448  sample[iband+2]=imgBuffer[iband][static_cast<int>(iimg)];
449  }
450  float theThreshold=(threshold_opt.size()>1)?threshold_opt[processClass]:threshold_opt[0];
451  if(theThreshold>0){//percentual value
452  double p=static_cast<double>(rand())/(RAND_MAX);
453  p*=100.0;
454  if(p>theThreshold)
455  continue;//do not select for now, go to next column
456  }
457  else if(nvalid.size()>processClass){//absolute value
458  if(nvalid[processClass]>=-theThreshold)
459  continue;//do not select any more pixels for this class, go to next column to search for other classes
460  }
461  writeBuffer.push_back(sample);
462  writeBufferClass.push_back(theClass);
463  ++ntotalvalid;
464  if(nvalid.size()>processClass)
465  ++(nvalid[processClass]);
466  }
467  else{
468  ++ntotalinvalid;
469  if(ninvalid.size()>processClass)
470  ++(ninvalid[processClass]);
471  }
472  }//processClass
473  }//icol
474  progress=static_cast<float>(irow+1.0)/classReader.nrOfRow();
475  pfnProgress(progress,pszMessage,pProgressArg);
476  }//irow
477  progress=100;
478  pfnProgress(progress,pszMessage,pProgressArg);
479  if(writeBuffer.size()>0){
480  assert(ntotalvalid==writeBuffer.size());
481  if(verbose_opt[0]>0)
482  std::cout << "creating image sample writer " << output_opt[0] << " with " << writeBuffer.size() << " samples (" << ntotalinvalid << " invalid)" << std::endl;
483  ogrWriter.open(output_opt[0],ogrformat_opt[0]);
484  char **papszOptions=NULL;
485  ostringstream slayer;
486  slayer << "training data";
487  std::string layername=slayer.str();
488  ogrWriter.createLayer(layername, imgReader.getProjection(), wkbPoint, papszOptions);
489  std::string fieldname="fid";//number of the point
490  ogrWriter.createField(fieldname,OFTInteger);
491  map<std::string,double> pointAttributes;
492  ogrWriter.createField(label_opt[0],labelType);
493  for(int iband=0;iband<nband;++iband){
494  int theBand=(band_opt.size()) ? band_opt[iband] : iband;
495  ogrWriter.createField(fieldname_opt[iband],fieldType);
496  }
497  std::cout << "writing sample to " << output_opt[0] << "..." << std::endl;
498  progress=0;
499  pfnProgress(progress,pszMessage,pProgressArg);
500  for(int isample=0;isample<writeBuffer.size();++isample){
501  if(verbose_opt[0]>1)
502  std::cout << "writing sample " << isample << std::endl;
503  pointAttributes[label_opt[0]]=writeBufferClass[isample];
504  for(int iband=0;iband<writeBuffer[0].size()-2;++iband){
505  int theBand=(band_opt.size()) ? band_opt[iband] : iband;
506  // ostringstream fs;
507  // if(nband==1)
508  // fs << fieldname_opt[0];
509  // else
510  // fs << fieldname_opt[0] << theBand;
511  // pointAttributes[fs.str()]=writeBuffer[isample][iband+2];
512  pointAttributes[fieldname_opt[iband]]=writeBuffer[isample][iband+2];
513  }
514  if(verbose_opt[0]>1)
515  std::cout << "all bands written" << std::endl;
516  ogrWriter.addPoint(writeBuffer[isample][0],writeBuffer[isample][1],pointAttributes,fieldname,isample);
517  progress=static_cast<float>(isample+1.0)/writeBuffer.size();
518  pfnProgress(progress,pszMessage,pProgressArg);
519  }
520  ogrWriter.close();
521  }
522  else{
523  std::cout << "No data found for any class " << std::endl;
524  }
525  classReader.close();
526  nsample=writeBuffer.size();
527  if(verbose_opt[0])
528  std::cout << "total number of samples written: " << nsample << std::endl;
529  }
530  else{//class_opt.size()!=0
531  assert(class_opt[0]);
532  // if(class_opt[0]){
533  assert(threshold_opt.size()==1||threshold_opt.size()==class_opt.size());
534  ImgReaderGdal classReader;
535  ImgWriterOgr ogrWriter;
536  if(verbose_opt[0]>1){
537  std::cout << "reading position from sample dataset " << std::endl;
538  std::cout << "class thresholds: " << std::endl;
539  for(int iclass=0;iclass<class_opt.size();++iclass){
540  if(threshold_opt.size()>1)
541  std::cout << class_opt[iclass] << ": " << threshold_opt[iclass] << std::endl;
542  else
543  std::cout << class_opt[iclass] << ": " << threshold_opt[0] << std::endl;
544  }
545  }
546  classReader.open(sample_opt[0]);
547  vector<int> classBuffer(classReader.nrOfCol());
548  // vector<double> classBuffer(classReader.nrOfCol());
549  Vector2d<double> imgBuffer(nband);//[band][col]
550  vector<double> sample(2+nband);//x,y,band values
551  Vector2d<double> writeBuffer;
552  vector<int> writeBufferClass;
553  // vector<double> writeBufferClass;
554  vector<int> selectedClass;
555  Vector2d<double> selectedBuffer;
556  double oldimgrow=-1;
557  int irow=0;
558  int icol=0;
559  if(verbose_opt[0]>1)
560  std::cout << "extracting sample from image..." << std::endl;
561  progress=0;
562  pfnProgress(progress,pszMessage,pProgressArg);
563  for(irow=0;irow<classReader.nrOfRow();++irow){
564  if(irow%down_opt[0])
565  continue;
566  classReader.readData(classBuffer,GDT_Int32,irow);
567  // classReader.readData(classBuffer,GDT_Float64,irow);
568  double x,y;//geo coordinates
569  double iimg,jimg;//image coordinates in img image
570  for(icol=0;icol<classReader.nrOfCol();++icol){
571  if(icol%down_opt[0])
572  continue;
573  int theClass=0;
574  // double theClass=0;
575  int processClass=-1;
576  if(class_opt.empty()){//process every class
577  if(classBuffer[icol]){
578  processClass=0;
579  theClass=classBuffer[icol];
580  }
581  }
582  else{
583  for(int iclass=0;iclass<class_opt.size();++iclass){
584  if(classBuffer[icol]==class_opt[iclass]){
585  processClass=iclass;
586  theClass=class_opt[iclass];
587  }
588  }
589  }
590  if(processClass>=0){
591  // if(classBuffer[icol]==class_opt[0]){
592  if(geo_opt[0]){
593  classReader.image2geo(icol,irow,x,y);
594  sample[0]=x;
595  sample[1]=y;
596  if(verbose_opt[0]>1){
597  std::cout.precision(12);
598  std::cout << theClass << " " << x << " " << y << std::endl;
599  }
600  //find col in img
601  imgReader.geo2image(x,y,iimg,jimg);
602  //nearest neighbour
603  jimg=static_cast<int>(jimg);
604  iimg=static_cast<int>(iimg);
605  if(static_cast<int>(iimg)<0||static_cast<int>(iimg)>=imgReader.nrOfCol())
606  continue;
607  }
608  else{
609  iimg=icol;
610  jimg=irow;
611  sample[0]=iimg;
612  sample[1]=jimg;
613  }
614  if(static_cast<int>(jimg)<0||static_cast<int>(jimg)>=imgReader.nrOfRow())
615  continue;
616 
617  bool valid=true;
618 
619  if(static_cast<int>(jimg)!=static_cast<int>(oldimgrow)){
620  assert(imgBuffer.size()==nband);
621  for(int iband=0;iband<nband;++iband){
622  int theBand=(band_opt.size()) ? band_opt[iband] : iband;
623  imgReader.readData(imgBuffer[iband],GDT_Float64,static_cast<int>(jimg),theBand);
624  assert(imgBuffer[iband].size()==imgReader.nrOfCol());
625 
626  if(srcnodata_opt.size()){
627  vector<int>::const_iterator bndit=bndnodata_opt.begin();
628  vector<double>::const_iterator srcit=srcnodata_opt.begin();
629  while(bndit!=bndnodata_opt.end()&&srcit!=srcnodata_opt.end()){
630  if((*bndit==theBand)&&(*srcit==imgBuffer[iband][static_cast<int>(iimg)])){
631  valid=false;
632  break;
633  }
634  else{
635  ++bndit;
636  ++srcit;
637  }
638  }
639  }
640  }
641  oldimgrow=jimg;
642  }
643  if(valid){
644  for(int iband=0;iband<imgBuffer.size();++iband){
645  if(imgBuffer[iband].size()!=imgReader.nrOfCol()){
646  std::cout << "Error in band " << iband << ": " << imgBuffer[iband].size() << "!=" << imgReader.nrOfCol() << std::endl;
647  assert(imgBuffer[iband].size()==imgReader.nrOfCol());
648  }
649  sample[iband+2]=imgBuffer[iband][static_cast<int>(iimg)];
650  }
651  float theThreshold=(threshold_opt.size()>1)?threshold_opt[processClass]:threshold_opt[0];
652  if(theThreshold>0){//percentual value
653  double p=static_cast<double>(rand())/(RAND_MAX);
654  p*=100.0;
655  if(p>theThreshold)
656  continue;//do not select for now, go to next column
657  }
658  else if(nvalid.size()>processClass){//absolute value
659  if(nvalid[processClass]>=-theThreshold)
660  continue;//do not select any more pixels for this class, go to next column to search for other classes
661  }
662  writeBuffer.push_back(sample);
663  // writeBufferClass.push_back(class_opt[processClass]);
664  writeBufferClass.push_back(theClass);
665  ++ntotalvalid;
666  if(nvalid.size()>processClass)
667  ++(nvalid[processClass]);
668  }
669  else{
670  ++ntotalinvalid;
671  if(ninvalid.size()>processClass)
672  ++(ninvalid[processClass]);
673  }
674  }//processClass
675  }//icol
676  progress=static_cast<float>(irow+1.0)/classReader.nrOfRow();
677  pfnProgress(progress,pszMessage,pProgressArg);
678  }//irow
679  if(writeBuffer.size()>0){
680  assert(ntotalvalid==writeBuffer.size());
681  if(verbose_opt[0]>0)
682  std::cout << "creating image sample writer " << output_opt[0] << " with " << writeBuffer.size() << " samples (" << ntotalinvalid << " invalid)" << std::endl;
683  ogrWriter.open(output_opt[0],ogrformat_opt[0]);
684  char **papszOptions=NULL;
685  ostringstream slayer;
686  slayer << "training data";
687  std::string layername=slayer.str();
688  ogrWriter.createLayer(layername, imgReader.getProjection(), wkbPoint, papszOptions);
689  std::string fieldname="fid";//number of the point
690  ogrWriter.createField(fieldname,OFTInteger);
691  map<std::string,double> pointAttributes;
692  // ogrWriter.createField(label_opt[0],OFTInteger);
693  ogrWriter.createField(label_opt[0],labelType);
694  for(int iband=0;iband<nband;++iband){
695  int theBand=(band_opt.size()) ? band_opt[iband] : iband;
696  // ostringstream fs;
697  // if(nband==1)
698  // fs << fieldname_opt[0];
699  // else
700  // fs << fieldname_opt[0] << theBand;
701  // ogrWriter.createField(fs.str(),fieldType);
702  ogrWriter.createField(fieldname_opt[iband],fieldType);
703  }
704  pfnProgress(progress,pszMessage,pProgressArg);
705  std::cout << "writing sample to " << output_opt[0] << "..." << std::endl;
706  progress=0;
707  pfnProgress(progress,pszMessage,pProgressArg);
708  for(int isample=0;isample<writeBuffer.size();++isample){
709  pointAttributes[label_opt[0]]=writeBufferClass[isample];
710  for(int iband=0;iband<writeBuffer[0].size()-2;++iband){
711  int theBand=(band_opt.size()) ? band_opt[iband] : iband;
712  // ostringstream fs;
713  // if(nband==1)
714  // fs << fieldname_opt[0];
715  // else
716  // fs << fieldname_opt[0] << theBand;
717  // pointAttributes[fs.str()]=writeBuffer[isample][iband+2];
718  pointAttributes[fieldname_opt[iband]]=writeBuffer[isample][iband+2];
719  }
720  ogrWriter.addPoint(writeBuffer[isample][0],writeBuffer[isample][1],pointAttributes,fieldname,isample);
721  progress=static_cast<float>(isample+1.0)/writeBuffer.size();
722  pfnProgress(progress,pszMessage,pProgressArg);
723  }
724  ogrWriter.close();
725  }
726  else{
727  std::cout << "No data found for any class " << std::endl;
728  }
729  classReader.close();
730  nsample=writeBuffer.size();
731  if(verbose_opt[0]){
732  std::cout << "total number of samples written: " << nsample << std::endl;
733  if(nvalid.size()==class_opt.size()){
734  for(int iclass=0;iclass<class_opt.size();++iclass)
735  std::cout << "class " << class_opt[iclass] << " has " << nvalid[iclass] << " samples" << std::endl;
736  }
737  }
738  }
739  }
740  else{//vector dataset
741  if(verbose_opt[0]>1)
742  std::cout << "creating image sample writer " << output_opt[0] << std::endl;
743  ImgWriterOgr ogrWriter;
744  ImgWriterOgr ogrTestWriter;
745  ogrWriter.open(output_opt[0],ogrformat_opt[0]);
746  if(test_opt.size()){
747  if(verbose_opt[0]>1)
748  std::cout << "creating image test writer " << test_opt[0] << std::endl;
749  try{
750  ogrTestWriter.open(test_opt[0],ogrformat_opt[0]);
751  }
752  catch(string errorString){
753  cerr << errorString << endl;
754  }
755  }
756  //support multiple layers
757  int nlayerRead=sampleReaderOgr.getDataSource()->GetLayerCount();
758  int ilayerWrite=0;
759  if(verbose_opt[0])
760  std::cout << "number of layers: " << nlayerRead << endl;
761 
762  for(int ilayer=0;ilayer<nlayerRead;++ilayer){
763  OGRLayer *readLayer=sampleReaderOgr.getLayer(ilayer);
764  string currentLayername=readLayer->GetName();
765  if(layer_opt.size())
766  if(find(layer_opt.begin(),layer_opt.end(),currentLayername)==layer_opt.end())
767  continue;
768  cout << "processing layer " << currentLayername << endl;
769 
770  readLayer->ResetReading();
771  OGRLayer *writeLayer;
772  OGRLayer *writeTestLayer;
773 
774  if(polygon_opt[0]){
775  if(verbose_opt[0])
776  std::cout << "create polygons" << std::endl;
777  char **papszOptions=NULL;
778  writeLayer=ogrWriter.createLayer(readLayer->GetName(), imgReader.getProjection(), wkbPolygon, papszOptions);
779  if(test_opt.size())
780  writeTestLayer=ogrTestWriter.createLayer(readLayer->GetName(), imgReader.getProjection(), wkbPolygon, papszOptions);
781  }
782  else{
783  if(verbose_opt[0])
784  std::cout << "create points in layer " << readLayer->GetName() << std::endl;
785  char **papszOptions=NULL;
786 
787  writeLayer=ogrWriter.createLayer(readLayer->GetName(), imgReader.getProjection(), wkbPoint, papszOptions);
788  if(test_opt.size()){
789  char **papszOptions=NULL;
790  writeTestLayer=ogrTestWriter.createLayer(readLayer->GetName(), imgReader.getProjection(), wkbPoint, papszOptions);
791  }
792  }
793  if(verbose_opt[0])
794  std::cout << "copy fields from layer " << ilayer << std::flush << std::endl;
795  ogrWriter.copyFields(sampleReaderOgr,ilayer,ilayerWrite);
796 
797  if(test_opt.size()){
798  if(verbose_opt[0])
799  std::cout << "copy fields test writer" << std::flush << std::endl;
800  ogrTestWriter.copyFields(sampleReaderOgr,ilayer,ilayerWrite);
801  }
802  // vector<std::string> fieldnames;
803  // if(verbose_opt[0])
804  // std::cout << "get fields" << std::flush << std::endl;
805  // sampleReaderOgr.getFields(fieldnames);
806  // assert(fieldnames.size()==ogrWriter.getFieldCount(ilayerWrite));
807  // map<std::string,double> pointAttributes;
808 
809  if(class_opt.size()){
810  switch(ruleMap[rule_opt[0]]){
811  case(rule::proportion):{//proportion for each class
812  for(int iclass=0;iclass<class_opt.size();++iclass){
813  ostringstream cs;
814  cs << class_opt[iclass];
815  ogrWriter.createField(cs.str(),fieldType,ilayerWrite);
816  }
817  break;
818  }
819  case(rule::custom):
820  case(rule::mode):
821  ogrWriter.createField(label_opt[0],fieldType,ilayerWrite);
822  if(test_opt.size())
823  ogrTestWriter.createField(label_opt[0],fieldType,ilayerWrite);
824  break;
825  }
826  }
827  else{
828  for(int iband=0;iband<nband;++iband){
829  int theBand=(band_opt.size()) ? band_opt[iband] : iband;
830  ostringstream fs;
831  fs << fieldname_opt[iband];
832  if(verbose_opt[0]>1)
833  std::cout << "creating field " << fs.str() << std::endl;
834 
835  ogrWriter.createField(fs.str(),fieldType,ilayerWrite);
836  if(test_opt.size())
837  ogrTestWriter.createField(fs.str(),fieldType,ilayerWrite);
838  }
839  }
840  OGRFeature *readFeature;
841  unsigned long int ifeature=0;
842  unsigned long int nfeature=sampleReaderOgr.getFeatureCount();
843  progress=0;
844  pfnProgress(progress,pszMessage,pProgressArg);
845  while( (readFeature = readLayer->GetNextFeature()) != NULL ){
846  bool validFeature=false;
847  bool writeTest=false;//write this feature to test_opt[0] instead of output_opt
848  if(verbose_opt[0]>0)
849  std::cout << "reading feature " << readFeature->GetFID() << std::endl;
850  if(threshold_opt[0]>0){//percentual value
851  double p=static_cast<double>(rand())/(RAND_MAX);
852  p*=100.0;
853  if(p>threshold_opt[0]){
854  if(test_opt.size())
855  writeTest=true;
856  else
857  continue;//do not select for now, go to next feature
858  }
859  }
860  else{//absolute value
861  if(ntotalvalid>=-threshold_opt[0]){
862  if(test_opt.size())
863  writeTest=true;
864  else
865  continue;//do not select any more pixels, go to next column feature
866  }
867  }
868  if(verbose_opt[0]>0)
869  std::cout << "processing feature " << readFeature->GetFID() << std::endl;
870  //get x and y from readFeature
871  double x,y;
872  OGRGeometry *poGeometry;
873  poGeometry = readFeature->GetGeometryRef();
874  assert(poGeometry!=NULL);
875  try{
876  if(wkbFlatten(poGeometry->getGeometryType()) == wkbPoint ){
877 
878  if(!buffer_opt.size()){
879  switch(ruleMap[rule_opt[0]]){
880  case(rule::point):
881  case(rule::centroid):
882  buffer_opt.push_back(1);//default
883  break;
884  default:
885  buffer_opt.push_back(3);//default
886  }
887  }
888 
889  if(verbose_opt[0]>1)
890  std::cout << "boundary: " << buffer_opt[0] << std::endl;
891 
892  OGRPolygon writePolygon;
893  OGRLinearRing writeRing;
894  OGRPoint writeCentroidPoint;
895  OGRFeature *writePolygonFeature;
896  OGRFeature *writeCentroidFeature;
897 
898  OGRPoint *poPoint = (OGRPoint *) poGeometry;
899  writeCentroidPoint=*poPoint;
900 
901  x=poPoint->getX();
902  y=poPoint->getY();
903 
904  double i_centre,j_centre;
905  if(geo_opt[0])
906  imgReader.geo2image(x,y,i_centre,j_centre);
907  else{
908  i_centre=x;
909  j_centre=y;
910  }
911  //nearest neighbour
912  j_centre=static_cast<int>(j_centre);
913  i_centre=static_cast<int>(i_centre);
914 
915  double uli=i_centre-buffer_opt[0]/2;
916  double ulj=j_centre-buffer_opt[0]/2;
917  double lri=i_centre+buffer_opt[0]/2;
918  double lrj=j_centre+buffer_opt[0]/2;
919  // double uli=i_centre-buffer_opt[0]/2-0.5;
920  // double ulj=j_centre-buffer_opt[0]/2-0.5;
921  // double lri=i_centre+buffer_opt[0]/2+0.5;
922  // double lrj=j_centre+buffer_opt[0]/2+0.5;
923 
924  //nearest neighbour
925  ulj=static_cast<int>(ulj);
926  uli=static_cast<int>(uli);
927  lrj=static_cast<int>(lrj);
928  lri=static_cast<int>(lri);
929 
930  if((polygon_opt[0]&&ruleMap[rule_opt[0]]==rule::point)||(ruleMap[rule_opt[0]]==rule::centroid)){
931  uli=i_centre;
932  ulj=j_centre;
933  lri=i_centre;
934  lrj=j_centre;
935  }
936 
937  //check if j is out of bounds
938  if(static_cast<int>(ulj)<0||static_cast<int>(ulj)>=imgReader.nrOfRow())
939  continue;
940  //check if j is out of bounds
941  if(static_cast<int>(uli)<0||static_cast<int>(lri)>=imgReader.nrOfCol())
942  continue;
943 
944  OGRPoint ulPoint,urPoint,llPoint,lrPoint;
945  double ulx,uly;
946  double urx,ury;
947 
948  if(polygon_opt[0]){
949  if(disc_opt[0]){
950  double gt[6];// { 444720, 30, 0, 3751320, 0, -30 };
951  double radius=buffer_opt[0]/2.0*sqrt(imgReader.getDeltaX()*imgReader.getDeltaY());
952  unsigned short nstep = 25;
953  for(int i=0;i<nstep;++i){
954  OGRPoint aPoint;
955  aPoint.setX(x+radius*cos(2*PI*i/nstep));
956  aPoint.setY(y+radius*sin(2*PI*i/nstep));
957  writeRing.addPoint(&aPoint);
958  }
959  writePolygon.addRing(&writeRing);
960  writePolygon.closeRings();
961  }
962  else{
963  double llx,lly;
964  double lrx,lry;
965  imgReader.image2geo(uli,ulj,ulx,uly);
966  imgReader.image2geo(lri,lrj,lrx,lry);
967  ulPoint.setX(ulx-imgReader.getDeltaX()/2.0);
968  ulPoint.setY(uly+imgReader.getDeltaY()/2.0);
969  lrPoint.setX(lrx+imgReader.getDeltaX()/2.0);
970  lrPoint.setY(lry-imgReader.getDeltaY()/2.0);
971  urPoint.setX(lrx+imgReader.getDeltaX()/2.0);
972  urPoint.setY(uly+imgReader.getDeltaY()/2.0);
973  llPoint.setX(ulx-imgReader.getDeltaX()/2.0);
974  llPoint.setY(lry-imgReader.getDeltaY()/2.0);
975 
976  writeRing.addPoint(&ulPoint);
977  writeRing.addPoint(&urPoint);
978  writeRing.addPoint(&lrPoint);
979  writeRing.addPoint(&llPoint);
980  writePolygon.addRing(&writeRing);
981  writePolygon.closeRings();
982  }
983  }
984 
985  int nPointWindow=0;//similar to nPointPolygon for polygons
986  if(polygon_opt[0]){
987  if(writeTest)
988  writePolygonFeature = OGRFeature::CreateFeature(writeTestLayer->GetLayerDefn());
989  else
990  writePolygonFeature = OGRFeature::CreateFeature(writeLayer->GetLayerDefn());
991  }
992  else if(ruleMap[rule_opt[0]]!=rule::point){
993  if(writeTest)
994  writeCentroidFeature = OGRFeature::CreateFeature(writeTestLayer->GetLayerDefn());
995  else
996  writeCentroidFeature = OGRFeature::CreateFeature(writeLayer->GetLayerDefn());
997  }
998  Vector2d<double> windowValues;
999  vector<double> windowClassValues;
1000 
1001  if(class_opt.size()){
1002  windowClassValues.resize(class_opt.size());
1003  //initialize
1004  for(int iclass=0;iclass<class_opt.size();++iclass)
1005  windowClassValues[iclass]=0;
1006  }
1007  else
1008  windowValues.resize(nband);
1009  vector< Vector2d<double> > readValues(nband);
1010  for(int iband=0;iband<nband;++iband){
1011  int theBand=(band_opt.size()) ? band_opt[iband] : iband;
1012  //test
1013  assert(uli>=0);
1014  assert(uli<imgReader.nrOfCol());
1015  assert(lri>=0);
1016  assert(lri<imgReader.nrOfCol());
1017  assert(ulj>=0);
1018  assert(ulj<imgReader.nrOfRow());
1019  assert(lrj>=0);
1020  assert(lrj<imgReader.nrOfRow());
1021  imgReader.readDataBlock(readValues[iband],GDT_Float64,uli,lri,ulj,lrj,theBand);
1022  }
1023 
1024  OGRPoint thePoint;
1025  for(int j=ulj;j<=lrj;++j){
1026  for(int i=uli;i<=lri;++i){
1027  //check if within raster image
1028  if(i<0||i>=imgReader.nrOfCol())
1029  continue;
1030  if(j<0||j>=imgReader.nrOfRow())
1031  continue;
1032  //no need to check if point is on surface
1033  double theX=0;
1034  double theY=0;
1035  imgReader.image2geo(i,j,theX,theY);
1036  thePoint.setX(theX);
1037  thePoint.setY(theY);
1038 
1039  if(disc_opt[0]&&buffer_opt[0]>1){
1040  double radius=buffer_opt[0]/2.0*sqrt(imgReader.getDeltaX()*imgReader.getDeltaY());
1041  if((theX-x)*(theX-x)+(theY-y)*(theY-y)>radius*radius)
1042  continue;
1043  }
1044  bool valid=true;
1045 
1046  if(srcnodata_opt.size()){
1047  for(int vband=0;vband<bndnodata_opt.size();++vband){
1048  double value=((readValues[bndnodata_opt[vband]])[j-ulj])[i-uli];
1049  if(value==srcnodata_opt[vband]){
1050  valid=false;
1051  break;
1052  }
1053  }
1054  }
1055 
1056  if(!valid)
1057  continue;
1058  else
1059  validFeature=true;
1060 
1061  // writeRing.addPoint(&thePoint);//already done
1062 
1063  ++nPointWindow;
1064  OGRFeature *writePointFeature;
1065  if(!polygon_opt[0]){
1066  //create feature
1067  if(ruleMap[rule_opt[0]]==rule::point){//do not create in case of mean, stdev, median, sum or centroid (only create point at centroid)
1068  if(writeTest)
1069  writePointFeature = OGRFeature::CreateFeature(writeTestLayer->GetLayerDefn());
1070  else
1071  writePointFeature = OGRFeature::CreateFeature(writeLayer->GetLayerDefn());
1072  if(verbose_opt[0]>1)
1073  std::cout << "copying fields from polygons " << std::endl;
1074  //Geometry of readFeature and writePointFeature are both wkbPoint
1075  //attributes AND geometry are copied with SetFrom
1076  //test
1077  // writePointFeature->SetGeometry(&thePoint);
1078  if(writePointFeature->SetFrom(readFeature)!= OGRERR_NONE)
1079  cerr << "writing feature failed" << std::endl;
1080 
1081  assert(wkbFlatten(writePointFeature->GetGeometryRef()->getGeometryType()) == wkbPoint);
1082  // OGRGeometry *updateGeometry;
1083  // updateGeometry = writePointFeature->GetGeometryRef();
1084  // OGRPoint *poPoint = (OGRPoint *) updateGeometry;
1085  if(verbose_opt[0]>1)
1086  std::cout << "write feature has " << writePointFeature->GetFieldCount() << " fields" << std::endl;
1087  }
1088  }
1089  if(class_opt.size()){
1090  short value=((readValues[0])[j-ulj])[i-uli];
1091  for(int iclass=0;iclass<class_opt.size();++iclass){
1092  if(value==class_opt[iclass])
1093  windowClassValues[iclass]+=1;
1094  }
1095  }
1096  else{
1097  for(int iband=0;iband<nband;++iband){
1098  int theBand=(band_opt.size()) ? band_opt[iband] : iband;
1099  assert(j-ulj>=0);
1100  assert(j-ulj<readValues[iband].size());
1101  assert(i-uli>=0);
1102  assert(i-uli<((readValues[iband])[j-ulj]).size());
1103  double value=((readValues[iband])[j-ulj])[i-uli];
1104  // imgReader.readData(value,GDT_Float64,i,j,theBand);
1105  if(verbose_opt[0]>1)
1106  std::cout << ": " << value << std::endl;
1107  if(polygon_opt[0]||ruleMap[rule_opt[0]]!=rule::point){
1108  windowValues[iband].push_back(value);
1109  }
1110  else{
1111  try{
1112  if(verbose_opt[0]>1)
1113  std::cout << "set field " << fieldname_opt[iband] << " to " << value << std::endl;
1114  switch( fieldType ){
1115  case OFTInteger:
1116  case OFTReal:
1117  writePointFeature->SetField(fieldname_opt[iband].c_str(),value);
1118  break;
1119  case OFTString:
1120  writePointFeature->SetField(fieldname_opt[iband].c_str(),type2string<double>(value).c_str());
1121  break;
1122  default://not supported
1123  std::string errorString="field type not supported";
1124  throw(errorString);
1125  break;
1126  }
1127  }
1128  catch(std::string e){
1129  std::cout << e << std::endl;
1130  exit(1);
1131  }
1132  }//else
1133  }//iband
1134  }//else (class_opt.size())
1135  if(!polygon_opt[0]){
1136  if(ruleMap[rule_opt[0]]==rule::point){//do not create in case of mean or median value (only at centroid)
1137  //write feature
1138  if(verbose_opt[0]>1)
1139  std::cout << "creating point feature" << std::endl;
1140  if(writeTest){
1141  if(writeTestLayer->CreateFeature( writePointFeature ) != OGRERR_NONE ){
1142  std::string errorString="Failed to create feature in test ogr vector dataset";
1143  throw(errorString);
1144  }
1145  }
1146  else{
1147  if(writeLayer->CreateFeature( writePointFeature ) != OGRERR_NONE ){
1148  std::string errorString="Failed to create feature in ogr vector dataset";
1149  throw(errorString);
1150  }
1151  }
1152  //destroy feature
1153  OGRFeature::DestroyFeature( writePointFeature );
1154  ++ntotalvalid;
1155  if(verbose_opt[0])
1156  std::cout << "ntotalvalid(2): " << ntotalvalid << std::endl;
1157  }
1158  }
1159  }
1160  }
1161  if(polygon_opt[0]||ruleMap[rule_opt[0]]!=rule::point){
1162  //do not create if no points found within polygon
1163  if(!nPointWindow){
1164  if(verbose_opt[0])
1165  cout << "no points found in window, continuing" << endl;
1166  continue;
1167  }
1168  //add ring to polygon
1169  if(polygon_opt[0]){
1170  // writePolygon.addRing(&writeRing);//already done
1171  // writePolygon.closeRings();//already done
1172  //write geometry of writePolygon
1173  //test
1174  // writePolygonFeature->SetGeometry(&writePolygon);
1175  if(writePolygonFeature->SetFrom(readFeature)!= OGRERR_NONE)
1176  cerr << "writing feature failed" << std::endl;
1177  //test
1178  writePolygonFeature->SetGeometry(&writePolygon);
1179  assert(wkbFlatten(writePolygonFeature->GetGeometryRef()->getGeometryType()) == wkbPolygon);
1180 
1181  if(verbose_opt[0]>1)
1182  std::cout << "copying new fields write polygon " << std::endl;
1183  if(verbose_opt[0]>1)
1184  std::cout << "write feature has " << writePolygonFeature->GetFieldCount() << " fields" << std::endl;
1185  //write polygon feature
1186  }
1187  else{//write value of polygon to centroid point
1188  //create feature
1189  if(verbose_opt[0]>1)
1190  std::cout << "copying fields from polygons " << std::endl;
1191  //test
1192  //Geometry of readFeature and writeCentroidFeature are both wkbPoint
1193  //attributes AND geometry are copied with SetFrom
1194  // writeCentroidFeature->SetGeometry(&writeCentroidPoint);
1195  if(writeCentroidFeature->SetFrom(readFeature)!= OGRERR_NONE)
1196  cerr << "writing feature failed" << std::endl;
1197  assert(wkbFlatten(writeCentroidFeature->GetGeometryRef()->getGeometryType()) == wkbPoint);
1198  //test
1199  // OGRGeometry *updateGeometry;
1200  // updateGeometry = writeCentroidFeature->GetGeometryRef();
1201  // assert(wkbFlatten(updateGeometry->getGeometryType()) == wkbPoint );
1202  if(verbose_opt[0]>1)
1203  std::cout << "write feature has " << writeCentroidFeature->GetFieldCount() << " fields" << std::endl;
1204  }
1205  if(class_opt.empty()){
1206  if(ruleMap[rule_opt[0]]==rule::point){//value at centroid of polygon
1207  if(verbose_opt[0])
1208  std::cout << "number of points in window: " << nPointWindow << std::endl;
1209  for(int index=0;index<windowValues.size();++index){
1210  //test
1211  if(windowValues[index].size()!=1){
1212  cerr << "Error: windowValues[index].size()=" << windowValues[index].size() << endl;
1213  assert(windowValues[index].size()==1);
1214  }
1215  double theValue=windowValues[index].back();
1216 
1217  if(verbose_opt[0])
1218  std::cout << "number of points in window: " << nPointWindow << std::endl;
1219  int theBand=(band_opt.size()) ? band_opt[index] : index;
1220 
1221  try{
1222  if(verbose_opt[0]>1)
1223  std::cout << "set field " << fieldname_opt[index] << " to " << theValue << std::endl;
1224  switch( fieldType ){
1225  case OFTInteger:
1226  case OFTReal:
1227  if(polygon_opt[0])
1228  writePolygonFeature->SetField(fieldname_opt[index].c_str(),theValue);
1229  else
1230  writeCentroidFeature->SetField(fieldname_opt[index].c_str(),theValue);
1231  break;
1232  case OFTString:
1233  if(polygon_opt[0])
1234  writePolygonFeature->SetField(fieldname_opt[index].c_str(),type2string<double>(theValue).c_str());
1235  else
1236  writeCentroidFeature->SetField(fieldname_opt[index].c_str(),type2string<double>(theValue).c_str());
1237  break;
1238  default://not supported
1239  std::string errorString="field type not supported";
1240  throw(errorString);
1241  break;
1242  }
1243  }
1244  catch(std::string e){
1245  std::cout << e << std::endl;
1246  exit(1);
1247  }
1248  }
1249  }
1250  else{//ruleMap[rule_opt[0]] is not rule::point
1251  double theValue=0;
1252  for(int index=0;index<windowValues.size();++index){
1253  try{
1254  if(ruleMap[rule_opt[0]]==rule::mean)
1255  theValue=stat.mean(windowValues[index]);
1256  else if(ruleMap[rule_opt[0]]==rule::stdev)
1257  theValue=sqrt(stat.var(windowValues[index]));
1258  else if(ruleMap[rule_opt[0]]==rule::median)
1259  theValue=stat.median(windowValues[index]);
1260  else if(ruleMap[rule_opt[0]]==rule::percentile)
1261  theValue=stat.percentile(windowValues[index],windowValues[index].begin(),windowValues[index].end(),percentile_opt[0]);
1262  else if(ruleMap[rule_opt[0]]==rule::sum)
1263  theValue=stat.sum(windowValues[index]);
1264  else if(ruleMap[rule_opt[0]]==rule::max)
1265  theValue=stat.mymax(windowValues[index]);
1266  else if(ruleMap[rule_opt[0]]==rule::min)
1267  theValue=stat.mymin(windowValues[index]);
1268  else if(ruleMap[rule_opt[0]]==rule::centroid){
1269  if(verbose_opt[0])
1270  std::cout << "number of points in polygon: " << nPointWindow << std::endl;
1271  assert(nPointWindow<=1);
1272  assert(nPointWindow==windowValues[index].size());
1273  theValue=windowValues[index].back();
1274  }
1275  else{
1276  std::string errorString="rule not supported";
1277  throw(errorString);
1278  }
1279  if(verbose_opt[0]>1)
1280  std::cout << "set field " << fieldname_opt[index] << " to " << theValue << std::endl;
1281  switch( fieldType ){
1282  case OFTInteger:
1283  case OFTReal:
1284  if(polygon_opt[0])
1285  writePolygonFeature->SetField(fieldname_opt[index].c_str(),theValue);
1286  else
1287  writeCentroidFeature->SetField(fieldname_opt[index].c_str(),theValue);
1288  break;
1289  case OFTString:
1290  if(polygon_opt[0])
1291  writePolygonFeature->SetField(fieldname_opt[index].c_str(),type2string<double>(theValue).c_str());
1292  else
1293  writeCentroidFeature->SetField(fieldname_opt[index].c_str(),type2string<double>(theValue).c_str());
1294  break;
1295  default://not supported
1296  std::string errorString="field type not supported";
1297  throw(errorString);
1298  break;
1299  }
1300  }
1301  catch(std::string e){
1302  std::cout << e << std::endl;
1303  exit(1);
1304  }
1305  }
1306  }
1307  }
1308  else{//class_opt is set
1309  if(ruleMap[rule_opt[0]]==rule::proportion){
1310  if(verbose_opt[0])
1311  std::cout << "number of points in polygon: " << nPointWindow << std::endl;
1312  stat.normalize_pct(windowClassValues);
1313  for(int index=0;index<windowClassValues.size();++index){
1314  double theValue=windowClassValues[index];
1315  ostringstream fs;
1316  fs << class_opt[index];
1317  if(polygon_opt[0])
1318  writePolygonFeature->SetField(fs.str().c_str(),static_cast<int>(theValue));
1319  else
1320  writeCentroidFeature->SetField(fs.str().c_str(),static_cast<int>(theValue));
1321  }
1322  }
1323  else if(ruleMap[rule_opt[0]]==rule::custom){
1324  assert(polygon_opt[0]);//not implemented for points
1325  if(verbose_opt[0])
1326  std::cout << "number of points in polygon: " << nPointWindow << std::endl;
1327  stat.normalize_pct(windowClassValues);
1328  assert(windowClassValues.size()==2);//11:broadleaved, 12:coniferous
1329  if(windowClassValues[0]>=75)//broadleaved
1330  writePolygonFeature->SetField(label_opt[0].c_str(),static_cast<int>(11));
1331  else if(windowClassValues[1]>=75)//coniferous
1332  writePolygonFeature->SetField(label_opt[0].c_str(),static_cast<int>(12));
1333  else if(windowClassValues[0]>25&&windowClassValues[1]>25)//mixed
1334  writePolygonFeature->SetField(label_opt[0].c_str(),static_cast<int>(13));
1335  else{
1336  if(verbose_opt[0]){
1337  std::cout << "No valid value in windowClassValues..." << std::endl;
1338  for(int index=0;index<windowClassValues.size();++index){
1339  double theValue=windowClassValues[index];
1340  std::cout << theValue << " ";
1341  }
1342  std::cout << std::endl;
1343  }
1344  writePolygonFeature->SetField(label_opt[0].c_str(),static_cast<int>(20));
1345  }
1346  }
1347  else if(ruleMap[rule_opt[0]]==rule::mode){
1348  //maximum votes in polygon
1349  if(verbose_opt[0])
1350  std::cout << "number of points in window: " << nPointWindow << std::endl;
1351  //search for class with maximum votes
1352  int maxClass=stat.mymin(class_opt);
1353  vector<double>::iterator maxit;
1354  maxit=stat.mymax(windowClassValues,windowClassValues.begin(),windowClassValues.end());
1355  int maxIndex=distance(windowClassValues.begin(),maxit);
1356  maxClass=class_opt[maxIndex];
1357  if(verbose_opt[0]>0)
1358  std::cout << "maxClass: " << maxClass << std::endl;
1359  if(polygon_opt[0])
1360  writePolygonFeature->SetField(label_opt[0].c_str(),maxClass);
1361  else
1362  writeCentroidFeature->SetField(label_opt[0].c_str(),maxClass);
1363  }
1364  }
1365  if(polygon_opt[0]){
1366  if(verbose_opt[0]>1)
1367  std::cout << "creating polygon feature" << std::endl;
1368  if(writeTest){
1369  if(writeTestLayer->CreateFeature( writePolygonFeature ) != OGRERR_NONE ){
1370  std::string errorString="Failed to create polygon feature in ogr vector dataset";
1371  throw(errorString);
1372  }
1373  }
1374  else{
1375  if(writeLayer->CreateFeature( writePolygonFeature ) != OGRERR_NONE ){
1376  std::string errorString="Failed to create polygon feature in ogr vector dataset";
1377  throw(errorString);
1378  }
1379  }
1380  OGRFeature::DestroyFeature( writePolygonFeature );
1381  ++ntotalvalid;
1382  if(verbose_opt[0])
1383  std::cout << "ntotalvalid(1): " << ntotalvalid << std::endl;
1384  }
1385  else{
1386  if(verbose_opt[0]>1)
1387  std::cout << "creating point feature in centroid" << std::endl;
1388  if(writeTest){
1389  if(writeTestLayer->CreateFeature( writeCentroidFeature ) != OGRERR_NONE ){
1390  std::string errorString="Failed to create point feature in ogr vector dataset";
1391  throw(errorString);
1392  }
1393  }
1394  else{
1395  //test
1396  assert(validFeature);
1397  if(writeLayer->CreateFeature( writeCentroidFeature ) != OGRERR_NONE ){
1398  std::string errorString="Failed to create point feature in ogr vector dataset";
1399  throw(errorString);
1400  }
1401  }
1402  OGRFeature::DestroyFeature( writeCentroidFeature );
1403  ++ntotalvalid;
1404  if(verbose_opt[0])
1405  std::cout << "ntotalvalid: " << ntotalvalid << std::endl;
1406  }
1407  }
1408  }//if wkbPoint
1409  else if(wkbFlatten(poGeometry->getGeometryType()) == wkbPolygon){
1410 
1411  OGRPolygon readPolygon = *((OGRPolygon *) poGeometry);
1412  OGRPolygon writePolygon;
1413  OGRLinearRing writeRing;
1414  OGRPoint writeCentroidPoint;
1415  OGRFeature *writePolygonFeature;
1416  OGRFeature *writeCentroidFeature;
1417 
1418  readPolygon.closeRings();
1419 
1420  if(verbose_opt[0]>1)
1421  std::cout << "get point on polygon" << std::endl;
1422  if(ruleMap[rule_opt[0]]==rule::centroid)
1423  readPolygon.Centroid(&writeCentroidPoint);
1424  else
1425  readPolygon.PointOnSurface(&writeCentroidPoint);
1426 
1427  double ulx,uly,lrx,lry;
1428  double uli,ulj,lri,lrj;
1429  if((polygon_opt[0]&&ruleMap[rule_opt[0]]==rule::point)||(ruleMap[rule_opt[0]]==rule::centroid)){
1430  ulx=writeCentroidPoint.getX();
1431  uly=writeCentroidPoint.getY();
1432  lrx=ulx;
1433  lry=uly;
1434  }
1435  else{
1436  //get envelope
1437  if(verbose_opt[0])
1438  std::cout << "reading envelope for polygon " << ifeature << std::endl;
1439  OGREnvelope* psEnvelope=new OGREnvelope();
1440  readPolygon.getEnvelope(psEnvelope);
1441  ulx=psEnvelope->MinX;
1442  uly=psEnvelope->MaxY;
1443  lrx=psEnvelope->MaxX;
1444  lry=psEnvelope->MinY;
1445  delete psEnvelope;
1446  }
1447  if(geo_opt[0]){
1448  imgReader.geo2image(ulx,uly,uli,ulj);
1449  imgReader.geo2image(lrx,lry,lri,lrj);
1450  }
1451  else{
1452  uli=ulx;
1453  ulj=uly;
1454  lri=lrx;
1455  lrj=lry;
1456  }
1457  //nearest neighbour
1458  ulj=static_cast<int>(ulj);
1459  uli=static_cast<int>(uli);
1460  lrj=static_cast<int>(lrj);
1461  lri=static_cast<int>(lri);
1462  //iterate through all pixels
1463  if(verbose_opt[0]>1)
1464  std::cout << "bounding box for polygon feature " << ifeature << ": " << uli << " " << ulj << " " << lri << " " << lrj << std::endl;
1465 
1466  if(uli<0)
1467  uli=0;
1468  if(lri<0)
1469  lri=0;
1470  if(uli>=imgReader.nrOfCol())
1471  uli=imgReader.nrOfCol()-1;
1472  if(lri>=imgReader.nrOfCol())
1473  lri=imgReader.nrOfCol()-1;
1474  if(ulj<0)
1475  ulj=0;
1476  if(lrj<0)
1477  lrj=0;
1478  if(ulj>=imgReader.nrOfRow())
1479  ulj=imgReader.nrOfRow()-1;
1480  if(lrj>=imgReader.nrOfRow())
1481  lrj=imgReader.nrOfRow()-1;
1482  // if(uli<0||lri>=imgReader.nrOfCol()||ulj<0||lrj>=imgReader.nrOfRow())
1483  // continue;
1484 
1485  int nPointPolygon=0;
1486 
1487  if(polygon_opt[0]){
1488  if(writeTest)
1489  writePolygonFeature = OGRFeature::CreateFeature(writeTestLayer->GetLayerDefn());
1490  else
1491  writePolygonFeature = OGRFeature::CreateFeature(writeLayer->GetLayerDefn());
1492  }
1493  else if(ruleMap[rule_opt[0]]!=rule::point){
1494  if(writeTest)
1495  writeCentroidFeature = OGRFeature::CreateFeature(writeTestLayer->GetLayerDefn());
1496  else
1497  writeCentroidFeature = OGRFeature::CreateFeature(writeLayer->GetLayerDefn());
1498  }
1499  // vector<double> polyValues;
1500  Vector2d<double> polyValues;
1501  vector<double> polyClassValues;
1502 
1503  if(class_opt.size()){
1504 
1505  polyClassValues.resize(class_opt.size());
1506  //initialize
1507  for(int iclass=0;iclass<class_opt.size();++iclass)
1508  polyClassValues[iclass]=0;
1509  }
1510  else
1511  polyValues.resize(nband);
1512  vector< Vector2d<double> > readValues(nband);
1513  for(int iband=0;iband<nband;++iband){
1514  int theBand=(band_opt.size()) ? band_opt[iband] : iband;
1515  //test
1516  assert(uli>=0);
1517  assert(uli<imgReader.nrOfCol());
1518  assert(lri>=0);
1519  assert(lri<imgReader.nrOfCol());
1520  assert(ulj>=0);
1521  assert(ulj<imgReader.nrOfRow());
1522  assert(lrj>=0);
1523  assert(lrj<imgReader.nrOfRow());
1524  imgReader.readDataBlock(readValues[iband],GDT_Float64,uli,lri,ulj,lrj,theBand);
1525  }
1526 
1527  OGRPoint thePoint;
1528  for(int j=ulj;j<=lrj;++j){
1529  for(int i=uli;i<=lri;++i){
1530  //check if within raster image
1531  if(i<0||i>=imgReader.nrOfCol())
1532  continue;
1533  if(j<0||j>=imgReader.nrOfRow())
1534  continue;
1535  //check if point is on surface
1536  double theX=0;
1537  double theY=0;
1538  imgReader.image2geo(i,j,theX,theY);
1539  thePoint.setX(theX);
1540  thePoint.setY(theY);
1541 
1542  if(ruleMap[rule_opt[0]]!=rule::centroid&&!readPolygon.Contains(&thePoint))
1543  continue;
1544 
1545  bool valid=true;
1546 
1547  if(srcnodata_opt.size()){
1548  for(int vband=0;vband<bndnodata_opt.size();++vband){
1549  double value=((readValues[bndnodata_opt[vband]])[j-ulj])[i-uli];
1550  if(value==srcnodata_opt[vband]){
1551  valid=false;
1552  break;
1553  }
1554  }
1555  }
1556 
1557  if(!valid)
1558  continue;
1559  else
1560  validFeature=true;
1561 
1562  writeRing.addPoint(&thePoint);//todo: check if I need to add all interior points to ring or do I need to check if point is on ring first?
1563  // if(writeRing.isPointOnRingBoundary(&thePoint))
1564  // writeRing.addPoint(&thePoint);
1565  if(verbose_opt[0]>1)
1566  std::cout << "point is on surface:" << thePoint.getX() << "," << thePoint.getY() << std::endl;
1567  ++nPointPolygon;
1568 
1569  if(polythreshold_opt.size())
1570  if(nPointPolygon>polythreshold_opt[0])
1571  continue;
1572  // throw(nPointPolygon);
1573  OGRFeature *writePointFeature;
1574  if(!polygon_opt[0]){
1575  //create feature
1576  if(ruleMap[rule_opt[0]]==rule::point){//do not create in case of mean, stdev, median, sum or centroid (only create point at centroid)
1577  if(writeTest)
1578  writePointFeature = OGRFeature::CreateFeature(writeTestLayer->GetLayerDefn());
1579  else
1580  writePointFeature = OGRFeature::CreateFeature(writeLayer->GetLayerDefn());
1581  if(verbose_opt[0]>1)
1582  std::cout << "copying fields from polygons " << std::endl;
1583  if(writePointFeature->SetFrom(readFeature)!= OGRERR_NONE)
1584  cerr << "writing feature failed" << std::endl;
1585  if(verbose_opt[0]>1)
1586  std::cout << "set geometry as point " << std::endl;
1587  //test
1588  writePointFeature->SetGeometry(&thePoint);
1589  assert(wkbFlatten(writePointFeature->GetGeometryRef()->getGeometryType()) == wkbPoint);
1590  //test
1591  // OGRGeometry *updateGeometry;
1592  // updateGeometry = writePointFeature->GetGeometryRef();
1593  // OGRPoint *poPoint = (OGRPoint *) updateGeometry;
1594  if(verbose_opt[0]>1)
1595  std::cout << "write feature has " << writePointFeature->GetFieldCount() << " fields" << std::endl;
1596  }
1597  }
1598  if(class_opt.size()){
1599  short value=((readValues[0])[j-ulj])[i-uli];
1600  for(int iclass=0;iclass<class_opt.size();++iclass){
1601  if(value==class_opt[iclass])
1602  polyClassValues[iclass]+=1;
1603  }
1604  }
1605  else{
1606  for(int iband=0;iband<nband;++iband){
1607  int theBand=(band_opt.size()) ? band_opt[iband] : iband;
1608  assert(j-ulj>=0);
1609  assert(j-ulj<readValues[iband].size());
1610  assert(i-uli>=0);
1611  assert(i-uli<((readValues[iband])[j-ulj]).size());
1612  double value=((readValues[iband])[j-ulj])[i-uli];
1613  // imgReader.readData(value,GDT_Float64,i,j,theBand);
1614  if(verbose_opt[0]>1)
1615  std::cout << ": " << value << std::endl;
1616  if(polygon_opt[0]||ruleMap[rule_opt[0]]!=rule::point)
1617  polyValues[iband].push_back(value);
1618  else{
1619  if(verbose_opt[0]>1)
1620  std::cout << "set field " << fieldname_opt[iband] << " to " << value << std::endl;
1621  switch( fieldType ){
1622  case OFTInteger:
1623  case OFTReal:
1624  writePointFeature->SetField(fieldname_opt[iband].c_str(),value);
1625  break;
1626  case OFTString:
1627  writePointFeature->SetField(fieldname_opt[iband].c_str(),type2string<double>(value).c_str());
1628  break;
1629  default://not supported
1630  assert(0);
1631  break;
1632  }
1633  }//else
1634  }//iband
1635  }//else (class_opt.size())
1636  if(!polygon_opt[0]){
1637  if(ruleMap[rule_opt[0]]==rule::point){//do not create in case of mean or median value (only at centroid)
1638  //write feature
1639  if(verbose_opt[0]>1)
1640  std::cout << "creating point feature" << std::endl;
1641  if(writeTest){
1642  if(writeTestLayer->CreateFeature( writePointFeature ) != OGRERR_NONE ){
1643  std::string errorString="Failed to create feature in test ogr vector dataset";
1644  throw(errorString);
1645  }
1646  }
1647  else{
1648  if(writeLayer->CreateFeature( writePointFeature ) != OGRERR_NONE ){
1649  std::string errorString="Failed to create feature in ogr vector dataset";
1650  throw(errorString);
1651  }
1652  }
1653  //destroy feature
1654  OGRFeature::DestroyFeature( writePointFeature );
1655  ++ntotalvalid;
1656  if(verbose_opt[0])
1657  std::cout << "ntotalvalid(2): " << ntotalvalid << std::endl;
1658  }
1659  }
1660  }
1661  }
1662  if(polygon_opt[0]||ruleMap[rule_opt[0]]!=rule::point){
1663  //do not create if no points found within polygon
1664  if(!nPointPolygon){
1665  if(verbose_opt[0])
1666  cout << "no points found in polygon, continuing" << endl;
1667  continue;
1668  }
1669  //add ring to polygon
1670  if(polygon_opt[0]){
1671  writePolygon.addRing(&writeRing);
1672  writePolygon.closeRings();
1673  //write geometry of writePolygon
1674  //test
1675  //writePolygonFeature and readFeature are both of type wkbPolygon
1676  // writePolygonFeature->SetGeometry(&writePolygon);
1677  if(writePolygonFeature->SetFrom(readFeature)!= OGRERR_NONE)
1678  cerr << "writing feature failed" << std::endl;
1679  if(verbose_opt[0]>1)
1680  std::cout << "copying new fields write polygon " << std::endl;
1681  if(verbose_opt[0]>1)
1682  std::cout << "write feature has " << writePolygonFeature->GetFieldCount() << " fields" << std::endl;
1683  //write polygon feature
1684  }
1685  else{//write value of polygon to centroid point
1686  //create feature
1687  if(verbose_opt[0]>1)
1688  std::cout << "copying fields from polygons " << std::endl;
1689  //test
1690  //writeCentroidFeature->SetGeometry(&writeCentroidPoint);
1691  if(writeCentroidFeature->SetFrom(readFeature)!= OGRERR_NONE)
1692  cerr << "writing feature failed" << std::endl;
1693  //test
1694  writeCentroidFeature->SetGeometry(&writeCentroidPoint);
1695  assert(wkbFlatten(writeCentroidFeature->GetGeometryRef()->getGeometryType()) == wkbPoint );
1696  // OGRGeometry *updateGeometry;
1697  // updateGeometry = writeCentroidFeature->GetGeometryRef();
1698  // assert(wkbFlatten(updateGeometry->getGeometryType()) == wkbPoint );
1699  if(verbose_opt[0]>1)
1700  std::cout << "write feature has " << writeCentroidFeature->GetFieldCount() << " fields" << std::endl;
1701  }
1702  if(class_opt.empty()){
1703  if(ruleMap[rule_opt[0]]==rule::point){//value at centroid of polygon
1704  if(verbose_opt[0])
1705  std::cout << "number of points in polygon: " << nPointPolygon << std::endl;
1706  for(int index=0;index<polyValues.size();++index){
1707  assert(polyValues[index].size()==1);
1708  double theValue=polyValues[index].back();
1709 
1710  if(verbose_opt[0])
1711  std::cout << "number of points in polygon: " << nPointPolygon << std::endl;
1712  int theBand=(band_opt.size()) ? band_opt[index] : index;
1713  try{
1714  if(verbose_opt[0]>1)
1715  std::cout << "set field " << fieldname_opt[index] << " to " << theValue << std::endl;
1716  switch( fieldType ){
1717  case OFTInteger:
1718  case OFTReal:
1719  if(polygon_opt[0])
1720  writePolygonFeature->SetField(fieldname_opt[index].c_str(),theValue);
1721  else
1722  writeCentroidFeature->SetField(fieldname_opt[index].c_str(),theValue);
1723  break;
1724  case OFTString:
1725  if(polygon_opt[0])
1726  writePolygonFeature->SetField(fieldname_opt[index].c_str(),type2string<double>(theValue).c_str());
1727  else
1728  writeCentroidFeature->SetField(fieldname_opt[index].c_str(),type2string<double>(theValue).c_str());
1729  break;
1730  default://not supported
1731  std::string errorString="field type not supported";
1732  throw(errorString);
1733  break;
1734  }
1735  }
1736  catch(std::string e){
1737  std::cout << e << std::endl;
1738  exit(1);
1739  }
1740  }
1741  }
1742  else{//ruleMap[rule_opt[0]] is not rule::point
1743  double theValue=0;
1744  for(int index=0;index<polyValues.size();++index){
1745  try{
1746  if(ruleMap[rule_opt[0]]==rule::mean)
1747  theValue=stat.mean(polyValues[index]);
1748  else if(ruleMap[rule_opt[0]]==rule::stdev)
1749  theValue=sqrt(stat.var(polyValues[index]));
1750  else if(ruleMap[rule_opt[0]]==rule::median)
1751  theValue=stat.median(polyValues[index]);
1752  else if(ruleMap[rule_opt[0]]==rule::percentile)
1753  theValue=stat.percentile(polyValues[index],polyValues[index].begin(),polyValues[index].end(),percentile_opt[0]);
1754  else if(ruleMap[rule_opt[0]]==rule::sum)
1755  theValue=stat.sum(polyValues[index]);
1756  else if(ruleMap[rule_opt[0]]==rule::max)
1757  theValue=stat.mymax(polyValues[index]);
1758  else if(ruleMap[rule_opt[0]]==rule::min)
1759  theValue=stat.mymin(polyValues[index]);
1760  else if(ruleMap[rule_opt[0]]==rule::centroid){
1761  if(verbose_opt[0])
1762  std::cout << "number of points in polygon: " << nPointPolygon << std::endl;
1763  assert(nPointPolygon<=1);
1764  assert(nPointPolygon==polyValues[index].size());
1765  theValue=polyValues[index].back();
1766  }
1767  else{
1768  std::string errorString="rule not supported";
1769  throw(errorString);
1770  }
1771  if(verbose_opt[0]>1)
1772  std::cout << "set field " << fieldname_opt[index] << " to " << theValue << std::endl;
1773  switch( fieldType ){
1774  case OFTInteger:
1775  case OFTReal:
1776  if(polygon_opt[0])
1777  writePolygonFeature->SetField(fieldname_opt[index].c_str(),theValue);
1778  else
1779  writeCentroidFeature->SetField(fieldname_opt[index].c_str(),theValue);
1780  break;
1781  case OFTString:
1782  if(polygon_opt[0])
1783  writePolygonFeature->SetField(fieldname_opt[index].c_str(),type2string<double>(theValue).c_str());
1784  else
1785  writeCentroidFeature->SetField(fieldname_opt[index].c_str(),type2string<double>(theValue).c_str());
1786  break;
1787  default:
1788  std::string errorString="field type not supported";
1789  throw(errorString);
1790  break;
1791  }
1792  }
1793  catch(std::string e){
1794  std::cout << e << std::endl;
1795  exit(1);
1796  }
1797  }
1798  }
1799  }
1800  else{//class_opt is set
1801  if(ruleMap[rule_opt[0]]==rule::proportion){
1802  if(verbose_opt[0])
1803  std::cout << "number of points in polygon: " << nPointPolygon << std::endl;
1804  stat.normalize_pct(polyClassValues);
1805  for(int index=0;index<polyClassValues.size();++index){
1806  double theValue=polyClassValues[index];
1807  ostringstream fs;
1808  fs << class_opt[index];
1809  if(polygon_opt[0])
1810  writePolygonFeature->SetField(fs.str().c_str(),static_cast<int>(theValue));
1811  else
1812  writeCentroidFeature->SetField(fs.str().c_str(),static_cast<int>(theValue));
1813  }
1814  }
1815  else if(ruleMap[rule_opt[0]]==rule::custom){
1816  assert(polygon_opt[0]);//not implemented for points
1817  if(verbose_opt[0])
1818  std::cout << "number of points in polygon: " << nPointPolygon << std::endl;
1819  stat.normalize_pct(polyClassValues);
1820  assert(polyClassValues.size()==2);//11:broadleaved, 12:coniferous
1821  if(polyClassValues[0]>=75)//broadleaved
1822  writePolygonFeature->SetField(label_opt[0].c_str(),static_cast<int>(11));
1823  else if(polyClassValues[1]>=75)//coniferous
1824  writePolygonFeature->SetField(label_opt[0].c_str(),static_cast<int>(12));
1825  else if(polyClassValues[0]>25&&polyClassValues[1]>25)//mixed
1826  writePolygonFeature->SetField(label_opt[0].c_str(),static_cast<int>(13));
1827  else{
1828  if(verbose_opt[0]){
1829  std::cout << "No valid value in polyClassValues..." << std::endl;
1830  for(int index=0;index<polyClassValues.size();++index){
1831  double theValue=polyClassValues[index];
1832  std::cout << theValue << " ";
1833  }
1834  std::cout << std::endl;
1835  }
1836  writePolygonFeature->SetField(label_opt[0].c_str(),static_cast<int>(20));
1837  }
1838  }
1839  else if(ruleMap[rule_opt[0]]==rule::mode){
1840  //maximum votes in polygon
1841  if(verbose_opt[0])
1842  std::cout << "number of points in polygon: " << nPointPolygon << std::endl;
1843  //search for class with maximum votes
1844  int maxClass=stat.mymin(class_opt);
1845  vector<double>::iterator maxit;
1846  maxit=stat.mymax(polyClassValues,polyClassValues.begin(),polyClassValues.end());
1847  int maxIndex=distance(polyClassValues.begin(),maxit);
1848  maxClass=class_opt[maxIndex];
1849  if(verbose_opt[0]>0)
1850  std::cout << "maxClass: " << maxClass << std::endl;
1851  if(polygon_opt[0])
1852  writePolygonFeature->SetField(label_opt[0].c_str(),maxClass);
1853  else
1854  writeCentroidFeature->SetField(label_opt[0].c_str(),maxClass);
1855  }
1856  }
1857  if(polygon_opt[0]){
1858  if(verbose_opt[0]>1)
1859  std::cout << "creating polygon feature" << std::endl;
1860  if(writeTest){
1861  if(writeTestLayer->CreateFeature( writePolygonFeature ) != OGRERR_NONE ){
1862  std::string errorString="Failed to create polygon feature in ogr vector dataset";
1863  throw(errorString);
1864  }
1865  }
1866  else{
1867  if(writeLayer->CreateFeature( writePolygonFeature ) != OGRERR_NONE ){
1868  std::string errorString="Failed to create polygon feature in ogr vector dataset";
1869  throw(errorString);
1870  }
1871  }
1872  OGRFeature::DestroyFeature( writePolygonFeature );
1873  ++ntotalvalid;
1874  if(verbose_opt[0])
1875  std::cout << "ntotalvalid(1): " << ntotalvalid << std::endl;
1876  }
1877  else{
1878  if(verbose_opt[0]>1)
1879  std::cout << "creating point feature in centroid" << std::endl;
1880  if(writeTest){
1881  if(writeTestLayer->CreateFeature( writeCentroidFeature ) != OGRERR_NONE ){
1882  std::string errorString="Failed to create point feature in ogr vector dataset";
1883  throw(errorString);
1884  }
1885  }
1886  else{
1887  //test
1888  assert(validFeature);
1889  if(writeLayer->CreateFeature( writeCentroidFeature ) != OGRERR_NONE ){
1890  std::string errorString="Failed to create point feature in ogr vector dataset";
1891  throw(errorString);
1892  }
1893  }
1894  OGRFeature::DestroyFeature( writeCentroidFeature );
1895  ++ntotalvalid;
1896  if(verbose_opt[0])
1897  std::cout << "ntotalvalid: " << ntotalvalid << std::endl;
1898  }
1899  }
1900  }
1901  else if(wkbFlatten(poGeometry->getGeometryType()) == wkbMultiPolygon){//todo: try to use virtual OGRGeometry instead of OGRMultiPolygon and OGRPolygon
1902  OGRMultiPolygon readPolygon = *((OGRMultiPolygon *) poGeometry);
1903  OGRPolygon writePolygon;
1904  OGRLinearRing writeRing;
1905  OGRPoint writeCentroidPoint;
1906  OGRFeature *writePolygonFeature;
1907  OGRFeature *writeCentroidFeature;
1908 
1909  readPolygon.closeRings();
1910 
1911  if(verbose_opt[0]>1)
1912  std::cout << "get centroid point from polygon" << std::endl;
1913 
1914  readPolygon.Centroid(&writeCentroidPoint);
1915 
1916  double ulx,uly,lrx,lry;
1917  double uli,ulj,lri,lrj;
1918  if((polygon_opt[0]&&ruleMap[rule_opt[0]]==rule::point)||(ruleMap[rule_opt[0]]==rule::centroid)){
1919  ulx=writeCentroidPoint.getX();
1920  uly=writeCentroidPoint.getY();
1921  lrx=ulx;
1922  lry=uly;
1923  }
1924  else{
1925  //get envelope
1926  if(verbose_opt[0])
1927  std::cout << "reading envelope for polygon " << ifeature << std::endl;
1928  OGREnvelope* psEnvelope=new OGREnvelope();
1929  readPolygon.getEnvelope(psEnvelope);
1930  ulx=psEnvelope->MinX;
1931  uly=psEnvelope->MaxY;
1932  lrx=psEnvelope->MaxX;
1933  lry=psEnvelope->MinY;
1934  delete psEnvelope;
1935  }
1936  // if(geo_opt[0]){
1937  imgReader.geo2image(ulx,uly,uli,ulj);
1938  imgReader.geo2image(lrx,lry,lri,lrj);
1939  // }
1940  // else{
1941  // uli=ulx;
1942  // ulj=uly;
1943  // lri=lrx;
1944  // lrj=lry;
1945  // }
1946  //nearest neighbour
1947  ulj=static_cast<int>(ulj);
1948  uli=static_cast<int>(uli);
1949  lrj=static_cast<int>(lrj);
1950  lri=static_cast<int>(lri);
1951  //iterate through all pixels
1952  if(verbose_opt[0]>1)
1953  std::cout << "bounding box for multipologon feature " << ifeature << ": " << uli << " " << ulj << " " << lri << " " << lrj << std::endl;
1954 
1955  if(uli<0)
1956  uli=0;
1957  if(lri<0)
1958  lri=0;
1959  if(uli>=imgReader.nrOfCol())
1960  uli=imgReader.nrOfCol()-1;
1961  if(lri>=imgReader.nrOfCol())
1962  lri=imgReader.nrOfCol()-1;
1963  if(ulj<0)
1964  ulj=0;
1965  if(lrj<0)
1966  lrj=0;
1967  if(ulj>=imgReader.nrOfRow())
1968  ulj=imgReader.nrOfRow()-1;
1969  if(lrj>=imgReader.nrOfRow())
1970  lrj=imgReader.nrOfRow()-1;
1971  // if(uli<0||lri>=imgReader.nrOfCol()||ulj<0||lrj>=imgReader.nrOfRow())
1972  // continue;
1973 
1974  int nPointPolygon=0;
1975  if(polygon_opt[0]){
1976  if(writeTest)
1977  writePolygonFeature = OGRFeature::CreateFeature(writeTestLayer->GetLayerDefn());
1978  else
1979  writePolygonFeature = OGRFeature::CreateFeature(writeLayer->GetLayerDefn());
1980  }
1981  else if(ruleMap[rule_opt[0]]!=rule::point){
1982  if(writeTest)
1983  writeCentroidFeature = OGRFeature::CreateFeature(writeTestLayer->GetLayerDefn());
1984  else
1985  writeCentroidFeature = OGRFeature::CreateFeature(writeLayer->GetLayerDefn());
1986  }
1987  // vector<double> polyValues;
1988  Vector2d<double> polyValues;
1989  vector<double> polyClassValues;
1990 
1991  if(class_opt.size()){
1992  polyClassValues.resize(class_opt.size());
1993  //initialize
1994  for(int iclass=0;iclass<class_opt.size();++iclass)
1995  polyClassValues[iclass]=0;
1996  }
1997  else
1998  polyValues.resize(nband);
1999  vector< Vector2d<double> > readValues(nband);
2000  for(int iband=0;iband<nband;++iband){
2001  int theBand=(band_opt.size()) ? band_opt[iband] : iband;
2002  //test
2003  assert(uli>=0);
2004  assert(uli<imgReader.nrOfCol());
2005  assert(lri>=0);
2006  assert(lri<imgReader.nrOfCol());
2007  assert(ulj>=0);
2008  assert(ulj<imgReader.nrOfRow());
2009  assert(lrj>=0);
2010  assert(lrj<imgReader.nrOfRow());
2011  imgReader.readDataBlock(readValues[iband],GDT_Float64,uli,lri,ulj,lrj,theBand);
2012  }
2013 
2014  OGRPoint thePoint;
2015  for(int j=ulj;j<=lrj;++j){
2016  for(int i=uli;i<=lri;++i){
2017  //check if within raster image
2018  if(i<0||i>=imgReader.nrOfCol())
2019  continue;
2020  if(j<0||j>=imgReader.nrOfRow())
2021  continue;
2022  //check if point is on surface
2023  double theX=0;
2024  double theY=0;
2025  imgReader.image2geo(i,j,theX,theY);
2026  thePoint.setX(theX);
2027  thePoint.setY(theY);
2028 
2029  if(ruleMap[rule_opt[0]]!=rule::centroid&&!readPolygon.Contains(&thePoint))
2030  continue;
2031 
2032  bool valid=true;
2033 
2034  if(srcnodata_opt.size()){
2035  for(int vband=0;vband<bndnodata_opt.size();++vband){
2036  double value=((readValues[bndnodata_opt[vband]])[j-ulj])[i-uli];
2037  if(value==srcnodata_opt[vband]){
2038  valid=false;
2039  break;
2040  }
2041  }
2042  }
2043 
2044  if(!valid)
2045  continue;
2046  else
2047  validFeature=true;
2048 
2049  writeRing.addPoint(&thePoint);
2050  // if(writeRing.isPointOnRingBoundary(&thePoint))
2051  // writeRing.addPoint(&thePoint);
2052  if(verbose_opt[0]>1)
2053  std::cout << "point is on surface:" << thePoint.getX() << "," << thePoint.getY() << std::endl;
2054  ++nPointPolygon;
2055 
2056  if(polythreshold_opt.size())
2057  if(nPointPolygon>polythreshold_opt[0])
2058  continue;
2059  // throw(nPointPolygon);
2060  OGRFeature *writePointFeature;
2061  if(!polygon_opt[0]){
2062  //create feature
2063  if(ruleMap[rule_opt[0]]==rule::point){//do not create in case of mean, stdev, median or sum (only create point at centroid)
2064  if(writeTest)
2065  writePointFeature = OGRFeature::CreateFeature(writeTestLayer->GetLayerDefn());
2066  else
2067  writePointFeature = OGRFeature::CreateFeature(writeLayer->GetLayerDefn());
2068  if(verbose_opt[0]>1)
2069  std::cout << "copying fields from polygons " << std::endl;
2070  //test
2071  // writePointFeature->SetGeometry(&thePoint);
2072  if(writePointFeature->SetFrom(readFeature)!= OGRERR_NONE)
2073  cerr << "writing feature failed" << std::endl;
2074  //test
2075  writePointFeature->SetGeometry(&thePoint);
2076  assert(wkbFlatten(writePointFeature->GetGeometryRef()->getGeometryType()) == wkbPoint);
2077  // OGRGeometry *updateGeometry;
2078  // updateGeometry = writePointFeature->GetGeometryRef();
2079  // OGRPoint *poPoint = (OGRPoint *) updateGeometry;
2080  if(verbose_opt[0]>1)
2081  std::cout << "write feature has " << writePointFeature->GetFieldCount() << " fields" << std::endl;
2082  }
2083  }
2084  if(class_opt.size()){
2085  short value=((readValues[0])[j-ulj])[i-uli];
2086  for(int iclass=0;iclass<class_opt.size();++iclass){
2087  if(value==class_opt[iclass])
2088  polyClassValues[iclass]+=1;
2089  }
2090  }
2091  else{
2092  for(int iband=0;iband<nband;++iband){
2093  //test
2094  assert(j-ulj>=0);
2095  assert(j-ulj<readValues[iband].size());
2096  assert(i-uli>=0);
2097  assert(i-uli<((readValues[iband])[j-ulj]).size());
2098  double value=((readValues[iband])[j-ulj])[i-uli];
2099  // imgReader.readData(value,GDT_Float64,i,j,theBand);
2100  if(verbose_opt[0]>1)
2101  std::cout << ": " << value << std::endl;
2102  if(polygon_opt[0]||ruleMap[rule_opt[0]]!=rule::point)
2103  polyValues[iband].push_back(value);
2104  else{
2105  if(verbose_opt[0]>1)
2106  std::cout << "set field " << fieldname_opt[iband] << " to " << value << std::endl;
2107  switch( fieldType ){
2108  case OFTInteger:
2109  case OFTReal:
2110  writePointFeature->SetField(fieldname_opt[iband].c_str(),value);
2111  break;
2112  case OFTString:
2113  writePointFeature->SetField(fieldname_opt[iband].c_str(),type2string<double>(value).c_str());
2114  break;
2115  // case OFTRealList:{
2116  // int fieldIndex=writePointFeature->GetFieldIndex(fieldname_opt[iband].c_str());
2117  // int nCount;
2118  // const double *theList;
2119  // theList=writePointFeature->GetFieldAsDoubleList(fieldIndex,&nCount);
2120  // vector<double> vectorList(nCount+1);
2121  // for(int index=0;index<nCount;++index)
2122  // vectorList[nCount]=value;
2123  // writePointFeature->SetField(fieldIndex,vectorList.size(),&(vectorList[0]));
2124  // break;
2125  // }
2126  default://not supported
2127  assert(0);
2128  break;
2129  }
2130  }//else
2131  }//iband
2132  }//else (class_opt.size())
2133  if(!polygon_opt[0]){
2134  if(ruleMap[rule_opt[0]]==rule::point){//do not create in case of mean, stdev or median value (only at centroid)
2135  //write feature
2136  if(verbose_opt[0]>1)
2137  std::cout << "creating point feature" << std::endl;
2138  if(writeTest){
2139  if(writeTestLayer->CreateFeature( writePointFeature ) != OGRERR_NONE ){
2140  std::string errorString="Failed to create feature in ogr vector dataset";
2141  throw(errorString);
2142  }
2143  }
2144  else{
2145  if(writeLayer->CreateFeature( writePointFeature ) != OGRERR_NONE ){
2146  std::string errorString="Failed to create feature in ogr vector dataset";
2147  throw(errorString);
2148  }
2149  }
2150  //destroy feature
2151  OGRFeature::DestroyFeature( writePointFeature );
2152  }
2153  }
2154  // ++isample;
2155  ++ntotalvalid;
2156  if(verbose_opt[0])
2157  std::cout << "ntotalvalid: " << ntotalvalid << std::endl;
2158  }
2159  }
2160  if(!validFeature)
2161  continue;
2162  if(polygon_opt[0]||ruleMap[rule_opt[0]]!=rule::point){
2163  //do not create if no points found within polygon
2164  if(!nPointPolygon)
2165  continue;
2166  //add ring to polygon
2167  if(polygon_opt[0]){
2168  writePolygon.addRing(&writeRing);
2169  writePolygon.closeRings();
2170  //write geometry of writePolygon
2171  //test
2172  //writePolygon and readFeature are from geometry type wkbMultiPolygon
2173  // writePolygonFeature->SetGeometry(&writePolygon);
2174  if(writePolygonFeature->SetFrom(readFeature)!= OGRERR_NONE)
2175  cerr << "writing feature failed" << std::endl;
2176  assert(writePolygonFeature->GetGeometryRef()->getGeometryType()==wkbMultiPolygon);
2177  if(verbose_opt[0]>1)
2178  std::cout << "copying new fields write polygon " << std::endl;
2179  if(verbose_opt[0]>1)
2180  std::cout << "write feature has " << writePolygonFeature->GetFieldCount() << " fields" << std::endl;
2181  //write polygon feature
2182  }
2183  else{//write band information of polygon to centroid point
2184  //create feature
2185  if(verbose_opt[0]>1)
2186  std::cout << "copying fields from polygons " << std::endl;
2187  //test
2188  // writeCentroidFeature->SetGeometry(&writeCentroidPoint);
2189  if(writeCentroidFeature->SetFrom(readFeature)!= OGRERR_NONE)
2190  cerr << "writing feature failed" << std::endl;
2191  writeCentroidFeature->SetGeometry(&writeCentroidPoint);
2192  assert(wkbFlatten(writeCentroidFeature->GetGeometryRef()->getGeometryType()) == wkbPoint);
2193  //test
2194  // OGRGeometry *updateGeometry;
2195  // updateGeometry = writeCentroidFeature->GetGeometryRef();
2196  // assert(wkbFlatten(updateGeometry->getGeometryType()) == wkbPoint );
2197  if(verbose_opt[0]>1)
2198  std::cout << "write feature has " << writeCentroidFeature->GetFieldCount() << " fields" << std::endl;
2199  }
2200  if(class_opt.empty()){
2201  if(ruleMap[rule_opt[0]]==rule::point){//value at centroid of polygon
2202  if(verbose_opt[0])
2203  std::cout << "number of points in polygon: " << nPointPolygon << std::endl;
2204  for(int index=0;index<polyValues.size();++index){
2205  //test
2206  assert(polyValues[index].size()==1);
2207  double theValue=polyValues[index].back();
2208  if(verbose_opt[0])
2209  std::cout << "number of points in polygon: " << nPointPolygon << std::endl;
2210  int theBand=(band_opt.size()) ? band_opt[index] : index;
2211  try{
2212  if(verbose_opt[0]>1)
2213  std::cout << "set field " << fieldname_opt[index] << " to " << theValue << std::endl;
2214  switch( fieldType ){
2215  case OFTInteger:
2216  case OFTReal:
2217  if(polygon_opt[0])
2218  writePolygonFeature->SetField(fieldname_opt[index].c_str(),theValue);
2219  else
2220  writeCentroidFeature->SetField(fieldname_opt[index].c_str(),theValue);
2221  break;
2222  case OFTString:
2223  if(polygon_opt[0])
2224  writePolygonFeature->SetField(fieldname_opt[index].c_str(),type2string<double>(theValue).c_str());
2225  else
2226  writeCentroidFeature->SetField(fieldname_opt[index].c_str(),type2string<double>(theValue).c_str());
2227  break;
2228  default://not supported
2229  std::string errorString="field type not supported";
2230  throw(errorString);
2231  break;
2232  }
2233  }
2234  catch(std::string e){
2235  std::cout << e << std::endl;
2236  exit(1);
2237  }
2238  }
2239  }
2240  else{//ruleMap[rule_opt[0]] is not rule::point
2241  double theValue=0;
2242  for(int index=0;index<polyValues.size();++index){
2243  try{
2244  if(ruleMap[rule_opt[0]]==rule::mean)
2245  theValue=stat.mean(polyValues[index]);
2246  else if(ruleMap[rule_opt[0]]==rule::stdev)
2247  theValue=sqrt(stat.var(polyValues[index]));
2248  else if(ruleMap[rule_opt[0]]==rule::median)
2249  theValue=stat.median(polyValues[index]);
2250  else if(ruleMap[rule_opt[0]]==rule::percentile)
2251  theValue=stat.percentile(polyValues[index],polyValues[index].begin(),polyValues[index].end(),percentile_opt[0]);
2252  else if(ruleMap[rule_opt[0]]==rule::sum)
2253  theValue=stat.sum(polyValues[index]);
2254  else if(ruleMap[rule_opt[0]]==rule::max)
2255  theValue=stat.mymax(polyValues[index]);
2256  else if(ruleMap[rule_opt[0]]==rule::min)
2257  theValue=stat.mymin(polyValues[index]);
2258  else if(ruleMap[rule_opt[0]]==rule::centroid){
2259  if(verbose_opt[0])
2260  std::cout << "number of points in polygon: " << nPointPolygon << std::endl;
2261  assert(nPointPolygon<=1);
2262  assert(nPointPolygon==polyValues[index].size());
2263  theValue=polyValues[index].back();
2264  }
2265  else{
2266  std::string errorString="rule not supported";
2267  throw(errorString);
2268  }
2269  if(verbose_opt[0]>1)
2270  std::cout << "set field " << fieldname_opt[index] << " to " << theValue << std::endl;
2271  switch( fieldType ){
2272  case OFTInteger:
2273  case OFTReal:
2274  if(polygon_opt[0])
2275  writePolygonFeature->SetField(fieldname_opt[index].c_str(),theValue);
2276  else
2277  writeCentroidFeature->SetField(fieldname_opt[index].c_str(),theValue);
2278  break;
2279  case OFTString:
2280  if(polygon_opt[0])
2281  writePolygonFeature->SetField(fieldname_opt[index].c_str(),type2string<double>(theValue).c_str());
2282  else
2283  writeCentroidFeature->SetField(fieldname_opt[index].c_str(),type2string<double>(theValue).c_str());
2284  break;
2285  default://not supported
2286  std::string errorString="field type not supported";
2287  throw(errorString);
2288  break;
2289  }
2290  }
2291  catch(std::string e){
2292  std::cout << e << std::endl;
2293  exit(1);
2294  }
2295  }
2296  }
2297  }
2298  else{//class_opt is set
2299  if(ruleMap[rule_opt[0]]==rule::proportion){
2300  if(verbose_opt[0])
2301  std::cout << "number of points in polygon: " << nPointPolygon << std::endl;
2302  stat.normalize_pct(polyClassValues);
2303  for(int index=0;index<polyClassValues.size();++index){
2304  double theValue=polyClassValues[index];
2305  ostringstream fs;
2306  fs << class_opt[index];
2307  if(polygon_opt[0])
2308  writePolygonFeature->SetField(fs.str().c_str(),static_cast<int>(theValue));
2309  else
2310  writeCentroidFeature->SetField(fs.str().c_str(),static_cast<int>(theValue));
2311  }
2312  }
2313  else if(ruleMap[rule_opt[0]]==rule::custom){
2314  assert(polygon_opt[0]);//not implemented for points
2315  if(verbose_opt[0])
2316  std::cout << "number of points in polygon: " << nPointPolygon << std::endl;
2317  stat.normalize_pct(polyClassValues);
2318  assert(polyClassValues.size()==2);//11:broadleaved, 12:coniferous
2319  if(polyClassValues[0]>=75)//broadleaved
2320  writePolygonFeature->SetField(label_opt[0].c_str(),static_cast<int>(11));
2321  else if(polyClassValues[1]>=75)//coniferous
2322  writePolygonFeature->SetField(label_opt[0].c_str(),static_cast<int>(12));
2323  else if(polyClassValues[0]>25&&polyClassValues[1]>25)//mixed
2324  writePolygonFeature->SetField(label_opt[0].c_str(),static_cast<int>(13));
2325  else{
2326  if(verbose_opt[0]){
2327  std::cout << "No valid value in polyClassValues..." << std::endl;
2328  for(int index=0;index<polyClassValues.size();++index){
2329  double theValue=polyClassValues[index];
2330  std::cout << theValue << " ";
2331  }
2332  std::cout << std::endl;
2333  }
2334  writePolygonFeature->SetField(label_opt[0].c_str(),static_cast<int>(20));
2335  }
2336  }
2337  else if(ruleMap[rule_opt[0]]==rule::mode){
2338  //maximum votes in polygon
2339  if(verbose_opt[0])
2340  std::cout << "number of points in polygon: " << nPointPolygon << std::endl;
2341  //search for class with maximum votes
2342  int maxClass=stat.mymin(class_opt);
2343  vector<double>::iterator maxit;
2344  maxit=stat.mymax(polyClassValues,polyClassValues.begin(),polyClassValues.end());
2345  int maxIndex=distance(polyClassValues.begin(),maxit);
2346  maxClass=class_opt[maxIndex];
2347  if(verbose_opt[0]>0)
2348  std::cout << "maxClass: " << maxClass << std::endl;
2349  if(polygon_opt[0])
2350  writePolygonFeature->SetField(label_opt[0].c_str(),maxClass);
2351  else
2352  writeCentroidFeature->SetField(label_opt[0].c_str(),maxClass);
2353  }
2354  }
2355 
2356  if(polygon_opt[0]){
2357  if(verbose_opt[0]>1)
2358  std::cout << "creating polygon feature" << std::endl;
2359  if(writeTest){
2360  if(writeTestLayer->CreateFeature( writePolygonFeature ) != OGRERR_NONE ){
2361  std::string errorString="Failed to create polygon feature in ogr vector dataset";
2362  throw(errorString);
2363  }
2364  }
2365  else{
2366  if(writeLayer->CreateFeature( writePolygonFeature ) != OGRERR_NONE ){
2367  std::string errorString="Failed to create polygon feature in ogr vector dataset";
2368  throw(errorString);
2369  }
2370  }
2371  OGRFeature::DestroyFeature( writePolygonFeature );
2372  ++ntotalvalid;
2373  if(verbose_opt[0])
2374  std::cout << "ntotalvalid: " << ntotalvalid << std::endl;
2375  }
2376  else{
2377  if(verbose_opt[0]>1)
2378  std::cout << "creating point feature in centroid" << std::endl;
2379  if(writeTest){
2380  if(writeTestLayer->CreateFeature( writeCentroidFeature ) != OGRERR_NONE ){
2381  std::string errorString="Failed to create point feature in ogr vector dataset";
2382  throw(errorString);
2383  }
2384  }
2385  else{
2386  //test
2387  assert(validFeature);
2388  if(writeLayer->CreateFeature( writeCentroidFeature ) != OGRERR_NONE ){
2389  std::string errorString="Failed to create point feature in ogr vector dataset";
2390  throw(errorString);
2391  }
2392  }
2393  OGRFeature::DestroyFeature( writeCentroidFeature );
2394  ++ntotalvalid;
2395  if(verbose_opt[0])
2396  std::cout << "ntotalvalid: " << ntotalvalid << std::endl;
2397  }
2398  }
2399  }
2400  else{
2401  std::string test;
2402  test=poGeometry->getGeometryName();
2403  ostringstream oss;
2404  oss << "geometry " << test << " not supported";
2405  throw(oss.str());
2406  }
2407  ++ifeature;
2408  progress=static_cast<float>(ifeature+1)/nfeature;
2409  pfnProgress(progress,pszMessage,pProgressArg);
2410  }
2411  catch(std::string e){
2412  std::cout << e << std::endl;
2413  continue;
2414  }
2415  catch(int npoint){
2416  if(verbose_opt[0])
2417  std::cout << "number of points read in polygon: " << npoint << std::endl;
2418  continue;
2419  }
2420  }//end of getNextFeature
2421  // if(rbox_opt[0]>0||cbox_opt[0]>0)
2422  // boxWriter.close();
2423  progress=1.0;
2424  pfnProgress(progress,pszMessage,pProgressArg);
2425  ++ilayerWrite;
2426  }//for ilayer
2427  ogrWriter.close();
2428  if(test_opt.size())
2429  ogrTestWriter.close();
2430  }//else (vector)
2431  progress=1.0;
2432  pfnProgress(progress,pszMessage,pProgressArg);
2433  imgReader.close();
2434 }
2435