pktools  2.6.5
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  if(verbose_opt[0])
902  std::cout << "number of layers: " << nlayerRead << endl;
903 
904  for(int ilayer=0;ilayer<nlayerRead;++ilayer){
905  OGRLayer *readLayer=sampleReaderOgr.getLayer(ilayer);
906  string currentLayername=readLayer->GetName();
907  if(layer_opt.size())
908  if(find(layer_opt.begin(),layer_opt.end(),currentLayername)==layer_opt.end())
909  continue;
910  cout << "processing layer " << currentLayername << endl;
911 
912  readLayer->ResetReading();
913  OGRLayer *writeLayer;
914  OGRLayer *writeTestLayer;
915 
916  if(polygon_opt[0]){
917  if(verbose_opt[0])
918  std::cout << "create polygons" << std::endl;
919  char **papszOptions=NULL;
920  writeLayer=ogrWriter.createLayer(readLayer->GetName(), imgReader.getProjection(), wkbPolygon, papszOptions);
921  if(test_opt.size())
922  writeTestLayer=ogrTestWriter.createLayer(readLayer->GetName(), imgReader.getProjection(), wkbPolygon, papszOptions);
923  }
924  else{
925  if(verbose_opt[0])
926  std::cout << "create points in layer " << readLayer->GetName() << std::endl;
927  char **papszOptions=NULL;
928 
929  writeLayer=ogrWriter.createLayer(readLayer->GetName(), imgReader.getProjection(), wkbPoint, papszOptions);
930  if(test_opt.size()){
931  char **papszOptions=NULL;
932  writeTestLayer=ogrTestWriter.createLayer(readLayer->GetName(), imgReader.getProjection(), wkbPoint, papszOptions);
933  }
934  }
935  if(verbose_opt[0])
936  std::cout << "copy fields from layer " << ilayer << std::flush << std::endl;
937  ogrWriter.copyFields(sampleReaderOgr,ilayer,ilayerWrite);
938 
939  if(test_opt.size()){
940  if(verbose_opt[0])
941  std::cout << "copy fields test writer" << std::flush << std::endl;
942  ogrTestWriter.copyFields(sampleReaderOgr,ilayer,ilayerWrite);
943  }
944  // vector<std::string> fieldnames;
945  // if(verbose_opt[0])
946  // std::cout << "get fields" << std::flush << std::endl;
947  // sampleReaderOgr.getFields(fieldnames);
948  // assert(fieldnames.size()==ogrWriter.getFieldCount(ilayerWrite));
949  // map<std::string,double> pointAttributes;
950 
951  if(class_opt.size()){
952  switch(ruleMap[rule_opt[0]]){
953  case(rule::proportion)://proportion for each class
954  case(rule::count):{//count for each class
955  for(int iclass=0;iclass<class_opt.size();++iclass){
956  ostringstream cs;
957  cs << class_opt[iclass];
958  ogrWriter.createField(cs.str(),fieldType,ilayerWrite);
959  }
960  break;
961  }
962  case(rule::custom):
963  case(rule::mode):
964  ogrWriter.createField(label_opt[0],fieldType,ilayerWrite);
965  if(test_opt.size())
966  ogrTestWriter.createField(label_opt[0],fieldType,ilayerWrite);
967  break;
968  }
969  }
970  else{
971  for(int iband=0;iband<nband;++iband){
972  int theBand=(band_opt.size()) ? band_opt[iband] : iband;
973  ostringstream fs;
974  fs << fieldname_opt[iband];
975  if(verbose_opt[0]>1)
976  std::cout << "creating field " << fs.str() << std::endl;
977 
978  ogrWriter.createField(fs.str(),fieldType,ilayerWrite);
979  if(test_opt.size())
980  ogrTestWriter.createField(fs.str(),fieldType,ilayerWrite);
981  }
982  }
983  OGRFeature *readFeature;
984  unsigned long int ifeature=0;
985  unsigned long int nfeature=sampleReaderOgr.getFeatureCount();
986  progress=0;
987  pfnProgress(progress,pszMessage,pProgressArg);
988  while( (readFeature = readLayer->GetNextFeature()) != NULL ){
989  bool validFeature=false;
990  bool writeTest=false;//write this feature to test_opt[0] instead of output_opt
991  if(verbose_opt[0]>0)
992  std::cout << "reading feature " << readFeature->GetFID() << std::endl;
993  if(threshold_opt[0]>0){//percentual value
994  double p=static_cast<double>(rand())/(RAND_MAX);
995  p*=100.0;
996  if(p>threshold_opt[0]){
997  if(test_opt.size())
998  writeTest=true;
999  else
1000  continue;//do not select for now, go to next feature
1001  }
1002  }
1003  else{//absolute value
1004  if(ntotalvalid>=-threshold_opt[0]){
1005  if(test_opt.size())
1006  writeTest=true;
1007  else
1008  continue;//do not select any more pixels, go to next column feature
1009  }
1010  }
1011  if(verbose_opt[0]>0)
1012  std::cout << "processing feature " << readFeature->GetFID() << std::endl;
1013  //get x and y from readFeature
1014  double x,y;
1015  OGRGeometry *poGeometry;
1016  poGeometry = readFeature->GetGeometryRef();
1017  assert(poGeometry!=NULL);
1018  try{
1019  if(wkbFlatten(poGeometry->getGeometryType()) == wkbPoint ){
1020 
1021  if(!buffer_opt.size()){
1022  switch(ruleMap[rule_opt[0]]){
1023  case(rule::point):
1024  case(rule::centroid):
1025  buffer_opt.push_back(1);//default
1026  break;
1027  default:
1028  buffer_opt.push_back(3);//default
1029  }
1030  }
1031 
1032  if(verbose_opt[0]>1)
1033  std::cout << "boundary: " << buffer_opt[0] << std::endl;
1034 
1035  OGRPolygon writePolygon;
1036  OGRLinearRing writeRing;
1037  OGRPoint writeCentroidPoint;
1038  OGRFeature *writePolygonFeature;
1039  OGRFeature *writeCentroidFeature;
1040 
1041  OGRPoint *poPoint = (OGRPoint *) poGeometry;
1042  writeCentroidPoint=*poPoint;
1043 
1044  x=poPoint->getX();
1045  y=poPoint->getY();
1046 
1047  double i_centre,j_centre;
1048  if(geo_opt[0])
1049  imgReader.geo2image(x,y,i_centre,j_centre);
1050  else{
1051  i_centre=x;
1052  j_centre=y;
1053  }
1054  //nearest neighbour
1055  j_centre=static_cast<int>(j_centre);
1056  i_centre=static_cast<int>(i_centre);
1057 
1058  double uli=i_centre-buffer_opt[0]/2;
1059  double ulj=j_centre-buffer_opt[0]/2;
1060  double lri=i_centre+buffer_opt[0]/2;
1061  double lrj=j_centre+buffer_opt[0]/2;
1062 
1063  //nearest neighbour
1064  ulj=static_cast<int>(ulj);
1065  uli=static_cast<int>(uli);
1066  lrj=static_cast<int>(lrj);
1067  lri=static_cast<int>(lri);
1068 
1069  // if((polygon_opt[0]&&ruleMap[rule_opt[0]]==rule::point)||(ruleMap[rule_opt[0]]==rule::centroid)){
1070  // uli=i_centre;
1071  // ulj=j_centre;
1072  // lri=i_centre;
1073  // lrj=j_centre;
1074  // }
1075 
1076  //check if j is out of bounds
1077  if(static_cast<int>(ulj)<0||static_cast<int>(ulj)>=imgReader.nrOfRow())
1078  continue;
1079  //check if j is out of bounds
1080  if(static_cast<int>(uli)<0||static_cast<int>(lri)>=imgReader.nrOfCol())
1081  continue;
1082 
1083  OGRPoint ulPoint,urPoint,llPoint,lrPoint;
1084  double ulx,uly;
1085  double urx,ury;
1086 
1087  if(polygon_opt[0]){
1088  if(disc_opt[0]){
1089  double gt[6];// { 444720, 30, 0, 3751320, 0, -30 };
1090  double radius=buffer_opt[0]/2.0*sqrt(imgReader.getDeltaX()*imgReader.getDeltaY());
1091  unsigned short nstep = 25;
1092  for(int i=0;i<nstep;++i){
1093  OGRPoint aPoint;
1094  aPoint.setX(x+imgReader.getDeltaX()/2.0+radius*cos(2*PI*i/nstep));
1095  aPoint.setY(y-imgReader.getDeltaY()/2.0+radius*sin(2*PI*i/nstep));
1096  writeRing.addPoint(&aPoint);
1097  }
1098  writePolygon.addRing(&writeRing);
1099  writePolygon.closeRings();
1100  }
1101  else{
1102  double llx,lly;
1103  double lrx,lry;
1104  imgReader.image2geo(uli,ulj,ulx,uly);
1105  imgReader.image2geo(lri,lrj,lrx,lry);
1106  ulPoint.setX(ulx-imgReader.getDeltaX()/2.0);
1107  ulPoint.setY(uly+imgReader.getDeltaY()/2.0);
1108  lrPoint.setX(lrx+imgReader.getDeltaX()/2.0);
1109  lrPoint.setY(lry-imgReader.getDeltaY()/2.0);
1110  urPoint.setX(lrx+imgReader.getDeltaX()/2.0);
1111  urPoint.setY(uly+imgReader.getDeltaY()/2.0);
1112  llPoint.setX(ulx-imgReader.getDeltaX()/2.0);
1113  llPoint.setY(lry-imgReader.getDeltaY()/2.0);
1114 
1115  writeRing.addPoint(&ulPoint);
1116  writeRing.addPoint(&urPoint);
1117  writeRing.addPoint(&lrPoint);
1118  writeRing.addPoint(&llPoint);
1119  writePolygon.addRing(&writeRing);
1120  writePolygon.closeRings();
1121  }
1122  }
1123 
1124  if((polygon_opt[0]&&ruleMap[rule_opt[0]]==rule::point)||(ruleMap[rule_opt[0]]==rule::centroid)){
1125  uli=i_centre;
1126  ulj=j_centre;
1127  lri=i_centre;
1128  lrj=j_centre;
1129  }
1130 
1131  int nPointWindow=0;//similar to nPointPolygon for polygons
1132  if(polygon_opt[0]){
1133  if(writeTest)
1134  writePolygonFeature = OGRFeature::CreateFeature(writeTestLayer->GetLayerDefn());
1135  else
1136  writePolygonFeature = OGRFeature::CreateFeature(writeLayer->GetLayerDefn());
1137  }
1138  else if(ruleMap[rule_opt[0]]!=rule::point){
1139  if(writeTest)
1140  writeCentroidFeature = OGRFeature::CreateFeature(writeTestLayer->GetLayerDefn());
1141  else
1142  writeCentroidFeature = OGRFeature::CreateFeature(writeLayer->GetLayerDefn());
1143  }
1144  Vector2d<double> windowValues;
1145  vector<double> windowClassValues;
1146 
1147  if(class_opt.size()){
1148  windowClassValues.resize(class_opt.size());
1149  //initialize
1150  for(int iclass=0;iclass<class_opt.size();++iclass)
1151  windowClassValues[iclass]=0;
1152  }
1153  else
1154  windowValues.resize(nband);
1155  vector< Vector2d<double> > readValues(nband);
1156  for(int iband=0;iband<nband;++iband){
1157  int theBand=(band_opt.size()) ? band_opt[iband] : iband;
1158  imgReader.readDataBlock(readValues[iband],GDT_Float64,uli,lri,ulj,lrj,theBand);
1159  }
1160 
1161  OGRPoint thePoint;
1162  for(int j=ulj;j<=lrj;++j){
1163  for(int i=uli;i<=lri;++i){
1164  //check if within raster image
1165  if(i<0||i>=imgReader.nrOfCol())
1166  continue;
1167  if(j<0||j>=imgReader.nrOfRow())
1168  continue;
1169  //no need to check if point is on surface
1170  double theX=0;
1171  double theY=0;
1172  imgReader.image2geo(i,j,theX,theY);
1173  thePoint.setX(theX);
1174  thePoint.setY(theY);
1175 
1176  if(disc_opt[0]&&buffer_opt[0]>1){
1177  double radius=buffer_opt[0]/2.0*sqrt(imgReader.getDeltaX()*imgReader.getDeltaY());
1178  if((theX-x)*(theX-x)+(theY-y)*(theY-y)>radius*radius)
1179  continue;
1180  }
1181  bool valid=true;
1182 
1183  if(srcnodata_opt.size()){
1184  for(int vband=0;vband<bndnodata_opt.size();++vband){
1185  double value=((readValues[bndnodata_opt[vband]])[j-ulj])[i-uli];
1186  if(value==srcnodata_opt[vband]){
1187  valid=false;
1188  break;
1189  }
1190  }
1191  }
1192 
1193  if(!valid)
1194  continue;
1195  else
1196  validFeature=true;
1197 
1198  // writeRing.addPoint(&thePoint);//already done
1199 
1200  ++nPointWindow;
1201  OGRFeature *writePointFeature;
1202  if(!polygon_opt[0]){
1203  //create feature
1204  if(ruleMap[rule_opt[0]]==rule::point){//do not create in case of mean, stdev, median, sum or centroid (only create point at centroid)
1205  if(writeTest)
1206  writePointFeature = OGRFeature::CreateFeature(writeTestLayer->GetLayerDefn());
1207  else
1208  writePointFeature = OGRFeature::CreateFeature(writeLayer->GetLayerDefn());
1209  if(verbose_opt[0]>1)
1210  std::cout << "copying fields from polygons " << std::endl;
1211  //Geometry of readFeature and writePointFeature are both wkbPoint
1212  //attributes AND geometry are copied with SetFrom
1213  //test
1214  // writePointFeature->SetGeometry(&thePoint);
1215  if(writePointFeature->SetFrom(readFeature)!= OGRERR_NONE)
1216  cerr << "writing feature failed" << std::endl;
1217 
1218  assert(wkbFlatten(writePointFeature->GetGeometryRef()->getGeometryType()) == wkbPoint);
1219  // OGRGeometry *updateGeometry;
1220  // updateGeometry = writePointFeature->GetGeometryRef();
1221  // OGRPoint *poPoint = (OGRPoint *) updateGeometry;
1222  if(verbose_opt[0]>1)
1223  std::cout << "write feature has " << writePointFeature->GetFieldCount() << " fields" << std::endl;
1224  }
1225  }
1226  if(class_opt.size()){
1227  short value=((readValues[0])[j-ulj])[i-uli];
1228  for(int iclass=0;iclass<class_opt.size();++iclass){
1229  if(value==class_opt[iclass])
1230  windowClassValues[iclass]+=1;
1231  }
1232  }
1233  else{
1234  for(int iband=0;iband<nband;++iband){
1235  int theBand=(band_opt.size()) ? band_opt[iband] : iband;
1236  assert(j-ulj>=0);
1237  assert(j-ulj<readValues[iband].size());
1238  assert(i-uli>=0);
1239  assert(i-uli<((readValues[iband])[j-ulj]).size());
1240  double value=((readValues[iband])[j-ulj])[i-uli];
1241  // imgReader.readData(value,GDT_Float64,i,j,theBand);
1242  if(verbose_opt[0]>1)
1243  std::cout << ": " << value << std::endl;
1244  if(polygon_opt[0]||ruleMap[rule_opt[0]]!=rule::point){
1245  windowValues[iband].push_back(value);
1246  }
1247  else{
1248  try{
1249  if(verbose_opt[0]>1)
1250  std::cout << "set field " << fieldname_opt[iband] << " to " << value << std::endl;
1251  switch( fieldType ){
1252  case OFTInteger:
1253  case OFTReal:
1254  writePointFeature->SetField(fieldname_opt[iband].c_str(),value);
1255  break;
1256  case OFTString:
1257  writePointFeature->SetField(fieldname_opt[iband].c_str(),type2string<double>(value).c_str());
1258  break;
1259  default://not supported
1260  std::string errorString="field type not supported";
1261  throw(errorString);
1262  break;
1263  }
1264  }
1265  catch(std::string e){
1266  std::cout << e << std::endl;
1267  exit(1);
1268  }
1269  }//else
1270  }//iband
1271  }//else (class_opt.size())
1272  if(!polygon_opt[0]){
1273  if(ruleMap[rule_opt[0]]==rule::point){//do not create in case of mean or median value (only at centroid)
1274  //write feature
1275  if(verbose_opt[0]>1)
1276  std::cout << "creating point feature" << std::endl;
1277  if(writeTest){
1278  if(writeTestLayer->CreateFeature( writePointFeature ) != OGRERR_NONE ){
1279  std::string errorString="Failed to create feature in test ogr vector dataset";
1280  throw(errorString);
1281  }
1282  }
1283  else{
1284  if(writeLayer->CreateFeature( writePointFeature ) != OGRERR_NONE ){
1285  std::string errorString="Failed to create feature in ogr vector dataset";
1286  throw(errorString);
1287  }
1288  }
1289  //destroy feature
1290  OGRFeature::DestroyFeature( writePointFeature );
1291  ++ntotalvalid;
1292  if(verbose_opt[0])
1293  std::cout << "ntotalvalid(2): " << ntotalvalid << std::endl;
1294  }
1295  }
1296  }
1297  }
1298  if(polygon_opt[0]||ruleMap[rule_opt[0]]!=rule::point){
1299  //do not create if no points found within polygon
1300  if(!nPointWindow){
1301  if(verbose_opt[0])
1302  cout << "no points found in window, continuing" << endl;
1303  continue;
1304  }
1305  //add ring to polygon
1306  if(polygon_opt[0]){
1307  // writePolygon.addRing(&writeRing);//already done
1308  // writePolygon.closeRings();//already done
1309  //write geometry of writePolygon
1310  //test
1311  // writePolygonFeature->SetGeometry(&writePolygon);
1312  if(writePolygonFeature->SetFrom(readFeature)!= OGRERR_NONE)
1313  cerr << "writing feature failed" << std::endl;
1314  //test
1315  writePolygonFeature->SetGeometry(&writePolygon);
1316  assert(wkbFlatten(writePolygonFeature->GetGeometryRef()->getGeometryType()) == wkbPolygon);
1317 
1318  if(verbose_opt[0]>1)
1319  std::cout << "copying new fields write polygon " << std::endl;
1320  if(verbose_opt[0]>1)
1321  std::cout << "write feature has " << writePolygonFeature->GetFieldCount() << " fields" << std::endl;
1322  //write polygon feature
1323  }
1324  else{//write value of polygon to centroid point
1325  //create feature
1326  if(verbose_opt[0]>1)
1327  std::cout << "copying fields from polygons " << std::endl;
1328  //test
1329  //Geometry of readFeature and writeCentroidFeature are both wkbPoint
1330  //attributes AND geometry are copied with SetFrom
1331  // writeCentroidFeature->SetGeometry(&writeCentroidPoint);
1332  if(writeCentroidFeature->SetFrom(readFeature)!= OGRERR_NONE)
1333  cerr << "writing feature failed" << std::endl;
1334  assert(wkbFlatten(writeCentroidFeature->GetGeometryRef()->getGeometryType()) == wkbPoint);
1335  //test
1336  // OGRGeometry *updateGeometry;
1337  // updateGeometry = writeCentroidFeature->GetGeometryRef();
1338  // assert(wkbFlatten(updateGeometry->getGeometryType()) == wkbPoint );
1339  if(verbose_opt[0]>1)
1340  std::cout << "write feature has " << writeCentroidFeature->GetFieldCount() << " fields" << std::endl;
1341  }
1342  if(class_opt.empty()){
1343  if(ruleMap[rule_opt[0]]==rule::point){//value at centroid of polygon
1344  if(verbose_opt[0])
1345  std::cout << "number of points in window: " << nPointWindow << std::endl;
1346  for(int index=0;index<windowValues.size();++index){
1347  //test
1348  if(windowValues[index].size()!=1){
1349  cerr << "Error: windowValues[index].size()=" << windowValues[index].size() << endl;
1350  assert(windowValues[index].size()==1);
1351  }
1352  double theValue=windowValues[index].back();
1353 
1354  if(verbose_opt[0])
1355  std::cout << "number of points in window: " << nPointWindow << std::endl;
1356  int theBand=(band_opt.size()) ? band_opt[index] : index;
1357 
1358  try{
1359  if(verbose_opt[0]>1)
1360  std::cout << "set field " << fieldname_opt[index] << " to " << theValue << std::endl;
1361  switch( fieldType ){
1362  case OFTInteger:
1363  case OFTReal:
1364  if(polygon_opt[0])
1365  writePolygonFeature->SetField(fieldname_opt[index].c_str(),theValue);
1366  else
1367  writeCentroidFeature->SetField(fieldname_opt[index].c_str(),theValue);
1368  break;
1369  case OFTString:
1370  if(polygon_opt[0])
1371  writePolygonFeature->SetField(fieldname_opt[index].c_str(),type2string<double>(theValue).c_str());
1372  else
1373  writeCentroidFeature->SetField(fieldname_opt[index].c_str(),type2string<double>(theValue).c_str());
1374  break;
1375  default://not supported
1376  std::string errorString="field type not supported";
1377  throw(errorString);
1378  break;
1379  }
1380  }
1381  catch(std::string e){
1382  std::cout << e << std::endl;
1383  exit(1);
1384  }
1385  }
1386  }
1387  else{//ruleMap[rule_opt[0]] is not rule::point
1388  double theValue=0;
1389  for(int index=0;index<windowValues.size();++index){
1390  try{
1391  if(ruleMap[rule_opt[0]]==rule::mean)
1392  theValue=stat.mean(windowValues[index]);
1393  else if(ruleMap[rule_opt[0]]==rule::stdev)
1394  theValue=sqrt(stat.var(windowValues[index]));
1395  else if(ruleMap[rule_opt[0]]==rule::median)
1396  theValue=stat.median(windowValues[index]);
1397  else if(ruleMap[rule_opt[0]]==rule::percentile)
1398  theValue=stat.percentile(windowValues[index],windowValues[index].begin(),windowValues[index].end(),percentile_opt[0]);
1399  else if(ruleMap[rule_opt[0]]==rule::sum)
1400  theValue=stat.sum(windowValues[index]);
1401  else if(ruleMap[rule_opt[0]]==rule::max)
1402  theValue=stat.mymax(windowValues[index]);
1403  else if(ruleMap[rule_opt[0]]==rule::min)
1404  theValue=stat.mymin(windowValues[index]);
1405  else if(ruleMap[rule_opt[0]]==rule::centroid){
1406  if(verbose_opt[0])
1407  std::cout << "number of points in polygon: " << nPointWindow << std::endl;
1408  assert(nPointWindow<=1);
1409  assert(nPointWindow==windowValues[index].size());
1410  theValue=windowValues[index].back();
1411  }
1412  else{
1413  std::string errorString="rule not supported";
1414  throw(errorString);
1415  }
1416  if(verbose_opt[0]>1)
1417  std::cout << "set field " << fieldname_opt[index] << " to " << theValue << std::endl;
1418  switch( fieldType ){
1419  case OFTInteger:
1420  case OFTReal:
1421  if(polygon_opt[0])
1422  writePolygonFeature->SetField(fieldname_opt[index].c_str(),theValue);
1423  else
1424  writeCentroidFeature->SetField(fieldname_opt[index].c_str(),theValue);
1425  break;
1426  case OFTString:
1427  if(polygon_opt[0])
1428  writePolygonFeature->SetField(fieldname_opt[index].c_str(),type2string<double>(theValue).c_str());
1429  else
1430  writeCentroidFeature->SetField(fieldname_opt[index].c_str(),type2string<double>(theValue).c_str());
1431  break;
1432  default://not supported
1433  std::string errorString="field type not supported";
1434  throw(errorString);
1435  break;
1436  }
1437  }
1438  catch(std::string e){
1439  std::cout << e << std::endl;
1440  exit(1);
1441  }
1442  }
1443  }
1444  }
1445  else{//class_opt is set
1446  if(ruleMap[rule_opt[0]]==rule::proportion||ruleMap[rule_opt[0]]==rule::count){
1447  if(verbose_opt[0])
1448  std::cout << "number of points in polygon: " << nPointWindow << std::endl;
1449  if(ruleMap[rule_opt[0]]==rule::proportion)
1450  stat.normalize_pct(windowClassValues);
1451  for(int index=0;index<windowClassValues.size();++index){
1452  double theValue=windowClassValues[index];
1453  ostringstream fs;
1454  fs << class_opt[index];
1455  if(polygon_opt[0])
1456  writePolygonFeature->SetField(fs.str().c_str(),static_cast<int>(theValue));
1457  else
1458  writeCentroidFeature->SetField(fs.str().c_str(),static_cast<int>(theValue));
1459  }
1460  }
1461  else if(ruleMap[rule_opt[0]]==rule::custom){
1462  assert(polygon_opt[0]);//not implemented for points
1463  if(verbose_opt[0])
1464  std::cout << "number of points in polygon: " << nPointWindow << std::endl;
1465  stat.normalize_pct(windowClassValues);
1466  assert(windowClassValues.size()==2);//11:broadleaved, 12:coniferous
1467  if(windowClassValues[0]>=75)//broadleaved
1468  writePolygonFeature->SetField(label_opt[0].c_str(),static_cast<int>(11));
1469  else if(windowClassValues[1]>=75)//coniferous
1470  writePolygonFeature->SetField(label_opt[0].c_str(),static_cast<int>(12));
1471  else if(windowClassValues[0]>25&&windowClassValues[1]>25)//mixed
1472  writePolygonFeature->SetField(label_opt[0].c_str(),static_cast<int>(13));
1473  else{
1474  if(verbose_opt[0]){
1475  std::cout << "No valid value in windowClassValues..." << std::endl;
1476  for(int index=0;index<windowClassValues.size();++index){
1477  double theValue=windowClassValues[index];
1478  std::cout << theValue << " ";
1479  }
1480  std::cout << std::endl;
1481  }
1482  writePolygonFeature->SetField(label_opt[0].c_str(),static_cast<int>(20));
1483  }
1484  }
1485  else if(ruleMap[rule_opt[0]]==rule::mode){
1486  //maximum votes in polygon
1487  if(verbose_opt[0])
1488  std::cout << "number of points in window: " << nPointWindow << std::endl;
1489  //search for class with maximum votes
1490  int maxClass=stat.mymin(class_opt);
1491  vector<double>::iterator maxit;
1492  maxit=stat.mymax(windowClassValues,windowClassValues.begin(),windowClassValues.end());
1493  int maxIndex=distance(windowClassValues.begin(),maxit);
1494  maxClass=class_opt[maxIndex];
1495  if(verbose_opt[0]>0)
1496  std::cout << "maxClass: " << maxClass << std::endl;
1497  if(polygon_opt[0])
1498  writePolygonFeature->SetField(label_opt[0].c_str(),maxClass);
1499  else
1500  writeCentroidFeature->SetField(label_opt[0].c_str(),maxClass);
1501  }
1502  }
1503  if(polygon_opt[0]){
1504  if(verbose_opt[0]>1)
1505  std::cout << "creating polygon feature" << std::endl;
1506  if(writeTest){
1507  if(writeTestLayer->CreateFeature( writePolygonFeature ) != OGRERR_NONE ){
1508  std::string errorString="Failed to create polygon feature in ogr vector dataset";
1509  throw(errorString);
1510  }
1511  }
1512  else{
1513  if(writeLayer->CreateFeature( writePolygonFeature ) != OGRERR_NONE ){
1514  std::string errorString="Failed to create polygon feature in ogr vector dataset";
1515  throw(errorString);
1516  }
1517  }
1518  OGRFeature::DestroyFeature( writePolygonFeature );
1519  ++ntotalvalid;
1520  if(verbose_opt[0])
1521  std::cout << "ntotalvalid(1): " << ntotalvalid << std::endl;
1522  }
1523  else{
1524  if(verbose_opt[0]>1)
1525  std::cout << "creating point feature in centroid" << std::endl;
1526  if(writeTest){
1527  if(writeTestLayer->CreateFeature( writeCentroidFeature ) != OGRERR_NONE ){
1528  std::string errorString="Failed to create point feature in ogr vector dataset";
1529  throw(errorString);
1530  }
1531  }
1532  else{
1533  //test
1534  assert(validFeature);
1535  if(writeLayer->CreateFeature( writeCentroidFeature ) != OGRERR_NONE ){
1536  std::string errorString="Failed to create point feature in ogr vector dataset";
1537  throw(errorString);
1538  }
1539  }
1540  OGRFeature::DestroyFeature( writeCentroidFeature );
1541  ++ntotalvalid;
1542  if(verbose_opt[0])
1543  std::cout << "ntotalvalid: " << ntotalvalid << std::endl;
1544  }
1545  }
1546  }//if wkbPoint
1547  else if(wkbFlatten(poGeometry->getGeometryType()) == wkbPolygon){
1548 
1549  OGRPolygon readPolygon = *((OGRPolygon *) poGeometry);
1550  OGRPolygon writePolygon;
1551  OGRLinearRing writeRing;
1552  OGRPoint writeCentroidPoint;
1553  OGRFeature *writePolygonFeature;
1554  OGRFeature *writeCentroidFeature;
1555 
1556  readPolygon.closeRings();
1557 
1558  if(verbose_opt[0]>1)
1559  std::cout << "get point on polygon" << std::endl;
1560  if(ruleMap[rule_opt[0]]==rule::centroid)
1561  readPolygon.Centroid(&writeCentroidPoint);
1562  else if(readPolygon.PointOnSurface(&writeCentroidPoint)!=OGRERR_NONE){
1563  // cerr << "function PointOnSurface failed, trying centroid instead" << endl;
1564  readPolygon.Centroid(&writeCentroidPoint);
1565  }
1566  double ulx,uly,lrx,lry;
1567  double uli,ulj,lri,lrj;
1568  if((polygon_opt[0]&&ruleMap[rule_opt[0]]==rule::point)||(ruleMap[rule_opt[0]]==rule::centroid)){
1569  ulx=writeCentroidPoint.getX();
1570  uly=writeCentroidPoint.getY();
1571  lrx=ulx;
1572  lry=uly;
1573  }
1574  else{
1575  //get envelope
1576  if(verbose_opt[0])
1577  std::cout << "reading envelope for polygon " << ifeature << std::endl;
1578  OGREnvelope* psEnvelope=new OGREnvelope();
1579  readPolygon.getEnvelope(psEnvelope);
1580  ulx=psEnvelope->MinX;
1581  uly=psEnvelope->MaxY;
1582  lrx=psEnvelope->MaxX;
1583  lry=psEnvelope->MinY;
1584  delete psEnvelope;
1585  }
1586  if(geo_opt[0]){
1587  imgReader.geo2image(ulx,uly,uli,ulj);
1588  imgReader.geo2image(lrx,lry,lri,lrj);
1589  }
1590  else{
1591  uli=ulx;
1592  ulj=uly;
1593  lri=lrx;
1594  lrj=lry;
1595  }
1596  //nearest neighbour
1597  ulj=static_cast<int>(ulj);
1598  uli=static_cast<int>(uli);
1599  lrj=static_cast<int>(lrj);
1600  lri=static_cast<int>(lri);
1601  //iterate through all pixels
1602  if(verbose_opt[0]>1)
1603  std::cout << "bounding box for polygon feature " << ifeature << ": " << uli << " " << ulj << " " << lri << " " << lrj << std::endl;
1604 
1605  if(uli<0)
1606  uli=0;
1607  if(lri<0)
1608  lri=0;
1609  if(uli>=imgReader.nrOfCol())
1610  uli=imgReader.nrOfCol()-1;
1611  if(lri>=imgReader.nrOfCol())
1612  lri=imgReader.nrOfCol()-1;
1613  if(ulj<0)
1614  ulj=0;
1615  if(lrj<0)
1616  lrj=0;
1617  if(ulj>=imgReader.nrOfRow())
1618  ulj=imgReader.nrOfRow()-1;
1619  if(lrj>=imgReader.nrOfRow())
1620  lrj=imgReader.nrOfRow()-1;
1621  // if(uli<0||lri>=imgReader.nrOfCol()||ulj<0||lrj>=imgReader.nrOfRow())
1622  // continue;
1623 
1624  int nPointPolygon=0;
1625 
1626  if(polygon_opt[0]){
1627  if(writeTest)
1628  writePolygonFeature = OGRFeature::CreateFeature(writeTestLayer->GetLayerDefn());
1629  else
1630  writePolygonFeature = OGRFeature::CreateFeature(writeLayer->GetLayerDefn());
1631  }
1632  else if(ruleMap[rule_opt[0]]!=rule::point){
1633  if(writeTest)
1634  writeCentroidFeature = OGRFeature::CreateFeature(writeTestLayer->GetLayerDefn());
1635  else
1636  writeCentroidFeature = OGRFeature::CreateFeature(writeLayer->GetLayerDefn());
1637  }
1638  // vector<double> polyValues;
1639  Vector2d<double> polyValues;
1640  vector<double> polyClassValues;
1641 
1642  if(class_opt.size()){
1643 
1644  polyClassValues.resize(class_opt.size());
1645  //initialize
1646  for(int iclass=0;iclass<class_opt.size();++iclass)
1647  polyClassValues[iclass]=0;
1648  }
1649  else
1650  polyValues.resize(nband);
1651  vector< Vector2d<double> > readValues(nband);
1652  for(int iband=0;iband<nband;++iband){
1653  int theBand=(band_opt.size()) ? band_opt[iband] : iband;
1654  imgReader.readDataBlock(readValues[iband],GDT_Float64,uli,lri,ulj,lrj,theBand);
1655  }
1656 
1657  OGRPoint thePoint;
1658  for(int j=ulj;j<=lrj;++j){
1659  for(int i=uli;i<=lri;++i){
1660  //check if within raster image
1661  if(i<0||i>=imgReader.nrOfCol())
1662  continue;
1663  if(j<0||j>=imgReader.nrOfRow())
1664  continue;
1665  //check if point is on surface
1666  double theX=0;
1667  double theY=0;
1668  imgReader.image2geo(i,j,theX,theY);
1669  thePoint.setX(theX);
1670  thePoint.setY(theY);
1671  if(ruleMap[rule_opt[0]]!=rule::centroid&&!readPolygon.Contains(&thePoint))
1672  continue;
1673 
1674  bool valid=true;
1675 
1676  if(srcnodata_opt.size()){
1677  for(int vband=0;vband<bndnodata_opt.size();++vband){
1678  double value=((readValues[bndnodata_opt[vband]])[j-ulj])[i-uli];
1679  if(value==srcnodata_opt[vband]){
1680  valid=false;
1681  break;
1682  }
1683  }
1684  }
1685 
1686  if(!valid)
1687  continue;
1688  else
1689  validFeature=true;
1690 
1691  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?
1692  // if(writeRing.isPointOnRingBoundary(&thePoint))
1693  // writeRing.addPoint(&thePoint);
1694  if(verbose_opt[0]>1)
1695  std::cout << "point is on surface:" << thePoint.getX() << "," << thePoint.getY() << std::endl;
1696  ++nPointPolygon;
1697 
1698  if(polythreshold_opt.size())
1699  if(nPointPolygon>polythreshold_opt[0])
1700  continue;
1701  // throw(nPointPolygon);
1702  OGRFeature *writePointFeature;
1703  if(!polygon_opt[0]){
1704  //create feature
1705  if(ruleMap[rule_opt[0]]==rule::point){//do not create in case of mean, stdev, median, sum or centroid (only create point at centroid)
1706  if(writeTest)
1707  writePointFeature = OGRFeature::CreateFeature(writeTestLayer->GetLayerDefn());
1708  else
1709  writePointFeature = OGRFeature::CreateFeature(writeLayer->GetLayerDefn());
1710  if(verbose_opt[0]>1)
1711  std::cout << "copying fields from polygons " << std::endl;
1712  if(writePointFeature->SetFrom(readFeature)!= OGRERR_NONE)
1713  cerr << "writing feature failed" << std::endl;
1714  if(verbose_opt[0]>1)
1715  std::cout << "set geometry as point " << std::endl;
1716  //test
1717  writePointFeature->SetGeometry(&thePoint);
1718  assert(wkbFlatten(writePointFeature->GetGeometryRef()->getGeometryType()) == wkbPoint);
1719  // OGRGeometry *updateGeometry;
1720  // updateGeometry = writePointFeature->GetGeometryRef();
1721  // OGRPoint *poPoint = (OGRPoint *) updateGeometry;
1722  if(verbose_opt[0]>1)
1723  std::cout << "write feature has " << writePointFeature->GetFieldCount() << " fields" << std::endl;
1724  }
1725  }
1726  if(class_opt.size()){
1727  short value=((readValues[0])[j-ulj])[i-uli];
1728  for(int iclass=0;iclass<class_opt.size();++iclass){
1729  if(value==class_opt[iclass])
1730  polyClassValues[iclass]+=1;
1731  }
1732  }
1733  else{
1734  for(int iband=0;iband<nband;++iband){
1735  double value=((readValues[iband])[j-ulj])[i-uli];
1736  if(verbose_opt[0]>1)
1737  std::cout << ": " << value << std::endl;
1738  if(polygon_opt[0]||ruleMap[rule_opt[0]]!=rule::point)
1739  polyValues[iband].push_back(value);
1740  else{
1741  if(verbose_opt[0]>1)
1742  std::cout << "set field " << fieldname_opt[iband] << " to " << value << std::endl;
1743  switch( fieldType ){
1744  case OFTInteger:
1745  case OFTReal:
1746  writePointFeature->SetField(fieldname_opt[iband].c_str(),value);
1747  break;
1748  case OFTString:
1749  writePointFeature->SetField(fieldname_opt[iband].c_str(),type2string<double>(value).c_str());
1750  break;
1751  default://not supported
1752  assert(0);
1753  break;
1754  }
1755  }//else
1756  }//iband
1757  }//else (class_opt.size())
1758  if(!polygon_opt[0]){
1759  if(ruleMap[rule_opt[0]]==rule::point){//do not create in case of mean or median value (only at centroid)
1760  //write feature
1761  if(verbose_opt[0]>1)
1762  std::cout << "creating point feature" << std::endl;
1763  if(writeTest){
1764  if(writeTestLayer->CreateFeature( writePointFeature ) != OGRERR_NONE ){
1765  std::string errorString="Failed to create feature in test ogr vector dataset";
1766  throw(errorString);
1767  }
1768  }
1769  else{
1770  if(writeLayer->CreateFeature( writePointFeature ) != OGRERR_NONE ){
1771  std::string errorString="Failed to create feature in ogr vector dataset";
1772  throw(errorString);
1773  }
1774  }
1775  //destroy feature
1776  OGRFeature::DestroyFeature( writePointFeature );
1777  ++ntotalvalid;
1778  if(verbose_opt[0])
1779  std::cout << "ntotalvalid(2): " << ntotalvalid << std::endl;
1780  }
1781  }
1782  }
1783  }
1784  if(polygon_opt[0]||ruleMap[rule_opt[0]]!=rule::point){
1785  //do not create if no points found within polygon
1786  if(!nPointPolygon){
1787  if(verbose_opt[0])
1788  cout << "no points found in polygon, continuing" << endl;
1789  continue;
1790  }
1791  //add ring to polygon
1792  if(polygon_opt[0]){
1793  writePolygon.addRing(&writeRing);
1794  writePolygon.closeRings();
1795  //write geometry of writePolygon
1796  //test
1797  //writePolygonFeature and readFeature are both of type wkbPolygon
1798  // writePolygonFeature->SetGeometry(&writePolygon);
1799  if(writePolygonFeature->SetFrom(readFeature)!= OGRERR_NONE)
1800  cerr << "writing feature failed" << std::endl;
1801  if(verbose_opt[0]>1)
1802  std::cout << "copying new fields write polygon " << std::endl;
1803  if(verbose_opt[0]>1)
1804  std::cout << "write feature has " << writePolygonFeature->GetFieldCount() << " fields" << std::endl;
1805  //write polygon feature
1806  }
1807  else{//write value of polygon to centroid point
1808  //create feature
1809  if(verbose_opt[0]>1)
1810  std::cout << "copying fields from polygons " << std::endl;
1811  if(writeCentroidFeature->SetFrom(readFeature)!= OGRERR_NONE)
1812  cerr << "writing feature failed" << std::endl;
1813  writeCentroidFeature->SetGeometry(&writeCentroidPoint);
1814  assert(wkbFlatten(writeCentroidFeature->GetGeometryRef()->getGeometryType()) == wkbPoint );
1815  if(verbose_opt[0]>1)
1816  std::cout << "write feature has " << writeCentroidFeature->GetFieldCount() << " fields" << std::endl;
1817  }
1818  if(class_opt.empty()){
1819  if(ruleMap[rule_opt[0]]==rule::point){//value at centroid of polygon
1820  if(verbose_opt[0])
1821  std::cout << "number of points in polygon: " << nPointPolygon << std::endl;
1822  for(int index=0;index<polyValues.size();++index){
1823  assert(polyValues[index].size()==1);
1824  double theValue=polyValues[index].back();
1825 
1826  if(verbose_opt[0])
1827  std::cout << "number of points in polygon: " << nPointPolygon << std::endl;
1828  int theBand=(band_opt.size()) ? band_opt[index] : index;
1829  try{
1830  if(verbose_opt[0]>1)
1831  std::cout << "set field " << fieldname_opt[index] << " to " << theValue << std::endl;
1832  switch( fieldType ){
1833  case OFTInteger:
1834  case OFTReal:
1835  if(polygon_opt[0])
1836  writePolygonFeature->SetField(fieldname_opt[index].c_str(),theValue);
1837  else
1838  writeCentroidFeature->SetField(fieldname_opt[index].c_str(),theValue);
1839  break;
1840  case OFTString:
1841  if(polygon_opt[0])
1842  writePolygonFeature->SetField(fieldname_opt[index].c_str(),type2string<double>(theValue).c_str());
1843  else
1844  writeCentroidFeature->SetField(fieldname_opt[index].c_str(),type2string<double>(theValue).c_str());
1845  break;
1846  default://not supported
1847  std::string errorString="field type not supported";
1848  throw(errorString);
1849  break;
1850  }
1851  }
1852  catch(std::string e){
1853  std::cout << e << std::endl;
1854  exit(1);
1855  }
1856  }
1857  }
1858  else{//ruleMap[rule_opt[0]] is not rule::point
1859  double theValue=0;
1860  for(int index=0;index<polyValues.size();++index){
1861  try{
1862  if(ruleMap[rule_opt[0]]==rule::mean)
1863  theValue=stat.mean(polyValues[index]);
1864  else if(ruleMap[rule_opt[0]]==rule::stdev)
1865  theValue=sqrt(stat.var(polyValues[index]));
1866  else if(ruleMap[rule_opt[0]]==rule::median)
1867  theValue=stat.median(polyValues[index]);
1868  else if(ruleMap[rule_opt[0]]==rule::percentile)
1869  theValue=stat.percentile(polyValues[index],polyValues[index].begin(),polyValues[index].end(),percentile_opt[0]);
1870  else if(ruleMap[rule_opt[0]]==rule::sum)
1871  theValue=stat.sum(polyValues[index]);
1872  else if(ruleMap[rule_opt[0]]==rule::max)
1873  theValue=stat.mymax(polyValues[index]);
1874  else if(ruleMap[rule_opt[0]]==rule::min)
1875  theValue=stat.mymin(polyValues[index]);
1876  else if(ruleMap[rule_opt[0]]==rule::centroid){
1877  if(verbose_opt[0])
1878  std::cout << "number of points in polygon: " << nPointPolygon << std::endl;
1879  assert(nPointPolygon<=1);
1880  assert(nPointPolygon==polyValues[index].size());
1881  theValue=polyValues[index].back();
1882  }
1883  else{
1884  std::string errorString="rule not supported";
1885  throw(errorString);
1886  }
1887  if(verbose_opt[0]>1)
1888  std::cout << "set field " << fieldname_opt[index] << " to " << theValue << std::endl;
1889  switch( fieldType ){
1890  case OFTInteger:
1891  case OFTReal:
1892  if(polygon_opt[0])
1893  writePolygonFeature->SetField(fieldname_opt[index].c_str(),theValue);
1894  else
1895  writeCentroidFeature->SetField(fieldname_opt[index].c_str(),theValue);
1896  break;
1897  case OFTString:
1898  if(polygon_opt[0])
1899  writePolygonFeature->SetField(fieldname_opt[index].c_str(),type2string<double>(theValue).c_str());
1900  else
1901  writeCentroidFeature->SetField(fieldname_opt[index].c_str(),type2string<double>(theValue).c_str());
1902  break;
1903  default:
1904  std::string errorString="field type not supported";
1905  throw(errorString);
1906  break;
1907  }
1908  }
1909  catch(std::string e){
1910  std::cout << e << std::endl;
1911  exit(1);
1912  }
1913  }
1914  }
1915  }
1916  else{//class_opt is set
1917  if(ruleMap[rule_opt[0]]==rule::proportion||ruleMap[rule_opt[0]]==rule::count){
1918  if(verbose_opt[0])
1919  std::cout << "number of points in polygon: " << nPointPolygon << std::endl;
1920  if(ruleMap[rule_opt[0]]==rule::proportion)
1921  stat.normalize_pct(polyClassValues);
1922  for(int index=0;index<polyClassValues.size();++index){
1923  double theValue=polyClassValues[index];
1924  ostringstream fs;
1925  fs << class_opt[index];
1926  if(polygon_opt[0])
1927  writePolygonFeature->SetField(fs.str().c_str(),static_cast<int>(theValue));
1928  else
1929  writeCentroidFeature->SetField(fs.str().c_str(),static_cast<int>(theValue));
1930  }
1931  }
1932  else if(ruleMap[rule_opt[0]]==rule::custom){
1933  assert(polygon_opt[0]);//not implemented for points
1934  if(verbose_opt[0])
1935  std::cout << "number of points in polygon: " << nPointPolygon << std::endl;
1936  stat.normalize_pct(polyClassValues);
1937  assert(polyClassValues.size()==2);//11:broadleaved, 12:coniferous
1938  if(polyClassValues[0]>=75)//broadleaved
1939  writePolygonFeature->SetField(label_opt[0].c_str(),static_cast<int>(11));
1940  else if(polyClassValues[1]>=75)//coniferous
1941  writePolygonFeature->SetField(label_opt[0].c_str(),static_cast<int>(12));
1942  else if(polyClassValues[0]>25&&polyClassValues[1]>25)//mixed
1943  writePolygonFeature->SetField(label_opt[0].c_str(),static_cast<int>(13));
1944  else{
1945  if(verbose_opt[0]){
1946  std::cout << "No valid value in polyClassValues..." << std::endl;
1947  for(int index=0;index<polyClassValues.size();++index){
1948  double theValue=polyClassValues[index];
1949  std::cout << theValue << " ";
1950  }
1951  std::cout << std::endl;
1952  }
1953  writePolygonFeature->SetField(label_opt[0].c_str(),static_cast<int>(20));
1954  }
1955  }
1956  else if(ruleMap[rule_opt[0]]==rule::mode){
1957  //maximum votes in polygon
1958  if(verbose_opt[0])
1959  std::cout << "number of points in polygon: " << nPointPolygon << std::endl;
1960  //search for class with maximum votes
1961  int maxClass=stat.mymin(class_opt);
1962  vector<double>::iterator maxit;
1963  maxit=stat.mymax(polyClassValues,polyClassValues.begin(),polyClassValues.end());
1964  int maxIndex=distance(polyClassValues.begin(),maxit);
1965  maxClass=class_opt[maxIndex];
1966  if(verbose_opt[0]>0)
1967  std::cout << "maxClass: " << maxClass << std::endl;
1968  if(polygon_opt[0])
1969  writePolygonFeature->SetField(label_opt[0].c_str(),maxClass);
1970  else
1971  writeCentroidFeature->SetField(label_opt[0].c_str(),maxClass);
1972  }
1973  }
1974  if(polygon_opt[0]){
1975  if(verbose_opt[0]>1)
1976  std::cout << "creating polygon feature" << std::endl;
1977  if(writeTest){
1978  if(writeTestLayer->CreateFeature( writePolygonFeature ) != OGRERR_NONE ){
1979  std::string errorString="Failed to create polygon feature in ogr vector dataset";
1980  throw(errorString);
1981  }
1982  }
1983  else{
1984  if(writeLayer->CreateFeature( writePolygonFeature ) != OGRERR_NONE ){
1985  std::string errorString="Failed to create polygon feature in ogr vector dataset";
1986  throw(errorString);
1987  }
1988  }
1989  OGRFeature::DestroyFeature( writePolygonFeature );
1990  ++ntotalvalid;
1991  if(verbose_opt[0])
1992  std::cout << "ntotalvalid(1): " << ntotalvalid << std::endl;
1993  }
1994  else{
1995  if(verbose_opt[0]>1)
1996  std::cout << "creating point feature in centroid" << std::endl;
1997  if(writeTest){
1998  if(writeTestLayer->CreateFeature( writeCentroidFeature ) != OGRERR_NONE ){
1999  std::string errorString="Failed to create point feature in ogr vector dataset";
2000  throw(errorString);
2001  }
2002  }
2003  else{
2004  //test
2005  assert(validFeature);
2006  if(writeLayer->CreateFeature( writeCentroidFeature ) != OGRERR_NONE ){
2007  std::string errorString="Failed to create point feature in ogr vector dataset";
2008  throw(errorString);
2009  }
2010  }
2011  OGRFeature::DestroyFeature( writeCentroidFeature );
2012  ++ntotalvalid;
2013  if(verbose_opt[0])
2014  std::cout << "ntotalvalid: " << ntotalvalid << std::endl;
2015  }
2016  }
2017  }
2018  else if(wkbFlatten(poGeometry->getGeometryType()) == wkbMultiPolygon){//todo: try to use virtual OGRGeometry instead of OGRMultiPolygon and OGRPolygon
2019  OGRMultiPolygon readPolygon = *((OGRMultiPolygon *) poGeometry);
2020  OGRPolygon writePolygon;
2021  OGRLinearRing writeRing;
2022  OGRPoint writeCentroidPoint;
2023  OGRFeature *writePolygonFeature;
2024  OGRFeature *writeCentroidFeature;
2025 
2026  readPolygon.closeRings();
2027 
2028  if(verbose_opt[0]>1)
2029  std::cout << "get centroid point from polygon" << std::endl;
2030  readPolygon.Centroid(&writeCentroidPoint);
2031 
2032  double ulx,uly,lrx,lry;
2033  double uli,ulj,lri,lrj;
2034  if((polygon_opt[0]&&ruleMap[rule_opt[0]]==rule::point)||(ruleMap[rule_opt[0]]==rule::centroid)){
2035  ulx=writeCentroidPoint.getX();
2036  uly=writeCentroidPoint.getY();
2037  lrx=ulx;
2038  lry=uly;
2039  }
2040  else{
2041  //get envelope
2042  if(verbose_opt[0])
2043  std::cout << "reading envelope for polygon " << ifeature << std::endl;
2044  OGREnvelope* psEnvelope=new OGREnvelope();
2045  readPolygon.getEnvelope(psEnvelope);
2046  ulx=psEnvelope->MinX;
2047  uly=psEnvelope->MaxY;
2048  lrx=psEnvelope->MaxX;
2049  lry=psEnvelope->MinY;
2050  delete psEnvelope;
2051  }
2052  // if(geo_opt[0]){
2053  imgReader.geo2image(ulx,uly,uli,ulj);
2054  imgReader.geo2image(lrx,lry,lri,lrj);
2055  // }
2056  // else{
2057  // uli=ulx;
2058  // ulj=uly;
2059  // lri=lrx;
2060  // lrj=lry;
2061  // }
2062  //nearest neighbour
2063  ulj=static_cast<int>(ulj);
2064  uli=static_cast<int>(uli);
2065  lrj=static_cast<int>(lrj);
2066  lri=static_cast<int>(lri);
2067  //iterate through all pixels
2068  if(verbose_opt[0]>1)
2069  std::cout << "bounding box for multipologon feature " << ifeature << ": " << uli << " " << ulj << " " << lri << " " << lrj << std::endl;
2070 
2071  if(uli<0)
2072  uli=0;
2073  if(lri<0)
2074  lri=0;
2075  if(uli>=imgReader.nrOfCol())
2076  uli=imgReader.nrOfCol()-1;
2077  if(lri>=imgReader.nrOfCol())
2078  lri=imgReader.nrOfCol()-1;
2079  if(ulj<0)
2080  ulj=0;
2081  if(lrj<0)
2082  lrj=0;
2083  if(ulj>=imgReader.nrOfRow())
2084  ulj=imgReader.nrOfRow()-1;
2085  if(lrj>=imgReader.nrOfRow())
2086  lrj=imgReader.nrOfRow()-1;
2087  // if(uli<0||lri>=imgReader.nrOfCol()||ulj<0||lrj>=imgReader.nrOfRow())
2088  // continue;
2089 
2090  int nPointPolygon=0;
2091  if(polygon_opt[0]){
2092  if(writeTest)
2093  writePolygonFeature = OGRFeature::CreateFeature(writeTestLayer->GetLayerDefn());
2094  else
2095  writePolygonFeature = OGRFeature::CreateFeature(writeLayer->GetLayerDefn());
2096  }
2097  else if(ruleMap[rule_opt[0]]!=rule::point){
2098  if(writeTest)
2099  writeCentroidFeature = OGRFeature::CreateFeature(writeTestLayer->GetLayerDefn());
2100  else
2101  writeCentroidFeature = OGRFeature::CreateFeature(writeLayer->GetLayerDefn());
2102  }
2103  // vector<double> polyValues;
2104  Vector2d<double> polyValues;
2105  vector<double> polyClassValues;
2106 
2107  if(class_opt.size()){
2108  polyClassValues.resize(class_opt.size());
2109  //initialize
2110  for(int iclass=0;iclass<class_opt.size();++iclass)
2111  polyClassValues[iclass]=0;
2112  }
2113  else
2114  polyValues.resize(nband);
2115  vector< Vector2d<double> > readValues(nband);
2116  for(int iband=0;iband<nband;++iband){
2117  int theBand=(band_opt.size()) ? band_opt[iband] : iband;
2118  imgReader.readDataBlock(readValues[iband],GDT_Float64,uli,lri,ulj,lrj,theBand);
2119  }
2120 
2121  OGRPoint thePoint;
2122  for(int j=ulj;j<=lrj;++j){
2123  for(int i=uli;i<=lri;++i){
2124  //check if within raster image
2125  if(i<0||i>=imgReader.nrOfCol())
2126  continue;
2127  if(j<0||j>=imgReader.nrOfRow())
2128  continue;
2129  //check if point is on surface
2130  double theX=0;
2131  double theY=0;
2132  imgReader.image2geo(i,j,theX,theY);
2133  thePoint.setX(theX);
2134  thePoint.setY(theY);
2135 
2136  if(ruleMap[rule_opt[0]]!=rule::centroid&&!readPolygon.Contains(&thePoint))
2137  continue;
2138 
2139  bool valid=true;
2140 
2141  if(srcnodata_opt.size()){
2142  for(int vband=0;vband<bndnodata_opt.size();++vband){
2143  double value=((readValues[bndnodata_opt[vband]])[j-ulj])[i-uli];
2144  if(value==srcnodata_opt[vband]){
2145  valid=false;
2146  break;
2147  }
2148  }
2149  }
2150 
2151  if(!valid)
2152  continue;
2153  else
2154  validFeature=true;
2155 
2156  writeRing.addPoint(&thePoint);
2157  // if(writeRing.isPointOnRingBoundary(&thePoint))
2158  // writeRing.addPoint(&thePoint);
2159  if(verbose_opt[0]>1)
2160  std::cout << "point is on surface:" << thePoint.getX() << "," << thePoint.getY() << std::endl;
2161  ++nPointPolygon;
2162 
2163  if(polythreshold_opt.size())
2164  if(nPointPolygon>polythreshold_opt[0])
2165  continue;
2166  // throw(nPointPolygon);
2167  OGRFeature *writePointFeature;
2168  if(!polygon_opt[0]){
2169  //create feature
2170  if(ruleMap[rule_opt[0]]==rule::point){//do not create in case of mean, stdev, median or sum (only create point at centroid)
2171  if(writeTest)
2172  writePointFeature = OGRFeature::CreateFeature(writeTestLayer->GetLayerDefn());
2173  else
2174  writePointFeature = OGRFeature::CreateFeature(writeLayer->GetLayerDefn());
2175  if(verbose_opt[0]>1)
2176  std::cout << "copying fields from polygons " << std::endl;
2177  if(writePointFeature->SetFrom(readFeature)!= OGRERR_NONE)
2178  cerr << "writing feature failed" << std::endl;
2179  if(verbose_opt[0]>1)
2180  std::cout << "set geometry as point " << std::endl;
2181  //test
2182  writePointFeature->SetGeometry(&thePoint);
2183  assert(wkbFlatten(writePointFeature->GetGeometryRef()->getGeometryType()) == wkbPoint);
2184  // OGRGeometry *updateGeometry;
2185  // updateGeometry = writePointFeature->GetGeometryRef();
2186  // OGRPoint *poPoint = (OGRPoint *) updateGeometry;
2187  if(verbose_opt[0]>1)
2188  std::cout << "write feature has " << writePointFeature->GetFieldCount() << " fields" << std::endl;
2189  }
2190  }
2191  if(class_opt.size()){
2192  short value=((readValues[0])[j-ulj])[i-uli];
2193  for(int iclass=0;iclass<class_opt.size();++iclass){
2194  if(value==class_opt[iclass])
2195  polyClassValues[iclass]+=1;
2196  }
2197  }
2198  else{
2199  for(int iband=0;iband<nband;++iband){
2200  double value=((readValues[iband])[j-ulj])[i-uli];
2201  if(verbose_opt[0]>1)
2202  std::cout << ": " << value << std::endl;
2203  if(polygon_opt[0]||ruleMap[rule_opt[0]]!=rule::point)
2204  polyValues[iband].push_back(value);
2205  else{
2206  if(verbose_opt[0]>1)
2207  std::cout << "set field " << fieldname_opt[iband] << " to " << value << std::endl;
2208  switch( fieldType ){
2209  case OFTInteger:
2210  case OFTReal:
2211  writePointFeature->SetField(fieldname_opt[iband].c_str(),value);
2212  break;
2213  case OFTString:
2214  writePointFeature->SetField(fieldname_opt[iband].c_str(),type2string<double>(value).c_str());
2215  break;
2216  default://not supported
2217  assert(0);
2218  break;
2219  }
2220  }//else
2221  }//iband
2222  }//else (class_opt.size())
2223  if(!polygon_opt[0]){
2224  if(ruleMap[rule_opt[0]]==rule::point){//do not create in case of mean, stdev or median value (only at centroid)
2225  //write feature
2226  if(verbose_opt[0]>1)
2227  std::cout << "creating point feature" << std::endl;
2228  if(writeTest){
2229  if(writeTestLayer->CreateFeature( writePointFeature ) != OGRERR_NONE ){
2230  std::string errorString="Failed to create feature in ogr vector dataset";
2231  throw(errorString);
2232  }
2233  }
2234  else{
2235  if(writeLayer->CreateFeature( writePointFeature ) != OGRERR_NONE ){
2236  std::string errorString="Failed to create feature in ogr vector dataset";
2237  throw(errorString);
2238  }
2239  }
2240  //destroy feature
2241  OGRFeature::DestroyFeature( writePointFeature );
2242  }
2243  }
2244  // ++isample;
2245  ++ntotalvalid;
2246  if(verbose_opt[0])
2247  std::cout << "ntotalvalid: " << ntotalvalid << std::endl;
2248  }
2249  }
2250  if(!validFeature)
2251  continue;
2252  if(polygon_opt[0]||ruleMap[rule_opt[0]]!=rule::point){
2253  //do not create if no points found within polygon
2254  if(!nPointPolygon)
2255  continue;
2256  //add ring to polygon
2257  if(polygon_opt[0]){
2258  writePolygon.addRing(&writeRing);
2259  writePolygon.closeRings();
2260  //write geometry of writePolygon
2261  //test
2262  //writePolygon and readFeature are from geometry type wkbMultiPolygon
2263  // writePolygonFeature->SetGeometry(&writePolygon);
2264  if(writePolygonFeature->SetFrom(readFeature)!= OGRERR_NONE)
2265  cerr << "writing feature failed" << std::endl;
2266  assert(writePolygonFeature->GetGeometryRef()->getGeometryType()==wkbMultiPolygon);
2267  if(verbose_opt[0]>1)
2268  std::cout << "copying new fields write polygon " << std::endl;
2269  if(verbose_opt[0]>1)
2270  std::cout << "write feature has " << writePolygonFeature->GetFieldCount() << " fields" << std::endl;
2271  //write polygon feature
2272  }
2273  else{//write band information of polygon to centroid point
2274  //create feature
2275  if(verbose_opt[0]>1)
2276  std::cout << "copying fields from polygons " << std::endl;
2277  if(writeCentroidFeature->SetFrom(readFeature)!= OGRERR_NONE)
2278  cerr << "writing feature failed" << std::endl;
2279  writeCentroidFeature->SetGeometry(&writeCentroidPoint);
2280  assert(wkbFlatten(writeCentroidFeature->GetGeometryRef()->getGeometryType()) == wkbPoint);
2281  if(verbose_opt[0]>1)
2282  std::cout << "write feature has " << writeCentroidFeature->GetFieldCount() << " fields" << std::endl;
2283  }
2284  if(class_opt.empty()){
2285  if(ruleMap[rule_opt[0]]==rule::point){//value at centroid of polygon
2286  if(verbose_opt[0])
2287  std::cout << "number of points in polygon: " << nPointPolygon << std::endl;
2288  for(int index=0;index<polyValues.size();++index){
2289  //test
2290  assert(polyValues[index].size()==1);
2291  double theValue=polyValues[index].back();
2292  if(verbose_opt[0])
2293  std::cout << "number of points in polygon: " << nPointPolygon << std::endl;
2294  int theBand=(band_opt.size()) ? band_opt[index] : index;
2295  try{
2296  if(verbose_opt[0]>1)
2297  std::cout << "set field " << fieldname_opt[index] << " to " << theValue << std::endl;
2298  switch( fieldType ){
2299  case OFTInteger:
2300  case OFTReal:
2301  if(polygon_opt[0])
2302  writePolygonFeature->SetField(fieldname_opt[index].c_str(),theValue);
2303  else
2304  writeCentroidFeature->SetField(fieldname_opt[index].c_str(),theValue);
2305  break;
2306  case OFTString:
2307  if(polygon_opt[0])
2308  writePolygonFeature->SetField(fieldname_opt[index].c_str(),type2string<double>(theValue).c_str());
2309  else
2310  writeCentroidFeature->SetField(fieldname_opt[index].c_str(),type2string<double>(theValue).c_str());
2311  break;
2312  default://not supported
2313  std::string errorString="field type not supported";
2314  throw(errorString);
2315  break;
2316  }
2317  }
2318  catch(std::string e){
2319  std::cout << e << std::endl;
2320  exit(1);
2321  }
2322  }
2323  }
2324  else{//ruleMap[rule_opt[0]] is not rule::point
2325  double theValue=0;
2326  for(int index=0;index<polyValues.size();++index){
2327  try{
2328  if(ruleMap[rule_opt[0]]==rule::mean)
2329  theValue=stat.mean(polyValues[index]);
2330  else if(ruleMap[rule_opt[0]]==rule::stdev)
2331  theValue=sqrt(stat.var(polyValues[index]));
2332  else if(ruleMap[rule_opt[0]]==rule::median)
2333  theValue=stat.median(polyValues[index]);
2334  else if(ruleMap[rule_opt[0]]==rule::percentile)
2335  theValue=stat.percentile(polyValues[index],polyValues[index].begin(),polyValues[index].end(),percentile_opt[0]);
2336  else if(ruleMap[rule_opt[0]]==rule::sum)
2337  theValue=stat.sum(polyValues[index]);
2338  else if(ruleMap[rule_opt[0]]==rule::max)
2339  theValue=stat.mymax(polyValues[index]);
2340  else if(ruleMap[rule_opt[0]]==rule::min)
2341  theValue=stat.mymin(polyValues[index]);
2342  else if(ruleMap[rule_opt[0]]==rule::centroid){
2343  if(verbose_opt[0])
2344  std::cout << "number of points in polygon: " << nPointPolygon << std::endl;
2345  assert(nPointPolygon<=1);
2346  assert(nPointPolygon==polyValues[index].size());
2347  theValue=polyValues[index].back();
2348  }
2349  else{
2350  std::string errorString="rule not supported";
2351  throw(errorString);
2352  }
2353  if(verbose_opt[0]>1)
2354  std::cout << "set field " << fieldname_opt[index] << " to " << theValue << std::endl;
2355  switch( fieldType ){
2356  case OFTInteger:
2357  case OFTReal:
2358  if(polygon_opt[0])
2359  writePolygonFeature->SetField(fieldname_opt[index].c_str(),theValue);
2360  else
2361  writeCentroidFeature->SetField(fieldname_opt[index].c_str(),theValue);
2362  break;
2363  case OFTString:
2364  if(polygon_opt[0])
2365  writePolygonFeature->SetField(fieldname_opt[index].c_str(),type2string<double>(theValue).c_str());
2366  else
2367  writeCentroidFeature->SetField(fieldname_opt[index].c_str(),type2string<double>(theValue).c_str());
2368  break;
2369  default://not supported
2370  std::string errorString="field type not supported";
2371  throw(errorString);
2372  break;
2373  }
2374  }
2375  catch(std::string e){
2376  std::cout << e << std::endl;
2377  exit(1);
2378  }
2379  }
2380  }
2381  }
2382  else{//class_opt is set
2383  if(ruleMap[rule_opt[0]]==rule::proportion||ruleMap[rule_opt[0]]==rule::count){
2384  if(verbose_opt[0])
2385  std::cout << "number of points in polygon: " << nPointPolygon << std::endl;
2386  if(ruleMap[rule_opt[0]]==rule::proportion)
2387  stat.normalize_pct(polyClassValues);
2388  for(int index=0;index<polyClassValues.size();++index){
2389  double theValue=polyClassValues[index];
2390  ostringstream fs;
2391  fs << class_opt[index];
2392  if(polygon_opt[0])
2393  writePolygonFeature->SetField(fs.str().c_str(),static_cast<int>(theValue));
2394  else
2395  writeCentroidFeature->SetField(fs.str().c_str(),static_cast<int>(theValue));
2396  }
2397  }
2398  else if(ruleMap[rule_opt[0]]==rule::custom){
2399  assert(polygon_opt[0]);//not implemented for points
2400  if(verbose_opt[0])
2401  std::cout << "number of points in polygon: " << nPointPolygon << std::endl;
2402  stat.normalize_pct(polyClassValues);
2403  assert(polyClassValues.size()==2);//11:broadleaved, 12:coniferous
2404  if(polyClassValues[0]>=75)//broadleaved
2405  writePolygonFeature->SetField(label_opt[0].c_str(),static_cast<int>(11));
2406  else if(polyClassValues[1]>=75)//coniferous
2407  writePolygonFeature->SetField(label_opt[0].c_str(),static_cast<int>(12));
2408  else if(polyClassValues[0]>25&&polyClassValues[1]>25)//mixed
2409  writePolygonFeature->SetField(label_opt[0].c_str(),static_cast<int>(13));
2410  else{
2411  if(verbose_opt[0]){
2412  std::cout << "No valid value in polyClassValues..." << std::endl;
2413  for(int index=0;index<polyClassValues.size();++index){
2414  double theValue=polyClassValues[index];
2415  std::cout << theValue << " ";
2416  }
2417  std::cout << std::endl;
2418  }
2419  writePolygonFeature->SetField(label_opt[0].c_str(),static_cast<int>(20));
2420  }
2421  }
2422  else if(ruleMap[rule_opt[0]]==rule::mode){
2423  //maximum votes in polygon
2424  if(verbose_opt[0])
2425  std::cout << "number of points in polygon: " << nPointPolygon << std::endl;
2426  //search for class with maximum votes
2427  int maxClass=stat.mymin(class_opt);
2428  vector<double>::iterator maxit;
2429  maxit=stat.mymax(polyClassValues,polyClassValues.begin(),polyClassValues.end());
2430  int maxIndex=distance(polyClassValues.begin(),maxit);
2431  maxClass=class_opt[maxIndex];
2432  if(verbose_opt[0]>0)
2433  std::cout << "maxClass: " << maxClass << std::endl;
2434  if(polygon_opt[0])
2435  writePolygonFeature->SetField(label_opt[0].c_str(),maxClass);
2436  else
2437  writeCentroidFeature->SetField(label_opt[0].c_str(),maxClass);
2438  }
2439  }
2440 
2441  if(polygon_opt[0]){
2442  if(verbose_opt[0]>1)
2443  std::cout << "creating polygon feature" << std::endl;
2444  if(writeTest){
2445  if(writeTestLayer->CreateFeature( writePolygonFeature ) != OGRERR_NONE ){
2446  std::string errorString="Failed to create polygon feature in ogr vector dataset";
2447  throw(errorString);
2448  }
2449  }
2450  else{
2451  if(writeLayer->CreateFeature( writePolygonFeature ) != OGRERR_NONE ){
2452  std::string errorString="Failed to create polygon feature in ogr vector dataset";
2453  throw(errorString);
2454  }
2455  }
2456  OGRFeature::DestroyFeature( writePolygonFeature );
2457  ++ntotalvalid;
2458  if(verbose_opt[0])
2459  std::cout << "ntotalvalid: " << ntotalvalid << std::endl;
2460  }
2461  else{
2462  if(verbose_opt[0]>1)
2463  std::cout << "creating point feature in centroid" << std::endl;
2464  if(writeTest){
2465  if(writeTestLayer->CreateFeature( writeCentroidFeature ) != OGRERR_NONE ){
2466  std::string errorString="Failed to create point feature in ogr vector dataset";
2467  throw(errorString);
2468  }
2469  }
2470  else{
2471  //test
2472  assert(validFeature);
2473  if(writeLayer->CreateFeature( writeCentroidFeature ) != OGRERR_NONE ){
2474  std::string errorString="Failed to create point feature in ogr vector dataset";
2475  throw(errorString);
2476  }
2477  }
2478  OGRFeature::DestroyFeature( writeCentroidFeature );
2479  ++ntotalvalid;
2480  if(verbose_opt[0])
2481  std::cout << "ntotalvalid: " << ntotalvalid << std::endl;
2482  }
2483  }
2484  }
2485  else{
2486  std::string test;
2487  test=poGeometry->getGeometryName();
2488  ostringstream oss;
2489  oss << "geometry " << test << " not supported";
2490  throw(oss.str());
2491  }
2492  ++ifeature;
2493  progress=static_cast<float>(ifeature+1)/nfeature;
2494  pfnProgress(progress,pszMessage,pProgressArg);
2495  }
2496  catch(std::string e){
2497  std::cout << e << std::endl;
2498  continue;
2499  }
2500  catch(int npoint){
2501  if(verbose_opt[0])
2502  std::cout << "number of points read in polygon: " << npoint << std::endl;
2503  continue;
2504  }
2505  }//end of getNextFeature
2506  // if(rbox_opt[0]>0||cbox_opt[0]>0)
2507  // boxWriter.close();
2508  progress=1.0;
2509  pfnProgress(progress,pszMessage,pProgressArg);
2510  ++ilayerWrite;
2511  }//for ilayer
2512  sampleReaderOgr.close();
2513  ogrWriter.close();
2514  if(test_opt.size())
2515  ogrTestWriter.close();
2516  }//else (vector)
2517  progress=1.0;
2518  pfnProgress(progress,pszMessage,pProgressArg);
2519  imgReader.close();
2520 }
2521