├── .gitignore
├── .gitmodules
├── .travis.yml
├── LICENSE
├── Mapbox.VectorTile.nuspec
├── README.md
├── VectorTileCs.sln
├── VectorTileCsPortable.sln
├── appveyor.yml
└── src
├── AssemblyInfoVersion.cs
├── Bench
├── Bench.csproj
├── Program.cs
├── Properties
│ └── AssemblyInfo.cs
└── app.config
├── DemoConsoleApp
├── App.config
├── DemoConsoleApp.csproj
├── Properties
│ └── AssemblyInfo.cs
└── program.cs
├── ExtensionMethods
├── Enums.cs
├── ExtensionMethods.csproj
├── ExtensionMethodsPortable.csproj
├── Properties
│ └── AssemblyInfo.cs
├── VectorTile.cs
└── VectorTileFeature.cs
├── Geometry
├── DecodeGeometry.cs
├── Geometry.cs
├── Geometry.csproj
├── GeometryPortable.csproj
├── Properties
│ └── AssemblyInfo.cs
├── Util.cs
└── clipper.cs
├── PbfReader
├── Constants.cs
├── PbfReader.cs
├── PbfReader.csproj
├── PbfReaderPortable.csproj
└── Properties
│ └── AssemblyInfo.cs
├── VectorTileReader
├── Properties
│ └── AssemblyInfo.cs
├── VectorTile.cs
├── VectorTileFeature.cs
├── VectorTileLayer.cs
├── VectorTileReader.cs
├── VectorTileReader.csproj
└── VectorTileReaderPortable.csproj
├── VectorTiles.Tests
├── Properties
│ └── AssemblyInfo.cs
├── TestGeometry.cs
├── TestInvalidMvtInBulk.cs
├── TestMvtInBulk.cs
├── TestMvtSingle.cs
├── TestPbfReader.cs
├── VectorTiles.Tests.csproj
└── packages.config
└── VerifyNetFrameworkVersion
├── App.config
├── Program.cs
├── Properties
└── AssemblyInfo.cs
└── VerifyNetFrameworkVersion.csproj
/.gitignore:
--------------------------------------------------------------------------------
1 | # Autosave files
2 | *~
3 |
4 | TestResult.xml
5 | openCoverCoverage.xml
6 |
7 | # build
8 | [Oo]bj/
9 | [Bb]in/
10 | packages/
11 | TestResults/
12 | StyleCop.Cache
13 | nuget.exe
14 | .vscode/
15 | .vs/
16 | tools/
17 |
18 | # globs
19 | Makefile.in
20 | *.DS_Store
21 | *.sln.cache
22 | *.suo
23 | *.cache
24 | *.pidb
25 | *.userprefs
26 | *.usertasks
27 | config.log
28 | config.make
29 | config.status
30 | aclocal.m4
31 | install-sh
32 | autom4te.cache/
33 | *.user
34 | *.tar.gz
35 | tarballs/
36 | test-results/
37 | Thumbs.db
38 |
39 | # Mac bundle stuff
40 | *.dmg
41 | *.app
42 |
43 | # resharper
44 | *_Resharper.*
45 | *.Resharper
46 |
47 | # dotCover
48 | *.dotCover
49 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "test/mvt-fixtures"]
2 | path = test/mvt-fixtures
3 | url = https://github.com/mapbox/mvt-fixtures.git
4 | [submodule "bench/mvt-bench-fixtures"]
5 | path = bench/mvt-bench-fixtures
6 | url = https://github.com/mapbox/mvt-bench-fixtures.git
7 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | # https://docs.travis-ci.com/user/languages/csharp/
2 |
3 | language: csharp
4 | solution: VectorTileCs.sln
5 |
6 | matrix:
7 | include:
8 | - os: linux
9 | sudo: false
10 | mono: latest
11 |
12 | install:
13 | - nuget restore VectorTileCs.sln
14 | - nuget install NUnit.ConsoleRunner -Version 3.5.0 -OutputDirectory testrunner
15 |
16 | script:
17 | - xbuild /p:Configuration=Release VectorTileCs.sln
18 | - mono ./testrunner/NUnit.ConsoleRunner.3.5.0/tools/nunit3-console.exe ./bin/VectorTiles.Tests.dll
19 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | BSD 3-Clause License
2 |
3 | Copyright (c) 2017, Mapbox
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | * Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 |
12 | * Redistributions in binary form must reproduce the above copyright notice,
13 | this list of conditions and the following disclaimer in the documentation
14 | and/or other materials provided with the distribution.
15 |
16 | * Neither the name of the copyright holder nor the names of its
17 | contributors may be used to endorse or promote products derived from
18 | this software without specific prior written permission.
19 |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
--------------------------------------------------------------------------------
/Mapbox.VectorTile.nuspec:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Mapbox.VectorTile
5 | 1.0.4-alpha2
6 | Mapbox
7 | Mapbox
8 | https://github.com/mapbox/vector-tile-cs
9 | https://github.com/mapbox/vector-tile-cs
10 | false
11 | Mapbox VectorTileReader CSharp
12 | Republish of 1.0.4-alpha2, nupkg seem to have been corrupted
13 | Copyright 2017
14 | vector tiles c# mapbox
15 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # vector-tile-cs
2 |
3 | C# library for decoding [`Mapbox Vector Tiles @ v2.x`](https://www.mapbox.com/vector-tiles/) ([vector tile specification](https://github.com/mapbox/vector-tile-spec)).
4 |
5 | _**Decoding tiles created according to `Mapbox Vector Tile Specification @ v1.x` is not supported!**_
6 |
7 | Available as nuget package: [](https://www.nuget.org/packages/Mapbox.VectorTile)
8 |
9 | Vector tile parsers in other languages:
10 | * JavaScript: https://github.com/mapbox/vector-tile-js
11 | * C++: https://github.com/mapbox/vector-tile
12 |
13 | # Build status
14 | master branch:
15 | * Travis: [](https://travis-ci.com/mapbox/vector-tile-cs)
16 | * AppVeyor: [](https://ci.appveyor.com/project/Mapbox/vector-tile-cs/branch/master)
17 | * Coveralls: [](https://coveralls.io/github/mapbox/vector-tile-cs?branch=master)
18 |
19 | # Depends
20 |
21 | Native C# implementation - no dependencies.
22 | `NUnit` and `NUnit3TestAdapter` for running tests - will get restored automatically when building the solution.
23 |
24 | #Example
25 |
26 | ```c#
27 | byte[] data = //raw unzipped vectortile
28 | VectorTile vt = new VectorTile(data);
29 | //get available layer names
30 | foreach(var lyrName in vt.LayerNames()) {
31 | //get layer by name
32 | VectorTileLayer lyr = vt.GetLayer(lyrName);
33 | //iterate through all features
34 | for(int i = 0; i < lyr.FeatureCount(); i++) {
35 | Debug.WriteLine("{0} lyr:{1} feat:{2}", fileName, lyr.Name, i);
36 | //get the feature
37 | VectorTileFeature feat = lyr.GetFeature(i);
38 | //get feature properties
39 | var properties = feat.GetProperties();
40 | foreach(var prop in properties) {
41 | Debug.WriteLine("key:{0} value:{1}", prop.Key, prop.Value);
42 | }
43 | //or get property value if you already know the key
44 | //object value = feat.GetValue(prop.Key);
45 | //iterate through all geometry parts
46 | //requesting coordinates as ints
47 | foreach(var part in feat.Geometry()) {
48 | //iterate through coordinates of the part
49 | foreach(var geom in part) {
50 | Debug.WriteLine("geom.X:{0} geom.Y:{1}", geom.X, geom.Y);
51 | }
52 | }
53 | }
54 | }
55 |
56 | ```
57 |
--------------------------------------------------------------------------------
/VectorTileCs.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.25420.1
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VectorTileReader", "src\VectorTileReader\VectorTileReader.csproj", "{4656B308-1492-4A22-A73E-06BF6AA858F2}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PbfReader", "src\PbfReader\PbfReader.csproj", "{4BCE42EE-C33F-4FA4-BFDD-86F3D45C647C}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DemoConsoleApp", "src\DemoConsoleApp\DemoConsoleApp.csproj", "{D01BA6CB-9A2B-4AA5-95E1-085D9B569309}"
11 | EndProject
12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Geometry", "src\Geometry\Geometry.csproj", "{F0967389-29C8-4D50-B397-9BB698F13ED6}"
13 | EndProject
14 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VectorTiles.Tests", "src\VectorTiles.Tests\VectorTiles.Tests.csproj", "{067456C0-086C-46A8-B37F-1405717B7BFC}"
15 | EndProject
16 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bench", "src\Bench\Bench.csproj", "{5FA56C72-348A-4B52-980C-EA8287E66422}"
17 | EndProject
18 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExtensionMethods", "src\ExtensionMethods\ExtensionMethods.csproj", "{55503403-0083-4ED8-B618-F8377610B225}"
19 | EndProject
20 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VerifyNetFrameworkVersion", "src\VerifyNetFrameworkVersion\VerifyNetFrameworkVersion.csproj", "{1717CD14-720F-4373-81E1-3505FCB2CF03}"
21 | EndProject
22 | Global
23 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
24 | Debug|Any CPU = Debug|Any CPU
25 | Net20Debug|Any CPU = Net20Debug|Any CPU
26 | Net35Debug|Any CPU = Net35Debug|Any CPU
27 | Net462Debug|Any CPU = Net462Debug|Any CPU
28 | Release|Any CPU = Release|Any CPU
29 | EndGlobalSection
30 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
31 | {4656B308-1492-4A22-A73E-06BF6AA858F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
32 | {4656B308-1492-4A22-A73E-06BF6AA858F2}.Debug|Any CPU.Build.0 = Debug|Any CPU
33 | {4656B308-1492-4A22-A73E-06BF6AA858F2}.Net20Debug|Any CPU.ActiveCfg = Net20Debug|Any CPU
34 | {4656B308-1492-4A22-A73E-06BF6AA858F2}.Net20Debug|Any CPU.Build.0 = Net20Debug|Any CPU
35 | {4656B308-1492-4A22-A73E-06BF6AA858F2}.Net35Debug|Any CPU.ActiveCfg = Net35Debug|Any CPU
36 | {4656B308-1492-4A22-A73E-06BF6AA858F2}.Net35Debug|Any CPU.Build.0 = Net35Debug|Any CPU
37 | {4656B308-1492-4A22-A73E-06BF6AA858F2}.Net462Debug|Any CPU.ActiveCfg = Net462Debug|Any CPU
38 | {4656B308-1492-4A22-A73E-06BF6AA858F2}.Net462Debug|Any CPU.Build.0 = Net462Debug|Any CPU
39 | {4656B308-1492-4A22-A73E-06BF6AA858F2}.Release|Any CPU.ActiveCfg = Release|Any CPU
40 | {4656B308-1492-4A22-A73E-06BF6AA858F2}.Release|Any CPU.Build.0 = Release|Any CPU
41 | {4BCE42EE-C33F-4FA4-BFDD-86F3D45C647C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
42 | {4BCE42EE-C33F-4FA4-BFDD-86F3D45C647C}.Debug|Any CPU.Build.0 = Debug|Any CPU
43 | {4BCE42EE-C33F-4FA4-BFDD-86F3D45C647C}.Net20Debug|Any CPU.ActiveCfg = Net20Debug|Any CPU
44 | {4BCE42EE-C33F-4FA4-BFDD-86F3D45C647C}.Net20Debug|Any CPU.Build.0 = Net20Debug|Any CPU
45 | {4BCE42EE-C33F-4FA4-BFDD-86F3D45C647C}.Net35Debug|Any CPU.ActiveCfg = Net35Debug|Any CPU
46 | {4BCE42EE-C33F-4FA4-BFDD-86F3D45C647C}.Net35Debug|Any CPU.Build.0 = Net35Debug|Any CPU
47 | {4BCE42EE-C33F-4FA4-BFDD-86F3D45C647C}.Net462Debug|Any CPU.ActiveCfg = Net462Debug|Any CPU
48 | {4BCE42EE-C33F-4FA4-BFDD-86F3D45C647C}.Net462Debug|Any CPU.Build.0 = Net462Debug|Any CPU
49 | {4BCE42EE-C33F-4FA4-BFDD-86F3D45C647C}.Release|Any CPU.ActiveCfg = Release|Any CPU
50 | {4BCE42EE-C33F-4FA4-BFDD-86F3D45C647C}.Release|Any CPU.Build.0 = Release|Any CPU
51 | {D01BA6CB-9A2B-4AA5-95E1-085D9B569309}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
52 | {D01BA6CB-9A2B-4AA5-95E1-085D9B569309}.Debug|Any CPU.Build.0 = Debug|Any CPU
53 | {D01BA6CB-9A2B-4AA5-95E1-085D9B569309}.Net20Debug|Any CPU.ActiveCfg = Net20Debug|Any CPU
54 | {D01BA6CB-9A2B-4AA5-95E1-085D9B569309}.Net20Debug|Any CPU.Build.0 = Net20Debug|Any CPU
55 | {D01BA6CB-9A2B-4AA5-95E1-085D9B569309}.Net35Debug|Any CPU.ActiveCfg = Net35Debug|Any CPU
56 | {D01BA6CB-9A2B-4AA5-95E1-085D9B569309}.Net35Debug|Any CPU.Build.0 = Net35Debug|Any CPU
57 | {D01BA6CB-9A2B-4AA5-95E1-085D9B569309}.Net462Debug|Any CPU.ActiveCfg = Net462Debug|Any CPU
58 | {D01BA6CB-9A2B-4AA5-95E1-085D9B569309}.Net462Debug|Any CPU.Build.0 = Net462Debug|Any CPU
59 | {D01BA6CB-9A2B-4AA5-95E1-085D9B569309}.Release|Any CPU.ActiveCfg = Release|Any CPU
60 | {D01BA6CB-9A2B-4AA5-95E1-085D9B569309}.Release|Any CPU.Build.0 = Release|Any CPU
61 | {F0967389-29C8-4D50-B397-9BB698F13ED6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
62 | {F0967389-29C8-4D50-B397-9BB698F13ED6}.Debug|Any CPU.Build.0 = Debug|Any CPU
63 | {F0967389-29C8-4D50-B397-9BB698F13ED6}.Net20Debug|Any CPU.ActiveCfg = Net20Debug|Any CPU
64 | {F0967389-29C8-4D50-B397-9BB698F13ED6}.Net20Debug|Any CPU.Build.0 = Net20Debug|Any CPU
65 | {F0967389-29C8-4D50-B397-9BB698F13ED6}.Net35Debug|Any CPU.ActiveCfg = Net35Debug|Any CPU
66 | {F0967389-29C8-4D50-B397-9BB698F13ED6}.Net35Debug|Any CPU.Build.0 = Net35Debug|Any CPU
67 | {F0967389-29C8-4D50-B397-9BB698F13ED6}.Net462Debug|Any CPU.ActiveCfg = Net462Debug|Any CPU
68 | {F0967389-29C8-4D50-B397-9BB698F13ED6}.Net462Debug|Any CPU.Build.0 = Net462Debug|Any CPU
69 | {F0967389-29C8-4D50-B397-9BB698F13ED6}.Release|Any CPU.ActiveCfg = Release|Any CPU
70 | {F0967389-29C8-4D50-B397-9BB698F13ED6}.Release|Any CPU.Build.0 = Release|Any CPU
71 | {067456C0-086C-46A8-B37F-1405717B7BFC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
72 | {067456C0-086C-46A8-B37F-1405717B7BFC}.Debug|Any CPU.Build.0 = Debug|Any CPU
73 | {067456C0-086C-46A8-B37F-1405717B7BFC}.Net20Debug|Any CPU.ActiveCfg = Net20Debug|Any CPU
74 | {067456C0-086C-46A8-B37F-1405717B7BFC}.Net20Debug|Any CPU.Build.0 = Net20Debug|Any CPU
75 | {067456C0-086C-46A8-B37F-1405717B7BFC}.Net35Debug|Any CPU.ActiveCfg = Net35Debug|Any CPU
76 | {067456C0-086C-46A8-B37F-1405717B7BFC}.Net35Debug|Any CPU.Build.0 = Net35Debug|Any CPU
77 | {067456C0-086C-46A8-B37F-1405717B7BFC}.Net462Debug|Any CPU.ActiveCfg = Net462Debug|Any CPU
78 | {067456C0-086C-46A8-B37F-1405717B7BFC}.Net462Debug|Any CPU.Build.0 = Net462Debug|Any CPU
79 | {067456C0-086C-46A8-B37F-1405717B7BFC}.Release|Any CPU.ActiveCfg = Release|Any CPU
80 | {067456C0-086C-46A8-B37F-1405717B7BFC}.Release|Any CPU.Build.0 = Release|Any CPU
81 | {5FA56C72-348A-4B52-980C-EA8287E66422}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
82 | {5FA56C72-348A-4B52-980C-EA8287E66422}.Debug|Any CPU.Build.0 = Debug|Any CPU
83 | {5FA56C72-348A-4B52-980C-EA8287E66422}.Net20Debug|Any CPU.ActiveCfg = Net20Debug|Any CPU
84 | {5FA56C72-348A-4B52-980C-EA8287E66422}.Net20Debug|Any CPU.Build.0 = Net20Debug|Any CPU
85 | {5FA56C72-348A-4B52-980C-EA8287E66422}.Net35Debug|Any CPU.ActiveCfg = Net35Debug|Any CPU
86 | {5FA56C72-348A-4B52-980C-EA8287E66422}.Net35Debug|Any CPU.Build.0 = Net35Debug|Any CPU
87 | {5FA56C72-348A-4B52-980C-EA8287E66422}.Net462Debug|Any CPU.ActiveCfg = Net462Debug|Any CPU
88 | {5FA56C72-348A-4B52-980C-EA8287E66422}.Net462Debug|Any CPU.Build.0 = Net462Debug|Any CPU
89 | {5FA56C72-348A-4B52-980C-EA8287E66422}.Release|Any CPU.ActiveCfg = Release|Any CPU
90 | {5FA56C72-348A-4B52-980C-EA8287E66422}.Release|Any CPU.Build.0 = Release|Any CPU
91 | {55503403-0083-4ED8-B618-F8377610B225}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
92 | {55503403-0083-4ED8-B618-F8377610B225}.Debug|Any CPU.Build.0 = Debug|Any CPU
93 | {55503403-0083-4ED8-B618-F8377610B225}.Net20Debug|Any CPU.ActiveCfg = Net20Debug|Any CPU
94 | {55503403-0083-4ED8-B618-F8377610B225}.Net20Debug|Any CPU.Build.0 = Net20Debug|Any CPU
95 | {55503403-0083-4ED8-B618-F8377610B225}.Net35Debug|Any CPU.ActiveCfg = Net35Debug|Any CPU
96 | {55503403-0083-4ED8-B618-F8377610B225}.Net35Debug|Any CPU.Build.0 = Net35Debug|Any CPU
97 | {55503403-0083-4ED8-B618-F8377610B225}.Net462Debug|Any CPU.ActiveCfg = Net462Debug|Any CPU
98 | {55503403-0083-4ED8-B618-F8377610B225}.Net462Debug|Any CPU.Build.0 = Net462Debug|Any CPU
99 | {55503403-0083-4ED8-B618-F8377610B225}.Release|Any CPU.ActiveCfg = Release|Any CPU
100 | {55503403-0083-4ED8-B618-F8377610B225}.Release|Any CPU.Build.0 = Release|Any CPU
101 | {1717CD14-720F-4373-81E1-3505FCB2CF03}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
102 | {1717CD14-720F-4373-81E1-3505FCB2CF03}.Debug|Any CPU.Build.0 = Debug|Any CPU
103 | {1717CD14-720F-4373-81E1-3505FCB2CF03}.Net20Debug|Any CPU.ActiveCfg = Net20Debug|Any CPU
104 | {1717CD14-720F-4373-81E1-3505FCB2CF03}.Net20Debug|Any CPU.Build.0 = Net20Debug|Any CPU
105 | {1717CD14-720F-4373-81E1-3505FCB2CF03}.Net35Debug|Any CPU.ActiveCfg = Net35Debug|Any CPU
106 | {1717CD14-720F-4373-81E1-3505FCB2CF03}.Net35Debug|Any CPU.Build.0 = Net35Debug|Any CPU
107 | {1717CD14-720F-4373-81E1-3505FCB2CF03}.Net462Debug|Any CPU.ActiveCfg = Net462Debug|Any CPU
108 | {1717CD14-720F-4373-81E1-3505FCB2CF03}.Net462Debug|Any CPU.Build.0 = Net462Debug|Any CPU
109 | {1717CD14-720F-4373-81E1-3505FCB2CF03}.Release|Any CPU.ActiveCfg = Release|Any CPU
110 | {1717CD14-720F-4373-81E1-3505FCB2CF03}.Release|Any CPU.Build.0 = Release|Any CPU
111 | EndGlobalSection
112 | GlobalSection(SolutionProperties) = preSolution
113 | HideSolutionNode = FALSE
114 | EndGlobalSection
115 | EndGlobal
116 |
--------------------------------------------------------------------------------
/VectorTileCsPortable.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.25420.1
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PbfReaderPortable", "src\PbfReader\PbfReaderPortable.csproj", "{E3ED95C9-42D9-4480-90E5-87F4FE60B8E2}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GeometryPortable", "src\Geometry\GeometryPortable.csproj", "{B6044F02-10A3-4637-962E-8B2F882DCD59}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VectorTileReaderPortable", "src\VectorTileReader\VectorTileReaderPortable.csproj", "{88F3D60F-3C95-4E14-9731-622306630F4B}"
11 | EndProject
12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExtensionMethodsPortable", "src\ExtensionMethods\ExtensionMethodsPortable.csproj", "{826340DD-E375-4D1B-878C-FF67EAC7E0B7}"
13 | EndProject
14 | Global
15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
16 | Debug|Any CPU = Debug|Any CPU
17 | Debug|ARM = Debug|ARM
18 | Debug|x64 = Debug|x64
19 | Debug|x86 = Debug|x86
20 | Release|Any CPU = Release|Any CPU
21 | Release|ARM = Release|ARM
22 | Release|x64 = Release|x64
23 | Release|x86 = Release|x86
24 | EndGlobalSection
25 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
26 | {E3ED95C9-42D9-4480-90E5-87F4FE60B8E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
27 | {E3ED95C9-42D9-4480-90E5-87F4FE60B8E2}.Debug|Any CPU.Build.0 = Debug|Any CPU
28 | {E3ED95C9-42D9-4480-90E5-87F4FE60B8E2}.Debug|ARM.ActiveCfg = Debug|Any CPU
29 | {E3ED95C9-42D9-4480-90E5-87F4FE60B8E2}.Debug|ARM.Build.0 = Debug|Any CPU
30 | {E3ED95C9-42D9-4480-90E5-87F4FE60B8E2}.Debug|x64.ActiveCfg = Debug|Any CPU
31 | {E3ED95C9-42D9-4480-90E5-87F4FE60B8E2}.Debug|x64.Build.0 = Debug|Any CPU
32 | {E3ED95C9-42D9-4480-90E5-87F4FE60B8E2}.Debug|x86.ActiveCfg = Debug|Any CPU
33 | {E3ED95C9-42D9-4480-90E5-87F4FE60B8E2}.Debug|x86.Build.0 = Debug|Any CPU
34 | {E3ED95C9-42D9-4480-90E5-87F4FE60B8E2}.Release|Any CPU.ActiveCfg = Release|Any CPU
35 | {E3ED95C9-42D9-4480-90E5-87F4FE60B8E2}.Release|Any CPU.Build.0 = Release|Any CPU
36 | {E3ED95C9-42D9-4480-90E5-87F4FE60B8E2}.Release|ARM.ActiveCfg = Release|Any CPU
37 | {E3ED95C9-42D9-4480-90E5-87F4FE60B8E2}.Release|ARM.Build.0 = Release|Any CPU
38 | {E3ED95C9-42D9-4480-90E5-87F4FE60B8E2}.Release|x64.ActiveCfg = Release|Any CPU
39 | {E3ED95C9-42D9-4480-90E5-87F4FE60B8E2}.Release|x64.Build.0 = Release|Any CPU
40 | {E3ED95C9-42D9-4480-90E5-87F4FE60B8E2}.Release|x86.ActiveCfg = Release|Any CPU
41 | {E3ED95C9-42D9-4480-90E5-87F4FE60B8E2}.Release|x86.Build.0 = Release|Any CPU
42 | {B6044F02-10A3-4637-962E-8B2F882DCD59}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
43 | {B6044F02-10A3-4637-962E-8B2F882DCD59}.Debug|Any CPU.Build.0 = Debug|Any CPU
44 | {B6044F02-10A3-4637-962E-8B2F882DCD59}.Debug|ARM.ActiveCfg = Debug|Any CPU
45 | {B6044F02-10A3-4637-962E-8B2F882DCD59}.Debug|ARM.Build.0 = Debug|Any CPU
46 | {B6044F02-10A3-4637-962E-8B2F882DCD59}.Debug|x64.ActiveCfg = Debug|Any CPU
47 | {B6044F02-10A3-4637-962E-8B2F882DCD59}.Debug|x64.Build.0 = Debug|Any CPU
48 | {B6044F02-10A3-4637-962E-8B2F882DCD59}.Debug|x86.ActiveCfg = Debug|Any CPU
49 | {B6044F02-10A3-4637-962E-8B2F882DCD59}.Debug|x86.Build.0 = Debug|Any CPU
50 | {B6044F02-10A3-4637-962E-8B2F882DCD59}.Release|Any CPU.ActiveCfg = Release|Any CPU
51 | {B6044F02-10A3-4637-962E-8B2F882DCD59}.Release|Any CPU.Build.0 = Release|Any CPU
52 | {B6044F02-10A3-4637-962E-8B2F882DCD59}.Release|ARM.ActiveCfg = Release|Any CPU
53 | {B6044F02-10A3-4637-962E-8B2F882DCD59}.Release|ARM.Build.0 = Release|Any CPU
54 | {B6044F02-10A3-4637-962E-8B2F882DCD59}.Release|x64.ActiveCfg = Release|Any CPU
55 | {B6044F02-10A3-4637-962E-8B2F882DCD59}.Release|x64.Build.0 = Release|Any CPU
56 | {B6044F02-10A3-4637-962E-8B2F882DCD59}.Release|x86.ActiveCfg = Release|Any CPU
57 | {B6044F02-10A3-4637-962E-8B2F882DCD59}.Release|x86.Build.0 = Release|Any CPU
58 | {88F3D60F-3C95-4E14-9731-622306630F4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
59 | {88F3D60F-3C95-4E14-9731-622306630F4B}.Debug|Any CPU.Build.0 = Debug|Any CPU
60 | {88F3D60F-3C95-4E14-9731-622306630F4B}.Debug|ARM.ActiveCfg = Debug|Any CPU
61 | {88F3D60F-3C95-4E14-9731-622306630F4B}.Debug|ARM.Build.0 = Debug|Any CPU
62 | {88F3D60F-3C95-4E14-9731-622306630F4B}.Debug|x64.ActiveCfg = Debug|Any CPU
63 | {88F3D60F-3C95-4E14-9731-622306630F4B}.Debug|x64.Build.0 = Debug|Any CPU
64 | {88F3D60F-3C95-4E14-9731-622306630F4B}.Debug|x86.ActiveCfg = Debug|Any CPU
65 | {88F3D60F-3C95-4E14-9731-622306630F4B}.Debug|x86.Build.0 = Debug|Any CPU
66 | {88F3D60F-3C95-4E14-9731-622306630F4B}.Release|Any CPU.ActiveCfg = Release|Any CPU
67 | {88F3D60F-3C95-4E14-9731-622306630F4B}.Release|Any CPU.Build.0 = Release|Any CPU
68 | {88F3D60F-3C95-4E14-9731-622306630F4B}.Release|ARM.ActiveCfg = Release|Any CPU
69 | {88F3D60F-3C95-4E14-9731-622306630F4B}.Release|ARM.Build.0 = Release|Any CPU
70 | {88F3D60F-3C95-4E14-9731-622306630F4B}.Release|x64.ActiveCfg = Release|Any CPU
71 | {88F3D60F-3C95-4E14-9731-622306630F4B}.Release|x64.Build.0 = Release|Any CPU
72 | {88F3D60F-3C95-4E14-9731-622306630F4B}.Release|x86.ActiveCfg = Release|Any CPU
73 | {88F3D60F-3C95-4E14-9731-622306630F4B}.Release|x86.Build.0 = Release|Any CPU
74 | {826340DD-E375-4D1B-878C-FF67EAC7E0B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
75 | {826340DD-E375-4D1B-878C-FF67EAC7E0B7}.Debug|Any CPU.Build.0 = Debug|Any CPU
76 | {826340DD-E375-4D1B-878C-FF67EAC7E0B7}.Debug|ARM.ActiveCfg = Debug|Any CPU
77 | {826340DD-E375-4D1B-878C-FF67EAC7E0B7}.Debug|ARM.Build.0 = Debug|Any CPU
78 | {826340DD-E375-4D1B-878C-FF67EAC7E0B7}.Debug|x64.ActiveCfg = Debug|Any CPU
79 | {826340DD-E375-4D1B-878C-FF67EAC7E0B7}.Debug|x64.Build.0 = Debug|Any CPU
80 | {826340DD-E375-4D1B-878C-FF67EAC7E0B7}.Debug|x86.ActiveCfg = Debug|Any CPU
81 | {826340DD-E375-4D1B-878C-FF67EAC7E0B7}.Debug|x86.Build.0 = Debug|Any CPU
82 | {826340DD-E375-4D1B-878C-FF67EAC7E0B7}.Release|Any CPU.ActiveCfg = Release|Any CPU
83 | {826340DD-E375-4D1B-878C-FF67EAC7E0B7}.Release|Any CPU.Build.0 = Release|Any CPU
84 | {826340DD-E375-4D1B-878C-FF67EAC7E0B7}.Release|ARM.ActiveCfg = Release|Any CPU
85 | {826340DD-E375-4D1B-878C-FF67EAC7E0B7}.Release|ARM.Build.0 = Release|Any CPU
86 | {826340DD-E375-4D1B-878C-FF67EAC7E0B7}.Release|x64.ActiveCfg = Release|Any CPU
87 | {826340DD-E375-4D1B-878C-FF67EAC7E0B7}.Release|x64.Build.0 = Release|Any CPU
88 | {826340DD-E375-4D1B-878C-FF67EAC7E0B7}.Release|x86.ActiveCfg = Release|Any CPU
89 | {826340DD-E375-4D1B-878C-FF67EAC7E0B7}.Release|x86.Build.0 = Release|Any CPU
90 | EndGlobalSection
91 | GlobalSection(SolutionProperties) = preSolution
92 | HideSolutionNode = FALSE
93 | EndGlobalSection
94 | EndGlobal
95 |
--------------------------------------------------------------------------------
/appveyor.yml:
--------------------------------------------------------------------------------
1 | image: Visual Studio 2015
2 |
3 | init:
4 | - git config --global core.autocrlf input
5 |
6 | clone_depth: 5
7 |
8 | install:
9 | - git submodule update --init --recursive
10 | # print nuget version
11 | - nuget help
12 | - nuget restore VectorTileCsPortable.sln
13 | - nuget restore VectorTileCs.sln
14 | - nuget install NUnit.Runners -OutputDirectory tools
15 | - nuget install OpenCover -OutputDirectory tools
16 | # - nuget install ReportGenerator -Pre -OutputDirectory tools
17 | - nuget install coveralls.net -Pre -OutputDirectory tools
18 | - nuget install Microsoft.CodeAnalysis.CSharp.FxCopAnalyzers -Pre -OutputDirectory tools
19 | - nuget install Microsoft.CodeAnalysis.FxCopAnalyzers -Pre -OutputDirectory tools
20 |
21 | platform: Any CPU
22 | configuration:
23 | - Debug
24 |
25 | environment:
26 | COVERALLS_REPO_TOKEN:
27 | secure: gO7ftSjlgxhWlaWnPRDjgR64iGQw1kg83UX7nA62TpqfZsRyU0NaDO/WeGpjLKDm
28 |
29 | build_script:
30 | #build UWP
31 | - msbuild VectorTileCsPortable.sln /p:Configuration=Debug /p:Platform="Any Cpu" /maxcpucount:%NUMBER_OF_PROCESSORS%
32 | #build Net 2.0
33 | - msbuild VectorTileCs.sln /p:Configuration=Net20Debug /p:Platform="Any Cpu" /maxcpucount:%NUMBER_OF_PROCESSORS%
34 | - bin\Net20Debug\v2.0\VerifyNetFrameworkVersion.exe
35 | #build Net 3.5
36 | - msbuild VectorTileCs.sln /p:Configuration=Net35Debug /p:Platform="Any Cpu" /maxcpucount:%NUMBER_OF_PROCESSORS%
37 | - bin\Net35Debug\v3.5\VerifyNetFrameworkVersion.exe
38 | #build Net 4.6.2
39 | - msbuild VectorTileCs.sln /p:Configuration=Net462Debug /p:Platform="Any Cpu" /maxcpucount:%NUMBER_OF_PROCESSORS%
40 | - bin\Net462Debug\v4.6.2\VerifyNetFrameworkVersion.exe
41 |
42 | after_build:
43 | - cmd: nuget pack Mapbox.VectorTile.nuspec
44 | - ps: Get-ChildItem .\*.nupkg | % { Push-AppveyorArtifact $_.FullName -FileName $_.Name }
45 |
46 | after_test:
47 | - ps: >-
48 | $nunitrunner = (Resolve-Path "tools/NUnit.ConsoleRunner.*/tools/nunit3-console.exe").ToString();
49 | $opencov = (Resolve-Path "tools/OpenCover.*/tools/OpenCover.Console.exe").ToString();
50 | $coveralls = (Resolve-Path "tools/coveralls.net.*/tools/csmacnz.coveralls.exe").ToString();
51 | Write-Host "nunitrunner: $nunitrunner"
52 | Write-Host "opencov: $opencov"
53 | Write-Host "coveralls: $coveralls"
54 | - ps: >-
55 | & $opencov `
56 | -register:user `
57 | -target:"$nunitrunner" `
58 | -targetargs:"bin\Net35Debug\v3.5\VectorTiles.Tests.dll" `
59 | -filter:"+[*]* -[*.Tests]* -[*]*.InteralClipperLib.*" `
60 | -output:opencoverCoverage.xml;
61 | - ps: >-
62 | & $coveralls --opencover -i opencoverCoverage.xml `
63 | --repoToken $env:COVERALLS_REPO_TOKEN `
64 | --useRelativePaths `
65 | --commitId $env:APPVEYOR_REPO_COMMIT `
66 | --commitBranch $env:APPVEYOR_REPO_BRANCH `
67 | --commitAuthor $env:APPVEYOR_REPO_COMMIT_AUTHOR `
68 | --commitEmail $env:APPVEYOR_REPO_COMMIT_AUTHOR_EMAIL `
69 | --commitMessage $env:APPVEYOR_REPO_COMMIT_MESSAGE `
70 | --jobId $env:APPVEYOR_BUILD_NUMBER `
71 | --serviceName appveyor;
72 | - cmd: SET PATH=c:\Program Files (x86)\Microsoft Visual Studio 14.0\Team Tools\Static Analysis Tools\FxCop;%PATH%
73 | - cmd: FxCopCmd.exe /out:fxcop.out.xml /file:bin\Net35Debug\v3.5\Mapbox.VectorTile.VectorTileReader.dll /file:bin\Net35Debug\v3.5\Mapbox.VectorTile.Geometry.dll /file:bin\Net35Debug\v3.5\Mapbox.VectorTile.PbfReader.dll /file:bin\Net35Debug\v3.5\Mapbox.VectorTile.ExtensionMethods.dll
74 | #http://help.appveyor.com/discussions/kb/9-support-for-stylecop-report#comment_34865295
75 | #http://help.appveyor.com/discussions/kb/5-code-analysis-fxcop-support
76 | - ps: >-
77 | $codeAnalysisErrors = [xml](Get-Content fxcop.out.xml);
78 | foreach ($codeAnalysisError in $codeAnalysisErrors.SelectNodes("//Message")) {
79 | $issueNode = $codeAnalysisError.SelectSingleNode("Issue");
80 | $errorLevel = $($issueNode.Level);
81 | if(!$errorLevel){$errorLevel='Warning'};
82 | $errorLevel = $errorLevel.Replace("Critical","").Replace("Informational", "Information");
83 | Write-Host "$($codeAnalysisError.CheckId): $($codeAnalysisError.TypeName) Line Number: $($issueNode.Line) FileName: $($issueNode.Path)\$($codeAnalysisError.Issue.File) ErrorMessage: $($issueNode.InnerXml)";
84 | Add-AppveyorCompilationMessage "$($codeAnalysisError.CheckId): $($codeAnalysisError.TypeName)" -Category $errorLevel -FileName "$($issueNode.Path)\$($codeAnalysisError.Issue.File)" -Line $($issueNode.Line) -Details $($issueNode.InnerXml);
85 | }
86 | Push-AppveyorArtifact opencoverCoverage.xml;
87 | Push-AppveyorArtifact fxcop.out.xml;
88 | - cmd: cd %APPVEYOR_BUILD_FOLDER%\bin\Net20Debug\v2.0 && bench
89 | - cmd: cd %APPVEYOR_BUILD_FOLDER%\bin\Net35Debug\v3.5 && bench
90 | - cmd: cd %APPVEYOR_BUILD_FOLDER%\bin\Net462Debug\v4.6.2 && bench
91 |
--------------------------------------------------------------------------------
/src/AssemblyInfoVersion.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 |
3 | [assembly: AssemblyVersion( "1.0.2" )]
4 | [assembly: AssemblyFileVersion( "1.0.2" )]
5 | [assembly: AssemblyInformationalVersion( "1.0.2" )]
6 |
--------------------------------------------------------------------------------
/src/Bench/Bench.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {5FA56C72-348A-4B52-980C-EA8287E66422}
8 | Exe
9 | Properties
10 | Bench
11 | Bench
12 | v4.6.1
13 | 512
14 |
15 |
16 |
17 | AnyCPU
18 | true
19 | full
20 | false
21 | ..\..\bin\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 | false
26 |
27 |
28 | AnyCPU
29 | pdbonly
30 | true
31 | ..\..\bin\
32 | TRACE
33 | prompt
34 | 4
35 | false
36 |
37 |
38 | v2.0
39 | ..\..\bin\$(Configuration)\$(TargetFrameworkVersion)\
40 | true
41 | full
42 | DEBUG;TRACE;NET20
43 | AnyCPU
44 | prompt
45 | MinimumRecommendedRules.ruleset
46 | false
47 |
48 |
49 | v3.5
50 | ..\..\bin\$(Configuration)\$(TargetFrameworkVersion)\
51 | true
52 | full
53 | DEBUG;TRACE;NET35
54 | AnyCPU
55 | prompt
56 | MinimumRecommendedRules.ruleset
57 | false
58 |
59 |
60 | v4.6.2
61 | ..\..\bin\$(Configuration)\$(TargetFrameworkVersion)\
62 | true
63 | full
64 | DEBUG;TRACE;NET462
65 | AnyCPU
66 | prompt
67 | MinimumRecommendedRules.ruleset
68 | false
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 | Properties\AssemblyInfoVersion.cs
81 |
82 |
83 |
84 |
85 |
86 |
87 | {55503403-0083-4ed8-b618-f8377610b225}
88 | ExtensionMethods
89 |
90 |
91 | {4656b308-1492-4a22-a73e-06bf6aa858f2}
92 | VectorTileReader
93 |
94 |
95 |
96 |
97 |
98 |
99 |
106 |
--------------------------------------------------------------------------------
/src/Bench/Program.cs:
--------------------------------------------------------------------------------
1 | using Mapbox.VectorTile;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Diagnostics;
5 | using System.IO;
6 | using System.Net;
7 |
8 | #if !NET20
9 | using System.Linq;
10 | #endif
11 |
12 | namespace Bench
13 | {
14 |
15 |
16 | class Program
17 | {
18 |
19 |
20 | static int Main(string[] args)
21 | {
22 |
23 | //ul 14/4680/6260
24 | //lr 14/4693/6274
25 | ulong zoom = 14;
26 | ulong minCol = 4680;
27 | ulong minRow = 6260;
28 | ulong maxCol = 4693;
29 | ulong maxRow = 6274;
30 |
31 | string fixturePath = Path.Combine(Path.Combine(Path.Combine(Path.Combine(Path.Combine("..", ".."), ".."), "bench"), "mvt-bench-fixtures"), "fixtures");
32 | if (!Directory.Exists(fixturePath))
33 | {
34 | Console.Error.WriteLine("fixture directory not found: [{0}]", fixturePath);
35 | return 1;
36 | }
37 |
38 | ulong nrOfTiles = (maxCol - minCol + 1) * (maxRow - minRow + 1);
39 | List tiles = new List((int)nrOfTiles);
40 |
41 | for (ulong col = minCol; col <= maxCol; col++)
42 | {
43 | for (ulong row = minRow; row <= maxRow; row++)
44 | {
45 | string fileName = string.Format("{0}-{1}-{2}.mvt", zoom, col, row);
46 | fileName = Path.Combine(fixturePath, fileName);
47 | if (!File.Exists(fileName))
48 | {
49 | Console.Error.WriteLine("fixture mvt not found: [{0}]", fileName);
50 | return 1;
51 | }
52 | else
53 | {
54 | tiles.Add(new TileData()
55 | {
56 | zoom = zoom,
57 | col = col,
58 | row = row,
59 | pbf = File.ReadAllBytes(fileName)
60 | });
61 | }
62 | }
63 | }
64 |
65 | Stopwatch stopWatch = new Stopwatch();
66 | List elapsed = new List();
67 |
68 | for (int i = 0; i <= 100; i++)
69 | {
70 | Console.Write(".");
71 | stopWatch.Start();
72 | foreach (var tile in tiles)
73 | {
74 | VectorTile vt = new VectorTile(tile.pbf, false);
75 | foreach (var layerName in vt.LayerNames())
76 | {
77 | VectorTileLayer layer = vt.GetLayer(layerName);
78 | for (int j = 0; j < layer.FeatureCount(); j++)
79 | {
80 | VectorTileFeature feat = layer.GetFeature(j);
81 | var props = feat.GetProperties();
82 | }
83 | }
84 | }
85 | stopWatch.Stop();
86 | //skip first run
87 | if (i != 0)
88 | {
89 | elapsed.Add(stopWatch.ElapsedMilliseconds);
90 | }
91 | stopWatch.Reset();
92 | }
93 |
94 |
95 | Console.WriteLine(
96 | @"
97 | runs : {0}
98 | tiles per run : {1}
99 | min [ms] : {2}
100 | max [ms] : {3}
101 | avg [ms] : {4}
102 | StdDev : {5:0.00}
103 | overall [ms] : {6}
104 | tiles/sec : {7:0.0}
105 | ",
106 | elapsed.Count,
107 | tiles.Count,
108 | elapsed.Min(),
109 | elapsed.Max(),
110 | elapsed.Average(),
111 | StdDev(elapsed),
112 | elapsed.Sum(),
113 | ((float)elapsed.Count * (float)tiles.Count / (float)elapsed.Sum()) * 1000
114 | );
115 |
116 |
117 | return 0;
118 | }
119 |
120 |
121 | private static double StdDev(List values)
122 | {
123 | double ret = 0;
124 | int count = values.Count;
125 | if (count > 1)
126 | {
127 | //Compute the Average
128 | double avg = values.Average();
129 |
130 | //Perform the Sum of (value-avg)^2
131 | #if NET20
132 | List pows = new List();
133 | for (int i = 0; i < values.Count; i++)
134 | {
135 | pows.Add(Math.Pow(values[i] - avg, 2));
136 | }
137 | double sum = pows.Sum();
138 | #else
139 | double sum = values.Sum(d => (d - avg) * (d - avg));
140 | #endif
141 |
142 | //Put it all together
143 | ret = Math.Sqrt(sum / count);
144 | }
145 | return ret;
146 | }
147 |
148 |
149 | }
150 |
151 |
152 | public struct TileData
153 | {
154 | public ulong zoom;
155 | public ulong col;
156 | public ulong row;
157 | public byte[] pbf;
158 | }
159 |
160 |
161 | public class GZipWebClient : WebClient
162 | {
163 | protected override WebRequest GetWebRequest(Uri address)
164 | {
165 | HttpWebRequest request = (HttpWebRequest)base.GetWebRequest(address);
166 | request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
167 | return request;
168 | }
169 | }
170 |
171 |
172 | #if NET20
173 | public static class Net20Extensions
174 | {
175 |
176 | public static long Min(this List theList)
177 | {
178 | long min = long.MaxValue;
179 | for (int i = 0; i < theList.Count; i++)
180 | {
181 | if (min > theList[i]) { min = theList[i]; }
182 | }
183 | return min;
184 | }
185 |
186 | public static long Max(this List theList)
187 | {
188 | long max = long.MinValue;
189 | for (int i = 0; i < theList.Count; i++)
190 | {
191 | if (max < theList[i]) { max = theList[i]; }
192 | }
193 | return max;
194 | }
195 |
196 | public static long Sum(this List theList)
197 | {
198 | long retVal = 0;
199 | for (int i = 0; i < theList.Count; i++)
200 | {
201 | retVal += theList[i];
202 | }
203 | return retVal;
204 | }
205 |
206 | public static double Average(this List theList)
207 | {
208 | long sum = theList.Sum();
209 | return (double)sum / (double)theList.Count;
210 | }
211 |
212 | public static double Sum(this List theList)
213 | {
214 | double retVal = 0;
215 | for (int i = 0; i < theList.Count; i++)
216 | {
217 | retVal += theList[i];
218 | }
219 | return retVal;
220 | }
221 |
222 | }
223 | #endif
224 |
225 |
226 |
227 | }
228 |
--------------------------------------------------------------------------------
/src/Bench/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Bench")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("Bench")]
13 | [assembly: AssemblyCopyright("Copyright © 2016")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("5fa56c72-348a-4b52-980c-ea8287e66422")]
24 |
25 |
--------------------------------------------------------------------------------
/src/Bench/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/DemoConsoleApp/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/src/DemoConsoleApp/DemoConsoleApp.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {D01BA6CB-9A2B-4AA5-95E1-085D9B569309}
8 | Exe
9 | Properties
10 | DemoConsoleApp
11 | DemoConsoleApp
12 | v4.6
13 | 512
14 | true
15 | publish\
16 | true
17 | Disk
18 | false
19 | Foreground
20 | 7
21 | Days
22 | false
23 | false
24 | true
25 | 0
26 | 1.0.0.%2a
27 | false
28 | false
29 | true
30 |
31 |
32 |
33 | true
34 | ..\..\bin\
35 | DEBUG;TRACE
36 | full
37 | x64
38 | prompt
39 | MinimumRecommendedRules.ruleset
40 | true
41 |
42 |
43 | ..\..\bin\
44 | TRACE
45 | true
46 | pdbonly
47 | x64
48 | prompt
49 | MinimumRecommendedRules.ruleset
50 | true
51 |
52 |
53 | true
54 | ..\..\bin\
55 | DEBUG;TRACE
56 | full
57 | AnyCPU
58 | prompt
59 | MinimumRecommendedRules.ruleset
60 | true
61 |
62 |
63 | ..\..\bin\
64 | TRACE
65 | true
66 | pdbonly
67 | AnyCPU
68 | prompt
69 | MinimumRecommendedRules.ruleset
70 | true
71 |
72 |
73 | true
74 | bin\x64\Net20Debug\
75 | DEBUG;TRACE
76 | full
77 | x64
78 | prompt
79 | MinimumRecommendedRules.ruleset
80 | true
81 |
82 |
83 | v2.0
84 | ..\..\bin\$(Configuration)\$(TargetFrameworkVersion)\
85 | true
86 | full
87 | DEBUG;TRACE;NET20
88 | AnyCPU
89 | prompt
90 | MinimumRecommendedRules.ruleset
91 | false
92 |
93 |
94 | v3.5
95 | ..\..\bin\$(Configuration)\$(TargetFrameworkVersion)\
96 | true
97 | full
98 | DEBUG;TRACE;NET35
99 | AnyCPU
100 | prompt
101 | MinimumRecommendedRules.ruleset
102 | false
103 |
104 |
105 | v4.6.2
106 | ..\..\bin\$(Configuration)\$(TargetFrameworkVersion)\
107 | true
108 | full
109 | DEBUG;TRACE;NET462
110 | AnyCPU
111 | prompt
112 | MinimumRecommendedRules.ruleset
113 | false
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 | Properties\AssemblyInfoVersion.cs
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 | {55503403-0083-4ed8-b618-f8377610b225}
136 | ExtensionMethods
137 |
138 |
139 | {f0967389-29c8-4d50-b397-9bb698f13ed6}
140 | Geometry
141 |
142 |
143 | {4656b308-1492-4a22-a73e-06bf6aa858f2}
144 | VectorTileReader
145 |
146 |
147 |
148 |
149 | False
150 | Microsoft .NET Framework 4.5.2 %28x86 and x64%29
151 | true
152 |
153 |
154 | False
155 | .NET Framework 3.5 SP1
156 | false
157 |
158 |
159 |
160 |
167 |
--------------------------------------------------------------------------------
/src/DemoConsoleApp/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Resources;
3 | using System.Runtime.CompilerServices;
4 | using System.Runtime.InteropServices;
5 |
6 | // General Information about an assembly is controlled through the following
7 | // set of attributes. Change these attribute values to modify the information
8 | // associated with an assembly.
9 | [assembly: AssemblyTitle("VectorTilesCs")]
10 | [assembly: AssemblyDescription("")]
11 | [assembly: AssemblyConfiguration("")]
12 | [assembly: AssemblyCompany("")]
13 | [assembly: AssemblyProduct("VectorTilesCs")]
14 | [assembly: AssemblyCopyright("Copyright © 2016")]
15 | [assembly: AssemblyTrademark("")]
16 | [assembly: AssemblyCulture("")]
17 | [assembly: NeutralResourcesLanguage("en-US")]
18 |
19 | // Setting ComVisible to false makes the types in this assembly not visible
20 | // to COM components. If you need to access a type in this assembly from
21 | // COM, set the ComVisible attribute to true on that type.
22 | [assembly: ComVisible(false)]
23 |
24 | // The following GUID is for the ID of the typelib if this project is exposed to COM
25 | [assembly: Guid("d01ba6cb-9a2b-4aa5-95e1-085d9b569309")]
26 |
27 |
--------------------------------------------------------------------------------
/src/DemoConsoleApp/program.cs:
--------------------------------------------------------------------------------
1 | using Mapbox.VectorTile.ExtensionMethods;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.IO;
5 |
6 |
7 | namespace Mapbox.VectorTile
8 | {
9 |
10 |
11 | public class DemoConsoleApp
12 | {
13 |
14 |
15 | public static int Main(string[] args)
16 | {
17 |
18 | string vtIn = string.Empty;
19 | uint? clipBuffer = null;
20 | bool outGeoJson = false;
21 | ulong? zoom = null;
22 | ulong? tileCol = null;
23 | ulong? tileRow = null;
24 |
25 | for (int i = 0; i < args.Length; i++)
26 | {
27 | string argLow = args[i].ToLower();
28 | if (argLow.Contains("vt:"))
29 | {
30 | vtIn = argLow.Replace("vt:", "");
31 | }
32 | else if (argLow.Contains("clip:"))
33 | {
34 | clipBuffer = Convert.ToUInt32(argLow.Replace("clip:", ""));
35 | }
36 | else if (argLow.Contains("out:"))
37 | {
38 | outGeoJson = argLow.Replace("out:", "").Equals("geojson");
39 | }
40 | else if (argLow.Contains("tileid:"))
41 | {
42 | parseArg(argLow.Replace("tileid:", ""), out zoom, out tileCol, out tileRow);
43 | }
44 | }
45 |
46 | if (!File.Exists(vtIn))
47 | {
48 | Console.WriteLine($"file [{vtIn}] not found");
49 | usage();
50 | return 1;
51 | }
52 |
53 | // z-x-y weren't passed via parameters, try to get them from file name
54 | if (!zoom.HasValue || !tileCol.HasValue || !tileRow.HasValue)
55 | {
56 | if (!parseArg(Path.GetFileName(vtIn), out zoom, out tileCol, out tileRow))
57 | {
58 | usage();
59 | return 1;
60 | }
61 | }
62 |
63 | var bufferedData = File.ReadAllBytes(vtIn);
64 |
65 | VectorTile tile = new VectorTile(bufferedData);
66 |
67 | if (outGeoJson)
68 | {
69 | Console.WriteLine(tile.ToGeoJson(zoom.Value, tileCol.Value, tileRow.Value, clipBuffer));
70 | }
71 | else
72 | {
73 | foreach (string lyrName in tile.LayerNames())
74 | {
75 | VectorTileLayer lyr = tile.GetLayer(lyrName);
76 | Console.WriteLine(string.Format("------------ {0} ---------", lyrName));
77 | //if (lyrName != "building") { continue; }
78 | int featCnt = lyr.FeatureCount();
79 | for (int i = 0; i < featCnt; i++)
80 | {
81 | VectorTileFeature feat = lyr.GetFeature(i, clipBuffer);
82 | Console.WriteLine(string.Format("feature {0}: {1}", i, feat.GeometryType));
83 | Dictionary props = feat.GetProperties();
84 | foreach (var prop in props)
85 | {
86 | Console.WriteLine(string.Format(" {0}\t : ({1}) {2}", prop.Key, prop.Value.GetType(), prop.Value));
87 | }
88 | }
89 | }
90 | }
91 |
92 | return 0;
93 | }
94 |
95 | private static void usage()
96 | {
97 |
98 | Console.WriteLine("");
99 | Console.WriteLine("DemoConsoleApp.exe vt: ");
100 | Console.WriteLine("");
101 | Console.WriteLine("- vt: or vt:--.tile.mvt>");
102 | Console.WriteLine("- clip: to clip geometries extending beyong the tile border");
103 | Console.WriteLine("- out: to ouput either GeoJson or some metadata");
104 | Console.WriteLine("- tileid:-- to pass tile id if not contained within the file name");
105 | Console.WriteLine("");
106 | Console.WriteLine("");
107 | }
108 |
109 | private static bool parseArg(string fileName, out ulong? zoom, out ulong? tileCol, out ulong? tileRow)
110 | {
111 | zoom = null;
112 | tileCol = null;
113 | tileRow = null;
114 |
115 | string zxyTxt = fileName.Split(".".ToCharArray(), StringSplitOptions.RemoveEmptyEntries)[0];
116 | string[] zxy = zxyTxt.Split("-".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
117 | if (zxy.Length != 3)
118 | {
119 | Console.WriteLine("invalid zoom, tileCol or tileRow [{0}]", zxyTxt);
120 | return false;
121 | }
122 |
123 | ulong z;
124 | if (!ulong.TryParse(zxy[0], out z))
125 | {
126 | Console.WriteLine($"could not parse zoom: {zxy[0]}");
127 | return false;
128 | }
129 | zoom = z;
130 |
131 | ulong x;
132 | if (!ulong.TryParse(zxy[1], out x))
133 | {
134 | Console.WriteLine($"could not parse tileCol: {zxy[1]}");
135 | return false;
136 | }
137 | tileCol = x;
138 |
139 | ulong y;
140 | if (!ulong.TryParse(zxy[2], out y))
141 | {
142 | Console.WriteLine($"could not parse tileRow: {zxy[2]}");
143 | return false;
144 | }
145 | tileRow = y;
146 |
147 | return true;
148 | }
149 |
150 |
151 |
152 | }
153 | }
154 |
--------------------------------------------------------------------------------
/src/ExtensionMethods/Enums.cs:
--------------------------------------------------------------------------------
1 | using Mapbox.VectorTile.Geometry;
2 | using System;
3 | using System.ComponentModel;
4 |
5 | #if PORTABLE || WINDOWS_UWP
6 | using System.Reflection;
7 | using System.Linq;
8 | #endif
9 |
10 | #if NET20
11 |
12 | namespace System.Runtime.CompilerServices
13 | {
14 | [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class
15 | | AttributeTargets.Method)]
16 | public sealed class ExtensionAttribute : Attribute { }
17 | }
18 |
19 | #endif
20 |
21 |
22 | namespace Mapbox.VectorTile.ExtensionMethods
23 | {
24 |
25 | ///
26 | /// Extension method to extract the [Description] attribute from an Enum
27 | ///
28 | public static class EnumExtensions
29 | {
30 | public static string Description(this Enum value)
31 | {
32 | var enumType = value.GetType();
33 | #if PORTABLE || WINDOWS_UWP
34 | var field = enumType.GetRuntimeField(value.ToString());
35 | var attributes = field.GetCustomAttributes(typeof(DescriptionAttribute), false);
36 | return attributes.Count() == 0 ? value.ToString() : ((DescriptionAttribute)attributes.First()).Description;
37 | #else
38 | var field = enumType.GetField(value.ToString());
39 | var attributes = field.GetCustomAttributes(typeof(DescriptionAttribute), false);
40 | return attributes.Length == 0 ? value.ToString() : ((DescriptionAttribute)attributes[0]).Description;
41 | #endif
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/ExtensionMethods/ExtensionMethods.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {55503403-0083-4ED8-B618-F8377610B225}
8 | Library
9 | Properties
10 | Mapbox.VectorTile.ExtensionMethods
11 | Mapbox.VectorTile.ExtensionMethods
12 | v3.5
13 | 512
14 |
15 |
16 |
17 | true
18 | ..\..\bin\
19 | DEBUG;TRACE
20 | full
21 | x64
22 | prompt
23 | MinimumRecommendedRules.ruleset
24 | false
25 |
26 |
27 | ..\..\bin\
28 | TRACE
29 | true
30 | pdbonly
31 | x64
32 | prompt
33 | MinimumRecommendedRules.ruleset
34 | false
35 |
36 |
37 | true
38 | ..\..\bin\
39 | DEBUG;TRACE
40 | full
41 | AnyCPU
42 | prompt
43 | MinimumRecommendedRules.ruleset
44 | false
45 |
46 |
47 | ..\..\bin\
48 | TRACE
49 | true
50 | pdbonly
51 | AnyCPU
52 | prompt
53 | MinimumRecommendedRules.ruleset
54 | false
55 |
56 |
57 | true
58 | bin\x64\Net20Debug\
59 | DEBUG;TRACE
60 | full
61 | x64
62 | prompt
63 | MinimumRecommendedRules.ruleset
64 |
65 |
66 | v2.0
67 | ..\..\bin\$(Configuration)\$(TargetFrameworkVersion)\
68 | true
69 | full
70 | DEBUG;TRACE;NET20
71 | AnyCPU
72 | prompt
73 | MinimumRecommendedRules.ruleset
74 | false
75 |
76 |
77 | v3.5
78 | ..\..\bin\$(Configuration)\$(TargetFrameworkVersion)\
79 | true
80 | full
81 | DEBUG;TRACE;NET35
82 | AnyCPU
83 | prompt
84 | MinimumRecommendedRules.ruleset
85 | false
86 |
87 |
88 | v4.6.2
89 | ..\..\bin\$(Configuration)\$(TargetFrameworkVersion)\
90 | true
91 | full
92 | DEBUG;TRACE;NET462
93 | AnyCPU
94 | prompt
95 | MinimumRecommendedRules.ruleset
96 | false
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 | Properties\AssemblyInfoVersion.cs
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 | {f0967389-29c8-4d50-b397-9bb698f13ed6}
117 | Geometry
118 |
119 |
120 | {4bce42ee-c33f-4fa4-bfdd-86f3d45c647c}
121 | PbfReader
122 |
123 |
124 | {4656b308-1492-4a22-a73e-06bf6aa858f2}
125 | VectorTileReader
126 |
127 |
128 |
129 |
136 |
--------------------------------------------------------------------------------
/src/ExtensionMethods/ExtensionMethodsPortable.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 10.0
6 | Debug
7 | AnyCPU
8 | {826340DD-E375-4D1B-878C-FF67EAC7E0B7}
9 | Library
10 | Properties
11 | Mapbox.VectorTile.ExtensionMethods
12 | Mapbox.VectorTile.ExtensionMethods
13 | en-US
14 | 512
15 | {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
16 | Profile7
17 | v4.5
18 |
19 |
20 | true
21 | full
22 | false
23 | ..\..\bin\PortableDebug\portable-net45+uap10\
24 | TRACE;DEBUG;PORTABLE;WINDOWS_UWP
25 | prompt
26 | 4
27 |
28 |
29 | pdbonly
30 | true
31 | bin\Release\
32 | TRACE
33 | prompt
34 | 4
35 |
36 |
37 |
38 |
39 | {b6044f02-10a3-4637-962e-8b2f882dcd59}
40 | GeometryPortable
41 |
42 |
43 | {e3ed95c9-42d9-4480-90e5-87f4fe60b8e2}
44 | PbfReaderPortable
45 |
46 |
47 | {88f3d60f-3c95-4e14-9731-622306630f4b}
48 | VectorTileReaderPortable
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
65 |
--------------------------------------------------------------------------------
/src/ExtensionMethods/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Resources;
3 | using System.Runtime.CompilerServices;
4 | using System.Runtime.InteropServices;
5 |
6 | // General Information about an assembly is controlled through the following
7 | // set of attributes. Change these attribute values to modify the information
8 | // associated with an assembly.
9 | [assembly: AssemblyTitle("Util")]
10 | [assembly: AssemblyDescription("")]
11 | [assembly: AssemblyConfiguration("")]
12 | [assembly: AssemblyCompany("")]
13 | [assembly: AssemblyProduct("Util")]
14 | [assembly: AssemblyCopyright("Copyright © 2016")]
15 | [assembly: AssemblyTrademark("")]
16 | [assembly: AssemblyCulture("")]
17 | [assembly: NeutralResourcesLanguage("en-US")]
18 |
19 | // Setting ComVisible to false makes the types in this assembly not visible
20 | // to COM components. If you need to access a type in this assembly from
21 | // COM, set the ComVisible attribute to true on that type.
22 | [assembly: ComVisible(false)]
23 |
24 | // The following GUID is for the ID of the typelib if this project is exposed to COM
25 | [assembly: Guid("55503403-0083-4ed8-b618-f8377610b225")]
26 |
27 |
--------------------------------------------------------------------------------
/src/ExtensionMethods/VectorTile.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using Mapbox.VectorTile;
4 | using System.Globalization;
5 | using Mapbox.VectorTile.Geometry;
6 |
7 | #if !NET20
8 | using System.Linq;
9 | #endif
10 |
11 | namespace Mapbox.VectorTile.ExtensionMethods
12 | {
13 |
14 |
15 | public static class VectorTileExtensions
16 | {
17 |
18 |
19 | ///
20 | /// Return the whole vector tile as GeoJSON
21 | ///
22 | ///
23 | /// Zoom level of the tile
24 | /// Column of the tile (OSM tile schema)
25 | /// Row of the tile (OSM tile schema)
26 | ///
27 | /// Vector tiles may contain data reaching beyond the actual tile border.
28 | /// Define if/how this data should be included.
29 | /// 'null': data from the vector tile as is
30 | /// '>=0': clip distance in internal tile units
31 | ///
32 | /// GeoJSON of the vector tile contents
33 | public static string ToGeoJson(
34 | this VectorTile tile
35 | , ulong zoom
36 | , ulong tileColumn
37 | , ulong tileRow
38 | , uint? clipBuffer = null
39 | )
40 | {
41 |
42 | //to get '.' instead of ',' when using "string.format" with double/float and non-US system number format settings
43 | //CultureInfo en_US = new CultureInfo("en-US");
44 |
45 | // escaping '{' '}' -> @"{{" "}}"
46 | //escaping '"' -> @""""
47 | string templateFeatureCollection = @"{{""type"":""FeatureCollection"",""features"":[{0}]}}";
48 | string templateFeature = @"{{""type"":""Feature"",""geometry"":{{""type"":""{0}"",""coordinates"":[{1}]}},""properties"":{2}}}";
49 |
50 | List geojsonFeatures = new List();
51 |
52 | foreach (var layerName in tile.LayerNames())
53 | {
54 | var layer = tile.GetLayer(layerName);
55 |
56 | for (int i = 0; i < layer.FeatureCount(); i++)
57 | {
58 | var feat = layer.GetFeature(i, clipBuffer, 1.0f);
59 |
60 | if (feat.GeometryType == GeomType.UNKNOWN) { continue; }
61 |
62 | //resolve properties
63 | List keyValue = new List();
64 | int tagCnt = feat.Tags.Count;
65 | for (int j = 0; j < tagCnt; j += 2)
66 | {
67 | string key = layer.Keys[feat.Tags[j]];
68 | object val = layer.Values[feat.Tags[j + 1]];
69 | keyValue.Add(string.Format(NumberFormatInfo.InvariantInfo, @"""{0}"":""{1}""", key, val));
70 | }
71 |
72 | //build geojson properties object from resolved properties
73 | string geojsonProps = string.Format(
74 | NumberFormatInfo.InvariantInfo
75 | , @"{{""id"":{0},""lyr"":""{1}""{2}{3}}}"
76 | , feat.Id
77 | , layer.Name
78 | , keyValue.Count > 0 ? "," : ""
79 | , string.Join(",", keyValue.ToArray())
80 | );
81 |
82 | //work through geometries
83 | string geojsonCoords = "";
84 | string geomType = feat.GeometryType.Description();
85 |
86 | //multipart
87 | List> geomWgs84 = feat.GeometryAsWgs84(zoom, tileColumn, tileRow);
88 | if (geomWgs84.Count > 1)
89 | {
90 | switch (feat.GeometryType)
91 | {
92 | case GeomType.POINT:
93 | geomType = "MultiPoint";
94 | #if NET20
95 | List allPoints = new List();
96 | foreach (var part in geomWgs84)
97 | {
98 | foreach (var pnt in part)
99 | {
100 | allPoints.Add(pnt);
101 | }
102 | }
103 | geojsonCoords = string.Join(
104 | ","
105 | , allPoints.ConvertAll(g => string.Format(NumberFormatInfo.InvariantInfo, "[{0},{1}]", g.Lng, g.Lat)).ToArray()
106 | );
107 | #else
108 | geojsonCoords = string.Join(
109 | ","
110 | , geomWgs84
111 | .SelectMany((List g) => g)
112 | .Select(g => string.Format(NumberFormatInfo.InvariantInfo, "[{0},{1}]", g.Lng, g.Lat)).ToArray()
113 | );
114 | #endif
115 | break;
116 | case GeomType.LINESTRING:
117 | geomType = "MultiLineString";
118 | List parts = new List();
119 | foreach (var part in geomWgs84)
120 | {
121 | parts.Add("[" + string.Join(
122 | ","
123 | #if NET20
124 | , part.ConvertAll(g => string.Format(NumberFormatInfo.InvariantInfo, "[{0},{1}]", g.Lng, g.Lat)).ToArray()
125 | #else
126 | , part.Select(g => string.Format(NumberFormatInfo.InvariantInfo, "[{0},{1}]", g.Lng, g.Lat)).ToArray()
127 | #endif
128 | ) + "]");
129 | }
130 | geojsonCoords = string.Join(",", parts.ToArray());
131 | break;
132 | case GeomType.POLYGON:
133 | geomType = "MultiPolygon";
134 | List partsMP = new List();
135 | foreach (var part in geomWgs84)
136 | {
137 | partsMP.Add("[" + string.Join(
138 | ","
139 | #if NET20
140 | , part.ConvertAll(g => string.Format(NumberFormatInfo.InvariantInfo, "[{0},{1}]", g.Lng, g.Lat)).ToArray()
141 | #else
142 | , part.Select(g => string.Format(NumberFormatInfo.InvariantInfo, "[{0},{1}]", g.Lng, g.Lat)).ToArray()
143 | #endif
144 | ) + "]");
145 | }
146 | geojsonCoords = "[" + string.Join(",", partsMP.ToArray()) + "]";
147 | break;
148 | default:
149 | break;
150 | }
151 | }
152 | else if (geomWgs84.Count == 1)
153 | { //singlepart
154 | switch (feat.GeometryType)
155 | {
156 | case GeomType.POINT:
157 | geojsonCoords = string.Format(NumberFormatInfo.InvariantInfo, "{0},{1}", geomWgs84[0][0].Lng, geomWgs84[0][0].Lat);
158 | break;
159 | case GeomType.LINESTRING:
160 | geojsonCoords = string.Join(
161 | ","
162 | #if NET20
163 | , geomWgs84[0].ConvertAll(g => string.Format(NumberFormatInfo.InvariantInfo, "[{0},{1}]", g.Lng, g.Lat)).ToArray()
164 | #else
165 | , geomWgs84[0].Select(g => string.Format(NumberFormatInfo.InvariantInfo, "[{0},{1}]", g.Lng, g.Lat)).ToArray()
166 | #endif
167 | );
168 | break;
169 | case GeomType.POLYGON:
170 | geojsonCoords = "[" + string.Join(
171 | ","
172 | #if NET20
173 | , geomWgs84[0].ConvertAll(g => string.Format(NumberFormatInfo.InvariantInfo, "[{0},{1}]", g.Lng, g.Lat)).ToArray()
174 | #else
175 | , geomWgs84[0].Select(g => string.Format(NumberFormatInfo.InvariantInfo, "[{0},{1}]", g.Lng, g.Lat)).ToArray()
176 | #endif
177 | ) + "]";
178 | break;
179 | default:
180 | break;
181 | }
182 | }
183 | else
184 | {//no geometry
185 | continue;
186 | }
187 |
188 | geojsonFeatures.Add(
189 | string.Format(
190 | NumberFormatInfo.InvariantInfo
191 | , templateFeature
192 | , geomType
193 | , geojsonCoords
194 | , geojsonProps
195 | )
196 | );
197 | }
198 | }
199 |
200 | string geoJsonFeatColl = string.Format(
201 | NumberFormatInfo.InvariantInfo
202 | , templateFeatureCollection
203 | , string.Join(",", geojsonFeatures.ToArray())
204 | );
205 |
206 | return geoJsonFeatColl;
207 | }
208 |
209 |
210 |
211 | }
212 | }
213 |
214 |
215 |
--------------------------------------------------------------------------------
/src/ExtensionMethods/VectorTileFeature.cs:
--------------------------------------------------------------------------------
1 | using Mapbox.VectorTile.Geometry;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Text;
5 |
6 | #if !NET20
7 | using System.Linq;
8 | #endif
9 |
10 | namespace Mapbox.VectorTile.ExtensionMethods
11 | {
12 |
13 |
14 | public static class VectorTileFeatureExtensions
15 | {
16 |
17 |
18 | ///
19 | /// >Geometry in LatLng coordinates instead of internal tile coordinates
20 | ///
21 | ///
22 | /// Zoom level of the tile
23 | /// Column of the tile (OSM tile schema)
24 | /// Row of the tile (OSM tile schema)
25 | ///
26 | public static List> GeometryAsWgs84(
27 | this VectorTileFeature feature
28 | , ulong zoom
29 | , ulong tileColumn
30 | , ulong tileRow
31 | , uint? clipBuffer = null
32 | )
33 | {
34 |
35 | List> geometryAsWgs84 = new List>();
36 | foreach (var part in feature.Geometry(clipBuffer, 1.0f))
37 | {
38 | #if NET20
39 | List partAsWgs84 = new List();
40 | foreach (var partGeom in part)
41 | {
42 | partAsWgs84.Add(partGeom.ToLngLat(zoom, tileColumn, tileRow, feature.Layer.Extent));
43 | }
44 | geometryAsWgs84.Add(partAsWgs84);
45 | #else
46 | geometryAsWgs84.Add(
47 | part.Select(g => g.ToLngLat(zoom, tileColumn, tileRow, feature.Layer.Extent)).ToList()
48 | );
49 | #endif
50 | }
51 |
52 | return geometryAsWgs84;
53 | }
54 |
55 |
56 |
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/Geometry/DecodeGeometry.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using Mapbox.VectorTile.Contants;
4 |
5 | namespace Mapbox.VectorTile.Geometry
6 | {
7 |
8 |
9 | ///
10 | /// Decode tile geometries
11 | ///
12 | public static class DecodeGeometry
13 | {
14 |
15 | ///
16 | /// returns a list of lists.
17 | /// If the root list contains one child list it is a single part feature
18 | /// and the child list contains the coordinate pairs.
19 | /// e.g. single part point:
20 | /// Parent list with one child list, child list contains one Pont2D
21 | /// If the root list contains several child lists, it is a multipart feature
22 | /// e.g. multipart or donut polygon:
23 | /// Parent list contains number of list equal to the number of parts.
24 | /// Each child list contains the corrdinates of this part.
25 | ///
26 | /// Tile extent
27 | /// Geometry type
28 | /// VT geometry commands, see spec
29 | /// factor for scaling internal tile coordinates
30 | /// List>>> of decoded geometries (in internal tile coordinates)
31 | public static List>> GetGeometry(
32 | ulong extent
33 | , GeomType geomType
34 | , List geometryCommands
35 | , float scale = 1.0f
36 | )
37 | {
38 |
39 | List>> geomOut = new List>>();
40 | List> geomTmp = new List>();
41 | long cursorX = 0;
42 | long cursorY = 0;
43 |
44 | int geomCmdCnt = geometryCommands.Count;
45 | for (int i = 0; i < geomCmdCnt; i++)
46 | {
47 |
48 | uint g = geometryCommands[i];
49 | Commands cmd = (Commands)(g & 0x7);
50 | uint cmdCount = g >> 3;
51 |
52 | if (cmd == Commands.MoveTo || cmd == Commands.LineTo)
53 | {
54 | for (int j = 0; j < cmdCount; j++)
55 | {
56 | Point2d delta = zigzagDecode(geometryCommands[i + 1], geometryCommands[i + 2]);
57 | cursorX += delta.X;
58 | cursorY += delta.Y;
59 | i += 2;
60 | //end of part of multipart feature
61 | if (cmd == Commands.MoveTo && geomTmp.Count > 0)
62 | {
63 | geomOut.Add(geomTmp);
64 | geomTmp = new List>();
65 | }
66 |
67 | //Point2d pntTmp = new Point2d(cursorX, cursorY);
68 | Point2d pntTmp = new Point2d()
69 | {
70 | X = cursorX,
71 | Y = cursorY
72 | };
73 | geomTmp.Add(pntTmp);
74 | }
75 | }
76 | if (cmd == Commands.ClosePath)
77 | {
78 | if (geomType == GeomType.POLYGON && geomTmp.Count > 0)
79 | {
80 | geomTmp.Add(geomTmp[0]);
81 | }
82 | }
83 | }
84 |
85 | if (geomTmp.Count > 0)
86 | {
87 | geomOut.Add(geomTmp);
88 | }
89 |
90 | return geomOut;
91 | }
92 |
93 |
94 | ///
95 | ///
96 | ///
97 | /// Type of to be returned. Currently supported: int, long and float.
98 | /// Geometry in internal tile coordinates.
99 | /// Scale factor.
100 | ///
101 | public static List>> Scale(
102 | List>> inGeom
103 | , float scale = 1.0f
104 | )
105 | {
106 |
107 | List>> outGeom = new List>>();
108 | foreach (var inPart in inGeom)
109 | {
110 | List> outPart = new List>();
111 | foreach (var inVertex in inPart)
112 | {
113 | float fX = ((float)inVertex.X) * scale;
114 | float fY = ((float)inVertex.Y) * scale;
115 | // TODO: find a better solution to make this work
116 | // scaled value has to be converted to target type beforehand
117 | // casting to T only works via intermediate cast to object
118 | // suppose (typeof(T) == typeof(x))
119 | // works : T x = (T)(object)x;
120 | // doesn't work : T x = (T)x;
121 | if (typeof(T) == typeof(int))
122 | {
123 | int x = Convert.ToInt32(fX);
124 | int y = Convert.ToInt32(fY);
125 | outPart.Add(new Point2d((T)(object)x, (T)(object)y));
126 | }
127 | else if (typeof(T) == typeof(long))
128 | {
129 | long x = Convert.ToInt64(fX);
130 | long y = Convert.ToInt64(fY);
131 | outPart.Add(new Point2d((T)(object)x, (T)(object)y));
132 | }
133 | else if (typeof(T) == typeof(float))
134 | {
135 | float x = Convert.ToSingle(fX);
136 | float y = Convert.ToSingle(fY);
137 | outPart.Add(new Point2d((T)(object)x, (T)(object)y));
138 | }
139 | }
140 | outGeom.Add(outPart);
141 | }
142 |
143 | return outGeom;
144 | }
145 |
146 | private static Point2d zigzagDecode(long x, long y)
147 | {
148 |
149 | //TODO: verify speed improvements using
150 | // new Point2d(){X=x, Y=y} instead of
151 | // new Point3d(x, y);
152 |
153 | //return new Point2d(
154 | // ((x >> 1) ^ (-(x & 1))),
155 | // ((y >> 1) ^ (-(y & 1)))
156 | //);
157 | return new Point2d()
158 | {
159 | X = ((x >> 1) ^ (-(x & 1))),
160 | Y = ((y >> 1) ^ (-(y & 1)))
161 | };
162 | }
163 |
164 |
165 | }
166 | }
167 |
--------------------------------------------------------------------------------
/src/Geometry/Geometry.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using System.Globalization;
4 |
5 |
6 | namespace Mapbox.VectorTile.Geometry
7 | {
8 |
9 |
10 | #if (PORTABLE || WINDOWS_UWP) && !UNITY_5_4_OR_NEWER
11 | [AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
12 | public class DescriptionAttribute : Attribute {
13 | private readonly string description;
14 | public string Description { get { return description; } }
15 | public DescriptionAttribute(string description) {
16 | this.description = description;
17 | }
18 | }
19 | #endif
20 |
21 |
22 | ///
23 | /// Available geometry types
24 | ///
25 | public enum GeomType
26 | {
27 | UNKNOWN = 0,
28 | [Description("Point")]
29 | POINT = 1,
30 | [Description("LineString")]
31 | LINESTRING = 2,
32 | [Description("Polygon")]
33 | POLYGON = 3
34 | }
35 |
36 |
37 | ///
38 | /// Structure to hold a LatLng coordinate pair
39 | ///
40 | public struct LatLng
41 | {
42 | public double Lat { get; set; }
43 | public double Lng { get; set; }
44 |
45 | public override string ToString()
46 | {
47 | return string.Format(
48 | NumberFormatInfo.InvariantInfo
49 | , "{0:0.000000}/{1:0.000000}"
50 | , Lat
51 | , Lng);
52 | }
53 | }
54 |
55 |
56 | ///
57 | /// Structure to hold a 2D point coordinate pair
58 | ///
59 | public struct Point2d
60 | {
61 |
62 | public Point2d(T x, T y)
63 | {
64 | X = x;
65 | Y = y;
66 | }
67 |
68 | public T X; //performance: field instead of property
69 | public T Y; //performance: field instead of property
70 |
71 | public LatLng ToLngLat(ulong z, ulong x, ulong y, ulong extent, bool checkLatLngMax = false)
72 | {
73 |
74 | double size = (double)extent * Math.Pow(2, (double)z);
75 | double x0 = (double)extent * (double)x;
76 | double y0 = (double)extent * (double)y;
77 |
78 | double dblY = Convert.ToDouble(Y);
79 | double dblX = Convert.ToDouble(X);
80 | double y2 = 180d - (dblY + y0) * 360d / size;
81 | double lng = (dblX + x0) * 360d / size - 180d;
82 | double lat = 360d / Math.PI * Math.Atan(Math.Exp(y2 * Math.PI / 180d)) - 90d;
83 |
84 | if (checkLatLngMax)
85 | {
86 | if (lng < -180d || lng > 180d)
87 | {
88 | throw new ArgumentOutOfRangeException("Longitude out of range");
89 | }
90 | if (lat < -85.051128779806589d || lat > 85.051128779806589d)
91 | {
92 | throw new ArgumentOutOfRangeException("Latitude out of range");
93 | }
94 | }
95 |
96 | LatLng latLng = new LatLng()
97 | {
98 | Lat = lat,
99 | Lng = lng
100 | };
101 |
102 | return latLng;
103 | }
104 |
105 | public override string ToString()
106 | {
107 | return string.Format(NumberFormatInfo.InvariantInfo, "{0}/{1}", X, Y);
108 | }
109 |
110 | //#if !PORTABLE
111 |
112 | // public static explicit operator Point2d(Point2d v) {
113 | // TypeConverter converter = TypeDescriptor.GetConverter(typeof(float));
114 | // Point2d pnt = new Point2d();
115 | // pnt.X = (T)converter.ConvertTo(v.X, typeof(T));
116 | // pnt.Y = (T)converter.ConvertTo(v.Y, typeof(T));
117 | // return pnt;
118 | // }
119 |
120 | // public static explicit operator Point2d(Point2d v) {
121 | // TypeConverter converter = TypeDescriptor.GetConverter(typeof(int));
122 | // Point2d pnt = new Point2d();
123 | // pnt.X = (T)converter.ConvertTo(v.X, typeof(T));
124 | // pnt.Y = (T)converter.ConvertTo(v.Y, typeof(T));
125 | // return pnt;
126 | // }
127 |
128 | // public static explicit operator Point2d(Point2d v) {
129 | // TypeConverter converter = TypeDescriptor.GetConverter(typeof(long));
130 | // Point2d pnt = new Point2d();
131 | // pnt.X = (T)converter.ConvertTo(v.X, typeof(T));
132 | // pnt.Y = (T)converter.ConvertTo(v.Y, typeof(T));
133 | // return pnt;
134 | // }
135 | //#else
136 | // public static explicit operator Point2d(Point2d v) {
137 | // bool bla = typeof(IConvertible).IsAssignableFrom(T);
138 |
139 | // Point2d pnt = new Point2d();
140 | // return pnt;
141 | // }
142 | //#endif
143 |
144 | }
145 |
146 |
147 | }
148 |
--------------------------------------------------------------------------------
/src/Geometry/Geometry.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {F0967389-29C8-4D50-B397-9BB698F13ED6}
8 | Library
9 | Properties
10 | Geometry
11 | Mapbox.VectorTile.Geometry
12 | v3.5
13 | 512
14 |
15 |
16 |
17 | true
18 | ..\..\bin\
19 | DEBUG;TRACE
20 | full
21 | x64
22 | prompt
23 | MinimumRecommendedRules.ruleset
24 | false
25 |
26 |
27 | ..\..\bin\
28 | TRACE
29 | true
30 | pdbonly
31 | x64
32 | prompt
33 | MinimumRecommendedRules.ruleset
34 | false
35 |
36 |
37 | true
38 | ..\..\bin\
39 | DEBUG;TRACE
40 | full
41 | AnyCPU
42 | prompt
43 | MinimumRecommendedRules.ruleset
44 | false
45 |
46 |
47 | ..\..\bin\
48 | TRACE
49 | true
50 | pdbonly
51 | AnyCPU
52 | prompt
53 | MinimumRecommendedRules.ruleset
54 | false
55 |
56 |
57 | true
58 | bin\x64\Net20Debug\
59 | DEBUG;TRACE
60 | full
61 | x64
62 | prompt
63 | MinimumRecommendedRules.ruleset
64 |
65 |
66 | v2.0
67 | ..\..\bin\$(Configuration)\$(TargetFrameworkVersion)\
68 | true
69 | full
70 | DEBUG;TRACE;NET20
71 | AnyCPU
72 | prompt
73 | MinimumRecommendedRules.ruleset
74 | false
75 |
76 |
77 | v3.5
78 | ..\..\bin\$(Configuration)\$(TargetFrameworkVersion)\
79 | true
80 | full
81 | DEBUG;TRACE;NET35
82 | AnyCPU
83 | prompt
84 | MinimumRecommendedRules.ruleset
85 | false
86 |
87 |
88 | v4.6.2
89 | ..\..\bin\$(Configuration)\$(TargetFrameworkVersion)\
90 | true
91 | full
92 | DEBUG;TRACE;NET462
93 | AnyCPU
94 | prompt
95 | MinimumRecommendedRules.ruleset
96 | false
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 | Properties\AssemblyInfoVersion.cs
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 | {4bce42ee-c33f-4fa4-bfdd-86f3d45c647c}
119 | PbfReader
120 |
121 |
122 |
123 |
130 |
--------------------------------------------------------------------------------
/src/Geometry/GeometryPortable.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 10.0
6 | Debug
7 | AnyCPU
8 | {B6044F02-10A3-4637-962E-8B2F882DCD59}
9 | Library
10 | Properties
11 | Geometry
12 | Mapbox.VectorTile.Geometry
13 | en-US
14 | 512
15 | {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
16 | Profile7
17 | v4.5
18 |
19 |
20 | true
21 | full
22 | false
23 | ..\..\bin\PortableDebug\portable-net45+uap10\
24 | TRACE;DEBUG;PORTABLE;WINDOWS_UWP
25 | prompt
26 | 4
27 |
28 |
29 | pdbonly
30 | true
31 | bin\Release\
32 | TRACE
33 | prompt
34 | 4
35 |
36 |
37 |
38 |
39 | {e3ed95c9-42d9-4480-90e5-87f4fe60b8e2}
40 | PbfReaderPortable
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
58 |
--------------------------------------------------------------------------------
/src/Geometry/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Resources;
3 | using System.Runtime.CompilerServices;
4 | using System.Runtime.InteropServices;
5 |
6 | // General Information about an assembly is controlled through the following
7 | // set of attributes. Change these attribute values to modify the information
8 | // associated with an assembly.
9 | [assembly: AssemblyTitle("Geometry")]
10 | [assembly: AssemblyDescription("")]
11 | [assembly: AssemblyConfiguration("")]
12 | [assembly: AssemblyCompany("")]
13 | [assembly: AssemblyProduct("Geometry")]
14 | [assembly: AssemblyCopyright("Copyright © 2016")]
15 | [assembly: AssemblyTrademark("")]
16 | [assembly: AssemblyCulture("")]
17 | [assembly: NeutralResourcesLanguage("en-US")]
18 |
19 | // Setting ComVisible to false makes the types in this assembly not visible
20 | // to COM components. If you need to access a type in this assembly from
21 | // COM, set the ComVisible attribute to true on that type.
22 | [assembly: ComVisible(false)]
23 |
24 | // The following GUID is for the ID of the typelib if this project is exposed to COM
25 | [assembly: Guid("f0967389-29c8-4d50-b397-9bb698f13ed6")]
26 |
27 |
--------------------------------------------------------------------------------
/src/Geometry/Util.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using Mapbox.VectorTile.Geometry.InteralClipperLib;
3 |
4 |
5 | namespace Mapbox.VectorTile.Geometry
6 | {
7 |
8 | using Polygon = List;
9 | using Polygons = List>;
10 |
11 |
12 | ///
13 | /// Geometry related helper methods
14 | ///
15 | public static class UtilGeom
16 | {
17 |
18 |
19 | ///
20 | /// TO BE REMOVED!!! Processing geometries is out of scope.
21 | /// Clip geometries extending beyond the tile border.
22 | ///
23 | /// Raw tile geometries of the feature
24 | /// Geometry type of the feature
25 | /// Extent of the layer
26 | /// Units (in internal tile coordinates) to go beyond the tile border. Pass '0' to clip exactly at the tile border
27 | /// Factor for scaling the geometries
28 | ///
29 | public static List>> ClipGeometries(
30 | List>> geoms
31 | , GeomType geomType
32 | , long extent
33 | , uint bufferSize
34 | , float scale
35 | )
36 | {
37 |
38 | List>> retVal = new List>>();
39 |
40 | //points: simply remove them if one part of the coordinate pair is out of bounds:
41 | // <0 || >extent
42 | if (geomType == GeomType.POINT)
43 | {
44 | foreach (var geomPart in geoms)
45 | {
46 | List> outGeom = new List>();
47 | foreach (var geom in geomPart)
48 | {
49 | if (
50 | geom.X < (0L - bufferSize)
51 | || geom.Y < (0L - bufferSize)
52 | || geom.X > (extent + bufferSize)
53 | || geom.Y > (extent + bufferSize)
54 | )
55 | {
56 | continue;
57 | }
58 | outGeom.Add(geom);
59 | }
60 |
61 | if (outGeom.Count > 0)
62 | {
63 | retVal.Add(outGeom);
64 | }
65 | }
66 |
67 | return retVal;
68 | }
69 |
70 | //use clipper for lines and polygons
71 | bool closed = true;
72 | if (geomType == GeomType.LINESTRING) { closed = false; }
73 |
74 |
75 | Polygons subjects = new Polygons();
76 | Polygons clip = new Polygons(1);
77 | Polygons solution = new Polygons();
78 |
79 | clip.Add(new Polygon(4));
80 | clip[0].Add(new InternalClipper.IntPoint(0L - bufferSize, 0L - bufferSize));
81 | clip[0].Add(new InternalClipper.IntPoint(extent + bufferSize, 0L - bufferSize));
82 | clip[0].Add(new InternalClipper.IntPoint(extent + bufferSize, extent + bufferSize));
83 | clip[0].Add(new InternalClipper.IntPoint(0L - bufferSize, extent + bufferSize));
84 |
85 | foreach (var geompart in geoms)
86 | {
87 | Polygon part = new Polygon();
88 |
89 | foreach (var geom in geompart)
90 | {
91 | part.Add(new InternalClipper.IntPoint(geom.X, geom.Y));
92 | }
93 | subjects.Add(part);
94 | }
95 |
96 | InternalClipper.Clipper c = new InternalClipper.Clipper();
97 | c.AddPaths(subjects, InternalClipper.PolyType.ptSubject, closed);
98 | c.AddPaths(clip, InternalClipper.PolyType.ptClip, true);
99 |
100 | bool succeeded = false;
101 | if (geomType == GeomType.LINESTRING)
102 | {
103 | InternalClipper.PolyTree lineSolution = new InternalClipper.PolyTree();
104 | succeeded = c.Execute(
105 | InternalClipper.ClipType.ctIntersection
106 | , lineSolution
107 | , InternalClipper.PolyFillType.pftNonZero
108 | , InternalClipper.PolyFillType.pftNonZero
109 | );
110 | if (succeeded)
111 | {
112 | solution = InternalClipper.Clipper.PolyTreeToPaths(lineSolution);
113 | }
114 | }
115 | else
116 | {
117 | succeeded = c.Execute(
118 | InternalClipper.ClipType.ctIntersection
119 | , solution
120 | , InternalClipper.PolyFillType.pftNonZero
121 | , InternalClipper.PolyFillType.pftNonZero
122 | );
123 | }
124 |
125 | if (succeeded)
126 | {
127 | retVal = new List>>();
128 | foreach (var part in solution)
129 | {
130 | List> geompart = new List>();
131 | // HACK:
132 | // 1. clipper may or may not reverse order of vertices of LineStrings
133 | // 2. clipper semms to drop the first vertex of a Polygon
134 | // * We don't care about 1.
135 | // * Added a check for 2 and insert a copy of last vertex as first
136 | foreach (var geom in part)
137 | {
138 | geompart.Add(new Point2d() { X = geom.X, Y = geom.Y });
139 | }
140 | if (geomType == GeomType.POLYGON)
141 | {
142 | if (!geompart[0].Equals(geompart[geompart.Count - 1]))
143 | {
144 | geompart.Insert(0, geompart[geompart.Count - 1]);
145 | }
146 | }
147 | retVal.Add(geompart);
148 | }
149 |
150 | return retVal;
151 | }
152 | else
153 | {
154 | //if clipper was not successfull return original geometries
155 | return geoms;
156 | }
157 | }
158 |
159 |
160 |
161 |
162 | }
163 | }
164 |
--------------------------------------------------------------------------------
/src/PbfReader/Constants.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 |
5 | namespace Mapbox.VectorTile.Contants
6 | {
7 |
8 |
9 | ///
10 | /// PBF wire types
11 | ///
12 | public enum WireTypes
13 | {
14 | VARINT = 0,// varint: int32, int64, uint32, uint64, sint32, sint64, bool, enum
15 | FIXED64 = 1, // 64-bit: double, fixed64, sfixed64
16 | BYTES = 2, // length-delimited: string, bytes, embedded messages, packed repeated fields
17 | FIXED32 = 5, // 32-bit: float, fixed32, sfixed32
18 | UNDEFINED = 99
19 | }
20 |
21 |
22 | ///
23 | /// Vector tile geometry commands https://github.com/mapbox/vector-tile-spec/tree/master/2.1#431-command-integers
24 | ///
25 | public enum Commands
26 | {
27 | MoveTo = 1,
28 | LineTo = 2,
29 | ClosePath = 7
30 | }
31 |
32 |
33 | ///
34 | /// Root types contained in the vector tile. Currently just 'Layers' https://github.com/mapbox/vector-tile-spec/blob/master/2.1/vector_tile.proto#L75
35 | ///
36 | public enum TileType
37 | {
38 | Layers = 3
39 | }
40 |
41 |
42 | ///
43 | /// Types contained in a layer https://github.com/mapbox/vector-tile-spec/blob/master/2.1/vector_tile.proto#L50-L73
44 | ///
45 | public enum LayerType
46 | {
47 | Version = 15,
48 | Name = 1,
49 | Features = 2,
50 | Keys = 3,
51 | Values = 4,
52 | Extent = 5
53 | }
54 |
55 |
56 | ///
57 | /// Types contained in a feature https://github.com/mapbox/vector-tile-spec/blob/master/2.1/vector_tile.proto#L31-L47
58 | ///
59 | public enum FeatureType
60 | {
61 | Id = 1,
62 | Tags = 2,
63 | Type = 3,
64 | Geometry = 4,
65 | Raster = 5
66 | }
67 |
68 |
69 | ///
70 | /// Available ypes for values https://github.com/mapbox/vector-tile-spec/blob/master/2.1/vector_tile.proto#L17-L28
71 | ///
72 | public enum ValueType
73 | {
74 | String = 1,
75 | Float = 2,
76 | Double = 3,
77 | Int = 4,
78 | UInt = 5,
79 | SInt = 6,
80 | Bool = 7
81 | }
82 |
83 |
84 | ///
85 | /// [wip] Investigate how to increase decoding speed. Looking up values in enums is slow
86 | ///
87 | public static class ConstantsAsDictionary
88 | {
89 |
90 |
91 | ///
92 | /// Root types contained in the vector tile. Currently just 'Layers' https://github.com/mapbox/vector-tile-spec/blob/master/2.1/vector_tile.proto#L75
93 | ///
94 | public static readonly Dictionary TileType = new Dictionary()
95 | {
96 | {3, "Layers" }
97 | };
98 |
99 |
100 | ///
101 | /// Types contained in a layer https://github.com/mapbox/vector-tile-spec/blob/master/2.1/vector_tile.proto#L50-L73
102 | ///
103 | public static readonly Dictionary LayerType = new Dictionary()
104 | {
105 | {15, "Version" },
106 | {1, "Name" },
107 | {2,"Features" },
108 | {3, "Keys" },
109 | {4, "Values" },
110 | {5, "Extent" }
111 | };
112 |
113 | ///
114 | /// Types contained in a feature https://github.com/mapbox/vector-tile-spec/blob/master/2.1/vector_tile.proto#L31-L47
115 | ///
116 | public static readonly Dictionary FeatureType = new Dictionary()
117 | {
118 | { 1, "Id"},
119 | { 2, "Tags"},
120 | { 3, "Type"},
121 | { 4, "Geometry"},
122 | { 5, "Raster"}
123 | };
124 |
125 |
126 | ///
127 | /// Available geometry types https://github.com/mapbox/vector-tile-spec/tree/master/2.1#434-geometry-types
128 | ///
129 | public static readonly Dictionary GeomType = new Dictionary()
130 | {
131 | { 0, "Unknown"},
132 | { 1, "Point"},
133 | { 2, "LineString"},
134 | { 3, "Polygon"}
135 | };
136 | }
137 |
138 | }
--------------------------------------------------------------------------------
/src/PbfReader/PbfReader.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Globalization;
3 | using System.Text;
4 | using Mapbox.VectorTile.Contants;
5 |
6 |
7 | namespace Mapbox.VectorTile
8 | {
9 |
10 |
11 | //TODO: implement DataView using the same byte array instead of copying byte arrays
12 | //public struct DataView {
13 | // public ulong start;
14 | // public ulong end;
15 | //}
16 |
17 |
18 | ///
19 | /// Low level protobuf (PBF) decoder https://developers.google.com/protocol-buffers/docs/overview
20 | ///
21 | public class PbfReader
22 | {
23 |
24 |
25 | /// Tag at current position
26 | public int Tag { get; private set; }
27 | /// Value at current position
28 | public ulong Value { get; private set; }
29 | //public ulong Pos { get; private set; }
30 | /// Wire type at current position
31 | public WireTypes WireType { get; private set; }
32 |
33 |
34 | private byte[] _buffer;
35 | private ulong _length;
36 | private ulong _pos;
37 |
38 |
39 | ///
40 | /// PbfReader constructor
41 | ///
42 | /// Byte array containing the raw (already unzipped) tile data
43 | public PbfReader(byte[] tileBuffer)
44 | {
45 | _buffer = tileBuffer;
46 | _length = (ulong)_buffer.Length;
47 | WireType = WireTypes.UNDEFINED;
48 | }
49 |
50 |
51 | ///
52 | /// Gets Varint at current position, moves to position after Varint.
53 | /// Throws exception if Varint cannot be decoded
54 | ///
55 | /// Decoded Varint
56 | public long Varint()
57 | {
58 | // convert to base 128 varint
59 | // https://developers.google.com/protocol-buffers/docs/encoding
60 | int shift = 0;
61 | long result = 0;
62 | while (shift < 64)
63 | {
64 | byte b = _buffer[_pos];
65 | result |= (long)(b & 0x7F) << shift;
66 | _pos++;
67 | if ((b & 0x80) == 0)
68 | {
69 | return result;
70 | }
71 | shift += 7;
72 | }
73 | throw new System.ArgumentException("Invalid varint");
74 |
75 | }
76 |
77 |
78 | ///
79 | /// Get a view into the buffer.
80 | /// TODO: refactor to return a DataView instead of a byte array
81 | ///
82 | /// Byte array containing the view
83 | public byte[] View()
84 | {
85 | // return layer/feature subsections of the main stream
86 | if (Tag == 0)
87 | {
88 | throw new System.Exception("call next() before accessing field value");
89 | };
90 | if (WireType != WireTypes.BYTES)
91 | {
92 | throw new System.Exception("not of type string, bytes or message");
93 | }
94 |
95 | ulong skipBytes = (ulong)Varint();
96 | SkipBytes(skipBytes);
97 |
98 | byte[] buf = new byte[skipBytes];
99 | System.Array.Copy(_buffer, (int)_pos - (int)skipBytes, buf, 0, (int)skipBytes);
100 |
101 | return buf;
102 | }
103 |
104 |
105 | ///
106 | /// Get repeated `uint`s a current position, move position
107 | ///
108 | /// List of decoded `uint`s
109 | public List GetPackedUnit32()
110 | {
111 | List values = new List(200);
112 | ulong sizeInByte = (ulong)Varint();
113 | ulong end = _pos + sizeInByte;
114 | while (_pos < end)
115 | {
116 | values.Add((uint)Varint());
117 | }
118 | return values;
119 | }
120 |
121 |
122 | public List GetPackedSInt32()
123 | {
124 | List values = new List(200);
125 | ulong sizeInByte = (ulong)Varint();
126 | ulong end = _pos + sizeInByte;
127 | while (_pos < end)
128 | {
129 | values.Add(decodeZigZag32((int)Varint()));
130 | }
131 | return values;
132 | }
133 |
134 |
135 | public List GetPackedSInt64()
136 | {
137 | List values = new List(200);
138 | ulong sizeInByte = (ulong)Varint();
139 | ulong end = _pos + sizeInByte;
140 | while (_pos < end)
141 | {
142 | values.Add(decodeZigZag64((long)Varint()));
143 | }
144 | return values;
145 | }
146 |
147 |
148 | private int decodeZigZag32(int value)
149 | {
150 | return (value >> 1) ^ -(value & 1);
151 | }
152 |
153 |
154 | private long decodeZigZag64(long value)
155 | {
156 | return (value >> 1) ^ -(value & 1);
157 | }
158 |
159 |
160 | ///
161 | /// Get double at current position, move to next position
162 | ///
163 | /// Decoded double
164 | public double GetDouble()
165 | {
166 | byte[] buf = new byte[8];
167 | System.Array.Copy(_buffer, (int)_pos, buf, 0, 8);
168 | _pos += 8;
169 | double dblVal = System.BitConverter.ToDouble(buf, 0);
170 | return dblVal;
171 | }
172 |
173 |
174 | ///
175 | /// Get float a current position, move to next position
176 | ///
177 | /// Decoded float
178 | public float GetFloat()
179 | {
180 | byte[] buf = new byte[4];
181 | System.Array.Copy(_buffer, (int)_pos, buf, 0, 4);
182 | _pos += 4;
183 | float snglVal = System.BitConverter.ToSingle(buf, 0);
184 | return snglVal;
185 | }
186 |
187 |
188 | ///
189 | /// Get bytes as string
190 | ///
191 | /// Number of bytes to read
192 | /// Decoded string
193 | public string GetString(ulong length)
194 | {
195 | byte[] buf = new byte[length];
196 | System.Array.Copy(_buffer, (int)_pos, buf, 0, (int)length);
197 | _pos += length;
198 | return Encoding.UTF8.GetString(buf, 0, buf.Length);
199 | }
200 |
201 |
202 | ///
203 | /// Move to next byte and set wire type. Throws exeception if tag is out of range
204 | ///
205 | /// Returns false if at end of buffer
206 | public bool NextByte()
207 | {
208 | if (_pos >= _length)
209 | {
210 | return false;
211 | }
212 | // get and process the next byte in the buffer
213 | // return true until end of stream
214 | Value = (ulong)Varint();
215 | Tag = (int)Value >> 3;
216 | if (
217 | (Tag == 0 || Tag >= 19000)
218 | && (Tag > 19999 || Tag <= ((1 << 29) - 1))
219 | )
220 | {
221 | throw new System.Exception("tag out of range");
222 | }
223 | WireType = (WireTypes)(Value & 0x07);
224 | return true;
225 | }
226 |
227 |
228 | ///
229 | /// Skip over a Varint
230 | ///
231 | public void SkipVarint()
232 | {
233 | Varint();
234 | //while (0 == (_buffer[Pos] & 0x80))
235 | //{
236 | // Pos++;
237 | // if (Pos >= _length)
238 | // {
239 | // throw new Exception("Truncated message.");
240 | // }
241 | //}
242 |
243 | //if (Pos > _length)
244 | //{
245 | // throw new Exception("Truncated message.");
246 | //}
247 | }
248 |
249 |
250 | ///
251 | /// Skip bytes
252 | ///
253 | /// Number of bytes to skip
254 | public void SkipBytes(ulong skip)
255 | {
256 | if (_pos + skip > _length)
257 | {
258 | string msg = string.Format(NumberFormatInfo.InvariantInfo, "[SkipBytes()] skip:{0} pos:{1} len:{2}", skip, _pos, _length);
259 | throw new System.Exception(msg);
260 | }
261 | _pos += skip;
262 | }
263 |
264 |
265 | ///
266 | /// Automatically skip bytes based on wire type
267 | ///
268 | /// New position within the byte array
269 | public ulong Skip()
270 | {
271 | if (Tag == 0)
272 | {
273 | throw new System.Exception("call next() before calling skip()");
274 | }
275 |
276 | switch (WireType)
277 | {
278 | case WireTypes.VARINT:
279 | SkipVarint();
280 | break;
281 | case WireTypes.BYTES:
282 | SkipBytes((ulong)Varint());
283 | break;
284 | case WireTypes.FIXED32:
285 | SkipBytes(4);
286 | break;
287 | case WireTypes.FIXED64:
288 | SkipBytes(8);
289 | break;
290 | case WireTypes.UNDEFINED:
291 | throw new System.Exception("undefined wire type");
292 | default:
293 | throw new System.Exception("unknown wire type");
294 | }
295 |
296 | return _pos;
297 | }
298 |
299 |
300 |
301 | }
302 | }
303 |
--------------------------------------------------------------------------------
/src/PbfReader/PbfReader.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {4BCE42EE-C33F-4FA4-BFDD-86F3D45C647C}
8 | Library
9 | Properties
10 | PbfReader
11 | Mapbox.VectorTile.PbfReader
12 | v3.5
13 | 512
14 |
15 |
16 |
17 | true
18 | ..\..\bin\
19 | DEBUG;TRACE
20 | full
21 | x64
22 | prompt
23 | MinimumRecommendedRules.ruleset
24 | false
25 |
26 |
27 | ..\..\bin\
28 | TRACE
29 | true
30 | pdbonly
31 | x64
32 | prompt
33 | MinimumRecommendedRules.ruleset
34 | false
35 |
36 |
37 | true
38 | ..\..\bin\
39 | DEBUG;TRACE
40 | full
41 | AnyCPU
42 | prompt
43 | MinimumRecommendedRules.ruleset
44 | false
45 |
46 |
47 | ..\..\bin\
48 | TRACE
49 | true
50 | pdbonly
51 | AnyCPU
52 | prompt
53 | MinimumRecommendedRules.ruleset
54 | false
55 |
56 |
57 | v2.0
58 | ..\..\bin\$(Configuration)\$(TargetFrameworkVersion)\
59 | true
60 | full
61 | DEBUG;TRACE;NET20
62 | AnyCPU
63 | prompt
64 | MinimumRecommendedRules.ruleset
65 | false
66 |
67 |
68 | v3.5
69 | ..\..\bin\$(Configuration)\$(TargetFrameworkVersion)\
70 | true
71 | full
72 | DEBUG;TRACE;NET35
73 | AnyCPU
74 | prompt
75 | MinimumRecommendedRules.ruleset
76 | false
77 |
78 |
79 | v4.6.2
80 | ..\..\bin\$(Configuration)\$(TargetFrameworkVersion)\
81 | true
82 | full
83 | DEBUG;TRACE;NET462
84 | AnyCPU
85 | prompt
86 | MinimumRecommendedRules.ruleset
87 | false
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 | Properties\AssemblyInfoVersion.cs
96 |
97 |
98 |
99 |
100 |
101 |
102 |
109 |
--------------------------------------------------------------------------------
/src/PbfReader/PbfReaderPortable.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 10.0
6 | Debug
7 | AnyCPU
8 | {E3ED95C9-42D9-4480-90E5-87F4FE60B8E2}
9 | Library
10 | Properties
11 | PbfReader
12 | Mapbox.VectorTile.PbfReader
13 | en-US
14 | 512
15 | {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
16 | Profile7
17 | v4.5
18 |
19 |
20 | true
21 | full
22 | false
23 | ..\..\bin\PortableDebug\portable-net45+uap10\
24 | TRACE;DEBUG;PORTABLE;WINDOWS_UWP
25 | prompt
26 | 4
27 |
28 |
29 | pdbonly
30 | true
31 | bin\Release\
32 | TRACE
33 | prompt
34 | 4
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
49 |
--------------------------------------------------------------------------------
/src/PbfReader/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Resources;
3 | using System.Runtime.CompilerServices;
4 | using System.Runtime.InteropServices;
5 |
6 | // General Information about an assembly is controlled through the following
7 | // set of attributes. Change these attribute values to modify the information
8 | // associated with an assembly.
9 | [assembly: AssemblyTitle("PbfReader")]
10 | [assembly: AssemblyDescription("")]
11 | [assembly: AssemblyConfiguration("")]
12 | [assembly: AssemblyCompany("")]
13 | [assembly: AssemblyProduct("PbfReader")]
14 | [assembly: AssemblyCopyright("Copyright © 2016")]
15 | [assembly: AssemblyTrademark("")]
16 | [assembly: AssemblyCulture("")]
17 | [assembly: NeutralResourcesLanguage("en-US")]
18 |
19 | // Setting ComVisible to false makes the types in this assembly not visible
20 | // to COM components. If you need to access a type in this assembly from
21 | // COM, set the ComVisible attribute to true on that type.
22 | [assembly: ComVisible(false)]
23 |
24 | // The following GUID is for the ID of the typelib if this project is exposed to COM
25 | [assembly: Guid("4bce42ee-c33f-4fa4-bfdd-86f3d45c647c")]
26 |
27 |
--------------------------------------------------------------------------------
/src/VectorTileReader/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Resources;
3 | using System.Runtime.CompilerServices;
4 | using System.Runtime.InteropServices;
5 |
6 | // General Information about an assembly is controlled through the following
7 | // set of attributes. Change these attribute values to modify the information
8 | // associated with an assembly.
9 | [assembly: AssemblyTitle("VectorTileReader")]
10 | [assembly: AssemblyDescription("")]
11 | [assembly: AssemblyConfiguration("")]
12 | [assembly: AssemblyCompany("")]
13 | [assembly: AssemblyProduct("VectorTileReader")]
14 | [assembly: AssemblyCopyright("Copyright © 2016")]
15 | [assembly: AssemblyTrademark("")]
16 | [assembly: AssemblyCulture("")]
17 | [assembly: NeutralResourcesLanguage("en-US")]
18 |
19 | // Setting ComVisible to false makes the types in this assembly not visible
20 | // to COM components. If you need to access a type in this assembly from
21 | // COM, set the ComVisible attribute to true on that type.
22 | [assembly: ComVisible(false)]
23 |
24 | // The following GUID is for the ID of the typelib if this project is exposed to COM
25 | [assembly: Guid("4656b308-1492-4a22-a73e-06bf6aa858f2")]
26 |
--------------------------------------------------------------------------------
/src/VectorTileReader/VectorTile.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Diagnostics;
3 | using System.Collections.ObjectModel;
4 |
5 |
6 | namespace Mapbox.VectorTile
7 | {
8 |
9 |
10 | ///
11 | /// Class to access the tile data
12 | ///
13 | [DebuggerDisplay("{Zoom}/{TileColumn}/{TileRow}")]
14 | public class VectorTile
15 | {
16 |
17 |
18 | ///
19 | /// Class to access the tile data
20 | ///
21 | /// Byte array containing the raw (already unzipped) tile data
22 | /// If true, run checks if the tile contains valid data. Decreases decoding speed.
23 | public VectorTile(byte[] data, bool validate = true)
24 | {
25 | _VTR = new VectorTileReader(data, validate);
26 | }
27 |
28 |
29 | private VectorTileReader _VTR;
30 |
31 |
32 | ///
33 | /// Collection of layers contained in the tile
34 | ///
35 | /// Collection of layer names
36 | public ReadOnlyCollection LayerNames()
37 | {
38 | return _VTR.LayerNames();
39 | }
40 |
41 |
42 | ///
43 | /// Get a tile layer by name
44 | ///
45 | /// Name of the layer to request
46 | /// Decoded
47 | public VectorTileLayer GetLayer(string layerName)
48 | {
49 | return _VTR.GetLayer(layerName);
50 | }
51 |
52 |
53 |
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/VectorTileReader/VectorTileFeature.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using Mapbox.VectorTile.Geometry;
3 | using System;
4 |
5 |
6 | namespace Mapbox.VectorTile
7 | {
8 |
9 |
10 | public class VectorTileFeature
11 | {
12 |
13 |
14 | ///
15 | /// Initialize VectorTileFeature
16 | ///
17 | /// Parent
18 | public VectorTileFeature(VectorTileLayer layer, uint? clipBuffer = null, float scale = 1.0f)
19 | {
20 | _layer = layer;
21 | _clipBuffer = clipBuffer;
22 | _scale = scale;
23 | Tags = new List();
24 | }
25 |
26 |
27 | private VectorTileLayer _layer;
28 | // TODO: how to cache without using object
29 | // may a dictionary with parameters clip and scale as key to keep different requests fast
30 | private object _cachedGeometry;
31 | private uint? _clipBuffer;
32 | private float? _scale;
33 | private float? _previousScale; //cache previous scale to not return
34 |
35 |
36 | /// Id of this feature https://github.com/mapbox/vector-tile-spec/blob/master/2.1/vector_tile.proto#L32
37 | public ulong Id { get; set; }
38 |
39 |
40 | /// Parent this feature belongs too
41 | public VectorTileLayer Layer { get { return _layer; } }
42 |
43 |
44 | /// of this feature
45 | public GeomType GeometryType { get; set; }
46 |
47 |
48 | /// Geometry in internal tile coordinates
49 | public List GeometryCommands { get; set; }
50 |
51 |
52 | public List>> Geometry(
53 | uint? clipBuffer = null
54 | , float? scale = null
55 | )
56 | {
57 |
58 | // parameters passed to this method override parameters passed to the constructor
59 | if (_clipBuffer.HasValue && !clipBuffer.HasValue) { clipBuffer = _clipBuffer; }
60 | if (_scale.HasValue && !scale.HasValue) { scale = _scale; }
61 |
62 | // TODO: how to cache 'finalGeom' without making whole class generic???
63 | // and without using an object (boxing) ???
64 | List>> finalGeom = _cachedGeometry as List>>;
65 | if (null != finalGeom && scale == _previousScale)
66 | {
67 | return finalGeom;
68 | }
69 |
70 | //decode commands and coordinates
71 | List>> geom = DecodeGeometry.GetGeometry(
72 | _layer.Extent
73 | , GeometryType
74 | , GeometryCommands
75 | , scale.Value
76 | );
77 | if (clipBuffer.HasValue)
78 | {
79 | // HACK !!!
80 | // work around a 'feature' of clipper where the ring order gets mixed up
81 | // with multipolygons containing holes
82 | if (geom.Count < 2 || GeometryType != GeomType.POLYGON)
83 | {
84 | // work on points, lines and single part polygons as before
85 | geom = UtilGeom.ClipGeometries(geom, GeometryType, (long)_layer.Extent, clipBuffer.Value, scale.Value);
86 | }
87 | else
88 | {
89 | // process every ring of a polygon in a separate loop
90 | List>> newGeom = new List>>();
91 | int geomCount = geom.Count;
92 | for (int i = 0; i < geomCount; i++)
93 | {
94 | List> part = geom[i];
95 | List>> tmp = new List>>();
96 | // flip order of inner rings to look like outer rings
97 | bool isInner = signedPolygonArea(part) >= 0;
98 | if (isInner) { part.Reverse(); }
99 | tmp.Add(part);
100 | tmp = UtilGeom.ClipGeometries(tmp, GeometryType, (long)_layer.Extent, clipBuffer.Value, scale.Value);
101 | // ring was completely outside of clip border
102 | if (0 == tmp.Count)
103 | {
104 | continue;
105 | }
106 | // one part might result in several geoms after clipping, eg 'u'-shape where the
107 | // lower part is completely beyond the actual tile border but still within the buffer
108 | foreach (var item in tmp)
109 | {
110 | // flip winding order of inner rings back
111 | if (isInner) { item.Reverse(); }
112 | newGeom.Add(item);
113 | }
114 | }
115 | geom = newGeom;
116 | }
117 | }
118 |
119 | //HACK: use 'Scale' to convert to too
120 | finalGeom = DecodeGeometry.Scale(geom, scale.Value);
121 |
122 | //set field needed for next iteration
123 | _previousScale = scale;
124 | _cachedGeometry = finalGeom;
125 |
126 | return finalGeom;
127 | }
128 |
129 |
130 | private float signedPolygonArea(List> vertices)
131 | {
132 | int num_points = vertices.Count - 1;
133 | float area = 0;
134 | for (int i = 0; i < num_points; i++)
135 | {
136 | area +=
137 | (vertices[i + 1].X - vertices[i].X) *
138 | (vertices[i + 1].Y + vertices[i].Y) / 2;
139 | }
140 | return area;
141 | }
142 |
143 |
144 | /// Tags to resolve properties https://github.com/mapbox/vector-tile-spec/tree/master/2.1#44-feature-attributes
145 | public List Tags { get; set; }
146 |
147 |
148 | ///
149 | /// Get properties of this feature. Throws exception if there is an uneven number of feature tag ids
150 | ///
151 | /// Dictionary of this feature's properties
152 | public Dictionary GetProperties()
153 | {
154 |
155 | if (0 != Tags.Count % 2)
156 | {
157 | throw new Exception(string.Format("Layer [{0}]: uneven number of feature tag ids", _layer.Name));
158 | }
159 | Dictionary properties = new Dictionary();
160 | int tagCount = Tags.Count;
161 | for (int i = 0; i < tagCount; i += 2)
162 | {
163 | properties.Add(_layer.Keys[Tags[i]], _layer.Values[Tags[i + 1]]);
164 | }
165 | return properties;
166 | }
167 |
168 |
169 | ///
170 | /// Get property by name
171 | ///
172 | /// Name of the property to request
173 | /// Value of the requested property
174 | public object GetValue(string key)
175 | {
176 |
177 | var idxKey = _layer.Keys.IndexOf(key);
178 | if (-1 == idxKey)
179 | {
180 | throw new Exception(string.Format("Key [{0}] does not exist", key));
181 | }
182 |
183 | int tagCount = Tags.Count;
184 | for (int i = 0; i < tagCount; i++)
185 | {
186 | if (idxKey == Tags[i])
187 | {
188 | return _layer.Values[Tags[i + 1]];
189 | }
190 | }
191 | return null;
192 | }
193 |
194 |
195 |
196 | }
197 | }
198 |
--------------------------------------------------------------------------------
/src/VectorTileReader/VectorTileLayer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 |
5 | namespace Mapbox.VectorTile
6 | {
7 |
8 |
9 | ///
10 | /// Class to access a vector tile layer
11 | ///
12 | [DebuggerDisplay("Layer {Name}")]
13 | public class VectorTileLayer
14 | {
15 |
16 |
17 | ///
18 | /// Class to access a vector tile layer
19 | ///
20 | public VectorTileLayer()
21 | {
22 | _FeaturesData = new List();
23 | Keys = new List();
24 | Values = new List