#include ".\pseudonormalsdfalgo.h" using namespace SDF; PseudoNormalSdfAlgo::PseudoNormalSdfAlgo(void) { } PseudoNormalSdfAlgo::~PseudoNormalSdfAlgo(void) { } SdfValue PseudoNormalSdfAlgo::compute_sdf_result() { //----------------------- // Preconditions //----------------------- if(this->tri_sets.size() == 0) { __ERROR__("PseudoNormalSdfAlgo::compute_sdf_result was called, but no triangles were given!"); return SdfValue(0, Point(0,0,0), Vector(0,0,0), DONT_KNOW); } //----------------------- // Find the min-dist set //----------------------- list::iterator it; ClosestTriSet *classifying_set = NULL; double best_dist = 0.0; for(it = this->tri_sets.begin(); it != this->tri_sets.end(); ++it) { if( classifying_set == NULL || (*it)->abs_dist < best_dist) { // Got a better one classifying_set = *it; best_dist = (*it)->abs_dist; } } assert(classifying_set != NULL); //__DBc("Using classifying set: " << *classifying_set); // Save some typing const ClosestTriSet *set = classifying_set; // TEMP DEBUG - print out tris /* for(int foo = 0; foo < set->tris.size(); ++foo) { __DBc("tri #" << foo << ": " << *(set->tris[foo])); } */ //--------------------------------- // Now _try_ to use this set to classify the point. //--------------------------------- PointClass clazz = DONT_KNOW; Vector grad(0,0,0); // This will be set correctly in the code below // check that the tri-set is complete! this is a must bool set_complete = true; // The logic below will set the bool to false if incompleteness is detected if(set->p.getType() == PointOnTriangle::POT_EDGE) { // edge pts must have at least 2 tris // we allow for >2 tris because the surface may be pseudo-2-manifold if(set->tris.size() < 2) { set_complete = false; __DBc("incomplete EDGE set: " << *set); } } else if(set->p.getType() == PointOnTriangle::POT_VERTEX) { if(set->tris.size() < 3) { set_complete = false; __DBc("incomplete VERTEX set"); } } if(set_complete) { // Use the angle-weighted pseudo-normal method to classify Vector pseudo_norm = this->calc_angle_weighted_pseudo_normal(*set); Vector to_testpt = this->test_point - set->p.getPoint(); double dotp = pseudo_norm.Dot(to_testpt); // __DBc("pseudo-norm: " << pseudo_norm << " dotp: " << dotp); if(dotp < 0.0) clazz = SDF::INTERIOR; else clazz = SDF::EXTERIOR; // Use the pseudo-norm to approx the grad grad = this->pseudo_normal_to_gradient(pseudo_norm); } else { // incomplete set! clazz = SDF::DONT_KNOW; } //-------------------------------- // Now return a signed distance field according to the class //-------------------------------- SdfValue sdf(set->abs_dist, set->p.getPoint(), grad, clazz); return sdf; }