Monday, August 19, 2013

Simple C# example using SharpMap and OGR to read a DGN file

SharpMap is an easy to use library for working with GIS data. It comes with wrappers for OGR and GDAL. I recently had to work with DGN files. I thought I would share that experience by posting a simple C# wrapper for reading a Microstation DGN file (version 7) as SharpMap geometries.

The example code below simply opens up a DGN file as an OGR data source. The wrapper exposes a public method to return all the DGN elements as SharpMap geometries for further manipulation.



//...etc...
using SharpMap;
using SharpMap.Geometries;
using SharpMap.Converters.WellKnownBinary;
using SharpMap.Converters.WellKnownText;
using OSGeo.OGR;
 
//A simple example DGN file wrapper using SharpMap and OGR
public class DGNFile
{
#region private member variables
//Variable for the OGR DGN data source
private DataSource _dataSource = null;
private ArrayList _layers = new ArrayList();
#endregion
public DGNFile(string filename)
{
//Register OGR drivers
Ogr.RegisterAll();
string format = string.Empty;

//Attempt to open the DGN file with OGR. 
//If successful, the format string "DGN" will be returned. 
//Otherwise, throw an exception
_dataSource = Ogr.Open(filename, 0);
if (_dataSource != null)
{
format = _dataSource.GetDriver().GetName();
}
if (format.CompareTo("DGN") != 0 || _dataSource == null)
{
throw new Exception("Unable to open DGN file");
}
 
//Get a list of the DGN layers. 
//Note: so far, I have not encountered more than 1 layer
for (int i = 0; i < _dataSource.GetLayerCount(); i++)
{
Layer layer = _dataSource.GetLayerByIndex(i);
if (layer != null)
{
FeatureDefn def = layer.GetLayerDefn();
_layers.Add(def.GetName());
}
}
}
//Just a destructor to free up the OGR resources
~DGNFile()
{
if (_dataSource != null)
{
_dataSource.Dispose();
}
}
//A public method to get all the DGN elements as SharpMap geometries
public ArrayList GetElements()
{
ArrayList geometries = new ArrayList();
 
for (int i = 0; i < _layers.Count; i++)
{
string layerName = (string) _layers[i];
Layer layer = _dataSource.GetLayerByName(layerName);
FeatureDefn def = layer.GetLayerDefn();

//A reset is necessary if you want to read the DGN from the top of the file again
layer.ResetReading();
Feature fea;

//Loop through all the elements
while ((fea = layer.GetNextFeature()) != null)
{
OSGeo.OGR.Geometry geom = fea.GetGeometryRef();
if (geom != null)
{
wkbGeometryType geomType = geom.GetGeometryType();
geom.FlattenTo2D();

//Allocate a buffer to store the WKB geometry
Byte[] buff = new Byte[geom.WkbSize()];
geom.ExportToWkb(buff);

//Convert the WKB geometry to SharpMap geometry
SharpMap.Geometries.Geometry sharpMapGeom = GeometryFromWKB.Parse(buff);
geometries.Add(rec);

//Free up resources
geom.Dispose();
}
fea.Dispose();
}
layer.Dispose();
}
//Return the DGN elements formatted as SharpMap geometries
return geometries;
}        

3 comments:

Anonymous said...

hey I was asked about DGN support just last week. Thanks for the sample.

Did you use SharpmMap 1.0?

auto_ea said...

Hi dominoc925,
Thanks for your nice sample. I have 3 questions:
Could you publish a sourcecode?
What is version of SharpMap did you used?
Could ogr sharpmap read an annotation (text) of dgn file?

dominoc925 said...

Hi Truong
(1) I have already extracted out and published the code from a much larger project, most of which is irrelevant to the post.
(2) I was using Sharpmap 0.9.
(3) I believe text is read as a point geometry but I don't believe you can get the text string (but I could be wrong).