/*===========================================================================*\
* *
* OpenVolumeMesh *
* Copyright (C) 2011 by Computer Graphics Group, RWTH Aachen *
* www.openvolumemesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenVolumeMesh. *
* *
* OpenVolumeMesh is free software: you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 3 of *
* the License, or (at your option) any later version with the *
* following exceptions: *
* *
* If other files instantiate templates or use macros *
* or inline functions from this file, or you compile this file and *
* link it with other files to produce an executable, this file does *
* not by itself cause the resulting executable to be covered by the *
* GNU Lesser General Public License. This exception does not however *
* invalidate any other reasons why the executable file might be *
* covered by the GNU Lesser General Public License. *
* *
* OpenVolumeMesh 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 Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU LesserGeneral Public *
* License along with OpenVolumeMesh. If not, *
* see . *
* *
\*===========================================================================*/
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* $LastChangedBy$ *
* *
\*===========================================================================*/
#include
#include "HexahedralMeshIterators.hh"
#include "HexahedralMeshTopologyKernel.hh"
namespace OpenVolumeMesh {
//================================================================================================
// CellSheetCellIter
//================================================================================================
CellSheetCellIter::CellSheetCellIter(const CellHandle& _ref_h,
const unsigned char _orthDir, const HexahedralMeshTopologyKernel* _mesh, int _max_laps) :
BaseIter(_mesh, _ref_h, _max_laps) {
if(!_mesh->has_face_bottom_up_incidences()) {
#ifndef NDEBUG
std::cerr << "This iterator needs bottom-up incidences!" << std::endl;
#endif
BaseIter::valid(false);
return;
}
// First off, get all surrounding cells
std::vector halffaces = _mesh->cell(_ref_h).halffaces();
for(std::vector::const_iterator hf_it = halffaces.begin();
hf_it != halffaces.end(); ++hf_it) {
// Add those, that are perpendicular to the specified _orthDir
if(_mesh->orientation(*hf_it, _ref_h) != _orthDir &&
_mesh->orientation(*hf_it, _ref_h) != _mesh->opposite_orientation(_orthDir)) {
CellHandle ch = _mesh->incident_cell(_mesh->opposite_halfface_handle(*hf_it));
if(ch != TopologyKernel::InvalidCellHandle) {
neighb_sheet_cell_hs_.push_back(ch);
}
}
}
// Remove all duplicate entries
std::sort(neighb_sheet_cell_hs_.begin(), neighb_sheet_cell_hs_.end());
neighb_sheet_cell_hs_.resize(std::unique(neighb_sheet_cell_hs_.begin(), neighb_sheet_cell_hs_.end()) - neighb_sheet_cell_hs_.begin());
cur_index_ = 0;
BaseIter::valid(neighb_sheet_cell_hs_.size() > 0);
if(BaseIter::valid()) {
BaseIter::cur_handle(neighb_sheet_cell_hs_[cur_index_]);
}
}
CellSheetCellIter& CellSheetCellIter::operator--() {
if (cur_index_ == 0) {
cur_index_ = neighb_sheet_cell_hs_.size() - 1;
--lap_;
if (lap_ < 0)
BaseIter::valid(false);
} else {
--cur_index_;
}
BaseIter::cur_handle(neighb_sheet_cell_hs_[cur_index_]);
return *this;
}
CellSheetCellIter& CellSheetCellIter::operator++() {
++cur_index_;
if(cur_index_ == neighb_sheet_cell_hs_.size()) {
cur_index_ = 0;
++lap_;
if (lap_ >= max_laps_)
BaseIter::valid(false);
}
BaseIter::cur_handle(neighb_sheet_cell_hs_[cur_index_]);
return *this;
}
//================================================================================================
// HalfFaceSheetHalfFaceIter
//================================================================================================
HalfFaceSheetHalfFaceIter::HalfFaceSheetHalfFaceIter(const HalfFaceHandle& _ref_h,
const HexahedralMeshTopologyKernel* _mesh, int _max_laps) :
BaseIter(_mesh, _ref_h, _max_laps) {
if(!_mesh->has_face_bottom_up_incidences()) {
#ifndef NDEBUG
std::cerr << "This iterator needs bottom-up incidences!" << std::endl;
#endif
BaseIter::valid(false);
return;
}
/*
* Each halfface uniquely belongs to either a cell
* or the boundary. If the halfface belongs
* to a cell, it suffices to determine the local axis
* the halfface represents w.r.t. the cell and to
* iterate over all neighboring cells orthogonal to
* this direction. We have to find those halffaces
* of the neighboring cells that contain exactly one
* of the initial halfface's opposite halfedges.
*/
if(_mesh->is_boundary(_ref_h)) {
#ifndef NDEBUG
std::cerr << "HalfFaceSheetHalfFaceIter: HalfFace is boundary!" << std::endl;
#endif
BaseIter::valid(false);
return;
}
CellHandle ch = _mesh->incident_cell(_ref_h);
unsigned char orientation = _mesh->orientation(_ref_h, ch);
std::vector hes_v = _mesh->opposite_halfface(_mesh->halfface(_ref_h)).halfedges();
std::set hes;
hes.insert(hes_v.begin(), hes_v.end());
for(CellSheetCellIter csc_it = _mesh->csc_iter(ch, orientation);
csc_it.valid(); ++csc_it) {
std::vector hfs = _mesh->cell(*csc_it).halffaces();
for(std::vector::const_iterator hf_it = hfs.begin();
hf_it != hfs.end(); ++hf_it) {
std::vector hf_hes = _mesh->halfface(*hf_it).halfedges();
for(std::vector::const_iterator he_it = hf_hes.begin();
he_it != hf_hes.end(); ++he_it) {
if(hes.count(*he_it) > 0) {
// Found halfface that lies on the same sheet
adjacent_halffaces_.push_back(*hf_it);
common_edges_.push_back(_mesh->edge_handle(*he_it));
break;
}
}
}
}
cur_index_ = 0;
BaseIter::valid(adjacent_halffaces_.size() > 0);
if(BaseIter::valid()) {
BaseIter::cur_handle(adjacent_halffaces_[cur_index_]);
}
}
HalfFaceSheetHalfFaceIter& HalfFaceSheetHalfFaceIter::operator--() {
if (cur_index_ == 0) {
cur_index_ = adjacent_halffaces_.size() - 1;
--lap_;
if (lap_ < 0)
BaseIter::valid(false);
} else {
--cur_index_;
}
BaseIter::cur_handle(adjacent_halffaces_[cur_index_]);
return *this;
}
HalfFaceSheetHalfFaceIter& HalfFaceSheetHalfFaceIter::operator++() {
++cur_index_;
if(cur_index_ == adjacent_halffaces_.size()) {
cur_index_ = 0;
++lap_;
if (lap_ >= max_laps_)
BaseIter::valid(false);
}
BaseIter::cur_handle(adjacent_halffaces_[cur_index_]);
return *this;
}
//================================================================================================
// HexVertexIter
//================================================================================================
HexVertexIter::HexVertexIter(const CellHandle& _ref_h,
const HexahedralMeshTopologyKernel* _mesh, int _max_laps) :
BaseIter(_mesh, _ref_h, _max_laps) {
assert(_ref_h.is_valid());
HexahedralMeshTopologyKernel::Cell cell = _mesh->cell(_ref_h);
assert(cell.halffaces().size() == 6);
// Get first half-face
HalfFaceHandle curHF = *cell.halffaces().begin();
assert(curHF.is_valid());
// Get first half-edge
assert(_mesh->halfface(curHF).halfedges().size() == 4);
HalfEdgeHandle curHE = *_mesh->halfface(curHF).halfedges().begin();
assert(curHE.is_valid());
vertices_.push_back(_mesh->halfedge(curHE).from_vertex());
curHE = _mesh->prev_halfedge_in_halfface(curHE, curHF);
vertices_.push_back(_mesh->halfedge(curHE).from_vertex());
curHE = _mesh->prev_halfedge_in_halfface(curHE, curHF);
vertices_.push_back(_mesh->halfedge(curHE).from_vertex());
curHE = _mesh->prev_halfedge_in_halfface(curHE, curHF);
vertices_.push_back(_mesh->halfedge(curHE).from_vertex());
curHE = _mesh->prev_halfedge_in_halfface(curHE, curHF);
curHF = _mesh->adjacent_halfface_in_cell(curHF, curHE);
curHE = _mesh->opposite_halfedge_handle(curHE);
curHE = _mesh->next_halfedge_in_halfface(curHE, curHF);
curHE = _mesh->next_halfedge_in_halfface(curHE, curHF);
curHF = _mesh->adjacent_halfface_in_cell(curHF, curHE);
curHE = _mesh->opposite_halfedge_handle(curHE);
vertices_.push_back(_mesh->halfedge(curHE).to_vertex());
curHE = _mesh->prev_halfedge_in_halfface(curHE, curHF);
vertices_.push_back(_mesh->halfedge(curHE).to_vertex());
curHE = _mesh->prev_halfedge_in_halfface(curHE, curHF);
vertices_.push_back(_mesh->halfedge(curHE).to_vertex());
vertices_.push_back(_mesh->halfedge(curHE).from_vertex());
cur_index_ = 0;
BaseIter::valid(vertices_.size() > 0);
if(BaseIter::valid()) {
BaseIter::cur_handle(vertices_[cur_index_]);
}
}
HexVertexIter& HexVertexIter::operator--() {
if (cur_index_ == 0) {
cur_index_ = vertices_.size() - 1;
--lap_;
if (lap_ < 0)
BaseIter::valid(false);
} else {
--cur_index_;
}
BaseIter::cur_handle(vertices_[cur_index_]);
return *this;
}
HexVertexIter& HexVertexIter::operator++() {
++cur_index_;
if(cur_index_ == vertices_.size()) {
cur_index_ = 0;
++lap_;
if (lap_ >= max_laps_)
BaseIter::valid(false);
}
BaseIter::cur_handle(vertices_[cur_index_]);
return *this;
}
} // Namespace OpenVolumeMesh