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