add shell and beam support to FEM mesh ViewProvider

This commit is contained in:
jriegel
2015-05-19 21:42:36 +02:00
parent 4ae424b44a
commit aa142250e0
2 changed files with 219 additions and 82 deletions

View File

@@ -176,7 +176,9 @@ ViewProviderFemMesh::ViewProviderFemMesh()
ShapeColor.setValue(App::Color(1.0f,0.7f,0.0f));
ADD_PROPERTY(BackfaceCulling,(true));
ADD_PROPERTY(ShowInner, (false));
ADD_PROPERTY(ShowInner, (false));
onlyEdges = false;
pcDrawStyle = new SoDrawStyle();
pcDrawStyle->ref();
@@ -364,7 +366,7 @@ void ViewProviderFemMesh::updateData(const App::Property* prop)
ViewProviderFEMMeshBuilder builder;
resetColorByNodeId();
resetDisplacementByNodeId();
builder.createMesh(prop, pcCoords, pcFaces, pcLines,vFaceElementIdx,vNodeElementIdx, ShowInner.getValue());
builder.createMesh(prop, pcCoords, pcFaces, pcLines, vFaceElementIdx, vNodeElementIdx, onlyEdges, ShowInner.getValue());
}
Gui::ViewProviderGeometryObject::updateData(prop);
}
@@ -387,10 +389,10 @@ void ViewProviderFemMesh::onChanged(const App::Property* prop)
//pShapeHints->vertexOrdering = SoShapeHints::CLOCKWISE;
}
}
else if (prop == &ShowInner) {
else if (prop == &ShowInner ) {
// recalc mesh with new settings
ViewProviderFEMMeshBuilder builder;
builder.createMesh(&(dynamic_cast<Fem::FemMeshObject*>(this->pcObject)->FemMesh), pcCoords, pcFaces, pcLines,vFaceElementIdx,vNodeElementIdx, ShowInner.getValue());
builder.createMesh(&(dynamic_cast<Fem::FemMeshObject*>(this->pcObject)->FemMesh), pcCoords, pcFaces, pcLines, vFaceElementIdx, vNodeElementIdx, onlyEdges, ShowInner.getValue());
}
else if (prop == &LineWidth) {
pcDrawStyle->lineWidth = LineWidth.getValue();
@@ -410,11 +412,12 @@ std::string ViewProviderFemMesh::getElement(const SoDetail* detail) const
str << "Elem" << (edx>>3) << "F"<< (edx&7)+1;
}
//else if (detail->getTypeId() == SoLineDetail::getClassTypeId()) {
// const SoLineDetail* line_detail = static_cast<const SoLineDetail*>(detail);
// int edge = line_detail->getLineIndex() + 1;
// str << "Edge" << edge;
//}
// trigger on edges only if edge only mesh, otherwise you only hit edges an never faces....
else if (onlyEdges && detail->getTypeId() == SoLineDetail::getClassTypeId()) {
const SoLineDetail* line_detail = static_cast<const SoLineDetail*>(detail);
int edge = line_detail->getLineIndex() + 1;
str << "Edge" << edge;
}
else if (detail->getTypeId() == SoPointDetail::getClassTypeId()) {
const SoPointDetail* point_detail = static_cast<const SoPointDetail*>(detail);
int idx = point_detail->getCoordinateIndex();
@@ -683,7 +686,8 @@ void ViewProviderFEMMeshBuilder::buildNodes(const App::Property* prop, std::vect
if (pcPointsCoord && pcFaces){
std::vector<unsigned long> vFaceElementIdx;
std::vector<unsigned long> vNodeElementIdx;
createMesh(prop, pcPointsCoord, pcFaces,pcLines,vFaceElementIdx,vNodeElementIdx);
bool onlyEdges;
createMesh(prop, pcPointsCoord, pcFaces,pcLines,vFaceElementIdx,vNodeElementIdx,onlyEdges,false);
}
}
@@ -703,7 +707,14 @@ inline unsigned long ElemFold(unsigned long Element,unsigned long FaceNbr)
return t2;
}
void ViewProviderFEMMeshBuilder::createMesh(const App::Property* prop, SoCoordinate3* coords, SoIndexedFaceSet* faces, SoIndexedLineSet* lines,std::vector<unsigned long> &vFaceElementIdx,std::vector<unsigned long> &vNodeElementIdx, bool ShowInner) const
void ViewProviderFEMMeshBuilder::createMesh(const App::Property* prop,
SoCoordinate3* coords,
SoIndexedFaceSet* faces,
SoIndexedLineSet* lines,
std::vector<unsigned long> &vFaceElementIdx,
std::vector<unsigned long> &vNodeElementIdx,
bool &onlyEdges,
bool ShowInner) const
{
const Fem::PropertyFemMesh* mesh = static_cast<const Fem::PropertyFemMesh*>(prop);
@@ -719,25 +730,31 @@ void ViewProviderFEMMeshBuilder::createMesh(const App::Property* prop, SoCoordin
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 numVolu = info.NbVolumes();
int numTetr = info.NbTetras();
int numHexa = info.NbHexas();
int numPyrd = info.NbPyramids();
int numPris = info.NbPrisms();
//int numHedr = info.NbPolyhedrons();
int numHedr = info.NbPolyhedrons();
bool ShowFaces = false;
bool ShowFaces = (numFaces >0 && numVolu == 0);
int numTries;
if(ShowFaces)
numTries = numTria+numQuad+numPoly+numTetr*4+numHexa*6+numPyrd*5+numPris*6;
numTries = numTria+numQuad/*+numPoly*/+numTetr*4+numHexa*6+numPyrd*5+numPris*6;
else
numTries = numTetr*4+numHexa*6+numPyrd*5+numPris*6;
// corner case only edges (Beams) in the mesh. This need some special cases in building up visual
onlyEdges = false;
if (numFaces <= 0 && numVolu <= 0 && numEdges > 0){
onlyEdges = true;
}
std::vector<FemFace> facesHelper(numTries);
@@ -746,7 +763,7 @@ void ViewProviderFEMMeshBuilder::createMesh(const App::Property* prop, SoCoordin
int i=0;
if(false){
if (ShowFaces){
SMDS_FaceIteratorPtr aFaceIter = data->facesIterator();
for (;aFaceIter->more();) {
const SMDS_MeshFace* aFace = aFaceIter->next();
@@ -754,65 +771,73 @@ void ViewProviderFEMMeshBuilder::createMesh(const App::Property* prop, SoCoordin
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;
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;
case 3:// tria face
BndBox.Add(facesHelper[i++].set(3, aFace, aFace->GetID(), 0, aFace->GetNode(0), aFace->GetNode(1), aFace->GetNode(2)));
break;
case 6:// tria face with 6 nodes
BndBox.Add(facesHelper[i++].set(6, aFace, aFace->GetID(), 0, aFace->GetNode(0), aFace->GetNode(1), aFace->GetNode(2), aFace->GetNode(3), aFace->GetNode(4), aFace->GetNode(5)));
break;
//unknown case
default: assert(0);
}
}
}
else{
SMDS_VolumeIteratorPtr aVolIter = data->volumesIterator();
for (;aVolIter->more();) {
const SMDS_MeshVolume* aVol = aVolIter->next();
int num = aVol->NbNodes();
// iterate all volumes
SMDS_VolumeIteratorPtr aVolIter = data->volumesIterator();
for (; aVolIter->more();) {
const SMDS_MeshVolume* aVol = aVolIter->next();
switch(num){
// tet 4 element
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)));
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)));
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)));
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)));
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)));
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)));
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)));
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)));
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)));
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)));
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)));
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)));
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)));
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)));
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();
@@ -900,13 +925,29 @@ void ViewProviderFEMMeshBuilder::createMesh(const App::Property* prop, SoCoordin
// sort out double nodes and build up index map
std::map<const SMDS_MeshNode*, int> 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;
// handling the corner case beams only, means no faces/triangles only nodes and edges
if (onlyEdges){
SMDS_EdgeIteratorPtr aEdgeIte = data->edgesIterator();
for (; aEdgeIte->more();) {
const SMDS_MeshEdge* aEdge = aEdgeIte->next();
int num = aEdge->NbNodes();
for (int i = 0; i < num; i++) {
mapNodeIndex[aEdge->GetNode(i)] = 0;
}
}
}else{
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;
}
}
}
}
@@ -929,18 +970,45 @@ void ViewProviderFEMMeshBuilder::createMesh(const App::Property* prop, SoCoordin
// 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);
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<int,std::set<int> > EdgeMap;
// handling the corner case beams only, means no faces/triangles only nodes and edges
if (onlyEdges){
SMDS_EdgeIteratorPtr aEdgeIte = data->edgesIterator();
for (; aEdgeIte->more();) {
const SMDS_MeshEdge* aEdge = aEdgeIte->next();
int num = aEdge->NbNodes();
switch (num){
case 2: { // case for Segment element
int nIdx0 = mapNodeIndex[aEdge->GetNode(0)];
int nIdx1 = mapNodeIndex[aEdge->GetNode(1)];
insEdgeVec(EdgeMap, nIdx0, nIdx1);
break;
}
case 3: { // case for Segment element
int nIdx0 = mapNodeIndex[aEdge->GetNode(0)];
int nIdx1 = mapNodeIndex[aEdge->GetNode(1)];
int nIdx2 = mapNodeIndex[aEdge->GetNode(2)];
insEdgeVec(EdgeMap, nIdx0, nIdx1);
insEdgeVec(EdgeMap, nIdx1, nIdx2);
break;
}
}
}
}
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);
@@ -951,29 +1019,49 @@ void ViewProviderFEMMeshBuilder::createMesh(const App::Property* prop, SoCoordin
for(int l=0; l< FaceSize;l++){
if(! facesHelper[l].hide){
switch( facesHelper[l].Element->NbNodes()){
case 3: // Face 3
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)];
indices[index++] = nIdx2;
indices[index++] = nIdx0;
indices[index++] = nIdx1;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx0, nIdx1);
insEdgeVec(EdgeMap, nIdx1, nIdx2);
insEdgeVec(EdgeMap, nIdx2, nIdx0);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 0);
break; }
default: assert(0);
}
break;
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
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)];
@@ -1029,6 +1117,52 @@ void ViewProviderFEMMeshBuilder::createMesh(const App::Property* prop, SoCoordin
}
break;
case 6: // face 6
switch (facesHelper[l].FaceNo){
case 0: { // element face number 0
// 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 nIdx3 = mapNodeIndex[facesHelper[l].Element->GetNode(3)];
int nIdx4 = mapNodeIndex[facesHelper[l].Element->GetNode(4)];
int nIdx5 = mapNodeIndex[facesHelper[l].Element->GetNode(5)];
// create triangle number 1 ----------------------------------------------
// fill in the node indexes in CLOCKWISE order
indices[index++] = nIdx0;
indices[index++] = nIdx3;
indices[index++] = nIdx5;
indices[index++] = SO_END_FACE_INDEX;
// add the two edge segments for that triangle
insEdgeVec(EdgeMap, nIdx0, nIdx3);
insEdgeVec(EdgeMap, nIdx0, nIdx5);
// rember the element and face number for that triangle
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 0);
// create triangle number 2 ----------------------------------------------
indices[index++] = nIdx3;
indices[index++] = nIdx1;
indices[index++] = nIdx4;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx3, nIdx1);
insEdgeVec(EdgeMap, nIdx1, nIdx4);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 0);
// create triangle number 3 ----------------------------------------------
indices[index++] = nIdx4;
indices[index++] = nIdx2;
indices[index++] = nIdx5;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx4, nIdx2);
insEdgeVec(EdgeMap, nIdx2, nIdx5);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 0);
// create triangle number 4 ----------------------------------------------
indices[index++] = nIdx5;
indices[index++] = nIdx3;
indices[index++] = nIdx4;
indices[index++] = SO_END_FACE_INDEX;
// this triangle has no edge (inner triangle).
break; }
break;
}
case 8: // Hex 8
switch(facesHelper[l].FaceNo){
case 1: {

View File

@@ -51,8 +51,9 @@ public:
SoIndexedLineSet*,
std::vector<unsigned long>&,
std::vector<unsigned long>&,
bool ShowInner=false
) const;
bool &edgeOnly,
bool ShowInner
) const;
};
class FemGuiExport ViewProviderFemMesh : public Gui::ViewProviderGeometryObject
@@ -157,6 +158,8 @@ protected:
SoCoordinate3 * pcAnoCoords;
SoIndexedFaceSet * pcFaces;
SoIndexedLineSet * pcLines;
bool onlyEdges;
};
} //namespace FemGui