Skip to content
Nutiteq edited this page Aug 26, 2014 · 7 revisions

The OGR Simple Features Library is a C++ open source library (and commandline tools) providing read (and sometimes write) access to a variety of vector file formats including ESRI Shapefiles, S-57, SDTS, PostGIS, Oracle Spatial, and Mapinfo mid/mif and TAB formats. AdvancedMap3D VectorFileMapActivity shows how to open and show OGR files. OGR databases (PostGIS, Oracle) are not really accessible from mobile as they need client libraries.

Code sample:

    // Set limit for the number of vector elements that are loaded
    int MAX_ELEMENTS = 1000;

    // set styles for all 3 object types: point, line and polygon
        int minZoom = 5;
        int color = Color.BLUE;

        DisplayMetrics metrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(metrics);
        float dpi = metrics.density;

        pointStyleSet = new StyleSet<PointStyle>();
        Bitmap pointMarker = UnscaledBitmapLoader.decodeResource(getResources(), R.drawable.point);
        PointStyle pointStyle = PointStyle.builder().setBitmap(pointMarker).setSize(0.05f).setColor(color).setPickingSize(0.2f).build();
        pointStyleSet.setZoomStyle(minZoom, pointStyle);

        lineStyleSet = new StyleSet<LineStyle>();
        LineStyle lineStyle = LineStyle.builder()
                .setWidth(0.05f)
                .setColor(color)
                .build();
        lineStyleSet.setZoomStyle(minZoom, lineStyle);

        polygonStyleSet = new StyleSet<PolygonStyle>(null);
        PolygonStyle polygonStyle = PolygonStyle.builder().setColor(color & 0x80FFFFFF).setLineStyle(lineStyle).build();
        polygonStyleSet.setZoomStyle(minZoom, polygonStyle);

        labelStyle = 
                LabelStyle.builder()
                .setEdgePadding((int) (12 * dpi))
                .setLinePadding((int) (6 * dpi))
                .setTitleFont(Typeface.create("Arial", Typeface.BOLD), (int) (16 * dpi))
                .setDescriptionFont(Typeface.create("Arial", Typeface.NORMAL), (int) (13 * dpi))
                .build();

//  Now add GeometryLayer, with OGRVectorDataSource.java as data source. 
//Note that in createLabel you can modify object popup balloon contents. 
//This one shows lists all attributes and values from the table. 
//You will find OGRVectorDataSource.java and required OGRFileHelper.java as source files from AdvancedMap3D project

        // data projection, and source location. With Shapefiles table name is same as filename.
        proj = new EPSG3857();
        dbPath = "/sdcard/myfile.shp";
        table = "myfile";

        OGRVectorDataSource dataSource;
        try {
            dataSource = new OGRVectorDataSource(proj, dbPath, table) {
                @Override
                protected Label createLabel(Map<String, String> userData) {
		        StringBuffer labelTxt = new StringBuffer();
		        for(Map.Entry<String, String> entry : userData.entrySet()){
		            labelTxt.append(entry.getKey() + ": " + entry.getValue() + "\n");
		        }
	            return new DefaultLabel("Data:", labelTxt.toString(), labelStyle);
                }

                @Override
                protected StyleSet<PointStyle> createPointStyleSet(Map<String, String> userData, int zoom) {
                    return pointStyleSet;
                }

                @Override
                protected StyleSet<LineStyle> createLineStyleSet(Map<String, String> userData, int zoom) {
                    return lineStyleSet;
                }

                @Override
                protected StyleSet<PolygonStyle> createPolygonStyleSet(Map<String, String> userData, int zoom) {
                    return polygonStyleSet;
                }

            };
        } catch (IOException e) {
            Log.error(e.getLocalizedMessage());
            Toast.makeText(this, "ERROR "+e.getLocalizedMessage(), Toast.LENGTH_LONG).show();
            return;
        }

        dataSource.setMaxElements(MAX_ELEMENTS);

        GeometryLayer ogrLayer = new GeometryLayer(dataSource);
        mapView.getLayers().addLayer(ogrLayer);

        //zoom map to data extent
        Envelope extent = ogrLayer.getDataExtent();
        mapView.setBoundingBox(new Bounds(extent.minX, extent.maxY, extent.maxX, extent.minY), false);

        // custom event handler to get events for object, or label clicks
        mapView.getOptions().setMapListener(new MapListener(){

            @Override
            public void onLabelClicked(VectorElement geometry, boolean longClick) {
                // Called when user has clicked object balloon Label
                // log attribute "name" value, if this exists
                String name = ((Map<String, String>)geometry.userData).get("name");
                Log.debug("clicked on "+name);
            }

            @Override
            public void onMapClicked(double x, double y, boolean longClick) {
                // Called when user has clicked map on given point
                
            }

            @Override
            public void onMapMoved() {
                // Called when map was moved. Check mapView parameters to get new view bounds, center etc
                
            }

            @Override
            public void onVectorElementClicked(VectorElement geometry, double x, double y, boolean longClick) {
                // Called when Vector element was clicked, gives click coordinates. Label in shown the same time
                
            }
            
        });

More complex styling

You can have object attribute and zoom-based styling. For example if you have lines and want to have different styles based on table attributes, then you would have something like following (assuming you have defined class members for lineStyleSets beforehand):

                @Override
                protected StyleSet<LineStyle> createLineStyleSet(Map<String, String> userData, int zoom) {
                    // if zoom < 5 then do not show the objects at all
                    if (zoom < 5) 
                        return null;
                    // based on object attribute "type" give different style (for type=2). 
    //   Note that all values are Strings here
                    if(userData.get("type").equals("2")){
                        return lineStyleSet2;
                    }else{
                        return lineStyleSet1;
                    }
                }

Performance optimization

  • See performance optimization hints in Vector layer speed optimization
  • This layer implementation does automatic reprojection, but it works faster if source data is in same projection as BaseMapLayer.
  • With big polygon and polyline datasets use generalized layer copies for lower zoom levels.
  • For bigger datasets (tens of thousands of objects or more) make sure that it has spatial index. For example Shapefiles should have qix file, or native Shapefile index. To generate index with OGR tools use:
ogrinfo buildings.shp -sql "CREATE SPATIAL INDEX ON buildings"

OGR supported drivers

The list can be different (longer) depending on native side compilation options, especially extra libraries compiled in.

ESRI Shapefile
MapInfo File
UK .NTF
SDTS
TIGER
S57
DGN
VRT
REC
Memory
BNA
CSV
GML
GPX
KML
GeoJSON
GMT
PCIDSK
XPlane
AVCBin
AVCE00
DXF
Geoconcept
GeoRSS
GPSTrackMaker
VFK
PGDump
GPSBabel
SUA
OpenAir
PDS
HTF
AeronavFAA
EDIGEO
SVG
Idrisi
ARCGEN
SEGUKOOA
SEGY
Clone this wiki locally