Files
create/src/Mod/Fem/Gui/ViewProviderFemMesh.cpp
2011-10-10 13:44:52 +00:00

339 lines
12 KiB
C++

/***************************************************************************
* Copyright (c) 2008 Jürgen Riegel (juergen.riegel@web.de) *
* *
* 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 <Standard_math.hxx>
# include <Inventor/SoDB.h>
# include <Inventor/SoInput.h>
# include <Inventor/SbVec3f.h>
# include <Inventor/actions/SoSearchAction.h>
# include <Inventor/nodes/SoBaseColor.h>
# include <Inventor/nodes/SoLightModel.h>
# include <Inventor/nodes/SoMaterial.h>
# include <Inventor/nodes/SoSeparator.h>
# include <Inventor/nodes/SoTransform.h>
# include <Inventor/nodes/SoRotation.h>
# include <Inventor/nodes/SoCoordinate3.h>
# include <Inventor/nodes/SoDrawStyle.h>
# include <Inventor/nodes/SoIndexedFaceSet.h>
# include <Inventor/nodes/SoShapeHints.h>
# include <Inventor/nodes/SoPointSet.h>
# include <Inventor/nodes/SoPolygonOffset.h>
# include <QFile>
#endif
#include "ViewProviderFemMesh.h"
#include <Mod/Fem/App/FemMeshObject.h>
#include <Mod/Fem/App/FemMesh.h>
#include <Gui/SoFCSelection.h>
#include <App/Document.h>
#include <Base/FileInfo.h>
#include <Base/Stream.h>
#include <Base/Console.h>
#include <sstream>
#include <SMESH_Mesh.hxx>
#include <SMESHDS_Mesh.hxx>
using namespace FemGui;
PROPERTY_SOURCE(FemGui::ViewProviderFemMesh, Gui::ViewProviderGeometryObject)
App::PropertyFloatConstraint::Constraints ViewProviderFemMesh::floatRange = {1.0f,64.0f,1.0f};
ViewProviderFemMesh::ViewProviderFemMesh()
{
App::Material mat;
mat.ambientColor.set(0.2f,0.2f,0.2f);
mat.diffuseColor.set(0.1f,0.1f,0.1f);
mat.specularColor.set(0.0f,0.0f,0.0f);
mat.emissiveColor.set(0.0f,0.0f,0.0f);
mat.shininess = 0.0f;
mat.transparency = 0.0f;
ADD_PROPERTY(PointMaterial,(mat));
ADD_PROPERTY(PointColor,(mat.diffuseColor));
ADD_PROPERTY(PointSize,(2.0f));
PointSize.setConstraints(&floatRange);
ADD_PROPERTY(LineWidth,(1.0f));
LineWidth.setConstraints(&floatRange);
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->ref();
pcMatBinding = new SoMaterialBinding;
pcMatBinding->value = SoMaterialBinding::OVERALL;
pcMatBinding->ref();
pcCoords = new SoCoordinate3();
pcCoords->ref();
pcFaces = new SoIndexedFaceSet;
pcFaces->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();
pShapeHints->unref();
pcMatBinding->unref();
pcPointMaterial->unref();
pcPointStyle->unref();
}
void ViewProviderFemMesh::attach(App::DocumentObject *pcObj)
{
ViewProviderGeometryObject::attach(pcObj);
// flat
SoGroup* pcFlatRoot = new SoGroup();
pcFlatRoot->addChild(pShapeHints);
pcFlatRoot->addChild(pcShapeMaterial);
pcFlatRoot->addChild(pcMatBinding);
pcFlatRoot->addChild(pcHighlight);
addDisplayMaskMode(pcFlatRoot, "Flat");
// line
SoLightModel* pcLightModel = new SoLightModel();
pcLightModel->model = SoLightModel::BASE_COLOR;
SoGroup* pcWireRoot = new SoGroup();
pcWireRoot->addChild(pcDrawStyle);
pcWireRoot->addChild(pcLightModel);
SoBaseColor* color = new SoBaseColor();
color->rgb.setValue(0.0f,0.0f,0.0f);
pcWireRoot->addChild(color);
pcWireRoot->addChild(pcHighlight);
addDisplayMaskMode(pcWireRoot, "Wireframe");
// flat+line
SoPolygonOffset* offset = new SoPolygonOffset();
offset->styles = SoPolygonOffset::LINES;
offset->factor = -2.0f;
offset->units = 1.0f;
SoGroup* pcFlatWireRoot = new SoSeparator();
pcFlatWireRoot->addChild(pcFlatRoot);
pcFlatWireRoot->addChild(offset);
pcFlatWireRoot->addChild(pcWireRoot);
addDisplayMaskMode(pcFlatWireRoot, "Flat Lines");
// Points
SoGroup* pcPointsRoot = new SoSeparator();
pcPointsRoot->addChild(pcPointMaterial);
pcPointsRoot->addChild(pcPointStyle);
pcPointsRoot->addChild(pcCoords);
SoPointSet * pointset = new SoPointSet;
pcPointsRoot->addChild(pointset);
addDisplayMaskMode(pcPointsRoot, "Points");
pcHighlight->addChild(pcCoords);
pcHighlight->addChild(pcFaces);
}
void ViewProviderFemMesh::setDisplayMode(const char* ModeName)
{
if (strcmp("Flat Lines",ModeName)==0)
setDisplayMaskMode("Flat Lines");
else if (strcmp("Shaded",ModeName)==0)
setDisplayMaskMode("Flat");
else if (strcmp("Wireframe",ModeName)==0)
setDisplayMaskMode("Wireframe");
else if (strcmp("Points",ModeName)==0)
setDisplayMaskMode("Points");
ViewProviderGeometryObject::setDisplayMode( ModeName );
}
std::vector<std::string> ViewProviderFemMesh::getDisplayModes(void) const
{
std::vector<std::string> StrList;
StrList.push_back("Flat Lines");
StrList.push_back("Shaded");
StrList.push_back("Wireframe");
StrList.push_back("Points");
return StrList;
}
void ViewProviderFemMesh::updateData(const App::Property* prop)
{
if (prop->isDerivedFrom(Fem::PropertyFemMesh::getClassTypeId())) {
ViewProviderFEMMeshBuilder builder;
builder.createMesh(prop, pcCoords, pcFaces);
}
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);
if (c != PointMaterial.getValue().diffuseColor)
PointMaterial.setDiffuseColor(c);
}
else if (prop == &PointMaterial) {
const App::Material& Mat = PointMaterial.getValue();
if (PointColor.getValue() != Mat.diffuseColor)
PointColor.setValue(Mat.diffuseColor);
pcPointMaterial->ambientColor.setValue(Mat.ambientColor.r,Mat.ambientColor.g,Mat.ambientColor.b);
pcPointMaterial->diffuseColor.setValue(Mat.diffuseColor.r,Mat.diffuseColor.g,Mat.diffuseColor.b);
pcPointMaterial->specularColor.setValue(Mat.specularColor.r,Mat.specularColor.g,Mat.specularColor.b);
pcPointMaterial->emissiveColor.setValue(Mat.emissiveColor.r,Mat.emissiveColor.g,Mat.emissiveColor.b);
pcPointMaterial->shininess.setValue(Mat.shininess);
pcPointMaterial->transparency.setValue(Mat.transparency);
}
else if (prop == &LineWidth) {
pcDrawStyle->lineWidth = LineWidth.getValue();
}
else {
ViewProviderGeometryObject::onChanged(prop);
}
}
// ----------------------------------------------------------------------------
void ViewProviderFEMMeshBuilder::buildNodes(const App::Property* prop, std::vector<SoNode*>& nodes) const
{
SoCoordinate3 *pcPointsCoord=0;
SoIndexedFaceSet *pcFaces=0;
if (nodes.empty()) {
pcPointsCoord = new SoCoordinate3();
nodes.push_back(pcPointsCoord);
pcFaces = new SoIndexedFaceSet();
nodes.push_back(pcFaces);
}
else if (nodes.size() == 2) {
if (nodes[0]->getTypeId() == SoCoordinate3::getClassTypeId())
pcPointsCoord = static_cast<SoCoordinate3*>(nodes[0]);
if (nodes[1]->getTypeId() == SoIndexedFaceSet::getClassTypeId())
pcFaces = static_cast<SoIndexedFaceSet*>(nodes[1]);
}
if (pcPointsCoord && pcFaces)
createMesh(prop, pcPointsCoord, pcFaces);
}
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 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();
int index=0;
std::map<const SMDS_MeshNode*, int> mapNodeIndex;
// set the point coordinates
coords->point.setNum(numNode);
SMDS_NodeIteratorPtr aNodeIter = data->nodesIterator();
unsigned int i=0;
SbVec3f* verts = coords->point.startEditing();
for (;aNodeIter->more();) {
const SMDS_MeshNode* aNode = aNodeIter->next();
verts[i++].setValue((float)aNode->X(),(float)aNode->Y(),(float)aNode->Z());
mapNodeIndex[aNode] = index++;
}
coords->point.finishEditing();
// set the face indices
index=0;
faces->coordIndex.setNum(4*numTria + 5*numQuad + 16*numTetr);
int32_t* indices = faces->coordIndex.startEditing();
SMDS_FaceIteratorPtr aFaceIter = data->facesIterator();
for (;aFaceIter->more();) {
const SMDS_MeshFace* aFace = aFaceIter->next();
int num = aFace->NbNodes();
if (num != 3 && num != 4)
continue;
for (int j=0; j<num;j++) {
const SMDS_MeshNode* node = aFace->GetNode(j);
indices[index++] = mapNodeIndex[node];
}
indices[index++] = SO_END_FACE_INDEX;
}
SMDS_VolumeIteratorPtr aVolIter = data->volumesIterator();
for (;aVolIter->more();) {
const SMDS_MeshVolume* aVol = aVolIter->next();
int num = aVol->NbNodes();
if (num != 4)
continue;
int i1 = mapNodeIndex[aVol->GetNode(0)];
int i2 = mapNodeIndex[aVol->GetNode(1)];
int i3 = mapNodeIndex[aVol->GetNode(2)];
int i4 = mapNodeIndex[aVol->GetNode(3)];
indices[index++] = i1;
indices[index++] = i3;
indices[index++] = i2;
indices[index++] = SO_END_FACE_INDEX;
indices[index++] = i1;
indices[index++] = i2;
indices[index++] = i4;
indices[index++] = SO_END_FACE_INDEX;
indices[index++] = i1;
indices[index++] = i4;
indices[index++] = i3;
indices[index++] = SO_END_FACE_INDEX;
indices[index++] = i2;
indices[index++] = i3;
indices[index++] = i4;
indices[index++] = SO_END_FACE_INDEX;
}
faces->coordIndex.finishEditing();
}