#ifndef TOPOLOGYENUMERATOR_HPP #define TOPOLOGYENUMERATOR_HPP #include "nlohmann/json.hpp" #include "patternIO.hpp" #include "trianglepatterngeometry.hpp" #include "trianglepattterntopology.hpp" #include #include #include #include #include using GraphEdge = std::pair; /* * 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 numberOfNodesPerSlot; size_t numberOfNodes; size_t computeCoincideEdges(const std::vector &numberOfNodesPerSlot) const; size_t computeNumberOfPossibleEdges( const std::vector &numberOfNodesPerSlot) const; void createLabelMesh(const std::vector vertices, const std::filesystem::path &savePath) const; size_t getEdgeIndex(size_t ni0, size_t ni1) const; public: TopologyEnumerator(); void computeValidPatterns(const std::vector &reducedNumberOfNodesPerSlot, const std::string &desiredResultsPath, const int& numberOfDesiredEdges=-1); private: std::vector getCoincideEdges(const std::vector &edgeNodeIndices) const; bool isValidPattern(const std::string &patternIndex, const std::vector &validEdges, const size_t &numberOfDesiredEdges) const; std::vector getValidEdges(const std::vector &numberOfNodesPerSlot, const std::filesystem::path &resultsPath, const PatternGeometry &patternGeometryAllEdges, const std::vector &allPossibleEdges); std::unordered_set computeDuplicateEdges(); std::unordered_set computeCoincideEdges(const std::vector &numberOfNodesPerSlot); void computeEdgeNodes(const std::vector &numberOfNodesPerSlot, std::vector &nodesEdge0, std::vector &nodesEdge1, std::vector &nodesEdge2); std::unordered_set computeDuplicateEdges(const std::vector &numberOfNodesPerSlot); void computeValidPatterns( const std::vector &numberOfNodesPerSlot, const size_t &numberOfDesiredEdges, const std::filesystem::path &resultsPath, const std::vector &vertices, const std::unordered_map> &intersectingEdges, const std::vector &validEdges, const std::unordered_set &interfaceNodes); void exportPattern(const std::filesystem::path &saveToPath, PatternGeometry &patternGeometry, const bool saveTilledPattern) const; }; #endif // TOPOLOGYENUMERATOR_HPP