diff --git a/applications/test/edges/Test-edges.C b/applications/test/edges/Test-edges.C index abd5f9d8a19e04938ff91801cd105c25e2105351..eda9ae0dd9f6730548cda3f7fcf81b2825d49023 100644 --- a/applications/test/edges/Test-edges.C +++ b/applications/test/edges/Test-edges.C @@ -31,6 +31,7 @@ Description #include "argList.H" #include "edgeList.H" +#include "edgeHashes.H" using namespace Foam; @@ -79,6 +80,28 @@ int main(int argc, char *argv[]) printInfo(e4); } + e4.start() = e4.end() = -1; + Info<< "insert from list\n"; + labelHashSet newIndices({2, -1, 2, 1, 4, 1, 2, 3}); + e4.insert(newIndices.toc()); + printInfo(e4); + + e4.start() = e4.end() = -1; + Info<< "insert from list\n"; + e4.insert({0, 5, 2, -1, 2, 1, 4, 1, 2, 3}); + printInfo(e4); + + FixedList<label, 8> otherIndices{12, 2, -1, 1, 4, 1, 2, 3}; + e4.start() = e4.end() = -1; + Info<< "insert from list: " << otherIndices << nl; + e4.insert(otherIndices); + printInfo(e4); + + e4.start() = e4.end(); + Info<< "erase from list: " << otherIndices << nl; + Info<< "removed " << e4.erase(otherIndices) << " values" << nl; + printInfo(e4); + for (label i : {-1, 0, 1, 3}) { bool ok = e4.erase(i); diff --git a/src/OpenFOAM/containers/Lists/FixedList/FixedList.H b/src/OpenFOAM/containers/Lists/FixedList/FixedList.H index c969f4f4ad870afd92a23c1260200ec396f4f368..bdf75aa40101e8f61511b421a3318a09c0d88179 100644 --- a/src/OpenFOAM/containers/Lists/FixedList/FixedList.H +++ b/src/OpenFOAM/containers/Lists/FixedList/FixedList.H @@ -329,7 +329,7 @@ public: //- Return size of the largest possible FixedList inline label max_size() const; - //- Return true if the FixedList is empty (ie, size() is zero) + //- Always false since zero-sized FixedList is compile-time disabled. inline bool empty() const; //- Swap two FixedLists of the same type in constant time diff --git a/src/OpenFOAM/meshes/meshShapes/edge/edge.H b/src/OpenFOAM/meshes/meshShapes/edge/edge.H index f804fda8141f96111a69881af9fcbe3c8705d7b8..f15c901b122d198e6bdcc1575ebd08acc9edaa5a 100644 --- a/src/OpenFOAM/meshes/meshShapes/edge/edge.H +++ b/src/OpenFOAM/meshes/meshShapes/edge/edge.H @@ -28,6 +28,14 @@ Description An edge is a list of two point labels. The functionality it provides supports the discretisation on a 2-D flat mesh. + The edge is implemented as a FixedList of labels. + As well as geometrically relevant methods, it also provides methods + similar to HashSet for additional convenience. + Valid point labels are always non-negative (since they correspond to + addressing within the mesh). The value '-1' is used to tag invalid + point labels that correspond conceptually to open 'slots', which + can be filled with the HashSet-like functionality. + SourceFiles edgeI.H @@ -60,6 +68,24 @@ class edge : public FixedList<label, 2> { + // Private Member Functions + + //- Insert values, using begin/end iterators. + template<class InputIter> + inline int insertMultiple + ( + const InputIter begIter, + const InputIter endIter + ); + + //- Remove values, using begin/end iterators. + template<class InputIter> + inline int eraseMultiple + ( + const InputIter begIter, + const InputIter endIter + ); + public: @@ -91,6 +117,8 @@ public: // Member Functions + // Access + //- Return start vertex label inline label start() const; @@ -103,67 +131,138 @@ public: //- Return end vertex label inline label& end(); + //- Return reverse edge as copy. + // No special handling of negative point labels. + inline edge reverseEdge() const; + + + // Queries + + //- Return the smallest point label used by the edge + // No special handling of negative point labels. + inline label minVertex() const; + + //- Return the largest point label used by the edge + // No special handling of negative point labels. + inline label maxVertex() const; + + //- True if start() is less-than end() + // No special handling of negative point labels. + inline bool sorted() const; + + //- Return true if point label is found in edge. + // Always false for a negative label. + inline bool found(const label index) const; + //- Do the edges share a common vertex index? + // Negative point labels never connect. inline bool connects(const edge& other) const; //- Return vertex common with otherEdge or -1 on failure + // Negative point labels are never considered common between edges. inline label commonVertex(const edge& other) const; //- Given one vertex index, return the other one. + // No special treatment for negative point labels. inline label otherVertex(const label index) const; - //- 'Collapse' edge by marking duplicate point labels. - // Duplicates point labels are marked with '-1'. - // (the lower vertex is retained). - // Return the collapsed size. - inline label collapse(); - //- Return true if point label is found in edge - // No special treatment for '-1'. - inline bool found(const label index) const; + // Editing + + //- 'Collapse' edge by marking duplicate point labels as '-1', + // the lower vertex is retained. + // Return the effective size after collapsing. + inline int collapse(); + + //- Flip the edge in-place. + // No special handling of negative point labels. + inline void flip(); + + //- Sort so that start() is less-than end() + // No special handling of negative point labels. + inline void sort(); + + + // Hash-like functions //- Return the number of unique, valid (non -1) point labels. // Similar to a HashTable::size(). - inline label count() const; + inline int count() const; + + //- Return true if edge has no valid point labels. + inline bool empty() const; - //- Insert the index if it did not previously exist on the edge. + //- 'Clears' edge by setting both ends to invalid point labels. + inline void clear(); + + //- Fill any open slot with the index if it did not previously exist. // Returns true on success. A negative label never inserts. // Similar to a HashTable::insert(). inline bool insert(const label index); + //- Fill open slots with the indices if they did not previously exist. + // Returns true on success. Negative labels never inserts. + // Return the number of slots filled. + // Similar to a HashTable::insert(). + inline int insert(const UList<label>& lst); + + //- Fill open slots with the indices if they did not previously exist. + // Returns true on success. Negative labels never inserts. + // Return the number of slots filled. + // Similar to a HashTable::insert(). + template<unsigned AnySize> + inline int insert(const FixedList<label, AnySize>& lst); + + //- Fill open slots with the indices if they did not previously exist. + // Returns true on success. Negative labels never inserts. + // Return the number of slots filled. + // Similar to a HashTable::insert(). + inline int insert(std::initializer_list<label> lst); + //- Remove an existing index from the edge and set its location to '-1'. - // Returns true on success. A negative label never removes. + // Returns the number of changes. A negative label never removes. // Similar to a HashTable::erase(). - inline bool erase(const label index); + inline int erase(const label index); + //- Remove existing indices from the edge and set locations to '-1'. + // Returns the number of changes. + inline int erase(const UList<label>& lst); - //- True if the edge is sorted such that start is less-than end - inline bool sorted() const; + //- Remove existing indices from the edge and set locations to '-1'. + // Returns the number of changes. + template<unsigned AnySize> + inline int erase(const FixedList<label, AnySize>& lst); - //- Sort start/end that start is less-than end - inline void sort(); + //- Remove existing indices from the edge and set locations to '-1'. + // Returns the number of changes. + inline int erase(std::initializer_list<label> lst); - //- Flip the edge in-place. - inline void flip(); - //- Return reverse edge - inline edge reverseEdge() const; + // Geometric functions - //- Return centre (centroid) + //- Return centre point (centroid) of the edge. + // No special handling of negative point labels. inline point centre(const UList<point>& pts) const; //- Return the vector (end - start) + // No special handling of negative point labels. inline vector vec(const UList<point>& pts) const; //- Return the unit vector (end - start) + // No special handling of negative point labels. inline vector unitVec(const UList<point>& pts) const; - //- Return scalar magnitude + //- Return scalar magnitude of the edge. + // No special handling of negative point labels. inline scalar mag(const UList<point>& pts) const; //- Return edge line + // No special handling of negative point labels. inline linePointRef line(const UList<point>& pts) const; + + // Comparison + //- Compare edges // Returns: // - 0: different diff --git a/src/OpenFOAM/meshes/meshShapes/edge/edgeI.H b/src/OpenFOAM/meshes/meshShapes/edge/edgeI.H index b1b4f493682179a70bdd6b242626cf9ab935c449..d5d5b045124568370cba32c749cb590127a849c9 100644 --- a/src/OpenFOAM/meshes/meshShapes/edge/edgeI.H +++ b/src/OpenFOAM/meshes/meshShapes/edge/edgeI.H @@ -45,6 +45,66 @@ inline int Foam::edge::compare(const edge& a, const edge& b) } +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +template<class InputIter> +inline int Foam::edge::insertMultiple +( + const InputIter begIter, + const InputIter endIter +) +{ + // Available slots. + // Don't use count() since it has special treatment for duplicates + const int maxChange = (start() < 0 ? 1 : 0) + (end() < 0 ? 1 : 0); + + int changed = 0; + if (maxChange) + { + for (InputIter iter = begIter; iter != endIter; ++iter) + { + if (insert(*iter)) + { + if (++changed >= maxChange) + { + break; + } + } + } + } + + return changed; +} + + +template<class InputIter> +inline int Foam::edge::eraseMultiple +( + const InputIter begIter, + const InputIter endIter +) +{ + // Occupied slots. + // Don't use count() since it has special treatment for duplicates + const int maxChange = (start() >= 0 ? 1 : 0) + (end() >= 0 ? 1 : 0); + + int changed = 0; + if (maxChange) + { + for (InputIter iter = begIter; iter != endIter; ++iter) + { + changed += erase(*iter); + if (changed >= maxChange) + { + break; + } + } + } + + return changed; +} + + // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // inline Foam::edge::edge() @@ -127,27 +187,40 @@ inline Foam::label& Foam::edge::end() } +inline Foam::label Foam::edge::minVertex() const +{ + return (start() < end() ? start() : end()); +} + + +inline Foam::label Foam::edge::maxVertex() const +{ + return (start() > end() ? start() : end()); +} + + inline bool Foam::edge::found(const label index) const { - return (index == start() || index == end()); + // -1: always false + return (index >= 0 && (index == start() || index == end())); } inline bool Foam::edge::connects(const edge& other) const { - return (other.found(this->start()) || other.found(this->end())); + return (other.found(start()) || other.found(end())); } inline Foam::label Foam::edge::commonVertex(const edge& other) const { - if (other.found(this->start())) + if (other.found(start())) { - return this->start(); + return start(); } - else if (other.found(this->end())) + else if (other.found(end())) { - return this->end(); + return end(); } else { @@ -175,19 +248,19 @@ inline Foam::label Foam::edge::otherVertex(const label index) const } -inline Foam::label Foam::edge::collapse() +inline int Foam::edge::collapse() { // Cannot resize FixedList, so mark duplicates with '-1' // (the lower vertex is retained) // catch any '-1' (eg, if called multiple times) - label n = 2; - if (start() == end() || end() == -1) + int n = 2; + if (start() == end() || end() < 0) { end() = -1; --n; } - if (start() == -1) + if (start() < 0) { --n; } @@ -196,15 +269,48 @@ inline Foam::label Foam::edge::collapse() } -inline Foam::label Foam::edge::count() const +inline bool Foam::edge::sorted() const +{ + return (start() < end()); +} + + +inline void Foam::edge::sort() +{ + if (start() > end()) + { + flip(); + } +} + + +inline void Foam::edge::flip() +{ + Swap(operator[](0), operator[](1)); +} + + +inline Foam::edge Foam::edge::reverseEdge() const +{ + return edge(end(), start()); +} + + +inline void Foam::edge::clear() +{ + start() = -1; + end() = -1; +} + + +inline int Foam::edge::count() const { label n = 2; - if (start() == end() || end() == -1) + if (start() == end() || end() < 0) { --n; } - - if (start() == -1) + if (start() < 0) { --n; } @@ -213,15 +319,21 @@ inline Foam::label Foam::edge::count() const } +inline bool Foam::edge::empty() const +{ + return (start() < 0 && end() < 0); +} + + inline bool Foam::edge::insert(const label index) { if (index < 0) { - // Can never insert invalid point labels. - // Use direct assignment for that. + // Cannot insert invalid point labels (use direct assignment for that) return false; } - else if (start() == -1) + + if (start() < 0) { // Store at [0], if not duplicate of [1] if (index != end()) @@ -230,7 +342,7 @@ inline bool Foam::edge::insert(const label index) return true; } } - else if (end() == -1) + else if (end() < 0) { // Store at [1], if not duplicate of [0] if (index != start()) @@ -244,12 +356,29 @@ inline bool Foam::edge::insert(const label index) } -inline bool Foam::edge::erase(const label index) +inline int Foam::edge::insert(const UList<label>& lst) +{ + return insertMultiple(lst.begin(), lst.end()); +} + +template<unsigned AnySize> +inline int Foam::edge::insert(const FixedList<label, AnySize>& lst) +{ + return insertMultiple(lst.begin(), lst.end()); +} + +inline int Foam::edge::insert(std::initializer_list<label> lst) +{ + return insertMultiple(lst.begin(), lst.end()); +} + + +inline int Foam::edge::erase(const label index) { if (index < 0) { // Can never remove invalid point labels! - return false; + return 0; } int n = 0; @@ -259,7 +388,7 @@ inline bool Foam::edge::erase(const label index) ++n; } - // Automatically handle duplicates, should not have been there anyhow + // Automatically handle duplicates, which should not have been there anyhow if (index == end()) { end() = -1; @@ -270,32 +399,24 @@ inline bool Foam::edge::erase(const label index) } -inline bool Foam::edge::sorted() const +inline int Foam::edge::erase(const UList<label>& lst) { - return (start() < end()); + return eraseMultiple(lst.begin(), lst.end()); } - -inline void Foam::edge::sort() +template<unsigned AnySize> +inline int Foam::edge::erase(const FixedList<label, AnySize>& lst) { - if (start() > end()) - { - flip(); - } + return eraseMultiple(lst.begin(), lst.end()); } - -inline void Foam::edge::flip() +inline int Foam::edge::erase(std::initializer_list<label> lst) { - Swap(operator[](0), operator[](1)); + return eraseMultiple(lst.begin(), lst.end()); } -inline Foam::edge Foam::edge::reverseEdge() const -{ - return edge(end(), start()); -} - +// Geometric inline Foam::point Foam::edge::centre(const UList<point>& pts) const {