static void TriangulatePolygon(Polygon polygon) { var xy = TwoDimensionalPolygon(polygon, "xy"); var xz = TwoDimensionalPolygon(polygon, "xz"); var yz = TwoDimensionalPolygon(polygon, "yz"); var xyArea = PolygonArea(xy); var xzArea = PolygonArea(xz); var yzArea = PolygonArea(yz); string components = ((xyArea > xzArea) && (xyArea > yzArea)) ? "xy" : ((xzArea > xyArea) && (xzArea > yzArea)) ? "xz" : "yz"; polygon.CreateVertUVDictionary(); double[,] exterior = ListTo2DArray(polygon.bounds, components); polygon.CreateVertDictionary(ListTo2DArray(polygon.verts, components)); double[,] bounds = CalculateBounds(exterior); DelaunayClient delaunayClient = new DelaunayClient(bounds, settings: (int)DelaunayClient.Option.REMOVE_EXTERIOR | (int)DelaunayClient.Option.REMOVE_HOLES); delaunayClient.InsertConstrainedPolygon(exterior); foreach (List <double> interior in polygon.interior) { var interiorArray = ListTo2DArray(interior, components); delaunayClient.InsertConstrainedPolygon(interiorArray); } double[,] empty = new double[0, 0]; delaunayClient.GatherTriangles(empty, true, out polygon.delaunayVerts, out polygon.delaunayTriangles); polygon.ConvertDelaunay(); }
static void WriteBuildingToOBJ(Building building, string path) { //var thread = Thread.CurrentThread; //Console.WriteLine("Starting Thread {0}", thread.ManagedThreadId); building.CreateSideUVs(); if (building.needsCoordinateTransform) { for (int i = 0; i < building.sides.Count; ++i) { Polygon p = building.sides[i]; ProjectPolygon(ref p, building.latitude, building.longitude); } } foreach (Polygon polygon in building.sides) { var xy = TwoDimensionalPolygon(polygon, "xy"); var xz = TwoDimensionalPolygon(polygon, "xz"); var yz = TwoDimensionalPolygon(polygon, "yz"); var xyArea = PolygonArea(xy); var xzArea = PolygonArea(xz); var yzArea = PolygonArea(yz); string components = ((xyArea > xzArea) && (xyArea > yzArea)) ? "xy" : ((xzArea > xyArea) && (xzArea > yzArea)) ? "xz" : "yz"; polygon.CreateVertUVDictionary(); double[,] exterior = ListTo2DArray(polygon.bounds, components); polygon.CreateVertDictionary(ListTo2DArray(polygon.verts, components)); double[,] bounds = CalculateBounds(exterior); DelaunayClient delaunayClient = new DelaunayClient(bounds, settings: (int)DelaunayClient.Option.REMOVE_EXTERIOR | (int)DelaunayClient.Option.REMOVE_HOLES); delaunayClient.InsertConstrainedPolygon(exterior); foreach (List <double> interior in polygon.interior) { var interiorArray = ListTo2DArray(interior, components); delaunayClient.InsertConstrainedPolygon(interiorArray); } double[,] empty = new double[0, 0]; delaunayClient.GatherTriangles(empty, true, out polygon.delaunayVerts, out polygon.delaunayTriangles); polygon.ConvertDelaunay(); delaunayClient.Release(); } string filename = Path.GetFileName(path); var filenameNoExtension = filename.Replace(".gml", ""); string buildingName = "\\" + building.state + "_" + building.county + "_" + building.ubid + ".obj"; if (buildingName == "\\__.obj") { buildingName = "\\" + building.GetID() + ".obj"; } string buildingMTL = buildingName.Replace(".obj", ".mtl"); CreateMTLFile(building.textures, PathToOutputFolder + buildingMTL); buildingMTL = buildingMTL.Trim('\\'); using (StreamWriter sw = File.CreateText(PathToOutputFolder + buildingName)) { int vtOffset = 0; sw.WriteLine("Produced by Cognitics"); sw.WriteLine(DateTime.Now); string origin = building.centerpoint == null ? "ORIGIN: " + building.latitude + " " + building.longitude : "ORIGIN: " + building.centerpoint[0] + " " + building.centerpoint[1] + " " + building.centerpoint[2]; sw.WriteLine(origin); sw.WriteLine("mtllib " + buildingMTL); sw.WriteLine(""); int triangleOffset = 1; foreach (Polygon p in building.sides) { bool vertexTextures = false; sw.WriteLine("# PolygonID " + p.gmlID + " ParentID " + p.parentID); for (int i = 0; i < p.verts.Count - 1; i += 3) { sw.WriteLine("v " + p.verts[i] + " " + p.verts[i + 1] + " " + p.verts[i + 2]); } for (int i = 0; i < p.uvs.Count - 1; i += 2) { vertexTextures = true; sw.WriteLine("vt " + p.uvs[i] + " " + p.uvs[i + 1]); } if (!vertexTextures) { vtOffset -= (p.verts.Count / 3); } if (vertexTextures) { sw.WriteLine("usemtl " + p.gmlID); for (int i = 0; i < p.triangles.Length; i += 3) { int firstV = p.triangles[i] + triangleOffset; int secondV = p.triangles[i + 1] + triangleOffset; int thirdV = p.triangles[i + 2] + triangleOffset; int firstVT = p.triangles[i] + triangleOffset + vtOffset; int secondVT = p.triangles[i + 1] + triangleOffset + vtOffset; int thirdVT = p.triangles[i + 2] + triangleOffset + vtOffset; sw.WriteLine("f " + firstV + "/" + firstVT + " " + secondV + "/" + secondVT + " " + thirdV + "/" + thirdVT); } } else { for (int i = 0; i < p.triangles.Length; i += 3) { sw.WriteLine("f " + (p.triangles[i] + triangleOffset) + " " + (p.triangles[i + 1] + triangleOffset) + " " + (p.triangles[i + 2] + triangleOffset)); } } triangleOffset += p.verts.Count / 3; sw.WriteLine(); } } ++progress; }