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