Beispiel #1
0
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 ;
}
Beispiel #2
0
/*
 * 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
}
Beispiel #3
0
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 );
}
Beispiel #4
0
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;
}
Beispiel #5
0
/*
 * 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 ;
}
Beispiel #6
0
// -------------------------------------------------------------
// 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;
}
Beispiel #7
0
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;
}