internal List<string> loadOSMWays(string osmFileLocation, ref ITrackCancel TrackCancel, ref IGPMessages message, IGPValue targetGPValue, IFeatureClass osmPointFeatureClass, IFeatureClass osmLineFeatureClass, IFeatureClass osmPolygonFeatureClass, bool conserveMemory, bool fastLoad, int wayCapacity, ref Dictionary<string, simplePointRef> osmNodeDictionary, IFeatureWorkspace featureWorkspace, ISpatialReference downloadSpatialReference, OSMDomains availableDomains, bool checkForExisting) { if (osmLineFeatureClass == null) { throw new ArgumentNullException("osmLineFeatureClass"); } if (osmPolygonFeatureClass == null) { throw new ArgumentNullException("osmPolygonFeatureClass"); } XmlReader osmFileXmlReader = null; XmlSerializer waySerializer = null; List<string> missingWays = null; try { missingWays = new List<string>(); int osmPointIDFieldIndex = osmPointFeatureClass.FindField("OSMID"); int osmWayRefCountFieldIndex = osmPointFeatureClass.FindField("wayRefCount"); int osmLineIDFieldIndex = osmLineFeatureClass.FindField("OSMID"); Dictionary<string, int> osmLineDomainAttributeFieldIndices = new Dictionary<string, int>(); Dictionary<string, int> osmLineDomainAttributeFieldLength = new Dictionary<string, int>(); foreach (var domains in availableDomains.domain) { int currentFieldIndex = osmLineFeatureClass.FindField(domains.name); if (currentFieldIndex != -1) { osmLineDomainAttributeFieldIndices.Add(domains.name, currentFieldIndex); osmLineDomainAttributeFieldLength.Add(domains.name, osmLineFeatureClass.Fields.get_Field(currentFieldIndex).Length); } } int tagCollectionPolylineFieldIndex = osmLineFeatureClass.FindField("osmTags"); int osmUserPolylineFieldIndex = osmLineFeatureClass.FindField("osmuser"); int osmUIDPolylineFieldIndex = osmLineFeatureClass.FindField("osmuid"); int osmVisiblePolylineFieldIndex = osmLineFeatureClass.FindField("osmvisible"); int osmVersionPolylineFieldIndex = osmLineFeatureClass.FindField("osmversion"); int osmChangesetPolylineFieldIndex = osmLineFeatureClass.FindField("osmchangeset"); int osmTimeStampPolylineFieldIndex = osmLineFeatureClass.FindField("osmtimestamp"); int osmMemberOfPolylineFieldIndex = osmLineFeatureClass.FindField("osmMemberOf"); int osmMembersPolylineFieldIndex = osmLineFeatureClass.FindField("osmMembers"); int osmSupportingElementPolylineFieldIndex = osmLineFeatureClass.FindField("osmSupportingElement"); int osmPolygonIDFieldIndex = osmPolygonFeatureClass.FindField("OSMID"); Dictionary<string, int> osmPolygonDomainAttributeFieldIndices = new Dictionary<string, int>(); Dictionary<string, int> osmPolygonDomainAttributeFieldLength = new Dictionary<string, int>(); foreach (var domains in availableDomains.domain) { int currentFieldIndex = osmPolygonFeatureClass.FindField(domains.name); if (currentFieldIndex != -1) { osmPolygonDomainAttributeFieldIndices.Add(domains.name, currentFieldIndex); osmPolygonDomainAttributeFieldLength.Add(domains.name, osmPolygonFeatureClass.Fields.get_Field(currentFieldIndex).Length); } } int tagCollectionPolygonFieldIndex = osmPolygonFeatureClass.FindField("osmTags"); int osmUserPolygonFieldIndex = osmPolygonFeatureClass.FindField("osmuser"); int osmUIDPolygonFieldIndex = osmPolygonFeatureClass.FindField("osmuid"); int osmVisiblePolygonFieldIndex = osmPolygonFeatureClass.FindField("osmvisible"); int osmVersionPolygonFieldIndex = osmPolygonFeatureClass.FindField("osmversion"); int osmChangesetPolygonFieldIndex = osmPolygonFeatureClass.FindField("osmchangeset"); int osmTimeStampPolygonFieldIndex = osmPolygonFeatureClass.FindField("osmtimestamp"); int osmMemberOfPolygonFieldIndex = osmPolygonFeatureClass.FindField("osmMemberOf"); int osmMembersPolygonFieldIndex = osmPolygonFeatureClass.FindField("osmMembers"); int osmSupportingElementPolygonFieldIndex = osmPolygonFeatureClass.FindField("osmSupportingElement"); ISpatialReferenceFactory spatialRef = new SpatialReferenceEnvironmentClass(); ISpatialReference wgs84 = spatialRef.CreateGeographicCoordinateSystem((int)esriSRGeoCSType.esriSRGeoCS_WGS1984); bool shouldProject = !((IClone)wgs84).IsEqual((IClone)downloadSpatialReference); // set up the progress indicator IStepProgressor stepProgressor = TrackCancel as IStepProgressor; if (stepProgressor != null) { stepProgressor.MinRange = 0; stepProgressor.MaxRange = wayCapacity; stepProgressor.Position = 0; stepProgressor.Message = _resourceManager.GetString("GPTools_OSMGPFileReader_loadingWays"); stepProgressor.StepValue = 1; stepProgressor.Show(); } bool lineIndexRebuildRequired = false; bool polygonIndexRebuildRequired = false; int wayCount = 0; object missingValue = System.Reflection.Missing.Value; // enterprise GDB indicator -- supporting load only mode IFeatureClassLoad lineFeatureLoad = null; IFeatureClassLoad polygonFeatureLoad = null; using (SchemaLockManager lineLock = new SchemaLockManager(osmLineFeatureClass as ITable), polygonLock = new SchemaLockManager(osmPolygonFeatureClass as ITable)) { using (ComReleaser comReleaser = new ComReleaser()) { IFeatureCursor insertLineCursor = osmLineFeatureClass.Insert(true); comReleaser.ManageLifetime(insertLineCursor); IFeatureBuffer featureLineBuffer = osmLineFeatureClass.CreateFeatureBuffer(); comReleaser.ManageLifetime(featureLineBuffer); IFeatureCursor insertPolygonCursor = osmPolygonFeatureClass.Insert(true); comReleaser.ManageLifetime(insertPolygonCursor); IFeatureBuffer featurePolygonBuffer = osmPolygonFeatureClass.CreateFeatureBuffer(); comReleaser.ManageLifetime(featurePolygonBuffer); if (((IWorkspace)featureWorkspace).WorkspaceFactory.WorkspaceType == esriWorkspaceType.esriRemoteDatabaseWorkspace) { lineFeatureLoad = osmLineFeatureClass as IFeatureClassLoad; polygonFeatureLoad = osmPolygonFeatureClass as IFeatureClassLoad; } if (lineFeatureLoad != null) { lineFeatureLoad.LoadOnlyMode = true; } if (polygonFeatureLoad != null) { polygonFeatureLoad.LoadOnlyMode = true; } ISpatialReference nativeLineSpatialReference = ((IGeoDataset)osmLineFeatureClass).SpatialReference; ISpatialReference nativePolygonSpatialReference = ((IGeoDataset)osmPolygonFeatureClass).SpatialReference; IQueryFilter osmIDQueryFilter = new QueryFilterClass(); string sqlPointOSMID = osmPointFeatureClass.SqlIdentifier("OSMID"); IFeatureCursor updatePointCursor = null; osmFileXmlReader = System.Xml.XmlReader.Create(osmFileLocation); waySerializer = new XmlSerializer(typeof(way)); // the point query filter for updates will not changes, so let's do that ahead of time try { osmIDQueryFilter.SubFields = osmPointFeatureClass.ShapeFieldName + "," + osmPointFeatureClass.Fields.get_Field(osmPointIDFieldIndex).Name + "," + osmPointFeatureClass.Fields.get_Field(osmWayRefCountFieldIndex).Name; } catch { } osmFileXmlReader.MoveToContent(); while (osmFileXmlReader.Read()) { if (osmFileXmlReader.IsStartElement()) { if (osmFileXmlReader.Name == "way") { string currentwayString = osmFileXmlReader.ReadOuterXml(); // assuming the way to be a polyline is sort of a safe assumption // and won't cause any topology problem due to orientation and closeness bool wayIsLine = true; bool wayIsComplete = true; way currentWay = null; try { using (StringReader wayReader = new System.IO.StringReader(currentwayString)) { currentWay = waySerializer.Deserialize(wayReader) as way; } // if the deserialization fails then go ahead and read the next xml element if (currentWay == null) { continue; } // and we are expecting at least some nodes on the way itself if (currentWay.nd == null) { continue; } featureLineBuffer = osmLineFeatureClass.CreateFeatureBuffer(); featurePolygonBuffer = osmPolygonFeatureClass.CreateFeatureBuffer(); IPointCollection wayPointCollection = null; wayIsLine = IsThisWayALine(currentWay); if (wayIsLine) { // check if a feature with the same OSMID already exists, because the can only be one if (checkForExisting == true) { if (CheckIfExists(osmLineFeatureClass as ITable, currentWay.id)) { continue; } } IPolyline wayPolyline = new PolylineClass(); comReleaser.ManageLifetime(wayPointCollection); wayPolyline.SpatialReference = downloadSpatialReference; IPointIDAware polylineIDAware = wayPolyline as IPointIDAware; polylineIDAware.PointIDAware = true; wayPointCollection = wayPolyline as IPointCollection; # region generate line geometry if (conserveMemory == false) { for (int ndIndex = 0; ndIndex < currentWay.nd.Length; ndIndex++) { string ndID = currentWay.nd[ndIndex].@ref; if (osmNodeDictionary.ContainsKey(ndID)) { IPoint newPoint = new PointClass(); newPoint.X = osmNodeDictionary[ndID].Longitude; newPoint.Y = osmNodeDictionary[ndID].Latitude; newPoint.SpatialReference = wgs84; if (shouldProject) { newPoint.Project(((IGeoDataset)osmLineFeatureClass).SpatialReference); } IPointIDAware idAware = newPoint as IPointIDAware; idAware.PointIDAware = true; newPoint.ID = osmNodeDictionary[ndID].pointObjectID; wayPointCollection.AddPoint(newPoint, ref missingValue, ref missingValue); osmNodeDictionary[ndID].RefCounter = osmNodeDictionary[ndID].RefCounter + 1; } else { message.AddWarning(String.Format(_resourceManager.GetString("GPTools_OSMGPFileReader_undeterminedline_node"), currentWay.id, ndID)); // set the flag that the way is complete due to a missing node wayIsComplete = false; break; } } } else { for (int pointIndex = 0; pointIndex < currentWay.nd.Length; pointIndex++) { wayPointCollection.AddPoint(new PointClass()); } List<string> idRequests = SplitOSMIDRequests(currentWay, 2); // build a list of node ids we can use to determine the point index in the line geometry // as well as a dictionary to determine the position in the list in case of duplicates nodes Dictionary<string, int> nodePositionDictionary = new Dictionary<string, int>(currentWay.nd.Length); List<string> nodeIDs = new List<string>(currentWay.nd.Length); foreach (nd wayNode in currentWay.nd) { nodeIDs.Add(wayNode.@ref); if (nodePositionDictionary.ContainsKey(wayNode.@ref) == false) { nodePositionDictionary.Add(wayNode.@ref, 0); } } try { osmIDQueryFilter.SubFields = osmPointFeatureClass.ShapeFieldName + "," + osmPointFeatureClass.Fields.get_Field(osmPointIDFieldIndex).Name + "," + osmPointFeatureClass.Fields.get_Field(osmWayRefCountFieldIndex).Name; } catch { } foreach (string request in idRequests) { string idCompareString = request; osmIDQueryFilter.WhereClause = sqlPointOSMID + " IN " + request; using (ComReleaser innerComReleaser = new ComReleaser()) { updatePointCursor = osmPointFeatureClass.Update(osmIDQueryFilter, true); innerComReleaser.ManageLifetime(updatePointCursor); IFeature nodeFeature = updatePointCursor.NextFeature(); while (nodeFeature != null) { // determine the index of the point in with respect to the node position string nodeOSMIDString = Convert.ToString(nodeFeature.get_Value(osmPointIDFieldIndex)); // remove the ID from the request string idCompareString = idCompareString.Replace(nodeOSMIDString, String.Empty); int nodePositionIndex = -1; while ((nodePositionIndex = nodeIDs.IndexOf(nodeOSMIDString, nodePositionDictionary[nodeOSMIDString])) != -1) { //// update the new position start search index nodePositionDictionary[nodeOSMIDString] = nodePositionIndex + 1; wayPointCollection.UpdatePoint(nodePositionIndex, (IPoint)nodeFeature.Shape); // increase the reference counter if (osmWayRefCountFieldIndex != -1) { nodeFeature.set_Value(osmWayRefCountFieldIndex, ((int)nodeFeature.get_Value(osmWayRefCountFieldIndex)) + 1); updatePointCursor.UpdateFeature(nodeFeature); } } if (nodeFeature != null) Marshal.ReleaseComObject(nodeFeature); nodeFeature = updatePointCursor.NextFeature(); } idCompareString = CleanReportedNodes(idCompareString); // after removing the commas we should be left with only paranthesis left, meaning a string of length 2 // if we have more then we have found a missing node, resulting in an incomplete way geometry if (idCompareString.Length > 2) { message.AddWarning(String.Format(_resourceManager.GetString("GPTools_OSMGPFileReader_undeterminedline_node"), currentWay.id, idCompareString)); wayIsComplete = false; } } } } #endregion if (wayIsComplete == false) { // if the way geometry is incomplete due to a missing node let's continue to the next way element missingWays.Add(currentWay.id); continue; } featureLineBuffer.Shape = wayPolyline; featureLineBuffer.set_Value(osmLineIDFieldIndex, currentWay.id); } else { // check if a feature with the same OSMID already exists, because the can only be one if (checkForExisting == true) { if (CheckIfExists(osmPolygonFeatureClass as ITable, currentWay.id)) { continue; } } IPolygon wayPolygon = new PolygonClass(); comReleaser.ManageLifetime(wayPointCollection); wayPolygon.SpatialReference = downloadSpatialReference; IPointIDAware polygonIDAware = wayPolygon as IPointIDAware; polygonIDAware.PointIDAware = true; wayPointCollection = wayPolygon as IPointCollection; #region generate polygon geometry if (conserveMemory == false) { for (int ndIndex = 0; ndIndex < currentWay.nd.Length; ndIndex++) { string ndID = currentWay.nd[ndIndex].@ref; if (osmNodeDictionary.ContainsKey(ndID)) { IPoint newPoint = new PointClass(); newPoint.X = osmNodeDictionary[ndID].Longitude; newPoint.Y = osmNodeDictionary[ndID].Latitude; newPoint.SpatialReference = wgs84; if (shouldProject) { newPoint.Project(nativePolygonSpatialReference); } IPointIDAware idAware = newPoint as IPointIDAware; idAware.PointIDAware = true; newPoint.ID = osmNodeDictionary[ndID].pointObjectID; wayPointCollection.AddPoint(newPoint, ref missingValue, ref missingValue); } else { message.AddWarning(String.Format(_resourceManager.GetString("GPTools_OSMGPFileReader_undeterminedpolygon_node"), currentWay.id, ndID)); wayIsComplete = false; break; } } } else { for (int pointIndex = 0; pointIndex < currentWay.nd.Length; pointIndex++) { wayPointCollection.AddPoint(new PointClass()); } List<string> idRequests = SplitOSMIDRequests(currentWay, 2); // build a list of node ids we can use to determine the point index in the line geometry // as well as a dictionary to determine the position in the list in case of duplicates nodes Dictionary<string, int> nodePositionDictionary = new Dictionary<string, int>(currentWay.nd.Length); List<string> nodeIDs = new List<string>(currentWay.nd.Length); foreach (nd wayNode in currentWay.nd) { nodeIDs.Add(wayNode.@ref); if (nodePositionDictionary.ContainsKey(wayNode.@ref) == false) { nodePositionDictionary.Add(wayNode.@ref, 0); } } try { osmIDQueryFilter.SubFields = osmPointFeatureClass.ShapeFieldName + "," + osmPointFeatureClass.Fields.get_Field(osmPointIDFieldIndex).Name + "," + osmPointFeatureClass.Fields.get_Field(osmWayRefCountFieldIndex).Name; } catch { } foreach (string osmIDRequest in idRequests) { string idCompareString = osmIDRequest; using (ComReleaser innercomReleaser = new ComReleaser()) { osmIDQueryFilter.WhereClause = sqlPointOSMID + " IN " + osmIDRequest; updatePointCursor = osmPointFeatureClass.Update(osmIDQueryFilter, false); innercomReleaser.ManageLifetime(updatePointCursor); IFeature nodeFeature = updatePointCursor.NextFeature(); while (nodeFeature != null) { // determine the index of the point in with respect to the node position string nodeOSMIDString = Convert.ToString(nodeFeature.get_Value(osmPointIDFieldIndex)); idCompareString = idCompareString.Replace(nodeOSMIDString, String.Empty); int nodePositionIndex = nodeIDs.IndexOf(nodeOSMIDString, nodePositionDictionary[nodeOSMIDString]); // update the new position start search index nodePositionDictionary[nodeOSMIDString] = nodePositionIndex + 1; wayPointCollection.UpdatePoint(nodePositionIndex, (IPoint)nodeFeature.Shape); // increase the reference counter if (osmWayRefCountFieldIndex != -1) { nodeFeature.set_Value(osmWayRefCountFieldIndex, ((int)nodeFeature.get_Value(osmWayRefCountFieldIndex)) + 1); updatePointCursor.UpdateFeature(nodeFeature); } if (nodeFeature != null) Marshal.ReleaseComObject(nodeFeature); nodeFeature = updatePointCursor.NextFeature(); } idCompareString = CleanReportedNodes(idCompareString); if (idCompareString.Length > 2) { message.AddWarning(String.Format(_resourceManager.GetString("GPTools_OSMGPFileReader_undeterminedpolygon_node"), currentWay.id, idCompareString)); wayIsComplete = false; } } } } #endregion if (wayIsComplete == false) { continue; } // remove the last point as OSM considers them to be coincident wayPointCollection.RemovePoints(wayPointCollection.PointCount - 1, 1); ((IPolygon)wayPointCollection).Close(); featurePolygonBuffer.Shape = (IPolygon)wayPointCollection; featurePolygonBuffer.set_Value(osmPolygonIDFieldIndex, currentWay.id); } if (wayIsLine) { insertTags(osmLineDomainAttributeFieldIndices, osmLineDomainAttributeFieldLength, tagCollectionPolylineFieldIndex, featureLineBuffer, currentWay.tag); } else { insertTags(osmPolygonDomainAttributeFieldIndices, osmPolygonDomainAttributeFieldLength, tagCollectionPolygonFieldIndex, featurePolygonBuffer, currentWay.tag); } // store the administrative attributes // user, uid, version, changeset, timestamp, visible if (fastLoad == false) { if (!String.IsNullOrEmpty(currentWay.user)) { if (wayIsLine) { if (osmUserPolylineFieldIndex != -1) { featureLineBuffer.set_Value(osmUserPolylineFieldIndex, currentWay.user); } } else { if (osmUserPolygonFieldIndex != -1) { featurePolygonBuffer.set_Value(osmUserPolygonFieldIndex, currentWay.user); } } } if (!String.IsNullOrEmpty(currentWay.uid)) { if (wayIsLine) { if (osmUIDPolylineFieldIndex != -1) { featureLineBuffer.set_Value(osmUIDPolylineFieldIndex, Convert.ToInt32(currentWay.uid)); } } else { if (osmUIDPolygonFieldIndex != -1) { featurePolygonBuffer.set_Value(osmUIDPolygonFieldIndex, Convert.ToInt32(currentWay.uid)); } } } if (wayIsLine) { if (osmVisiblePolylineFieldIndex != -1) { featureLineBuffer.set_Value(osmVisiblePolylineFieldIndex, currentWay.visible.ToString()); } } else { if (osmVisiblePolygonFieldIndex != -1) { featurePolygonBuffer.set_Value(osmVisiblePolygonFieldIndex, currentWay.visible.ToString()); } } if (!String.IsNullOrEmpty(currentWay.version)) { if (wayIsLine) { if (osmVersionPolylineFieldIndex != -1) { featureLineBuffer.set_Value(osmVersionPolylineFieldIndex, Convert.ToInt32(currentWay.version)); } } else { if (osmVersionPolygonFieldIndex != -1) { featurePolygonBuffer.set_Value(osmVersionPolygonFieldIndex, Convert.ToInt32(currentWay.version)); } } } if (!String.IsNullOrEmpty(currentWay.changeset)) { if (wayIsLine) { if (osmChangesetPolylineFieldIndex != -1) { featureLineBuffer.set_Value(osmChangesetPolylineFieldIndex, Convert.ToInt32(currentWay.changeset)); } } else { if (osmChangesetPolygonFieldIndex != -1) { featurePolygonBuffer.set_Value(osmChangesetPolygonFieldIndex, Convert.ToInt32(currentWay.changeset)); } } } if (!String.IsNullOrEmpty(currentWay.timestamp)) { try { if (wayIsLine) { if (osmTimeStampPolylineFieldIndex != -1) { featureLineBuffer.set_Value(osmTimeStampPolylineFieldIndex, Convert.ToDateTime(currentWay.timestamp)); } } else { if (osmTimeStampPolygonFieldIndex != -1) { featurePolygonBuffer.set_Value(osmTimeStampPolygonFieldIndex, Convert.ToDateTime(currentWay.timestamp)); } } } catch (Exception ex) { message.AddWarning(String.Format(_resourceManager.GetString("GPTools_OSMGPFileReader_invalidTimeFormat"), ex.Message)); } } if (wayIsLine) { if (osmSupportingElementPolylineFieldIndex > -1) { if (currentWay.tag == null) { featureLineBuffer.set_Value(osmSupportingElementPolylineFieldIndex, "yes"); } else { featureLineBuffer.set_Value(osmSupportingElementPolylineFieldIndex, "no"); } } } else { if (osmSupportingElementPolygonFieldIndex > -1) { if (currentWay.tag == null) { featurePolygonBuffer.set_Value(osmSupportingElementPolygonFieldIndex, "yes"); } else { featurePolygonBuffer.set_Value(osmSupportingElementPolygonFieldIndex, "no"); } } } } // fast load try { if (wayIsLine) { insertLineCursor.InsertFeature(featureLineBuffer); lineIndexRebuildRequired = true; } else { insertPolygonCursor.InsertFeature(featurePolygonBuffer); polygonIndexRebuildRequired = true; } wayCount = wayCount + 1; if (stepProgressor != null) { stepProgressor.Position = wayCount; } if ((wayCount % 50000) == 0) { message.AddMessage(String.Format(_resourceManager.GetString("GPTools_OSMGPFileReader_waysloaded"), wayCount)); } } catch (Exception ex) { message.AddWarning(ex.Message); message.AddWarning(currentwayString); } } catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.Message); System.Diagnostics.Debug.WriteLine(ex.StackTrace); } finally { if (featureLineBuffer != null) { Marshal.ReleaseComObject(featureLineBuffer); if (featureLineBuffer != null) featureLineBuffer = null; } if (featurePolygonBuffer != null) { Marshal.ReleaseComObject(featurePolygonBuffer); if (featurePolygonBuffer != null) featurePolygonBuffer = null; } currentWay = null; } if (TrackCancel.Continue() == false) { insertPolygonCursor.Flush(); if (polygonFeatureLoad != null) { polygonFeatureLoad.LoadOnlyMode = false; } insertLineCursor.Flush(); if (lineFeatureLoad != null) { lineFeatureLoad.LoadOnlyMode = false; } return missingWays; } } } } osmFileXmlReader.Close(); if (stepProgressor != null) { stepProgressor.Hide(); } message.AddMessage(String.Format(_resourceManager.GetString("GPTools_OSMGPFileReader_waysloaded"), wayCount)); insertPolygonCursor.Flush(); if (polygonFeatureLoad != null) { polygonFeatureLoad.LoadOnlyMode = false; } insertLineCursor.Flush(); if (lineFeatureLoad != null) { lineFeatureLoad.LoadOnlyMode = false; } } } IGeoProcessor2 geoProcessor = new GeoProcessorClass(); IGPUtilities3 gpUtilities3 = new GPUtilitiesClass(); bool storedOriginal = geoProcessor.AddOutputsToMap; IVariantArray parameterArrary = null; IGeoProcessorResult2 gpResults2 = null; try { geoProcessor.AddOutputsToMap = false; if (lineIndexRebuildRequired) { IIndexes featureClassIndexes = osmLineFeatureClass.Indexes; int indexPosition = -1; featureClassIndexes.FindIndex("osmID_IDX", out indexPosition); string fcLocation = GetLocationString(targetGPValue, osmLineFeatureClass); if (indexPosition == -1) { message.AddMessage(_resourceManager.GetString("GPTools_buildinglineidx")); // Addd index for osmid column parameterArrary = CreateAddIndexParameterArray(fcLocation, "OSMID", "osmID_IDX", "UNIQUE", ""); gpResults2 = geoProcessor.Execute("AddIndex_management", parameterArrary, TrackCancel) as IGeoProcessorResult2; } if (wayCount > 100) { // in this case we are dealing with a file geodatabase if (lineFeatureLoad == null) { UpdateSpatialGridIndex(TrackCancel, message, geoProcessor, fcLocation); } } } if (polygonIndexRebuildRequired) { IIndexes featureClassIndexes = osmPolygonFeatureClass.Indexes; int indexPosition = -1; featureClassIndexes.FindIndex("osmID_IDX", out indexPosition); string fcLocation = GetLocationString(targetGPValue, osmPolygonFeatureClass); if (indexPosition == -1) { message.AddMessage(_resourceManager.GetString("GPTools_buildingpolygonidx")); IGPValue polygonFeatureClassGPValue = gpUtilities3.MakeGPValueFromObject(osmPolygonFeatureClass); if (polygonFeatureClassGPValue != null) { // Addd index for osmid column parameterArrary = CreateAddIndexParameterArray(fcLocation, "OSMID", "osmID_IDX", "UNIQUE", ""); gpResults2 = geoProcessor.Execute("AddIndex_management", parameterArrary, TrackCancel) as IGeoProcessorResult2; } } if (wayCount > 100) { if (polygonFeatureLoad == null) { UpdateSpatialGridIndex(TrackCancel, message, geoProcessor, fcLocation); } } } } catch (Exception ex) { message.AddWarning(ex.Message); } finally { geoProcessor.AddOutputsToMap = storedOriginal; Marshal.FinalReleaseComObject(gpUtilities3); Marshal.FinalReleaseComObject(geoProcessor); } } catch (Exception ex) { message.AddWarning(ex.Message); } finally { if (waySerializer != null) waySerializer = null; if (osmFileXmlReader != null) osmFileXmlReader = null; System.GC.Collect(); System.GC.WaitForPendingFinalizers(); } return missingWays; }
internal List<ESRI.ArcGIS.OSM.OSMClassExtension.tag> MergeTagsFromOuterPolygonToRelation(ESRI.ArcGIS.OSM.OSMClassExtension.relation currentRelation, IFeatureClass polygonFeatureClass) { Dictionary<string, ESRI.ArcGIS.OSM.OSMClassExtension.tag> mergedTagList = new Dictionary<string, ESRI.ArcGIS.OSM.OSMClassExtension.tag>(); IQueryFilter osmIDQueryFilter = new QueryFilterClass(); try { int osmIDPolygonFieldIndex = polygonFeatureClass.FindField("OSMID"); string sqlPolyOSMID = polygonFeatureClass.SqlIdentifier("OSMID"); foreach (var relationItem in currentRelation.Items) { if (relationItem is ESRI.ArcGIS.OSM.OSMClassExtension.member) { ESRI.ArcGIS.OSM.OSMClassExtension.member currentRelationMember = relationItem as ESRI.ArcGIS.OSM.OSMClassExtension.member; if (currentRelationMember.role.ToLower().Equals("outer")) { using (ComReleaser comReleaser = new ComReleaser()) { osmIDQueryFilter.WhereClause = sqlPolyOSMID + " = " + currentRelationMember.@ref; IFeatureCursor featureCursor = polygonFeatureClass.Search(osmIDQueryFilter, false); comReleaser.ManageLifetime(featureCursor); IFeature foundPolygonFeature = featureCursor.NextFeature(); if (foundPolygonFeature == null) continue; tag[] foundTags = _osmUtility.retrieveOSMTags(foundPolygonFeature, osmIDPolygonFieldIndex, ((IDataset)polygonFeatureClass).Workspace); foreach (tag currentWayTag in foundTags) { // first one in wins try { if (!mergedTagList.ContainsKey(currentWayTag.k)) { mergedTagList.Add(currentWayTag.k, currentWayTag); } } catch { } } } } } else if (relationItem is tag) { tag relationTag = relationItem as tag; try { if (!mergedTagList.ContainsKey(relationTag.k)) { mergedTagList.Add(relationTag.k, relationTag); } } catch { } } } } catch { } return mergedTagList.Values.ToList(); }
internal List<string> loadOSMRelations(string osmFileLocation, ref ITrackCancel TrackCancel, ref IGPMessages message, IGPValue targetGPValue, IFeatureClass osmPointFeatureClass, IFeatureClass osmLineFeatureClass, IFeatureClass osmPolygonFeatureClass, int relationCapacity, ITable relationTable, OSMDomains availableDomains, bool fastLoad, bool checkForExisting) { List<string> missingRelations = null; XmlReader osmFileXmlReader = null; XmlSerializer relationSerializer = null; try { missingRelations = new List<string>(); if (osmLineFeatureClass == null) { throw new ArgumentNullException("osmLineFeatureClass"); } if (osmPolygonFeatureClass == null) { throw new ArgumentNullException("osmPolygonFeatureClass"); } if (relationTable == null) { throw new ArgumentNullException("relationTable"); } int osmPointIDFieldIndex = osmPointFeatureClass.FindField("OSMID"); Dictionary<string, int> osmPointDomainAttributeFieldIndices = new Dictionary<string, int>(); foreach (var domains in availableDomains.domain) { int currentFieldIndex = osmPointFeatureClass.FindField(domains.name); if (currentFieldIndex != -1) { osmPointDomainAttributeFieldIndices.Add(domains.name, currentFieldIndex); } } int tagCollectionPointFieldIndex = osmPointFeatureClass.FindField("osmTags"); int osmUserPointFieldIndex = osmPointFeatureClass.FindField("osmuser"); int osmUIDPointFieldIndex = osmPointFeatureClass.FindField("osmuid"); int osmVisiblePointFieldIndex = osmPointFeatureClass.FindField("osmvisible"); int osmVersionPointFieldIndex = osmPointFeatureClass.FindField("osmversion"); int osmChangesetPointFieldIndex = osmPointFeatureClass.FindField("osmchangeset"); int osmTimeStampPointFieldIndex = osmPointFeatureClass.FindField("osmtimestamp"); int osmMemberOfPointFieldIndex = osmPointFeatureClass.FindField("osmMemberOf"); int osmSupportingElementPointFieldIndex = osmPointFeatureClass.FindField("osmSupportingElement"); int osmWayRefCountFieldIndex = osmPointFeatureClass.FindField("wayRefCount"); int osmLineIDFieldIndex = osmLineFeatureClass.FindField("OSMID"); Dictionary<string, int> osmLineDomainAttributeFieldIndices = new Dictionary<string, int>(); Dictionary<string, int> osmLineDomainAttributeFieldLength = new Dictionary<string, int>(); foreach (var domains in availableDomains.domain) { int currentFieldIndex = osmLineFeatureClass.FindField(domains.name); if (currentFieldIndex != -1) { osmLineDomainAttributeFieldIndices.Add(domains.name, currentFieldIndex); osmLineDomainAttributeFieldLength.Add(domains.name, osmLineFeatureClass.Fields.get_Field(currentFieldIndex).Length); } } int tagCollectionPolylineFieldIndex = osmLineFeatureClass.FindField("osmTags"); int osmUserPolylineFieldIndex = osmLineFeatureClass.FindField("osmuser"); int osmUIDPolylineFieldIndex = osmLineFeatureClass.FindField("osmuid"); int osmVisiblePolylineFieldIndex = osmLineFeatureClass.FindField("osmvisible"); int osmVersionPolylineFieldIndex = osmLineFeatureClass.FindField("osmversion"); int osmChangesetPolylineFieldIndex = osmLineFeatureClass.FindField("osmchangeset"); int osmTimeStampPolylineFieldIndex = osmLineFeatureClass.FindField("osmtimestamp"); int osmMemberOfPolylineFieldIndex = osmLineFeatureClass.FindField("osmMemberOf"); int osmMembersPolylineFieldIndex = osmLineFeatureClass.FindField("osmMembers"); int osmSupportingElementPolylineFieldIndex = osmLineFeatureClass.FindField("osmSupportingElement"); int osmPolygonIDFieldIndex = osmPolygonFeatureClass.FindField("OSMID"); Dictionary<string, int> osmPolygonDomainAttributeFieldIndices = new Dictionary<string, int>(); Dictionary<string, int> osmPolygonDomainAttributeFieldLength = new Dictionary<string, int>(); foreach (var domains in availableDomains.domain) { int currentFieldIndex = osmPolygonFeatureClass.FindField(domains.name); if (currentFieldIndex != -1) { osmPolygonDomainAttributeFieldIndices.Add(domains.name, currentFieldIndex); osmPolygonDomainAttributeFieldLength.Add(domains.name, osmPolygonFeatureClass.Fields.get_Field(currentFieldIndex).Length); } } int tagCollectionPolygonFieldIndex = osmPolygonFeatureClass.FindField("osmTags"); int osmUserPolygonFieldIndex = osmPolygonFeatureClass.FindField("osmuser"); int osmUIDPolygonFieldIndex = osmPolygonFeatureClass.FindField("osmuid"); int osmVisiblePolygonFieldIndex = osmPolygonFeatureClass.FindField("osmvisible"); int osmVersionPolygonFieldIndex = osmPolygonFeatureClass.FindField("osmversion"); int osmChangesetPolygonFieldIndex = osmPolygonFeatureClass.FindField("osmchangeset"); int osmTimeStampPolygonFieldIndex = osmPolygonFeatureClass.FindField("osmtimestamp"); int osmMemberOfPolygonFieldIndex = osmPolygonFeatureClass.FindField("osmMemberOf"); int osmMembersPolygonFieldIndex = osmPolygonFeatureClass.FindField("osmMembers"); int osmSupportingElementPolygonFieldIndex = osmPolygonFeatureClass.FindField("osmSupportingElement"); int osmRelationIDFieldIndex = relationTable.FindField("OSMID"); int tagCollectionRelationFieldIndex = relationTable.FindField("osmTags"); int osmUserRelationFieldIndex = relationTable.FindField("osmuser"); int osmUIDRelationFieldIndex = relationTable.FindField("osmuid"); int osmVisibleRelationFieldIndex = relationTable.FindField("osmvisible"); int osmVersionRelationFieldIndex = relationTable.FindField("osmversion"); int osmChangesetRelationFieldIndex = relationTable.FindField("osmchangeset"); int osmTimeStampRelationFieldIndex = relationTable.FindField("osmtimestamp"); int osmMemberOfRelationFieldIndex = relationTable.FindField("osmMemberOf"); int osmMembersRelationFieldIndex = relationTable.FindField("osmMembers"); int osmSupportingElementRelationFieldIndex = relationTable.FindField("osmSupportingElement"); // list for reference count and relation list for lines/polygons/relations // set up the progress indicator IStepProgressor stepProgressor = TrackCancel as IStepProgressor; if (stepProgressor != null) { stepProgressor.MinRange = 0; stepProgressor.MaxRange = relationCapacity; stepProgressor.Position = 0; stepProgressor.Message = _resourceManager.GetString("GPTools_OSMGPFileReader_loadingRelations"); stepProgressor.StepValue = 1; stepProgressor.Show(); } bool relationIndexRebuildRequired = false; if (relationTable != null) { osmFileXmlReader = System.Xml.XmlReader.Create(osmFileLocation); relationSerializer = new XmlSerializer(typeof(relation)); using (ComReleaser comReleaser = new ComReleaser()) { using (SchemaLockManager linelock = new SchemaLockManager(osmLineFeatureClass as ITable), polygonLock = new SchemaLockManager(osmPolygonFeatureClass as ITable), relationLock = new SchemaLockManager(relationTable)) { ICursor rowCursor = relationTable.Insert(true); comReleaser.ManageLifetime(rowCursor); IRowBuffer rowBuffer = relationTable.CreateRowBuffer(); comReleaser.ManageLifetime(rowBuffer); IFeatureCursor lineFeatureInsertCursor = osmLineFeatureClass.Insert(true); comReleaser.ManageLifetime(lineFeatureInsertCursor); IFeatureBuffer lineFeatureBuffer = osmLineFeatureClass.CreateFeatureBuffer(); comReleaser.ManageLifetime(lineFeatureBuffer); IFeatureCursor polygonFeatureInsertCursor = osmPolygonFeatureClass.Insert(true); comReleaser.ManageLifetime(polygonFeatureInsertCursor); IFeatureBuffer polygonFeatureBuffer = osmPolygonFeatureClass.CreateFeatureBuffer(); comReleaser.ManageLifetime(polygonFeatureBuffer); int relationCount = 1; int relationDebugCount = 1; string lineSQLIdentifier = osmLineFeatureClass.SqlIdentifier("OSMID"); string polygonSQLIdentifier = osmPolygonFeatureClass.SqlIdentifier("OSMID"); message.AddMessage(_resourceManager.GetString("GPTools_OSMGPFileReader_resolvegeometries")); osmFileXmlReader.MoveToContent(); while (osmFileXmlReader.Read()) { if (osmFileXmlReader.IsStartElement()) { if (osmFileXmlReader.Name == "relation") { relation currentRelation = null; try { // read the full relation node string currentrelationString = osmFileXmlReader.ReadOuterXml(); using (StringReader relationReader = new System.IO.StringReader(currentrelationString)) { // de-serialize the xml into to the class instance currentRelation = relationSerializer.Deserialize(relationReader) as relation; } if (currentRelation == null) continue; relationDebugCount = relationDebugCount + 1; esriGeometryType detectedGeometryType = determineRelationGeometryType(osmLineFeatureClass, osmPolygonFeatureClass, relationTable, currentRelation); if (checkForExisting) { switch (detectedGeometryType) { case esriGeometryType.esriGeometryAny: if (CheckIfExists(relationTable, currentRelation.id)) continue; break; case esriGeometryType.esriGeometryBag: if (CheckIfExists(relationTable, currentRelation.id)) continue; break; case esriGeometryType.esriGeometryBezier3Curve: break; case esriGeometryType.esriGeometryCircularArc: break; case esriGeometryType.esriGeometryEllipticArc: break; case esriGeometryType.esriGeometryEnvelope: break; case esriGeometryType.esriGeometryLine: if (CheckIfExists(osmLineFeatureClass as ITable, currentRelation.id)) continue; break; case esriGeometryType.esriGeometryMultiPatch: break; case esriGeometryType.esriGeometryMultipoint: break; case esriGeometryType.esriGeometryNull: if (CheckIfExists(relationTable, currentRelation.id)) continue; break; case esriGeometryType.esriGeometryPath: break; case esriGeometryType.esriGeometryPoint: break; case esriGeometryType.esriGeometryPolygon: if (CheckIfExists(osmPolygonFeatureClass as ITable, currentRelation.id)) continue; break; case esriGeometryType.esriGeometryPolyline: if (CheckIfExists(osmLineFeatureClass as ITable, currentRelation.id)) continue; break; case esriGeometryType.esriGeometryRay: break; case esriGeometryType.esriGeometryRing: break; case esriGeometryType.esriGeometrySphere: break; case esriGeometryType.esriGeometryTriangleFan: break; case esriGeometryType.esriGeometryTriangleStrip: break; case esriGeometryType.esriGeometryTriangles: break; default: break; } } List<tag> relationTagList = new List<tag>(); List<member> relationMemberList = new List<member>(); Dictionary<string, string> wayList = new Dictionary<string, string>(); // sanity check that the overall relation notation contains at least something if (currentRelation.Items == null) continue; List<OSMNodeFeature> osmPointList = null; List<OSMLineFeature> osmLineList = null; List<OSMPolygonFeature> osmPolygonList = null; List<OSMRelation> osmRelationList = null; rowBuffer = relationTable.CreateRowBuffer(); comReleaser.ManageLifetime(rowBuffer); lineFeatureBuffer = osmLineFeatureClass.CreateFeatureBuffer(); comReleaser.ManageLifetime(lineFeatureBuffer); polygonFeatureBuffer = osmPolygonFeatureClass.CreateFeatureBuffer(); comReleaser.ManageLifetime(polygonFeatureBuffer); foreach (var item in currentRelation.Items) { if (item is member) { member memberItem = item as member; relationMemberList.Add(memberItem); switch (memberItem.type) { case memberType.way: if (!wayList.ContainsKey(memberItem.@ref)) wayList.Add(memberItem.@ref, memberItem.role); if (IsThisWayALine(memberItem.@ref, osmLineFeatureClass, lineSQLIdentifier, osmPolygonFeatureClass, polygonSQLIdentifier)) { if (osmLineList == null) { osmLineList = new List<OSMLineFeature>(); } OSMLineFeature lineFeature = new OSMLineFeature(); lineFeature.relationList = new List<string>(); lineFeature.lineID = memberItem.@ref; if (detectedGeometryType == esriGeometryType.esriGeometryPolygon) { lineFeature.relationList.Add(currentRelation.id + "_ply"); } else if (detectedGeometryType == esriGeometryType.esriGeometryPolyline) { lineFeature.relationList.Add(currentRelation.id + "_ln"); } else { lineFeature.relationList.Add(currentRelation.id + "_rel"); } osmLineList.Add(lineFeature); } else { if (osmPolygonList == null) { osmPolygonList = new List<OSMPolygonFeature>(); } OSMPolygonFeature polygonFeature = new OSMPolygonFeature(); polygonFeature.relationList = new List<string>(); polygonFeature.polygonID = memberItem.@ref; if (detectedGeometryType == esriGeometryType.esriGeometryPolygon) { polygonFeature.relationList.Add(currentRelation.id + "_ply"); } else if (detectedGeometryType == esriGeometryType.esriGeometryPolyline) { polygonFeature.relationList.Add(currentRelation.id + "_ln"); } else { polygonFeature.relationList.Add(currentRelation.id + "_rel"); } osmPolygonList.Add(polygonFeature); } break; case memberType.node: if (osmPointList == null) { osmPointList = new List<OSMNodeFeature>(); } OSMNodeFeature nodeFeature = new OSMNodeFeature(); nodeFeature.relationList = new List<string>(); nodeFeature.nodeID = memberItem.@ref; nodeFeature.relationList.Add(currentRelation.id + "_rel"); osmPointList.Add(nodeFeature); break; case memberType.relation: if (osmRelationList == null) { osmRelationList = new List<OSMRelation>(); } OSMRelation relation = new OSMRelation(); relation.relationList = new List<string>(); relation.relationID = memberItem.@ref; relation.relationList.Add(currentRelation.id + "_rel"); break; default: break; } } else if (item is tag) { relationTagList.Add((tag)item); } } // if there is a defined geometry type use it to generate a multipart geometry if (detectedGeometryType == esriGeometryType.esriGeometryPolygon) { #region create multipart polygon geometry //IFeature mpFeature = osmPolygonFeatureClass.CreateFeature(); IPolygon relationMPPolygon = new PolygonClass(); relationMPPolygon.SpatialReference = ((IGeoDataset)osmPolygonFeatureClass).SpatialReference; ISegmentCollection relationPolygonGeometryCollection = relationMPPolygon as ISegmentCollection; IQueryFilter osmIDQueryFilter = new QueryFilterClass(); string sqlPolyOSMID = osmPolygonFeatureClass.SqlIdentifier("OSMID"); object missing = Type.Missing; bool relationComplete = true; // loop through the list of referenced ways that are listed in a relation // for each of the items we need to make a decision if they have merit to qualify as stand-alone features // due to the presence of meaningful attributes (tags) foreach (KeyValuePair<string, string> wayKey in wayList) { if (relationComplete == false) break; if (TrackCancel.Continue() == false) { return missingRelations; } osmIDQueryFilter.WhereClause = sqlPolyOSMID + " = '" + wayKey.Key + "'"; System.Diagnostics.Debug.WriteLine("Relation (Polygon) #: " + relationDebugCount + " :___: " + currentRelation.id + " :___: " + wayKey.Key); using (ComReleaser relationComReleaser = new ComReleaser()) { IFeatureCursor featureCursor = osmPolygonFeatureClass.Search(osmIDQueryFilter, false); relationComReleaser.ManageLifetime(featureCursor); IFeature partFeature = featureCursor.NextFeature(); // set the appropriate field attribute to become invisible as a standalone features if (partFeature != null) { IGeometryCollection ringCollection = partFeature.Shape as IGeometryCollection; // test for available content in the geometry collection if (ringCollection.GeometryCount > 0) { // test if we dealing with a valid geometry if (ringCollection.get_Geometry(0).IsEmpty == false) { // add it to the new geometry and mark the added geometry as a supporting element relationPolygonGeometryCollection.AddSegmentCollection((ISegmentCollection)ringCollection.get_Geometry(0)); if (osmSupportingElementPolygonFieldIndex > -1) { // if the member of a relation has the role of "inner" and it has tags, then let's keep it // as a standalone feature as well // the geometry is then a hole in the relation but due to the tags it also has merits to be // considered a stand-alone feature if (wayKey.Value.ToLower().Equals("inner")) { if (!_osmUtility.DoesHaveKeys(partFeature, tagCollectionPolygonFieldIndex, null)) { partFeature.set_Value(osmSupportingElementPolygonFieldIndex, "yes"); } } else { // relation member without an explicit role or the role of "outer" are turned into // supporting features if they don't have relevant attribute if (!_osmUtility.DoesHaveKeys(partFeature, tagCollectionPolylineFieldIndex, null)) { partFeature.set_Value(osmSupportingElementPolygonFieldIndex, "yes"); } } } partFeature.Store(); } } } else { // it still can be a line geometry that will be pieced together into a polygon IFeatureCursor lineFeatureCursor = osmLineFeatureClass.Search(osmIDQueryFilter, false); relationComReleaser.ManageLifetime(lineFeatureCursor); partFeature = lineFeatureCursor.NextFeature(); if (partFeature != null) { IGeometryCollection ringCollection = partFeature.Shape as IGeometryCollection; // test for available content in the geometry collection if (ringCollection.GeometryCount > 0) { // test if we dealing with a valid geometry if (ringCollection.get_Geometry(0).IsEmpty == false) { // add it to the new geometry and mark the added geometry as a supporting element relationPolygonGeometryCollection.AddSegmentCollection((ISegmentCollection)ringCollection.get_Geometry(0)); if (osmSupportingElementPolylineFieldIndex > -1) { // if the member of a relation has the role of "inner" and it has tags, then let's keep it // as a standalone feature as well // the geometry is then a hole in the relation but due to the tags it also has merits to be // considered a stand-alone feature if (wayKey.Value.ToLower().Equals("inner")) { if (!_osmUtility.DoesHaveKeys(partFeature, tagCollectionPolylineFieldIndex, null)) { partFeature.set_Value(osmSupportingElementPolylineFieldIndex, "yes"); } } else { // relation member without an explicit role or the role of "outer" are turned into // supporting features if they don't have relevant attribute if (!_osmUtility.DoesHaveKeys(partFeature, tagCollectionPolylineFieldIndex, null)) { partFeature.set_Value(osmSupportingElementPolylineFieldIndex, "yes"); } } } partFeature.Store(); } } } else { relationComplete = false; continue; } } } } // mark the relation as incomplete if (relationComplete == false) { missingRelations.Add(currentRelation.id); continue; } // transform the added collections for geometries into a topological correct geometry representation ((IPolygon4)relationMPPolygon).SimplifyEx(true, false, true); polygonFeatureBuffer.Shape = relationMPPolygon; if (_osmUtility.DoesHaveKeys(currentRelation)) { } else { relationTagList = MergeTagsFromOuterPolygonToRelation(currentRelation, osmPolygonFeatureClass); } insertTags(osmPolygonDomainAttributeFieldIndices, osmPolygonDomainAttributeFieldLength, tagCollectionPolygonFieldIndex, polygonFeatureBuffer, relationTagList.ToArray()); if (fastLoad == false) { if (osmMembersPolygonFieldIndex > -1) { _osmUtility.insertMembers(osmMembersPolygonFieldIndex, (IFeature)polygonFeatureBuffer, relationMemberList.ToArray()); } // store the administrative attributes // user, uid, version, changeset, timestamp, visible if (osmUserPolygonFieldIndex != -1) { if (!String.IsNullOrEmpty(currentRelation.user)) { polygonFeatureBuffer.set_Value(osmUserPolygonFieldIndex, currentRelation.user); } } if (osmUIDPolygonFieldIndex != -1) { if (!String.IsNullOrEmpty(currentRelation.uid)) { polygonFeatureBuffer.set_Value(osmUIDPolygonFieldIndex, Convert.ToInt32(currentRelation.uid)); } } if (osmVisiblePolygonFieldIndex != -1) { if (String.IsNullOrEmpty(currentRelation.visible) == false) { polygonFeatureBuffer.set_Value(osmVisiblePolygonFieldIndex, currentRelation.visible.ToString()); } else { polygonFeatureBuffer.set_Value(osmVisiblePolygonFieldIndex, "unknown"); } } if (osmVersionPolygonFieldIndex != -1) { if (!String.IsNullOrEmpty(currentRelation.version)) { polygonFeatureBuffer.set_Value(osmVersionPolygonFieldIndex, Convert.ToInt32(currentRelation.version)); } } if (osmChangesetPolygonFieldIndex != -1) { if (!String.IsNullOrEmpty(currentRelation.changeset)) { polygonFeatureBuffer.set_Value(osmChangesetPolygonFieldIndex, Convert.ToInt32(currentRelation.changeset)); } } if (osmTimeStampPolygonFieldIndex != -1) { if (!String.IsNullOrEmpty(currentRelation.timestamp)) { polygonFeatureBuffer.set_Value(osmTimeStampPolygonFieldIndex, Convert.ToDateTime(currentRelation.timestamp)); } } if (osmPolygonIDFieldIndex != -1) { polygonFeatureBuffer.set_Value(osmPolygonIDFieldIndex, currentRelation.id); } if (osmSupportingElementPolygonFieldIndex > -1) { polygonFeatureBuffer.set_Value(osmSupportingElementPolygonFieldIndex, "no"); } } try { //mpFeature.Store(); polygonFeatureInsertCursor.InsertFeature(polygonFeatureBuffer); } catch (Exception ex) { message.AddWarning(ex.Message); } #endregion } else if (detectedGeometryType == esriGeometryType.esriGeometryPolyline) { #region create multipart polyline geometry //IFeature mpFeature = osmLineFeatureClass.CreateFeature(); IPolyline relationMPPolyline = new PolylineClass(); relationMPPolyline.SpatialReference = ((IGeoDataset)osmLineFeatureClass).SpatialReference; IGeometryCollection relationPolylineGeometryCollection = relationMPPolyline as IGeometryCollection; IQueryFilter osmIDQueryFilter = new QueryFilterClass(); object missing = Type.Missing; // loop through the foreach (KeyValuePair<string, string> wayKey in wayList) { if (TrackCancel.Continue() == false) { return missingRelations; } osmIDQueryFilter.WhereClause = osmLineFeatureClass.WhereClauseByExtensionVersion(wayKey.Key, "OSMID", 2); System.Diagnostics.Debug.WriteLine("Relation (Polyline) #: " + relationDebugCount + " :___: " + currentRelation.id + " :___: " + wayKey); using (ComReleaser relationComReleaser = new ComReleaser()) { IFeatureCursor featureCursor = osmLineFeatureClass.Search(osmIDQueryFilter, false); relationComReleaser.ManageLifetime(featureCursor); IFeature partFeature = featureCursor.NextFeature(); // set the appropriate field attribute to become invisible as a standalone features if (partFeature != null) { if (partFeature.Shape.IsEmpty == false) { IGeometryCollection pathCollection = partFeature.Shape as IGeometryCollection; relationPolylineGeometryCollection.AddGeometry(pathCollection.get_Geometry(0), ref missing, ref missing); if (osmSupportingElementPolylineFieldIndex > -1) { if (!_osmUtility.DoesHaveKeys(partFeature, tagCollectionPolylineFieldIndex, null)) { partFeature.set_Value(osmSupportingElementPolylineFieldIndex, "yes"); } } partFeature.Store(); } } } } lineFeatureBuffer.Shape = relationMPPolyline; insertTags(osmLineDomainAttributeFieldIndices, osmLineDomainAttributeFieldLength, tagCollectionPolylineFieldIndex, lineFeatureBuffer, relationTagList.ToArray()); if (fastLoad == false) { if (osmMembersPolylineFieldIndex > -1) { _osmUtility.insertMembers(osmMembersPolylineFieldIndex, (IFeature)lineFeatureBuffer, relationMemberList.ToArray()); } // store the administrative attributes // user, uid, version, changeset, timestamp, visible if (osmUserPolylineFieldIndex != -1) { if (!String.IsNullOrEmpty(currentRelation.user)) { lineFeatureBuffer.set_Value(osmUserPolylineFieldIndex, currentRelation.user); } } if (osmUIDPolylineFieldIndex != -1) { if (!String.IsNullOrEmpty(currentRelation.uid)) { lineFeatureBuffer.set_Value(osmUIDPolylineFieldIndex, Convert.ToInt32(currentRelation.uid)); } } if (osmVisiblePolylineFieldIndex != -1) { if (String.IsNullOrEmpty(currentRelation.visible) == false) { lineFeatureBuffer.set_Value(osmVisiblePolylineFieldIndex, currentRelation.visible.ToString()); } else { lineFeatureBuffer.set_Value(osmVisiblePolylineFieldIndex, "unknown"); } } if (osmVersionPolylineFieldIndex != -1) { if (!String.IsNullOrEmpty(currentRelation.version)) { lineFeatureBuffer.set_Value(osmVersionPolylineFieldIndex, Convert.ToInt32(currentRelation.version)); } } if (osmChangesetPolylineFieldIndex != -1) { if (!String.IsNullOrEmpty(currentRelation.changeset)) { lineFeatureBuffer.set_Value(osmChangesetPolylineFieldIndex, Convert.ToInt32(currentRelation.changeset)); } } if (osmTimeStampPolylineFieldIndex != -1) { if (!String.IsNullOrEmpty(currentRelation.timestamp)) { lineFeatureBuffer.set_Value(osmTimeStampPolylineFieldIndex, Convert.ToDateTime(currentRelation.timestamp)); } } if (osmLineIDFieldIndex != -1) { lineFeatureBuffer.set_Value(osmLineIDFieldIndex, currentRelation.id); } if (osmSupportingElementPolylineFieldIndex > -1) { lineFeatureBuffer.set_Value(osmSupportingElementPolylineFieldIndex, "no"); } } try { lineFeatureInsertCursor.InsertFeature(lineFeatureBuffer); } catch (Exception ex) { message.AddWarning(ex.Message); } #endregion } else if (detectedGeometryType == esriGeometryType.esriGeometryPoint) { System.Diagnostics.Debug.WriteLine("Relation #: " + relationDebugCount + " :____: POINT!!!"); if (TrackCancel.Continue() == false) { return missingRelations; } } else // otherwise it is relation that needs to be dealt with separately { if (TrackCancel.Continue() == false) { return missingRelations; } System.Diagnostics.Debug.WriteLine("Relation #: " + relationDebugCount + " :____: Kept as relation"); if (tagCollectionRelationFieldIndex != -1) { _osmUtility.insertOSMTags(tagCollectionRelationFieldIndex, rowBuffer, relationTagList.ToArray()); } if (fastLoad == false) { if (osmMembersRelationFieldIndex != -1) { _osmUtility.insertMembers(osmMembersRelationFieldIndex, rowBuffer, relationMemberList.ToArray()); } // store the administrative attributes // user, uid, version, changeset, timestamp, visible if (osmUserRelationFieldIndex != -1) { if (!String.IsNullOrEmpty(currentRelation.user)) { rowBuffer.set_Value(osmUserRelationFieldIndex, currentRelation.user); } } if (osmUIDRelationFieldIndex != -1) { if (!String.IsNullOrEmpty(currentRelation.uid)) { rowBuffer.set_Value(osmUIDRelationFieldIndex, Convert.ToInt64(currentRelation.uid)); } } if (osmVisibleRelationFieldIndex != -1) { if (currentRelation.visible != null) { rowBuffer.set_Value(osmVisibleRelationFieldIndex, currentRelation.visible.ToString()); } } if (osmVersionRelationFieldIndex != -1) { if (!String.IsNullOrEmpty(currentRelation.version)) { rowBuffer.set_Value(osmVersionRelationFieldIndex, Convert.ToInt32(currentRelation.version)); } } if (osmChangesetRelationFieldIndex != -1) { if (!String.IsNullOrEmpty(currentRelation.changeset)) { rowBuffer.set_Value(osmChangesetRelationFieldIndex, Convert.ToInt32(currentRelation.changeset)); } } if (osmTimeStampRelationFieldIndex != -1) { if (!String.IsNullOrEmpty(currentRelation.timestamp)) { try { rowBuffer.set_Value(osmTimeStampRelationFieldIndex, Convert.ToDateTime(currentRelation.timestamp)); } catch (Exception ex) { message.AddWarning(String.Format(_resourceManager.GetString("GPTools_OSMGPFileReader_invalidTimeFormat"), ex.Message)); } } } if (osmRelationIDFieldIndex != -1) { rowBuffer.set_Value(osmRelationIDFieldIndex, currentRelation.id); } } try { rowCursor.InsertRow(rowBuffer); relationCount = relationCount + 1; relationIndexRebuildRequired = true; } catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.Message); } // check for user interruption if (TrackCancel.Continue() == false) { return missingRelations; } } // update the isMemberOf fields of the attached features if (osmPointList != null) { foreach (OSMNodeFeature nodeFeature in osmPointList) { updateIsMemberOf(osmLineFeatureClass, osmMemberOfPolylineFieldIndex, nodeFeature.nodeID, nodeFeature.relationList); } } if (osmLineList != null) { foreach (OSMLineFeature lineFeature in osmLineList) { updateIsMemberOf(osmLineFeatureClass, osmMemberOfPolylineFieldIndex, lineFeature.lineID, lineFeature.relationList); } } if (osmPolygonList != null) { foreach (OSMPolygonFeature polygonFeature in osmPolygonList) { updateIsMemberOf(osmLineFeatureClass, osmMemberOfPolylineFieldIndex, polygonFeature.polygonID, polygonFeature.relationList); } } if (stepProgressor != null) { stepProgressor.Position = relationCount; } if ((relationCount % 50000) == 0) { message.AddMessage(String.Format(_resourceManager.GetString("GPTools_OSMGPFileReader_relationsloaded"), relationCount)); } } catch (Exception ex) { message.AddWarning(ex.Message); } finally { if (rowBuffer != null) { Marshal.ReleaseComObject(rowBuffer); if (rowBuffer != null) rowBuffer = null; } if (lineFeatureBuffer != null) { Marshal.ReleaseComObject(lineFeatureBuffer); if (lineFeatureBuffer != null) lineFeatureBuffer = null; } if (polygonFeatureBuffer != null) { Marshal.ReleaseComObject(polygonFeatureBuffer); if (polygonFeatureBuffer != null) polygonFeatureBuffer = null; } currentRelation = null; } } } } // close the OSM file osmFileXmlReader.Close(); // flush any remaining entities from the cursor rowCursor.Flush(); polygonFeatureInsertCursor.Flush(); lineFeatureInsertCursor.Flush(); // force a garbage collection System.GC.Collect(); // let the user know that we are done dealing with the relations message.AddMessage(String.Format(_resourceManager.GetString("GPTools_OSMGPFileReader_relationsloaded"), relationCount)); } } if (stepProgressor != null) { stepProgressor.Hide(); } // Addd index for osmid column as well IGeoProcessor2 geoProcessor = new GeoProcessorClass(); bool storedOriginalLocal = geoProcessor.AddOutputsToMap; IGPUtilities3 gpUtilities3 = new GPUtilitiesClass(); try { geoProcessor.AddOutputsToMap = false; if (relationIndexRebuildRequired) { IIndexes tableIndexes = relationTable.Indexes; int indexPosition = -1; tableIndexes.FindIndex("osmID_IDX", out indexPosition); if (indexPosition == -1) { IGPValue relationTableGPValue = gpUtilities3.MakeGPValueFromObject(relationTable); string sddd = targetGPValue.GetAsText(); string tableLocation = GetLocationString(targetGPValue, relationTable); IVariantArray parameterArrary = CreateAddIndexParameterArray(tableLocation, "OSMID", "osmID_IDX", "UNIQUE", ""); IGeoProcessorResult2 gpResults2 = geoProcessor.Execute("AddIndex_management", parameterArrary, TrackCancel) as IGeoProcessorResult2; } } } catch (Exception ex) { message.AddWarning(ex.Message); } finally { geoProcessor.AddOutputsToMap = storedOriginalLocal; Marshal.FinalReleaseComObject(gpUtilities3); Marshal.FinalReleaseComObject(geoProcessor); } } } catch (Exception ex) { } finally { if (relationSerializer != null) relationSerializer = null; if (osmFileXmlReader != null) osmFileXmlReader = null; System.GC.Collect(); System.GC.WaitForPendingFinalizers(); } return missingRelations; }