void onPrepared()
    {
      if (m_Series.empty())
        return;

      std::vector<GeoVectorSerie>::iterator it;


      // preparation of output directory for series (if any)
      QDir().mkpath(QString::fromStdString(m_OutputPath));


      // preparation of series
      for (it = m_Series.begin();it!=m_Series.end(); ++it)
        prepareSerie(*it);


      // removal of wrong formatted source geovector file
      for (it=m_Series.begin();it!=m_Series.end(); )
      {
        if ((*it).GeoSource == nullptr)
        {
          OPENFLUID_LogWarning("Cannot open geographic source for serie "+(*it).SerieName);
          closeSerie(*it);
          it = m_Series.erase(it);
        }
        else if ((*it).GeoLayer == nullptr)
        {
          OPENFLUID_LogWarning("Cannot open layer in geographic source for serie "+(*it).SerieName);
          closeSerie(*it);
          it = m_Series.erase(it);
        }
        else if ((*it).OFLDIDFieldIndex < 0)
        {
          OPENFLUID_LogWarning("File not found or wrong file format for geographic source for serie "+
                                 (*it).SerieName);
          closeSerie(*it);
          it = m_Series.erase(it);
        }
        else if ((*it).VariablesSet.empty())
        {
          OPENFLUID_LogWarning("No correct variable name in serie "+(*it).SerieName);
          closeSerie(*it);
          it = m_Series.erase(it);
        }
        else
          ++it;
      }


      // Update field names if necessary
      for (it=m_Series.begin();it!=m_Series.end(); ++it)
         updateFieldNamesUsingFormat((*it).VariablesSet);

    }
Exemple #2
0
    void tryOpenGNUplot()
    {
      if (m_TryOpenGNUplot)
      {
        openfluid::utils::ExternalProgram GNUPlotProgram =
            openfluid::utils::ExternalProgram::getRegisteredProgram(openfluid::utils::ExternalProgram::GnuplotProgram);

        if (GNUPlotProgram.isFound())
        {
          QString PersistOption = " ";
          if (m_Persistent) PersistOption = " -persist ";

          QString GNUPlotCommand = QString("\"%1\"%2\"%3\"").arg(GNUPlotProgram.getFullProgramPath())
                                                    .arg(PersistOption)
                                                    .arg(QDir(QString::fromStdString(m_OutputDir))
                                                         .absoluteFilePath("script.gnuplot"));

          QProcess::execute(GNUPlotCommand);
        }
        else
        {
          OPENFLUID_LogWarning("Cannot find GNUPlot");
        }
      }
    }
    void prepareTempDirectory()
    {

      std::string TmpDir;

      OPENFLUID_GetRunEnvironment("dir.temp",TmpDir);

      m_TmpDir = openfluid::tools::Filesystem::makeUniqueSubdirectory(TmpDir,m_TmpSubDirRoot);

      openfluid::tools::Filesystem::makeDirectory(m_TmpDir);

      if (!openfluid::tools::Filesystem::isDirectory(m_TmpDir))
      {
        OPENFLUID_LogWarning("Cannot initialize temporary directory");
        m_OKToGo = false;
        return;
      }

      openfluid::tools::Filesystem::removeDirectory(m_TmpDir+"/"+m_KmzSubDir);
      openfluid::tools::Filesystem::makeDirectory(m_TmpDir+"/"+m_KmzSubDir);

      if (!openfluid::tools::Filesystem::isDirectory(m_TmpDir+"/"+m_KmzSubDir))
      {
        OPENFLUID_LogWarning("Cannot initialize kmz temporary directory");
        m_OKToGo = false;
        return;
      }


      openfluid::tools::Filesystem::makeDirectory(m_TmpDir+"/"+m_KmzSubDir+"/"+m_KmzDataSubDir);

      if (!openfluid::tools::Filesystem::isDirectory(m_TmpDir+"/"+m_KmzSubDir+"/"+m_KmzDataSubDir))
      {
        OPENFLUID_LogWarning("Cannot initialize kmz data temporary directory");
        m_OKToGo = false;
        return;
      }
    }
    void tryOpenGEarth()
    {
      if (m_TryOpenGEarth)
      {
        openfluid::utils::ExternalProgram GEarthProgram =
            openfluid::utils::ExternalProgram::getRegisteredProgram(
                openfluid::utils::ExternalProgram::GoogleEarthProgram);

        if (GEarthProgram.isFound())
        {
          QString GEarthCommand = QString("%1 %2").arg(GEarthProgram.getFullProgramPath())
                                                  .arg(QDir(QString::fromStdString(m_OutputDir))
                                                       .absoluteFilePath(QString::fromStdString(m_OutputFileName)));
          QProcess::execute(GEarthCommand);
        }
        else
        {
          OPENFLUID_LogWarning("Cannot find Google Earth");
        }
      }
    }
Exemple #5
0
    void initParams(const openfluid::ware::WareParams_t& Params)
    {
      openfluid::ware::WareParamsTree ParamsTree;

      try
      {
        ParamsTree.setParams(Params);

        ParamsTree.root().getChildValue("tryopengnuplot",m_TryOpenGNUplot).toBoolean(m_TryOpenGNUplot);
        ParamsTree.root().getChildValue("persistent",m_Persistent).toBoolean(m_Persistent);
        m_Terminal = ParamsTree.root().getChildValue("terminal",m_Terminal);
        m_Output = ParamsTree.root().getChildValue("output",m_Output);

      }
      catch (openfluid::base::FrameworkException& E)
      {
        OPENFLUID_RaiseError(E.getMessage());
      }

      if (!ParamsTree.root().hasChild("serie"))
        OPENFLUID_RaiseError("No serie defined");

      if (!ParamsTree.root().hasChild("graph"))
        OPENFLUID_RaiseError("No graph defined");


      for (auto& Serie : ParamsTree.root().child("serie"))
      {
        std::string SerieID = Serie.first;

        SerieInfo SInfo;
        SInfo.VarName = Serie.second.getChildValue("var","");
        SInfo.UnitsClass = Serie.second.getChildValue("unitsclass","");
        if (SInfo.UnitsClass == "")
        {
          // search for deprecated "unitclass" parameter
          SInfo.UnitsClass = Serie.second.getChildValue("unitclass","");
        }
        std::string UnitIDStr = Serie.second.getChildValue("unitID","");
        SInfo.SourceFile = Serie.second.getChildValue("sourcefile","");
        SInfo.Label = Serie.second.getChildValue("label","");
        SInfo.Style = Serie.second.getChildValue("style","line");
        SInfo.Color = Serie.second.getChildValue("color","");

        if (!SInfo.VarName.empty() &&
            !SInfo.UnitsClass.empty() &&
            openfluid::tools::convertString(UnitIDStr,&SInfo.UnitID))
        {
          openfluid::core::SpatialUnit* TmpU;
          TmpU = mp_SpatialData->spatialUnit(SInfo.UnitsClass,SInfo.UnitID);
          if (TmpU != NULL)
          {
            SInfo.Type = SerieInfo::SERIE_VAR;
            SInfo.Unit = TmpU;
            SInfo.SourceFile = SerieID + "_data.gnuplot";
          }
        }
        else if (!SInfo.SourceFile.empty())
          SInfo.Type = SerieInfo::SERIE_FILE;

        if (SInfo.Type!=SerieInfo::SERIE_UNKNOWN) m_Series[SerieID] = SInfo;
        else OPENFLUID_LogWarning("Serie " + SerieID + "ignored");

      }


      for (auto& Graph : ParamsTree.root().child("graph"))
      {
        std::string GraphID = Graph.first;

         GraphInfo GInfo;

         GInfo.Title = Graph.second.getChildValue("title",GraphID);
         GInfo.Key = Graph.second.getChildValue("key","default");
         GInfo.YLabel = Graph.second.getChildValue("ylabel","");

         std::vector<std::string> SeriesStr =
             openfluid::tools::splitString(Graph.second.getChildValue("series",""),
                                           ";",false);

         for (std::vector<std::string>::const_iterator it = SeriesStr.begin();it != SeriesStr.end();++it)
         {
           if (m_Series.find(*it) != m_Series.end())
             GInfo.Series.push_back(&(m_Series[*it]));
         }

         if (!GInfo.Series.empty())
           m_Graphs[GraphID] = GInfo;
         else
           OPENFLUID_LogWarning("Graph " + GraphID + "ignored");
      }
    }
Exemple #6
0
    void onPrepared()
    {
      if (!m_OKToGo)
        return;

      if (!m_PlotProgram.isFound())
      {
        OPENFLUID_LogWarning("Required GNUplot program not found");
        m_OKToGo = false;
        return;
      }


      std::ostringstream TmpOSS;

      TmpOSS << ((OPENFLUID_GetEndDate().diffInSeconds(OPENFLUID_GetBeginDate())) / 2);

      m_PlotXTics = TmpOSS.str();


      prepareTempDirectory();

      if (!m_OKToGo)
        return;


      openfluid::tools::Filesystem::removeDirectory(m_TmpDir+"/"+m_GNUPlotSubDir);
      openfluid::tools::Filesystem::makeDirectory(m_TmpDir+"/"+m_GNUPlotSubDir);

      if (!openfluid::tools::Filesystem::isDirectory(m_TmpDir+"/"+m_GNUPlotSubDir))
      {
        OPENFLUID_LogWarning("Cannot initialize gnuplot temporary directory");
        m_OKToGo = false;
        return;
      }



      // initialize data files

      for (std::list<KmlSerieInfo>::iterator it=m_KmlSeriesInfos.begin();it!=m_KmlSeriesInfos.end();++it)
      {
        if ((*it).VarsListStr == "*")
        {
          (*it).VarsList =
              mp_SpatialData->spatialUnits((*it).UnitsClass)->list()->front().variables()->getVariablesNames();
        }
        else
        {
          openfluid::tools::tokenizeString((*it).VarsListStr,(*it).VarsList,";");
        }

        if ((*it).VarsList.empty())
        {
          OPENFLUID_LogWarning("Variable list is empty");
          m_OKToGo = false;
          return;
        }


        for (std::map<openfluid::core::UnitID_t,KmlUnitInfoExtra>::iterator it2=(*it).UnitsInfos.begin();
            it2!=(*it).UnitsInfos.end();
            ++it2)
        {

          if ((*it2).second.IsPlotted)
          {
            std::string DataFilename =
                buildFilePath(m_TmpDir+"/"+m_GNUPlotSubDir,
                              (*it).UnitsClass,(*it2).second.UnitID,
                              "","dat");

            (*it2).second.DataFile = new std::ofstream(DataFilename.c_str());
            (*((*it2).second.DataFile)) << "#" << DataFilename << "\n";
          }
        }
      }
    }
Exemple #7
0
    void initParams(const openfluid::ware::WareParams_t& Params)
    {
      openfluid::ware::WareParamsTree ParamsTree;

      try
      {
        ParamsTree.setParams(Params);
      }
      catch (openfluid::base::FrameworkException& E)
      {
        OPENFLUID_LogWarning(E.getMessage());
        m_OKToGo = false;
        return;
      }


      OGRRegisterAll();

      OPENFLUID_GetRunEnvironment("dir.input",m_InputDir);
      OPENFLUID_GetRunEnvironment("dir.output",m_OutputDir);

      // general

      try
      {
        m_Title = ParamsTree.root().getChildValue("title",m_Title);

        m_OutputFileName = ParamsTree.root().getChildValue("kmzfilename",m_OutputFileName);
        ParamsTree.root().getChildValue("tryopengearth",m_TryOpenGEarth).toBoolean(m_TryOpenGEarth);


        if (!ParamsTree.root().hasChild("layers"))
        {
          OPENFLUID_LogWarning("No layer defined");
          m_OKToGo = false;
          return;
        }

        for (auto& Layer : ParamsTree.root().child("layers"))
        {
          KmlSerieInfo KSI;

          KSI.UnitsClass = Layer.second.getChildValue("unitsclass","");
          if (KSI.UnitsClass == "")
          {
            // search for deprecated "unitclass" parameter
            KSI.UnitsClass = Layer.second.getChildValue("unitclass","");
          }


          KSI.VarsListStr = Layer.second.getChildValue("varslist","*");

          // TODO Manage selection of plotted spatial units

          Layer.second.getChildValue("linewidth",1).toInteger(KSI.LineWidth);
          KSI.DefaultColor = Layer.second.getChildValue("defaultcolor","ffffffff");
          KSI.PlottedColor = Layer.second.getChildValue("plottedcolor","ff0000ff");

          KSI.SourceIsDatastore = (Layer.second.getChildValue("source","file").get() == "datastore");
          if (KSI.SourceIsDatastore)
            return;
          else
          {
            KSI.SourceFilename = Layer.second.getChildValue("sourcefile","");
            if (KSI.SourceFilename.empty())
            {
              OPENFLUID_LogWarning("wrong sourcefile format");
              m_OKToGo = false;
              return;
            }
            KSI.SourceFilename = m_InputDir + "/" + KSI.SourceFilename;
          }

          if (transformVectorLayerToKmlGeometry(KSI))
          {
            m_KmlSeriesInfos.push_back(KSI);
          }

        }
      }
      catch (openfluid::base::FrameworkException& E)
      {
        OPENFLUID_LogWarning(E.getMessage());
        m_OKToGo = false;
        return;
      }

      m_OKToGo = true;

      m_KmzSubDir = m_OutputFileName + "_kmz-dir";
      m_GNUPlotSubDir = m_OutputFileName + "_gnuplot-dir";
    }
Exemple #8
0
    void writeKmlFile(const std::string& DocFilePath)
    {
      std::ofstream KmlFile(DocFilePath.c_str());

      KmlFile << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
      KmlFile << "<kml xmlns=\"http://www.opengis.net/kml/2.2\" "
                 "xmlns:gx=\"http://www.google.com/kml/ext/2.2\" "
                 "xmlns:kml=\"http://www.opengis.net/kml/2.2\" xmlns:atom=\"http://www.w3.org/2005/Atom\">\n";

      KmlFile << "<Document>\n";

      KmlFile << "  <name>" << m_Title << "</name>\n";
      KmlFile << "  <open>1</open>\n";

      for (std::list<KmlSerieInfo>::iterator it=m_KmlSeriesInfos.begin();it!=m_KmlSeriesInfos.end();++it)
      {

        std::string TmpStyleID = (*it).UnitsClass +"_style";

        if ((*((*it).UnitsInfos.begin())).second.GeometryType == wkbPolygon)
        {
          KmlFile << "    <Style id=\"" << TmpStyleID << "\"><PolyStyle><color>"<< (*it).DefaultColor
                  << "</color><outline>1</outline></PolyStyle></Style>\n";
          KmlFile << "    <Style id=\"" << TmpStyleID << "_plotted\"><PolyStyle><color>"<< (*it).PlottedColor
                  << "</color></PolyStyle><outline>1</outline></Style>\n";
        }
        else if ((*((*it).UnitsInfos.begin())).second.GeometryType == wkbLineString)
        {
          KmlFile << "    <Style id=\"" << TmpStyleID << "\"><LineStyle><color>"<< (*it).DefaultColor
                  << "</color><width>" << (*it).LineWidth
                  << "</width></LineStyle><PolyStyle><fill>0</fill></PolyStyle></Style>\n";
          KmlFile << "    <Style id=\"" << TmpStyleID << "_plotted\"><LineStyle><color>"
                  << (*it).PlottedColor << "</color><width>" << (*it).LineWidth
                  << "</width></LineStyle><PolyStyle><fill>0</fill></PolyStyle></Style>\n";
        }
        else
        {
          OPENFLUID_LogWarning("Unsupported geometry format in source geometry file");
          m_OKToGo = false;
          return;
        }

        KmlFile << "    <Folder>\n";
        KmlFile << "      <name>" << (*it).UnitsClass << "</name>\n";

        for (std::map<openfluid::core::UnitID_t,KmlUnitInfoExtra>::iterator it2=(*it).UnitsInfos.begin();
            it2!=(*it).UnitsInfos.end();
            ++it2)
        {
          KmlFile << "    <Placemark>\n";


          KmlFile << "      <name>" << (*it).UnitsClass << " " << (*it2).second.UnitID << "</name>\n";

          KmlFile << "      <description>\n<![CDATA[\n";
          KmlFile << "Unit class: " << (*it).UnitsClass << "<br/>\n";
          KmlFile << "Unit ID: " << (*it2).second.UnitID << "<br/>\n";

          KmlFile << "<br/>\n";

          if ((*it2).second.IsPlotted)
          {
            KmlFile << "<img src=\"" << buildFilePath(m_KmzDataSubDir,(*it).UnitsClass,
                                                      (*it2).second.UnitID,"","png") << "\"/>\n";
          }

          KmlFile << "\n]]>\n      </description>\n";


          if ((*it2).second.IsPlotted)
          {
            KmlFile << "      <styleUrl>#" << TmpStyleID << "_plotted</styleUrl>\n";
          }
          else
          {
            KmlFile << "      <styleUrl>#" << TmpStyleID << "</styleUrl>\n";
          }



          if ((*it2).second.GeometryType == wkbPolygon)
          {
            KmlFile << "<Polygon><tessellate>1</tessellate><outerBoundaryIs><LinearRing><coordinates>"
                    << (*it2).second.CoordsStr << "</coordinates></LinearRing></outerBoundaryIs></Polygon>\n";
          }
          else if ((*it2).second.GeometryType == wkbLineString)
          {
            KmlFile << "<LineString><tessellate>1</tessellate><coordinates>" << (*it2).second.CoordsStr
                    << "</coordinates></LineString>\n";
          }
          else
          {
            OPENFLUID_LogWarning("Unsupported geometry format in source geometry file");
            m_OKToGo = false;
            return;
          }


          KmlFile << "    </Placemark>\n";
        }

        KmlFile << "    </Folder>\n";
      }


      KmlFile << "</Document>\n";
      KmlFile << "</kml>\n";
      KmlFile.close();
    }
    void initParams(const openfluid::ware::WareParams_t& Params)
    {
      openfluid::ware::WareParamsTree ParamsTree;

      try
      {
        ParamsTree.setParams(Params);
      }
      catch (openfluid::base::FrameworkException& E)
      {
        OPENFLUID_RaiseError(E.getMessage());
      }

      // checking of mandatory parameters
      if (!ParamsTree.root().hasChild("format"))
      {
        OPENFLUID_LogWarning("Missing GDAL format for output files");
        return;
      }

      if (!ParamsTree.root().hasChild("format"))
      {
        OPENFLUID_LogWarning("No serie defined");
        return;
      }


      // process of format parameter
      m_GDALFormat = ParamsTree.root().getChildValue("format","");

      openfluid::utils::GDALDriversFilesExts_t ValidVectorDrivers =
          openfluid::utils::getOGRFilesDriversForOpenFLUID();

      if (ValidVectorDrivers.find(m_GDALFormat) == ValidVectorDrivers.end())
      {
        OPENFLUID_LogWarning("Unsupported GDAL format for output files");
        return;
      }

      std::string OutfileExt = ValidVectorDrivers[m_GDALFormat].FilesExts.front();


      // process of parameter for optional output subdirectory
      std::string OutSeriesSubdir = ParamsTree.root().getChildValue("outsubdir","");


      // get paths for input dataset and output directory
      OPENFLUID_GetRunEnvironment("dir.input",m_InputPath);
      OPENFLUID_GetRunEnvironment("dir.output",m_OutputPath);

      if (!OutSeriesSubdir.empty())
        m_OutputPath += "/"+OutSeriesSubdir;


      for (auto& Serie : ParamsTree.root().child("geoserie"))
      {
        GeoVectorSerie::WhenModeCases Mode = GeoVectorSerie::WHENCONTINUOUS;
        openfluid::core::Duration_t ContinuousDelay = 1;

        std::string SerieName = Serie.first;

        std::string GeoSourceFilename = Serie.second.getChildValue("sourcefile","");
        std::string VarsString = Serie.second.getChildValue("vars","");
        openfluid::core::UnitsClass_t UnitsClass = Serie.second.getChildValue("unitsclass","");
        std::string WhenModeString = Serie.second.getChildValue("when","");


        if (GeoSourceFilename.empty())
          OPENFLUID_LogWarning("Missing geographic source filename for serie "+SerieName);
        else if (UnitsClass.empty())
          OPENFLUID_LogWarning("Missing units class for serie "+SerieName);
        else if (VarsString.empty())
          OPENFLUID_LogWarning("Missing variables list for serie "+SerieName);
        else
        {
          GeoVectorSerie::VariablesSet_t VarsSet = convertParamToVariableSet(VarsString);

          if (VarsSet.empty())
            OPENFLUID_LogWarning("Format error in variables list for serie "+SerieName);
          else
          {
            if (setWhenModeFromParam(WhenModeString,Mode,ContinuousDelay))
            {
              // everything's OK, add the serie to the active series set
              m_Series.push_back(GeoVectorSerie(SerieName,
                                                m_InputPath + "/" + GeoSourceFilename,
                                                UnitsClass,VarsSet,
                                                OutfileExt,
                                                Mode,ContinuousDelay));
            }
            else
              OPENFLUID_LogWarning("Format error in whenmode for serie "+SerieName);
          }
        }
      }
    }
    void processSerie(GeoVectorSerie& Serie)
    {
      QString IndexStr = "init";

      openfluid::base::SimulationStatus::SimulationStage CurrentStage =
          OPENFLUID_GetCurrentStage();

      bool OKToWrite = false;

      if (CurrentStage == openfluid::base::SimulationStatus::INITIALIZERUN)
      {
        OKToWrite = Serie.WhenMode == GeoVectorSerie::WHENINIT ||
                    Serie.WhenMode == GeoVectorSerie::WHENCONTINUOUS;

      }
      else if (CurrentStage == openfluid::base::SimulationStatus::RUNSTEP)
      {
        if (Serie.WhenMode == GeoVectorSerie::WHENCONTINUOUS)
        {
          openfluid::core::TimeIndex_t CurrentIndex = OPENFLUID_GetCurrentTimeIndex();
          IndexStr = QString("%1").arg(CurrentIndex);

          if (Serie.LatestContinuousIndex + Serie.WhenContinuousDelay < CurrentIndex)
          {
            OKToWrite = true;
            Serie.LatestContinuousIndex = CurrentIndex;
          }
        }
      }
      else if (CurrentStage == openfluid::base::SimulationStatus::FINALIZERUN)
      {
        IndexStr = "final";
        OKToWrite = Serie.WhenMode == GeoVectorSerie::WHENCONTINUOUS ||
                    Serie.WhenMode == GeoVectorSerie::WHENFINAL;
      }
      else
      {
        OPENFLUID_LogWarning("Internal stage error when processing geographic series");
        return;
      }


      if (OKToWrite)
      {
        std::string FullFilePath =
            m_OutputPath + "/" + QString(QString::fromStdString(Serie.OutfilePattern).arg(IndexStr)).toStdString();


        GDALDriver_COMPAT* Driver = GDALGetDriverByName_COMPAT(m_GDALFormat.c_str());

        if (openfluid::tools::Filesystem::isFile(FullFilePath))
        {
          // deletion of an existing file or files set
          GDALDelete_COMPAT(Driver,FullFilePath.c_str());
        }

        GDALDataset_COMPAT* CreatedFile = GDALCreate_COMPAT(Driver,FullFilePath.c_str());

        std::string CreatedLayerName = QFileInfo(QString::fromStdString(FullFilePath)).completeBaseName().toStdString();

        OGRLayer* CreatedLayer = CreatedFile->CreateLayer(CreatedLayerName.c_str(),nullptr,
                                                          Serie.GeoLayer->GetLayerDefn()->GetGeomType(),
                                                          nullptr);

        OGRFieldDefn IDField("OFLD_ID",OFTInteger);
        CreatedLayer->CreateField(&IDField);


        GeoVectorSerie::VariablesSet_t::const_iterator itV;
        GeoVectorSerie::VariablesSet_t::const_iterator itVb = Serie.VariablesSet.begin();
        GeoVectorSerie::VariablesSet_t::const_iterator itVe = Serie.VariablesSet.end();

        for (itV = itVb; itV != itVe; ++itV)
        {
          std::string FieldName = (*itV).second;

          OGRFieldDefn VarField(FieldName.c_str(),OFTReal);
          VarField.SetWidth(24);
          VarField.SetPrecision(15);

          CreatedLayer->CreateField(&VarField);
        }


        OGRFeature* SourceFeature;
        openfluid::core::SpatialUnit* UU;

        Serie.GeoLayer->ResetReading();
        while ((SourceFeature = Serie.GeoLayer->GetNextFeature()) != nullptr)
        {
          int SourceID = SourceFeature->GetFieldAsInteger(Serie.OFLDIDFieldIndex);

          UU = OPENFLUID_GetUnit(Serie.UnitsClass,SourceID);

          if (UU)
          {
            CreatedLayer->GetLayerDefn();

            OGRFeature* CreatedFeature = OGRFeature::CreateFeature(CreatedLayer->GetLayerDefn());

            CreatedFeature->SetGeometry(SourceFeature->GetGeometryRef()->clone());
            CreatedFeature->SetField("OFLD_ID",SourceID);


            for (itV = itVb; itV != itVe; ++itV)
            {
              std::string VarName = (*itV).first;
              std::string FieldName = (*itV).second;
              openfluid::core::DoubleValue CreatedValue = 0.0;
              bool IsValueCreated = false;

              if (FieldName.empty())
                FieldName = VarName;

              openfluid::core::IndexedValue VarValue;

              if (OPENFLUID_IsVariableExist(UU,VarName))
              {
                OPENFLUID_GetLatestVariable(UU,VarName,VarValue);

                if (VarValue.value()->isDoubleValue()) // OpenFLUID value is double
                {
                  CreatedValue = VarValue.value()->asDoubleValue();
                  IsValueCreated = true;
                }
                else if (VarValue.value()->convert(CreatedValue)) // OpenFLUID value can be converted to double
                {
                  IsValueCreated = true;
                }
                else
                {
                  QString Msg = QString("Variable %1 on unit %2#%3 is not a double or a compatible type")
                                .arg(VarName.c_str()).arg(UU->getClass().c_str()).arg(UU->getID());
                  OPENFLUID_LogWarning(Msg.toStdString());
                }
              }
              else
              {
                QString Msg = QString("Variable %1 does not exist on unit %2#%3")
                              .arg(VarName.c_str()).arg(UU->getClass().c_str()).arg(UU->getID());
                OPENFLUID_LogWarning(Msg.toStdString());
              }

              if (IsValueCreated) // OpenFLUID value is written to GIS file only if it is double or converted to double
                CreatedFeature->SetField(FieldName.c_str(),CreatedValue);
            }

            if (CreatedLayer->CreateFeature(CreatedFeature) != OGRERR_NONE)
            {
              QString Msg = QString("Feature for unit %1#%2 cannot be created")
                            .arg(UU->getClass().c_str()).arg(UU->getID());
              OPENFLUID_LogWarning(Msg.toStdString());
            }


            OGRFeature::DestroyFeature(CreatedFeature);
          }
        }
        GDALClose_COMPAT(CreatedFile);
      }
    }
    bool transformVectorLayerToKmlGeometry(KmlLayerInfo<T>& LayerInfo)
    {

      // TODO manage when data are coming from datastore

      GDALDataset_COMPAT* DataSource;
      OGRLayer *Layer;
      OGRFeature *Feature;


      DataSource = GDALOpenRO_COMPAT(LayerInfo.SourceFilename.c_str());
      if( DataSource == nullptr )
      {
        OPENFLUID_LogWarning("Cannot open shapefile "+LayerInfo.SourceFilename+". This Kml output is ignored.");
        return false;
      }

      std::string LayerName = openfluid::tools::Filesystem::basename(LayerInfo.SourceFilename);

      Layer = DataSource->GetLayerByName(LayerName.c_str());

      if (Layer == nullptr)
      {
        OPENFLUID_LogWarning("Cannot open shapefile layer from " + LayerInfo.SourceFilename +
                               ". This Kml output is ignored.");
        return false;
      }


      int OfldIDFieldIndex = Layer->GetLayerDefn()->GetFieldIndex("OFLD_ID");

      if (OfldIDFieldIndex < 0)
      {
        OPENFLUID_LogWarning("Cannot find OFLD_ID attribute in " + LayerInfo.SourceFilename +
                               ". This Kml output is ignored.");
        return false;
      }


      Layer->ResetReading();
      while((Feature = Layer->GetNextFeature()) != nullptr)
      {
        openfluid::core::UnitID_t UnitID = Feature->GetFieldAsInteger(OfldIDFieldIndex);

        if (OPENFLUID_IsUnitExist(LayerInfo.UnitsClass,UnitID))
        {

          OGRGeometry *Geometry;

          Geometry = Feature->GetGeometryRef();

          std::stringstream CoordSS;

          CoordSS << std::fixed << std::setprecision(12);

          T KUI;

          KUI.UnitID = UnitID;

          if (Geometry != nullptr)
          {

            if (Geometry->getGeometryType() != wkbPolygon && Geometry->getGeometryType() != wkbLineString)
            {
              OPENFLUID_LogWarning("Unsupported geometry type in " + LayerInfo.SourceFilename +
                                     ". This Kml output is ignored.");
              return false;
            }

            KUI.GeometryType = Geometry->getGeometryType();

            // polygons
            if (Geometry->getGeometryType() == wkbPolygon)
            {
              OGRLinearRing* Ring;

              Ring = ((OGRPolygon*)(Geometry))->getExteriorRing();

              int NumPoints = Ring->getNumPoints()-1;

              for (int i=0;i<NumPoints;i++)
              {
                OGRPoint *Point = new OGRPoint();
                Ring->getPoint(i,Point);
                CoordSS << " " << Point->getX() << "," << Point->getY();
                delete Point;
              }

              // close the polygon
              if (NumPoints > 0)
              {
                OGRPoint *Point = new OGRPoint();
                Ring->getPoint(0,Point);
                CoordSS << " " << Point->getX() << "," << Point->getY();
                delete Point;
              }

            }


            // line strings
            if (Geometry->getGeometryType() == wkbLineString)
            {

              OGRLineString* LineString;
              LineString = (OGRLineString*)(Geometry);

              int NumPoints = LineString->getNumPoints();

              for (int i=0;i<NumPoints;i++)
              {
                OGRPoint *Point = new OGRPoint();
                LineString->getPoint(i,Point);
                CoordSS << " " << Point->getX() << "," << Point->getY();
                delete Point;
              }
            }

            KUI.CoordsStr = CoordSS.str();

            LayerInfo.UnitsInfos[UnitID] = KUI;

          }
          else
          {
            OPENFLUID_LogWarning("Wrong geometry reference in " + LayerInfo.SourceFilename +
                                   ". This Kml output is ignored.");
            return false;
          }

        }
        OGRFeature::DestroyFeature(Feature);
      }


      GDALClose_COMPAT(DataSource);


      return true;
    }