Example #1
0
OGRFeature *    OGRBNALayer::BuildFeatureFromBNARecord (BNARecord* record, long fid)
{
    OGRFeature  *poFeature;
    int i;

    poFeature = new OGRFeature( poFeatureDefn );
    for(i=0;i<nIDs;i++)
    {
        poFeature->SetField( i, record->ids[i] ? record->ids[i] : "");
    }
    poFeature->SetFID( fid );
    if (bnaFeatureType == BNA_POINT)
    {
        poFeature->SetGeometryDirectly( new OGRPoint( record->tabCoords[0][0], record->tabCoords[0][1] ) );
    }
    else if (bnaFeatureType == BNA_POLYLINE)
    {
        OGRLineString* lineString = new OGRLineString ();
        lineString->setCoordinateDimension(2);
        lineString->setNumPoints(record->nCoords);
        for(i=0;i<record->nCoords;i++)
        {
            lineString->setPoint(i, record->tabCoords[i][0], record->tabCoords[i][1] );
        }
        poFeature->SetGeometryDirectly(lineString);
    }
    else if (bnaFeatureType == BNA_POLYGON)
    {
        double firstX = record->tabCoords[0][0];
        double firstY = record->tabCoords[0][1];
        int isFirstPolygon = 1;
        double secondaryFirstX = 0, secondaryFirstY = 0;
  
        OGRLinearRing* ring = new OGRLinearRing ();
        ring->setCoordinateDimension(2);
        ring->addPoint(record->tabCoords[0][0], record->tabCoords[0][1] );
  
        /* record->nCoords is really a safe upper bound */
        int nbPolygons = 0;
        OGRPolygon** tabPolygons =
            (OGRPolygon**)CPLMalloc(record->nCoords * sizeof(OGRPolygon*));

        for(i=1;i<record->nCoords;i++)
        {
            ring->addPoint(record->tabCoords[i][0], record->tabCoords[i][1] );
            if (isFirstPolygon == 1 &&
                record->tabCoords[i][0] == firstX &&
                record->tabCoords[i][1] == firstY)
            {
                OGRPolygon* polygon = new OGRPolygon ();
                polygon->addRingDirectly(ring);
                tabPolygons[nbPolygons] = polygon;
                nbPolygons++;
    
                if (i == record->nCoords - 1)
                {
                    break;
                }
    
                isFirstPolygon = 0;
    
                i ++;
                secondaryFirstX = record->tabCoords[i][0];
                secondaryFirstY = record->tabCoords[i][1];
                ring = new OGRLinearRing ();
                ring->setCoordinateDimension(2);
                ring->addPoint(record->tabCoords[i][0], record->tabCoords[i][1] );
            }
            else if (isFirstPolygon == 0 &&
                    record->tabCoords[i][0] == secondaryFirstX &&
                    record->tabCoords[i][1] == secondaryFirstY)
            {

                OGRPolygon* polygon = new OGRPolygon ();
                polygon->addRingDirectly(ring);
                tabPolygons[nbPolygons] = polygon;
                nbPolygons++;

                if (i < record->nCoords - 1)
                {
                    /* After the closing of a subpolygon, the first coordinates of the first polygon */
                    /* should be recalled... in theory */
                    if (record->tabCoords[i+1][0] == firstX &&  record->tabCoords[i+1][1] == firstY)
                    {
                        if (i + 1 == record->nCoords - 1)
                            break;
                        i ++;
                    }
                    else
                    {
#if 0
                        CPLError(CE_Warning, CPLE_AppDefined, 
                                 "Geometry of polygon of fid %d starting at line %d is not strictly conformant. "
                                 "Trying to go on...\n",
                                 fid,
                                 offsetAndLineFeaturesTable[fid].line + 1);
#endif
                    }

                    i ++;
                    secondaryFirstX = record->tabCoords[i][0];
                    secondaryFirstY = record->tabCoords[i][1];
                    ring = new OGRLinearRing ();
                    ring->setCoordinateDimension(2);
                    ring->addPoint(record->tabCoords[i][0], record->tabCoords[i][1] );
                }
                else
                {
#if 0
                    CPLError(CE_Warning, CPLE_AppDefined, 
                        "Geometry of polygon of fid %d starting at line %d is not strictly conformant. Trying to go on...\n",
                        fid,
                        offsetAndLineFeaturesTable[fid].line + 1);
#endif
                }
            }
        }
        if (i == record->nCoords)
        {
            /* Let's be a bit tolerant abount non closing polygons */
            if (isFirstPolygon)
            {
                ring->addPoint(record->tabCoords[0][0], record->tabCoords[0][1] );

                OGRPolygon* polygon = new OGRPolygon ();
                polygon->addRingDirectly(ring);
                tabPolygons[nbPolygons] = polygon;
                nbPolygons++;
            }
        }
        
        if (nbPolygons == 1)
        {
            /* Special optimization here : we directly put the polygon into the multipolygon. */
            /* This should save quite a few useless copies */
            OGRMultiPolygon* multipolygon = new OGRMultiPolygon();
            multipolygon->addGeometryDirectly(tabPolygons[0]);
            poFeature->SetGeometryDirectly(multipolygon);
        }
        else
        {
            int isValidGeometry;
            poFeature->SetGeometryDirectly(
                OGRGeometryFactory::organizePolygons((OGRGeometry**)tabPolygons, nbPolygons, &isValidGeometry, NULL));
            
            if (!isValidGeometry)
            {
                CPLError(CE_Warning, CPLE_AppDefined, 
                        "Geometry of polygon of fid %ld starting at line %d cannot be translated to Simple Geometry. "
                        "All polygons will be contained in a multipolygon.\n",
                        fid,
                        offsetAndLineFeaturesTable[fid].line + 1);
            }
        }

        CPLFree(tabPolygons);
    }
    else
    {
        /* Circle or ellipses are not part of the OGR Simple Geometry, so we discretize them
           into polygons by 1 degree step */
        OGRPolygon* polygon = new OGRPolygon ();
        OGRLinearRing* ring = new OGRLinearRing ();
        ring->setCoordinateDimension(2);
        double center_x = record->tabCoords[0][0];
        double center_y = record->tabCoords[0][1];
        double major_radius = record->tabCoords[1][0];
        double minor_radius = record->tabCoords[1][1];
        if (minor_radius == 0)
            minor_radius = major_radius;
        for(i=0;i<360;i++)
        {
            ring->addPoint(center_x + major_radius * cos(i * (M_PI / 180)),
                           center_y + minor_radius * sin(i * (M_PI / 180)) );
        }
        ring->addPoint(center_x + major_radius, center_y);
        polygon->addRingDirectly  (  ring );
        poFeature->SetGeometryDirectly(polygon);

        poFeature->SetField( nIDs, major_radius);
        poFeature->SetField( nIDs+1, minor_radius);
    }
    
    return poFeature;
}
Example #2
0
void SavePolygons( const std::vector< std::string > InFilenames,
                   const char *OutFilename,
                   const cv::Mat klabels,
                   const std::vector< cv::Mat > raster,
                   const std::vector< u_int32_t > labelpixels,
                   const std::vector< std::vector <double> > sumCH,
                   const std::vector< std::vector <double> > avgCH,
                   const std::vector< std::vector <double> > stdCH,
                   std::vector< std::vector< LINE > >& linelists )
{

  CPLLocaleC oLocaleCForcer();
  CPLErrorReset();

  const char *pszDriverName = "ESRI Shapefile";
  GDALDriver *liDriver;

  liDriver = GetGDALDriverManager()->GetDriverByName(pszDriverName );
  if( liDriver == NULL )
  {
      printf( "\nERROR: %s driver not available.\n", pszDriverName );
      exit( 1 );
  }

  const size_t m_bands = raster.size();
  const size_t m_labels = labelpixels.size();

  GDALDataset *liDS;
  liDS = liDriver->Create( OutFilename, 0, 0, 0, GDT_Unknown, NULL );

  if( liDS == NULL )
  {
      printf( "\nERROR: Creation of output file failed.\n" );
      exit( 1 );
  }

  // dataset
  GDALDataset* piDataset;
  piDataset = (GDALDataset*) GDALOpen(InFilenames[0].c_str(), GA_ReadOnly);

  // spatialref
  OGRSpatialReference oSRS;
  oSRS.SetProjCS( piDataset->GetProjectionRef() );

  OGRLayer *liLayer;
  liLayer = liDS->CreateLayer( "segments", &oSRS, wkbPolygon, NULL );
  if( liLayer == NULL )
  {
      printf( "\nERROR: Layer creation failed.\n" );
      exit( 1 );
  }
  // spatial transform
  double adfGeoTransform[6];
  double oX = 0.0f; double oY = 0.0f;
  double mX = 1.0f; double mY = -1.0f;
  if( piDataset->GetGeoTransform( adfGeoTransform ) == CE_None ) {
      oX = adfGeoTransform[0]; oY = adfGeoTransform[3];
      mX = adfGeoTransform[1]; mY = adfGeoTransform[5];
  }
  GDALClose( (GDALDatasetH) piDataset );

  OGRFieldDefn *clsIdField = new OGRFieldDefn( "CLASS", OFTInteger );
  liLayer->CreateField( clsIdField );

  OGRFieldDefn *pixArField = new OGRFieldDefn( "AREA", OFTInteger );
  liLayer->CreateField( pixArField );

  for ( size_t b = 0; b < m_bands; b++ )
  {
     stringstream value; value << b+1;
     std::string FieldName = value.str() + "_AVERAGE";
     OGRFieldDefn *lavrgField = new OGRFieldDefn( FieldName.c_str(), OFTReal );
     liLayer->CreateField( lavrgField );
  }

  for ( size_t b = 0; b < m_bands; b++ )
  {
     stringstream value; value << b+1;
     std::string FieldName = value.str() + "_STDDEV";
     OGRFieldDefn *lavrgField = new OGRFieldDefn( FieldName.c_str(), OFTReal );
     liLayer->CreateField( lavrgField );
  }

  int multiring = 0;
  printf ("Write File: %s (polygon)\n", OutFilename);
  for (size_t k = 0; k < m_labels; k++)
  {

      if (multiring == 1) {
        k = k - 1;
        multiring = 0;
      }

      if (linelists[k].size() == 0)
        continue;
      // insert field data
      OGRFeature *liFeature;
      liFeature = OGRFeature::CreateFeature( liLayer->GetLayerDefn() );
      liFeature->SetField( "CLASS", (int) k );
      liFeature->SetField( "AREA", (int) labelpixels.at(k) );
      for ( size_t b = 0; b < m_bands; b++ )
      {
        stringstream value; value << b+1;
        std::string FieldName = value.str() + "_AVERAGE";
        liFeature->SetField( FieldName.c_str(), (double) avgCH[b].at(k) );
      }
      for ( size_t b = 0; b < m_bands; b++ )
      {
        stringstream value; value << b+1;
        std::string FieldName = value.str() + "_STDDEV";
        liFeature->SetField( FieldName.c_str(), stdCH[b].at(k) );
      }

      // initiate polygon start
      OGRLinearRing linestring;
      linestring.setCoordinateDimension(2);
      linestring.addPoint( oX + (double) linelists[k][0].sX * mX, oY + mY * (double) linelists[k][0].sY );
      linestring.addPoint( oX + (double) linelists[k][0].eX * mX, oY + mY * (double) linelists[k][0].eY );
      linelists[k].erase( linelists[k].begin() );

      // construct polygon from lines
      while ( linelists[k].size() > 0 )
      {
        if (multiring == 1) break;

        vector<LINE>::iterator it = linelists[k].begin();
        for (; it != linelists[k].end(); ++it)
        {
          double ltX = linestring.getX(linestring.getNumPoints()-1);
          double ltY = linestring.getY(linestring.getNumPoints()-1);
          double csX = oX + (double) it->sX * mX;
          double csY = oY + mY * (double) it->sY;
          double ceX = oX + (double) it->eX * mX;
          double ceY = oY + mY * (double) it->eY;

          if ( ( csX == ltX  ) && ( csY == ltY ) ) {
              linestring.addPoint(ceX, ceY);
              linelists[k].erase(it);
              break;
          }
          if ( ( ceX == ltX  ) && ( ceY == ltY ) ) {
              linestring.addPoint(csX, csY);
              linelists[k].erase(it);
              break;
          }
          if (it == linelists[k].end()-1) {
              multiring = 1;
              break;
          }
        }
      }

      OGRPolygon polygon;
      linestring.closeRings();

      // simplify poligons
      // remove colinear vertices
      OGRLinearRing linesimple;
      float pointPrevX = 0, pointPrevY = 0;
      for (int i = 0; i < linestring.getNumPoints(); i++)
      {
        OGRPoint point;
        linestring.getPoint(i, &point);

        // start
        if ( i == 0)
        {
          linesimple.addPoint( &point );
          pointPrevX = point.getX();
          pointPrevY = point.getY();
          continue;
        }
        // end vertex
        if ( i == linestring.getNumPoints() - 1 )
        {
          linesimple.addPoint( &point );
          continue;
        }

        OGRPoint pointNext;
        linestring.getPoint(i+1, &pointNext);
        //     | x1 y1 1 |
        // det | x2 y2 1 | = 0 => p1,p2,p3 are colinear
        //     | x3 y3 1 |
        // x1*(y2-y3) + x2*(y3-y1) + x3*(y1-y2) == 0
        // only if not colinear with previous and next
        if ( pointPrevX*(point.getY()-pointNext.getY()) +
             point.getX()*(pointNext.getY()-pointPrevY) +
             pointNext.getX()*(pointPrevY-point.getY()) != 0 )
        {
          linesimple.addPoint( &point );
          pointPrevX = point.getX();
          pointPrevY = point.getY();
        }
      }

      // as polygon geometry
      polygon.addRing( &linesimple );
      liFeature->SetGeometry( &polygon );

      if( liLayer->CreateFeature( liFeature ) != OGRERR_NONE )
      {
         printf( "\nERROR: Failed to create feature in shapefile.\n" );
         exit( 1 );
      }
      OGRFeature::DestroyFeature( liFeature );
      GDALTermProgress( (float)(k+1) / (float)(m_labels), NULL, NULL );
  }
  GDALTermProgress( 1.0f, NULL, NULL );

  GDALClose( liDS );

}