Backup commit
This commit is contained in:
parent
01dff95f9d
commit
266aca08c2
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
297
polymesh.hpp
297
polymesh.hpp
|
|
@ -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 ©From)
|
|
||||||
{
|
|
||||||
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 ©From) { 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
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 ©From)
|
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) {
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue