/// <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); } } } }
/// <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 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, CompleteOsmGeo osmGeo) { // set the scene backcolor. scene.BackColor = this.GetCanvasColor().Value; if (osmGeo == null) { return; } // store the object count. int countBefore = scene.Count; // interpret the osm-objects. switch (osmGeo.Type) { case CompleteOsmType.Node: this.TranslateNode(scene, projection, osmGeo as CompleteNode); break; case CompleteOsmType.Way: this.TranslateWay(scene, projection, osmGeo as CompleteWay); break; case CompleteOsmType.Relation: this.TranslateRelation(scene, projection, osmGeo as CompleteRelation); break; case CompleteOsmType.ChangeSet: break; default: throw new ArgumentOutOfRangeException(); } // interpret the osmGeo object and check if it makes up an area. GeometryCollection 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. CompleteNode node = (osmGeo as CompleteNode); 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); } } } }