ENH: various enhancements for edge.

- support edge-ordering on construction, and additional methods:
  - sort(), sorted(), unitVec(), collapse()

- null constructor initializes with -1, for consistency with face,
  triFace and since it is generally much more useful that way.

- add some methods that allow edges to used somewhat more like hashes.
  - count(), found(), insert(), erase()

  Here is possible way to use that:

      edge someEdge;  // initializes with '-1' for both entries

      if (someEdge.insert(pt1))
      {
         // added a new point label
      }

      ... later

      // unmark point on edge
      someEdge.erase(pt2);

--

STYLE:

- use UList<point> instead of pointField for edge methods for flexibility.

  The pointField include is retained, however, since many other routines
  may be relying on it being included via edge.H
This commit is contained in:
Mark Olesen 2017-04-23 19:25:35 +02:00
parent 32a2a23466
commit f2304f7c0b
5 changed files with 363 additions and 45 deletions

View File

@ -0,0 +1,3 @@
Test-edges.C
EXE = $(FOAM_USER_APPBIN)/Test-edges

View File

View File

@ -0,0 +1,114 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2017 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Application
Test-edges
Description
Simple tests for edges
\*---------------------------------------------------------------------------*/
#include "argList.H"
#include "edgeList.H"
using namespace Foam;
void printInfo(const edge& e)
{
Info<< "edge: " << e << " count:" << e.count() << nl;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
int main(int argc, char *argv[])
{
edge e1;
printInfo(e1);
Info<<"has '2'? " << e1.found(2) << endl;
edge e2(1, 2);
printInfo(e2);
Info<<"has '2'? " << e2.found(2) << endl;
edge e3{2, 3};
printInfo(e3);
Info<<"has '2'? " << e3.found(2) << endl;
edge e4(4, 4);
printInfo(e4);
Info<<"has '2'? " << e4.found(2) << endl;
Info<<"collapse? -> " << e4.collapse() << endl;
printInfo(e4);
Info<< e3 << " connects " << e2 << " => " << e2.connects(e3) << endl;
Info<< nl << "hash-like functionality" << nl;
// doesn't work e4 = -1;
e4.start() = e4.end() = -1;
printInfo(e4);
for (label i : {2, -1, 2, 1, 4, 1, 2, 3})
{
bool ok = e4.insert(i);
Info<< "insert(" << i << ") = " << ok << " resulting ";
printInfo(e4);
}
for (label i : {-1, 0, 1, 3})
{
bool ok = e4.erase(i);
Info<< "erase(" << i << ") = " << ok << " resulting ";
printInfo(e4);
}
for (label i : {-1, 0, 1, 3})
{
bool ok = e4.insert(i);
Info<< "insert(" << i << ") = " << ok << " resulting ";
printInfo(e4);
}
e4.flip();
Info<< "flipped ";
printInfo(e4);
for (label i : {-1, 0, 1, 3})
{
bool ok = e4.erase(i);
Info<< "erase(" << i << ") = " << ok << " resulting ";
printInfo(e4);
}
e4.sort();
Info<< "sorted ";
printInfo(e4);
return 0;
}
// ************************************************************************* //

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation
\\/ M anipulation |
\\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -70,17 +70,23 @@ public:
// Constructors
//- Null constructor for lists
//- Construct null with invalid point labels (-1)
inline edge();
//- Construct from components
inline edge(const label a, const label b);
inline edge(const label from, const label to);
//- Construct, optionally sorted with start less-than end
inline edge(const label from, const label to, const bool doSort);
//- Construct from FixedList
inline edge(const FixedList<label, 2>&);
inline edge(const FixedList<label, 2>& lst);
//- Construct, optionally sorted with start less-than end
inline edge(const FixedList<label, 2>& lst, const bool doSort);
//- Construct from Istream
inline edge(Istream&);
inline edge(Istream& is);
// Member Functions
@ -97,11 +103,45 @@ public:
//- Return end vertex label
inline label& end();
//- Given one vertex, return the other
inline label otherVertex(const label a) const;
//- Do the edges share a common vertex index?
inline bool connects(const edge& other) const;
//- Return common vertex
inline label commonVertex(const edge& a) const;
//- Return vertex common with otherEdge or -1 on failure
inline label commonVertex(const edge& other) const;
//- Given one vertex index, return the other one.
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;
//- Return the number of unique, valid (non -1) point labels.
// Similar to a HashTable::size().
inline label count() const;
//- Insert the index if it did not previously exist on the edge.
// Returns true on success. A negative label never inserts.
// Similar to a HashTable::insert().
inline bool insert(const label index);
//- Remove an existing index from the edge and set its location to '-1'.
// Returns true on success. A negative label never removes.
// Similar to a HashTable::erase().
inline bool erase(const label index);
//- True if the edge is sorted such that start is less-than end
inline bool sorted() const;
//- Sort start/end that start is less-than end
inline void sort();
//- Flip the edge in-place.
inline void flip();
@ -110,23 +150,26 @@ public:
inline edge reverseEdge() const;
//- Return centre (centroid)
inline point centre(const pointField&) const;
inline point centre(const UList<point>& pts) const;
//- Return the vector (end - start)
inline vector vec(const pointField&) const;
inline vector vec(const UList<point>& pts) const;
//- Return the unit vector (end - start)
inline vector unitVec(const UList<point>& pts) const;
//- Return scalar magnitude
inline scalar mag(const pointField&) const;
inline scalar mag(const UList<point>& pts) const;
//- Return edge line
inline linePointRef line(const pointField&) const;
inline linePointRef line(const UList<point>& pts) const;
//- Compare edges
// Returns:
// - 0: different
// - +1: identical
// - -1: same edge, but different orientation
static inline int compare(const edge&, const edge&);
static inline int compare(const edge& a, const edge& b);
// Friend Operators

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
\\/ M anipulation |
\\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -28,11 +28,6 @@ License
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
// return
// - 0: different
// - +1: identical
// - -1: same edge, but different orientation
inline int Foam::edge::compare(const edge& a, const edge& b)
{
if (a[0] == b[0] && a[1] == b[1])
@ -53,20 +48,52 @@ inline int Foam::edge::compare(const edge& a, const edge& b)
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
inline Foam::edge::edge()
:
FixedList<label, 2>(-1)
{}
inline Foam::edge::edge(const label a, const label b)
inline Foam::edge::edge(const label from, const label to)
{
start() = a;
end() = b;
start() = from;
end() = to;
}
inline Foam::edge::edge(const FixedList<label, 2>& a)
inline Foam::edge::edge(const label from, const label to, const bool doSort)
{
start() = a[0];
end() = a[1];
if (doSort && from > to)
{
start() = to;
end() = from;
}
else
{
start() = from;
end() = to;
}
}
inline Foam::edge::edge(const FixedList<label, 2>& lst)
{
start() = lst[0];
end() = lst[1];
}
inline Foam::edge::edge(const FixedList<label, 2>& lst, const bool doSort)
{
if (doSort && lst[0] > lst[1])
{
start() = lst[1];
end() = lst[0];
}
else
{
start() = lst[0];
end() = lst[1];
}
}
@ -100,13 +127,43 @@ inline Foam::label& Foam::edge::end()
}
inline Foam::label Foam::edge::otherVertex(const label a) const
inline bool Foam::edge::found(const label index) const
{
if (a == start())
return (index == start() || index == end());
}
inline bool Foam::edge::connects(const edge& other) const
{
return (other.found(this->start()) || other.found(this->end()));
}
inline Foam::label Foam::edge::commonVertex(const edge& other) const
{
if (other.found(this->start()))
{
return this->start();
}
else if (other.found(this->end()))
{
return this->end();
}
else
{
// No shared vertex.
return -1;
}
}
inline Foam::label Foam::edge::otherVertex(const label index) const
{
if (index == start())
{
return end();
}
else if (a == end())
else if (index == end())
{
return start();
}
@ -118,20 +175,112 @@ inline Foam::label Foam::edge::otherVertex(const label a) const
}
inline Foam::label Foam::edge::commonVertex(const edge& a) const
inline Foam::label Foam::edge::collapse()
{
if (start() == a.start() || start() == a.end())
// 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)
{
return start();
end() = -1;
--n;
}
else if (end() == a.start() || end() == a.end())
if (start() == -1)
{
return end();
--n;
}
else
return n;
}
inline Foam::label Foam::edge::count() const
{
label n = 2;
if (start() == end() || end() == -1)
{
// No shared vertex.
return -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
{
return (start() < end());
}
inline void Foam::edge::sort()
{
if (start() > end())
{
flip();
}
}
@ -148,27 +297,36 @@ inline Foam::edge Foam::edge::reverseEdge() const
}
inline Foam::point Foam::edge::centre(const pointField& p) const
inline Foam::point Foam::edge::centre(const UList<point>& pts) const
{
return 0.5*(p[start()] + p[end()]);
return 0.5*(pts[start()] + pts[end()]);
}
inline Foam::vector Foam::edge::vec(const pointField& p) const
inline Foam::vector Foam::edge::vec(const UList<point>& pts) const
{
return p[end()] - p[start()];
return pts[end()] - pts[start()];
}
inline Foam::scalar Foam::edge::mag(const pointField& p) const
inline Foam::vector Foam::edge::unitVec(const UList<point>& pts) const
{
return ::Foam::mag(vec(p));
Foam::vector v = pts[end()] - pts[start()];
v /= ::Foam::mag(v) + VSMALL;
return v;
}
inline Foam::linePointRef Foam::edge::line(const pointField& p) const
inline Foam::scalar Foam::edge::mag(const UList<point>& pts) const
{
return linePointRef(p[start()], p[end()]);
return ::Foam::mag(vec(pts));
}
inline Foam::linePointRef Foam::edge::line(const UList<point>& pts) const
{
return linePointRef(pts[start()], pts[end()]);
}