diff --git a/sandbox/mesh-layering-2023/CMakeLists.txt b/sandbox/mesh-layering-2023/CMakeLists.txt new file mode 100644 index 0000000..54a2e73 --- /dev/null +++ b/sandbox/mesh-layering-2023/CMakeLists.txt @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 3.12) +project(mesh_layering) + +find_package(pybind11 REQUIRED) + +set(SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/cpp/) +set(BUILDER_DIR $ENV{HOME}/dtcc-builder) + +# Set include directories +include_directories(${BUILDER_DIR}/src/cpp/include/) +include_directories(${BUILDER_DIR}/src/cpp/include/model/) +include_directories(${BUILDER_DIR}/src/cpp/external) +include_directories(/usr/local/include) + +pybind11_add_module(_mesh_layering ${SRC_DIR}/mesh_layering.cpp) \ No newline at end of file diff --git a/sandbox/mesh-layering-2023/cpp/include/FaceColoring.h b/sandbox/mesh-layering-2023/cpp/include/FaceColoring.h new file mode 100644 index 0000000..5f41973 --- /dev/null +++ b/sandbox/mesh-layering-2023/cpp/include/FaceColoring.h @@ -0,0 +1,229 @@ +#ifndef DTCC_FACE_COLORING_H +#define DTCC_FACE_COLORING_H + +#include "Logging.h" +#include "model/Mesh.h" + +namespace DTCC_BUILDER +{ + +double ideal_layer_height(double area, const double scale = 1.0) +{ + // Compute ideal layer height for a regular tetrahedron + const double c = std::pow(2.0, 1.5) * std::pow(3.0, -0.75); + double h = scale * c * std::sqrt(area); + return h; +} + +double area2(std::array &vertices) +{ + Vector3D e0 = vertices[2] - vertices[1]; + Vector3D e1 = vertices[0] - vertices[2]; + Vector3D e2 = vertices[1] - vertices[0]; + const double l0 = e0.magnitude(); + const double l1 = e1.magnitude(); + const double l2 = e2.magnitude(); + + double s = (l0 + l1 + l2) * 0.5; + return sqrt(s * (s - l0) * (s - l1) * (s - l2)); +} + +double area(std::array &vertices) +{ + const Vector3D e0 = vertices[2] - vertices[1]; + const Vector3D e1 = vertices[0] - vertices[2]; + const Vector3D e2 = vertices[0] - vertices[1]; + + // Calculate the cross product of the two sides + double crossProductX = e0.y * e2.z - e0.z * e2.y; + double crossProductY = e0.z * e2.x - e0.x * e2.z; + double crossProductZ = e0.x * e2.y - e0.y * e2.x; + + double area = 0.5 * std::sqrt(crossProductX * crossProductX + crossProductY * crossProductY + crossProductZ * crossProductZ); + return area ; +} + +void assign_colors(std::vector &layer_heights, + std::vector &areas, + std::vector &face_colors) +{ + const size_t num_faces = areas.size(); + + // Assign layer heights to mesh (closest by quotient) + for (size_t i = 0; i < num_faces; i++) + { + double h = ideal_layer_height(areas[i]); + std::vector d(layer_heights.size()); + d.reserve(layer_heights.size()); + + for (size_t ih = 0; ih < layer_heights.size(); ih++) + { + d[ih] = std::abs(std::log(h / layer_heights[ih])); + } + auto min_it = std::min_element(d.begin(), d.end()); + face_colors[i] = std::distance(d.begin(), min_it); + } +} + +void reassign_colors(std::vector &face_colors, std::vector> &ff ) +{ + // Reassign colors to avoid big jumps + for (size_t i = 0; i < ff.size(); i++) + { + for (const auto& j : ff[i]) + { + int diff = face_colors[i] - face_colors[j]; + if(diff > 1 ) + { + face_colors[i] -= diff -1 ; + } + } + } + +} + +size_t check_neighbors(std::vector &face_colors, + std::vector> &ff) +{ + int max_diff = 0; + size_t num_big_diffs = 0; + std::vector big_diff_colors; + for (size_t i = 0; i < ff.size(); i++) + { + const auto face = ff[i]; + int diff_num = 0; + for (const auto &f : face) + { + int diff = face_colors[i] - face_colors[f]; + if (diff > 1) + { + max_diff = std::max(max_diff, diff); + diff_num++; + } + } + if (diff_num > 0) + { + num_big_diffs++; + big_diff_colors.push_back(1); + } + else + { + big_diff_colors.push_back(0); + } + } + double big_diff_percentage = 100.0 * num_big_diffs / static_cast(ff.size()); + const std::string s = "Num Big diffs " + + str(num_big_diffs) + + " / " + + str(ff.size()) + + " (" + + str(big_diff_percentage, 2L) + + "%)" ; + + info(s); + return num_big_diffs; +} + +void compute_layer_heights(const Mesh &mesh, + std::vector &layer_heights, + std::vector &face_colors) +{ + std::vector areas(mesh.faces.size()) ; + for (std::size_t i = 0; i < mesh.faces.size(); i++) + { + std::array vertices = { + mesh.vertices[mesh.faces[i].v0], + mesh.vertices[mesh.faces[i].v1], + mesh.vertices[mesh.faces[i].v2]}; + areas[i] = area(vertices); + } + + // Compute ideal layer heights for smallest and largest mesh sizes + double _min_area = 0.0; + auto min = std::min_element(areas.begin(), areas.end()); + if (min != areas.end()) + { + _min_area = *min; + } + + double _max_area = 0.0; + auto max = std::max_element(areas.begin(), areas.end()); + if (max != areas.end()) + { + _max_area = *max; + } + + info("Min Face Area: " + str(_min_area)); + info("Max Face Area: " + str(_max_area)); + + info("Min Face Ideal Layer Height: " + str(ideal_layer_height(_min_area))); + info("Max Face Ideal Layer Height: " + str(ideal_layer_height(_max_area))); + // info("Test Layer Height: " + str(ideal_layer_height(1.0))); + + double _min_height = ideal_layer_height(_min_area); + double _max_height = ideal_layer_height(_max_area); + + // Compute dyadic mesh sizes to match min/max as close as possible + double rho = _max_height / _min_height ; + double mid = std::sqrt(_min_height*_max_height); + int num_layers = static_cast(std::log2(rho) + 0.5); + double min_height = mid / std::pow(2, num_layers / 2); + + info("rho: " + str(rho) + " | mid: " + str(mid)); + info("Num of Layers: " + str(num_layers)); + + // Create layer_heights array + for (int i = 0; i < num_layers ; i++) { + layer_heights.push_back(min_height * std::pow(2.0, i)); + } + + for (size_t i=0 ; i < layer_heights.size(); i++) + { + std::cout <<"Layer "<< i <<": "<< layer_heights[i] <<"m"<< std::endl; + } + + info("Assign layer heights to mesh"); + // Assign layer heights to mesh (closest by quotient) + assign_colors(layer_heights, areas, face_colors ); + + + info("Build mapping from vertices to faces"); + // Build mapping from vertices to faces + std::vector> vf(mesh.vertices.size()); + for (size_t i = 0; i < mesh.faces.size(); i++) + { + vf[mesh.faces[i].v0].insert(i); + vf[mesh.faces[i].v1].insert(i); + vf[mesh.faces[i].v2].insert(i); + } + + info("Build mapping from faces to faces"); + // Build mapping from faces to faces + std::vector> ff(mesh.faces.size()); + for (size_t i = 0; i < mesh.faces.size(); i++) + { + for (size_t j = 0; j < 3; j++) + { + for (const int &v : vf[mesh.faces[i][j]]) + { + ff[i].insert(v); + } + } + } + + info("Iteratively reassign colors to avoid big jumps"); + // Iteratively reassign colors to avoid big jumps + // Note: It should not do 3 iterations but reassign colors until there are + // 0 big jumps. + for( size_t i = 0 ; i < 3; i++) + { + if(check_neighbors(face_colors,ff)){ + info("Reassigning colors, iteration " + str(i)); + reassign_colors(face_colors, ff); + } + } +} + +} // namespace DTCC_BUILDER + +#endif // DTCC_FACE_COLORING_H \ No newline at end of file diff --git a/sandbox/mesh-layering-2023/cpp/include/MeshLayering.h b/sandbox/mesh-layering-2023/cpp/include/MeshLayering.h new file mode 100644 index 0000000..62e7b33 --- /dev/null +++ b/sandbox/mesh-layering-2023/cpp/include/MeshLayering.h @@ -0,0 +1,327 @@ +/* Notes: +* +* - NULL values will be removed. Are there to make partitions more intuitive. +* - Partition index "errors" are counting how many times index is getting out of vertex column bounds. +*/ + +#ifndef DTCC_MESH_LAYERING_H +#define DTCC_MESH_LAYERING_H + +#include "model/Mesh.h" +#include "Logging.h" + +namespace DTCC_BUILDER +{ + +void color_sort(std::array &vertices ,std::array &colors ) +{ + // Combine colors and vertices into a vector of pairs + std::vector> combinedList; + for (size_t i = 0; i < colors.size(); ++i) { + combinedList.emplace_back(vertices[i], colors[i]); + } + + // Sort the combined list first based on the first element (vertices) + std::sort(combinedList.begin(), combinedList.end(), + [](const auto& lhs, const auto& rhs) { + return lhs.first < rhs.first; + }); + + // Sort again based on the second element (colors) + std::sort(combinedList.begin(), combinedList.end(), + [](const auto& lhs, const auto& rhs) { + return lhs.second < rhs.second; + }); + + // Unpack the sorted list back into colors and vertices + for (size_t i = 0; i < combinedList.size(); ++i) { + colors[i] = combinedList[i].second; + vertices[i] = combinedList[i].first; + } +} + + +VolumeMesh mesh_layering(const Mesh &mesh, + std::vector &layer_heights, + std::vector &face_colors, + const double domain_height) +{ + VolumeMesh volume_mesh; + info("Mesh Layering Function."); + const size_t num_vertices = mesh.vertices.size() ; + const size_t num_faces = mesh.faces.size(); + + const size_t num_layers = layer_heights.size(); + if(num_layers == 0) + { + error("Error: Empty Layer heights Vector."); + return volume_mesh; + } + const double min_layer_height = layer_heights[0]; + const double max_layer_height = layer_heights[num_layers-1]; + info("Number of layers: " + str(num_layers) ); + info("Min Layer Height: " + str(min_layer_height)); + info("Max Layer Height: " + str(max_layer_height)); + + const double adjusted_domain_height = std::ceil(domain_height/max_layer_height) * max_layer_height; + info("Domain height adjusted to fit chosen layer heights: " + str(adjusted_domain_height) + "m"); + + // Each Vertex inherits the minimum color (layer height) from the faces it belongs to. + std::vector vertex_colors(num_vertices, num_layers); + for (size_t i = 0; i < num_faces; i++) + { + const std::vector face = {mesh.faces[i].v0, mesh.faces[i].v1, mesh.faces[i].v2}; + for( const auto &j : face) + { + if (vertex_colors[j] > face_colors[i]) vertex_colors[j] = face_colors[i]; + } + } + + + std::vector> col_vertices(num_vertices); + std::vector col_index_offset(num_vertices+1,0); + + for (size_t i = 0; i < num_vertices; i++) + { + const double layer_h = layer_heights[vertex_colors[i]]; + const size_t col_count = static_cast((adjusted_domain_height/layer_h)) + 1; + for (size_t j = 0; j < col_count; j++) + { + Vector3D v(mesh.vertices[i].x,mesh.vertices[i].y, mesh.vertices[i].z + j * layer_h); + col_vertices[i].push_back(v); + } + col_index_offset[i+1] = col_index_offset[i] + col_vertices[i].size(); + } + + // for (size_t i = 0; i < 1000; i++) + // { + // std::cout < partition_errors = {0}; + std::vector cells; + for (size_t i = 0; i < num_faces; i++) + { + //std::cout << "Working on face "<< i+1 <<"/"<< num_faces<< std::endl; + const Simplex2D face_simplex = mesh.faces[i]; + std::array face = {face_simplex.v0, face_simplex.v1, face_simplex.v2}; + std::array v_colors = {vertex_colors[face_simplex.v0], vertex_colors[face_simplex.v1], vertex_colors[face_simplex.v2]}; + color_sort(face, v_colors); + + + const std::array column_offsets = {col_index_offset[face[0]], + col_index_offset[face[1]], + col_index_offset[face[2]]}; + // std::cout << "Face: "< column_len = {col_index_offset[face[0]+1] - col_index_offset[face[0]], + col_index_offset[face[1]+1] - col_index_offset[face[1]], + col_index_offset[face[2]+1] - col_index_offset[face[2]]}; + // std::cout << "Face: "<> prism_iterator(num_prisms); + + for (size_t j = 0; j < num_prisms; j++) + { + prism_iterator[j] = { column_offsets[0]+ j * (1 << (face_colors[i]-v_colors[0])), + column_offsets[1]+ j * (1 << (face_colors[i]-v_colors[1])), + column_offsets[2]+ j * (1 << (face_colors[i]-v_colors[2]))}; + } + + switch (3*face_colors[i] - (v_colors[0]+v_colors[1]+v_colors[2])) + { + case 0: + { + for (const auto& ar: prism_iterator) + { + const size_t k = ar[0]; + const size_t l = ar[1]; + const size_t m = ar[2]; + + if (k + 1 >= col_index_offset[face[0] + 1]) partition_errors[0]++; + if (l + 1 >= col_index_offset[face[1] + 1]) partition_errors[0]++; + if (m + 1 >= col_index_offset[face[2] + 1]) partition_errors[0]++; + + std::array bot_triangle = {k, l, m}; + std::array mid_triangle = {NULL, NULL, NULL}; + std::array top_triangle = {k+1, l+1, m+1}; + + Simplex3D K0(bot_triangle[0], bot_triangle[1], bot_triangle[2], top_triangle[2]); + Simplex3D K1(bot_triangle[0], top_triangle[1], bot_triangle[1], top_triangle[2]); + Simplex3D K2(bot_triangle[0], top_triangle[0], top_triangle[1], top_triangle[2]); + + + cells.emplace_back(K0); + cells.emplace_back(K1); + cells.emplace_back(K2); + } + } + break; + case 1: + { + for (const auto& ar: prism_iterator) + { + const size_t k = ar[0]; + const size_t l = ar[1]; + const size_t m = ar[2]; + + if (k + 2 >= col_index_offset[face[0] + 1]) partition_errors[1]++; + if (l + 1 >= col_index_offset[face[1] + 1]) partition_errors[1]++; + if (m + 1 >= col_index_offset[face[2] + 1]) partition_errors[1]++; + + std::array bot_triangle = {k, l, m}; + std::array mid_triangle = {k+1, NULL, NULL}; + std::array top_triangle = {k+2, l+1, m+1}; + + // Simplex3D K0(k, l, m, k + 1); + // Simplex3D K1(l, m, k + 1, k + 1); + // Simplex3D K2(l, m, k + 1, k + 2); + // Simplex3D K3(k + 1, m + 1, k + 2, l + 1); + + Simplex3D K0(bot_triangle[0], bot_triangle[1], bot_triangle[2], mid_triangle[0]); + Simplex3D K1(bot_triangle[1], top_triangle[2], bot_triangle[2], mid_triangle[0]); + Simplex3D K2(bot_triangle[1], top_triangle[2], mid_triangle[0], top_triangle[1]); + Simplex3D K3(mid_triangle[0], top_triangle[0], top_triangle[1], top_triangle[2]); + + cells.emplace_back(K0); + cells.emplace_back(K1); + cells.emplace_back(K2); + cells.emplace_back(K3); + } + } + break; + case 2: + { + for (const auto& ar: prism_iterator) + { + const size_t k = ar[0]; + const size_t l = ar[1]; + const size_t m = ar[2]; + + if (k + 2 >= col_index_offset[face[0] + 1]) + { + partition_errors[2]++; + } + if (l + 2 >= col_index_offset[face[1] + 1]) + { + partition_errors[2]++; + + } + if (m + 1 >= col_index_offset[face[2] + 1]) + { + partition_errors[2]++; + + } + + std::array bot_triangle = {k, l, m}; + std::array mid_triangle = {k+1, l+1, NULL}; + std::array top_triangle = {k+2, l+2, m+1}; + + // Simplex3D K0(k, l, m, l + 1); + // Simplex3D K1(k, m, k + 1, l + 1); + // Simplex3D K2(m, l, k + 1, l + 1); + // Simplex3D K3(k + 2, l + 2, m + 1, k + 1); + // Simplex3D K4(l + 2, m + 1, l + 1, k + 1); + + Simplex3D K0(bot_triangle[0], bot_triangle[1], bot_triangle[2], mid_triangle[1]); + Simplex3D K1(bot_triangle[0], bot_triangle[2], mid_triangle[0], mid_triangle[1]); + Simplex3D K2(bot_triangle[2], top_triangle[2], mid_triangle[0], mid_triangle[1]); + Simplex3D K3(top_triangle[0], top_triangle[2], top_triangle[1], mid_triangle[0]); + Simplex3D K4(top_triangle[1], top_triangle[2], mid_triangle[1], mid_triangle[0]); + + cells.emplace_back(K0); + cells.emplace_back(K1); + cells.emplace_back(K2); + cells.emplace_back(K3); + cells.emplace_back(K4); + + } + } + break; + + case 3: + { + for (const auto& ar: prism_iterator) + { + const size_t k = ar[0]; + const size_t l = ar[1]; + const size_t m = ar[2]; + + if (k + 2 >= col_index_offset[face[0] + 1]) + { + // std::cout <= col_index_offset[face[1] + 1]) + { + // std::cout << "Partition 3 l+2 = " << l+2 << " Next Column index" << col_index_offset[face[1] + 1] << " | " << col_index_offset[face[1]] << std::endl; + partition_errors[3]++; + continue; + } + if (m + 2 >= col_index_offset[face[2] + 1]) + { + // std::cout << "Partition 3 m+2 = " << m+2 << " Next Column index" << col_index_offset[face[2] + 1] << " | " << col_index_offset[face[2]] << std::endl; + partition_errors[3]++; + continue; + } + + std::array bot_triangle = {k, l, m}; + std::array mid_triangle = {k+1, l+1, m+1}; + std::array top_triangle = {k+2, l+2, m+2}; + + // Simplex3D K0(k, l, m, m + 1); + // Simplex3D K1(k, m + 1, l, m + 1); + // Simplex3D K2(k, m + 1, m, m + 1); + // Simplex3D K3(m + 1, m + 1, m + 2, m + 2); + // Simplex3D K4(m + 1, m + 2, m + 1, m + 2); + // Simplex3D K5(m + 1, m + 2, m, m + 2); + + Simplex3D K0(bot_triangle[0], bot_triangle[1], bot_triangle[2], mid_triangle[2]); + Simplex3D K1(bot_triangle[0], mid_triangle[1], bot_triangle[1], mid_triangle[2]); + Simplex3D K2(bot_triangle[0], mid_triangle[0], mid_triangle[1], mid_triangle[2]); + Simplex3D K3(mid_triangle[0], mid_triangle[1], mid_triangle[2], top_triangle[2]); + Simplex3D K4(mid_triangle[0], top_triangle[1], mid_triangle[1], top_triangle[2]); + Simplex3D K5(mid_triangle[0], top_triangle[0], top_triangle[1], top_triangle[2]); + + cells.emplace_back(K0); + cells.emplace_back(K1); + cells.emplace_back(K2); + cells.emplace_back(K3); + cells.emplace_back(K4); + cells.emplace_back(K5); + } + break; + } + default: + error("Face Coloring Error: Large layer height difference"); + break; + } + } + std::cout << "Index skip error Cases:" << std::endl; + std::cout << "Partition 0 Indexing errors: " << partition_errors[0] << std::endl; + std::cout << "Partition 1 Indexing errors: " << partition_errors[1] << std::endl; + std::cout << "Partition 2 Indexing errors: " << partition_errors[2] << std::endl; + std::cout << "Partition 3 Indexing errors: " << partition_errors[3] << std::endl; + + std::vector vertices; + for (size_t j = 0; j < col_vertices.size(); j++) + { + for (size_t k = 0; k < col_vertices[j].size(); k++) + { + vertices.push_back(col_vertices[j][k]); + } + } + + volume_mesh.cells = cells; + volume_mesh.vertices = vertices; + return volume_mesh; + } + + +} // namespace DTCC_BUILDER + +#endif // DTCC_MESH_LAYERING_H \ No newline at end of file diff --git a/sandbox/mesh-layering-2023/cpp/mesh_layering.cpp b/sandbox/mesh-layering-2023/cpp/mesh_layering.cpp new file mode 100644 index 0000000..e88fbd5 --- /dev/null +++ b/sandbox/mesh-layering-2023/cpp/mesh_layering.cpp @@ -0,0 +1,79 @@ +#include +#include + +#include "CityBuilder.h" +#include "ElevationBuilder.h" +#include "MeshBuilder.h" +#include "MeshProcessor.h" +#include "MeshQualityMetrics.h" +#include "Smoother.h" +#include "VertexSmoother.h" +#include "model/Building.h" +#include "model/City.h" +#include "model/GridField.h" +#include "model/Mesh.h" +#include "model/PointCloud.h" +#include "model/Polygon.h" +#include "model/Simplices.h" +#include "model/Vector.h" +#include "Timer.h" + +#include "include/FaceColoring.h" +#include "include/MeshLayering.h" + +namespace py = pybind11; + +namespace DTCC_BUILDER +{ + +VolumeMesh create_volume_mesh(py::array_t vertices, + py::array_t faces, + py::array_t markers) +{ + Mesh mesh; + auto verts_r = vertices.unchecked<2>(); + auto faces_r = faces.unchecked<2>(); + auto markers_r = markers.unchecked<1>(); + size_t num_vertices = verts_r.shape(0); + size_t num_faces = faces_r.shape(0); + size_t num_markers = markers_r.size(); + + for (size_t i = 0; i < num_vertices; i++) + { + mesh.vertices.push_back( + Vector3D(verts_r(i, 0), verts_r(i, 1), verts_r(i, 2))); + } + + for (size_t i = 0; i < num_faces; i++) + { + mesh.faces.push_back( + Simplex2D(faces_r(i, 0), faces_r(i, 1), faces_r(i, 2))); + } + + for (size_t i = 0; i < num_markers; i++) + { + mesh.markers.push_back(markers_r(i)); + } + info(mesh.__str__()) ; + + std::vector layer_heights; + std::vector face_colors(num_faces) ; + + Timer t1("Layer height computation"); + compute_layer_heights(mesh,layer_heights, face_colors); + t1.stop(); + t1.print(); + const double domain_height = 50; + + Timer t2("Mesh layering"); + VolumeMesh vm = mesh_layering(mesh, layer_heights,face_colors, domain_height); + t2.stop(); + t2.print(); + return vm; +} + +} // namespace DTCC_BUILDER + +PYBIND11_MODULE(_mesh_layering, m) { + m.def("create_volume_mesh", &DTCC_BUILDER::create_volume_mesh, "Create C++ mesh"); +} \ No newline at end of file diff --git a/sandbox/mesh-layering-2023/mesh_layering.py b/sandbox/mesh-layering-2023/mesh_layering.py new file mode 100644 index 0000000..ec81f47 --- /dev/null +++ b/sandbox/mesh-layering-2023/mesh_layering.py @@ -0,0 +1,71 @@ +from build import _mesh_layering +from dtcc import * +from dtcc_builder.model import builder_volume_mesh_to_volume_mesh +from dtcc_builder.logging import info +import numpy as np + +def crop_mesh(mesh, x_max: float = 0.05, y_max: float = 0.05): + + num_vertices = len(mesh.vertices) + num_faces = len(mesh.faces) + info(f"Loaded Mesh with: \n- Num of vertices:\t{num_vertices}\n- Num of faces: \t{num_faces}") + elevation = mesh.vertices[:,2] + domain_min_z = np.min(elevation) + domain_max_z = np.max(elevation) + domain_min_x = np.min(mesh.vertices[:,0]) + domain_max_x = np.max(mesh.vertices[:,0]) + domain_min_y = np.min(mesh.vertices[:,1]) + domain_max_y = np.max(mesh.vertices[:,1]) + info("Base Surface Mesh Domain") + info(f"X Range: [{domain_min_x}, {domain_max_x}]") + info(f"Y Range: [{domain_min_y}, {domain_max_y}]") + info(f"Z Range: [{domain_min_z}, {domain_max_z}]") + + + new_max_x = x_max * domain_max_x + new_max_y= y_max * domain_max_y + mesh_tile = Mesh() + vertices = [] + vertices_indexes = [] + for i,v in enumerate(mesh.vertices): + if v[0] <= new_max_x and v[1] <= new_max_y: + print(i,v) + vertices.append(v) + vertices_indexes.append(i) + faces = [] + face_indexes = [] + tile_face_colors = [] + for i,face in enumerate(mesh.faces): + if all(v in vertices_indexes for v in face): + faces.append(face) + face_indexes.append(i) + # tile_face_colors.append(face_colors[i]) + old_faces = faces.copy() + for i,idx in enumerate(vertices_indexes): + for j,f in enumerate(faces): + faces[j] = [i if vertex == idx else vertex for vertex in f] + for of, nf in zip(old_faces,faces): + of = np.array([mesh.vertices[of[0]], mesh.vertices[of[1]],mesh.vertices[of[2]]]) + nf = np.array([vertices[nf[0]], vertices[nf[1]], vertices[nf[2]]]) + if not np.array_equal(of,nf): + print("Error:", of ,nf) + + mesh_tile.vertices = np.array(vertices) + mesh_tile.faces = np.array(faces) + return mesh_tile + +def main(): + + mesh = load_mesh("../ansys-test-case-2023/output/surface_mesh_tc_1.pb") + # mesh = crop_mesh(mesh) + info(mesh.__str__()) + + _builder_volume_mesh = _mesh_layering.create_volume_mesh(mesh.vertices,mesh.faces, mesh.normals.flatten()) + info("Layering Complete!") + volume_mesh = builder_volume_mesh_to_volume_mesh(_builder_volume_mesh) + info("Converted from C++ to python DTCC mesh") + # volume_mesh.save("output/test1.vtu") + info(volume_mesh.__str__()) + +if __name__ == "__main__": + main() \ No newline at end of file