Backup commit

This commit is contained in:
iasonmanolas 2022-09-14 13:04:05 +02:00
parent 01dff95f9d
commit 266aca08c2
14 changed files with 6146 additions and 5829 deletions

View File

@ -45,7 +45,8 @@ target_include_directories(${PROJECT_NAME} PUBLIC ${DRMSimulationModelDir})
#add_compile_definitions(DLIB_DEFINED) #add_compile_definitions(DLIB_DEFINED)
## polyscope ## polyscope
#if(NOT TARGET polyscope AND ${USE_POLYSCOPE}) if(#[[NOT TARGET polyscope AND]] ${USE_POLYSCOPE})
message("Using polyscope")
FetchContent_Declare(polyscope FetchContent_Declare(polyscope
GIT_REPOSITORY https://github.com/nmwsharp/polyscope.git GIT_REPOSITORY https://github.com/nmwsharp/polyscope.git
GIT_TAG master GIT_TAG master
@ -55,7 +56,7 @@ target_include_directories(${PROJECT_NAME} PUBLIC ${DRMSimulationModelDir})
# target_include_directories(${PROJECT_NAME} PUBLIC ${polyscope_SOURCE_DIR}/deps/imgui) # target_include_directories(${PROJECT_NAME} PUBLIC ${polyscope_SOURCE_DIR}/deps/imgui)
target_sources(${PROJECT_NAME} PUBLIC ${polyscope_SOURCE_DIR}/deps/imgui/imgui/misc/cpp/imgui_stdlib.h ${polyscope_SOURCE_DIR}/deps/imgui/imgui/misc/cpp/imgui_stdlib.cpp) target_sources(${PROJECT_NAME} PUBLIC ${polyscope_SOURCE_DIR}/deps/imgui/imgui/misc/cpp/imgui_stdlib.h ${polyscope_SOURCE_DIR}/deps/imgui/imgui/misc/cpp/imgui_stdlib.cpp)
target_link_libraries(${PROJECT_NAME} PUBLIC polyscope) target_link_libraries(${PROJECT_NAME} PUBLIC polyscope)
#endif() endif()
#if(NOT TARGET polyscope AND ${USE_POLYSCOPE}) #if(NOT TARGET polyscope AND ${USE_POLYSCOPE})
# set(POLYSCOPE_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/polyscope) # set(POLYSCOPE_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/polyscope)
# download_project(PROJ POLYSCOPE # download_project(PROJ POLYSCOPE
@ -149,8 +150,9 @@ add_subdirectory(${ARMADILLO_SOURCE_DIR} ${ARMADILLO_BIN_DIR})
target_include_directories(${PROJECT_NAME} PUBLIC ${ARMADILLO_SOURCE_DIR}/include) target_include_directories(${PROJECT_NAME} PUBLIC ${ARMADILLO_SOURCE_DIR}/include)
add_compile_definitions(ARMA_DONT_USE_WRAPPER) add_compile_definitions(ARMA_DONT_USE_WRAPPER)
target_link_libraries(${PROJECT_NAME} PUBLIC "/home/iason/Coding/Libraries/armadillo/build/libarmadillo.a" #[[blas lapack]]) target_link_libraries(${PROJECT_NAME} PUBLIC "/home/iason/Coding/Libraries/armadillo/build/libarmadillo.a" #[[blas lapack]])
find_package(Armadillo REQUIRED) #find_package(Armadillo REQUIRED)
target_link_libraries(${PROJECT_NAME} PUBLIC ${ARMADILLO_LIBRARIES}) #target_link_libraries(${PROJECT_NAME} PUBLIC ${ARMADILLO_LIBRARIES})
#if(NOT TARGET ThreedBeamFEA) #if(NOT TARGET ThreedBeamFEA)
#FetchContent_Declare(armadillo #FetchContent_Declare(armadillo
# GIT_REPOSITORY https://gitlab.com/conradsnicta/armadillo-code.git # GIT_REPOSITORY https://gitlab.com/conradsnicta/armadillo-code.git
@ -203,7 +205,7 @@ add_compile_definitions(USE_ENSMALLEN)
# LINK_FLAGS "${CHRONO_LINKER_FLAGS}") # LINK_FLAGS "${CHRONO_LINKER_FLAGS}")
#include_directories(${CHRONO_INCLUDE_DIRS}) #include_directories(${CHRONO_INCLUDE_DIRS})
#target_link_libraries(${PROJECT_NAME} PUBLIC ${CHRONO_LIBRARIES}) #target_link_libraries(${PROJECT_NAME} PUBLIC ${CHRONO_LIBRARIES})
#target_include_directories(${PROJECT_NAME} PUBLIC "/home/iason/Coding/Libraries/chrono-7.0.3/src" #[[${CHRONO_INCLUDE_DIRS}]] #[["/home/iason/Coding/Libraries/chrono-7.0.3/src"]] #[["/usr/include/irrlicht"]] ) target_include_directories(${PROJECT_NAME} PUBLIC "/home/iason/Coding/Libraries/chrono-7.0.3/src" #[[${CHRONO_INCLUDE_DIRS}]] #[["/home/iason/Coding/Libraries/chrono-7.0.3/src"]] #[["/usr/include/irrlicht"]] )
#target_link_directories(${PROJECT_NAME} PRIVATE "/home/iason/Coding/build/external dependencies/CHRONO-src/build/RelWithDebInfo/lib") #target_link_directories(${PROJECT_NAME} PRIVATE "/home/iason/Coding/build/external dependencies/CHRONO-src/build/RelWithDebInfo/lib")
#target_link_libraries(${PROJECT_NAME} PUBLIC "/home/iason/Coding/build/external dependencies/CHRONO-src/build/RelWithDebInfo/lib/libChronoEngine.a") #target_link_libraries(${PROJECT_NAME} PUBLIC "/home/iason/Coding/build/external dependencies/CHRONO-src/build/RelWithDebInfo/lib/libChronoEngine.a")
target_link_libraries(${PROJECT_NAME} PUBLIC "/home/iason/Coding/Libraries/chrono-7.0.3/build/Release/lib/libChronoEngine.a") target_link_libraries(${PROJECT_NAME} PUBLIC "/home/iason/Coding/Libraries/chrono-7.0.3/build/Release/lib/libChronoEngine.a")
@ -252,11 +254,12 @@ if(NOT TARGET tbb_static AND NOT TARGET tbb)
# option(TBB_BUILD_TESTS "Build TBB tests and enable testing infrastructure" OFF) # option(TBB_BUILD_TESTS "Build TBB tests and enable testing infrastructure" OFF)
# add_subdirectory(${TBB_SOURCE_DIR} ${TBB_BINARY_DIR}) # add_subdirectory(${TBB_SOURCE_DIR} ${TBB_BINARY_DIR})
#link_directories(${TBB_BINARY_DIR}) #link_directories(${TBB_BINARY_DIR})
message("Using tbb")
FetchContent_Declare(tbb FetchContent_Declare(tbb
GIT_REPOSITORY https://github.com/wjakob/tbb.git GIT_REPOSITORY https://github.com/wjakob/tbb.git
GIT_TAG master GIT_TAG master
) )
FetchContent_MakeAvailable(tbb) FetchContent_MakeAvailable(tbb)
# target_link_libraries(${PROJECT_NAME} PRIVATE tbb_static) # target_link_libraries(${PROJECT_NAME} PRIVATE tbb_static)
target_link_libraries(${PROJECT_NAME} PRIVATE tbb)
endif() endif()
target_link_libraries(${PROJECT_NAME} PRIVATE tbb_static)

View File

@ -106,6 +106,33 @@ void ChronosEulerSimulationModel::parseForces(
} }
} }
void ChronosEulerSimulationModel::parseForcedDisplacements(
const std::shared_ptr<const SimulationJob>& pJob,
const std::vector<std::shared_ptr<chrono::fea::ChNodeFEAxyzrot>>&
edgeMeshVertsToChronoNodes,
chrono::ChSystemSMC& my_system) {
assert(!edgeMeshVertsToChronoNodes.empty());
ChState x;
ChStateDelta v;
double t;
for (const std::pair<VertexIndex, Eigen::Vector3d>& forcedDisplacement :
pJob->nodalForcedDisplacements) {
assert(false);
std::cerr << "Forced displacements dont work" << std::endl;
// std::terminate();
const int& constrainedVi = forcedDisplacement.first;
ChVector<double> displacementVector(
pJob->nodalForcedDisplacements.at(constrainedVi));
const std::shared_ptr<chrono::fea::ChNodeFEAxyzrot>& constrainedChronoNode =
edgeMeshVertsToChronoNodes[constrainedVi];
constrainedChronoNode->NodeIntStateGather(0, x, 0, v, t);
std::cout << "state rows:" << x.rows() << std::endl;
std::cout << "state cols:" << x.cols() << std::endl;
// x = x + displacementVector;
constrainedChronoNode->NodeIntStateScatter(0, x, 0, v, t);
}
}
void ChronosEulerSimulationModel::parseConstrainedVertices( void ChronosEulerSimulationModel::parseConstrainedVertices(
const std::shared_ptr<const SimulationJob>& pJob, const std::shared_ptr<const SimulationJob>& pJob,
const std::vector<std::shared_ptr<chrono::fea::ChNodeFEAxyzrot>>& const std::vector<std::shared_ptr<chrono::fea::ChNodeFEAxyzrot>>&
@ -120,30 +147,17 @@ void ChronosEulerSimulationModel::parseConstrainedVertices(
auto truss = chrono_types::make_shared<ChBody>(); auto truss = chrono_types::make_shared<ChBody>();
truss->SetBodyFixed(true); truss->SetBodyFixed(true);
my_system.Add(truss); my_system.Add(truss);
const auto& constrainedChronoNode = const std::shared_ptr<chrono::fea::ChNodeFEAxyzrot>& constrainedChronoNode =
edgeMeshVertsToChronoNodes[constrainedVi]; edgeMeshVertsToChronoNodes[constrainedVi];
// Create a constraint at the end of the beam auto constraint = chrono_types::make_shared<ChLinkMateGeneric>();
auto constr_a = chrono_types::make_shared<ChLinkMateGeneric>(); constraint->SetConstrainedCoords(
constr_a->SetConstrainedCoords(
constrainedDoF.contains(0), constrainedDoF.contains(1), constrainedDoF.contains(0), constrainedDoF.contains(1),
constrainedDoF.contains(2), constrainedDoF.contains(3), constrainedDoF.contains(2), constrainedDoF.contains(3),
constrainedDoF.contains(4), constrainedDoF.contains(5)); constrainedDoF.contains(4), constrainedDoF.contains(5));
constr_a->Initialize(constrainedChronoNode, truss, false, constraint->Initialize(constrainedChronoNode, truss, false,
constrainedChronoNode->Frame(), constrainedChronoNode->Frame(),
constrainedChronoNode->Frame()); constrainedChronoNode->Frame());
// const auto frameNode = constrainedChronoNode->Frame(); my_system.Add(constraint);
my_system.Add(constr_a);
// edgeMeshVertsToChronoNodes[constrainedVi]->SetFixed(true);
// if (vertexIsFullyConstrained) {
// } else {
// std::cerr << "Currently only rigid vertices are handled." <<
// std::endl;
// // SimulationResults simulationResults;
// // simulationResults.converged = false;
// // assert(false);
// // return simulationResults;
// }
} }
} }
@ -177,6 +191,7 @@ SimulationResults ChronosEulerSimulationModel::executeSimulation(
// -1)); // -1));
// my_system.SetTimestepperType(chrono::ChTimestepper::Type::EULER_IMPLICIT_LINEARIZED); // my_system.SetTimestepperType(chrono::ChTimestepper::Type::EULER_IMPLICIT_LINEARIZED);
// parse forces // parse forces
parseForcedDisplacements(pJob, edgeMeshVertsToChronoNodes, my_system);
parseForces(mesh_chronos, edgeMeshVertsToChronoNodes, parseForces(mesh_chronos, edgeMeshVertsToChronoNodes,
pJob->nodalExternalForces); pJob->nodalExternalForces);
// parse constrained vertices // parse constrained vertices
@ -198,20 +213,29 @@ SimulationResults ChronosEulerSimulationModel::executeSimulation(
auto solver = chrono_types::make_shared<ChSolverMINRES>(); auto solver = chrono_types::make_shared<ChSolverMINRES>();
my_system.SetSolver(solver); my_system.SetSolver(solver);
// solver->SetMaxIterations(1e5); solver->SetMaxIterations(1e5);
// solver->SetTolerance(1e-12);
solver->EnableWarmStart( solver->EnableWarmStart(
true); // IMPORTANT for convergence when using EULER_IMPLICIT_LINEARIZED true); // IMPORTANT for convergence when using EULER_IMPLICIT_LINEARIZED
solver->EnableDiagonalPreconditioner(true); solver->EnableDiagonalPreconditioner(true);
my_system.SetSolverForceTolerance(1e-9); // solver->SetTolerance(1e-15);
solver->SetVerbose(false); my_system.SetSolverForceTolerance(1e-15);
SimulationResults simulationResults; SimulationResults simulationResults;
//#ifdef POLYSCOPE_DEFINED
// solver->SetVerbose(true);
// // edgeMeshVertsToChronoNodes[10]->Frame().Move({0, 0, 1e-1});
// simulationResults.converged = my_system.DoEntireKinematics(5e2);
//// edgeMeshVertsToChronoNodes[10]->SetForce({0, 0, 1e6});
//#else
solver->SetVerbose(false);
if (settings.analysisType == Settings::AnalysisType::Linear) { if (settings.analysisType == Settings::AnalysisType::Linear) {
simulationResults.converged = my_system.DoStaticLinear(); simulationResults.converged = my_system.DoStaticLinear();
// simulationResults.converged = my_system.DoStaticRelaxing();
} else { } else {
simulationResults.converged = my_system.DoStaticNonlinear(); simulationResults.converged = my_system.DoStaticNonlinear();
// simulationResults.converged = my_system.DoStaticRelaxing();
} }
//#endif
if (!simulationResults.converged) { if (!simulationResults.converged) {
std::cerr << "Simulation failed" << std::endl; std::cerr << "Simulation failed" << std::endl;
assert(false); assert(false);

View File

@ -11,32 +11,41 @@ class ChNodeFEAxyzrot;
} // namespace fea } // namespace fea
} // namespace chrono } // namespace chrono
class ChronosEulerSimulationModel : public SimulationModel class ChronosEulerSimulationModel : public SimulationModel {
{
std::shared_ptr<chrono::fea::ChMesh> mesh_chronos; std::shared_ptr<chrono::fea::ChMesh> mesh_chronos;
std::vector<std::shared_ptr<chrono::fea::ChNodeFEAxyzrot>> edgeMeshVertsToChronoNodes; std::vector<std::shared_ptr<chrono::fea::ChNodeFEAxyzrot>>
edgeMeshVertsToChronoNodes;
static void parseConstrainedVertices( static void parseConstrainedVertices(
const std::shared_ptr<const SimulationJob>& pJob, const std::shared_ptr<const SimulationJob>& pJob,
const std::vector<std::shared_ptr<chrono::fea::ChNodeFEAxyzrot>> &edgeMeshVertsToChronoNodes, const std::vector<std::shared_ptr<chrono::fea::ChNodeFEAxyzrot>>&
edgeMeshVertsToChronoNodes,
chrono::ChSystemSMC& my_system); chrono::ChSystemSMC& my_system);
static void parseForces( static void parseForces(
const std::shared_ptr<chrono::fea::ChMesh>& mesh_chronos, const std::shared_ptr<chrono::fea::ChMesh>& mesh_chronos,
const std::vector<std::shared_ptr<chrono::fea::ChNodeFEAxyzrot>> &edgeMeshVertsToChronoNodes, const std::vector<std::shared_ptr<chrono::fea::ChNodeFEAxyzrot>>&
edgeMeshVertsToChronoNodes,
const std::unordered_map<VertexIndex, Vector6d>& nodalExternalForces); const std::unordered_map<VertexIndex, Vector6d>& nodalExternalForces);
static void parseForcedDisplacements(
const std::shared_ptr<const SimulationJob>& pJob,
const std::vector<std::shared_ptr<chrono::fea::ChNodeFEAxyzrot>>&
edgeMeshVertsToChronoNodes,
chrono::ChSystemSMC& my_system);
public: public:
ChronosEulerSimulationModel(); ChronosEulerSimulationModel();
SimulationResults executeSimulation(const std::shared_ptr<SimulationJob> &pJob) override; SimulationResults executeSimulation(
const std::shared_ptr<SimulationJob>& pJob) override;
void setStructure(const std::shared_ptr<SimulationEdgeMesh>& pMesh) override; void setStructure(const std::shared_ptr<SimulationEdgeMesh>& pMesh) override;
static std::shared_ptr<chrono::fea::ChMesh> convertToChronosMesh_Euler( static std::shared_ptr<chrono::fea::ChMesh> convertToChronosMesh_Euler(
const std::shared_ptr<SimulationEdgeMesh>& pMesh, const std::shared_ptr<SimulationEdgeMesh>& pMesh,
std::vector<std::shared_ptr<chrono::fea::ChNodeFEAxyzrot>> &edgeMeshVertsToChronosNodes); std::vector<std::shared_ptr<chrono::fea::ChNodeFEAxyzrot>>&
edgeMeshVertsToChronosNodes);
inline const static std::string label{"Chronos_Euler"}; inline const static std::string label{"Chronos_Euler"};
struct Settings struct Settings {
{
enum AnalysisType { Linear = 0, NonLinear }; enum AnalysisType { Linear = 0, NonLinear };
AnalysisType analysisType{NonLinear}; AnalysisType analysisType{NonLinear};
}; };

View File

@ -1,297 +0,0 @@
#ifndef POLYMESH_HPP
#define POLYMESH_HPP
#include "mesh.hpp"
#include "utilities.hpp"
#include "vcg/complex/complex.h"
#include <filesystem>
#include <wrap/io_trimesh/export_obj.h>
#include <wrap/io_trimesh/export_ply.h>
#include <wrap/io_trimesh/import.h>
#ifdef POLYSCOPE_DEFINED
#include <polyscope/surface_mesh.h>
#endif
class PFace;
class PVertex;
class PEdge;
struct PUsedTypes : public vcg::UsedTypes<vcg::Use<PVertex>::AsVertexType,
vcg::Use<PFace>::AsFaceType,
vcg::Use<PEdge>::AsEdgeType>
{};
class PVertex : public vcg::Vertex<PUsedTypes,
vcg::vertex::Coord3d,
vcg::vertex::Normal3d,
vcg::vertex::Mark,
vcg::vertex::Qualityf,
vcg::vertex::BitFlags,
vcg::vertex::VFAdj,
vcg::vertex::VEAdj>
{};
class PEdge : public vcg::Edge<PUsedTypes,
vcg::edge::VertexRef,
vcg::edge::BitFlags,
vcg::edge::EEAdj,
vcg::edge::EFAdj,
vcg::edge::VEAdj,
vcg::edge::EVAdj>
{};
class PFace : public vcg::Face<PUsedTypes,
vcg::face::PolyInfo // this is necessary if you use component in
// vcg/simplex/face/component_polygon.h
// It says "this class is a polygon and the memory for its components
// (e.g. pointer to its vertices will be allocated dynamically")
,
// vcg::face::FHAdj,
vcg::face::PVFAdj,
vcg::face::PFEAdj,
vcg::face::PFVAdj,
vcg::face::PVFAdj,
// vcg::face::PVFAdj,
vcg::face::PFFAdj // Pointer to edge-adjacent face (just like FFAdj )
,
vcg::face::BitFlags // bit flags
,
vcg::face::Qualityf // quality
,
vcg::face::Normal3f // normal
,
vcg::face::Color4b>
{};
class VCGPolyMesh
: public vcg::tri::TriMesh<std::vector<PVertex>, std::vector<PFace>, std::vector<PEdge>>,
public Mesh
{
public:
virtual bool load(const std::filesystem::__cxx11::path &meshFilePath) override
{
int mask;
vcg::tri::io::Importer<VCGPolyMesh>::LoadMask(meshFilePath.c_str(), mask);
int error = vcg::tri::io::Importer<VCGPolyMesh>::Open(*this, meshFilePath.c_str(), mask);
if (error != 0) {
std::cerr << "Could not load polygonal mesh:" << meshFilePath << std::endl;
return false;
}
vcg::tri::UpdateTopology<VCGPolyMesh>::FaceFace(*this);
vcg::tri::UpdateTopology<VCGPolyMesh>::VertexEdge(*this);
vcg::tri::UpdateTopology<VCGPolyMesh>::VertexFace(*this);
vcg::tri::UpdateNormal<VCGPolyMesh>::PerVertexNormalized(*this);
vcg::tri::Clean<VCGPolyMesh>::RemoveUnreferencedVertex(*this);
//finally remove valence 1 vertices on the border
// vcg::PolygonalAlgorithm<PolyMeshType>::RemoveValence2Vertices(dual);
return true;
}
// // vcg::tri::io::ImporterOBJ<VCGPolyMesh>::Open();
// // unsigned int mask = 0;
// // mask |= nanoply::NanoPlyWrapper<VCGPolyMesh>::IO_VERTCOORD;
// // mask |= nanoply::NanoPlyWrapper<VCGPolyMesh>::IO_VERTNORMAL;
// // mask |= nanoply::NanoPlyWrapper<VCGPolyMesh>::IO_VERTCOLOR;
// // mask |= nanoply::NanoPlyWrapper<VCGPolyMesh>::IO_EDGEINDEX;
// // mask |= nanoply::NanoPlyWrapper<VCGPolyMesh>::IO_FACEINDEX;
// // if (nanoply::NanoPlyWrapper<VCGPolyMesh>::LoadModel(
// // std::filesystem::absolute(filename).c_str(), *this, mask) !=
// // 0) {
// // std::cout << "Could not load tri mesh" << std::endl;
// // }
// }
Eigen::MatrixX3d getVertices() const
{
Eigen::MatrixX3d vertices(VN(), 3);
for (size_t vi = 0; vi < VN(); vi++) {
VCGPolyMesh::CoordType vertexCoordinates = vert[vi].cP();
vertices.row(vi) = vertexCoordinates.ToEigenVector<Eigen::Vector3d>();
}
return vertices;
}
std::vector<std::vector<int>> getFaces() const
{
std::vector<std::vector<int>> faces(FN());
for (const VCGPolyMesh::FaceType &f : this->face) {
const int fi = vcg::tri::Index<VCGPolyMesh>(*this, f);
for (size_t vi = 0; vi < f.VN(); vi++) {
const size_t viGlobal = vcg::tri::Index<VCGPolyMesh>(*this, f.cV(vi));
faces[fi].push_back(viGlobal);
}
}
return faces;
}
// bool load(const std::filesystem::__cxx11::path &meshFilePath)
// {
// const std::string extension = ".ply";
// std::filesystem::path filePath = meshFilePath;
// assert(std::filesystem::path(filePath).extension().string() == extension);
// unsigned int mask = 0;
// mask |= vcg::tri::io::Mask::IOM_VERTCOORD;
// mask |= vcg::tri::io::Mask::IOM_VERTNORMAL;
// mask |= vcg::tri::io::Mask::IOM_FACEINDEX;
// mask |= vcg::tri::io::Mask::IOM_FACECOLOR;
// if (vcg::tri::io::Importer<VCGPolyMesh>::Open(*this, filePath.c_str()) != 0) {
// return false;
// }
// label = meshFilePath.filename();
// return true;
// }
bool save(const std::filesystem::__cxx11::path &meshFilePath = std::filesystem::path()) override
{
if (meshFilePath.extension() == ".obj") {
return saveOBJ(meshFilePath);
} else if (meshFilePath.extension() == ".ply") {
return savePLY(meshFilePath);
}
return false;
}
bool saveOBJ(const std::filesystem::path &objFilePath = std::filesystem::path())
{
const std::string extension = ".obj";
std::filesystem::path filePath = objFilePath;
if (filePath.empty()) {
filePath = std::filesystem::current_path().append(getLabel() + extension).string();
} else if (std::filesystem::is_directory(std::filesystem::path(objFilePath))) {
filePath = std::filesystem::path(objFilePath).append(getLabel() + extension).string();
}
assert(std::filesystem::path(filePath).extension().string() == extension);
unsigned int mask = 0;
mask |= vcg::tri::io::Mask::IOM_VERTCOORD;
mask |= vcg::tri::io::Mask::IOM_VERTNORMAL;
mask |= vcg::tri::io::Mask::IOM_FACEINDEX;
mask |= vcg::tri::io::Mask::IOM_FACECOLOR;
if (vcg::tri::io::ExporterOBJ<VCGPolyMesh>::Save(*this, filePath.string().c_str(), mask) != 0) {
return false;
}
return true;
}
bool savePLY(const std::filesystem::path &objFilePath = std::filesystem::path())
{
const std::string extension = ".ply";
std::filesystem::path filePath = objFilePath;
if (filePath.empty()) {
filePath = std::filesystem::current_path().append(getLabel() + extension).string();
} else if (std::filesystem::is_directory(std::filesystem::path(objFilePath))) {
filePath = std::filesystem::path(objFilePath).append(getLabel() + extension).string();
}
assert(std::filesystem::path(filePath).extension().string() == extension);
unsigned int mask = 0;
mask |= vcg::tri::io::Mask::IOM_VERTCOORD;
mask |= vcg::tri::io::Mask::IOM_VERTNORMAL;
mask |= vcg::tri::io::Mask::IOM_FACEINDEX;
mask |= vcg::tri::io::Mask::IOM_FACECOLOR;
if (vcg::tri::io::ExporterPLY<VCGPolyMesh>::Save(*this, filePath.string().c_str(), mask, false) != 0) {
return false;
}
return true;
}
#ifdef POLYSCOPE_DEFINED
polyscope::SurfaceMesh *registerForDrawing(
const std::optional<std::array<double, 3>> &desiredColor = std::nullopt,
const bool &shouldEnable = true)
{
auto vertices = getVertices();
auto faces = getFaces();
PolyscopeInterface::init();
polyscope::SurfaceMesh *polyscopeHandle_mesh = polyscope::registerSurfaceMesh(label,
vertices,
faces);
const double drawingRadius = 0.002;
polyscopeHandle_mesh->setEnabled(shouldEnable);
polyscopeHandle_mesh->setEdgeWidth(drawingRadius);
if (desiredColor.has_value()) {
const glm::vec3 desiredColor_glm(desiredColor.value()[0],
desiredColor.value()[1],
desiredColor.value()[2]);
polyscopeHandle_mesh->setSurfaceColor(desiredColor_glm);
}
return polyscopeHandle_mesh;
}
#endif
void moveToCenter()
{
CoordType centerOfMass(0, 0, 0);
for (int vi = 0; vi < VN(); vi++) {
centerOfMass += vert[vi].cP();
}
centerOfMass /= VN();
vcg::tri::UpdatePosition<VCGPolyMesh>::Translate(*this, -centerOfMass);
}
/*
* Returns the average distance from the center of each edge to the center of its face over the whole mesh
* */
double getAverageFaceRadius() const
{
double averageFaceRadius = 0;
for (int fi = 0; fi < FN(); fi++) {
const VCGPolyMesh::FaceType &f = face[fi];
CoordType centerOfFace(0, 0, 0);
for (int vi = 0; vi < f.VN(); vi++) {
centerOfFace = centerOfFace + f.cP(vi);
}
centerOfFace /= f.VN();
double faceRadius = 0;
// for (int face_ei = 0; face_ei < f.EN(); face_ei++) {
// std::cout << "fi:" << getIndex(f) << std::endl;
// auto vps = f.FVp(0);
// auto vpe = vps;
for (int i = 0; i < f.VN(); i++) {
faceRadius += vcg::Distance(centerOfFace, (f.cP0(i) + f.cP1(i)) / 2);
}
// }
const int faceEdges = f.VN(); //NOTE: When does this not hold?
faceRadius /= faceEdges;
averageFaceRadius += faceRadius;
}
averageFaceRadius /= FN();
return averageFaceRadius;
}
bool copy(VCGPolyMesh &copyFrom)
{
vcg::tri::Append<VCGPolyMesh, VCGPolyMesh>::MeshCopy(*this, copyFrom);
label = copyFrom.getLabel();
// eigenEdges = mesh.getEigenEdges();
// if (eigenEdges.rows() == 0) {
// getEdges(eigenEdges);
// }
// eigenVertices = mesh.getEigenVertices();
// if (eigenVertices.rows() == 0) {
// getVertices();
// }
vcg::tri::UpdateTopology<VCGPolyMesh>::VertexEdge(*this);
vcg::tri::UpdateTopology<VCGPolyMesh>::VertexFace(*this);
vcg::tri::UpdateTopology<VCGPolyMesh>::FaceFace(*this);
vcg::tri::UpdateTopology<VCGPolyMesh>::AllocateEdge(*this);
vcg::tri::UpdateTopology<VCGPolyMesh>::EdgeEdge(*this);
// vcg::tri::UpdateTopology<VCGPolyMesh>::VertexFace(*this);
return true;
}
VCGPolyMesh(VCGPolyMesh &copyFrom) { copy(copyFrom); }
VCGPolyMesh() {}
template<typename MeshElement>
size_t getIndex(const MeshElement &meshElement) const
{
return vcg::tri::Index<VCGPolyMesh>(*this, meshElement);
}
};
using ConstVCGPolyMesh = VCGPolyMesh;
#endif // POLYMESH_HPP

View File

@ -1,121 +1,45 @@
#include "reducedmodelevaluator.hpp" #include "reducedmodelevaluator.hpp"
#include <execution>
#include <filesystem>
#include "hexagonremesher.hpp" #include "hexagonremesher.hpp"
#include "reducedmodel.hpp" #include "reducedmodel.hpp"
#include "reducedmodeloptimizer.hpp" #include "reducedmodeloptimizer.hpp"
#include "simulationmodelfactory.hpp" #include "simulationmodelfactory.hpp"
#include "trianglepatterngeometry.hpp" #include "trianglepatterngeometry.hpp"
#include <execution>
#include <filesystem>
using FullPatternVertexIndex = VertexIndex; using PatternVertexIndex = VertexIndex;
using ReducedPatternVertexIndex = VertexIndex; using ReducedModelVertexIndex = VertexIndex;
ReducedModelEvaluator::ReducedModelEvaluator() ReducedModelEvaluator::ReducedModelEvaluator() {
{
pTileIntoSurface = [&]() { pTileIntoSurface = [&]() {
std::istringstream inputStream_tileIntoTriSurface(tileIntoSurfaceFileContent); std::istringstream inputStream_tileIntoTriSurface(
tileIntoSurfaceFileContent);
VCGTriMesh tileInto_triMesh; VCGTriMesh tileInto_triMesh;
const bool surfaceLoadSuccessfull = tileInto_triMesh.load(inputStream_tileIntoTriSurface); const bool surfaceLoadSuccessfull =
tileInto_triMesh.load(inputStream_tileIntoTriSurface);
tileInto_triMesh.setLabel("instantMeshes_plane_34"); tileInto_triMesh.setLabel("instantMeshes_plane_34");
assert(surfaceLoadSuccessfull); assert(surfaceLoadSuccessfull);
return PolygonalRemeshing::remeshWithPolygons(tileInto_triMesh); return PolygonalRemeshing::remeshWithPolygons(tileInto_triMesh);
}(); }();
} }
//double ReducedModelEvaluator::evaluateOptimizationSettings(
// const ReducedModelOptimization::Settings &optimizationSettings,
// const std::vector<std::shared_ptr<PatternGeometry>> &pPatterns,
// std::vector<ReducedModelEvaluator::Results> &patternEvaluationResults)
//{
// assert(!pPatterns.empty());
// double optimizationError = 0;
// auto start = std::chrono::high_resolution_clock::now();
// std::vector<double> averageNormalizedError(pPatterns.size(), 0);
// patternEvaluationResults.clear();
// patternEvaluationResults.resize(pPatterns.size());
// std::for_each(
// // std::execution::par_unseq,
// pPatterns.begin(),
// pPatterns.end(),
// [&](const std::shared_ptr<ConstPatternGeometry> &pPattern) {
// // std::cout << "Optimizing " << pPattern->getLabel() << std::endl;
// ReducedModelOptimization::Results optimizationResults;
// ReducedModelOptimizer optimizer;
// optimizer.optimize(*pPattern, optimizationSettings, optimizationResults);
// const auto evaluationResults
// = ReducedModelEvaluator::evaluateReducedModel(optimizationResults,
// tileIntoSurfaceFilePath,
// scenariosDirPath,
// fullPatternTessellatedResultsDirPath);
// const double averageNormalizedErrorOfPattern
// = std::reduce(evaluationResults.distances_normalizedDrm2reduced.begin(),
// evaluationResults.distances_normalizedDrm2reduced.end())
// / evaluationResults.distances_normalizedDrm2reduced.size();
// const int patternIndex = &pPattern - &patterns[0];
// averageNormalizedError[patternIndex] = averageNormalizedErrorOfPattern;
// patternsEvaluationResults[patternIndex] = evaluationResults;
// });
// const double strategyAverageNormalizedError = std::reduce(std::execution::par_unseq,
// averageNormalizedError.begin(),
// averageNormalizedError.end())
// / pPointers.size();
// const auto totalDuration_min = std::chrono::duration_cast<std::chrono::seconds>(
// std::chrono::high_resolution_clock::now() - start)
// .count()
// / 60.0;
// std::cout << "Optimized pattern(s) in:" << totalDuration_min << " minutes." << std::endl;
// std::cout << "Average time per pattern:" << totalDuration_min / patternsPointers.size()
// << " minutes." << std::endl;
// std::cout << "Objective value:" << strategyAverageNormalizedError << std::endl;
// return strategyAverageNormalizedError;
// // std::cout << "After:" << ++numberOfOptimizationRoundsExecuted << " iterations." << std::endl;
//}
ReducedModelEvaluator::Results ReducedModelEvaluator::evaluateReducedModel( ReducedModelEvaluator::Results ReducedModelEvaluator::evaluateReducedModel(
ReducedModelOptimization::Results &optimizationResult) ReducedModelOptimization::Results& optimizationResult) {
{ const std::filesystem::path scenariosDirectoryPath =
const std::filesystem::path scenariosDirectoryPath "/home/iason/Coding/Projects/Approximating shapes with flat "
= "/home/iason/Coding/Projects/Approximating shapes with flat "
"patterns/ReducedModelEvaluator/Scenarios"; "patterns/ReducedModelEvaluator/Scenarios";
const std::filesystem::path fullPatternTessellatedResultsDirectoryPath const std::filesystem::path fullPatternTessellatedResultsDirectoryPath =
= "/home/iason/Coding/Projects/Approximating shapes with flat " "/home/iason/Coding/Projects/Approximating shapes with flat "
"patterns/ReducedModelEvaluator/TessellatedResults"; "patterns/ReducedModelEvaluator/TessellatedResults";
return evaluateReducedModel(optimizationResult, return evaluateReducedModel(optimizationResult, scenariosDirectoryPath,
scenariosDirectoryPath,
fullPatternTessellatedResultsDirectoryPath); fullPatternTessellatedResultsDirectoryPath);
} }
//void ReducedModelEvaluator::printResults(const Results &evaluationResults,
// const std::string &resultsLabel,
// const std::filesystem::path &resultsOutputPath)
//{
// const bool outputPathIsDirectory = !resultsOutputPath.empty()
// && !resultsOutputPath.has_extension();
// const bool outputPathIsFile = !resultsOutputPath.empty() && resultsOutputPath.has_extension();
// assert(outputPathIsDirectory && outputPathIsFile);
// if (outputPathIsDirectory) {
// std::filesystem::create_directories(resultsOutputPath);
// }
//#else
// std::filesystem::path csvOutputFilePath;
// bool shouldOverwrite = false;
// if (outputPathIsDirectory) {
// csvOutputFilePath = std::filesystem::path(resultsOutputPath)
// .append("distances_" + resultsLabel + ".csv")
// .string();
// shouldOverwrite = true;
// } else if (outputPathIsFile) {
// csvOutputFilePath = resultsOutputPath;
// }
// csvFile csvOutput(csvOutputFilePath, shouldOverwrite);
// printResults(evaluationResults, resultsLabel, csvOutput);
//}
void ReducedModelEvaluator::printResults(const Results& evaluationResults, void ReducedModelEvaluator::printResults(const Results& evaluationResults,
const std::string &resultsLabel) const std::string& resultsLabel) {
{
csvFile csvOutputToCout({}, true); csvFile csvOutputToCout({}, true);
Settings exportSettings; Settings exportSettings;
exportSettings.exportingDirection = Vertical; exportSettings.exportingDirection = Vertical;
@ -126,13 +50,10 @@ void ReducedModelEvaluator::printResults(const Results &evaluationResults,
void ReducedModelEvaluator::printResults(const Results& evaluationResults, void ReducedModelEvaluator::printResults(const Results& evaluationResults,
const Settings& settings, const Settings& settings,
csvFile &csvOutput) csvFile& csvOutput) {
{
if (settings.shouldWriteHeader) { if (settings.shouldWriteHeader) {
csvOutput << csvExportingDataStrings[settings.exportingData]; csvOutput << csvExportingDataStrings[settings.exportingData];
printHeader(settings, csvOutput); printHeader(settings, csvOutput);
// csvOutput << "Average error";
// csvOutput<<"Cumulative error";
csvOutput << endrow; csvOutput << endrow;
} }
if (!settings.resultsLabel.empty()) { if (!settings.resultsLabel.empty()) {
@ -145,13 +66,15 @@ void ReducedModelEvaluator::printResults(const Results &evaluationResults,
} }
} }
void ReducedModelEvaluator::printHeader(const Settings &settings, csvFile &csvOutput) void ReducedModelEvaluator::printHeader(const Settings& settings,
{ csvFile& csvOutput) {
if (settings.exportingDirection == Horizontal) { if (settings.exportingDirection == Horizontal) {
// csvOutput << "Job label"; // csvOutput << "Job label";
for (int jobIndex = 0; jobIndex < ReducedModelEvaluator::scenariosTestSetLabels.size(); for (int jobIndex = 0;
jobIndex < ReducedModelEvaluator::scenariosTestSetLabels.size();
jobIndex++) { jobIndex++) {
const std::string &jobLabel = ReducedModelEvaluator::scenariosTestSetLabels[jobIndex]; const std::string& jobLabel =
ReducedModelEvaluator::scenariosTestSetLabels[jobIndex];
csvOutput << jobLabel; csvOutput << jobLabel;
} }
} else { } else {
@ -161,20 +84,20 @@ void ReducedModelEvaluator::printHeader(const Settings &settings, csvFile &csvOu
} }
} }
void ReducedModelEvaluator::printResultsHorizontally(const Results &evaluationResults, void ReducedModelEvaluator::printResultsHorizontally(
csvFile &csvOutput) const Results& evaluationResults,
{ csvFile& csvOutput) {
// print header // print header
// print raw error // print raw error
constexpr bool shouldPrintRawError = false; constexpr bool shouldPrintRawError = false;
if (shouldPrintRawError) { if (shouldPrintRawError) {
// csvOutput << "drm2Reduced";
double sumOfFull2Reduced = 0; double sumOfFull2Reduced = 0;
int numOfNonEvaluatedScenarios = 0; int numOfNonEvaluatedScenarios = 0;
for (int jobIndex = 0; jobIndex < ReducedModelEvaluator::scenariosTestSetLabels.size(); for (int jobIndex = 0;
jobIndex < ReducedModelEvaluator::scenariosTestSetLabels.size();
jobIndex++) { jobIndex++) {
const double &distance_fullDrmToReduced = evaluationResults const double& distance_fullDrmToReduced =
.distances_drm2reduced[jobIndex]; evaluationResults.distances_drm2reduced[jobIndex];
if (distance_fullDrmToReduced == -1) { if (distance_fullDrmToReduced == -1) {
csvOutput << "notEvaluated"; csvOutput << "notEvaluated";
numOfNonEvaluatedScenarios++; numOfNonEvaluatedScenarios++;
@ -183,19 +106,14 @@ void ReducedModelEvaluator::printResultsHorizontally(const Results &evaluationRe
sumOfFull2Reduced += distance_fullDrmToReduced; sumOfFull2Reduced += distance_fullDrmToReduced;
} }
} }
// const int numOfEvaluatedScenarios = ReducedModelEvaluator::scenariosTestSetLabels.size()
// - numOfNonEvaluatedScenarios;
// const double averageDistance_full2Reduced = sumOfFull2Reduced / numOfEvaluatedScenarios;
// csvOutput << averageDistance_full2Reduced;
// csvOutput << endrow;
} }
// print normalized error // print normalized error
// csvOutput << "norm_drm2Reduced";
double sumOfNormalizedFull2Reduced = 0; double sumOfNormalizedFull2Reduced = 0;
for (int jobIndex = 0; jobIndex < ReducedModelEvaluator::scenariosTestSetLabels.size(); for (int jobIndex = 0;
jobIndex < ReducedModelEvaluator::scenariosTestSetLabels.size();
jobIndex++) { jobIndex++) {
const double &distance_normalizedFullDrmToReduced const double& distance_normalizedFullDrmToReduced =
= evaluationResults.distances_normalizedDrm2reduced[jobIndex]; evaluationResults.distances_normalizedDrm2reduced[jobIndex];
if (distance_normalizedFullDrmToReduced == -1) { if (distance_normalizedFullDrmToReduced == -1) {
csvOutput << "notEvaluated"; csvOutput << "notEvaluated";
} else { } else {
@ -203,15 +121,11 @@ void ReducedModelEvaluator::printResultsHorizontally(const Results &evaluationRe
sumOfNormalizedFull2Reduced += distance_normalizedFullDrmToReduced; sumOfNormalizedFull2Reduced += distance_normalizedFullDrmToReduced;
} }
} }
// const double averageDistance_normalizedFull2Reduced = sumOfNormalizedFull2Reduced
// / numOfEvaluatedScenarios;
// csvOutput << averageDistance_normalizedFull2Reduced;
// csvOutput << endrow;
} }
void ReducedModelEvaluator::printResultsVertically(const Results &evaluationResults, void ReducedModelEvaluator::printResultsVertically(
csvFile &csvOutput) const Results& evaluationResults,
{ csvFile& csvOutput) {
#ifdef POLYSCOPE_DEFINED #ifdef POLYSCOPE_DEFINED
csvOutput << "pattern2Reduced" csvOutput << "pattern2Reduced"
<< "norm_pattern2Reduced"; << "norm_pattern2Reduced";
@ -225,13 +139,16 @@ void ReducedModelEvaluator::printResultsVertically(const Results &evaluationResu
double sumOfFull2Reduced = 0; double sumOfFull2Reduced = 0;
double sumOfNormalizedFull2Reduced = 0; double sumOfNormalizedFull2Reduced = 0;
int numOfNonEvaluatedScenarios = 0; int numOfNonEvaluatedScenarios = 0;
for (int jobIndex = 0; jobIndex < ReducedModelEvaluator::scenariosTestSetLabels.size(); for (int jobIndex = 0;
jobIndex < ReducedModelEvaluator::scenariosTestSetLabels.size();
jobIndex++) { jobIndex++) {
const double &distance_fullDrmToReduced = evaluationResults.distances_drm2reduced[jobIndex]; const double& distance_fullDrmToReduced =
const double &distance_normalizedFullDrmToReduced evaluationResults.distances_drm2reduced[jobIndex];
= evaluationResults.distances_normalizedDrm2reduced[jobIndex]; const double& distance_normalizedFullDrmToReduced =
evaluationResults.distances_normalizedDrm2reduced[jobIndex];
#ifndef POLYSCOPE_DEFINED #ifndef POLYSCOPE_DEFINED
const std::string &jobLabel = ReducedModelEvaluator::scenariosTestSetLabels[jobIndex]; const std::string& jobLabel =
ReducedModelEvaluator::scenariosTestSetLabels[jobIndex];
csvOutput << jobLabel; csvOutput << jobLabel;
#endif #endif
if (distance_fullDrmToReduced == -1) { if (distance_fullDrmToReduced == -1) {
@ -239,22 +156,25 @@ void ReducedModelEvaluator::printResultsVertically(const Results &evaluationResu
<< "notEvaluated"; << "notEvaluated";
numOfNonEvaluatedScenarios++; numOfNonEvaluatedScenarios++;
} else { } else {
csvOutput << distance_fullDrmToReduced << distance_normalizedFullDrmToReduced; csvOutput << distance_fullDrmToReduced
<< distance_normalizedFullDrmToReduced;
sumOfFull2Reduced += distance_fullDrmToReduced; sumOfFull2Reduced += distance_fullDrmToReduced;
sumOfNormalizedFull2Reduced += distance_normalizedFullDrmToReduced; sumOfNormalizedFull2Reduced += distance_normalizedFullDrmToReduced;
} }
csvOutput << endrow; csvOutput << endrow;
// sumOfNormalizedFull2Reduced += distance_normalizedFullDrmToReduced;
} }
const int numOfEvaluatedScenarios = ReducedModelEvaluator::scenariosTestSetLabels.size() const int numOfEvaluatedScenarios =
- numOfNonEvaluatedScenarios; ReducedModelEvaluator::scenariosTestSetLabels.size() -
const double averageDistance_full2Reduced = sumOfFull2Reduced / numOfEvaluatedScenarios; numOfNonEvaluatedScenarios;
const double averageDistance_normalizedFull2Reduced = sumOfNormalizedFull2Reduced const double averageDistance_full2Reduced =
/ numOfEvaluatedScenarios; sumOfFull2Reduced / numOfEvaluatedScenarios;
const double averageDistance_normalizedFull2Reduced =
sumOfNormalizedFull2Reduced / numOfEvaluatedScenarios;
#ifndef POLYSCOPE_DEFINED #ifndef POLYSCOPE_DEFINED
csvOutput << "Average error"; csvOutput << "Average error";
#endif #endif
csvOutput << averageDistance_full2Reduced << averageDistance_normalizedFull2Reduced; csvOutput << averageDistance_full2Reduced
<< averageDistance_normalizedFull2Reduced;
csvOutput << endrow; csvOutput << endrow;
#ifndef POLYSCOPE_DEFINED #ifndef POLYSCOPE_DEFINED
csvOutput << "Cumulative error"; csvOutput << "Cumulative error";
@ -264,106 +184,67 @@ void ReducedModelEvaluator::printResultsVertically(const Results &evaluationResu
csvOutput << endrow; csvOutput << endrow;
} }
//void ReducedModelEvaluator::createFullAndReducedPatternTessellations(){
//}
//ReducedModelEvaluator::Results ReducedModelEvaluator::evaluateReducedModel(
// std::vector<ReducedModelOptimization::Results> &optimizationResults,
// const std::filesystem::path &tileInto_triMesh_filePath,
// const std::filesystem::path &scenariosDirectoryPath,
// // const std::filesystem::path &reducedPatternFilePath,
// const std::filesystem::path &fullPatternTessellatedResultsDirectoryPath)
//{
// //Load surface
// std::shared_ptr<VCGPolyMesh> pTileIntoSurface = [&]() {
// VCGTriMesh tileInto_triMesh;
// const bool surfaceLoadSuccessfull = tileInto_triMesh.load(tileInto_triMesh_filePath);
// assert(surfaceLoadSuccessfull);
// return PolygonalRemeshing::remeshWithPolygons(tileInto_triMesh);
// }();
// const double optimizedBaseTriangleHeight = vcg::Distance(optimizationResult.baseTriangle.cP(0),
// (optimizationResult.baseTriangle.cP(1)
// + optimizationResult.baseTriangle.cP(
// 2))
// / 2);
// pTileIntoSurface->moveToCenter();
// const double scaleFactor = optimizedBaseTriangleHeight
// / pTileIntoSurface->getAverageFaceRadius();
// vcg::tri::UpdatePosition<VCGPolyMesh>::Scale(*pTileIntoSurface, scaleFactor);
// //Tile full pattern into surface
//}
ReducedModelEvaluator::Results ReducedModelEvaluator::evaluateReducedModel( ReducedModelEvaluator::Results ReducedModelEvaluator::evaluateReducedModel(
ReducedModelOptimization::Results& optimizationResult, ReducedModelOptimization::Results& optimizationResult,
const std::filesystem::path& scenariosDirectoryPath, const std::filesystem::path& scenariosDirectoryPath,
const std::filesystem::path &fullPatternTessellatedResultsDirectoryPath) const std::filesystem::path& patternTessellatedResultsDirectoryPath) {
{ // Apply optimization results to the reduced model
// const double optimizedBaseTriangleHeight = vcg::Distance(optimizationResult.baseTriangle.cP(0), ReducedModel reducedModel;
// (optimizationResult.baseTriangle.cP(1) reducedModel.deleteDanglingVertices();
// + optimizationResult.baseTriangle.cP( std::unordered_map<std::string, double> optimalXVariables_set(
// 2)) optimizationResult.optimalXNameValuePairs.begin(),
// / 2); optimizationResult.optimalXNameValuePairs.end());
reducedModel.updateBaseTriangleGeometry_R(optimalXVariables_set.at("R"));
reducedModel.updateBaseTriangleGeometry_theta(
optimalXVariables_set.at("Theta"));
// reducedModel.registerForDrawing();
// Scale tile-into surface
pTileIntoSurface->moveToCenter(); pTileIntoSurface->moveToCenter();
const double scaleFactor = optimizationResult.settings.targetBaseTriangleSize const double scaleFactor =
/ pTileIntoSurface->getAverageFaceRadius(); optimizationResult.settings.targetBaseTriangleSize /
pTileIntoSurface->getAverageFaceRadius();
vcg::tri::UpdatePosition<VCGPolyMesh>::Scale(*pTileIntoSurface, scaleFactor); vcg::tri::UpdatePosition<VCGPolyMesh>::Scale(*pTileIntoSurface, scaleFactor);
// tileIntoSurface.registerForDrawing(); #ifdef POLYSCOPE_DEFINED
// polyscope::show(); pTileIntoSurface->registerForDrawing(color_tileIntoSurface);
#endif
// Tile full pattern into surface // Tile full pattern into surface
std::vector<PatternGeometry> fullPatterns(1); std::vector<PatternGeometry> patterns(1);
fullPatterns[0].copy(optimizationResult.baseTriangleFullPattern); patterns[0].copy(optimizationResult.baseTrianglePattern);
//// Base triangle pattern might contain dangling vertices.Remove those patterns[0].interfaceNodeIndex = 3;
fullPatterns[0].interfaceNodeIndex = 3; patterns[0].deleteDanglingVertices();
fullPatterns[0].deleteDanglingVertices();
std::vector<int> perSurfaceFacePatternIndices(pTileIntoSurface->FN(), 0); std::vector<int> perSurfaceFacePatternIndices(pTileIntoSurface->FN(), 0);
std::vector<std::vector<size_t>> perPatternIndexTiledFullPatternEdgeIndices; std::vector<std::vector<size_t>> perPatternIndexTiledFullPatternEdgeIndices;
std::vector<size_t> tileIntoEdgeToTiledFullVi; std::vector<size_t> tileIntoEdgeToTiledFullVi;
std::shared_ptr<PatternGeometry> pTiledFullPattern std::shared_ptr<PatternGeometry> pTilled_pattern =
= PatternGeometry::tilePattern(fullPatterns, PatternGeometry::tilePattern(patterns, {}, *pTileIntoSurface,
{},
*pTileIntoSurface,
perSurfaceFacePatternIndices, perSurfaceFacePatternIndices,
tileIntoEdgeToTiledFullVi, tileIntoEdgeToTiledFullVi,
perPatternIndexTiledFullPatternEdgeIndices); perPatternIndexTiledFullPatternEdgeIndices);
pTiledFullPattern->setLabel("Tiled_full_patterns"); pTilled_pattern->setLabel("Tilled_pattern");
// pTiledFullPattern->registerForDrawing();
//Tile reduced pattern into surface
ReducedModel reducedModel;
reducedModel.deleteDanglingVertices();
std::unordered_map<std::string, double>
optimalXVariables_set(optimizationResult.optimalXNameValuePairs.begin(),
optimizationResult.optimalXNameValuePairs.end());
reducedModel.updateBaseTriangleGeometry_R(optimalXVariables_set.at("R"));
reducedModel.updateBaseTriangleGeometry_theta(optimalXVariables_set.at("Theta"));
// const auto reducedPatternBaseTriangle = reducedModel.computeBaseTriangle();
// ReducedModelOptimization::Results::applyOptimizationResults_reducedModel_nonFanned(
// optimizationResult, reducedPatternBaseTriangle, reducedModel);
std::vector<PatternGeometry> reducedPatterns(1); // Tile reduced pattern into surface
reducedPatterns[0].copy(reducedModel); std::vector<PatternGeometry> reducedModels(1);
std::vector<std::vector<size_t>> perPatternIndexTiledReducedPatternEdgeIndices; reducedModels[0].copy(reducedModel);
std::vector<std::vector<size_t>>
perPatternIndexTiledReducedPatternEdgeIndices;
std::vector<size_t> tileIntoEdgeToTiledReducedVi; std::vector<size_t> tileIntoEdgeToTiledReducedVi;
std::shared_ptr<PatternGeometry> pTiledReducedPattern std::shared_ptr<PatternGeometry> pTilled_reducedModel =
= PatternGeometry::tilePattern(reducedPatterns, PatternGeometry::tilePattern(
{0}, reducedModels, {0}, *pTileIntoSurface, perSurfaceFacePatternIndices,
*pTileIntoSurface,
perSurfaceFacePatternIndices,
tileIntoEdgeToTiledReducedVi, tileIntoEdgeToTiledReducedVi,
perPatternIndexTiledReducedPatternEdgeIndices); perPatternIndexTiledReducedPatternEdgeIndices);
pTiledReducedPattern->setLabel("Tiled_reduced_patterns"); pTilled_reducedModel->setLabel("Tilled_reduced_model");
#ifdef POLYSCOPE_DEFINED
pTiledReducedPattern->registerForDrawing();
#endif
std::unordered_map<FullPatternVertexIndex, ReducedPatternVertexIndex> std::unordered_map<PatternVertexIndex, ReducedModelVertexIndex>
fullToReducedViMap; // of only the common vertices fullToReducedViMap; // of only the common vertices
std::unordered_map<ReducedPatternVertexIndex, FullPatternVertexIndex> std::unordered_map<ReducedModelVertexIndex, PatternVertexIndex>
reducedToFullViMap; // of only the common vertices reducedToFullViMap; // of only the common vertices
for (int ei = 0; ei < pTileIntoSurface->EN(); ei++) { for (int ei = 0; ei < pTileIntoSurface->EN(); ei++) {
fullToReducedViMap[tileIntoEdgeToTiledFullVi[ei]] = tileIntoEdgeToTiledReducedVi[ei]; fullToReducedViMap[tileIntoEdgeToTiledFullVi[ei]] =
tileIntoEdgeToTiledReducedVi[ei];
} }
constructInverseMap(fullToReducedViMap, reducedToFullViMap); constructInverseMap(fullToReducedViMap, reducedToFullViMap);
@ -377,121 +258,148 @@ ReducedModelEvaluator::Results ReducedModelEvaluator::evaluateReducedModel(
// Create simulation meshes // Create simulation meshes
////Tessellated full pattern simulation mesh ////Tessellated full pattern simulation mesh
std::shared_ptr<SimulationMesh> pTiledFullPattern_simulationMesh; std::shared_ptr<SimulationEdgeMesh> pSimulationEdgeMesh_tilledPattern =
pTiledFullPattern_simulationMesh = std::make_shared<SimulationMesh>(*pTiledFullPattern); std::make_shared<SimulationEdgeMesh>(*pTilled_pattern);
//NOTE: Those should be derived from the optimization results instead of hardcoding them pSimulationEdgeMesh_tilledPattern->setBeamCrossSection(
// const double beamWidth = optimizationResult.settings.patternBeamDimensions.getWidth(); optimizationResult.settings.beamDimensions_pattern);
// const double beamHeight = optimizationResult.settings.patternBeamDimensions.getHeight(); if (optimizationResult.settings.youngsModulus_pattern == 0) {
pTiledFullPattern_simulationMesh->setBeamCrossSection(
optimizationResult.settings.patternBeamDimensions);
if (optimizationResult.fullPatternYoungsModulus == 0) {
std::cerr << "Full pattern's young modulus not found." << std::endl; std::cerr << "Full pattern's young modulus not found." << std::endl;
std::terminate(); std::terminate();
} }
pTiledFullPattern_simulationMesh->setBeamMaterial(0.3, pSimulationEdgeMesh_tilledPattern->setBeamMaterial(
optimizationResult.fullPatternYoungsModulus); 0.3, optimizationResult.settings.youngsModulus_pattern);
pTiledFullPattern_simulationMesh->reset(); pSimulationEdgeMesh_tilledPattern->reset();
// optimizationResult.draw();
#ifdef POLYSCOPE_DEFINED
pSimulationEdgeMesh_tilledPattern->registerForDrawing(
color_tesselatedPatterns);
#endif
////Tessellated reduced pattern simulation mesh ////Tessellated reduced pattern simulation mesh
std::shared_ptr<SimulationMesh> pTiledReducedPattern_simulationMesh; std::shared_ptr<SimulationEdgeMesh> pSimulationEdgeMesh_tilledReducedModel;
pTiledReducedPattern_simulationMesh = std::make_shared<SimulationMesh>(*pTiledReducedPattern); pSimulationEdgeMesh_tilledReducedModel =
const std::vector<size_t> &tiledPatternElementIndicesForReducedPattern std::make_shared<SimulationEdgeMesh>(*pTilled_reducedModel);
= perPatternIndexTiledReducedPatternEdgeIndices[0];
ReducedModelOptimization::Results::applyOptimizationResults_elements( ReducedModelOptimization::Results::applyOptimizationResults_elements(
optimizationResult, pTiledReducedPattern_simulationMesh); optimizationResult, pSimulationEdgeMesh_tilledReducedModel);
// pTiledReducedPattern_simulationMesh->reset(); pSimulationEdgeMesh_tilledReducedModel->reset();
#ifdef POLYSCOPE_DEFINED
pSimulationEdgeMesh_tilledReducedModel->registerForDrawing(
color_tesselatedReducedModels);
polyscope::show();
#endif
Results evaluationResults; Results evaluationResults;
evaluationResults.distances_drm2reduced.fill(-1); evaluationResults.distances_drm2reduced.fill(-1);
evaluationResults.distances_normalizedDrm2reduced.fill(-1); evaluationResults.distances_normalizedDrm2reduced.fill(-1);
DRMSimulationModel::Settings drmSimulationSettings; DRMSimulationModel::Settings drmSimulationSettings;
drmSimulationSettings.totalExternalForcesNormPercentageTermination = 1e-3; // drmSimulationSettings.threshold_residualToExternalForcesNorm = 1e-3;
// drmSimulationSettings.load(drmSettingsFilePath); // drmSimulationSettings.load(drmSettingsFilePath);
drmSimulationSettings.beVerbose = true; drmSimulationSettings.beVerbose = true;
drmSimulationSettings.maxDRMIterations = 5e6; drmSimulationSettings.maxDRMIterations = 5e6;
drmSimulationSettings.debugModeStep = 100000; drmSimulationSettings.debugModeStep = 100000;
drmSimulationSettings.translationalKineticEnergyThreshold = 1e-15; drmSimulationSettings.threshold_totalTranslationalKineticEnergy = 1e-14;
drmSimulationSettings.linearGuessForceScaleFactor = 0.8; // drmSimulationSettings.threshold_currentToFirstPeakTranslationalKineticEnergy
drmSimulationSettings.viscousDampingFactor = 7e-3; // =
drmSimulationSettings.xi = 0.9999; // 1e-10;
// drmSimulationSettings.Dtini = 5.86; drmSimulationSettings.threshold_averageResidualToExternalForcesNorm = 1e-5;
drmSimulationSettings.gamma = 0.25; // drmSimulationSettings.linearGuessForceScaleFactor = 0.8;
// drmSimulationSettings.viscousDampingFactor = 7e-3;
// drmSimulationSettings.xi = 0.9999;
// drmSimulationSettings.gamma = 0.25;
#ifdef POLYSCOPE_DEFINED #ifdef POLYSCOPE_DEFINED
// drmSimulationSettings.shouldDraw = true; // drmSimulationSettings.shouldDraw = true;
drmSimulationSettings.shouldCreatePlots = true; drmSimulationSettings.shouldCreatePlots = false;
constexpr bool shouldDrawScenarioResults = true;
if (shouldDrawScenarioResults) {
pSimulationEdgeMesh_tilledPattern->registerForDrawing(
ReducedModelOptimization::Colors::patternInitial);
}
#endif #endif
constexpr bool shouldRerunFullPatternSimulation = false; const std::string& simulationModelLabel_pattern =
const std::string &simulationModelLabel = optimizationResult.settings.simulationModelLabel; optimizationResult.settings.simulationModelLabel_groundTruth;
// for (int jobIndex = 0; jobIndex < scenariosTestSetLabels.size(); jobIndex++) { const std::string& simulationModelLabel_reducedModel =
optimizationResult.settings.simulationModelLabel_reducedModel;
const bool shouldRerunFullPatternSimulation = [&]() {
// if (simulationModelLabel_pattern == DRMSimulationModel::label) {
return false;
// }
// return true;
}();
std::for_each( std::for_each(
//#ifndef POLYSCOPE_DEFINED #ifndef POLYSCOPE_DEFINED
std::execution::par_unseq, std::execution::par_unseq,
//#endif #endif
scenariosTestSetLabels.begin(), scenariosTestSetLabels.begin(), scenariosTestSetLabels.end(),
scenariosTestSetLabels.end(),
[&](const std::string& jobLabel) { [&](const std::string& jobLabel) {
// check if reduced model scenario exists // check if reduced model scenario exists
// const std::string &jobLabel = scenariosTestSetLabels[jobIndex]; // const std::string &jobLabel =
const std::filesystem::path tiledReducedPatternJobFilePath // scenariosTestSetLabels[jobIndex];
= std::filesystem::path(scenariosDirectoryPath) const std::filesystem::path tiledReducedPatternJobFilePath =
std::filesystem::path(scenariosDirectoryPath)
.append(pTileIntoSurface->getLabel()) .append(pTileIntoSurface->getLabel())
.append(jobLabel) .append(jobLabel)
.append("ReducedJob") .append("ReducedJob")
.append(SimulationJob::jsonDefaultFileName); .append(SimulationJob::jsonDefaultFileName);
if (!std::filesystem::exists(tiledReducedPatternJobFilePath)) { if (!std::filesystem::exists(tiledReducedPatternJobFilePath)) {
std::cerr << "Scenario " << jobLabel std::cerr << "Scenario " << jobLabel
<< " not found in:" << tiledReducedPatternJobFilePath << std::endl; << " not found in:" << tiledReducedPatternJobFilePath
<< std::endl;
// continue; //if not move on to the next scenario // continue; //if not move on to the next scenario
return; return;
} }
// Map the reduced job to the job on the pattern tessellation // Map the reduced job to the job on the pattern tessellation
// set jobs // set jobs
std::shared_ptr<SimulationJob> pJob_tiledReducedPattern; std::shared_ptr<SimulationJob> pJob_tiledReducedModel;
pJob_tiledReducedPattern = std::make_shared<SimulationJob>(SimulationJob()); pJob_tiledReducedModel =
pJob_tiledReducedPattern->load(tiledReducedPatternJobFilePath, false); std::make_shared<SimulationJob>(SimulationJob());
pJob_tiledReducedPattern->pMesh = pTiledReducedPattern_simulationMesh; pJob_tiledReducedModel->load(tiledReducedPatternJobFilePath, false);
std::shared_ptr<SimulationJob> pJob_tiledFullPattern; pJob_tiledReducedModel->pMesh = pSimulationEdgeMesh_tilledReducedModel;
pJob_tiledFullPattern = std::make_shared<SimulationJob>(SimulationJob()); std::shared_ptr<SimulationJob> pJob_tilledPattern;
pJob_tiledFullPattern->pMesh = pTiledFullPattern_simulationMesh; pJob_tilledPattern = std::make_shared<SimulationJob>(SimulationJob());
pJob_tiledReducedPattern->remap(reducedToFullViMap, *pJob_tiledFullPattern); pJob_tilledPattern->pMesh = pSimulationEdgeMesh_tilledPattern;
pJob_tiledReducedModel->remap(reducedToFullViMap, *pJob_tilledPattern);
// pJob_tiledReducedPattern->registerForDrawing(pTiledReducedPattern->getLabel()); // pJob_tiledReducedPattern->registerForDrawing(pTiledReducedPattern->getLabel());
// pJob_tiledFullPattern->registerForDrawing(pTiledFullPattern->getLabel()); // pJob_tiledFullPattern->registerForDrawing(pTiledFullPattern->getLabel());
// polyscope::show(); // polyscope::show();
const std::filesystem::path surfaceFolderPath const std::filesystem::path surfaceFolderPath =
= std::filesystem::path(fullPatternTessellatedResultsDirectoryPath) std::filesystem::path(patternTessellatedResultsDirectoryPath)
.append(simulationModelLabel + "_" + pTileIntoSurface->getLabel()); .append(simulationModelLabel_pattern + "_" +
const std::string scenarioLabel = pJob_tiledFullPattern->getLabel(); pTileIntoSurface->getLabel());
const std::filesystem::path scenarioDirectoryPath const std::string scenarioLabel = pJob_tilledPattern->getLabel();
= std::filesystem::path(surfaceFolderPath).append(scenarioLabel); const std::filesystem::path scenarioDirectoryPath =
std::filesystem::path(surfaceFolderPath).append(scenarioLabel);
// Save reduced job // Save reduced job
constexpr bool exportReducedJob = false; constexpr bool exportReducedJob = false;
if (exportReducedJob) { if (exportReducedJob) {
const std::filesystem::path reducedJobDirectoryPath const std::filesystem::path reducedJobDirectoryPath =
= std::filesystem::path(scenarioDirectoryPath).append("ReducedJob"); std::filesystem::path(scenarioDirectoryPath).append("ReducedJob");
std::filesystem::create_directories(reducedJobDirectoryPath); std::filesystem::create_directories(reducedJobDirectoryPath);
pJob_tiledReducedPattern->save(reducedJobDirectoryPath); pJob_tiledReducedModel->save(reducedJobDirectoryPath);
} }
//Check if the drm simulation of the full pattern has already been computed // Check if the drm simulation of the full pattern has already been
// computed
////Full ////Full
const std::string& patternLabel = [&]() { const std::string& patternLabel = [&]() {
const std::string patternLabel = optimizationResult.baseTriangleFullPattern const std::string patternLabel =
.getLabel(); optimizationResult.baseTrianglePattern.getLabel();
if (patternLabel.find("_") == std::string::npos) { if (patternLabel.find("_") == std::string::npos) {
return std::to_string(optimizationResult.baseTriangleFullPattern.EN()) + "_" return std::to_string(optimizationResult.baseTrianglePattern.EN()) +
+ patternLabel; "_" + patternLabel;
} else { } else {
return patternLabel; return patternLabel;
} }
}(); }();
const auto tilledPatternResultsFolderPath = std::filesystem::path(scenarioDirectoryPath) const auto tilledPatternResultsFolderPath =
std::filesystem::path(scenarioDirectoryPath)
.append(patternLabel) .append(patternLabel)
.append("Results"); .append("Results");
if (shouldRerunFullPatternSimulation if (shouldRerunFullPatternSimulation &&
&& std::filesystem::exists(tilledPatternResultsFolderPath)) { std::filesystem::exists(tilledPatternResultsFolderPath)) {
std::filesystem::remove_all(tilledPatternResultsFolderPath); std::filesystem::remove_all(tilledPatternResultsFolderPath);
} }
const std::filesystem::path fullPatternJobFolderPath = std::filesystem::path( const std::filesystem::path fullPatternJobFolderPath =
scenarioDirectoryPath) std::filesystem::path(scenarioDirectoryPath)
.append(patternLabel) .append(patternLabel)
.append("SimulationJob"); .append("SimulationJob");
SimulationResults simulationResults_tilledPattern; SimulationResults simulationResults_tilledPattern;
@ -500,30 +408,32 @@ ReducedModelEvaluator::Results ReducedModelEvaluator::evaluateReducedModel(
assert(std::filesystem::exists(fullPatternJobFolderPath)); assert(std::filesystem::exists(fullPatternJobFolderPath));
simulationResults_tilledPattern.load(tilledPatternResultsFolderPath, simulationResults_tilledPattern.load(tilledPatternResultsFolderPath,
fullPatternJobFolderPath); fullPatternJobFolderPath);
//#ifdef POLYSCOPE_DEFINED #ifdef POLYSCOPE_DEFINED
// std::array<double, 3> resultsColor({28.0, 99.0, 227.0}); simulationResults_tilledPattern.registerForDrawing(
// simulationResults_tiledFullPattern_drm.registerForDrawing(resultsColor); color_tesselatedPatterns);
// std::ifstream ifs("CameraSettings.json"); // std::ifstream ifs("CameraSettings.json");
// nlohmann::json json; // nlohmann::json json;
// ifs >> json; // ifs >> json;
// polyscope::view::setCameraFromJson(json.dump(), false); // polyscope::view::setCameraFromJson(json.dump(), false);
// // polyscope::show(); polyscope::show();
// const std::string cameraJson = polyscope::view::getCameraJson(); const std::string cameraJson = polyscope::view::getCameraJson();
// std::filesystem::path jsonFilePath("CameraSettings.json"); std::filesystem::path jsonFilePath("CameraSettings.json");
// std::ofstream jsonFile_cameraSettings(jsonFilePath.string()); std::ofstream jsonFile_cameraSettings(jsonFilePath.string());
// jsonFile_cameraSettings << cameraJson; jsonFile_cameraSettings << cameraJson;
// jsonFile_cameraSettings.close(); jsonFile_cameraSettings.close();
// std::filesystem::create_directories("screenshots"); std::filesystem::create_directories("screenshots");
// const std::string screenshotOutputFilePath const std::string screenshotOutputFilePath =
// = (std::filesystem::current_path() (std::filesystem::current_path()
// .append("screenshots") .append("screenshots")
// .append(optimizationResult.label + "_" + pJob_tiledFullPattern->getLabel())) .append(optimizationResult.label + "_" +
// .string() pJob_tilledPattern->getLabel()))
// + ".png"; .string() +
// // std::cout << "Saving image to:" << screenshotOutputFilePath << std::endl; ".png";
// polyscope::screenshot(screenshotOutputFilePath, false); std::cout << "Saving image to:" << screenshotOutputFilePath
// simulationResults_tiledFullPattern_drm.unregister(); << std::endl;
//#endif polyscope::screenshot(screenshotOutputFilePath, false);
simulationResults_tilledPattern.unregister();
#endif
simulationResults_tilledPattern.converged = true; simulationResults_tilledPattern.converged = true;
} else { } else {
@ -532,22 +442,22 @@ ReducedModelEvaluator::Results ReducedModelEvaluator::evaluateReducedModel(
// Full // Full
std::cout << "Executing:" << jobLabel << std::endl; std::cout << "Executing:" << jobLabel << std::endl;
SimulationModelFactory factory; SimulationModelFactory factory;
std::unique_ptr<SimulationModel> pTilledPatternSimulationModel = factory.create( std::unique_ptr<SimulationModel> pTilledPatternSimulationModel =
simulationModelLabel); factory.create(simulationModelLabel_pattern);
//TODO: since the drm simulation model does not have a common interface with the rest of simulation models I need to cast it in order to pass simulation settings. Fix it by removing the SimulationSettings argument // TODO: since the drm simulation model does not have a common
if (simulationModelLabel == DRMSimulationModel::label) { // interface with the rest of simulation models I need to cast it in
simulationResults_tilledPattern = static_cast<DRMSimulationModel *>( // order to pass simulation settings. Fix it by removing the
// SimulationSettings argument
if (simulationModelLabel_pattern == DRMSimulationModel::label) {
simulationResults_tilledPattern =
static_cast<DRMSimulationModel*>(
pTilledPatternSimulationModel.get()) pTilledPatternSimulationModel.get())
->executeSimulation(pJob_tiledFullPattern, ->executeSimulation(pJob_tilledPattern,
drmSimulationSettings); drmSimulationSettings);
} else if (simulationModelLabel == ChronosEulerSimulationModel::label) {
simulationResults_tilledPattern
= pTilledPatternSimulationModel->executeSimulation(pJob_tiledFullPattern);
} else { } else {
std::cerr << "Simulation model used for computing the optimization results was " simulationResults_tilledPattern =
"not recognized" pTilledPatternSimulationModel->executeSimulation(
<< std::endl; pJob_tilledPattern);
std::terminate();
} }
} }
if (!simulationResults_tilledPattern.converged) { if (!simulationResults_tilledPattern.converged) {
@ -557,37 +467,65 @@ ReducedModelEvaluator::Results ReducedModelEvaluator::evaluateReducedModel(
return; return;
} }
std::filesystem::create_directories(tilledPatternResultsFolderPath); std::filesystem::create_directories(tilledPatternResultsFolderPath);
const std::filesystem::path drmResultsOutputPath const std::filesystem::path drmResultsOutputPath =
= std::filesystem::path(scenarioDirectoryPath).append(patternLabel); std::filesystem::path(scenarioDirectoryPath).append(patternLabel);
simulationResults_tilledPattern.save(drmResultsOutputPath); simulationResults_tilledPattern.save(drmResultsOutputPath);
LinearSimulationModel linearSimulationModel; // LinearSimulationModel linearSimulationModel;
SimulationResults simulationResults_tiledReducedModel SimulationModelFactory factory;
= linearSimulationModel.executeSimulation(pJob_tiledReducedPattern); std::unique_ptr<SimulationModel> pSimulationModel_tilledReducedModel =
factory.create(simulationModelLabel_reducedModel);
SimulationResults simulationResults_tiledReducedModel =
pSimulationModel_tilledReducedModel->executeSimulation(
pJob_tiledReducedModel);
// ChronosEulerNonLinearSimulationModel
// debug_chronosNonLinearSimulationModel;
// const auto debug_chronosResults =
// debug_chronosNonLinearSimulationModel.executeSimulation(
// pJob_tilledPattern);
// LinearSimulationModel debug_linearSimulationModel;
// const auto debug_linearSimResults =
// debug_linearSimulationModel.executeSimulation(pJob_tilledPattern);
#ifdef POLYSCOPE_DEFINED #ifdef POLYSCOPE_DEFINED
simulationResults_tiledReducedModel.registerForDrawing(); if (shouldDrawScenarioResults) {
simulationResults_tilledPattern.registerForDrawing(); simulationResults_tiledReducedModel.registerForDrawing(
ReducedModelOptimization::Colors::reducedDeformed, true,
simulationResults_tilledPattern.pJob->pMesh
->getBeamDimensions()[0]
.getDrawingRadius());
simulationResults_tilledPattern.registerForDrawing(
ReducedModelOptimization::Colors::patternDeformed);
// debug_chronosResults.registerForDrawing();
// debug_linearSimResults.registerForDrawing();
polyscope::show(); polyscope::show();
// debug_linearSimResults.unregister();
simulationResults_tiledReducedModel.unregister();
simulationResults_tilledPattern.unregister();
// debug_chronosResults.unregister();
}
#endif #endif
// compute the full2reduced distance // compute the full2reduced distance
const double distance_patternToReduced const double distance_patternToReduced =
= simulationResults_tilledPattern simulationResults_tilledPattern.computeDistance(
.computeDistance(simulationResults_tiledReducedModel, fullToReducedViMap); simulationResults_tiledReducedModel, fullToReducedViMap);
double distance_patternSumOfAllVerts = 0; double distance_patternSumOfAllVerts = 0;
for (std::pair<size_t, size_t> fullToReducedPair : fullToReducedViMap) { for (std::pair<size_t, size_t> fullToReducedPair : fullToReducedViMap) {
distance_patternSumOfAllVerts += simulationResults_tilledPattern distance_patternSumOfAllVerts +=
simulationResults_tilledPattern
.displacements[fullToReducedPair.first] .displacements[fullToReducedPair.first]
.getTranslation() .getTranslation()
.norm(); .norm();
} }
const double distance_normalizedPatternToReduced = distance_patternToReduced const double distance_normalizedPatternToReduced =
/ distance_patternSumOfAllVerts; distance_patternToReduced / distance_patternSumOfAllVerts;
const int jobIndex = &jobLabel - &scenariosTestSetLabels[0]; const int jobIndex = &jobLabel - &scenariosTestSetLabels[0];
evaluationResults.distances_drm2reduced[jobIndex] = distance_patternToReduced; evaluationResults.distances_drm2reduced[jobIndex] =
evaluationResults.distances_normalizedDrm2reduced[jobIndex] distance_patternToReduced;
= distance_normalizedPatternToReduced; evaluationResults.distances_normalizedDrm2reduced[jobIndex] =
distance_normalizedPatternToReduced;
}); });
return evaluationResults; return evaluationResults;

View File

@ -2,9 +2,9 @@
#define REDUCEDMODELEVALUATOR_HPP #define REDUCEDMODELEVALUATOR_HPP
#include "reducedmodeloptimizer_structs.hpp" #include "reducedmodeloptimizer_structs.hpp"
#include "utilities.hpp"
class ReducedModelEvaluator class ReducedModelEvaluator {
{
public: public:
enum CSVExportingDirection { Vertical = 0, Horizontal }; enum CSVExportingDirection { Vertical = 0, Horizontal };
enum CSVExportingData { enum CSVExportingData {
@ -14,9 +14,9 @@ public:
NumberOfDataTypes NumberOfDataTypes
}; };
inline static std::array<std::string, NumberOfDataTypes> inline static std::array<std::string, NumberOfDataTypes>
csvExportingDataStrings{"raw_drm2Reduced", "norm_drm2Reduced", "raw_and_norm_drm2Reduced"}; csvExportingDataStrings{"raw_drm2Reduced", "norm_drm2Reduced",
struct Settings "raw_and_norm_drm2Reduced"};
{ struct Settings {
CSVExportingDirection exportingDirection{Horizontal}; CSVExportingDirection exportingDirection{Horizontal};
CSVExportingData exportingData{norm_drm2Reduced}; CSVExportingData exportingData{norm_drm2Reduced};
bool shouldWriteHeader{true}; bool shouldWriteHeader{true};
@ -24,11 +24,12 @@ public:
}; };
inline static constexpr int NumberOfEvaluationScenarios{22}; inline static constexpr int NumberOfEvaluationScenarios{22};
struct Results struct Results {
{
std::array<double, NumberOfEvaluationScenarios> distances_drm2reduced; std::array<double, NumberOfEvaluationScenarios> distances_drm2reduced;
std::array<double, NumberOfEvaluationScenarios> distances_normalizedDrm2reduced; std::array<double, NumberOfEvaluationScenarios>
std::array<std::string, NumberOfEvaluationScenarios> evaluationScenarioLabels; distances_normalizedDrm2reduced;
std::array<std::string, NumberOfEvaluationScenarios>
evaluationScenarioLabels;
}; };
ReducedModelEvaluator(); ReducedModelEvaluator();
Results evaluateReducedModel( Results evaluateReducedModel(
@ -36,40 +37,35 @@ public:
const std::filesystem::path& scenariosDirectoryPath, const std::filesystem::path& scenariosDirectoryPath,
// const std::filesystem::path &reducedPatternFilePath, // const std::filesystem::path &reducedPatternFilePath,
const std::filesystem::path& fullPatternTessellatedResultsDirectoryPath); const std::filesystem::path& fullPatternTessellatedResultsDirectoryPath);
Results evaluateReducedModel(ReducedModelOptimization::Results &optimizationResult); Results evaluateReducedModel(
static void printResultsVertically(const ReducedModelEvaluator::Results &evaluationResults, ReducedModelOptimization::Results& optimizationResult);
static void printResultsVertically(
const ReducedModelEvaluator::Results& evaluationResults,
csvFile& csvOutput); csvFile& csvOutput);
static void printResults(const ReducedModelEvaluator::Results &evaluationResults, static void printResults(
const ReducedModelEvaluator::Results& evaluationResults,
const std::string& resultsLabel); const std::string& resultsLabel);
inline static std::array<std::string, NumberOfEvaluationScenarios> scenariosTestSetLabels{ inline static std::array<std::string, NumberOfEvaluationScenarios>
"22Hex_randomBending0", scenariosTestSetLabels{
"22Hex_randomBending1", "22Hex_randomBending0", "22Hex_randomBending1",
"22Hex_randomBending2", "22Hex_randomBending2",
// "22Hex_randomBending3", // "22Hex_randomBending3",
"22Hex_randomBending4", "22Hex_randomBending4", "22Hex_randomBending5",
"22Hex_randomBending5",
// "22Hex_randomBending6", // "22Hex_randomBending6",
// "22Hex_randomBending7", // "22Hex_randomBending7",
"22Hex_randomBending8", "22Hex_randomBending8", "22Hex_randomBending9",
"22Hex_randomBending9", "22Hex_randomBending10", "22Hex_randomBending11",
"22Hex_randomBending10",
"22Hex_randomBending11",
"22Hex_randomBending12", "22Hex_randomBending12",
// "22Hex_randomBending13", // "22Hex_randomBending13",
// "22Hex_randomBending14", // "22Hex_randomBending14",
// "22Hex_randomBending15", // "22Hex_randomBending15",
"22Hex_randomBending16", "22Hex_randomBending16", "22Hex_randomBending17",
"22Hex_randomBending17", "22Hex_randomBending18", "22Hex_randomBending19",
"22Hex_randomBending18",
"22Hex_randomBending19",
// "22Hex_randomBending20", // "22Hex_randomBending20",
"22Hex_bending_0.005N", "22Hex_bending_0.005N", "22Hex_bending_0.01N", "22Hex_bending_0.03N",
"22Hex_bending_0.01N",
"22Hex_bending_0.03N",
// "22Hex_bending_0.05N", // "22Hex_bending_0.05N",
"22Hex_pullOppositeVerts_0.05N", "22Hex_pullOppositeVerts_0.05N", "22Hex_pullOppositeVerts_0.1N",
"22Hex_pullOppositeVerts_0.1N",
// "22Hex_pullOppositeVerts_0.3N", // "22Hex_pullOppositeVerts_0.3N",
//#ifdef POLYSCOPE_DEFINED //#ifdef POLYSCOPE_DEFINED
// "22Hex_shear_2N", // "22Hex_shear_2N",
@ -82,12 +78,11 @@ public:
// "notUsed_22Hex_axial_10N", // "notUsed_22Hex_axial_10N",
// "notUsed_22Hex_axial_20N", // "notUsed_22Hex_axial_20N",
//#endif //#endif
"22Hex_cylinder_0.05N", "22Hex_cylinder_0.05N", "22Hex_cylinder_0.1N", "22Hex_s_0.05N",
"22Hex_cylinder_0.1N",
"22Hex_s_0.05N",
// "22Hex_s_0.1N" // "22Hex_s_0.1N"
}; };
static void printResultsHorizontally(const Results &evaluationResults, csvFile &csvOutput); static void printResultsHorizontally(const Results& evaluationResults,
csvFile& csvOutput);
static void printResults(const Results& evaluationResults, static void printResults(const Results& evaluationResults,
const Settings& settings, const Settings& settings,
csvFile& csvOutput); csvFile& csvOutput);
@ -95,8 +90,17 @@ public:
// static double evaluateOptimizationSettings( // static double evaluateOptimizationSettings(
// const ReducedModelOptimization::Settings &optimizationSettings, // const ReducedModelOptimization::Settings &optimizationSettings,
// const std::vector<std::shared_ptr<PatternGeometry>> &pPatterns, // const std::vector<std::shared_ptr<PatternGeometry>> &pPatterns,
// std::vector<ReducedModelEvaluator::Results> &patternEvaluationResults); // std::vector<ReducedModelEvaluator::Results>
// &patternEvaluationResults);
std::shared_ptr<VCGPolyMesh> pTileIntoSurface; std::shared_ptr<VCGPolyMesh> pTileIntoSurface;
ReducedModelOptimization::Colors::RGBColor color_tesselatedPatterns{
24.0 / 255, 23.0 / 255, 23.0 / 255};
ReducedModelOptimization::Colors::RGBColor color_tesselatedReducedModels{
67.0 / 255, 160.00 / 255, 232.0 / 255};
ReducedModelOptimization::Colors::RGBColor color_tileIntoSurface{
222 / 255.0, 235 / 255.0, 255 / 255.0};
ReducedModelOptimization::Colors::RGBColor interfaceNodes_color{
63.0 / 255, 85.0 / 255, 42.0 / 255};
inline static constexpr char* tileIntoSurfaceFileContent = R"~(OFF inline static constexpr char* tileIntoSurfaceFileContent = R"~(OFF
46 66 0 46 66 0
-0.0745923 0.03573945 0 -0.0745923 0.03573945 0

File diff suppressed because it is too large Load Diff

View File

@ -1,18 +1,17 @@
#ifndef REDUCEDMODELOPTIMIZER_HPP #ifndef REDUCEDMODELOPTIMIZER_HPP
#define REDUCEDMODELOPTIMIZER_HPP #define REDUCEDMODELOPTIMIZER_HPP
#include "chronoseulersimulationmodel.hpp" //#include "csvfile.hpp"
#include "csvfile.hpp"
#include "drmsimulationmodel.hpp" #include "drmsimulationmodel.hpp"
#include "edgemesh.hpp" #include "edgemesh.hpp"
#include "linearsimulationmodel.hpp" #include "linearsimulationmodel.hpp"
#ifdef POLYSCOPE_DEFINED #ifdef POLYSCOPE_DEFINED
#include "matplot/matplot.h" #include "matplot/matplot.h"
#endif #endif
#include <Eigen/Dense>
#include "reducedmodel.hpp" #include "reducedmodel.hpp"
#include "reducedmodeloptimizer_structs.hpp" #include "reducedmodeloptimizer_structs.hpp"
#include "simulationmesh.hpp" #include "simulationmesh.hpp"
#include <Eigen/Dense>
#ifdef DLIB_DEFINED #ifdef DLIB_DEFINED
#include <dlib/global_optimization.h> #include <dlib/global_optimization.h>
#include <dlib/optimization.h> #include <dlib/optimization.h>
@ -21,32 +20,32 @@
#ifdef POLYSCOPE_DEFINED #ifdef POLYSCOPE_DEFINED
#include "polyscope/color_management.h" #include "polyscope/color_management.h"
#endif // POLYSCOPE_DEFINED #endif // POLYSCOPE_DEFINED
using FullPatternVertexIndex = VertexIndex; using PatternVertexIndex = VertexIndex;
using ReducedPatternVertexIndex = VertexIndex; using ReducedModelVertexIndex = VertexIndex;
class ReducedModelOptimizer class ReducedModelOptimizer {
{
public: public:
struct OptimizationState struct OptimizationState {
{
std::vector<SimulationResults> fullPatternResults; std::vector<SimulationResults> fullPatternResults;
std::vector<double> translationalDisplacementNormalizationValues; std::vector<double> translationalDisplacementNormalizationValues;
std::vector<double> rotationalDisplacementNormalizationValues; std::vector<double> rotationalDisplacementNormalizationValues;
std::vector<std::shared_ptr<SimulationJob>> fullPatternSimulationJobs; std::vector<std::shared_ptr<SimulationJob>> pSimulationJobs_pattern;
std::vector<std::shared_ptr<SimulationJob>> reducedPatternSimulationJobs; std::vector<std::shared_ptr<SimulationJob>> simulationJobs_reducedModel;
std::unordered_map<ReducedPatternVertexIndex, FullPatternVertexIndex> std::unordered_map<ReducedModelVertexIndex, PatternVertexIndex>
reducedToFullInterfaceViMap; reducedToFullInterfaceViMap;
std::vector<std::pair<FullPatternVertexIndex, FullPatternVertexIndex>> std::vector<std::pair<PatternVertexIndex, PatternVertexIndex>>
fullPatternOppositeInterfaceViPairs; fullPatternOppositeInterfaceViPairs;
matplot::line_handle gPlotHandle; matplot::line_handle gPlotHandle;
std::vector<size_t> objectiveValueHistory_iteration; std::vector<size_t> objectiveValueHistory_iteration;
std::vector<double> objectiveValueHistory; std::vector<double> objectiveValueHistory;
std::vector<double> plotColors; std::vector<double> plotColors;
std::array<double, std::array<double,
ReducedModelOptimization::OptimizationParameterIndex::NumberOfOptimizationVariables> ReducedModelOptimization::OptimizationParameterIndex::
NumberOfOptimizationVariables>
parametersInitialValue; parametersInitialValue;
std::array<double, std::array<double,
ReducedModelOptimization::OptimizationParameterIndex::NumberOfOptimizationVariables> ReducedModelOptimization::OptimizationParameterIndex::
NumberOfOptimizationVariables>
optimizationInitialValue; optimizationInitialValue;
std::vector<int> simulationScenarioIndices; std::vector<int> simulationScenarioIndices;
double minY{DBL_MAX}; double minY{DBL_MAX};
@ -54,50 +53,51 @@ public:
int numOfSimulationCrashes{false}; int numOfSimulationCrashes{false};
int numberOfFunctionCalls{0}; int numberOfFunctionCalls{0};
// Variables for finding the full pattern simulation forces // Variables for finding the full pattern simulation forces
std::shared_ptr<SimulationMesh> pFullPatternSimulationMesh; std::shared_ptr<SimulationEdgeMesh> pFullPatternSimulationEdgeMesh;
std::array<std::function<void(const double& newValue, std::array<std::function<void(const double& newValue,
std::shared_ptr<SimulationMesh> &pReducedPatternSimulationMesh)>, std::shared_ptr<SimulationEdgeMesh>&
pReducedPatternSimulationEdgeMesh)>,
7> 7>
functions_updateReducedPatternParameter; functions_updateReducedPatternParameter;
std::vector<double> xMin; std::vector<double> xMin;
std::vector<double> xMax; std::vector<double> xMax;
std::vector<double> scenarioWeights; std::vector<double> scenarioWeights;
std::vector<ReducedModelOptimization::Settings::ObjectiveWeights> objectiveWeights; std::vector<ReducedModelOptimization::Settings::ObjectiveWeights>
objectiveWeights;
std::string simulationModelLabel_reducedModel;
}; };
private: private:
OptimizationState optimizationState; OptimizationState optimizationState;
vcg::Triangle3<double> baseTriangle; vcg::Triangle3<double> baseTriangle;
std::function<void(const double &, std::function<void(
const std::vector<std::pair<FullPatternVertexIndex, FullPatternVertexIndex>> &, const double&,
const std::vector<std::pair<PatternVertexIndex, PatternVertexIndex>>&,
SimulationJob&)> SimulationJob&)>
constructScenarioFunction; constructScenarioFunction;
std::shared_ptr<SimulationMesh> m_pReducedModelSimulationMesh; std::shared_ptr<SimulationEdgeMesh> m_pReducedModelSimulationEdgeMesh;
std::shared_ptr<SimulationMesh> m_pFullPatternSimulationMesh; std::shared_ptr<SimulationEdgeMesh> m_pSimulationEdgeMesh_pattern;
std::unordered_map<FullPatternVertexIndex, ReducedPatternVertexIndex> std::unordered_map<PatternVertexIndex, ReducedModelVertexIndex>
m_fullToReducedInterfaceViMap; m_fullToReducedInterfaceViMap;
std::vector<std::pair<FullPatternVertexIndex, FullPatternVertexIndex>> std::vector<std::pair<PatternVertexIndex, PatternVertexIndex>>
m_fullPatternOppositeInterfaceViPairs; m_fullPatternOppositeInterfaceViPairs;
std::unordered_map<size_t, size_t> nodeToSlot; std::unordered_map<size_t, size_t> nodeToSlot;
std::unordered_map<size_t, std::unordered_set<size_t>> slotToNode; std::unordered_map<size_t, std::unordered_set<size_t>> slotToNode;
std::string optimizationNotes; std::string optimizationNotes;
std::array<std::function<void( std::array<
std::function<void(
const double&, const double&,
const std::vector<std::pair<FullPatternVertexIndex, FullPatternVertexIndex>> &, const std::vector<std::pair<PatternVertexIndex, PatternVertexIndex>>&,
SimulationJob&)>, SimulationJob&)>,
ReducedModelOptimization::NumberOfBaseSimulationScenarios> ReducedModelOptimization::NumberOfBaseSimulationScenarios>
constructBaseScenarioFunctions; constructBaseScenarioFunctions;
std::vector<bool> scenarioIsSymmetrical; std::vector<bool> scenarioIsSymmetrical;
int fullPatternNumberOfEdges; int fullPatternNumberOfEdges;
constexpr static double youngsModulus{1 * 1e9};
constexpr static double defaultBeamWidth{0.002};
constexpr static double defaultBeamHeight{0.002};
std::string fullPatternLabel; std::string fullPatternLabel;
// ReducedModelOptimization::Settings optimizationSettings; // ReducedModelOptimization::Settings optimizationSettings;
public: public:
struct FunctionEvaluation struct FunctionEvaluation {
{
FunctionEvaluation() = default; FunctionEvaluation() = default;
FunctionEvaluation(const std::vector<double>& x, double y) : x(x), y(y) {} FunctionEvaluation(const std::vector<double>& x, double y) : x(x), y(y) {}
@ -117,18 +117,24 @@ public:
// }; // };
// inline constexpr static ParameterLabels parameterLabels(); // inline constexpr static ParameterLabels parameterLabels();
inline static std::array<std::string, ReducedModelOptimization::NumberOfOptimizationVariables> inline static std::array<
std::string,
ReducedModelOptimization::NumberOfOptimizationVariables>
parameterLabels = {"E", "A", "I2", "I3", "J", "Theta", "R"}; parameterLabels = {"E", "A", "I2", "I3", "J", "Theta", "R"};
constexpr static std::array<double, ReducedModelOptimization::NumberOfBaseSimulationScenarios> constexpr static std::
array<double, ReducedModelOptimization::NumberOfBaseSimulationScenarios>
simulationScenariosResolution = {12, 12, 22, 22, 22, 22}; simulationScenariosResolution = {12, 12, 22, 22, 22, 22};
constexpr static std::array<double, ReducedModelOptimization::NumberOfBaseSimulationScenarios> // simulationScenariosResolution = {2, 2, 2, 22, 22, 22};
constexpr static std::
array<double, ReducedModelOptimization::NumberOfBaseSimulationScenarios>
baseScenarioWeights = {1, 1, 2, 2, 2}; baseScenarioWeights = {1, 1, 2, 2, 2};
inline static int totalNumberOfSimulationScenarios inline static int totalNumberOfSimulationScenarios =
= std::accumulate(simulationScenariosResolution.begin(), std::accumulate(simulationScenariosResolution.begin(),
simulationScenariosResolution.end(), simulationScenariosResolution.end(),
0); 0);
inline static int fanSize{6}; inline static int fanCardinality{6};
inline static double initialHexagonSize{0.3}; inline static double initialValue_R{0.3};
inline static double initialValue_theta{0};
int interfaceNodeIndex; int interfaceNodeIndex;
double operator()(const Eigen::VectorXd& x, Eigen::VectorXd&) const; double operator()(const Eigen::VectorXd& x, Eigen::VectorXd&) const;
@ -138,128 +144,145 @@ public:
const std::unordered_map<size_t, size_t>& fullToReducedMap, const std::unordered_map<size_t, size_t>& fullToReducedMap,
SimulationJob& simulationJobOfReducedModel); SimulationJob& simulationJobOfReducedModel);
SimulationJob getReducedSimulationJob(const SimulationJob &fullModelSimulationJob); SimulationJob getReducedSimulationJob(
const SimulationJob& fullModelSimulationJob);
static void runSimulation(const std::string &filename, std::vector<double> &x); static void runSimulation(const std::string& filename,
std::vector<double>& x);
static std::vector<std::shared_ptr<SimulationJob>> createFullPatternSimulationJobs( static std::vector<std::shared_ptr<SimulationJob>>
const std::shared_ptr<SimulationMesh> &pMesh, createFullPatternSimulationJobs(
const std::unordered_map<size_t, size_t> &fullPatternOppositeInterfaceViMap); const std::shared_ptr<SimulationEdgeMesh>& pMesh,
const std::unordered_map<size_t, size_t>&
fullPatternOppositeInterfaceViMap);
static void createSimulationMeshes( static void createSimulationEdgeMeshes(
PatternGeometry& pattern, PatternGeometry& pattern,
PatternGeometry& reducedModel, PatternGeometry& reducedModel,
const RectangularBeamDimensions &beamDimensions, const ReducedModelOptimization::Settings& optimizationSettings,
std::shared_ptr<SimulationMesh> &pFullPatternSimulationMesh, std::shared_ptr<SimulationEdgeMesh>& pFullPatternSimulationEdgeMesh,
std::shared_ptr<SimulationMesh> &pReducedPatternSimulationMesh); std::shared_ptr<SimulationEdgeMesh>& pReducedPatternSimulationEdgeMesh);
void computeMaps(const std::unordered_map<size_t, std::unordered_set<size_t>> &slotToNode, void computeMaps(
const std::unordered_map<size_t, std::unordered_set<size_t>>& slotToNode,
PatternGeometry& fullPattern, PatternGeometry& fullPattern,
ReducedModel& reducedPattern, ReducedModel& reducedPattern,
std::unordered_map<ReducedPatternVertexIndex, FullPatternVertexIndex> std::unordered_map<ReducedModelVertexIndex, PatternVertexIndex>&
&reducedToFullInterfaceViMap, reducedToFullInterfaceViMap,
std::unordered_map<FullPatternVertexIndex, ReducedPatternVertexIndex> std::unordered_map<PatternVertexIndex, ReducedModelVertexIndex>&
&fullToReducedInterfaceViMap, fullToReducedInterfaceViMap,
std::vector<std::pair<FullPatternVertexIndex, ReducedPatternVertexIndex>> std::vector<std::pair<PatternVertexIndex, ReducedModelVertexIndex>>&
&fullPatternOppositeInterfaceViMap); fullPatternOppositeInterfaceViMap);
static void visualizeResults( static void visualizeResults(
const std::vector<std::shared_ptr<SimulationJob>> &fullPatternSimulationJobs, const std::vector<std::shared_ptr<SimulationJob>>&
const std::vector<std::shared_ptr<SimulationJob>> &reducedPatternSimulationJobs, fullPatternSimulationJobs,
const std::vector<ReducedModelOptimization::BaseSimulationScenario> &simulationScenarios, const std::vector<std::shared_ptr<SimulationJob>>&
const std::unordered_map<ReducedPatternVertexIndex, FullPatternVertexIndex> reducedPatternSimulationJobs,
&reducedToFullInterfaceViMap); const std::vector<ReducedModelOptimization::BaseSimulationScenario>&
simulationScenarios,
const std::unordered_map<ReducedModelVertexIndex, PatternVertexIndex>&
reducedToFullInterfaceViMap);
static void registerResultsForDrawing( static void registerResultsForDrawing(
const std::shared_ptr<SimulationJob>& pFullPatternSimulationJob, const std::shared_ptr<SimulationJob>& pFullPatternSimulationJob,
const std::shared_ptr<SimulationJob>& pReducedPatternSimulationJob, const std::shared_ptr<SimulationJob>& pReducedPatternSimulationJob,
const std::unordered_map<ReducedPatternVertexIndex, FullPatternVertexIndex> const std::unordered_map<ReducedModelVertexIndex, PatternVertexIndex>&
&reducedToFullInterfaceViMap); reducedToFullInterfaceViMap);
static double computeRawTranslationalError( static double computeRawTranslationalError(
const std::vector<Vector6d>& fullPatternDisplacements, const std::vector<Vector6d>& fullPatternDisplacements,
const std::vector<Vector6d>& reducedPatternDisplacements, const std::vector<Vector6d>& reducedPatternDisplacements,
const std::unordered_map<ReducedPatternVertexIndex, FullPatternVertexIndex> const std::unordered_map<ReducedModelVertexIndex, PatternVertexIndex>&
&reducedToFullInterfaceViMap); reducedToFullInterfaceViMap);
static double computeDisplacementError( static double computeDisplacementError(
const std::vector<Vector6d>& fullPatternDisplacements, const std::vector<Vector6d>& fullPatternDisplacements,
const std::vector<Vector6d>& reducedPatternDisplacements, const std::vector<Vector6d>& reducedPatternDisplacements,
const std::unordered_map<ReducedPatternVertexIndex, FullPatternVertexIndex> const std::unordered_map<ReducedModelVertexIndex, PatternVertexIndex>&
&reducedToFullInterfaceViMap, reducedToFullInterfaceViMap,
const double& normalizationFactor); const double& normalizationFactor);
static double computeRawRotationalError( static double computeRawRotationalError(
const std::vector<Eigen::Quaterniond>& rotatedQuaternion_fullPattern, const std::vector<Eigen::Quaterniond>& rotatedQuaternion_fullPattern,
const std::vector<Eigen::Quaterniond>& rotatedQuaternion_reducedPattern, const std::vector<Eigen::Quaterniond>& rotatedQuaternion_reducedPattern,
const std::unordered_map<ReducedPatternVertexIndex, FullPatternVertexIndex> const std::unordered_map<ReducedModelVertexIndex, PatternVertexIndex>&
&reducedToFullInterfaceViMap); reducedToFullInterfaceViMap);
static double computeRotationalError(const std::vector<Eigen::Quaterniond> &rotatedQuaternion_fullPattern, static double computeRotationalError(
const std::vector<Eigen::Quaterniond>& rotatedQuaternion_fullPattern,
const std::vector<Eigen::Quaterniond>& rotatedQuaternion_reducedPattern, const std::vector<Eigen::Quaterniond>& rotatedQuaternion_reducedPattern,
const std::unordered_map<ReducedPatternVertexIndex, FullPatternVertexIndex> const std::unordered_map<ReducedModelVertexIndex, PatternVertexIndex>&
&reducedToFullInterfaceViMap, reducedToFullInterfaceViMap,
const double& normalizationFactor); const double& normalizationFactor);
static double computeError( static double computeError(
const SimulationResults& simulationResults_fullPattern, const SimulationResults& simulationResults_fullPattern,
const SimulationResults& simulationResults_reducedPattern, const SimulationResults& simulationResults_reducedPattern,
const std::unordered_map<ReducedPatternVertexIndex, FullPatternVertexIndex> const std::unordered_map<ReducedModelVertexIndex, PatternVertexIndex>&
&reducedToFullInterfaceViMap, reducedToFullInterfaceViMap,
const double& normalizationFactor_translationalDisplacement, const double& normalizationFactor_translationalDisplacement,
const double& normalizationFactor_rotationalDisplacement, const double& normalizationFactor_rotationalDisplacement,
const double& scenarioWeight, const double& scenarioWeight,
const ReducedModelOptimization::Settings::ObjectiveWeights &objectiveWeights); const ReducedModelOptimization::Settings::ObjectiveWeights&
objectiveWeights);
static void constructAxialSimulationScenario( static void constructAxialSimulationScenario(
const double& forceMagnitude, const double& forceMagnitude,
const std::vector<std::pair<FullPatternVertexIndex, FullPatternVertexIndex>> const std::vector<std::pair<PatternVertexIndex, PatternVertexIndex>>&
&oppositeInterfaceViPairs, oppositeInterfaceViPairs,
SimulationJob& job); SimulationJob& job);
static void constructShearSimulationScenario( static void constructShearSimulationScenario(
const double& forceMagnitude, const double& forceMagnitude,
const std::vector<std::pair<FullPatternVertexIndex, FullPatternVertexIndex>> const std::vector<std::pair<PatternVertexIndex, PatternVertexIndex>>&
&oppositeInterfaceViPairs, oppositeInterfaceViPairs,
SimulationJob& job); SimulationJob& job);
static void constructBendingSimulationScenario( static void constructBendingSimulationScenario(
const double& forceMagnitude, const double& forceMagnitude,
const std::vector<std::pair<FullPatternVertexIndex, FullPatternVertexIndex>> const std::vector<std::pair<PatternVertexIndex, PatternVertexIndex>>&
&oppositeInterfaceViPairs, oppositeInterfaceViPairs,
SimulationJob& job); SimulationJob& job);
static void constructDomeSimulationScenario( static void constructDomeSimulationScenario(
const double& forceMagnitude, const double& forceMagnitude,
const std::vector<std::pair<FullPatternVertexIndex, FullPatternVertexIndex>> const std::vector<std::pair<PatternVertexIndex, PatternVertexIndex>>&
&oppositeInterfaceViPairs, oppositeInterfaceViPairs,
SimulationJob& job); SimulationJob& job);
static void constructSaddleSimulationScenario( static void constructSaddleSimulationScenario(
const double& forceMagnitude, const double& forceMagnitude,
const std::vector<std::pair<FullPatternVertexIndex, FullPatternVertexIndex>> const std::vector<std::pair<PatternVertexIndex, PatternVertexIndex>>&
&oppositeInterfaceViPairs, oppositeInterfaceViPairs,
SimulationJob& job); SimulationJob& job);
static void constructSSimulationScenario( static void constructSSimulationScenario(
const double& forceMagnitude, const double& forceMagnitude,
const std::vector<std::pair<FullPatternVertexIndex, FullPatternVertexIndex>> const std::vector<std::pair<PatternVertexIndex, PatternVertexIndex>>&
&oppositeInterfaceViPairs, oppositeInterfaceViPairs,
SimulationJob& job); SimulationJob& job);
static std::function<void(const std::vector<double> &x, static std::function<void(
std::shared_ptr<SimulationMesh> &pReducedPatternSimulationMesh)> const std::vector<double>& x,
std::shared_ptr<SimulationEdgeMesh>& pReducedPatternSimulationEdgeMesh)>
function_updateReducedPattern; function_updateReducedPattern;
static std::function<void(const double &newE, static std::function<void(
std::shared_ptr<SimulationMesh> &pReducedPatternSimulationMesh)> const double& newE,
std::shared_ptr<SimulationEdgeMesh>& pReducedPatternSimulationEdgeMesh)>
function_updateReducedPattern_material_E; function_updateReducedPattern_material_E;
static std::function<void(const double &newA, static std::function<void(
std::shared_ptr<SimulationMesh> &pReducedPatternSimulationMesh)> const double& newA,
std::shared_ptr<SimulationEdgeMesh>& pReducedPatternSimulationEdgeMesh)>
function_updateReducedPattern_material_A; function_updateReducedPattern_material_A;
static std::function<void(const double &newI, static std::function<void(
std::shared_ptr<SimulationMesh> &pReducedPatternSimulationMesh)> const double& newI,
std::shared_ptr<SimulationEdgeMesh>& pReducedPatternSimulationEdgeMesh)>
function_updateReducedPattern_material_I; function_updateReducedPattern_material_I;
static std::function<void(const double &newI2, static std::function<void(
std::shared_ptr<SimulationMesh> &pReducedPatternSimulationMesh)> const double& newI2,
std::shared_ptr<SimulationEdgeMesh>& pReducedPatternSimulationEdgeMesh)>
function_updateReducedPattern_material_I2; function_updateReducedPattern_material_I2;
static std::function<void(const double &newI3, static std::function<void(
std::shared_ptr<SimulationMesh> &pReducedPatternSimulationMesh)> const double& newI3,
std::shared_ptr<SimulationEdgeMesh>& pReducedPatternSimulationEdgeMesh)>
function_updateReducedPattern_material_I3; function_updateReducedPattern_material_I3;
static std::function<void(const double &newJ, static std::function<void(
std::shared_ptr<SimulationMesh> &pReducedPatternSimulationMesh)> const double& newJ,
std::shared_ptr<SimulationEdgeMesh>& pReducedPatternSimulationEdgeMesh)>
function_updateReducedPattern_material_J; function_updateReducedPattern_material_J;
static double objective(const std::vector<double>& x); static double objective(const std::vector<double>& x);
void initializeUpdateReducedPatternFunctions(); void initializeUpdateReducedPatternFunctions();
@ -272,15 +295,17 @@ public:
void optimize(ConstPatternGeometry& fullPattern, void optimize(ConstPatternGeometry& fullPattern,
ReducedModelOptimization::Settings& optimizationSettings, ReducedModelOptimization::Settings& optimizationSettings,
ReducedModelOptimization::Results& optimizationResults); ReducedModelOptimization::Results& optimizationResults);
static double objective(const std::vector<double> &x, static double objective(
const std::vector<double>& x,
ReducedModelOptimizer::OptimizationState& optimizationState); ReducedModelOptimizer::OptimizationState& optimizationState);
private: private:
void optimize( void optimize(
ReducedModelOptimization::Settings& optimizationSettings, ReducedModelOptimization::Settings& optimizationSettings,
ReducedModelOptimization::Results& results, ReducedModelOptimization::Results& results,
const std::vector<ReducedModelOptimization::BaseSimulationScenario> &simulationScenarios const std::vector<ReducedModelOptimization::BaseSimulationScenario>&
= std::vector<ReducedModelOptimization::BaseSimulationScenario>( simulationScenarios =
std::vector<ReducedModelOptimization::BaseSimulationScenario>(
{ReducedModelOptimization::Axial, {ReducedModelOptimization::Axial,
ReducedModelOptimization::Shear, ReducedModelOptimization::Shear,
ReducedModelOptimization::Bending, ReducedModelOptimization::Bending,
@ -288,7 +313,8 @@ private:
ReducedModelOptimization::Saddle, ReducedModelOptimization::Saddle,
ReducedModelOptimization::S})); ReducedModelOptimization::S}));
void initializePatterns(PatternGeometry &fullPattern, void initializePatterns(
PatternGeometry& fullPattern,
ReducedModel& reducedModel, ReducedModel& reducedModel,
const ReducedModelOptimization::Settings& optimizationSettings); const ReducedModelOptimization::Settings& optimizationSettings);
static void computeDesiredReducedModelDisplacements( static void computeDesiredReducedModelDisplacements(
@ -298,17 +324,16 @@ private:
void runOptimization(const ReducedModelOptimization::Settings& settings, void runOptimization(const ReducedModelOptimization::Settings& settings,
ReducedModelOptimization::Results& results); ReducedModelOptimization::Results& results);
void computeMaps(PatternGeometry& fullModel, ReducedModel& reducedModel); void computeMaps(PatternGeometry& fullModel, ReducedModel& reducedModel);
void createSimulationMeshes(PatternGeometry &fullModel, void createSimulationEdgeMeshes(
PatternGeometry& fullModel,
PatternGeometry& reducedModel, PatternGeometry& reducedModel,
const RectangularBeamDimensions &beamDimensions); const ReducedModelOptimization::Settings& optimizationSettings);
void initializeOptimizationParameters( void initializeOptimizationParameters(
const std::shared_ptr<SimulationMesh> &mesh, const std::shared_ptr<SimulationEdgeMesh>& mesh,
const std::array<ReducedModelOptimization::xRange, const std::array<ReducedModelOptimization::xRange,
ReducedModelOptimization::NumberOfOptimizationVariables> ReducedModelOptimization::NumberOfOptimizationVariables>&
&optimizationParamters); optimizationParamters);
ChronosEulerSimulationModel patternSimulator;
LinearSimulationModel reducedModelSimulator;
void computeObjectiveValueNormalizationFactors( void computeObjectiveValueNormalizationFactors(
const ReducedModelOptimization::Settings& optimizationSettings); const ReducedModelOptimization::Settings& optimizationSettings);
@ -323,43 +348,53 @@ private:
#endif #endif
std::array<double, ReducedModelOptimization::NumberOfBaseSimulationScenarios> std::array<double, ReducedModelOptimization::NumberOfBaseSimulationScenarios>
computeFullPatternMaxSimulationForces( computeFullPatternMaxSimulationForces(
const std::vector<ReducedModelOptimization::BaseSimulationScenario> const std::vector<ReducedModelOptimization::BaseSimulationScenario>&
&desiredBaseSimulationScenario) const; desiredBaseSimulationScenario) const;
std::vector<std::shared_ptr<SimulationJob>> createFullPatternSimulationJobs( std::vector<std::shared_ptr<SimulationJob>> createFullPatternSimulationJobs(
const std::shared_ptr<SimulationMesh> &pMesh, const std::shared_ptr<SimulationEdgeMesh>& pMesh,
const std::array<double, ReducedModelOptimization::NumberOfBaseSimulationScenarios> const std::array<
&baseScenarioMaxForceMagnitudes) const; double,
ReducedModelOptimization::NumberOfBaseSimulationScenarios>&
baseScenarioMaxForceMagnitudes) const;
std::array<double, ReducedModelOptimization::NumberOfBaseSimulationScenarios> std::array<double, ReducedModelOptimization::NumberOfBaseSimulationScenarios>
getFullPatternMaxSimulationForces( getFullPatternMaxSimulationForces(
const std::vector<ReducedModelOptimization::BaseSimulationScenario> const std::vector<ReducedModelOptimization::BaseSimulationScenario>&
&desiredBaseSimulationScenarioIndices, desiredBaseSimulationScenarioIndices,
const std::filesystem::path& intermediateResultsDirectoryPath, const std::filesystem::path& intermediateResultsDirectoryPath,
const bool& recomputeForceMagnitudes); const bool& recomputeForceMagnitudes);
std::array<double, ReducedModelOptimization::NumberOfBaseSimulationScenarios> std::array<double, ReducedModelOptimization::NumberOfBaseSimulationScenarios>
getFullPatternMaxSimulationForces(); getFullPatternMaxSimulationForces();
void computeScenarioWeights( void computeScenarioWeights(
const std::vector<ReducedModelOptimization::BaseSimulationScenario> &baseSimulationScenarios, const std::vector<ReducedModelOptimization::BaseSimulationScenario>&
baseSimulationScenarios,
const ReducedModelOptimization::Settings& optimizationSettings); const ReducedModelOptimization::Settings& optimizationSettings);
}; };
inline std::function<void(const double &newE, inline std::function<void(
std::shared_ptr<SimulationMesh> &pReducedPatternSimulationMesh)> const double& newE,
std::shared_ptr<SimulationEdgeMesh>& pReducedPatternSimulationEdgeMesh)>
ReducedModelOptimizer::function_updateReducedPattern_material_E; ReducedModelOptimizer::function_updateReducedPattern_material_E;
inline std::function<void(const double &newA, inline std::function<void(
std::shared_ptr<SimulationMesh> &pReducedPatternSimulationMesh)> const double& newA,
std::shared_ptr<SimulationEdgeMesh>& pReducedPatternSimulationEdgeMesh)>
ReducedModelOptimizer::function_updateReducedPattern_material_A; ReducedModelOptimizer::function_updateReducedPattern_material_A;
inline std::function<void(const double &newI, inline std::function<void(
std::shared_ptr<SimulationMesh> &pReducedPatternSimulationMesh)> const double& newI,
std::shared_ptr<SimulationEdgeMesh>& pReducedPatternSimulationEdgeMesh)>
ReducedModelOptimizer::function_updateReducedPattern_material_I; ReducedModelOptimizer::function_updateReducedPattern_material_I;
inline std::function<void(const double &newI2, inline std::function<void(
std::shared_ptr<SimulationMesh> &pReducedPatternSimulationMesh)> const double& newI2,
std::shared_ptr<SimulationEdgeMesh>& pReducedPatternSimulationEdgeMesh)>
ReducedModelOptimizer::function_updateReducedPattern_material_I2; ReducedModelOptimizer::function_updateReducedPattern_material_I2;
inline std::function<void(const double &newI3, inline std::function<void(
std::shared_ptr<SimulationMesh> &pReducedPatternSimulationMesh)> const double& newI3,
std::shared_ptr<SimulationEdgeMesh>& pReducedPatternSimulationEdgeMesh)>
ReducedModelOptimizer::function_updateReducedPattern_material_I3; ReducedModelOptimizer::function_updateReducedPattern_material_I3;
inline std::function<void(const double &newJ, inline std::function<void(
std::shared_ptr<SimulationMesh> &pReducedPatternSimulationMesh)> const double& newJ,
std::shared_ptr<SimulationEdgeMesh>& pReducedPatternSimulationEdgeMesh)>
ReducedModelOptimizer::function_updateReducedPattern_material_J; ReducedModelOptimizer::function_updateReducedPattern_material_J;
inline std::function<void(const std::vector<double> &x, std::shared_ptr<SimulationMesh> &m)> inline std::function<void(const std::vector<double>& x,
std::shared_ptr<SimulationEdgeMesh>& m)>
ReducedModelOptimizer::function_updateReducedPattern; ReducedModelOptimizer::function_updateReducedPattern;
extern ReducedModelOptimizer::OptimizationState global; extern ReducedModelOptimizer::OptimizationState global;

File diff suppressed because it is too large Load Diff

View File

@ -1,12 +1,13 @@
#include "topologyenumerator.hpp" #include "topologyenumerator.hpp"
#include <math.h>
#include <algorithm> #include <algorithm>
#include <boost/graph/biconnected_components.hpp> #include <boost/graph/biconnected_components.hpp>
#include <iostream> #include <iostream>
#include <math.h>
#include <numeric> #include <numeric>
#include <thread>
#include <unordered_set> #include <unordered_set>
const bool debugIsOn{false}; const bool debugIsOn{true};
const bool savePlyFiles{true}; const bool savePlyFiles{true};
// size_t binomialCoefficient(size_t n, size_t m) { // size_t binomialCoefficient(size_t n, size_t m) {
@ -34,8 +35,7 @@ const bool savePlyFiles{true};
// .string()); // .string());
//} //}
size_t TopologyEnumerator::getEdgeIndex(size_t ni0, size_t ni1) const size_t TopologyEnumerator::getEdgeIndex(size_t ni0, size_t ni1) const {
{
if (ni1 <= ni0) { if (ni1 <= ni0) {
std::swap(ni0, ni1); std::swap(ni0, ni1);
} }
@ -46,30 +46,35 @@ size_t TopologyEnumerator::getEdgeIndex(size_t ni0, size_t ni1) const
TopologyEnumerator::TopologyEnumerator() {} TopologyEnumerator::TopologyEnumerator() {}
void TopologyEnumerator::computeValidPatterns(const std::vector<size_t> &reducedNumberOfNodesPerSlot, void TopologyEnumerator::computeValidPatterns(
const std::vector<size_t>& reducedNumberOfNodesPerSlot,
const std::string& desiredResultsPath, const std::string& desiredResultsPath,
const int &numberOfDesiredEdges) const int& numberOfDesiredEdges) {
{
assert(reducedNumberOfNodesPerSlot.size() == 5); assert(reducedNumberOfNodesPerSlot.size() == 5);
assert(reducedNumberOfNodesPerSlot[0] == 0 || reducedNumberOfNodesPerSlot[0] == 1); assert(reducedNumberOfNodesPerSlot[0] == 0 ||
assert(reducedNumberOfNodesPerSlot[1] == 0 || reducedNumberOfNodesPerSlot[1] == 1); reducedNumberOfNodesPerSlot[0] == 1);
std::vector<size_t> numberOfNodesPerSlot{reducedNumberOfNodesPerSlot[0], assert(reducedNumberOfNodesPerSlot[1] == 0 ||
reducedNumberOfNodesPerSlot[1], reducedNumberOfNodesPerSlot[1] == 1);
reducedNumberOfNodesPerSlot[1], std::vector<size_t> numberOfNodesPerSlot{
reducedNumberOfNodesPerSlot[2], reducedNumberOfNodesPerSlot[0], reducedNumberOfNodesPerSlot[1],
reducedNumberOfNodesPerSlot[3], reducedNumberOfNodesPerSlot[1], reducedNumberOfNodesPerSlot[2],
reducedNumberOfNodesPerSlot[2], reducedNumberOfNodesPerSlot[3], reducedNumberOfNodesPerSlot[2],
reducedNumberOfNodesPerSlot[4]}; reducedNumberOfNodesPerSlot[4]};
// Generate an edge mesh wih all possible edges // Generate an edge mesh wih all possible edges
numberOfNodes = std::accumulate(numberOfNodesPerSlot.begin(), numberOfNodesPerSlot.end(), 0); numberOfNodes = std::accumulate(numberOfNodesPerSlot.begin(),
const size_t numberOfAllPossibleEdges = numberOfNodes * (numberOfNodes - 1) / 2; numberOfNodesPerSlot.end(), 0);
const size_t numberOfAllPossibleEdges =
numberOfNodes * (numberOfNodes - 1) / 2;
std::vector<vcg::Point2i> allPossibleEdges(numberOfAllPossibleEdges); std::vector<vcg::Point2i> allPossibleEdges(numberOfAllPossibleEdges);
const int& n = numberOfNodes; const int& n = numberOfNodes;
for (size_t edgeIndex = 0; edgeIndex < numberOfAllPossibleEdges; edgeIndex++) { for (size_t edgeIndex = 0; edgeIndex < numberOfAllPossibleEdges;
const int ni0 = n - 2 edgeIndex++) {
- std::floor(std::sqrt(-8 * edgeIndex + 4 * n * (n - 1) - 7) / 2.0 - 0.5); const int ni0 =
const int ni1 = edgeIndex + ni0 + 1 - n * (n - 1) / 2 + (n - ni0) * ((n - ni0) - 1) / 2; n - 2 -
std::floor(std::sqrt(-8 * edgeIndex + 4 * n * (n - 1) - 7) / 2.0 - 0.5);
const int ni1 =
edgeIndex + ni0 + 1 - n * (n - 1) / 2 + (n - ni0) * ((n - ni0) - 1) / 2;
allPossibleEdges[edgeIndex] = vcg::Point2i(ni0, ni1); allPossibleEdges[edgeIndex] = vcg::Point2i(ni0, ni1);
} }
PatternGeometry patternGeometryAllEdges; PatternGeometry patternGeometryAllEdges;
@ -88,13 +93,15 @@ void TopologyEnumerator::computeValidPatterns(const std::vector<size_t> &reduced
std::string elemID; std::string elemID;
if (numberOfNodesPerSlotIndex == 0 || numberOfNodesPerSlotIndex == 1) { if (numberOfNodesPerSlotIndex == 0 || numberOfNodesPerSlotIndex == 1) {
elemID = "v"; elemID = "v";
} else if (numberOfNodesPerSlotIndex == 2 || numberOfNodesPerSlotIndex == 3) { } else if (numberOfNodesPerSlotIndex == 2 ||
numberOfNodesPerSlotIndex == 3) {
elemID = "e"; elemID = "e";
} else { } else {
elemID = "c"; elemID = "c";
} }
setupString += std::to_string(reducedNumberOfNodesPerSlot[numberOfNodesPerSlotIndex]) setupString +=
+ elemID + "_"; std::to_string(reducedNumberOfNodesPerSlot[numberOfNodesPerSlotIndex]) +
elemID + "_";
} }
setupString += std::to_string(PatternGeometry().getFanSize()) + "fan"; setupString += std::to_string(PatternGeometry().getFanSize()) + "fan";
if (debugIsOn) { if (debugIsOn) {
@ -105,34 +112,39 @@ void TopologyEnumerator::computeValidPatterns(const std::vector<size_t> &reduced
std::filesystem::create_directory(resultsPath); std::filesystem::create_directory(resultsPath);
if (debugIsOn) { if (debugIsOn) {
patternGeometryAllEdges.save( patternGeometryAllEdges.save(std::filesystem::path(resultsPath)
std::filesystem::path(resultsPath).append("allPossibleEdges.ply").string()); .append("allPossibleEdges.ply")
.string());
} }
// statistics.numberOfPossibleEdges = numberOfAllPossibleEdges; // statistics.numberOfPossibleEdges = numberOfAllPossibleEdges;
std::vector<vcg::Point2i> validEdges = getValidEdges(numberOfNodesPerSlot, std::vector<vcg::Point2i> validEdges =
resultsPath, getValidEdges(numberOfNodesPerSlot, resultsPath, patternGeometryAllEdges,
patternGeometryAllEdges,
allPossibleEdges); allPossibleEdges);
PatternGeometry patternAllValidEdges; PatternGeometry patternAllValidEdges;
patternAllValidEdges.add(patternGeometryAllEdges.computeVertices(), validEdges); patternAllValidEdges.add(patternGeometryAllEdges.computeVertices(),
validEdges);
if (debugIsOn) { if (debugIsOn) {
// Export all valid edges in a ply // Export all valid edges in a ply
patternAllValidEdges.save( patternAllValidEdges.save(std::filesystem::path(resultsPath)
std::filesystem::path(resultsPath).append("allValidEdges.ply").string()); .append("allValidEdges.ply")
.string());
} }
// statistics.numberOfValidEdges = validEdges.size(); // statistics.numberOfValidEdges = validEdges.size();
// Find pairs of intersecting edges // Find pairs of intersecting edges
const std::unordered_map<size_t, std::unordered_set<size_t>> intersectingEdges const std::unordered_map<size_t, std::unordered_set<size_t>>
= patternAllValidEdges.getIntersectingEdges(statistics.numberOfIntersectingEdgePairs); intersectingEdges = patternAllValidEdges.getIntersectingEdges(
statistics.numberOfIntersectingEdgePairs);
if (debugIsOn) { if (debugIsOn) {
auto intersectingEdgesPath = std::filesystem::path(resultsPath) auto intersectingEdgesPath = std::filesystem::path(resultsPath)
.append("All_intersecting_edge_pairs"); .append("All_intersecting_edge_pairs");
std::filesystem::create_directory(intersectingEdgesPath); std::filesystem::create_directory(intersectingEdgesPath);
// Export intersecting pairs in ply files // Export intersecting pairs in ply files
for (auto mapIt = intersectingEdges.begin(); mapIt != intersectingEdges.end(); mapIt++) { for (auto mapIt = intersectingEdges.begin();
for (auto setIt = mapIt->second.begin(); setIt != mapIt->second.end(); setIt++) { mapIt != intersectingEdges.end(); mapIt++) {
for (auto setIt = mapIt->second.begin(); setIt != mapIt->second.end();
setIt++) {
PatternGeometry intersectingEdgePair; PatternGeometry intersectingEdgePair;
const size_t ei0 = mapIt->first; const size_t ei0 = mapIt->first;
const size_t ei1 = *setIt; const size_t ei1 = *setIt;
@ -145,15 +157,16 @@ void TopologyEnumerator::computeValidPatterns(const std::vector<size_t> &reduced
patternGeometryAllEdges.computeVertices()[validEdges[ei1][0]], patternGeometryAllEdges.computeVertices()[validEdges[ei1][0]],
patternGeometryAllEdges.computeVertices()[validEdges[ei1][1]]); patternGeometryAllEdges.computeVertices()[validEdges[ei1][1]]);
intersectingEdgePair.save(std::filesystem::path(intersectingEdgesPath) intersectingEdgePair.save(std::filesystem::path(intersectingEdgesPath)
.append(std::to_string(mapIt->first) + "_" .append(std::to_string(mapIt->first) +
+ std::to_string(*setIt) + ".ply") "_" + std::to_string(*setIt) +
".ply")
.string()); .string());
} }
} }
} }
const std::unordered_set<VertexIndex> interfaceNodes = patternGeometryAllEdges.getInterfaceNodes( const std::unordered_set<VertexIndex> interfaceNodes =
numberOfNodesPerSlot); patternGeometryAllEdges.getInterfaceNodes(numberOfNodesPerSlot);
// assert(validEdges.size() == allPossibleEdges.size() - // assert(validEdges.size() == allPossibleEdges.size() -
// coincideEdges.size() - // coincideEdges.size() -
@ -174,9 +187,10 @@ void TopologyEnumerator::computeValidPatterns(const std::vector<size_t> &reduced
// std::filesystem::path(resultsPath).append("patterns.patt")); // std::filesystem::path(resultsPath).append("patterns.patt"));
// } // }
if (numberOfDesiredEdges == -1) { if (numberOfDesiredEdges == -1) {
for (size_t numberOfEdges = 2; numberOfEdges <= validEdges.size(); numberOfEdges++) { for (size_t numberOfEdges = 2; numberOfEdges <= validEdges.size();
std::cout << "Computing " + setupString << " with " << numberOfEdges << " edges." numberOfEdges++) {
<< std::endl; std::cout << "Computing " + setupString << " with " << numberOfEdges
<< " edges." << std::endl;
auto perEdgeResultPath = std::filesystem::path(resultsPath) auto perEdgeResultPath = std::filesystem::path(resultsPath)
.append(std::to_string(numberOfEdges)); .append(std::to_string(numberOfEdges));
@ -189,19 +203,16 @@ void TopologyEnumerator::computeValidPatterns(const std::vector<size_t> &reduced
// } // }
} }
std::filesystem::create_directory(perEdgeResultPath); std::filesystem::create_directory(perEdgeResultPath);
computeValidPatterns(numberOfNodesPerSlot, computeValidPatterns(numberOfNodesPerSlot, numberOfEdges,
numberOfEdges,
perEdgeResultPath, perEdgeResultPath,
patternGeometryAllEdges.computeVertices(), patternGeometryAllEdges.computeVertices(),
intersectingEdges, intersectingEdges, validEdges, interfaceNodes);
validEdges,
interfaceNodes);
statistics.print(setupString, perEdgeResultPath); statistics.print(setupString, perEdgeResultPath);
statistics.reset(); statistics.reset();
} }
} else { } else {
std::cout << "Computing " + setupString << " with " << numberOfDesiredEdges << " edges." std::cout << "Computing " + setupString << " with " << numberOfDesiredEdges
<< std::endl; << " edges." << std::endl;
auto perEdgeResultPath = std::filesystem::path(resultsPath) auto perEdgeResultPath = std::filesystem::path(resultsPath)
.append(std::to_string(numberOfDesiredEdges)); .append(std::to_string(numberOfDesiredEdges));
@ -210,22 +221,19 @@ void TopologyEnumerator::computeValidPatterns(const std::vector<size_t> &reduced
std::filesystem::remove_all(perEdgeResultPath); std::filesystem::remove_all(perEdgeResultPath);
} }
std::filesystem::create_directory(perEdgeResultPath); std::filesystem::create_directory(perEdgeResultPath);
computeValidPatterns(numberOfNodesPerSlot, computeValidPatterns(numberOfNodesPerSlot, numberOfDesiredEdges,
numberOfDesiredEdges,
perEdgeResultPath, perEdgeResultPath,
patternGeometryAllEdges.computeVertices(), patternGeometryAllEdges.computeVertices(),
intersectingEdges, intersectingEdges, validEdges, interfaceNodes);
validEdges,
interfaceNodes);
statistics.print(setupString, perEdgeResultPath); statistics.print(setupString, perEdgeResultPath);
} }
} }
void TopologyEnumerator::computeEdgeNodes(const std::vector<size_t> &numberOfNodesPerSlot, void TopologyEnumerator::computeEdgeNodes(
const std::vector<size_t>& numberOfNodesPerSlot,
std::vector<size_t>& nodesEdge0, std::vector<size_t>& nodesEdge0,
std::vector<size_t>& nodesEdge1, std::vector<size_t>& nodesEdge1,
std::vector<size_t> &nodesEdge2) std::vector<size_t>& nodesEdge2) {
{
// Create vectors holding the node indices of each pattern node of each // Create vectors holding the node indices of each pattern node of each
// triangle edge // triangle edge
size_t nodeIndex = 0; size_t nodeIndex = 0;
@ -238,18 +246,21 @@ void TopologyEnumerator::computeEdgeNodes(const std::vector<size_t> &numberOfNod
nodesEdge2.push_back(nodeIndex++); nodesEdge2.push_back(nodeIndex++);
if (numberOfNodesPerSlot[3] != 0) { if (numberOfNodesPerSlot[3] != 0) {
for (size_t edgeNodeIndex = 0; edgeNodeIndex < numberOfNodesPerSlot[3]; edgeNodeIndex++) { for (size_t edgeNodeIndex = 0; edgeNodeIndex < numberOfNodesPerSlot[3];
edgeNodeIndex++) {
nodesEdge0.push_back(nodeIndex++); nodesEdge0.push_back(nodeIndex++);
} }
} }
if (numberOfNodesPerSlot[4] != 0) { if (numberOfNodesPerSlot[4] != 0) {
for (size_t edgeNodeIndex = 0; edgeNodeIndex < numberOfNodesPerSlot[4]; edgeNodeIndex++) { for (size_t edgeNodeIndex = 0; edgeNodeIndex < numberOfNodesPerSlot[4];
edgeNodeIndex++) {
nodesEdge1.push_back(nodeIndex++); nodesEdge1.push_back(nodeIndex++);
} }
} }
if (numberOfNodesPerSlot[5] != 0) { if (numberOfNodesPerSlot[5] != 0) {
for (size_t edgeNodeIndex = 0; edgeNodeIndex < numberOfNodesPerSlot[5]; edgeNodeIndex++) { for (size_t edgeNodeIndex = 0; edgeNodeIndex < numberOfNodesPerSlot[5];
edgeNodeIndex++) {
nodesEdge2.push_back(nodeIndex++); nodesEdge2.push_back(nodeIndex++);
} }
} }
@ -265,8 +276,7 @@ void TopologyEnumerator::computeEdgeNodes(const std::vector<size_t> &numberOfNod
} }
std::unordered_set<size_t> TopologyEnumerator::computeCoincideEdges( std::unordered_set<size_t> TopologyEnumerator::computeCoincideEdges(
const std::vector<size_t> &numberOfNodesPerSlot) const std::vector<size_t>& numberOfNodesPerSlot) {
{
/* /*
* A coincide edge is defined as an edge connection between two nodes that lay * A coincide edge is defined as an edge connection between two nodes that lay
* on a triangle edge and which have another node in between * on a triangle edge and which have another node in between
@ -279,12 +289,11 @@ std::unordered_set<size_t> TopologyEnumerator::computeCoincideEdges(
std::vector<size_t> coincideEdges0 = getCoincideEdges(nodesEdge0); std::vector<size_t> coincideEdges0 = getCoincideEdges(nodesEdge0);
std::vector<size_t> coincideEdges1 = getCoincideEdges(nodesEdge1); std::vector<size_t> coincideEdges1 = getCoincideEdges(nodesEdge1);
std::vector<size_t> coincideEdges2 = getCoincideEdges(nodesEdge2); std::vector<size_t> coincideEdges2 = getCoincideEdges(nodesEdge2);
std::unordered_set<size_t> coincideEdges{coincideEdges0.begin(), coincideEdges0.end()}; std::unordered_set<size_t> coincideEdges{coincideEdges0.begin(),
std::copy(coincideEdges1.begin(), coincideEdges0.end()};
coincideEdges1.end(), std::copy(coincideEdges1.begin(), coincideEdges1.end(),
std::inserter(coincideEdges, coincideEdges.end())); std::inserter(coincideEdges, coincideEdges.end()));
std::copy(coincideEdges2.begin(), std::copy(coincideEdges2.begin(), coincideEdges2.end(),
coincideEdges2.end(),
std::inserter(coincideEdges, coincideEdges.end())); std::inserter(coincideEdges, coincideEdges.end()));
if (numberOfNodesPerSlot[0] && numberOfNodesPerSlot[1]) { if (numberOfNodesPerSlot[0] && numberOfNodesPerSlot[1]) {
@ -300,8 +309,7 @@ std::unordered_set<size_t> TopologyEnumerator::computeCoincideEdges(
} }
std::unordered_set<size_t> TopologyEnumerator::computeDuplicateEdges( std::unordered_set<size_t> TopologyEnumerator::computeDuplicateEdges(
const std::vector<size_t> &numberOfNodesPerSlot) const std::vector<size_t>& numberOfNodesPerSlot) {
{
/* /*
* A duplicate edges are all edges the "right" edge since due to rotational * A duplicate edges are all edges the "right" edge since due to rotational
* symmetry "left" edge=="right" edge * symmetry "left" edge=="right" edge
@ -312,7 +320,8 @@ std::unordered_set<size_t> TopologyEnumerator::computeDuplicateEdges(
std::vector<size_t> nodesEdge2; // right edge std::vector<size_t> nodesEdge2; // right edge
computeEdgeNodes(numberOfNodesPerSlot, nodesEdge0, nodesEdge1, nodesEdge2); computeEdgeNodes(numberOfNodesPerSlot, nodesEdge0, nodesEdge1, nodesEdge2);
if (numberOfNodesPerSlot[5]) { if (numberOfNodesPerSlot[5]) {
for (size_t edge2NodeIndex = 0; edge2NodeIndex < nodesEdge2.size() - 1; edge2NodeIndex++) { for (size_t edge2NodeIndex = 0; edge2NodeIndex < nodesEdge2.size() - 1;
edge2NodeIndex++) {
const size_t nodeIndex = nodesEdge2[edge2NodeIndex]; const size_t nodeIndex = nodesEdge2[edge2NodeIndex];
const size_t nextNodeIndex = nodesEdge2[edge2NodeIndex + 1]; const size_t nextNodeIndex = nodesEdge2[edge2NodeIndex + 1];
duplicateEdges.insert(getEdgeIndex(nodeIndex, nextNodeIndex)); duplicateEdges.insert(getEdgeIndex(nodeIndex, nextNodeIndex));
@ -326,15 +335,17 @@ std::vector<vcg::Point2i> TopologyEnumerator::getValidEdges(
const std::vector<size_t>& numberOfNodesPerSlot, const std::vector<size_t>& numberOfNodesPerSlot,
const std::filesystem::path& resultsPath, const std::filesystem::path& resultsPath,
const PatternGeometry& patternGeometryAllEdges, const PatternGeometry& patternGeometryAllEdges,
const std::vector<vcg::Point2i> &allPossibleEdges) const std::vector<vcg::Point2i>& allPossibleEdges) {
{ std::unordered_set<size_t> coincideEdges =
std::unordered_set<size_t> coincideEdges = computeCoincideEdges(numberOfNodesPerSlot); computeCoincideEdges(numberOfNodesPerSlot);
// Export each coincide edge into a ply file // Export each coincide edge into a ply file
if (!coincideEdges.empty() && debugIsOn) { if (!coincideEdges.empty() && debugIsOn) {
auto coincideEdgesPath = std::filesystem::path(resultsPath).append("Coincide_edges"); auto coincideEdgesPath =
std::filesystem::path(resultsPath).append("Coincide_edges");
std::filesystem::create_directories(coincideEdgesPath); std::filesystem::create_directories(coincideEdgesPath);
for (auto coincideEdgeIndex : coincideEdges) { for (auto coincideEdgeIndex : coincideEdges) {
PatternGeometry::EdgeType e = patternGeometryAllEdges.edge[coincideEdgeIndex]; PatternGeometry::EdgeType e =
patternGeometryAllEdges.edge[coincideEdgeIndex];
PatternGeometry singleEdgeMesh; PatternGeometry singleEdgeMesh;
vcg::Point3d p0 = e.cP(0); vcg::Point3d p0 = e.cP(0);
vcg::Point3d p1 = e.cP(1); vcg::Point3d p1 = e.cP(1);
@ -345,34 +356,40 @@ std::vector<vcg::Point2i> TopologyEnumerator::getValidEdges(
singleEdgeMesh.add(std::vector<vcg::Point2i>{vcg::Point2i{0, 1}}); singleEdgeMesh.add(std::vector<vcg::Point2i>{vcg::Point2i{0, 1}});
singleEdgeMesh.save(std::filesystem::path(coincideEdgesPath) singleEdgeMesh.save(std::filesystem::path(coincideEdgesPath)
.append(std::to_string(coincideEdgeIndex)) .append(std::to_string(coincideEdgeIndex))
.string() .string() +
+ ".ply"); ".ply");
} }
} }
statistics.numberOfCoincideEdges = coincideEdges.size(); statistics.numberOfCoincideEdges = coincideEdges.size();
// Compute duplicate edges // Compute duplicate edges
std::unordered_set<size_t> duplicateEdges = computeDuplicateEdges(numberOfNodesPerSlot); std::unordered_set<size_t> duplicateEdges =
computeDuplicateEdges(numberOfNodesPerSlot);
if (!duplicateEdges.empty() && debugIsOn) { if (!duplicateEdges.empty() && debugIsOn) {
// Export duplicate edges in a single ply file // Export duplicate edges in a single ply file
auto duplicateEdgesPath = std::filesystem::path(resultsPath).append("duplicate"); auto duplicateEdgesPath =
std::filesystem::path(resultsPath).append("duplicate");
std::filesystem::create_directory(duplicateEdgesPath); std::filesystem::create_directory(duplicateEdgesPath);
PatternGeometry patternDuplicateEdges; PatternGeometry patternDuplicateEdges;
for (auto duplicateEdgeIndex : duplicateEdges) { for (auto duplicateEdgeIndex : duplicateEdges) {
PatternGeometry::EdgeType e = patternGeometryAllEdges.edge[duplicateEdgeIndex]; PatternGeometry::EdgeType e =
patternGeometryAllEdges.edge[duplicateEdgeIndex];
vcg::Point3d p0 = e.cP(0); vcg::Point3d p0 = e.cP(0);
vcg::Point3d p1 = e.cP(1); vcg::Point3d p1 = e.cP(1);
vcg::tri::Allocator<PatternGeometry>::AddEdge(patternDuplicateEdges, p0, p1); vcg::tri::Allocator<PatternGeometry>::AddEdge(patternDuplicateEdges, p0,
p1);
} }
patternDuplicateEdges.save( patternDuplicateEdges.save(std::filesystem::path(duplicateEdgesPath)
std::filesystem::path(duplicateEdgesPath).append("duplicateEdges.ply").string()); .append("duplicateEdges.ply")
.string());
} }
statistics.numberOfDuplicateEdges = duplicateEdges.size(); statistics.numberOfDuplicateEdges = duplicateEdges.size();
// Create the set of all possible edges without coincide and duplicate edges // Create the set of all possible edges without coincide and duplicate edges
std::vector<vcg::Point2i> validEdges; std::vector<vcg::Point2i> validEdges;
for (size_t edgeIndex = 0; edgeIndex < allPossibleEdges.size(); edgeIndex++) { for (size_t edgeIndex = 0; edgeIndex < allPossibleEdges.size(); edgeIndex++) {
if (coincideEdges.count(edgeIndex) == 0 && duplicateEdges.count(edgeIndex) == 0) { if (coincideEdges.count(edgeIndex) == 0 &&
duplicateEdges.count(edgeIndex) == 0) {
validEdges.push_back(allPossibleEdges[edgeIndex]); validEdges.push_back(allPossibleEdges[edgeIndex]);
} }
} }
@ -382,15 +399,18 @@ std::vector<vcg::Point2i> TopologyEnumerator::getValidEdges(
void TopologyEnumerator::exportPattern(const std::filesystem::path& saveToPath, void TopologyEnumerator::exportPattern(const std::filesystem::path& saveToPath,
PatternGeometry& patternGeometry, PatternGeometry& patternGeometry,
const bool saveTilledPattern) const const bool saveTilledPattern) const {
{
const std::string patternName = patternGeometry.getLabel(); const std::string patternName = patternGeometry.getLabel();
std::filesystem::create_directory(saveToPath); std::filesystem::create_directory(saveToPath);
patternGeometry.save(std::filesystem::path(saveToPath).append(patternName).string() + ".ply"); patternGeometry.save(
std::filesystem::path(saveToPath).append(patternName).string() + ".ply");
if (saveTilledPattern) { if (saveTilledPattern) {
PatternGeometry tiledPatternGeometry = PatternGeometry::createTile(patternGeometry); PatternGeometry tiledPatternGeometry =
tiledPatternGeometry.save( PatternGeometry::createTile(patternGeometry);
std::filesystem::path(saveToPath).append(patternName + "_tiled").string() + ".ply"); tiledPatternGeometry.save(std::filesystem::path(saveToPath)
.append(patternName + "_tiled")
.string() +
".ply");
} }
} }
@ -399,10 +419,10 @@ void TopologyEnumerator::computeValidPatterns(
const size_t& numberOfDesiredEdges, const size_t& numberOfDesiredEdges,
const std::filesystem::path& resultsPath, const std::filesystem::path& resultsPath,
const std::vector<vcg::Point3d>& allVertices, const std::vector<vcg::Point3d>& allVertices,
const std::unordered_map<size_t, std::unordered_set<size_t>> &intersectingEdges, const std::unordered_map<size_t, std::unordered_set<size_t>>&
intersectingEdges,
const std::vector<vcg::Point2i>& validEdges, const std::vector<vcg::Point2i>& validEdges,
const std::unordered_set<VertexIndex> &interfaceNodes) const std::unordered_set<VertexIndex>& interfaceNodes) {
{
assert(numberOfNodesPerSlot.size() == 7); assert(numberOfNodesPerSlot.size() == 7);
// Iterate over all patterns which have numberOfDesiredEdges edges from // Iterate over all patterns which have numberOfDesiredEdges edges from
// from the validEdges Identify patterns that contain dangling edges // from the validEdges Identify patterns that contain dangling edges
@ -414,27 +434,33 @@ void TopologyEnumerator::computeValidPatterns(
assert(enoughValidEdgesExist); assert(enoughValidEdgesExist);
// Create pattern result paths // Create pattern result paths
const auto validPatternsPath = std::filesystem::path(resultsPath).append("Valid"); const auto validPatternsPath =
const bool validPathCreatedSuccesfully = std::filesystem::create_directories(validPatternsPath); std::filesystem::path(resultsPath).append("Valid");
assert(validPathCreatedSuccesfully && std::filesystem::exists(validPatternsPath)); const bool validPathCreatedSuccesfully =
std::filesystem::create_directories(validPatternsPath);
assert(validPathCreatedSuccesfully &&
std::filesystem::exists(validPatternsPath));
// std::ofstream validPatternsFileStream; // std::ofstream validPatternsFileStream;
// validPatternsFileStream.open( // validPatternsFileStream.open(
// validPatternsPath.append("patterns.patt").string()); // validPatternsPath.append("patterns.patt").string());
const std::string compressedPatternsFilePath const std::string compressedPatternsFilePath =
= std::filesystem::path(validPatternsPath).append("patterns.patt").string(); std::filesystem::path(validPatternsPath).append("patterns.patt").string();
PatternIO::PatternSet patternSet; PatternIO::PatternSet patternSet;
patternSet.nodes = allVertices; patternSet.nodes = allVertices;
const int patternSetBufferSize = 10000; const int patternSetBufferSize = 10000;
const size_t numberOfPatterns = PatternGeometry::binomialCoefficient(validEdges.size(), const size_t numberOfPatterns = PatternGeometry::binomialCoefficient(
numberOfDesiredEdges); validEdges.size(), numberOfDesiredEdges);
statistics.numberOfPatterns = numberOfPatterns; statistics.numberOfPatterns = numberOfPatterns;
// Initialize pattern binary representation // Initialize pattern binary representation
std::string patternBinaryRepresentation; std::string patternBinaryRepresentation;
patternBinaryRepresentation = std::string(numberOfDesiredEdges, '1'); patternBinaryRepresentation = std::string(numberOfDesiredEdges, '1');
patternBinaryRepresentation += std::string(validEdges.size() - numberOfDesiredEdges, '0'); patternBinaryRepresentation +=
std::sort(patternBinaryRepresentation.begin(), patternBinaryRepresentation.end()); std::string(validEdges.size() - numberOfDesiredEdges, '0');
std::sort(patternBinaryRepresentation.begin(),
patternBinaryRepresentation.end());
/*TODO: Performance could be improved by changing the patternGeometry with /*TODO: Performance could be improved by changing the patternGeometry with
* respect to the previous one. Maybe I could xor the binaryRepresentation * respect to the previous one. Maybe I could xor the binaryRepresentation
* to the previous one.*/ * to the previous one.*/
@ -445,8 +471,8 @@ void TopologyEnumerator::computeValidPatterns(
constexpr bool saveCompressedFormat = false; constexpr bool saveCompressedFormat = false;
do { do {
patternIndex++; patternIndex++;
const std::string patternName = std::to_string(numberOfDesiredEdges) + "_" const std::string patternName = std::to_string(numberOfDesiredEdges) + "_" +
+ std::to_string(patternIndex); std::to_string(patternIndex);
// std::cout << "Pattern name:" + patternBinaryRepresentation << // std::cout << "Pattern name:" + patternBinaryRepresentation <<
// std::endl; isValidPattern(patternBinaryRepresentation, validEdges, // std::endl; isValidPattern(patternBinaryRepresentation, validEdges,
// numberOfDesiredEdges); // numberOfDesiredEdges);
@ -454,7 +480,8 @@ void TopologyEnumerator::computeValidPatterns(
// Compute the pattern edges from the binary representation // Compute the pattern edges from the binary representation
std::vector<vcg::Point2i> patternEdges(numberOfDesiredEdges); std::vector<vcg::Point2i> patternEdges(numberOfDesiredEdges);
size_t patternEdgeIndex = 0; size_t patternEdgeIndex = 0;
for (size_t validEdgeIndex = 0; validEdgeIndex < patternBinaryRepresentation.size(); for (size_t validEdgeIndex = 0;
validEdgeIndex < patternBinaryRepresentation.size();
validEdgeIndex++) { validEdgeIndex++) {
if (patternBinaryRepresentation[validEdgeIndex] == '1') { if (patternBinaryRepresentation[validEdgeIndex] == '1') {
assert(patternEdgeIndex < numberOfDesiredEdges); assert(patternEdgeIndex < numberOfDesiredEdges);
@ -462,96 +489,124 @@ void TopologyEnumerator::computeValidPatterns(
} }
} }
// DEBUG: Export only part of the pattern set
// if (statistics.numberOfValidPatterns > 1e4) {
// break;
// }
// const bool patternContainsCentroid =
// std::find_if(patternEdges.begin(), patternEdges.end(),
// [](const vcg::Point2i& edge) {
// if (edge[0] == 0 || edge[1] == 0) {
// return true;
// }
// return false;
// }) != patternEdges.end();
// if (!patternContainsCentroid) {
// continue;
// }
PatternGeometry patternGeometry; PatternGeometry patternGeometry;
patternGeometry.add(allVertices, patternEdges); patternGeometry.add(allVertices, patternEdges);
patternGeometry.setLabel(patternName); patternGeometry.setLabel(patternName);
#ifdef POLYSCOPE_DEFINED #ifdef POLYSCOPE_DEFINED
// 1st example // 1st example
// const bool shouldBreak = patternBinaryRepresentation == "00100000100100000"; //398 // const bool shouldBreak =
// const bool shouldBreak = patternBinaryRepresentation == "10000010101110110";//13036 // patternIndex == 1970494; // 398 const bool shouldBreak =
// const bool shouldBreak = patternBinaryRepresentation == "00010111000010100"; //2481 // patternBinaryRepresentation == "10000010101110110";//13036 const
// const bool shouldBreak = patternBinaryRepresentation == "10000101100110010"; //12116 // bool shouldBreak = patternBinaryRepresentation ==
// const bool shouldBreak = patternBinaryRepresentation == "10010111000000110"; //13915 // "00010111000010100"; //2481 const bool shouldBreak =
// patternBinaryRepresentation == "10000101100110010"; //12116 const
// bool shouldBreak = patternBinaryRepresentation ==
// "10010111000000110"; //13915
// 2nd example // 2nd example
// const bool shouldBreak = patternBinaryRepresentation == "00001011100010011"; //7_1203 // const bool shouldBreak = patternBinaryRepresentation ==
// const bool shouldBreak = patternBinaryRepresentation == "00110001100100111"; //4865 // "00001011100010011"; //7_1203 const bool shouldBreak =
// const bool shouldBreak = patternBinaryRepresentation == "00010000101000110"; //1380 // patternBinaryRepresentation == "00110001100100111"; //4865 const
// const bool shouldBreak = patternBinaryRepresentation == "00000010100010111"; //268 // bool shouldBreak = patternBinaryRepresentation ==
// "00010000101000110"; //1380 const bool shouldBreak =
// patternBinaryRepresentation == "00000010100010111"; //268
// 3rd // 3rd
// const bool shouldBreak = patternBinaryRepresentation == "10011011100000010"; //14272 // const bool shouldBreak = patternBinaryRepresentation ==
// const bool shouldBreak = patternBinaryRepresentation == "10000111100110110"; //11877 // "10011011100000010"; //14272 const bool shouldBreak =
// const bool shouldBreak = patternBinaryRepresentation == "00001011100010011"; //1203 // patternBinaryRepresentation == "10000111100110110"; //11877 const
// const bool shouldBreak = patternBinaryRepresentation == "00010101000110000"; //12117 // bool shouldBreak = patternBinaryRepresentation ==
// "00001011100010011"; //1203 const bool shouldBreak =
// patternBinaryRepresentation == "00010101000110000"; //12117
// const bool shouldBreak = patternBinaryRepresentation == "10000101100110100"; //12117 // const bool shouldBreak = patternBinaryRepresentation ==
// "10000101100110100"; //12117
// std::thread drawingThread([&]() {
// if (shouldBreak) { // if (shouldBreak) {
// patternGeometry.registerForDrawing(); // patternGeometry.registerForDrawing();
// polyscope::show(); // polyscope::show();
// patternGeometry.unregister(); // patternGeometry.unregister();
// } // }
// });
#endif #endif
// Check if pattern contains intersecting edges // Check if pattern contains intersecting edges
const bool isInterfaceConnected = patternGeometry.isInterfaceConnected(interfaceNodes); const bool isInterfaceConnected =
patternGeometry.isInterfaceConnected(interfaceNodes);
// Export the tiled ply file if it contains intersecting edges // Export the tiled ply file if it contains intersecting edges
if (!isInterfaceConnected) { if (!isInterfaceConnected) {
// create the tiled geometry of the pattern // create the tiled geometry of the pattern
statistics.numberOfPatternViolatingInterfaceEnforcement++; statistics.numberOfPatternViolatingInterfaceEnforcement++;
if (debugIsOn) { if (debugIsOn) {
if (savePlyFiles) { if (savePlyFiles) {
exportPattern(std::filesystem::path(resultsPath).append("InterfaceEnforcement"), exportPattern(
patternGeometry, std::filesystem::path(resultsPath).append("InterfaceEnforcement"),
exportTilledPattern); patternGeometry, exportTilledPattern);
}
} else {
continue; // should be uncommented in order to improve performance
}
}
// Check if pattern contains intersecting edges
const bool patternContainsIntersectingEdges
= patternGeometry.hasIntersectingEdges(patternBinaryRepresentation, intersectingEdges);
// Export the tiled ply file if it contains intersecting edges
if (patternContainsIntersectingEdges) {
// create the tiled geometry of the pattern
statistics.numberOfPatternsWithIntersectingEdges++;
if (debugIsOn) {
if (savePlyFiles) {
exportPattern(std::filesystem::path(resultsPath).append("Intersecting"),
patternGeometry,
exportTilledPattern);
}
} else {
continue; // should be uncommented in order to improve performance
}
}
// const bool shouldBreak = numberOfDesiredEdges == 4 && patternIndex == 53;
const bool tiledPatternHasEdgesWithAngleSmallerThanThreshold
= patternGeometry.hasAngleSmallerThanThreshold(numberOfNodesPerSlot, 15);
if (tiledPatternHasEdgesWithAngleSmallerThanThreshold) {
statistics.numberOfPatternsViolatingAngleThreshold++;
if (debugIsOn /*|| savePlyFiles*/) {
if (savePlyFiles) {
exportPattern(std::filesystem::path(resultsPath)
.append("ExceedingAngleThreshold"),
patternGeometry,
exportTilledPattern);
} }
} else { } else {
continue; continue;
} }
} }
const bool tiledPatternHasNodeWithValenceGreaterThanDesired // Check if pattern contains intersecting edges
= patternGeometry.hasValenceGreaterThan(numberOfNodesPerSlot, 6); const bool patternContainsIntersectingEdges =
patternGeometry.hasIntersectingEdges(patternBinaryRepresentation,
intersectingEdges);
// Export the tiled ply file if it contains intersecting edges
if (patternContainsIntersectingEdges) {
// create the tiled geometry of the pattern
statistics.numberOfPatternsWithIntersectingEdges++;
if (debugIsOn) {
if (savePlyFiles) {
exportPattern(
std::filesystem::path(resultsPath).append("Intersecting"),
patternGeometry, exportTilledPattern);
}
} else {
continue;
}
}
// const bool shouldBreak = numberOfDesiredEdges == 4 && patternIndex
// == 53;
const bool tiledPatternHasEdgesWithAngleSmallerThanThreshold =
patternGeometry.hasAngleSmallerThanThreshold(numberOfNodesPerSlot, 15);
if (tiledPatternHasEdgesWithAngleSmallerThanThreshold) {
statistics.numberOfPatternsViolatingAngleThreshold++;
if (debugIsOn /*|| savePlyFiles*/) {
if (savePlyFiles) {
exportPattern(std::filesystem::path(resultsPath)
.append("ExceedingAngleThreshold"),
patternGeometry, exportTilledPattern);
}
} else {
continue;
}
}
const bool tiledPatternHasNodeWithValenceGreaterThanDesired =
patternGeometry.hasValenceGreaterThan(numberOfNodesPerSlot, 6);
if (tiledPatternHasNodeWithValenceGreaterThanDesired) { if (tiledPatternHasNodeWithValenceGreaterThanDesired) {
statistics.numberOfPatternsViolatingValenceThreshold++; statistics.numberOfPatternsViolatingValenceThreshold++;
if (debugIsOn) { if (debugIsOn) {
if (savePlyFiles) { if (savePlyFiles) {
auto highValencePath = std::filesystem::path(resultsPath) auto highValencePath =
.append("HighValencePatterns"); std::filesystem::path(resultsPath).append("HighValencePatterns");
exportPattern(highValencePath, patternGeometry, exportTilledPattern); exportPattern(highValencePath, patternGeometry, exportTilledPattern);
} }
} else { } else {
@ -563,35 +618,42 @@ void TopologyEnumerator::computeValidPatterns(
const bool tiledPatternHasDanglingEdges = patternGeometry.hasDanglingEdges( const bool tiledPatternHasDanglingEdges = patternGeometry.hasDanglingEdges(
numberOfNodesPerSlot); // marks the nodes with valence>=1 numberOfNodesPerSlot); // marks the nodes with valence>=1
// Create the tiled geometry of the pattern // Create the tiled geometry of the pattern
const bool hasFloatingComponents = !patternGeometry.isFullyConnectedWhenFanned(); const bool hasFloatingComponents =
!patternGeometry.isFullyConnectedWhenFanned();
PatternGeometry fanPatternGeometry = PatternGeometry::createFan(patternGeometry); PatternGeometry fanPatternGeometry =
PatternGeometry::createFan(patternGeometry);
const int interfaceNodeVi = 3; const int interfaceNodeVi = 3;
std::vector<PatternGeometry::EdgeType*> connectedEdges; std::vector<PatternGeometry::EdgeType*> connectedEdges;
vcg::edge::VEStarVE(&fanPatternGeometry.vert[interfaceNodeVi], connectedEdges); vcg::edge::VEStarVE(&fanPatternGeometry.vert[interfaceNodeVi],
connectedEdges);
if (!connectedEdges.empty()) { if (!connectedEdges.empty()) {
for (int i = 1; i < 6; i++) { for (int i = 1; i < 6; i++) {
vcg::tri::Allocator<PatternGeometry>::AddEdge(fanPatternGeometry, vcg::tri::Allocator<PatternGeometry>::AddEdge(
interfaceNodeVi fanPatternGeometry,
+ (i - 1) * patternGeometry.VN(), interfaceNodeVi + (i - 1) * patternGeometry.VN(),
interfaceNodeVi interfaceNodeVi + i * patternGeometry.VN());
+ i * patternGeometry.VN());
} }
} }
vcg::tri::Clean<PatternGeometry>::MergeCloseVertex(fanPatternGeometry, 0.0000005); vcg::tri::Clean<PatternGeometry>::MergeCloseVertex(fanPatternGeometry,
vcg::tri::Allocator<PatternGeometry>::CompactEveryVector(fanPatternGeometry); 0.0000005);
vcg::tri::Allocator<PatternGeometry>::CompactEveryVector(
fanPatternGeometry);
vcg::tri::UpdateTopology<PatternGeometry>::VertexEdge(fanPatternGeometry); vcg::tri::UpdateTopology<PatternGeometry>::VertexEdge(fanPatternGeometry);
vcg::tri::UpdateTopology<PatternGeometry>::EdgeEdge(fanPatternGeometry); vcg::tri::UpdateTopology<PatternGeometry>::EdgeEdge(fanPatternGeometry);
// for (PatternGeometry::VertexType &v : tilledPatternGeometry.vert) { // for (PatternGeometry::VertexType &v : tilledPatternGeometry.vert)
// {
// std::vector<PatternGeometry::EdgeType *> connectedEdges; // std::vector<PatternGeometry::EdgeType *> connectedEdges;
// vcg::edge::VEStarVE(&v, connectedEdges); // vcg::edge::VEStarVE(&v, connectedEdges);
// if (connectedEdges.size() == 1) { // if (connectedEdges.size() == 1) {
// vcg::tri::Allocator<PatternGeometry>::DeleteVertex(tilledPatternGeometry, v); // vcg::tri::Allocator<PatternGeometry>::DeleteVertex(tilledPatternGeometry,
// v);
// vcg::tri::Allocator<PatternGeometry>::DeleteEdge(tilledPatternGeometry, // vcg::tri::Allocator<PatternGeometry>::DeleteEdge(tilledPatternGeometry,
// *connectedEdges[0]); // *connectedEdges[0]);
// } // }
// } // }
// // vcg::tri::Allocator<PatternGeometry>::CompactEveryVector(tilledPatternGeometry); // //
// vcg::tri::Allocator<PatternGeometry>::CompactEveryVector(tilledPatternGeometry);
// fanPatternGeometry.updateEigenEdgeAndVertices(); // fanPatternGeometry.updateEigenEdgeAndVertices();
BoostGraph fanPatternGraph(fanPatternGeometry.VN()); BoostGraph fanPatternGraph(fanPatternGeometry.VN());
@ -608,21 +670,28 @@ void TopologyEnumerator::computeValidPatterns(
// std::cout << std::endl; // std::cout << std::endl;
std::vector<vertex_t> articulationPoints; std::vector<vertex_t> articulationPoints;
boost::articulation_points(fanPatternGraph, std::back_inserter(articulationPoints)); boost::articulation_points(fanPatternGraph,
std::back_inserter(articulationPoints));
const bool hasArticulationPoints = !articulationPoints.empty(); const bool hasArticulationPoints = !articulationPoints.empty();
// if (!hasArticulationPoints && tiledPatternHasDanglingEdges) { // if (!hasArticulationPoints && tiledPatternHasDanglingEdges) {
// PatternGeometry tilledPatternGeometry = PatternGeometry::createTile(patternGeometry); // PatternGeometry tilledPatternGeometry =
// PatternGeometry::createTile(patternGeometry);
// tilledPatternGeometry.updateEigenEdgeAndVertices(); // tilledPatternGeometry.updateEigenEdgeAndVertices();
// tilledPatternGeometry.registerForDrawing(); // tilledPatternGeometry.registerForDrawing();
// // ->addNodeColorQuantity("de_noAp_tilled", fanVertexColors) // // ->addNodeColorQuantity("de_noAp_tilled",
// fanVertexColors)
// // ->setEnabled(true); // // ->setEnabled(true);
// polyscope::show(); // polyscope::show();
// tilledPatternGeometry.unregister(); // tilledPatternGeometry.unregister();
// } // }
// if (hasArticulationPoints && !tiledPatternHasDanglingEdges/*&& !patternContainsIntersectingEdges // if (hasArticulationPoints && !tiledPatternHasDanglingEdges/*&&
// !patternContainsIntersectingEdges
// && !hasFloatingComponents // && !hasFloatingComponents
// && !tiledPatternHasNodeWithValenceGreaterThanDesired // &&
// && !tiledPatternHasEdgesWithAngleSmallerThanThreshold*/) { // !tiledPatternHasNodeWithValenceGreaterThanDesired
// &&
// !tiledPatternHasEdgesWithAngleSmallerThanThreshold*/)
// {
// for (PatternGeometry::VertexType &v : patternGeometry.vert) { // for (PatternGeometry::VertexType &v : patternGeometry.vert) {
// v.C() = vcg::Color4b::Yellow; // v.C() = vcg::Color4b::Yellow;
// } // }
@ -632,15 +701,20 @@ void TopologyEnumerator::computeValidPatterns(
// continue; // continue;
// } // }
// // std::cout << articulationPointVi << " "; // // std::cout << articulationPointVi << " ";
// patternGeometry.vert[articulationPointVi].C() = vcg::Color4b::Red; // patternGeometry.vert[articulationPointVi].C() =
// vcg::Color4b::Red;
// } // }
// PatternGeometry tilledPatternGeometry = PatternGeometry::createTile(patternGeometry); // PatternGeometry tilledPatternGeometry =
// PatternGeometry::createTile(patternGeometry);
// // std::cout << std::endl; // // std::cout << std::endl;
// std::vector<glm::vec3> fanVertexColors(tilledPatternGeometry.VN(), glm::vec3(0, 0, 1)); // std::vector<glm::vec3>
// for (const PatternGeometry::VertexType &v : tilledPatternGeometry.vert) { // fanVertexColors(tilledPatternGeometry.VN(), glm::vec3(0, 0,
// const auto vColor = glm::vec3(v.cC()[0] / 255, v.cC()[1] / 255, v.cC()[2] / 255); // 1)); for (const PatternGeometry::VertexType &v :
// const auto vi = tilledPatternGeometry.getIndex(v); // tilledPatternGeometry.vert) {
// fanVertexColors[vi] = vColor; // const auto vColor = glm::vec3(v.cC()[0] / 255, v.cC()[1] /
// 255, v.cC()[2] / 255); const auto vi =
// tilledPatternGeometry.getIndex(v); fanVertexColors[vi] =
// vColor;
// } // }
// tilledPatternGeometry.updateEigenEdgeAndVertices(); // tilledPatternGeometry.updateEigenEdgeAndVertices();
// tilledPatternGeometry.registerForDrawing() // tilledPatternGeometry.registerForDrawing()
@ -657,8 +731,10 @@ void TopologyEnumerator::computeValidPatterns(
statistics.numberOfPatternsWithADanglingEdgeOrNode++; statistics.numberOfPatternsWithADanglingEdgeOrNode++;
if (debugIsOn) { if (debugIsOn) {
if (savePlyFiles) { if (savePlyFiles) {
auto danglingEdgesPath = std::filesystem::path(resultsPath).append("Dangling"); auto danglingEdgesPath =
exportPattern(danglingEdgesPath, patternGeometry, exportTilledPattern); std::filesystem::path(resultsPath).append("Dangling");
exportPattern(danglingEdgesPath, patternGeometry,
exportTilledPattern);
} }
} else { } else {
continue; continue;
@ -669,22 +745,23 @@ void TopologyEnumerator::computeValidPatterns(
statistics.numberOfPatternsWithMoreThanASingleCC++; statistics.numberOfPatternsWithMoreThanASingleCC++;
if (debugIsOn) { if (debugIsOn) {
if (savePlyFiles) { if (savePlyFiles) {
auto moreThanOneCCPath = std::filesystem::path(resultsPath) auto moreThanOneCCPath =
.append("MoreThanOneCC"); std::filesystem::path(resultsPath).append("MoreThanOneCC");
std::filesystem::create_directory(moreThanOneCCPath); std::filesystem::create_directory(moreThanOneCCPath);
patternGeometry.save( patternGeometry.save(std::filesystem::path(moreThanOneCCPath)
std::filesystem::path(moreThanOneCCPath).append(patternName).string() .append(patternName)
+ ".ply"); .string() +
".ply");
PatternGeometry tiledPatternGeometry = PatternGeometry::createTile( PatternGeometry tiledPatternGeometry = PatternGeometry::createTile(
patternGeometry); // the marked nodes of hasDanglingEdges are patternGeometry); // the marked nodes of hasDanglingEdges are
std::vector<std::pair<int, PatternGeometry::EdgePointer>> eCC; std::vector<std::pair<int, PatternGeometry::EdgePointer>> eCC;
vcg::tri::Clean<PatternGeometry>::edgeMeshConnectedComponents(tiledPatternGeometry, vcg::tri::Clean<PatternGeometry>::edgeMeshConnectedComponents(
eCC); tiledPatternGeometry, eCC);
vcg::tri::UpdateFlags<PatternGeometry>::EdgeClear(tiledPatternGeometry); vcg::tri::UpdateFlags<PatternGeometry>::EdgeClear(
tiledPatternGeometry);
const size_t numberOfCC_edgeBased = eCC.size(); const size_t numberOfCC_edgeBased = eCC.size();
std::sort(eCC.begin(), std::sort(eCC.begin(), eCC.end(),
eCC.end(),
[](const std::pair<int, PatternGeometry::EdgePointer>& a, [](const std::pair<int, PatternGeometry::EdgePointer>& a,
const std::pair<int, PatternGeometry::EdgePointer>& b) { const std::pair<int, PatternGeometry::EdgePointer>& b) {
return a.first > b.first; return a.first > b.first;
@ -706,12 +783,10 @@ void TopologyEnumerator::computeValidPatterns(
stack.push(vei.E()); stack.push(vei.E());
tiledPatternGeometry tiledPatternGeometry
.vert[tiledPatternGeometry.getIndex(vei.V1())] .vert[tiledPatternGeometry.getIndex(vei.V1())]
.C() .C() = vcg::Color4b::Blue;
= vcg::Color4b::Blue;
tiledPatternGeometry tiledPatternGeometry
.vert[tiledPatternGeometry.getIndex(vei.V0())] .vert[tiledPatternGeometry.getIndex(vei.V0())]
.C() .C() = vcg::Color4b::Blue;
= vcg::Color4b::Blue;
colorsRegistered++; colorsRegistered++;
} }
++vei; ++vei;
@ -724,8 +799,8 @@ void TopologyEnumerator::computeValidPatterns(
if (exportTilledPattern) { if (exportTilledPattern) {
tiledPatternGeometry.save(std::filesystem::path(moreThanOneCCPath) tiledPatternGeometry.save(std::filesystem::path(moreThanOneCCPath)
.append(patternName + "_tiled") .append(patternName + "_tiled")
.string() .string() +
+ ".ply"); ".ply");
} }
} }
} else { } else {
@ -737,35 +812,40 @@ void TopologyEnumerator::computeValidPatterns(
statistics.numberOfPatternsWithArticulationPoints++; statistics.numberOfPatternsWithArticulationPoints++;
if (debugIsOn) { if (debugIsOn) {
if (savePlyFiles) { if (savePlyFiles) {
auto articulationPointsPath = std::filesystem::path(resultsPath) auto articulationPointsPath =
.append("ArticulationPoints"); std::filesystem::path(resultsPath).append("ArticulationPoints");
exportPattern(articulationPointsPath, patternGeometry, exportTilledPattern); exportPattern(articulationPointsPath, patternGeometry,
exportTilledPattern);
} }
} else { } else {
continue; continue;
} }
} }
const bool isValidPattern = !patternContainsIntersectingEdges const bool isValidPattern =
&& isInterfaceConnected !patternContainsIntersectingEdges &&
isInterfaceConnected
/*&& !tiledPatternHasDanglingEdges*/ /*&& !tiledPatternHasDanglingEdges*/
&& !hasFloatingComponents && !hasArticulationPoints && !hasFloatingComponents && !hasArticulationPoints &&
&& !tiledPatternHasNodeWithValenceGreaterThanDesired !tiledPatternHasNodeWithValenceGreaterThanDesired &&
&& !tiledPatternHasEdgesWithAngleSmallerThanThreshold; !tiledPatternHasEdgesWithAngleSmallerThanThreshold;
// if (!hasArticulationPoints && !patternContainsIntersectingEdges // if (!hasArticulationPoints && !patternContainsIntersectingEdges
// && !tiledPatternHasDanglingEdges && !hasFloatingComponents // && !tiledPatternHasDanglingEdges && !hasFloatingComponents
// && !tiledPatternHasNodeWithValenceGreaterThanDesired // && !tiledPatternHasNodeWithValenceGreaterThanDesired
// && tiledPatternHasEdgesWithAngleSmallerThanThreshold && numberOfDesiredEdges > 4) { // && tiledPatternHasEdgesWithAngleSmallerThanThreshold &&
// std::cout << "Pattern found:" << patternName << std::endl; // numberOfDesiredEdges > 4) { std::cout << "Pattern found:" <<
// patternName << std::endl;
// patternGeometry.registerForDrawing(); // patternGeometry.registerForDrawing();
// polyscope::show(); // polyscope::show();
// patternGeometry.unregister(); // patternGeometry.unregister();
// } // }
if (isValidPattern) { if (isValidPattern) {
// if(patternName=='2055'){ // if(patternName=='2055'){
// PatternGeometry tiledPatternGeometry = PatternGeometry::createTile( // PatternGeometry tiledPatternGeometry =
// patternGeometry); // the marked nodes of hasDanglingEdges are // PatternGeometry::createTile(
// tiledPatternGeometry.registerForDrawing(std::array<double, 3>{0, 0, 1}); // patternGeometry); // the marked nodes of
// hasDanglingEdges are
// tiledPatternGeometry.registerForDrawing(RGBColor{0, 0, 1});
// polyscope::show(); // polyscope::show();
// tiledPatternGeometry.unregister(); // tiledPatternGeometry.unregister();
// } // }
@ -789,6 +869,10 @@ void TopologyEnumerator::computeValidPatterns(
} }
} }
// if (drawingThread.joinable()) {
// drawingThread.join();
// }
// assert(vcg_tiledPatternHasDangling == tiledPatternHasDanglingEdges); // assert(vcg_tiledPatternHasDangling == tiledPatternHasDanglingEdges);
} while (std::next_permutation(patternBinaryRepresentation.begin(), } while (std::next_permutation(patternBinaryRepresentation.begin(),
patternBinaryRepresentation.end())); patternBinaryRepresentation.end()));
@ -805,16 +889,15 @@ void TopologyEnumerator::computeValidPatterns(
} }
std::vector<size_t> TopologyEnumerator::getCoincideEdges( std::vector<size_t> TopologyEnumerator::getCoincideEdges(
const std::vector<size_t> &edgeNodeIndices) const const std::vector<size_t>& edgeNodeIndices) const {
{
std::vector<size_t> coincideEdges; std::vector<size_t> coincideEdges;
if (edgeNodeIndices.size() < 3) if (edgeNodeIndices.size() < 3)
return coincideEdges; return coincideEdges;
for (size_t edgeNodeIndex = 0; edgeNodeIndex < edgeNodeIndices.size() - 2; edgeNodeIndex++) { for (size_t edgeNodeIndex = 0; edgeNodeIndex < edgeNodeIndices.size() - 2;
edgeNodeIndex++) {
const size_t& firstNodeIndex = edgeNodeIndices[edgeNodeIndex]; const size_t& firstNodeIndex = edgeNodeIndices[edgeNodeIndex];
for (size_t secondEdgeNodeIndex = edgeNodeIndex + 2; for (size_t secondEdgeNodeIndex = edgeNodeIndex + 2;
secondEdgeNodeIndex < edgeNodeIndices.size(); secondEdgeNodeIndex < edgeNodeIndices.size(); secondEdgeNodeIndex++) {
secondEdgeNodeIndex++) {
const size_t& secondNodeIndex = edgeNodeIndices[secondEdgeNodeIndex]; const size_t& secondNodeIndex = edgeNodeIndices[secondEdgeNodeIndex];
coincideEdges.push_back(getEdgeIndex(firstNodeIndex, secondNodeIndex)); coincideEdges.push_back(getEdgeIndex(firstNodeIndex, secondNodeIndex));
} }
@ -822,9 +905,9 @@ std::vector<size_t> TopologyEnumerator::getCoincideEdges(
return coincideEdges; return coincideEdges;
} }
bool TopologyEnumerator::isValidPattern(const std::string &patternBinaryRepresentation, bool TopologyEnumerator::isValidPattern(
const std::string& patternBinaryRepresentation,
const std::vector<vcg::Point2i>& validEdges, const std::vector<vcg::Point2i>& validEdges,
const size_t &numberOfDesiredEdges) const const size_t& numberOfDesiredEdges) const {
{
return true; return true;
} }

View File

@ -1,12 +1,12 @@
#include "trianglepatterngeometry.hpp" #include "trianglepatterngeometry.hpp"
#include "trianglepattterntopology.hpp"
#include <algorithm>
#include <iterator>
#include <numeric>
#include <vcg/complex/algorithms/update/position.h> #include <vcg/complex/algorithms/update/position.h>
#include <vcg/simplex/edge/topology.h> #include <vcg/simplex/edge/topology.h>
#include <vcg/space/intersection2.h> #include <vcg/space/intersection2.h>
#include <wrap/io_trimesh/export.h> #include <wrap/io_trimesh/export.h>
#include <algorithm>
#include <iterator>
#include <numeric>
#include "trianglepattterntopology.hpp"
/* include the support for half edges */ /* include the support for half edges */
#include <vcg/complex/algorithms/update/halfedge_indexed.h> #include <vcg/complex/algorithms/update/halfedge_indexed.h>
@ -72,14 +72,17 @@ size_t PatternGeometry::computeTiledValence(
return 0; return 0;
} }
size_t PatternGeometry::getFanSize() const { return fanSize; } size_t PatternGeometry::getFanSize() const {
return fanSize;
}
double PatternGeometry::getTriangleEdgeSize() const { return triangleEdgeSize; } double PatternGeometry::getTriangleEdgeSize() const {
return triangleEdgeSize;
}
PatternGeometry::PatternGeometry() {} PatternGeometry::PatternGeometry() {}
std::vector<vcg::Point3d> PatternGeometry::computeVertices() const std::vector<vcg::Point3d> PatternGeometry::computeVertices() const {
{
std::vector<VCGEdgeMesh::CoordType> verts(VN()); std::vector<VCGEdgeMesh::CoordType> verts(VN());
for (size_t vi = 0; vi < VN(); vi++) { for (size_t vi = 0; vi < VN(); vi++) {
verts[vi] = vert[vi].cP(); verts[vi] = vert[vi].cP();
@ -87,8 +90,7 @@ std::vector<vcg::Point3d> PatternGeometry::computeVertices() const
return verts; return verts;
} }
PatternGeometry PatternGeometry::createTile(PatternGeometry &pattern) PatternGeometry PatternGeometry::createTile(PatternGeometry& pattern) {
{
const size_t fanSize = PatternGeometry().getFanSize(); const size_t fanSize = PatternGeometry().getFanSize();
PatternGeometry fan(createFan(pattern)); PatternGeometry fan(createFan(pattern));
PatternGeometry tile(fan); PatternGeometry tile(fan);
@ -141,13 +143,11 @@ PatternGeometry PatternGeometry::createFan(PatternGeometry &pattern) {
return fan; return fan;
} }
void PatternGeometry::updateBaseTriangle() void PatternGeometry::updateBaseTriangle() {
{
baseTriangle = computeBaseTriangle(); baseTriangle = computeBaseTriangle();
} }
PatternGeometry::PatternGeometry(PatternGeometry &other) PatternGeometry::PatternGeometry(PatternGeometry& other) {
{
vcg::tri::Append<PatternGeometry, PatternGeometry>::MeshCopy(*this, other); vcg::tri::Append<PatternGeometry, PatternGeometry>::MeshCopy(*this, other);
this->vertices = other.computeVertices(); this->vertices = other.computeVertices();
baseTriangle = other.getBaseTriangle(); baseTriangle = other.getBaseTriangle();
@ -156,8 +156,7 @@ PatternGeometry::PatternGeometry(PatternGeometry &other)
vcg::tri::UpdateTopology<PatternGeometry>::EdgeEdge(*this); vcg::tri::UpdateTopology<PatternGeometry>::EdgeEdge(*this);
} }
bool PatternGeometry::load(const std::filesystem::__cxx11::path &meshFilePath) bool PatternGeometry::load(const std::filesystem::__cxx11::path& meshFilePath) {
{
if (!VCGEdgeMesh::load(meshFilePath)) { if (!VCGEdgeMesh::load(meshFilePath)) {
return false; return false;
} }
@ -190,8 +189,7 @@ void PatternGeometry::add(const std::vector<vcg::Point2i> &edges) {
} }
void PatternGeometry::add(const std::vector<vcg::Point3d>& vertices, void PatternGeometry::add(const std::vector<vcg::Point3d>& vertices,
const std::vector<vcg::Point2i> &edges) const std::vector<vcg::Point2i>& edges) {
{
add(vertices); add(vertices);
add(edges); add(edges);
updateEigenEdgeAndVertices(); updateEigenEdgeAndVertices();
@ -209,9 +207,9 @@ void PatternGeometry::add(const std::vector<size_t> &numberOfNodesPerSlot,
} }
std::vector<vcg::Point3d> PatternGeometry::constructVertexVector( std::vector<vcg::Point3d> PatternGeometry::constructVertexVector(
const std::vector<size_t> &numberOfNodesPerSlot, const size_t &fanSize, const std::vector<size_t>& numberOfNodesPerSlot,
const size_t& fanSize,
const double& triangleEdgeSize) { const double& triangleEdgeSize) {
std::vector<vcg::Point3d> vertices; std::vector<vcg::Point3d> vertices;
const double centerAngle = 2 * M_PI / fanSize; const double centerAngle = 2 * M_PI / fanSize;
const double triangleHeight = const double triangleHeight =
@ -244,7 +242,6 @@ std::vector<vcg::Point3d> PatternGeometry::constructVertexVector(
const vcg::Point3d edgeVector0(triangleV1 - triangleV0); const vcg::Point3d edgeVector0(triangleV1 - triangleV0);
for (size_t vertexIndex = 0; vertexIndex < numberOfNodesPerSlot[3]; for (size_t vertexIndex = 0; vertexIndex < numberOfNodesPerSlot[3];
vertexIndex++) { vertexIndex++) {
// vertices[std::accumulate(numberOfNodesPerSlot.begin(), // vertices[std::accumulate(numberOfNodesPerSlot.begin(),
// numberOfNodesPerSlot.begin() + 2, 0) + // numberOfNodesPerSlot.begin() + 2, 0) +
// vertexIndex] = // vertexIndex] =
@ -260,7 +257,6 @@ std::vector<vcg::Point3d> PatternGeometry::constructVertexVector(
const vcg::Point3d edgeVector1(triangleV2 - triangleV1); const vcg::Point3d edgeVector1(triangleV2 - triangleV1);
for (size_t vertexIndex = 0; vertexIndex < numberOfNodesPerSlot[4]; for (size_t vertexIndex = 0; vertexIndex < numberOfNodesPerSlot[4];
vertexIndex++) { vertexIndex++) {
// vertices[std::accumulate(numberOfNodesPerSlot.begin(), // vertices[std::accumulate(numberOfNodesPerSlot.begin(),
// numberOfNodesPerSlot.begin() + 3, 0) + // numberOfNodesPerSlot.begin() + 3, 0) +
// vertexIndex] = // vertexIndex] =
@ -313,32 +309,34 @@ void PatternGeometry::constructNodeToTiledValenceMap(
} }
std::vector<VectorType> PatternGeometry::getEdgeVectorsWithVertexAsOrigin( std::vector<VectorType> PatternGeometry::getEdgeVectorsWithVertexAsOrigin(
std::vector<EdgePointer> &edgePointers, const int &vi) std::vector<EdgePointer>& edgePointers,
{ const int& vi) {
std::vector<VectorType> incidentElementsVectors(edgePointers.size()); std::vector<VectorType> incidentElementsVectors(edgePointers.size());
for (int incidentElementsIndex = 0; incidentElementsIndex < edgePointers.size(); for (int incidentElementsIndex = 0;
incidentElementsIndex++) { incidentElementsIndex < edgePointers.size(); incidentElementsIndex++) {
assert(vi == getIndex(edgePointers[incidentElementsIndex]->cV(0)) assert(vi == getIndex(edgePointers[incidentElementsIndex]->cV(0)) ||
|| vi == getIndex(edgePointers[incidentElementsIndex]->cV(1))); vi == getIndex(edgePointers[incidentElementsIndex]->cV(1)));
incidentElementsVectors[incidentElementsIndex] incidentElementsVectors[incidentElementsIndex] =
= vi == getIndex(edgePointers[incidentElementsIndex]->cV(0)) vi == getIndex(edgePointers[incidentElementsIndex]->cV(0))
? edgePointers[incidentElementsIndex]->cP(1) ? edgePointers[incidentElementsIndex]->cP(1) -
- edgePointers[incidentElementsIndex]->cP(0) edgePointers[incidentElementsIndex]->cP(0)
: edgePointers[incidentElementsIndex]->cP(0) : edgePointers[incidentElementsIndex]->cP(0) -
- edgePointers[incidentElementsIndex]->cP(1); edgePointers[incidentElementsIndex]->cP(1);
} }
return incidentElementsVectors; return incidentElementsVectors;
} }
bool PatternGeometry::hasAngleSmallerThanThreshold(const std::vector<size_t> &numberOfNodesPerSlot, bool PatternGeometry::hasAngleSmallerThanThreshold(
const double &angleThreshold_degrees) const std::vector<size_t>& numberOfNodesPerSlot,
{ const double& angleThreshold_degrees,
const bool shouldBreak) {
assert(numberOfNodesPerSlot.size() == 7); assert(numberOfNodesPerSlot.size() == 7);
// Initialize helping structs // Initialize helping structs
if (nodeToSlotMap.empty()) { if (nodeToSlotMap.empty()) {
FlatPatternTopology::constructNodeToSlotMap(numberOfNodesPerSlot, nodeToSlotMap); FlatPatternTopology::constructNodeToSlotMap(numberOfNodesPerSlot,
nodeToSlotMap);
} }
if (correspondingNode.empty()) { if (correspondingNode.empty()) {
constructCorrespondingNodeMap(numberOfNodesPerSlot); constructCorrespondingNodeMap(numberOfNodesPerSlot);
@ -349,11 +347,13 @@ bool PatternGeometry::hasAngleSmallerThanThreshold(const std::vector<size_t> &nu
// const double theta2 = vcg::math::ToDeg(vcg::Point2d(0, 1).Angle()); // const double theta2 = vcg::math::ToDeg(vcg::Point2d(0, 1).Angle());
// const double theta3 = vcg::math::ToDeg(vcg::Point2d(-1, 1).Angle()); // const double theta3 = vcg::math::ToDeg(vcg::Point2d(-1, 1).Angle());
// const double theta4 = vcg::math::ToDeg(vcg::Point2d(-1, 0).Angle()); // const double theta4 = vcg::math::ToDeg(vcg::Point2d(-1, 0).Angle());
// const double theta5 = vcg::math::ToDeg(vcg::Point2d(-1, -1).Angle() + 2 * M_PI); // const double theta5 = vcg::math::ToDeg(vcg::Point2d(-1, -1).Angle() + 2
// const double theta6 = vcg::math::ToDeg(vcg::Point2d(0, -1).Angle() + 2 * M_PI); // * M_PI); const double theta6 = vcg::math::ToDeg(vcg::Point2d(0,
// const double theta7 = vcg::math::ToDeg(vcg::Point2d(1, -1).Angle() + 2 * M_PI); // -1).Angle() + 2 * M_PI); const double theta7 =
// vcg::math::ToDeg(vcg::Point2d(1, -1).Angle() + 2 * M_PI);
// std::set<double> test{theta0, theta1, theta2, theta3, theta4, theta5, theta6, theta7}; // std::set<double> test{theta0, theta1, theta2, theta3, theta4, theta5,
// theta6, theta7};
bool hasAngleSmallerThan = false; bool hasAngleSmallerThan = false;
// find tiled incident edges for each node // find tiled incident edges for each node
@ -366,127 +366,152 @@ bool PatternGeometry::hasAngleSmallerThanThreshold(const std::vector<size_t> &nu
if (numberOfIncidentEdges == 0) { if (numberOfIncidentEdges == 0) {
continue; continue;
} }
std::vector<VectorType> incidentEdgeVectors std::vector<VectorType> incidentEdgeVectors =
= getEdgeVectorsWithVertexAsOrigin(incidentElementPointers, vi); getEdgeVectorsWithVertexAsOrigin(incidentElementPointers, vi);
std::vector<VectorType> tiledIncidentVectors = incidentEdgeVectors; std::vector<VectorType> tiledIncidentVectors = incidentEdgeVectors;
const size_t slotIndex = nodeToSlotMap[vi]; const size_t slotIndex = nodeToSlotMap[vi];
if (slotIndex == 2) { if (slotIndex == 2) {
//NOTE:I assume that base triangle slots 1,2(bottom triangle nodes) are not used // NOTE:I assume that base triangle slots 1,2(bottom triangle nodes) are
std::cerr // not used
<< "Slot of bottom base triangle nodes detected.This case is not handled.Exiting.." std::cerr << "Slot of bottom base triangle nodes detected.This case is "
"not handled.Exiting.."
<< std::endl; << std::endl;
std::terminate(); std::terminate();
} else if (slotIndex == 3 || slotIndex == 5) { } else if (slotIndex == 3 || slotIndex == 5) {
// NOTE: I don't need to check both triangle edges // NOTE: I don't need to check both triangle edges
std::vector<PatternGeometry::EdgePointer> correspondingVertexIncidentElementPointers; std::vector<PatternGeometry::EdgePointer>
correspondingVertexIncidentElementPointers;
vcg::edge::VEStarVE(&vert[correspondingNode[vi]], vcg::edge::VEStarVE(&vert[correspondingNode[vi]],
correspondingVertexIncidentElementPointers); correspondingVertexIncidentElementPointers);
std::vector<VectorType> correspondingVertexIncidentVectors std::vector<VectorType> correspondingVertexIncidentVectors =
= getEdgeVectorsWithVertexAsOrigin(correspondingVertexIncidentElementPointers, getEdgeVectorsWithVertexAsOrigin(
correspondingVertexIncidentElementPointers,
correspondingNode[vi]); correspondingNode[vi]);
// const CoordType &correspondingVertexPosition = vert[correspondingNode[vi]].cP(); // const CoordType &correspondingVertexPosition =
// vert[correspondingNode[vi]].cP();
vcg::Matrix33d R; vcg::Matrix33d R;
if (slotIndex == 3) { if (slotIndex == 3) {
R = vcg::RotationMatrix(vcg::Point3d(0, 0, 1), vcg::math::ToRad(-360.0 / fanSize)); R = vcg::RotationMatrix(vcg::Point3d(0, 0, 1),
vcg::math::ToRad(-360.0 / fanSize));
} else { } else {
R = vcg::RotationMatrix(vcg::Point3d(0, 0, 1), vcg::math::ToRad(360.0 / fanSize)); R = vcg::RotationMatrix(vcg::Point3d(0, 0, 1),
vcg::math::ToRad(360.0 / fanSize));
} }
// const CoordType &correspondingVertexPosition_rotated = vert[vi].cP(); // const CoordType &correspondingVertexPosition_rotated =
std::transform( // vert[vi].cP();
correspondingVertexIncidentVectors.begin(), std::transform(correspondingVertexIncidentVectors.begin(),
correspondingVertexIncidentVectors.end(), correspondingVertexIncidentVectors.end(),
correspondingVertexIncidentVectors.begin(), correspondingVertexIncidentVectors.begin(),
[&](const VectorType& v) { [&](const VectorType& v) {
// CoordType rotatedTarget = v * R; // CoordType rotatedTarget
// v = rotatedTarget - correspondingVertexPosition_rotated; // = v * R; v =
// rotatedTarget -
// correspondingVertexPosition_rotated;
return R * v; return R * v;
}); });
tiledIncidentVectors.insert(tiledIncidentVectors.end(), tiledIncidentVectors.insert(tiledIncidentVectors.end(),
correspondingVertexIncidentVectors.begin(), correspondingVertexIncidentVectors.begin(),
correspondingVertexIncidentVectors.end()); correspondingVertexIncidentVectors.end());
} else if (slotIndex == 4) { } else if (slotIndex == 4) {
std::vector<VectorType> reversedIncidentElementVectors(incidentEdgeVectors.size()); std::vector<VectorType> reversedIncidentElementVectors(
std::transform(incidentEdgeVectors.begin(), incidentEdgeVectors.size());
incidentEdgeVectors.end(), std::transform(incidentEdgeVectors.begin(), incidentEdgeVectors.end(),
reversedIncidentElementVectors.begin(), reversedIncidentElementVectors.begin(),
[&](const VectorType& v) { return -v; }); [&](const VectorType& v) { return -v; });
//NOTE: for checking the angles not all opposite incident element vectors are needed but rather the two "extreme" ones of slot 4 // NOTE: for checking the angles not all opposite incident element vectors
//here I simply add them all // are needed but rather the two "extreme" ones of slot 4 here I simply
// add them all
tiledIncidentVectors.insert(tiledIncidentVectors.end(), tiledIncidentVectors.insert(tiledIncidentVectors.end(),
reversedIncidentElementVectors.begin(), reversedIncidentElementVectors.begin(),
reversedIncidentElementVectors.end()); reversedIncidentElementVectors.end());
} }
// if (shouldBreak) {
// std::vector<std::array<double, 3>> edgePoints; // std::vector<std::array<double, 3>> edgePoints;
// for (int tiledVectorIndex = 0; tiledVectorIndex < tiledIncidentVectors.size(); // for (int tiledVectorIndex = 0;
// tiledVectorIndex < tiledIncidentVectors.size();
// tiledVectorIndex++) { // tiledVectorIndex++) {
// edgePoints.push_back( // edgePoints.push_back(std::array<double, 3>{
// std::array<double, 3>{vert[vi].cP()[0], vert[vi].cP()[1], vert[vi].cP()[2]}); // vert[vi].cP()[0], vert[vi].cP()[1], vert[vi].cP()[2]});
// edgePoints.push_back( // edgePoints.push_back(std::array<double, 3>{
// std::array<double, 3>{(vert[vi].cP() + tiledIncidentVectors[tiledVectorIndex])[0], // (vert[vi].cP() +
// (vert[vi].cP() + tiledIncidentVectors[tiledVectorIndex])[1], // tiledIncidentVectors[tiledVectorIndex])[0], (vert[vi].cP()
// (vert[vi].cP() + tiledIncidentVectors[tiledVectorIndex])[2]}); // + tiledIncidentVectors[tiledVectorIndex])[1],
// (vert[vi].cP() +
// tiledIncidentVectors[tiledVectorIndex])[2]});
// } // }
// polyscope::init(); // polyscope::init();
// polyscope::registerCurveNetworkLine("temp", edgePoints); // polyscope::registerCurveNetworkLine("vi:" + std::to_string(vi),
// polyscope::removeStructure("temp"); // edgePoints);
// polyscope::show();
// polyscope::removeStructure("vi:" + std::to_string(vi));
// }
if (tiledIncidentVectors.size() == 1) { if (tiledIncidentVectors.size() == 1) {
continue; continue;
} }
std::vector<double> thetaAnglesOfIncidentVectors(tiledIncidentVectors.size()); std::vector<double> thetaAnglesOfIncidentVectors(
std::transform(tiledIncidentVectors.begin(), tiledIncidentVectors.size());
tiledIncidentVectors.end(), std::transform(
tiledIncidentVectors.begin(), tiledIncidentVectors.end(),
thetaAnglesOfIncidentVectors.begin(), thetaAnglesOfIncidentVectors.begin(),
[](const VectorType& v) { return vcg::Point2d(v[0], v[1]).Angle(); }); [](const VectorType& v) { return vcg::Point2d(v[0], v[1]).Angle(); });
// sort them using theta angles // sort them using theta angles
std::sort(thetaAnglesOfIncidentVectors.begin(), thetaAnglesOfIncidentVectors.end()); std::sort(thetaAnglesOfIncidentVectors.begin(),
// polyscope::show(); thetaAnglesOfIncidentVectors.end());
// std::vector<double> angles_theta(thetaAnglesOfIncidentVectors); // std::vector<double> angles_theta(thetaAnglesOfIncidentVectors);
// for (double &theta_rad : angles_theta) { // for (double &theta_rad : angles_theta) {
// theta_rad = vcg::math::ToDeg(theta_rad); // theta_rad = vcg::math::ToDeg(theta_rad);
// } // }
//find nodes that contain incident edges with relative angles less than the threshold // find nodes that contain incident edges with relative angles less than the
// threshold
const double angleThreshold_rad = vcg::math::ToRad(angleThreshold_degrees); const double angleThreshold_rad = vcg::math::ToRad(angleThreshold_degrees);
for (int thetaAngleIndex = 0; thetaAngleIndex < thetaAnglesOfIncidentVectors.size(); for (int thetaAngleIndex = 0;
thetaAngleIndex < thetaAnglesOfIncidentVectors.size();
thetaAngleIndex++) { thetaAngleIndex++) {
const auto &va_theta const auto& va_theta =
= thetaAnglesOfIncidentVectors[(thetaAngleIndex + 1) thetaAnglesOfIncidentVectors[(thetaAngleIndex + 1) %
% thetaAnglesOfIncidentVectors.size()]; thetaAnglesOfIncidentVectors.size()];
const auto& vb_theta = thetaAnglesOfIncidentVectors[thetaAngleIndex]; const auto& vb_theta = thetaAnglesOfIncidentVectors[thetaAngleIndex];
// const auto &va // const auto &va
// = tiledIncidentVectors[(thetaAngleIndex + 1) % thetaAnglesOfIncidentVectors.size()]; // = tiledIncidentVectors[(thetaAngleIndex + 1) %
// thetaAnglesOfIncidentVectors.size()];
// const auto &vb = tiledIncidentVectors[thetaAngleIndex]; // const auto &vb = tiledIncidentVectors[thetaAngleIndex];
const double absAngleDifference = std::abs(va_theta - vb_theta); const double absAngleDifference = std::abs(va_theta - vb_theta);
// const double debug_difDegOtherway = vcg::math::ToDeg( // const double debug_difDegOtherway = vcg::math::ToDeg(
// std::acos((va * vb) / (va.Norm() * vb.Norm()))); // std::acos((va * vb) / (va.Norm() * vb.Norm())));
// const double debug_diffDeg = vcg::math::ToDeg(absAngleDifference); // const double debug_diffDeg =
// vcg::math::ToDeg(absAngleDifference);
if (absAngleDifference < angleThreshold_rad if (absAngleDifference < angleThreshold_rad
/*&& absAngleDifference > vcg::math::ToRad(0.01)*/) { /*&& absAngleDifference > vcg::math::ToRad(0.01)*/) {
// std::cout << "Found angDiff:" << absAngleDifference << std::endl; // std::cout << "Found angDiff:" << absAngleDifference <<
// vert[vi].C() = vcg::Color4b::Magenta; // std::endl; vert[vi].C() = vcg::Color4b::Magenta;
// hasAngleSmallerThan = true; // hasAngleSmallerThan = true;
return true; return true;
} }
} }
const double firstLastPairAngleDiff = std::abs( const double firstLastPairAngleDiff = std::abs(
thetaAnglesOfIncidentVectors[0] thetaAnglesOfIncidentVectors[0] -
- thetaAnglesOfIncidentVectors[thetaAnglesOfIncidentVectors.size() - 1]); thetaAnglesOfIncidentVectors[thetaAnglesOfIncidentVectors.size() - 1]);
if (firstLastPairAngleDiff < angleThreshold_rad && firstLastPairAngleDiff > 0.01) { if (firstLastPairAngleDiff < angleThreshold_rad &&
firstLastPairAngleDiff > 0.01) {
return true; return true;
} }
} }
return false; return false;
} }
bool PatternGeometry::hasValenceGreaterThan(const std::vector<size_t> &numberOfNodesPerSlot, bool PatternGeometry::hasValenceGreaterThan(
const size_t &valenceThreshold) const std::vector<size_t>& numberOfNodesPerSlot,
{ const size_t& valenceThreshold) {
// Initialize helping structs // Initialize helping structs
if (nodeToSlotMap.empty()) { if (nodeToSlotMap.empty()) {
FlatPatternTopology::constructNodeToSlotMap(numberOfNodesPerSlot, nodeToSlotMap); FlatPatternTopology::constructNodeToSlotMap(numberOfNodesPerSlot,
nodeToSlotMap);
} }
if (correspondingNode.empty()) { if (correspondingNode.empty()) {
constructCorrespondingNodeMap(numberOfNodesPerSlot); constructCorrespondingNodeMap(numberOfNodesPerSlot);
@ -511,7 +536,8 @@ bool PatternGeometry::hasDanglingEdges(
const std::vector<size_t>& numberOfNodesPerSlot) { const std::vector<size_t>& numberOfNodesPerSlot) {
// Initialize helping structs // Initialize helping structs
if (nodeToSlotMap.empty()) { if (nodeToSlotMap.empty()) {
FlatPatternTopology::constructNodeToSlotMap(numberOfNodesPerSlot, nodeToSlotMap); FlatPatternTopology::constructNodeToSlotMap(numberOfNodesPerSlot,
nodeToSlotMap);
} }
if (correspondingNode.empty()) { if (correspondingNode.empty()) {
constructCorrespondingNodeMap(numberOfNodesPerSlot); constructCorrespondingNodeMap(numberOfNodesPerSlot);
@ -545,7 +571,6 @@ bool PatternGeometry::hasUntiledDanglingEdges() {
const size_t nodeValence = connectedEdges.size(); const size_t nodeValence = connectedEdges.size();
if (nodeValence == 1) { if (nodeValence == 1) {
if (vert[vi].C().operator==(vcg::Color4b(vcg::Color4b::Red))) { if (vert[vi].C().operator==(vcg::Color4b(vcg::Color4b::Red))) {
} else { } else {
vert[vi].C() = vcg::Color4b::Blue; vert[vi].C() = vcg::Color4b::Blue;
} }
@ -557,10 +582,10 @@ bool PatternGeometry::hasUntiledDanglingEdges() {
// TODO: The function expects that the numberOfNodesPerSlot follows a specific // TODO: The function expects that the numberOfNodesPerSlot follows a specific
// format and that the vertex container was populated in a particular order. // format and that the vertex container was populated in a particular order.
void PatternGeometry::constructCorrespondingNodeMap(const std::vector<size_t> &numberOfNodesPerSlot) void PatternGeometry::constructCorrespondingNodeMap(
{ const std::vector<size_t>& numberOfNodesPerSlot) {
assert(vn != 0 && !nodeToSlotMap.empty() && correspondingNode.empty() assert(vn != 0 && !nodeToSlotMap.empty() && correspondingNode.empty() &&
&& numberOfNodesPerSlot.size() == 7); numberOfNodesPerSlot.size() == 7);
for (size_t nodeIndex = 0; nodeIndex < vn; nodeIndex++) { for (size_t nodeIndex = 0; nodeIndex < vn; nodeIndex++) {
const size_t slotIndex = nodeToSlotMap[nodeIndex]; const size_t slotIndex = nodeToSlotMap[nodeIndex];
@ -569,33 +594,32 @@ void PatternGeometry::constructCorrespondingNodeMap(const std::vector<size_t> &n
} else if (slotIndex == 2) { } else if (slotIndex == 2) {
correspondingNode[nodeIndex] = nodeIndex - 1; correspondingNode[nodeIndex] = nodeIndex - 1;
} else if (slotIndex == 3) { } else if (slotIndex == 3) {
const size_t numberOfNodesBefore = nodeIndex const size_t numberOfNodesBefore =
- std::accumulate(numberOfNodesPerSlot.begin(), nodeIndex - std::accumulate(numberOfNodesPerSlot.begin(),
numberOfNodesPerSlot.begin() + 3, numberOfNodesPerSlot.begin() + 3, 0);
0); correspondingNode[nodeIndex] =
correspondingNode[nodeIndex] = std::accumulate(numberOfNodesPerSlot.begin(), std::accumulate(numberOfNodesPerSlot.begin(),
numberOfNodesPerSlot.begin() + 6, numberOfNodesPerSlot.begin() + 6, 0) -
0) 1 - numberOfNodesBefore;
- 1 - numberOfNodesBefore;
} else if (slotIndex == 5) { } else if (slotIndex == 5) {
const size_t numberOfNodesAfter = std::accumulate(numberOfNodesPerSlot.begin(), const size_t numberOfNodesAfter =
numberOfNodesPerSlot.begin() + 6, std::accumulate(numberOfNodesPerSlot.begin(),
0) numberOfNodesPerSlot.begin() + 6, 0) -
- 1 - nodeIndex; 1 - nodeIndex;
correspondingNode[nodeIndex] = numberOfNodesAfter correspondingNode[nodeIndex] =
+ std::accumulate(numberOfNodesPerSlot.begin(), numberOfNodesAfter + std::accumulate(numberOfNodesPerSlot.begin(),
numberOfNodesPerSlot.begin() + 3, numberOfNodesPerSlot.begin() + 3,
0); 0);
} }
} }
} }
bool PatternGeometry::isFullyConnectedWhenFanned() bool PatternGeometry::isFullyConnectedWhenFanned() {
{
assert(vn != 0 /* && !correspondingNode.empty()*/); assert(vn != 0 /* && !correspondingNode.empty()*/);
// TrianglePatternGeometry copyOfPattern(*this); // TrianglePatternGeometry copyOfPattern(*this);
// // If bottom interface nodes have a valence of zero there definetely more than // // If bottom interface nodes have a valence of zero there definetely more
// than
// // a single cc // // a single cc
// bool bottomInterfaceIsConnected = false; // bool bottomInterfaceIsConnected = false;
// for (size_t nodeIndex = 0; nodeIndex < vn; nodeIndex++) { // for (size_t nodeIndex = 0; nodeIndex < vn; nodeIndex++) {
@ -620,7 +644,8 @@ bool PatternGeometry::isFullyConnectedWhenFanned()
vcg::tri::UpdateTopology<PatternGeometry>::VertexEdge(fanedPattern); vcg::tri::UpdateTopology<PatternGeometry>::VertexEdge(fanedPattern);
vcg::tri::UpdateTopology<PatternGeometry>::EdgeEdge(fanedPattern); vcg::tri::UpdateTopology<PatternGeometry>::EdgeEdge(fanedPattern);
std::vector<std::pair<int, PatternGeometry::EdgePointer>> eCC; std::vector<std::pair<int, PatternGeometry::EdgePointer>> eCC;
vcg::tri::Clean<PatternGeometry>::edgeMeshConnectedComponents(fanedPattern, eCC); vcg::tri::Clean<PatternGeometry>::edgeMeshConnectedComponents(fanedPattern,
eCC);
const bool sideInterfaceIsConnected = 1 == eCC.size(); const bool sideInterfaceIsConnected = 1 == eCC.size();
if (!sideInterfaceIsConnected) { if (!sideInterfaceIsConnected) {
@ -699,14 +724,15 @@ bool PatternGeometry::isFullyConnectedWhenFanned()
bool PatternGeometry::hasIntersectingEdges( bool PatternGeometry::hasIntersectingEdges(
const std::string& patternBinaryRepresentation, const std::string& patternBinaryRepresentation,
const std::unordered_map<size_t, std::unordered_set<size_t>> const std::unordered_map<size_t, std::unordered_set<size_t>>&
&intersectingEdges) { intersectingEdges) {
bool containsIntersectingEdges = false; bool containsIntersectingEdges = false;
for (size_t validEdgeIndex = 0; for (size_t validEdgeIndex = 0;
validEdgeIndex < patternBinaryRepresentation.size(); validEdgeIndex++) { validEdgeIndex < patternBinaryRepresentation.size(); validEdgeIndex++) {
if (patternBinaryRepresentation[validEdgeIndex] == '1' if (patternBinaryRepresentation[validEdgeIndex] == '1' &&
&& intersectingEdges.contains(validEdgeIndex)) { intersectingEdges.contains(validEdgeIndex)) {
for (auto edgeIndexIt = intersectingEdges.find(validEdgeIndex)->second.begin(); for (auto edgeIndexIt =
intersectingEdges.find(validEdgeIndex)->second.begin();
edgeIndexIt != intersectingEdges.find(validEdgeIndex)->second.end(); edgeIndexIt != intersectingEdges.find(validEdgeIndex)->second.end();
edgeIndexIt++) { edgeIndexIt++) {
if (patternBinaryRepresentation[*edgeIndexIt] == '1') { if (patternBinaryRepresentation[*edgeIndexIt] == '1') {
@ -777,8 +803,7 @@ PatternGeometry::getIntersectingEdges(
} }
PatternGeometry::PatternGeometry(const std::filesystem::path& patternFilePath, PatternGeometry::PatternGeometry(const std::filesystem::path& patternFilePath,
bool addNormalsIfAbsent) bool addNormalsIfAbsent) {
{
if (!std::filesystem::exists(std::filesystem::path(patternFilePath))) { if (!std::filesystem::exists(std::filesystem::path(patternFilePath))) {
assert(false); assert(false);
std::cerr << "No flat pattern with name " << patternFilePath << std::endl; std::cerr << "No flat pattern with name " << patternFilePath << std::endl;
@ -800,18 +825,15 @@ PatternGeometry::PatternGeometry(const std::filesystem::path &patternFilePath,
updateEigenEdgeAndVertices(); updateEigenEdgeAndVertices();
} }
double PatternGeometry::computeBaseTriangleHeight() const double PatternGeometry::computeBaseTriangleHeight() const {
{
return vcg::Distance(vert[0].cP(), vert[interfaceNodeIndex].cP()); return vcg::Distance(vert[0].cP(), vert[interfaceNodeIndex].cP());
} }
void PatternGeometry::updateBaseTriangleHeight() void PatternGeometry::updateBaseTriangleHeight() {
{
baseTriangleHeight = computeBaseTriangleHeight(); baseTriangleHeight = computeBaseTriangleHeight();
} }
void PatternGeometry::deleteDanglingVertices() void PatternGeometry::deleteDanglingVertices() {
{
vcg::tri::Allocator<VCGEdgeMesh>::PointerUpdater<VertexPointer> pu; vcg::tri::Allocator<VCGEdgeMesh>::PointerUpdater<VertexPointer> pu;
VCGEdgeMesh::deleteDanglingVertices(pu); VCGEdgeMesh::deleteDanglingVertices(pu);
if (!pu.remap.empty()) { if (!pu.remap.empty()) {
@ -820,18 +842,15 @@ void PatternGeometry::deleteDanglingVertices()
} }
void PatternGeometry::deleteDanglingVertices( void PatternGeometry::deleteDanglingVertices(
vcg::tri::Allocator<VCGEdgeMesh>::PointerUpdater<VertexPointer> &pu) vcg::tri::Allocator<VCGEdgeMesh>::PointerUpdater<VertexPointer>& pu) {
{
VCGEdgeMesh::deleteDanglingVertices(pu); VCGEdgeMesh::deleteDanglingVertices(pu);
} }
vcg::Triangle3<double> PatternGeometry::getBaseTriangle() const vcg::Triangle3<double> PatternGeometry::getBaseTriangle() const {
{
return baseTriangle; return baseTriangle;
} }
void PatternGeometry::addNormals() void PatternGeometry::addNormals() {
{
bool normalsAreAbsent = vert[0].cN().Norm() < 0.000001; bool normalsAreAbsent = vert[0].cN().Norm() < 0.000001;
if (normalsAreAbsent) { if (normalsAreAbsent) {
for (auto& v : vert) { for (auto& v : vert) {
@ -840,16 +859,16 @@ void PatternGeometry::addNormals()
} }
} }
vcg::Triangle3<double> PatternGeometry::computeBaseTriangle() const vcg::Triangle3<double> PatternGeometry::computeBaseTriangle() const {
{
const double baseTriangleHeight = computeBaseTriangleHeight(); const double baseTriangleHeight = computeBaseTriangleHeight();
double bottomEdgeHalfSize = baseTriangleHeight / std::tan(M_PI / 3); double bottomEdgeHalfSize = baseTriangleHeight / std::tan(M_PI / 3);
CoordType patternCoord0 = vert[0].cP(); CoordType patternCoord0 = vert[0].cP();
CoordType patternBottomRight = vert[interfaceNodeIndex].cP() CoordType patternBottomRight =
+ CoordType(bottomEdgeHalfSize, 0, 0); vert[interfaceNodeIndex].cP() + CoordType(bottomEdgeHalfSize, 0, 0);
CoordType patternBottomLeft = vert[interfaceNodeIndex].cP() CoordType patternBottomLeft =
- CoordType(bottomEdgeHalfSize, 0, 0); vert[interfaceNodeIndex].cP() - CoordType(bottomEdgeHalfSize, 0, 0);
return vcg::Triangle3<double>(patternCoord0, patternBottomLeft, patternBottomRight); return vcg::Triangle3<double>(patternCoord0, patternBottomLeft,
patternBottomRight);
} }
PatternGeometry::PatternGeometry( PatternGeometry::PatternGeometry(
@ -864,30 +883,32 @@ PatternGeometry::PatternGeometry(
updateEigenEdgeAndVertices(); updateEigenEdgeAndVertices();
} }
//TODO: refactor such that it takes as an input a single pattern and tiles into the desired faces without requiring the each face will contain a single pattern // TODO: refactor such that it takes as an input a single pattern and tiles into
// the desired faces without requiring the each face will contain a single
// pattern
std::shared_ptr<PatternGeometry> PatternGeometry::tilePattern( std::shared_ptr<PatternGeometry> PatternGeometry::tilePattern(
std::vector<ConstPatternGeometry>& patterns, std::vector<ConstPatternGeometry>& patterns,
const std::vector<int>& connectToNeighborsVi, const std::vector<int>& connectToNeighborsVi,
const VCGPolyMesh& tileInto, const VCGPolyMesh& tileInto,
const std::vector<int>& perSurfaceFacePatternIndices, const std::vector<int>& perSurfaceFacePatternIndices,
std::vector<size_t>& tileIntoEdgesToTiledVi, std::vector<size_t>& tileIntoEdgesToTiledVi,
std::vector<std::vector<size_t>> &perPatternIndexToTiledPatternEdgeIndex) std::vector<std::vector<size_t>>& perPatternIndexToTiledPatternEdgeIndex) {
{
perPatternIndexToTiledPatternEdgeIndex.resize(patterns.size()); perPatternIndexToTiledPatternEdgeIndex.resize(patterns.size());
std::shared_ptr<PatternGeometry> pTiledPattern(new PatternGeometry); std::shared_ptr<PatternGeometry> pTiledPattern(new PatternGeometry);
std::vector<std::vector<int>> tileIntoEdgeToInterfaceVi( std::vector<std::vector<int>> tileIntoEdgeToInterfaceVi(
tileInto.EN()); //ith element contains all the interface nodes that lay on the ith edge of tileInto tileInto.EN()); // ith element contains all the interface nodes that lay
// on the ith edge of tileInto
// Compute the barycentric coords of the verts in the base triangle pattern // Compute the barycentric coords of the verts in the base triangle pattern
std::vector<std::vector<CoordType>> barycentricCoordinates(patterns.size()); std::vector<std::vector<CoordType>> barycentricCoordinates(patterns.size());
for (size_t patternIndex = 0; patternIndex < patterns.size(); patternIndex++) { for (size_t patternIndex = 0; patternIndex < patterns.size();
patternIndex++) {
const PatternGeometry& pattern = patterns[patternIndex]; const PatternGeometry& pattern = patterns[patternIndex];
const vcg::Triangle3<double>& baseTriangle = pattern.getBaseTriangle(); const vcg::Triangle3<double>& baseTriangle = pattern.getBaseTriangle();
barycentricCoordinates[patternIndex].resize(pattern.VN()); barycentricCoordinates[patternIndex].resize(pattern.VN());
for (int vi = 0; vi < pattern.VN(); vi++) { for (int vi = 0; vi < pattern.VN(); vi++) {
CoordType barycentricCoords_vi; CoordType barycentricCoords_vi;
vcg::InterpolationParameters<vcg::Triangle3<double>, double>(baseTriangle, vcg::InterpolationParameters<vcg::Triangle3<double>, double>(
pattern.vert[vi].cP(), baseTriangle, pattern.vert[vi].cP(), barycentricCoords_vi);
barycentricCoords_vi);
barycentricCoordinates[patternIndex][vi] = barycentricCoords_vi; barycentricCoordinates[patternIndex][vi] = barycentricCoords_vi;
} }
} }
@ -905,8 +926,7 @@ std::shared_ptr<PatternGeometry> PatternGeometry::tilePattern(
centerOfFace = centerOfFace + f.cP(vi); centerOfFace = centerOfFace + f.cP(vi);
} }
centerOfFace /= f.VN(); centerOfFace /= f.VN();
vcg::tri::Allocator<VCGTriMesh>::AddVertex(tileIntoEdgeMesh, vcg::tri::Allocator<VCGTriMesh>::AddVertex(tileIntoEdgeMesh, centerOfFace,
centerOfFace,
vcg::Color4b::Yellow); vcg::Color4b::Yellow);
std::vector<int> firstInFanConnectToNeighbor_vi(connectToNeighborsVi); std::vector<int> firstInFanConnectToNeighbor_vi(connectToNeighborsVi);
@ -918,16 +938,17 @@ std::shared_ptr<PatternGeometry> PatternGeometry::tilePattern(
for (size_t vi = 0; vi < f.VN(); vi++) { for (size_t vi = 0; vi < f.VN(); vi++) {
auto ep = f.FEp(vi); auto ep = f.FEp(vi);
assert(vcg::tri::IsValidPointer(tileInto, ep)); assert(vcg::tri::IsValidPointer(tileInto, ep));
std::vector<vcg::Point3d> meshTrianglePoints{centerOfFace, std::vector<vcg::Point3d> meshTrianglePoints{
f.cP(vi), centerOfFace, f.cP(vi), vi + 1 == f.VN() ? f.cP(0) : f.cP(vi + 1)};
vi + 1 == f.VN() ? f.cP(0) : f.cP(vi + 1)}; // std::vector<vcg::Point3d> meshTrianglePoints{centerOfFace,
// std::vector<vcg::Point3d> meshTrianglePoints{centerOfFace, ep->cP(0), ep->cP(1)}; // ep->cP(0), ep->cP(1)};
auto fit = vcg::tri::Allocator<VCGTriMesh>::AddFace(tileIntoEdgeMesh, auto fit = vcg::tri::Allocator<VCGTriMesh>::AddFace(
meshTrianglePoints[0], tileIntoEdgeMesh, meshTrianglePoints[0], meshTrianglePoints[1],
meshTrianglePoints[1],
meshTrianglePoints[2]); meshTrianglePoints[2]);
// CoordType faceNormal = ((meshTrianglePoints[1] - meshTrianglePoints[0]) // CoordType faceNormal = ((meshTrianglePoints[1] -
// ^ (meshTrianglePoints[2] - meshTrianglePoints[0])) // meshTrianglePoints[0])
// ^ (meshTrianglePoints[2] -
// meshTrianglePoints[0]))
// .Normalize(); // .Normalize();
// TODO: in planar surfaces I should compute the face of triangle // TODO: in planar surfaces I should compute the face of triangle
CoordType faceNormal = f.cN(); CoordType faceNormal = f.cN();
@ -938,12 +959,16 @@ std::shared_ptr<PatternGeometry> PatternGeometry::tilePattern(
// pattern.registerForDrawing(); // pattern.registerForDrawing();
// polyscope::show(); // polyscope::show();
// pattern.unregister(); // pattern.unregister();
//Transform the base triangle nodes to the mesh triangle using barycentric coords // Transform the base triangle nodes to the mesh triangle using
// barycentric coords
for (int vi = 0; vi < transformedPattern.VN(); vi++) { for (int vi = 0; vi < transformedPattern.VN(); vi++) {
transformedPattern.vert[vi].P() = CoordType( transformedPattern.vert[vi].P() =
meshTrianglePoints[0] * barycentricCoordinates[patternIndex][vi][0] CoordType(meshTrianglePoints[0] *
+ meshTrianglePoints[1] * barycentricCoordinates[patternIndex][vi][1] barycentricCoordinates[patternIndex][vi][0] +
+ meshTrianglePoints[2] * barycentricCoordinates[patternIndex][vi][2]); meshTrianglePoints[1] *
barycentricCoordinates[patternIndex][vi][1] +
meshTrianglePoints[2] *
barycentricCoordinates[patternIndex][vi][2]);
} }
for (VertexType& v : transformedPattern.vert) { for (VertexType& v : transformedPattern.vert) {
@ -951,18 +976,19 @@ std::shared_ptr<PatternGeometry> PatternGeometry::tilePattern(
} }
vcg::tri::Append<PatternGeometry, PatternGeometry>::Remap remap; vcg::tri::Append<PatternGeometry, PatternGeometry>::Remap remap;
vcg::tri::Append<PatternGeometry, PatternGeometry>::Mesh(*pTiledPattern, vcg::tri::Append<PatternGeometry, PatternGeometry>::Mesh(
transformedPattern, *pTiledPattern, transformedPattern, remap);
remap);
for (size_t ei = 0; ei < pattern.EN(); ei++) { for (size_t ei = 0; ei < pattern.EN(); ei++) {
perPatternIndexToTiledPatternEdgeIndex[patternIndex].push_back(remap.edge[ei]); perPatternIndexToTiledPatternEdgeIndex[patternIndex].push_back(
remap.edge[ei]);
} }
// pTiledPattern->registerForDrawing(); // pTiledPattern->registerForDrawing();
// pTiledPattern->markVertices({remap.vert[pattern.interfaceNodeIndex]}); // pTiledPattern->markVertices({remap.vert[pattern.interfaceNodeIndex]});
// polyscope::show(); // polyscope::show();
// pTiledPattern->unregister(); // pTiledPattern->unregister();
const size_t ei = tileInto.getIndex(ep); const size_t ei = tileInto.getIndex(ep);
tileIntoEdgeToInterfaceVi[ei].push_back(remap.vert[pattern.interfaceNodeIndex]); tileIntoEdgeToInterfaceVi[ei].push_back(
remap.vert[pattern.interfaceNodeIndex]);
// Add edges for connecting the desired vertices // Add edges for connecting the desired vertices
if (!connectToNeighborsVi.empty()) { if (!connectToNeighborsVi.empty()) {
if (vi + 1 == f.VN()) { if (vi + 1 == f.VN()) {
@ -972,8 +998,8 @@ std::shared_ptr<PatternGeometry> PatternGeometry::tilePattern(
auto eIt = vcg::tri::Allocator<PatternGeometry>::AddEdge( auto eIt = vcg::tri::Allocator<PatternGeometry>::AddEdge(
*pTiledPattern, *pTiledPattern,
firstInFanConnectToNeighbor_vi[connectToNeighborIndex], firstInFanConnectToNeighbor_vi[connectToNeighborIndex],
pTiledPattern->VN() - pattern.VN() pTiledPattern->VN() - pattern.VN() +
+ connectToNeighborsVi[connectToNeighborIndex]); connectToNeighborsVi[connectToNeighborIndex]);
perPatternIndexToTiledPatternEdgeIndex[patternIndex].push_back( perPatternIndexToTiledPatternEdgeIndex[patternIndex].push_back(
pTiledPattern->getIndex(*eIt)); pTiledPattern->getIndex(*eIt));
} }
@ -984,10 +1010,10 @@ std::shared_ptr<PatternGeometry> PatternGeometry::tilePattern(
connectToNeighborIndex++) { connectToNeighborIndex++) {
auto eIt = vcg::tri::Allocator<PatternGeometry>::AddEdge( auto eIt = vcg::tri::Allocator<PatternGeometry>::AddEdge(
*pTiledPattern, *pTiledPattern,
pTiledPattern->VN() - 2 * pattern.VN() pTiledPattern->VN() - 2 * pattern.VN() +
+ connectToNeighborsVi[connectToNeighborIndex], connectToNeighborsVi[connectToNeighborIndex],
pTiledPattern->VN() - pattern.VN() pTiledPattern->VN() - pattern.VN() +
+ connectToNeighborsVi[connectToNeighborIndex]); connectToNeighborsVi[connectToNeighborIndex]);
perPatternIndexToTiledPatternEdgeIndex[patternIndex].push_back( perPatternIndexToTiledPatternEdgeIndex[patternIndex].push_back(
pTiledPattern->getIndex(*eIt)); pTiledPattern->getIndex(*eIt));
} }
@ -999,7 +1025,8 @@ std::shared_ptr<PatternGeometry> PatternGeometry::tilePattern(
vcg::tri::Allocator<VCGEdgeMesh>::PointerUpdater<EdgePointer> pu_edges; vcg::tri::Allocator<VCGEdgeMesh>::PointerUpdater<EdgePointer> pu_edges;
pTiledPattern->removeDuplicateVertices(pu_vertices, pu_edges); pTiledPattern->removeDuplicateVertices(pu_vertices, pu_edges);
// Update perPattern // Update perPattern
// for (std::vector<size_t> &tiledPatternEdges : perPatternIndexToTiledPatternEdgeIndex) { // for (std::vector<size_t> &tiledPatternEdges :
// perPatternIndexToTiledPatternEdgeIndex) {
// for (size_t &ei : tiledPatternEdges) { // for (size_t &ei : tiledPatternEdges) {
// ei = pu_edges.remap[ei]; // ei = pu_edges.remap[ei];
// } // }
@ -1012,11 +1039,10 @@ std::shared_ptr<PatternGeometry> PatternGeometry::tilePattern(
// tiledPatternEdges.erase(end, tiledPatternEdges.end()); // tiledPatternEdges.erase(end, tiledPatternEdges.end());
// } // }
const size_t sumOfEdgeIndices = std::accumulate(perPatternIndexToTiledPatternEdgeIndex.begin(), const size_t sumOfEdgeIndices =
perPatternIndexToTiledPatternEdgeIndex.end(), std::accumulate(perPatternIndexToTiledPatternEdgeIndex.begin(),
0, perPatternIndexToTiledPatternEdgeIndex.end(), 0,
[](const size_t &sum, [](const size_t& sum, const std::vector<size_t>& v) {
const std::vector<size_t> &v) {
return sum + v.size(); return sum + v.size();
}); });
@ -1032,10 +1058,11 @@ std::shared_ptr<PatternGeometry> PatternGeometry::tilePattern(
} }
assert(interfaceVis.size() == 1 || interfaceVis.size() == 2); assert(interfaceVis.size() == 1 || interfaceVis.size() == 2);
assert( assert(
interfaceVis.size() == 1 interfaceVis.size() == 1 ||
|| (interfaceVis.size() == 2 (interfaceVis.size() == 2 && (pu_vertices.remap[interfaceVis[0]] ==
&& (pu_vertices.remap[interfaceVis[0]] == std::numeric_limits<size_t>::max() std::numeric_limits<size_t>::max() ||
|| pu_vertices.remap[interfaceVis[1]] == std::numeric_limits<size_t>::max()))); pu_vertices.remap[interfaceVis[1]] ==
std::numeric_limits<size_t>::max())));
tileIntoEdgesToTiledVi[ei] = pu_vertices.remap[interfaceVis[0]]; tileIntoEdgesToTiledVi[ei] = pu_vertices.remap[interfaceVis[0]];
} }
@ -1046,8 +1073,7 @@ std::shared_ptr<PatternGeometry> PatternGeometry::tilePattern(
return pTiledPattern; return pTiledPattern;
} }
bool PatternGeometry::createHoneycombAtom() bool PatternGeometry::createHoneycombAtom() {
{
VCGEdgeMesh honeycombQuarter; VCGEdgeMesh honeycombQuarter;
const VCGEdgeMesh::CoordType n(0, 0, 1); const VCGEdgeMesh::CoordType n(0, 0, 1);
const double H = 0.2; const double H = 0.2;
@ -1055,38 +1081,38 @@ bool PatternGeometry::createHoneycombAtom()
const double width = 0.2; const double width = 0.2;
const double theta = 70; const double theta = 70;
const double dy = tan(vcg::math::ToRad(90 - theta)) * width / 2; const double dy = tan(vcg::math::ToRad(90 - theta)) * width / 2;
vcg::tri::Allocator<VCGEdgeMesh>::AddVertex(honeycombQuarter, vcg::tri::Allocator<VCGEdgeMesh>::AddVertex(
VCGEdgeMesh::CoordType(0, height / 2, 0), honeycombQuarter, VCGEdgeMesh::CoordType(0, height / 2, 0), n);
n); vcg::tri::Allocator<VCGEdgeMesh>::AddVertex(
vcg::tri::Allocator<VCGEdgeMesh>::AddVertex(honeycombQuarter, honeycombQuarter, VCGEdgeMesh::CoordType(0, H / 2 - dy, 0), n);
VCGEdgeMesh::CoordType(0, H / 2 - dy, 0), vcg::tri::Allocator<VCGEdgeMesh>::AddVertex(
n); honeycombQuarter, VCGEdgeMesh::CoordType(width / 2, H / 2, 0), n);
vcg::tri::Allocator<VCGEdgeMesh>::AddVertex(honeycombQuarter, vcg::tri::Allocator<VCGEdgeMesh>::AddVertex(
VCGEdgeMesh::CoordType(width / 2, H / 2, 0), honeycombQuarter, VCGEdgeMesh::CoordType(width / 2, 0, 0), n);
n);
vcg::tri::Allocator<VCGEdgeMesh>::AddVertex(honeycombQuarter,
VCGEdgeMesh::CoordType(width / 2, 0, 0),
n);
vcg::tri::Allocator<VCGEdgeMesh>::AddEdge(honeycombQuarter, 0, 1); vcg::tri::Allocator<VCGEdgeMesh>::AddEdge(honeycombQuarter, 0, 1);
vcg::tri::Allocator<VCGEdgeMesh>::AddEdge(honeycombQuarter, 1, 2); vcg::tri::Allocator<VCGEdgeMesh>::AddEdge(honeycombQuarter, 1, 2);
vcg::tri::Allocator<VCGEdgeMesh>::AddEdge(honeycombQuarter, 2, 3); vcg::tri::Allocator<VCGEdgeMesh>::AddEdge(honeycombQuarter, 2, 3);
VCGEdgeMesh honeycombAtom; VCGEdgeMesh honeycombAtom;
// Top right // Top right
vcg::tri::Append<VCGEdgeMesh, VCGEdgeMesh>::MeshCopy(honeycombAtom, honeycombQuarter); vcg::tri::Append<VCGEdgeMesh, VCGEdgeMesh>::MeshCopy(honeycombAtom,
honeycombQuarter);
// Bottom right // Bottom right
vcg::Matrix44d rotM; vcg::Matrix44d rotM;
rotM.SetRotateDeg(180, vcg::Point3d(1, 0, 0)); rotM.SetRotateDeg(180, vcg::Point3d(1, 0, 0));
vcg::tri::UpdatePosition<VCGEdgeMesh>::Matrix(honeycombQuarter, rotM); vcg::tri::UpdatePosition<VCGEdgeMesh>::Matrix(honeycombQuarter, rotM);
vcg::tri::Append<VCGEdgeMesh, VCGEdgeMesh>::Mesh(honeycombAtom, honeycombQuarter); vcg::tri::Append<VCGEdgeMesh, VCGEdgeMesh>::Mesh(honeycombAtom,
honeycombQuarter);
// Bottom left // Bottom left
rotM.SetRotateDeg(180, vcg::Point3d(0, 1, 0)); rotM.SetRotateDeg(180, vcg::Point3d(0, 1, 0));
vcg::tri::UpdatePosition<VCGEdgeMesh>::Matrix(honeycombQuarter, rotM); vcg::tri::UpdatePosition<VCGEdgeMesh>::Matrix(honeycombQuarter, rotM);
vcg::tri::Append<VCGEdgeMesh, VCGEdgeMesh>::Mesh(honeycombAtom, honeycombQuarter); vcg::tri::Append<VCGEdgeMesh, VCGEdgeMesh>::Mesh(honeycombAtom,
honeycombQuarter);
// Top left // Top left
rotM.SetRotateDeg(180, vcg::Point3d(1, 0, 0)); rotM.SetRotateDeg(180, vcg::Point3d(1, 0, 0));
vcg::tri::UpdatePosition<VCGEdgeMesh>::Matrix(honeycombQuarter, rotM); vcg::tri::UpdatePosition<VCGEdgeMesh>::Matrix(honeycombQuarter, rotM);
vcg::tri::Append<VCGEdgeMesh, VCGEdgeMesh>::Mesh(honeycombAtom, honeycombQuarter); vcg::tri::Append<VCGEdgeMesh, VCGEdgeMesh>::Mesh(honeycombAtom,
honeycombQuarter);
for (VertexType& v : honeycombAtom.vert) { for (VertexType& v : honeycombAtom.vert) {
v.P()[2] = 0; v.P()[2] = 0;
@ -1095,51 +1121,51 @@ bool PatternGeometry::createHoneycombAtom()
return true; return true;
} }
void PatternGeometry::copy(PatternGeometry &copyFrom) void PatternGeometry::copy(PatternGeometry& copyFrom) {
{
VCGEdgeMesh::copy(copyFrom); VCGEdgeMesh::copy(copyFrom);
baseTriangleHeight = copyFrom.getBaseTriangleHeight(); baseTriangleHeight = copyFrom.getBaseTriangleHeight();
baseTriangle = copyFrom.getBaseTriangle(); baseTriangle = copyFrom.getBaseTriangle();
interfaceNodeIndex = copyFrom.interfaceNodeIndex; interfaceNodeIndex = copyFrom.interfaceNodeIndex;
} }
void PatternGeometry::scale(const double &desiredBaseTriangleCentralEdgeSize) void PatternGeometry::scale(const double& desiredBaseTriangleCentralEdgeSize) {
{
const double baseTriangleCentralEdgeSize = getBaseTriangleHeight(); const double baseTriangleCentralEdgeSize = getBaseTriangleHeight();
const double scaleRatio = desiredBaseTriangleCentralEdgeSize / baseTriangleCentralEdgeSize; const double scaleRatio =
desiredBaseTriangleCentralEdgeSize / baseTriangleCentralEdgeSize;
vcg::tri::UpdatePosition<VCGEdgeMesh>::Scale(*this, scaleRatio); vcg::tri::UpdatePosition<VCGEdgeMesh>::Scale(*this, scaleRatio);
baseTriangle = computeBaseTriangle(); baseTriangle = computeBaseTriangle();
baseTriangleHeight = computeBaseTriangleHeight(); baseTriangleHeight = computeBaseTriangleHeight();
const double debug_baseTriHeight = vcg::Distance(baseTriangle.cP(0), const double debug_baseTriHeight = vcg::Distance(
(baseTriangle.cP(1) + baseTriangle.cP(2)) / 2); baseTriangle.cP(0), (baseTriangle.cP(1) + baseTriangle.cP(2)) / 2);
assert(std::abs(desiredBaseTriangleCentralEdgeSize - baseTriangleHeight) < 1e-10); assert(std::abs(desiredBaseTriangleCentralEdgeSize - baseTriangleHeight) <
1e-10);
int i = 0; int i = 0;
i++; i++;
} }
void PatternGeometry::createFan(const size_t &fanSize) void PatternGeometry::createFan(const size_t& fanSize) {
{
PatternGeometry rotatedPattern; PatternGeometry rotatedPattern;
vcg::tri::Append<PatternGeometry, PatternGeometry>::MeshCopy(rotatedPattern, *this); vcg::tri::Append<PatternGeometry, PatternGeometry>::MeshCopy(rotatedPattern,
*this);
for (int rotationCounter = 1; rotationCounter < fanSize; rotationCounter++) { for (int rotationCounter = 1; rotationCounter < fanSize; rotationCounter++) {
vcg::Matrix44d R; vcg::Matrix44d R;
auto rotationAxis = vcg::Point3d(0, 0, 1); auto rotationAxis = vcg::Point3d(0, 0, 1);
R.SetRotateDeg(360.0 / fanSize, rotationAxis); R.SetRotateDeg(360.0 / fanSize, rotationAxis);
vcg::tri::UpdatePosition<PatternGeometry>::Matrix(rotatedPattern, R); vcg::tri::UpdatePosition<PatternGeometry>::Matrix(rotatedPattern, R);
vcg::tri::Append<PatternGeometry, PatternGeometry>::Mesh(*this, rotatedPattern); vcg::tri::Append<PatternGeometry, PatternGeometry>::Mesh(*this,
rotatedPattern);
// Add edges for connecting the desired vertices // Add edges for connecting the desired vertices
removeDuplicateVertices(); removeDuplicateVertices();
updateEigenEdgeAndVertices(); updateEigenEdgeAndVertices();
} }
} }
double PatternGeometry::getBaseTriangleHeight() const double PatternGeometry::getBaseTriangleHeight() const {
{
return baseTriangleHeight; return baseTriangleHeight;
} }
bool PatternGeometry::isInterfaceConnected(const std::unordered_set<VertexIndex> &interfaceNodes) bool PatternGeometry::isInterfaceConnected(
{ const std::unordered_set<VertexIndex>& interfaceNodes) {
std::unordered_set<VertexIndex> interfaceNodesConnected; std::unordered_set<VertexIndex> interfaceNodesConnected;
for (int ei = 0; ei < EN(); ei++) { for (int ei = 0; ei < EN(); ei++) {
@ -1147,7 +1173,8 @@ bool PatternGeometry::isInterfaceConnected(const std::unordered_set<VertexIndex>
const int evi1 = getIndex(edge[ei].cV(1)); const int evi1 = getIndex(edge[ei].cV(1));
if (interfaceNodes.contains(evi0) && !interfaceNodes.contains(evi1)) { if (interfaceNodes.contains(evi0) && !interfaceNodes.contains(evi1)) {
interfaceNodesConnected.insert(evi0); interfaceNodesConnected.insert(evi0);
} else if (!interfaceNodes.contains(evi0) && interfaceNodes.contains(evi1)) { } else if (!interfaceNodes.contains(evi0) &&
interfaceNodes.contains(evi1)) {
interfaceNodesConnected.insert(evi1); interfaceNodesConnected.insert(evi1);
} }
} }
@ -1159,10 +1186,10 @@ bool PatternGeometry::isInterfaceConnected(const std::unordered_set<VertexIndex>
} }
std::unordered_set<VertexIndex> PatternGeometry::getInterfaceNodes( std::unordered_set<VertexIndex> PatternGeometry::getInterfaceNodes(
const std::vector<size_t> &numberOfNodesPerSlot) const std::vector<size_t>& numberOfNodesPerSlot) {
{
if (nodeToSlotMap.empty()) { if (nodeToSlotMap.empty()) {
FlatPatternTopology::constructNodeToSlotMap(numberOfNodesPerSlot, nodeToSlotMap); FlatPatternTopology::constructNodeToSlotMap(numberOfNodesPerSlot,
nodeToSlotMap);
} }
std::unordered_set<VertexIndex> interfaceNodes; std::unordered_set<VertexIndex> interfaceNodes;
for (std::pair<VertexIndex, size_t> viSlotPair : nodeToSlotMap) { for (std::pair<VertexIndex, size_t> viSlotPair : nodeToSlotMap) {

View File

@ -1,20 +1,19 @@
#ifndef FLATPATTERNGEOMETRY_HPP #ifndef FLATPATTERNGEOMETRY_HPP
#define FLATPATTERNGEOMETRY_HPP #define FLATPATTERNGEOMETRY_HPP
#include "edgemesh.hpp"
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include <unordered_set> #include <unordered_set>
#include "vcgtrimesh.hpp" #include "edgemesh.hpp"
#include "polymesh.hpp" #include "polymesh.hpp"
#include "vcgtrimesh.hpp"
class PatternGeometry; class PatternGeometry;
using ConstPatternGeometry = PatternGeometry; using ConstPatternGeometry = PatternGeometry;
class PatternGeometry : public VCGEdgeMesh class PatternGeometry : public VCGEdgeMesh {
{
private: private:
size_t size_t computeTiledValence(
computeTiledValence(const size_t &nodeIndex, const size_t& nodeIndex,
const std::vector<size_t>& numberOfNodesPerSlot) const; const std::vector<size_t>& numberOfNodesPerSlot) const;
size_t getNodeValence(const size_t& nodeIndex) const; size_t getNodeValence(const size_t& nodeIndex) const;
size_t getNodeSlot(const size_t& nodeIndex) const; size_t getNodeSlot(const size_t& nodeIndex) const;
@ -30,12 +29,14 @@ private:
std::unordered_map<size_t, size_t> nodeTiledValence; std::unordered_map<size_t, size_t> nodeTiledValence;
vcg::Triangle3<double> baseTriangle; vcg::Triangle3<double> baseTriangle;
void void constructCorrespondingNodeMap(
constructCorrespondingNodeMap(const std::vector<size_t> &numberOfNodesPerSlot); const std::vector<size_t>& numberOfNodesPerSlot);
void constructNodeToTiledValenceMap(const std::vector<size_t> &numberOfNodesPerSlot); void constructNodeToTiledValenceMap(
const std::vector<size_t>& numberOfNodesPerSlot);
std::vector<VectorType> getEdgeVectorsWithVertexAsOrigin(std::vector<EdgePointer> &edgePointers, std::vector<VectorType> getEdgeVectorsWithVertexAsOrigin(
std::vector<EdgePointer>& edgePointers,
const int& vi); const int& vi);
public: public:
@ -49,8 +50,10 @@ private:
bool load(const std::filesystem::path& meshFilePath) override; bool load(const std::filesystem::path& meshFilePath) override;
void add(const std::vector<vcg::Point3d>& vertices); void add(const std::vector<vcg::Point3d>& vertices);
void add(const std::vector<vcg::Point2i>& edges); void add(const std::vector<vcg::Point2i>& edges);
void add(const std::vector<vcg::Point3d> &vertices, const std::vector<vcg::Point2i> &edges); void add(const std::vector<vcg::Point3d>& vertices,
void add(const std::vector<size_t> &numberOfNodesPerSlot, const std::vector<vcg::Point2i> &edges); const std::vector<vcg::Point2i>& edges);
void add(const std::vector<size_t>& numberOfNodesPerSlot,
const std::vector<vcg::Point2i>& edges);
static std::vector<vcg::Point3d> constructVertexVector( static std::vector<vcg::Point3d> constructVertexVector(
const std::vector<size_t>& numberOfNodesPerSlot, const std::vector<size_t>& numberOfNodesPerSlot,
const size_t& fanSize, const size_t& fanSize,
@ -66,8 +69,7 @@ private:
std::unordered_map<size_t, std::unordered_set<size_t>> getIntersectingEdges( std::unordered_map<size_t, std::unordered_set<size_t>> getIntersectingEdges(
size_t& numberOfIntersectingEdgePairs) const; size_t& numberOfIntersectingEdgePairs) const;
static size_t binomialCoefficient(size_t n, size_t m) static size_t binomialCoefficient(size_t n, size_t m) {
{
assert(n >= m); assert(n >= m);
return tgamma(n + 1) / (tgamma(m + 1) * tgamma(n - m + 1)); return tgamma(n + 1) / (tgamma(m + 1) * tgamma(n - m + 1));
} }
@ -75,8 +77,8 @@ private:
bool hasIntersectingEdges( bool hasIntersectingEdges(
const std::string& patternBinaryRepresentation, const std::string& patternBinaryRepresentation,
const std::unordered_map<size_t, std::unordered_set<size_t>> const std::unordered_map<size_t, std::unordered_set<size_t>>&
&intersectingEdges); intersectingEdges);
bool isPatternValid(); bool isPatternValid();
size_t getFanSize() const; size_t getFanSize() const;
void add(const std::vector<vcg::Point2d>& vertices, void add(const std::vector<vcg::Point2d>& vertices,
@ -84,7 +86,8 @@ private:
PatternGeometry(const std::vector<size_t>& numberOfNodesPerSlot, PatternGeometry(const std::vector<size_t>& numberOfNodesPerSlot,
const std::vector<vcg::Point2i>& edges); const std::vector<vcg::Point2i>& edges);
PatternGeometry(const std::filesystem::path &patternFilePath, bool addNormalsIfAbsent = true); PatternGeometry(const std::filesystem::path& patternFilePath,
bool addNormalsIfAbsent = true);
bool createHoneycombAtom(); bool createHoneycombAtom();
void copy(PatternGeometry& copyFrom); void copy(PatternGeometry& copyFrom);
@ -102,20 +105,26 @@ private:
double computeBaseTriangleHeight() const; double computeBaseTriangleHeight() const;
void updateBaseTriangleHeight(); void updateBaseTriangleHeight();
// PatternGeometry(const std::vector<vcg::Point2d> &vertices, const std::vector<vcg::Point2i> &edges); // PatternGeometry(const std::vector<vcg::Point2d> &vertices, const
// static std::shared_ptr<PatternGeometry> tilePattern( // std::vector<vcg::Point2i> &edges); static std::shared_ptr<PatternGeometry>
// tilePattern(
// std::vector<PatternGeometry> &pattern, // std::vector<PatternGeometry> &pattern,
// const std::vector<int> &connectToNeighborsVi, // const std::vector<int> &connectToNeighborsVi,
// const VCGPolyMesh &tileInto, // const VCGPolyMesh &tileInto,
// std::vector<int> &tileIntoEdgesToTiledVi, // std::vector<int> &tileIntoEdgesToTiledVi,
// std::vector<std::vector<size_t>> &perPatternEdges); // std::vector<std::vector<size_t>> &perPatternEdges);
virtual void createFan(/*const std::vector<int> &connectToNeighborsVi = std::vector<int>(),*/ virtual void createFan(/*const std::vector<int> &connectToNeighborsVi =
std::vector<int>(),*/
const size_t& fanSize = 6); const size_t& fanSize = 6);
int interfaceNodeIndex{3}; //TODO: Fix this. This should be automatically computed int interfaceNodeIndex{
bool hasAngleSmallerThanThreshold(const std::vector<size_t> &numberOfNodesPerSlot, 3}; // TODO: Fix this. This should be automatically computed
const double &angleThreshold_degrees); bool hasAngleSmallerThanThreshold(
const std::vector<size_t>& numberOfNodesPerSlot,
const double& angleThreshold_degrees,
const bool shouldBreak = false);
vcg::Triangle3<double> getBaseTriangle() const; vcg::Triangle3<double> getBaseTriangle() const;
static std::shared_ptr<PatternGeometry> tilePattern(PatternGeometry &pattern, static std::shared_ptr<PatternGeometry> tilePattern(
PatternGeometry& pattern,
const std::vector<int>& connectToNeighborsVi, const std::vector<int>& connectToNeighborsVi,
const VCGPolyMesh& tileInto, const VCGPolyMesh& tileInto,
std::vector<int>& tileIntoEdgesToTiledVi); std::vector<int>& tileIntoEdgesToTiledVi);
@ -126,11 +135,14 @@ private:
const std::vector<int>& perSurfaceFacePatternIndices, const std::vector<int>& perSurfaceFacePatternIndices,
std::vector<size_t>& tileIntoEdgesToTiledVi, std::vector<size_t>& tileIntoEdgesToTiledVi,
std::vector<std::vector<size_t>>& perPatternIndexTiledPatternEdgeIndex); std::vector<std::vector<size_t>>& perPatternIndexTiledPatternEdgeIndex);
std::unordered_set<VertexIndex> getInterfaceNodes(const std::vector<size_t> &numberOfNodesPerSlot); std::unordered_set<VertexIndex> getInterfaceNodes(
bool isInterfaceConnected(const std::unordered_set<VertexIndex> &interfaceNodes); const std::vector<size_t>& numberOfNodesPerSlot);
bool isInterfaceConnected(
const std::unordered_set<VertexIndex>& interfaceNodes);
void deleteDanglingVertices() override; void deleteDanglingVertices() override;
void deleteDanglingVertices( void deleteDanglingVertices(
vcg::tri::Allocator<VCGEdgeMesh>::PointerUpdater<VertexPointer> &pu) override; vcg::tri::Allocator<VCGEdgeMesh>::PointerUpdater<VertexPointer>& pu)
override;
}; };
#endif // FLATPATTERNGEOMETRY_HPP #endif // FLATPATTERNGEOMETRY_HPP

View File

@ -121,8 +121,7 @@ bool VCGTriMesh::save(const std::string plyFilename)
#ifdef POLYSCOPE_DEFINED #ifdef POLYSCOPE_DEFINED
polyscope::SurfaceMesh *VCGTriMesh::registerForDrawing( polyscope::SurfaceMesh *VCGTriMesh::registerForDrawing(const std::optional<std::array<float, 3> > &desiredColor, const bool &shouldEnable) const
const std::optional<std::array<double, 3>> &desiredColor, const bool &shouldEnable) const
{ {
auto vertices = getVertices(); auto vertices = getVertices();
auto faces = getFaces(); auto faces = getFaces();

View File

@ -1,8 +1,8 @@
#ifndef VCGTRIMESH_HPP #ifndef VCGTRIMESH_HPP
#define VCGTRIMESH_HPP #define VCGTRIMESH_HPP
#include "mesh.hpp"
#include <vcg/complex/complex.h> #include <vcg/complex/complex.h>
#include <optional> #include <optional>
#include "mesh.hpp"
#ifdef POLYSCOPE_DEFINED #ifdef POLYSCOPE_DEFINED
#include <polyscope/surface_mesh.h> #include <polyscope/surface_mesh.h>
@ -22,20 +22,21 @@ class VCGTriMeshVertex : public vcg::Vertex<VCGTriMeshUsedTypes,
vcg::vertex::Color4b, vcg::vertex::Color4b,
vcg::vertex::VFAdj, vcg::vertex::VFAdj,
vcg::vertex::Qualityd, vcg::vertex::Qualityd,
vcg::vertex::VEAdj> vcg::vertex::VEAdj> {};
{}; class VCGTriMeshFace : public vcg::Face<VCGTriMeshUsedTypes,
class VCGTriMeshFace vcg::face::FFAdj,
: public vcg::Face<VCGTriMeshUsedTypes, vcg::face::FFAdj, vcg::face::VFAdj, vcg::face::VFAdj,
vcg::face::VertexRef, vcg::face::BitFlags, vcg::face::VertexRef,
vcg::face::BitFlags,
vcg::face::Normal3d> {}; vcg::face::Normal3d> {};
class VCGTriMeshEdge : public vcg::Edge<VCGTriMeshUsedTypes, vcg::edge::VertexRef, vcg::edge::VEAdj> class VCGTriMeshEdge : public vcg::Edge<VCGTriMeshUsedTypes,
{}; vcg::edge::VertexRef,
vcg::edge::VEAdj> {};
class VCGTriMesh : public vcg::tri::TriMesh<std::vector<VCGTriMeshVertex>, class VCGTriMesh : public vcg::tri::TriMesh<std::vector<VCGTriMeshVertex>,
std::vector<VCGTriMeshFace>, std::vector<VCGTriMeshFace>,
std::vector<VCGTriMeshEdge>>, std::vector<VCGTriMeshEdge>>,
public Mesh public Mesh {
{
public: public:
VCGTriMesh(); VCGTriMesh();
VCGTriMesh(const std::string& filename); VCGTriMesh(const std::string& filename);
@ -44,13 +45,14 @@ public:
Eigen::MatrixX3d getVertices() const; Eigen::MatrixX3d getVertices() const;
Eigen::MatrixX3i getFaces() const; Eigen::MatrixX3i getFaces() const;
bool save(const std::string plyFilename); bool save(const std::string plyFilename);
template <typename MeshElement> size_t getIndex(const MeshElement &element) { template <typename MeshElement>
size_t getIndex(const MeshElement& element) {
return vcg::tri::Index<VCGTriMesh>(*this, element); return vcg::tri::Index<VCGTriMesh>(*this, element);
} }
#ifdef POLYSCOPE_DEFINED #ifdef POLYSCOPE_DEFINED
polyscope::SurfaceMesh* registerForDrawing( polyscope::SurfaceMesh* registerForDrawing(
const std::optional<std::array<double, 3>> &desiredColor = std::nullopt, const std::optional<std::array<float, 3>>& desiredColor = std::nullopt,
const bool& shouldEnable = true) const; const bool& shouldEnable = true) const;
#endif #endif
Eigen::MatrixX2i getEdges() const; Eigen::MatrixX2i getEdges() const;