Exemple #1
0
        public void ClipHardAtTileBoundary(string fileName)
        {
            string fullFileName = Path.Combine(fixturesPath, fileName);

            Assert.True(File.Exists(fullFileName), "Vector tile exists");
            byte[]     data = File.ReadAllBytes(fullFileName);
            VectorTile vt   = new VectorTile(data);

            Assert.GreaterOrEqual(vt.LayerNames().Count, 1, "At least one layer");
            string geojson = vt.ToGeoJson(0, 0, 0);

            Assert.GreaterOrEqual(geojson.Length, 30, "geojson >= 30 chars");
            foreach (var lyrName in vt.LayerNames())
            {
                VectorTileLayer lyr = vt.GetLayer(lyrName);
                for (int i = 0; i < lyr.FeatureCount(); i++)
                {
                    Debug.WriteLine("{0} lyr:{1} feat:{2}", fileName, lyr.Name, i);
                    VectorTileFeature feat = lyr.GetFeature(i, 0);
                    long extent            = (long)lyr.Extent;
                    foreach (var part in feat.Geometry <int>())
                    {
                        foreach (var geom in part)
                        {
                            Assert.GreaterOrEqual(geom.X, 0, "geom.X equal or greater 0");
                            Assert.GreaterOrEqual(geom.Y, 0, "geom.Y eqaul or greater 0");
                            Assert.LessOrEqual(geom.X, extent, "geom.X less or equal extent");
                            Assert.LessOrEqual(geom.Y, extent, "geom.Y less or equal extent");
                        }
                    }
                }
            }
        }
Exemple #2
0
        public override IEnumerator ParseTileData(object m, Coordinates tilecenter, int zoom, GOLayer[] layers, bool delayedLoad, List <string> layerNames)
        {
            if (mapData == null)
            {
                Debug.LogWarning("Map Data is null!");
                                #if !UNITY_WEBPLAYER
                FileHandler.Remove(gameObject.name);
                                #endif
                yield break;
            }

            var decompressed = Compression.Decompress((byte[])mapData);
            vt = new VectorTile(decompressed, false);

            foreach (GOLayer layer in layers)
            {
                string[] lyrs = GetLayersStrings(layer).Split(',');

                foreach (string l in lyrs)
                {
                    VectorTileLayer lyr = vt.GetLayer(l);
                    if (lyr != null)
                    {
                        yield return(StartCoroutine(BuildLayer(lyr, layer, delayedLoad)));
                    }
                }
            }
        }
Exemple #3
0
        public void AtLeastOneLayer(string fileName)
        {
            string fullFileName = Path.Combine(fixturesPath, fileName);

            Assert.True(File.Exists(fullFileName), "Vector tile exists");
            byte[]     data = File.ReadAllBytes(fullFileName);
            VectorTile vt   = new VectorTile(data);

            Assert.GreaterOrEqual(vt.LayerNames().Count, 1, "At least one layer");
            string geojson = vt.ToGeoJson(0, 0, 0);

            Assert.GreaterOrEqual(geojson.Length, 30, "geojson >= 30 chars");
            foreach (var lyrName in vt.LayerNames())
            {
                VectorTileLayer lyr = vt.GetLayer(lyrName);
                for (int i = 0; i < lyr.FeatureCount(); i++)
                {
                    Debug.WriteLine("{0} lyr:{1} feat:{2}", fileName, lyr.Name, i);
                    VectorTileFeature feat = lyr.GetFeature(i);
                    long extent            = (long)lyr.Extent;
                    foreach (var part in feat.Geometry <long>())
                    {
                        foreach (var geom in part)
                        {
                            if (geom.X < 0 || geom.Y < 0 || geom.X > extent || geom.Y > extent)
                            {
                                Debug.WriteLine("{0} lyr:{1} feat:{2} x:{3} y:{4}", fileName, lyr.Name, i, geom.X, geom.Y);
                            }
                        }
                    }
                }
            }
        }
Exemple #4
0
        public void Clipping(string fileName)
        {
            string fullFileName = Path.Combine(fixturesPath, fileName);

            Assert.True(File.Exists(fullFileName), "Vector tile exists");
            byte[]     data = File.ReadAllBytes(fullFileName);
            VectorTile vt   = new VectorTile(data);

            foreach (var lyrName in vt.LayerNames())
            {
                VectorTileLayer lyr = vt.GetLayer(lyrName);
                for (int i = 0; i < lyr.FeatureCount(); i++)
                {
                    VectorTileFeature feat = lyr.GetFeature(i);
                    //skip features with unknown geometry type
                    if (feat.GeometryType == GeomType.UNKNOWN)
                    {
                        continue;
                    }
                    List <List <Point2d <long> > > geomRaw     = feat.Geometry <long>();
                    List <List <Point2d <long> > > geomClipped = feat.Geometry <long>(0);
                    for (int j = 0; j < geomRaw.Count; j++)
                    {
                        List <Point2d <long> > part        = geomRaw[j];
                        List <Point2d <long> > partClipped = geomClipped[j];
                        // Workaround to compare parts as clipping may or may not change the order of vertices
                        // This only works if no actual clipping is done
                        Assert.False(part.Except(partClipped).Any(), $"{fileName}, feature[{i}], geometry part[{j}]: geometry parts don't match after clipping");
                    }
                }
            }
        }
Exemple #5
0
        public void Scaling(string fileName)
        {
            float[] scales       = new float[] { 1.5f, 2.25f, 5.75f, 197.3f };
            string  fullFileName = Path.Combine(fixturesPath, fileName);

            byte[]     data = File.ReadAllBytes(fullFileName);
            VectorTile vt   = new VectorTile(data);

            foreach (var lyrName in vt.LayerNames())
            {
                VectorTileLayer lyr     = vt.GetLayer(lyrName);
                int             featCnt = lyr.FeatureCount();
                for (int idxFeat = 0; idxFeat < featCnt; idxFeat++)
                {
                    VectorTileFeature             feat     = lyr.GetFeature(idxFeat);
                    List <List <Point2d <int> > > rawParts = feat.Geometry <int>();
                    for (int idxPart = 0; idxPart < rawParts.Count; idxPart++)
                    {
                        List <Point2d <int> > rawGeom = rawParts[idxPart];
                        foreach (var scale in scales)
                        {
                            List <List <Point2d <float> > > scaledParts = feat.Geometry <float>(null, scale);
                            List <Point2d <float> >         scaledGeom  = scaledParts[idxPart];
                            for (int idxVertex = 0; idxVertex < rawGeom.Count; idxVertex++)
                            {
                                Point2d <int>   rawVertex    = rawGeom[idxVertex];
                                Point2d <float> scaledVertex = scaledGeom[idxVertex];
                                Assert.AreEqual(scale * (float)rawVertex.X, scaledVertex.X, $"{fileName}, feature[{idxFeat}], geometry part[{idxPart}], vertex[{idxVertex}], scale[{scale}]: X does not match");
                                Assert.AreEqual(scale * (float)rawVertex.Y, scaledVertex.Y, $"{fileName}, feature[{idxFeat}], geometry part[{idxPart}], vertex[{idxVertex}], scale[{scale}]: Y does not match");
                            }
                        }
                    }
                }
            }
        }
Exemple #6
0
        public void LazyDecoding(string fileName)
        {
            string fullFileName = Path.Combine(fixturesPath, fileName);

            Assert.True(File.Exists(fullFileName), "Vector tile exists");
            byte[]     data = File.ReadAllBytes(fullFileName);
            VectorTile vt   = new VectorTile(data);

            foreach (var layerName in vt.LayerNames())
            {
                VectorTileLayer layer = vt.GetLayer(layerName);
                for (int i = 0; i < layer.FeatureCount(); i++)
                {
                    VectorTileFeature feat = layer.GetFeature(i);
                    var properties         = feat.GetProperties();
                    foreach (var prop in properties)
                    {
                        Assert.AreEqual(prop.Value, feat.GetValue(prop.Key), "Property values match");
                    }
                    foreach (var geomPart in feat.Geometry <int>())
                    {
                        foreach (var coord in geomPart)
                        {
                            //TODO add Assert
                        }
                    }
                }
            }
            string geojson = vt.ToGeoJson(0, 0, 0);

            Assert.GreaterOrEqual(geojson.Length, 30, "geojson >= 30 chars");
        }
Exemple #7
0
        private void ParseLabelLayerToList(List <GOParsedLayer> list, VectorTile vt, GOLabelsLayer layer)
        {
            string[] lyrs = tile.GetLabelsStrings().Split(',');
//			string kindKey = tile.GetPoisKindKey();

            foreach (string l in lyrs)
            {
                VectorTileLayer lyr = vt.GetLayer(l);
                if (lyr != null)
                {
                    int featureCount = lyr.FeatureCount();

                    if (featureCount == 0)
                    {
                        continue;
                    }

                    GOParsedLayer pl = new GOParsedLayer();
                    pl.name        = lyr.Name;
                    pl.labelsLayer = layer;
                    pl.goFeatures  = new List <GOFeature> ();

                    for (int i = 0; i < featureCount; i++)
                    {
                        VectorTileFeature vtf        = lyr.GetFeature(i);
                        IDictionary       properties = vtf.GetProperties();

                        List <List <LatLng> > geomWgs = vtf.GeometryAsWgs84((ulong)goTile.zoomLevel, (ulong)goTile.tileCoordinates.x, (ulong)goTile.tileCoordinates.y, 0);

                        if (geomWgs.Count == 0 || geomWgs[0].Count <= 1)
                        {
                            continue;
                        }

                        GOFeature gf = new GOFeature();
                        gf.properties    = properties;
                        gf.goFeatureType = vtf.GOFeatureType(geomWgs);
                        gf.labelsLayer   = layer;
                        gf.featureIndex  = (Int64)i + vt.LayerNames().IndexOf(lyr.Name);
                        gf.goTile        = goTile;
                        gf = tile.EditLabelData(gf);
                        gf.goFeatureType = GOFeatureType.Label;

                        gf.ConvertAttributes();
                        if (geomWgs.Count > 0)
                        {
                            gf.geometry = geomWgs[0];
                            gf.ConvertGeometries();
                            gf.preloadedLabelData = GOSegment.FindTheLongestStreightSegment(gf.convertedGeometry, 0);
                            AddFatureToList(gf, pl.goFeatures);
                        }
                    }
                    list.Add(pl);
                }
            }
        }
Exemple #8
0
        private void BuildVectorTile()
        {
            // Define which features from the vector tile will be made into game objects
            var builderDictionary = new Dictionary <string, MeshBuilder>()
            {
                {
                    "building", new MeshBuilder()
                    {
                        Modifiers = new List <MeshModifier>()
                        {
                            new PolygonMeshModifier(),
                            new UvModifier(),
                            new HeightModifier()
                        }
                    }
                },
                // Not using these for now.
                //{
                //    "road", new MeshBuilder()
                //    {
                //        Modifiers = new List<MeshModifier>()
                //        {
                //            new LineMeshModifier(),
                //            new UvModifier(),
                //            new HeightModifier()
                //        }
                //    }
                //}
            };

            var parameters = new Tile.Parameters
            {
                Fs = _fileSource,
                Id = new CanonicalTileId(zoomLevel, (int)tileCoordinate.x, (int)tileCoordinate.y)
            };

            // Use VectorTile class for vector tiles. Requests mapbox.mapbox-streets-v7 mapid by default.
            var vectorTile = new VectorTile();

            vectorTile.Initialize(parameters, () =>
            {
                if (vectorTile.Error != null)
                {
                    Debug.Log(vectorTile.Error);
                    return;
                }

                foreach (var builder in builderDictionary)
                {
                    var layer = vectorTile.GetLayer(builder.Key);
                    builder.Value.Create(layer, tileRect, heightData, tileObject.transform, parameters);
                }
            });
        }
        public VectorTileFeature[] SelectLayerFeatures(VectorTile tile, string layerName)
        {
            var layer = tile.GetLayer(layerName);

            var features = new VectorTileFeature[layer.FeatureCount()];

            for (var i = 0; i < features.Length; i++)
            {
                features[i] = layer.GetFeature(i);
            }

            return(features);
        }
Exemple #10
0
        public void TestVectTile()
        {
            var        pbf = File.ReadAllBytes(@"E:\Downloads\63.pbf");
            VectorTile vt  = new VectorTile(pbf, false);

            foreach (var layerName in vt.LayerNames())
            {
                VectorTileLayer layer = vt.GetLayer(layerName);
                for (int j = 0; j < layer.FeatureCount(); j++)
                {
                    VectorTileFeature feat = layer.GetFeature(j);
                    var ff    = feat.Geometry <long>();
                    var props = feat.GetProperties();
                }
            }
        }
Exemple #11
0
        public void FeatureSinglePoint()
        {
            byte[]     data = File.ReadAllBytes(Path.Combine(fixturesPath, "Feature-single-point.mvt"));
            VectorTile vt   = new VectorTile(data);

            Assert.AreEqual(1, vt.LayerNames().Count, "one layer");
            VectorTileLayer lyr = vt.GetLayer(vt.LayerNames()[0]);

            Assert.AreEqual("layer_name", lyr.Name, "Layer name");
            Assert.AreEqual(1, lyr.FeatureCount(), "Feature count");
            VectorTileFeature feat = lyr.GetFeature(0);

            Assert.AreEqual(GeomType.POINT, feat.GeometryType, "Geometry type");
            Assert.AreEqual(123, feat.Id, "id");
            Dictionary <string, object> properties = feat.GetProperties();

            Assert.AreEqual("world", properties["hello"]);
            Assert.AreEqual("world", feat.GetValue("hello"));
        }
Exemple #12
0
        public void Validate(string fileName)
        {
            string fullFileName = Path.Combine(_fixturesPath, fileName);

            Assert.True(File.Exists(fullFileName), "Vector tile exists");
            byte[] data = File.ReadAllBytes(fullFileName);
            Assert.Throws(Is.InstanceOf <Exception>(), () =>
            {
                VectorTile vt = new VectorTile(data);
                foreach (var layerName in vt.LayerNames())
                {
                    var layer = vt.GetLayer(layerName);
                    for (int i = 0; i < layer.FeatureCount(); i++)
                    {
                        var feat = layer.GetFeature(i);
                        feat.GetProperties();
                    }
                }
            });
        }
Exemple #13
0
        public void IterateAllProperties(string fileName)
        {
            string fullFileName = Path.Combine(fixturesPath, fileName);

            Assert.True(File.Exists(fullFileName), "Vector tile exists");
            byte[]     data = File.ReadAllBytes(fullFileName);
            VectorTile vt   = new VectorTile(data);

            foreach (var layerName in vt.LayerNames())
            {
                var layer = vt.GetLayer(layerName);
                for (int i = 0; i < layer.FeatureCount(); i++)
                {
                    var feat       = layer.GetFeature(i);
                    var properties = feat.GetProperties();
                    foreach (var prop in properties)
                    {
                        Assert.IsInstanceOf <string>(prop.Key);
                    }
                }
            }
        }
Exemple #14
0
        static int Main(string[] args)
        {
            //ul 14/4680/6260
            //lr 14/4693/6274
            ulong zoom   = 14;
            ulong minCol = 4680;
            ulong minRow = 6260;
            ulong maxCol = 4693;
            ulong maxRow = 6274;

            string fixturePath = Path.Combine(Path.Combine(Path.Combine(Path.Combine(Path.Combine("..", ".."), ".."), "bench"), "mvt-bench-fixtures"), "fixtures");

            if (!Directory.Exists(fixturePath))
            {
                Console.Error.WriteLine("fixture directory not found: [{0}]", fixturePath);
                return(1);
            }

            ulong           nrOfTiles = (maxCol - minCol + 1) * (maxRow - minRow + 1);
            List <TileData> tiles     = new List <TileData>((int)nrOfTiles);

            for (ulong col = minCol; col <= maxCol; col++)
            {
                for (ulong row = minRow; row <= maxRow; row++)
                {
                    string fileName = string.Format("{0}-{1}-{2}.mvt", zoom, col, row);
                    fileName = Path.Combine(fixturePath, fileName);
                    if (!File.Exists(fileName))
                    {
                        Console.Error.WriteLine("fixture mvt not found: [{0}]", fileName);
                        return(1);
                    }
                    else
                    {
                        tiles.Add(new TileData()
                        {
                            zoom = zoom,
                            col  = col,
                            row  = row,
                            pbf  = File.ReadAllBytes(fileName)
                        });
                    }
                }
            }

            Stopwatch   stopWatch = new Stopwatch();
            List <long> elapsed   = new List <long>();

            for (int i = 0; i <= 100; i++)
            {
                Console.Write(".");
                stopWatch.Start();
                foreach (var tile in tiles)
                {
                    VectorTile vt = new VectorTile(tile.pbf, false);
                    foreach (var layerName in vt.LayerNames())
                    {
                        VectorTileLayer layer = vt.GetLayer(layerName);
                        for (int j = 0; j < layer.FeatureCount(); j++)
                        {
                            VectorTileFeature feat = layer.GetFeature(j);
                            var props = feat.GetProperties();
                        }
                    }
                }
                stopWatch.Stop();
                //skip first run
                if (i != 0)
                {
                    elapsed.Add(stopWatch.ElapsedMilliseconds);
                }
                stopWatch.Reset();
            }


            Console.WriteLine(
                @"
runs          : {0}
tiles per run : {1}
min [ms]      : {2}
max [ms]      : {3}
avg [ms]      : {4}
StdDev        : {5:0.00}
overall [ms]  : {6}
tiles/sec     : {7:0.0}
",
                elapsed.Count,
                tiles.Count,
                elapsed.Min(),
                elapsed.Max(),
                elapsed.Average(),
                StdDev(elapsed),
                elapsed.Sum(),
                ((float)elapsed.Count * (float)tiles.Count / (float)elapsed.Sum()) * 1000
                );


            return(0);
        }
Exemple #15
0
        private void ParsePOILayerToList(List <GOParsedLayer> list, VectorTile vt, GOPOILayer layer)
        {
            string[] lyrs    = tile.GetPoisStrings().Split(',');
            string   kindKey = tile.GetPoisKindKey();

            foreach (string l in lyrs)
            {
                VectorTileLayer lyr = vt.GetLayer(l);
                if (lyr != null)
                {
                    int featureCount = lyr.FeatureCount();

                    if (featureCount == 0)
                    {
                        continue;
                    }

                    GOParsedLayer pl = new GOParsedLayer();
                    pl.name       = lyr.Name;
                    pl.poiLayer   = layer;
                    pl.goFeatures = new List <GOFeature> ();

                    for (int i = 0; i < featureCount; i++)
                    {
                        VectorTileFeature vtf        = lyr.GetFeature(i);
                        IDictionary       properties = vtf.GetProperties();

                        GOPOIKind      kind      = GOEnumUtils.PoiKindToEnum((string)properties[kindKey]);
                        GOPOIRendering rendering = layer.GetRenderingForPoiKind(kind);

                        if (kind == GOPOIKind.UNDEFINED || rendering == null)
                        {
                            continue;
                        }

                        List <List <LatLng> > geomWgs = vtf.GeometryAsWgs84((ulong)goTile.zoomLevel, (ulong)goTile.tileCoordinates.x, (ulong)goTile.tileCoordinates.y, 0);
                        GOFeature             gf      = new GOFeature();
                        gf.poiKind       = kind;
                        gf.goTile        = goTile;
                        gf.properties    = properties;
                        gf.attributes    = GOFeature.PropertiesToAttributes(gf.properties);
                        gf.goFeatureType = vtf.GOFeatureType(geomWgs);

                        if (gf.goFeatureType == GOFeatureType.Undefined)
                        {
                            continue;
                        }

                        gf.poiLayer     = layer;
                        gf.poiRendering = rendering;
                        gf.featureIndex = (Int64)i + vt.LayerNames().IndexOf(lyr.Name);
                        gf = tile.EditFeatureData(gf);
                        gf.ConvertAttributes();

                        if (geomWgs.Count > 0 && gf.goFeatureType == GOFeatureType.Point)
                        {
                            gf.geometry = geomWgs [0];
                            gf.ConvertPOIGeometries();
                            AddFatureToList(gf, pl.goFeatures);
                        }
                    }

                    list.Add(pl);
                }
            }
        }
Exemple #16
0
        private void ParseGOLayerToList(List <GOParsedLayer> list, VectorTile vt, GOLayer layer)
        {
            string[] lyrs = tile.GetLayersStrings(layer).Split(',');

            foreach (string l in lyrs)
            {
                VectorTileLayer lyr = vt.GetLayer(l);
                if (lyr != null)
                {
                    int featureCount = lyr.FeatureCount();

                    if (featureCount == 0)
                    {
                        continue;
                    }

                    GOParsedLayer pl = new GOParsedLayer();
                    pl.name       = lyr.Name;
                    pl.goLayer    = layer;
                    pl.goFeatures = new List <GOFeature> ();

                    int indexOfLayer = vt.LayerNames().IndexOf(lyr.Name);

                    for (int i = 0; i < featureCount; i++)
                    {
                        VectorTileFeature vtf = lyr.GetFeature(i);

                        List <List <LatLng> > geomWgs = vtf.GeometryAsWgs84((ulong)goTile.zoomLevel, (ulong)goTile.tileCoordinates.x, (ulong)goTile.tileCoordinates.y, 0);

                        GOFeature gf;
                        if (layer.layerType == GOLayer.GOLayerType.Roads)
                        {
                            gf = new GORoadFeature();
                        }
                        else
                        {
                            gf = new GOFeature();
                        }

                        gf.properties    = vtf.GetProperties();
                        gf.attributes    = GOFeature.PropertiesToAttributes(gf.properties);
                        gf.goFeatureType = vtf.GOFeatureType(geomWgs);
                        gf.layer         = layer;
                        gf.featureIndex  = (Int64)i;
                        gf.layerIndex    = indexOfLayer;
                        gf.featureCount  = featureCount;
                        gf        = tile.EditFeatureData(gf);
                        gf.goTile = goTile;
//							gf.setRenderingOptions ();
                        gf.ConvertAttributes();

                        if (geomWgs.Count > 0)
                        {
                            switch (gf.goFeatureType)
                            {
                            case GOFeatureType.Line:
                                gf.geometry = geomWgs [0];
                                gf.ConvertGeometries();
                                AddFatureToList(gf, pl.goFeatures);
                                break;

                            case GOFeatureType.Polygon:
                                gf.geometry = geomWgs[0];
                                gf.ConvertGeometries();
                                AddFatureToList(gf, pl.goFeatures);
                                break;

                            case GOFeatureType.MultiLine:
                                foreach (IList geometry in geomWgs)
                                {
                                    float     indexMulti = (((float)geomWgs.IndexOf((List <LatLng>)geometry) + 1) * (i + 1) / geomWgs.Count);
                                    GOFeature gfm;
                                    if (layer.layerType == GOLayer.GOLayerType.Roads)
                                    {
                                        gfm = new GORoadFeature((GORoadFeature)gf);
                                    }
                                    else
                                    {
                                        gfm = new GOFeature(gf);
                                    }

//									gfm.index = indexMulti;
                                    gfm.geometry = geometry;
                                    gfm.ConvertGeometries();
                                    AddFatureToList(gfm, pl.goFeatures);
                                }
                                break;

                            case GOFeatureType.MultiPolygon:
                                foreach (IList geometry in geomWgs)
                                {
                                    List <Vector3>         convertedSubject = null;
                                    List <List <Vector3> > convertedClips   = new List <List <Vector3> >();

                                    for (int j = 0; j < geomWgs.Count; j++)                                     //Clip ascending

                                    {
                                        IList          p          = geomWgs [j];
                                        List <Vector3> convertedP = GOFeature.CoordsToVerts(p, layer.layerType == GOLayer.GOLayerType.Buildings);
                                        if (GOFeature.IsClockwise(convertedP))
                                        {
                                            convertedSubject = convertedP;
                                        }
                                        else
                                        {
                                            //Add clip
                                            convertedClips.Add(convertedP);
                                        }
                                        //Last one
                                        if (j == geomWgs.Count - 1 || (j < geomWgs.Count - 1 && GOFeature.IsGeoPolygonClockwise(geomWgs [j + 1]) && convertedSubject != null))
                                        {
                                            GOFeature gfm = new GOFeature(gf);
//											gfm.index = (i +1)*j;
                                            gfm.convertedGeometry = convertedSubject;
                                            gfm.clips             = convertedClips;
                                            AddFatureToList(gfm, pl.goFeatures);

                                            convertedSubject = null;
                                            convertedClips   = new List <List <Vector3> >();
                                        }
                                    }
                                }
                                break;
                            }
                        }
                    }

                    if (goTile.combineFeatures)
                    {
                        pl = GOCombineFeatures.Combine(pl);
                    }

                    list.Add(pl);
                }
            }
        }
        /// <summary>
        /// Return the whole vector tile as GeoJSON
        /// </summary>
        /// <param name="tile"></param>
        /// <param name="zoom">Zoom level of the tile</param>
        /// <param name="tileColumn">Column of the tile (OSM tile schema)</param>
        /// <param name="tileRow">Row of the tile (OSM tile schema)</param>
        /// <param name="clipBuffer">
        /// <para>Vector tiles may contain data reaching beyond the actual tile border.</para>
        /// <para>Define if/how this data should be included.</para>
        /// <para>'null': data from the vector tile as is</para>
        /// <para>'&gt;=0': clip distance in internal tile units</para>
        /// </param>
        /// <returns>GeoJSON of the vector tile contents</returns>
        public static string ToGeoJson(
            this VectorTile tile
            , ulong zoom
            , ulong tileColumn
            , ulong tileRow
            , uint?clipBuffer = null
            )
        {
            //to get '.' instead of ',' when using "string.format" with double/float and non-US system number format settings
            //CultureInfo en_US = new CultureInfo("en-US");

            // escaping '{' '}' -> @"{{" "}}"
            //escaping '"' -> @""""
            string templateFeatureCollection = @"{{""type"":""FeatureCollection"",""features"":[{0}]}}";
            string templateFeature           = @"{{""type"":""Feature"",""geometry"":{{""type"":""{0}"",""coordinates"":[{1}]}},""properties"":{2}}}";

            List <string> geojsonFeatures = new List <string>();

            foreach (var layerName in tile.LayerNames())
            {
                var layer = tile.GetLayer(layerName);

                for (int i = 0; i < layer.FeatureCount(); i++)
                {
                    var feat = layer.GetFeature(i, clipBuffer);

                    if (feat.GeometryType == GeomType.UNKNOWN)
                    {
                        continue;
                    }

                    //resolve properties
                    List <string> keyValue = new List <string>();
                    for (int j = 0; j < feat.Tags.Count; j += 2)
                    {
                        string key = layer.Keys[feat.Tags[j]];
                        object val = layer.Values[feat.Tags[j + 1]];
                        keyValue.Add(string.Format(NumberFormatInfo.InvariantInfo, @"""{0}"":""{1}""", key, val));
                    }

                    //build geojson properties object from resolved properties
                    string geojsonProps = string.Format(
                        NumberFormatInfo.InvariantInfo
                        , @"{{""id"":{0},""lyr"":""{1}""{2}{3}}}"
                        , feat.Id
                        , layer.Name
                        , keyValue.Count > 0 ? "," : ""
                        , string.Join(",", keyValue.ToArray())
                        );

                    //work through geometries
                    string geojsonCoords = "";
                    string geomType      = feat.GeometryType.Description();

                    //multipart
                    List <List <LatLng> > geomWgs84 = feat.GeometryAsWgs84(zoom, tileColumn, tileRow);
                    if (geomWgs84.Count > 1)
                    {
                        switch (feat.GeometryType)
                        {
                        case GeomType.POINT:
                            geomType = "MultiPoint";
#if NET20
                            List <LatLng> allPoints = new List <LatLng>();
                            foreach (var part in geomWgs84)
                            {
                                foreach (var pnt in part)
                                {
                                    allPoints.Add(pnt);
                                }
                            }
                            geojsonCoords = string.Join(
                                ","
                                , allPoints.ConvertAll <string>(g => string.Format(NumberFormatInfo.InvariantInfo, "[{0},{1}]", g.Lng, g.Lat)).ToArray()
                                );
#else
                            geojsonCoords = string.Join(
                                ","
                                , geomWgs84
                                .SelectMany((List <LatLng> g) => g)
                                .Select(g => string.Format(NumberFormatInfo.InvariantInfo, "[{0},{1}]", g.Lng, g.Lat)).ToArray()
                                );
#endif
                            break;

                        case GeomType.LINESTRING:
                            geomType = "MultiLineString";
                            List <string> parts = new List <string>();
                            foreach (var part in geomWgs84)
                            {
                                parts.Add("[" + string.Join(
                                              ","
#if NET20
                                              , part.ConvertAll <string>(g => string.Format(NumberFormatInfo.InvariantInfo, "[{0},{1}]", g.Lng, g.Lat)).ToArray()
#else
                                              , part.Select(g => string.Format(NumberFormatInfo.InvariantInfo, "[{0},{1}]", g.Lng, g.Lat)).ToArray()
#endif
                                              ) + "]");
                            }
                            geojsonCoords = string.Join(",", parts.ToArray());
                            break;

                        case GeomType.POLYGON:
                            geomType = "MultiPolygon";
                            List <string> partsMP = new List <string>();
                            foreach (var part in geomWgs84)
                            {
                                partsMP.Add("[" + string.Join(
                                                ","
#if NET20
                                                , part.ConvertAll <string>(g => string.Format(NumberFormatInfo.InvariantInfo, "[{0},{1}]", g.Lng, g.Lat)).ToArray()
#else
                                                , part.Select(g => string.Format(NumberFormatInfo.InvariantInfo, "[{0},{1}]", g.Lng, g.Lat)).ToArray()
#endif
                                                ) + "]");
                            }
                            geojsonCoords = "[" + string.Join(",", partsMP.ToArray()) + "]";
                            break;

                        default:
                            break;
                        }
                    }
                    else if (geomWgs84.Count == 1)                        //singlepart
                    {
                        switch (feat.GeometryType)
                        {
                        case GeomType.POINT:
                            geojsonCoords = string.Format(NumberFormatInfo.InvariantInfo, "{0},{1}", geomWgs84[0][0].Lng, geomWgs84[0][0].Lat);
                            break;

                        case GeomType.LINESTRING:
                            geojsonCoords = string.Join(
                                ","
#if NET20
                                , geomWgs84[0].ConvertAll <string>(g => string.Format(NumberFormatInfo.InvariantInfo, "[{0},{1}]", g.Lng, g.Lat)).ToArray()
#else
                                , geomWgs84[0].Select(g => string.Format(NumberFormatInfo.InvariantInfo, "[{0},{1}]", g.Lng, g.Lat)).ToArray()
#endif
                                );
                            break;

                        case GeomType.POLYGON:
                            geojsonCoords = "[" + string.Join(
                                ","
#if NET20
                                , geomWgs84[0].ConvertAll <string>(g => string.Format(NumberFormatInfo.InvariantInfo, "[{0},{1}]", g.Lng, g.Lat)).ToArray()
#else
                                , geomWgs84[0].Select(g => string.Format(NumberFormatInfo.InvariantInfo, "[{0},{1}]", g.Lng, g.Lat)).ToArray()
#endif
                                ) + "]";
                            break;

                        default:
                            break;
                        }
                    }
                    else                        //no geometry
                    {
                        continue;
                    }

                    geojsonFeatures.Add(
                        string.Format(
                            NumberFormatInfo.InvariantInfo
                            , templateFeature
                            , geomType
                            , geojsonCoords
                            , geojsonProps
                            )
                        );
                }
            }

            string geoJsonFeatColl = string.Format(
                NumberFormatInfo.InvariantInfo
                , templateFeatureCollection
                , string.Join(",", geojsonFeatures.ToArray())
                );

            return(geoJsonFeatColl);
        }
        private void ParseTilesetsToList(List <GOParsedLayer> list, VectorTile vt, GOTilesetLayer[] tilesets)
        {
            foreach (GOTilesetLayer tileSet in tilesets)
            {
                string kind = string.IsNullOrEmpty(tileSet.TilesetKindProperty)? tileSet.TilesetKindProperty : "kind";

                VectorTileLayer lyr = vt.GetLayer(tileSet.TilesetName);
                if (lyr != null)
                {
                    int featureCount = lyr.FeatureCount();

                    if (featureCount == 0)
                    {
                        continue;
                    }

                    GOParsedLayer pl = new GOParsedLayer();
                    pl.name         = lyr.Name;
                    pl.tilesetLayer = tileSet;
                    pl.goFeatures   = new List <GOFeature>();

                    for (int i = 0; i < featureCount; i++)
                    {
                        VectorTileFeature vtf = lyr.GetFeature(i);

                        List <List <LatLng> > geomWgs = vtf.GeometryAsWgs84((ulong)goTile.zoomLevel, (ulong)goTile.tileCoordinates.x, (ulong)goTile.tileCoordinates.y, 0);
                        GOFeature             gf      = new GOFeature();

                        gf.properties    = vtf.GetProperties();
                        gf.attributes    = GOFeature.PropertiesToAttributes(gf.properties);
                        gf.goFeatureType = vtf.GOFeatureType(geomWgs);
                        gf.tileSetKind   = kind;
                        gf.tilesetLayer  = tileSet;
                        gf.goTile        = goTile;
                        gf.featureIndex  = (Int64)i;
                        //gf.layerIndex = indexOfLayer;
                        gf.featureCount = featureCount;
                        //gf = tile.EditFeatureData(gf);
                        gf.goTile = goTile;
                        gf.ConvertAttributes();

                        if (gf.goFeatureType == GOFeatureType.Undefined)
                        {
                            continue;
                        }

                        string name = "Dataset " + gf.goFeatureType.ToString();
                        //Debug.Log(name);

                        if (geomWgs.Count > 0 && (gf.goFeatureType == GOFeatureType.Point || gf.goFeatureType == GOFeatureType.MultiPoint)) //Probably needs a fix for multi points
                        {
                            //GOPOIKind kind = GOEnumUtils.PoiKindToEnum((string)properties[kindKey]);
                            GOTilesetPOIRendering rendering = tileSet.TilesetPOIRenderingForKind(kind);
                            if (rendering == null)
                            {
                                continue;
                            }

                            gf.geometry            = geomWgs[0];
                            gf.tileSetPoiRendering = rendering;
                            gf.name = name;
                            gf.ConvertPOIGeometries();
                            AddFatureToList(gf, pl.goFeatures);
                        }

                        else if (geomWgs.Count > 0)
                        {
                            switch (gf.goFeatureType)
                            {
                            case GOFeatureType.Line:
                                GOTilesetLINERendering lineRendering = tileSet.TilesetLINERenderingForKind(kind);
                                if (lineRendering == null)
                                {
                                    continue;
                                }
                                gf.geometry = geomWgs[0];
                                gf.ConvertGeometries();
                                gf.tileSetLineRendering = lineRendering;
                                gf.name   = name;
                                gf.height = lineRendering.height;
                                AddFatureToList(gf, pl.goFeatures);
                                break;

                            case GOFeatureType.Polygon:

                                GOTilesetPOLYGONRendering polygonRendering = tileSet.TilesetPOLYGONRenderingForKind(kind);
                                if (polygonRendering == null)
                                {
                                    continue;
                                }
                                gf.geometry = geomWgs[0];
                                gf.ConvertGeometries();
                                gf.name = name;
                                gf.tileSetPolygonRendering = polygonRendering;
                                gf.height = polygonRendering.height;
                                AddFatureToList(gf, pl.goFeatures);
                                break;

                            case GOFeatureType.MultiLine:
                                lineRendering = tileSet.TilesetLINERenderingForKind(kind);
                                if (lineRendering == null)
                                {
                                    continue;
                                }
                                foreach (IList geometry in geomWgs)
                                {
                                    float     indexMulti = (((float)geomWgs.IndexOf((List <LatLng>)geometry) + 1) * (i + 1) / geomWgs.Count);
                                    GOFeature gfm        = new GOFeature(gf);
                                    gf.name      = name;
                                    gfm.geometry = geometry;
                                    gfm.ConvertGeometries();
                                    gf.tileSetLineRendering = lineRendering;
                                    gf.height = lineRendering.height;
                                    AddFatureToList(gfm, pl.goFeatures);
                                }
                                break;

                            case GOFeatureType.MultiPolygon:
                                foreach (IList geometry in geomWgs)
                                {
                                    polygonRendering = tileSet.TilesetPOLYGONRenderingForKind(kind);
                                    if (polygonRendering == null)
                                    {
                                        continue;
                                    }
                                    List <Vector3>         convertedSubject = null;
                                    List <List <Vector3> > convertedClips   = new List <List <Vector3> >();

                                    for (int j = 0; j < geomWgs.Count; j++)
                                    {     //Clip ascending
                                        IList          p          = geomWgs[j];
                                        List <Vector3> convertedP = GOFeature.CoordsToVerts(p, false);
                                        if (GOFeature.IsClockwise(convertedP))
                                        {
                                            convertedSubject = convertedP;
                                        }
                                        else
                                        {
                                            //Add clip
                                            convertedClips.Add(convertedP);
                                        }
                                        //Last one
                                        if (j == geomWgs.Count - 1 || (j < geomWgs.Count - 1 && GOFeature.IsGeoPolygonClockwise(geomWgs[j + 1]) && convertedSubject != null))
                                        {
                                            GOFeature gfm = new GOFeature(gf);
                                            //											gfm.index = (i +1)*j;
                                            gfm.convertedGeometry      = convertedSubject;
                                            gfm.clips                  = convertedClips;
                                            gf.tileSetPolygonRendering = polygonRendering;
                                            gf.name = name;
                                            AddFatureToList(gfm, pl.goFeatures);
                                            convertedSubject = null;
                                            convertedClips   = new List <List <Vector3> >();
                                        }
                                    }
                                }
                                break;
                            }
                        }
                    }

                    list.Add(pl);
                }
            }
        }
Exemple #19
0
        public void DifferentPoint2dTypesAndScaling()
        {
            string fullFileName = Path.Combine(fixturesPath, "Feature-single-linestring.mvt");

            byte[]     data = File.ReadAllBytes(fullFileName);
            VectorTile vt   = new VectorTile(data);

            foreach (var layerName in vt.LayerNames())
            {
                VectorTileLayer layer = vt.GetLayer(layerName);
                for (int i = 0; i < layer.FeatureCount(); i++)
                {
                    VectorTileFeature featLong = layer.GetFeature(i);
                    foreach (var geomPart in featLong.Geometry <long>())
                    {
                        foreach (var coord in geomPart)
                        {
                            Debug.WriteLine("long: {0}/{1}", coord.X, coord.Y);
                        }
                        Assert.AreEqual(2L, geomPart[0].X);
                        Assert.AreEqual(2L, geomPart[0].Y);
                        Assert.AreEqual(2L, geomPart[1].X);
                        Assert.AreEqual(10L, geomPart[1].Y);
                        Assert.AreEqual(10L, geomPart[2].X);
                        Assert.AreEqual(10L, geomPart[2].Y);
                    }

                    // don't clip, as this might change order of vertices
                    // test 'scale' on the VectorTileFeature constructor
                    VectorTileFeature featInt = layer.GetFeature(i, null, 1.5f);
                    foreach (var geomPart in featInt.Geometry <int>())
                    {
                        foreach (var coord in geomPart)
                        {
                            Debug.WriteLine("integer: {0}/{1}", coord.X, coord.Y);
                        }
                        Assert.AreEqual(3, geomPart[0].X);
                        Assert.AreEqual(3, geomPart[0].Y);
                        Assert.AreEqual(3, geomPart[1].X);
                        Assert.AreEqual(15, geomPart[1].Y);
                        Assert.AreEqual(15, geomPart[2].X);
                        Assert.AreEqual(15, geomPart[2].Y);
                    }

                    // don't clip, as this might change order of vertices
                    VectorTileFeature featFloat = layer.GetFeature(i);
                    // test 'scale' on the Geometry method
                    foreach (var geomPart in featFloat.Geometry <float>(null, 2.0f))
                    {
                        foreach (var coord in geomPart)
                        {
                            Debug.WriteLine("float: {0}/{1}", coord.X, coord.Y);
                        }
                        Assert.AreEqual(4f, geomPart[0].X);
                        Assert.AreEqual(4f, geomPart[0].Y);
                        Assert.AreEqual(4f, geomPart[1].X);
                        Assert.AreEqual(20f, geomPart[1].Y);
                        Assert.AreEqual(20f, geomPart[2].X);
                        Assert.AreEqual(20f, geomPart[2].Y);
                    }
                }
            }
            string geojson = vt.ToGeoJson(0, 0, 0);

            Assert.GreaterOrEqual(geojson.Length, 30, "geojson >= 30 chars");
        }