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"); } } } } } }
public CustomFeatureUnity(VectorTileFeature feature, CustomTile tile, float layerExtent, bool buildingsWithUniqueIds = false) { Data = feature; Properties = Data.GetProperties(); Points.Clear(); Tile = tile; //this is a temp hack until we figure out how streets ids works _geom = buildingsWithUniqueIds ? feature.Geometry <float>() : feature.Geometry <float>(0); _rectSizex = tile.Rect.Size.x; _rectSizey = tile.Rect.Size.y; _geomCount = _geom.Count; for (var i = 0; i < _geomCount; i++) { _pointCount = _geom[i].Count; _newPoints = new List <Vector3>(_pointCount); for (var j = 0; j < _pointCount; j++) { var point = _geom[i][j]; _newPoints.Add(new Vector3((float)(point.X / layerExtent * _rectSizex - (_rectSizex / 2)) * tile.TileScale, 0, (float)((layerExtent - point.Y) / layerExtent * _rectSizey - (_rectSizey / 2)) * tile.TileScale)); } Points.Add(_newPoints); } }
public VectorFeatureUnity(VectorTileFeature feature, UnityTile tile, float layerExtent, bool buildingsWithUniqueIds = false) { Data = feature; Properties = Data.GetProperties(); Points.Clear(); //this is a temp hack until we figure out how streets ids works if (buildingsWithUniqueIds == true) //ids from building dataset is big ulongs { _geom = feature.Geometry <float>(); //and we're not clipping by passing no parameters } else //streets ids, will require clipping { _geom = feature.Geometry <float>(0); //passing zero means clip at tile edge } _rectSizex = tile.Rect.Size.x; _rectSizey = tile.Rect.Size.y; _geomCount = _geom.Count; for (int i = 0; i < _geomCount; i++) { _pointCount = _geom[i].Count; _newPoints = new List <Vector3>(_pointCount); for (int j = 0; j < _pointCount; j++) { var point = _geom[i][j]; _newPoints.Add(new Vector3((float)(point.X / layerExtent * _rectSizex - (_rectSizex / 2)) * tile.TileScale, 0, (float)((layerExtent - point.Y) / layerExtent * _rectSizey - (_rectSizey / 2)) * tile.TileScale)); } Points.Add(_newPoints); } }
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"); } } } }
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"); }
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"); } } } } }
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); } } } } } }
/// <summary> /// >Geometry in LatLng coordinates instead of internal tile coordinates /// </summary> /// <param name="feature"></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> /// <returns></returns> public static List <List <LatLng> > GeometryAsWgs84( this VectorTileFeature feature , ulong zoom , ulong tileColumn , ulong tileRow , uint?clipBuffer = null ) { List <List <LatLng> > geometryAsWgs84 = new List <List <LatLng> >(); foreach (var part in feature.Geometry <long>(clipBuffer, 1.0f)) { #if NET20 List <LatLng> partAsWgs84 = new List <LatLng>(); foreach (var partGeom in part) { partAsWgs84.Add(partGeom.ToLngLat(zoom, tileColumn, tileRow, feature.Layer.Extent)); } geometryAsWgs84.Add(partAsWgs84); #else geometryAsWgs84.Add( part.Select(g => g.ToLngLat(zoom, tileColumn, tileRow, feature.Layer.Extent)).ToList() ); #endif } return(geometryAsWgs84); }
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(); } } }
private static void DrawPolygon(VectorTileFeature feature, Pallete pallete, Graphics graphics, double divisionRatio) { List <List <Vector2 <int> > > list = feature.Geometry <int>(); foreach (List <Vector2 <int> > item in list) { Point[] points = item.Select(vector2 => new Point((int)Math.Ceiling(vector2.X / divisionRatio), (int)Math.Ceiling(vector2.Y / divisionRatio))).ToArray(); using (SolidBrush solidBrush = new SolidBrush(pallete.MainFillColor)) { graphics.FillPolygon(solidBrush, points); } using (Pen pen = new Pen(pallete.MainDrawPen.Color, 2)) { graphics.DrawPolygon(pen, points); } } }
// Need check memory and disk existing because we can load road graph for path finding private void CacheRoads(Vector3 <double> lonLatZoom, VectorTileObj data) { if (memoryRoadsCache.ContainsKey(lonLatZoom.ToString())) { return; } if (diskRoadCache.TryGetValue(lonLatZoom.ToString(), out string path)) { memoryRoadsCache.TryAdd(lonLatZoom.ToString(), JsonConvert.DeserializeObject <Graph>(File.ReadAllText(path), settings)); return; } Graph graph; if (data.LayerNames().Contains("roads")) { VectorTileLayer layer = data.GetLayer("roads"); MaskGraphCreator maskDrawer = new MaskGraphCreator(GetTileSize(ConvertToMapZoom(Settings.zoom))); for (int i = 0; i < layer.FeatureCount(); i++) { VectorTileFeature feature = layer.GetFeature(i); foreach (List <Vector2 <int> > geometry in feature.Geometry <int>()) { for (int index = 1; index < geometry.Count; index++) { maskDrawer.DrawMaskLine(geometry[index - 1], geometry[index]); } } } graph = maskDrawer.GetGraph(); } else { graph = new Graph(); } memoryRoadsCache.TryAdd(lonLatZoom.ToString(), graph); // Save to disk path = $"{pathToDataFolder}\\roads\\{lonLatZoom.EncodeToString()}{RoadFileExtension}"; File.WriteAllText(path, JsonConvert.SerializeObject(graph, settings)); // Add to disk cache diskRoadCache.TryAdd(lonLatZoom.ToString(), path); }
/// <summary> /// >Geometry in LatLng coordinates instead of internal tile coordinates /// </summary> /// <param name="feature"></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> /// <returns></returns> public static List <List <LatLng> > GeometryAsWgs84( this VectorTileFeature feature , ulong zoom , ulong tileColumn , ulong tileRow , uint?clipBuffer = null ) { var geometryAsWgs84 = new List <List <LatLng> >(); foreach (List <Vector2 <long> > part in feature.Geometry <long>(clipBuffer, 1.0f)) { geometryAsWgs84.Add( part.Select(g => g.ToLngLat(zoom, tileColumn, tileRow, feature.Layer.Extent)).ToList() ); } return(geometryAsWgs84); }
public VectorFeatureUnity(VectorTileFeature feature, UnityTile tile, float layerExtent) { Data = feature; Properties = Data.GetProperties(); Points = new List <List <Vector3> >(); List <List <Point2d <float> > > geom = feature.Geometry <float>(0); for (int i = 0; i < geom.Count; i++) { var nl = new List <Vector3>(geom[i].Count); for (int j = 0; j < geom[i].Count; j++) { var point = geom[i][j]; nl.Add(new Vector3((float)(point.X / layerExtent * tile.Rect.Size.x - (tile.Rect.Size.x / 2)), 0, (float)((layerExtent - point.Y) / layerExtent * tile.Rect.Size.y - (tile.Rect.Size.y / 2)))); } Points.Add(nl); } }
private static void CreatePolygon(VectorTileFeature feature, Pallete pallete, Model3DGroup model3DGroup, Vector2 <int> shiftCoords) { PointCollection points = new PointCollection(); List <List <Vector2 <int> > > list = feature.Geometry <int>(); foreach (List <Vector2 <int> > item in list) { points.Clear(); foreach (Vector2 <int> point in item) { points.Add(new Point(point.X + shiftCoords.X, point.Y + shiftCoords.Y)); } points.RemoveAt(points.Count - 1); var model = new GeometryModel3D(); var meshbuilder = new MeshBuilder(true, true); var result = CuttingEarsTriangulator.Triangulate(points); List <int> tri = new List <int>(); for (int i = 0; i < result.Count; i++) { tri.Add(result[i]); if (tri.Count == 3) { //Console.WriteLine("Triangle " + (i / 3).ToString() + " : " + tri[0].ToString() + ", " + tri[1].ToString() + ", " + tri[2].ToString()); meshbuilder.AddTriangle(new Point3D(points[tri[0]].X, points[tri[0]].Y, 1), new Point3D(points[tri[1]].X, points[tri[1]].Y, 1), new Point3D(points[tri[2]].X, points[tri[2]].Y, 1)); tri.Clear(); } } model.Geometry = meshbuilder.ToMesh(); model.Material = MaterialHelper.CreateMaterial(pallete.MainFillColor.ToMediaColor()); model3DGroup.Children.Add(model); } }
public VectorFeatureUnity(VectorTileFeature feature, UnityTile tile, float layerExtent) { Data = feature; Properties = Data.GetProperties(); Points.Clear(); _rectSizex = tile.Rect.Size.x; _rectSizey = tile.Rect.Size.y; _geom = feature.Geometry <float>(0); _geomCount = _geom.Count; for (int i = 0; i < _geomCount; i++) { _pointCount = _geom[i].Count; _newPoints = new List <Vector3>(_pointCount); for (int j = 0; j < _pointCount; j++) { var point = _geom[i][j]; _newPoints.Add(new Vector3((float)(point.X / layerExtent * _rectSizex - (_rectSizex / 2)) * tile.TileScale, 0, (float)((layerExtent - point.Y) / layerExtent * _rectSizey - (_rectSizey / 2)) * tile.TileScale)); } Points.Add(_newPoints); } }
private static void DrawLineString(VectorTileFeature feature, Pallete pallete, Graphics graphics, double divisionRatio) { Dictionary <string, object> props = feature.GetProperties(); foreach (List <Vector2 <int> > geometry in feature.Geometry <int>()) { Point[] points = geometry.Select(vector2 => new Point((int)Math.Ceiling(vector2.X / divisionRatio), (int)Math.Ceiling(vector2.Y / divisionRatio))).ToArray(); using (Pen pen = new Pen(pallete.MainDrawPen.Color, 2)) { graphics.DrawLines(pen, points); } // Draw name of street //if (props.ContainsKey("name")) //{ // var text = (string)props["name"]; // foreach (Vector2<int> point in geometry) // { // graphics.DrawString(text, font, pallete.GetPropFillBrush("name"), point.X, point.Y); // } //} } }
public VectorFeatureUnity(VectorTileFeature feature, UnityTile tile, float layerExtent) { Data = feature; Properties = Data.GetProperties(); Points = new List <List <Vector3> >(); double unityTileSizeX = tile.Rect.Size.x; double unityTileSizeY = tile.Rect.Size.y; List <List <Point2d <float> > > geom = feature.Geometry <float>(); var geomCount = geom.Count; for (int i = 0; i < geomCount; i++) { var pointCount = geom[i].Count; var nl = new List <Vector3>(pointCount); for (int j = 0; j < pointCount; j++) { var point = geom[i][j]; nl.Add(new Vector3((float)(point.X / layerExtent * unityTileSizeX - (unityTileSizeX / 2)) * tile.TileScale, 0, (float)((layerExtent - point.Y) / layerExtent * unityTileSizeY - (unityTileSizeY / 2)) * tile.TileScale)); } Points.Add(nl); } }
private void btnGo_Click(object sender, EventArgs e) { SynchronizationContext sync = SynchronizationContext.Current; lvInfo.Items.Clear(); int countReq = 0; int countResp = 0; FileSource fs = new FileSource(); //https://api.mapbox.com/v4/mapbox.mapbox-streets-v7/14/3410/6200.vector.pbf //https://api.mapbox.com/v4/mapbox.mapbox-streets-v7/14/3410/6200.vector.pbf //https://a.tiles.mapbox.com/v4/mapbox.mapbox-streets-v7/18/74984/100276.vector.pbf object locker = new object(); DateTime dtStart = DateTime.Now; System.Diagnostics.Debug.WriteLine(string.Format(" ============> WinForm, thread id:{0} <==============", System.Threading.Thread.CurrentThread.ManagedThreadId)); for (int i = (int)outerLoopStart.Value; i < (int)outerLoopStop.Value; i++) { for (int x = (int)tileXstart.Value; x < tileXstop.Value; x++) { countReq++; lblReqCnt.Text = countReq.ToString(); HTTPRequest request = (HTTPRequest)fs.Request( string.Format("https://a.tiles.mapbox.com/v4/mapbox.mapbox-streets-v7/18/{0}/100276.vector.pbf", x) , (Response r) => { System.Diagnostics.Debug.WriteLine(string.Format("winform response, thread id:{0}", System.Threading.Thread.CurrentThread.ManagedThreadId)); //lock (locker) { countResp++; if (countResp == 1) { foreach (var hdr in r.Headers) { addItem(string.Format("{0}: {1}", hdr.Key, hdr.Value)); } } if (0 == countResp % 500) { Application.DoEvents(); } try { if (lblRespCnt.InvokeRequired) { System.Diagnostics.Debug.WriteLine(string.Format("winform lblRespCnt.InvokeRequired, thread id:{0}", System.Threading.Thread.CurrentThread.ManagedThreadId)); //lblRespCnt.Invoke(new Action(() => { lblRespCnt.Text = countResp.ToString(); })); //Invoke((MethodInvoker)delegate { lblRespCnt.Text = countResp.ToString(); }); //sync.Send(delegate { lblRespCnt.Text = countResp.ToString(); }, null); //sync.Send(delegate { lblRespCnt.Text = countResp.ToString(); }, null); sync.Post(delegate { lblRespCnt.Text = countResp.ToString(); }, null); } else { System.Diagnostics.Debug.WriteLine(string.Format("winform !lblRespCnt.InvokeRequired, thread id:{0}", System.Threading.Thread.CurrentThread.ManagedThreadId)); lblRespCnt.Text = countResp.ToString(); } } catch (Exception ex) { addItem(ex.ToString()); } //} if (r.RateLimitHit) { addItem(string.Format("{3} statuscode:{4} rate limit hit:{5} --- LimitInterval:{0} LimitLimit:{1} LimitReset:{2}", r.XRateLimitInterval, r.XRateLimitLimit, r.XRateLimitReset, x, r.StatusCode, r.RateLimitHit)); } if (r.StatusCode != 200) { if (null != r.Data && r.Data.Length > 0) { addItem(Encoding.UTF8.GetString(r.Data)); } else { addItem(string.Format("StatusCode: {0} - NO body", r.StatusCode)); } } if (r.HasError) { addItem(""); foreach (var ex in r.Exceptions) { addItem(ex.ToString()); } addItem(""); return; } if (IDC_chkDecodeVTs.Checked) { try { VectorTile.VectorTile vt = new VectorTile.VectorTile(r.Data); foreach (var lyrName in vt.LayerNames()) { VectorTileLayer lyr = vt.GetLayer(lyrName); for (int j = 0; j < lyr.FeatureCount(); j++) { VectorTileFeature feat = lyr.GetFeature(j); feat.GetProperties(); feat.Geometry <int>(); } } } catch (Exception ex) { addItem(ex.ToString()); } } } ); } } addItem("waiting ..."); Application.DoEvents(); //while (!request.IsCompleted) { } fs.WaitForAllRequests(); DateTime dtFinished = DateTime.Now; addItem(string.Format("finished! requests:{0} responses:{1}", countReq, countResp)); addItem(string.Format( "{0} -> {1}, elapsed {2}s" , dtStart.ToString("HH:mm:ss") , dtFinished.ToString("HH:mm:ss") , dtFinished.Subtract(dtStart).TotalSeconds )); }
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"); }