Exemplo n.º 1
0
void Foam::cellShapeControlMesh::barycentricCoords
(
    const Foam::point& pt,
    barycentric& bary,
    Cell_handle& ch
) const
{
    // Use the previous cell handle as a hint on where to start searching
    // Giving a hint causes strange errors...
    ch = locate(toPoint(pt));

    if (dimension() > 2 && !is_infinite(ch))
    {
        oldCellHandle_ = ch;

        tetPointRef tet
        (
            topoint(ch->vertex(0)->point()),
            topoint(ch->vertex(1)->point()),
            topoint(ch->vertex(2)->point()),
            topoint(ch->vertex(3)->point())
        );

        bary = tet.pointToBarycentric(pt);
    }
}
Exemplo n.º 2
0
  double operator() (const AdvancingFront& adv, Cell_handle& c,
                     const int& index) const
  {
    // bound == 0 is better than bound < infinity
    // as it avoids the distance computations
    if(bound == 0){
      return adv.smallest_radius_delaunay_sphere (c, index);
    }

    // If perimeter > bound, return infinity so that facet is not used
    double d  = 0;
    d = sqrt(squared_distance(c->vertex((index+1)%4)->point(),
                              c->vertex((index+2)%4)->point()));
    if(d>bound) return adv.infinity();
    d += sqrt(squared_distance(c->vertex((index+2)%4)->point(),
                               c->vertex((index+3)%4)->point()));
    if(d>bound) return adv.infinity();
    d += sqrt(squared_distance(c->vertex((index+1)%4)->point(),
                               c->vertex((index+3)%4)->point()));
    if(d>bound) return adv.infinity();

    // Otherwise, return usual priority value: smallest radius of
    // delaunay sphere
    return adv.smallest_radius_delaunay_sphere (c, index);
  }
Exemplo n.º 3
0
// Returns whether the facet facet is attached to the cell
// that is used to represent facet
bool edge_attached_to(const DT_3& dt, const Edge& edge, const Facet& facet) {
  
  if(dt.is_infinite(facet)) {
    return false;
  }

  Vertex_handle v1 = edge.first->vertex(edge.second);
  Vertex_handle v2 = edge.first->vertex(edge.third);

  Cell_handle cell = facet.first;
  int i1 = facet.second;
  int i2 = cell->index(v1);
  int i3 = cell->index(v2);
  CGAL_assertion(i1!=i2);
  CGAL_assertion(i1!=i3);
  CGAL_assertion(i2!=i3);
  int j = 0;
  
  while(j==i1 || j==i2 || j==i3) {
    j++;
  }
  // j is the index of the third point of the facet
  Vertex_handle w = cell->vertex(j);
  
  return CGAL::side_of_bounded_sphere(v1->point(),v2->point(),w->point())==CGAL::ON_BOUNDED_SIDE;

}
Exemplo n.º 4
0
void draw_facets(Delaunay &Tr,std::vector<Facet> &facets,PointColor pcolors,CGAL::Geomview_stream &gv) {
  if(! gv_on) return;
  CGAL::Color colors[] = {CGAL::BLUE,CGAL::GREEN,CGAL::YELLOW,CGAL::DEEPBLUE,
			  CGAL::PURPLE,CGAL::VIOLET,CGAL::ORANGE,CGAL::RED};
  if(pcolors.size() == 0) 
    return draw_facets(Tr,facets,gv);
  // draw with color interpolation
  for (std::vector<Facet>::iterator it = facets.begin();it != facets.end();it++) {
    Facet f = *it;
    Cell_handle c = f.first;
    int j = f.second;
    CGAL::Color vcolors[3];
    int k = 0;
    for(int i = 0;i < 4;i++) 
      if(i != j)
	vcolors[k++] = pcolors[c->vertex(i)->info()];
    int r = (vcolors[0].red() + vcolors[1].red() + vcolors[2].red()) / 3;
    int g = (vcolors[0].green() + vcolors[1].green() + vcolors[2].green()) / 3;
    int b = (vcolors[0].blue() + vcolors[1].blue() + vcolors[2].blue()) / 3;
    gv << CGAL::Color(r,g,b);
    //    std::cout << "RGB " << r << " " << g << " " << b <<std::endl;
    Triangle t = Tr.triangle(f);
    gv << t;
  }
}
AlphaSimplex3D::
AlphaSimplex3D(const Delaunay3D::Edge& e)
{
    Cell_handle c = e.first;
    Parent::add(c->vertex(e.second));
    Parent::add(c->vertex(e.third));
}
AlphaSimplex3D::
AlphaSimplex3D(const Delaunay3D::Facet& f)
{
    Cell_handle c = f.first;
    for (int i = 0; i < 4; ++i)
        if (i != f.second)
            Parent::add(c->vertex(i));
}
Exemplo n.º 7
0
double
cell_volume(const Cell_handle& c)
{
   Tetrahedron t = Tetrahedron(c->vertex(0)->point(),
                               c->vertex(1)->point(),
                               c->vertex(2)->point(),
                               c->vertex(3)->point());
   return ( CGAL::to_double(CGAL::abs(t.volume()) ) );
}
Exemplo n.º 8
0
Point
circumcenter(const Facet& f)
{
    Cell_handle c = f.first;
    int id = f.second;
    Point p[3];
    for(int i = 0; i < 3; i ++)
        p[i] = c->vertex((id + (i+1))%4)->point();
    return cc_tr_3(p[0], p[1], p[2]);
}
void Foam::cellShapeControlMesh::writeTriangulation()
{
    OFstream str
    (
        "refinementTriangulation_"
      + name(Pstream::myProcNo())
      + ".obj"
    );

    label count = 0;

    Info<< "Write refinementTriangulation" << endl;

    for
    (
        CellSizeDelaunay::Finite_edges_iterator e = finite_edges_begin();
        e != finite_edges_end();
        ++e
    )
    {
        Cell_handle c = e->first;
        Vertex_handle vA = c->vertex(e->second);
        Vertex_handle vB = c->vertex(e->third);

        // Don't write far edges
        if (vA->farPoint() || vB->farPoint())
        {
            continue;
        }

        // Don't write unowned edges
        if (vA->referred() && vB->referred())
        {
            continue;
        }

        pointFromPoint p1 = topoint(vA->point());
        pointFromPoint p2 = topoint(vB->point());

        meshTools::writeOBJ(str, p1, p2, count);
    }

    if (is_valid())
    {
        Info<< "    Triangulation is valid" << endl;
    }
    else
    {
        FatalErrorIn
        (
            "Foam::triangulatedMesh::writeRefinementTriangulation()"
        )   << "Triangulation is not valid"
            << abort(FatalError);
    }
}
static void printCell(const Cell_handle &cell, const Vertex_handle &infinity)
{
	DEBUG_START;
	unsigned infinityIndex = cell->index(infinity);
	for (unsigned i = 0; i < NUM_CELL_VERTICES; ++i)
		if (i != infinityIndex)
			std::cout << cell->vertex(i)->info()
				<< " ";
	std::cout << std::endl;
	DEBUG_END;
}
Exemplo n.º 11
0
/**
 * Gets the material for the given point
 * @param p The point to get the material for
 * @return The material at the given point
 */
Contents StoneWeatherer::getContents( const Point & p ) const {

	// Get a handle to the cell that contains the given point
	Cell_handle ch = newDT->locate( p );

	if ( newDT->is_infinite( ch ) ) {

		return AIR;
	}
	else {

		return ch->info();
	}
}
// Calculates void volume and spheres area (only for own four spheres) of regular triangulation cell.
// Doesn't consider extraneous atoms from neighbor cells! True volume can be obtained only for cluster of cells comprising one connected void.
// S. Sastry, D.S. Corti, P.G. Debenedetti, F.H. Stillinger, "Statistical geometry of particle packings. I. Algorithm for exact determination of connectivity,
// volume, and surface areas of void space in monodisperse and polydisperse sphere packings", Phys. Rev. E, V.56, N5, p. 5524, 1997. doi:10.1103/PhysRevE.56.5524
double cell_void_volume(Cell_handle c, double &out_surf, Array_double_4 &out_atom_surf)
{
    const Point *pts[4] = { &((c->vertex(0)->point()).point()),
                            &((c->vertex(1)->point()).point()),
                            &((c->vertex(2)->point()).point()),
                            &((c->vertex(3)->point()).point()) };
    const Point &V = c->weighted_circumcenter().point();   // Voronoi vertex V

    double volume = 0.0, surface = 0.0;
    Array_double_4 per_atom_surface;
    std::fill(per_atom_surface.begin(), per_atom_surface.end(), 0.0);

    // General idea: consider 24 subsimplexes with three orthogonal edges 
    // by constructing normals from weighted circumcenter to the faces and then to the edges
    for (int i = 0; i < 4; i++) {                             // iteration over cell facets
        const Point *p_vertex_i = pts[i];
        pts[i] = &V;     // replace vertex(i) in array  by weighted circumcenter of cell
        CGAL::Sign sV = orientation(*pts[0], *pts[1], *pts[2], *pts[3]);  // do V and vertex(i) on the same side of facet?

        const int a[3] = { (i+1)%4, (i+2)%4, (i+3)%4 };    // indicies of atoms of face opposite to cell vertex i
        const Point E = K::Plane_3(*pts[a[0]], *pts[a[1]], *pts[a[2]]).projection(V);  // projection of Voronoi vertex to facet
        const double z0 = sqrt((V-E).squared_length());    // length of normal to facet

        for (int j = 0; j < 3; j++) {                      // iteration over facet edges
            const int e[2] = { a[(j+1)%3], a[(j+2)%3] };   // indices of two edge atoms
            const Weighted_point WA[2] = { c->vertex(e[0])->point(), c->vertex(e[1])->point() };
            const Point A[2] = { WA[0].point(), WA[1].point() };
            const CGAL::Sign sE = coplanar_orientation(A[0], A[1], *pts[a[j]], E);

            const Point B = K::Line_3(A[0], A[1]).projection(E);  // projection of E to edge
            const double y0 = sqrt((E-B).squared_length());

            for (int k = 0; k < 2; k++) {                         // iteration over edge ends (two atoms)
                CGAL::Sign sB = CGAL::sign((B - A[k])*(A[(k+1)%2] - A[k]));  // negative if point B is in other direction than opposite A[(k+1)%2] looking from A[k]
                CGAL::Sign sF = sV * sE * sB;                                // final subsimplex sign
                double x0 = sqrt((B-A[k]).squared_length());
                double area;
                volume += sF * subsimplex_void_volume(x0, y0, z0, WA[k].weight(), &area);  // sum signed volume contribution from subsimplexes
                surface += sF * area;
                per_atom_surface[e[k]] += sF * area;
            }
        }

        pts[i] = p_vertex_i;  // place vertex(i) back to array
    }

    out_atom_surf = per_atom_surface;
    out_surf = surface;
    return volume;
}
Exemplo n.º 13
0
// Returns whether the facet facet is attached to the cell
// that is used to represent facet
bool triangle_attached_to(const DT_3& dt, const Facet& facet) {
  Cell_handle cell = facet.first;
  int index = facet.second;

  if(dt.is_infinite(cell)) {
    return false;
  }

  Vertex_handle v1 = cell->vertex((index+1)%4);
  Vertex_handle v2 = cell->vertex((index+2)%4);
  Vertex_handle v3 = cell->vertex((index+3)%4);

  Vertex_handle w = cell->vertex(facet.second); 

  return CGAL::side_of_bounded_sphere(v1->point(),v2->point(),v3->point(),w->point())==CGAL::ON_BOUNDED_SIDE;
}
Exemplo n.º 14
0
void draw_line_tetra(Delaunay &Tr,std::vector<Cell_handle> &cells,CGAL::Geomview_stream &gv) {
  if(! gv_on) return;
  CGAL::Color colors[] = {CGAL::BLUE,CGAL::GREEN,CGAL::YELLOW,CGAL::DEEPBLUE,
			  CGAL::PURPLE,CGAL::VIOLET,CGAL::ORANGE,CGAL::RED};
  int k = 0;
  for (std::vector<Cell_handle>::iterator it = cells.begin();it != cells.end();it++,k++) {
    Cell_handle c = *it;
    gv << colors[k % 8];
    Segment segs[4];
    for(int i = 0;i < 4;i++) {
      for(int j = i + 1;j < 4;j++) {
	Segment s = Segment(c->vertex(i)->point(),c->vertex(j)->point());
	gv << s;
      }
    }
  }
}
Exemplo n.º 15
0
  void print(const Cell_handle c, const std::string& name) const
  {
    std::cerr << name << ":[" ;

    for ( int i=0; i<4 ; ++i )
      std::cerr << "[" << c->vertex(i)->point() << "]";

    std::cerr << "] ";
  }
Exemplo n.º 16
0
Arquivo: diag.cpp Projeto: ramja/TDA-1
Vertex_list fromCell(const Cell_handle& ch)
{
	Vertex_list the_list;
	for (auto i = 0; i < 4; i++)
	{
		the_list.push_back(ch->vertex(i));
	}
	return the_list;
}
Exemplo n.º 17
0
bool
is_p_inside_cell(const Point& p, const Cell_handle& c, bool& is_degenerate)
{
   is_degenerate = false;
   for(int id = 0; id < 4; id ++)
   {
       Tetrahedron t1 (c->vertex((id+1)%4)->point(),
                       c->vertex((id+2)%4)->point(),
                       c->vertex((id+3)%4)->point(),
                       p);
       Tetrahedron t2 (c->vertex((id+1)%4)->point(),
                       c->vertex((id+2)%4)->point(),
                       c->vertex((id+3)%4)->point(),
                       c->vertex(id)->point());
       if( CGAL::is_negative(t1.volume()*t2.volume()) ) return false;
       if( ! CGAL::is_positive(t1.volume()*t2.volume()) ) is_degenerate = true;
   }
   return true;
}
static std::vector<unsigned> calculateActiveGroup(const Cell_handle &cell,
		unsigned iNearest,
		const std::vector<SupportItem> &items)
{
	DEBUG_START;
	Vector_3 xOld = cell->info().point - CGAL::Origin();
	std::vector<unsigned> activeGroup;
	unsigned numUnresolvedCurrent = 0;
	bool nearestFound = false;
	for (unsigned iPlane : cell->info().associations)
	{
		const SupportItem &item = items[iPlane];
		double delta = item.direction * xOld - item.value;
		std::cout << "  delta for plane #" << iPlane << "= " << delta
			<< "; resolved: " << item.resolved << std::endl;
		if (!item.resolved)
		{
			++numUnresolvedCurrent;
			if (iPlane == iNearest)
			{
				activeGroup.push_back(iPlane);
				nearestFound = true;
			}
		}
		else
			activeGroup.push_back(iPlane);
	}
	std::cout << "  Number of current unresolved items: "
		<< numUnresolvedCurrent << std::endl;
	if (numUnresolvedCurrent == 0)
	{
		DEBUG_END;
		return std::vector<unsigned>();
	}
	ASSERT(numUnresolvedCurrent > 0 && "Nothing to be resolved");
	ASSERT(nearestFound && "Failed to find nearest point inside given "
			"cell");
	ASSERT(activeGroup.size() > NUM_FACET_VERTICES && "Not enough planes");

	DEBUG_END;
	return activeGroup;
}
AlphaSimplex3D::
AlphaSimplex3D(const Delaunay3D::Edge& e, const SimplexSet& simplices, const Delaunay3D& Dt, Facet_circulator facet_bg)
{
    Cell_handle c = e.first;
    Parent::add(c->vertex(e.second));
    Parent::add(c->vertex(e.third));

    Facet_circulator cur = facet_bg;
    while (Dt.is_infinite(*cur))    ++cur;
    SimplexSet::const_iterator cur_iter = simplices.find(AlphaSimplex3D(*cur));
    RealValue min = cur_iter->alpha();

    const VertexSet& vertices = static_cast<const Parent*>(this)->vertices();
    VertexSet::const_iterator v = vertices.begin();
    const DPoint& p1 = (*v++)->point();
    const DPoint& p2 = (*v)->point();
    attached_ = false;

    if (facet_bg != 0) do
    {
        VertexSet::const_iterator v = vertices.begin();
        int i0 = (*cur).first->index(*v++);
        int i1 = (*cur).first->index(*v);
        int i = 6 - i0 - i1 - (*cur).second;
        if (Dt.is_infinite(cur->first->vertex(i))) { ++cur; continue; }
        DPoint p3 = (*cur).first->vertex(i)->point();

        cur_iter = simplices.find(AlphaSimplex3D(*cur));
        if (CGAL::side_of_bounded_sphere(p1, p2, p3) == CGAL::ON_BOUNDED_SIDE)
            attached_ = true;
        RealValue val = cur_iter->alpha();
        if (val < min)
            min = val;
        ++cur;
    } while (cur != facet_bg);

    if (attached_)
        alpha_ = min;
    else
        alpha_ = CGAL::squared_radius(p1, p2);
}
Exemplo n.º 20
0
/**
 * Computes the circumcenters of the given cell
 * @param cell The cell to compute the circumcenters for
 * @param result Stores the circumcenter
 * @return TRUE always
 */
bool computeCircumcenter( const Cell_handle & cell, Point & result ) {

	// The four vertices of the cell (tetrahedron)
	const Point & p = cell->vertex( 0 )->point();
	const Point & q = cell->vertex( 1 )->point();
	const Point & r = cell->vertex( 2 )->point();
	const Point & s = cell->vertex( 3 )->point();

	// Translate p to the origin to simplify the expression
	double qpx = q.x() - p.x();
	double qpy = q.y() - p.y();
	double qpz = q.z() - p.z();
	double qp2 = square( qpx ) + square( qpy ) + square( qpz );
	double rpx = r.x() - p.x();
	double rpy = r.y() - p.y();
	double rpz = r.z() - p.z();
	double rp2 = square( rpx ) + square( rpy ) + square( rpz );
	double spx = s.x() - p.x();
	double spy = s.y() - p.y();
	double spz = s.z() - p.z();
	double sp2 = square( spx ) + square( spy ) + square( spz );

	double determinant = CGAL::determinant( qpx, qpy, qpz, rpx, rpy, rpz, spx, spy, spz );

	if ( determinant == 0 ) {

		result = CGAL::ORIGIN + ( ( p - CGAL::ORIGIN ) * 0.25 + ( q - CGAL::ORIGIN ) * 0.25 + ( r - CGAL::ORIGIN ) * 0.25 + ( s - CGAL::ORIGIN ) * 0.25 );

		return true;
	}

	double numX = CGAL::determinant( qpy, qpz, qp2, rpy, rpz, rp2, spy, spz, sp2 );
	double numY = CGAL::determinant( qpx, qpz, qp2, rpx, rpz, rp2, spx, spz, sp2 );
	double numZ = CGAL::determinant( qpx, qpy, qp2, rpx, rpy, rp2, spx, spy, sp2 );
	double inverse = 1.0 / ( 2.0 * determinant );

	result = Point( p.x() + numX * inverse, p.y() - numY * inverse, p.z() + numZ * inverse );

	return true;
}
static Cell_handle findBestCell(const Vector_3 &direction,
		const Vertex_handle &infinity,
		const Cell_handle &startingCell)
{
	DEBUG_START;
	/* FIXME: Maybe some hint will be useful here */
	ASSERT(startingCell->has_vertex(infinity) && "Wrong input");
	Cell_handle bestCell = startingCell;
	Cell_handle nextCell = bestCell;
	double maxProduct = calculateProduct(direction, bestCell, infinity);
	unsigned numIterations = 0;
	do
	{
		++numIterations;
		bestCell = nextCell;
		ASSERT(bestCell->has_vertex(infinity) && "Wrong iteration");
		int infinityIndex = bestCell->index(infinity);
		for (int i = 0; i < NUM_CELL_VERTICES; ++i)
		{
			if (i == infinityIndex)
				continue;
			Cell_handle neighbor = bestCell->neighbor(i);
			double product = calculateProduct(direction,
					neighbor, infinity);
			if (product > maxProduct)
			{
				nextCell = neighbor;
				maxProduct = product;
			}
		}
	} while (nextCell != bestCell);
	ASSERT(bestCell->has_vertex(infinity) && "Wrong result");
	DEBUG_END;
	return bestCell;
}
static unsigned getNearestOuterItemID(const Cell_handle &cell,
		const std::vector<SupportItem> &items,
		const Vertex_handle &infinity)
{
	DEBUG_START;
	Plane_3 plane = getOppositeFacetPlane(cell, infinity);
	Point_3 point = dual(plane);
	cell->info().point = point;
	
	double distanceMin = MINIMIZATION_STARTING_VALUE;
	unsigned iNearest = 0;
	const auto &associations = cell->info().associations;
	unsigned numUnresolved = 0;
	for (unsigned iPlane : associations)
	{
		SupportItem item = items[iPlane];
		Vector_3 u = item.direction;
		double value = item.value;
		double distance = value - u * (point - CGAL::Origin());
		if (!item.resolved)
		{
			ASSERT(distance > 0. && "Incorrect resolved flag");
			if (distance < distanceMin)
			{
				iNearest = iPlane;
				distanceMin = distance;
			}
			++numUnresolved;
		}
	}
	if (numUnresolved > 0)
		ASSERT(distanceMin < MINIMIZATION_STARTING_VALUE
				&& "Failed to find");
	cell->info().distance = distanceMin;
	DEBUG_END;
	return iNearest;
}
Exemplo n.º 23
0
/**
 * Finds a circumcenter in the grid and labels its associated cell
 * @param point The location of the circumcenter
 * @param cell The cell to label
 * @param midpoint Stores the weighted midpoint of non-air cells
 * @param volume Accumulates the volume of non-air cells
 */
void UniformGrid::locateAndLabel( const Point & point, Cell_handle & cell, double * midpoint, double & volume ) const {

	Point3D p( point.x(), point.y(), point.z() );
	unsigned int x = ( unsigned int ) ( ( p.x - xmin ) * inv_Xsize );
	unsigned int y = ( unsigned int ) ( ( p.y - ymin ) * inv_Ysize );
	unsigned int z = ( unsigned int ) ( ( p.z - zmin ) * inv_Zsize );

	unsigned int i = ( ( ( My * z ) + y ) * Mx ) + x;
	unsigned int start = grid[ i ];
	unsigned int end = grid[ i + 1 ];
	double tetrahedronVolume = 0.0;

	for ( i = start; i < end; ++i ) {

		if ( tetrahedrons[ L[ i ] ]->contains( p ) ) {

			cell->info() = tetrahedrons[ L[ i ] ]->cell->info();

			if ( cell->info() > AIR ) {

				tetrahedronVolume = Tetrahedron::volume( cell );
				
				#pragma omp critical(updateVolume)
				{
					volume += tetrahedronVolume;
					midpoint[ 0 ] += p.x * tetrahedronVolume;
					midpoint[ 1 ] += p.y * tetrahedronVolume;
					midpoint[ 2 ] += p.z * tetrahedronVolume;
				}
			}

			return;
		}
	}

	cell->info() = AIR;
}
AlphaSimplex3D::
AlphaSimplex3D(const Delaunay3D::Facet& f, const SimplexSet& simplices, const Delaunay3D& Dt)
{
    Cell_handle c = f.first;
    for (int i = 0; i < 4; ++i)
        if (i != f.second)
            Parent::add(c->vertex(i));

    Cell_handle o = c->neighbor(f.second);
    int oi = o->index(c);

    VertexSet::const_iterator v = static_cast<const Parent*>(this)->vertices().begin();
    const DPoint& p1 = (*v++)->point();
    const DPoint& p2 = (*v++)->point();
    const DPoint& p3 = (*v)->point();

    attached_ = false;
    if (!Dt.is_infinite(c->vertex(f.second)) &&
        CGAL::side_of_bounded_sphere(p1, p2, p3,
                                     c->vertex(f.second)->point()) == CGAL::ON_BOUNDED_SIDE)
        attached_ = true;
    else if (!Dt.is_infinite(o->vertex(oi)) &&
             CGAL::side_of_bounded_sphere(p1, p2, p3,
                                          o->vertex(oi)->point()) == CGAL::ON_BOUNDED_SIDE)
        attached_ = true;
    else
        alpha_ = CGAL::squared_radius(p1, p2, p3);

    if (attached_)
    {
        if (Dt.is_infinite(c))
            alpha_ = simplices.find(AlphaSimplex3D(*o))->alpha();
        else if (Dt.is_infinite(o))
            alpha_ = simplices.find(AlphaSimplex3D(*c))->alpha();
        else
            alpha_ = std::min(simplices.find(AlphaSimplex3D(*c))->alpha(),
                              simplices.find(AlphaSimplex3D(*o))->alpha());
    }
}
Exemplo n.º 25
0
bool
is_p_outside(const Point& q, const Triangulation& triang,
             const Cell_handle& start_cell,
             Cell_handle& c, int& u, int& v)
{
   Triangulation::Locate_type lt;
   u = -1; v = -1;
   c = triang.locate(q, lt, u, v, start_cell);
   if( lt == Triangulation::OUTSIDE_AFFINE_HULL )
   {
     cerr << "Point " << q << " is outside the affine hull." << endl;
     return true;
   }
   else if( lt == Triangulation::OUTSIDE_CONVEX_HULL )
     return true;
   else
   {
     if( lt == Triangulation::CELL )
     {
        if( c->outside )
           return true; 
        else
           return false; 
     }
     else if( lt == Triangulation::FACET )
     {
        Cell_handle _c = c->neighbor(u);
        if( c->outside && _c->outside )
           return true; 
        else
           return false; 
     }
     else if( lt == Triangulation::EDGE )
     {
        if( is_outside_VF(triang, Edge(c, u, v)) )
           return true; 
        else
           return false;
     }
     else
     {
        CGAL_assertion( lt == Triangulation::VERTEX );
        return false; 
     }
   }
}
Exemplo n.º 26
0
/**
 * Adds a new tetrahedron to the hierarchy
 * @param cell The cell associated with the tetrahedron
 */
void UniformGrid::add( Cell_handle cell ) {

	Point3D v0( cell->vertex( 0 )->point().x(), cell->vertex( 0 )->point().y(), cell->vertex( 0 )->point().z() );
	Point3D v1( cell->vertex( 1 )->point().x(), cell->vertex( 1 )->point().y(), cell->vertex( 1 )->point().z() );
	Point3D v2( cell->vertex( 2 )->point().x(), cell->vertex( 2 )->point().y(), cell->vertex( 2 )->point().z() );
	Point3D v3( cell->vertex( 3 )->point().x(), cell->vertex( 3 )->point().y(), cell->vertex( 3 )->point().z() );

	tetrahedrons.push_back( new Tetrahedron( v0, v1, v2, v3, cell ) );

	xmin = MIN( xmin, MIN( MIN( v0.x, v1.x ), MIN( v2.x, v3.x ) ) );
	ymin = MIN( ymin, MIN( MIN( v0.y, v1.y ), MIN( v2.y, v3.y ) ) );
	zmin = MIN( zmin, MIN( MIN( v0.z, v1.z ), MIN( v2.z, v3.z ) ) );

	xmax = MAX( xmax, MAX( MAX( v0.x, v1.x ), MAX( v2.x, v3.x ) ) );
	ymax = MAX( ymax, MAX( MAX( v0.y, v1.y ), MAX( v2.y, v3.y ) ) );
	zmax = MAX( zmax, MAX( MAX( v0.z, v1.z ), MAX( v2.z, v3.z ) ) );
}
void DualPolyhedron_3::associateVertex(const Vertex_handle &vertex)
{
	DEBUG_START;
	int iPlane = vertex->info();
	if (isOuterVertex(vertex))
	{
		Cell_handle cell;
		int iVertex, iInfinity;
		bool result = is_edge(vertex, infinite_vertex(), cell,
				iVertex, iInfinity);
		ASSERT(result && "Wrong set");
		
		TDelaunay_3::Edge edge(cell, iVertex, iInfinity);
		auto circulator = incident_cells(edge);
		auto end = circulator;
		do
		{
			Cell_handle currentCell = circulator;
			ASSERT(currentCell->has_vertex(vertex));
			ASSERT(currentCell->has_vertex(infinite_vertex()));
			currentCell->info().associations.insert(iPlane);
			items[iPlane].associations.insert(currentCell);
			items[iPlane].resolved = true;
			++circulator;
		} while (circulator != end);
	}
	else
	{
		Vector_3 direction = items[iPlane].direction;
		Cell_handle bestCell = findBestCell(direction,
				infinite_vertex(), infinite_cell());
		bestCell->info().associations.insert(iPlane);
		/* FIXME: Maybe the association for a plane is singular? */
		items[iPlane].associations.insert(bestCell);
	}
	DEBUG_END;
}
Exemplo n.º 28
0
bool is_degenerate_VF(const Triangulation& triang, const Cell_handle& c, const int& fid, const int& uid, const int& vid, const Point& d, const char* prefix)
{
	char degen_op_filename[200];
	strcat(strcpy(degen_op_filename, prefix), ".degen_VF");
	// an extra check - probably not needed.
	if (triang.is_infinite(c) || triang.is_infinite(c->neighbor(fid)) || triang.is_infinite(c->neighbor(6 - fid - uid - vid)))
	{
		return true;
	}
	vector<Cell_handle> VF;
	Facet_circulator fcirc = triang.incident_facets(Edge(c,uid,vid));
	Facet_circulator begin = fcirc;
	do
	{
		if (triang.is_infinite((*fcirc).first))
		{
			cerr << "< Inf VF >";
			return true; // by check-1 it is degenerate.
		}
		Cell_handle cur_c = (*fcirc).first;
		int cur_fid = (*fcirc).second;
		// check if cur_c and its cur_fid neighbors are cospherical.
		if (is_cospherical_pair(triang, Facet(cur_c,cur_fid)))
		{
			cerr << "< Cosph VF >";
			return true; // by check-2 it is degenerate.
		}
		fcirc ++;
	}
	while (fcirc != begin);
	// check-3
	Point vv[3];
	vv[0] = c->voronoi();
	vv[1] = c->neighbor(fid)->voronoi();
	vv[2] = c->neighbor(6 - fid - uid - vid)->voronoi();
	Vector v[3];
	v[0] = vv[0] - d;
	v[1] = vv[1] - d;
	v[2] = vv[2] - d;
	Vector v1xv0 = CGAL::cross_product(v[1], v[0]);
	Vector v0xv2 = CGAL::cross_product(v[0], v[2]);
	if (CGAL::to_double(v1xv0 * v0xv2) < 0)
	{
		ofstream fout;
		fout.open(degen_op_filename, ofstream::app);
		fout << "# prob : v1xv0 * v0xv2 = " <<
			 CGAL::to_double(v1xv0 * v0xv2) << endl;
		fout << "{LIST " << endl;
		fout << "# VF - color yellow " << endl;
		draw_VF(triang, Edge(c, uid, vid), 1, 1, 0, 1, fout);
		fout << "# v0 : segment(driver, voronoi(c)) - color red " << endl;
		draw_segment(Segment(d, vv[0]), 1, 0, 0, 1, fout);
		fout << "# v1 : segment(driver, voronoi(c->neighbor1)) - color green " << endl;
		draw_segment(Segment(d, vv[1]), 0, 1, 0, 1, fout);
		fout << "# v2 : segment(driver, voronoi(c->neighbor2)) - color blue " << endl;
		draw_segment(Segment(d, vv[2]), 0, 0, 1, 1, fout);
		fout << "}" << endl;
		fout.close();
		cerr << "< - v1xv0 * v0xv2 < 0 - >";
		return true;
	}
	return false;
}
bool DualPolyhedron_3::lift(Cell_handle cell, unsigned iNearest)
{
	DEBUG_START;
	Vector_3 xOld = cell->info().point - CGAL::Origin();
	std::cout << "Old tangient point: " << xOld << std::endl;
	const auto activeGroup = calculateActiveGroup(cell, iNearest, items);
	if (activeGroup.empty())
	{
		DEBUG_END;
		return false;
	}

	Vector_3 xNew = leastSquaresPoint(activeGroup, items);
	std::cout << "New tangient point: " << xNew << std::endl;

	ASSERT(cell->has_vertex(infinite_vertex()));
	unsigned infinityIndex = cell->index(infinite_vertex());
	std::vector<Vertex_handle> vertices;
	Vertex_handle dominator;
	double alphaMax = 0.;
	double alphaMax2 = 0.;
	for (unsigned i = 0; i < NUM_CELL_VERTICES; ++i)
	{
		if (i == infinityIndex)
			continue;

		vertices.push_back(cell->vertex(i));

		Vertex_handle vertex = mirror_vertex(cell, i);
		Plane_3 plane = ::dual(vertex->point());
		double alpha;
	        bool succeeded;
		std::tie(succeeded, alpha) = calculateAlpha(xOld, xNew, plane);
		if (!succeeded)
			return false;
		std::cout << "Alpha #" << i << ": " << alpha << std::endl;
		ASSERT(alpha <= 1. && "Wrongly computed alpha");
		if (alpha > alphaMax)
		{
			alphaMax2 = alphaMax;
			alphaMax = alpha;
			dominator = vertex;
		}
	}
	
	std::cout << "Maximal alpha: " << alphaMax << std::endl;
	std::cout << "Maximal alpha 2nd: " << alphaMax2 << std::endl;
	ASSERT(alphaMax < 1. && "What to do then?");
	if (alphaMax > 0.)
	{
		std::cout << "Full move is impossible, performing partial move"
			<< std::endl;
		partiallyMove(xOld, xNew, vertices, dominator, alphaMax,
				alphaMax2);
	}
	else
	{
		std::cout << "Performing full move" << std::endl;
		if (!fullyMove(vertices, xNew, activeGroup))
		{
			DEBUG_END;
			return false;
		}
	}
	DEBUG_END;
	return true;
}
// Constructs regular triangulation of weighted points.
// Builds graph of cells with voids. Finds connected components of this graph (voids as clusters of cells).
// For each component calculates total void volume and area.
// Excludes roughs on the surface (components, connected to the infinite cell).
bool regular_triangulation_voids(const Wpi_container& points, Voids_result &res)
{
    typedef typename boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS, Cell_handle> CellGraph;
    typedef typename boost::graph_traits<CellGraph>::vertex_descriptor GVertex;
    typedef typename boost::graph_traits<CellGraph>::vertex_iterator GVertex_iterator;

    Rt T;            // regular triangulation
    CellGraph G;     // Voronoi subgraph where cells_sqr_r > 0 and edges_sqr_r > 0 (cells and edges with voids)
    GVertex_iterator vi, vi_end;


    res.out_log << "Number of input points for RT : " <<  points.size() << std::endl;
    T.insert(points.begin(), points.end());    // insert all points in a row (this is faster than one insert() at a time).
    T.infinite_vertex()->info().atom_id = -1;  // set special atom_id for dummy infinite triangulation vertex

    assert(T.dimension() == 3);
    /*res.out_log << "Is valid : " << T.is_valid() << std::endl;*/
    res.out_log << "Number of vertices in RT : " << T.number_of_vertices() << std::endl;
    res.out_log << "Number of cells : " << T.number_of_cells() << std::endl;
    res.out_log << "Number of finite cells : " << T.number_of_finite_cells() << std::endl;
    /*res.out_log << "Inf. vert. atom id : " << T.infinite_vertex()->info().atom_id << std::endl;*/

    // Add finite cells having sqr_r > 0 as graph verticies
    Finite_cells_iterator cit, cit_end = T.finite_cells_end();
    for (cit = T.finite_cells_begin(); cit != cit_end; cit++) {
        if (cit->weighted_circumcenter().weight() > 0)       // cached weighted circumcenter computation
            cit->id() = add_vertex(Cell_handle(cit), G);     // store corresponding graph vertex descriptor in cell's id()
    }

    // store one of infinite cells in graph: it will represent all of them. It should be the last vertex in graph with maximal vertex_descriptor.
    const GVertex inf_graph_v = add_vertex(T.infinite_cell(), G);
    res.out_log << "inf_graph_v descriptor : " << inf_graph_v << std::endl;

    // Add graph edges connecting cells with void
    for (boost::tie(vi, vi_end) = vertices(G); vi != vi_end; ++vi) {
        const GVertex v1 = *vi;           // current graph vertex

        if (v1 != inf_graph_v) { // check edges only from finite cells
            const Cell_handle c1 = G[v1];    // current cell

            for (int i = 0; i < 4; i++) {       // for each of four neighbor cells
                const Cell_handle c2 = c1->neighbor(i);
                bool ends_in_void = false;   // do both corresponding Voronoi verticies lie in void space?
                bool on_same_side = false;   // do both ends lie on the same side of corresponding cell facet?
                const Weighted_point &p1 = c1->vertex((i+1)&3)->point();     // weighted points of common facet between c and c2 cells
                const Weighted_point &p2 = c1->vertex((i+2)&3)->point();
                const Weighted_point &p3 = c1->vertex((i+3)&3)->point();
                const Point &wcc = c1->weighted_circumcenter().point();
                GVertex v2;  // neighbor vertex in graph to construct edge to

                if (c2->id() != -1) {    // neighbor cell is finite and in graph: id()=vertex_descriptor
                    v2 = c2->id();
                    ends_in_void = true;
                    on_same_side = (orientation(p1.point(), p2.point(), p3.point(), wcc) ==
                                    orientation(p1.point(), p2.point(), p3.point(), c2->weighted_circumcenter().point()));
                } else if (T.is_infinite(c2))   {
                    v2 = inf_graph_v;    // use our infinite graph vertex as destination if neighbor cell is infinite
                    ends_in_void = true;
                    on_same_side = (orientation(p1.point(), p2.point(), p3.point(), wcc) !=
                                    orientation(p1.point(), p2.point(), p3.point(), c1->vertex(i)->point().point()));  // same side with infinite vertex = different sides with cell vertex
                }

                typename K::Compute_squared_radius_smallest_orthogonal_sphere_3 r_mouth;  // facet bottleneck squared radius (facet closed if < 0)
                if (ends_in_void && (v2 > v1) && (on_same_side || r_mouth(p1, p2, p3) > 0))
                    add_edge(v1, v2, G);  // use ordering v2>v1 to rule out most of the parallel edges: rely on v_inf>v1 for all finite vertices
            }
        }
    }

    res.out_log << "Number of vertices in G : " << num_vertices(G) << std::endl;
    res.out_log << "Number of edges in G : " << num_edges(G) << std::endl;

    // Find connected components on this Voronoi subnetwork
    std::vector<int> component(num_vertices(G));
    int num_components = boost::connected_components(G, &component[0]);
    const int inf_comp_id = component[inf_graph_v];  // component of infinite vertex
    res.out_log << "Number of connected components : " << num_components << std::endl;
    res.out_log << "Component id of infinite vertex : " << inf_comp_id << std::endl;

    // Reserve storage for results
    res.voids.resize(num_components);
    std::fill(res.atom_surf.begin(), res.atom_surf.end(), 0.0L);

    // Calculate total volume of each finite component
    for (boost::tie(vi, vi_end) = vertices(G); vi != vi_end; ++vi) {
        const int comp_id = component[*vi];
        if (comp_id != inf_comp_id) {   // skip infinite component
            Cell_handle cell = G[*vi];  // current cell
            double Vc, Sc;              // cell volume and surface
            Array_double_4 Sa;          // per atom surface in cell
            Vc = cell_void_volume(cell, Sc, Sa);     // void volume of cell and its surface area

            res.voids[comp_id].volume += Vc;  // add to volume of component
            res.voids[comp_id].surface += Sc;
            for (int k = 0; k < 4; k++) {  // process four cell atoms
                int atom_id = cell->vertex(k)->info().atom_id;
                res.atom_surf[atom_id] += Sa[k];     // atom exposed surface
                res.voids[comp_id].atoms.insert(atom_id);  // add to set of cavity atoms
            }
        }
    }

    // Remove skipped infinite component with zero values
    res.voids.erase(res.voids.begin() + inf_comp_id);

    // Sort cavities by volume
    std::sort(res.voids.begin(), res.voids.end(), void_greater);

    return true;
}