orientation.
To determine if 2 neighbors have the same or opposite orientation we use
- a table of truth. Its entries are indexes by the local indices of the
+ a truth table. Its entries are indexed by the local indices of the
common face. For example if two elements share a face, and this face is
face 0 for element 0 and face 1 for element 1, then table(0,1) will tell
whether the orientation are the same (true) or opposite (false).
in 1D and 2D to generate the table.
Assuming that a surface respects the standard orientation for 2d meshes,
- the tables of truth are symmetric and their true values are the following
+ the truth tables are symmetric and their true values are the following
- 1D curves: (0,1)
- 2D surface: (0,1),(0,2),(1,3),(2,3)
{
case 1:
{
- bool values[][2] = {{false, true}, {true, false}};
+ const bool values[][2] = {{false, true}, {true, false}};
for (const unsigned int i : GeometryInfo<dim>::face_indices())
for (const unsigned int j : GeometryInfo<dim>::face_indices())
- correct(i, j) = (values[i][j]);
+ correct(i, j) = values[i][j];
break;
}
case 2:
{
- bool values[][4] = {{false, true, true, false},
- {true, false, false, true},
- {true, false, false, true},
- {false, true, true, false}};
+ const bool values[][4] = {{false, true, true, false},
+ {true, false, false, true},
+ {true, false, false, true},
+ {false, true, true, false}};
for (const unsigned int i : GeometryInfo<dim>::face_indices())
for (const unsigned int j : GeometryInfo<dim>::face_indices())
correct(i, j) = (values[i][j]);
std::list<active_cell_iterator> this_round, next_round;
active_cell_iterator neighbor;
+ // Start with the first cell and (arbitrarily) decide that its
+ // direction flag should be 'true':
this_round.push_back(begin_active());
begin_active()->set_direction_flag(true);
begin_active()->set_user_flag();
while (this_round.size() > 0)
{
- for (typename std::list<active_cell_iterator>::iterator cell =
- this_round.begin();
- cell != this_round.end();
- ++cell)
+ for (const auto &cell : this_round)
{
- for (const unsigned int i : (*cell)->face_indices())
+ for (const unsigned int i : cell->face_indices())
{
- if (!((*cell)->face(i)->at_boundary()))
+ if (cell->face(i)->at_boundary() == false)
{
- neighbor = (*cell)->neighbor(i);
+ // Consider the i'th neighbor of a cell for
+ // which we have already set the direction:
+ neighbor = cell->neighbor(i);
- unsigned int cf = (*cell)->face_index(i);
- unsigned int j = 0;
- while (neighbor->face_index(j) != cf)
- {
- ++j;
- }
+ const unsigned int nb_of_nb =
+ cell->neighbor_of_neighbor(i);
-
- // If we already saw this guy, check that everything is
- // fine
+ // If we already saw this neighboring cell,
+ // check that everything is fine:
if (neighbor->user_flag_set())
{
- // If we have visited this guy, then the ordering and
- // the orientation should agree
- Assert(!(correct(i, j) ^
- (neighbor->direction_flag() ==
- (*cell)->direction_flag())),
- ExcNonOrientableTriangulation());
+ Assert(
+ !(correct(i, nb_of_nb) ^
+ (neighbor->direction_flag() ==
+ cell->direction_flag())),
+ ExcMessage(
+ "The triangulation you are trying to create is not orientable."));
}
else
{
- next_round.push_back(neighbor);
- neighbor->set_user_flag();
- if ((correct(i, j) ^ (neighbor->direction_flag() ==
- (*cell)->direction_flag())))
+ // We had not seen this cell yet. Set its
+ // orientation flag (if necessary), mark it
+ // as treated via the user flag, and push it
+ // onto the list of cells to start work from
+ // the next time around:
+ if (correct(i, nb_of_nb) ^
+ (neighbor->direction_flag() ==
+ cell->direction_flag()))
neighbor->set_direction_flag(
!neighbor->direction_flag());
+ neighbor->set_user_flag();
+ next_round.push_back(neighbor);
}
}
}
}
// Before we quit let's check that if the triangulation is
- // disconnected that we still get all cells
+ // disconnected that we still get all cells by starting
+ // again from the first cell we haven't treated yet -- that
+ // is, the first cell of the next disconnected component we
+ // had not yet touched.
if (next_round.empty())
for (const auto &cell : this->active_cell_iterators())
if (cell->user_flag_set() == false)
break;
}
- this_round = next_round;
+ // Go on to the next round:
+ next_round.swap(this_round);
next_round.clear();
}
clear_user_flags();