Commit 54564c5c authored by Vincent Knyrim's avatar Vincent Knyrim
Browse files

Finally fixed default `check()`.

All faces belonging to a connected component
are visited using a breadth first search algorithm.
Thus, indices "jumping around" as seen in the `stripe` test
are no longer a problem.

If there are faces left after dealing with an entire
connected component, the one with smallest index
is used as the reference for its connected component.
parent a17178d8
#pragma once
#include <array>
#include <queue>
#include <dune/geometry/type.hh>
#include <dune/geometry/referenceelements.hh>
......@@ -404,64 +405,74 @@ namespace Dec
{
// remember which faces have been visited and, if necessary, reoriented
std::vector<bool> oriented(size(0), false);
// use orientation of face_0 as reference
oriented[0] = true;
// visit all faces
for (IndexType T1 = 0; T1 < size(0); ++T1) {
// check adjacent faces by iterating the half edges
IndexType i = halfEdgeOfIndex<0>(T1);
for (int n_i = 0; n_i < dimension+1; ++n_i) {
// skip half edges on the inside of the boundary curve
auto const& he = halfEdge(i);
if (he.opposite_ == invalid || halfEdge(he.opposite_).outside()) {
i = he.next_;
continue;
}
auto const& he_opp = halfEdge(he.opposite_);
IndexType T2 = he_opp.face_; // no boundary edge
if (! (oriented[T1] || oriented[T2]))
{
msg("Warning: The check method can not deal with this case, yet.");
msg(" The faces ", T1, " and ", T2, " have the same orientation.");
msg(" However, neither has been checked against the reference face 0.");
}
// If `he` and `he_opp` have different target vectors
// the faces have the same orientation.
// Otherwise the faces have different orientations.
if(he.vertex_ == he_opp.vertex_) {
// If they have both been checked against the reference,
// the grid is not orientable.
if (oriented[T1] && oriented[T2]) {
std::string message = "The grid is not orientable:";
// " ERROR: ";
message += "\n The faces " + std::to_string(T1)
+ " and " + std::to_string(T2) + " have different orientation,";
message += "\n although both have been checked";
message += "\n -- directly or indirectly --";
message += "\n against the reference face 0.";
error_exit(message);
std::queue<IndexType> face_buffer;
// make sure to visit all faces
for (IndexType reference = 0; reference < size(0); ++reference) {
// At this point face_buffer should be empty.
assert(face_buffer.empty());
// All oriented faces have been visited before.
if (oriented[reference])
continue;
// Use the face as the reference for the new connected component.
// Note: In the first iteration this is face 0.
face_buffer.push(reference);
oriented[reference] = true;
while (!face_buffer.empty()) {
auto const T1 = face_buffer.front();
face_buffer.pop();
// All elements of the queue should be oriented.
assert(oriented[T1]);
// Check adjacent faces by iterating the half edges.
auto i = halfEdgeOfIndex<0>(T1);
for (int n_i = 0; n_i < dimension + 1; ++n_i) {
// Skip half edges on the inside of the boundary curve.
auto const& he = halfEdge(i);
if (he.opposite_ == invalid) { // If the opposite is on the boundary,
i = he.next_; // opposite_ was not yet defined.
continue;
}
// One of the faces was checked against the reference,
// so reorient the other.
msg("Note: The faces ", T1, " and ", T2, " have different orientation.");
if (oriented[T1])
auto const& he_opp = halfEdge(he.opposite_);
assert(!he_opp.outside());
auto const T2 = he_opp.face_; // not a boundary edge
// If `he` and `he_opp` have different target vectors
// the faces have the same orientation.
// Otherwise the faces have different orientations.
if(he.vertex_ == he_opp.vertex_) {
msg("Note: The faces ", T1, " and ", T2, " have different orientation.");
// If they have both been checked against the reference,
// the grid is not orientable.
if (oriented[T2]) {
std::string message = "The grid is not orientable:";
// " ERROR: ";
message += "\n The faces " + std::to_string(T1)
+ " and " + std::to_string(T2) + " have different orientation,";
message += "\n although both have been checked";
message += "\n -- directly or indirectly --";
message += "\n against the reference face " + std::to_string(reference) + ".";
error_exit(message);
}
// T1 was checked against the reference, so reorient T2.
reorient(T2);
else
reorient(T1);
}
// Now both faces have been checked against the reference.
oriented[T1] = oriented[T2] = true;
}
// If T2 was not visited before, remember to visit its neighbors!
if(!oriented[T2])
face_buffer.push(T2);
// Now both faces have been checked against the reference.
oriented[T2] = true;
i = he.next_;
i = he.next_;
}
}
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment