Implementing Visual for FEM mesh higher degrees

- Tet10
- Add interface to insert higher degree nodes
This commit is contained in:
jriegel
2013-02-17 15:38:14 +01:00
parent 1c9fe432f7
commit 82905f7be2
4 changed files with 526 additions and 55 deletions

View File

@@ -57,9 +57,110 @@
#include <SMESH_Mesh.hxx>
#include <SMESHDS_Mesh.hxx>
#include <SMDSAbs_ElementType.hxx>
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;
void 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);
};
void 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.
}
}
}
};
bool FemFace::isSameFace (FemFace &face)
{
// the same element can not have the same face
if(face.ElementNumber == ElementNumber)
return false;
if(face.Size == Size){
// 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;
}
}else{
// TODO: normaly no valid net
// // if the size is not the same test if the nodes are a subset
// bool breakIt = false;
//
// if(Size < face.Size){
// for(int i=0; i<Size;i++){
// int j;
//for(j=0; j< face.Size ;j++)
// if(Nodes[i] == face.Nodes[j])
// break;
// if(j==face.Size) return false;
// }
// hide = true;
// return true;
// }else{
// return false;
// }
// assert(0);
}
};
PROPERTY_SOURCE(FemGui::ViewProviderFemMesh, Gui::ViewProviderGeometryObject)
App::PropertyFloatConstraint::Constraints ViewProviderFemMesh::floatRange = {1.0f,64.0f,1.0f};
@@ -77,18 +178,20 @@ ViewProviderFemMesh::ViewProviderFemMesh()
ADD_PROPERTY(PointColor,(mat.diffuseColor));
ADD_PROPERTY(PointSize,(2.0f));
PointSize.setConstraints(&floatRange);
ADD_PROPERTY(LineWidth,(1.0f));
ADD_PROPERTY(LineWidth,(4.0f));
LineWidth.setConstraints(&floatRange);
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::UNKNOWN_SHAPE_TYPE;
pShapeHints->vertexOrdering = SoShapeHints::UNKNOWN_ORDERING;
pShapeHints->vertexOrdering = SoShapeHints::COUNTERCLOCKWISE;
pShapeHints->shapeType = SoShapeHints::SOLID;
pShapeHints->vertexOrdering = SoShapeHints::CLOCKWISE;
pShapeHints->ref();
pcMatBinding = new SoMaterialBinding;
@@ -200,7 +303,7 @@ void ViewProviderFemMesh::updateData(const App::Property* prop)
{
if (prop->isDerivedFrom(Fem::PropertyFemMesh::getClassTypeId())) {
ViewProviderFEMMeshBuilder builder;
builder.createMesh(prop, pcCoords, pcFaces);
builder.createMesh(prop, pcCoords, pcFaces,ShowInner.getValue());
}
Gui::ViewProviderGeometryObject::updateData(prop);
}
@@ -216,6 +319,20 @@ void ViewProviderFemMesh::onChanged(const App::Property* prop)
if (c != PointMaterial.getValue().diffuseColor)
PointMaterial.setDiffuseColor(c);
}
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<Fem::FemMeshObject*>(this->pcObject)->FemMesh), pcCoords, pcFaces,ShowInner.getValue());
}
else if (prop == &PointMaterial) {
const App::Material& Mat = PointMaterial.getValue();
if (PointColor.getValue() != Mat.diffuseColor)
@@ -258,23 +375,262 @@ void ViewProviderFEMMeshBuilder::buildNodes(const App::Property* prop, std::vect
if (pcPointsCoord && pcFaces)
createMesh(prop, pcPointsCoord, pcFaces);
}
#if 1 // new visual
void ViewProviderFEMMeshBuilder::createMesh(const App::Property* prop, SoCoordinate3* coords, SoIndexedFaceSet* faces,bool ShowInner) const
{
const Fem::PropertyFemMesh* mesh = static_cast<const Fem::PropertyFemMesh*>(prop);
SMESHDS_Mesh* data = const_cast<SMESH_Mesh*>(mesh->getValue().getSMesh())->GetMeshDS();
int numFaces = data->NbFaces();
int numNodes = data->NbNodes();
int numEdges = data->NbEdges();
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();
std::vector<FemFace> facesHelper(numTria+numQuad+numPoly+numTetr*4+numHexa*6+numPyrd*5+numPris*6);
SMDS_VolumeIteratorPtr aVolIter = data->volumesIterator();
for (int i=0;aVolIter->more();) {
const SMDS_MeshVolume* aVol = aVolIter->next();
int num = aVol->NbNodes();
switch(num){
// tet 4 element
case 4:
// face 1
facesHelper[i++].set(3,aVol,aVol->GetID(),1,aVol->GetNode(0),aVol->GetNode(1),aVol->GetNode(2));
// face 2
facesHelper[i++].set(3,aVol,aVol->GetID(),2,aVol->GetNode(0),aVol->GetNode(3),aVol->GetNode(1));
// face 3
facesHelper[i++].set(3,aVol,aVol->GetID(),3,aVol->GetNode(1),aVol->GetNode(3),aVol->GetNode(2));
// face 4
facesHelper[i++].set(3,aVol,aVol->GetID(),4,aVol->GetNode(2),aVol->GetNode(3),aVol->GetNode(0));
break;
//unknown case
case 10:
// face 1
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
facesHelper[i++].set(6,aVol,aVol->GetID(),2,aVol->GetNode(0),aVol->GetNode(3),aVol->GetNode(7),aVol->GetNode(1),aVol->GetNode(8),aVol->GetNode(4));
// face 3
facesHelper[i++].set(6,aVol,aVol->GetID(),3,aVol->GetNode(1),aVol->GetNode(3),aVol->GetNode(8),aVol->GetNode(2),aVol->GetNode(9),aVol->GetNode(5));
// face 4
facesHelper[i++].set(6,aVol,aVol->GetID(),4,aVol->GetNode(2),aVol->GetNode(3),aVol->GetNode(9),aVol->GetNode(0),aVol->GetNode(7),aVol->GetNode(6));
break;
//unknown case
default: assert(0);
}
}
int FaceSize = facesHelper.size();
// 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<FaceSize; i++){
if(facesHelper[l].isSameFace(facesHelper[i]) ){
break;
}
}
}
}
}
// 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;
}
// set the point coordinates
coords->point.setNum(mapNodeIndex.size());
std::map<const SMDS_MeshNode*, int>::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;
}
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 6:triangleCount+=4 ;break;
default: assert(0);
}
// set the triangle face indices
faces->coordIndex.setNum(4*triangleCount);
int index=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 1: {
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(0)];
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(2)];
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(1)];
indices[index++] = SO_END_FACE_INDEX;
break; }
case 2: {
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(0)];
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(1)];
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(3)];
indices[index++] = SO_END_FACE_INDEX;
break; }
case 3: {
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(1)];
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(2)];
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(3)];
indices[index++] = SO_END_FACE_INDEX;
break; }
case 4: {
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(0)];
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(3)];
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(2)];
indices[index++] = SO_END_FACE_INDEX;
break; }
default: assert(0);
}
break;
case 10: // Tet 10
switch(facesHelper[l].FaceNo){
case 1: {
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(0)];
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(6)];
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(4)];
indices[index++] = SO_END_FACE_INDEX;
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(6)];
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(2)];
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(5)];
indices[index++] = SO_END_FACE_INDEX;
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(5)];
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(1)];
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(4)];
indices[index++] = SO_END_FACE_INDEX;
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(4)];
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(6)];
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(5)];
indices[index++] = SO_END_FACE_INDEX;
break; }
case 2: {
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(0)];
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(4)];
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(7)];
indices[index++] = SO_END_FACE_INDEX;
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(4)];
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(1)];
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(8)];
indices[index++] = SO_END_FACE_INDEX;
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(8)];
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(3)];
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(7)];
indices[index++] = SO_END_FACE_INDEX;
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(4)];
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(8)];
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(7)];
indices[index++] = SO_END_FACE_INDEX;
break; }
case 3: {
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(1)];
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(5)];
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(8)];
indices[index++] = SO_END_FACE_INDEX;
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(5)];
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(2)];
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(9)];
indices[index++] = SO_END_FACE_INDEX;
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(9)];
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(3)];
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(8)];
indices[index++] = SO_END_FACE_INDEX;
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(5)];
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(9)];
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(8)];
indices[index++] = SO_END_FACE_INDEX;
break; }
case 4: {
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(6)];
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(0)];
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(7)];
indices[index++] = SO_END_FACE_INDEX;
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(2)];
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(6)];
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(9)];
indices[index++] = SO_END_FACE_INDEX;
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(9)];
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(7)];
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(3)];
indices[index++] = SO_END_FACE_INDEX;
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(6)];
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(7)];
indices[index++] = mapNodeIndex[facesHelper[l].Element->GetNode(9)];
indices[index++] = SO_END_FACE_INDEX;
break; }
default: assert(0);
}
break;
default:assert(0); // not implemented node
}
}
}
faces->coordIndex.finishEditing();
}
#else // old version of createMesh()
void ViewProviderFEMMeshBuilder::createMesh(const App::Property* prop, SoCoordinate3* coords, SoIndexedFaceSet* faces) const
{
const Fem::PropertyFemMesh* mesh = static_cast<const Fem::PropertyFemMesh*>(prop);
SMESHDS_Mesh* data = const_cast<SMESH_Mesh*>(mesh->getValue().getSMesh())->GetMeshDS();
const SMDS_MeshInfo& info = data->GetMeshInfo();
int numFaces = data->NbFaces();
int numNodes = data->NbNodes ();
int numEdges = data->NbEdges ();
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 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();
int numHexa = info.NbHexas();
int numPyrd = info.NbPyramids();
int numPris = info.NbPrisms();
int numHedr = info.NbPolyhedrons();
int index=0;
std::map<const SMDS_MeshNode*, int> mapNodeIndex;
@@ -295,6 +651,7 @@ void ViewProviderFEMMeshBuilder::createMesh(const App::Property* prop, SoCoordin
index=0;
faces->coordIndex.setNum(4*numTria + 5*numQuad + 16*numTetr);
int32_t* indices = faces->coordIndex.startEditing();
// iterate all faces
SMDS_FaceIteratorPtr aFaceIter = data->facesIterator();
for (;aFaceIter->more();) {
const SMDS_MeshFace* aFace = aFaceIter->next();
@@ -336,3 +693,4 @@ void ViewProviderFEMMeshBuilder::createMesh(const App::Property* prop, SoCoordin
}
faces->coordIndex.finishEditing();
}
#endif