public BuildingPart BuildPart(XElement way, bool volume = true) { var tags = way.Descendants("tag") .ToDictionary( tag => tag.Attribute("k").Value, // add key tag => tag.Attribute("v").Value); // add value // Building creation var buildingPart = new BuildingPart( tags.ContainsKey("name") ? tags["name"] : "", Convert.ToInt64(way.Attribute("id").Value)); // Outline construction // TODO check if closed? foreach (var elt in way.Descendants("nd")) { // find node that matches ways' node ref var query = (from node in Xdoc.Descendants("node") where (string)node.Attribute("id") == (string)elt.Attribute("ref") select node).First(); var pos = Mercator.ToMeters(Convert.ToDouble(query.Attribute("lat").Value), Convert.ToDouble(query.Attribute("lon").Value)); var x = pos.X - Tile.Center.X; var y = pos.Y - Tile.Center.Y; buildingPart.Outline.Add(new Vector2(x, y)); } // Part data PartData part; part.volume = volume; part.height = float.Parse(tags.ContainsKey("height") ? Regex.Match(tags["height"], @"\d+").Value : "-1", CultureInfo.InvariantCulture); part.min_height = float.Parse(tags.ContainsKey("min_height") ? Regex.Match(tags["min_height"], @"\d+").Value : "-1", CultureInfo.InvariantCulture); part.levels = Convert.ToInt16(tags.ContainsKey("building:levels") ? tags["building:levels"] : "-1"); part.min_level = Convert.ToInt16(tags.ContainsKey("building:min_level") ? tags["building:min_level"] : "-1"); buildingPart.Data = part; Surface surf; surf.colour = tags.ContainsKey("building:colour") ? tags["building:colour"] : ""; surf.material = tags.ContainsKey("building:material") ? tags["building:material"] : ""; buildingPart.PartSurface = surf; return(buildingPart); }
/// <summary> /// Create builidng esh /// </summary> /// <param name="building"></param> /// <returns></returns> public static Mesh CreateMesh(BuildingPart building) { var minY = building.Body.min_height; var maxY = building.Body.height; var poly = building.Footprint; var total = poly.Points.Count; if (poly is MultiPolygon) { (poly as MultiPolygon).Holes.ForEach(x => total += x.Points.Count); } // Build mesh var vertices = new Vector3[total * 2]; var faces = new List <int>(); var colors = Enumerable.Repeat(building.Body.surface.color, total * 2).ToArray(); // Create vertices and polygon for triangulation var idx = 0; var P2Tpoints = new List <PolygonPointExt>(); foreach (var point in poly.Points) { vertices[idx] = new Vector3(point.X, minY, -point.Y); vertices[idx + total] = new Vector3(point.X, maxY, -point.Y); P2Tpoints.Add(new PolygonPointExt(point.X, point.Y, idx++)); } var P2Tpoly = new Poly2TriPolygon.Polygon(P2Tpoints); // add faces = 2 triangles for (var i = 0; i < poly.Points.Count - 1; i++) { faces.Add(i + total); faces.Add(i); faces.Add(i + 1); faces.Add(i + total); faces.Add(i + 1); faces.Add(i + total + 1); } if (poly is MultiPolygon) { (poly as MultiPolygon).Holes.ForEach(hole => { // Create holes vertices and holes for triangulation var P2Thole = new List <PolygonPointExt>(); for (var i = 0; i < hole.Points.Count; i++) { vertices[idx + i] = new Vector3(hole.Points[i].X, minY, -hole.Points[i].Y); vertices[idx + i + total] = new Vector3(hole.Points[i].X, maxY, -hole.Points[i].Y); P2Thole.Add(new PolygonPointExt(hole.Points[i].X, hole.Points[i].Y, idx + i)); } // Create holes faces = 2 triangles for (var i = 0; i < hole.Points.Count - 1; i++) { faces.Add(idx + i + total); faces.Add(idx + i); faces.Add(idx + i + 1); faces.Add(idx + i + total); faces.Add(idx + i + 1); faces.Add(idx + i + total + 1); } P2Tpoly.AddHole(new Poly2TriPolygon.Polygon(P2Thole)); idx += hole.Points.Count; }); } try { P2T.Triangulate(P2Tpoly); // Add triangulated top faces foreach (var tri in P2Tpoly.Triangles) { var i0 = tri.Points[0] as PolygonPointExt; var i1 = tri.Points[1] as PolygonPointExt; var i2 = tri.Points[2] as PolygonPointExt; // apply to bottom // faces.Add(i2.Idx); // faces.Add(i1.Idx); // faces.Add(i0.Idx); // apply to top faces.Add(i2.Idx + total); faces.Add(i1.Idx + total); faces.Add(i0.Idx + total); // Add roof color colors[i0.Idx + total] = building.Roof.surface.color; colors[i2.Idx + total] = building.Roof.surface.color; colors[i1.Idx + total] = building.Roof.surface.color; } return(new Mesh(vertices, faces.ToArray(), colors)); } catch (Exception ex) { Console.WriteLine(ex.Message); } return(null); }