Beispiel #1
0
        /// <summary>
        /// 在指定路径下构建shp数据源(此操作不会生成实际的shp文件)
        /// </summary>
        /// <param name="shpFilePath">shp文件路径</param>
        /// <returns></returns>
        public static DataSource CreateShapefileSource(string shpFilePath)
        {
            Driver driver = Ogr.GetDriverByName("ESRI Shapefile");

            if (driver == null)
            {
                throw new Exception("ESRI Shapefile 驱动不可使用");
            }

            Gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES"); // 为了支持中文路径
            DataSource dataSource = driver.CreateDataSource(shpFilePath, null);

            if (dataSource == null)
            {
                throw new Exception("创建SHP文件" + shpFilePath + "失败");
            }

            DirectoryInfo directoryInfo = new DirectoryInfo(Path.GetDirectoryName(shpFilePath));

            if (!directoryInfo.Exists)
            {
                directoryInfo.Create();
            }

            driver.Dispose();

            return(dataSource);
        }
Beispiel #2
0
        public static bool CovertRegion2Line(string path, string savePath)
        {
            try
            {
                OSGeo.OGR.Ogr.RegisterAll();
                OSGeo.OGR.Driver dr = OSGeo.OGR.Ogr.GetDriverByName("ESRI shapefile");
                if (dr == null)
                {
                    Console.WriteLine("启动驱动失败!\n");
                }

                OSGeo.OGR.DataSource ds    = dr.Open(path, 0);
                int             layerCount = ds.GetLayerCount();
                OSGeo.OGR.Layer layer      = ds.GetLayerByIndex(0);
                FeatureDefn     fdf        = layer.GetLayerDefn();
                int             fieldCount = fdf.GetFieldCount();

                // 创建数据源
                DataSource oDS = dr.CreateDataSource(savePath, null);
                if (oDS == null)
                {
                    Console.WriteLine("创建矢量文件【%s】失败!\n", savePath);
                    return(false);
                }
                OSGeo.OSR.SpatialReference srs = layer.GetSpatialRef();
                // 创建图层,创建一个多边形图层,这里没有指定空间参考,如果需要的话,需要在这里进行指定
                Layer oLayer = oDS.CreateLayer("line", srs, OSGeo.OGR.wkbGeometryType.wkbMultiLineString, null);

                if (oLayer == null)
                {
                    Console.WriteLine("图层创建失败!\n");
                    return(false);
                }
                for (int i = 0; i < fieldCount; i++)
                {
                    FieldDefn fieldDefn = fdf.GetFieldDefn(i);
                    oLayer.CreateField(fieldDefn, 1);
                }
                FeatureDefn       oDefn = oLayer.GetLayerDefn();
                OSGeo.OGR.Feature feat;
                while ((feat = layer.GetNextFeature()) != null)
                {
                    Feature            oFeatureMulty = new Feature(oDefn);
                    OSGeo.OGR.Geometry geometry      = feat.GetGeometryRef();
                    for (int i = 0; i < fieldCount; i++)
                    {
                        string value = feat.GetFieldAsString(i);
                        oFeatureMulty.SetField(i, value);
                    }
                    OSGeo.OGR.wkbGeometryType goetype = geometry.GetGeometryType();
                    if (goetype == OSGeo.OGR.wkbGeometryType.wkbPolygon)
                    {
                        Geometry tempGeo = new Geometry(wkbGeometryType.wkbMultiLineString);
                        int      count   = geometry.GetGeometryCount();
                        for (int j = 0; j < count; j++)
                        {
                            Geometry line = new Geometry(wkbGeometryType.wkbLinearRing);
                            Geometry geo  = geometry.GetGeometryRef(j);
                            for (int i = 0; i < geo.GetPointCount(); i++)
                            {
                                double x = geo.GetX(i);
                                double y = geo.GetY(i);
                                line.AddPoint(x, y, 0);
                            }
                            tempGeo.AddGeometryDirectly(line);
                        }
                        oFeatureMulty.SetGeometry(tempGeo);
                    }
                    oLayer.SetFeature(oFeatureMulty);
                }
                oLayer.Dispose();
                layer.Dispose();
                oDS.Dispose();
                ds.Dispose();
                dr.Dispose();
            }
            catch
            { }
            return(false);
        }
Beispiel #3
0
        /// <summary>
        /// 转换并纠偏,只使用与火星坐标纠偏
        /// </summary>
        /// <param name="dataTable">数据表,如果是点表中含X,Y字段,如果是线和面,表中含有PATH字段</param>
        /// <param name="filePath">存储路径</param>
        /// <param name="geoType">数据类型,暂时支持简单的点线面</param>
        //public static void saveShpFile(DataTable dataTable,string filePath,wkbGeometryType geoType)
        //{
        //    saveShpFile(dataTable, filePath, geoType, ProjectConvert.GCJ_WGS);
        //}
        /// <summary>
        /// 导出shp数据到表格
        /// </summary>
        /// <param name="path">文件路径</param>
        /// <returns>DataTable</returns>
        public static DataTable GetData(string path)
        {
            try
            {
                OSGeo.OGR.Ogr.RegisterAll();
                OSGeo.OGR.Driver dr = OSGeo.OGR.Ogr.GetDriverByName("ESRI shapefile");

                if (dr == null)
                {
                    Console.WriteLine("启动驱动失败!\n");
                }

                OSGeo.OGR.DataSource ds    = dr.Open(path, 0);
                int             layerCount = ds.GetLayerCount();
                OSGeo.OGR.Layer layer      = ds.GetLayerByIndex(0);
                DataTable       dataTable  = new DataTable();
                FeatureDefn     fdf        = layer.GetLayerDefn();
                int             fieldCount = fdf.GetFieldCount();
                for (int i = 0; i < fieldCount; i++)
                {
                    dataTable.Columns.Add(fdf.GetFieldDefn(i).GetName(), Type.GetType("System.String"));
                }
                if (fdf.GetGeomType() == OSGeo.OGR.wkbGeometryType.wkbPoint)
                {
                    if (!dataTable.Columns.Contains("X"))
                    {
                        dataTable.Columns.Add("X", Type.GetType("System.String"));
                    }
                    if (!dataTable.Columns.Contains("Y"))
                    {
                        dataTable.Columns.Add("Y", Type.GetType("System.String"));
                    }
                }
                else if (fdf.GetGeomType() == OSGeo.OGR.wkbGeometryType.wkbPolygon || fdf.GetGeomType() == OSGeo.OGR.wkbGeometryType.wkbLineString)
                {
                    if (!dataTable.Columns.Contains("PATH"))
                    {
                        dataTable.Columns.Add("PATH", Type.GetType("System.String"));
                    }
                }
                OSGeo.OGR.Feature feat;
                while ((feat = layer.GetNextFeature()) != null)
                {
                    DataRow            row      = dataTable.NewRow();
                    OSGeo.OGR.Geometry geometry = feat.GetGeometryRef();
                    for (int i = 0; i < fieldCount; i++)
                    {
                        string value = feat.GetFieldAsString(i);
                        row[i] = value.Replace(",", "");
                    }
                    OSGeo.OGR.wkbGeometryType goetype = geometry.GetGeometryType();
                    if (goetype == OSGeo.OGR.wkbGeometryType.wkbPoint)
                    {
                        double x = geometry.GetX(0);
                        double y = geometry.GetY(0);
                        row["X"] = x.ToString();
                        row["Y"] = y.ToString();
                    }
                    else if (goetype == OSGeo.OGR.wkbGeometryType.wkbLineString)
                    {
                        string points = "";
                        for (int i = 0; i < geometry.GetPointCount(); i++)
                        {
                            double x = geometry.GetX(i);
                            double y = geometry.GetY(i);
                            points += x.ToString() + "|" + y.ToString() + ";";
                        }
                        if (points != "")
                        {
                            points.Substring(0, points.Length - 1);
                        }
                        row["PATH"] = points;
                    }
                    else if (goetype == OSGeo.OGR.wkbGeometryType.wkbPolygon)
                    {
                        int    count  = geometry.GetGeometryCount();
                        string points = "";
                        for (int j = 0; j < count; j++)
                        {
                            Geometry geo = geometry.GetGeometryRef(j);
                            for (int i = 0; i < geo.GetPointCount(); i++)
                            {
                                double x = geo.GetX(i);
                                double y = geo.GetY(i);
                                points += x.ToString() + "|" + y.ToString() + ";";
                            }
                            if (points != "")
                            {
                                points.Substring(0, points.Length - 1);
                            }
                            points += "|";
                        }
                        if (points != "")
                        {
                            points.Substring(0, points.Length - 1);
                        }
                        row["PATH"] = points;
                    }
                }
                layer.Dispose();
                ds.Dispose();
                dr.Dispose();
                return(dataTable);
            }
            catch
            {
                return(null);
            }
        }
        public static bool ExportSelectedDatabaseToGML(Action <string, bool> aLog, string pOutputFilename)
        {
            // Get database, return if no database selected
            if (frmMain.dbx == null)
            {
                aLog("Please select a database first...", true);
                return(false);
            }

            // Setup driver
            OSGeo.OGR.Driver drv = Ogr.GetDriverByName("GML");
            if (drv == null)
            {
                aLog("Could not load driver", true);
                return(false);
            }

            // Create fieldAttributes datasource
            DataSource ds = drv.CreateDataSource(pOutputFilename, null);

            if (ds == null)
            {
                aLog("Could not create datasource", true);
                return(false);
            }

            // Create fieldAttributes layer
            OSGeo.OGR.Layer l = ds.CreateLayer("AddressUnits", null, wkbGeometryType.wkbPoint, null);
            if (l == null)
            {
                aLog("Failed to create GML file: AddressUnits", true);
                return(false);
            }

            // Create fieldAttributes class to hold address unit data
            AddressUnit mAddressUnits = new AddressUnit();

            // Add fields to shapefile
            foreach (System.Reflection.FieldInfo mFld in mAddressUnits.GetType().GetFields())
            {
                var val       = (DatFld)mFld.GetValue(mAddressUnits);
                var mNewField = new FieldDefn(mFld.Name, val.type);
                if (val.type == FieldType.OFTString)
                {
                    mNewField.SetWidth(val.length);
                }
                if (Ogr.OGRERR_NONE != l.CreateField(mNewField, 1))
                {
                    aLog("Failed to add field: " + mFld.Name, true);
                }
            }

            int    ctr = 0;
            double mX, mY;

            var mAdmAdrFeature = new AddressUnitFeature(frmMain.dbx);

            DataTable mTable = mAdmAdrFeature.GetTable(sqlStatements.selectAddressUnitsSQL);

            // Add features
            foreach (DataRow mRow in mTable.Rows)
            {
                if (Double.TryParse(mRow["loc_x"].ToString(), out mX) && Double.TryParse(mRow["loc_y"].ToString(), out mY))
                {
                    var mFeature = new OSGeo.OGR.Feature(l.GetLayerDefn());
                    var mPoint   = new OSGeo.OGR.Geometry(wkbGeometryType.wkbPoint);

                    mPoint.SetPoint(0, mX, mY, 0);
                    mFeature.SetFID(ctr);
                    mFeature.SetGeometry(mPoint);
                    mFeature.SetField("ADDRESSUNITID", int.Parse(mRow["id"].ToString()));
                    mFeature.SetField("ROADID", int.Parse(mRow["road_id"].ToString()));
                    mFeature.SetField("ADDRESSUNITNR", int.Parse(mRow["addressUnitNumber"].ToString()));
                    mFeature.SetField("ROADNAME_EN", Utilities.GetANSI(mRow["NAMEENGLISH"].ToString()));
                    mFeature.SetField("ROADNAME_AR", Utilities.GetANSI(mRow["NAMEARABIC"].ToString()));
                    mFeature.SetField("DISTRICT_EN", Utilities.GetANSI(mRow["DISTRICT_EN"].ToString()));
                    mFeature.SetField("DISTRICT_AR", Utilities.GetANSI(mRow["DISTRICT_AR"].ToString()));
                    mFeature.SetField("MUNICIPALITY_EN", Utilities.GetANSI(Utilities.LABEL_ABUDHABI_EN));
                    mFeature.SetField("MUNICIPALITY_AR", Utilities.GetANSI(Utilities.LABEL_ABUDHABI_AR));
                    mFeature.SetField("QR_CODE", Utilities.GetANSI(mAdmAdrFeature.GetQRCode(mRow, mTable)));
                    l.CreateFeature(mFeature);
                }
                else
                {
                    Utilities.LogDebug("Error");
                }

                ctr++;
            }

            l.Dispose();
            ds.Dispose();
            drv.Dispose();
            return(true);
        }
Beispiel #5
0
        public bool ContourGenerate(string dstVectorFilename, string strAtrrName, Dataset pInDataset, int nBandIndex = 1, double[] dLevelIntervals = null, double dLevelBase = 0, bool isPolygon = true, string driverName = "GeoJSON")
        {
            if (pInDataset == null)
            {
                return(false);
            }

            //提取图像参数值
            int nDemWidth  = pInDataset.RasterXSize;    //获取图像宽
            int nDemHeight = pInDataset.RasterYSize;    //获取图像高
            int nCount     = pInDataset.RasterCount;    //波段数

            //读取图像数据波段
            Band poBand = pInDataset.GetRasterBand(nBandIndex);

            float[] pData = new float[nDemWidth * nDemHeight];

            CPLErr err = poBand.ReadRaster(0, 0, nDemWidth, nDemHeight, pData, nDemWidth, nDemHeight, 4, 0);

            if (err == CPLErr.CE_Failure)
            {
                Gdal.GDALDestroyDriverManager();
                Console.WriteLine("读取DEM图像数据时出错!");
                return(false);
            }

            //判断图像中是否有异常值,并获取异常值实际值
            float fNoData = 0;
            int   nIdx;

            for (int i = 0; i < nDemHeight; i++)
            {
                for (int j = 0; j < nDemWidth; j++)
                {
                    nIdx = i * nDemWidth + j;
                    if (pData[nIdx] <= -9999)
                    {
                        fNoData = pData[nIdx];
                    }
                }
            }


            //创建矢量图
            OSGeo.OGR.Driver poDriver = Ogr.GetDriverByName(driverName);
            if (poDriver == null)
            {
                Console.WriteLine(driverName + " driver not available.");
                return(false);
            }

            //载入数据源
            DataSource poDS = poDriver.CreateDataSource(dstVectorFilename, null);

            if (poDS == null)
            {
                Console.WriteLine("Creation of output file failed.");
                return(false);
            }

            SpatialReference poSpatialRef = new SpatialReference(pInDataset.GetProjectionRef());
            Layer            poLayer      = poDS.CreateLayer("Contour", poSpatialRef, wkbGeometryType.wkbLineString, null);

            if (poLayer == null)
            {
                Console.WriteLine("Layer creation failed.");
                return(false);
            }

            if (strAtrrName == "")
            {
                strAtrrName = "Elevation";
            }
            FieldDefn oFieldDef = new FieldDefn(strAtrrName, FieldType.OFTInteger);    //在矢量图中创建高程值字段

            if (poLayer.CreateField(oFieldDef, 1) != Ogr.OGRERR_NONE)
            {
                Console.WriteLine("创建矢量图层属性表失败!");
                poDS.Dispose();
                pInDataset.Dispose();
                return(false);
            }


            //组装参数
            List <string> lstOptions = new List <string>()
            {
            };

            if (dLevelIntervals == null)
            {
                lstOptions.Add("LEVEL_INTERVAL=" + 0);
            }
            else
            {
                if (dLevelIntervals.Length == 1)
                {
                    lstOptions.Add("LEVEL_INTERVAL=" + dLevelIntervals[1]);
                }
                else
                {
                    lstOptions.Add("FIXED_LEVELS=[" + string.Join(",", dLevelIntervals) + "]");
                }
            }
            lstOptions.Add("LEVEL_BASE=" + dLevelBase);
            lstOptions.Add("NODATA=" + fNoData);
            lstOptions.Add("POLYGONIZE=" + (isPolygon ? "YES" : "NO"));
            if (isPolygon)
            {
                lstOptions.Add("ELEV_FIELD_MAX=0");
                lstOptions.Add("ELEV_FIELD_MIN=0");
            }

            //根据图像波段生成矢量图等高线
            //Gdal.ContourGenerate(pInRasterBand, dfContourInterval, 0, 0, null, 1, fNoData, poLayer, -1, 0, null, null);
            //string[] options = new string[] { "LEVEL_INTERVAL=" + 5, "LEVEL_BASE=" + 5, "NODATA=" + fNoData, "POLYGONIZE=YES", "ELEV_FIELD_MIN=0", "ELEV_FIELD_MAX=0", "FIXED_LEVELS=[20,30,40,50,60,100]" };
            Gdal.ContourGenerateEx(poBand, poLayer, lstOptions.ToArray(), null, null);

            //释放资源
            poDS.Dispose();
            poLayer.Dispose();
            poDriver.Dispose();
            pInDataset.Dispose();
            return(true);
        }
Beispiel #6
0
        /// <summary>
        /// This is the method that actually does the work.
        /// </summary>
        /// <param name="DA">The DA object is used to retrieve from inputs and store in outputs.</param>
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            ///TODO:    fix crash with "multi" types in a branch for shapefiles, can't create lines in a points layer
            ///         fix mesh/polygon face creation issue on sphere, dropping faces or flipped faces
            ///         fix swtich case for shapfiles so that points and multipoints (eg) are written to the same file. don't use switch anymore, us ifs
            ///         fix sql statements, they don't seem to have an effect.  Need these to work for pulling apart geometry collections.

            ///Gather GHA inputs
            string filename = string.Empty;

            DA.GetData <string>("Vector Data Filename", ref filename);

            string folder = string.Empty;

            DA.GetData <string>("Vector Data Folder", ref folder);
            folder = Path.GetFullPath(folder);
            if (!folder.EndsWith(Path.DirectorySeparatorChar.ToString()))
            {
                folder += Path.DirectorySeparatorChar;
            }

            string shpPath = folder + filename + drvExtension;
            ///for more than one geometry type, a list of files for shapefile output needs to be established
            List <string> shpPathList = new List <string>();
            List <string> shpTypeList = new List <string>();

            List <string> fields = new List <string>();

            DA.GetDataList <string>("Fields", fields);

            GH_Structure <GH_String> values = new GH_Structure <GH_String>();

            DA.GetDataTree <GH_String>("Values", out values);

            GH_Structure <IGH_GeometricGoo> gGoo = new GH_Structure <IGH_GeometricGoo>();

            DA.GetDataTree <IGH_GeometricGoo>("Feature Geometry", out gGoo);

            bool export = false;

            DA.GetData <bool>("Export", ref export);

            ///GDAL setup
            RESTful.GdalConfiguration.ConfigureOgr();
            OSGeo.GDAL.Gdal.SetConfigOption("OGR_SKIP", "KML");

            string driverType = drvType;

            //OSGeo.OGR.Driver drv = Ogr.GetDriverByName("LIBKML");// driverType);
            OSGeo.OGR.Driver drv = Ogr.GetDriverByName("GeoJSON");



            if (export == true)
            {
                ///File setup for save
                FileInfo file = new FileInfo(folder);
                file.Directory.Create();

                if (File.Exists(shpPath))
                {
                    drv.DeleteDataSource(shpPath);
                }

                ///Create virtual datasource to be converted later
                ///Using geojson as a flexiblle base file type which can be converted later with ogr2ogr
                DataSource ds = drv.CreateDataSource("/vsimem/out.geojson", null);

                ///Use WGS84 spatial reference
                OSGeo.OSR.SpatialReference dst = new OSGeo.OSR.SpatialReference("");
                dst.SetWellKnownGeogCS("WGS84");
                Transform transform = Heron.Convert.XYZToWGSTransform();

                ///Use OGR catch-all for geometry types
                var gtype = wkbGeometryType.wkbGeometryCollection;

                ///Create layer
                //string[] layerOptions = new string[] { "LIBKML_USE_SCHEMADATA=NO", "LIBKML_USE_SIMPLEFIELD=NO", "LIBKML_ALTITUDEMODE_FIELD=relativeToGround" };
                //string[] layerOptions = new string[] { "LIBKML_STRICT_COMPLIANCE=FALSE" };
                OSGeo.OGR.Layer layer = ds.CreateLayer(filename, dst, gtype, null);
                FeatureDefn     def   = layer.GetLayerDefn();

                ///Add fields to layer
                for (int f = 0; f < fields.Count; f++)
                {
                    OSGeo.OGR.FieldDefn fname = new OSGeo.OGR.FieldDefn(fields[f], OSGeo.OGR.FieldType.OFTString);
                    layer.CreateField(fname, f);
                }

                ///Specific fields for LIBKML for use in Google Earth
                ///See LIBMKL driver for more info https://gdal.org/drivers/vector/libkml.html
                if (drvType == "LIBKML")
                {
                    OSGeo.OGR.FieldDefn kmlFieldAltitudeMode = new OSGeo.OGR.FieldDefn("altitudeMode", OSGeo.OGR.FieldType.OFTString);
                    layer.CreateField(kmlFieldAltitudeMode, fields.Count());
                    //OSGeo.OGR.FieldDefn kmlFieldExtrude = new OSGeo.OGR.FieldDefn("tessellate", OSGeo.OGR.FieldType.OFTInteger);
                    //layer.CreateField(kmlFieldExtrude, fields.Count()+1);
                }


                for (int a = 0; a < gGoo.Branches.Count; a++)
                {
                    ///create feature
                    OSGeo.OGR.Feature feature = new OSGeo.OGR.Feature(def);

                    ///Set LIBKML specific fields for use in Google Earth, defaulting to 'relativeToGround'.  Consider setting to 'absolute'.
                    if (drvType == "LIBKML")
                    {
                        feature.SetField("altitudeMode", "relativeToGround");
                        //feature.SetField("altitudeMode", "absolute");
                        //feature.SetField("tessellate", 0);
                    }

                    ///TODO: Build style table
                    OSGeo.OGR.StyleTable styleTable = new StyleTable();
                    //feature.SetStyleString("BRUSH(fc:#0000FF);PEN(c:#000000)");

                    ///Get geometry type(s) in branch
                    var           geomList     = gGoo.Branches[a];
                    string        geomType     = string.Empty;
                    List <string> geomTypeList = geomList.Select(o => o.TypeName).ToList();
                    ///Test if geometry in the branch is of the same type.
                    ///If there is more than one element of a type, tag as multi, if there is more than one type, tag as mixed
                    if (geomTypeList.Count == 1)
                    {
                        geomType = geomTypeList.First();
                    }
                    else if (geomTypeList.Count > 1 && geomTypeList.All(gt => gt == geomTypeList.First()))
                    {
                        geomType = "Multi" + geomTypeList.First();
                    }

                    else
                    {
                        geomType = "Mixed";
                    }

                    ///For testing
                    //AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, geomType);

                    ///Add geomtery to feature
                    ///Create containers for translating from GH Goo
                    Point3d        pt  = new Point3d();
                    List <Point3d> pts = new List <Point3d>();

                    Curve        crv  = null;
                    List <Curve> crvs = new List <Curve>();

                    Mesh mesh      = new Mesh();
                    Mesh multiMesh = new Mesh();

                    switch (geomType)
                    {
                    case "Point":
                        geomList.First().CastTo <Point3d>(out pt);
                        feature.SetGeometry(Heron.Convert.Point3dToOgrPoint(pt, transform));
                        if (!shpTypeList.Contains("POINT"))
                        {
                            shpTypeList.Add("POINT");
                        }
                        break;

                    case "MultiPoint":
                        foreach (var point in geomList)
                        {
                            point.CastTo <Point3d>(out pt);
                            pts.Add(pt);
                        }
                        feature.SetGeometry(Heron.Convert.Point3dsToOgrMultiPoint(pts, transform));
                        if (!shpTypeList.Contains("MULTIPOINT"))
                        {
                            shpTypeList.Add("MULTIPOINT");
                        }
                        break;

                    case "Curve":
                        geomList.First().CastTo <Curve>(out crv);
                        feature.SetGeometry(Heron.Convert.CurveToOgrLinestring(crv, transform));
                        if (!shpTypeList.Contains("LINESTRING"))
                        {
                            shpTypeList.Add("LINESTRING");
                        }
                        break;

                    case "MultiCurve":
                        foreach (var curve in geomList)
                        {
                            curve.CastTo <Curve>(out crv);
                            crvs.Add(crv);
                        }
                        feature.SetGeometry(Heron.Convert.CurvesToOgrMultiLinestring(crvs, transform));
                        if (!shpTypeList.Contains("MULTILINESTRING"))
                        {
                            shpTypeList.Add("MULTILINESTRING");
                        }
                        break;

                    case "Mesh":
                        geomList.First().CastTo <Mesh>(out mesh);
                        feature.SetGeometry(Heron.Convert.MeshToMultiPolygon(mesh, transform));
                        if (!shpTypeList.Contains("MULTIPOLYGON"))
                        {
                            shpTypeList.Add("MULTIPOLYGON");
                        }
                        break;

                    case "MultiMesh":
                        foreach (var m in geomList)
                        {
                            Mesh meshPart = new Mesh();
                            m.CastTo <Mesh>(out meshPart);
                            multiMesh.Append(meshPart);
                        }
                        feature.SetGeometry(Heron.Convert.MeshToMultiPolygon(multiMesh, transform));
                        if (!shpTypeList.Contains("MULTIPOLYGON"))
                        {
                            shpTypeList.Add("MULTIPOLYGON");
                        }
                        break;

                    case "Mixed":
                        OSGeo.OGR.Geometry geoCollection = new OSGeo.OGR.Geometry(wkbGeometryType.wkbGeometryCollection);
                        for (int gInt = 0; gInt < geomList.Count; gInt++)
                        {
                            string geomTypeMixed = geomTypeList[gInt];
                            switch (geomTypeMixed)
                            {
                            case "Point":
                                geomList[gInt].CastTo <Point3d>(out pt);
                                geoCollection.AddGeometry(Heron.Convert.Point3dToOgrPoint(pt, transform));
                                break;

                            case "Curve":
                                geomList[gInt].CastTo <Curve>(out crv);
                                geoCollection.AddGeometry(Heron.Convert.CurveToOgrLinestring(crv, transform));
                                break;

                            case "Mesh":
                                geomList[gInt].CastTo <Mesh>(out mesh);
                                geoCollection.AddGeometry(Ogr.ForceToMultiPolygon(Heron.Convert.MeshToMultiPolygon(mesh, transform)));
                                break;

                            default:
                                AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "Not able to export " + geomType + " geometry at branch " + gGoo.get_Path(a).ToString() +
                                                  ". Geometry must be a Point, Curve or Mesh.");
                                break;
                            }
                        }
                        feature.SetGeometry(geoCollection);
                        if (!shpTypeList.Contains("GEOMETRYCOLLECTION"))
                        {
                            shpTypeList.Add("GEOMETRYCOLLECTION");
                        }
                        break;

                    default:
                        AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "Not able to export " + geomType + " geometry at branch " + gGoo.get_Path(a).ToString() +
                                          ". Geometry must be a Point, Curve or Mesh.");
                        break;
                    }



                    ///Give the feature a unique ID
                    feature.SetFID(a);

                    ///Add values to fields
                    GH_Path path = gGoo.get_Path(a);

                    for (int vInt = 0; vInt < fields.Count; vInt++)
                    {
                        string val = string.Empty;
                        if (values.get_Branch(path) != null)
                        {
                            val = values.get_DataItem(path, vInt).ToString();
                        }
                        feature.SetField(fields[vInt], val);
                    }

                    ///Save feature to layer
                    layer.CreateFeature(feature);

                    ///Cleanup
                    feature.Dispose();
                }

                layer.Dispose();
                ds.Dispose();
                drv.Dispose();

                ///Convert in memory dataset to file using ogr2ogr
                ///For KML set 'altitudeMode' to 'relativeToGround' or 'absolute'

                ///Set base options for all export types
                if (drvType == "KML")
                {
                    drvType = "LIBKML";
                }
                List <string> ogr2ogrOptions = new List <string> {
                    "-overwrite",
                    "-f", drvType,
                    "-dim", "XYZ",
                    "-skipfailures",

                    //"-lco", "LIBKML_STRICT_COMPLIANCE=FALSE",
                    //"-lco", "AltitudeMode=absolute",

                    //"-dsco", "SHAPE_REWIND_ON_WRITE=YES"
                };

                Dataset src = Gdal.OpenEx("/vsimem/out.geojson", 0, null, null, null);

                if (drvType != "ESRI Shapefile")
                {
                    Dataset destDataset = Gdal.wrapper_GDALVectorTranslateDestName(shpPath, src, new GDALVectorTranslateOptions(ogr2ogrOptions.ToArray()), null, null);
                    destDataset.Dispose();
                    shpPathList.Add(shpPath);
                }

                ///Export multiple layers for shapefile
                ///https://trac.osgeo.org/gdal/wiki/FAQVector#HowdoItranslateamixedgeometryfiletoshapefileformat
                else
                {
                    ///
                    if (shpTypeList.Count <= 1 && shpTypeList.First() != "GEOMETRYCOLLECTION")
                    {
                        if (shpTypeList.First() == "POLYGON" || shpTypeList.First() == "MULTIPOLYGON")
                        {
                            ogr2ogrOptions.AddRange(new List <string> {
                                "-lco", "SHPT=MULTIPATCH"
                            });
                        }
                        Dataset destDataset = Gdal.wrapper_GDALVectorTranslateDestName(shpPath, src, new GDALVectorTranslateOptions(ogr2ogrOptions.ToArray()), null, null);
                        destDataset.Dispose();
                        shpPathList.Add(shpPath);
                    }

                    else
                    {
                        ///Add -explodecollections for mixed geometries in a branch
                        ///"-where" statement is not necessary, but could speed up big datasets

                        string        shpFileName       = string.Empty;
                        List <string> ogr2ogrShpOptions = new List <string>();

                        if (shpTypeList.Contains("POINT") || shpTypeList.Contains("MULTIPOINT"))
                        {
                            shpFileName = folder + filename + "_points.shp";
                            shpPathList.Add(shpFileName);
                            List <string> ogr2ogrShpOptionsPts = new List <string> {
                                "-overwrite",
                                "-f", drvType,
                                "-dim", "XYZ",
                                "-skipfailures"
                            };
                            //ogr2ogrShpOptionsPts.AddRange(new List<string> { "-where", "ogr_geometry=POINT", "-where", "ogr_geometry=MULTIPOINT", "-lco", "SHPT=MULTIPOINTZ", "-nlt", "PROMOTE_TO_MULTI"});
                            ogr2ogrShpOptionsPts.AddRange(new List <string> {
                                "-sql", "SELECT * FROM " + filename + " WHERE OGR_GEOMETRY='MULTIPOINT' OR OGR_GEOMETRY='POINT'", "-lco", "SHPT=MULTIPOINTZ", "-nlt", "PROMOTE_TO_MULTI"
                            });
                            //ogr2ogrShpOptionsPts.AddRange(new List<string> { "-dialect", "sqlite", "-sql", "select * from " + filename + " where GeometryType(geometry) in ('POINT','MULTIPOINT')", "-lco", "SHPT=MULTIPOINTZ", "-nlt", "PROMOTE_TO_MULTI" });

                            Dataset destDatasetPoint = Gdal.wrapper_GDALVectorTranslateDestName(shpFileName, src, new GDALVectorTranslateOptions(ogr2ogrShpOptionsPts.ToArray()), null, null);
                            destDatasetPoint.Dispose();
                        }

                        if (shpTypeList.Contains("LINESTRING") || shpTypeList.Contains("MULTILINESTRING"))
                        {
                            shpFileName = folder + filename + "_lines.shp";
                            shpPathList.Add(shpFileName);
                            List <string> ogr2ogrShpOptionsLines = new List <string> {
                                "-overwrite",
                                "-f", drvType,
                                "-dim", "XYZ",
                                "-skipfailures"
                            };
                            //ogr2ogrShpOptionsLines.AddRange(new List<string> { "-where", "ogr_geometry=LINESTRING25D", "-where", "ogr_geometry=MULTILINESTRING25D", "-lco", "SHPT=ARCZ", "-nlt", "PROMOTE_TO_MULTI" });
                            ogr2ogrShpOptionsLines.AddRange(new List <string> {
                                "-sql", "SELECT * FROM " + filename + " WHERE OGR_GEOMETRY='LINESTRING' OR OGR_GEOMETRY='MULTILINESTRING'", "-lco", "SHPT=ARCZ", "-nlt", "PROMOTE_TO_MULTI"
                            });
                            //ogr2ogrShpOptionsLines.AddRange(new List<string> { "-dialect", "sqlite", "-sql", "select * from " + filename + " where GeometryType(geometry) in ('LINESTRING','MULTILINESTRING')", "-lco", "SHPT=ARCZ", "-nlt", "PROMOTE_TO_MULTI" });

                            Dataset destDatasetLinestring = Gdal.wrapper_GDALVectorTranslateDestName(shpFileName, src, new GDALVectorTranslateOptions(ogr2ogrShpOptionsLines.ToArray()), null, null);
                            destDatasetLinestring.Dispose();
                        }

                        if (shpTypeList.Contains("POLYGON") || shpTypeList.Contains("MULTIPOLYGON"))
                        {
                            shpFileName = folder + filename + "_polygons.shp";
                            shpPathList.Add(shpFileName);
                            List <string> ogr2ogrShpOptionsPolygons = new List <string> {
                                "-overwrite",
                                "-f", drvType,
                                "-dim", "XYZ",
                                "-skipfailures",
                                "-dsco", "SHAPE_REWIND_ON_WRITE=NO"
                            };
                            //ogr2ogrShpOptionsPolygons.AddRange(new List<string> { "-where", "ogr_geometry=POLYGON", "-where", "ogr_geometry=MULTIPOLYGON", "-lco", "SHPT=POLYGONZ", "-nlt", "PROMOTE_TO_MULTI" });
                            ogr2ogrShpOptionsPolygons.AddRange(new List <string> {
                                "-sql", "SELECT * FROM " + filename + " WHERE OGR_GEOMETRY='MULTIPOLYGON25D' OR OGR_GEOMETRY='POLYGON25D'", "-lco", "SHPT=POLYGONZ", "-nlt", "PROMOTE_TO_MULTI"
                            });
                            Dataset destDatasetPolygon = Gdal.wrapper_GDALVectorTranslateDestName(shpFileName, src, new GDALVectorTranslateOptions(ogr2ogrShpOptionsPolygons.ToArray()), null, null);
                            destDatasetPolygon.Dispose();
                        }

                        ///Not working properly when multiple geometry types are part of the same branch for SHP export.
                        if (shpTypeList.Contains("GEOMETRYCOLLECTION"))
                        {
                            AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "One or more branches contain a mix of geometry types.");
                            ///export points
                            shpFileName = folder + filename + "_gc-points.shp";
                            shpPathList.Add(shpFileName);
                            List <string> ogr2ogrShpOptionsGCPts = new List <string> {
                                "-overwrite",
                                "-f", drvType,
                                "-dim", "XYZ",
                                "-skipfailures"
                            };
                            ogr2ogrShpOptionsGCPts.AddRange(new List <string> {
                                "-explodecollections", "-where", "ogr_geometry=GEOMETRYCOLLECTION", "-lco", "SHPT=MULTIPOINTZ", "-nlt", "PROMOTE_TO_MULTI"
                            });
                            //ogr2ogrShpOptionsGCPts.AddRange(new List<string> { "-explodecollections", "-sql", "SELECT * FROM " + filename + " WHERE OGR_GEOMETRY='MULTIPOINT' OR OGR_GEOMETRY='POINT'", "-lco", "SHPT=MULTIPOINTZ", "-nlt", "PROMOTE_TO_MULTI" });

                            Dataset destDatasetGCPoints = Gdal.wrapper_GDALVectorTranslateDestName(shpFileName, src, new GDALVectorTranslateOptions(ogr2ogrShpOptionsGCPts.ToArray()), null, null);
                            destDatasetGCPoints.Dispose();

                            ///export lines
                            shpFileName = folder + filename + "_gc-lines.shp";
                            shpPathList.Add(shpFileName);
                            List <string> ogr2ogrShpOptionsGCLines = new List <string> {
                                "-overwrite",
                                "-f", drvType,
                                "-dim", "XYZ",
                                "-skipfailures"
                            };
                            ogr2ogrShpOptionsGCLines.AddRange(new List <string> {
                                "-explodecollections", "-where", "ogr_geometry=GEOMETRYCOLLECTION", "-lco", "SHPT=ARCZ", "-nlt", "PROMOTE_TO_MULTI"
                            });
                            //ogr2ogrShpOptionsGCLines.AddRange(new List<string> { "-explodecollections", "-sql", "SELECT * FROM " + filename + " WHERE OGR_GEOMETRY='MULTILINESTRING25D' OR OGR_GEOMETRY='LINESTRING25D'", "-lco", "SHPT=ARCZ", "-nlt", "PROMOTE_TO_MULTI" });
                            Dataset destDatasetGCLines = Gdal.wrapper_GDALVectorTranslateDestName(shpFileName, src, new GDALVectorTranslateOptions(ogr2ogrShpOptionsGCLines.ToArray()), null, null);
                            destDatasetGCLines.Dispose();

                            ///export meshes
                            shpFileName = folder + filename + "_gc-polygons.shp";
                            shpPathList.Add(shpFileName);
                            List <string> ogr2ogrShpOptionsGCPolygons = new List <string> {
                                "-overwrite",
                                "-f", drvType,
                                "-dim", "XYZ",
                                "-skipfailures",
                                "-dsco", "SHAPE_REWIND_ON_WRITE=NO"
                            };
                            ogr2ogrShpOptionsGCPolygons.AddRange(new List <string> {
                                "-explodecollections", "-where", "ogr_geometry=GEOMETRYCOLLECTION", "-lco", "SHPT=POLYGONZ", "-nlt", "PROMOTE_TO_MULTI"
                            });
                            //ogr2ogrShpOptionsGCPolygons.AddRange(new List<string> { "-explodecollections", "-sql", "SELECT * FROM " + filename + " WHERE OGR_GEOMETRY='MULTIPOLYGON' OR OGR_GEOMETRY='POLYGON'", "-lco", "SHPT=POLYGONZ", "-nlt", "PROMOTE_TO_MULTI" });
                            Dataset destDatasetGCPolygons = Gdal.wrapper_GDALVectorTranslateDestName(shpFileName, src, new GDALVectorTranslateOptions(ogr2ogrShpOptionsGCPolygons.ToArray()), null, null);
                            destDatasetGCPolygons.Dispose();
                        }
                    }
                }

                ///Clean up
                Gdal.Unlink("/vsimem/out.geojson");
            }

            DA.SetDataList(0, shpPathList);
        }
        /// <summary>
        /// Outputs the specified DotSpatial IFeatureLayer to an OGR layer
        /// </summary>
        /// <param name="pDrvNm">A name like KML, ESRI SHapefile or FileGDB etc.</param>
        /// <param name="pFLyr">A layer that implements the IFeatureLayer interface</param>
        /// <param name="pOPFn">The outputShapefileName of the output file</param>
        /// <param name="pSrcProj">The SRS of the source dataset</param>
        /// <param name="pTgtProj">The SRS of the output dataset</param>
        /// <param name="pHasTitle">A boolean flag that determines whether to create fieldAttributes special title field</param>
        /// <param name="pTitleFieldNames">A comma separated list of field names to be used in the special title field</param>
        /// <param name="pTitleFormat">The C# String.Format format of the special title field</param>
        /// <param name="pLCOpts">A string array of layer creation options in the form of OPTION=VALUE entries</param>
        /// <param name="pDSCOpts">A string of data source creation options in the form of OPTION=VALUE entries</param>
        /// <param name="pFieldMap">A dictionary of source and target field names to be translated on the source
        /// the title format field names and the special title field name all observe this field mapping.</param>
        /// <param name="pOnlyInFieldMap">If true, only writes fields that are included in the field-map</param>
        /// <returns>True on success, false on error</returns>
        /// <remarks>
        /// Presently implements special functions for KML that perhaps should be kept separate.
        /// </remarks>
        public static ReturnValue ExportFeatureLayerToOGR(
            string pDrvNm, IFeatureLayer pFLyr,
            string pOPFn, ProjectionInfo pSrcProj,
            ProjectionInfo pTgtProj,
            bool pHasTitle          = false,
            string pTitleFieldNames = "",
            string pTitleFormat     = "",
            List <string> pLCOpts   = null,
            List <string> pDSCOpts  = null,
            Dictionary <string, string> pFieldMap = null,
            bool pOnlyInFieldMap = false, bool pAppend = false)
        {
            var mReturnValue = new ReturnValue(true);

            //Check if data source and layer creation options are null and if so, create an empty list object for them
            pDSCOpts = (pDSCOpts != null) ? pDSCOpts : new List <string>();
            pLCOpts  = (pLCOpts != null) ? pLCOpts : new List <string>();

            // May or may not be used, declared in any case;
            Dictionary <string, string> mTitleFieldValues = null;

            // Determine whether transformation is required
            bool mTransformRequired = (pSrcProj != pTgtProj) ? true : false;

            // Read the target SRS
            SpatialReference mTgtSRS = ExtFunctions.GetSpatialReferenceByEPSG(pTgtProj.AuthorityCode);

            // If transformation is needed, create fieldAttributes shared transformation object for the export
            if (mTransformRequired)
            {
                pFLyr.Projection = pSrcProj;
                pFLyr.Reproject(pTgtProj);
            }

            // Setup driver
            OSGeo.OGR.Driver drv = Ogr.GetDriverByName(pDrvNm);
            if (drv == null)
            {
                mReturnValue.AddMessage("Could not load driver", true);
                return(mReturnValue);
            }

            // Special handling of KML mFiles
            // Add special title name as datasource creation option
            if (pHasTitle && pDrvNm == "KML")
            {
                pDSCOpts.Add("NameField=" + ExtFunctions.TitleFieldName);
            }

            // Create fieldAttributes datasource
            DataSource ds = null;

            try
            {
                if (pAppend && (Directory.Exists(pOPFn) || File.Exists(pOPFn)))
                {
                    ds = drv.Open(pOPFn, 1);
                }
                else
                {
                    ds = drv.CreateDataSource(pOPFn, pDSCOpts.ToArray());
                }
                if (ds == null)
                {
                    mReturnValue.AddMessage("Could not create/open datasource");
                    return(mReturnValue);
                }
            }
            catch (Exception ex)
            {
                mReturnValue.AddMessage(ex.Message);
                return(mReturnValue);
            }

            // Find the geometry type of the source layer to determine output type
            wkbGeometryType mGeomType = DSGeomTypeToOgrGeomType(pFLyr.DataSet.FeatureType);

            if (mGeomType == wkbGeometryType.wkbNone)
            {
                mReturnValue.AddMessage("Could not parse geometry type of input layer");
                return(mReturnValue);
            }

            // Create the new layer
            OSGeo.OGR.Layer l;
            if (pAppend && ds.HasLayer(pFLyr.LegendText.Replace(" ", "_")))
            {
                l = ds.GetLayerByName(pFLyr.LegendText.Replace(" ", "_"));
            }
            else
            {
                l = ds.CreateLayer(pFLyr.LegendText, mTgtSRS, mGeomType, pLCOpts.ToArray());
            }
            if (l == null)
            {
                mReturnValue.AddMessage("Failed to create file: ");
                return(mReturnValue);
            }

            // Create fieldAttributes list to hold the names of fields
            var mDataSourceFieldNames = new List <string>();

            // Loop through all the fields
            foreach (DataColumn mDataColumn in pFLyr.DataSet.DataTable.Columns)
            {
                var mColType  = DataTypeToOgrFieldType(mDataColumn.DataType);
                var mNewField = new FieldDefn(MapFieldName(mDataColumn.ColumnName, pFieldMap), mColType);

                if (mColType == FieldType.OFTString)
                {
                    mNewField.SetWidth(mDataColumn.MaxLength);
                }


                if (pOnlyInFieldMap == false || (pOnlyInFieldMap && pFieldMap.Keys.Contains(mDataColumn.ColumnName)))
                {
                    if (!pAppend || !l.HasField(mNewField.GetName()))
                    {
                        if (Ogr.OGRERR_NONE != l.CreateField(mNewField, 1))
                        {
                            mReturnValue.AddMessage("Failed to add field: " + mDataColumn.ColumnName + " => " + MapFieldName(mDataColumn.ColumnName, pFieldMap));
                            return(mReturnValue);
                        }
                    }
                }

                mDataSourceFieldNames.Add(mNewField.GetName());
            }

            // Add special title field, if the necessary information is present
            if (pHasTitle == true &&
                !string.IsNullOrEmpty(pTitleFieldNames) &&
                !string.IsNullOrEmpty(pTitleFormat) &&
                !mDataSourceFieldNames.Contains(ExtFunctions.TitleFieldName))
            {
                mTitleFieldValues = new Dictionary <string, string>();

                var mTitleField = new FieldDefn(MapFieldName(TitleFieldName, pFieldMap), FieldType.OFTString);
                mTitleField.SetWidth(254);

                foreach (var mTitleFieldName in pTitleFieldNames.Split(','))
                {
                    mTitleFieldValues.Add(mTitleFieldName, "");
                }

                l.CreateField(mTitleField, 1);
            }

            int createdFeatures = 0;

            // For each row in the source featureset
            for (int i = 0; i < pFLyr.DataSet.NumRows(); i++)
            {
                // Read the source feature
                IFeature mSrcFeature = pFLyr.DataSet.GetFeature(i);

                // Read and set the geometry on the new feature
                byte[] mSrcGeom = mSrcFeature.ToBinary();
                var    mFeature = new OSGeo.OGR.Feature(l.GetLayerDefn());
                var    mGeom    = OSGeo.OGR.Geometry.CreateFromWkb(mSrcGeom);
                mFeature.SetGeometry(mGeom);

                // Set feature id
                mFeature.SetFID(i);

                // Handle fieldAttributes
                for (int j = 0; j < mDataSourceFieldNames.Count(); j++)
                {
                    var mCurrentValue = mSrcFeature.DataRow[j];

                    if (pOnlyInFieldMap == false || (pOnlyInFieldMap && pFieldMap.Values.Contains(mDataSourceFieldNames[j])))
                    {
                        if (mCurrentValue.GetType() == typeof(string))
                        {
                            mFeature.SetField(mDataSourceFieldNames[j], Utilities.GetANSI((string)mCurrentValue));
                        }
                        else if (mCurrentValue.GetType() == typeof(int))
                        {
                            mFeature.SetField(mDataSourceFieldNames[j], (int)mCurrentValue);
                        }
                        else if (mCurrentValue.GetType() == typeof(double))
                        {
                            mFeature.SetField(mDataSourceFieldNames[j], (double)mCurrentValue);
                        }
                    }


                    if (pHasTitle && mTitleFieldValues.Keys.Contains(mDataSourceFieldNames[j]))
                    {
                        mTitleFieldValues[mDataSourceFieldNames[j]] = mCurrentValue.ToString();
                    }
                }

                // If title field is to be created, use field values collected above to construct fieldAttributes new string format
                // to go into the title-field
                if (pHasTitle == true)
                {
                    var mTitleValue = string.Format(pTitleFormat, mTitleFieldValues.Values.ToArray <string>());
                    mFeature.SetField(MapFieldName(TitleFieldName, pFieldMap), Utilities.GetANSI(mTitleValue));
                }

                // Create the feature
                try
                {
                    l.CreateFeature(mFeature);
                    createdFeatures++;
                }
                catch (Exception ex)
                {
                    mReturnValue.AddMessage(ex.Message);
                    mReturnValue.AddMessage("Tip: A datasource may appear read-only if the file location is inside a dropbox folder and the dropbox application is running");
                }
            }

            if (mTransformRequired)
            {
                pFLyr.Reproject(pSrcProj);
            }
            // Dispose and cleanup
            l.Dispose();
            ds.Dispose();
            drv.Dispose();

            mReturnValue.AddMessage(String.Format("Added {0} features to layer {1}",
                                                  createdFeatures,
                                                  pFLyr.LegendText));

            return(mReturnValue);
        }