[MOAB-dev] r1722 - MOAB/trunk/test/obb
kraftche at mcs.anl.gov
kraftche at mcs.anl.gov
Fri Mar 28 18:11:46 CDT 2008
Author: kraftche
Date: 2008-03-28 18:11:46 -0500 (Fri, 28 Mar 2008)
New Revision: 1722
Added:
MOAB/trunk/test/obb/obb_tree_tool.cpp
Modified:
MOAB/trunk/test/obb/Makefile.am
Log:
add a tool to generate OBB tress for testing. I thought I had one of these already, but couldn't find it.
Modified: MOAB/trunk/test/obb/Makefile.am
===================================================================
--- MOAB/trunk/test/obb/Makefile.am 2008-03-28 23:11:01 UTC (rev 1721)
+++ MOAB/trunk/test/obb/Makefile.am 2008-03-28 23:11:46 UTC (rev 1722)
@@ -1,4 +1,4 @@
-check_PROGRAMS = obb_test obb_time
+check_PROGRAMS = obb_test obb_time obb_tree_tool
TESTS = obb_test
DEFS = $(DEFINES)
@@ -7,3 +7,4 @@
obb_test_SOURCES = obb_test.cpp
obb_time_SOURCES = obb_time.cpp
+obb_tree_tool_SOURCES = obb_tree_tool.cpp
Added: MOAB/trunk/test/obb/obb_tree_tool.cpp
===================================================================
--- MOAB/trunk/test/obb/obb_tree_tool.cpp (rev 0)
+++ MOAB/trunk/test/obb/obb_tree_tool.cpp 2008-03-28 23:11:46 UTC (rev 1722)
@@ -0,0 +1,545 @@
+#define IS_BUILDING_MB
+#include "MBCore.hpp"
+#include "MBCartVect.hpp"
+#include "MBOrientedBoxTreeTool.hpp"
+#include "MBOrientedBox.hpp"
+#include "MBInternals.hpp"
+#include <iostream>
+#include <iomanip>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+std::string clock_to_string( clock_t t );
+std::string mem_to_string( unsigned long mem );
+
+const int MAX_TAG_VALUE = 20;
+const char* const TAG_NAME = "OBB_ID";
+const char* const TREE_TAG = "OBB_ROOT";
+const char* root_tag = TREE_TAG;
+
+MBErrorCode get_root( MBInterface* moab, MBEntityHandle& root );
+void build_tree( MBInterface* interface,
+ MBOrientedBoxTreeTool::Settings settings );
+void delete_existing_tree( MBInterface* interface );
+void print_stats( MBInterface* interface );
+void tag_triangles( MBInterface* interface );
+void tag_vertices( MBInterface* interface );
+void write_tree_blocks( MBInterface* interface, const char* file );
+
+static void usage( bool err = true )
+{
+ std::ostream& s = err ? std::cerr : std::cout;
+ s << "obb_tree_tool [-s|-S] [-d <int>] [-n <int>] <input file> <output file>" << std::endl
+ << "obb_tree_tool [-h]" << std::endl;
+ if (!err) {
+ MBOrientedBoxTreeTool::Settings st;
+ s << "Tool to build adaptive kd-Tree from triangles" << std::endl;
+ s << " -s Use range-based sets for tree nodes" << std::endl
+ << " -S Use vector-based sets for tree nodes" << std::endl
+ << " -d <int> Specify maximum depth for tree. Default: " << st.max_depth << std::endl
+ << " -n <int> Specify maximum entities per leaf. Default: " << st.max_leaf_entities << std::endl
+ << " -m <real> Specify worst split ratio. Default: " << st.worst_split_ratio << std::endl
+ << " -M <real> Specify best split ratio. Default: " << st.best_split_ratio << std::endl
+ << " -t Tag triangles will tree cell number." << std::endl
+ << " -T Write tree boxes to file." << std::endl
+ << " -N Specify mesh tag containing tree root. Default: \"" << TREE_TAG << '"' << std::endl
+ << std::endl;
+ }
+ exit( err );
+}
+
+static void memory_use( unsigned long& vsize, unsigned long& rss )
+{
+ char buffer[512];
+ int filp = open( "/proc/self/stat", O_RDONLY );
+ ssize_t r = read( filp, buffer, sizeof(buffer)-1 );
+ close( filp );
+ if (r < 0) r = 0;
+ vsize = rss = 0;
+ buffer[r] = '\0';
+ sscanf( buffer, "%*d %*s %*c " // pid command state
+ "%*d %*d " // ppid pgrp
+ "%*d %*d %*d " // session tty_nr tpgid
+ "%*u " // flags
+ "%*u %*u %*u %*u " // minflt cminflt majflt cmajflt
+ "%*u %*u %*d %*d " // utime stime cutime cstime
+ "%*d %*d %*d " // priority nice (unused)
+ "%*d %*u " // itrealval starttime
+ "%lu %lu", &vsize, &rss );
+ rss *= getpagesize();
+}
+
+static int parseint( int& i, int argc, char* argv[] )
+{
+ char* end;
+ ++i;
+ if (i == argc) {
+ std::cerr << "Expected value following '" << argv[i-1] << "'" << std::endl;
+ usage();
+ }
+
+ int result = strtol( argv[i], &end, 0 );
+ if (result < 0 || *end) {
+ std::cerr << "Expected positive integer following '" << argv[i-1] << "'" << std::endl;
+ usage();
+ }
+
+ return result;
+}
+
+static double parsedouble( int& i, int argc, char* argv[] )
+{
+ char* end;
+ ++i;
+ if (i == argc) {
+ std::cerr << "Expected value following '" << argv[i-1] << "'" << std::endl;
+ usage();
+ }
+
+ double result = strtod( argv[i], &end );
+ if (result < 0 || *end) {
+ std::cerr << "Expected positive real number following '" << argv[i-1] << "'" << std::endl;
+ usage();
+ }
+
+ return result;
+}
+
+
+int main( int argc, char* argv[] )
+{
+ const char* input_file = 0;
+ const char* output_file = 0;
+ const char* tree_file = 0;
+ MBOrientedBoxTreeTool::Settings settings;
+ bool tag_tris = false;
+ clock_t load_time, build_time, stat_time, tag_time, write_time, block_time;
+
+ for (int i = 1; i < argc; ++i) {
+ if (argv[i][0] != '-') {
+ if (!input_file)
+ input_file = argv[i];
+ else if (!output_file)
+ output_file = argv[i];
+ else
+ usage();
+ continue;
+ }
+
+ if (!argv[i][1] || argv[i][2])
+ usage();
+
+ switch (argv[i][1]) {
+ case 's': settings.set_options = MESHSET_SET; break;
+ case 'S': settings.set_options = MESHSET_ORDERED; break;
+ case 'd': settings.max_depth = parseint( i, argc, argv ); break;
+ case 'n': settings.max_leaf_entities = parseint( i, argc, argv ); break;
+ case 'm': settings.worst_split_ratio = parsedouble( i, argc, argv ); break;
+ case 'M': settings.best_split_ratio = parsedouble( i, argc, argv ); break;
+ case 't': tag_tris = true; break;
+ case 'T': if (++i == argc) usage(); tree_file = argv[i]; break;
+ case 'N': if (++i == argc) usage(); root_tag = argv[i]; break;
+ case 'h': usage(false);
+ default: usage();
+ }
+ }
+
+ if (!output_file)
+ usage();
+
+ MBErrorCode rval;
+ MBCore moab_core;
+ MBInterface* interface = &moab_core;
+
+ load_time = clock();
+ rval = interface->load_mesh( input_file );
+ if (MB_SUCCESS != rval) {
+ std::cerr << "Error reading file: " << input_file << std::endl;
+ exit(2);
+ }
+ load_time = clock() - load_time;
+
+
+ delete_existing_tree( interface );
+
+ std::cout << "Building tree..." << std::endl;
+ build_time = clock();
+ build_tree( interface, settings );
+ build_time = clock() - build_time;
+
+ std::cout << "Calculating stats..." << std::endl;
+ print_stats( interface );
+ stat_time = clock() - build_time;
+
+ if (tag_tris) {
+ std::cout << "Tagging tree..." << std::endl;
+ tag_triangles( interface );
+ tag_vertices( interface );
+ }
+ tag_time = clock() - stat_time;
+
+ std::cout << "Writing file... "; std::cout.flush();
+ rval = interface->write_mesh( output_file );
+ if (MB_SUCCESS != rval) {
+ std::cerr << "Error writing file: " << output_file << std::endl;
+ exit(3);
+ }
+ write_time = clock() - tag_time;
+ std::cout << "Wrote " << output_file << std::endl;
+
+ if (tree_file) {
+ std::cout << "Writing tree block rep..."; std::cout.flush();
+ write_tree_blocks( interface, tree_file );
+ std::cout << "Wrote " << tree_file << std::endl;
+ }
+ block_time = clock() - write_time;
+
+ std::cout << "Times: "
+ << " Load"
+ << " Build"
+ << " Stats"
+ << " Write";
+ if (tag_tris)
+ std::cout << "Tag Sets";
+ if (tree_file)
+ std::cout << "Block ";
+ std::cout << std::endl;
+
+ std::cout << " "
+ << std::setw(8) << clock_to_string(load_time)
+ << std::setw(8) << clock_to_string(build_time)
+ << std::setw(8) << clock_to_string(stat_time)
+ << std::setw(8) << clock_to_string(write_time);
+ if (tag_tris)
+ std::cout << std::setw(8) << clock_to_string(tag_time);
+ if (tree_file)
+ std::cout << std::setw(8) << clock_to_string(block_time);
+ std::cout << std::endl;
+
+ return 0;
+}
+
+MBErrorCode get_root( MBInterface* moab, MBEntityHandle& root )
+{
+ MBTag tag;
+ MBErrorCode rval;
+
+ rval = moab->tag_get_handle( root_tag, tag );
+ if (MB_SUCCESS != rval)
+ return rval;
+
+ int size;
+ rval = moab->tag_get_size( tag, size );
+ if (MB_SUCCESS != rval)
+ return rval;
+ if (size != sizeof(MBEntityHandle))
+ return MB_TAG_NOT_FOUND;
+
+ MBDataType type;
+ rval = moab->tag_get_data_type( tag, type );
+ if (MB_SUCCESS != rval)
+ return rval;
+ if (MB_TYPE_HANDLE != type)
+ return MB_TAG_NOT_FOUND;
+
+ return moab->tag_get_data( tag, 0, 1, &root );
+}
+
+
+void delete_existing_tree( MBInterface* interface )
+{
+ MBEntityHandle root;
+ MBErrorCode rval = get_root(interface, root);
+ if (MB_SUCCESS == rval) {
+ MBOrientedBoxTreeTool tool(interface);
+ rval = tool.delete_tree( root );
+ if (MB_SUCCESS != rval) {
+ std::cerr << "Failed to destroy existing trees. Aborting" << std::endl;
+ exit( 5 );
+ }
+ }
+}
+
+void build_tree( MBInterface* interface, MBOrientedBoxTreeTool::Settings settings )
+{
+ MBErrorCode rval;
+ MBEntityHandle root = 0;
+ MBRange triangles;
+
+ rval = interface->get_entities_by_type( 0, MBTRI, triangles );
+ if (MB_SUCCESS != rval || triangles.empty()) {
+ std::cerr << "No triangles from which to build tree." << std::endl;
+ exit(4);
+ }
+
+ MBOrientedBoxTreeTool tool( interface );
+ rval = tool.build( triangles, root, &settings );
+ if (MB_SUCCESS != rval || !root) {
+ std::cerr << "Tree construction failed." << std::endl;
+ exit(4);
+ }
+}
+
+std::string clock_to_string( clock_t t )
+{
+ char unit[5] = "s";
+ char buffer[256];
+ double dt = t / (double)CLOCKS_PER_SEC;
+ //if (dt > 300) {
+ // dt /= 60;
+ // strcpy( unit, "min" );
+ //}
+ //if (dt > 300) {
+ // dt /= 60;
+ // strcpy( unit, "hr" );
+ //}
+ //if (dt > 100) {
+ // dt /= 24;
+ // strcpy( unit, "days" );
+ //}
+ sprintf(buffer,"%0.2f%s",dt,unit);
+ return buffer;
+}
+
+std::string mem_to_string( unsigned long mem )
+{
+ char unit[3] = "B";
+ if (mem > 9*1024) {
+ mem = (mem + 512) / 1024;
+ strcpy( unit, "kB" );
+ }
+ if (mem > 9*1024) {
+ mem = (mem + 512) / 1024;
+ strcpy( unit, "MB" );
+ }
+ if (mem > 9*1024) {
+ mem = (mem + 512) / 1024;
+ strcpy( unit, "GB" );
+ }
+ char buffer[256];
+ sprintf(buffer, "%lu %s", mem, unit );
+ return buffer;
+}
+
+template <typename T>
+struct SimpleStat
+{
+ T min, max, sum, sqr;
+ size_t count;
+ SimpleStat();
+ void add( T value );
+ double avg() const { return (double)sum / count; }
+ double rms() const { return sqrt( (double)sqr / count ); }
+ double dev() const { return sqrt( (count * (double)sqr - (double)sum * (double)sum) / ((double)count * (count - 1) ) ); }
+};
+
+template <typename T> SimpleStat<T>::SimpleStat()
+ : min( std::numeric_limits<T>::max() ),
+ max( std::numeric_limits<T>::min() ),
+ sum( 0 ), sqr( 0 ), count( 0 )
+ {}
+
+void print_stats( MBInterface* interface )
+{
+ MBEntityHandle root;
+ MBRange range;
+ get_root( interface, root );
+ MBOrientedBoxTreeTool tool(interface);
+
+ MBRange tree_sets, triangles, verts;
+ //interface->get_child_meshsets( root, tree_sets, 0 );
+ interface->get_entities_by_type( 0, MBENTITYSET, tree_sets );
+ tree_sets.erase( tree_sets.begin(), MBRange::lower_bound( tree_sets.begin(), tree_sets.end(), root ) );
+ interface->get_entities_by_type( 0, MBTRI, triangles );
+ interface->get_entities_by_type( 0, MBVERTEX, verts );
+ triangles.merge( verts );
+ tree_sets.insert( root );
+ unsigned long set_used, set_amortized, set_store_used, set_store_amortized,
+ set_tag_used, set_tag_amortized, tri_used, tri_amortized;
+ interface->estimated_memory_use( tree_sets,
+ &set_used, &set_amortized,
+ &set_store_used, &set_store_amortized,
+ 0, 0, 0, 0,
+ &set_tag_used, &set_tag_amortized );
+ interface->estimated_memory_use( triangles, &tri_used, &tri_amortized );
+
+ int num_tri = 0;
+ interface->get_number_entities_by_type( 0, MBTRI, num_tri );
+
+ tool.stats( root, std::cout );
+
+ unsigned long real_rss, real_vsize;
+ memory_use( real_vsize, real_rss );
+
+ printf("------------------------------------------------------------------\n");
+ printf("\nmemory: used amortized\n");
+ printf(" ---------- ----------\n");
+ printf("triangles %10s %10s\n",mem_to_string(tri_used).c_str(), mem_to_string(tri_amortized).c_str());
+ printf("sets (total)%10s %10s\n",mem_to_string(set_used).c_str(), mem_to_string(set_amortized).c_str());
+ printf("sets %10s %10s\n",mem_to_string(set_store_used).c_str(), mem_to_string(set_store_amortized).c_str());
+ printf("set tags %10s %10s\n",mem_to_string(set_tag_used).c_str(), mem_to_string(set_tag_amortized).c_str());
+ printf("total real %10s %10s\n",mem_to_string(real_rss).c_str(), mem_to_string(real_vsize).c_str());
+ printf("------------------------------------------------------------------\n");
+}
+
+
+static int hash_handle( MBEntityHandle handle )
+{
+ MBEntityID h = ID_FROM_HANDLE(handle);
+ return (int)((h * 13 + 7) % MAX_TAG_VALUE) + 1;
+}
+
+class TriTagger : public MBOrientedBoxTreeTool::Op
+{
+private:
+ MBInterface* mMB;
+ MBTag mTag;
+ std::vector<MBEntityHandle> mHandles;
+ std::vector<int> mTagData;
+public:
+ TriTagger( MBTag tag, MBInterface* moab )
+ : mMB(moab), mTag(tag) {}
+
+ MBErrorCode visit( MBEntityHandle, int, bool& descent )
+ { descent = true; return MB_SUCCESS; }
+
+ MBErrorCode leaf( MBEntityHandle node ) {
+ mHandles.clear();
+ mMB->get_entities_by_handle( node, mHandles );
+ mTagData.clear();
+ mTagData.resize( mHandles.size(), hash_handle( node ) );
+ mMB->tag_set_data( mTag, &mHandles[0], mHandles.size(), &mTagData[0] );
+ return MB_SUCCESS;
+ }
+};
+
+
+void tag_triangles( MBInterface* moab )
+{
+ MBEntityHandle root;
+ MBErrorCode rval = get_root( moab, root );
+ if (MB_SUCCESS != rval) {
+ std::cerr << "Internal error: Failed to retreive tree." << std::endl;
+ exit(5);
+ }
+
+ MBTag tag;
+ int zero = 0;
+ moab->tag_create( TAG_NAME, sizeof(int), MB_TAG_DENSE, MB_TYPE_INTEGER, tag, &zero, true );
+ TriTagger op( tag, moab );
+
+ MBOrientedBoxTreeTool tool(moab);
+ rval = tool.preorder_traverse( root, op );
+ if (MB_SUCCESS != rval) {
+ std::cerr << "Internal error tagging triangles" << std::endl;
+ exit(5);
+ }
+}
+
+
+class VtxTagger : public MBOrientedBoxTreeTool::Op
+{
+private:
+ MBInterface* mMB;
+ MBTag mTag;
+ std::vector<MBEntityHandle> mHandles;
+ std::vector<MBEntityHandle> mConn;
+ std::vector<int> mTagData;
+public:
+ VtxTagger( MBTag tag, MBInterface* moab )
+ : mMB(moab), mTag(tag) {}
+
+ MBErrorCode visit( MBEntityHandle, int, bool& descent )
+ { descent = true; return MB_SUCCESS; }
+
+ MBErrorCode leaf( MBEntityHandle node ) {
+ mHandles.clear();
+ mMB->get_entities_by_handle( node, mHandles );
+ mConn.clear();
+ mMB->get_connectivity( &mHandles[0], mHandles.size(), mConn );
+ mTagData.clear();
+ mTagData.resize( mConn.size(), hash_handle( node ) );
+ mMB->tag_set_data( mTag, &mConn[0], mConn.size(), &mTagData[0] );
+ return MB_SUCCESS;
+ }
+};
+
+
+void tag_vertices( MBInterface* moab )
+{
+ MBEntityHandle root;
+ MBErrorCode rval = get_root( moab, root );
+ if (MB_SUCCESS != rval) {
+ std::cerr << "Internal error: Failed to retreive tree." << std::endl;
+ exit(5);
+ }
+
+ MBTag tag;
+ int zero = 0;
+ moab->tag_create( TAG_NAME, sizeof(int), MB_TAG_DENSE, MB_TYPE_INTEGER, tag, &zero, true );
+ VtxTagger op( tag, moab );
+
+ MBOrientedBoxTreeTool tool(moab);
+ rval = tool.preorder_traverse( root, op );
+ if (MB_SUCCESS != rval) {
+ std::cerr << "Internal error tagging vertices" << std::endl;
+ exit(5);
+ }
+}
+
+
+class LeafHexer : public MBOrientedBoxTreeTool::Op
+{
+private:
+ MBOrientedBoxTreeTool* mTool;
+ MBInterface* mOut;
+ MBTag mTag;
+ std::vector<MBEntityHandle> mHandles;
+ std::vector<MBEntityHandle> mConn;
+ std::vector<int> mTagData;
+public:
+ LeafHexer( MBOrientedBoxTreeTool* tool, MBInterface* mb2, MBTag tag )
+ : mTool(tool), mOut( mb2 ), mTag(tag) {}
+
+ MBErrorCode visit( MBEntityHandle, int, bool& descent )
+ { descent = true; return MB_SUCCESS; }
+
+ MBErrorCode leaf( MBEntityHandle node ) {
+ MBOrientedBox box;
+ MBErrorCode rval = mTool->box( node, box );
+ MBEntityHandle h;
+ rval = box.make_hex( h, mOut );
+ if (MB_SUCCESS !=rval) return rval;
+ int i = hash_handle( node );
+ return mOut->tag_set_data( mTag, &h, 1, &i );
+ }
+};
+
+void write_tree_blocks( MBInterface* interface, const char* file )
+{
+ MBEntityHandle root;
+ MBErrorCode rval = get_root( interface, root );
+ if (MB_SUCCESS != rval) {
+ std::cerr << "Internal error: Failed to retreive tree." << std::endl;
+ exit(5);
+ }
+
+ MBCore moab2;
+ MBTag tag;
+ int zero = 0;
+ moab2.tag_create( TAG_NAME, sizeof(int), MB_TAG_DENSE, MB_TYPE_INTEGER, tag, &zero, true );
+
+ MBOrientedBoxTreeTool tool(interface);
+ LeafHexer op( &tool, &moab2, tag );
+ rval = tool.preorder_traverse( root, op );
+ if (MB_SUCCESS != rval) {
+ std::cerr << "Internal error: failed to construct leaf hexes" << std::endl;
+ exit(5);
+ }
+
+ moab2.write_mesh( file );
+}
+
More information about the moab-dev
mailing list