private IAttributesTable ConvertTags(ICompleteOsmGeo osmObject) { var table = new AttributesTable(osmObject.Tags.ToDictionary(t => t.Key, t => t.Value as object)) { { FeatureAttributes.ID, osmObject.Type.ToString().ToLower() + "_" + osmObject.Id } }; // HM TODO: Avoid down case, required feature: https://github.com/OsmSharp/core/issues/60 if (osmObject is CompleteOsmGeo complete) { if (complete.TimeStamp.HasValue) { table.Add(FeatureAttributes.POI_LAST_MODIFIED, complete.TimeStamp.Value.ToString("o")); } if (!string.IsNullOrWhiteSpace(complete.UserName)) { table.Add(FeatureAttributes.POI_USER_NAME, complete.UserName); table.Add(FeatureAttributes.POI_USER_ADDRESS, $"//www.openstreetmap.org/user/{Uri.EscapeUriString(complete.UserName)}"); } } else if (osmObject is OsmGeo osmGeo) { if (osmGeo.TimeStamp.HasValue) { table.Add(FeatureAttributes.POI_LAST_MODIFIED, osmGeo.TimeStamp.Value.ToString("o")); } if (!string.IsNullOrWhiteSpace(osmGeo.UserName)) { table.Add(FeatureAttributes.POI_USER_NAME, osmGeo.UserName); table.Add(FeatureAttributes.POI_USER_ADDRESS, $"//www.openstreetmap.org/user/{Uri.EscapeUriString(osmGeo.UserName)}"); } } return(table); }
public Feature ToGeoJson(ICompleteOsmGeo completeOsmGeo) { if (completeOsmGeo.Tags.Count == 0) { return null; } switch (completeOsmGeo.Type) { case CompleteOsmType.Node: var node = completeOsmGeo as Node; return new Feature(new Point(ConvertNode(node)), ConvertTags(node.Tags, node.Id.Value)); case CompleteOsmType.Way: var way = completeOsmGeo as CompleteWay; if (way == null || way.Nodes.Count <= 1) { // can't convert a way with 1 coordinates to geojson. return null; } var properties = ConvertTags(way.Tags, way.Id); var geometry = GetGeometryFromNodes(way.Nodes); return new Feature(geometry, properties); case CompleteOsmType.Relation: return ConvertRelation(completeOsmGeo as CompleteRelation); default: return null; } }
/// <inheritdoc /> public Feature ToGeoJson(ICompleteOsmGeo completeOsmGeo) { if (completeOsmGeo.Tags.Count == 0) { return(null); } switch (completeOsmGeo.Type) { case OsmGeoType.Node: var node = completeOsmGeo as Node; return(new Feature(new Point(ConvertNode(node)), ConvertTags(node))); case OsmGeoType.Way: var way = completeOsmGeo as CompleteWay; if (way == null || way.Nodes.Length <= 1) { // can't convert a way with 1 coordinates to geojson. return(null); } var properties = ConvertTags(way); var geometry = GetGeometryFromNodes(way.Nodes); return(new Feature(geometry, properties)); case OsmGeoType.Relation: return(ConvertRelation(completeOsmGeo as CompleteRelation)); default: return(null); } }
/// <inheritdoc /> public async Task <PointOfInterestExtended> UpdatePointOfInterest(PointOfInterestExtended pointOfInterest, TokenAndSecret tokenAndSecret, string language) { var osmGateway = CreateOsmGateway(tokenAndSecret); var id = pointOfInterest.Id; ICompleteOsmGeo completeOsmGeo = await osmGateway.GetCompleteElement(GeoJsonExtensions.GetOsmId(id), GeoJsonExtensions.GetOsmType(id)); var featureBeforeUpdate = ConvertOsmToFeature(completeOsmGeo, pointOfInterest.Title); var oldIcon = featureBeforeUpdate.Attributes[FeatureAttributes.POI_ICON].ToString(); var oldTags = completeOsmGeo.Tags.ToArray(); SetWebsiteUrl(completeOsmGeo.Tags, pointOfInterest); SetTagByLanguage(completeOsmGeo.Tags, FeatureAttributes.NAME, pointOfInterest.Title, language); SetTagByLanguage(completeOsmGeo.Tags, FeatureAttributes.DESCRIPTION, pointOfInterest.Description, language); SyncImages(completeOsmGeo.Tags, pointOfInterest.ImagesUrls); if (pointOfInterest.Icon != oldIcon && pointOfInterest.Icon != SEARCH_ICON) { RemoveTagsByIcon(completeOsmGeo.Tags, oldIcon); AddTagsByIcon(completeOsmGeo.Tags, pointOfInterest.Icon); } RemoveEmptyTags(completeOsmGeo.Tags); if (AreTagsCollectionEqual(oldTags, completeOsmGeo.Tags.ToArray())) { return(pointOfInterest); } var changesetId = await osmGateway.CreateChangeset($"Updated {pointOfInterest.Title} using IsraelHiking.osm.org.il"); await osmGateway.UpdateElement(changesetId, completeOsmGeo); await osmGateway.CloseChangeset(changesetId); var featureToReturn = await UpdateElasticSearch(completeOsmGeo, pointOfInterest.Title); return(await FeatureToExtendedPoi(featureToReturn, language)); }
/// <inheritdoc /> public Feature ToGeoJson(ICompleteOsmGeo completeOsmGeo) { if (completeOsmGeo.Tags.Count == 0) { return(null); } switch (completeOsmGeo.Type) { case OsmGeoType.Node: var node = completeOsmGeo as Node; return(new Feature(new Point(ConvertNode(node)), ConvertTags(node))); case OsmGeoType.Way: if (!(completeOsmGeo is CompleteWay way) || way.Nodes.Length <= 1) { // can't convert a way with 1 coordinates to geojson. return(null); } var properties = ConvertTags(way); properties.AddAttribute(FeatureAttributes.OSM_NODES, way.Nodes.Select(n => n.Id).ToArray()); var geometry = GetGeometryFromNodes(way.Nodes); return(new Feature(geometry, properties)); case OsmGeoType.Relation: return(ConvertRelation(completeOsmGeo as CompleteRelation)); default: return(null); } }
public static bool IsNodeInBuilding(Node node, ICompleteOsmGeo building) { if (building is Node buildingNode) { return(DistanceMeters(node, buildingNode) <= 1); } else if (building is CompleteWay buildingWay) { var point = new NetTopologySuite.Geometries.Point(node.Longitude.Value, node.Latitude.Value); if (buildingWay.Nodes.Length < 4 || (buildingWay.Nodes.First() != buildingWay.Nodes.Last())) { return(false); } var ring = new NetTopologySuite.Geometries.LinearRing( buildingWay.Nodes.Select(n => new Coordinate(n.Longitude.Value, n.Latitude.Value)).ToArray()); var polygon = new NetTopologySuite.Geometries.Polygon(ring); return(point.Within(polygon)); } else if (building is CompleteRelation buildingRelation) { // "in" means that even if I land in the center of a donut, I'm still "in" the building. // This isn't 100% accurate (false negative) for polygons where the closed outer ring is defined by more than 2 open ways. return(buildingRelation.Members.Any(m => m.Role != "inner" && IsNodeInBuilding(node, m.Member))); } throw new Exception("ICompleteOsmGeo wasn't a Node, Way or Relation."); }
public static Bounds AsBounds(this ICompleteOsmGeo element) { if (element is Node node) { return(new Bounds() { MaxLatitude = (float)node.Latitude, MinLatitude = (float)node.Latitude, MaxLongitude = (float)node.Longitude, MinLongitude = (float)node.Longitude }); } else if (element is CompleteWay way) { return(new Bounds() { MaxLatitude = (float)way.Nodes.Max(n => n.Latitude), MinLatitude = (float)way.Nodes.Min(n => n.Latitude), MaxLongitude = (float)way.Nodes.Max(n => n.Longitude), MinLongitude = (float)way.Nodes.Min(n => n.Longitude) }); } else if (element is CompleteRelation relation) { var allBounds = relation.Members.Select(m => AsBounds(m.Member)); return(new Bounds() { MaxLatitude = (float)allBounds.Max(n => n.MaxLatitude), MinLatitude = (float)allBounds.Min(n => n.MinLatitude), MaxLongitude = (float)allBounds.Max(n => n.MaxLongitude), MinLongitude = (float)allBounds.Min(n => n.MinLongitude) }); } throw new Exception("element wasn't a node, way or relation"); }
private void MergeTags(ICompleteOsmGeo fromItem, ICompleteOsmGeo toItem) { foreach (var tag in fromItem.Tags.Except(toItem.Tags, new TagKeyComparer())) { toItem.Tags.Add(tag); } }
private static AttributesTable TagsAndIdToAttributes(ICompleteOsmGeo osmObject) { var attr = osmObject.Tags.ToAttributeTable(); attr.Add("id", osmObject.Id); return(attr); }
private bool IsMultipolygon(ICompleteOsmGeo relation) { if (relation.Tags.ContainsKey(TYPE) == false) { return(false); } return(relation.Tags[TYPE] == MULTIPOLYGON || relation.Tags[TYPE] == BOUNDARY); }
private async Task <Feature> UpdateElasticSearch(ICompleteOsmGeo osm, string name) { var feature = ConvertOsmToFeature(osm, name); if (feature != null) { await _elasticSearchGateway.UpdateNamesData(feature); } return(feature); }
private async Task <Feature> UpdateElasticSearch(ICompleteOsmGeo osm, string name) { var feature = ConvertOsmToFeature(osm, name); if (feature != null) { await _elasticSearchGateway.UpdatePointsOfInterestData(new List <Feature> { feature }); } return(feature); }
private Feature ConvertOsmToFeature(ICompleteOsmGeo osm, string name) { var features = _osmGeoJsonPreprocessorExecutor.Preprocess( new Dictionary <string, List <ICompleteOsmGeo> > { { name ?? string.Empty, new List <ICompleteOsmGeo> { osm } } }); return(features.Any() ? features.First() : null); }
private IAttributesTable ConvertTags(ICompleteOsmGeo osmObject) { var properties = osmObject.Tags.ToDictionary(t => t.Key, t => t.Value); properties.Add(FeatureAttributes.ID, osmObject.Id.ToString()); var table = new AttributesTable(); foreach (var key in properties.Keys) { table.Add(key, properties[key]); } return(table); }
private string GetName(ICompleteOsmGeo osm) { if (osm.Tags.ContainsKey(NAME)) { return osm.Tags[NAME]; } foreach (var tag in osm.Tags) { if (tag.Key.Contains(NAME)) { return tag.Value; } } return string.Empty; }
private string GetName(ICompleteOsmGeo osm) { if (osm.Tags.ContainsKey(NAME)) { return(osm.Tags[NAME]); } foreach (var tag in osm.Tags) { if (tag.Key.Contains(NAME)) { return(tag.Value); } } return(string.Empty); }
private async Task <Feature> UpdateElasticSearch(ICompleteOsmGeo osm, string name) { var feature = ConvertOsmToFeature(osm, name); if (feature == null) { return(null); } var featureFromDb = await _elasticSearchGateway.GetPointOfInterestById(feature.Attributes[FeatureAttributes.ID].ToString(), Sources.OSM); if (featureFromDb != null) { foreach (var attributeKey in featureFromDb.Attributes.GetNames().Where(n => n.StartsWith(FeatureAttributes.POI_PREFIX))) { if (!feature.Attributes.GetNames().Any(n => n == attributeKey)) { feature.Attributes.AddOrUpdate(attributeKey, featureFromDb.Attributes[attributeKey]); } } if (feature.Geometry.OgcGeometryType == OgcGeometryType.Point && featureFromDb.Geometry.OgcGeometryType != OgcGeometryType.Point) { feature.Geometry = featureFromDb.Geometry; } } await _elasticSearchGateway.UpdatePointsOfInterestData(new List <Feature> { feature }); foreach (var language in Languages.Array) { var title = feature.Attributes.GetWikipediaTitle(language); if (string.IsNullOrWhiteSpace(title)) { continue; } var pageFetaure = await _wikipediaGateway.GetByPageTitle(title, language); if (pageFetaure == null) { continue; } await _elasticSearchGateway.DeletePointOfInterestById(pageFetaure.Attributes[FeatureAttributes.ID].ToString(), Sources.WIKIPEDIA); } return(feature); }
public static Node[] AsNodes(this ICompleteOsmGeo element) { if (element is Node node) { return new[] { node } } ; else if (element is CompleteWay way) { return(way.Nodes); } else if (element is CompleteRelation relation) { return(relation.Members.SelectMany(m => AsNodes(m.Member)).ToArray()); } throw new Exception("element wasn't a node, way or relation"); }
public static bool IsTouching(this Bounds bounds, ICompleteOsmGeo geo) { switch (geo) { case Node node: return(IsTouching(bounds, node)); case CompleteWay way: return(IsTouching(bounds, way)); case CompleteRelation relation: return(IsTouching(bounds, relation)); default: throw new Exception("Unknown Complete Element Type."); } }
private async Task <Feature> UpdateElasticSearch(ICompleteOsmGeo osm, string name) { var features = _osmGeoJsonPreprocessorExecutor.Preprocess( new Dictionary <string, List <ICompleteOsmGeo> > { { name, new List <ICompleteOsmGeo> { osm } } }); var feature = features.Values.FirstOrDefault()?.FirstOrDefault(); if (feature != null) { await _elasticSearchGateway.UpdateNamesData(feature); } return(feature); }
/// <summary> /// Converts a complete element into its simple counterpart, /// including the simple versions of its component elements. /// </summary> public static OsmGeo[] ToSimpleWithChildren(this ICompleteOsmGeo complete) { switch (complete) { case Node node: return(new [] { node }); case CompleteWay way: return(way.ToSimpleWithChildren()); case CompleteRelation relation: return(relation.ToSimpleWithChildren()); default: throw new Exception("Unknown Complete Element Type."); } }
/// <inheritdoc /> public async Task <int> UpdateElement(long changesetId, ICompleteOsmGeo osmGeo) { switch (osmGeo.Type) { case OsmGeoType.Node: return(await UpdateElement(changesetId, osmGeo as OsmGeo)); case OsmGeoType.Way: return(await UpdateElement(changesetId, ((CompleteWay)osmGeo).ToSimple())); case OsmGeoType.Relation: return(await UpdateElement(changesetId, ((CompleteRelation)osmGeo).ToSimple())); default: throw new Exception($"Invalid OSM geometry type: {osmGeo.Type}"); } }
private IAttributesTable ConvertTags(ICompleteOsmGeo osmObject) { var table = new AttributesTable(osmObject.Tags.ToDictionary(t => t.Key, t => t.Value as object)) { { FeatureAttributes.ID, osmObject.GetId() } }; if (osmObject.TimeStamp.HasValue) { table.Add(FeatureAttributes.POI_LAST_MODIFIED, osmObject.TimeStamp.Value.ToString("o")); } if (!string.IsNullOrWhiteSpace(osmObject.UserName)) { table.Add(FeatureAttributes.POI_USER_NAME, osmObject.UserName); table.Add(FeatureAttributes.POI_USER_ADDRESS, $"https://www.openstreetmap.org/user/{Uri.EscapeUriString(osmObject.UserName)}"); } return(table); }
public static string OsmIDString(ICompleteOsmGeo geo) { if (geo is Node) { return("n" + geo.Id); } else if (geo is CompleteWay) { return("w" + geo.Id); } else if (geo is CompleteRelation) { return("r" + geo.Id); } else { return("x"); } }
public static Coordinate AsPosition(this ICompleteOsmGeo element) { if (element is Node node) { return(new Coordinate(node.Longitude.Value, node.Latitude.Value)); } else if (element is CompleteWay way) { return(new Coordinate(way.Nodes.Average(n => n.Longitude.Value), way.Nodes.Average(n => n.Latitude.Value))); } else if (element is CompleteRelation relation) { // This isn't exact for relations. Good enough. var positions = relation.Members.Select(m => AsPosition(m.Member)); return(new Coordinate(positions.Average(n => n.X), positions.Average(n => n.Y))); } throw new Exception("element wasn't a node, way or relation"); }
public void AddChange(ICompleteOsmGeo geo) { modifiedComplete.Add(geo); switch (geo) { case CompleteWay w: modified.Add(w.ToSimple()); break; case Node n: modified.Add(n); break; case CompleteRelation r: modified.Add(r.ToSimple()); break; default: throw new Exception($"Unknown type: {geo}"); } }
public void Pull() { this._source.Initialize(); this.Initialize(); while (this._source.MoveNext()) { ICompleteOsmGeo completeOsmGeo = this._source.Current(); if (completeOsmGeo is Node) { this.AddNode(completeOsmGeo as Node); } else if (completeOsmGeo is CompleteWay) { this.AddWay(completeOsmGeo as CompleteWay); } else if (completeOsmGeo is CompleteRelation) { this.AddRelation(completeOsmGeo as CompleteRelation); } } this.Flush(); this.Close(); }
/// <summary> /// Pulls the changes from the source to this target. /// </summary> public void Pull() { _source.Initialize(); this.Initialize(); while (_source.MoveNext()) { ICompleteOsmGeo sourceObject = _source.Current(); if (sourceObject is Node) { this.AddNode(sourceObject as Node); } else if (sourceObject is CompleteWay) { this.AddWay(sourceObject as CompleteWay); } else if (sourceObject is CompleteRelation) { this.AddRelation(sourceObject as CompleteRelation); } } this.Flush(); this.Close(); }
/// <inheritdoc /> public async Task <PointOfInterestExtended> UpdatePointOfInterest(PointOfInterestExtended pointOfInterest, TokenAndSecret tokenAndSecret, string language) { var osmGateway = _httpGatewayFactory.CreateOsmGateway(tokenAndSecret); var id = pointOfInterest.Id; ICompleteOsmGeo completeOsmGeo = await osmGateway.GetElement(id, pointOfInterest.Type); var featureBeforeUpdate = ConvertOsmToFeature(completeOsmGeo, pointOfInterest.Title); var oldIcon = featureBeforeUpdate.Attributes[FeatureAttributes.ICON].ToString(); var oldTags = completeOsmGeo.Tags.ToArray(); SetWebsiteUrl(completeOsmGeo.Tags, pointOfInterest); SetTagByLanguage(completeOsmGeo.Tags, FeatureAttributes.NAME, pointOfInterest.Title, language); SetTagByLanguage(completeOsmGeo.Tags, FeatureAttributes.DESCRIPTION, pointOfInterest.Description, language); SyncImages(completeOsmGeo.Tags, pointOfInterest.ImagesUrls); if (pointOfInterest.Icon != oldIcon) { RemoveTagsByIcon(completeOsmGeo.Tags, oldIcon); AddTagsByIcon(completeOsmGeo.Tags, pointOfInterest.Icon); } RemoveEmptyTags(completeOsmGeo.Tags); if (AreTagsCollectionEqual(oldTags, completeOsmGeo.Tags.ToArray())) { var feature = ConvertOsmToFeature(completeOsmGeo, pointOfInterest.Title); return(await FeatureToExtendedPoi(feature, language)); } var changesetId = await osmGateway.CreateChangeset("Update POI interface from IHM site."); await osmGateway.UpdateElement(changesetId, completeOsmGeo); await osmGateway.CloseChangeset(changesetId); var featureToReturn = await UpdateElasticSearch(completeOsmGeo, pointOfInterest.Title); return(await FeatureToExtendedPoi(featureToReturn, language)); }
/// <summary> /// Adds the given tag to the given object, iff that tag did not exist yet. /// Emits a warning if the tag already exists and has a different value /// </summary> /// <param name="geo"></param> /// <param name="key"></param> /// <param name="value"></param> public static void AddNewTag(this ICompleteOsmGeo geo, string key, string value) { if (string.IsNullOrWhiteSpace(key) || string.IsNullOrWhiteSpace(value)) { throw new ArgumentException("Key or value are either null or whitespace"); } var oldValue = geo.Tags.GetValue(key); if (!string.IsNullOrEmpty(oldValue)) { if (!oldValue.Equals(value)) { // Hmm, our mechanical edit would like to change something - lets warn for this; human interaction is needed throw new ArgumentException( $"Warning for object {geo}: not overriding tag {key}={oldValue} with {value}"); } // The tag already exists! We don't do anything return; } geo.Tags.Add(key, value); }
/// <summary> /// Interprets an OSM-object and returns the corresponding geometry. /// </summary> /// <param name="osmObject"></param> /// <returns></returns> public override FeatureCollection Interpret(ICompleteOsmGeo osmObject) { // DISCLAIMER: this is a very very very simple geometry interpreter and // contains hardcoded all relevant tags. var collection = new FeatureCollection(); TagsCollectionBase tags; if (osmObject != null) { switch (osmObject.Type) { case CompleteOsmType.Node: var newCollection = new TagsCollection( osmObject.Tags); newCollection.RemoveKey("FIXME"); newCollection.RemoveKey("node"); newCollection.RemoveKey("source"); if (newCollection.Count > 0) { // there is still some relevant information left. collection.Add(new Feature(new Point((osmObject as Node).Coordinate), new SimpleGeometryAttributeCollection(osmObject.Tags))); } break; case CompleteOsmType.Way: tags = osmObject.Tags; bool isArea = false; if ((tags.ContainsKey("building") && !tags.IsFalse("building")) || (tags.ContainsKey("landuse") && !tags.IsFalse("landuse")) || (tags.ContainsKey("amenity") && !tags.IsFalse("amenity")) || (tags.ContainsKey("harbour") && !tags.IsFalse("harbour")) || (tags.ContainsKey("historic") && !tags.IsFalse("historic")) || (tags.ContainsKey("leisure") && !tags.IsFalse("leisure")) || (tags.ContainsKey("man_made") && !tags.IsFalse("man_made")) || (tags.ContainsKey("military") && !tags.IsFalse("military")) || (tags.ContainsKey("natural") && !tags.IsFalse("natural")) || (tags.ContainsKey("office") && !tags.IsFalse("office")) || (tags.ContainsKey("place") && !tags.IsFalse("place")) || (tags.ContainsKey("power") && !tags.IsFalse("power")) || (tags.ContainsKey("public_transport") && !tags.IsFalse("public_transport")) || (tags.ContainsKey("shop") && !tags.IsFalse("shop")) || (tags.ContainsKey("sport") && !tags.IsFalse("sport")) || (tags.ContainsKey("tourism") && !tags.IsFalse("tourism")) || (tags.ContainsKey("waterway") && !tags.IsFalse("waterway")) || (tags.ContainsKey("wetland") && !tags.IsFalse("wetland")) || (tags.ContainsKey("water") && !tags.IsFalse("water")) || (tags.ContainsKey("aeroway") && !tags.IsFalse("aeroway"))) { // these tags usually indicate an area. isArea = true; } if (tags.IsTrue("area")) { // explicitly indicated that this is an area. isArea = true; } else if (tags.IsFalse("area")) { // explicitly indicated that this is not an area. isArea = false; } if (isArea) { // area tags leads to simple polygon var lineairRing = new Feature(new LineairRing((osmObject as CompleteWay).GetCoordinates().ToArray<GeoCoordinate>()), new SimpleGeometryAttributeCollection(tags)); collection.Add(lineairRing); } else { // no area tag leads to just a line. var lineString = new Feature(new LineString((osmObject as CompleteWay).GetCoordinates().ToArray<GeoCoordinate>()), new SimpleGeometryAttributeCollection(tags)); collection.Add(lineString); } break; case CompleteOsmType.Relation: var relation = (osmObject as CompleteRelation); tags = relation.Tags; string typeValue; if (tags.TryGetValue("type", out typeValue)) { // there is a type in this relation. if (typeValue == "multipolygon") { // this relation is a multipolygon. var feature = this.InterpretMultipolygonRelation(relation); if (feature != null) { // add the geometry. collection.Add(feature); } } else if (typeValue == "boundary") { // this relation is a boundary. } } break; } } return collection; }
/// <summary> /// Interprets an OSM-object and returns the corresponding geometry. /// </summary> /// <param name="osmObject"></param> /// <returns></returns> public abstract FeatureCollection Interpret(ICompleteOsmGeo osmObject);
/// <summary> /// Translates the given OSM objects into corresponding geometries. /// </summary> /// <param name="projection">The projection to use.</param> /// <param name="osmGeo">The osm object.</param> /// <param name="scene">The scene to fill with the resulting geometries.</param> /// <returns></returns> public abstract void Translate(Scene2D scene, IProjection projection, ICompleteOsmGeo osmGeo);
/// <summary> /// Interprets an OSM-object and returns the corresponding geometry. /// </summary> /// <param name="osmObject"></param> /// <returns></returns> public abstract GeometryCollection Interpret(ICompleteOsmGeo osmObject);
/// <summary> /// The actual conflation. /// Returns true if conflation is finished and this grbPoly has been matched /// </summary> private static bool AttemptConflate(Geometry grbPoly, Geometry osmPoly, TagsCollectionBase grbTags, ICompleteOsmGeo osmObj, EasyChangeset cs) { // Is there geographical match? if (Math.Abs(osmPoly.Centroid.Distance(grbPoly.Centroid)) > 0.000001) { return(false); } if (osmPoly.Difference(grbPoly).Area > 0.000000001) { return(false); } if (grbPoly.Difference(osmPoly).Area > 0.000000001) { return(false); } if (grbTags == null) { Console.WriteLine("PANIC for grb object " + grbPoly); return(false); } if (osmObj.Tags.TryGetValue("building", out var osmBuildingValue)) { if (osmBuildingValue.Equals("yes")) { osmObj.Tags.RemoveKey("building"); } else { grbTags.TryGetValue("building", out var grbBuildingValue); if (grbBuildingValue == null) { Console.WriteLine("GRB Building value is null"); } else if (osmBuildingValue != grbBuildingValue) { if (!grbBuildingValue.Equals("yes")) { Console.WriteLine( $"Preferring OSM building-tag '{osmBuildingValue}' over the grb tag '{grbBuildingValue}'"); } grbTags.RemoveKey("building"); } } } if (osmObj.Tags.TryGetValue("source:geometry:ref", out var osmSourceRef)) { grbTags.TryGetValue("source:geometry:ref", out var grbRef); if (!osmSourceRef.Equals(grbRef)) { throw new Exception($"MISMATCH for {osmObj}: {osmSourceRef} != {grbRef}"); } osmObj.Tags.RemoveKey("source:geometry:date"); } if (osmObj.Tags.TryGetValue("addr:housenumber", out var osmHouseNumber)) { grbTags.TryGetValue("addr:housenumber", out var grbHouseNumber); if (!osmHouseNumber.Equals(grbHouseNumber)) { grbTags.RemoveKey("addr:housenumber"); var msg = "GRB thinks that this has number " + (string.IsNullOrEmpty(grbHouseNumber) ? "no number" : grbHouseNumber); Console.WriteLine( $"GRB and OSM disagree over housenumber of {osmObj}. Putting a fixme instead: grb: {grbHouseNumber} != osm {osmHouseNumber}"); if (grbTags.ContainsKey("fixme")) { msg += ";" + grbTags.GetValue("fixme"); } grbTags.AddOrReplace("fixme", msg); } } if (osmObj.Tags.TryGetValue("addr:street", out var osmStreet)) { grbTags.TryGetValue("addr:street", out var grbStreet); if (!string.IsNullOrEmpty(grbStreet) && !osmStreet.Equals(grbStreet)) { grbTags.RemoveKey("addr:street"); var msg = "GRB thinks that this lays in street " + grbStreet; Console.WriteLine( $"GRB and OSM disagree over streetname of {osmObj}. Putting a fixme instead: grb: {grbStreet} != osm {osmStreet}"); if (grbTags.ContainsKey("fixme")) { msg += ";" + grbTags.GetValue("fixme"); } grbTags.AddOrReplace("fixme", msg); } } try { foreach (var grbTag in grbTags) { if (grbTag.Key.Contains("wrong")) { continue; } osmObj.AddNewTag(grbTag.Key, grbTag.Value); } cs.AddChange(osmObj); } catch (Exception e) { Console.WriteLine($"{osmObj}: {e.Message}: skipping match"); } return(true); }
/// <summary> /// Translates OSM objects into basic renderable primitives. /// </summary> /// <param name="scene">The scene to add primitives to.</param> /// <param name="projection">The projection used to convert the objects.</param> /// <param name="osmGeo">The osm object.</param> /// <returns></returns> public override void Translate(Scene2D scene, IProjection projection, ICompleteOsmGeo osmGeo) { // set the scene backcolor. scene.BackColor = this.GetCanvasColor().Value; if (osmGeo == null) { return; } if (_mapCSSFile == null) { return; } // store the object count. int countBefore = scene.Count; // interpret the osm-objects. switch (osmGeo.Type) { case CompleteOsmType.Node: if (!_mapCSSFile.HasNodeIdSelector && osmGeo.Tags.Count == 0) { // this node can never be selected, no tags and no id selectors. break; } if (!_mapCSSFile.HasNodeIdSelector && _keysForNodes != null && !osmGeo.Tags.ContainsOneOfKeys(_keysForNodes)) { // no good keys present. break; } this.TranslateNode(scene, projection, osmGeo as Node); break; case CompleteOsmType.Way: var relevantWayTags = osmGeo.Tags; if (_keysForWays != null) { // filter the collection. relevantWayTags = relevantWayTags.KeepKeysOf(_keysForWays); } if (!_mapCSSFile.HasWayIdSelector && _keysForWays != null && relevantWayTags.Count == 0) { // no good keys present. break; } if (!_unsuccesfullWays.Contains(relevantWayTags)) { // way has some potential. var completeWay = osmGeo as CompleteWay; if (completeWay.Nodes.Count > 0 && !this.TranslateWay(scene, projection, completeWay, relevantWayTags)) { // ... but translate was unsuccesfull. _unsuccesfullWays.Add(relevantWayTags); } } break; case CompleteOsmType.Relation: if (!_mapCSSFile.HasRelationIdSelector && _keysForRelations != null && !osmGeo.Tags.ContainsOneOfKeys(_keysForRelations)) { // no good keys present. break; } this.TranslateRelation(scene, projection, osmGeo as CompleteRelation); break; } // interpret the osmGeo object and check if it makes up an area. if (osmGeo.Type != CompleteOsmType.Node) { // nodes cannot lead to a geometry for MapCSS. if (_keysForLines == null || osmGeo.Tags.ContainsOneOfKeys(_keysForLines) || _keysForAreas == null || osmGeo.Tags.ContainsOneOfKeys(_keysForAreas)) { // good keys present. var collection = _geometryInterpreter.Interpret(osmGeo); foreach (Geometry geometry in collection) { if (geometry is LineairRing) { // a simple lineair ring. this.TranslateLineairRing(scene, projection, geometry as LineairRing); } else if (geometry is Polygon) { // a simple polygon. this.TranslatePolygon(scene, projection, geometry as Polygon); } else if (geometry is MultiPolygon) { // a multipolygon. this.TranslateMultiPolygon(scene, projection, geometry as MultiPolygon); } } } } // check if any objects have been added to the scene. if (scene.Count <= countBefore) { // no objects have been added. Apply default styles if needed. if (osmGeo.Type == CompleteOsmType.Node && _mapCSSFile != null && _mapCSSFile.DefaultPoints) { // apply default points style. Node node = (osmGeo as Node); uint pointId = scene.AddPoint(projection.LongitudeToX(node.Coordinate.Longitude), projection.LatitudeToY(node.Coordinate.Latitude)); scene.AddStylePoint(pointId, this.CalculateSceneLayer(OffsetPoint, 0), float.MinValue, float.MaxValue, SimpleColor.FromKnownColor(KnownColor.Black).Value, 2); } else if (osmGeo.Type == CompleteOsmType.Way && _mapCSSFile != null && _mapCSSFile.DefaultLines) { // apply default lines style. CompleteWay way = (osmGeo as CompleteWay); // get x/y. double[] x = null, y = null; if (x == null) { // pre-calculate x/y. x = new double[way.Nodes.Count]; y = new double[way.Nodes.Count]; for (int idx = 0; idx < way.Nodes.Count; idx++) { x[idx] = projection.LongitudeToX( way.Nodes[idx].Coordinate.Longitude); y[idx] = projection.LatitudeToY( way.Nodes[idx].Coordinate.Latitude); } // simplify. if (x.Length > 2) { double[][] simplified = SimplifyCurve.Simplify(new double[][] { x, y }, 0.0001); x = simplified[0]; y = simplified[1]; } } uint? points = scene.AddPoints(x, y); if (points.HasValue) { scene.AddStyleLine(points.Value, this.CalculateSceneLayer(OffsetLine, 0), float.MinValue, float.MaxValue, SimpleColor.FromKnownColor(KnownColor.Red).Value, 1, LineJoin.Round, null); } } } }