/// <summary> /// Creates a new OSM data layer. /// </summary> /// <param name="dataSource"></param> /// <param name="styleInterpreter"></param> public LayerOsm(IDataSourceReadOnly dataSource, StyleInterpreter styleInterpreter, IProjection projection) { // build the zoom-level cutoffs. List<float> zoomLevelCutoffs = new List<float>(); zoomLevelCutoffs.Add((float)projection.ToZoomFactor(18)); //zoomLevelCutoffs.Add((float)projection.ToZoomFactor(16)); //zoomLevelCutoffs.Add((float)projection.ToZoomFactor(14)); //zoomLevelCutoffs.Add((float)projection.ToZoomFactor(12)); //zoomLevelCutoffs.Add((float)projection.ToZoomFactor(10)); //zoomLevelCutoffs.Add((float)projection.ToZoomFactor(8)); zoomLevelCutoffs.Add((float)projection.ToZoomFactor(0)); _dataSource = dataSource; _styleSceneManager = new StyleSceneManager(styleInterpreter, zoomLevelCutoffs); //_styleSceneManager = new StyleSceneManager(styleInterpreter); }
/// <summary> /// Translates a way. /// </summary> /// <param name="scene">The scene to add primitives to.</param> /// <param name="projection">The projection used to convert the objects.</param> /// <param name="way"></param> /// <param name="relevantTags"></param> private bool TranslateWay(Scene2D scene, IProjection projection, CompleteWay way, TagsCollectionBase relevantTags) { // build the rules. List<MapCSSRuleProperties> rules = null; if (!_succesfullWays.TryGetValue(relevantTags, out rules)) { rules = this.BuildRules(new MapCSSObject(way)); _succesfullWays.Add(relevantTags, rules); } // validate what's there. if (rules.Count == 0) { return false; } bool success = false; // 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]; } } // add the z-index. foreach (var rule in rules) { float minZoom = (float)projection.ToZoomFactor(rule.MinZoom); float maxZoom = (float)projection.ToZoomFactor(rule.MaxZoom); int zIndex ; if (!rule.TryGetProperty<int>("zIndex", out zIndex)) { zIndex = 0; } // interpret the results. if (x != null && x.Length > 1) { // there is a valid interpretation of this way. int color; bool renderAsLine = true; if (way.IsOfType(MapCSSTypes.Area)) { // the way is an area. check if it can be rendered as an area. int fillColor; if (rule.TryGetProperty("fillColor", out fillColor)) { // render as an area. uint? pointsId = scene.AddPoints(x, y); if (pointsId.HasValue) { scene.AddStylePolygon(pointsId.Value, this.CalculateSceneLayer(OffsetArea, zIndex), minZoom, maxZoom, fillColor, 1, true); success = true; if (rule.TryGetProperty("color", out color)) { scene.AddStylePolygon(pointsId.Value, this.CalculateSceneLayer(OffsetCasing, zIndex), minZoom, maxZoom, color, 1, false); success = true; } } renderAsLine = false; // was validly rendered als a line. } } if (renderAsLine) { // was not rendered as an area. // the way has to rendered as a line. LineJoin lineJoin; if (!rule.TryGetProperty("lineJoin", out lineJoin)) { lineJoin = LineJoin.Miter; } int[] dashes; if (!rule.TryGetProperty("dashes", out dashes)) { dashes = null; } if (rule.TryGetProperty("color", out color)) { float casingWidth; int casingColor; if (!rule.TryGetProperty("casingWidth", out casingWidth)) { casingWidth = 0; } if (!rule.TryGetProperty("casingColor", out casingColor)) { // casing: use the casing layer. casingColor = -1; } float width; if (!rule.TryGetProperty("width", out width)) { width = 1; } uint? pointsId = scene.AddPoints(x, y); success = true; if (pointsId.HasValue) { if (casingWidth > 0) { // adds the casing scene.AddStyleLine(pointsId.Value, this.CalculateSceneLayer(OffsetCasing, zIndex), minZoom, maxZoom, casingColor, width + (casingWidth * 2), lineJoin, dashes); } if (dashes == null) { // dashes not set, use line offset. scene.AddStyleLine(pointsId.Value, this.CalculateSceneLayer(OffsetLine, zIndex), minZoom, maxZoom, color, width, lineJoin, dashes); } else { // dashes set, use line pattern offset. scene.AddStyleLine(pointsId.Value, this.CalculateSceneLayer(OffsetLinePattern, zIndex), minZoom, maxZoom, color, width, lineJoin, dashes); } int textColor; int fontSize; string nameTag; if (!rule.TryGetProperty("fontSize", out fontSize)) { fontSize = 10; } if (rule.TryGetProperty("text", out nameTag) && rule.TryGetProperty("textColor", out textColor)) { int haloColor; int? haloColorNullable = null; if (rule.TryGetProperty("textHaloColor", out haloColor)) { haloColorNullable = haloColor; } int haloRadius; int? haloRadiusNullable = null; if (rule.TryGetProperty("textHaloRadius", out haloRadius)) { haloRadiusNullable = haloRadius; } string fontFamily; if (!rule.TryGetProperty("fontFamily", out fontFamily)) { fontFamily = "Arial"; // just some default font. } string name; if (way.Tags.TryGetValue(nameTag, out name)) { scene.AddStyleLineText(pointsId.Value, this.CalculateSceneLayer(OffsetLineText, zIndex), minZoom, maxZoom, textColor, fontSize, name, fontFamily, haloColorNullable, haloRadiusNullable); } } } } } } else { // don't report as an error when no nodes. success = true; } } if(!success) { // make sure this sucess is stored. _succesfullWays[relevantTags] = null; } return success; }
/// <summary> /// Translates a node. /// </summary> /// <param name="scene">The scene to add primitives to.</param> /// <param name="projection">The projection used to convert the objects.</param> /// <param name="node"></param> private void TranslateNode(Scene2D scene, IProjection projection, Node node) { // build the rules. IEnumerable<MapCSSRuleProperties> rules = this.BuildRules(new MapCSSObject(node)); // interpret the results. foreach (var rule in rules) { int zIndex; if (!rule.TryGetProperty<int>("zIndex", out zIndex)) { zIndex = 0; } float minZoom = (float)projection.ToZoomFactor(rule.MinZoom); float maxZoom = (float)projection.ToZoomFactor(rule.MaxZoom); uint? pointId = null; int color; if (rule.TryGetProperty<int>("color", out color)) { float width; if (rule.TryGetProperty<float>("width", out width)) { pointId = scene.AddPoint(projection.LongitudeToX(node.Coordinate.Longitude), projection.LatitudeToY(node.Coordinate.Latitude)); scene.AddStylePoint(pointId.Value, this.CalculateSceneLayer(OffsetPoint, zIndex), minZoom, maxZoom, color, width); } else { pointId = scene.AddPoint(projection.LongitudeToX(node.Coordinate.Longitude), projection.LatitudeToY(node.Coordinate.Latitude)); scene.AddStylePoint(pointId.Value, this.CalculateSceneLayer(OffsetPoint, zIndex), minZoom, maxZoom, color, 1); } } byte[] iconImage; if (rule.TryGetProperty("iconImage", out iconImage)) { if (!pointId.HasValue) { pointId = scene.AddPoint(projection.LongitudeToX(node.Coordinate.Longitude), projection.LatitudeToY(node.Coordinate.Latitude)); } // an icon is to be drawn! ushort imageId = scene.AddImage(iconImage); scene.AddIcon(pointId.Value, this.CalculateSceneLayer(OffsetPoint, zIndex), minZoom, maxZoom, imageId); } string text; if (rule.TryGetProperty("text", out text)) { int textColor; if(!rule.TryGetProperty("textColor", out textColor)) { textColor = SimpleColor.FromKnownColor(KnownColor.Black).Value; } int haloColor; int? haloColorNullable = null; if (rule.TryGetProperty("textHaloColor", out haloColor)) { haloColorNullable = haloColor; } int haloRadius; int? haloRadiusNullable = null; if (rule.TryGetProperty("textHaloRadius", out haloRadius)) { haloRadiusNullable = haloRadius; } int fontSize; if (!rule.TryGetProperty("fontSize", out fontSize)) { fontSize = 10; } string fontFamily; if (!rule.TryGetProperty ("fontFamily", out fontFamily)) { fontFamily = "Arial"; // just some default font. } // a text is to be drawn. string value; if (node.Tags.TryGetValue(text, out value)) { if (!pointId.HasValue) { pointId = scene.AddPoint(projection.LongitudeToX(node.Coordinate.Longitude), projection.LatitudeToY(node.Coordinate.Latitude)); } scene.AddText(pointId.Value, this.CalculateSceneLayer(OffsetPointText, zIndex), minZoom, maxZoom, fontSize, value, textColor, haloColorNullable, haloRadiusNullable, fontFamily); } } } }
/// <summary> /// Translates a lineair ring. /// </summary> /// <param name="scene">The scene to add primitives to.</param> /// <param name="projection">The projection used to convert the objects.</param> /// <param name="lineairRing"></param> private void TranslateLineairRing(Scene2D scene, IProjection projection, LineairRing lineairRing) { // build the rules. List<MapCSSRuleProperties> rules = this.BuildRules(new MapCSSObject(lineairRing)); // validate what's there. if (rules.Count == 0) { return; } // get x/y. double[] x = null, y = null; if (lineairRing.Coordinates != null && lineairRing.Coordinates.Count > 0) { // pre-calculate x/y. x = new double[lineairRing.Coordinates.Count]; y = new double[lineairRing.Coordinates.Count]; for (int idx = 0; idx < lineairRing.Coordinates.Count; idx++) { x[idx] = projection.LongitudeToX( lineairRing.Coordinates[idx].Longitude); y[idx] = projection.LatitudeToY( lineairRing.Coordinates[idx].Latitude); } // simplify. if (x.Length > 2) { double[][] simplified = SimplifyCurve.Simplify(new double[][] { x, y }, 0.0001); x = simplified[0]; y = simplified[1]; } } // add the z-index. foreach (var rule in rules) { float minZoom = (float)projection.ToZoomFactor(rule.MinZoom); float maxZoom = (float)projection.ToZoomFactor(rule.MaxZoom); int zIndex; if (!rule.TryGetProperty<int>("zIndex", out zIndex)) { zIndex = 0; } // interpret the results. if (x != null) { // there is a valid interpretation of this way. int color; int fillColor; if (rule.TryGetProperty("fillColor", out fillColor)) { // render as an area. float fillOpacity; if(rule.TryGetProperty("fillOpacity", out fillOpacity)) { SimpleColor simpleFillColor = new SimpleColor() { Value = fillColor }; fillColor = SimpleColor.FromArgb((int)(255 * fillOpacity), simpleFillColor.R, simpleFillColor.G, simpleFillColor.B).Value; } uint? pointsId = scene.AddPoints(x, y); if (pointsId.HasValue) { scene.AddStylePolygon(pointsId.Value, this.CalculateSceneLayer(OffsetArea, zIndex), minZoom, maxZoom, fillColor, 1, true); if (rule.TryGetProperty("color", out color)) { scene.AddStylePolygon(pointsId.Value, this.CalculateSceneLayer(OffsetCasing, zIndex), minZoom, maxZoom, color, 1, false); } } } } } }
/// <summary> /// Translates a way. /// </summary> /// <param name="scene">The scene to add primitives to.</param> /// <param name="projection">The projection used to convert the objects.</param> /// <param name="way"></param> private void TranslateWay(Scene2D scene, IProjection projection, CompleteWay way) { // build the rules. List<MapCSSRuleProperties> rules = this.BuildRules(new MapCSSObject(way)); // validate what's there. if (rules.Count == 0) { return; } // 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]; } } // add the z-index. foreach (var rule in rules) { float minZoom = (float)projection.ToZoomFactor(rule.MinZoom); float maxZoom = (float)projection.ToZoomFactor(rule.MaxZoom); int zIndex ; if (!rule.TryGetProperty<int>("zIndex", out zIndex)) { zIndex = 0; } // interpret the results. if (x != null) { // there is a valid interpretation of this way. int color; if (way.IsOfType(MapCSSTypes.Area)) { // the way is an area. check if it can be rendered as an area. int fillColor; if (rule.TryGetProperty("fillColor", out fillColor)) { // render as an area. scene.AddPolygon(this.CalculateSceneLayer(OffsetArea, zIndex), minZoom, maxZoom, x, y, fillColor, 1, true); if (rule.TryGetProperty("color", out color)) { scene.AddPolygon(this.CalculateSceneLayer(OffsetCasing, zIndex), minZoom, maxZoom, x, y, color, 1, false); } } } // the way has to rendered as a line. LineJoin lineJoin; if (!rule.TryGetProperty("lineJoin", out lineJoin)) { lineJoin = LineJoin.Miter; } int[] dashes; if (!rule.TryGetProperty("dashes", out dashes)) { dashes = null; } if (rule.TryGetProperty("color", out color)) { float casingWidth; int casingColor; if (!rule.TryGetProperty("casingWidth", out casingWidth)) { casingWidth = 0; } if(!rule.TryGetProperty("casingColor", out casingColor)) { // casing: use the casing layer. casingColor = -1; } float width; if (!rule.TryGetProperty("width", out width)) { width = 1; } if (casingWidth > 0) { // adds the casing scene.AddLine(this.CalculateSceneLayer(OffsetCasing, zIndex), minZoom, maxZoom, x, y, casingColor, width + (casingWidth * 2), lineJoin, dashes); } if (dashes == null) { // dashes not set, use line offset. scene.AddLine(this.CalculateSceneLayer(OffsetLine, zIndex), minZoom, maxZoom, x, y, color, width, lineJoin, dashes); } else { // dashes set, use line pattern offset. scene.AddLine(this.CalculateSceneLayer(OffsetLinePattern, zIndex), minZoom, maxZoom, x, y, color, width, lineJoin, dashes); } int textColor; int fontSize; string nameTag; if (!rule.TryGetProperty("fontSize", out fontSize)) { fontSize = 10; } if (rule.TryGetProperty("text", out nameTag) && rule.TryGetProperty("textColor", out textColor)) { int haloColor; int? haloColorNullable = null; if (rule.TryGetProperty("textHaloColor", out haloColor)) { haloColorNullable = haloColor; } int haloRadius; int? haloRadiusNullable = null; if (rule.TryGetProperty("textHaloRadius", out haloRadius)) { haloRadiusNullable = haloRadius; } string name; if (way.Tags.TryGetValue(nameTag, out name)) { scene.AddTextLine(this.CalculateSceneLayer(OffsetLineText, zIndex), minZoom, maxZoom, x, y, textColor, fontSize, name, haloColorNullable, haloRadiusNullable); } } } } } }
/// <summary> /// Translates a way. /// </summary> /// <param name="scene">The scene to add primitives to.</param> /// <param name="projection">The projection used to convert the objects.</param> /// <param name="way"></param> private void TranslateWay(Scene2D scene, IProjection projection, CompleteWay way) { // build the rules. List <MapCSSRuleProperties> rules = this.BuildRules(new MapCSSObject(way)); // validate what's there. if (rules.Count == 0) { return; } // 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]; } } // add the z-index. foreach (var rule in rules) { float minZoom = (float)projection.ToZoomFactor(rule.MinZoom); float maxZoom = (float)projection.ToZoomFactor(rule.MaxZoom); int zIndex; if (!rule.TryGetProperty <int>("zIndex", out zIndex)) { zIndex = 0; } // interpret the results. if (x != null) { // there is a valid interpretation of this way. int color; if (way.IsOfType(MapCSSTypes.Area)) { // the way is an area. check if it can be rendered as an area. int fillColor; if (rule.TryGetProperty("fillColor", out fillColor)) { // render as an area. scene.AddPolygon(this.CalculateSceneLayer(OffsetArea, zIndex), minZoom, maxZoom, x, y, fillColor, 1, true); if (rule.TryGetProperty("color", out color)) { scene.AddPolygon(this.CalculateSceneLayer(OffsetCasing, zIndex), minZoom, maxZoom, x, y, color, 1, false); } } } // the way has to rendered as a line. LineJoin lineJoin; if (!rule.TryGetProperty("lineJoin", out lineJoin)) { lineJoin = LineJoin.Miter; } int[] dashes; if (!rule.TryGetProperty("dashes", out dashes)) { dashes = null; } if (rule.TryGetProperty("color", out color)) { float casingWidth; int casingColor; if (!rule.TryGetProperty("casingWidth", out casingWidth)) { casingWidth = 0; } if (!rule.TryGetProperty("casingColor", out casingColor)) { // casing: use the casing layer. casingColor = -1; } float width; if (!rule.TryGetProperty("width", out width)) { width = 1; } if (casingWidth > 0) { // adds the casing scene.AddLine(this.CalculateSceneLayer(OffsetCasing, zIndex), minZoom, maxZoom, x, y, casingColor, width + (casingWidth * 2), lineJoin, dashes); } if (dashes == null) { // dashes not set, use line offset. scene.AddLine(this.CalculateSceneLayer(OffsetLine, zIndex), minZoom, maxZoom, x, y, color, width, lineJoin, dashes); } else { // dashes set, use line pattern offset. scene.AddLine(this.CalculateSceneLayer(OffsetLinePattern, zIndex), minZoom, maxZoom, x, y, color, width, lineJoin, dashes); } int textColor; int fontSize; string nameTag; if (!rule.TryGetProperty("fontSize", out fontSize)) { fontSize = 10; } if (rule.TryGetProperty("text", out nameTag) && rule.TryGetProperty("textColor", out textColor)) { int haloColor; int?haloColorNullable = null; if (rule.TryGetProperty("textHaloColor", out haloColor)) { haloColorNullable = haloColor; } int haloRadius; int?haloRadiusNullable = null; if (rule.TryGetProperty("textHaloRadius", out haloRadius)) { haloRadiusNullable = haloRadius; } string name; if (way.Tags.TryGetValue(nameTag, out name)) { scene.AddTextLine(this.CalculateSceneLayer(OffsetLineText, zIndex), minZoom, maxZoom, x, y, textColor, fontSize, name, haloColorNullable, haloRadiusNullable); } } } } } }
/// <summary> /// Translates a node. /// </summary> /// <param name="scene">The scene to add primitives to.</param> /// <param name="projection">The projection used to convert the objects.</param> /// <param name="node"></param> private void TranslateNode(Scene2D scene, IProjection projection, CompleteNode node) { double?x = projection.LongitudeToX( node.Coordinate.Longitude); double?y = projection.LatitudeToY( node.Coordinate.Latitude); // build the rules. IEnumerable <MapCSSRuleProperties> rules = this.BuildRules(new MapCSSObject(node)); // interpret the results. foreach (var rule in rules) { int zIndex; if (!rule.TryGetProperty <int>("zIndex", out zIndex)) { zIndex = 0; } float minZoom = (float)projection.ToZoomFactor(rule.MinZoom); float maxZoom = (float)projection.ToZoomFactor(rule.MaxZoom); int color; if (rule.TryGetProperty <int>("color", out color)) { float width; if (rule.TryGetProperty <float>("width", out width)) { scene.AddPoint(this.CalculateSceneLayer(OffsetPoint, zIndex), minZoom, maxZoom, projection.LongitudeToX(node.Coordinate.Longitude), projection.LatitudeToY(node.Coordinate.Latitude), color, width); } else { scene.AddPoint(this.CalculateSceneLayer(OffsetPoint, zIndex), minZoom, maxZoom, projection.LongitudeToX(node.Coordinate.Longitude), projection.LatitudeToY(node.Coordinate.Latitude), color, 1); } } byte[] iconImage; if (rule.TryGetProperty("iconImage", out iconImage)) { // an icon is to be drawn! scene.AddIcon(this.CalculateSceneLayer(OffsetPoint, zIndex), minZoom, maxZoom, projection.LongitudeToX(node.Coordinate.Longitude), projection.LatitudeToY(node.Coordinate.Latitude), iconImage); } string text; if (rule.TryGetProperty("text", out text)) { int textColor; if (!rule.TryGetProperty("textColor", out textColor)) { textColor = SimpleColor.FromKnownColor(KnownColor.Black).Value; } int haloColor; int?haloColorNullable = null; if (rule.TryGetProperty("textHaloColor", out haloColor)) { haloColorNullable = haloColor; } int haloRadius; int?haloRadiusNullable = null; if (rule.TryGetProperty("textHaloRadius", out haloRadius)) { haloRadiusNullable = haloRadius; } int fontSize; if (!rule.TryGetProperty("fontSize", out fontSize)) { fontSize = 10; } string fontFamily; if (!rule.TryGetProperty("fontFamily", out fontFamily)) { fontFamily = "Arial"; // just some default font. } // a text is to be drawn. string value; if (node.Tags.TryGetValue(text, out value)) { scene.AddText(this.CalculateSceneLayer(OffsetPointText, zIndex), minZoom, maxZoom, projection.LongitudeToX(node.Coordinate.Longitude), projection.LatitudeToY(node.Coordinate.Latitude), fontSize, value, textColor, haloColorNullable, haloRadiusNullable, fontFamily); } } } }
/// <summary> /// Returns all primitives from this layer visible for the given parameters. /// </summary> /// <param name="zoomFactor"></param> /// <param name="view"></param> /// <returns></returns> protected internal override IEnumerable <Primitive2D> Get(float zoomFactor, View2D view) { var primitives = new List <Primitive2D>(); if (_suspended) { // just return an empty primitives list if suspended. return(primitives); } try { // calculate the current zoom level. var zoomLevel = (int)System.Math.Round(_projection.ToZoomLevel(zoomFactor), 0); if (zoomLevel >= _minZoomLevel && zoomLevel <= _maxZoomLevel) { // build the bounding box. var viewBox = view.OuterBox; var box = new GeoCoordinateBox(_projection.ToGeoCoordinates(viewBox.Min[0], viewBox.Min[1]), _projection.ToGeoCoordinates(viewBox.Max[0], viewBox.Max[1])); var tileRange = TileRange.CreateAroundBoundingBox(box, zoomLevel); var tileRangeIndex = new TileRangeIndex(tileRange); var primitivePerTile = new Dictionary <Tile, Primitive2D>(); lock (_cache) { Image2D temp; foreach (var tile in _cache) { if (tile.Value.IsVisibleIn(view)) { tileRangeIndex.Add(tile.Key); primitivePerTile.Add(tile.Key, tile.Value); var minZoom = _projection.ToZoomFactor(tile.Key.Zoom - _zoomMinOffset); var maxZoom = _projection.ToZoomFactor(tile.Key.Zoom + (1 - _zoomMinOffset)); if (zoomFactor < maxZoom && zoomFactor > minZoom) { // just hit the cache for tiles of this zoom level. _cache.TryGet(tile.Key, out temp); } } } // set the ascending flag. if (_previousZoomFactor != zoomFactor) { // only change flag when difference. _ascending = (_previousZoomFactor < zoomFactor); _previousZoomFactor = zoomFactor; } // get candidate tiles for every tile. var selectedTiles = new List <Tile>(); foreach (var tile in tileRange) { var best = tileRangeIndex.ChooseBest(tile, _ascending); foreach (var bestTile in best) { if (!selectedTiles.Contains(bestTile)) { // make sure no doubles are added! selectedTiles.Add(bestTile); } } } // sort according to the tiles index. selectedTiles.Sort(delegate(Tile x, Tile y) { return(TileRangeIndex.TileWeight(tileRange.Zoom, x.Zoom, !_ascending).CompareTo( TileRangeIndex.TileWeight(tileRange.Zoom, y.Zoom, !_ascending))); }); selectedTiles.Reverse(); // recursively remove tiles. for (int idx = selectedTiles.Count; idx > 0; idx--) { if (selectedTiles[selectedTiles.Count - idx].IsOverlappedBy( selectedTiles.GetRange(selectedTiles.Count - idx + 1, selectedTiles.Count - (selectedTiles.Count - idx + 1)))) { selectedTiles.RemoveAt(selectedTiles.Count - idx); } } // TODO: trim this collection so that only tiles remain close to the zoom level not overlapping. Image2D primitive; foreach (Tile tile in selectedTiles) { if (_cache.TryPeek(tile, out primitive)) { // add to the primitives list. primitives.Add(primitive); } } } } OsmSharp.Logging.Log.TraceEvent("LayerTile", Logging.TraceEventType.Information, string.Format("LayerTile returned {0} primitives.", primitives.Count)); return(primitives); } catch (Exception ex) { // don't worry about exceptions here. OsmSharp.Logging.Log.TraceEvent("LayerTile", Logging.TraceEventType.Error, ex.Message); } return(primitives); }
/// <summary> /// Translates a lineair ring. /// </summary> /// <param name="scene">The scene to add primitives to.</param> /// <param name="projection">The projection used to convert the objects.</param> /// <param name="lineairRing"></param> private void TranslateLineairRing(Scene2D scene, IProjection projection, LineairRing lineairRing) { // build the rules. List <MapCSSRuleProperties> rules = this.BuildRules(new MapCSSObject(lineairRing)); // validate what's there. if (rules.Count == 0) { return; } // get x/y. double[] x = null, y = null; if (lineairRing.Coordinates != null && lineairRing.Coordinates.Count > 0) { // pre-calculate x/y. x = new double[lineairRing.Coordinates.Count]; y = new double[lineairRing.Coordinates.Count]; for (int idx = 0; idx < lineairRing.Coordinates.Count; idx++) { x[idx] = projection.LongitudeToX( lineairRing.Coordinates[idx].Longitude); y[idx] = projection.LatitudeToY( lineairRing.Coordinates[idx].Latitude); } // simplify. if (x.Length > 2) { double[][] simplified = SimplifyCurve.Simplify(new double[][] { x, y }, 0.0001); x = simplified[0]; y = simplified[1]; } } // add the z-index. foreach (var rule in rules) { float minZoom = (float)projection.ToZoomFactor(rule.MinZoom); float maxZoom = (float)projection.ToZoomFactor(rule.MaxZoom); int zIndex; if (!rule.TryGetProperty <int>("zIndex", out zIndex)) { zIndex = 0; } // interpret the results. if (x != null) { // there is a valid interpretation of this way. int color; int fillColor; if (rule.TryGetProperty("fillColor", out fillColor)) { // render as an area. float fillOpacity; if (rule.TryGetProperty("fillOpacity", out fillOpacity)) { SimpleColor simpleFillColor = new SimpleColor() { Value = fillColor }; fillColor = SimpleColor.FromArgb((int)(255 * fillOpacity), simpleFillColor.R, simpleFillColor.G, simpleFillColor.B).Value; } scene.AddPolygon(this.CalculateSceneLayer(OffsetArea, zIndex), minZoom, maxZoom, x, y, fillColor, 1, true); if (rule.TryGetProperty("color", out color)) { scene.AddPolygon(this.CalculateSceneLayer(OffsetCasing, zIndex), minZoom, maxZoom, x, y, color, 1, false); } } } } }
/// <summary> /// Loads the tiles. /// </summary> private void TilesLoading(object projectionParam) { IProjection projection = null; if (projectionParam is IProjection) { // the argument has to a projection. projection = projectionParam as IProjection; } if (projection == null) { throw new ArgumentException("Argument not of type IProjection."); } while (true) { for (int idx = 0; idx < 10; idx++) { Tile tile = null; lock (_tilesStack) { // load the stacked tiles. if (_tilesStack.Count > 0) { // the tiles stack contains at least some tiles. tile = _tilesStack.Pop(); } } // load the tile if (tile != null) { // a tile was found to load. string url = string.Format(_tilesURL, tile.Zoom, tile.X, tile.Y); // get file from tile server. var request = (HttpWebRequest)HttpWebRequest.Create( url); request.Accept = "text/html, image/png, image/jpeg, image/gif, */*"; request.UserAgent = "OsmSharp/4.0"; request.Timeout = 1000; WebResponse myResp = request.GetResponse(); Stream stream = myResp.GetResponseStream(); byte[] image = null; if (stream != null) { // there is data: read it. var memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); image = memoryStream.ToArray(); } if (image != null) { // data was read create the scene object. lock (this.Scene) { float minZoom = (float)projection.ToZoomFactor(tile.Zoom - 0.5f); float maxZoom = (float)projection.ToZoomFactor(tile.Zoom + 0.5f); float left = (float)projection.LongitudeToX(tile.TopLeft.Longitude); float right = (float)projection.LongitudeToX(tile.BottomRight.Longitude); float bottom = (float)projection.LatitudeToY(tile.BottomRight.Latitude); float top = (float)projection.LatitudeToY(tile.TopLeft.Latitude); this.Scene.AddImage(0, minZoom, maxZoom, left, top, right, bottom, image); } if (this.LayerChanged != null) { this.LayerChanged(this); } } } } System.Threading.Thread.Sleep(100); } }