using System; using System.Collections.Generic; using System.Text; using ESRI.ArcGIS.Geodatabase; using System.Runtime.InteropServices; using System.Data; using Kingo.Mobile.Shape2KOTool; using ESRI.ArcGIS.Geometry; using ESRI.ArcGIS.Carto; using KGIS.Framework.Utils; using KGIS.Framework.AE.ExtensionMethod; using OSGeo.OGR; using OSGeo.GDAL; using Kingo.Plugin.MakeTaskPackage.Model; using ESRI.ArcGIS.DataSourcesFile; using ESRI.ArcGIS.DataSourcesGDB; using KGIS.Framework.Maps; namespace Kingo.Plugin.MakeTaskPackage.Common { public class ArcFeatureDataSource : Kingo.Mobile.Shape2KOTool.KoDataBase.ISpatialDataSource { private IQueryFilter pQueryFilter = new QueryFilterClass() { WhereClause = "1=1" }; private IQueryFilter pSpatialFilter = new SpatialFilterClass() { WhereClause = "1=1" }; private DataRow dr = null; public ArcFeatureDataSource(IFeatureClass featureClass, ESRI.ArcGIS.Geometry.IGeometry queryGeometry, string geometryField, string whereClause, List fields) { this.FeatureSource = featureClass; if (!string.IsNullOrEmpty(whereClause)) this.pQueryFilter.WhereClause = whereClause; IEnvelope envelope = (FeatureSource as IGeoDataset).Extent; if (queryGeometry != null) { pSpatialFilter = new SpatialFilterClass() { Geometry = queryGeometry, GeometryField = geometryField, SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects, WhereClause = this.pQueryFilter.WhereClause }; envelope = queryGeometry.Envelope; } //获取字段 this.Fields = new List(); for (int i = 0; i < FeatureSource.Fields.FieldCount; i++) { IField field = FeatureSource.Fields.get_Field(i); //Kingo.Mobile.Shape2KOTool.XSDClass.Field fieldS = fields.Find(p => p.Name.ToLower() == field.Name.ToLower()); //if (fieldS == null) continue; if (featureClass.ShapeFieldName == field.Name) continue; this.Fields.Add(ConvertArcFieldToShapeFieldInfo(FeatureSource.Fields.get_Field(i), null)); } //获取空间参考 ISpatialReference spatialReference = (FeatureSource as IGeoDataset).SpatialReference; int wkid = spatialReference.FactoryCode; SpatialRefrenceStruct srs = SpatialRefrenceStruct.GetAllData().Find(p => p.WKID == wkid); if (srs != null) { this.SpatialReference = srs; } this.RecordCount = FeatureSource.FeatureCount(pQueryFilter); // 获取图形类型 点 线 面 this.GeometryType = (Mobile.Shape2KOTool.XSDClass.esriGeometryType)FeatureSource.ShapeType; //计算最大范围 if (envelope.IsEmpty) { //当图层数据为空时,extent为空 this.Extent = new Mobile.Shape2KOTool.XSDClass.EnvelopeN(); } else { this.Extent = new Kingo.Mobile.Shape2KOTool.XSDClass.EnvelopeN() { XMax = envelope.XMax, XMin = envelope.XMin, YMax = envelope.YMax, YMin = envelope.YMin }; } //创建DataTable Table = new DataTable(); foreach (var item in this.Fields) { Table.Columns.Add(item.FieldName, typeof(object)); } //this.Table.Columns.Add("OBJECTID", typeof(int)); this.Table.Columns.Add("SHAPE", typeof(string)); dr = Table.NewRow(); } public ArcFeatureDataSource( IFeatureLayer featureLayer, ESRI.ArcGIS.Geometry.IGeometry queryGeometry, string where="") { try { //// 注册所有的驱动 //Ogr.RegisterAll(); //Gdal.AllRegister(); ////消除中文路径无法识别的问题 //OSGeo.GDAL.Gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES"); ////解决shape文件字段中文内容读取问题 //OSGeo.GDAL.Gdal.SetConfigOption("SHAPE_ENCODING", "UTF-8"); this.FeatureSource = featureLayer.FeatureClass; if (!string.IsNullOrWhiteSpace(where)) { this.pQueryFilter.WhereClause = where; } else { this.pQueryFilter.WhereClause = (featureLayer as IFeatureLayerDefinition).DefinitionExpression; } IEnvelope envelope = (FeatureSource as IGeoDataset).Extent; if (queryGeometry != null) { pSpatialFilter = new SpatialFilterClass() { Geometry = queryGeometry, GeometryField = featureLayer.FeatureClass.ShapeFieldName, SpatialRel = esriSpatialRelEnum.esriSpatialRelContains, WhereClause = this.pQueryFilter.WhereClause }; envelope = queryGeometry.Envelope; } else { pSpatialFilter.WhereClause = where; } //获取字段 this.Fields = new List(); ILayerFields layerFields = featureLayer as ILayerFields; for (int i = 0; i < FeatureSource.Fields.FieldCount; i++) { IField field = FeatureSource.Fields.get_Field(i); int index = layerFields.FindField(field.Name); IFieldInfo fieldInfo = layerFields.get_FieldInfo(index); if (!fieldInfo.Visible) continue; if (FeatureSource.ShapeFieldName == field.Name) continue; this.Fields.Add(ConvertArcFieldToShapeFieldInfo(FeatureSource.Fields.get_Field(i), fieldInfo.Alias)); } //增加SHAPE_AREA 字段 //int areaIndex= layerFields.FindField("SHAPE_AREA"); //if (areaIndex < 0) //{ // this.Fields.Add(new ShapeFieldInfo() { // FieldName="SHAPE_AREA", // FieldAlias = "SHAPE_AREA", // FieldType= eFieldType.shpDouble // }); //} //获取空间参考 ISpatialReference spatialReference = (FeatureSource as IGeoDataset).SpatialReference; int wkid = spatialReference.FactoryCode; SpatialRefrenceStruct srs = SpatialRefrenceStruct.GetAllData().Find(p => p.WKID == wkid); if (srs != null) { this.SpatialReference = srs; } this.RecordCount = FeatureSource.FeatureCount(pQueryFilter); // 获取图形类型 点 线 面 this.GeometryType = (Mobile.Shape2KOTool.XSDClass.esriGeometryType)FeatureSource.ShapeType; //计算最大范围 if (envelope.IsEmpty) { //当图层数据为空时,extent为空 this.Extent = new Mobile.Shape2KOTool.XSDClass.EnvelopeN(); } else { this.Extent = new Kingo.Mobile.Shape2KOTool.XSDClass.EnvelopeN() { XMax = envelope.XMax, XMin = envelope.XMin, YMax = envelope.YMax, YMin = envelope.YMin }; } //创建DataTable Table = new DataTable(); foreach (var item in this.Fields) { Table.Columns.Add(item.FieldName, typeof(object)); } //this.Table.Columns.Add("OBJECTID", typeof(int)); this.Table.Columns.Add("SHAPE", typeof(string)); dr = Table.NewRow(); } catch (Exception ex) { LogAPI.Debug("获取图层信息失败:" + ex); } } private DataTable Table = null; private IFeatureCursor pFeatureCursor = null; public void Close() { if (pFeatureCursor != null) { Marshal.ReleaseComObject(pFeatureCursor); pFeatureCursor = null; } this.EOF = true; } public IFeatureClass FeatureSource { get; private set; } public string DataSourcePath { get; set; } public Dictionary Distinct(string fieldName) { Dictionary values = new Dictionary(); //ICursor cursor = (ICursor)FeatureSource.Search(null, false); //IDataStatistics dataStatistics = new DataStatisticsClass(); //dataStatistics.Field = "Layer"; //dataStatistics.Cursor = cursor; //System.Collections.IEnumerator enumerator = dataStatistics.UniqueValues; //enumerator.Reset(); //while (enumerator.MoveNext()) //{ // object myObject = enumerator.Current; // values.Add(myObject.ToString(), 0); //} ////cursor = (ICursor)featureClass.Search(null, false); //dataStatistics.Cursor = cursor; //ESRI.ArcGIS.esriSystem.IStatisticsResults statisticsResults = dataStatistics.Statistics; //Console.WriteLine("mean value - {0}", statisticsResults.Mean); IDataset pDataset = FeatureSource as IDataset; IQueryDef pQueryDef = (pDataset.Workspace.WorkspaceFactory as IFeatureWorkspace).CreateQueryDef(); pQueryDef.SubFields = "count(*)," + fieldName; pQueryDef.Tables = pDataset.Name + " group by " + fieldName; ICursor pCur = pQueryDef.Evaluate(); try { IRow row = pCur.NextRow(); while (row != null) { values.Add(row.get_Value(1).ToString(), Convert.ToInt32(row.get_Value(0))); } } finally { Marshal.ReleaseComObject(pCur); pCur = null; Marshal.ReleaseComObject(pQueryDef); pQueryDef = null; } return values; } public bool EOF { get; private set; } public Mobile.Shape2KOTool.XSDClass.EnvelopeN Extent { get; private set; } public List Fields { get; set; } public Mobile.Shape2KOTool.XSDClass.esriGeometryType GeometryType { get; private set; } public System.Data.DataTable GetAllRecord() { throw new NotImplementedException(); } private IFeature pFeature = null; public System.Data.DataRow GetNextRecord() { if (EOF == true) { throw new Exception("读取已经结束"); } if (pFeatureCursor == null) { throw new Exception("没有打开数据"); } //DateTime dt1 = DateTime.Now; //Console.WriteLine(DateTime.Now.ToString()); DataRow row = ConvertFeature2DataRow(pFeature); //DateTime dt2 = DateTime.Now; //Console.WriteLine(dt2.Subtract(dt1).TotalMilliseconds.ToString()); //释放资源 Marshal.ReleaseComObject(pFeature); pFeature = null; pFeature = pFeatureCursor.NextFeature(); if (pFeature == null) { EOF = true; } //DateTime dt3 = DateTime.Now; //Console.WriteLine(dt3.Subtract(dt2).TotalMilliseconds.ToString()); //GC.Collect(); //row.Delete(); //row = null; return row; } private System.Data.DataRow ConvertFeature2DataRow(IFeature feature) { //DateTime dt1 = DateTime.Now; //Console.WriteLine(DateTime.Now.ToString()); //DataRow dr = Table.NewRow(); foreach (DataColumn item in Table.Columns) { int index = feature.Fields.FindField(item.ColumnName); if (index > -1) { dr[item] = feature.get_Value(index); } } //DateTime dt2 = DateTime.Now; //Console.WriteLine(dt2.Subtract(dt1).TotalMilliseconds.ToString()); //if (feature.Shape.GeometryType == esriGeometryType.esriGeometryPolygon) //{ // IArea area = feature.Shape as IArea; // if (area != null) // dr["SHAPE_AREA"] = area.Area; //} //else // dr["SHAPE_AREA"] = 0; dr["SHAPE"] = GetShapeString(feature.ShapeCopy); //DateTime dt3 = DateTime.Now; //Console.WriteLine(dt3.Subtract(dt2).TotalMilliseconds.ToString()); return dr; } private string GetShapeString(IGeometry geometry) { byte[] wkb = ConvertGeometryToWKB(geometry); OSGeo.OGR.Geometry rstGeometry = null; try { rstGeometry = OSGeo.OGR.Geometry.CreateFromWkb(wkb); } catch (Exception ex) { LogAPI.Debug("rstGeometry:" + ex.Message); } string wkt = ""; try { rstGeometry.ExportToWkt(out wkt); } catch (Exception ex) { LogAPI.Debug("rstGeometry.ExportToWkt:" + ex.Message); } return wkt; if (geometry.GeometryType == esriGeometryType.esriGeometryPolygon) { IPolygon polygon = geometry as IPolygon; if (polygon == null || polygon.IsEmpty) return "MULTIPOLYGON EMPTY"; //"MULTIPOLYGON ((( 39496841.71395018 3996653.16102896, 39496672.94504374 3996656.38199206, 39496669.92898465 3996498.40799711, 39496838.69799109 3996495.18603399, 39496841.71395018 3996653.16102896)))" IGeometryCollection pGeometryCollection = polygon as IGeometryCollection; if (pGeometryCollection == null || pGeometryCollection.GeometryCount < 1) return "MULTIPOLYGON EMPTY"; StringBuilder sb = new StringBuilder("MULTIPOLYGON (("); for (int i = 0; i < pGeometryCollection.GeometryCount; i++) { if (pGeometryCollection.get_Geometry(i) is IRing) { sb.Append("("); IPointCollection pPoints = pGeometryCollection.get_Geometry(i) as IPointCollection; for (int j = 0; j < pPoints.PointCount; j++) { IPoint pt = pPoints.get_Point(j); sb.AppendFormat("{0} {1},", pt.X, pt.Y); } sb.Remove(sb.Length - 1, 1); sb.Append("),"); } } sb.Remove(sb.Length - 1, 1); sb.Append("))"); return sb.ToString(); } else if (geometry.GeometryType == esriGeometryType.esriGeometryPoint) { IPoint point = geometry as IPoint; if (point == null) return "POINT EMPTY"; return string.Format("POINT ( {0} {1})", point.X, point.Y); } else if (geometry.GeometryType == esriGeometryType.esriGeometryPolyline) { IPolyline polygon = geometry as IPolyline; if (polygon == null || polygon.IsEmpty) return "MULTILINESTRING EMPTY"; //"MULTIPOLYGON ((( 39496841.71395018 3996653.16102896, 39496672.94504374 3996656.38199206, 39496669.92898465 3996498.40799711, 39496838.69799109 3996495.18603399, 39496841.71395018 3996653.16102896)))" IGeometryCollection pGeometryCollection = polygon as IGeometryCollection; if (pGeometryCollection == null || pGeometryCollection.GeometryCount < 1) return "MULTILINESTRING EMPTY"; StringBuilder sb = new StringBuilder("MULTILINESTRING ("); for (int i = 0; i < pGeometryCollection.GeometryCount; i++) { if (pGeometryCollection.get_Geometry(i) is IPointCollection) { sb.Append("("); IPointCollection pPoints = pGeometryCollection.get_Geometry(i) as IPointCollection; for (int j = 0; j < pPoints.PointCount; j++) { IPoint pt = pPoints.get_Point(j); sb.AppendFormat("{0} {1},", pt.X, pt.Y); } sb.Remove(sb.Length - 1, 1); sb.Append("),"); } } sb.Remove(sb.Length - 1, 1); sb.Append(")"); return sb.ToString(); ; } else return "EMPTY"; } public byte[] ConvertGeometryToWKB(IGeometry geometry) { IWkb wkb = geometry as IWkb; //byte[] b = new byte[wkb.WkbSize]; //int byte_count = wkb.WkbSize; //try //{ // wkb.ExportToWkb(ref byte_count, out b[0]); //} //catch (Exception ex) //{ // Kingo.Mobile.Common.LogAPI.Debug(ex); //} //return b; ITopologicalOperator oper = geometry as ITopologicalOperator; oper.Simplify(); IGeometryFactory3 factory = new GeometryEnvironment() as IGeometryFactory3; byte[] b = factory.CreateWkbVariantFromGeometry(geometry) as byte[]; return b; } //public string ConvertGeometryToWKT(IGeometry geometry) //{ // byte[] b = ConvertGeometryToWKB(geometry); // WKBReader reader = new WKBReader(); // GeoAPI.Geometries.IGeometry g = reader.Read(b); // WKTWriter writer = new WKTWriter(); // return writer.Write(g); //} public void Open() { try { if (FeatureSource == null) { throw new Exception("矢量数据为空!"); } if (pFeatureCursor != null) { Marshal.ReleaseComObject(pFeatureCursor); pFeatureCursor = null; } if (pFeature != null) { Marshal.ReleaseComObject(pFeature); pFeature = null; } pFeatureCursor = FeatureSource.Search(pSpatialFilter, false); pFeature = pFeatureCursor.NextFeature(); //防止没有记录 if (pFeature == null) { EOF = true; } else { EOF = false; } } catch (Exception ex) { LogAPI.Debug("打开数据源失败:" + ex); } } private ShapeFieldInfo ConvertArcFieldToShapeFieldInfo(IField field, string aliasName) { ShapeFieldInfo pShapeFieldInfo = new ShapeFieldInfo(); pShapeFieldInfo.FieldName = field.Name; pShapeFieldInfo.FieldAlias = aliasName; pShapeFieldInfo.FieldSize = (short)field.Length; pShapeFieldInfo.FieldDecimal = (short)field.Scale; switch (field.Type) { case esriFieldType.esriFieldTypeInteger: case esriFieldType.esriFieldTypeSmallInteger: pShapeFieldInfo.FieldType = eFieldType.shpInteger; break; case esriFieldType.esriFieldTypeDouble: case esriFieldType.esriFieldTypeSingle: pShapeFieldInfo.FieldType = eFieldType.shpDouble; break; case esriFieldType.esriFieldTypeString: case esriFieldType.esriFieldTypeGlobalID: case esriFieldType.esriFieldTypeGUID: case esriFieldType.esriFieldTypeOID: case esriFieldType.esriFieldTypeXML: case esriFieldType.esriFieldTypeDate: pShapeFieldInfo.FieldType = eFieldType.shpText; break; //pShapeFieldInfo.FieldType = eFieldType.shpDate; break; default: pShapeFieldInfo.FieldType = eFieldType.shpText; break; } return pShapeFieldInfo; } public int RecordCount { get; private set; } public void Reset() { if (pFeatureCursor != null) { Marshal.ReleaseComObject(pFeatureCursor); pFeatureCursor = null; } if (pFeature != null) { Marshal.ReleaseComObject(pFeature); pFeature = null; } pFeatureCursor = FeatureSource.Search(pQueryFilter, false); pFeature = pFeatureCursor.NextFeature(); //防止没有记录 if (pFeature == null) { EOF = true; } else { EOF = false; } } public Mobile.Shape2KOTool.SpatialRefrenceStruct SpatialReference { get; private set; } } }