/** * \return Number of segments. The number of segments equals the * number of vertices for a closed polyline and one less for * an open polyline. */ int RPolyline::countSegments() const { if (closed) { return countVertices(); } else { return countVertices() - 1; } }
void countVertices(MeshGroup const & mg, long & num_vertices) { for (MeshGroup::MeshConstIterator mi = mg.meshesBegin(); mi != mg.meshesEnd(); ++mi) num_vertices += (*mi)->numVertices(); for (MeshGroup::GroupConstIterator ci = mg.childrenBegin(); ci != mg.childrenEnd(); ++ci) countVertices(**ci, num_vertices); }
void RPolyline::print(QDebug dbg) const { dbg.nospace() << "RPolyline("; RShape::print(dbg); dbg.nospace() << ", "; dbg.nospace() << "vertices: " << countVertices() << ", "; QList<QSharedPointer<RShape> > sub = getExploded(); QList<QSharedPointer<RShape> >::iterator it; for (it=sub.begin(); it!=sub.end(); ++it) { dbg.nospace() << "\n" << *it->data() << ", "; } dbg.nospace() << ")"; }
std::vector<uint> sefield::TetMesh::getVertexPermutation(void) { uint nverts = countVertices(); // Return a copy of this vector std::vector<uint> vert_ret = std::vector<uint>(nverts); for (uint i = 0; i < nverts; ++i) { vert_ret[i] = pVertexPerm[i]; } return vert_ret; }
RBox RPolyline::getBoundingBox() const { RBox ret; if (countVertices()==1) { ret = RBox(vertices.at(0), vertices.at(0)); } QList<QSharedPointer<RShape> > sub = getExploded(); QList<QSharedPointer<RShape> >::iterator it; for (it=sub.begin(); it!=sub.end(); ++it) { RBox bb = (*it)->getBoundingBox(); ret.growToInclude(bb); } return ret; }
void countSubents() { AcBr::ErrorStatus returnValue = AcBr::eOk; Acad::ErrorStatus acadReturnValue = eOk; // Get the subentity path for a brep AcDbFullSubentPath subPath(kNullSubent); acadReturnValue = selectEntity(AcDb::kNullSubentType, subPath); if (acadReturnValue != eOk) { acutPrintf(ACRX_T("\n Error in getPath: %d"), acadReturnValue); return; } // Make a brep entity to access the solid AcBrBrep brepEntity; returnValue = ((AcBrEntity*)&brepEntity)->set(subPath); if (returnValue != AcBr::eOk) { acutPrintf(ACRX_T("\n Error in AcBrBrep::set:")); errorReport(returnValue); return; } // count the unique complexes in the brep returnValue = countComplexes(brepEntity); if (returnValue != AcBr::eOk) { acutPrintf(ACRX_T("\n Error in countComplexes:")); errorReport(returnValue); return; } // count the unique shells in the brep returnValue = countShells(brepEntity); if (returnValue != AcBr::eOk) { acutPrintf(ACRX_T("\n Error in countShells:")); errorReport(returnValue); return; } // count the unique faces in the brep returnValue = countFaces(brepEntity); if (returnValue != AcBr::eOk) { acutPrintf(ACRX_T("\n Error in countFaces:")); errorReport(returnValue); return; } // count the unique edges in the brep returnValue = countEdges(brepEntity); if (returnValue != AcBr::eOk) { acutPrintf(ACRX_T("\n Error in countEdges:")); errorReport(returnValue); return; } // count the unique vertices in the brep returnValue = countVertices(brepEntity); if (returnValue != AcBr::eOk) { acutPrintf(ACRX_T("\n Error in countVertices:")); errorReport(returnValue); return; } return; }
bool NTriangulation::simplifyToLocalMinimum(bool perform) { BoundaryComponentIterator bit; unsigned long nTriangles; unsigned long iTriangle; // unsigned long nEdges; // unsigned long iEdge; // std::deque<NEdgeEmbedding>::const_iterator embit, embbeginit, embendit; bool changed = false; // Has anything changed ever (for return value)? bool changedNow = true; // Did we just change something (for loop control)? { // Begin scope for change event span. ChangeEventSpan span(this); while (changedNow) { changedNow = false; ensureSkeleton(); // Crush edges if we can. if (countVertices() > components().size() && countVertices() > boundaryComponents_.size()) { for (NEdge* edge : edges()) if (collapseEdge(edge, true, perform)) { changedNow = changed = true; break; } if (changedNow) { if (perform) continue; else return true; } } // Look for internal simplifications. for (NEdge* edge : edges()) { if (threeTwoMove(edge, true, perform)) { changedNow = changed = true; break; } if (twoZeroMove(edge, true, perform)) { changedNow = changed = true; break; } if (twoOneMove(edge, 0, true, perform)) { changedNow = changed = true; break; } if (twoOneMove(edge, 1, true, perform)) { changedNow = changed = true; break; } } if (changedNow) { if (perform) continue; else return true; } for (NVertex* vertex : vertices()) if (twoZeroMove(vertex, true, perform)) { changedNow = changed = true; break; } if (changedNow) { if (perform) continue; else return true; } // Look for boundary simplifications. if (hasBoundaryTriangles()) { for (bit = boundaryComponents_.begin(); bit != boundaryComponents_.end(); bit++) { // Run through triangles of this boundary component looking // for shell boundary moves. nTriangles = (*bit)->countTriangles(); for (iTriangle = 0; iTriangle < nTriangles; iTriangle++) { if (shellBoundary((*bit)->triangle(iTriangle)-> front().tetrahedron(), true, perform)) { changedNow = changed = true; break; } } if (changedNow) break; } if (changedNow) { if (perform) continue; else return true; } } } } // End scope for change event span. return changed; }
void sefield::TetMesh::axisOrderElements(uint opt_method, std::string const & opt_file_name) { // Now this method provides a choice between Stefan and Robert's method // and the new method by Iain. The original method is fast and suffices for // simple geometries, Iain's method is superior and important for complex // geometries, but slow. if (opt_file_name != "") { std::fstream opt_file; opt_file.open(opt_file_name.c_str(), std::fstream::in | std::fstream::binary); opt_file.seekg(0); uint nelems = 0; opt_file.read((char*)&nelems, sizeof(uint)); if (pElements.size() != nelems) { std::ostringstream os; os << "optimal data mismatch with simulator parameters: sefield::Tetmesh::nelems, "; os << nelems << ":" << pElements.size(); throw steps::ArgErr(os.str()); } opt_file.read((char*)pVertexPerm, sizeof(uint) * nelems); VertexElementPVec elements_temp = pElements; for (uint vidx = 0; vidx < nelems; ++vidx) { VertexElementP vep = elements_temp[vidx]; // sanity check assert(vep->getIDX() == vidx); uint new_idx = pVertexPerm[vidx]; pElements[new_idx] = vep; } reindexElements(); reordered(); opt_file.close(); return; } if (opt_method == 2) { // / / / / / / / / / / / / / / NEW / / / / / / / / / / / / / / / / / / // // LOOPING OVER ALL VERTICES, APPLYING THE WALK METHOD AND FINDING WHICH // STARTING VERTEX GIVES THE LOWEST MATRIX WIDTH. uint pNVerts = pElements.size(); // the best vertex(narrowest width) uint bestone = 0; uint bestwidth = pNVerts; std::vector<VertexElement*> orig_indices = pElements; stringstream ss; ss << "\nFinding optimal vertex indexing. This can take some time..."; cout << ss.str() << endl; for (uint vidx = 0; vidx < pNVerts; ++vidx) { set<VertexElement*> verteleset = set<VertexElement*>(); vector<VertexElement*> vertelevec = vector<VertexElement*>(); queue<VertexElement*> vertelqueue = queue<VertexElement*>(); verteleset.insert(orig_indices[vidx]); vertelevec.push_back(orig_indices[vidx]); uint ve0ncons = orig_indices[vidx]->getNCon(); VertexElement ** ve0neighbs = orig_indices[vidx]->getNeighbours(); fill_ve_vec(verteleset, vertelevec, vertelqueue, ve0ncons, ve0neighbs); pElements.clear(); vector<VertexElement*>::iterator vertele_end = vertelevec.end(); uint ielt = 0; for (vector<VertexElement*>::iterator vertele = vertelevec.begin(); vertele != vertele_end; ++vertele) { pElements.push_back(*vertele); pVertexPerm[(*vertele)->getIDX()]=ielt; ielt++; } // Note: this will reorder the vertex indices as we go- not a problem in this loop // but they must be reset for the final index setting to work reindexElements(); uint maxdi = 0; for (int iv = 0; iv < pNVerts; ++iv) { VertexElement* ve = getVertex(iv); int ind = ve->getIDX(); for (int i = 0; i < ve->getNCon(); ++i) { int inbr = ve->nbrIdx(i); int di = ind - inbr; if (di < 0) { di = -di; } if (di > maxdi) { maxdi = di; } } } if (maxdi < bestwidth) { bestone = vidx; bestwidth = maxdi; //cout << "\nOriginal vertex "<< vidx << " gives banded matrix half-width " << maxdi; } } // reset the vertex indices to their original value: important for (uint v = 0; v < pNVerts; ++v) { orig_indices[v]->setIDX(v); } set<VertexElement*> verteleset = set<VertexElement*>(); vector<VertexElement*> vertelevec = vector<VertexElement*>(); queue<VertexElement*> vertelqueue = queue<VertexElement*>(); verteleset.insert(orig_indices[bestone]); vertelevec.push_back(orig_indices[bestone]); uint ve0ncons = orig_indices[bestone]->getNCon(); VertexElement ** ve0neighbs = orig_indices[bestone]->getNeighbours(); fill_ve_vec(verteleset, vertelevec, vertelqueue, ve0ncons, ve0neighbs); pElements.clear(); vector<VertexElement*>::iterator vertele_end = vertelevec.end(); uint ielt = 0; for (vector<VertexElement*>::iterator vertele = vertelevec.begin(); vertele != vertele_end; ++vertele) { pElements.push_back(*vertele); pVertexPerm[(*vertele)->getIDX()]=ielt; ielt++; } } // / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / // else if (opt_method == 1) { /* THIS ORIGINAL CODE REPLACED WITH NEW 'WALKING' METHOD. A DRAMATIC REDUCTION IN BAND HALF-WIDTHS FOR COMPLEX 3D MESHES. This is not the end of the story: TODO investigate whether reordering a vertices neighbour's for the queue by distance will improve again. */ std::vector<double> com = centerOfMass(); double ** m = new double*[3]; for (uint i = 0; i < 3; i++) { m[i] = new double[3]; m[i][0] = 0.0; m[i][1] = 0.0; m[i][2] = 0.0; } for (uint ivert = 0; ivert < countVertices(); ivert++) { VertexElement* ve = getVertex(ivert); double x = ve->getX() - com[0]; double y = ve->getY() - com[1]; double z = ve->getZ() - com[2]; m[0][0] += x * x; m[0][1] += x * y; m[0][2] += x * z; m[1][0] += y * x; m[1][1] += y * y; m[1][2] += y * z; m[2][0] += z * x; m[2][1] += z * y; m[2][2] += z * z; } uint iret; double gamma; double evec[3]; mainEvec(3, m, &iret, &gamma, evec); if (iret != 1) { cout << "\nWarning - eigenvalue faliure " << endl; } for (uint i = 0; i < 3; i++) { delete[] m[i]; } delete[] m; double vx = evec[0]; double vy = evec[1]; double vz = evec[2]; vx += 1.e-8; vy += 1.e-9; vz += 1.e-10; stringstream ss; ss << "aligning to axis " << vx << " " << vy << " " << vz << endl; //cout << ss.str(); map<double, VertexElement*> hm; //vector<double> da; for (uint ielt = 0; ielt < countVertices(); ielt++) { VertexElement * ve = getVertex(ielt); double d = vx * ve->getX() + vy * ve->getY() + vz * ve->getZ(); hm[d] = ve; //da.push_back(d); } //sort(da.begin(), da.end()); pElements.clear(); uint ielt = 0; map<double, VertexElement*>::const_iterator iter = hm.begin(); while (iter != hm.end()) { double d = iter->first; pElements.push_back(hm[d]); ++iter; // pVertexPerm[i] contains the new index in the elements array // for the vertex that was originally at index i pVertexPerm[hm[d]->getIDX()] = ielt; ielt++; } } else { std::ostringstream os; os << "Unknown optimization method.\n"; throw steps::ArgErr(os.str()); } reindexElements(); reordered(); }