├── .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: [![nuget.org](https://img.shields.io/nuget/v/Mapbox.VectorTile.svg)](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: [![Build Status](https://travis-ci.com/mapbox/vector-tile-cs.svg?token=hLpUd9oZwpjSs5JzfqFa&branch=master)](https://travis-ci.com/mapbox/vector-tile-cs) 16 | * AppVeyor: [![Build status](https://ci.appveyor.com/api/projects/status/k8u69w8u13f7i0a7/branch/master?svg=true)](https://ci.appveyor.com/project/Mapbox/vector-tile-cs/branch/master) 17 | * Coveralls: [![Coverage Status](https://coveralls.io/repos/github/mapbox/vector-tile-cs/badge.svg?branch=master&t=q2Lud9)](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(); 25 | } 26 | 27 | 28 | /// 29 | /// Initialize vector tile layer with data 30 | /// 31 | /// Raw layer data as byte array 32 | public VectorTileLayer(byte[] data) : this() 33 | { 34 | Data = data; 35 | } 36 | 37 | 38 | /// Raw byte array data 39 | public byte[] Data { get; private set; } 40 | 41 | 42 | /// 43 | /// Get number of features. 44 | /// 45 | /// Number of features in this layer 46 | public int FeatureCount() 47 | { 48 | return _FeaturesData.Count; 49 | } 50 | 51 | 52 | /// 53 | /// Get a feature of this layer 54 | /// 55 | /// Index of the feature to request 56 | /// 57 | /// 'null': returns the geometries unaltered as they are in the vector tile. 58 | /// Any value >=0 clips a border with the size around the tile. 59 | /// These are not pixels but the same units as the 'extent' of the layer. 60 | /// 61 | /// 62 | public VectorTileFeature GetFeature(int feature, uint? clipBuffer = null, float scale = 1.0f) 63 | { 64 | return VectorTileReader.GetFeature(this, _FeaturesData[feature], true, clipBuffer, scale); 65 | } 66 | 67 | 68 | public void AddFeatureData(byte[] data) 69 | { 70 | _FeaturesData.Add(data); 71 | } 72 | 73 | 74 | /// Name of this layer https://github.com/mapbox/vector-tile-spec/blob/master/2.1/vector_tile.proto#L57 75 | public string Name { get; set; } 76 | 77 | 78 | /// Version of this layer https://github.com/mapbox/vector-tile-spec/blob/master/2.1/vector_tile.proto#L55 79 | public ulong Version { get; set; } 80 | 81 | 82 | /// Extent of this layer https://github.com/mapbox/vector-tile-spec/blob/master/2.1/vector_tile.proto#L70 83 | public ulong Extent { get; set; } 84 | 85 | 86 | /// Raw data of the features contained in this layer 87 | private List _FeaturesData { get; set; } 88 | 89 | 90 | /// 91 | /// TODO: switch to 'dynamic' when Unity supports .Net 4.5 92 | /// Values contained in this layer 93 | /// 94 | public List Values { get; set; } 95 | 96 | 97 | /// 98 | /// Keys contained in this layer 99 | /// 100 | public List Keys { get; set; } 101 | 102 | 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/VectorTileReader/VectorTileReader.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Collections.ObjectModel; 3 | using System.Globalization; 4 | using System.Text; 5 | using Mapbox.VectorTile.Contants; 6 | using Mapbox.VectorTile.Geometry; 7 | 8 | #if !NET20 9 | using System.Linq; 10 | #endif 11 | 12 | namespace Mapbox.VectorTile 13 | { 14 | 15 | 16 | 17 | 18 | /// 19 | /// Mail vector tile reader class 20 | /// 21 | public class VectorTileReader 22 | { 23 | 24 | /// 25 | /// Initialize VectorTileReader 26 | /// 27 | /// Byte array containing the raw (already unzipped) tile data 28 | /// If true, run checks if the tile contains valid data. Decreases decoding speed. 29 | public VectorTileReader(byte[] data, bool validate = true) 30 | { 31 | if (null == data) 32 | { 33 | throw new System.Exception("Tile data cannot be null"); 34 | } 35 | if (data.Length < 1) 36 | { 37 | throw new System.Exception("Tile data cannot be empty"); 38 | } 39 | if (data[0] == 0x1f && data[1] == 0x8b) 40 | { 41 | throw new System.Exception("Tile data is zipped"); 42 | } 43 | 44 | _Validate = validate; 45 | layers(data); 46 | } 47 | 48 | 49 | private Dictionary _Layers = new Dictionary(); 50 | private bool _Validate; 51 | 52 | 53 | private void layers(byte[] data) 54 | { 55 | PbfReader tileReader = new PbfReader(data); 56 | while (tileReader.NextByte()) 57 | { 58 | if (_Validate) 59 | { 60 | if (!ConstantsAsDictionary.TileType.ContainsKey(tileReader.Tag)) 61 | { 62 | throw new System.Exception(string.Format("Unknown tile tag: {0}", tileReader.Tag)); 63 | } 64 | } 65 | if (tileReader.Tag == (int)TileType.Layers) 66 | { 67 | string name = null; 68 | byte[] layerMessage = tileReader.View(); 69 | PbfReader layerView = new PbfReader(layerMessage); 70 | while (layerView.NextByte()) 71 | { 72 | if (layerView.Tag == (int)LayerType.Name) 73 | { 74 | ulong strLen = (ulong)layerView.Varint(); 75 | name = layerView.GetString(strLen); 76 | } 77 | else 78 | { 79 | layerView.Skip(); 80 | } 81 | } 82 | if (_Validate) 83 | { 84 | if (string.IsNullOrEmpty(name)) 85 | { 86 | throw new System.Exception("Layer missing name"); 87 | } 88 | if (_Layers.ContainsKey(name)) 89 | { 90 | throw new System.Exception(string.Format("Duplicate layer names: {0}", name)); 91 | } 92 | } 93 | _Layers.Add(name, layerMessage); 94 | } 95 | else 96 | { 97 | tileReader.Skip(); 98 | } 99 | } 100 | } 101 | 102 | 103 | /// 104 | /// Collection of layers contained in the tile 105 | /// 106 | /// Collection of layer names 107 | public ReadOnlyCollection LayerNames() 108 | { 109 | #if NET20 || PORTABLE || WINDOWS_UWP 110 | string[] lyrNames = new string[_Layers.Keys.Count]; 111 | _Layers.Keys.CopyTo(lyrNames, 0); 112 | return new ReadOnlyCollection(lyrNames); 113 | #else 114 | return _Layers.Keys.ToList().AsReadOnly(); 115 | #endif 116 | } 117 | 118 | /// 119 | /// Get a tile layer by name 120 | /// 121 | /// Name of the layer to request 122 | /// Decoded 123 | public VectorTileLayer GetLayer(string name) 124 | { 125 | if (!_Layers.ContainsKey(name)) 126 | { 127 | return null; 128 | } 129 | 130 | return getLayer(_Layers[name]); 131 | } 132 | 133 | 134 | private VectorTileLayer getLayer(byte[] data) 135 | { 136 | VectorTileLayer layer = new VectorTileLayer(data); 137 | PbfReader layerReader = new PbfReader(layer.Data); 138 | while (layerReader.NextByte()) 139 | { 140 | int layerType = layerReader.Tag; 141 | if (_Validate) 142 | { 143 | if (!ConstantsAsDictionary.LayerType.ContainsKey(layerType)) 144 | { 145 | throw new System.Exception(string.Format("Unknown layer type: {0}", layerType)); 146 | } 147 | } 148 | switch ((LayerType)layerType) 149 | { 150 | case LayerType.Version: 151 | ulong version = (ulong)layerReader.Varint(); 152 | layer.Version = version; 153 | break; 154 | case LayerType.Name: 155 | ulong strLength = (ulong)layerReader.Varint(); 156 | layer.Name = layerReader.GetString(strLength); 157 | break; 158 | case LayerType.Extent: 159 | layer.Extent = (ulong)layerReader.Varint(); 160 | break; 161 | case LayerType.Keys: 162 | byte[] keyBuffer = layerReader.View(); 163 | string key = Encoding.UTF8.GetString(keyBuffer, 0, keyBuffer.Length); 164 | layer.Keys.Add(key); 165 | break; 166 | case LayerType.Values: 167 | byte[] valueBuffer = layerReader.View(); 168 | PbfReader valReader = new PbfReader(valueBuffer); 169 | while (valReader.NextByte()) 170 | { 171 | switch ((ValueType)valReader.Tag) 172 | { 173 | case ValueType.String: 174 | byte[] stringBuffer = valReader.View(); 175 | string value = Encoding.UTF8.GetString(stringBuffer, 0, stringBuffer.Length); 176 | layer.Values.Add(value); 177 | break; 178 | case ValueType.Float: 179 | float snglVal = valReader.GetFloat(); 180 | layer.Values.Add(snglVal); 181 | break; 182 | case ValueType.Double: 183 | double dblVal = valReader.GetDouble(); 184 | layer.Values.Add(dblVal); 185 | break; 186 | case ValueType.Int: 187 | long i64 = valReader.Varint(); 188 | layer.Values.Add(i64); 189 | break; 190 | case ValueType.UInt: 191 | long u64 = valReader.Varint(); 192 | layer.Values.Add(u64); 193 | break; 194 | case ValueType.SInt: 195 | long s64 = valReader.Varint(); 196 | layer.Values.Add(s64); 197 | break; 198 | case ValueType.Bool: 199 | long b = valReader.Varint(); 200 | layer.Values.Add(b == 1); 201 | break; 202 | default: 203 | throw new System.Exception(string.Format( 204 | NumberFormatInfo.InvariantInfo 205 | , "NOT IMPLEMENTED valueReader.Tag:{0} valueReader.WireType:{1}" 206 | , valReader.Tag 207 | , valReader.WireType 208 | )); 209 | //uncomment the following lines when not throwing!! 210 | //valReader.Skip(); 211 | //break; 212 | } 213 | } 214 | break; 215 | case LayerType.Features: 216 | layer.AddFeatureData(layerReader.View()); 217 | break; 218 | default: 219 | layerReader.Skip(); 220 | break; 221 | } 222 | } 223 | 224 | if (_Validate) 225 | { 226 | if (string.IsNullOrEmpty(layer.Name)) 227 | { 228 | throw new System.Exception("Layer has no name"); 229 | } 230 | if (0 == layer.Version) 231 | { 232 | throw new System.Exception(string.Format("Layer [{0}] has invalid version. Only version 2.x of 'Mapbox Vector Tile Specification' (https://github.com/mapbox/vector-tile-spec) is supported.", layer.Name)); 233 | } 234 | if (2 != layer.Version) 235 | { 236 | throw new System.Exception(string.Format("Layer [{0}] has invalid version: {1}. Only version 2.x of 'Mapbox Vector Tile Specification' (https://github.com/mapbox/vector-tile-spec) is supported.", layer.Name, layer.Version)); 237 | } 238 | if (0 == layer.Extent) 239 | { 240 | throw new System.Exception(string.Format("Layer [{0}] has no extent.", layer.Name)); 241 | } 242 | if (0 == layer.FeatureCount()) 243 | { 244 | throw new System.Exception(string.Format("Layer [{0}] has no features.", layer.Name)); 245 | } 246 | //TODO: find equivalent of 'Distinct()' for NET20 247 | #if !NET20 248 | if (layer.Values.Count != layer.Values.Distinct().Count()) { 249 | throw new System.Exception(string.Format("Layer [{0}]: duplicate attribute values found", layer.Name)); 250 | } 251 | #endif 252 | } 253 | 254 | return layer; 255 | } 256 | 257 | 258 | /// 259 | /// Get a feature of the 260 | /// 261 | /// containing the feature 262 | /// Raw byte data of the feature 263 | /// If true, run checks if the tile contains valid data. Decreases decoding speed. 264 | /// 265 | /// 'null': returns the geometries unaltered as they are in the vector tile. 266 | /// Any value >=0 clips a border with the size around the tile. 267 | /// These are not pixels but the same units as the 'extent' of the layer. 268 | /// 269 | /// 270 | public static VectorTileFeature GetFeature( 271 | VectorTileLayer layer 272 | , byte[] data 273 | , bool validate = true 274 | , uint? clipBuffer = null 275 | , float scale = 1.0f 276 | ) 277 | { 278 | 279 | PbfReader featureReader = new PbfReader(data); 280 | VectorTileFeature feat = new VectorTileFeature(layer, clipBuffer, scale); 281 | bool geomTypeSet = false; 282 | while (featureReader.NextByte()) 283 | { 284 | int featureType = featureReader.Tag; 285 | if (validate) 286 | { 287 | if (!ConstantsAsDictionary.FeatureType.ContainsKey(featureType)) 288 | { 289 | throw new System.Exception(string.Format("Layer [{0}] has unknown feature type: {1}", layer.Name, featureType)); 290 | } 291 | } 292 | switch ((FeatureType)featureType) 293 | { 294 | case FeatureType.Id: 295 | feat.Id = (ulong)featureReader.Varint(); 296 | break; 297 | case FeatureType.Tags: 298 | #if NET20 299 | List tags = featureReader.GetPackedUnit32().ConvertAll(ui => (int)ui); 300 | #else 301 | List tags = featureReader.GetPackedUnit32().Select(t => (int)t).ToList(); 302 | #endif 303 | feat.Tags = tags; 304 | break; 305 | case FeatureType.Type: 306 | int geomType = (int)featureReader.Varint(); 307 | if (validate) 308 | { 309 | if (!ConstantsAsDictionary.GeomType.ContainsKey(geomType)) 310 | { 311 | throw new System.Exception(string.Format("Layer [{0}] has unknown geometry type tag: {1}", layer.Name, geomType)); 312 | } 313 | } 314 | feat.GeometryType = (GeomType)geomType; 315 | geomTypeSet = true; 316 | break; 317 | case FeatureType.Geometry: 318 | if (null != feat.GeometryCommands) 319 | { 320 | throw new System.Exception(string.Format("Layer [{0}], feature already has a geometry", layer.Name)); 321 | } 322 | //get raw array of commands and coordinates 323 | feat.GeometryCommands = featureReader.GetPackedUnit32(); 324 | break; 325 | default: 326 | featureReader.Skip(); 327 | break; 328 | } 329 | } 330 | 331 | if (validate) 332 | { 333 | if (!geomTypeSet) 334 | { 335 | throw new System.Exception(string.Format("Layer [{0}]: feature missing geometry type", layer.Name)); 336 | } 337 | if (null == feat.GeometryCommands) 338 | { 339 | throw new System.Exception(string.Format("Layer [{0}]: feature has no geometry", layer.Name)); 340 | } 341 | if (0 != feat.Tags.Count % 2) 342 | { 343 | throw new System.Exception(string.Format("Layer [{0}]: uneven number of feature tag ids", layer.Name)); 344 | } 345 | if (feat.Tags.Count > 0) 346 | { 347 | #if NET20 348 | int maxKeyIndex = -9999; 349 | int tagCount = feat.Tags.Count; 350 | for (int i = 0; i < tagCount; i += 2) 351 | { 352 | if (feat.Tags[i] > maxKeyIndex) { maxKeyIndex = feat.Tags[i]; } 353 | } 354 | int maxValueIndex = -9999; 355 | for (int i = 1; i < tagCount; i += 2) 356 | { 357 | if (feat.Tags[i] > maxValueIndex) { maxValueIndex = feat.Tags[i]; } 358 | } 359 | #else 360 | int maxKeyIndex = feat.Tags.Where((key, idx) => idx % 2 == 0).Max(); 361 | int maxValueIndex = feat.Tags.Where((key, idx) => (idx + 1) % 2 == 0).Max(); 362 | #endif 363 | if (maxKeyIndex >= layer.Keys.Count) 364 | { 365 | throw new System.Exception(string.Format("Layer [{0}]: maximum key index equal or greater number of key elements", layer.Name)); 366 | } 367 | if (maxValueIndex >= layer.Values.Count) 368 | { 369 | throw new System.Exception(string.Format("Layer [{0}]: maximum value index equal or greater number of value elements", layer.Name)); 370 | } 371 | } 372 | } 373 | 374 | return feat; 375 | } 376 | 377 | 378 | 379 | } 380 | } 381 | -------------------------------------------------------------------------------- /src/VectorTileReader/VectorTileReader.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {4656B308-1492-4A22-A73E-06BF6AA858F2} 8 | Library 9 | Properties 10 | VectorTileReader 11 | Mapbox.VectorTile.VectorTileReader 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 | 96 | 97 | 98 | 99 | Properties\AssemblyInfoVersion.cs 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | {f0967389-29c8-4d50-b397-9bb698f13ed6} 110 | Geometry 111 | 112 | 113 | {4bce42ee-c33f-4fa4-bfdd-86f3d45c647c} 114 | PbfReader 115 | 116 | 117 | 118 | 125 | -------------------------------------------------------------------------------- /src/VectorTileReader/VectorTileReaderPortable.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 10.0 6 | Debug 7 | AnyCPU 8 | {88F3D60F-3C95-4E14-9731-622306630F4B} 9 | Library 10 | Properties 11 | VectorTileReader 12 | Mapbox.VectorTile.VectorTileReader 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 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 62 | -------------------------------------------------------------------------------- /src/VectorTiles.Tests/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("VectorTiles.Tests")] 10 | [assembly: AssemblyDescription("")] 11 | [assembly: AssemblyConfiguration("")] 12 | [assembly: AssemblyCompany("")] 13 | [assembly: AssemblyProduct("VectorTiles.Tests")] 14 | [assembly: AssemblyCopyright("Copyright © 2016")] 15 | [assembly: AssemblyTrademark("")] 16 | [assembly: AssemblyCulture("")] 17 | [assembly: NeutralResourcesLanguage("en-US")] 18 | 19 | 20 | // Setting ComVisible to false makes the types in this assembly not visible 21 | // to COM components. If you need to access a type in this assembly from 22 | // COM, set the ComVisible attribute to true on that type. 23 | [assembly: ComVisible(false)] 24 | 25 | // The following GUID is for the ID of the typelib if this project is exposed to COM 26 | [assembly: Guid("067456c0-086c-46a8-b37f-1405717b7bfc")] 27 | -------------------------------------------------------------------------------- /src/VectorTiles.Tests/TestGeometry.cs: -------------------------------------------------------------------------------- 1 | using Mapbox.VectorTile; 2 | using Mapbox.VectorTile.Geometry; 3 | using System; 4 | using System.IO; 5 | #if WINDOWS_UWP 6 | using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; 7 | using ATestClass = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestClassAttribute; 8 | using ATestMethod = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestMethodAttribute; 9 | #else 10 | using NUnit.Framework; 11 | using ATestClass = NUnit.Framework.TestFixtureAttribute; 12 | using ATestMethod = NUnit.Framework.TestAttribute; 13 | #endif 14 | 15 | namespace VectorTiles.Tests 16 | { 17 | 18 | 19 | [ATestClass] 20 | public class GeometryTests 21 | { 22 | 23 | 24 | // [ATestMethod] 25 | // public void GeometryObjects() { 26 | // LatLng ll = new LatLng() { Lng = 15, Lat = 48 }; 27 | // Assert.AreEqual("48.000000/15.000000", ll.ToString(), "LatLng.ToString()"); 28 | 29 | // Point2d ptSE = new Point2d(4096, 4096); 30 | // Assert.AreEqual("4096/4096", ptSE.ToString(), "Point2d.ToString()"); 31 | 32 | // LatLng fromPtSE = ptSE.ToLngLat(0, 0, 0, 4096); 33 | // Assert.AreEqual(180, fromPtSE.Lng, "correct longitude"); 34 | // Assert.AreEqual(-85.051128779806589, fromPtSE.Lat, "correct latitude"); 35 | 36 | // ptSE.X = 4210; 37 | // fromPtSE = ptSE.ToLngLat(0, 0, 0, 4096); 38 | // Assert.AreEqual(190, fromPtSE.Lng, 0.02, "correct longitude - out of bounds"); 39 | //#if WINDOWS_UWP 40 | // Assert.ThrowsException(() => { ptSE.ToLngLat(0, 0, 0, 04096, true); }); 41 | //#else 42 | // Assert.Throws(Is.InstanceOf(), () => { ptSE.ToLngLat(0, 0, 0, 04096, true); }); 43 | //#endif 44 | 45 | // ptSE.X = 4096; 46 | // ptSE.Y = 4210; 47 | // fromPtSE = ptSE.ToLngLat(0, 0, 0, 4096); 48 | // Assert.AreEqual(-85.844, fromPtSE.Lat, 0.02, "correct latitude - out of bounds"); 49 | //#if WINDOWS_UWP 50 | // Assert.ThrowsException(() => { ptSE.ToLngLat(0, 0, 0, 04096, true); }); 51 | //#else 52 | // Assert.Throws(Is.InstanceOf(), () => { ptSE.ToLngLat(0, 0, 0, 04096, true); }); 53 | //#endif 54 | // } 55 | 56 | 57 | 58 | 59 | 60 | } 61 | 62 | } -------------------------------------------------------------------------------- /src/VectorTiles.Tests/TestInvalidMvtInBulk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using Mapbox.VectorTile; 4 | using System.Collections; 5 | #if WINDOWS_UWP 6 | using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; 7 | using ATestClass = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestClassAttribute; 8 | using ATestMethod = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestMethodAttribute; 9 | using ATestClassSetup = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.ClassInitializeAttribute; //run once per class 10 | using ATestSetup = Microsoft.VisualStudio.TestPlatform.UnitTestFramework.TestInitializeAttribute; //run before every test 11 | using ATestDataSource = Microsoft.VisualStudio.TestTools.UnitTesting.DataSourceAttribute; 12 | #else 13 | using NUnit.Framework; 14 | using ATestClass = NUnit.Framework.TestFixtureAttribute; 15 | using ATestMethod = NUnit.Framework.TestAttribute; 16 | using ATestClassSetup = NUnit.Framework.OneTimeSetUpAttribute; 17 | using ATestDataSource = NUnit.Framework.TestCaseSourceAttribute; 18 | #endif 19 | 20 | 21 | namespace VectorTiles.Tests 22 | { 23 | 24 | 25 | [ATestClass] 26 | public class BulkInvalidMvtTests 27 | { 28 | 29 | private string _fixturesPath; 30 | public static string _executingFolder = AppDomain.CurrentDomain.BaseDirectory; 31 | 32 | 33 | [ATestClassSetup] 34 | protected void SetUp() 35 | { 36 | _fixturesPath = Path.Combine(_executingFolder, "..", "..", "..", "test", "mvt-fixtures", "fixtures", "invalid"); 37 | } 38 | 39 | [ATestMethod, Order(1)] 40 | public void FixturesPathExists() 41 | { 42 | Assert.True(Directory.Exists(_fixturesPath), "MVT fixtures directory exists"); 43 | } 44 | 45 | 46 | [ATestMethod, ATestDataSource(typeof(GetMVTs), "GetInValidFixtureFileName")] 47 | public void Validate(string fileName) 48 | { 49 | string fullFileName = Path.Combine(_fixturesPath, fileName); 50 | Assert.True(File.Exists(fullFileName), "Vector tile exists"); 51 | byte[] data = File.ReadAllBytes(fullFileName); 52 | Assert.Throws(Is.InstanceOf(), () => 53 | { 54 | VectorTile vt = new VectorTile(data); 55 | foreach (var layerName in vt.LayerNames()) 56 | { 57 | var layer = vt.GetLayer(layerName); 58 | for (int i = 0; i < layer.FeatureCount(); i++) 59 | { 60 | var feat = layer.GetFeature(i); 61 | feat.GetProperties(); 62 | } 63 | } 64 | }); 65 | } 66 | } 67 | 68 | public partial class GetMVTs 69 | { 70 | public static IEnumerable GetInValidFixtureFileName() 71 | { 72 | string path = Path.Combine(BulkInvalidMvtTests._executingFolder, "..", "..", "..", "test", "mvt-fixtures", "fixtures", "invalid"); 73 | 74 | foreach (var file in Directory.GetFiles(path)) 75 | { 76 | //return file basename only to make test description more readable 77 | yield return new TestCaseData(Path.GetFileName(file)); 78 | } 79 | } 80 | } 81 | 82 | 83 | 84 | 85 | 86 | } -------------------------------------------------------------------------------- /src/VectorTiles.Tests/TestMvtInBulk.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using NUnit.Framework; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Diagnostics; 6 | using System.Collections.Generic; 7 | using Mapbox.VectorTile; 8 | using System.Collections; 9 | using Mapbox.VectorTile.Geometry; 10 | using Mapbox.VectorTile.ExtensionMethods; 11 | 12 | 13 | 14 | namespace VectorTiles.Tests 15 | { 16 | 17 | 18 | [TestFixture] 19 | public class BulkMvtTests 20 | { 21 | 22 | 23 | private string fixturesPath; 24 | 25 | 26 | [OneTimeSetUp] 27 | protected void SetUp() 28 | { 29 | fixturesPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "..", "..", "..", "test", "mvt-fixtures", "fixtures", "valid"); 30 | } 31 | 32 | 33 | [Test, Order(1)] 34 | public void FixturesPathExists() 35 | { 36 | Assert.True(Directory.Exists(fixturesPath), "MVT fixtures directory exists"); 37 | } 38 | 39 | 40 | [Test, TestCaseSource(typeof(GetMVTs), "GetFixtureFileName")] 41 | public void LazyDecoding(string fileName) 42 | { 43 | string fullFileName = Path.Combine(fixturesPath, fileName); 44 | Assert.True(File.Exists(fullFileName), "Vector tile exists"); 45 | byte[] data = File.ReadAllBytes(fullFileName); 46 | VectorTile vt = new VectorTile(data); 47 | foreach (var layerName in vt.LayerNames()) 48 | { 49 | VectorTileLayer layer = vt.GetLayer(layerName); 50 | for (int i = 0; i < layer.FeatureCount(); i++) 51 | { 52 | VectorTileFeature feat = layer.GetFeature(i); 53 | var properties = feat.GetProperties(); 54 | foreach (var prop in properties) 55 | { 56 | Assert.AreEqual(prop.Value, feat.GetValue(prop.Key), "Property values match"); 57 | } 58 | foreach (var geomPart in feat.Geometry()) 59 | { 60 | foreach (var coord in geomPart) 61 | { 62 | //TODO add Assert 63 | } 64 | } 65 | } 66 | } 67 | string geojson = vt.ToGeoJson(0, 0, 0); 68 | Assert.GreaterOrEqual(geojson.Length, 30, "geojson >= 30 chars"); 69 | } 70 | 71 | 72 | [Test] 73 | public void DifferentPoint2dTypesAndScaling() 74 | { 75 | string fullFileName = Path.Combine(fixturesPath, "Feature-single-linestring.mvt"); 76 | byte[] data = File.ReadAllBytes(fullFileName); 77 | VectorTile vt = new VectorTile(data); 78 | foreach (var layerName in vt.LayerNames()) 79 | { 80 | VectorTileLayer layer = vt.GetLayer(layerName); 81 | for (int i = 0; i < layer.FeatureCount(); i++) 82 | { 83 | 84 | VectorTileFeature featLong = layer.GetFeature(i); 85 | foreach (var geomPart in featLong.Geometry()) 86 | { 87 | foreach (var coord in geomPart) 88 | { 89 | Debug.WriteLine("long: {0}/{1}", coord.X, coord.Y); 90 | } 91 | Assert.AreEqual(2L, geomPart[0].X); 92 | Assert.AreEqual(2L, geomPart[0].Y); 93 | Assert.AreEqual(2L, geomPart[1].X); 94 | Assert.AreEqual(10L, geomPart[1].Y); 95 | Assert.AreEqual(10L, geomPart[2].X); 96 | Assert.AreEqual(10L, geomPart[2].Y); 97 | } 98 | 99 | // don't clip, as this might change order of vertices 100 | // test 'scale' on the VectorTileFeature constructor 101 | VectorTileFeature featInt = layer.GetFeature(i, null, 1.5f); 102 | foreach (var geomPart in featInt.Geometry()) 103 | { 104 | foreach (var coord in geomPart) 105 | { 106 | Debug.WriteLine("integer: {0}/{1}", coord.X, coord.Y); 107 | } 108 | Assert.AreEqual(3, geomPart[0].X); 109 | Assert.AreEqual(3, geomPart[0].Y); 110 | Assert.AreEqual(3, geomPart[1].X); 111 | Assert.AreEqual(15, geomPart[1].Y); 112 | Assert.AreEqual(15, geomPart[2].X); 113 | Assert.AreEqual(15, geomPart[2].Y); 114 | } 115 | 116 | // don't clip, as this might change order of vertices 117 | VectorTileFeature featFloat = layer.GetFeature(i); 118 | // test 'scale' on the Geometry method 119 | foreach (var geomPart in featFloat.Geometry(null, 2.0f)) 120 | { 121 | foreach (var coord in geomPart) 122 | { 123 | Debug.WriteLine("float: {0}/{1}", coord.X, coord.Y); 124 | } 125 | Assert.AreEqual(4f, geomPart[0].X); 126 | Assert.AreEqual(4f, geomPart[0].Y); 127 | Assert.AreEqual(4f, geomPart[1].X); 128 | Assert.AreEqual(20f, geomPart[1].Y); 129 | Assert.AreEqual(20f, geomPart[2].X); 130 | Assert.AreEqual(20f, geomPart[2].Y); 131 | } 132 | 133 | } 134 | } 135 | string geojson = vt.ToGeoJson(0, 0, 0); 136 | Assert.GreaterOrEqual(geojson.Length, 30, "geojson >= 30 chars"); 137 | } 138 | 139 | 140 | 141 | [Test, TestCaseSource(typeof(GetMVTs), "GetFixtureFileName")] 142 | public void Scaling(string fileName) 143 | { 144 | float[] scales = new float[] { 1.5f, 2.25f, 5.75f, 197.3f }; 145 | string fullFileName = Path.Combine(fixturesPath, fileName); 146 | byte[] data = File.ReadAllBytes(fullFileName); 147 | VectorTile vt = new VectorTile(data); 148 | foreach (var lyrName in vt.LayerNames()) 149 | { 150 | VectorTileLayer lyr = vt.GetLayer(lyrName); 151 | int featCnt = lyr.FeatureCount(); 152 | for (int idxFeat = 0; idxFeat < featCnt; idxFeat++) 153 | { 154 | VectorTileFeature feat = lyr.GetFeature(idxFeat); 155 | List>> rawParts = feat.Geometry(); 156 | for (int idxPart = 0; idxPart < rawParts.Count; idxPart++) 157 | { 158 | List> rawGeom = rawParts[idxPart]; 159 | foreach (var scale in scales) 160 | { 161 | List>> scaledParts = feat.Geometry(null, scale); 162 | List> scaledGeom = scaledParts[idxPart]; 163 | for (int idxVertex = 0; idxVertex < rawGeom.Count; idxVertex++) 164 | { 165 | Point2d rawVertex = rawGeom[idxVertex]; 166 | Point2d scaledVertex = scaledGeom[idxVertex]; 167 | Assert.AreEqual(scale * (float)rawVertex.X, scaledVertex.X, $"{fileName}, feature[{idxFeat}], geometry part[{idxPart}], vertex[{idxVertex}], scale[{scale}]: X does not match"); 168 | Assert.AreEqual(scale * (float)rawVertex.Y, scaledVertex.Y, $"{fileName}, feature[{idxFeat}], geometry part[{idxPart}], vertex[{idxVertex}], scale[{scale}]: Y does not match"); 169 | } 170 | } 171 | } 172 | } 173 | 174 | } 175 | } 176 | 177 | /// 178 | /// This test assumes that the features do *NOT* extend beyong the tile extent!!! 179 | /// It will fail otherwise. 180 | /// 181 | /// 182 | [Test, TestCaseSource(typeof(GetMVTs), "GetFixtureFileName")] 183 | public void Clipping(string fileName) 184 | { 185 | string fullFileName = Path.Combine(fixturesPath, fileName); 186 | Assert.True(File.Exists(fullFileName), "Vector tile exists"); 187 | byte[] data = File.ReadAllBytes(fullFileName); 188 | VectorTile vt = new VectorTile(data); 189 | foreach (var lyrName in vt.LayerNames()) 190 | { 191 | VectorTileLayer lyr = vt.GetLayer(lyrName); 192 | for (int i = 0; i < lyr.FeatureCount(); i++) 193 | { 194 | VectorTileFeature feat = lyr.GetFeature(i); 195 | //skip features with unknown geometry type 196 | if (feat.GeometryType == GeomType.UNKNOWN) { continue; } 197 | List>> geomRaw = feat.Geometry(); 198 | List>> geomClipped = feat.Geometry(0); 199 | for (int j = 0; j < geomRaw.Count; j++) 200 | { 201 | List> part = geomRaw[j]; 202 | List> partClipped = geomClipped[j]; 203 | // Workaround to compare parts as clipping may or may not change the order of vertices 204 | // This only works if no actual clipping is done 205 | Assert.False(part.Except(partClipped).Any(), $"{fileName}, feature[{i}], geometry part[{j}]: geometry parts don't match after clipping"); 206 | } 207 | } 208 | } 209 | } 210 | 211 | 212 | [Test, TestCaseSource(typeof(GetMVTs), "GetFixtureFileName")] 213 | public void AtLeastOneLayer(string fileName) 214 | { 215 | string fullFileName = Path.Combine(fixturesPath, fileName); 216 | Assert.True(File.Exists(fullFileName), "Vector tile exists"); 217 | byte[] data = File.ReadAllBytes(fullFileName); 218 | VectorTile vt = new VectorTile(data); 219 | Assert.GreaterOrEqual(vt.LayerNames().Count, 1, "At least one layer"); 220 | string geojson = vt.ToGeoJson(0, 0, 0); 221 | Assert.GreaterOrEqual(geojson.Length, 30, "geojson >= 30 chars"); 222 | foreach (var lyrName in vt.LayerNames()) 223 | { 224 | VectorTileLayer lyr = vt.GetLayer(lyrName); 225 | for (int i = 0; i < lyr.FeatureCount(); i++) 226 | { 227 | Debug.WriteLine("{0} lyr:{1} feat:{2}", fileName, lyr.Name, i); 228 | VectorTileFeature feat = lyr.GetFeature(i); 229 | long extent = (long)lyr.Extent; 230 | foreach (var part in feat.Geometry()) 231 | { 232 | foreach (var geom in part) 233 | { 234 | if (geom.X < 0 || geom.Y < 0 || geom.X > extent || geom.Y > extent) 235 | { 236 | Debug.WriteLine("{0} lyr:{1} feat:{2} x:{3} y:{4}", fileName, lyr.Name, i, geom.X, geom.Y); 237 | } 238 | } 239 | } 240 | } 241 | } 242 | } 243 | 244 | 245 | [Test, TestCaseSource(typeof(GetMVTs), "GetFixtureFileName")] 246 | public void ClipHardAtTileBoundary(string fileName) 247 | { 248 | string fullFileName = Path.Combine(fixturesPath, fileName); 249 | Assert.True(File.Exists(fullFileName), "Vector tile exists"); 250 | byte[] data = File.ReadAllBytes(fullFileName); 251 | VectorTile vt = new VectorTile(data); 252 | Assert.GreaterOrEqual(vt.LayerNames().Count, 1, "At least one layer"); 253 | string geojson = vt.ToGeoJson(0, 0, 0); 254 | Assert.GreaterOrEqual(geojson.Length, 30, "geojson >= 30 chars"); 255 | foreach (var lyrName in vt.LayerNames()) 256 | { 257 | VectorTileLayer lyr = vt.GetLayer(lyrName); 258 | for (int i = 0; i < lyr.FeatureCount(); i++) 259 | { 260 | Debug.WriteLine("{0} lyr:{1} feat:{2}", fileName, lyr.Name, i); 261 | VectorTileFeature feat = lyr.GetFeature(i, 0); 262 | long extent = (long)lyr.Extent; 263 | foreach (var part in feat.Geometry()) 264 | { 265 | foreach (var geom in part) 266 | { 267 | Assert.GreaterOrEqual(geom.X, 0, "geom.X equal or greater 0"); 268 | Assert.GreaterOrEqual(geom.Y, 0, "geom.Y eqaul or greater 0"); 269 | Assert.LessOrEqual(geom.X, extent, "geom.X less or equal extent"); 270 | Assert.LessOrEqual(geom.Y, extent, "geom.Y less or equal extent"); 271 | } 272 | } 273 | } 274 | } 275 | } 276 | 277 | 278 | [Test, TestCaseSource(typeof(GetMVTs), "GetFixtureFileName")] 279 | public void IterateAllProperties(string fileName) 280 | { 281 | string fullFileName = Path.Combine(fixturesPath, fileName); 282 | Assert.True(File.Exists(fullFileName), "Vector tile exists"); 283 | byte[] data = File.ReadAllBytes(fullFileName); 284 | VectorTile vt = new VectorTile(data); 285 | foreach (var layerName in vt.LayerNames()) 286 | { 287 | var layer = vt.GetLayer(layerName); 288 | for (int i = 0; i < layer.FeatureCount(); i++) 289 | { 290 | var feat = layer.GetFeature(i); 291 | var properties = feat.GetProperties(); 292 | foreach (var prop in properties) 293 | { 294 | Assert.IsInstanceOf(prop.Key); 295 | } 296 | } 297 | } 298 | } 299 | } 300 | 301 | 302 | 303 | public partial class GetMVTs 304 | { 305 | public static IEnumerable GetFixtureFileName() 306 | { 307 | string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "..", "..", "..", "test", "mvt-fixtures", "fixtures", "valid"); 308 | 309 | foreach (var file in Directory.GetFiles(path)) 310 | { 311 | //return file basename only to make test description more readable 312 | yield return new TestCaseData(Path.GetFileName(file)); 313 | } 314 | } 315 | } 316 | 317 | 318 | 319 | 320 | 321 | } -------------------------------------------------------------------------------- /src/VectorTiles.Tests/TestMvtSingle.cs: -------------------------------------------------------------------------------- 1 | using Mapbox.VectorTile; 2 | using Mapbox.VectorTile.Geometry; 3 | using NUnit.Framework; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.IO; 7 | 8 | namespace VectorTiles.Tests 9 | { 10 | 11 | 12 | [TestFixture] 13 | public class SingleMvtTests 14 | { 15 | 16 | private string fixturesPath; 17 | 18 | [OneTimeSetUp] 19 | protected void SetUp() 20 | { 21 | fixturesPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "..", "..", "..", "test", "mvt-fixtures", "fixtures", "valid"); 22 | } 23 | 24 | 25 | [Test] 26 | public void FeatureSinglePoint() 27 | { 28 | 29 | byte[] data = File.ReadAllBytes(Path.Combine(fixturesPath, "Feature-single-point.mvt")); 30 | VectorTile vt = new VectorTile(data); 31 | Assert.AreEqual(1, vt.LayerNames().Count, "one layer"); 32 | VectorTileLayer lyr = vt.GetLayer(vt.LayerNames()[0]); 33 | Assert.AreEqual("layer_name", lyr.Name, "Layer name"); 34 | Assert.AreEqual(1, lyr.FeatureCount(), "Feature count"); 35 | VectorTileFeature feat = lyr.GetFeature(0); 36 | Assert.AreEqual(GeomType.POINT, feat.GeometryType, "Geometry type"); 37 | Assert.AreEqual(123, feat.Id, "id"); 38 | Dictionary properties = feat.GetProperties(); 39 | Assert.AreEqual("world", properties["hello"]); 40 | Assert.AreEqual("world", feat.GetValue("hello")); 41 | } 42 | 43 | 44 | 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/VectorTiles.Tests/TestPbfReader.cs: -------------------------------------------------------------------------------- 1 | using Mapbox.VectorTile.Contants; 2 | using NUnit.Framework; 3 | 4 | 5 | namespace VectorTiles.Tests 6 | { 7 | 8 | 9 | [TestFixture] 10 | public class PbfReaderTests 11 | { 12 | 13 | [Test] 14 | public void Constants() 15 | { 16 | Assert.AreEqual(0, (int)WireTypes.VARINT, "WireTypes.VARINT"); 17 | Assert.AreEqual(1, (int)WireTypes.FIXED64, "WireTypes.FIXED64"); 18 | Assert.AreEqual(2, (int)WireTypes.BYTES, "WireTypes.BYTES"); 19 | Assert.AreEqual(5, (int)WireTypes.FIXED32, "WireTypes.FIXED32"); 20 | Assert.AreEqual(99, (int)WireTypes.UNDEFINED, "WireTypes.UNDEFINED"); 21 | 22 | Assert.AreEqual(1, (int)Commands.MoveTo, "Commands.MoveTo"); 23 | Assert.AreEqual(2, (int)Commands.LineTo, "Commands.LineTo"); 24 | Assert.AreEqual(7, (int)Commands.ClosePath, "Commands.ClosePath"); 25 | 26 | Assert.AreEqual(3, (int)TileType.Layers, "TileType.Layers"); 27 | 28 | Assert.AreEqual(15, (int)LayerType.Version, "LayerType.Version"); 29 | Assert.AreEqual(1, (int)LayerType.Name, "LayerType.Name"); 30 | Assert.AreEqual(2, (int)LayerType.Features, "LayerType.Features"); 31 | Assert.AreEqual(3, (int)LayerType.Keys, "LayerType.Keys"); 32 | Assert.AreEqual(4, (int)LayerType.Values, "LayerType.Values"); 33 | Assert.AreEqual(5, (int)LayerType.Extent, "LayerType.Extent"); 34 | 35 | Assert.AreEqual(1, (int)FeatureType.Id, "FeatureType.Id"); 36 | Assert.AreEqual(2, (int)FeatureType.Tags, "FeatureType.Tags"); 37 | Assert.AreEqual(3, (int)FeatureType.Type, "FeatureType.Type"); 38 | Assert.AreEqual(4, (int)FeatureType.Geometry, "FeatureType.Geometry"); 39 | Assert.AreEqual(5, (int)FeatureType.Raster, "FeatureType.Raster"); 40 | 41 | Assert.AreEqual(1, (int)ValueType.String, "ValueType.String"); 42 | Assert.AreEqual(2, (int)ValueType.Float, "ValueType.Float"); 43 | Assert.AreEqual(3, (int)ValueType.Double, "ValueType.Double"); 44 | Assert.AreEqual(4, (int)ValueType.Int, "ValueType.Int"); 45 | Assert.AreEqual(5, (int)ValueType.UInt, "ValueType.UInt"); 46 | Assert.AreEqual(6, (int)ValueType.SInt, "ValueType.SInt"); 47 | Assert.AreEqual(7, (int)ValueType.Bool, "ValueType.Bool"); 48 | } 49 | 50 | 51 | 52 | 53 | 54 | } 55 | 56 | } -------------------------------------------------------------------------------- /src/VectorTiles.Tests/VectorTiles.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | {067456C0-086C-46A8-B37F-1405717B7BFC} 7 | Library 8 | Properties 9 | VectorTiles.Tests 10 | VectorTiles.Tests 11 | v4.6.2 12 | 512 13 | {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 14 | 15 | 16 | 17 | true 18 | full 19 | false 20 | ..\..\bin\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | pdbonly 27 | true 28 | ..\..\bin\ 29 | TRACE 30 | prompt 31 | 4 32 | 33 | 34 | true 35 | ..\..\bin\ 36 | DEBUG;TRACE 37 | full 38 | x64 39 | prompt 40 | MinimumRecommendedRules.ruleset 41 | 42 | 43 | ..\..\bin\ 44 | TRACE 45 | true 46 | pdbonly 47 | x64 48 | prompt 49 | MinimumRecommendedRules.ruleset 50 | 51 | 52 | true 53 | ..\..\bin\Net20Debug\v2.0\ 54 | DEBUG;TRACE 55 | full 56 | AnyCPU 57 | prompt 58 | MinimumRecommendedRules.ruleset 59 | 60 | 61 | ..\..\bin\Net35Debug\v3.5\ 62 | true 63 | full 64 | DEBUG;TRACE;NET20 65 | AnyCPU 66 | prompt 67 | MinimumRecommendedRules.ruleset 68 | false 69 | 70 | 71 | ..\..\bin\Net462Debug\v4.6.2\ 72 | true 73 | full 74 | DEBUG;TRACE;NET20 75 | AnyCPU 76 | prompt 77 | MinimumRecommendedRules.ruleset 78 | false 79 | 80 | 81 | 82 | False 83 | 84 | 85 | ..\..\packages\NUnit.3.6.1\lib\net45\nunit.framework.dll 86 | True 87 | 88 | 89 | 90 | 91 | 92 | Properties\AssemblyInfoVersion.cs 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | {55503403-0083-4ed8-b618-f8377610b225} 107 | ExtensionMethods 108 | 109 | 110 | {f0967389-29c8-4d50-b397-9bb698f13ed6} 111 | Geometry 112 | 113 | 114 | {4BCE42EE-C33F-4FA4-BFDD-86F3D45C647C} 115 | PbfReader 116 | 117 | 118 | {4656b308-1492-4a22-a73e-06bf6aa858f2} 119 | VectorTileReader 120 | 121 | 122 | 123 | 130 | -------------------------------------------------------------------------------- /src/VectorTiles.Tests/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/VerifyNetFrameworkVersion/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/VerifyNetFrameworkVersion/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Reflection; 4 | #if NET462 5 | using System.Runtime.Versioning; 6 | #endif 7 | 8 | namespace VerifyNetFrameworkVersion 9 | { 10 | 11 | class Program 12 | { 13 | 14 | 15 | static int Main(string[] args) 16 | { 17 | 18 | string myName = "VerifyNetFrameworkVersion"; 19 | string assemblyDir; 20 | 21 | if (args.Length < 1) 22 | { 23 | assemblyDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); 24 | Console.Error.WriteLine($"{myName}: no directory passed, using current directory: '{assemblyDir}'"); 25 | } 26 | else 27 | { 28 | assemblyDir = args[0]; 29 | } 30 | if (!Directory.Exists(assemblyDir)) 31 | { 32 | Console.Error.WriteLine($"{myName}: directory does not exist: {assemblyDir}"); 33 | return 1; 34 | } 35 | 36 | string[] dlls = Directory.GetFiles(assemblyDir, "*.dll"); 37 | if (dlls.Length < 1) 38 | { 39 | Console.Error.WriteLine($"{myName}: no dlls found in {assemblyDir}"); 40 | return 1; 41 | } 42 | 43 | Console.WriteLine($"{myName} analyzing assemblies:"); 44 | foreach (var dll in dlls) 45 | { 46 | Assembly assembly = Assembly.LoadFrom(dll); 47 | string frameworkName = "NA"; 48 | string frameworkDisplayName = "NA"; 49 | #if NET462 50 | TargetFrameworkAttribute targetFWA = assembly.GetCustomAttribute(); 51 | frameworkName = targetFWA.FrameworkName; 52 | frameworkDisplayName = targetFWA.FrameworkDisplayName; 53 | #endif 54 | Console.WriteLine($"* {Path.GetFileName(dll)}, ImageRuntimeVersion:{assembly.ImageRuntimeVersion}, FrameworkName:{frameworkName}, FrameworkDisplayName:{frameworkDisplayName}"); 55 | } 56 | return 0; 57 | } 58 | 59 | 60 | 61 | 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/VerifyNetFrameworkVersion/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("VerifyNetFrameworkVersion")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("VerifyNetFrameworkVersion")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 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("1717cd14-720f-4373-81e1-3505fcb2cf03")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /src/VerifyNetFrameworkVersion/VerifyNetFrameworkVersion.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {1717CD14-720F-4373-81E1-3505FCB2CF03} 8 | Exe 9 | Properties 10 | VerifyNetFrameworkVersion 11 | VerifyNetFrameworkVersion 12 | v4.6.2 13 | 512 14 | true 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | AnyCPU 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | v2.0 37 | ..\..\bin\$(Configuration)\$(TargetFrameworkVersion)\ 38 | true 39 | full 40 | DEBUG;TRACE;NET20 41 | AnyCPU 42 | prompt 43 | MinimumRecommendedRules.ruleset 44 | false 45 | 46 | 47 | v3.5 48 | ..\..\bin\$(Configuration)\$(TargetFrameworkVersion)\ 49 | true 50 | full 51 | DEBUG;TRACE;NET35 52 | AnyCPU 53 | prompt 54 | MinimumRecommendedRules.ruleset 55 | false 56 | 57 | 58 | v4.6.2 59 | ..\..\bin\$(Configuration)\$(TargetFrameworkVersion)\ 60 | true 61 | full 62 | DEBUG;TRACE;NET462 63 | AnyCPU 64 | prompt 65 | MinimumRecommendedRules.ruleset 66 | false 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | {d01ba6cb-9a2b-4aa5-95e1-085d9b569309} 88 | DemoConsoleApp 89 | 90 | 91 | {55503403-0083-4ed8-b618-f8377610b225} 92 | ExtensionMethods 93 | 94 | 95 | {f0967389-29c8-4d50-b397-9bb698f13ed6} 96 | Geometry 97 | 98 | 99 | {4bce42ee-c33f-4fa4-bfdd-86f3d45c647c} 100 | PbfReader 101 | 102 | 103 | {4656b308-1492-4a22-a73e-06bf6aa858f2} 104 | VectorTileReader 105 | 106 | 107 | {067456c0-086c-46a8-b37f-1405717b7bfc} 108 | VectorTiles.Tests 109 | 110 | 111 | 112 | 113 | $(TargetPath) 114 | 115 | 122 | --------------------------------------------------------------------------------