[gdal-dev] S57 questions

ogr user mrxonx at hotmail.com
Wed Dec 16 15:57:40 EST 2009


In case anyone is interested, here is a simple patch for the polygon
outer ring issue. It's not a perfect way to detect the outer ring since
in some cases inner rings can have the *same* envelope area as the outer
ring, but in any practical chart case this works just fine. Calculating
actual ring area would work better, but would be slower (though not by
much considering that getEnvelope does not use any cached envelope
information and keeps iterating over all the vertices). In any case,
this patch solved the issue I was grappling with and may help in many
other similar cases.

Pardon the trivial variable names - I am not quite familiar with
variable naming convention in OGR.
This would also work faster if there was a way to delete a ring from
polygon, so we wouldn't have to copy it over.
--Make


===================================================================
--- ogr/ograssemblepolygon.cpp    (revision 17)
+++ ogr/ograssemblepolygon.cpp    (working copy)
@@ -276,6 +276,40 @@
 // perhaps even ordering the direction of rings, though this isn't
 // required by the OGC geometry model.
 
+    double maxarea, tarea;
+    int maxring = -1, rn, rcount;
+    OGREnvelope tenv;
+    OGRLinearRing *tring;
+
+    tring = poPolygon->getExteriorRing();
+    if (tring) tring->getEnvelope(&tenv);
+    maxarea = (tenv.MaxX - tenv.MinX) * (tenv.MaxY - tenv.MinY);
+
+    rcount = poPolygon->getNumInteriorRings();
+    for (rn = 0; rn < rcount; ++rn) {
+      tring = poPolygon->getInteriorRing(rn);
+      tring->getEnvelope(&tenv);
+      tarea = (tenv.MaxX - tenv.MinX) * (tenv.MaxY - tenv.MinY);
+      if (tarea > maxarea) {
+         maxarea = tarea;
+         maxring = rn;
+      }
+    }
+
+    if (maxring != -1) {
+       OGRPolygon  *poNewPoly = new OGRPolygon();
+
+       poNewPoly->addRing(poPolygon->getInteriorRing(maxring));
+       poNewPoly->addRing(poPolygon->getExteriorRing());
+       for (rn = 0; rn < rcount; ++rn) {
+          if (rn == maxring) continue;
+          poNewPoly->addRing(poPolygon->getInteriorRing(rn));
+       }
+
+       delete poPolygon;
+       poPolygon = poNewPoly;
+    }
+     
     if( peErr != NULL )
     {
         if( bSuccess )

Frank Warmerdam wrote:
>
> Mike,
>
> The S-57 driver uses OGRBuildPolygonFromEdges() to form the set of lines
> into a polygon.  No effort is currently made to properly represent
> exterior vs. interior rings as is required by the simple features
> geometry
> specification.
>
> So, I believe this is a bug of the S-57 driver and
> OGRBuildPolygonFromEdges()
> function.  In OGRBuildPolygonFromEdges() I see this comment:
>
> // Eventually we should at least identify the external ring properly,
> // perhaps even ordering the direction of rings, though this isn't
> // required by the OGC geometry model.
>
> You might want to file a ticket on this issue, though I can't say when
> the
> issue will be fixed.
>
> Best regards,



More information about the gdal-dev mailing list