squared_distance_t squaredDistanceSegmentTriangle3D( const Segment_3& sAB, const Triangle_3& tABC ) { typedef Kernel::FT squared_distance_t ; /* * If [sAsB] intersects the triangle (tA,tB,tC), distance is 0.0 */ if ( boost::none != CGAL::intersection( sAB, tABC ) ) { return 0.0 ; } /* * else, distance is the min of the following values : * - distance from sA to the Triangle * - distance from sB to the Triangle * - distance from sAB to the side of the Triangles */ squared_distance_t dMin = squaredDistancePointTriangle3D( sAB.vertex( 0 ), tABC ); dMin = std::min( dMin, squaredDistancePointTriangle3D( sAB.vertex( 1 ), tABC ) ); for ( int i = 0; i < 3; i++ ) { dMin = std::min( dMin, CGAL::squared_distance( sAB, Segment_3( tABC.vertex( i ), tABC.vertex( i+1 ) ) ) ) ; } return dMin ; }
/* * missing in CGAL? */ squared_distance_t squaredDistancePointTriangle3D( const Point_3& p, const Triangle_3& abc ) { #if CGAL_VERSION_NR >= 1041001000 // >= 4.10 return CGAL::squared_distance(p, abc); #else Point_3 a = abc.vertex( 0 ); Point_3 b = abc.vertex( 1 ); Point_3 c = abc.vertex( 2 ); /* * project P on ABC plane as projP. */ Point_3 projP = Plane_3( a, b, c ).projection( p ); squared_distance_t dMin ; if ( abc.has_on( projP ) ) { // Is projP is in the triangle, return distance from P to its projection // on the plane dMin = CGAL::squared_distance( p, projP ) ; } else { // Else, the distance is the minimum from P to triangle sides dMin = CGAL::squared_distance( p, Segment_3( a,b ) ) ; dMin = std::min( dMin, CGAL::squared_distance( p, Segment_3( b,c ) ) ); dMin = std::min( dMin, CGAL::squared_distance( p, Segment_3( c,a ) ) ); } return dMin ; #endif }
void Viewer::drawFacet(const Triangle_3& t, const QColor& /*clr*/) { // disable lighting ::glDisable( GL_LIGHTING ); // disable depth buffer writing ::glDepthMask( GL_FALSE ); qglColor( m_colorFacet ); ::glBegin(GL_TRIANGLES); Point_3 p0 = t.vertex(0); Point_3 p1 = t.vertex(1); Point_3 p2 = t.vertex(2); ::glVertex3f( p0.x(), p0.y(), p0.z() ); ::glVertex3f( p1.x(), p1.y(), p1.z() ); ::glVertex3f( p2.x(), p2.y(), p2.z() ); ::glEnd(); // resume depth buffer writing ::glDepthMask( GL_TRUE ); // resume lighting ::glEnable( GL_LIGHTING ); }
double Q(const Triangle_3& t) { const double S = sqrt(t.squared_area()); const double p = (1/2.0) * (dist(t[0],t[1]) + dist(t[1],t[2]) + dist(t[2],t[0])); const double rho = S/p; const double h = max(dist(t[0],t[1]), max(dist(t[1],t[2]), dist(t[2],t[0]))); return (6/sqrt(3)) * rho/h; }
/* * missing in CGAL? */ squared_distance_t squaredDistanceTriangleTriangle3D( const Triangle_3& triangleA, const Triangle_3& triangleB ) { if ( boost::none != CGAL::intersection( triangleA, triangleB ) ) { return squared_distance_t( 0 ); } /* * min of distance from A segments to B triangle and B segments to A triangle */ squared_distance_t dMin = squaredDistanceSegmentTriangle3D( Segment_3( triangleA.vertex( 0 ), triangleA.vertex( 1 ) ), triangleB ); dMin = std::min( dMin, squaredDistanceSegmentTriangle3D( Segment_3( triangleA.vertex( 1 ), triangleA.vertex( 2 ) ), triangleB ) ); dMin = std::min( dMin, squaredDistanceSegmentTriangle3D( Segment_3( triangleA.vertex( 2 ), triangleA.vertex( 0 ) ), triangleB ) ); dMin = std::min( dMin, squaredDistanceSegmentTriangle3D( Segment_3( triangleB.vertex( 0 ), triangleB.vertex( 1 ) ), triangleA ) ); dMin = std::min( dMin, squaredDistanceSegmentTriangle3D( Segment_3( triangleB.vertex( 1 ), triangleB.vertex( 2 ) ), triangleA ) ); dMin = std::min( dMin, squaredDistanceSegmentTriangle3D( Segment_3( triangleB.vertex( 2 ), triangleB.vertex( 0 ) ), triangleA ) ); return dMin ; }
// ------------------------------------------------------------- // dg_voronoi_point // ------------------------------------------------------------- // This function computes a voronoi point when some degeneracies // have been discovered about the four points of a tetrahedron. // // In this function we assume that the degeneracies occured // because of the coplanarity. We approximate the circumcenter // of the tetrahedron by the circumcenter of one of the triangular // facets. // ------------------------------------------------------------- Point dg_voronoi_point(const Point &a, const Point &b, const Point &c, const Point &d, bool &is_correct_computation) { // First, we check if our assumption is correct. // This is more of a debugging purpose than of // actual computation. Tetrahedron t = Tetrahedron(a,b,c,d); if( ! t.is_degenerate() ) { // cerr << "error in the assumption of coplanarity." << endl; /* // debug cout << "{OFF " << endl; cout << "4 4 0" << endl; cout << a << "\n" << b << "\n" << c << "\n" << d << endl; cout << "3\t0 1 2" << endl; cout << "3\t0 2 3" << endl; cout << "3\t0 3 1" << endl; cout << "3\t1 2 3" << endl; cout << "}" << endl; // end debug */ } // Approximate the circumcenter of the tetrahedron with that of // one of its triangular facets. The facet should not be collinear. // The following boolean variable will keep track if we have found // a valid circumcenter (of a triangle) to replace that of a // tetrahedron. Point cc = CGAL::ORIGIN; is_correct_computation = false; Point p[4] = {a,b,c,d}; for(int i = 0; i < 4; i ++) { // first check if the facet is degenerate or not. Triangle_3 t = Triangle_3(p[(i+1)%4], p[(i+2)%4], p[(i+3)%4]); if( t.is_degenerate() ) continue; // since we found a non-degenerate triangle we can now compute // its circumcenter and we will be done. cc = nondg_cc_tr_3(p[(i+1)%4], p[(i+2)%4], p[(i+3)%4], is_correct_computation); if( is_correct_computation ) break; } if( is_correct_computation ) { if(cc == CGAL::ORIGIN) cerr << "<dg_vp : returning cc as ORIGIN>" << endl; return cc; } cerr << "four points are colinear. " << endl; // for the time being, I just average the four points. What should be // the circumcenter of a tetrahedron whose four points are collinear ? cc = CGAL::ORIGIN + ( 0.25*Vector ( a[0]+b[0]+c[0]+d[0], a[1]+b[1]+c[1]+d[1], a[2]+b[2]+c[2]+d[2] ) ); if(cc == CGAL::ORIGIN) cerr << "<dg_vp : returning cc as ORIGIN>" << endl; return cc; }
float sdf( const Point& q, const Mesh &mesh, const vector<double>& weights, KdTree& kd_tree, const Triangulation& triang ) { VECTOR3 query (CGAL::to_double(q.x()), CGAL::to_double(q.y()), CGAL::to_double(q.z())); kd_tree.queryPosition(query); // Initialize the search structure, and search all N points int n_vid = kd_tree.getNeighbourPositionIndex(0); if(n_vid == -1) throw std::runtime_error("No nearest neighbor. MDS empty?"); CGAL_assertion( ! mesh.vert_list[n_vid].iso()); MVertex nv = mesh.vert_list[n_vid]; double min_sq_d = HUGE; int n_fid = -1; for(int i = 0; i < nv.num_inc_face; i ++) { MFace f = mesh.face_list[nv.inc_face(i)]; Point p[3] = {mesh.vert_list[f.get_corner(0)].point(), mesh.vert_list[f.get_corner(1)].point(), mesh.vert_list[f.get_corner(2)].point()}; Triangle_3 t (p[0], p[1], p[2]); Plane_3 H (p[0], p[1], p[2]); Point _q = H.projection(q); // check if _q is inside t. if( t.has_on(_q) ) { double sq_d = CGAL::to_double((q-_q)*(q-_q)); if( sq_d < min_sq_d ) { min_sq_d = sq_d; n_fid = nv.inc_face(i); } } else { for(int j = 0; j < 3; j ++) { double _d = CGAL::to_double(CGAL::squared_distance(_q,Segment(p[j], p[(j+1)%3]))); double sq_d = CGAL::to_double((q-_q)*(q-_q)) + _d; if( sq_d < min_sq_d ) { min_sq_d = sq_d; n_fid = nv.inc_face(i); } } } } // locate the query point in the triang which is already tagged // with in-out flag by the reconstruction. bool is_q_outside = false; Triangulation::Locate_type lt; int u = -1, v = -1; Cell_handle c = triang.locate(q, lt, u, v); if( lt == Triangulation::OUTSIDE_AFFINE_HULL ) { is_q_outside = true; cerr << "Point " << q << " is outside the affine hull." << endl; } else if( lt == Triangulation::OUTSIDE_CONVEX_HULL ) is_q_outside = true; else { if( lt == Triangulation::CELL ) { if( c->outside ) is_q_outside = true; else is_q_outside = false; } else if( lt == Triangulation::FACET ) { Cell_handle _c = c->neighbor(u); if( c->outside && _c->outside ) is_q_outside = true; else is_q_outside = false; } else if( lt == Triangulation::EDGE ) { if( is_outside_VF(triang, Edge(c, u, v)) ) is_q_outside = true; else is_q_outside = false; } else { CGAL_assertion( lt == Triangulation::VERTEX ); is_q_outside = false; } } double w; if(weights.size() && mesh.face_list[n_fid].label != -1) w = weights[mesh.face_list[n_fid].label]; else w = 1.0; // double w = mesh.face_list[n_fid].w; double gen_sdf = 0; if( is_q_outside ) gen_sdf = w*sqrt(min_sq_d); else gen_sdf = -w*min_sq_d; #if 0 double MAX = 10, MIN = -10; if( gen_sdf > MAX ) gen_sdf = MAX; if( gen_sdf < MIN ) gen_sdf = MIN; #endif return gen_sdf; }