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; }
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 ); }