/// <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); }
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); }
/// <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); }
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); }
/// <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); }