12 #ifndef BEMBEL_SRC_CLUSTERTREE_ELEMENTTREE_HPP_
13 #define BEMBEL_SRC_CLUSTERTREE_ELEMENTTREE_HPP_
108 max_level_ = max_level;
109 number_of_patches_ = geometry_->size();
112 std::vector<Eigen::Vector3d> uniquePts;
113 std::vector<ElementTreeNode *> patches;
115 number_of_points_ = 0;
116 number_of_elements_ = number_of_patches_;
119 for (
auto i = 0; i < number_of_patches_; ++i) {
120 root.
sons_[i].adjcents_ = std::vector<ElementTreeNode *>(4,
nullptr);
132 if (i == number_of_patches_ - 1) {
140 for (
auto j = 0; j < 4; ++j) {
141 v = (*geometry_)[i].eval(Constants::corners[0][j],
142 Constants::corners[1][j]);
143 unsigned int index = 0;
144 for (; index < uniquePts.size(); ++index)
145 if ((uniquePts[index] - v).norm() < Constants::pt_comp_tolerance)
147 if (index != uniquePts.size()) {
150 uniquePts.push_back(v);
151 root.
sons_[i].vertices_[j] = number_of_points_;
155 patches.push_back(std::addressof(
root.
sons_[i]));
157 updateTopology(patches);
170 if (el.
sons_.size()) {
171 for (
auto i = 0; i < el.
sons_.size(); ++i)
207 Eigen::MatrixXd pts(3, number_of_points_);
208 if (idct !=
nullptr) {
209 idct->resize(number_of_points_);
212 for (
auto it =
pbegin(); it !=
pend(); ++it) {
213 double h = double(1) / double(1 << it->level_);
214 pts.col(it->vertices_[0]) =
215 (*geometry_)[it->patch_].eval(it->llc_(0), it->llc_(1));
216 pts.col(it->vertices_[1]) =
217 (*geometry_)[it->patch_].eval(it->llc_(0) + h, it->llc_(1));
218 pts.col(it->vertices_[2]) =
219 (*geometry_)[it->patch_].eval(it->llc_(0) + h, it->llc_(1) + h);
220 pts.col(it->vertices_[3]) =
221 (*geometry_)[it->patch_].eval(it->llc_(0), it->llc_(1) + h);
222 if (idct !=
nullptr) {
223 ++((*idct)(it->vertices_[0]));
224 ++((*idct)(it->vertices_[1]));
225 ++((*idct)(it->vertices_[2]));
226 ++((*idct)(it->vertices_[3]));
241 unsigned int elID = 0;
242 Eigen::MatrixXi retval(4, number_of_elements_);
243 for (
auto it =
pbegin(); it !=
pend(); ++it) {
244 retval.col(elID) << it->vertices_[0], it->vertices_[1], it->vertices_[2],
357 for (
auto i = 0; i < root_.
sons_.size(); ++i)
369 const Eigen::MatrixXd &P) {
370 Eigen::Vector3d mp1, mp2;
373 if (!el.
sons_.size()) {
375 util::computeEnclosingBall(&mp1, &r1, P.col(el.
vertices_[0]), 0,
377 util::computeEnclosingBall(&mp2, &r2, P.col(el.
vertices_[1]), 0,
379 util::computeEnclosingBall(&(el.
midpoint_), &(el.radius_), mp1, r1, mp2,
383 for (
auto i = 0; i < 4; ++i)
386 util::computeEnclosingBall(&mp1, &r1, el.
sons_[0].midpoint_,
388 el.
sons_[2].radius_);
389 util::computeEnclosingBall(&mp2, &r2, el.
sons_[1].midpoint_,
391 el.
sons_[3].radius_);
392 util::computeEnclosingBall(&(el.
midpoint_), &(el.radius_), mp1, r1, mp2,
403 for (
auto it =
pbegin(); it !=
pend(); ++it) {
404 std::cout <<
"element[" << i++ <<
"] = ";
418 Eigen::MatrixXd retval(3, number_of_elements_);
420 for (
auto it =
pbegin(); it !=
pend(); ++it) {
421 retval.col(i) = it->midpoint_;
433 Eigen::VectorXd retval(number_of_elements_);
435 for (
auto it =
pbegin(); it !=
pend(); ++it) {
436 retval(i) = it->radius_;
448 Eigen::VectorXi retval(number_of_elements_);
450 for (
auto it =
pbegin(); it !=
pend(); ++it) {
451 retval(i) = compute_global_id(*it);
468 Eigen::VectorXi retval(number_of_elements_);
471 for (
auto it =
pbegin(); it !=
pend(); ++it) {
472 for (
auto j = 0; j < 4; ++j)
473 if (it->adjcents_[j] ==
nullptr) {
476 }
else if (it->adjcents_[j]->patch_ != it->patch_) {
493 Eigen::VectorXi retval(number_of_elements_);
495 assert(pn < number_of_patches_);
497 for (
auto it =
pbegin(); it !=
pend(); ++it) {
498 retval[i] = it->patch_ == pn ? 1 : 0;
511 std::vector<std::array<int, 4>> retval;
512 for (
auto it = root_.
sons_.begin(); it != root_.
sons_.end(); ++it) {
513 for (
auto j = 0; j < 4; ++j) {
515 if (it->adjcents_[j] !=
nullptr) {
519 if (it->id_ < cur_neighbour.
id_) {
522 if (cur_neighbour.
adjcents_[k] !=
nullptr &&
523 cur_neighbour.
adjcents_[k]->id_ == it->id_)
525 retval.push_back({it->id_, cur_neighbour.
id_, j, k});
528 retval.push_back({it->id_, -1, j, -1});
545 std::vector<int> out(number_of_elements_);
546 for (
auto it =
pbegin(); it !=
pend(); ++it) {
547 const double h = it->get_h();
548 const Eigen::Vector2d ref_mid =
549 it->llc_ + Eigen::Vector2d(.5 * h, .5 * h);
550 const int x_idx = std::floor(ref_mid(0) / h);
551 const int y_idx = std::floor(ref_mid(1) / h);
552 const int num_in_one_dir = 1 << max_level_;
553 const int num_per_patch = num_in_one_dir * num_in_one_dir;
555 it->patch_ * num_per_patch + y_idx * num_in_one_dir + x_idx;
556 out[tp_idx] = it->id_;
562 return number_of_patches_ *
573 template <
typename T>
575 bool operator()(
const T &v1,
const T &v2)
const {
576 return ((v1 - v2).norm() < Constants::pt_comp_tolerance);
584 void updateTopology(
const std::vector<ElementTreeNode *> &elements) {
585 std::map<std::array<int, 2>, ElementTreeNode *> edges;
586 std::array<int, 2> e1, e2;
588 for (
auto i = 0; i < elements.size(); ++i)
589 for (
auto j = 0; j < 4; ++j) {
591 const int v1 = elements[i]->vertices_[j];
592 const int v2 = elements[i]->vertices_[(j + 1) % 4];
593 e1 = {v1 < v2 ? v1 : v2, v1 < v2 ? v2 : v1};
595 auto it = edges.find(e1);
597 if (it != edges.end()) {
598 elements[i]->adjcents_[j] = it->second;
600 for (
auto k = 0; k < 4; ++k) {
601 const int v3 = it->second->vertices_[k];
602 const int v4 = it->second->vertices_[(k + 1) % 4];
603 e2 = {v3 < v4 ? v3 : v4, v3 < v4 ? v4 : v3};
605 it->second->adjcents_[k] = elements[i];
611 edges.insert(std::make_pair(e1, elements[i]));
624 void refineLeaf(ElementTreeNode &cur_el) {
626 if (cur_el.sons_.size())
return;
627 std::vector<int> ptIds(5);
628 std::vector<int> refNeighbours(4);
629 std::vector<ElementTreeNode *> elements;
631 for (
auto i = 0; i < 4; ++i) {
633 if (cur_el.adjcents_[i] !=
nullptr) {
634 for (
auto j = 0; j < 4; ++j)
635 if (cur_el.adjcents_[i]->adjcents_[j] == std::addressof(cur_el)) {
636 refNeighbours[i] = j;
640 refNeighbours[i] = -1;
644 for (
auto i = 0; i < 4; ++i) {
646 if (cur_el.adjcents_[i] !=
nullptr) {
647 ElementTreeNode &ref_cur_neighbour = *(cur_el.adjcents_[i]);
649 if (ref_cur_neighbour.sons_.size()) {
651 ptIds[i] = ref_cur_neighbour.sons_[refNeighbours[i]]
652 .vertices_[(refNeighbours[i] + 1) % 4];
655 std::addressof(ref_cur_neighbour.sons_[refNeighbours[i]]));
656 elements.push_back(std::addressof(
657 ref_cur_neighbour.sons_[(refNeighbours[i] + 1) % 4]));
660 ptIds[i] = number_of_points_;
665 ptIds[i] = number_of_points_;
670 ptIds[4] = number_of_points_;
673 cur_el.sons_.resize(4);
674 number_of_elements_ += 3;
676 max_level_ < cur_el.level_ + 1 ? cur_el.level_ + 1 : max_level_;
679 for (
auto i = 0; i < 4; ++i) {
683 cur_el.sons_[i].prev_ = cur_el.prev_;
684 if (cur_el.prev_ !=
nullptr)
685 (cur_el.prev_)->next_ = std::addressof(cur_el.sons_[i]);
686 cur_el.prev_ =
nullptr;
687 if (std::addressof(cur_el) == pfirst_)
688 pfirst_ = std::addressof(cur_el.sons_[i]);
691 cur_el.sons_[i].prev_ = std::addressof(cur_el.sons_[i - 1]);
694 cur_el.sons_[i].next_ = cur_el.next_;
695 if (cur_el.next_ !=
nullptr)
696 (cur_el.next_)->prev_ = std::addressof(cur_el.sons_[i]);
697 cur_el.next_ =
nullptr;
698 if (std::addressof(cur_el) == plast_)
699 plast_ = std::addressof(cur_el.sons_[i]);
701 cur_el.sons_[i].next_ = std::addressof(cur_el.sons_[i + 1]);
704 cur_el.sons_[i].patch_ = cur_el.patch_;
705 cur_el.sons_[i].level_ = cur_el.level_ + 1;
706 cur_el.sons_[i].id_ = 4 * cur_el.id_ + i;
707 cur_el.sons_[i].adjcents_ = std::vector<ElementTreeNode *>(4,
nullptr);
708 cur_el.sons_[i].llc_(0) =
709 cur_el.llc_(0) + Constants::llcs[0][i] / double(1 << cur_el.level_);
710 cur_el.sons_[i].llc_(1) =
711 cur_el.llc_(1) + Constants::llcs[1][i] / double(1 << cur_el.level_);
712 elements.push_back(std::addressof(cur_el.sons_[i]));
716 cur_el.sons_[0].vertices_.push_back(cur_el.vertices_[0]);
717 cur_el.sons_[0].vertices_.push_back(ptIds[0]);
718 cur_el.sons_[0].vertices_.push_back(ptIds[4]);
719 cur_el.sons_[0].vertices_.push_back(ptIds[3]);
721 cur_el.sons_[1].vertices_.push_back(ptIds[0]);
722 cur_el.sons_[1].vertices_.push_back(cur_el.vertices_[1]);
723 cur_el.sons_[1].vertices_.push_back(ptIds[1]);
724 cur_el.sons_[1].vertices_.push_back(ptIds[4]);
726 cur_el.sons_[2].vertices_.push_back(ptIds[4]);
727 cur_el.sons_[2].vertices_.push_back(ptIds[1]);
728 cur_el.sons_[2].vertices_.push_back(cur_el.vertices_[2]);
729 cur_el.sons_[2].vertices_.push_back(ptIds[2]);
731 cur_el.sons_[3].vertices_.push_back(ptIds[3]);
732 cur_el.sons_[3].vertices_.push_back(ptIds[4]);
733 cur_el.sons_[3].vertices_.push_back(ptIds[2]);
734 cur_el.sons_[3].vertices_.push_back(cur_el.vertices_[3]);
736 updateTopology(elements);
743 std::shared_ptr<PatchVector> geometry_;
744 ElementTreeNode root_;
745 ElementTreeNode *pfirst_;
746 ElementTreeNode *plast_;
747 int number_of_patches_;
749 int number_of_points_;
750 int number_of_elements_;
This class organizes an element structure on a Geometry object and handles refinement.
ElementTreeNode::const_iterator cpbegin() const
Returns an iterator to the beginning of the sequence represented by the leafs as ElementTreeNodes of ...
Eigen::MatrixXd computeElementEnclosings()
Computes enclosing balls surrounding all elements.
std::vector< std::array< int, 4 > > patchTopologyInfo() const
Resolves neighborhood relations of the patches.
ElementTree & operator=(ElementTree &&)=delete
Deleted move assignment operator for the ElementTree class.
void refineUniformly()
Refine all patches uniformly.
const ElementTreeNode & root() const
Return const reference to the root ElementTreeNode.
ElementTree(const Geometry &g, unsigned int max_level=0)
Explicit constructor for the ElementTree class.
ElementTreeNode::const_iterator cpend() const
Returns an iterator one past the end of the sequence represented by the leafs as ElementTreeNodes of ...
ElementTreeNode::const_iterator pbegin() const
iterators
ElementTreeNode::const_iterator cluster_begin(const ElementTreeNode &cl) const
Returns a cluster iterator to the beginning of the sequence represented by the the given ElementTreeN...
ElementTree(const ElementTree &)=delete
Deleted copy constructor for the ElementTree class.
int get_number_of_points() const
getter
Eigen::VectorXi generatePatchBoundaryLabels() const
Generate list of labels if elements are on the patch boundary or at the boundary of the geometry.
ElementTreeNode::const_iterator pend() const
Returns an iterator one past the end of the sequence represented by the leafs as ElementTreeNodes of ...
Eigen::MatrixXd generateRadiusList() const
Return a matrix with all radii of the element enclosing.
Eigen::VectorXi identifyPatch(unsigned int pn) const
Generate list of labels if elements contained within a given patch.
void refinePatch(int patch)
Refine a given patch.
void printPanels() const
Prints all Elements of the Tree.
void init_ElementTree(const Geometry &g, unsigned int max_level)
init
void computeElementEnclosings_recursion(ElementTreeNode &el, const Eigen::MatrixXd &P)
Computes enclosing balls of one element and all its sons.
int get_number_of_elements() const
Return number of elements in the ElementTree.
Eigen::MatrixXd generatePointList(Eigen::VectorXi *idct=nullptr) const
Return the coordinates of all points of the elements.
Eigen::MatrixXd generateMidpointList() const
other Stuff
ElementTree(ElementTree &&)=delete
Deleted move constructor for the ElementTree class.
Eigen::VectorXi generateElementLabels() const
Return a vector with computed global indices of the elements.
std::vector< int > computeReorderingVector() const
The ordering of elements in the element tree does not correspond to the element order underlying the ...
Eigen::MatrixXi generateElementList() const
Return list of elements containing the indices of the vertices.
ElementTreeNode::const_iterator cluster_end(const ElementTreeNode &cl) const
Returns a cluster iterator one past the end of the sequence represented by the the given ElementTreeN...
ElementTree()
constructors
void refineUniformly_recursion(ElementTreeNode &el)
Refine the given element or it's sons.
const PatchVector & get_geometry() const
Return const reference to the Geometry.
int get_max_level() const
Return maximum level of refinement.
ElementTreeNode & root()
Return reference to the root ElementTreeNode.
ElementTree & operator=(const ElementTree &)=delete
Deleted copy assignment operator for the ElementTree class.
The ElementTreeNode corresponds to an element in the element tree.
int id_
radius of the element
const_iterator cend() const
Returns an iterator pointing to the element in the sequence after this ElementTreeNode.
int level_
element id with respect to the level
std::vector< int > vertices_
neighbouring elements indices
const_iterator cbegin() const
Returns an iterator pointing to the element in the sequence before this ElementTreeNodes.
Eigen::Vector3d midpoint_
indices of the vertices
std::vector< ElementTreeNode * > adjcents_
children
std::vector< ElementTreeNode > sons_
member variables
this class wraps a GeometryVector and provides some basic functionality, like reading Geometry files
const std::shared_ptr< PatchVector > get_geometry_ptr() const
Return const pointer to the geometry.
std::vector< Bembel::Patch > PatchVector
typedef for PatchVector
Routines for the evalutation of pointwise errors.
iterator struct for element tree nodes. They may be used to iterator over the elements in a cluster....