ENH: further refinement to edge methods

- more hash-like methods.
  Eg, insert/erase via lists, clear(), empty(),...

- minVertex(), maxVertex() to return the smallest/largest label used

- improved documentation, more clarification about where/how negative
  point labels are treated.
This commit is contained in:
Mark Olesen
2017-04-29 12:14:46 +02:00
parent 7edd801c72
commit 1d9b311b82
4 changed files with 353 additions and 110 deletions

View File

@ -31,6 +31,7 @@ Description
#include "argList.H" #include "argList.H"
#include "edgeList.H" #include "edgeList.H"
#include "edgeHashes.H"
using namespace Foam; using namespace Foam;
@ -79,6 +80,28 @@ int main(int argc, char *argv[])
printInfo(e4); 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}) for (label i : {-1, 0, 1, 3})
{ {
bool ok = e4.erase(i); bool ok = e4.erase(i);

View File

@ -329,7 +329,7 @@ public:
//- Return size of the largest possible FixedList //- Return size of the largest possible FixedList
inline label max_size() const; 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; inline bool empty() const;
//- Swap two FixedLists of the same type in constant time //- Swap two FixedLists of the same type in constant time

View File

@ -28,6 +28,14 @@ Description
An edge is a list of two point labels. The functionality it provides An edge is a list of two point labels. The functionality it provides
supports the discretisation on a 2-D flat mesh. 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 SourceFiles
edgeI.H edgeI.H
@ -60,6 +68,24 @@ class edge
: :
public FixedList<label, 2> 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: public:
@ -91,6 +117,8 @@ public:
// Member Functions // Member Functions
// Access
//- Return start vertex label //- Return start vertex label
inline label start() const; inline label start() const;
@ -103,67 +131,138 @@ public:
//- Return end vertex label //- Return end vertex label
inline label& end(); 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? //- Do the edges share a common vertex index?
// Negative point labels never connect.
inline bool connects(const edge& other) const; inline bool connects(const edge& other) const;
//- Return vertex common with otherEdge or -1 on failure //- 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; inline label commonVertex(const edge& other) const;
//- Given one vertex index, return the other one. //- Given one vertex index, return the other one.
// No special treatment for negative point labels.
inline label otherVertex(const label index) const; 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 // Editing
// No special treatment for '-1'.
inline bool found(const label index) const; //- '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. //- Return the number of unique, valid (non -1) point labels.
// Similar to a HashTable::size(). // Similar to a HashTable::size().
inline label count() const; inline int count() const;
//- Insert the index if it did not previously exist on the edge. //- Return true if edge has no valid point labels.
inline bool empty() const;
//- '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. // Returns true on success. A negative label never inserts.
// Similar to a HashTable::insert(). // Similar to a HashTable::insert().
inline bool insert(const label index); 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'. //- 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(). // 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);
//- 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);
//- Remove existing indices from the edge and set locations to '-1'.
// Returns the number of changes.
inline int erase(std::initializer_list<label> lst);
//- True if the edge is sorted such that start is less-than end // Geometric functions
inline bool sorted() const;
//- Sort start/end that start is less-than end //- Return centre point (centroid) of the edge.
inline void sort(); // No special handling of negative point labels.
//- Flip the edge in-place.
inline void flip();
//- Return reverse edge
inline edge reverseEdge() const;
//- Return centre (centroid)
inline point centre(const UList<point>& pts) const; inline point centre(const UList<point>& pts) const;
//- Return the vector (end - start) //- Return the vector (end - start)
// No special handling of negative point labels.
inline vector vec(const UList<point>& pts) const; inline vector vec(const UList<point>& pts) const;
//- Return the unit vector (end - start) //- Return the unit vector (end - start)
// No special handling of negative point labels.
inline vector unitVec(const UList<point>& pts) const; 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; inline scalar mag(const UList<point>& pts) const;
//- Return edge line //- Return edge line
// No special handling of negative point labels.
inline linePointRef line(const UList<point>& pts) const; inline linePointRef line(const UList<point>& pts) const;
// Comparison
//- Compare edges //- Compare edges
// Returns: // Returns:
// - 0: different // - 0: different

View File

@ -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 * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
inline Foam::edge::edge() 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 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 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 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 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' // Cannot resize FixedList, so mark duplicates with '-1'
// (the lower vertex is retained) // (the lower vertex is retained)
// catch any '-1' (eg, if called multiple times) // catch any '-1' (eg, if called multiple times)
label n = 2; int n = 2;
if (start() == end() || end() == -1) if (start() == end() || end() < 0)
{ {
end() = -1; end() = -1;
--n; --n;
} }
if (start() == -1) if (start() < 0)
{ {
--n; --n;
} }
@ -196,80 +269,6 @@ inline Foam::label Foam::edge::collapse()
} }
inline Foam::label Foam::edge::count() const
{
label n = 2;
if (start() == end() || end() == -1)
{
--n;
}
if (start() == -1)
{
--n;
}
return n;
}
inline bool Foam::edge::insert(const label index)
{
if (index < 0)
{
// Can never insert invalid point labels.
// Use direct assignment for that.
return false;
}
else if (start() == -1)
{
// Store at [0], if not duplicate of [1]
if (index != end())
{
start() = index;
return true;
}
}
else if (end() == -1)
{
// Store at [1], if not duplicate of [0]
if (index != start())
{
end() = index;
return true;
}
}
return false;
}
inline bool Foam::edge::erase(const label index)
{
if (index < 0)
{
// Can never remove invalid point labels!
return false;
}
int n = 0;
if (index == start())
{
start() = -1;
++n;
}
// Automatically handle duplicates, should not have been there anyhow
if (index == end())
{
end() = -1;
++n;
}
return n;
}
inline bool Foam::edge::sorted() const inline bool Foam::edge::sorted() const
{ {
return (start() < end()); return (start() < end());
@ -297,6 +296,128 @@ inline Foam::edge Foam::edge::reverseEdge() const
} }
inline void Foam::edge::clear()
{
start() = -1;
end() = -1;
}
inline int Foam::edge::count() const
{
label n = 2;
if (start() == end() || end() < 0)
{
--n;
}
if (start() < 0)
{
--n;
}
return n;
}
inline bool Foam::edge::empty() const
{
return (start() < 0 && end() < 0);
}
inline bool Foam::edge::insert(const label index)
{
if (index < 0)
{
// Cannot insert invalid point labels (use direct assignment for that)
return false;
}
if (start() < 0)
{
// Store at [0], if not duplicate of [1]
if (index != end())
{
start() = index;
return true;
}
}
else if (end() < 0)
{
// Store at [1], if not duplicate of [0]
if (index != start())
{
end() = index;
return true;
}
}
return false;
}
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 0;
}
int n = 0;
if (index == start())
{
start() = -1;
++n;
}
// Automatically handle duplicates, which should not have been there anyhow
if (index == end())
{
end() = -1;
++n;
}
return n;
}
inline int Foam::edge::erase(const UList<label>& lst)
{
return eraseMultiple(lst.begin(), lst.end());
}
template<unsigned AnySize>
inline int Foam::edge::erase(const FixedList<label, AnySize>& lst)
{
return eraseMultiple(lst.begin(), lst.end());
}
inline int Foam::edge::erase(std::initializer_list<label> lst)
{
return eraseMultiple(lst.begin(), lst.end());
}
// Geometric
inline Foam::point Foam::edge::centre(const UList<point>& pts) const inline Foam::point Foam::edge::centre(const UList<point>& pts) const
{ {
return 0.5*(pts[start()] + pts[end()]); return 0.5*(pts[start()] + pts[end()]);