public void CanProcessOneOuterNonClosed()
        {
            // ARRANGE
            var relation = new Relation()
            {
                Tags = new Dictionary <string, string>()
                {
                    { "type", "multipolygon" },
                    { "tag", "tags" }
                }.ToTags(),
                Members = new List <RelationMember>()
                {
                    CreateRelationWayMember("outer", new Vector2d(0, 0), new Vector2d(3, 5),
                                            new Vector2d(7, 3)),
                    CreateRelationWayMember("outer", new Vector2d(7, 3), new Vector2d(8, -1),
                                            new Vector2d(3, -4), new Vector2d(0, 0)),
                }
            };
            var areas = new List <Area>();

            // ACT
            MultipolygonProcessor.FillAreas(relation, areas);

            // ASSERT
            Assert.AreEqual(1, areas.Count);
            var area = areas.First();

            Assert.AreEqual(6, area.Points.Count);
            Assert.AreEqual(0, area.Holes.Count);
        }
        public void CanProcessMultiplyOuterAndMultiplyInnerArbitaryTypes()
        {
            // see fig.6 http://wiki.openstreetmap.org/wiki/Talk:Relation:multipolygon
            // accessed 22.11.2014

            // ARRANGE
            var relation = new Relation()
            {
                Tags = new Dictionary <string, string>()
                {
                    { "type", "multipolygon" },
                    { "tag", "tags" }
                }.ToTags(),
                Members = new List <RelationMember>()
                {
                    CreateRelationWayMember("outer", new Vector2d(1, 5), new Vector2d(8, 4)),
                    CreateRelationWayMember("outer", new Vector2d(8, 4), new Vector2d(9, -1)),
                    CreateRelationWayMember("outer", new Vector2d(9, -1), new Vector2d(8, -6), new Vector2d(2, -5)),
                    CreateRelationWayMember("outer", new Vector2d(2, -5), new Vector2d(0, -3), new Vector2d(1, 5)),

                    CreateRelationWayMember("inner", new Vector2d(2, 1), new Vector2d(3, 3), new Vector2d(6, 3)),
                    CreateRelationWayMember("inner", new Vector2d(6, 3), new Vector2d(4, 0), new Vector2d(2, 1)),
                    CreateRelationWayMember("inner", new Vector2d(1, -2), new Vector2d(3, -1)),
                    CreateRelationWayMember("inner", new Vector2d(3, -1), new Vector2d(4, -4)),
                    CreateRelationWayMember("inner", new Vector2d(4, -4), new Vector2d(1, -3)),
                    CreateRelationWayMember("inner", new Vector2d(1, -3), new Vector2d(1, -2)),
                    CreateRelationWayMember("inner", new Vector2d(6, -3), new Vector2d(7, -1),
                                            new Vector2d(8, -4), new Vector2d(6, -3)),

                    CreateRelationWayMember("outer", new Vector2d(10, 5), new Vector2d(14, 5)),
                    CreateRelationWayMember("outer", new Vector2d(14, 5), new Vector2d(14, -1)),
                    CreateRelationWayMember("outer", new Vector2d(14, -1), new Vector2d(10, -1)),
                    CreateRelationWayMember("outer", new Vector2d(10, -1), new Vector2d(10, 5)),

                    CreateRelationWayMember("inner", new Vector2d(11, 4), new Vector2d(13, 4)),
                    CreateRelationWayMember("inner", new Vector2d(13, 4), new Vector2d(13, 0), new Vector2d(11, 0)),
                    CreateRelationWayMember("inner", new Vector2d(11, 0), new Vector2d(12, 2)),
                    CreateRelationWayMember("inner", new Vector2d(12, 2), new Vector2d(11, 4)),

                    CreateRelationWayMember("outer", new Vector2d(10, -3), new Vector2d(14, -3), new Vector2d(14, -6),
                                            new Vector2d(10, -6), new Vector2d(10, -3)),
                }
            };
            var areas = new List <Area>();

            // ACT
            MultipolygonProcessor.FillAreas(relation, areas);

            // ASSERT
            Assert.AreEqual(3, areas.Count);
            Assert.AreEqual(3, areas.Single(a => a.Points.Count == 7).Holes.Count);
            Assert.AreEqual(1, areas.Single(a => a.Points.Count == 5 && a.Points[0].Longitude > -2).Holes.Count); // select higher rectangle
            Assert.AreEqual(0, areas.Single(a => a.Points.Count == 5 && a.Points[0].Longitude < -2).Holes.Count); // select lower rectangle
        }
        /// <inheritdoc />
        public override void VisitRelation(Entities.Relation relation)
        {
            string actualValue;
            var    modelRelation = new Relation()
            {
                Id   = relation.Id,
                Tags = relation.Tags,
            };

            if (relation.Tags != null && relation.Tags.TryGetValue("type", out actualValue) &&
                actualValue == "multipolygon")
            {
                // TODO use object pool
                modelRelation.Areas = new List <Area>(relation.Members.Count);
                MultipolygonProcessor.FillAreas(relation, modelRelation.Areas);
            }
            ModelLoader.LoadRelation(Tile, modelRelation);
        }