2020-11-27 11:47:21 +01:00
|
|
|
#ifndef TOPOLOGYENUMERATOR_HPP
|
|
|
|
#define TOPOLOGYENUMERATOR_HPP
|
2021-07-21 17:00:36 +02:00
|
|
|
#include "nlohmann/json.hpp"
|
2020-11-27 11:47:21 +01:00
|
|
|
#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};
|
2021-08-06 13:35:28 +02:00
|
|
|
size_t numberOfPatternsViolatingAngleThreshold{0};
|
|
|
|
size_t numberOfPatternsViolatingValenceThreshold{0};
|
2021-11-15 10:08:39 +01:00
|
|
|
size_t numberOfPatternViolatingInterfaceEnforcement{0};
|
2020-11-27 11:47:21 +01:00
|
|
|
size_t numberOfValidPatterns{0};
|
2021-07-21 17:00:36 +02:00
|
|
|
nlohmann::json convertToJson() const
|
|
|
|
{
|
|
|
|
nlohmann::json json;
|
2021-11-15 10:08:39 +01:00
|
|
|
// json["numPossibleEdges"] = numberOfPossibleEdges;
|
|
|
|
// json["numCoincideEdges"] = numberOfCoincideEdges;
|
|
|
|
// json["numDuplicateEdges"] = numberOfDuplicateEdges;
|
|
|
|
// json["numValidEdges"] = numberOfValidEdges;
|
|
|
|
// json["numIntersectingEdgePairs"] = numberOfIntersectingEdgePairs;
|
2021-07-21 17:00:36 +02:00
|
|
|
json["numPatterns"] = numberOfPatterns;
|
|
|
|
// json["numIntersectingEdgesOverAllPatterns"] =
|
|
|
|
// numberOfIntersectingEdgesOverAllPatterns;
|
|
|
|
json["numPatternsWithIntersectingEdges"] = numberOfPatternsWithIntersectingEdges;
|
2021-11-15 10:08:39 +01:00
|
|
|
json["numViolatingInterfaceEnforcement"] = numberOfPatternViolatingInterfaceEnforcement;
|
2021-07-21 17:00:36 +02:00
|
|
|
json["numPatternsWithNotASingleCC"] = numberOfPatternsWithMoreThanASingleCC;
|
|
|
|
json["numPatternsWithArticulationPoints"] = numberOfPatternsWithArticulationPoints;
|
2021-11-15 10:08:39 +01:00
|
|
|
json["numPatternsWithDangling"] = numberOfPatternsWithADanglingEdgeOrNode;
|
2021-08-06 13:35:28 +02:00
|
|
|
json["violatingAngle"] = numberOfPatternsViolatingAngleThreshold;
|
|
|
|
json["violatingValence"] = numberOfPatternsViolatingValenceThreshold;
|
2021-11-15 10:08:39 +01:00
|
|
|
json["numValidPatterns"] = numberOfValidPatterns;
|
2021-07-21 17:00:36 +02:00
|
|
|
|
|
|
|
return json;
|
|
|
|
}
|
2020-11-27 11:47:21 +01:00
|
|
|
|
|
|
|
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;
|
2021-11-15 10:08:39 +01:00
|
|
|
std::cout << numberOfPatternViolatingInterfaceEnforcement
|
|
|
|
<< " patterns found which violate interface enforcement" << std::endl;
|
2020-11-27 11:47:21 +01:00
|
|
|
std::cout << numberOfPatternsWithMoreThanASingleCC
|
2021-11-15 10:08:39 +01:00
|
|
|
<< " patterns found with more than one connected components" << std::endl;
|
2020-11-27 11:47:21 +01:00
|
|
|
std::cout << numberOfPatternsWithADanglingEdgeOrNode
|
|
|
|
<< " patterns found with a dangling node or edge" << std::endl;
|
|
|
|
std::cout << numberOfPatternsWithArticulationPoints
|
|
|
|
<< " patterns found with an articulation point" << std::endl;
|
2021-07-21 17:00:36 +02:00
|
|
|
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";
|
|
|
|
}
|
|
|
|
}
|
2020-11-27 11:47:21 +01:00
|
|
|
|
2021-07-21 17:00:36 +02:00
|
|
|
void reset()
|
|
|
|
{
|
|
|
|
numberOfPossibleEdges = 0;
|
|
|
|
numberOfCoincideEdges = 0;
|
|
|
|
numberOfDuplicateEdges = 0;
|
|
|
|
numberOfValidEdges = 0;
|
|
|
|
numberOfIntersectingEdgePairs = 0;
|
|
|
|
numberOfPatterns = 0;
|
|
|
|
numberOfPatternsWithIntersectingEdges = 0;
|
2021-11-15 10:08:39 +01:00
|
|
|
numberOfPatternViolatingInterfaceEnforcement = 0;
|
|
|
|
;
|
2021-07-21 17:00:36 +02:00
|
|
|
numberOfPatternsWithMoreThanASingleCC = 0;
|
|
|
|
numberOfPatternsWithADanglingEdgeOrNode = 0;
|
|
|
|
numberOfPatternsWithArticulationPoints = 0;
|
|
|
|
numberOfValidPatterns = 0;
|
2021-08-06 13:35:28 +02:00
|
|
|
numberOfPatternsViolatingAngleThreshold = 0;
|
|
|
|
numberOfPatternsViolatingValenceThreshold = 0;
|
2020-11-27 11:47:21 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
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
|
2021-04-08 20:03:23 +02:00
|
|
|
computeValidPatterns(const std::vector<size_t> &reducedNumberOfNodesPerSlot, const std::string &desiredResultsPath, const int& numberOfDesiredEdges=-1);
|
2020-11-27 11:47:21 +01:00
|
|
|
|
|
|
|
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,
|
2021-02-04 13:58:41 +01:00
|
|
|
const std::filesystem::path &resultsPath,
|
2021-03-15 18:04:29 +01:00
|
|
|
const PatternGeometry &patternGeometryAllEdges,
|
2020-11-27 11:47:21 +01:00
|
|
|
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,
|
2021-07-21 17:00:36 +02:00
|
|
|
const std::unordered_map<size_t, std::unordered_set<size_t>> &intersectingEdges,
|
2021-11-15 10:08:39 +01:00
|
|
|
const std::vector<vcg::Point2i> &validEdges,
|
|
|
|
const std::unordered_set<VertexIndex> &interfaceNodes);
|
2021-07-21 17:00:36 +02:00
|
|
|
void exportPattern(const std::filesystem::path &saveToPath,
|
|
|
|
PatternGeometry &patternGeometry,
|
|
|
|
const bool saveTilledPattern) const;
|
2020-11-27 11:47:21 +01:00
|
|
|
};
|
2021-04-08 20:03:23 +02:00
|
|
|
#endif // TOPOLOGYENUMERATOR_HPP
|