Skip to content
Snippets Groups Projects
otbGenerateRPCSensorModel.cxx 8.86 KiB
Newer Older
  • Learn to ignore specific revisions
  • /*=========================================================================
    
      Program:   ORFEO Toolbox
      Language:  C++
      Date:      $Date$
      Version:   $Revision$
    
    
      Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
      See OTBCopyright.txt for details.
    
    
      This software is distributed WITHOUT ANY WARRANTY; without even
      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
      PURPOSE.  See the above copyright notices for more information.
    
      =========================================================================*/
    // Wrappers
    #include "otbWrapperApplication.h"
    #include "otbWrapperApplicationFactory.h"
    #include "otbWrapperChoiceParameter.h"
    #include "otbWrapperElevationParametersHandler.h"
    #include "otbWrapperMapProjectionParametersHandler.h"
    #include "otbSensorModelAdapter.h"
    #include "otbRPCSolverAdapter.h"
    #include "itkPoint.h"
    #include "itkEuclideanDistance.h"
    #include "otbGenericRSTransform.h"
    #include "otbOGRDataSourceWrapper.h"
    #include "ogrsf_frmts.h"
    
    namespace otb
    {
    namespace Wrapper
    {
    class GenerateRPCSensorModel : public Application
    {
    public:
      /** Standard class typedefs. */
      typedef GenerateRPCSensorModel             Self;
      typedef Application                   Superclass;
      typedef itk::SmartPointer<Self>       Pointer;
      typedef itk::SmartPointer<const Self> ConstPointer;
    
      typedef otb::RPCSolverAdapter::Point3DType              Point3DType;
      typedef otb::RPCSolverAdapter::Point2DType              Point2DType;
      typedef itk::Statistics::EuclideanDistance<Point3DType> DistanceType;
    
      typedef otb::RPCSolverAdapter::GCPType           TiePointType;
      typedef otb::RPCSolverAdapter::GCPsContainerType TiePointsType;
    
      typedef otb::GenericRSTransform<double,3,3>  RSTransformType;
      
      /** Standard macro */
      itkNewMacro(Self);
      itkTypeMacro(GenerateRPCSensorModel, otb::Application);
    
    private:
      void DoInit()
      {
        SetName("GenerateRPCSensorModel");
        SetDescription("TODO");
        
        SetDocName("Generate a RPC sensor model");
        SetDocLongDescription("TODO");
    
        AddDocTag(Tags::Geometry);
    
        SetDocLimitations("None");
        SetDocSeeAlso("OrthoRectication,HomologousPointsExtraction,RefineSensorModel");
        SetDocAuthors("OTB-Team");
       
        AddParameter(ParameterType_OutputFilename,"outgeom","Output geom file");
        SetParameterDescription("outgeom","Geom file containing the generated RPC sensor model");
    
        AddParameter(ParameterType_InputFilename,"inpoints","Input file containing tie points");
        SetParameterDescription("inpoints","Input file containing tie points. Points are stored in following format: row col lon lat. Line beginning with # are ignored.");
    
        AddParameter(ParameterType_OutputFilename,"outstat","Output file containing output precision statistics");
        SetParameterDescription("outstat","Output file containing the following info: ref_lon ref_lat elevation predicted_lon predicted_lat x_error_ref(meters) y_error_ref(meters) global_error_ref(meters) x_error(meters) y_error(meters) overall_error(meters)");
        MandatoryOff("outstat");
        DisableParameter("outstat");
    
        AddParameter(ParameterType_OutputFilename,"outvector","Output vector file with residues");
        SetParameterDescription("outvector","File containing segments representing residues");
        MandatoryOff("outvector");
        DisableParameter("outvector");
    
        // Build the Output Map Projection
        MapProjectionParametersHandler::AddMapProjectionParameters(this, "map");
    
        // Elevation
        ElevationParametersHandler::AddElevationParameters(this, "elev");
    
        // Doc example parameter settings
        SetDocExampleParameterValue("ingeom", "input.geom");
        SetDocExampleParameterValue("outgeom","output.geom");
        SetDocExampleParameterValue("inpoints","points.txt");
        SetDocExampleParameterValue("map","epsg");
        SetDocExampleParameterValue("map.epsg.code","32631");
      }
    
      void DoUpdateParameters()
      {
        // Nothing to do here : all parameters are independent
      }
    
      void DoExecute()
      {
        OGRMultiLineString mls;
        
        // Setup the DEM Handler
        otb::Wrapper::ElevationParametersHandler::SetupDEMHandlerFromElevationParameters(this,"elev");
        
        // Parse the input file for ground control points
        std::ifstream ifs;
        ifs.open(GetParameterString("inpoints").c_str());
        
        TiePointsType tiepoints;
      
      while(!ifs.eof())
        {
        std::string line;
        std::getline(ifs,line);
        
        double x,y,z,lat,lon;
        
        // Avoid commented lines or too short ones
        if (!line.empty() && line[0] != '#')
          {
          // retrieve the x component
          std::string::size_type pos = 0;
          std::string::size_type nextpos = line.find_first_of("\t", pos);
          x = atof(line.substr(pos, nextpos).c_str());
          pos = nextpos + 1;
          nextpos = line.find_first_of("\t", pos);
          y = atof(line.substr(pos, nextpos).c_str());
          pos = nextpos + 1;
          nextpos = line.find_first_of("\t", pos);
          lon = atof(line.substr(pos, nextpos).c_str());
          pos = nextpos + 1;
          nextpos = line.find_first_of("\t", pos);
          lat = atof(line.substr(pos, nextpos).c_str());
          
          z = otb::DEMHandler::Instance()->GetHeightAboveEllipsoid(lon,lat);
    
          otbAppLogINFO("Adding tie point x="<<x<<", y="<<y<<", z="<<z<<", lon="<<lon<<", lat="<<lat);
    
          Point2DType p1;
          Point3DType p2;
          p1[0]=x;
          p1[1]=y;
          p2[0]=lon;
          p2[1]=lat;
          p2[2]=z;
    
          tiepoints.push_back(std::make_pair(p1,p2));
    
          }
        }
      ifs.close();
      
      otbAppLogINFO("Optimization in progress ...");
    
      double rms;
    
      otb::RPCSolverAdapter::Solve(tiepoints,rms,GetParameterString("outgeom"));
    
      otbAppLogINFO("Done.\n");
    
      otb::SensorModelAdapter::Pointer sm     = otb::SensorModelAdapter::New();
      sm->ReadGeomFile(GetParameterString("outgeom"));
    
      double rmse = 0;
      double rmsex = 0;
      double rmsey = 0;
    
      double meanx = 0;
      double meany = 0;
    
      DistanceType::Pointer distance = DistanceType::New();
    
      RSTransformType::Pointer rsTransform = RSTransformType::New();
      rsTransform->SetOutputProjectionRef(MapProjectionParametersHandler::GetProjectionRefFromChoice(this, "map"));
      rsTransform->InstanciateTransform();
    
      std::ofstream ofs;
      ofs<<std::fixed;
      ofs.precision(12);
      if(IsParameterEnabled("outstat"))
        {
        ofs.open(GetParameterString("outstat").c_str());
        ofs<<"#ref_lon ref_lat elevation predicted_lon predicted_lat x_error(meters) y_error(meters) global_error(meters)"<<std::endl;
        }
    
      for(TiePointsType::const_iterator it = tiepoints.begin();
          it!=tiepoints.end(); ++it)
        {
        Point3DType tmpPoint,ref;
    
        sm->ForwardTransformPoint(it->first[0],it->first[1],it->second[2],tmpPoint[0],tmpPoint[1],tmpPoint[2]);
    
    
        tmpPoint = rsTransform->TransformPoint(tmpPoint);
    
        ref[0] = it->second[0];
        ref[1] = it->second[1];
        ref[2] = it->second[2];
    
        ref = rsTransform->TransformPoint(ref);
    
        OGRLineString ls;
        ls.addPoint(tmpPoint[0],tmpPoint[1]);
        ls.addPoint(ref[0],ref[1]);
        mls.addGeometry(&ls);
    
        double gerror = distance->Evaluate(ref,tmpPoint);
        double xerror = ref[0]-tmpPoint[0];
        double yerror = ref[1]-tmpPoint[1];
        
        if(IsParameterEnabled("outstat"))
          ofs<<ref[0]<<"\t"<<ref[1]<<"\t"<<it->first[2]<<"\t"<<tmpPoint[0]<<"\t"<<tmpPoint[1]<<"\t"<<tmpPoint[2]<<"\t"<<xerror<<"\t"<<yerror<<"\t"<<gerror<<std::endl;
    
        rmse += gerror*gerror;
        rmsex+= xerror*xerror;
        rmsey+= yerror*yerror;
    
        meanx += xerror;
        meany += yerror;
        }
    
      rmse/=tiepoints.size();
    
      rmsex/=tiepoints.size();
    
      rmsey/=tiepoints.size();
    
    
      meanx/=tiepoints.size();
      meany/=tiepoints.size();
    
    
      double stdevx = vcl_sqrt(rmsex - meanx * meanx);
      double stdevy = vcl_sqrt(rmsey - meany * meany);
    
    
      rmse=vcl_sqrt(rmse);
      rmsex=vcl_sqrt(rmsex);
      rmsey=vcl_sqrt(rmsey);
    
      otbAppLogINFO("Estimation of final accuracy: ");
    
      otbAppLogINFO("Overall Root Mean Square Error: "<<rmse<<" meters");
      otbAppLogINFO("X Mean Error: "<<meanx<<" meters");
      otbAppLogINFO("X standard deviation: "<<stdevx<<" meters");
      otbAppLogINFO("X Root Mean Square Error: "<<rmsex<<" meters");
      otbAppLogINFO("Y Mean Error: "<<meany<<" meters");
      otbAppLogINFO("Y standard deviation: "<<stdevy<<" meters");
      otbAppLogINFO("Y Root Mean Square Error: "<<rmsey<<" meters");
    
    
      if(IsParameterEnabled("outstat"))
        ofs.close();
    
    
    if(IsParameterEnabled("outvector"))
      {
      // Create the datasource (for matches export)
      otb::ogr::Layer layer(NULL, false);
      otb::ogr::DataSource::Pointer ogrDS;
      
      ogrDS = otb::ogr::DataSource::New(GetParameterString("outvector"), otb::ogr::DataSource::Modes::Overwrite);
      std::string projref = MapProjectionParametersHandler::GetProjectionRefFromChoice(this, "map");
      OGRSpatialReference oSRS(projref.c_str());
      
      // and create the layer
      layer = ogrDS->CreateLayer("matches", &oSRS, wkbMultiLineString);
      OGRFeatureDefn & defn = layer.GetLayerDefn();
      ogr::Feature feature(defn);
      
      feature.SetGeometry(&mls);
      layer.CreateFeature(feature);
      }
      }
    };
    }
    }
    
    OTB_APPLICATION_EXPORT(otb::Wrapper::GenerateRPCSensorModel)