Example #1
0
        public override bool HandleGeometry(IGeometryHandler handler)
        {
            var decoder = new GeometryDecoder(feature, layer);

            // From https://github.com/mapbox/vector-tile-spec/tree/master/2.1
            //
            // The POINT geometry type encodes a point or multipoint geometry. The geometry command sequence for a point
            // geometry MUST consist of a single MoveTo command with a command count greater than 0.
            //
            // The LINESTRING geometry type encodes a linestring or multilinestring geometry. The geometry command sequence
            // for a linestring geometry MUST consist of one or more repetitions of the following sequence:
            //   1. A MoveTo command with a command count of 1
            //   2. A LineTo command with a command count greater than 0
            //
            // The POLYGON geometry type encodes a polygon or multipolygon geometry, each polygon consisting of exactly one
            // exterior ring that contains zero or more interior rings. The geometry command sequence for a polygon consists
            // of one or more repetitions of the following sequence:
            //   1. An ExteriorRing
            //   2. Zero or more InteriorRings
            // Each ExteriorRing and InteriorRing MUST consist of the following sequence:
            //   1. A MoveTo command with a command count of 1
            //   2. A LineTo command with a command count greater than 1
            //   3. A ClosePath command

            switch (feature.Type)
            {
            case PbfGeomType.Point:
                while (decoder.HasData())
                {
                    decoder.AdvanceCommand();
                    Debug.Assert(decoder.Command == CommandType.MoveTo && decoder.Repeat > 0);
                    for (int i = decoder.Repeat; i > 0; i--)
                    {
                        handler.OnPoint(decoder.AdvanceCursor());
                    }
                }
                break;

            case PbfGeomType.LineString:
                while (decoder.HasData())
                {
                    handler.OnBeginLineString();
                    decoder.AdvanceCommand();
                    Debug.Assert(decoder.Command == CommandType.MoveTo && decoder.Repeat == 1);
                    handler.OnPoint(decoder.AdvanceCursor());
                    decoder.AdvanceCommand();
                    Debug.Assert(decoder.Command == CommandType.LineTo && decoder.Repeat > 0);
                    for (int i = decoder.Repeat; i > 0; i--)
                    {
                        handler.OnPoint(decoder.AdvanceCursor());
                    }
                    handler.OnEndLineString();
                }
                break;

            case PbfGeomType.Polygon:
                // Create temporary storage to hold rings until we determine whether they are interior or exterior.
                var ring             = new List <Point>();
                var isPolygonStarted = false;
                while (decoder.HasData())
                {
                    // Read out the coordinates of the next ring.
                    decoder.AdvanceCommand();
                    Debug.Assert(decoder.Command == CommandType.MoveTo && decoder.Repeat == 1);
                    ring.Add(decoder.AdvanceCursor());
                    decoder.AdvanceCommand();
                    for (int i = decoder.Repeat; i > 0; i--)
                    {
                        ring.Add(decoder.AdvanceCursor());
                    }
                    ring.Add(ring.First());
                    decoder.AdvanceCommand();
                    Debug.Assert(decoder.Command == CommandType.ClosePath && decoder.Repeat == 1);
                    // If ring is exterior, end the current polygon, start a new one, add ring to new polygon.
                    // If ring is interior, add the ring to current polygon.
                    var area = SignedArea(ring);
                    if (area > 0)
                    {
                        if (isPolygonStarted)
                        {
                            handler.OnEndPolygon();
                        }
                        handler.OnBeginPolygon();
                        isPolygonStarted = true;
                    }
                    handler.OnBeginLinearRing();
                    foreach (var point in ring)
                    {
                        handler.OnPoint(point);
                    }
                    handler.OnEndLinearRing();
                    ring.Clear();
                }
                handler.OnEndPolygon();
                break;

            case PbfGeomType.Unknown:
                return(false);
            }
            return(true);
        }
Example #2
0
        public override bool HandleGeometry(IGeometryHandler handler)
        {
            var decoder = new GeometryDecoder(feature, layer);

            // From https://github.com/mapbox/vector-tile-spec/tree/master/2.1
            //
            // The POINT geometry type encodes a point or multipoint geometry. The geometry command sequence for a point
            // geometry MUST consist of a single MoveTo command with a command count greater than 0.
            //
            // The LINESTRING geometry type encodes a linestring or multilinestring geometry. The geometry command sequence
            // for a linestring geometry MUST consist of one or more repetitions of the following sequence:
            //   1. A MoveTo command with a command count of 1
            //   2. A LineTo command with a command count greater than 0
            //
            // The POLYGON geometry type encodes a polygon or multipolygon geometry, each polygon consisting of exactly one
            // exterior ring that contains zero or more interior rings. The geometry command sequence for a polygon consists
            // of one or more repetitions of the following sequence:
            //   1. An ExteriorRing
            //   2. Zero or more InteriorRings
            // Each ExteriorRing and InteriorRing MUST consist of the following sequence:
            //   1. A MoveTo command with a command count of 1
            //   2. A LineTo command with a command count greater than 1
            //   3. A ClosePath command

            switch (feature.Type)
            {
            case PbfGeomType.Point:
                if (decoder.AdvanceCommand() && decoder.Command == CommandType.MoveTo)
                {
                    for (int i = 0; i < decoder.Repeat; i++)
                    {
                        decoder.AdvanceCursor();
                        handler.OnPoint(decoder.CurrentPoint());
                    }
                }
                break;

            case PbfGeomType.LineString:
                while (decoder.AdvanceCommand() && (decoder.Command == CommandType.MoveTo && decoder.Repeat == 1))
                {
                    decoder.AdvanceCursor();
                    if (decoder.AdvanceCommand() && (decoder.Command == CommandType.LineTo && decoder.Repeat > 0))
                    {
                        handler.OnBeginLineString();
                        handler.OnPoint(decoder.CurrentPoint());
                        for (int i = 0; i < decoder.Repeat; i++)
                        {
                            decoder.AdvanceCursor();
                            handler.OnPoint(decoder.CurrentPoint());
                        }
                        handler.OnEndLineString();
                    }
                }
                break;

            case PbfGeomType.Polygon:
                while (decoder.AdvanceCommand() && (decoder.Command == CommandType.MoveTo && decoder.Repeat == 1))
                {
                    handler.OnBeginPolygon();
                    decoder.AdvanceCursor();
                    if (decoder.AdvanceCommand() && (decoder.Command == CommandType.LineTo && decoder.Repeat > 0))
                    {
                        handler.OnBeginLinearRing();
                        var start = decoder.CurrentPoint();
                        handler.OnPoint(start);
                        for (int i = 0; i < decoder.Repeat; i++)
                        {
                            decoder.AdvanceCursor();
                            handler.OnPoint(decoder.CurrentPoint());
                        }
                        handler.OnPoint(start);
                        handler.OnEndLinearRing();
                    }
                    if (decoder.AdvanceCommand() && decoder.Command == CommandType.ClosePath)
                    {
                        // We should assert that this condition holds.
                    }
                    handler.OnEndPolygon();
                }
                break;

            case PbfGeomType.Unknown:
                break;
            }
            return(true);
        }