MySources/topologyenumerator.hpp

210 lines
8.4 KiB
C++
Executable File

#ifndef TOPOLOGYENUMERATOR_HPP
#define TOPOLOGYENUMERATOR_HPP
#include "nlohmann/json.hpp"
#include "patternIO.hpp"
#include "trianglepatterngeometry.hpp"
#include "trianglepattterntopology.hpp"
#include <filesystem>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
using GraphEdge = std::pair<size_t, size_t>;
/*
* Represents a graph formed by slots on a triangle that can either be filled or
* not. The slots are three and are: 1) one slot per vertex. Each slot can hold
* a signle node. 2) one slot per edge. Each slot can hold many nodes. 3) one
* slot in the inside of the triangle. Each slot can hold multiple nodes.
* */
class TopologyEnumerator {
/*
* Holds the in a CCW order the vertex and the edge slots and then the face
* slot. [0],[1],[2] can either be 0 or 1 [3],[4],[5] are integers in [0,n]
* [6] an integer [0,n]
* */
/*
reduced nodes per slot
0
/\
/ \
2 2
/ 4 \
/ \
1----3-----1
nodes per slot
0
/\
/ \
3 5
/ 6 \
/ \
1----4-----2
slot=0 -> vi=0
slot=1 -> vi=1
slot=2 -> vi=2
...
see TrianglePatternGeometry::constructVertexVector
*/
struct TopologicalStatistics {
size_t numberOfPossibleEdges{0};
size_t numberOfCoincideEdges{0};
size_t numberOfDuplicateEdges{0};
size_t numberOfValidEdges{0};
size_t numberOfIntersectingEdgePairs{0};
size_t numberOfPatterns{0};
// size_t numberOfIntersectingEdgesOverAllPatterns{0};
size_t numberOfPatternsWithIntersectingEdges{0};
size_t numberOfPatternsWithMoreThanASingleCC{0};
size_t numberOfPatternsWithADanglingEdgeOrNode{0};
size_t numberOfPatternsWithArticulationPoints{0};
size_t numberOfPatternsViolatingAngleThreshold{0};
size_t numberOfPatternsViolatingValenceThreshold{0};
size_t numberOfPatternViolatingInterfaceEnforcement{0};
size_t numberOfValidPatterns{0};
nlohmann::json convertToJson() const
{
nlohmann::json json;
// json["numPossibleEdges"] = numberOfPossibleEdges;
// json["numCoincideEdges"] = numberOfCoincideEdges;
// json["numDuplicateEdges"] = numberOfDuplicateEdges;
// json["numValidEdges"] = numberOfValidEdges;
// json["numIntersectingEdgePairs"] = numberOfIntersectingEdgePairs;
json["numPatterns"] = numberOfPatterns;
// json["numIntersectingEdgesOverAllPatterns"] =
// numberOfIntersectingEdgesOverAllPatterns;
json["numPatternsWithIntersectingEdges"] = numberOfPatternsWithIntersectingEdges;
json["numViolatingInterfaceEnforcement"] = numberOfPatternViolatingInterfaceEnforcement;
json["numPatternsWithNotASingleCC"] = numberOfPatternsWithMoreThanASingleCC;
json["numPatternsWithArticulationPoints"] = numberOfPatternsWithArticulationPoints;
json["numPatternsWithDangling"] = numberOfPatternsWithADanglingEdgeOrNode;
json["violatingAngle"] = numberOfPatternsViolatingAngleThreshold;
json["violatingValence"] = numberOfPatternsViolatingValenceThreshold;
json["numValidPatterns"] = numberOfValidPatterns;
return json;
}
void print(const std::string &setupString,
const std::filesystem::path &directoryPath) const {
std::cout << "The setup " << setupString << std::endl;
std::cout << "Has following statistics:" << std::endl;
std::cout << numberOfPossibleEdges
<< " possible edges with the given arrangement of nodes"
<< std::endl;
std::cout << numberOfCoincideEdges << " coincide edges" << std::endl;
std::cout << numberOfDuplicateEdges << " duplicate edges" << std::endl;
std::cout << numberOfValidEdges << " valid edges" << std::endl;
std::cout << numberOfIntersectingEdgePairs << "intersecting edge pairs "
<< std::endl;
std::cout << numberOfPatterns
<< " patterns can be generated with the given setup"
<< std::endl;
// std::cout << numberOfIntersectingEdgesOverAllPatterns
// << " intersecting edges found over all patterns" <<
// std::endl;
std::cout << numberOfPatternsWithIntersectingEdges
<< " patterns found with intersecting edges" << std::endl;
std::cout << numberOfPatternViolatingInterfaceEnforcement
<< " patterns found which violate interface enforcement" << std::endl;
std::cout << numberOfPatternsWithMoreThanASingleCC
<< " patterns found with more than one connected components" << std::endl;
std::cout << numberOfPatternsWithADanglingEdgeOrNode
<< " patterns found with a dangling node or edge" << std::endl;
std::cout << numberOfPatternsWithArticulationPoints
<< " patterns found with an articulation point" << std::endl;
std::cout << numberOfValidPatterns << " valid patterns were found" << std::endl;
if (!directoryPath.empty()) {
auto json = convertToJson();
std::ofstream file;
file.open(std::filesystem::path(directoryPath).append("statistics.csv").string());
file << "setup," << setupString << "\n";
for (const auto &el : json.items()) {
file << el.key() << ",";
}
file << "\n";
for (const auto &el : json.items()) {
file << el.value() << ",";
}
file << "\n";
}
}
void reset()
{
numberOfPossibleEdges = 0;
numberOfCoincideEdges = 0;
numberOfDuplicateEdges = 0;
numberOfValidEdges = 0;
numberOfIntersectingEdgePairs = 0;
numberOfPatterns = 0;
numberOfPatternsWithIntersectingEdges = 0;
numberOfPatternViolatingInterfaceEnforcement = 0;
;
numberOfPatternsWithMoreThanASingleCC = 0;
numberOfPatternsWithADanglingEdgeOrNode = 0;
numberOfPatternsWithArticulationPoints = 0;
numberOfValidPatterns = 0;
numberOfPatternsViolatingAngleThreshold = 0;
numberOfPatternsViolatingValenceThreshold = 0;
}
};
TopologicalStatistics statistics;
std::vector<size_t> numberOfNodesPerSlot;
size_t numberOfNodes;
size_t
computeCoincideEdges(const std::vector<size_t> &numberOfNodesPerSlot) const;
size_t computeNumberOfPossibleEdges(
const std::vector<size_t> &numberOfNodesPerSlot) const;
void createLabelMesh(const std::vector<vcg::Point3d> vertices,
const std::filesystem::path &savePath) const;
size_t getEdgeIndex(size_t ni0, size_t ni1) const;
public:
TopologyEnumerator();
void
computeValidPatterns(const std::vector<size_t> &reducedNumberOfNodesPerSlot, const std::string &desiredResultsPath, const int& numberOfDesiredEdges=-1);
private:
std::vector<size_t>
getCoincideEdges(const std::vector<size_t> &edgeNodeIndices) const;
bool isValidPattern(const std::string &patternIndex,
const std::vector<vcg::Point2i> &validEdges,
const size_t &numberOfDesiredEdges) const;
std::vector<vcg::Point2i>
getValidEdges(const std::vector<size_t> &numberOfNodesPerSlot,
const std::filesystem::path &resultsPath,
const PatternGeometry &patternGeometryAllEdges,
const std::vector<vcg::Point2i> &allPossibleEdges);
std::unordered_set<size_t> computeDuplicateEdges();
std::unordered_set<size_t>
computeCoincideEdges(const std::vector<size_t> &numberOfNodesPerSlot);
void computeEdgeNodes(const std::vector<size_t> &numberOfNodesPerSlot,
std::vector<size_t> &nodesEdge0,
std::vector<size_t> &nodesEdge1,
std::vector<size_t> &nodesEdge2);
std::unordered_set<size_t>
computeDuplicateEdges(const std::vector<size_t> &numberOfNodesPerSlot);
void computeValidPatterns(
const std::vector<size_t> &numberOfNodesPerSlot,
const size_t &numberOfDesiredEdges,
const std::filesystem::path &resultsPath,
const std::vector<vcg::Point3d> &vertices,
const std::unordered_map<size_t, std::unordered_set<size_t>> &intersectingEdges,
const std::vector<vcg::Point2i> &validEdges,
const std::unordered_set<VertexIndex> &interfaceNodes);
void exportPattern(const std::filesystem::path &saveToPath,
PatternGeometry &patternGeometry,
const bool saveTilledPattern) const;
};
#endif // TOPOLOGYENUMERATOR_HPP