Refactoring. Saving intermediate states during drm
This commit is contained in:
parent
922b525fbe
commit
21d79f07aa
|
@ -54,7 +54,6 @@ download_project(PROJ 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(${TBB_BINARY_DIR})
|
|
||||||
|
|
||||||
|
|
||||||
###Eigen 3 NOTE: Eigen is required on the system the code is ran
|
###Eigen 3 NOTE: Eigen is required on the system the code is ran
|
||||||
|
@ -77,7 +76,7 @@ target_include_directories(${PROJECT_NAME}
|
||||||
)
|
)
|
||||||
|
|
||||||
if(${USE_POLYSCOPE})
|
if(${USE_POLYSCOPE})
|
||||||
target_link_libraries(${PROJECT_NAME} Eigen3::Eigen matplot polyscope glad ThreedBeamFEA ${TBB_BINARY_DIR}/libtbb_static.a pthread)
|
target_link_libraries(${PROJECT_NAME} Eigen3::Eigen matplot polyscope glad ThreedBeamFEA tbb pthread)
|
||||||
else()
|
else()
|
||||||
target_link_libraries(${PROJECT_NAME} -static Eigen3::Eigen matplot ThreedBeamFEA ${TBB_BINARY_DIR}/libtbb_static.a pthread)
|
target_link_libraries(${PROJECT_NAME} -static Eigen3::Eigen matplot ThreedBeamFEA ${TBB_BINARY_DIR}/libtbb_static.a pthread)
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -32,12 +32,8 @@ public:
|
||||||
fs_.clear(std::cout.rdstate());
|
fs_.clear(std::cout.rdstate());
|
||||||
fs_.basic_ios<char>::rdbuf(std::cout.rdbuf());
|
fs_.basic_ios<char>::rdbuf(std::cout.rdbuf());
|
||||||
} else {
|
} else {
|
||||||
if (!std::filesystem::exists(
|
if (!std::filesystem::exists(std::filesystem::path(filename))) {
|
||||||
std::filesystem::path("../OptimizationResults")
|
std::ofstream outfile(filename);
|
||||||
.append("statistics.csv"))) {
|
|
||||||
std::ofstream outfile(std::filesystem::path("../OptimizationResults")
|
|
||||||
.append("statistics.csv")
|
|
||||||
.string());
|
|
||||||
outfile.close();
|
outfile.close();
|
||||||
}
|
}
|
||||||
overwrite ? fs_.open(filename, std::ios::trunc)
|
overwrite ? fs_.open(filename, std::ios::trunc)
|
||||||
|
|
|
@ -1030,11 +1030,6 @@ void DRMSimulationModel::updateResidualForcesOnTheFly(
|
||||||
}
|
}
|
||||||
pMesh->previousTotalResidualForcesNorm = pMesh->totalResidualForcesNorm;
|
pMesh->previousTotalResidualForcesNorm = pMesh->totalResidualForcesNorm;
|
||||||
pMesh->totalResidualForcesNorm = totalResidualForcesNorm;
|
pMesh->totalResidualForcesNorm = totalResidualForcesNorm;
|
||||||
if (mSettings.beVerbose) {
|
|
||||||
if (minTotalResidualForcesNorm > pMesh->totalResidualForcesNorm) {
|
|
||||||
minTotalResidualForcesNorm = pMesh->totalResidualForcesNorm;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pMesh->averageResidualForcesNorm = totalResidualForcesNorm / pMesh->VN();
|
pMesh->averageResidualForcesNorm = totalResidualForcesNorm / pMesh->VN();
|
||||||
// pMesh->averageResidualForcesNorm = sumOfResidualForces.norm() / pMesh->VN();
|
// pMesh->averageResidualForcesNorm = sumOfResidualForces.norm() / pMesh->VN();
|
||||||
|
|
||||||
|
@ -2277,6 +2272,17 @@ SimulationResults DRMSimulationModel::executeSimulation(const std::shared_ptr<Si
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (minTotalResidualForcesNorm > pMesh->totalResidualForcesNorm) {
|
||||||
|
minTotalResidualForcesNorm = pMesh->totalResidualForcesNorm;
|
||||||
|
static int lastSavedStep = mCurrentSimulationStep;
|
||||||
|
if (mSettings.saveIntermediateBestStates.has_value()
|
||||||
|
&& mSettings.saveIntermediateBestStates.value()
|
||||||
|
&& mCurrentSimulationStep - lastSavedStep > 20000) {
|
||||||
|
lastSavedStep = mCurrentSimulationStep;
|
||||||
|
computeResults(pJob).save("./IntermediateResults_" + pJob->getLabel());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//normalized sum of displacements
|
//normalized sum of displacements
|
||||||
// double sumOfDisplacementsNorm = 0;
|
// double sumOfDisplacementsNorm = 0;
|
||||||
// for (size_t vi = 0; vi < pMesh->VN(); vi++) {
|
// for (size_t vi = 0; vi < pMesh->VN(); vi++) {
|
||||||
|
@ -2693,6 +2699,16 @@ void DRMSimulationModel::Settings::save(const std::filesystem::path &folderPath)
|
||||||
json[jsonLabels.linearGuessForceScaleFactor] = linearGuessForceScaleFactor.value();
|
json[jsonLabels.linearGuessForceScaleFactor] = linearGuessForceScaleFactor.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if (intermediateResultsSaveStep.has_value()) {
|
||||||
|
// json[GET_VARIABLE_NAME(intermediateResultsSaveStep)] = intermediateResultsSaveStep.value();
|
||||||
|
// }
|
||||||
|
|
||||||
|
if (saveIntermediateBestStates.has_value()) {
|
||||||
|
json[GET_VARIABLE_NAME(saveIntermediateBestStates)] = saveIntermediateBestStates.value()
|
||||||
|
? "true"
|
||||||
|
: "false";
|
||||||
|
}
|
||||||
|
|
||||||
const std::string jsonFilename = "drmSettings.json";
|
const std::string jsonFilename = "drmSettings.json";
|
||||||
std::ofstream jsonFile(std::filesystem::path(folderPath).append(jsonFilename));
|
std::ofstream jsonFile(std::filesystem::path(folderPath).append(jsonFilename));
|
||||||
jsonFile << json;
|
jsonFile << json;
|
||||||
|
@ -2756,5 +2772,16 @@ bool DRMSimulationModel::Settings::load(const std::filesystem::path &jsonFilePat
|
||||||
linearGuessForceScaleFactor = json.at(jsonLabels.linearGuessForceScaleFactor);
|
linearGuessForceScaleFactor = json.at(jsonLabels.linearGuessForceScaleFactor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if (json.contains(GET_VARIABLE_NAME(intermediateResultsSaveStep))) {
|
||||||
|
// intermediateResultsSaveStep = json.at(GET_VARIABLE_NAME(intermediateResultsSaveStep));
|
||||||
|
// }
|
||||||
|
|
||||||
|
if (json.contains(GET_VARIABLE_NAME(saveIntermediateBestStates))) {
|
||||||
|
saveIntermediateBestStates = json.at(GET_VARIABLE_NAME(saveIntermediateBestStates))
|
||||||
|
== "true"
|
||||||
|
? true
|
||||||
|
: false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,6 +45,8 @@ public:
|
||||||
std::optional<double> totalTranslationalKineticEnergyThreshold;
|
std::optional<double> totalTranslationalKineticEnergyThreshold;
|
||||||
std::optional<double> averageResidualForcesCriterionThreshold;
|
std::optional<double> averageResidualForcesCriterionThreshold;
|
||||||
std::optional<double> linearGuessForceScaleFactor;
|
std::optional<double> linearGuessForceScaleFactor;
|
||||||
|
// std::optional<int> intermediateResultsSaveStep;
|
||||||
|
std::optional<bool> saveIntermediateBestStates;
|
||||||
Settings() {}
|
Settings() {}
|
||||||
void save(const std::filesystem::path &folderPath) const;
|
void save(const std::filesystem::path &folderPath) const;
|
||||||
bool load(const std::filesystem::path &filePath);
|
bool load(const std::filesystem::path &filePath);
|
||||||
|
|
|
@ -195,6 +195,7 @@ public:
|
||||||
|
|
||||||
bool load(const std::string &jsonFilename, const bool &shouldLoadMesh = true)
|
bool load(const std::string &jsonFilename, const bool &shouldLoadMesh = true)
|
||||||
{
|
{
|
||||||
|
std::cout << jsonFilename << std::endl;
|
||||||
label = "empty_job";
|
label = "empty_job";
|
||||||
constrainedVertices.clear();
|
constrainedVertices.clear();
|
||||||
nodalExternalForces.clear();
|
nodalExternalForces.clear();
|
||||||
|
@ -256,8 +257,8 @@ public:
|
||||||
if (json.contains(jsonLabels.nodalForces)) {
|
if (json.contains(jsonLabels.nodalForces)) {
|
||||||
auto f =
|
auto f =
|
||||||
json[jsonLabels.nodalForces].get<std::unordered_map<VertexIndex, std::array<double, 6>>>();
|
json[jsonLabels.nodalForces].get<std::unordered_map<VertexIndex, std::array<double, 6>>>();
|
||||||
for (const auto &forces : f) {
|
for (const auto &force : f) {
|
||||||
nodalExternalForces[forces.first] = Vector6d(forces.second);
|
nodalExternalForces[force.first] = Vector6d(force.second);
|
||||||
}
|
}
|
||||||
if (beVerbose) {
|
if (beVerbose) {
|
||||||
std::cout << "Loaded forces. Number of forces found:" << nodalExternalForces.size()
|
std::cout << "Loaded forces. Number of forces found:" << nodalExternalForces.size()
|
||||||
|
@ -345,6 +346,7 @@ json[jsonLabels.meshFilename]= std::filesystem::relative(std::filesystem::path(m
|
||||||
}
|
}
|
||||||
std::ofstream jsonFile(jsonFilename);
|
std::ofstream jsonFile(jsonFilename);
|
||||||
jsonFile << json;
|
jsonFile << json;
|
||||||
|
jsonFile.close();
|
||||||
// std::cout << "Saved simulation job as:" << jsonFilename << std::endl;
|
// std::cout << "Saved simulation job as:" << jsonFilename << std::endl;
|
||||||
|
|
||||||
return returnValue;
|
return returnValue;
|
||||||
|
@ -518,9 +520,12 @@ struct SimulationResults
|
||||||
const std::string filename(getLabel() + "_displacements.eigenBin");
|
const std::string filename(getLabel() + "_displacements.eigenBin");
|
||||||
|
|
||||||
Eigen::MatrixXd m = Utilities::toEigenMatrix(displacements);
|
Eigen::MatrixXd m = Utilities::toEigenMatrix(displacements);
|
||||||
Eigen::write_binary(std::filesystem::path(outputFolderPath).append(filename).string(), m);
|
const std::filesystem::path resultsFolderPath(
|
||||||
|
std::filesystem::path(outputFolder).append("Results"));
|
||||||
|
std::filesystem::create_directories(resultsFolderPath);
|
||||||
|
Eigen::write_binary(std::filesystem::path(resultsFolderPath).append(filename).string(), m);
|
||||||
|
|
||||||
saveDeformedModel(outputFolderPath.string());
|
saveDeformedModel(resultsFolderPath.string());
|
||||||
}
|
}
|
||||||
|
|
||||||
// The comparison of the results happens comparing the 6-dof nodal
|
// The comparison of the results happens comparing the 6-dof nodal
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
#include "topologyenumerator.hpp"
|
#include "topologyenumerator.hpp"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <boost/graph/biconnected_components.hpp>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
const bool debugIsOn{true};
|
const bool debugIsOn{false};
|
||||||
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) {
|
||||||
|
@ -123,7 +124,7 @@ void TopologyEnumerator::computeValidPatterns(const std::vector<size_t> &reduced
|
||||||
// statistics.numberOfValidEdges = validEdges.size();
|
// statistics.numberOfValidEdges = validEdges.size();
|
||||||
|
|
||||||
// Find pairs of intersecting edges
|
// Find pairs of intersecting edges
|
||||||
std::unordered_map<size_t, std::unordered_set<size_t>> intersectingEdges
|
const std::unordered_map<size_t, std::unordered_set<size_t>> intersectingEdges
|
||||||
= patternAllValidEdges.getIntersectingEdges(statistics.numberOfIntersectingEdgePairs);
|
= patternAllValidEdges.getIntersectingEdges(statistics.numberOfIntersectingEdgePairs);
|
||||||
if (debugIsOn) {
|
if (debugIsOn) {
|
||||||
auto intersectingEdgesPath = std::filesystem::path(resultsPath)
|
auto intersectingEdgesPath = std::filesystem::path(resultsPath)
|
||||||
|
@ -170,19 +171,19 @@ 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(); numberOfEdges++) {
|
||||||
std::cout << "Computing " + setupString << " with " << numberOfEdges << " edges."
|
std::cout << "Computing " + setupString << " with " << numberOfEdges << " edges."
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
|
|
||||||
auto perEdgeResultPath = std::filesystem::path(resultsPath)
|
auto perEdgeResultPath = std::filesystem::path(resultsPath)
|
||||||
.append(std::to_string(numberOfEdges));
|
.append(std::to_string(numberOfEdges));
|
||||||
if (std::filesystem::exists(perEdgeResultPath)) {
|
if (std::filesystem::exists(perEdgeResultPath)) {
|
||||||
if (debugIsOn) {
|
// if (debugIsOn) {
|
||||||
std::filesystem::remove_all(perEdgeResultPath);
|
std::filesystem::remove_all(perEdgeResultPath);
|
||||||
|
|
||||||
} else {
|
// } else {
|
||||||
continue;
|
// continue;
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
std::filesystem::create_directory(perEdgeResultPath);
|
std::filesystem::create_directory(perEdgeResultPath);
|
||||||
computeValidPatterns(numberOfNodesPerSlot,
|
computeValidPatterns(numberOfNodesPerSlot,
|
||||||
|
@ -434,7 +435,7 @@ void TopologyEnumerator::computeValidPatterns(
|
||||||
// std::string previousPatternBinaryRepresentation(validEdges.size(),'0');
|
// std::string previousPatternBinaryRepresentation(validEdges.size(),'0');
|
||||||
size_t patternIndex = 0;
|
size_t patternIndex = 0;
|
||||||
bool validPatternsExist = false;
|
bool validPatternsExist = false;
|
||||||
const bool exportTilledPattern = false;
|
const bool exportTilledPattern = debugIsOn;
|
||||||
const bool saveCompressedFormat = false;
|
const bool saveCompressedFormat = false;
|
||||||
do {
|
do {
|
||||||
patternIndex++;
|
patternIndex++;
|
||||||
|
@ -479,6 +480,7 @@ void TopologyEnumerator::computeValidPatterns(
|
||||||
const bool tiledPatternHasEdgesWithAngleSmallerThanThreshold
|
const bool tiledPatternHasEdgesWithAngleSmallerThanThreshold
|
||||||
= patternGeometry.hasAngleSmallerThanThreshold(numberOfNodesPerSlot, 15);
|
= patternGeometry.hasAngleSmallerThanThreshold(numberOfNodesPerSlot, 15);
|
||||||
if (tiledPatternHasEdgesWithAngleSmallerThanThreshold) {
|
if (tiledPatternHasEdgesWithAngleSmallerThanThreshold) {
|
||||||
|
statistics.numberOfPatternsViolatingAngleThreshold++;
|
||||||
if (debugIsOn /*|| savePlyFiles*/) {
|
if (debugIsOn /*|| savePlyFiles*/) {
|
||||||
if (savePlyFiles) {
|
if (savePlyFiles) {
|
||||||
exportPattern(std::filesystem::path(resultsPath)
|
exportPattern(std::filesystem::path(resultsPath)
|
||||||
|
@ -494,6 +496,7 @@ void TopologyEnumerator::computeValidPatterns(
|
||||||
const bool tiledPatternHasNodeWithValenceGreaterThanDesired
|
const bool tiledPatternHasNodeWithValenceGreaterThanDesired
|
||||||
= patternGeometry.hasValenceGreaterThan(numberOfNodesPerSlot, 6);
|
= patternGeometry.hasValenceGreaterThan(numberOfNodesPerSlot, 6);
|
||||||
if (tiledPatternHasNodeWithValenceGreaterThanDesired) {
|
if (tiledPatternHasNodeWithValenceGreaterThanDesired) {
|
||||||
|
statistics.numberOfPatternsViolatingValenceThreshold++;
|
||||||
if (debugIsOn) {
|
if (debugIsOn) {
|
||||||
if (savePlyFiles) {
|
if (savePlyFiles) {
|
||||||
auto highValencePath = std::filesystem::path(resultsPath)
|
auto highValencePath = std::filesystem::path(resultsPath)
|
||||||
|
@ -510,8 +513,82 @@ void TopologyEnumerator::computeValidPatterns(
|
||||||
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.isFullyConnectedWhenTiled();
|
const bool hasFloatingComponents = !patternGeometry.isFullyConnectedWhenTiled();
|
||||||
FlatPatternTopology topology(numberOfNodesPerSlot, patternEdges);
|
|
||||||
const bool hasArticulationPoints = topology.containsArticulationPoints();
|
PatternGeometry fanPatternGeometry = PatternGeometry::createFan(patternGeometry);
|
||||||
|
const int interfaceNodeVi = 3;
|
||||||
|
std::vector<PatternGeometry::EdgeType *> connectedEdges;
|
||||||
|
vcg::edge::VEStarVE(&fanPatternGeometry.vert[interfaceNodeVi], connectedEdges);
|
||||||
|
if (!connectedEdges.empty()) {
|
||||||
|
for (int i = 1; i < 6; i++) {
|
||||||
|
vcg::tri::Allocator<PatternGeometry>::AddEdge(fanPatternGeometry,
|
||||||
|
interfaceNodeVi
|
||||||
|
+ (i - 1) * patternGeometry.VN(),
|
||||||
|
interfaceNodeVi
|
||||||
|
+ i * patternGeometry.VN());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vcg::tri::Clean<PatternGeometry>::MergeCloseVertex(fanPatternGeometry, 0.0000005);
|
||||||
|
vcg::tri::Allocator<PatternGeometry>::CompactEveryVector(fanPatternGeometry);
|
||||||
|
vcg::tri::UpdateTopology<PatternGeometry>::VertexEdge(fanPatternGeometry);
|
||||||
|
vcg::tri::UpdateTopology<PatternGeometry>::EdgeEdge(fanPatternGeometry);
|
||||||
|
// for (PatternGeometry::VertexType &v : tilledPatternGeometry.vert) {
|
||||||
|
// std::vector<PatternGeometry::EdgeType *> connectedEdges;
|
||||||
|
// vcg::edge::VEStarVE(&v, connectedEdges);
|
||||||
|
// if (connectedEdges.size() == 1) {
|
||||||
|
// vcg::tri::Allocator<PatternGeometry>::DeleteVertex(tilledPatternGeometry, v);
|
||||||
|
// vcg::tri::Allocator<PatternGeometry>::DeleteEdge(tilledPatternGeometry,
|
||||||
|
// *connectedEdges[0]);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// // vcg::tri::Allocator<PatternGeometry>::CompactEveryVector(tilledPatternGeometry);
|
||||||
|
// fanPatternGeometry.updateEigenEdgeAndVertices();
|
||||||
|
|
||||||
|
BoostGraph fanPatternGraph(fanPatternGeometry.VN());
|
||||||
|
// std::cout << "Edges:";
|
||||||
|
for (const PatternGeometry::EdgeType &e : fanPatternGeometry.edge) {
|
||||||
|
if (e.IsD() || e.cV(0)->IsD() || e.cV(1)->IsD()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const int vi0 = fanPatternGeometry.getIndex(e.cV(0));
|
||||||
|
const int vi1 = fanPatternGeometry.getIndex(e.cV(1));
|
||||||
|
boost::add_edge(vi0, vi1, fanPatternGraph);
|
||||||
|
// std::cout << vi0 << "," << vi1 << " ";
|
||||||
|
}
|
||||||
|
// std::cout << std::endl;
|
||||||
|
|
||||||
|
std::vector<vertex_t> articulationPoints;
|
||||||
|
boost::articulation_points(fanPatternGraph, std::back_inserter(articulationPoints));
|
||||||
|
const bool hasArticulationPoints = !articulationPoints.empty();
|
||||||
|
// if (hasArticulationPoints /*&& !patternContainsIntersectingEdges
|
||||||
|
// && !tiledPatternHasDanglingEdges && !hasFloatingComponents
|
||||||
|
// && !tiledPatternHasNodeWithValenceGreaterThanDesired
|
||||||
|
// && !tiledPatternHasEdgesWithAngleSmallerThanThreshold*/) {
|
||||||
|
// for (PatternGeometry::VertexType &v : patternGeometry.vert) {
|
||||||
|
// v.C() = vcg::Color4b::Yellow;
|
||||||
|
// }
|
||||||
|
// // std::cout << "AP:";
|
||||||
|
// for (const int articulationPointVi : articulationPoints) {
|
||||||
|
// if (articulationPointVi >= patternGeometry.VN()) {
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
// // std::cout << articulationPointVi << " ";
|
||||||
|
// patternGeometry.vert[articulationPointVi].C() = vcg::Color4b::Red;
|
||||||
|
// }
|
||||||
|
// PatternGeometry tilledPatternGeometry = PatternGeometry::createTile(patternGeometry);
|
||||||
|
// // std::cout << std::endl;
|
||||||
|
// std::vector<glm::vec3> fanVertexColors(tilledPatternGeometry.VN(), glm::vec3(0, 0, 1));
|
||||||
|
// for (const PatternGeometry::VertexType &v : tilledPatternGeometry.vert) {
|
||||||
|
// 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.registerForDrawing()
|
||||||
|
// // ->addNodeColorQuantity("ap_tilled", fanVertexColors)
|
||||||
|
// // ->setEnabled(true);
|
||||||
|
// // polyscope::show();
|
||||||
|
// // tilledPatternGeometry.unregister();
|
||||||
|
// }
|
||||||
// duplicated here
|
// duplicated here
|
||||||
// Check dangling edges with vcg method
|
// Check dangling edges with vcg method
|
||||||
// const bool vcg_tiledPatternHasDangling =
|
// const bool vcg_tiledPatternHasDangling =
|
||||||
|
@ -618,7 +695,7 @@ void TopologyEnumerator::computeValidPatterns(
|
||||||
// if(patternName=='2055'){
|
// if(patternName=='2055'){
|
||||||
// PatternGeometry tiledPatternGeometry = PatternGeometry::createTile(
|
// PatternGeometry tiledPatternGeometry = PatternGeometry::createTile(
|
||||||
// patternGeometry); // the marked nodes of hasDanglingEdges are
|
// patternGeometry); // the marked nodes of hasDanglingEdges are
|
||||||
// tiledPatternGeometry.registerForDrawing();
|
// tiledPatternGeometry.registerForDrawing(std::array<double, 3>{0, 0, 1});
|
||||||
// polyscope::show();
|
// polyscope::show();
|
||||||
// tiledPatternGeometry.unregister();
|
// tiledPatternGeometry.unregister();
|
||||||
// }
|
// }
|
||||||
|
@ -656,6 +733,7 @@ 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
|
||||||
{
|
{
|
||||||
|
|
|
@ -62,6 +62,8 @@ class TopologyEnumerator {
|
||||||
size_t numberOfPatternsWithMoreThanASingleCC{0};
|
size_t numberOfPatternsWithMoreThanASingleCC{0};
|
||||||
size_t numberOfPatternsWithADanglingEdgeOrNode{0};
|
size_t numberOfPatternsWithADanglingEdgeOrNode{0};
|
||||||
size_t numberOfPatternsWithArticulationPoints{0};
|
size_t numberOfPatternsWithArticulationPoints{0};
|
||||||
|
size_t numberOfPatternsViolatingAngleThreshold{0};
|
||||||
|
size_t numberOfPatternsViolatingValenceThreshold{0};
|
||||||
size_t numberOfValidPatterns{0};
|
size_t numberOfValidPatterns{0};
|
||||||
nlohmann::json convertToJson() const
|
nlohmann::json convertToJson() const
|
||||||
{
|
{
|
||||||
|
@ -79,6 +81,8 @@ class TopologyEnumerator {
|
||||||
json["numPatternsWithDangling"] = numberOfPatternsWithADanglingEdgeOrNode;
|
json["numPatternsWithDangling"] = numberOfPatternsWithADanglingEdgeOrNode;
|
||||||
json["numPatternsWithArticulationPoints"] = numberOfPatternsWithArticulationPoints;
|
json["numPatternsWithArticulationPoints"] = numberOfPatternsWithArticulationPoints;
|
||||||
json["numValidPatterns"] = numberOfValidPatterns;
|
json["numValidPatterns"] = numberOfValidPatterns;
|
||||||
|
json["violatingAngle"] = numberOfPatternsViolatingAngleThreshold;
|
||||||
|
json["violatingValence"] = numberOfPatternsViolatingValenceThreshold;
|
||||||
|
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
@ -141,6 +145,8 @@ class TopologyEnumerator {
|
||||||
numberOfPatternsWithADanglingEdgeOrNode = 0;
|
numberOfPatternsWithADanglingEdgeOrNode = 0;
|
||||||
numberOfPatternsWithArticulationPoints = 0;
|
numberOfPatternsWithArticulationPoints = 0;
|
||||||
numberOfValidPatterns = 0;
|
numberOfValidPatterns = 0;
|
||||||
|
numberOfPatternsViolatingAngleThreshold = 0;
|
||||||
|
numberOfPatternsViolatingValenceThreshold = 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -116,6 +116,7 @@ PatternGeometry PatternGeometry::createTile(PatternGeometry &pattern) {
|
||||||
// tile.vert[vi].C() = vcg::Color4b::Blue;
|
// tile.vert[vi].C() = vcg::Color4b::Blue;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
tile.setLabel("tilled_" + pattern.getLabel());
|
||||||
tile.updateEigenEdgeAndVertices();
|
tile.updateEigenEdgeAndVertices();
|
||||||
return tile;
|
return tile;
|
||||||
}
|
}
|
||||||
|
@ -674,10 +675,9 @@ bool PatternGeometry::hasIntersectingEdges(
|
||||||
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.count(validEdgeIndex) != 0) {
|
&& intersectingEdges.contains(validEdgeIndex)) {
|
||||||
for (auto edgeIndexIt =
|
for (auto edgeIndexIt = intersectingEdges.find(validEdgeIndex)->second.begin();
|
||||||
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') {
|
||||||
|
|
|
@ -5,14 +5,18 @@
|
||||||
|
|
||||||
FlatPatternTopology::FlatPatternTopology() {}
|
FlatPatternTopology::FlatPatternTopology() {}
|
||||||
|
|
||||||
FlatPatternTopology::FlatPatternTopology(
|
FlatPatternTopology::FlatPatternTopology(const std::vector<size_t> &numberOfNodesPerSlot,
|
||||||
const std::vector<size_t> &numberOfNodesPerSlot,
|
|
||||||
const std::vector<vcg::Point2i> &edges)
|
const std::vector<vcg::Point2i> &edges)
|
||||||
: numberOfNodesPerSlot(numberOfNodesPerSlot) {
|
: numberOfNodesPerSlot(numberOfNodesPerSlot)
|
||||||
pattern = BoostGraph(std::accumulate(numberOfNodesPerSlot.begin(),
|
{
|
||||||
numberOfNodesPerSlot.end(), 0));
|
pattern = BoostGraph(
|
||||||
|
std::accumulate(numberOfNodesPerSlot.begin(), numberOfNodesPerSlot.end(), 0));
|
||||||
|
isAdjacentTo.resize(boost::num_vertices(pattern),
|
||||||
|
std::vector<bool>(boost::num_vertices(pattern), false));
|
||||||
for (const vcg::Point2i &e : edges) {
|
for (const vcg::Point2i &e : edges) {
|
||||||
boost::add_edge(e[0], e[1], pattern);
|
boost::add_edge(e[0], e[1], pattern);
|
||||||
|
isAdjacentTo[e[0]][e[1]] = true;
|
||||||
|
isAdjacentTo[e[1]][e[0]] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructNodeToSlotMap();
|
constructNodeToSlotMap();
|
||||||
|
@ -20,19 +24,21 @@ FlatPatternTopology::FlatPatternTopology(
|
||||||
constructCorresponginNodeMap();
|
constructCorresponginNodeMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FlatPatternTopology::containsArticulationPoints() const {
|
bool FlatPatternTopology::containsArticulationPoints(std::vector<int> &articulationPointsVi) const
|
||||||
assert(numberOfNodesPerSlot.size() == 7 && numberOfNodesPerSlot[4] < 2 &&
|
{
|
||||||
!nodeToSlot.empty() && !correspondingNode.empty());
|
assert(numberOfNodesPerSlot.size() == 7 && numberOfNodesPerSlot[4] < 2 && !nodeToSlot.empty()
|
||||||
|
&& !correspondingNode.empty());
|
||||||
BoostGraph copyOfPattern(pattern);
|
BoostGraph copyOfPattern(pattern);
|
||||||
// std::cout << std::endl;
|
// std::cout << std::endl;
|
||||||
std::vector<int> componentsBefore(boost::num_vertices(copyOfPattern));
|
// std::vector<int> componentsBefore(boost::num_vertices(copyOfPattern));
|
||||||
size_t num_components =
|
// size_t num_components = boost::connected_components(copyOfPattern, &componentsBefore[0]);
|
||||||
boost::connected_components(copyOfPattern, &componentsBefore[0]);
|
|
||||||
// std::cout << "Number of cc before:" << num_components << std::endl;
|
// std::cout << "Number of cc before:" << num_components << std::endl;
|
||||||
// printGraph(copyOfPattern);
|
// printGraph(copyOfPattern);
|
||||||
|
|
||||||
copyOfPattern = constructRotationallySymmetricPattern(
|
copyOfPattern = constructRotationallySymmetricPattern(copyOfPattern,
|
||||||
copyOfPattern, slotToNode, nodeToSlot, correspondingNode);
|
slotToNode,
|
||||||
|
nodeToSlot,
|
||||||
|
correspondingNode);
|
||||||
// // Remove edges connected to the bottom edge node
|
// // Remove edges connected to the bottom edge node
|
||||||
// assert(slotToNode.find(4) != slotToNode.end());
|
// assert(slotToNode.find(4) != slotToNode.end());
|
||||||
// std::unordered_set<size_t> bottomEdgeNodeSet =
|
// std::unordered_set<size_t> bottomEdgeNodeSet =
|
||||||
|
@ -40,25 +46,26 @@ bool FlatPatternTopology::containsArticulationPoints() const {
|
||||||
// size_t bottomEdgeNodeIndex = *bottomEdgeNodeSet.begin();
|
// size_t bottomEdgeNodeIndex = *bottomEdgeNodeSet.begin();
|
||||||
// boost::clear_vertex(bottomEdgeNodeIndex, copyOfPattern);
|
// boost::clear_vertex(bottomEdgeNodeIndex, copyOfPattern);
|
||||||
|
|
||||||
std::vector<int> componentsAfter(boost::num_vertices(copyOfPattern));
|
// std::vector<int> componentsAfter(boost::num_vertices(copyOfPattern));
|
||||||
num_components =
|
// num_components = boost::connected_components(copyOfPattern, &componentsAfter[0]);
|
||||||
boost::connected_components(copyOfPattern, &componentsAfter[0]);
|
|
||||||
// std::cout << "Number of cc after:" << num_components << std::endl;
|
// std::cout << "Number of cc after:" << num_components << std::endl;
|
||||||
// printGraph(copyOfPattern);
|
// printGraph(copyOfPattern);
|
||||||
|
|
||||||
// Compute articulation points on the edited graph
|
// Compute articulation points on the edited graph
|
||||||
std::vector<vertex_t> articulationPoints;
|
std::vector<vertex_t> articulationPoints;
|
||||||
boost::articulation_points(copyOfPattern,
|
boost::articulation_points(copyOfPattern, std::back_inserter(articulationPoints));
|
||||||
std::back_inserter(articulationPoints));
|
for (const auto apVi : articulationPoints) {
|
||||||
|
articulationPointsVi.push_back(static_cast<int>(apVi));
|
||||||
|
}
|
||||||
// std::cout << "Found " << articulationPoints.size()
|
// std::cout << "Found " << articulationPoints.size()
|
||||||
// << " articulation points.\n";
|
// << " articulation points.\n";
|
||||||
// size_t numberOfNonValidArticulationPoints = 0;
|
// size_t numberOfNonValidArticulationPoints = 0;
|
||||||
for (std::size_t i = 0; i < articulationPoints.size(); ++i) {
|
// for (std::size_t i = 0; i < articulationPoints.size(); ++i) {
|
||||||
// std::cout << articulationPoints[i] << std::endl;
|
// std::cout << articulationPoints[i] << std::endl;
|
||||||
// if (boost::out_degree(articulationPoints[i], copyOfPattern) < 3) {
|
// if (boost::out_degree(articulationPoints[i], copyOfPattern) < 3) {
|
||||||
// numberOfNonValidArticulationPoints++;
|
// numberOfNonValidArticulationPoints++;
|
||||||
// }
|
// }
|
||||||
}
|
// }
|
||||||
// if (numberOfNonValidArticulationPoints == articulationPoints.size()) {
|
// if (numberOfNonValidArticulationPoints == articulationPoints.size()) {
|
||||||
// return false;
|
// return false;
|
||||||
// }
|
// }
|
||||||
|
@ -139,6 +146,29 @@ void FlatPatternTopology::constructCorresponginNodeMap() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FlatPatternTopology::pathExists(int src, int dest) const
|
||||||
|
{
|
||||||
|
const int N = boost::num_vertices(pattern);
|
||||||
|
std::vector<bool> visited(N, false);
|
||||||
|
visited[src] = true;
|
||||||
|
std::stack<int> next;
|
||||||
|
next.push(src);
|
||||||
|
|
||||||
|
while (!next.empty()) {
|
||||||
|
int cv = next.top();
|
||||||
|
next.pop();
|
||||||
|
|
||||||
|
for (int nv = 0; nv < N; ++nv) {
|
||||||
|
if (!visited[nv] && isAdjacentTo[cv][nv] == 1) {
|
||||||
|
visited[nv] = true;
|
||||||
|
next.push(nv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// dest was reached from src?
|
||||||
|
return visited[dest];
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* In this function I create an "extended" pattern of the one in the base
|
* In this function I create an "extended" pattern of the one in the base
|
||||||
* triangle by:
|
* triangle by:
|
||||||
|
@ -152,16 +182,24 @@ BoostGraph FlatPatternTopology::constructRotationallySymmetricPattern(
|
||||||
const BoostGraph &pattern,
|
const BoostGraph &pattern,
|
||||||
const std::unordered_map<size_t, std::unordered_set<size_t>> &slotToNodes,
|
const std::unordered_map<size_t, std::unordered_set<size_t>> &slotToNodes,
|
||||||
const std::unordered_map<size_t, size_t> &nodeToSlot,
|
const std::unordered_map<size_t, size_t> &nodeToSlot,
|
||||||
const std::unordered_map<size_t, size_t> &correspondingNode) {
|
const std::unordered_map<size_t, size_t> &correspondingNode) const
|
||||||
|
{
|
||||||
BoostGraph rotationallySymmetricPattern(pattern);
|
BoostGraph rotationallySymmetricPattern(pattern);
|
||||||
|
|
||||||
|
// for (const std::pair<size_t, size_t> &correspondingPair : correspondingNode) {
|
||||||
|
// const auto v0 = boost::vertex(correspondingPair.first, pattern);
|
||||||
|
// const auto v1 = boost::vertex(correspondingPair.second, pattern);
|
||||||
|
// if (boost::degree(v0, pattern) != 0 || boost::degree(v1, pattern) != 0) {
|
||||||
|
// boost::add_edge(v0, v1, rotationallySymmetricPattern);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
boost::graph_traits<BoostGraph>::out_edge_iterator ei, ei_end;
|
boost::graph_traits<BoostGraph>::out_edge_iterator ei, ei_end;
|
||||||
// Copy edges that lay on the left edge to the right edge
|
// Copy edges that lay on the left edge to the right edge
|
||||||
const auto slot3NodesPairIt = slotToNodes.find(3);
|
const auto slot3NodesPairIt = slotToNodes.find(3);
|
||||||
if (slot3NodesPairIt != slotToNodes.end()) {
|
if (slot3NodesPairIt != slotToNodes.end()) {
|
||||||
for (const size_t &nodeIndex : slot3NodesPairIt->second) {
|
for (const size_t &nodeIndex : slot3NodesPairIt->second) {
|
||||||
for (boost::tie(ei, ei_end) = boost::out_edges(nodeIndex, pattern);
|
for (boost::tie(ei, ei_end) = boost::out_edges(nodeIndex, pattern); ei != ei_end; ++ei) {
|
||||||
ei != ei_end; ++ei) {
|
|
||||||
auto vt = boost::target(*ei, pattern);
|
auto vt = boost::target(*ei, pattern);
|
||||||
const auto vtNodeSlotPairIt = nodeToSlot.find(vt);
|
const auto vtNodeSlotPairIt = nodeToSlot.find(vt);
|
||||||
assert(vtNodeSlotPairIt != nodeToSlot.end());
|
assert(vtNodeSlotPairIt != nodeToSlot.end());
|
||||||
|
@ -172,25 +210,24 @@ BoostGraph FlatPatternTopology::constructRotationallySymmetricPattern(
|
||||||
assert(correspondingNodeIndexIt != correspondingNode.end());
|
assert(correspondingNodeIndexIt != correspondingNode.end());
|
||||||
auto correspondingVtIt = correspondingNode.find(vt);
|
auto correspondingVtIt = correspondingNode.find(vt);
|
||||||
assert(correspondingVtIt != correspondingNode.end() || vtSlot == 0);
|
assert(correspondingVtIt != correspondingNode.end() || vtSlot == 0);
|
||||||
const size_t &correspondingNodeIndex =
|
const size_t &correspondingNodeIndex = correspondingNodeIndexIt->second;
|
||||||
correspondingNodeIndexIt->second;
|
|
||||||
size_t correspondingVt = 0;
|
size_t correspondingVt = 0;
|
||||||
if (correspondingVtIt != correspondingNode.end()) {
|
if (correspondingVtIt != correspondingNode.end()) {
|
||||||
correspondingVt = correspondingVtIt->second;
|
correspondingVt = correspondingVtIt->second;
|
||||||
}
|
}
|
||||||
boost::add_edge(correspondingNodeIndex, correspondingVt,
|
boost::add_edge(correspondingNodeIndex,
|
||||||
|
correspondingVt,
|
||||||
rotationallySymmetricPattern);
|
rotationallySymmetricPattern);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy edges that lay on the right edge to the left edge
|
// // Copy edges that lay on the right edge to the left edge
|
||||||
const auto slot5NodesPairIt = slotToNodes.find(5);
|
const auto slot5NodesPairIt = slotToNodes.find(5);
|
||||||
if (slot5NodesPairIt != slotToNodes.end()) {
|
if (slot5NodesPairIt != slotToNodes.end()) {
|
||||||
for (const size_t &nodeIndex : slot5NodesPairIt->second) {
|
for (const size_t &nodeIndex : slot5NodesPairIt->second) {
|
||||||
for (boost::tie(ei, ei_end) = boost::out_edges(nodeIndex, pattern);
|
for (boost::tie(ei, ei_end) = boost::out_edges(nodeIndex, pattern); ei != ei_end; ++ei) {
|
||||||
ei != ei_end; ++ei) {
|
|
||||||
auto vt = boost::target(*ei, pattern);
|
auto vt = boost::target(*ei, pattern);
|
||||||
const auto vtNodeSlotPairIt = nodeToSlot.find(vt);
|
const auto vtNodeSlotPairIt = nodeToSlot.find(vt);
|
||||||
assert(vtNodeSlotPairIt != nodeToSlot.end());
|
assert(vtNodeSlotPairIt != nodeToSlot.end());
|
||||||
|
@ -201,13 +238,13 @@ BoostGraph FlatPatternTopology::constructRotationallySymmetricPattern(
|
||||||
assert(correspondingNodeIndexIt != correspondingNode.end());
|
assert(correspondingNodeIndexIt != correspondingNode.end());
|
||||||
auto correspondingVtIt = correspondingNode.find(vt);
|
auto correspondingVtIt = correspondingNode.find(vt);
|
||||||
assert(correspondingVtIt != correspondingNode.end() || vtSlot == 0);
|
assert(correspondingVtIt != correspondingNode.end() || vtSlot == 0);
|
||||||
const size_t &correspondingNodeIndex =
|
const size_t &correspondingNodeIndex = correspondingNodeIndexIt->second;
|
||||||
correspondingNodeIndexIt->second;
|
|
||||||
size_t correspondingVt = 0;
|
size_t correspondingVt = 0;
|
||||||
if (correspondingVtIt != correspondingNode.end()) {
|
if (correspondingVtIt != correspondingNode.end()) {
|
||||||
correspondingVt = correspondingVtIt->second;
|
correspondingVt = correspondingVtIt->second;
|
||||||
}
|
}
|
||||||
boost::add_edge(correspondingNodeIndex, correspondingVt,
|
boost::add_edge(correspondingNodeIndex,
|
||||||
|
correspondingVt,
|
||||||
rotationallySymmetricPattern);
|
rotationallySymmetricPattern);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -235,37 +272,52 @@ BoostGraph FlatPatternTopology::constructRotationallySymmetricPattern(
|
||||||
}
|
}
|
||||||
// Add all slot3 nodes that have a connection to the "inside"
|
// Add all slot3 nodes that have a connection to the "inside"
|
||||||
if (slot3NodesPairIt != slotToNodes.end()) {
|
if (slot3NodesPairIt != slotToNodes.end()) {
|
||||||
|
externallyConnectedNodes.insert(slot3NodesPairIt->second.begin(),
|
||||||
|
slot3NodesPairIt->second.end());
|
||||||
for (const size_t &nodeIndex : slot3NodesPairIt->second) {
|
for (const size_t &nodeIndex : slot3NodesPairIt->second) {
|
||||||
for (boost::tie(ei, ei_end) = boost::out_edges(nodeIndex, pattern);
|
|
||||||
ei != ei_end; ++ei) {
|
|
||||||
auto vt = boost::target(*ei, pattern);
|
|
||||||
const auto vtNodeSlotPairIt = nodeToSlot.find(vt);
|
|
||||||
assert(vtNodeSlotPairIt != nodeToSlot.end());
|
|
||||||
const size_t vtSlot = vtNodeSlotPairIt->second;
|
|
||||||
if (vtSlot != 3) {
|
|
||||||
auto correspondingNodePairIt = correspondingNode.find(nodeIndex);
|
auto correspondingNodePairIt = correspondingNode.find(nodeIndex);
|
||||||
assert(correspondingNodePairIt != correspondingNode.end());
|
// for (boost::tie(ei, ei_end) = boost::out_edges(nodeIndex, pattern); ei != ei_end; ++ei) {
|
||||||
externallyConnectedNodes.insert(correspondingNodePairIt->second);
|
// auto vt = boost::target(*ei, pattern);
|
||||||
}
|
// const auto vtNodeSlotPairIt = nodeToSlot.find(vt);
|
||||||
}
|
// assert(vtNodeSlotPairIt != nodeToSlot.end());
|
||||||
|
// const size_t vtSlot = vtNodeSlotPairIt->second;
|
||||||
|
// if (vtSlot != 3) {
|
||||||
|
// assert(correspondingNodePairIt != correspondingNode.end());
|
||||||
|
// externallyConnectedNodes.insert(correspondingNodePairIt->second);
|
||||||
|
// // boost::add_edge(correspondingNodePairIt->second,
|
||||||
|
// // vt,
|
||||||
|
// // rotationallySymmetricPattern);
|
||||||
|
// // boost::add_edge(nodeIndex, vt, rotationallySymmetricPattern);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
boost::add_edge(correspondingNodePairIt->second,
|
||||||
|
nodeIndex,
|
||||||
|
rotationallySymmetricPattern);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Add all slot5 nodes that have a connection to the "inside"
|
// Add all slot5 nodes that have a connection to the "inside"
|
||||||
if (slot5NodesPairIt != slotToNodes.end()) {
|
if (slot5NodesPairIt != slotToNodes.end()) {
|
||||||
for (const size_t &nodeIndex : slot5NodesPairIt->second) {
|
for (const size_t &nodeIndex : slot5NodesPairIt->second) {
|
||||||
for (boost::tie(ei, ei_end) = boost::out_edges(nodeIndex, pattern);
|
|
||||||
ei != ei_end; ++ei) {
|
|
||||||
auto vt = boost::target(*ei, pattern);
|
|
||||||
const auto vtNodeSlotPairIt = nodeToSlot.find(vt);
|
|
||||||
assert(vtNodeSlotPairIt != nodeToSlot.end());
|
|
||||||
const size_t vtSlot = vtNodeSlotPairIt->second;
|
|
||||||
if (vtSlot != 5) {
|
|
||||||
auto correspondingNodePairIt = correspondingNode.find(nodeIndex);
|
auto correspondingNodePairIt = correspondingNode.find(nodeIndex);
|
||||||
assert(correspondingNodePairIt != correspondingNode.end());
|
// for (boost::tie(ei, ei_end) = boost::out_edges(nodeIndex, pattern); ei != ei_end; ++ei) {
|
||||||
externallyConnectedNodes.insert(correspondingNodePairIt->second);
|
// auto vt = boost::target(*ei, pattern);
|
||||||
}
|
// const auto vtNodeSlotPairIt = nodeToSlot.find(vt);
|
||||||
}
|
// assert(vtNodeSlotPairIt != nodeToSlot.end());
|
||||||
|
// const size_t vtSlot = vtNodeSlotPairIt->second;
|
||||||
|
// if (vtSlot != 5) {
|
||||||
|
// assert(correspondingNodePairIt != correspondingNode.end());
|
||||||
|
// externallyConnectedNodes.insert(correspondingNodePairIt->second);
|
||||||
|
// boost::add_edge(correspondingNodePairIt->second,
|
||||||
|
// vt,
|
||||||
|
// rotationallySymmetricPattern);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
boost::add_edge(correspondingNodePairIt->second,
|
||||||
|
nodeIndex,
|
||||||
|
rotationallySymmetricPattern);
|
||||||
}
|
}
|
||||||
|
externallyConnectedNodes.insert(slot5NodesPairIt->second.begin(),
|
||||||
|
slot5NodesPairIt->second.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
// connecting all is wrong. Maybe I should check whether the external nodes
|
// connecting all is wrong. Maybe I should check whether the external nodes
|
||||||
|
@ -276,23 +328,33 @@ BoostGraph FlatPatternTopology::constructRotationallySymmetricPattern(
|
||||||
const size_t numberOfExternalEdges = n * (n - 1) / 2;
|
const size_t numberOfExternalEdges = n * (n - 1) / 2;
|
||||||
// Connect all external nodes with each other
|
// Connect all external nodes with each other
|
||||||
for (size_t edgeIndex = 0; edgeIndex < numberOfExternalEdges; edgeIndex++) {
|
for (size_t edgeIndex = 0; edgeIndex < numberOfExternalEdges; edgeIndex++) {
|
||||||
const int sei0 =
|
const int sei0 = n - 2
|
||||||
n - 2 -
|
- std::floor(std::sqrt(-8 * edgeIndex + 4 * n * (n - 1) - 7) / 2.0 - 0.5);
|
||||||
std::floor(std::sqrt(-8 * edgeIndex + 4 * n * (n - 1) - 7) / 2.0 - 0.5);
|
const int sei1 = edgeIndex + sei0 + 1 - n * (n - 1) / 2 + (n - sei0) * ((n - sei0) - 1) / 2;
|
||||||
const int sei1 = edgeIndex + sei0 + 1 - n * (n - 1) / 2 +
|
|
||||||
(n - sei0) * ((n - sei0) - 1) / 2;
|
|
||||||
const size_t ni0 = *std::next(externallyConnectedNodes.begin(), sei0);
|
const size_t ni0 = *std::next(externallyConnectedNodes.begin(), sei0);
|
||||||
const size_t ni1 = *std::next(externallyConnectedNodes.begin(), sei1);
|
const size_t ni1 = *std::next(externallyConnectedNodes.begin(), sei1);
|
||||||
|
if (correspondingNode.contains(ni0) || correspondingNode.contains(ni1)) {
|
||||||
|
if (correspondingNode.contains(ni0) && correspondingNode.contains(ni1)
|
||||||
|
&& pathExists(correspondingNode.at(ni0), correspondingNode.at(ni1))) {
|
||||||
boost::add_edge(ni0, ni1, rotationallySymmetricPattern);
|
boost::add_edge(ni0, ni1, rotationallySymmetricPattern);
|
||||||
|
} else if (!correspondingNode.contains(ni0) && correspondingNode.contains(ni1)
|
||||||
|
&& pathExists(ni0, correspondingNode.at(ni1))) {
|
||||||
|
boost::add_edge(ni0, ni1, rotationallySymmetricPattern);
|
||||||
|
} else if (correspondingNode.contains(ni0) && !correspondingNode.contains(ni1)
|
||||||
|
&& pathExists(correspondingNode.at(ni0), ni1)) {
|
||||||
|
boost::add_edge(ni0, ni1, rotationallySymmetricPattern);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return rotationallySymmetricPattern;
|
return rotationallySymmetricPattern;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlatPatternTopology::printGraph(const BoostGraph &g) const {
|
void FlatPatternTopology::printGraph(const BoostGraph &g)
|
||||||
|
{
|
||||||
boost::graph_traits<BoostGraph>::edge_iterator ei, ei_end;
|
boost::graph_traits<BoostGraph>::edge_iterator ei, ei_end;
|
||||||
for (boost::tie(ei, ei_end) = boost::edges(g); ei != ei_end; ++ei)
|
for (boost::tie(ei, ei_end) = boost::edges(g); ei != ei_end; ++ei)
|
||||||
std::cout << (char)(boost::source(*ei, g) + 'A') << " -- "
|
std::cout << (char) (boost::source(*ei, g) + 'A') << " -- "
|
||||||
<< (char)(boost::target(*ei, g) + 'A');
|
<< (char) (boost::target(*ei, g) + 'A');
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ using vertex_t = boost::graph_traits<BoostGraph>::vertex_descriptor;
|
||||||
class FlatPatternTopology {
|
class FlatPatternTopology {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool containsArticulationPoints() const;
|
bool containsArticulationPoints(std::vector<int> &articulationPointsVi) const;
|
||||||
FlatPatternTopology(const std::vector<size_t> &numberOfNodesPerSlot,
|
FlatPatternTopology(const std::vector<size_t> &numberOfNodesPerSlot,
|
||||||
const std::vector<vcg::Point2i> &edges);
|
const std::vector<vcg::Point2i> &edges);
|
||||||
static void
|
static void
|
||||||
|
@ -22,28 +22,30 @@ public:
|
||||||
static void constructSlotToNodeMap(
|
static void constructSlotToNodeMap(
|
||||||
const std::unordered_map<size_t, size_t> &nodeToSlot,
|
const 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);
|
||||||
|
static void printGraph(const BoostGraph &g);
|
||||||
|
|
||||||
FlatPatternTopology();
|
FlatPatternTopology();
|
||||||
|
BoostGraph constructRotationallySymmetricPattern(
|
||||||
private:
|
const BoostGraph &pattern,
|
||||||
BoostGraph pattern;
|
const std::unordered_map<size_t, std::unordered_set<size_t>> &slotToNodes,
|
||||||
|
const std::unordered_map<size_t, size_t> &nodeToSlot,
|
||||||
|
const std::unordered_map<size_t, size_t> &correspondingNode) const;
|
||||||
std::vector<size_t> numberOfNodesPerSlot;
|
std::vector<size_t> numberOfNodesPerSlot;
|
||||||
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::unordered_map<size_t, size_t> correspondingNode;
|
std::unordered_map<size_t, size_t> correspondingNode;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<std::vector<bool>> isAdjacentTo;
|
||||||
|
BoostGraph pattern;
|
||||||
void constructCorresponginNodeMap();
|
void constructCorresponginNodeMap();
|
||||||
/*
|
/*
|
||||||
* Creates a pattern which is a copy of the input pattern but with added edges
|
* Creates a pattern which is a copy of the input pattern but with added edges
|
||||||
* that result
|
* that result
|
||||||
* */
|
* */
|
||||||
void printGraph(const BoostGraph &g) const;
|
|
||||||
static BoostGraph constructRotationallySymmetricPattern(
|
|
||||||
const BoostGraph &pattern,
|
|
||||||
const std::unordered_map<size_t, std::unordered_set<size_t>> &slotToNodes,
|
|
||||||
const std::unordered_map<size_t, size_t> &nodeToSlot,
|
|
||||||
const std::unordered_map<size_t, size_t> &correspondingNode);
|
|
||||||
void constructNodeToSlotMap();
|
void constructNodeToSlotMap();
|
||||||
void constructSlotToNodeMap();
|
void constructSlotToNodeMap();
|
||||||
|
bool pathExists(int src, int dest) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // FLATPATTTERNTOPOLOGY_HPP
|
#endif // FLATPATTTERNTOPOLOGY_HPP
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
|
#define GET_VARIABLE_NAME(Variable) (#Variable)
|
||||||
|
|
||||||
struct Vector6d : public std::array<double, 6> {
|
struct Vector6d : public std::array<double, 6> {
|
||||||
Vector6d() {
|
Vector6d() {
|
||||||
for (size_t i = 0; i < 6; i++) {
|
for (size_t i = 0; i < 6; i++) {
|
||||||
|
|
Loading…
Reference in New Issue