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