Commit 186d0ffa authored by Quentin Khan's avatar Quentin Khan
Browse files

FNode: add a new output format

The tree structure can now be printed to the WaveFront OBJ format. The
3D object generated is draws the tree leaves.

Two stream modifiers are added to choose the format:
 - scalfmm::fmt::term outputs the tree in terminal format
 - scalfmm::fmt::obj outputs the tree in obj format
parent 934f10f5
......@@ -116,6 +116,25 @@ namespace scalfmm {
using derived_from = use_if<true, std::is_base_of, Base,T >;
}
struct fmt {
enum : long {TERM, OBJ};
static const int& get_node_os_id() {
static const int i = std::ios_base::xalloc();
return i;
}
static std::ostream& term(std::ostream& os) {
os.iword(get_node_os_id()) = TERM;
return os;
};
static std::ostream& obj(std::ostream& os) {
os.iword(get_node_os_id()) = OBJ;
return os;
};
};
}
struct NodeEmptyData {};
......@@ -135,7 +154,7 @@ public:
/// Space dimension count
constexpr static const std::size_t Dim = _Tree::Dim;
/// Child count if the node is not a leaf
constexpr static std::size_t child_count = Fpow(2,Dim);
constexpr static const std::size_t child_count = 1 << Dim;
/// Node position type
using position_t = FPoint<FReal, Dim>;
......@@ -835,15 +854,14 @@ private:
}
public:
friend std::ostream& operator<<(std::ostream& os, const FNode& node) {
void terminal_print(std::ostream& os) const {
// Indentation
if(! node.getParent()) {
if(! this->getParent()) {
os << "└─ ";
} else {
std::string indent;
const FNode* parent = node.getParent();
const FNode* parent = this->getParent();
while(parent) {
if((parent->getIndex() & (child_count-1)) == child_count-1
|| ! parent->getParent()) {
......@@ -853,7 +871,7 @@ public:
}
parent = parent->getParent();
}
if((node.getIndex() & (child_count-1)) == child_count-1) {
if((this->getIndex() & (child_count-1)) == child_count-1) {
os << indent << "└─ ";
} else{
os << indent << "├─ ";
......@@ -861,24 +879,26 @@ public:
}
// Node data and recurrence
auto index_width = std::setw(static_cast<int>(
std::log10(std::pow(2, Dim * (node.getDepth()+1)))));
if(! node.is_leaf()) { // Internal node
os << "node " << index_width << node.getIndex() << ":" << std::endl;
for(auto&& child : node.getChildren()) {
os << *child;
auto index_width =
std::setw(static_cast<int>(
std::log10(1 << (Dim * (this->getDepth()+1)))));
if(! this->is_leaf()) { // Internal node
os << "node " << index_width << this->getIndex() << ":\n";
for(auto&& child : this->getChildren()) {
child->terminal_print(os);
}
} else { // Leaf
os << "leaf "<< index_width << node.getIndex() <<": ";
const typename FNode::particle_container_t& p_container = *(node.getParticleContainer());
auto count_width = std::setw(static_cast<int>(
std::log10(node.getTree().leaf_max_particle_count())));
os << "leaf "<< index_width << this->getIndex() <<": ";
const auto& p_container = *(this->getParticleContainer());
auto count_width =
std::setw(static_cast<int>(
std::log10(this->getTree().leaf_max_particle_count())));
os << count_width << p_container.size() << " particle";
os << (p_container.size() > 1 ? "s" : "");
os << " [";
if(node.getTree().print_particles) {
if(this->getTree().print_particles) {
std::size_t idx = 0;
for(idx = 0; idx + 1 < p_container.size(); ++idx) {
os << p_container[idx] << ", ";
......@@ -891,7 +911,46 @@ public:
}
os << "]";
os << std::endl;
}
}
void obj_print(std::ostream& os) const {
// When not on a leaf, recurse to leaf
if(! this->is_leaf()) {
for(auto& child : getChildren()) {
child->obj_print(os);
}
} else {
// Print each of the box vertices
const box_t& box = this->getBox();
// note, child_count is the box's corner count
for(std::size_t i = 0; i < child_count; ++i) {
const position_t p = box.corner(i);
os << "v";
for(auto c : p) {
os << ' ' << c;
}
os << '\n';
}
// Print the box faces
//TODO: other than 3D cube
os << "f -8 -7 -5 -6\n";
os << "f -8 -7 -3 -4\n";
os << "f -6 -5 -1 -2\n";
os << "f -4 -3 -1 -2\n";
os << "f -7 -5 -1 -3\n";
os << "f -8 -6 -2 -4\n";
os << '\n';
}
}
public:
friend std::ostream& operator<<(std::ostream& os, const FNode& node) {
if(os.iword(scalfmm::fmt::get_node_os_id()) == scalfmm::fmt::OBJ) {
node.obj_print(os);
} else {
node.terminal_print(os);
}
return os;
}
......
Markdown is supported
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