Click here to Skip to main content
15,881,248 members
Articles / Multimedia / OpenGL
Tip/Trick

Rendering Shapefile in OpenGL-2

Rate me:
Please Sign up or sign in to vote.
4.69/5 (6 votes)
24 Aug 2015CPOL2 min read 17.5K   821   8   2
Rendering polygon shapefiles and filling them

Introduction

This is a continuation to my previous article for rendering shapefiles in OpenGL environment. Shapefiles have either to be point, line or polygon types. The main focus of this tip is to render polygons and fill them.This revision will also handle polygons with holes i.e, Donut Polygons.

Background

Polygons in shapefiles are organized in a typical manner.Each Polygon element may have single or multiple parts.Each part is called a ring.The rings have vertices which are arranged in clockwise or counter clockwise based on whether they represent outer ring or inner ring. Shapelib library helps us to parse this special structure. The detailed description of this structure can be found in ESRI Shapefile Technical Description.

 Image 1

OpenGL cannot render concave polygonsOpenGL community advises to make use of Triangulation libraries for breaking a polygon into triangle fans and strips. Most popular libraries fail in successfully triangulating complex polygons that are typical in GIS. In his article, we use GLU tesselator to break a polygon into convex shapes and render them.

Using the Code

I assume that the intended audience is familiar with OpenGL and understands concepts like linking with static or dynamic libraries in Microsoft Visual Studio environment.

To parse the shapefile, I have used the Shapelib (http://shapelib.maptools.org/). Include the shapefile.h at the beginning. Make use of the shapelib.lib by adding shapelib\shapelib.lib to object/library modules.

The below structure defines the structure of a polygon. Each polygon has multiple rings. Each ring has a start index and end index within the array of points.

C++
typedef struct MyPolygonElement2D
{
 vector<MyPoint2D>vPointList;
 int nParts;
 vector <int> vPartsStartIndex;
 vector <int> vPartsEndIndex;
 
}MyPolygonElement2D;

We use the below function declarations to interact with GLU Tesselator.

C++
typedef void (__stdcall *TESSCALLBACK)(void);
void CALLBACK tess_edgeFlag( GLboolean );
void CALLBACK edgeCallback(void);
void errorCallback(GLenum errorCode);
void CALLBACK combineCallback(GLdouble coords[3],
GLdouble *vertex_data[4],GLfloat weight[4], GLdouble **dataOut );
void CALLBACK TessBeginCallback(GLenum which);   

Declare a Tesselator object and enclose the rings in contour begin and end calls to GLU tesselator.

C++
GLUtesselator *tobj;
 gluTessBeginPolygon(tobj, NULL);
 gluTessBeginContour(tobj);  

//Pass the vertices of a ring here
  
 gluTessEndContour(tobj);
 gluTessEndPolygon(tobj);

The rendering can be accomplished with the below logic.

C++
    for(int n=0;n<vPolygonElements2D.size();n++)
    {      
        gluTessBeginPolygon(tobj,NULL);
        for(int k=0;k<vPolygonElements2D[n].nParts;k++)
        {	int start=vPolygonElements2D[n].vPartsStartIndex[k];
			int finish=vPolygonElements2D[n].vPartsEndIndex[k];
			const int nNoOfVertices=finish-start;
			double **fPolygonVertices = 0;
			int nVertice=0;
            fPolygonVertices = new double *[nNoOfVertices] ;
            for(int i = 0 ; i < nNoOfVertices ; i++ )
              fPolygonVertices[i] = new double[3];		
		
			
			gluTessBeginContour(tobj);
            
            for(int l=start;l<finish;l++)
            {
                fPolygonVertices[nVertice][0] = vPolygonElements2D[n].vPointList[l].dX;
                fPolygonVertices[nVertice][1] = vPolygonElements2D[n].vPointList[l].dY;
                fPolygonVertices[nVertice][2] = 0.0;          
            
                nVertice++;
           }//for l   
           for( l=0;l<nVertice-1 ;l++)    
              gluTessVertex(tobj, fPolygonVertices[l],fPolygonVertices[l]); //store the vertex
            gluTessEndContour(tobj);
            
        
        }//for  k
           gluTessEndPolygon(tobj); 
    }//for n

Output

Image 2

Points of Interest

Please note the below things:

  1. The approach is only to demo the possibility of drawing filled polygons.
  2. The code is not performance oriented and written in a very legacy way.
  3. The shapefiles shall be WGS 84 and shall not contain multi geometry shapes.
  4. Performance  improved by making use of display lists 
  5. My next article would be to make use of OpenGL Shaders.

History

Refer to my previous article.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
India India
He works in the GIS and allied technologies. His areas of Interest are GIS/CAD ,Defence,Aerospace and Law Enforcement.

Comments and Discussions

 
Praisearticle Pin
Member 773274120-Feb-17 15:02
Member 773274120-Feb-17 15:02 
GeneralMy vote of 5 Pin
ToothRobber25-Aug-15 6:37
professionalToothRobber25-Aug-15 6:37 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.