/*************************************************************************** * Copyright (c) 2013 Jürgen Riegel (FreeCAD@juergen-riegel.net) * * * * This file is part of the FreeCAD CAx development system. * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Library General Public * * License as published by the Free Software Foundation; either * * version 2 of the License, or (at your option) any later version. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Library General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this library; see the file COPYING.LIB. If not, * * write to the Free Software Foundation, Inc., 59 Temple Place, * * Suite 330, Boston, MA 02111-1307, USA * * * ***************************************************************************/ #include "PreCompiled.h" #ifndef _PreComp_ # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include # include #endif #include "ViewProviderFemMesh.h" #include "ViewProviderFemMeshPy.h" #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace FemGui; struct FemFace { const SMDS_MeshNode *Nodes[8]; unsigned long ElementNumber; const SMDS_MeshElement* Element; unsigned short Size; unsigned short FaceNo; bool hide; Base::Vector3d getFirstNodePoint(void) { return Base::Vector3d(Nodes[0]->X(),Nodes[0]->Y(),Nodes[0]->Z()); } Base::Vector3d set(short size,const SMDS_MeshElement* element,unsigned short id, short faceNo, const SMDS_MeshNode* n1,const SMDS_MeshNode* n2,const SMDS_MeshNode* n3,const SMDS_MeshNode* n4=0,const SMDS_MeshNode* n5=0,const SMDS_MeshNode* n6=0,const SMDS_MeshNode* n7=0,const SMDS_MeshNode* n8=0); bool isSameFace (FemFace &face); }; Base::Vector3d FemFace::set(short size,const SMDS_MeshElement* element,unsigned short id,short faceNo, const SMDS_MeshNode* n1,const SMDS_MeshNode* n2,const SMDS_MeshNode* n3,const SMDS_MeshNode* n4,const SMDS_MeshNode* n5,const SMDS_MeshNode* n6,const SMDS_MeshNode* n7,const SMDS_MeshNode* n8) { Nodes[0] = n1; Nodes[1] = n2; Nodes[2] = n3; Nodes[3] = n4; Nodes[4] = n5; Nodes[5] = n6; Nodes[6] = n7; Nodes[7] = n8; Element = element; ElementNumber = id; Size = size; FaceNo = faceNo; hide = false; // sorting the nodes for later easier comparison (bubble sort) int i, j, flag = 1; // set flag to 1 to start first pass const SMDS_MeshNode* temp; // holding variable for(i = 1; (i <= size) && flag; i++) { flag = 0; for (j=0; j < (size -1); j++) { if (Nodes[j+1] > Nodes[j]) // ascending order simply changes to < { temp = Nodes[j]; // swap elements Nodes[j] = Nodes[j+1]; Nodes[j+1] = temp; flag = 1; // indicates that a swap occurred. } } } return Base::Vector3d(Nodes[0]->X(),Nodes[0]->Y(),Nodes[0]->Z()); }; class FemFaceGridItem :public std::vector{ public: //FemFaceGridItem(void){reserve(200);} }; bool FemFace::isSameFace (FemFace &face) { // the same element can not have the same face if(face.ElementNumber == ElementNumber) return false; if(face.Size != Size) return false; // if the same face size just compare if the sorted nodes are the same if( Nodes[0] == face.Nodes[0] && Nodes[1] == face.Nodes[1] && Nodes[2] == face.Nodes[2] && Nodes[3] == face.Nodes[3] && Nodes[4] == face.Nodes[4] && Nodes[5] == face.Nodes[5] && Nodes[6] == face.Nodes[6] && Nodes[7] == face.Nodes[7] ){ hide = true; face.hide = true; return true; } return false; }; PROPERTY_SOURCE(FemGui::ViewProviderFemMesh, Gui::ViewProviderGeometryObject) App::PropertyFloatConstraint::Constraints ViewProviderFemMesh::floatRange = {1.0f,64.0f,1.0f}; ViewProviderFemMesh::ViewProviderFemMesh() { ADD_PROPERTY(PointColor,(App::Color(0.7f,0.7f,0.7f))); ADD_PROPERTY(PointSize,(5.0f)); PointSize.setConstraints(&floatRange); ADD_PROPERTY(LineWidth,(2.0f)); LineWidth.setConstraints(&floatRange); ShapeColor.setValue(App::Color(1.0f,0.7f,0.0f)); ADD_PROPERTY(BackfaceCulling,(true)); ADD_PROPERTY(ShowInner, (false)); pcDrawStyle = new SoDrawStyle(); pcDrawStyle->ref(); pcDrawStyle->style = SoDrawStyle::LINES; pcDrawStyle->lineWidth = LineWidth.getValue(); pShapeHints = new SoShapeHints; pShapeHints->shapeType = SoShapeHints::SOLID; pShapeHints->vertexOrdering = SoShapeHints::COUNTERCLOCKWISE; pShapeHints->ref(); pcMatBinding = new SoMaterialBinding; pcMatBinding->value = SoMaterialBinding::OVERALL; pcMatBinding->ref(); pcCoords = new SoCoordinate3(); pcCoords->ref(); pcAnoCoords = new SoCoordinate3(); pcAnoCoords->ref(); pcAnoCoords->point.setNum(0); pcFaces = new SoIndexedFaceSet; pcFaces->ref(); pcLines = new SoIndexedLineSet; pcLines->ref(); pcPointStyle = new SoDrawStyle(); pcPointStyle->ref(); pcPointStyle->style = SoDrawStyle::POINTS; pcPointStyle->pointSize = PointSize.getValue(); pcPointMaterial = new SoMaterial; pcPointMaterial->ref(); //PointMaterial.touch(); } ViewProviderFemMesh::~ViewProviderFemMesh() { pcCoords->unref(); pcDrawStyle->unref(); pcFaces->unref(); pcLines->unref(); pShapeHints->unref(); pcMatBinding->unref(); pcPointMaterial->unref(); pcPointStyle->unref(); } void ViewProviderFemMesh::attach(App::DocumentObject *pcObj) { ViewProviderGeometryObject::attach(pcObj); // Move 'coords' before the switch //pcRoot->insertChild(pcCoords,pcRoot->findChild(reinterpret_cast(pcModeSwitch))); // Annotation sets SoGroup* pcAnotRoot = new SoAnnotation(); SoDrawStyle *pcAnoStyle = new SoDrawStyle(); pcAnoStyle->style = SoDrawStyle::POINTS; pcAnoStyle->pointSize = 5; SoMaterial * pcAnoMaterial = new SoMaterial; pcAnoMaterial->diffuseColor.setValue(0,1,0); pcAnoMaterial->emissiveColor.setValue(0,1,0); pcAnotRoot->addChild(pcAnoMaterial); pcAnotRoot->addChild(pcAnoStyle); pcAnotRoot->addChild(pcAnoCoords); SoPointSet * pointset = new SoPointSet; pcAnotRoot->addChild(pointset); //pcHighlight->addChild(pcFaces); // flat SoGroup* pcFlatRoot = new SoGroup(); // face nodes pcFlatRoot->addChild(pcCoords); pcFlatRoot->addChild(pShapeHints); pcFlatRoot->addChild(pcShapeMaterial); pcFlatRoot->addChild(pcMatBinding); pcFlatRoot->addChild(pcFaces); pcFlatRoot->addChild(pcAnotRoot); addDisplayMaskMode(pcFlatRoot, "Flat"); // line SoLightModel* pcLightModel = new SoLightModel(); pcLightModel->model = SoLightModel::BASE_COLOR; SoGroup* pcWireRoot = new SoGroup(); pcWireRoot->addChild(pcCoords); pcWireRoot->addChild(pcDrawStyle); pcWireRoot->addChild(pcLightModel); SoBaseColor* color = new SoBaseColor(); color->rgb.setValue(0.0f,0.0f,0.0f); pcWireRoot->addChild(color); pcWireRoot->addChild(pcLines); addDisplayMaskMode(pcWireRoot, "Wireframe"); // Points SoGroup* pcPointsRoot = new SoSeparator(); pcPointsRoot->addChild(pcPointMaterial); pcPointsRoot->addChild(pcPointStyle); pcPointsRoot->addChild(pcCoords); pointset = new SoPointSet; pcPointsRoot->addChild(pointset); addDisplayMaskMode(pcPointsRoot, "Nodes"); // flat+line (Elements) SoPolygonOffset* offset = new SoPolygonOffset(); offset->styles = SoPolygonOffset::LINES; //offset->factor = 2.0f; //offset->units = 1.0f; SoGroup* pcFlatWireRoot = new SoSeparator(); // add the complete flat group (contains the coordinates) pcFlatWireRoot->addChild(pcFlatRoot); //pcFlatWireRoot->addChild(offset); // makes no differents..... // add the line nodes pcFlatWireRoot->addChild(pcDrawStyle); pcFlatWireRoot->addChild(pcLightModel); pcFlatWireRoot->addChild(color); pcFlatWireRoot->addChild(pcLines); addDisplayMaskMode(pcFlatWireRoot, "Elements"); // flat+line+Nodes (Elements&Nodes) SoGroup* pcElemNodesRoot = new SoSeparator(); // add the complete flat group (contains the coordinates) pcElemNodesRoot->addChild(pcFlatRoot); //pcElemNodesRoot->addChild(offset); // add the line nodes pcElemNodesRoot->addChild(pcDrawStyle); pcElemNodesRoot->addChild(pcLightModel); pcElemNodesRoot->addChild(color); pcElemNodesRoot->addChild(pcLines); // add the points nodes pcElemNodesRoot->addChild(pcPointMaterial); pcElemNodesRoot->addChild(pcPointStyle); pcElemNodesRoot->addChild(pcPointMaterial); pcElemNodesRoot->addChild(pointset); addDisplayMaskMode(pcElemNodesRoot, "Elements & Nodes"); } void ViewProviderFemMesh::setDisplayMode(const char* ModeName) { if (strcmp("Elements",ModeName)==0) setDisplayMaskMode("Elements"); else if (strcmp("Elements & Nodes",ModeName)==0) setDisplayMaskMode("Elements & Nodes"); else if (strcmp("Flat",ModeName)==0) setDisplayMaskMode("Flat"); else if (strcmp("Wireframe",ModeName)==0) setDisplayMaskMode("Wireframe"); else if (strcmp("Nodes",ModeName)==0) setDisplayMaskMode("Nodes"); ViewProviderGeometryObject::setDisplayMode( ModeName ); } std::vector ViewProviderFemMesh::getDisplayModes(void) const { std::vector StrList; StrList.push_back("Elements"); StrList.push_back("Elements & Nodes"); StrList.push_back("Flat"); StrList.push_back("Wireframe"); StrList.push_back("Nodes"); return StrList; } void ViewProviderFemMesh::updateData(const App::Property* prop) { if (prop->isDerivedFrom(Fem::PropertyFemMesh::getClassTypeId())) { ViewProviderFEMMeshBuilder builder; builder.createMesh(prop, pcCoords, pcFaces, pcLines,vFaceElementIdx,vNodeElementIdx, ShowInner.getValue()); } Gui::ViewProviderGeometryObject::updateData(prop); } void ViewProviderFemMesh::onChanged(const App::Property* prop) { if (prop == &PointSize) { pcPointStyle->pointSize = PointSize.getValue(); } else if (prop == &PointColor) { const App::Color& c = PointColor.getValue(); pcPointMaterial->diffuseColor.setValue(c.r,c.g,c.b); } else if (prop == &BackfaceCulling) { if(BackfaceCulling.getValue()){ pShapeHints->shapeType = SoShapeHints::SOLID; //pShapeHints->vertexOrdering = SoShapeHints::CLOCKWISE; }else{ pShapeHints->shapeType = SoShapeHints::UNKNOWN_SHAPE_TYPE; //pShapeHints->vertexOrdering = SoShapeHints::CLOCKWISE; } } else if (prop == &ShowInner) { // recalc mesh with new settings ViewProviderFEMMeshBuilder builder; builder.createMesh(&(dynamic_cast(this->pcObject)->FemMesh), pcCoords, pcFaces, pcLines,vFaceElementIdx,vNodeElementIdx, ShowInner.getValue()); } else if (prop == &LineWidth) { pcDrawStyle->lineWidth = LineWidth.getValue(); } else { ViewProviderGeometryObject::onChanged(prop); } } std::string ViewProviderFemMesh::getElement(const SoDetail* detail) const { std::stringstream str; if (detail) { if (detail->getTypeId() == SoFaceDetail::getClassTypeId()) { const SoFaceDetail* face_detail = static_cast(detail); unsigned long edx = vFaceElementIdx[face_detail->getFaceIndex()]; str << "Elem" << (edx>>3) << "F"<< (edx&7)+1; } //else if (detail->getTypeId() == SoLineDetail::getClassTypeId()) { // const SoLineDetail* line_detail = static_cast(detail); // int edge = line_detail->getLineIndex() + 1; // str << "Edge" << edge; //} else if (detail->getTypeId() == SoPointDetail::getClassTypeId()) { const SoPointDetail* point_detail = static_cast(detail); int vertex = vNodeElementIdx[point_detail->getCoordinateIndex()]; str << "Node" << vertex; } } return str.str(); } SoDetail* ViewProviderFemMesh::getDetail(const char* subelement) const { std::string element = subelement; std::string::size_type pos = element.find_first_of("0123456789"); int index = -1; if (pos != std::string::npos) { index = std::atoi(element.substr(pos).c_str()); element = element.substr(0,pos); } SoDetail* detail = 0; if (index < 0) return detail; if (element == "Elem") { detail = new SoFaceDetail(); static_cast(detail)->setPartIndex(index - 1); } //else if (element == "Edge") { // detail = new SoLineDetail(); // static_cast(detail)->setLineIndex(index - 1); //} //else if (element == "Vertex") { // detail = new SoPointDetail(); // static_cast(detail)->setCoordinateIndex(index + nodeset->startIndex.getValue() - 1); //} return detail; } std::vector ViewProviderFemMesh::getSelectionShape(const char* Element) const { return std::vector(); } void ViewProviderFemMesh::setHighlightNodes(const std::set& HighlightedNodes) { if(HighlightedNodes.size()){ const Fem::PropertyFemMesh* mesh = &(dynamic_cast(this->pcObject)->FemMesh); SMESHDS_Mesh* data = const_cast((dynamic_cast(this->pcObject)->FemMesh).getValue().getSMesh())->GetMeshDS(); pcAnoCoords->point.setNum(HighlightedNodes.size()); SbVec3f* verts = pcAnoCoords->point.startEditing(); int i=0; for(std::set::const_iterator it=HighlightedNodes.begin();it!=HighlightedNodes.end();++it,i++){ const SMDS_MeshNode *Node = data->FindNode(*it); verts[i].setValue((float)Node->X(),(float)Node->Y(),(float)Node->Z()); } pcAnoCoords->point.finishEditing(); }else{ pcAnoCoords->point.setNum(0); } } void ViewProviderFemMesh::resetHighlightNodes(void) { pcAnoCoords->point.setNum(0); } PyObject * ViewProviderFemMesh::getPyObject() { if (PythonObject.is(Py::_None())){ // ref counter is set to 1 PythonObject = Py::Object(new ViewProviderFemMeshPy(this),true); } return Py::new_reference_to(PythonObject); } void ViewProviderFemMesh::setColorByNodeId(const std::map &NodeColorMap) { } void ViewProviderFemMesh::resetColorByNodeId(void) { } // ---------------------------------------------------------------------------- void ViewProviderFEMMeshBuilder::buildNodes(const App::Property* prop, std::vector& nodes) const { SoCoordinate3 *pcPointsCoord=0; SoIndexedFaceSet *pcFaces=0; SoIndexedLineSet *pcLines=0; if (nodes.empty()) { pcPointsCoord = new SoCoordinate3(); nodes.push_back(pcPointsCoord); pcFaces = new SoIndexedFaceSet(); pcLines = new SoIndexedLineSet(); nodes.push_back(pcFaces); } else if (nodes.size() == 2) { if (nodes[0]->getTypeId() == SoCoordinate3::getClassTypeId()) pcPointsCoord = static_cast(nodes[0]); if (nodes[1]->getTypeId() == SoIndexedFaceSet::getClassTypeId()) pcFaces = static_cast(nodes[1]); } if (pcPointsCoord && pcFaces){ std::vector vFaceElementIdx; std::vector vNodeElementIdx; createMesh(prop, pcPointsCoord, pcFaces,pcLines,vFaceElementIdx,vNodeElementIdx); } } inline void insEdgeVec(std::map > &map, int n1, int n2) { if(n1 &vFaceElementIdx,std::vector &vNodeElementIdx, bool ShowInner) const { const Fem::PropertyFemMesh* mesh = static_cast(prop); SMESHDS_Mesh* data = const_cast(mesh->getValue().getSMesh())->GetMeshDS(); int numFaces = data->NbFaces(); int numNodes = data->NbNodes(); int numEdges = data->NbEdges(); if(numFaces+numNodes+numEdges == 0) return; Base::TimeInfo Start; Base::Console().Log("Start: ViewProviderFEMMeshBuilder::createMesh() =================================\n"); const SMDS_MeshInfo& info = data->GetMeshInfo(); int numNode = info.NbNodes(); int numTria = info.NbTriangles(); int numQuad = info.NbQuadrangles(); int numPoly = info.NbPolygons(); int numVolu = info.NbVolumes(); int numTetr = info.NbTetras(); int numHexa = info.NbHexas(); int numPyrd = info.NbPyramids(); int numPris = info.NbPrisms(); int numHedr = info.NbPolyhedrons(); bool ShowFaces = false; int numTries; if(ShowFaces) numTries = numTria+numQuad+numPoly+numTetr*4+numHexa*6+numPyrd*5+numPris*6; else numTries = numTetr*4+numHexa*6+numPyrd*5+numPris*6; std::vector facesHelper(numTries); Base::Console().Log(" %f: Start build up %i face helper\n",Base::TimeInfo::diffTimeF(Start,Base::TimeInfo()),facesHelper.size()); Base::BoundBox3d BndBox; int i=0; if(false){ SMDS_FaceIteratorPtr aFaceIter = data->facesIterator(); for (;aFaceIter->more();) { const SMDS_MeshFace* aFace = aFaceIter->next(); int num = aFace->NbNodes(); switch(num){ case 4:// quad face BndBox.Add(facesHelper[i++].set(4,aFace,aFace->GetID(),0,aFace->GetNode(0),aFace->GetNode(1),aFace->GetNode(2),aFace->GetNode(3))); break; //unknown case default: assert(0); } } } SMDS_VolumeIteratorPtr aVolIter = data->volumesIterator(); for (;aVolIter->more();) { const SMDS_MeshVolume* aVol = aVolIter->next(); int num = aVol->NbNodes(); switch(num){ // tet 4 element case 4: // face 1 BndBox.Add(facesHelper[i++].set(3,aVol,aVol->GetID(),1,aVol->GetNode(0),aVol->GetNode(1),aVol->GetNode(2))); // face 2 BndBox.Add(facesHelper[i++].set(3,aVol,aVol->GetID(),2,aVol->GetNode(0),aVol->GetNode(3),aVol->GetNode(1))); // face 3 BndBox.Add(facesHelper[i++].set(3,aVol,aVol->GetID(),3,aVol->GetNode(1),aVol->GetNode(3),aVol->GetNode(2))); // face 4 BndBox.Add(facesHelper[i++].set(3,aVol,aVol->GetID(),4,aVol->GetNode(2),aVol->GetNode(3),aVol->GetNode(0))); break; //unknown case case 8: // face 1 BndBox.Add(facesHelper[i++].set(4,aVol,aVol->GetID(),1,aVol->GetNode(0),aVol->GetNode(1),aVol->GetNode(2),aVol->GetNode(3))); // face 2 BndBox.Add(facesHelper[i++].set(4,aVol,aVol->GetID(),2,aVol->GetNode(4),aVol->GetNode(5),aVol->GetNode(6),aVol->GetNode(7))); // face 3 BndBox.Add(facesHelper[i++].set(4,aVol,aVol->GetID(),3,aVol->GetNode(0),aVol->GetNode(1),aVol->GetNode(4),aVol->GetNode(5))); // face 4 BndBox.Add(facesHelper[i++].set(4,aVol,aVol->GetID(),4,aVol->GetNode(1),aVol->GetNode(2),aVol->GetNode(5),aVol->GetNode(6))); // face 5 BndBox.Add(facesHelper[i++].set(4,aVol,aVol->GetID(),5,aVol->GetNode(2),aVol->GetNode(3),aVol->GetNode(6),aVol->GetNode(7))); // face 6 BndBox.Add(facesHelper[i++].set(4,aVol,aVol->GetID(),6,aVol->GetNode(0),aVol->GetNode(3),aVol->GetNode(4),aVol->GetNode(7))); break; //unknown case case 10: // face 1 BndBox.Add(facesHelper[i++].set(6,aVol,aVol->GetID(),1,aVol->GetNode(0),aVol->GetNode(1),aVol->GetNode(2),aVol->GetNode(4),aVol->GetNode(5),aVol->GetNode(6))); // face 2 BndBox.Add(facesHelper[i++].set(6,aVol,aVol->GetID(),2,aVol->GetNode(0),aVol->GetNode(3),aVol->GetNode(1),aVol->GetNode(7),aVol->GetNode(8),aVol->GetNode(4))); // face 3 BndBox.Add(facesHelper[i++].set(6,aVol,aVol->GetID(),3,aVol->GetNode(1),aVol->GetNode(3),aVol->GetNode(2),aVol->GetNode(8),aVol->GetNode(9),aVol->GetNode(5))); // face 4 BndBox.Add(facesHelper[i++].set(6,aVol,aVol->GetID(),4,aVol->GetNode(2),aVol->GetNode(3),aVol->GetNode(0),aVol->GetNode(9),aVol->GetNode(7),aVol->GetNode(6))); break; //unknown case default: assert(0); } } int FaceSize = facesHelper.size(); if( FaceSize < 5000){ Base::Console().Log(" %f: Start eliminate internal faces SIMPLE\n",Base::TimeInfo::diffTimeF(Start,Base::TimeInfo())); // search for double (inside) faces and hide them if(!ShowInner){ for(int l=0; l< FaceSize;l++){ if(! facesHelper[l].hide){ for(int i=l+1; i Grid(NbrX*NbrY*NbrZ); unsigned int iX = 0; unsigned int iY = 0; unsigned int iZ = 0; for(int l=0; l< FaceSize;l++){ Base::Vector3d point(facesHelper[l].getFirstNodePoint()); double x = (point.x - Xmin) / Xln; double y = (point.y - Ymin) / Yln; double z = (point.z - Zmin) / Zln; iX = x; iY = y; iZ = z; if(iX >= NbrX || iY >= NbrY || iZ >= NbrZ) Base::Console().Log(" Outof range!\n"); Grid[iX + iY*NbrX + iZ*NbrX*NbrY].push_back(&facesHelper[l]); } unsigned int max =0, avg = 0; for(std::vector::iterator it=Grid.begin();it!=Grid.end();++it){ for(unsigned int l=0; l< it->size();l++){ if(! it->operator[](l)->hide){ for(unsigned int i=l+1; isize(); i++){ if(it->operator[](l)->isSameFace(*(it->operator[](i))) ){ break; } } } } if(it->size() > max)max=it->size(); avg += it->size(); } avg = avg/Grid.size(); Base::Console().Log(" VoxelSize: Max:%i ,Average:%i\n",max,avg); } //if( FaceSize < 1000) Base::Console().Log(" %f: Start build up node map\n",Base::TimeInfo::diffTimeF(Start,Base::TimeInfo())); // sort out double nodes and build up index map std::map mapNodeIndex; for(int l=0; l< FaceSize;l++){ if(!facesHelper[l].hide) for(int i=0; i<8;i++) if(facesHelper[l].Nodes[i]) mapNodeIndex[facesHelper[l].Nodes[i]]=0; else break; } Base::Console().Log(" %f: Start set point vector\n",Base::TimeInfo::diffTimeF(Start,Base::TimeInfo())); // set the point coordinates coords->point.setNum(mapNodeIndex.size()); vNodeElementIdx.resize(mapNodeIndex.size() ); std::map::iterator it= mapNodeIndex.begin(); SbVec3f* verts = coords->point.startEditing(); for (int i=0;it != mapNodeIndex.end() ;++it,i++) { verts[i].setValue((float)it->first->X(),(float)it->first->Y(),(float)it->first->Z()); it->second = i; // set selection idx vNodeElementIdx[i] = it->first->GetID(); } coords->point.finishEditing(); // count triangle size int triangleCount=0; for(int l=0; l< FaceSize;l++) if(! facesHelper[l].hide) switch(facesHelper[l].Size){ case 3:triangleCount++ ;break; case 4:triangleCount+=2 ;break; case 6:triangleCount+=4 ;break; default: assert(0); } // edge map collect and sort edges of the faces to be shown. std::map > EdgeMap; Base::Console().Log(" %f: Start build up triangle vector\n",Base::TimeInfo::diffTimeF(Start,Base::TimeInfo())); // set the triangle face indices faces->coordIndex.setNum(4*triangleCount); vFaceElementIdx.resize(triangleCount); int index=0,indexIdx=0; int32_t* indices = faces->coordIndex.startEditing(); // iterate all element faces, allways assure CLOCKWISE triangle ordering to allow backface culling for(int l=0; l< FaceSize;l++){ if(! facesHelper[l].hide){ switch( facesHelper[l].Element->NbNodes()){ case 4: // Tet 4 switch(facesHelper[l].FaceNo){ case 0: { // case for quad faces int nIdx0 = mapNodeIndex[facesHelper[l].Element->GetNode(0)]; int nIdx1 = mapNodeIndex[facesHelper[l].Element->GetNode(1)]; int nIdx2 = mapNodeIndex[facesHelper[l].Element->GetNode(2)]; int nIdx3 = mapNodeIndex[facesHelper[l].Element->GetNode(3)]; indices[index++] = nIdx2; indices[index++] = nIdx0; indices[index++] = nIdx1; indices[index++] = SO_END_FACE_INDEX; insEdgeVec(EdgeMap,nIdx0,nIdx1); insEdgeVec(EdgeMap,nIdx1,nIdx2); vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber,0); indices[index++] = nIdx3; indices[index++] = nIdx0; indices[index++] = nIdx2; indices[index++] = SO_END_FACE_INDEX; insEdgeVec(EdgeMap,nIdx2,nIdx3); insEdgeVec(EdgeMap,nIdx3,nIdx0); vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber,0); break; } case 1: { // face 1 of Tet10 int nIdx0 = mapNodeIndex[facesHelper[l].Element->GetNode(0)]; int nIdx1 = mapNodeIndex[facesHelper[l].Element->GetNode(1)]; int nIdx2 = mapNodeIndex[facesHelper[l].Element->GetNode(2)]; indices[index++] = nIdx2; indices[index++] = nIdx0; indices[index++] = nIdx1; indices[index++] = SO_END_FACE_INDEX; insEdgeVec(EdgeMap,nIdx0,nIdx1); insEdgeVec(EdgeMap,nIdx0,nIdx2); insEdgeVec(EdgeMap,nIdx1,nIdx2); vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber,0); break; } case 2: { int nIdx0 = mapNodeIndex[facesHelper[l].Element->GetNode(0)]; int nIdx1 = mapNodeIndex[facesHelper[l].Element->GetNode(1)]; int nIdx3 = mapNodeIndex[facesHelper[l].Element->GetNode(3)]; indices[index++] = nIdx1; indices[index++] = nIdx0; indices[index++] = nIdx3; indices[index++] = SO_END_FACE_INDEX; insEdgeVec(EdgeMap,nIdx0,nIdx1); insEdgeVec(EdgeMap,nIdx0,nIdx3); insEdgeVec(EdgeMap,nIdx1,nIdx3); vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber,1); break; } case 3: { int nIdx1 = mapNodeIndex[facesHelper[l].Element->GetNode(1)]; int nIdx2 = mapNodeIndex[facesHelper[l].Element->GetNode(2)]; int nIdx3 = mapNodeIndex[facesHelper[l].Element->GetNode(3)]; indices[index++] = nIdx2; indices[index++] = nIdx1; indices[index++] = nIdx3; indices[index++] = SO_END_FACE_INDEX; insEdgeVec(EdgeMap,nIdx1,nIdx2); insEdgeVec(EdgeMap,nIdx1,nIdx3); insEdgeVec(EdgeMap,nIdx2,nIdx3); vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber,2); break; } case 4: { int nIdx0 = mapNodeIndex[facesHelper[l].Element->GetNode(0)]; int nIdx2 = mapNodeIndex[facesHelper[l].Element->GetNode(2)]; int nIdx3 = mapNodeIndex[facesHelper[l].Element->GetNode(3)]; indices[index++] = nIdx3; indices[index++] = nIdx0; indices[index++] = nIdx2; indices[index++] = SO_END_FACE_INDEX; insEdgeVec(EdgeMap,nIdx0,nIdx2); insEdgeVec(EdgeMap,nIdx0,nIdx3); insEdgeVec(EdgeMap,nIdx3,nIdx2); vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber,3); break; } default: assert(0); } break; case 8: // Hex 8 switch(facesHelper[l].FaceNo){ case 1: { int nIdx0 = mapNodeIndex[facesHelper[l].Element->GetNode(0)]; int nIdx1 = mapNodeIndex[facesHelper[l].Element->GetNode(1)]; int nIdx2 = mapNodeIndex[facesHelper[l].Element->GetNode(2)]; int nIdx3 = mapNodeIndex[facesHelper[l].Element->GetNode(3)]; indices[index++] = nIdx0; indices[index++] = nIdx1; indices[index++] = nIdx3; indices[index++] = SO_END_FACE_INDEX; insEdgeVec(EdgeMap,nIdx0,nIdx1); insEdgeVec(EdgeMap,nIdx0,nIdx3); vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber,0); indices[index++] = nIdx2; indices[index++] = nIdx3; indices[index++] = nIdx1; indices[index++] = SO_END_FACE_INDEX; insEdgeVec(EdgeMap,nIdx2,nIdx1); insEdgeVec(EdgeMap,nIdx2,nIdx3); vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber,0); break; } case 2: { int nIdx4 = mapNodeIndex[facesHelper[l].Element->GetNode(4)]; int nIdx5 = mapNodeIndex[facesHelper[l].Element->GetNode(5)]; int nIdx6 = mapNodeIndex[facesHelper[l].Element->GetNode(6)]; int nIdx7 = mapNodeIndex[facesHelper[l].Element->GetNode(7)]; indices[index++] = nIdx5; indices[index++] = nIdx4; indices[index++] = nIdx7; indices[index++] = SO_END_FACE_INDEX; insEdgeVec(EdgeMap,nIdx4,nIdx5); insEdgeVec(EdgeMap,nIdx4,nIdx7); vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber,1); indices[index++] = nIdx6; indices[index++] = nIdx5; indices[index++] = nIdx7; indices[index++] = SO_END_FACE_INDEX; insEdgeVec(EdgeMap,nIdx6,nIdx5); insEdgeVec(EdgeMap,nIdx6,nIdx7); vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber,1); break; } case 3: { int nIdx0 = mapNodeIndex[facesHelper[l].Element->GetNode(0)]; int nIdx1 = mapNodeIndex[facesHelper[l].Element->GetNode(1)]; int nIdx4 = mapNodeIndex[facesHelper[l].Element->GetNode(4)]; int nIdx5 = mapNodeIndex[facesHelper[l].Element->GetNode(5)]; indices[index++] = nIdx1; indices[index++] = nIdx0; indices[index++] = nIdx5; indices[index++] = SO_END_FACE_INDEX; insEdgeVec(EdgeMap,nIdx1,nIdx0); insEdgeVec(EdgeMap,nIdx1,nIdx5); vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber,2); indices[index++] = nIdx5; indices[index++] = nIdx0; indices[index++] = nIdx4; indices[index++] = SO_END_FACE_INDEX; insEdgeVec(EdgeMap,nIdx4,nIdx0); insEdgeVec(EdgeMap,nIdx4,nIdx5); vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber,2); break; } case 4: { int nIdx1 = mapNodeIndex[facesHelper[l].Element->GetNode(1)]; int nIdx2 = mapNodeIndex[facesHelper[l].Element->GetNode(2)]; int nIdx5 = mapNodeIndex[facesHelper[l].Element->GetNode(5)]; int nIdx6 = mapNodeIndex[facesHelper[l].Element->GetNode(6)]; indices[index++] = nIdx1; indices[index++] = nIdx5; indices[index++] = nIdx2; indices[index++] = SO_END_FACE_INDEX; insEdgeVec(EdgeMap,nIdx1,nIdx5); insEdgeVec(EdgeMap,nIdx1,nIdx2); vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber,3); indices[index++] = nIdx2; indices[index++] = nIdx5; indices[index++] = nIdx6; indices[index++] = SO_END_FACE_INDEX; insEdgeVec(EdgeMap,nIdx6,nIdx5); insEdgeVec(EdgeMap,nIdx6,nIdx2); vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber,3); break; } case 5: { int nIdx2 = mapNodeIndex[facesHelper[l].Element->GetNode(2)]; int nIdx3 = mapNodeIndex[facesHelper[l].Element->GetNode(3)]; int nIdx6 = mapNodeIndex[facesHelper[l].Element->GetNode(6)]; int nIdx7 = mapNodeIndex[facesHelper[l].Element->GetNode(7)]; indices[index++] = nIdx3; indices[index++] = nIdx2; indices[index++] = nIdx7; indices[index++] = SO_END_FACE_INDEX; insEdgeVec(EdgeMap,nIdx3,nIdx2); insEdgeVec(EdgeMap,nIdx3,nIdx7); vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber,4); indices[index++] = nIdx7; indices[index++] = nIdx2; indices[index++] = nIdx6; indices[index++] = SO_END_FACE_INDEX; insEdgeVec(EdgeMap,nIdx6,nIdx2); insEdgeVec(EdgeMap,nIdx6,nIdx7); vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber,4); break; } case 6: { int nIdx0 = mapNodeIndex[facesHelper[l].Element->GetNode(0)]; int nIdx3 = mapNodeIndex[facesHelper[l].Element->GetNode(3)]; int nIdx4 = mapNodeIndex[facesHelper[l].Element->GetNode(4)]; int nIdx7 = mapNodeIndex[facesHelper[l].Element->GetNode(7)]; indices[index++] = nIdx0; indices[index++] = nIdx3; indices[index++] = nIdx4; indices[index++] = SO_END_FACE_INDEX; insEdgeVec(EdgeMap,nIdx0,nIdx4); insEdgeVec(EdgeMap,nIdx0,nIdx3); vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber,5); indices[index++] = nIdx4; indices[index++] = nIdx3; indices[index++] = nIdx7; indices[index++] = SO_END_FACE_INDEX; insEdgeVec(EdgeMap,nIdx7,nIdx4); insEdgeVec(EdgeMap,nIdx7,nIdx3); vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber,5); break; } } break; case 10: // Tet 10 switch(facesHelper[l].FaceNo){ case 1: { // element face number 1 // prefeche all node indexes of this face int nIdx0 = mapNodeIndex[facesHelper[l].Element->GetNode(0)]; int nIdx1 = mapNodeIndex[facesHelper[l].Element->GetNode(1)]; int nIdx2 = mapNodeIndex[facesHelper[l].Element->GetNode(2)]; int nIdx4 = mapNodeIndex[facesHelper[l].Element->GetNode(4)]; int nIdx5 = mapNodeIndex[facesHelper[l].Element->GetNode(5)]; int nIdx6 = mapNodeIndex[facesHelper[l].Element->GetNode(6)]; // create triangle number 1 ---------------------------------------------- // fill in the node indexes in CLOCKWISE order indices[index++] = nIdx6; indices[index++] = nIdx0; indices[index++] = nIdx4; indices[index++] = SO_END_FACE_INDEX; // add the two edge segments for that triangle insEdgeVec(EdgeMap,nIdx0,nIdx6); insEdgeVec(EdgeMap,nIdx0,nIdx4); // rember the element and face number for that triangle vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber,0); // create triangle number 2 ---------------------------------------------- indices[index++] = nIdx2; indices[index++] = nIdx6; indices[index++] = nIdx5; indices[index++] = SO_END_FACE_INDEX; insEdgeVec(EdgeMap,nIdx2,nIdx6); insEdgeVec(EdgeMap,nIdx2,nIdx5); vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber,0); // create triangle number 3 ---------------------------------------------- indices[index++] = nIdx1; indices[index++] = nIdx5; indices[index++] = nIdx4; indices[index++] = SO_END_FACE_INDEX; insEdgeVec(EdgeMap,nIdx1,nIdx5); insEdgeVec(EdgeMap,nIdx1,nIdx4); vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber,0); // create triangle number 4 ---------------------------------------------- indices[index++] = nIdx6; indices[index++] = nIdx4; indices[index++] = nIdx5; indices[index++] = SO_END_FACE_INDEX; // this triangle has no edge (inner triangle). break; } case 2: { int nIdx0 = mapNodeIndex[facesHelper[l].Element->GetNode(0)]; int nIdx1 = mapNodeIndex[facesHelper[l].Element->GetNode(1)]; int nIdx3 = mapNodeIndex[facesHelper[l].Element->GetNode(3)]; int nIdx4 = mapNodeIndex[facesHelper[l].Element->GetNode(4)]; int nIdx7 = mapNodeIndex[facesHelper[l].Element->GetNode(7)]; int nIdx8 = mapNodeIndex[facesHelper[l].Element->GetNode(8)]; indices[index++] = nIdx4; indices[index++] = nIdx0; indices[index++] = nIdx7; indices[index++] = SO_END_FACE_INDEX; insEdgeVec(EdgeMap,nIdx0,nIdx7); insEdgeVec(EdgeMap,nIdx0,nIdx4); vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber,1); indices[index++] = nIdx1; indices[index++] = nIdx4; indices[index++] = nIdx8; indices[index++] = SO_END_FACE_INDEX; insEdgeVec(EdgeMap,nIdx1,nIdx8); insEdgeVec(EdgeMap,nIdx1,nIdx4); vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber,1); indices[index++] = nIdx3; indices[index++] = nIdx8; indices[index++] = nIdx7; indices[index++] = SO_END_FACE_INDEX; insEdgeVec(EdgeMap,nIdx3,nIdx7); insEdgeVec(EdgeMap,nIdx3,nIdx8); vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber,1); indices[index++] = nIdx8; indices[index++] = nIdx4; indices[index++] = nIdx7; indices[index++] = SO_END_FACE_INDEX; vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber,1); break; } case 3: { int nIdx1 = mapNodeIndex[facesHelper[l].Element->GetNode(1)]; int nIdx2 = mapNodeIndex[facesHelper[l].Element->GetNode(2)]; int nIdx3 = mapNodeIndex[facesHelper[l].Element->GetNode(3)]; int nIdx5 = mapNodeIndex[facesHelper[l].Element->GetNode(5)]; int nIdx8 = mapNodeIndex[facesHelper[l].Element->GetNode(8)]; int nIdx9 = mapNodeIndex[facesHelper[l].Element->GetNode(9)]; indices[index++] = nIdx5; indices[index++] = nIdx1; indices[index++] = nIdx8; indices[index++] = SO_END_FACE_INDEX; insEdgeVec(EdgeMap,nIdx1,nIdx5); insEdgeVec(EdgeMap,nIdx1,nIdx8); vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber,2); indices[index++] = nIdx2; indices[index++] = nIdx5; indices[index++] = nIdx9; indices[index++] = SO_END_FACE_INDEX; insEdgeVec(EdgeMap,nIdx2,nIdx5); insEdgeVec(EdgeMap,nIdx2,nIdx9); vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber,2); indices[index++] = nIdx3; indices[index++] = nIdx9; indices[index++] = nIdx8; indices[index++] = SO_END_FACE_INDEX; insEdgeVec(EdgeMap,nIdx3,nIdx9); insEdgeVec(EdgeMap,nIdx3,nIdx8); vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber,2); indices[index++] = nIdx9; indices[index++] = nIdx5; indices[index++] = nIdx8; indices[index++] = SO_END_FACE_INDEX; vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber,2); break; } case 4: { int nIdx0 = mapNodeIndex[facesHelper[l].Element->GetNode(0)]; int nIdx2 = mapNodeIndex[facesHelper[l].Element->GetNode(2)]; int nIdx3 = mapNodeIndex[facesHelper[l].Element->GetNode(3)]; int nIdx6 = mapNodeIndex[facesHelper[l].Element->GetNode(6)]; int nIdx7 = mapNodeIndex[facesHelper[l].Element->GetNode(7)]; int nIdx9 = mapNodeIndex[facesHelper[l].Element->GetNode(9)]; indices[index++] = nIdx0; indices[index++] = nIdx6; indices[index++] = nIdx7; indices[index++] = SO_END_FACE_INDEX; insEdgeVec(EdgeMap,nIdx0,nIdx6); insEdgeVec(EdgeMap,nIdx0,nIdx7); vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber,3); indices[index++] = nIdx6; indices[index++] = nIdx2; indices[index++] = nIdx9; indices[index++] = SO_END_FACE_INDEX; insEdgeVec(EdgeMap,nIdx2,nIdx6); insEdgeVec(EdgeMap,nIdx2,nIdx9); vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber,3); indices[index++] = nIdx7; indices[index++] = nIdx9; indices[index++] = nIdx3; indices[index++] = SO_END_FACE_INDEX; insEdgeVec(EdgeMap,nIdx3,nIdx9); insEdgeVec(EdgeMap,nIdx3,nIdx7); vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber,3); indices[index++] = nIdx7; indices[index++] = nIdx6; indices[index++] = nIdx9; indices[index++] = SO_END_FACE_INDEX; vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber,3); break; } default: assert(0); } break; default:assert(0); // not implemented node } } } faces->coordIndex.finishEditing(); Base::Console().Log(" %f: Start build up edge vector\n",Base::TimeInfo::diffTimeF(Start,Base::TimeInfo())); // std::map > EdgeMap; // count edges int EdgeSize = 0; for(std::map >::const_iterator it= EdgeMap.begin();it!= EdgeMap.end();++it) EdgeSize += it->second.size(); // set the triangle face indices lines->coordIndex.setNum(3*EdgeSize); index=0; indices = lines->coordIndex.startEditing(); for(std::map >::const_iterator it= EdgeMap.begin();it!= EdgeMap.end();++it){ for(std::set::const_iterator it2=it->second.begin();it2!=it->second.end();++it2){ indices[index++] = it->first; indices[index++] = *it2; indices[index++] = -1; } } lines->coordIndex.finishEditing(); Base::Console().Log(" NumEdges:%i\n",EdgeSize); Base::Console().Log(" %f: Finish =========================================================\n",Base::TimeInfo::diffTimeF(Start,Base::TimeInfo())); }