コード例 #1
0
ファイル: mdal_gdal.cpp プロジェクト: AlisterH/Quantum-GIS
void MDAL::LoaderGdal::addDatasetGroups()
{
  // Add dataset to mMesh
  for ( data_hash::const_iterator band = mBands.begin(); band != mBands.end(); band++ )
  {
    std::shared_ptr<DatasetGroup> group = std::make_shared< DatasetGroup >();
    group->uri = mFileName;
    group->setName( band->first );
    group->isOnVertices = true;

    for ( timestep_map::const_iterator time_step = band->second.begin(); time_step != band->second.end(); time_step++ )
    {
      std::vector<GDALRasterBandH> raster_bands = time_step->second;
      bool is_vector = ( raster_bands.size() > 1 );

      std::shared_ptr<MDAL::Dataset> dataset = std::make_shared< MDAL::Dataset >();
      group->isScalar = !is_vector;

      dataset->time = time_step->first;
      dataset->values.resize( meshGDALDataset()->mNPoints );
      dataset->active.resize( meshGDALDataset()->mNVolumes );
      dataset->parent = group.get();

      for ( std::vector<GDALRasterBandH>::size_type i = 0; i < raster_bands.size(); ++i )
      {
        addDataToOutput( raster_bands[i], dataset, is_vector, i == 0 );
      }
      activateFaces( dataset );

      group->datasets.push_back( dataset );
    }
    mMesh->datasetGroups.push_back( group );
  }
}
コード例 #2
0
ファイル: mdal_gdal.cpp プロジェクト: FERRATON/QGIS
void MDAL::DriverGdal::createMesh()
{
  Vertices vertices( meshGDALDataset()->mNPoints );
  bool is_longitude_shifted = initVertices( vertices );

  Faces faces( meshGDALDataset()->mNVolumes );
  initFaces( vertices, faces, is_longitude_shifted );

  mMesh.reset( new MemoryMesh(
                 name(),
                 vertices.size(),
                 faces.size(),
                 4, //maximum quads
                 computeExtent( vertices ),
                 mFileName
               )
             );
  mMesh->vertices = vertices;
  mMesh->faces = faces;
  bool proj_added = addSrcProj();
  if ( ( !proj_added ) && is_longitude_shifted )
  {
    std::string wgs84( "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs" );
    mMesh->setSourceCrs( wgs84 );
  }
}
コード例 #3
0
ファイル: mdal_gdal.cpp プロジェクト: FERRATON/QGIS
void MDAL::DriverGdal::addDataToOutput( GDALRasterBandH raster_band, std::shared_ptr<MemoryDataset> tos, bool is_vector, bool is_x )
{
  assert( raster_band );

  double nodata =  GDALGetRasterNoDataValue( raster_band, nullptr );
  unsigned int mXSize = meshGDALDataset()->mXSize;
  unsigned int mYSize = meshGDALDataset()->mYSize;

  double *values = tos->values();

  for ( unsigned int y = 0; y < mYSize; ++y )
  {
    // buffering per-line
    CPLErr err = GDALRasterIO(
                   raster_band,
                   GF_Read,
                   0, //nXOff
                   static_cast<int>( y ), //nYOff
                   static_cast<int>( mXSize ), //nXSize
                   1, //nYSize
                   mPafScanline, //pData
                   static_cast<int>( mXSize ), //nBufXSize
                   1, //nBufYSize
                   GDT_Float64, //eBufType
                   0, //nPixelSpace
                   0 //nLineSpace
                 );
    if ( err != CE_None )
    {
      throw MDAL_Status::Err_InvalidData;
    }

    for ( unsigned int x = 0; x < mXSize; ++x )
    {
      unsigned int idx = x + mXSize * y;
      double val = mPafScanline[x];
      if ( !MDAL::equals( val, nodata ) )
      {
        // values is prepolulated with NODATA values, so store only legal values
        if ( is_vector )
        {
          if ( is_x )
          {
            values[2 * idx] = val;
          }
          else
          {
            values[2 * idx + 1] = val;
          }
        }
        else
        {
          values[idx] = val;
        }
      }
    }
  }
}
コード例 #4
0
ファイル: mdal_gdal.cpp プロジェクト: AlisterH/Quantum-GIS
void MDAL::LoaderGdal::initFaces( Vertices &Vertexs, Faces &Faces, bool is_longitude_shifted )
{
  int reconnected = 0;
  unsigned int mXSize = meshGDALDataset()->mXSize;
  unsigned int mYSize = meshGDALDataset()->mYSize;

  size_t i = 0;

  for ( unsigned int y = 0; y < mYSize - 1; ++y )
  {
    for ( unsigned int x = 0; x < mXSize - 1; ++x )
    {
      if ( is_longitude_shifted &&
           ( Vertexs[x + mXSize * y].x > 0.0 ) &&
           ( Vertexs[x + 1 + mXSize * y].x < 0.0 ) )
        // omit border face
      {
        --reconnected;
        continue;
      }

      if ( is_longitude_shifted && ( x == 0 ) )
      {
        // create extra faces around prime meridian
        Faces[i].resize( 4 );
        Faces[i][0] = mXSize * ( y + 1 );
        Faces[i][3] = mXSize * y;
        Faces[i][2] = mXSize - 1 + mXSize * y;
        Faces[i][1] = mXSize - 1 + mXSize * ( y + 1 );

        ++reconnected;
        ++i;
      }

      // other faces
      Faces[i].resize( 4 );
      Faces[i][0] = x + 1 + mXSize * ( y + 1 );
      Faces[i][3] = x + 1 + mXSize * y;
      Faces[i][2] = x + mXSize * y;
      Faces[i][1] = x + mXSize * ( y + 1 );

      ++i;
    }
  }
  //make sure we have discarded same amount of faces that we have added
  assert( reconnected == 0 );
}
コード例 #5
0
ファイル: mdal_gdal.cpp プロジェクト: AlisterH/Quantum-GIS
void MDAL::LoaderGdal::createMesh()
{
  Vertices vertices( meshGDALDataset()->mNPoints );
  bool is_longitude_shifted = initVertices( vertices );

  Faces faces( meshGDALDataset()->mNVolumes );
  initFaces( vertices, faces, is_longitude_shifted );

  mMesh.reset( new Mesh() );
  mMesh->vertices = vertices;
  mMesh->faces = faces;
  bool proj_added = addSrcProj();
  if ( ( !proj_added ) && is_longitude_shifted )
  {
    std::string wgs84( "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs" );
    mMesh->setSourceCrs( wgs84 );
  }
}
コード例 #6
0
ファイル: mdal_gdal.cpp プロジェクト: AlisterH/Quantum-GIS
bool MDAL::LoaderGdal::addSrcProj()
{
  std::string proj = meshGDALDataset()->mProj;
  if ( !proj.empty() )
  {
    mMesh->setSourceCrsFromWKT( proj );
    return true;
  }
  return false;
}
コード例 #7
0
ファイル: mdal_gdal.cpp プロジェクト: AlisterH/Quantum-GIS
bool MDAL::LoaderGdal::initVertices( Vertices &vertices )
{
  Vertex *VertexsPtr = vertices.data();
  unsigned int mXSize = meshGDALDataset()->mXSize;
  unsigned int mYSize = meshGDALDataset()->mYSize;
  const double *mGT = meshGDALDataset()->mGT;

  for ( unsigned int y = 0; y < mYSize; ++y )
  {
    for ( unsigned int x = 0; x < mXSize; ++x, ++VertexsPtr )
    {
      // VertexsPtr->setId(x + mXSize*y);
      VertexsPtr->x = mGT[0] + ( x + 0.5 ) * mGT[1] + ( y + 0.5 ) * mGT[2];
      VertexsPtr->y = mGT[3] + ( x + 0.5 ) * mGT[4] + ( y + 0.5 ) * mGT[5];
      VertexsPtr->z = 0.0;
    }
  }

  BBox extent = computeExtent( vertices );
  // we want to detect situation when there is whole earth represented in dataset
  bool is_longitude_shifted = ( extent.minX >= 0.0 ) &&
                              ( fabs( extent.minX + extent.maxX - 360.0 ) < 1.0 ) &&
                              ( extent.minY >= -90.0 ) &&
                              ( extent.maxX <= 360.0 ) &&
                              ( extent.maxX > 180.0 ) &&
                              ( extent.maxY <= 90.0 );
  if ( is_longitude_shifted )
  {
    for ( Vertices::size_type n = 0; n < vertices.size(); ++n )
    {
      if ( vertices[n].x > 180.0 )
      {
        vertices[n].x -= 360.0;
      }
    }
  }

  return is_longitude_shifted;
}
コード例 #8
0
ファイル: mdal_gdal.cpp プロジェクト: AlisterH/Quantum-GIS
void MDAL::LoaderGdal::activateFaces( std::shared_ptr<Dataset> tos )
{
  // Activate only Faces that do all Vertex's outputs with some data
  for ( unsigned int idx = 0; idx < meshGDALDataset()->mNVolumes; ++idx )
  {
    Face elem = mMesh->faces.at( idx );

    if ( tos->values[elem[0]].noData ||
         tos->values[elem[1]].noData ||
         tos->values[elem[2]].noData ||
         tos->values[elem[3]].noData )
    {
      tos->active[idx] = 0; //NOT ACTIVE
    }
    else
    {
      tos->active[idx] = 1; //ACTIVE
    }
  }
}
コード例 #9
0
ファイル: mdal_gdal.cpp プロジェクト: FERRATON/QGIS
void MDAL::DriverGdal::activateFaces( std::shared_ptr<MemoryDataset> tos )
{
  // only for data on vertices
  if ( !tos->group()->isOnVertices() )
    return;

  bool isScalar = tos->group()->isScalar();

  // Activate only Faces that do all Vertex's outputs with some data
  int *active = tos->active();
  const double *values = tos->constValues();

  for ( unsigned int idx = 0; idx < meshGDALDataset()->mNVolumes; ++idx )
  {
    Face elem = mMesh->faces.at( idx );
    for ( size_t i = 0; i < 4; ++i )
    {
      const size_t vertexIndex = elem[i];
      if ( isScalar )
      {
        double val = values[vertexIndex];
        if ( std::isnan( val ) )
        {
          active[idx] = 0; //NOT ACTIVE
          break;
        }
      }
      else
      {
        double x = values[2 * vertexIndex];
        double y = values[2 * vertexIndex + 1];
        if ( std::isnan( x ) || std::isnan( y ) )
        {
          active[idx] = 0; //NOT ACTIVE
          break;
        }
      }
    }
  }
}
コード例 #10
0
ファイル: mdal_gdal.cpp プロジェクト: AlisterH/Quantum-GIS
std::unique_ptr<MDAL::Mesh> MDAL::LoaderGdal::load( MDAL_Status *status )
{
  if ( status ) *status = MDAL_Status::None ;

  mPafScanline = nullptr;
  mMesh.reset();

  try
  {
    registerDriver();

    // some formats like NETCFD has data stored in subdatasets
    std::vector<std::string> subdatasets = parseDatasetNames( mFileName );

    // First parse ALL datasets/bands to gather vector quantities
    // if case they are splitted in different subdatasets
    for ( auto iter = subdatasets.begin(); iter != subdatasets.end(); ++iter )
    {
      std::string gdal_dataset_name = *iter;
      // Parse dataset parameters and projection
      MDAL::GdalDataset *cfGDALDataset = new MDAL::GdalDataset;
      cfGDALDataset->init( gdal_dataset_name );

      if ( !mMesh )
      {
        // If it is first dataset, create mesh from it
        gdal_datasets.push_back( cfGDALDataset );

        // Init memory for data reader
        mPafScanline = new double [cfGDALDataset->mXSize];

        // Create mMesh
        createMesh();

        // Parse bands
        parseRasterBands( cfGDALDataset );

      }
      else if ( meshes_equals( meshGDALDataset(), cfGDALDataset ) )
      {
        gdal_datasets.push_back( cfGDALDataset );
        // Parse bands
        parseRasterBands( cfGDALDataset );
      }
      else
      {
        // Do not use
        delete cfGDALDataset;
      }
    }

    // Create MDAL datasets
    addDatasetGroups();
  }
  catch ( MDAL_Status error )
  {
    if ( status ) *status = ( error );
    mMesh.reset();
  }

  for ( auto it = gdal_datasets.begin(); it != gdal_datasets.end(); ++it )
  {
    delete ( *it );
  }
  gdal_datasets.clear();

  if ( mPafScanline ) delete[] mPafScanline;

  // do not allow mesh without any valid datasets
  if ( mMesh && ( mMesh->datasetGroups.empty() ) )
  {
    if ( status ) *status = MDAL_Status::Err_InvalidData;
    mMesh.reset();
  }
  return std::unique_ptr<Mesh>( mMesh.release() );
}
コード例 #11
0
ファイル: mdal_gdal.cpp プロジェクト: AlisterH/Quantum-GIS
void MDAL::LoaderGdal::addDataToOutput( GDALRasterBandH raster_band, std::shared_ptr<Dataset> tos, bool is_vector, bool is_x )
{
  assert( raster_band );

  double nodata =  GDALGetRasterNoDataValue( raster_band, nullptr );
  unsigned int mXSize = meshGDALDataset()->mXSize;
  unsigned int mYSize = meshGDALDataset()->mYSize;

  for ( unsigned int y = 0; y < mYSize; ++y )
  {
    // buffering per-line
    CPLErr err = GDALRasterIO(
                   raster_band,
                   GF_Read,
                   0, //nXOff
                   static_cast<int>( y ), //nYOff
                   static_cast<int>( mXSize ), //nXSize
                   1, //nYSize
                   mPafScanline, //pData
                   static_cast<int>( mXSize ), //nBufXSize
                   1, //nBufYSize
                   GDT_Float64, //eBufType
                   0, //nPixelSpace
                   0 //nLineSpace
                 );
    if ( err != CE_None )
    {
      throw MDAL_Status::Err_InvalidData;
    }

    for ( unsigned int x = 0; x < mXSize; ++x )
    {
      unsigned int idx = x + mXSize * y;
      double val = mPafScanline[x];
      bool noData = false;
      if ( MDAL::equals( val, nodata ) )
      {
        // store all nodata value as this hardcoded number
        val = MDAL_NODATA;
        noData = true;
      }

      if ( is_vector )
      {
        if ( is_x )
        {
          tos->values[idx].x = val;
          tos->values[idx].noData = noData;
        }
        else
        {
          tos->values[idx].y = val;
          tos->values[idx].noData = noData;
        }
      }
      else
      {
        tos->values[idx].x = val;
        tos->values[idx].noData = noData;
      }
    }
  }
}
コード例 #12
0
ファイル: mdal_gdal.cpp プロジェクト: FERRATON/QGIS
std::unique_ptr<MDAL::Mesh> MDAL::DriverGdal::load( const std::string &fileName, MDAL_Status *status )
{
  mFileName = fileName;
  if ( status ) *status = MDAL_Status::None ;

  mPafScanline = nullptr;
  mMesh.reset();

  try
  {
    registerDriver();

    // some formats like NETCFD has data stored in subdatasets
    std::vector<std::string> subdatasets = parseDatasetNames( mFileName );

    // First parse ALL datasets/bands to gather vector quantities
    // if case they are splitted in different subdatasets
    for ( auto iter = subdatasets.begin(); iter != subdatasets.end(); ++iter )
    {
      std::string gdal_dataset_name = *iter;
      // Parse dataset parameters and projection
      std::shared_ptr<MDAL::GdalDataset> cfGDALDataset = std::make_shared<MDAL::GdalDataset>();
      cfGDALDataset->init( gdal_dataset_name );

      if ( !mMesh )
      {
        // If it is first dataset, create mesh from it
        gdal_datasets.push_back( cfGDALDataset );

        // Init memory for data reader
        mPafScanline = new double [cfGDALDataset->mXSize];

        // Create mMesh
        createMesh();

        // Parse bands
        parseRasterBands( cfGDALDataset.get() );

      }
      else if ( meshes_equals( meshGDALDataset(), cfGDALDataset.get() ) )
      {
        gdal_datasets.push_back( cfGDALDataset );
        // Parse bands
        parseRasterBands( cfGDALDataset.get() );
      }
    }

    // Fix consistency of groups
    // It can happen that we thought that the
    // group is vector based on name, but it could be just coicidence
    // or clash in naming
    fixRasterBands();

    // Create MDAL datasets
    addDatasetGroups();
  }
  catch ( MDAL_Status error )
  {
    if ( status ) *status = ( error );
    mMesh.reset();
  }

  gdal_datasets.clear();

  if ( mPafScanline ) delete[] mPafScanline;

  // do not allow mesh without any valid datasets
  if ( mMesh && ( mMesh->datasetGroups.empty() ) )
  {
    if ( status ) *status = MDAL_Status::Err_InvalidData;
    mMesh.reset();
  }
  return std::unique_ptr<Mesh>( mMesh.release() );
}