/// <summary> /// Scores the list of places given in full /// </summary> /// <param name="places">The places to report a score for each.</param> /// <returns>a string of names and scores, </returns> public static string GetScoresForFullArea(List <DbTables.Place> places) { //As above, but counts the Places' full area, not the area in the given Cell8 or Cell10. List <Tuple <string, long, Guid> > areaSizes = new List <Tuple <string, long, Guid> >(places.Count()); foreach (var place in places) { areaSizes.Add(Tuple.Create(TagParser.GetPlaceName(place.Tags), GetScoreForSinglePlace(place.ElementGeometry), place.PrivacyId)); } return(string.Join("\r\n", areaSizes.Select(a => a.Item1 + "|" + a.Item2 + "|" + a.Item3))); }
/// <summary> /// Returns the smallest (most-important) element in a list, to identify which element a client should use. /// </summary> /// <param name="entriesHere">the list of elements to pull data from</param> /// <returns>the name, areatype, and client facing ID of the OSM element to use</returns> public static TerrainData DetermineAreaPlace(List <DbTables.Place> entriesHere) { //Which Place in this given Area is the one that should be displayed on the game/map as the name? picks the smallest one. //This one only returns the smallest entry, for games that only need to check the most interesting area in a cell. var entry = entriesHere.Last(); return(new TerrainData() { Name = TagParser.GetPlaceName(entry.Tags), areaType = entry.GameElementName, PrivacyId = entry.PrivacyId }); }
/// <summary> /// Get the areatype (as defined by TagParser) for each OSM element in the list, along with name and client-facing ID. /// </summary> /// <param name="entriesHere">the list of elements to pull data from</param> /// <returns>A list of name, areatype, and elementIds for a client</returns> public static List <TerrainData> DetermineAreaPlaces(List <DbTables.Place> entriesHere) { //Which Place in this given Area is the one that should be displayed on the game/map as the name? picks the smallest one. //This one return all entries, for a game mode that might need all of them. var results = new List <TerrainData>(entriesHere.Count()); foreach (var e in entriesHere) { results.Add(new TerrainData() { Name = TagParser.GetPlaceName(e.Tags), areaType = e.GameElementName, PrivacyId = e.PrivacyId }); } return(results); }
//TODO: these might be slightly faster with StringBuilder during calculations than String.Join after doing all the calculation. Test and check that assumption. //Default Scoring rules: //Each Cell10 of surface area is 1 Score (would be Points in any other game, but Points is already an overloaded term in this system). //OSM Areas are measured in square area, divided by Cell10 area squared. (An area that covers 25 square Cell10s is 25 Score) //Lines are measured in their length. (A trail that's 25 * resolutionCell10 long is 25 Score) //OSM Points (single lat/lon pair) are assigned a Score of 1 as the minimum interactable size object. /// <summary> /// Get a list of element names, score, and client-facing IDs from a list of places and an area to search, cropped to that area. /// </summary> /// <param name="areaPoly">the area to search and use to determine scores of elements intersecting it </param> /// <param name="places">the elements to be scored, relative to their size in the given area</param> /// <returns>a string of pipe-separated values (name, score, ID) split by newlines</returns> public static string GetScoresForArea(Geometry areaPoly, List <DbTables.Place> places) { //Determines the Scores for the Places, limited to the intersection of the current Area. 1 Cell10 = 1 Score. //EX: if a park overlaps 800 Cell10s, but the current area overlaps 250 of them, this returns 250 for that park. //Lists each Place and its corresponding Score. List <Tuple <string, long, Guid> > areaSizes = new List <Tuple <string, long, Guid> >(places.Count()); foreach (var md in places) { var containedArea = md.ElementGeometry.Intersection(areaPoly); var areaCell10Count = GetScoreForSinglePlace(containedArea); areaSizes.Add(new Tuple <string, long, Guid>(TagParser.GetPlaceName(md.Tags), areaCell10Count, md.PrivacyId)); } return(string.Join("\r\n", areaSizes.Select(a => a.Item1 + "|" + a.Item2 + "|" + a.Item3))); }
/// <summary> /// Create a database StoredOsmElement from an OSMSharp Complete object. /// </summary> /// <param name="g">the CompleteOSMGeo object to prepare to save to the DB</param> /// <returns>the StoredOsmElement ready to save to the DB</returns> public static DbTables.Place ConvertOsmEntryToStoredElement(OsmSharp.Complete.ICompleteOsmGeo g) { var tags = TagParser.getFilteredTags(g.Tags); if (tags == null || tags.Count() == 0) { return(null); //For nodes, don't store every untagged node. } try { var geometry = featureInterpreter.Interpret(g); if (geometry == null) { Log.WriteLog("Error: " + g.Type.ToString() + " " + g.Id + "-" + TagParser.GetPlaceName(g.Tags) + " didn't interpret into a Geometry object", Log.VerbosityLevels.Errors); return(null); } var sw = new DbTables.Place(); sw.SourceItemID = g.Id; sw.SourceItemType = (g.Type == OsmGeoType.Relation ? 3 : g.Type == OsmGeoType.Way ? 2 : 1); var geo = SimplifyArea(geometry); if (geo == null) { Log.WriteLog("Error: " + g.Type.ToString() + " " + g.Id + " didn't simplify for some reason.", Log.VerbosityLevels.Errors); return(null); } geo.SRID = 4326;//Required for SQL Server to accept data. sw.ElementGeometry = geo; sw.Tags = tags; if (sw.ElementGeometry.GeometryType == "LinearRing" || (sw.ElementGeometry.GeometryType == "LineString" && sw.ElementGeometry.Coordinates.First() == sw.ElementGeometry.Coordinates.Last())) { //I want to update all LinearRings to Polygons, and let the style determine if they're Filled or Stroked. var poly = factory.CreatePolygon((LinearRing)sw.ElementGeometry); sw.ElementGeometry = poly; } sw.AreaSize = sw.ElementGeometry.Length > 0 ? sw.ElementGeometry.Length : resolutionCell10; return(sw); } catch (Exception ex) { Log.WriteLog("Error: Item " + g.Id + " failed to process. " + ex.Message); return(null); } }
/// <summary> /// A debugging function, writres some information an element using its OSM id (or internal primary key) to load from the database. /// </summary> /// <param name="id">the PlaceId or SourceElementId of an area to load.</param> /// <returns>a string with some details on the area in question.</returns> public static string LoadDataOnPlace(long id) { //Debugging helper call. Loads up some information on an area and display it. //Not currently used anywhere. var db = new PraxisContext(); var entries = db.Places.Where(m => m.Id == id || m.SourceItemID == id).ToList(); string results = ""; foreach (var entry in entries) { var shape = entry.ElementGeometry; results += "Name: " + TagParser.GetPlaceName(entry.Tags) + Environment.NewLine; results += "Game Type: " + TagParser.GetAreaType(entry.Tags.ToList()) + Environment.NewLine; results += "Geometry Type: " + shape.GeometryType + Environment.NewLine; results += "OSM Type: " + entry.SourceItemType + Environment.NewLine; results += "Area Tags: " + String.Join(",", entry.Tags.Select(t => t.Key + ":" + t.Value)); results += "IsValid? : " + shape.IsValid + Environment.NewLine; results += "Area: " + shape.Area + Environment.NewLine; //Not documented, but I believe this is the area in square degrees. Is that a real unit? results += "As Text: " + shape.AsText() + Environment.NewLine; } return(results); }
} = Guid.NewGuid(); //Pass this Id to clients, so we can attempt to block attaching players to locations in the DB. public override string ToString() { return((SourceItemType == 3 ? "Relation " : SourceItemType == 2 ? "Way " : "Node ") + SourceItemID.ToString() + TagParser.GetPlaceName(Tags)); }