//将任意坐标系统转换为自定义Albers大地坐标(米) public static IPoint GeoToGra(IPoint point) { IPoint pt = new PointClass(); pt.PutCoords(point.X, point.Y); ISpatialReferenceFactory2 pFact = new SpatialReferenceEnvironmentClass(); //定义地理坐标,由输入的对象决定,也可以自己定义,参考: esriSRGeoCSType IGeographicCoordinateSystem pGCS = new GeographicCoordinateSystemClass(); pGCS = pFact.CreateGeographicCoordinateSystem(point.SpatialReference.FactoryCode); //自定义投影方式 IProjectedCoordinateSystem pProjectedCS = new ProjectedCoordinateSystemClass(); IProjectedCoordinateSystemEdit pProjectedCSEdit = pProjectedCS as IProjectedCoordinateSystemEdit; //定义投影方式,参考: esriSRProjectionType IProjection pProjection = new ProjectionClass(); pProjection = pFact.CreateProjection((int)esriSRProjectionType.esriSRProjection_Albers); //定义投影单位,参考:esriSRUnitType ILinearUnit pUnit = new LinearUnitClass(); pUnit = pFact.CreateUnit((int)esriSRUnitType.esriSRUnit_Meter) as ILinearUnit; //定义其他参数,参考:esriSRParameterType IParameter[] pParm = new IParameter[6]; pParm[0] = pFact.CreateParameter((int)esriSRParameterType.esriSRParameter_FalseEasting); pParm[0].Value = 0; pParm[1] = pFact.CreateParameter((int)esriSRParameterType.esriSRParameter_FalseNorthing); pParm[1].Value = 0; pParm[2] = pFact.CreateParameter((int)esriSRParameterType.esriSRParameter_CentralMeridian); pParm[2].Value = 110; pParm[3] = pFact.CreateParameter((int)esriSRParameterType.esriSRParameter_StandardParallel1); pParm[3].Value = 25; pParm[4] = pFact.CreateParameter((int)esriSRParameterType.esriSRParameter_StandardParallel2); pParm[4].Value = 47; pParm[5] = pFact.CreateParameter((int)esriSRParameterType.esriSRParameter_LatitudeOfOrigin); pParm[5].Value = 0; //设置投影相关信息 object name = "User_Defined_Albers"; object alias = "Albers"; object abbreviation = "Albers"; object remarks = "User_Defined_Albers is the projection"; object usage = ""; object gcs = pGCS; object projectedUnit = pUnit; object projection = pProjection; object parameters = pParm; pProjectedCSEdit.Define(ref name, ref alias, ref abbreviation, ref remarks, ref usage, ref gcs, ref projectedUnit, ref projection, ref parameters); //获取自定义空间参考 ISpatialReference pSpatialRef = pProjectedCS as ISpatialReference; IGeometry pGeometry = (IGeometry)pt; pGeometry.SpatialReference = pGCS as ISpatialReference; //重投影处理 pGeometry.Project(pSpatialRef); return pt; }
static void Main(string[] args) { //ESRI License Initializer generated code. m_AOLicenseInitializer.InitializeApplication(new esriLicenseProductCode[] { esriLicenseProductCode.esriLicenseProductCodeAdvanced }, new esriLicenseExtensionCode[] { }); Dictionary <string, Vertex> nodeDict = new Dictionary <string, Vertex>(); Type factoryType = Type.GetTypeFromProgID("esriDataSourcesGDB.FileGDBWorkspaceFactory"); IWorkspaceFactory workspaceFactory = (IWorkspaceFactory)Activator.CreateInstance(factoryType); IWorkspace workspace = workspaceFactory.OpenFromFile(@"C:\Users\hellocomrade\NHDPlusV21_GL_04.gdb", 0); IFeatureWorkspace iFtrWs = workspace as IFeatureWorkspace; if (null != iFtrWs) { IFeatureClass fcLine = iFtrWs.OpenFeatureClass("NHD_Flowline"); IFeatureClass fcPoint = iFtrWs.OpenFeatureClass("Hydro_Net_Junctions"); System.Diagnostics.Debug.Assert(null != fcLine && null != fcPoint); var fldLst = new List <string> { "OBJECTID", "FlowDir", "FTYPE", "V0001E_MA", "V0001E_MM", "V0001E_01", "V0001E_02", "V0001E_03", "V0001E_04", "V0001E_05", "V0001E_06", "V0001E_07", "V0001E_08", "V0001E_09", "V0001E_10", "V0001E_11", "V0001E_12" }; Dictionary <string, int> fldDict = new Dictionary <string, int>(); fldLst.ForEach(fldName => fldDict.Add(fldName, fcLine.FindField(fldName))); int lineFtrId = -1; //Find field index for oid in Hydro_Net_Junctions feature class int pntFtrIdIdx = fcPoint.FindField("OBJECTID"); string pntFtrId = null; /* * It has been observed that the most time consuming part of this script is on spatial query. * We could take the same approach we had on Arcpy through fcLine.Search() with a spatial filter. * However, it will make us have the same granularity as using arcpy. * Instead, we took a different route here by using IFeatureIndex and IIndexQuery2 */ IGeoDataset geoLineDS = (IGeoDataset)fcLine; ISpatialReference srLine = geoLineDS.SpatialReference; IFeatureIndex lineIdx = new FeatureIndexClass(); lineIdx.FeatureClass = fcLine; lineIdx.Index(null, geoLineDS.Extent); IIndexQuery2 queryLineByIdx = lineIdx as IIndexQuery2; IFeatureIndex pointIdx = new FeatureIndexClass(); pointIdx.FeatureClass = fcPoint; pointIdx.Index(null, ((IGeoDataset)fcPoint).Extent); IIndexQuery2 queryPointByIdx = pointIdx as IIndexQuery2; //Get a cursor on Hydro_Net_Junctions as the iterator IFeatureCursor pntCur = fcPoint.Search(null, false); IFeature pnt = pntCur.NextFeature(); IFeature line = null; IFeature otherPnt = null; List <string> requiredTypes = new List <string> { "StreamRiver", "ArtificialPath" }; /* * ITopologicalOpeartor is good for two geometries comparing with each other. It doesn't fit * very well for our situation, which check the geometric relationships between a geometry * against a feature class that may have more than 100K geometries. */ //ITopologicalOperator optor = null; /* * It's a shame that we have to reference to a Server API in order to calcuate Geodesic * distances for a polyline with lon/lat as coordinates. * * We could do Haversine ourselves, but we have to believe ESRI could definitely does a * better job there, well, hard to figure out how to get this simple task done in an intutive * way though... */ IGeometryServer2 geoOperator = new GeometryServerClass(); IPolyline polyLine = null; List <DownstreamNode> dsLst = null; int[] lineIds = null; int[] pntIds = null; object idobjs; object idobjs1; PolylineArray tmpArr = null; IDoubleArray lengths = null; double lineLen = 0.0; double v = 0.0; ILinearUnit unit = new LinearUnitClass(); var range = Enumerable.Range(3, 14); int count = 0; int incoming = 0; while (null != pnt) { //get ftr id of the current vertex pntFtrId = pnt.get_Value(pntFtrIdIdx).ToString(); //optor = pnt.Shape as ITopologicalOperator; /* * This should return feature ids that interects with the given geometry in the feature * class having the index built. */ queryLineByIdx.IntersectedFeatures(pnt.Shape, out idobjs); lineIds = idobjs as int[]; if (null != lineIds && lineIds.Length > 0) { foreach (int id in lineIds) { line = fcLine.GetFeature(id); lineFtrId = int.Parse(line.get_Value(fldDict["OBJECTID"]).ToString()); if ("1" == line.get_Value(fldDict["FlowDir"]).ToString() && true == requiredTypes.Contains(line.get_Value(fldDict["FTYPE"]).ToString())) { polyLine = line.Shape as IPolyline; if (isSamePoint(polyLine.FromPoint, pnt.Shape as IPoint)) { queryPointByIdx.IntersectedFeatures(line.Shape, out idobjs1); pntIds = idobjs1 as int[]; if (null != pntIds && 2 == pntIds.Length) { foreach (int pid in pntIds) { otherPnt = fcPoint.GetFeature(pid); if (false == isSamePoint(otherPnt.Shape as IPoint, pnt.Shape as IPoint)) { tmpArr = new PolylineArrayClass(); tmpArr.Add(polyLine); lengths = geoOperator.GetLengthsGeodesic(srLine, tmpArr as IPolylineArray, unit); if (0 == lengths.Count) { continue; } lineLen = lengths.get_Element(0) * 3.28084; //var velos = from idx in range select double.Parse(line.get_Value(fldDict[fldLst[idx]]).ToString()); List <double> velos = new List <double>(); foreach (int idx in range) { v = double.Parse(line.get_Value(fldDict[fldLst[idx]]).ToString()); velos.Add(v == 0 ? 0 : lineLen / v); } if (null == dsLst) { dsLst = new List <DownstreamNode>(); } dsLst.Add(new DownstreamNode(pid, id, velos)); } } } } else // pnt at the end of the polyline { ++incoming; } } } } if (null != dsLst || incoming > 0) { nodeDict.Add(pntFtrId, new Vertex(int.Parse(pntFtrId), incoming, dsLst)); } pnt = pntCur.NextFeature(); if (++count % 1000 == 0) { Console.WriteLine("Processing Count: " + count); } incoming = 0; dsLst = null; }//end of while(null != pnt) ReleaseCOMObj(pntCur); } ReleaseCOMObj(workspaceFactory); //ESRI License Initializer generated code. //Do not make any call to ArcObjects after ShutDownApplication() m_AOLicenseInitializer.ShutdownApplication(); }
private void CalculateMetersKPHAndLanguageFields(string outputFileGdbPath) { // Open the Streets feature class and find the Meters and Language fields Type factoryType = Type.GetTypeFromProgID("esriDataSourcesGDB.FileGDBWorkspaceFactory"); var gdbWSF = Activator.CreateInstance(factoryType) as IWorkspaceFactory; var gdbFWS = gdbWSF.OpenFromFile(outputFileGdbPath, 0) as IFeatureWorkspace; IFeatureClass fc = gdbFWS.OpenFeatureClass(StreetsFCName); int metersField = fc.FindField("Meters"); int contrAccField = fc.FindField("CONTRACC"); int speedCatField = fc.FindField("SPEED_CAT"); int kphField = fc.FindField("KPH"); int suppliedLangField = fc.FindField("ST_LANGCD"); int suppliedLangAltField = fc.FindField("ST_LANGCD_Alt"); int languageField = fc.FindField("Language"); int languageAltField = fc.FindField("Language_Alt"); // Define a LinearUnit for meters ILinearUnit metersUnit = new LinearUnitClass(); double metersPerUnit = 1.0; ((ILinearUnitEdit)metersUnit).DefineEx("Meter", "Meter", "M", "Meter is the linear unit", ref metersPerUnit); // Get the language lookup hash System.Collections.Hashtable langLookup = CreateLanguageLookup(); // Use an UpdateCursor to populate the Meters field and Language fields IFeatureCursor cur = fc.Update(null, true); IFeature feat = null; while ((feat = cur.NextFeature()) != null) { var pg = feat.Shape as IPolycurveGeodetic; double geodLength = pg.get_LengthGeodetic(esriGeodeticType.esriGeodeticTypeGeodesic, metersUnit); feat.set_Value(metersField, geodLength); double kph = LookupKPH((string)(feat.get_Value(contrAccField)), (string)(feat.get_Value(speedCatField))); feat.set_Value(kphField, kph); string lang = SignpostUtilities.GetLanguageValue((string)(feat.get_Value(suppliedLangField)), langLookup); feat.set_Value(languageField, lang); // Alternate name language may be null -- we need to check for this condition before setting the value var getValueResult = feat.get_Value(suppliedLangAltField) as string; if (getValueResult != null) { string langAlt = SignpostUtilities.GetLanguageValue(getValueResult, langLookup); feat.set_Value(languageAltField, langAlt); } cur.UpdateFeature(feat); } }
static void Main(string[] args) { //ESRI License Initializer generated code. m_AOLicenseInitializer.InitializeApplication(new esriLicenseProductCode[] { esriLicenseProductCode.esriLicenseProductCodeAdvanced }, new esriLicenseExtensionCode[] { }); Dictionary<string, Vertex> nodeDict = new Dictionary<string, Vertex>(); Type factoryType = Type.GetTypeFromProgID("esriDataSourcesGDB.FileGDBWorkspaceFactory"); IWorkspaceFactory workspaceFactory = (IWorkspaceFactory)Activator.CreateInstance(factoryType); IWorkspace workspace = workspaceFactory.OpenFromFile(@"C:\Users\hellocomrade\NHDPlusV21_GL_04.gdb", 0); IFeatureWorkspace iFtrWs = workspace as IFeatureWorkspace; if(null != iFtrWs) { IFeatureClass fcLine = iFtrWs.OpenFeatureClass("NHD_Flowline"); IFeatureClass fcPoint = iFtrWs.OpenFeatureClass("Hydro_Net_Junctions"); System.Diagnostics.Debug.Assert(null != fcLine && null != fcPoint); var fldLst = new List<string>{"OBJECTID","FlowDir","FTYPE","V0001E_MA","V0001E_MM","V0001E_01","V0001E_02","V0001E_03","V0001E_04","V0001E_05","V0001E_06","V0001E_07","V0001E_08","V0001E_09","V0001E_10","V0001E_11","V0001E_12"}; Dictionary<string,int> fldDict = new Dictionary<string,int>(); fldLst.ForEach(fldName => fldDict.Add(fldName, fcLine.FindField(fldName))); int lineFtrId = -1; //Find field index for oid in Hydro_Net_Junctions feature class int pntFtrIdIdx = fcPoint.FindField("OBJECTID"); string pntFtrId = null; /* * It has been observed that the most time consuming part of this script is on spatial query. * We could take the same approach we had on Arcpy through fcLine.Search() with a spatial filter. * However, it will make us have the same granularity as using arcpy. * Instead, we took a different route here by using IFeatureIndex and IIndexQuery2 */ IGeoDataset geoLineDS = (IGeoDataset)fcLine; ISpatialReference srLine = geoLineDS.SpatialReference; IFeatureIndex lineIdx = new FeatureIndexClass(); lineIdx.FeatureClass = fcLine; lineIdx.Index(null, geoLineDS.Extent); IIndexQuery2 queryLineByIdx = lineIdx as IIndexQuery2; IFeatureIndex pointIdx = new FeatureIndexClass(); pointIdx.FeatureClass = fcPoint; pointIdx.Index(null, ((IGeoDataset)fcPoint).Extent); IIndexQuery2 queryPointByIdx = pointIdx as IIndexQuery2; //Get a cursor on Hydro_Net_Junctions as the iterator IFeatureCursor pntCur = fcPoint.Search(null, false); IFeature pnt = pntCur.NextFeature(); IFeature line = null; IFeature otherPnt = null; List<string> requiredTypes = new List<string>{"StreamRiver","ArtificialPath"}; /* * ITopologicalOpeartor is good for two geometries comparing with each other. It doesn't fit * very well for our situation, which check the geometric relationships between a geometry * against a feature class that may have more than 100K geometries. */ //ITopologicalOperator optor = null; /* * It's a shame that we have to reference to a Server API in order to calcuate Geodesic * distances for a polyline with lon/lat as coordinates. * * We could do Haversine ourselves, but we have to believe ESRI could definitely does a * better job there, well, hard to figure out how to get this simple task done in an intutive * way though... */ IGeometryServer2 geoOperator = new GeometryServerClass(); IPolyline polyLine = null; List<DownstreamNode> dsLst = null; int[] lineIds = null; int[] pntIds = null; object idobjs; object idobjs1; PolylineArray tmpArr = null; IDoubleArray lengths = null; double lineLen = 0.0; double v = 0.0; ILinearUnit unit = new LinearUnitClass(); var range = Enumerable.Range(3, 14); int count = 0; int incoming = 0; while(null != pnt) { //get ftr id of the current vertex pntFtrId = pnt.get_Value(pntFtrIdIdx).ToString(); //optor = pnt.Shape as ITopologicalOperator; /* * This should return feature ids that interects with the given geometry in the feature * class having the index built. */ queryLineByIdx.IntersectedFeatures(pnt.Shape, out idobjs); lineIds = idobjs as int[]; if(null != lineIds && lineIds.Length > 0) { foreach(int id in lineIds) { line = fcLine.GetFeature(id); lineFtrId = int.Parse(line.get_Value(fldDict["OBJECTID"]).ToString()); if ("1" == line.get_Value(fldDict["FlowDir"]).ToString() && true == requiredTypes.Contains(line.get_Value(fldDict["FTYPE"]).ToString())) { polyLine = line.Shape as IPolyline; if(isSamePoint(polyLine.FromPoint, pnt.Shape as IPoint)) { queryPointByIdx.IntersectedFeatures(line.Shape, out idobjs1); pntIds = idobjs1 as int[]; if(null != pntIds && 2 == pntIds.Length) { foreach(int pid in pntIds) { otherPnt = fcPoint.GetFeature(pid); if(false == isSamePoint(otherPnt.Shape as IPoint, pnt.Shape as IPoint)) { tmpArr = new PolylineArrayClass(); tmpArr.Add(polyLine); lengths = geoOperator.GetLengthsGeodesic(srLine, tmpArr as IPolylineArray, unit); if (0 == lengths.Count) continue; lineLen = lengths.get_Element(0) * 3.28084; //var velos = from idx in range select double.Parse(line.get_Value(fldDict[fldLst[idx]]).ToString()); List<double> velos = new List<double>(); foreach(int idx in range) { v = double.Parse(line.get_Value(fldDict[fldLst[idx]]).ToString()); velos.Add(v == 0 ? 0 : lineLen / v); } if (null == dsLst) dsLst = new List<DownstreamNode>(); dsLst.Add(new DownstreamNode(pid, id, velos)); } } } } else // pnt at the end of the polyline ++incoming; } } } if(null != dsLst || incoming > 0) nodeDict.Add(pntFtrId, new Vertex(int.Parse(pntFtrId), incoming, dsLst)); pnt = pntCur.NextFeature(); if (++count % 1000 == 0) Console.WriteLine("Processing Count: " + count); incoming = 0; dsLst = null; }//end of while(null != pnt) ReleaseCOMObj(pntCur); } ReleaseCOMObj(workspaceFactory); //ESRI License Initializer generated code. //Do not make any call to ArcObjects after ShutDownApplication() m_AOLicenseInitializer.ShutdownApplication(); }
//将任意坐标系统转换为自定义Albers大地坐标(米) public static IPoint GeoToGra(IPoint point) { IPoint pt = new PointClass(); pt.PutCoords(point.X, point.Y); ISpatialReferenceFactory2 pFact = new SpatialReferenceEnvironmentClass(); //定义地理坐标,由输入的对象决定,也可以自己定义,参考: esriSRGeoCSType IGeographicCoordinateSystem pGCS = new GeographicCoordinateSystemClass(); pGCS = pFact.CreateGeographicCoordinateSystem(point.SpatialReference.FactoryCode); //自定义投影方式 IProjectedCoordinateSystem pProjectedCS = new ProjectedCoordinateSystemClass(); IProjectedCoordinateSystemEdit pProjectedCSEdit = pProjectedCS as IProjectedCoordinateSystemEdit; //定义投影方式,参考: esriSRProjectionType IProjection pProjection = new ProjectionClass(); pProjection = pFact.CreateProjection((int)esriSRProjectionType.esriSRProjection_Albers); //定义投影单位,参考:esriSRUnitType ILinearUnit pUnit = new LinearUnitClass(); pUnit = pFact.CreateUnit((int)esriSRUnitType.esriSRUnit_Meter) as ILinearUnit; //定义其他参数,参考:esriSRParameterType IParameter[] pParm = new IParameter[6]; pParm[0] = pFact.CreateParameter((int)esriSRParameterType.esriSRParameter_FalseEasting); pParm[0].Value = 0; pParm[1] = pFact.CreateParameter((int)esriSRParameterType.esriSRParameter_FalseNorthing); pParm[1].Value = 0; pParm[2] = pFact.CreateParameter((int)esriSRParameterType.esriSRParameter_CentralMeridian); pParm[2].Value = 110; pParm[3] = pFact.CreateParameter((int)esriSRParameterType.esriSRParameter_StandardParallel1); pParm[3].Value = 25; pParm[4] = pFact.CreateParameter((int)esriSRParameterType.esriSRParameter_StandardParallel2); pParm[4].Value = 47; pParm[5] = pFact.CreateParameter((int)esriSRParameterType.esriSRParameter_LatitudeOfOrigin); pParm[5].Value = 0; //设置投影相关信息 object name = "User_Defined_Albers"; object alias = "Albers"; object abbreviation = "Albers"; object remarks = "User_Defined_Albers is the projection"; object usage = ""; object gcs = pGCS; object projectedUnit = pUnit; object projection = pProjection; object parameters = pParm; pProjectedCSEdit.Define(ref name, ref alias, ref abbreviation, ref remarks, ref usage, ref gcs, ref projectedUnit, ref projection, ref parameters); //获取自定义空间参考 ISpatialReference pSpatialRef = pProjectedCS as ISpatialReference; IGeometry pGeometry = (IGeometry)pt; pGeometry.SpatialReference = pGCS as ISpatialReference; //重投影处理 pGeometry.Project(pSpatialRef); return(pt); }