//----------------------------------------------------------------------------
void Mgc::FindIntersection (const Tetrahedron& rkT0, const Tetrahedron& rkT1,
    Mgc::TetrahedronConsumer& dest)
{
    // build planar faces of T0
    const int planePer=4;
    Plane akPlane[planePer];
    rkT0.GetPlanes(akPlane);
    
/* early-exit test for non-overlapping tets */
    if (1) {
        Plane ak1Plane[planePer];
        rkT1.GetPlanes(ak1Plane);
        if (allOutside(akPlane,planePer,rkT1) || allOutside(ak1Plane,planePer,rkT0))
            return; /* tets do not overlap */
    }
    
  /* Build filter to successively clip tets by each plane of T0,
      passing the final tets to the user's destination.
   */
    PlaneSplitTetrahedronConsumer cons0(akPlane[0],dest);
    PlaneSplitTetrahedronConsumer cons1(akPlane[1],cons0);
    PlaneSplitTetrahedronConsumer cons2(akPlane[2],cons1);
    PlaneSplitTetrahedronConsumer cons3(akPlane[3],cons2);
    
  /* Pass T1 through the filter chain */
    cons3.Add(rkT1);
}
Beispiel #2
0
void AddTetra()
{
	Tetrahedron* tetra = new Tetrahedron(ColouredParticleSystem::RandomVector(30.0) + Vec3(0, 15, 0), (float)rand() * 10.0f / RAND_MAX);
	tetra->ApplyImpulse(ColouredParticleSystem::RandomVector(0.05f));
	tetra->ApplyAngularImpulse(ColouredParticleSystem::RandomVector(0.05f));
	tetra->ConvexPolyhedron::SetDebugColour(Vec4(ColouredParticleSystem::RandomVector(1), 1));
	PhysicsSystem::GetCurrentInstance()->AddRigidBody(tetra);
}
Beispiel #3
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()) ) );
}
number CalculateVolume(const Tetrahedron& tet,
		Grid::VertexAttachmentAccessor<APosition>& aaPos) {
	vector3& a = aaPos[tet.vertex(0)];
	vector3& b = aaPos[tet.vertex(1)];
	vector3& c = aaPos[tet.vertex(2)];
	vector3& d = aaPos[tet.vertex(3)];

	return CalculateTetrahedronVolume(a, b, c, d);
}
Beispiel #5
0
int main(int argc, char *argv[])
{
//Add commentar
    QApplication app(argc, argv);
    if (!QGLFormat::hasOpenGL()) {
        cerr << "This system has no OpenGL support" << endl;
        return 1;
    }
	//skuska
    Tetrahedron tetrahedron;
    tetrahedron.setWindowTitle(QObject::tr("Tetrahedron"));
    tetrahedron.resize(300, 300);
    tetrahedron.show();

    return app.exec();
}
/// Centers a tetrahedral mesh (returning a new mesh)
void IndexedTetraArray::center()
{
  // determine the centroid of this array of tetrahedra
  Point3d centroid = Point3d::zero(GLOBAL);
  double total_volume = 0;
  for (unsigned i=0; i< num_tetra(); i++)
  {
    Tetrahedron tet = get_tetrahedron(i, GLOBAL);
    double volume = tet.calc_volume();
    centroid += tet.calc_centroid()*volume;
    total_volume += volume;
  }
  centroid /= total_volume;

  // translate the mesh so that the centroid is at the origin
  for (unsigned i=0; i< _vertices->size(); i++)
    ((Origin3d&) (*_vertices)[i]) -= Origin3d(centroid);
}
Beispiel #7
0
  void RCNeighbourList::removeDOFParent(int index)
  {
    Tetrahedron* el = dynamic_cast<Tetrahedron*>(rclist[index]->el);
    Mesh* mesh = el->getMesh();
    int edges = mesh->getGeo(EDGE);
    int faces = mesh->getGeo(FACE);


    if (mesh->getNumberOfDofs(EDGE))
    {
      int node = mesh->getNode(EDGE);
      for (int j = 0; j < edges; j++)
        el->setDof(node + j, NULL);
    }

    if (mesh->getNumberOfDofs(FACE))
    {
      int node = mesh->getNode(FACE);
      RCListElement* neigh = rclist[index]->neigh[0];

      // face 2
      if (!neigh || neigh > rclist[index])
        mesh->freeDof(const_cast<DegreeOfFreedom*>(el->getDof(node + 2)), FACE);

      neigh = rclist[index]->neigh[1];
      // face 3
      if (!neigh || neigh > rclist[index])
        mesh->freeDof(const_cast<DegreeOfFreedom*>(el->getDof(node + 3)), FACE);

      for (int j = 0; j < faces; j++)
        el->setDof(node + j, NULL);
    }

    if (mesh->getNumberOfDofs(CENTER))
    {
      int node = mesh->getNode(CENTER);
      mesh->freeDof(const_cast<DegreeOfFreedom*>(el->getDof(node)), CENTER);
      el->setDof(node, NULL);
    }
  }
//----------------------------------------------------------------------------
void Mgc::FindIntersection (const Tetrahedron& rkT0, const Tetrahedron& rkT1,
    vector<Tetrahedron>& rkIntr)
{
    // build planar faces of T0
    Plane akPlane[4];
    rkT0.GetPlanes(akPlane);

    // initial object to clip is T1
    rkIntr.clear();
    rkIntr.push_back(rkT1);

    // clip T1 against planes of T0
    for (int iP = 0; iP < 4; iP++)
    {
        vector<Tetrahedron> kInside;
        for (int iT = 0; iT < (int)rkIntr.size(); iT++)
            SplitAndDecompose(rkIntr[iT],akPlane[iP],kInside);
        rkIntr = kInside;
    }
}
Beispiel #9
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 #10
0
bool SaveGridToNCDF(Grid& grid, const char* filename,
					ISubsetHandler* pSH,
					APosition aPos)
{
//	open the file to which we'll write
	ofstream out(filename);
	if(!out)
		return false;

//	access subset-handler
	if(!pSH){
		UG_LOG("ERROR: SubsetHandler required for NCDF (Exodus) export.\n");
		return false;
	}

	ISubsetHandler& sh = *pSH;

//	access the position attachment
	if(!grid.has_vertex_attachment(aPos))
		return false;

	if(grid.num_volumes() != grid.num<Tetrahedron>()){
		UG_LOG("Saving grid to EXODUS-format.\n"
				<< "  WARNING: only Tetrahedrons exported in the moment.\n");
	}

	Grid::VertexAttachmentAccessor<APosition> aaPos(grid, aPos);

//	assign vertex indices
	AInt aInt;
	grid.attach_to_vertices(aInt);
	Grid::VertexAttachmentAccessor<AInt> aaInt(grid, aInt);
	AssignIndices(grid.vertices_begin(), grid.vertices_end(), aaInt, 1);

//	write exodus header
	int var4 = 4;
	out << "netcdf object {" << endl;
	out << "dimensions:" << endl;
	out << "\tlen_string = 33 ;" << endl;
	out << "\tlen_line = 81 ;" << endl;
	out << "\tfour = " << var4 << " ;" << endl;
	out << "\ttime_step = UNLIMITED ;" << endl;
	out << "\tnum_dim = 3 ;" << endl;
	out << "\tnum_nodes = " << grid.num_vertices() << " ;" << endl;
	out << "\tnum_elem = " << grid.num<Tetrahedron>() << " ;" << endl;
	out << "\tnum_el_blk = " << sh.num_subsets() << " ;" << endl;

	for(int i = 0; i < sh.num_subsets(); ++i){
		GridObjectCollection goc = sh.get_grid_objects_in_subset(i);
		out << "\tnum_el_in_blk" << i+1 << " = " << goc.num<Tetrahedron>() << " ;" << endl;
		out << "\tnum_nod_per_el" << i+1 << " = 4 ;" << endl;
	}

	out << "\tnum_qa_rec = 1 ;" << endl;

//	write variables
	out << endl;
	out << "variables:" << endl;
	out << "\tdouble time_whole(time_step) ;" << endl;
	out << "\tint eb_status(num_el_blk) ;" << endl;
	out << "\tint eb_prop1(num_el_blk) ;" << endl;
	out << "\t\teb_prop1:name = \"ID\" ;" << endl;

	for(int i = 0; i < sh.num_subsets(); ++i){
		out << "\tint connect" << i+1
			<< "(num_el_in_blk" << i+1
			<< ", num_nod_per_el" << i+1 << ") ;" << endl;
		out << "\t\tconnect" << i+1 << ":elem_type = \"TETRA4\" ;" << endl;
	}

	out << "\tdouble coord(num_dim, num_nodes) ;" << endl;
	out << "\tchar qa_records(num_qa_rec, four, len_string) ;" << endl;
	out << "\tchar coor_names(num_dim, len_string) ;" << endl;
	out << "\tint elem_map(num_elem) ;" << endl;
	out << "\tint elem_num_map(num_elem) ;" << endl;
	out << "\tint node_num_map(num_nodes) ;" << endl;

	out << "// global attributes:" << endl;
	out << "\t:api_version = 4.01f ;" << endl;
	out << "\t:version = 3.01f ;" << endl;
	out << "\t:floating_point_word_size = " << sizeof(number) << " ;" << endl;
	out << "\t:file_size = 0 ;" << endl;
	out << "\t:title = \"Exported from lib_grid.\" ;" << endl;

//	write data
	out << endl;
	out << "data:" << endl;

	out << "eb_status = ";
	for(int i = 0; i < sh.num_subsets(); ++i){
		out << "1";
		if(i + 1 < sh.num_subsets())
			out << ", ";
	}
	out << " ;" << endl << endl;

	out << "eb_prop1 = ";
	for(int i = 0; i < sh.num_subsets(); ++i){
		out << i+1;
		if(i + 1 < sh.num_subsets())
			out << ", ";
	}
	out << " ;" << endl << endl;

//	write elements
	for(int i = 0; i < sh.num_subsets(); ++i){
	//	get the goc for this subset
		GridObjectCollection goc = sh.get_grid_objects_in_subset(i);

		out << "connect" << i+1 << " =" << endl;
		for(size_t lvl = 0; lvl < goc.num_levels(); ++lvl){
			for(TetrahedronIterator iter = goc.begin<Tetrahedron>(lvl);
				iter != goc.end<Tetrahedron>(lvl); ++iter)
			{
			//	last comma in each row
				if(iter != goc.begin<Tetrahedron>(lvl))
					out << "," << endl;

				Tetrahedron* tet = *iter;
				out << "  ";
				out << aaInt[tet->vertex(0)] << ", ";
				out << aaInt[tet->vertex(1)] << ", ";
				out << aaInt[tet->vertex(2)] << ", ";
				out << aaInt[tet->vertex(3)];
			}
		}
		out << " ;" << endl << endl;
	}

//	write coords
//	x
	out << "coord =" << endl << " ";
	size_t endlCounter = 1;
	for(VertexIterator iter = grid.vertices_begin();
		iter != grid.vertices_end(); ++iter, ++endlCounter)
	{
		if(endlCounter > 5){
			endlCounter = 1;
			out << endl << " ";
		}

		out << " " << aaPos[*iter].x() << ",";
	}

//	y
	for(VertexIterator iter = grid.vertices_begin();
		iter != grid.vertices_end(); ++iter, ++endlCounter)
	{
		if(endlCounter > 5){
			endlCounter = 1;
			out << endl << " ";
		}
		out << " " << aaPos[*iter].y() << ",";
	}

//	z
	for(VertexIterator iter = grid.vertices_begin();
		iter != grid.vertices_end(); ++iter, ++endlCounter)
	{
		if(iter != grid.vertices_begin()){
			out << ",";
			if(endlCounter > 5){
				endlCounter = 1;
				out << endl << " ";
			}
		}

		out << " " << aaPos[*iter].z();
	}
	out << " ;" << endl << endl;

//	write qa_records
	out << "qa_records =" << endl;
	out << "  \"lib_grid\"," << endl;
	out << "  \"...\"," << endl;
	out << "  \"...\"," << endl;
	out << "  \"...\" ;" << endl;

//	write coor_names
	out << endl;
	out << "coor_names =" << endl;
	out << "  \"x\"," << endl;
	out << "  \"y\"," << endl;
	out << "  \"z\" ;" << endl;

//	write elem_map
	out << endl;
	out << "elem_map = ";
	endlCounter = 1;
	for(size_t i = 0; i < grid.num<Tetrahedron>(); ++i, ++endlCounter)
	{
		out << i+1;
		if(i+1 < grid.num<Tetrahedron>()){
			out << ", ";

			if(endlCounter > 4){
				endlCounter = 0;
				out << endl << "  ";
			}
		}
	}
	out << " ;" << endl;

//	write elem_num_map
	out << endl;
	out << "elem_num_map = ";
	endlCounter = 1;
	for(size_t i = 0; i < grid.num<Tetrahedron>(); ++i, ++endlCounter)
	{
		out << i+1;
		if(i+1 < grid.num<Tetrahedron>()){
			out << ", ";

			if(endlCounter > 4){
				endlCounter = 0;
				out << endl << "  ";
			}
		}
	}
	out << " ;" << endl;

//	write node_num_map
	out << endl;
	out << "node_num_map = ";
	endlCounter = 1;
	for(size_t i = 0; i < grid.num<Vertex>(); ++i, ++endlCounter)
	{
		out << i+1;
		if(i+1 < grid.num<Vertex>()){
			out << ", ";

			if(endlCounter > 4){
				endlCounter = 0;
				out << endl << "  ";
			}
		}
	}
	out << " ;" << endl;

//	close object
	out << "}" << endl;
//	remove vertex indices
	grid.detach_from_vertices(aInt);

//	done
	return true;
}
Beispiel #11
0
void CpuDelaunayMesher::findDelaunayBall(const glm::ivec3& cId, int vId)
{
    Tetrahedron* base = findBaseTetrahedron(cId, vId);
    Vertex& v0 = vert[base->v[0]];
    Vertex& v1 = vert[base->v[1]];
    Vertex& v2 = vert[base->v[2]];
    Vertex& v3 = vert[base->v[3]];

    _ballQueue.clear();
    _ballQueue.push_back(&v0);
    _ballQueue.push_back(&v1);
    _ballQueue.push_back(&v2);
    _ballQueue.push_back(&v3);

    _ball.xOrTri(base->t0());
    _ball.xOrTri(base->t1());
    _ball.xOrTri(base->t2());
    _ball.xOrTri(base->t3());

    removeTetrahedronGrid(base);
    const glm::dvec3& v = vert[vId].p;

    ++_currentVisitTime;
    v0.visitTime = _currentVisitTime;
    v1.visitTime = _currentVisitTime;
    v2.visitTime = _currentVisitTime;
    v3.visitTime = _currentVisitTime;


    for(int qId = 0; qId < _ballQueue.size(); ++qId)
    {
        Vertex* vertex = _ballQueue[qId];

        TetListNode* node = vertex->tetList.head;
        while(node != nullptr)
        {
            Tetrahedron* tet = node->tet;
            node = node->next;

            if(tet->visitTime < _currentVisitTime)
            {
                tet->visitTime = _currentVisitTime;

                if(intersects(v, tet))
                {
                    _ball.xOrTri(tet->t0());
                    _ball.xOrTri(tet->t1());
                    _ball.xOrTri(tet->t2());
                    _ball.xOrTri(tet->t3());


                    // First 8 vertices are corner vertices and are generally
                    // touching a large 'fan' of tetrahedron. Those tetrahedrons
                    // are still accessible via inserted neighboring vertices.
                    const int BOUNDING_VERTICES = 8;

                    if(tet->v[0] >= BOUNDING_VERTICES)
                    {
                        Vertex* tv0 = &vert[tet->v[0]];
                        if(tv0->visitTime < _currentVisitTime)
                        {
                            tv0->visitTime = _currentVisitTime;
                            _ballQueue.push_back(tv0);
                        }
                    }

                    if(tet->v[1] >= BOUNDING_VERTICES)
                    {
                        Vertex* tv1 = &vert[tet->v[1]];
                        if(tv1->visitTime < _currentVisitTime)
                        {
                            tv1->visitTime = _currentVisitTime;
                            _ballQueue.push_back(tv1);
                        }
                    }

                    if(tet->v[2] >= BOUNDING_VERTICES)
                    {
                        Vertex* tv2 = &vert[tet->v[2]];
                        if(tv2->visitTime < _currentVisitTime)
                        {
                            tv2->visitTime = _currentVisitTime;
                            _ballQueue.push_back(tv2);
                        }
                    }

                    if(tet->v[3] >= BOUNDING_VERTICES)
                    {
                        Vertex* tv3 = &vert[tet->v[3]];
                        if(tv3->visitTime < _currentVisitTime)
                        {
                            tv3->visitTime = _currentVisitTime;
                            _ballQueue.push_back(tv3);
                        }
                    }


                    removeTetrahedronGrid(tet);
                }
            }
        }
    }
}
Beispiel #12
0
DeformableBody* MeshLoader::tetrahedron( void ) {
    DeformableBody* body = new DeformableBody( );
    Mesh* mesh = new Mesh( );
    body->mesh = mesh;

    // -- build the mesh  --
    /*
    // x unit vector.  Will rotate it around the unit sphere in x and z
    Vector3 i_hat = Vector3( 1.0, 0.0, 0.0 );
    // y unit vector.  Will be the top of the tetrahedron
    Vector3 j_hat = Vector3( 0.0, 1.0, 0.0 );

    Vector3 u;

    // rotate x_hat around z axis by 30 degrees for first vertex
    u = Matrix3::rotZ( -1.0 * 1.0/12.0 * 2.0 * PI ) * i_hat;
    Vertex* v1 = new Vertex( u, u );

    // now rotate u around the y axis 120 degrees for second vertex
    u = Matrix3::rotY( 1.0/3.0 * 2.0 * PI ) * u;
    Vertex* v2 = new Vertex( u, u );

    // now rotate u around the y axis another 120 degrees for third vertex
    u = Matrix3::rotY( 1.0/3.0 * 2.0 * PI ) * u;
    Vertex* v3 = new Vertex( u, u );

    Vertex* v4 = new Vertex( j_hat, j_hat );
    */

    // Note the following is defined by Schneider & Eberly : Geometric Tools for Computer Graphics p. 347
    Vector3 u;

    u = Vector3( 2.0*sqrt(2.0)/3.0, -1.0/3.0, 0.0 );
    Vertex* v1 = new Vertex( u, u );

    u = Vector3( -sqrt(2.0)/3.0, -1.0/3.0, sqrt(6.0)/3.0 );
    Vertex* v2 = new Vertex( u, u );

    u = Vector3( -sqrt(2.0)/3.0, -1.0/3.0, -sqrt(6.0)/3.0 );
    Vertex* v3 = new Vertex( u, u );

    u = Vector3( 0.0, 1.0, 0.0 );
    Vertex* v4 = new Vertex( u, u );

    ///*
    v1->position.print();
    printf("\n");
    v2->position.print();
    printf("\n");
    v3->position.print();
    printf("\n");
    v4->position.print();
    printf("\n");
    //*/

    Trigon* t;
    t = new Trigon( );
    t->addVertex( 0 );
    t->addVertex( 1 );
    t->addVertex( 3 );
    mesh->appendPolygon( t );

    t = new Trigon( );
    t->addVertex( 1 );
    t->addVertex( 2 );
    t->addVertex( 3 );
    mesh->appendPolygon( t );

    t = new Trigon( );
    t->addVertex( 2 );
    t->addVertex( 0 );
    t->addVertex( 3 );
    mesh->appendPolygon( t );

    t = new Trigon( );
    t->addVertex( 0 );
    t->addVertex( 1 );
    t->addVertex( 2 );
    mesh->appendPolygon( t );

    // -- build the body --
    Node* node1, *node2, *node3, *node4;
    Spring* edge1, *edge2, *edge3, *edge4, *edge5, *edge6;
    Tetrahedron* tetra;

    mesh->appendVertex( v1 );
    node1 = new Node( );
    node1->vertex = v1;
    node1->mass = 0.25;
    body->appendNode( node1 );

    mesh->appendVertex( v2 );
    node2 = new Node( );
    node2->vertex = v2;
    node2->mass = 0.25;
    body->appendNode( node2 );

    mesh->appendVertex( v3 );
    node3 = new Node( );
    node3->vertex = v3;
    node3->mass = 0.25;
    body->appendNode( node3 );

    mesh->appendVertex( v4 );
    node4 = new Node( );
    node4->vertex = v4;
    node4->mass = 0.25;
    body->appendNode( node4 );

    edge1 = new Spring( node1, node2, TETRA_SPRING_COEFFICIENT, TETRA_DAMPING_COEFFICIENT );
    edge2 = new Spring( node2, node3, TETRA_SPRING_COEFFICIENT, TETRA_DAMPING_COEFFICIENT );
    edge3 = new Spring( node3, node1, TETRA_SPRING_COEFFICIENT, TETRA_DAMPING_COEFFICIENT );
    edge4 = new Spring( node1, node4, TETRA_SPRING_COEFFICIENT, TETRA_DAMPING_COEFFICIENT );
    edge5 = new Spring( node2, node4, TETRA_SPRING_COEFFICIENT, TETRA_DAMPING_COEFFICIENT );
    edge6 = new Spring( node3, node4, TETRA_SPRING_COEFFICIENT, TETRA_DAMPING_COEFFICIENT );

    body->appendEdge( edge1 );
    body->appendEdge( edge2 );
    body->appendEdge( edge3 );
    body->appendEdge( edge4 );
    body->appendEdge( edge5 );
    body->appendEdge( edge6 );

    tetra = new Tetrahedron( );
    tetra->insert( node1 );
    tetra->insert( node2 );
    tetra->insert( node3 );
    tetra->insert( node4 );
    tetra->insert( edge1 );
    tetra->insert( edge2 );
    tetra->insert( edge3 );
    tetra->insert( edge4 );
    tetra->insert( edge5 );
    tetra->insert( edge6 );
    body->appendTetrahedron( tetra );

    return body;
}
Beispiel #13
0
// creates edge and triangle structures and links them to existing vertex/tetrahedron structure, to permit storing attributes
void createAggregateDataStructure(){
	int i, j;

	// traverse all tetrahedra and create their triangles, edges and references to them
	stack<Cell> tetraStack;
	tetraStack.push(dt->infinite_cell());

	// while stack not empty
	while (tetraStack.size() > 0){
		// pop tetra from stack
		Cell ch = tetraStack.top();
		tetraStack.pop();
		Tetrahedron *currTetra = &ch->info();

		// DEBUG
		//		cout << "tetra " << COUT_CELL(ch) << endl;

		bool triangleCreated[4];
		Edge *edge[6];

		for (i = 0; i < 6; i++)
			edge[i] = NULL;

		// reference its four triangles (create if not yet existing)
		for (i = 0; i < 4; i++)	{
			triangleCreated[i] = false;

			// look up at neighbor tetrahedron
			Cell oppCH = ch->neighbor(i);
			int oppIndex = oppCH->index(ch);
			Tetrahedron *oppTetra = &oppCH->info();

			// test if triangle exists already
			Triangle *triangle = oppTetra->triangle(oppIndex);

			if (triangle == NULL){
				triangleCreated[i] = true;

				// create new triangle

				//int vIndex[3];

				//for (j = 0; j < 3; j++)
				//				//	vIndex[j] = (i + 1 + j) % 4;
				//	vIndex[j] = tetraTriVertexIndices[i][j];

				Triangle newTriangle(ch, i);
				dtTriangles.push_back(newTriangle);
				triangle = &dtTriangles.back();

				// also push tetrahedron on stack as unhandled
				tetraStack.push(oppCH);

				// DEBUG
				//				cout << "triangle " << *triangle << " created" << endl;
			}

			currTetra->setTriangle(i, triangle);	// reference triangle
			oppTetra->setTriangle(oppIndex, triangle);		// also in opposite tetrahedron
		}

		// reference its six edges (create if not yet existing)
		for (i = 0; i < 6; i++){
			int edgeVIndex[2];

			for (j = 0; j < 2; j++)
				edgeVIndex[j] = ch->vertex(tetraEdgeVertexIndices[i][j])->info().index();

			sort(edgeVIndex, edgeVIndex + 2);

			IntPair intPair(edgeVIndex[0], edgeVIndex[1]);
			map<IntPair, Edge>::iterator mapIter = dtEdgeMap.find(intPair);

			if (mapIter != dtEdgeMap.end())
				edge[i] = &mapIter->second;
			else
			{
				Edge newEdge(ch, tetraEdgeVertexIndices[i][0], tetraEdgeVertexIndices[i][1]);
				dtEdgeMap.insert(pair<IntPair, Edge>(intPair, newEdge));
				map<IntPair, Edge>::iterator mapIter = dtEdgeMap.find(intPair);
				edge[i] = &mapIter->second;
			}
		}

		// only set edges into newly created triangles
		for (i = 0; i < 4; i++)
			if (triangleCreated[i])
				for (j = 0; j < 3; j++)
					currTetra->triangle(i)->setEdge(j, edge[tetraTriEdgeIndices[i][j]]);
	}
	// DEBUG
	cout << "aggregate data structure: " << dtEdgeMap.size() << " edges, " << dtTriangles.size() << " triangles" << endl;
}
/**
 * Determines whether or not the node intersects the given tetrahedron
 * @param tetrahedron The tetrahedron to check
 * @return TRUE if the tetrahedron intersects the box, FALSE otherwise
 */
bool SpatialPartitionNode::intersects( const Tetrahedron & tetrahedron ) const {

	return boxesOverlap( box, tetrahedron.bbox() );
}