/*===========================================================================*\
* *
* OpenMesh *
* Copyright (C) 2001-2012 by Computer Graphics Group, RWTH Aachen *
* www.openmesh.org *
* *
*---------------------------------------------------------------------------*
* This file is part of OpenMesh. *
* *
* OpenMesh 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. *
* *
* OpenMesh 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 OpenMesh. If not, *
* see . *
* *
\*===========================================================================*/
/*===========================================================================*\
* *
* $Revision$ *
* $Date$ *
* *
\*===========================================================================*/
/** \file RulesT.cc
*/
//=============================================================================
//
// Rules - IMPLEMENTATION
//
//=============================================================================
#define OPENMESH_SUBDIVIDER_ADAPTIVE_RULEST_CC
//== INCLUDES =================================================================
#include
#include
#include "RulesT.hh"
// --------------------
#if defined(OM_CC_MIPS)
# include
#else
# include
#endif
#if defined(OM_CC_MSVC)
# pragma warning(disable:4244)
#endif
//== NAMESPACE ================================================================
namespace OpenMesh { // BEGIN_NS_OPENMESH
namespace Subdivider { // BEGIN_NS_DECIMATER
namespace Adaptive { // BEGIN_NS_ADAPTIVE
//== IMPLEMENTATION ==========================================================
#define MOBJ Base::mesh_.data
#define FH face_handle
#define VH vertex_handle
#define EH edge_handle
#define HEH halfedge_handle
#define NHEH next_halfedge_handle
#define PHEH prev_halfedge_handle
#define OHEH opposite_halfedge_handle
#define TVH to_vertex_handle
#define FVH from_vertex_handle
// ------------------------------------------------------------------ Tvv3 ----
template
void
Tvv3::raise(typename M::FaceHandle& _fh, state_t _target_state)
{
if (MOBJ(_fh).state() < _target_state)
{
this->update(_fh, _target_state);
typename M::VertexVertexIter vv_it;
typename M::FaceVertexIter fv_it;
typename M::VertexHandle vh;
typename M::Point position(0.0, 0.0, 0.0);
typename M::Point face_position;
const typename M::Point zero_point(0.0, 0.0, 0.0);
std::vector vertex_vector;
int valence(0);
// raise all adjacent vertices to level x-1
for (fv_it = Base::mesh_.fv_iter(_fh); fv_it; ++fv_it) {
vertex_vector.push_back(fv_it.handle());
}
while(!vertex_vector.empty()) {
vh = vertex_vector.back();
vertex_vector.pop_back();
if (_target_state > 1)
Base::prev_rule()->raise(vh, _target_state - 1);
}
face_position = MOBJ(_fh).position(_target_state - 1);
typename M::EdgeHandle eh;
std::vector edge_vector;
// interior face
if (!Base::mesh_.is_boundary(_fh) || MOBJ(_fh).final()) {
// insert new vertex
vh = Base::mesh_.new_vertex();
Base::mesh_.split(_fh, vh);
// calculate display position for new vertex
for (vv_it = Base::mesh_.vv_iter(vh); vv_it; ++vv_it)
{
position += Base::mesh_.point(vv_it.handle());
++valence;
}
position /= valence;
// set attributes for new vertex
Base::mesh_.set_point(vh, position);
MOBJ(vh).set_position(_target_state, zero_point);
MOBJ(vh).set_state(_target_state);
MOBJ(vh).set_not_final();
typename M::VertexOHalfedgeIter voh_it;
// check for edge flipping
for (voh_it = Base::mesh_.voh_iter(vh); voh_it; ++voh_it) {
if (Base::mesh_.FH(voh_it.handle()).is_valid()) {
MOBJ(Base::mesh_.FH(voh_it.handle())).set_state(_target_state);
MOBJ(Base::mesh_.FH(voh_it.handle())).set_not_final();
MOBJ(Base::mesh_.FH(voh_it.handle())).set_position(_target_state - 1, face_position);
for (state_t j = 0; j < _target_state; ++j) {
MOBJ(Base::mesh_.FH(voh_it.handle())).set_position(j, MOBJ(_fh).position(j));
}
if (Base::mesh_.FH(Base::mesh_.OHEH(Base::mesh_.NHEH(voh_it.handle()))).is_valid()) {
if (MOBJ(Base::mesh_.FH(Base::mesh_.OHEH(Base::mesh_.NHEH(voh_it.handle())))).state() == _target_state) {
if (Base::mesh_.is_flip_ok(Base::mesh_.EH(Base::mesh_.NHEH(voh_it.handle())))) {
edge_vector.push_back(Base::mesh_.EH(Base::mesh_.NHEH(voh_it.handle())));
}
}
}
}
}
}
// boundary face
else {
typename M::VertexHandle vh1 = Base::mesh_.new_vertex(),
vh2 = Base::mesh_.new_vertex();
typename M::HalfedgeHandle hh2 = Base::mesh_.HEH(_fh),
hh1, hh3;
while (!Base::mesh_.is_boundary(Base::mesh_.OHEH(hh2)))
hh2 = Base::mesh_.NHEH(hh2);
eh = Base::mesh_.EH(hh2);
hh2 = Base::mesh_.NHEH(hh2);
hh1 = Base::mesh_.NHEH(hh2);
assert(Base::mesh_.is_boundary(eh));
Base::mesh_.split(eh, vh1);
eh = Base::mesh_.EH(Base::mesh_.PHEH(hh2));
assert(Base::mesh_.is_boundary(eh));
Base::mesh_.split(eh, vh2);
hh3 = Base::mesh_.NHEH(Base::mesh_.OHEH(Base::mesh_.PHEH(hh1)));
typename M::VertexHandle vh0(Base::mesh_.TVH(hh1)),
vh3(Base::mesh_.FVH(hh2));
// set display position and attributes for new vertices
Base::mesh_.set_point(vh1, (Base::mesh_.point(vh0) * 2.0 + Base::mesh_.point(vh3)) / 3.0);
MOBJ(vh1).set_position(_target_state, zero_point);
MOBJ(vh1).set_state(_target_state);
MOBJ(vh1).set_not_final();
MOBJ(vh0).set_position(_target_state, MOBJ(vh0).position(_target_state - 1) * 3.0);
MOBJ(vh0).set_state(_target_state);
MOBJ(vh0).set_not_final();
// set display position and attributes for old vertices
Base::mesh_.set_point(vh2, (Base::mesh_.point(vh3) * 2.0 + Base::mesh_.point(vh0)) / 3.0);
MOBJ(vh2).set_position(_target_state, zero_point);
MOBJ(vh2).set_state(_target_state);
MOBJ(vh2).set_not_final();
MOBJ(vh3).set_position(_target_state, MOBJ(vh3).position(_target_state - 1) * 3.0);
MOBJ(vh3).set_state(_target_state);
MOBJ(vh3).set_not_final();
// init 3 faces
MOBJ(Base::mesh_.FH(hh1)).set_state(_target_state);
MOBJ(Base::mesh_.FH(hh1)).set_not_final();
MOBJ(Base::mesh_.FH(hh1)).set_position(_target_state - 1, face_position);
MOBJ(Base::mesh_.FH(hh2)).set_state(_target_state);
MOBJ(Base::mesh_.FH(hh2)).set_not_final();
MOBJ(Base::mesh_.FH(hh2)).set_position(_target_state - 1, face_position);
MOBJ(Base::mesh_.FH(hh3)).set_state(_target_state);
MOBJ(Base::mesh_.FH(hh3)).set_final();
MOBJ(Base::mesh_.FH(hh3)).set_position(_target_state - 1, face_position);
for (state_t j = 0; j < _target_state; ++j) {
MOBJ(Base::mesh_.FH(hh1)).set_position(j, MOBJ(_fh).position(j));
}
for (state_t j = 0; j < _target_state; ++j) {
MOBJ(Base::mesh_.FH(hh2)).set_position(j, MOBJ(_fh).position(j));
}
for (state_t j = 0; j < _target_state; ++j) {
MOBJ(Base::mesh_.FH(hh3)).set_position(j, MOBJ(_fh).position(j));
}
// check for edge flipping
if (Base::mesh_.FH(Base::mesh_.OHEH(hh1)).is_valid()) {
if (MOBJ(Base::mesh_.FH(Base::mesh_.OHEH(hh1))).state() == _target_state) {
if (Base::mesh_.is_flip_ok(Base::mesh_.EH(hh1))) {
edge_vector.push_back(Base::mesh_.EH(hh1));
}
}
}
if (Base::mesh_.FH(Base::mesh_.OHEH(hh2)).is_valid()) {
if (MOBJ(Base::mesh_.FH(Base::mesh_.OHEH(hh2))).state() == _target_state) {
if (Base::mesh_.is_flip_ok(Base::mesh_.EH(hh2))) {
edge_vector.push_back(Base::mesh_.EH(hh2));
}
}
}
}
// flip edges
while (!edge_vector.empty()) {
eh = edge_vector.back();
edge_vector.pop_back();
assert(Base::mesh_.is_flip_ok(eh));
Base::mesh_.flip(eh);
MOBJ(Base::mesh_.FH(Base::mesh_.HEH(eh, 0))).set_final();
MOBJ(Base::mesh_.FH(Base::mesh_.HEH(eh, 1))).set_final();
MOBJ(Base::mesh_.FH(Base::mesh_.HEH(eh, 0))).set_state(_target_state);
MOBJ(Base::mesh_.FH(Base::mesh_.HEH(eh, 1))).set_state(_target_state);
MOBJ(Base::mesh_.FH(Base::mesh_.HEH(eh, 0))).set_position(_target_state, face_position);
MOBJ(Base::mesh_.FH(Base::mesh_.HEH(eh, 1))).set_position(_target_state, face_position);
}
}
}
template
void Tvv3::raise(typename M::VertexHandle& _vh, state_t _target_state) {
if (MOBJ(_vh).state() < _target_state) {
this->update(_vh, _target_state);
// multiply old position by 3
MOBJ(_vh).set_position(_target_state, MOBJ(_vh).position(_target_state - 1) * 3.0);
MOBJ(_vh).inc_state();
assert(MOBJ(_vh).state() == _target_state);
}
}
// ------------------------------------------------------------------ Tvv4 ----
template
void
Tvv4::raise(typename M::FaceHandle& _fh, state_t _target_state)
{
if (MOBJ(_fh).state() < _target_state) {
this->update(_fh, _target_state);
typename M::FaceVertexIter fv_it;
typename M::VertexHandle temp_vh;
typename M::Point face_position;
const typename M::Point zero_point(0.0, 0.0, 0.0);
std::vector vertex_vector;
std::vector halfedge_vector;
// raise all adjacent vertices to level x-1
for (fv_it = Base::mesh_.fv_iter(_fh); fv_it; ++fv_it) {
vertex_vector.push_back(fv_it.handle());
}
while(!vertex_vector.empty()) {
temp_vh = vertex_vector.back();
vertex_vector.pop_back();
if (_target_state > 1) {
Base::prev_rule()->raise(temp_vh, _target_state - 1);
}
}
face_position = MOBJ(_fh).position(_target_state - 1);
typename M::HalfedgeHandle hh[3];
typename M::VertexHandle vh[3];
typename M::VertexHandle new_vh[3];
typename M::FaceHandle fh[4];
typename M::EdgeHandle eh;
typename M::HalfedgeHandle temp_hh;
// normal (final) face
if (MOBJ(_fh).final()) {
// define three halfedge handles around the face
hh[0] = Base::mesh_.HEH(_fh);
hh[1] = Base::mesh_.NHEH(hh[0]);
hh[2] = Base::mesh_.NHEH(hh[1]);
assert(hh[0] == Base::mesh_.NHEH(hh[2]));
vh[0] = Base::mesh_.TVH(hh[0]);
vh[1] = Base::mesh_.TVH(hh[1]);
vh[2] = Base::mesh_.TVH(hh[2]);
new_vh[0] = Base::mesh_.add_vertex(zero_point);
new_vh[1] = Base::mesh_.add_vertex(zero_point);
new_vh[2] = Base::mesh_.add_vertex(zero_point);
// split three edges
split_edge(hh[0], new_vh[0], _target_state);
eh = Base::mesh_.EH(Base::mesh_.PHEH(hh[2]));
split_edge(hh[1], new_vh[1], _target_state);
split_edge(hh[2], new_vh[2], _target_state);
assert(Base::mesh_.FVH(hh[2]) == vh[1]);
assert(Base::mesh_.FVH(hh[1]) == vh[0]);
assert(Base::mesh_.FVH(hh[0]) == vh[2]);
if (Base::mesh_.FH(Base::mesh_.OHEH(hh[0])).is_valid())
{
temp_hh = Base::mesh_.OHEH(Base::mesh_.PHEH(Base::mesh_.OHEH(hh[0])));
if (MOBJ(Base::mesh_.FH(temp_hh)).red_halfedge() != temp_hh)
halfedge_vector.push_back(temp_hh);
}
if (Base::mesh_.FH(Base::mesh_.OHEH(hh[1])).is_valid()) {
temp_hh = Base::mesh_.OHEH(Base::mesh_.PHEH(Base::mesh_.OHEH(hh[1])));
if (MOBJ(Base::mesh_.FH(temp_hh)).red_halfedge() != temp_hh)
halfedge_vector.push_back(temp_hh);
}
if (Base::mesh_.FH(Base::mesh_.OHEH(hh[2])).is_valid()) {
temp_hh = Base::mesh_.OHEH(Base::mesh_.PHEH(Base::mesh_.OHEH(hh[2])));
if (MOBJ(Base::mesh_.FH(temp_hh)).red_halfedge() != temp_hh)
halfedge_vector.push_back(temp_hh);
}
}
// splitted face, check for type
else {
// define red halfedge handle
typename M::HalfedgeHandle red_hh(MOBJ(_fh).red_halfedge());
if (Base::mesh_.FH(Base::mesh_.OHEH(Base::mesh_.PHEH(red_hh))).is_valid()
&& Base::mesh_.FH(Base::mesh_.OHEH(Base::mesh_.NHEH(Base::mesh_.OHEH(red_hh)))).is_valid()
&& MOBJ(Base::mesh_.FH(Base::mesh_.OHEH(Base::mesh_.PHEH(red_hh)))).red_halfedge() == red_hh
&& MOBJ(Base::mesh_.FH(Base::mesh_.OHEH(Base::mesh_.NHEH(Base::mesh_.OHEH(red_hh))))).red_halfedge() == red_hh)
{
// three times divided face
vh[0] = Base::mesh_.TVH(Base::mesh_.NHEH(Base::mesh_.OHEH(Base::mesh_.NHEH(Base::mesh_.OHEH(red_hh)))));
vh[1] = Base::mesh_.TVH(red_hh);
vh[2] = Base::mesh_.TVH(Base::mesh_.NHEH(Base::mesh_.OHEH(Base::mesh_.PHEH(red_hh))));
new_vh[0] = Base::mesh_.FVH(red_hh);
new_vh[1] = Base::mesh_.TVH(Base::mesh_.NHEH(Base::mesh_.OHEH(red_hh)));
new_vh[2] = Base::mesh_.TVH(Base::mesh_.NHEH(red_hh));
hh[0] = Base::mesh_.PHEH(Base::mesh_.OHEH(Base::mesh_.PHEH(red_hh)));
hh[1] = Base::mesh_.PHEH(Base::mesh_.OHEH(Base::mesh_.NHEH(Base::mesh_.OHEH(red_hh))));
hh[2] = Base::mesh_.NHEH(red_hh);
eh = Base::mesh_.EH(red_hh);
}
else
{
if ((Base::mesh_.FH(Base::mesh_.OHEH(Base::mesh_.PHEH(red_hh))).is_valid() &&
MOBJ(Base::mesh_.FH(Base::mesh_.OHEH(Base::mesh_.PHEH(red_hh)))).red_halfedge()
== red_hh )
|| (Base::mesh_.FH(Base::mesh_.OHEH(Base::mesh_.NHEH(Base::mesh_.OHEH(red_hh)))).is_valid()
&& MOBJ(Base::mesh_.FH(Base::mesh_.OHEH(Base::mesh_.NHEH(Base::mesh_.OHEH(red_hh))))).red_halfedge() == red_hh))
{
// double divided face
if (MOBJ(Base::mesh_.FH(Base::mesh_.OHEH(Base::mesh_.PHEH(red_hh)))).red_halfedge() == red_hh)
{
// first case
vh[0] = Base::mesh_.TVH(Base::mesh_.NHEH(Base::mesh_.OHEH(red_hh)));
vh[1] = Base::mesh_.TVH(red_hh);
vh[2] = Base::mesh_.TVH(Base::mesh_.NHEH(Base::mesh_.OHEH(Base::mesh_.PHEH(red_hh))));
new_vh[0] = Base::mesh_.FVH(red_hh);
new_vh[1] = Base::mesh_.add_vertex(zero_point);
new_vh[2] = Base::mesh_.TVH(Base::mesh_.NHEH(red_hh));
hh[0] = Base::mesh_.PHEH(Base::mesh_.OHEH(Base::mesh_.PHEH(red_hh)));
hh[1] = Base::mesh_.PHEH(Base::mesh_.OHEH(red_hh));
hh[2] = Base::mesh_.NHEH(red_hh);
// split one edge
eh = Base::mesh_.EH(red_hh);
split_edge(hh[1], new_vh[1], _target_state);
assert(Base::mesh_.FVH(hh[2]) == vh[1]);
assert(Base::mesh_.FVH(hh[1]) == vh[0]);
assert(Base::mesh_.FVH(hh[0]) == vh[2]);
if (Base::mesh_.FH(Base::mesh_.OHEH(hh[1])).is_valid())
{
temp_hh = Base::mesh_.OHEH(Base::mesh_.PHEH(Base::mesh_.OHEH(hh[1])));
if (MOBJ(Base::mesh_.FH(temp_hh)).red_halfedge() != temp_hh)
halfedge_vector.push_back(temp_hh);
}
}
else
{
// second case
vh[0] = Base::mesh_.TVH(Base::mesh_.NHEH(Base::mesh_.OHEH(Base::mesh_.NHEH(Base::mesh_.OHEH(red_hh)))));
vh[1] = Base::mesh_.TVH(red_hh);
vh[2] = Base::mesh_.TVH(Base::mesh_.NHEH(red_hh));
new_vh[0] = Base::mesh_.FVH(red_hh);
new_vh[1] = Base::mesh_.TVH(Base::mesh_.NHEH(Base::mesh_.OHEH(red_hh)));
new_vh[2] = Base::mesh_.add_vertex(zero_point);
hh[0] = Base::mesh_.PHEH(red_hh);
hh[1] = Base::mesh_.PHEH(Base::mesh_.OHEH(Base::mesh_.NHEH(Base::mesh_.OHEH(red_hh))));
hh[2] = Base::mesh_.NHEH(red_hh);
// split one edge
eh = Base::mesh_.EH(red_hh);
split_edge(hh[2], new_vh[2], _target_state);
assert(Base::mesh_.FVH(hh[2]) == vh[1]);
assert(Base::mesh_.FVH(hh[1]) == vh[0]);
assert(Base::mesh_.FVH(hh[0]) == vh[2]);
if (Base::mesh_.FH(Base::mesh_.OHEH(hh[2])).is_valid()) {
temp_hh = Base::mesh_.OHEH(Base::mesh_.PHEH(Base::mesh_.OHEH(hh[2])));
if (MOBJ(Base::mesh_.FH(temp_hh)).red_halfedge() != temp_hh)
halfedge_vector.push_back(temp_hh);
}
}
}
else {
// one time divided face
vh[0] = Base::mesh_.TVH(Base::mesh_.NHEH(Base::mesh_.OHEH(red_hh)));
vh[1] = Base::mesh_.TVH(red_hh);
vh[2] = Base::mesh_.TVH(Base::mesh_.NHEH(red_hh));
new_vh[0] = Base::mesh_.FVH(red_hh);
new_vh[1] = Base::mesh_.add_vertex(zero_point);
new_vh[2] = Base::mesh_.add_vertex(zero_point);
hh[0] = Base::mesh_.PHEH(red_hh);
hh[1] = Base::mesh_.PHEH(Base::mesh_.OHEH(red_hh));
hh[2] = Base::mesh_.NHEH(red_hh);
// split two edges
eh = Base::mesh_.EH(red_hh);
split_edge(hh[1], new_vh[1], _target_state);
split_edge(hh[2], new_vh[2], _target_state);
assert(Base::mesh_.FVH(hh[2]) == vh[1]);
assert(Base::mesh_.FVH(hh[1]) == vh[0]);
assert(Base::mesh_.FVH(hh[0]) == vh[2]);
if (Base::mesh_.FH(Base::mesh_.OHEH(hh[1])).is_valid()) {
temp_hh = Base::mesh_.OHEH(Base::mesh_.PHEH(Base::mesh_.OHEH(hh[1])));
if (MOBJ(Base::mesh_.FH(temp_hh)).red_halfedge() != temp_hh)
halfedge_vector.push_back(temp_hh);
}
if (Base::mesh_.FH(Base::mesh_.OHEH(hh[2])).is_valid()) {
temp_hh = Base::mesh_.OHEH(Base::mesh_.PHEH(Base::mesh_.OHEH(hh[2])));
if (MOBJ(Base::mesh_.FH(temp_hh)).red_halfedge() != temp_hh)
halfedge_vector.push_back(temp_hh);
}
}
}
}
// continue here for all cases
// flip edge
if (Base::mesh_.is_flip_ok(eh)) {
Base::mesh_.flip(eh);
}
// search new faces
fh[0] = Base::mesh_.FH(hh[0]);
fh[1] = Base::mesh_.FH(hh[1]);
fh[2] = Base::mesh_.FH(hh[2]);
fh[3] = Base::mesh_.FH(Base::mesh_.OHEH(Base::mesh_.NHEH(hh[0])));
assert(_fh == fh[0] || _fh == fh[1] || _fh == fh[2] || _fh == fh[3]);
// init new faces
for (int i = 0; i <= 3; ++i) {
MOBJ(fh[i]).set_state(_target_state);
MOBJ(fh[i]).set_final();
MOBJ(fh[i]).set_position(_target_state, face_position);
MOBJ(fh[i]).set_red_halfedge(Base::mesh_.InvalidHalfedgeHandle);
}
// init new vertices and edges
for (int i = 0; i <= 2; ++i) {
MOBJ(new_vh[i]).set_position(_target_state, zero_point);
MOBJ(new_vh[i]).set_state(_target_state);
MOBJ(new_vh[i]).set_not_final();
Base::mesh_.set_point(new_vh[i], (Base::mesh_.point(vh[i]) + Base::mesh_.point(vh[(i + 2) % 3])) * 0.5);
MOBJ(Base::mesh_.EH(hh[i])).set_state(_target_state);
MOBJ(Base::mesh_.EH(hh[i])).set_position(_target_state, zero_point);
MOBJ(Base::mesh_.EH(hh[i])).set_final();
MOBJ(Base::mesh_.EH(Base::mesh_.NHEH(hh[i]))).set_state(_target_state);
MOBJ(Base::mesh_.EH(Base::mesh_.NHEH(hh[i]))).set_position(_target_state, zero_point);
MOBJ(Base::mesh_.EH(Base::mesh_.NHEH(hh[i]))).set_final();
MOBJ(Base::mesh_.EH(Base::mesh_.PHEH(hh[i]))).set_state(_target_state);
MOBJ(Base::mesh_.EH(Base::mesh_.PHEH(hh[i]))).set_position(_target_state, zero_point);
MOBJ(Base::mesh_.EH(Base::mesh_.PHEH(hh[i]))).set_final();
}
// check, if opposite triangle needs splitting
while (!halfedge_vector.empty()) {
temp_hh = halfedge_vector.back();
halfedge_vector.pop_back();
check_edge(temp_hh, _target_state);
}
assert(MOBJ(fh[0]).state() == _target_state);
assert(MOBJ(fh[1]).state() == _target_state);
assert(MOBJ(fh[2]).state() == _target_state);
assert(MOBJ(fh[3]).state() == _target_state);
}
}
template
void
Tvv4::raise(typename M::VertexHandle& _vh, state_t _target_state)
{
if (MOBJ(_vh).state() < _target_state)
{
this->update(_vh, _target_state);
// multiply old position by 4
MOBJ(_vh).set_position(_target_state, MOBJ(_vh).position(_target_state - 1) * 4.0);
MOBJ(_vh).inc_state();
}
}
template
void
Tvv4::raise(typename M::EdgeHandle& _eh, state_t _target_state)
{
if (MOBJ(_eh).state() < _target_state)
{
this->update(_eh, _target_state);
typename M::FaceHandle fh(Base::mesh_.FH(Base::mesh_.HEH(_eh, 0)));
if (!fh.is_valid())
fh=Base::mesh_.FH(Base::mesh_.HEH(_eh, 1));
raise(fh, _target_state);
assert(MOBJ(_eh).state() == _target_state);
}
}
#ifndef DOXY_IGNORE_THIS
template
void
Tvv4::split_edge(typename M::HalfedgeHandle &_hh,
typename M::VertexHandle &_vh,
state_t _target_state)
{
typename M::HalfedgeHandle temp_hh;
if (Base::mesh_.FH(Base::mesh_.OHEH(_hh)).is_valid())
{
if (!MOBJ(Base::mesh_.FH(Base::mesh_.OHEH(_hh))).final())
{
if (MOBJ(Base::mesh_.FH(Base::mesh_.OHEH(_hh))).red_halfedge().is_valid())
{
temp_hh = MOBJ(Base::mesh_.FH(Base::mesh_.OHEH(_hh))).red_halfedge();
}
else
{
// two cases for divided, but not visited face
if (MOBJ(Base::mesh_.FH(Base::mesh_.OHEH(Base::mesh_.PHEH(Base::mesh_.OHEH(_hh))))).state()
== MOBJ(Base::mesh_.FH(Base::mesh_.OHEH(_hh))).state())
{
temp_hh = Base::mesh_.PHEH(Base::mesh_.OHEH(_hh));
}
else if (MOBJ(Base::mesh_.FH(Base::mesh_.OHEH(Base::mesh_.NHEH(Base::mesh_.OHEH(_hh))))).state()
== MOBJ(Base::mesh_.FH(Base::mesh_.OHEH(_hh))).state())
{
temp_hh = Base::mesh_.NHEH(Base::mesh_.OHEH(_hh));
}
}
}
else
temp_hh = Base::mesh_.InvalidHalfedgeHandle;
}
else
temp_hh = Base::mesh_.InvalidHalfedgeHandle;
// split edge
Base::mesh_.split(Base::mesh_.EH(_hh), _vh);
if (Base::mesh_.FVH(_hh) == _vh)
{
MOBJ(Base::mesh_.EH(Base::mesh_.PHEH(Base::mesh_.OHEH(Base::mesh_.PHEH(_hh))))).set_state(MOBJ(Base::mesh_.EH(_hh)).state());
_hh = Base::mesh_.PHEH(Base::mesh_.OHEH(Base::mesh_.PHEH(_hh)));
}
if (Base::mesh_.FH(Base::mesh_.OHEH(_hh)).is_valid()) {
MOBJ(Base::mesh_.EH(Base::mesh_.PHEH(Base::mesh_.OHEH(_hh)))).set_not_final();
MOBJ(Base::mesh_.FH(Base::mesh_.OHEH(_hh))).set_state(_target_state-1);
MOBJ(Base::mesh_.FH(Base::mesh_.OHEH(Base::mesh_.NHEH(Base::mesh_.OHEH(Base::mesh_.NHEH(_hh)))))).set_state(_target_state-1);
MOBJ(Base::mesh_.FH(Base::mesh_.OHEH(_hh))).set_not_final();
MOBJ(Base::mesh_.FH(Base::mesh_.OHEH(Base::mesh_.NHEH(Base::mesh_.OHEH(Base::mesh_.NHEH(_hh)))))).set_not_final();
MOBJ(Base::mesh_.EH(Base::mesh_.PHEH(Base::mesh_.OHEH(_hh)))).set_state(_target_state);
if (temp_hh.is_valid()) {
MOBJ(Base::mesh_.FH(Base::mesh_.OHEH(_hh))).set_red_halfedge(temp_hh);
MOBJ(Base::mesh_.FH(Base::mesh_.OHEH(Base::mesh_.NHEH(Base::mesh_.OHEH(Base::mesh_.NHEH(_hh)))))).set_red_halfedge(temp_hh);
}
else {
typename M::FaceHandle
fh1(Base::mesh_.FH(Base::mesh_.OHEH(_hh))),
fh2(Base::mesh_.FH(Base::mesh_.OHEH(Base::mesh_.NHEH(Base::mesh_.OHEH(Base::mesh_.NHEH(_hh))))));
MOBJ(fh1).set_red_halfedge(Base::mesh_.OHEH(Base::mesh_.PHEH(Base::mesh_.OHEH(_hh))));
MOBJ(fh2).set_red_halfedge(Base::mesh_.OHEH(Base::mesh_.PHEH(Base::mesh_.OHEH(_hh))));
const typename M::Point zero_point(0.0, 0.0, 0.0);
MOBJ(fh1).set_position(_target_state - 1, zero_point);
MOBJ(fh2).set_position(_target_state - 1, zero_point);
}
}
// init edges
MOBJ(Base::mesh_.EH(Base::mesh_.NHEH(Base::mesh_.OHEH(Base::mesh_.NHEH(_hh))))).set_state(_target_state - 1);
MOBJ(Base::mesh_.EH(Base::mesh_.NHEH(Base::mesh_.OHEH(Base::mesh_.NHEH(_hh))))).set_final();
MOBJ(Base::mesh_.EH(_hh)).set_state(_target_state - 1);
MOBJ(Base::mesh_.EH(_hh)).set_final();
}
template
void Tvv4::check_edge(const typename M::HalfedgeHandle& _hh,
state_t _target_state)
{
typename M::FaceHandle fh1(Base::mesh_.FH(_hh)),
fh2(Base::mesh_.FH(Base::mesh_.OHEH(_hh)));
assert(fh1.is_valid());
assert(fh2.is_valid());
typename M::HalfedgeHandle red_hh(MOBJ(fh1).red_halfedge());
if (!MOBJ(fh1).final()) {
assert (MOBJ(fh1).final() == MOBJ(fh2).final());
assert (!MOBJ(fh1).final());
assert (MOBJ(fh1).red_halfedge() == MOBJ(fh2).red_halfedge());
const typename M::Point zero_point(0.0, 0.0, 0.0);
MOBJ(fh1).set_position(_target_state - 1, zero_point);
MOBJ(fh2).set_position(_target_state - 1, zero_point);
assert(red_hh.is_valid());
if (!red_hh.is_valid()) {
MOBJ(fh1).set_state(_target_state - 1);
MOBJ(fh2).set_state(_target_state - 1);
MOBJ(fh1).set_red_halfedge(_hh);
MOBJ(fh2).set_red_halfedge(_hh);
MOBJ(Base::mesh_.EH(_hh)).set_not_final();
MOBJ(Base::mesh_.EH(_hh)).set_state(_target_state - 1);
}
else {
MOBJ(Base::mesh_.EH(_hh)).set_not_final();
MOBJ(Base::mesh_.EH(_hh)).set_state(_target_state - 1);
raise(fh1, _target_state);
assert(MOBJ(fh1).state() == _target_state);
}
}
}
// -------------------------------------------------------------------- VF ----
template
void VF::raise(typename M::FaceHandle& _fh, state_t _target_state)
{
if (MOBJ(_fh).state() < _target_state) {
this->update(_fh, _target_state);
// raise all neighbour vertices to level x-1
typename M::FaceVertexIter fv_it;
typename M::VertexHandle vh;
std::vector vertex_vector;
if (_target_state > 1) {
for (fv_it = Base::mesh_.fv_iter(_fh); fv_it; ++fv_it) {
vertex_vector.push_back(fv_it.handle());
}
while (!vertex_vector.empty()) {
vh = vertex_vector.back();
vertex_vector.pop_back();
Base::prev_rule()->raise(vh, _target_state - 1);
}
}
// calculate new position
typename M::Point position(0.0, 0.0, 0.0);
int valence(0);
for (fv_it = Base::mesh_.fv_iter(_fh); fv_it; ++fv_it) {
++valence;
position += Base::mesh_.data(fv_it).position(_target_state - 1);
}
position /= valence;
// boundary rule
if (Base::number() == Base::subdiv_rule()->number() + 1 &&
Base::mesh_.is_boundary(_fh) &&
!MOBJ(_fh).final())
position *= 0.5;
MOBJ(_fh).set_position(_target_state, position);
MOBJ(_fh).inc_state();
assert(_target_state == MOBJ(_fh).state());
}
}
// -------------------------------------------------------------------- FF ----
template
void FF::raise(typename M::FaceHandle& _fh, state_t _target_state) {
if (MOBJ(_fh).state() < _target_state) {
this->update(_fh, _target_state);
// raise all neighbour faces to level x-1
typename M::FaceFaceIter ff_it;
typename M::FaceHandle fh;
std::vector face_vector;
if (_target_state > 1) {
for (ff_it = Base::mesh_.ff_iter(_fh); ff_it; ++ff_it) {
face_vector.push_back(ff_it.handle());
}
while (!face_vector.empty()) {
fh = face_vector.back();
face_vector.pop_back();
Base::prev_rule()->raise(fh, _target_state - 1);
}
for (ff_it = Base::mesh_.ff_iter(_fh); ff_it; ++ff_it) {
face_vector.push_back(ff_it.handle());
}
while (!face_vector.empty()) {
fh = face_vector.back();
face_vector.pop_back();
while (MOBJ(fh).state() < _target_state - 1)
Base::prev_rule()->raise(fh, _target_state - 1);
}
}
// calculate new position
typename M::Point position(0.0, 0.0, 0.0);
int valence(0);
for (ff_it = Base::mesh_.ff_iter(_fh); ff_it; ++ff_it) {
++valence;
position += Base::mesh_.data(ff_it).position(_target_state - 1);
}
position /= valence;
MOBJ(_fh).set_position(_target_state, position);
MOBJ(_fh).inc_state();
}
}
// ------------------------------------------------------------------- FFc ----
template
void FFc::raise(typename M::FaceHandle& _fh, state_t _target_state)
{
if (MOBJ(_fh).state() < _target_state) {
this->update(_fh, _target_state);
// raise all neighbour faces to level x-1
typename M::FaceFaceIter ff_it(Base::mesh_.ff_iter(_fh));
typename M::FaceHandle fh;
std::vector face_vector;
if (_target_state > 1)
{
for (; ff_it; ++ff_it)
face_vector.push_back(ff_it.handle());
while (!face_vector.empty())
{
fh = face_vector.back();
face_vector.pop_back();
Base::prev_rule()->raise(fh, _target_state - 1);
}
for (ff_it = Base::mesh_.ff_iter(_fh); ff_it; ++ff_it)
face_vector.push_back(ff_it.handle());
while (!face_vector.empty()) {
fh = face_vector.back();
face_vector.pop_back();
while (MOBJ(fh).state() < _target_state - 1)
Base::prev_rule()->raise(fh, _target_state - 1);
}
}
// calculate new position
typename M::Point position(0.0, 0.0, 0.0);
int valence(0);
for (ff_it = Base::mesh_.ff_iter(_fh); ff_it; ++ff_it)
{
++valence;
position += Base::mesh_.data(ff_it).position(_target_state - 1);
}
position /= valence;
// choose coefficient c
typename M::Scalar c = Base::coeff();
position *= (1.0 - c);
position += MOBJ(_fh).position(_target_state - 1) * c;
MOBJ(_fh).set_position(_target_state, position);
MOBJ(_fh).inc_state();
}
}
// -------------------------------------------------------------------- FV ----
template
void FV::raise(typename M::VertexHandle& _vh, state_t _target_state)
{
if (MOBJ(_vh).state() < _target_state) {
this->update(_vh, _target_state);
// raise all neighbour vertices to level x-1
typename M::VertexFaceIter vf_it(Base::mesh_.vf_iter(_vh));
typename M::FaceHandle fh;
std::vector face_vector;
if (_target_state > 1) {
for (; vf_it; ++vf_it) {
face_vector.push_back(vf_it.handle());
}
while (!face_vector.empty()) {
fh = face_vector.back();
face_vector.pop_back();
Base::prev_rule()->raise(fh, _target_state - 1);
}
for (vf_it = Base::mesh_.vf_iter(_vh); vf_it; ++vf_it) {
face_vector.push_back(vf_it.handle());
}
while (!face_vector.empty()) {
fh = face_vector.back();
face_vector.pop_back();
while (MOBJ(fh).state() < _target_state - 1)
Base::prev_rule()->raise(fh, _target_state - 1);
}
}
// calculate new position
typename M::Point position(0.0, 0.0, 0.0);
int valence(0);
for (vf_it = Base::mesh_.vf_iter(_vh); vf_it; ++vf_it) {
++valence;
position += Base::mesh_.data(vf_it).position(_target_state - 1);
}
position /= valence;
MOBJ(_vh).set_position(_target_state, position);
MOBJ(_vh).inc_state();
if (Base::number() == Base::n_rules() - 1) {
Base::mesh_.set_point(_vh, position);
MOBJ(_vh).set_final();
}
}
}
// ------------------------------------------------------------------- FVc ----
template
void FVc::raise(typename M::VertexHandle& _vh, state_t _target_state)
{
if (MOBJ(_vh).state() < _target_state) {
this->update(_vh, _target_state);
typename M::VertexOHalfedgeIter voh_it;
typename M::FaceHandle fh;
std::vector face_vector;
int valence(0);
face_vector.clear();
// raise all neighbour faces to level x-1
if (_target_state > 1) {
for (voh_it = Base::mesh_.voh_iter(_vh); voh_it; ++voh_it) {
if (Base::mesh_.FH(voh_it.handle()).is_valid()) {
face_vector.push_back(Base::mesh_.FH(voh_it.handle()));
if (Base::mesh_.FH(Base::mesh_.OHEH(Base::mesh_.NHEH(voh_it.handle()))).is_valid()) {
face_vector.push_back(Base::mesh_.FH(Base::mesh_.OHEH(Base::mesh_.NHEH(voh_it.handle()))));
}
}
}
while (!face_vector.empty()) {
fh = face_vector.back();
face_vector.pop_back();
Base::prev_rule()->raise(fh, _target_state - 1);
}
for (voh_it = Base::mesh_.voh_iter(_vh); voh_it; ++voh_it) {
if (Base::mesh_.FH(voh_it.handle()).is_valid()) {
face_vector.push_back(Base::mesh_.FH(voh_it.handle()));
if (Base::mesh_.FH(Base::mesh_.OHEH(Base::mesh_.NHEH(voh_it.handle()))).is_valid()) {
face_vector.push_back(Base::mesh_.FH(Base::mesh_.OHEH(Base::mesh_.NHEH(voh_it.handle()))));
}
}
}
while (!face_vector.empty()) {
fh = face_vector.back();
face_vector.pop_back();
while (MOBJ(fh).state() < _target_state - 1)
Base::prev_rule()->raise(fh, _target_state - 1);
}
for (voh_it = Base::mesh_.voh_iter(_vh); voh_it; ++voh_it) {
if (Base::mesh_.FH(voh_it.handle()).is_valid()) {
face_vector.push_back(Base::mesh_.FH(voh_it.handle()));
if (Base::mesh_.FH(Base::mesh_.OHEH(Base::mesh_.NHEH(voh_it.handle()))).is_valid()) {
face_vector.push_back(Base::mesh_.FH(Base::mesh_.OHEH(Base::mesh_.NHEH(voh_it.handle()))));
}
}
}
while (!face_vector.empty()) {
fh = face_vector.back();
face_vector.pop_back();
while (MOBJ(fh).state() < _target_state - 1)
Base::prev_rule()->raise(fh, _target_state - 1);
}
}
// calculate new position
typename M::Point position(0.0, 0.0, 0.0);
typename M::Scalar c;
#if 0
const typename M::Scalar _2pi(2.0*M_PI);
const typename M::Scalar _2over3(2.0/3.0);
for (voh_it = Base::mesh_.voh_iter(_vh); voh_it; ++voh_it)
{
++valence;
}
// choose coefficient c
c = _2over3 * ( cos( _2pi / valence) + 1.0);
#else
valence = Base::mesh_.valence(_vh);
c = coeff(valence);
#endif
for (voh_it = Base::mesh_.voh_iter(_vh); voh_it; ++voh_it) {
fh = Base::mesh_.FH(voh_it.handle());
if (fh.is_valid())
Base::prev_rule()->raise(fh, _target_state - 1);
fh = Base::mesh_.FH(Base::mesh_.OHEH(Base::mesh_.NHEH(voh_it.handle())));
if (fh.is_valid())
Base::prev_rule()->raise(fh, _target_state - 1);
if (Base::mesh_.FH(voh_it.handle()).is_valid()) {
if (Base::mesh_.FH(Base::mesh_.OHEH(Base::mesh_.NHEH(voh_it.handle()))).is_valid()) {
position += MOBJ(Base::mesh_.FH(voh_it.handle())).position(_target_state - 1) * c;
position += MOBJ(Base::mesh_.FH(Base::mesh_.OHEH(Base::mesh_.NHEH(voh_it.handle())))).position(_target_state - 1) * (1.0 - c);
}
else {
position += MOBJ(Base::mesh_.FH(voh_it.handle())).position(_target_state - 1);
}
}
else {
--valence;
}
}
position /= valence;
MOBJ(_vh).set_position(_target_state, position);
MOBJ(_vh).inc_state();
assert(MOBJ(_vh).state() == _target_state);
// check if last rule
if (Base::number() == Base::n_rules() - 1) {
Base::mesh_.set_point(_vh, position);
MOBJ(_vh).set_final();
}
}
}
template
std::vector FVc::coeffs_;
template
void FVc::init_coeffs(size_t _max_valence)
{
if ( coeffs_.size() == _max_valence+1 )
return;
if ( coeffs_.size() < _max_valence+1 )
{
const double _2pi(2.0*M_PI);
const double _2over3(2.0/3.0);
if (coeffs_.empty())
coeffs_.push_back(0.0); // dummy for valence 0
for(size_t v=coeffs_.size(); v <= _max_valence; ++v)
coeffs_.push_back(_2over3 * ( cos( _2pi / v) + 1.0));
}
}
// -------------------------------------------------------------------- VV ----
template
void VV::raise(typename M::VertexHandle& _vh, state_t _target_state)
{
if (MOBJ(_vh).state() < _target_state)
{
this->update(_vh, _target_state);
// raise all neighbour vertices to level x-1
typename M::VertexVertexIter vv_it(Base::mesh_.vv_iter(_vh));
typename M::VertexHandle vh;
std::vector vertex_vector;
if (_target_state > 1) {
for (; vv_it; ++vv_it) {
vertex_vector.push_back(vv_it.handle());
}
while (!vertex_vector.empty()) {
vh = vertex_vector.back();
vertex_vector.pop_back();
Base::prev_rule()->raise(vh, _target_state - 1);
}
for (; vv_it; ++vv_it) {
vertex_vector.push_back(vv_it.handle());
}
while (!vertex_vector.empty()) {
vh = vertex_vector.back();
vertex_vector.pop_back();
Base::prev_rule()->raise(vh, _target_state - 1);
}
}
// calculate new position
typename M::Point position(0.0, 0.0, 0.0);
int valence(0);
for (vv_it = Base::mesh_.vv_iter(_vh); vv_it; ++vv_it) {
++valence;
position += Base::mesh_.data(vv_it).position(_target_state - 1);
}
position /= valence;
MOBJ(_vh).set_position(_target_state, position);
MOBJ(_vh).inc_state();
// check if last rule
if (Base::number() == Base::n_rules() - 1) {
Base::mesh_.set_point(_vh, position);
MOBJ(_vh).set_final();
}
}
}
// ------------------------------------------------------------------- VVc ----
template
void VVc::raise(typename M::VertexHandle& _vh, state_t _target_state)
{
if (MOBJ(_vh).state() < _target_state) {
this->update(_vh, _target_state);
// raise all neighbour vertices to level x-1
typename M::VertexVertexIter vv_it(Base::mesh_.vv_iter(_vh));
typename M::VertexHandle vh;
std::vector vertex_vector;
if (_target_state > 1) {
for (; vv_it; ++vv_it) {
vertex_vector.push_back(vv_it.handle());
}
while (!vertex_vector.empty()) {
vh = vertex_vector.back();
vertex_vector.pop_back();
Base::prev_rule()->raise(vh, _target_state - 1);
}
for (; vv_it; ++vv_it) {
vertex_vector.push_back(vv_it.handle());
}
while (!vertex_vector.empty()) {
vh = vertex_vector.back();
vertex_vector.pop_back();
Base::prev_rule()->raise(vh, _target_state - 1);
}
}
// calculate new position
typename M::Point position(0.0, 0.0, 0.0);
int valence(0);
typename M::Scalar c;
for (vv_it = Base::mesh_.vv_iter(_vh); vv_it; ++vv_it)
{
++valence;
position += Base::mesh_.data(vv_it).position(_target_state - 1);
}
position /= valence;
// choose coefficcient c
c = Base::coeff();
position *= (1.0 - c);
position += MOBJ(_vh).position(_target_state - 1) * c;
MOBJ(_vh).set_position(_target_state, position);
MOBJ(_vh).inc_state();
if (Base::number() == Base::n_rules() - 1)
{
Base::mesh_.set_point(_vh, position);
MOBJ(_vh).set_final();
}
}
}
// -------------------------------------------------------------------- VE ----
template
void VE::raise(typename M::EdgeHandle& _eh, state_t _target_state)
{
if (MOBJ(_eh).state() < _target_state) {
this->update(_eh, _target_state);
// raise all neighbour vertices to level x-1
typename M::VertexHandle vh;
typename M::HalfedgeHandle hh1(Base::mesh_.HEH(_eh, 0)),
hh2(Base::mesh_.HEH(_eh, 1));
if (_target_state > 1) {
vh = Base::mesh_.TVH(hh1);
Base::prev_rule()->raise(vh, _target_state - 1);
vh = Base::mesh_.TVH(hh2);
Base::prev_rule()->raise(vh, _target_state - 1);
}
// calculate new position
typename M::Point position(0.0, 0.0, 0.0);
int valence(0);
valence = 2;
position += MOBJ(Base::mesh_.TVH(hh1)).position(_target_state - 1);
position += MOBJ(Base::mesh_.TVH(hh2)).position(_target_state - 1);
position /= valence;
MOBJ(_eh).set_position(_target_state, position);
MOBJ(_eh).inc_state();
}
}
// ------------------------------------------------------------------- VdE ----
template
void VdE::raise(typename M::EdgeHandle& _eh, state_t _target_state)
{
if (MOBJ(_eh).state() < _target_state)
{
this->update(_eh, _target_state);
// raise all neighbour vertices to level x-1
typename M::VertexHandle vh;
typename M::HalfedgeHandle hh1(Base::mesh_.HEH(_eh, 0)),
hh2(Base::mesh_.HEH(_eh, 1));
typename M::FaceHandle fh1, fh2;
if (_target_state > 1) {
fh1 = Base::mesh_.FH(hh1);
fh2 = Base::mesh_.FH(hh2);
if (fh1.is_valid()) {
Base::prev_rule()->raise(fh1, _target_state - 1);
vh = Base::mesh_.TVH(Base::mesh_.NHEH(hh1));
Base::prev_rule()->raise(vh, _target_state - 1);
}
if (fh2.is_valid()) {
Base::prev_rule()->raise(fh2, _target_state - 1);
vh = Base::mesh_.TVH(Base::mesh_.NHEH(hh2));
Base::prev_rule()->raise(vh, _target_state - 1);
}
vh = Base::mesh_.TVH(hh1);
Base::prev_rule()->raise(vh, _target_state - 1);
vh = Base::mesh_.TVH(hh2);
Base::prev_rule()->raise(vh, _target_state - 1);
}
// calculate new position
typename M::Point position(0.0, 0.0, 0.0);
int valence(0);
valence = 2;
position += MOBJ(Base::mesh_.TVH(hh1)).position(_target_state - 1);
position += MOBJ(Base::mesh_.TVH(hh2)).position(_target_state - 1);
if (fh1.is_valid()) {
position += MOBJ(Base::mesh_.TVH(Base::mesh_.NHEH(hh1))).position(_target_state - 1);
++valence;
}
if (fh2.is_valid()) {
position += MOBJ(Base::mesh_.TVH(Base::mesh_.NHEH(hh2))).position(_target_state - 1);
++valence;
}
if (Base::number() == Base::subdiv_rule()->Base::number() + 1)
valence = 4;
position /= valence;
MOBJ(_eh).set_position(_target_state, position);
MOBJ(_eh).inc_state();
}
}
// ------------------------------------------------------------------ VdEc ----
template
void
VdEc::raise(typename M::EdgeHandle& _eh, state_t _target_state)
{
if (MOBJ(_eh).state() < _target_state)
{
this->update(_eh, _target_state);
// raise all neighbour vertices to level x-1
typename M::VertexHandle vh;
typename M::HalfedgeHandle hh1(Base::mesh_.HEH(_eh, 0)),
hh2(Base::mesh_.HEH(_eh, 1));
std::vector vertex_vector;
typename M::FaceHandle fh1, fh2;
if (_target_state > 1) {
fh1 = Base::mesh_.FH(Base::mesh_.HEH(_eh, 0));
fh2 = Base::mesh_.FH(Base::mesh_.HEH(_eh, 1));
Base::prev_rule()->raise(fh1, _target_state - 1);
Base::prev_rule()->raise(fh2, _target_state - 1);
vertex_vector.push_back(Base::mesh_.TVH(hh1));
vertex_vector.push_back(Base::mesh_.TVH(hh2));
vertex_vector.push_back(Base::mesh_.TVH(Base::mesh_.NHEH(hh1)));
vertex_vector.push_back(Base::mesh_.TVH(Base::mesh_.NHEH(hh2)));
while (!vertex_vector.empty()) {
vh = vertex_vector.back();
vertex_vector.pop_back();
Base::prev_rule()->raise(vh, _target_state - 1);
}
vertex_vector.push_back(Base::mesh_.TVH(hh1));
vertex_vector.push_back(Base::mesh_.TVH(hh2));
vertex_vector.push_back(Base::mesh_.TVH(Base::mesh_.NHEH(hh1)));
vertex_vector.push_back(Base::mesh_.TVH(Base::mesh_.NHEH(hh2)));
while (!vertex_vector.empty()) {
vh = vertex_vector.back();
vertex_vector.pop_back();
Base::prev_rule()->raise(vh, _target_state - 1);
}
}
// calculate new position
typename M::Point position(0.0, 0.0, 0.0);
int valence(0);
typename M::Scalar c;
// choose coefficient c
c = Base::coeff();
valence = 4;
position += MOBJ(Base::mesh_.TVH(hh1)).position(_target_state - 1) * c;
position += MOBJ(Base::mesh_.TVH(hh2)).position(_target_state - 1) * c;
position += MOBJ(Base::mesh_.TVH(Base::mesh_.NHEH(hh1))).position(_target_state - 1) * (0.5 - c);
position += MOBJ(Base::mesh_.TVH(Base::mesh_.NHEH(hh2))).position(_target_state - 1) * (0.5 - c);
position /= valence;
MOBJ(_eh).set_position(_target_state, position);
MOBJ(_eh).inc_state();
}
}
// -------------------------------------------------------------------- EV ----
template
void EV::raise(typename M::VertexHandle& _vh, state_t _target_state)
{
if (MOBJ(_vh).state() < _target_state) {
this->update(_vh, _target_state);
// raise all neighbour vertices to level x-1
typename M::VertexEdgeIter ve_it(Base::mesh_.ve_iter(_vh));
typename M::EdgeHandle eh;
std::vector edge_vector;
if (_target_state > 1) {
for (; ve_it; ++ve_it) {
edge_vector.push_back(ve_it.handle());
}
while (!edge_vector.empty()) {
eh = edge_vector.back();
edge_vector.pop_back();
Base::prev_rule()->raise(eh, _target_state - 1);
}
for (ve_it = Base::mesh_.ve_iter(_vh); ve_it; ++ve_it) {
edge_vector.push_back(ve_it.handle());
}
while (!edge_vector.empty()) {
eh = edge_vector.back();
edge_vector.pop_back();
while (MOBJ(eh).state() < _target_state - 1)
Base::prev_rule()->raise(eh, _target_state - 1);
}
}
// calculate new position
typename M::Point position(0.0, 0.0, 0.0);
int valence(0);
for (ve_it = Base::mesh_.ve_iter(_vh); ve_it; ++ve_it) {
if (Base::mesh_.data(ve_it).final()) {
++valence;
position += Base::mesh_.data(ve_it).position(_target_state - 1);
}
}
position /= valence;
MOBJ(_vh).set_position(_target_state, position);
MOBJ(_vh).inc_state();
// check if last rule
if (Base::number() == Base::n_rules() - 1) {
Base::mesh_.set_point(_vh, position);
MOBJ(_vh).set_final();
}
}
}
// ------------------------------------------------------------------- EVc ----
template
std::vector EVc::coeffs_;
template
void EVc::raise(typename M::VertexHandle& _vh, state_t _target_state)
{
if (MOBJ(_vh).state() < _target_state)
{
this->update(_vh, _target_state);
// raise all neighbour vertices to level x-1
typename M::VertexOHalfedgeIter voh_it;
typename M::EdgeHandle eh;
typename M::FaceHandle fh;
std::vector edge_vector;
std::vector face_vector;
if (_target_state > 1) {
for (voh_it = Base::mesh_.voh_iter(_vh); voh_it; ++voh_it) {
face_vector.push_back(Base::mesh_.FH(voh_it.handle()));
}
while (!face_vector.empty()) {
fh = face_vector.back();
face_vector.pop_back();
if (fh.is_valid())
Base::prev_rule()->raise(fh, _target_state - 1);
}
for (voh_it = Base::mesh_.voh_iter(_vh); voh_it; ++voh_it) {
edge_vector.push_back(Base::mesh_.EH(voh_it.handle()));
edge_vector.push_back(Base::mesh_.EH(Base::mesh_.NHEH(voh_it.handle())));
}
while (!edge_vector.empty()) {
eh = edge_vector.back();
edge_vector.pop_back();
while (MOBJ(eh).state() < _target_state - 1)
Base::prev_rule()->raise(eh, _target_state - 1);
}
}
// calculate new position
typename M::Point position(0.0, 0.0, 0.0);
typename M::Scalar c;
typename M::Point zero_point(0.0, 0.0, 0.0);
int valence(0);
valence = Base::mesh_.valence(_vh);
c = coeff( valence );
for (voh_it = Base::mesh_.voh_iter(_vh); voh_it; ++voh_it)
{
if (MOBJ(Base::mesh_.EH(voh_it.handle())).final())
{
position += MOBJ(Base::mesh_.EH(voh_it.handle())).position(_target_state-1)*c;
if ( Base::mesh_.FH(voh_it.handle()).is_valid() &&
MOBJ(Base::mesh_.EH(Base::mesh_.NHEH(voh_it.handle()))).final() &&
MOBJ(Base::mesh_.EH(Base::mesh_.NHEH(voh_it.handle()))).position(_target_state - 1) != zero_point)
{
position += MOBJ(Base::mesh_.EH(Base::mesh_.NHEH(voh_it.handle()))).position(_target_state-1) * (1.0-c);
}
else {
position += MOBJ(Base::mesh_.EH(voh_it.handle())).position(_target_state - 1) * (1.0 - c);
}
}
else {
--valence;
}
}
position /= valence;
MOBJ(_vh).set_position(_target_state, position);
MOBJ(_vh).inc_state();
// check if last rule
if (Base::number() == Base::n_rules() - 1) {
Base::mesh_.set_point(_vh, position);
MOBJ(_vh).set_final();
}
}
}
template
void
EVc::init_coeffs(size_t _max_valence)
{
if ( coeffs_.size() == _max_valence+1 ) // equal? do nothing
return;
if (coeffs_.size() < _max_valence+1) // less than? add additional valences
{
const double _2pi = 2.0*M_PI;
double c;
if (coeffs_.empty())
coeffs_.push_back(0.0); // dummy for invalid valences 0,1,2
for(size_t v=coeffs_.size(); v <= _max_valence; ++v)
{
// ( 3/2 + cos ( 2 PI / valence ) )� / 2 - 1
c = 1.5 + cos( _2pi / v );
c = c * c * 0.5 - 1.0;
coeffs_.push_back(c);
}
}
}
// -------------------------------------------------------------------- EF ----
template
void
EF::raise(typename M::FaceHandle& _fh, state_t _target_state) {
if (MOBJ(_fh).state() < _target_state) {
this->update(_fh, _target_state);
// raise all neighbour edges to level x-1
typename M::FaceEdgeIter fe_it(Base::mesh_.fe_iter(_fh));
typename M::EdgeHandle eh;
std::vector edge_vector;
if (_target_state > 1) {
for (; fe_it; ++fe_it) {
edge_vector.push_back(fe_it.handle());
}
while (!edge_vector.empty()) {
eh = edge_vector.back();
edge_vector.pop_back();
Base::prev_rule()->raise(eh, _target_state - 1);
}
for (fe_it = Base::mesh_.fe_iter(_fh); fe_it; ++fe_it) {
edge_vector.push_back(fe_it.handle());
}
while (!edge_vector.empty()) {
eh = edge_vector.back();
edge_vector.pop_back();
while (MOBJ(eh).state() < _target_state - 1)
Base::prev_rule()->raise(eh, _target_state - 1);
}
}
// calculate new position
typename M::Point position(0.0, 0.0, 0.0);
int valence(0);
for (fe_it = Base::mesh_.fe_iter(_fh); fe_it; ++fe_it) {
if (Base::mesh_.data(fe_it).final()) {
++valence;
position += Base::mesh_.data(fe_it).position(_target_state - 1);
}
}
assert (valence == 3);
position /= valence;
MOBJ(_fh).set_position(_target_state, position);
MOBJ(_fh).inc_state();
}
}
// -------------------------------------------------------------------- FE ----
template
void
FE::raise(typename M::EdgeHandle& _eh, state_t _target_state) {
if (MOBJ(_eh).state() < _target_state) {
this->update(_eh, _target_state);
// raise all neighbour faces to level x-1
typename M::FaceHandle fh;
if (_target_state > 1) {
fh = Base::mesh_.FH(Base::mesh_.HEH(_eh, 0));
Base::prev_rule()->raise(fh, _target_state - 1);
fh = Base::mesh_.FH(Base::mesh_.HEH(_eh, 1));
Base::prev_rule()->raise(fh, _target_state - 1);
fh = Base::mesh_.FH(Base::mesh_.HEH(_eh, 0));
Base::prev_rule()->raise(fh, _target_state - 1);
fh = Base::mesh_.FH(Base::mesh_.HEH(_eh, 1));
Base::prev_rule()->raise(fh, _target_state - 1);
}
// calculate new position
typename M::Point position(0.0, 0.0, 0.0);
int valence(2);
position += MOBJ(Base::mesh_.FH(Base::mesh_.HEH(_eh, 0))).position(_target_state - 1);
position += MOBJ(Base::mesh_.FH(Base::mesh_.HEH(_eh, 1))).position(_target_state - 1);
position /= valence;
MOBJ(_eh).set_position(_target_state, position);
MOBJ(_eh).inc_state();
}
}
// ------------------------------------------------------------------- EdE ----
template
void
EdE::raise(typename M::EdgeHandle& _eh, state_t _target_state) {
if (MOBJ(_eh).state() < _target_state) {
this->update(_eh, _target_state);
// raise all neighbour faces and edges to level x-1
typename M::HalfedgeHandle hh1, hh2;
typename M::FaceHandle fh;
typename M::EdgeHandle eh;
hh1 = Base::mesh_.HEH(_eh, 0);
hh2 = Base::mesh_.HEH(_eh, 1);
if (_target_state > 1) {
fh = Base::mesh_.FH(hh1);
Base::prev_rule()->raise(fh, _target_state - 1);
fh = Base::mesh_.FH(hh2);
Base::prev_rule()->raise(fh, _target_state - 1);
eh = Base::mesh_.EH(Base::mesh_.NHEH(hh1));
Base::prev_rule()->raise(eh, _target_state - 1);
eh = Base::mesh_.EH(Base::mesh_.PHEH(hh1));
Base::prev_rule()->raise(eh, _target_state - 1);
eh = Base::mesh_.EH(Base::mesh_.NHEH(hh2));
Base::prev_rule()->raise(eh, _target_state - 1);
eh = Base::mesh_.EH(Base::mesh_.PHEH(hh2));
Base::prev_rule()->raise(eh, _target_state - 1);
}
// calculate new position
typename M::Point position(0.0, 0.0, 0.0);
int valence(4);
position += MOBJ(Base::mesh_.EH(Base::mesh_.NHEH(hh1))).position(_target_state - 1);
position += MOBJ(Base::mesh_.EH(Base::mesh_.PHEH(hh1))).position(_target_state - 1);
position += MOBJ(Base::mesh_.EH(Base::mesh_.NHEH(hh2))).position(_target_state - 1);
position += MOBJ(Base::mesh_.EH(Base::mesh_.PHEH(hh2))).position(_target_state - 1);
position /= valence;
MOBJ(_eh).set_position(_target_state, position);
MOBJ(_eh).inc_state();
}
}
// ------------------------------------------------------------------ EdEc ----
template
void
EdEc::raise(typename M::EdgeHandle& _eh, state_t _target_state)
{
if (MOBJ(_eh).state() < _target_state) {
this->update(_eh, _target_state);
// raise all neighbour faces and edges to level x-1
typename M::HalfedgeHandle hh1, hh2;
typename M::FaceHandle fh;
typename M::EdgeHandle eh;
hh1 = Base::mesh_.HEH(_eh, 0);
hh2 = Base::mesh_.HEH(_eh, 1);
if (_target_state > 1) {
fh = Base::mesh_.FH(hh1);
Base::prev_rule()->raise(fh, _target_state - 1);
fh = Base::mesh_.FH(hh2);
Base::prev_rule()->raise(fh, _target_state - 1);
eh = Base::mesh_.EH(Base::mesh_.NHEH(hh1));
Base::prev_rule()->raise(eh, _target_state - 1);
eh = Base::mesh_.EH(Base::mesh_.PHEH(hh1));
Base::prev_rule()->raise(eh, _target_state - 1);
eh = Base::mesh_.EH(Base::mesh_.NHEH(hh2));
Base::prev_rule()->raise(eh, _target_state - 1);
eh = Base::mesh_.EH(Base::mesh_.PHEH(hh2));
Base::prev_rule()->raise(eh, _target_state - 1);
}
// calculate new position
typename M::Point position(0.0, 0.0, 0.0);
int valence(4);
typename M::Scalar c;
position += MOBJ(Base::mesh_.EH(Base::mesh_.NHEH(hh1))).position(_target_state - 1);
position += MOBJ(Base::mesh_.EH(Base::mesh_.PHEH(hh1))).position(_target_state - 1);
position += MOBJ(Base::mesh_.EH(Base::mesh_.NHEH(hh2))).position(_target_state - 1);
position += MOBJ(Base::mesh_.EH(Base::mesh_.PHEH(hh2))).position(_target_state - 1);
position /= valence;
// choose coefficient c
c = Base::coeff();
position *= (1.0 - c);
position += MOBJ(_eh).position(_target_state - 1) * c;
MOBJ(_eh).set_position(_target_state, position);
MOBJ(_eh).inc_state();
}
}
#endif // DOXY_IGNORE_THIS
#undef FH
#undef VH
#undef EH
#undef HEH
#undef M
#undef MOBJ
//=============================================================================
} // END_NS_ADAPTIVE
} // END_NS_SUBDIVIDER
} // END_NS_OPENMESH
//=============================================================================