static tetrahedra read_tetrahedra (boost::tokenizer<>::iterator & p, const boost::tokenizer<>::iterator & end, std::list<vertex_id> & finalized_vertices, const dias::vertex_db & vertices, int v_count) { vertex_id v_ids[4]; int j = 0; while (p != end) { std::string v_str = *p++; int v = boost::lexical_cast<int> (v_str); if (v >= 0) v_ids[j] = v; else { v_ids[j] = v_count + v; finalized_vertices.push_back (v_ids[j]); } j++; } assert (j == 4); return tetrahedra (v_ids, vertices); }
/// Returns the number of tetrahedra in the alpha shape. int AlphaShape::tetrahedronCount() const { return tetrahedra().size(); }
const NGroupPresentation& Dim4Triangulation::fundamentalGroup() const { if (fundGroup_.known()) return *fundGroup_.value(); NGroupPresentation* ans = new NGroupPresentation(); if (isEmpty()) return *(fundGroup_ = ans); ensureSkeleton(); // Each non-boundary not-in-forest tetrahedron is a generator. // Each non-boundary triangle is a relation. long nBdryTets = 0; for (BoundaryComponentIterator bit = boundaryComponents_.begin(); bit != boundaryComponents_.end(); ++bit) nBdryTets += (*bit)->countTetrahedra(); // Cast away all unsignedness in case we run into problems subtracting. long nGens = static_cast<long>(countTetrahedra()) - nBdryTets - static_cast<long>(size()) + static_cast<long>(countComponents()); // Insert the generators. ans->addGenerator(nGens); // Find out which tetrahedron corresponds to which generator. long* genIndex = new long[countTetrahedra()]; long i = 0; for (Dim4Tetrahedron* tet : tetrahedra()) if (! (tet->isBoundary() || tet->inMaximalForest())) genIndex[tet->index()] = i++; // Run through each triangle and insert the corresponding relations. Dim4Pentachoron* pent; int facet; Dim4Tetrahedron* tet; NGroupExpression* rel; for (Dim4Triangle* f : triangles()) { if (f->isBoundary()) continue; // Put in the relation corresponding to this triangle. rel = new NGroupExpression(); for (auto& emb : *f) { pent = emb.pentachoron(); facet = emb.vertices()[3]; tet = pent->tetrahedron(facet); if (tet->inMaximalForest()) continue; // We define the "direction" for this dual edge to point // from embedding tet->front() to embedding tet->back(). // // Test whether we are traversing this dual edge forwards or // backwards as we walk around the triangle (*fit). if ((tet->front().pentachoron() == pent) && (tet->front().tetrahedron() == facet)) rel->addTermLast(genIndex[tet->index()], 1); else rel->addTermLast(genIndex[tet->index()], -1); } ans->addRelation(rel); } // Tidy up. delete[] genIndex; ans->intelligentSimplify(); return *(fundGroup_ = ans); }