Exemplo n.º 1
0
        /// <summary>
        /// Compares what is in the complete list against the objects in the reference source.
        /// </summary>
        /// <param name="expected"></param>
        /// <param name="actual"></param>
        private void Compare(MemoryDataSource expected, List <CompleteOsmGeo> actual)
        {
            List <CompleteOsmGeo> exectedList = new List <CompleteOsmGeo>();

            foreach (Node node in expected.GetNodes())
            {
                CompleteNode completeNode = CompleteNode.CreateFrom(node);
                if (completeNode != null)
                {
                    exectedList.Add(completeNode);
                }
            }
            foreach (Way way in expected.GetWays())
            {
                CompleteWay completeWay = CompleteWay.CreateFrom(way, expected);
                if (completeWay != null)
                {
                    exectedList.Add(completeWay);
                }
            }
            foreach (Relation relation in expected.GetRelations())
            {
                CompleteRelation completeRelation = CompleteRelation.CreateFrom(relation, expected);
                if (completeRelation != null)
                {
                    exectedList.Add(completeRelation);
                }
            }

            ComparisonHelpers.CompareComplete(exectedList, actual);
        }
Exemplo n.º 2
0
        public void NodeToStringTests()
        {
            CompleteNode testNode    = CompleteNode.Create(-1);
            string       description = testNode.ToString(); //

            testNode.Coordinate = new OsmSharp.Math.Geo.GeoCoordinate(0, 0);
            description         = testNode.ToString();
        }
Exemplo n.º 3
0
        /// <summary>
        /// Interprets an OSM-object and returns the correctponding geometry.
        /// </summary>
        /// <param name="simpleOsmGeo"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public virtual GeometryCollection Interpret(OsmGeo simpleOsmGeo, IDataSourceReadOnly data)
        {
            switch (simpleOsmGeo.Type)
            {
            case OsmGeoType.Node:
                return(this.Interpret(CompleteNode.CreateFrom(simpleOsmGeo as Node)));

            case OsmGeoType.Way:
                return(this.Interpret(CompleteWay.CreateFrom(simpleOsmGeo as Way, data)));

            case OsmGeoType.Relation:
                return(this.Interpret(CompleteRelation.CreateFrom(simpleOsmGeo as Relation, data)));
            }
            throw new ArgumentOutOfRangeException();
        }
Exemplo n.º 4
0
        /// <summary>
        /// Translates the given OSM objects into corresponding geometries.
        /// </summary>
        /// <param name="scene"></param>
        /// <param name="projection"></param>
        /// <param name="source"></param>
        /// <param name="osmGeo"></param>
        public virtual void Translate(Scene2D scene, IProjection projection, IDataSourceReadOnly source, OsmGeo osmGeo)
        {
            switch (osmGeo.Type)
            {
            case OsmGeoType.Node:
                this.Translate(scene, projection, CompleteNode.CreateFrom(osmGeo as Node));
                break;

            case OsmGeoType.Way:
                this.Translate(scene, projection, CompleteWay.CreateFrom(osmGeo as Way, source));
                break;

            case OsmGeoType.Relation:
                this.Translate(scene, projection, CompleteRelation.CreateFrom(osmGeo as Relation, source));
                break;
            }
        }
Exemplo n.º 5
0
 /// <summary>
 /// Compares the two complete objects.
 /// </summary>
 /// <param name="expected"></param>
 /// <param name="actual"></param>
 public static void CompareComplete(CompleteNode expected, CompleteNode actual)
 {
     if (expected == null)
     { // ok, if the value is also null.
         Assert.IsNull(actual);
     }
     else
     { // check and compare the value.
         Assert.IsNotNull(actual);
         Assert.AreEqual(expected.Id, actual.Id);
         Assert.AreEqual(expected.ChangeSetId, actual.ChangeSetId);
         Assert.AreEqual(expected.Coordinate, actual.Coordinate);
         Assert.AreEqual(expected.TimeStamp, actual.TimeStamp);
         Assert.AreEqual(expected.User, actual.User);
         Assert.AreEqual(expected.UserId, actual.UserId);
         Assert.AreEqual(expected.Version, actual.Version);
         Assert.AreEqual(expected.Visible, actual.Visible);
     }
 }
Exemplo n.º 6
0
 /// <summary>
 /// Compares the two complete objects.
 /// </summary>
 /// <param name="expected"></param>
 /// <param name="actual"></param>
 public static void CompareComplete(CompleteNode expected, CompleteNode actual)
 {
     if (expected == null)
     { // ok, if the value is also null.
         Assert.IsNull(actual);
     }
     else
     { // check and compare the value.
         Assert.IsNotNull(actual);
         Assert.AreEqual(expected.Id, actual.Id);
         Assert.AreEqual(expected.ChangeSetId, actual.ChangeSetId);
         Assert.AreEqual(expected.Coordinate, actual.Coordinate);
         Assert.AreEqual(expected.TimeStamp, actual.TimeStamp);
         Assert.AreEqual(expected.User, actual.User);
         Assert.AreEqual(expected.UserId, actual.UserId);
         Assert.AreEqual(expected.Version, actual.Version);
         Assert.AreEqual(expected.Visible, actual.Visible);
     }
 }
 /// <summary>
 /// Adds a new node.
 /// </summary>
 /// <param name="node"></param>
 public override void AddNode(CompleteNode node)
 {
     _mapCSSInterpreter.Translate(_scene, _projection, node);
 }
Exemplo n.º 8
0
 /// <summary>
 /// Adds a node to the target.
 /// </summary>
 /// <param name="node"></param>
 public abstract void AddNode(CompleteNode node);
Exemplo n.º 9
0
 /// <summary>
 /// Adds a new node.
 /// </summary>
 /// <param name="node"></param>
 public override void AddNode(CompleteNode node)
 {
     _mapCSSInterpreter.Translate(_scene, _projection, node);
 }
Exemplo n.º 10
0
        /// <summary>
        /// Builds the scene.
        /// </summary>
        /// <param name="map"></param>
        /// <param name="zoomFactor"></param>
        /// <param name="center"></param>
        /// <param name="view"></param>
        private void BuildScene(Map map, float zoomFactor, GeoCoordinate center, View2D view)
        {
            // get the indexed object at this zoom.
            HashSet <ArcId> interpretedObjects;

            if (!_interpretedObjects.TryGetValue((int)zoomFactor, out interpretedObjects))
            {
                interpretedObjects = new HashSet <ArcId> ();
                _interpretedObjects.Add((int)zoomFactor, interpretedObjects);
            }

            // build the boundingbox.
            var viewBox = view.OuterBox;
            var box     = new GeoCoordinateBox(map.Projection.ToGeoCoordinates(viewBox.Min [0], viewBox.Min [1]),
                                               map.Projection.ToGeoCoordinates(viewBox.Max [0], viewBox.Max [1]));

            foreach (var requestedBox in _requestedBoxes)
            {
                if (requestedBox.Contains(box))
                {
                    return;
                }
            }
            _requestedBoxes.Add(box);

            //// set the scene backcolor.
            //SimpleColor? color = _styleInterpreter.GetCanvasColor ();
            //_scene.BackColor = color.HasValue
            //                               ? color.Value.Value
            //                               : SimpleColor.FromArgb (0, 255, 255, 255).Value;

            // get data.
            foreach (var arc in _dataSource.GetArcs(box))
            {
                // translate each object into scene object.
                var arcId = new ArcId()
                {
                    Vertex1 = arc.Key,
                    Vertex2 = arc.Value.Key
                };
                if (!interpretedObjects.Contains(arcId))
                {
                    interpretedObjects.Add(arcId);

                    // create nodes.
                    float latitude, longitude;
                    _dataSource.GetVertex(arcId.Vertex1, out latitude, out longitude);
                    var node1 = CompleteNode.Create(arcId.Vertex1);
                    node1.Coordinate = new GeoCoordinate(latitude, longitude);
                    _dataSource.GetVertex(arcId.Vertex2, out latitude, out longitude);
                    var node2 = CompleteNode.Create(arcId.Vertex2);
                    node2.Coordinate = new GeoCoordinate(latitude, longitude);

                    // create way.
                    var way = CompleteWay.Create(-1);
                    if (arc.Value.Value.Forward)
                    {
                        way.Nodes.Add(node1);
                        way.Nodes.Add(node2);
                    }
                    else
                    {
                        way.Nodes.Add(node2);
                        way.Nodes.Add(node1);
                    }
                    way.Tags.AddOrReplace(_dataSource.TagsIndex.Get(arc.Value.Value.Tags));

                    _styleInterpreter.Translate(_scene, map.Projection, way);
                    interpretedObjects.Add(arcId);
                }
            }
        }
Exemplo n.º 11
0
        /// <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)
        {
            // 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);
                    }
                }
            }
        }
Exemplo n.º 12
0
        /// <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);
                    }
                }
            }
        }
Exemplo n.º 13
0
 /// <summary>
 /// Returns true if this way contains the given node.
 /// </summary>
 /// <param name="node"></param>
 /// <returns></returns>
 public bool HasNode(CompleteNode node)
 {
     return this.Nodes.Contains(node);
 }
        /// <summary>
        /// Moves to the next object.
        /// </summary>
        /// <returns></returns>
        public override bool MoveNext()
        {
            if (!_cachingDone)
            { // first seek & cache.
                this.Seek();
                this.CacheRelations();
                _cachingDone = true;
            }

            while (_simpleSource.MoveNext())
            { // there is data.
                OsmGeo currentSimple = _simpleSource.Current();

                if (currentSimple.Id == 198214128 || currentSimple.Id == 1014892489)
                {
                    System.Diagnostics.Debug.WriteLine("");
                }

                switch (currentSimple.Type)
                {
                case OsmGeoType.Node:
                    // create complete version.
                    _current = CompleteNode.CreateFrom(currentSimple as Node);
                    if (_nodesToInclude.Contains(currentSimple.Id.Value))
                    {     // node needs to be cached.
                        _dataCache.AddNode(currentSimple as Node);
                        _nodesToInclude.Remove(currentSimple.Id.Value);
                    }
                    break;

                case OsmGeoType.Way:
                    // create complete way.
                    _current = CompleteWay.CreateFrom(currentSimple as Way, _dataCache);

                    if (_waysToInclude.Contains(currentSimple.Id.Value))
                    {     // keep the way because it is needed later on.
                        _dataCache.AddWay(currentSimple as Way);
                        _waysToInclude.Remove(currentSimple.Id.Value);
                    }
                    else
                    {     // only report that the nodes have been used when the way can be let-go.
                        Way way = currentSimple as Way;
                        if (way.Nodes != null)
                        {     // report usage.
                            way.Nodes.ForEach(x => this.ReportNodeUsage(x));
                        }
                    }
                    break;

                case OsmGeoType.Relation:
                    // create complate relation.
                    _current = CompleteRelation.CreateFrom(currentSimple as Relation, _dataCache);

                    if (!_relationsToInclude.Contains(currentSimple.Id.Value))
                    {     // only report relation usage when the relation can be let go.
                        Relation relation = currentSimple as Relation;
                        if (relation.Members != null)
                        {
                            foreach (RelationMember member in relation.Members)
                            {
                                switch (member.MemberType.Value)
                                {
                                case OsmGeoType.Node:
                                    this.ReportNodeUsage(member.MemberId.Value);
                                    break;

                                case OsmGeoType.Way:
                                    this.ReportWayUsage(member.MemberId.Value);
                                    break;

                                case OsmGeoType.Relation:
                                    this.ReportRelationUsage(member.MemberId.Value);
                                    break;
                                }
                            }
                        }
                    }
                    break;
                }
                if (_current != null)
                { // only return complete objects.
                    return(true);
                }
            }
            return(false);
        }
Exemplo n.º 15
0
 /// <summary>
 /// Adds a node to the target.
 /// </summary>
 /// <param name="node"></param>
 public abstract void AddNode(CompleteNode node);
        public void Scene2DSimpleSerializeDeserializeTest()
        {
            // create the MapCSS image source.
            var imageSource = new MapCSSDictionaryImageSource();

            // load mapcss style interpreter.
            var mapCSSInterpreter = new MapCSSInterpreter(
                Assembly.GetExecutingAssembly().GetManifestResourceStream(
                    "OsmSharp.UI.Test.Unittests.Data.MapCSS.test.mapcss"),
                imageSource);

            // initialize the data source.
            var xmlSource = new XmlOsmStreamSource(
                Assembly.GetExecutingAssembly().GetManifestResourceStream(
                    "OsmSharp.UI.Test.Unittests.Data.test.osm"));
            IEnumerable <OsmGeo> dataSource = xmlSource;
            MemoryDataSource     source     = MemoryDataSource.CreateFrom(xmlSource);

            // get data.
            var scene            = new Scene2DSimple();
            var projection       = new WebMercator();
            GeoCoordinateBox box = null;

            foreach (var osmGeo in dataSource)
            {
                CompleteOsmGeo completeOsmGeo = null;
                switch (osmGeo.Type)
                {
                case OsmGeoType.Node:
                    completeOsmGeo = CompleteNode.CreateFrom(osmGeo as Node);
                    break;

                case OsmGeoType.Way:
                    completeOsmGeo = CompleteWay.CreateFrom(osmGeo as Way,
                                                            source);
                    break;

                case OsmGeoType.Relation:
                    completeOsmGeo = CompleteRelation.CreateFrom(osmGeo as Relation,
                                                                 source);
                    break;
                }

                // update box.
                if (completeOsmGeo != null)
                {
                    if (box == null)
                    {
                        box = completeOsmGeo.BoundingBox;
                    }
                    else if (completeOsmGeo.BoundingBox != null)
                    {
                        box = box + completeOsmGeo.BoundingBox;
                    }
                }

                // translate each object into scene object.
                mapCSSInterpreter.Translate(scene, projection, source, osmGeo as OsmGeo);
            }

            // create the stream.
            var stream = new MemoryStream();

            scene.Serialize(stream, false);

            // deserialize the stream.
            IScene2DPrimitivesSource sceneSource = Scene2DSimple.Deserialize(stream, false);

            if (box != null)
            {
                // query both and get the same results.
                int counter = 100;
                var rand    = new Random();
                while (counter > 0)
                {
                    var queryBox = new GeoCoordinateBox(
                        box.GenerateRandomIn(rand),
                        box.GenerateRandomIn(rand));
                    var    zoomFactor = (float)projection.ToZoomFactor(15);
                    View2D testView   = View2D.CreateFromBounds(
                        projection.LatitudeToY(queryBox.MaxLat),
                        projection.LongitudeToX(queryBox.MinLon),
                        projection.LatitudeToY(queryBox.MinLat),
                        projection.LongitudeToX(queryBox.MaxLon));
                    var testScene = new Scene2DSimple();
                    sceneSource.Get(testScene, testView, zoomFactor);

//                    var resultIndex = new HashSet<Scene2DPrimitive>(testScene.Get(testView, zoomFactor));
//                    var resultReference = new HashSet<Scene2DPrimitive>(scene.Get(testView, zoomFactor));

                    //Assert.AreEqual(resultReference.Count, resultIndex.Count);
                    //foreach (var data in resultIndex)
                    //{
                    //    Assert.IsTrue(resultReference.Contains(data));
                    //}
                    //foreach (var data in resultReference)
                    //{
                    //    Assert.IsTrue(resultIndex.Contains(data));
                    //}
                    counter--;
                }
            }
        }
Exemplo n.º 17
0
        /// <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);
                    }
                }
            }
        }