Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ShapeBaseChart::DoDrawPolygonFilledGL performance #3835

Open
nohal opened this issue Apr 22, 2024 · 3 comments
Open

ShapeBaseChart::DoDrawPolygonFilledGL performance #3835

nohal opened this issue Apr 22, 2024 · 3 comments
Labels

Comments

@nohal
Copy link
Collaborator

nohal commented Apr 22, 2024

For high resolution basemaps we can't tesselate the whole polygons as the impact on performance is way too high. The points outside the viewport have to be filtered out.

When returning over a different edge of the bounding box, some artificial point(s) have to be added to ensure correct coverage.

@nohal nohal added the bug label Apr 22, 2024
@nohal nohal added this to the OpenCPN 5.10.0 milestone Apr 22, 2024
@nohal
Copy link
Collaborator Author

nohal commented Apr 22, 2024

Something like this:

diff --git a/gui/src/shapefile_basemap.cpp b/gui/src/shapefile_basemap.cpp
index 2301f107b..70d01731a 100644
--- a/gui/src/shapefile_basemap.cpp
+++ b/gui/src/shapefile_basemap.cpp
@@ -342,7 +342,6 @@ void ShapeBaseChart::DoDrawPolygonFilledGL(ocpnDC &pnt, ViewPort &vp,
       vp.GetBBox().GetMinLon() <= -180 || vp.GetBBox().GetMaxLon() >= 180;
   auto polygon = static_cast<shp::Polygon *>(feature.getGeometry());
   for (auto &ring : polygon->getRings()) {
-    size_t cnt{0};
     GLUtesselator *tobj = gluNewTess();
 
     gluTessCallback(tobj, GLU_TESS_VERTEX, (_GLUfuncptr)&shpsvertexCallback);
@@ -356,9 +355,27 @@ void ShapeBaseChart::DoDrawPolygonFilledGL(ocpnDC &pnt, ViewPort &vp,
 
     gluTessBeginPolygon(tobj, NULL);
     gluTessBeginContour(tobj);
+    bool lastin = false;
+    shp::Point lastpoint = ring.getPoints().front();
+    if (vp.GetBBox().Contains(lastpoint.getY(), lastpoint.getX())) {
+      lastin = true;
+    }
     for (auto &point : ring.getPoints()) {
-      AddPointToTessList(point, vp, tobj, idl);
-      cnt++;
+      if (vp.GetBBox().Contains(point.getY(), point.getX())) {
+        if (!lastin) { //Last point outside of the viewport before getting back to visible part must be included
+          AddPointToTessList(lastpoint, vp, tobj, idl);
+        }
+        AddPointToTessList(point, vp, tobj, idl);
+        lastin = true;
+      } else {
+        if (lastin) { // First point outside of the viewport must be included
+          AddPointToTessList(point, vp, tobj, idl);
+        } else {
+          // TODO: If we got to a different edge of the bounding box, we need to add an artificial point in the corner
+        }
+        lastin = false;
+      }
+      lastpoint = point;
     }
     gluTessEndContour(tobj);
     gluTessEndPolygon(tobj);

@bdbcat
Copy link
Member

bdbcat commented Apr 22, 2024

Tested?

@nohal
Copy link
Collaborator Author

nohal commented Apr 22, 2024

Yes, but it is missing the TODO part of course, so not ready to be merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants