protected void HandlePolygon(JSONArray polygonCoordinates, IGeometryHandler handler) { handler.OnBeginPolygon(); foreach (var linearRingCoordinates in polygonCoordinates.Children) { handler.OnBeginLinearRing(); foreach (var pointCoordinates in linearRingCoordinates.Children) { HandlePoint(pointCoordinates.AsArray, handler); } handler.OnEndLinearRing(); } handler.OnEndPolygon(); }
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); }
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); }