private relation ConvertRowToOSMRelation(IRow currentRow, IWorkspace featureWorkspace, int tagsFieldIndex, int osmIDFieldIndex, int changesetIDFieldIndex, int osmVersionFieldIndex, int userIDFieldIndex, int userNameFieldIndex, int timeStampFieldIndex, int visibleFieldIndex, int membersFieldIndex, int extensionVersion) { if (currentRow == null) throw new ArgumentNullException("currentRow"); relation osmRelation = new relation(); object featureValue = DBNull.Value; List<object> relationItems = new List<object>(); if (membersFieldIndex != -1) { member[] members = _osmUtility.retrieveMembers(currentRow, membersFieldIndex); relationItems.AddRange(members); } if (osmIDFieldIndex != -1) { osmRelation.id = Convert.ToString(currentRow.get_Value(osmIDFieldIndex)); } if (changesetIDFieldIndex != -1) { featureValue = currentRow.get_Value(changesetIDFieldIndex); if (featureValue != DBNull.Value) { osmRelation.changeset = Convert.ToString(currentRow.get_Value(changesetIDFieldIndex)); } } if (osmVersionFieldIndex != -1) { featureValue = currentRow.get_Value(osmVersionFieldIndex); if (featureValue != DBNull.Value) { osmRelation.version = Convert.ToString(featureValue); } } if (userIDFieldIndex != -1) { featureValue = currentRow.get_Value(userIDFieldIndex); if (featureValue != DBNull.Value) { osmRelation.uid = Convert.ToString(featureValue); } } if (userNameFieldIndex != -1) { featureValue = currentRow.get_Value(userNameFieldIndex); if (featureValue != DBNull.Value) { osmRelation.user = Convert.ToString(featureValue); } } if (timeStampFieldIndex != -1) { featureValue = currentRow.get_Value(timeStampFieldIndex); if (featureValue != DBNull.Value) { osmRelation.timestamp = Convert.ToDateTime(featureValue).ToUniversalTime().ToString("u"); } } if (visibleFieldIndex != -1) { featureValue = currentRow.get_Value(visibleFieldIndex); if (featureValue != DBNull.Value) { osmRelation.visible = Convert.ToString(featureValue); } } if (tagsFieldIndex > -1) { tag[] tags = null; tags = _osmUtility.retrieveOSMTags((IRow)currentRow, tagsFieldIndex, featureWorkspace); // if the row is of type IFeature and a polygon then add the type=multipolygon tag if (currentRow is IFeature) { IFeature currentFeature = currentRow as IFeature; if (currentFeature.Shape.GeometryType == esriGeometryType.esriGeometryPolygon) { tag mpTag = new tag(); mpTag.k = "type"; mpTag.v = "multipolygon"; relationItems.Add(mpTag); } } if (tags.Length != 0) { relationItems.AddRange(tags); } } // add all items (member and tags) to the relation element osmRelation.Items = relationItems.ToArray(); return osmRelation; }
/// <summary> /// This function assembles a version of the logged relation action from the revision table in the OsmChange format http://wiki.openstreetmap.org/wiki/OsmChange /// </summary> /// <param name="relationTable"></param> /// <param name="action"></param> /// <param name="osmID"></param> /// <param name="changeSetID"></param> /// <param name="osmVersion"></param> /// <param name="nodeosmIDLookup"></param> /// <param name="wayosmIDLookup"></param> /// <param name="relationosmIDLookup"></param> /// <param name="extensionVersion"></param> /// <returns></returns> private ESRI.ArcGIS.OSM.OSMClassExtension.relation CreateRelationRepresentation(ITable relationTable, string action, long osmID, string changeSetID, int osmVersion, Dictionary<long, long> nodeosmIDLookup, Dictionary<long, long> wayosmIDLookup, Dictionary<long, long> relationosmIDLookup, int extensionVersion) { ESRI.ArcGIS.OSM.OSMClassExtension.relation relationRepresentation = new ESRI.ArcGIS.OSM.OSMClassExtension.relation(); // let's find all the rows that have a different status than 200 - meaning success IQueryFilter queryFilter = new QueryFilterClass(); queryFilter.WhereClause = relationTable.WhereClauseByExtensionVersion(osmID, "OSMID", extensionVersion); using (ComReleaser comReleaser = new ComReleaser()) { ICursor searchCursor = relationTable.Search(queryFilter, false); comReleaser.ManageLifetime(searchCursor); IRow relationRow = searchCursor.NextRow(); int osmTagsFieldIndex = relationTable.Fields.FindField("osmTags"); int osmIDFieldIndex = relationTable.Fields.FindField("osmID"); int osmUserFieldIndex = relationTable.Fields.FindField("osmuser"); int osmUIDFieldIndex = relationTable.Fields.FindField("osmuid"); int osmVisibleFieldIndex = relationTable.Fields.FindField("osmvisible"); int osmVersionFieldIndex = relationTable.Fields.FindField("osmversion"); int osmMembersFieldIndex = relationTable.Fields.FindField("osmMembers"); if (relationRow != null) { switch (action) { case "create": // the newly created node needs to carry the changeset info, the coordinate and the tags relationRepresentation.changeset = changeSetID; ESRI.ArcGIS.OSM.OSMClassExtension.tag[] tags = null; if (osmTagsFieldIndex > -1) { tags = _osmUtility.retrieveOSMTags(relationRow, osmTagsFieldIndex, ((IDataset)relationTable).Workspace); } List<tag> valueOnlyTags = new List<tag>(); for (int index = 0; index < tags.Length; index++) { if (!String.IsNullOrEmpty(tags[index].v)) { valueOnlyTags.Add(tags[index]); } } if (osmIDFieldIndex > -1) { relationRepresentation.id = osmID.ToString(); } ESRI.ArcGIS.OSM.OSMClassExtension.member[] members = null; if (osmMembersFieldIndex > -1) { members = _osmUtility.retrieveMembers(relationRow, osmMembersFieldIndex); // run the member ids through the lookup table for (int memberIndex = 0; memberIndex < members.Length; memberIndex++) { switch (members[memberIndex].type) { case ESRI.ArcGIS.OSM.OSMClassExtension.memberType.way: if (wayosmIDLookup.ContainsKey(Convert.ToInt64(members[memberIndex].@ref))) { members[memberIndex].@ref = Convert.ToString(wayosmIDLookup[Convert.ToInt64(members[memberIndex].@ref)]); } break; case ESRI.ArcGIS.OSM.OSMClassExtension.memberType.node: if (nodeosmIDLookup.ContainsKey(Convert.ToInt64(members[memberIndex].@ref))) { members[memberIndex].@ref = Convert.ToString(nodeosmIDLookup[Convert.ToInt64(members[memberIndex].@ref)]); } break; case ESRI.ArcGIS.OSM.OSMClassExtension.memberType.relation: if (relationosmIDLookup.ContainsKey(Convert.ToInt64(members[memberIndex].@ref))) { members[memberIndex].@ref = Convert.ToString(relationosmIDLookup[Convert.ToInt64(members[memberIndex].@ref)]); } break; default: break; } } _osmUtility.insertMembers(osmMembersFieldIndex, relationRow, members); } // add the member and the tags to the relation element List<object> relationItems = new List<object>(); relationItems.AddRange(members); relationItems.AddRange(valueOnlyTags.ToArray()); relationRepresentation.Items = relationItems.ToArray(); break; case "modify": // for an update the complete (full) relation needs to be returned relationRepresentation.changeset = changeSetID; if (osmIDFieldIndex > -1) { relationRepresentation.id = Convert.ToString(relationRow.get_Value(osmIDFieldIndex), new CultureInfo("en-US")); } if (osmUserFieldIndex > -1) { relationRepresentation.user = Convert.ToString(relationRow.get_Value(osmUserFieldIndex)); } if (osmUIDFieldIndex > -1) { relationRepresentation.uid = Convert.ToString(relationRow.get_Value(osmUIDFieldIndex), new CultureInfo("en-US")); } if (osmVersionFieldIndex > -1) { relationRepresentation.version = Convert.ToString(relationRow.get_Value(osmVersionFieldIndex)); } tags = null; if (osmTagsFieldIndex > -1) { tags = _osmUtility.retrieveOSMTags((IRow)relationRow, osmTagsFieldIndex, ((IDataset)relationTable).Workspace); } valueOnlyTags = new List<tag>(); for (int index = 0; index < tags.Length; index++) { if (!String.IsNullOrEmpty(tags[index].v)) { valueOnlyTags.Add(tags[index]); } } members = null; if (osmMembersFieldIndex > -1) { members = _osmUtility.retrieveMembers(relationRow, osmMembersFieldIndex); // run the member ids through the lookup table for (int memberIndex = 0; memberIndex < members.Length; memberIndex++) { switch (members[memberIndex].type) { case memberType.way: if (wayosmIDLookup.ContainsKey(Convert.ToInt64(members[memberIndex].@ref))) { members[memberIndex].@ref = Convert.ToString(wayosmIDLookup[Convert.ToInt64(members[memberIndex].@ref)]); } break; case memberType.node: if (nodeosmIDLookup.ContainsKey(Convert.ToInt64(members[memberIndex].@ref))) { members[memberIndex].@ref = Convert.ToString(nodeosmIDLookup[Convert.ToInt64(members[memberIndex].@ref)]); } break; case memberType.relation: if (relationosmIDLookup.ContainsKey(Convert.ToInt64(members[memberIndex].@ref))) { members[memberIndex].@ref = Convert.ToString(relationosmIDLookup[Convert.ToInt64(members[memberIndex].@ref)]); } break; default: break; } } _osmUtility.insertMembers(osmMembersFieldIndex, relationRow, members); } // add the member and the tags to the relation element relationItems = new List<object>(); relationItems.AddRange(valueOnlyTags.ToArray()); relationItems.AddRange(members); relationRepresentation.Items = relationItems.ToArray(); break; case "delete": relationRepresentation.changeset = changeSetID; relationRepresentation.id = Convert.ToString(osmID); relationRepresentation.version = Convert.ToString(osmVersion); break; default: break; } } else { if (action.Equals("delete", StringComparison.InvariantCultureIgnoreCase)) { relationRepresentation.changeset = changeSetID; relationRepresentation.id = Convert.ToString(osmID); relationRepresentation.version = Convert.ToString(osmVersion); } } } return relationRepresentation; }
private osmRelationGeometryType walkRelationGeometry(IFeatureClass osmLineFeatureClass, IFeatureClass osmPolygonFeatureClass, ITable relationTable, relation currentRelation) { osmRelationGeometryType testedGeometry = osmRelationGeometryType.osmUnknownGeometry; // we use this dictionary to determine if we can fully walk this relation // - the assumption is that we can walk the geometry is all node counts are 2 Dictionary<int, int> nodeCountDictionary = new Dictionary<int, int>(); try { if (currentRelation.Items == null) return testedGeometry; foreach (var item in currentRelation.Items) { if (item is ESRI.ArcGIS.OSM.OSMClassExtension.member) { member memberItem = item as member; IQueryFilter osmIDQueryFilter = new QueryFilterClass(); using (ComReleaser comReleaser = new ComReleaser()) { if (osmLineFeatureClass != null) { osmIDQueryFilter.WhereClause = osmLineFeatureClass.WhereClauseByExtensionVersion(memberItem.@ref, "OSMID", 2); IFeatureCursor lineFeatureCursor = osmLineFeatureClass.Search(osmIDQueryFilter, false); comReleaser.ManageLifetime(lineFeatureCursor); IFeature foundLineFeature = lineFeatureCursor.NextFeature(); if (foundLineFeature != null) { IPointCollection pointCollection = foundLineFeature.Shape as IPointCollection; int firstPointID = pointCollection.get_Point(0).ID; int lastPointID = pointCollection.get_Point(pointCollection.PointCount - 1).ID; if (nodeCountDictionary.ContainsKey(firstPointID)) { nodeCountDictionary[firstPointID] = nodeCountDictionary[firstPointID] + 1; } else { nodeCountDictionary.Add(firstPointID, 1); } if (nodeCountDictionary.ContainsKey(lastPointID)) { nodeCountDictionary[lastPointID] = nodeCountDictionary[lastPointID] + 1; } else { nodeCountDictionary.Add(lastPointID, 1); } } osmIDQueryFilter.WhereClause = osmPolygonFeatureClass.WhereClauseByExtensionVersion(memberItem.@ref, "OSMID", 2); IFeatureCursor polygonFeatureCursor = osmPolygonFeatureClass.Search(osmIDQueryFilter, false); comReleaser.ManageLifetime(polygonFeatureCursor); IFeature foundPolygonFeature = polygonFeatureCursor.NextFeature(); if (foundPolygonFeature != null) { IPointCollection pointCollection = foundPolygonFeature.Shape as IPointCollection; int firstPointID = pointCollection.get_Point(0).ID; if (nodeCountDictionary.ContainsKey(firstPointID)) { nodeCountDictionary[firstPointID] = nodeCountDictionary[firstPointID] + 2; } else { nodeCountDictionary.Add(firstPointID, 2); } } osmIDQueryFilter.WhereClause = relationTable.WhereClauseByExtensionVersion(memberItem.@ref, "OSMID", 2); ICursor relationCursor = relationTable.Search(osmIDQueryFilter, false); comReleaser.ManageLifetime(relationCursor); IRow foundRelation = relationCursor.NextRow(); if (foundRelation != null) { // in order to be in the relation table is needs to be a either a super-relation or a mixed type entity (hence hybrid) testedGeometry = osmRelationGeometryType.osmHybridGeometry; break; } } } } } // check if there are any nodes counts other than 2, if there are then we cannot fully "walk" the geometry and it will be considered a line if (nodeCountDictionary.Values.Any(e => (e != 2))) { testedGeometry = osmRelationGeometryType.osmPolyline; } else { testedGeometry = osmRelationGeometryType.osmPolygon; } } catch { testedGeometry = osmRelationGeometryType.osmHybridGeometry; } return testedGeometry; }