Files
create/src/Mod/Fem/Gui/ViewProviderFemMesh.cpp
Kacper Donat 13fbab9e42 Base: Move App::Color to Base
Every basic data type is stored in Base module, color is standing out as
one that does not. Moving it to Base opens possibilities to integrate it
better with the rest of FreeCAD.
2025-02-17 21:10:26 +01:00

3174 lines
163 KiB
C++

/***************************************************************************
* 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 <Inventor/SbVec3f.h>
#include <Inventor/details/SoFaceDetail.h>
#include <Inventor/details/SoLineDetail.h>
#include <Inventor/details/SoPointDetail.h>
#include <Inventor/nodes/SoAnnotation.h>
#include <Inventor/nodes/SoBaseColor.h>
#include <Inventor/nodes/SoCoordinate3.h>
#include <Inventor/nodes/SoDrawStyle.h>
#include <Inventor/nodes/SoIndexedFaceSet.h>
#include <Inventor/nodes/SoIndexedLineSet.h>
#include <Inventor/nodes/SoLightModel.h>
#include <Inventor/nodes/SoMaterial.h>
#include <Inventor/nodes/SoPointSet.h>
#include <Inventor/nodes/SoPolygonOffset.h>
#include <Inventor/nodes/SoSeparator.h>
#include <Inventor/nodes/SoShapeHints.h>
#include <sstream>
#include <SMESHDS_Mesh.hxx>
#include <SMESH_Mesh.hxx>
#endif
#include <App/DocumentObject.h>
#include <Base/BoundBox.h>
#include <Base/Console.h>
#include <Base/TimeInfo.h>
#include <Mod/Fem/App/FemMeshObject.h>
#include "ViewProviderFemMesh.h"
#include "ViewProviderFemMeshPy.h"
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()
{
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 = nullptr,
const SMDS_MeshNode* n5 = nullptr,
const SMDS_MeshNode* n6 = nullptr,
const SMDS_MeshNode* n7 = nullptr,
const SMDS_MeshNode* n8 = nullptr);
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 flag = 1; // set flag to 1 to start first pass
const SMDS_MeshNode* temp; // holding variable
for (int i = 1; (i <= size) && flag; i++) {
flag = 0;
for (int 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<FemFace*>
{
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;
}
// ----------------------------------------------------------------------------
class ViewProviderFemMesh::Private
{
public:
static const char* dm_face_wire;
static const char* dm_wire_node;
static const char* dm_face_wire_node;
static const char* dm_face;
static const char* dm_node;
static const char* dm_wire;
};
const char* ViewProviderFemMesh::Private::dm_face_wire = "Faces & Wireframe";
const char* ViewProviderFemMesh::Private::dm_wire_node = "Wireframe & Nodes";
const char* ViewProviderFemMesh::Private::dm_face_wire_node = "Faces, Wireframe & Nodes";
const char* ViewProviderFemMesh::Private::dm_face = "Faces";
const char* ViewProviderFemMesh::Private::dm_node = "Nodes";
const char* ViewProviderFemMesh::Private::dm_wire = "Wireframe";
PROPERTY_SOURCE(FemGui::ViewProviderFemMesh, Gui::ViewProviderGeometryObject)
App::PropertyFloatConstraint::Constraints ViewProviderFemMesh::floatRange = {1.0, 64.0, 1.0};
const char* ViewProviderFemMesh::colorModeEnum[] = {"Overall", "ByElement", "ByNode", nullptr};
ViewProviderFemMesh::ViewProviderFemMesh()
{
sPixmap = "fem-femmesh-from-shape";
ADD_PROPERTY(PointColor, (Base::Color(0.7f, 0.7f, 0.7f)));
ADD_PROPERTY(PointSize, (5.0f));
PointSize.setConstraints(&floatRange);
ADD_PROPERTY(LineWidth, (1.0f));
LineWidth.setConstraints(&floatRange);
ShapeAppearance.setDiffuseColor(Base::Color(1.0f, 0.7f, 0.0f));
Transparency.setValue(0);
ADD_PROPERTY(BackfaceCulling, (true));
ADD_PROPERTY(ShowInner, (false));
ADD_PROPERTY(MaxFacesShowInner, (50000));
ADD_PROPERTY_TYPE(ColorMode,
("Overall"),
"Display Options",
App::Prop_None,
"Set the color mode");
ADD_PROPERTY_TYPE(NodeColorArray,
(PointColor.getValue()),
"Object Style",
App::Prop_Hidden,
"Node diffuse color array");
ADD_PROPERTY_TYPE(ElementColorArray,
(ShapeAppearance.getDiffuseColor()),
"Object Style",
App::Prop_Hidden,
"Node diffuse color array");
suppressibleExt.initExtension(this);
ColorMode.setEnums(colorModeEnum);
onlyEdges = 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();
DisplacementFactor = 0;
}
ViewProviderFemMesh::~ViewProviderFemMesh()
{
pcCoords->unref();
pcDrawStyle->unref();
pcFaces->unref();
pcLines->unref();
pShapeHints->unref();
pcMatBinding->unref();
pcPointMaterial->unref();
pcPointStyle->unref();
pcAnoCoords->unref();
}
void ViewProviderFemMesh::attach(App::DocumentObject* pcObj)
{
ViewProviderGeometryObject::attach(pcObj);
// Move 'coords' before the switch
// pcRoot->insertChild(pcCoords,pcRoot->findChild(static_cast<const SoNode*>(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);
// Faces
SoGroup* pcFlatRoot = new SoGroup();
pcFlatRoot->addChild(pcCoords);
pcFlatRoot->addChild(pShapeHints);
pcFlatRoot->addChild(pcShapeMaterial);
pcFlatRoot->addChild(pcMatBinding);
pcFlatRoot->addChild(pcFaces);
pcFlatRoot->addChild(pcAnotRoot);
addDisplayMaskMode(pcFlatRoot, Private::dm_face);
// Wireframe
SoGroup* pcWireRoot = new SoSeparator();
SoLightModel* pcLightModel = new SoLightModel();
pcLightModel->model = SoLightModel::BASE_COLOR;
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, Private::dm_wire);
// Nodes
SoGroup* pcPointsRoot = new SoSeparator();
pcPointsRoot->addChild(pcPointMaterial);
pcPointsRoot->addChild(pcPointStyle);
pcPointsRoot->addChild(pcCoords);
pointset = new SoPointSet;
pcPointsRoot->addChild(pointset);
addDisplayMaskMode(pcPointsRoot, Private::dm_node);
// For combined modes make sure to use a Separator instead of a Group
// because the group affects nodes that are rendered afterwards (#0003769)
// Faces + Wireframe (Elements)
SoPolygonOffset* offset = new SoPolygonOffset();
SoGroup* pcFlatWireRoot = new SoGroup();
pcFlatWireRoot->addChild(pcWireRoot);
pcFlatWireRoot->addChild(offset);
pcFlatWireRoot->addChild(pcFlatRoot);
addDisplayMaskMode(pcFlatWireRoot, Private::dm_face_wire);
// Faces + Wireframe + Nodes (Elements&Nodes)
SoGroup* pcElemNodesRoot = new SoGroup();
pcElemNodesRoot->addChild(pcPointsRoot);
pcElemNodesRoot->addChild(pcWireRoot);
pcElemNodesRoot->addChild(offset);
pcElemNodesRoot->addChild(pcFlatRoot);
addDisplayMaskMode(pcElemNodesRoot, Private::dm_face_wire_node);
// Wireframe + Nodes
SoGroup* pcWireNodeRoot = new SoGroup();
pcWireNodeRoot->addChild(pcPointsRoot);
pcWireNodeRoot->addChild(pcWireRoot);
addDisplayMaskMode(pcWireNodeRoot, Private::dm_wire_node);
}
void ViewProviderFemMesh::setDisplayMode(const char* ModeName)
{
setDisplayMaskMode(ModeName);
ViewProviderGeometryObject::setDisplayMode(ModeName);
}
std::vector<std::string> ViewProviderFemMesh::getDisplayModes() const
{
std::vector<std::string> StrList;
StrList.emplace_back(Private::dm_face_wire);
StrList.emplace_back(Private::dm_face_wire_node);
StrList.emplace_back(Private::dm_face);
StrList.emplace_back(Private::dm_wire);
StrList.emplace_back(Private::dm_node);
StrList.emplace_back(Private::dm_wire_node);
return StrList;
}
void ViewProviderFemMesh::updateData(const App::Property* prop)
{
if (prop->isDerivedFrom<Fem::PropertyFemMesh>()) {
ViewProviderFEMMeshBuilder builder;
resetColorByNodeId();
resetDisplacementByNodeId();
builder.createMesh(prop,
pcCoords,
pcFaces,
pcLines,
vFaceElementIdx,
vNodeElementIdx,
onlyEdges,
ShowInner.getValue(),
MaxFacesShowInner.getValue());
}
Gui::ViewProviderGeometryObject::updateData(prop);
}
void ViewProviderFemMesh::onChanged(const App::Property* prop)
{
auto matchTransparency = [&]() {
if (getObject() && getObject()->testStatus(App::ObjectStatus::TouchOnColorChange)) {
getObject()->touch(true);
}
long value = static_cast<long>(100 * ShapeAppearance.getTransparency() + 0.5);
if (value != Transparency.getValue()) {
Transparency.setValue(value);
}
};
if (prop == &PointSize) {
pcPointStyle->pointSize = PointSize.getValue();
}
else if (prop == &PointColor) {
const Base::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(&(static_cast<Fem::FemMeshObject*>(this->pcObject)->FemMesh),
pcCoords,
pcFaces,
pcLines,
vFaceElementIdx,
vNodeElementIdx,
onlyEdges,
ShowInner.getValue(),
MaxFacesShowInner.getValue());
}
else if (prop == &LineWidth) {
pcDrawStyle->lineWidth = LineWidth.getValue();
}
else if (prop == &ColorMode) {
switch (ColorMode.getValue()) {
case 1: // ByElement
setMaterialByColorArray(&ElementColorArray, vFaceElementIdx);
break;
case 2: // ByNode
setMaterialByColorArray(&NodeColorArray, vNodeElementIdx);
break;
default: // Overall
setMaterialOverall();
}
}
else if (prop == &ShapeAppearance && ColorMode.getValue() == 0) {
matchTransparency();
setMaterialOverall();
}
else if ((prop == &ElementColorArray || prop == &ShapeAppearance)
&& ColorMode.getValue() == 1) {
matchTransparency();
setMaterialByColorArray(&ElementColorArray, vFaceElementIdx);
}
else if ((prop == &NodeColorArray || prop == &ShapeAppearance) && ColorMode.getValue() == 2) {
matchTransparency();
setMaterialByColorArray(&NodeColorArray, vNodeElementIdx);
}
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<const SoFaceDetail*>(detail);
unsigned long edx = vFaceElementIdx[face_detail->getFaceIndex()];
str << "Elem" << (edx >> 3) << "F" << (edx & 7) + 1;
}
// trigger on edges only if edge only mesh, otherwise you only hit edges and 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();
// first check if the index is part of the highlighted nodes (#0003618)
if (idx < static_cast<int>(vHighlightedIdx.size())) {
int vertex = vHighlightedIdx[idx];
str << "Node" << vertex;
}
else if (idx < static_cast<int>(vNodeElementIdx.size())) {
int vertex = vNodeElementIdx[idx];
str << "Node" << vertex;
}
else {
return {};
}
}
}
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 = nullptr;
if (index < 0) {
return detail;
}
if (element == "Elem") {
detail = new SoFaceDetail();
static_cast<SoFaceDetail*>(detail)->setPartIndex(index - 1);
}
// else if (element == "Edge") {
// detail = new SoLineDetail();
// static_cast<SoLineDetail*>(detail)->setLineIndex(index - 1);
// }
// else if (element == "Vertex") {
// detail = new SoPointDetail();
// static_cast<SoPointDetail*>(detail)->setCoordinateIndex(index +
// nodeset->startIndex.getValue() - 1);
// }
return detail;
}
std::vector<Base::Vector3d> ViewProviderFemMesh::getSelectionShape(const char* /*Element*/) const
{
return {};
}
std::set<long> ViewProviderFemMesh::getHighlightNodes() const
{
std::set<long> nodes;
nodes.insert(vHighlightedIdx.begin(), vHighlightedIdx.end());
return nodes;
}
void ViewProviderFemMesh::setHighlightNodes(const std::set<long>& HighlightedNodes)
{
if (!HighlightedNodes.empty()) {
const SMESHDS_Mesh* data = static_cast<Fem::FemMeshObject*>(this->pcObject)
->FemMesh.getValue()
.getSMesh()
->GetMeshDS();
pcAnoCoords->point.setNum(HighlightedNodes.size());
SbVec3f* verts = pcAnoCoords->point.startEditing();
int i = 0;
for (std::set<long>::const_iterator it = HighlightedNodes.begin();
it != HighlightedNodes.end();
++it, i++) {
const SMDS_MeshNode* Node = data->FindNode(*it);
if (Node) {
verts[i].setValue((float)Node->X(), (float)Node->Y(), (float)Node->Z());
}
else {
verts[i].setValue(0, 0, 0);
}
}
pcAnoCoords->point.finishEditing();
// save the node ids
vHighlightedIdx.clear();
vHighlightedIdx.insert(vHighlightedIdx.end(),
HighlightedNodes.begin(),
HighlightedNodes.end());
}
else {
pcAnoCoords->point.setNum(0);
vHighlightedIdx.clear();
}
}
void ViewProviderFemMesh::resetHighlightNodes()
{
pcAnoCoords->point.setNum(0);
vHighlightedIdx.clear();
}
PyObject* ViewProviderFemMesh::getPyObject()
{
if (!pyViewObject) {
pyViewObject = new ViewProviderFemMeshPy(this);
}
pyViewObject->IncRef();
return pyViewObject;
}
void ViewProviderFemMesh::setDisplacementByNodeId(const std::map<long, Base::Vector3d>& NodeDispMap)
{
long startId = NodeDispMap.begin()->first;
long endId = (--NodeDispMap.end())->first;
std::vector<Base::Vector3d> vecVec(endId - startId + 2, Base::Vector3d());
for (const auto& it : NodeDispMap) {
vecVec[it.first - startId] = it.second;
}
setDisplacementByNodeIdHelper(vecVec, startId);
}
void ViewProviderFemMesh::setDisplacementByNodeId(const std::vector<long>& NodeIds,
const std::vector<Base::Vector3d>& NodeDisps)
{
long startId = *(std::min_element(NodeIds.begin(), NodeIds.end()));
long endId = *(std::max_element(NodeIds.begin(), NodeIds.end()));
std::vector<Base::Vector3d> vecVec(endId - startId + 2, Base::Vector3d());
long i = 0;
for (std::vector<long>::const_iterator it = NodeIds.begin(); it != NodeIds.end(); ++it, i++) {
vecVec[*it - startId] = NodeDisps[i];
}
setDisplacementByNodeIdHelper(vecVec, startId);
}
void ViewProviderFemMesh::setDisplacementByNodeIdHelper(
const std::vector<Base::Vector3d>& DispVector,
long startId)
{
DisplacementVector.resize(vNodeElementIdx.size());
int i = 0;
for (std::vector<unsigned long>::const_iterator it = vNodeElementIdx.begin();
it != vNodeElementIdx.end();
++it, i++) {
DisplacementVector[i] = DispVector[*it - startId];
}
applyDisplacementToNodes(1.0);
}
void ViewProviderFemMesh::resetDisplacementByNodeId()
{
applyDisplacementToNodes(0.0);
DisplacementVector.clear();
}
/// reaply the node displacement with a certain factor and do a redraw
void ViewProviderFemMesh::applyDisplacementToNodes(double factor)
{
if (DisplacementVector.empty()) {
return;
}
float x = 0, y = 0, z = 0;
// set the point coordinates
long sz = pcCoords->point.getNum();
SbVec3f* verts = pcCoords->point.startEditing();
for (long i = 0; i < sz; i++) {
verts[i].getValue(x, y, z);
// undo old factor#
Base::Vector3d oldDisp = DisplacementVector[i] * DisplacementFactor;
x -= oldDisp.x;
y -= oldDisp.y;
z -= oldDisp.z;
// apply new factor
Base::Vector3d newDisp = DisplacementVector[i] * factor;
x += newDisp.x;
y += newDisp.y;
z += newDisp.z;
// set the new value
verts[i].setValue(x, y, z);
}
pcCoords->point.finishEditing();
DisplacementFactor = factor;
}
void ViewProviderFemMesh::setColorByNodeId(const std::vector<long>& NodeIds,
const std::vector<Base::Color>& NodeColors)
{
long endId = *(std::max_element(NodeIds.begin(), NodeIds.end()));
std::vector<Base::Color> colorVec(endId + 1, Base::Color(0, 1, 0));
long i = 0;
for (std::vector<long>::const_iterator it = NodeIds.begin(); it != NodeIds.end(); ++it, i++) {
colorVec[*it] = NodeColors[i];
}
setColorByNodeIdHelper(colorVec);
}
void ViewProviderFemMesh::setColorByNodeIdHelper(const std::vector<Base::Color>& colorVec)
{
pcMatBinding->value = SoMaterialBinding::PER_VERTEX_INDEXED;
// resizing and writing the color vector:
pcShapeMaterial->diffuseColor.setNum(vNodeElementIdx.size());
SbColor* colors = pcShapeMaterial->diffuseColor.startEditing();
long i = 0;
for (std::vector<unsigned long>::const_iterator it = vNodeElementIdx.begin();
it != vNodeElementIdx.end();
++it, i++) {
colors[i] = SbColor(colorVec[*it].r, colorVec[*it].g, colorVec[*it].b);
}
pcShapeMaterial->diffuseColor.finishEditing();
}
void ViewProviderFemMesh::resetColorByNodeId()
{
const Base::Color& c = ShapeAppearance.getDiffuseColor();
NodeColorArray.setValue(c);
}
void ViewProviderFemMesh::setColorByNodeId(
const std::map<std::vector<long>, Base::Color>& elemColorMap)
{
setColorByIdHelper(elemColorMap, vNodeElementIdx, 0, NodeColorArray);
}
void ViewProviderFemMesh::setColorByElementId(
const std::map<std::vector<long>, Base::Color>& elemColorMap)
{
setColorByIdHelper(elemColorMap, vFaceElementIdx, 3, ElementColorArray);
}
void ViewProviderFemMesh::setColorByIdHelper(
const std::map<std::vector<long>, Base::Color>& elemColorMap,
const std::vector<unsigned long>& vElementIdx,
int rShift,
App::PropertyColorList& prop)
{
std::vector<Base::Color> vecColor(vElementIdx.size());
std::map<long, const Base::Color*> colorMap;
for (const auto& m : elemColorMap) {
for (long i : m.first) {
colorMap[i] = &m.second;
}
}
Base::Color baseDif = ShapeAppearance.getDiffuseColor();
int i = 0;
for (std::vector<unsigned long>::const_iterator it = vElementIdx.begin();
it != vElementIdx.end();
++it, i++) {
unsigned long ElemIdx = ((*it) >> rShift);
const std::map<long, const Base::Color*>::const_iterator pos = colorMap.find(ElemIdx);
vecColor[i] = pos == colorMap.end() ? baseDif : *pos->second;
}
prop.setValue(vecColor);
}
void ViewProviderFemMesh::setMaterialOverall() const
{
const App::Material& mat = ShapeAppearance[0];
Base::Color baseDif = mat.diffuseColor;
Base::Color baseAmb = mat.ambientColor;
Base::Color baseSpe = mat.specularColor;
Base::Color baseEmi = mat.emissiveColor;
float baseShi = mat.shininess;
float baseTra = mat.transparency;
pcMatBinding->value = SoMaterialBinding::OVERALL;
pcShapeMaterial->diffuseColor.setNum(0);
pcShapeMaterial->ambientColor.setNum(0);
pcShapeMaterial->specularColor.setNum(0);
pcShapeMaterial->emissiveColor.setNum(0);
pcShapeMaterial->shininess.setNum(0);
pcShapeMaterial->transparency.setNum(0);
pcShapeMaterial->diffuseColor.setValue(baseDif.r, baseDif.g, baseDif.b);
pcShapeMaterial->ambientColor.setValue(baseAmb.r, baseAmb.g, baseAmb.b);
pcShapeMaterial->specularColor.setValue(baseSpe.r, baseSpe.g, baseSpe.b);
pcShapeMaterial->emissiveColor.setValue(baseEmi.r, baseEmi.g, baseEmi.b);
pcShapeMaterial->shininess.setValue(baseShi);
pcShapeMaterial->transparency.setValue(baseTra);
pcFaces->touch();
return;
}
void ViewProviderFemMesh::setMaterialByColorArray(
const App::PropertyColorList* prop,
const std::vector<unsigned long>& vElementIdx) const
{
const App::Material& baseMat = ShapeAppearance[0];
Base::Color baseDif = baseMat.diffuseColor;
Base::Color baseAmb = baseMat.ambientColor;
Base::Color baseSpe = baseMat.specularColor;
Base::Color baseEmi = baseMat.emissiveColor;
float baseShi = baseMat.shininess;
float baseTra = baseMat.transparency;
// resizing and writing the color vector:
std::vector<Base::Color> vecColor = prop->getValue();
size_t elemSize = vElementIdx.size();
if (vecColor.size() == 1) {
pcMatBinding->value = SoMaterialBinding::OVERALL;
pcShapeMaterial->diffuseColor.setNum(0);
pcShapeMaterial->ambientColor.setNum(0);
pcShapeMaterial->specularColor.setNum(0);
pcShapeMaterial->emissiveColor.setNum(0);
pcShapeMaterial->shininess.setNum(0);
pcShapeMaterial->transparency.setNum(0);
pcShapeMaterial->diffuseColor.setValue(vecColor[0].r, vecColor[0].g, vecColor[0].b);
pcShapeMaterial->ambientColor.setValue(baseAmb.r, baseAmb.g, baseAmb.b);
pcShapeMaterial->specularColor.setValue(baseSpe.r, baseSpe.g, baseSpe.b);
pcShapeMaterial->emissiveColor.setValue(baseEmi.r, baseEmi.g, baseEmi.b);
pcShapeMaterial->shininess.setValue(baseShi);
pcShapeMaterial->transparency.setValue(baseTra);
return;
}
if (prop == &ElementColorArray) {
pcMatBinding->value = SoMaterialBinding::PER_FACE;
}
else if (prop == &NodeColorArray) {
pcMatBinding->value = SoMaterialBinding::PER_VERTEX_INDEXED;
}
pcShapeMaterial->diffuseColor.setNum(elemSize);
SbColor* diffuse = pcShapeMaterial->diffuseColor.startEditing();
pcShapeMaterial->ambientColor.setNum(elemSize);
SbColor* ambient = pcShapeMaterial->ambientColor.startEditing();
pcShapeMaterial->specularColor.setNum(elemSize);
SbColor* specular = pcShapeMaterial->specularColor.startEditing();
pcShapeMaterial->emissiveColor.setNum(elemSize);
SbColor* emissive = pcShapeMaterial->emissiveColor.startEditing();
pcShapeMaterial->shininess.setNum(elemSize);
float* shininess = pcShapeMaterial->shininess.startEditing();
pcShapeMaterial->transparency.setNum(elemSize);
float* transparency = pcShapeMaterial->transparency.startEditing();
vecColor.resize(elemSize, baseDif);
int i = 0;
for (const Base::Color& c : vecColor) {
diffuse[i] = SbColor(c.r, c.g, c.b);
ambient[i] = SbColor(baseAmb.r, baseAmb.g, baseAmb.b);
specular[i] = SbColor(baseSpe.r, baseSpe.g, baseSpe.b);
emissive[i] = SbColor(baseEmi.r, baseEmi.g, baseEmi.b);
shininess[i] = baseShi;
transparency[i] = baseTra;
++i;
}
pcShapeMaterial->diffuseColor.finishEditing();
pcShapeMaterial->ambientColor.finishEditing();
pcShapeMaterial->specularColor.finishEditing();
pcShapeMaterial->emissiveColor.finishEditing();
pcShapeMaterial->shininess.finishEditing();
pcShapeMaterial->transparency.finishEditing();
pcFaces->touch();
}
void ViewProviderFemMesh::resetColorByElementId()
{
const Base::Color& c = ShapeAppearance.getDiffuseColor();
ElementColorArray.setValue(c);
}
// ----------------------------------------------------------------------------
void ViewProviderFEMMeshBuilder::buildNodes(const App::Property* prop,
std::vector<SoNode*>& nodes) const
{
SoCoordinate3* pcPointsCoord = nullptr;
SoIndexedFaceSet* pcFaces = nullptr;
SoIndexedLineSet* pcLines = nullptr;
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<SoCoordinate3*>(nodes[0]);
}
if (nodes[1]->getTypeId() == SoIndexedFaceSet::getClassTypeId()) {
pcFaces = static_cast<SoIndexedFaceSet*>(nodes[1]);
}
}
if (pcPointsCoord && pcFaces && pcLines) {
std::vector<unsigned long> vFaceElementIdx;
std::vector<unsigned long> vNodeElementIdx;
bool onlyEdges;
createMesh(prop,
pcPointsCoord,
pcFaces,
pcLines,
vFaceElementIdx,
vNodeElementIdx,
onlyEdges,
false,
0);
}
}
inline void insEdgeVec(std::map<int, std::set<int>>& map, int n1, int n2)
{
// FIXME: The if-else distinction doesn't make sense
// if (n1<n2)
// map[n2].insert(n1);
// else
map[n2].insert(n1);
}
inline unsigned long ElemFold(unsigned long Element, unsigned long FaceNbr)
{
unsigned long t1 = Element << 3;
unsigned long t2 = t1 | 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& onlyEdges,
bool ShowInner,
int MaxFacesShowInner) const
{
const Fem::PropertyFemMesh* mesh = static_cast<const Fem::PropertyFemMesh*>(prop);
const SMESHDS_Mesh* data = mesh->getValue().getSMesh()->GetMeshDS();
int numFaces = data->NbFaces();
int numNodes = data->NbNodes();
int numEdges = data->NbEdges();
if (numFaces + numNodes + numEdges == 0) {
coords->point.setNum(0);
faces->coordIndex.setNum(0);
lines->coordIndex.setNum(0);
return;
}
Base::TimeElapsed Start;
Base::Console().Log(
"Start: ViewProviderFEMMeshBuilder::createMesh() =================================\n");
const SMDS_MeshInfo& info = data->GetMeshInfo();
int numTria = info.NbTriangles();
int numQuad = info.NbQuadrangles();
int numVolu = info.NbVolumes();
int numTetr = info.NbTetras();
int numHexa = info.NbHexas();
int numPyrd = info.NbPyramids();
int numPris = info.NbPrisms();
bool ShowFaces = (numFaces > 0 && numVolu == 0);
int numTries;
if (ShowFaces) {
numTries =
numTria + numQuad /*+numPoly*/ + numTetr * 4 + numHexa * 6 + numPyrd * 5 + numPris * 5;
}
else {
numTries = numTetr * 4 + numHexa * 6 + numPyrd * 5 + numPris * 5;
}
// It is not 100% sure that a prism in smesh is a pentahedron in any case, but it will be in
// most cases! See https://forum.freecad.org/viewtopic.php?f=18&t=13583#p109707
// 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);
Base::Console().Log(" %f: Start build up %i face helper\n",
Base::TimeElapsed::diffTimeF(Start, Base::TimeElapsed()),
facesHelper.size());
Base::BoundBox3d BndBox;
int i = 0;
if (ShowFaces) {
SMDS_FaceIteratorPtr aFaceIter = data->facesIterator();
for (; aFaceIter->more();) {
const SMDS_MeshFace* aFace = aFaceIter->next();
int num = aFace->NbNodes();
switch (num) {
case 3:
// tria3 face = N1, N2, N3
BndBox.Add(facesHelper[i++].set(3,
aFace,
aFace->GetID(),
0,
aFace->GetNode(0),
aFace->GetNode(1),
aFace->GetNode(2)));
break;
case 4:
// quad4 face = N1, N2, N3, N4
BndBox.Add(facesHelper[i++].set(4,
aFace,
aFace->GetID(),
0,
aFace->GetNode(0),
aFace->GetNode(1),
aFace->GetNode(2),
aFace->GetNode(3)));
break;
case 6:
// tria6 face = N1, N4, N2, N5, N3, N6
BndBox.Add(facesHelper[i++].set(6,
aFace,
aFace->GetID(),
0,
aFace->GetNode(0),
aFace->GetNode(3),
aFace->GetNode(1),
aFace->GetNode(4),
aFace->GetNode(2),
aFace->GetNode(5)));
break;
case 8:
// quad8 face = N1, N5, N2, N6, N3, N7, N4, N8
BndBox.Add(facesHelper[i++].set(8,
aFace,
aFace->GetID(),
0,
aFace->GetNode(0),
aFace->GetNode(4),
aFace->GetNode(1),
aFace->GetNode(5),
aFace->GetNode(2),
aFace->GetNode(6),
aFace->GetNode(3),
aFace->GetNode(7)));
break;
default:
// unknown face type
throw std::runtime_error(
"Node count not supported by ViewProviderFemMesh, [3|4|6|8] are allowed");
}
}
}
else {
// iterate all volumes
SMDS_VolumeIteratorPtr aVolIter = data->volumesIterator();
for (; aVolIter->more();) {
const SMDS_MeshVolume* aVol = aVolIter->next();
int num = aVol->NbNodes();
switch (num) {
// tetra4 volume
case 4:
// face 1 = N1, N2, N3
// face 2 = N1, N4, N2
// face 3 = N2, N4, N3
// face 4 = N3, N4, N1
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(),
2,
aVol->GetNode(0),
aVol->GetNode(3),
aVol->GetNode(1)));
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(),
4,
aVol->GetNode(2),
aVol->GetNode(3),
aVol->GetNode(0)));
break;
// pyra5 volume
case 5:
// face 1 = N1, N2, N3, N4
// face 2 = N1, N5, N2
// face 3 = N2, N5, N3
// face 4 = N3, N5, N4
// face 5 = N4, N5, N1
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(3,
aVol,
aVol->GetID(),
2,
aVol->GetNode(0),
aVol->GetNode(4),
aVol->GetNode(1)));
BndBox.Add(facesHelper[i++].set(3,
aVol,
aVol->GetID(),
3,
aVol->GetNode(1),
aVol->GetNode(4),
aVol->GetNode(2)));
BndBox.Add(facesHelper[i++].set(3,
aVol,
aVol->GetID(),
4,
aVol->GetNode(2),
aVol->GetNode(4),
aVol->GetNode(3)));
BndBox.Add(facesHelper[i++].set(3,
aVol,
aVol->GetID(),
5,
aVol->GetNode(3),
aVol->GetNode(4),
aVol->GetNode(0)));
break;
// penta6 volume
case 6:
// face 1 = N1, N2, N3
// face 2 = N4, N6, N5
// face 3 = N1, N4, N5, N2
// face 4 = N2, N5, N6, N3
// face 5 = N3, N6, N4, N1
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(),
2,
aVol->GetNode(3),
aVol->GetNode(5),
aVol->GetNode(4)));
BndBox.Add(facesHelper[i++].set(4,
aVol,
aVol->GetID(),
3,
aVol->GetNode(0),
aVol->GetNode(3),
aVol->GetNode(4),
aVol->GetNode(1)));
BndBox.Add(facesHelper[i++].set(4,
aVol,
aVol->GetID(),
4,
aVol->GetNode(1),
aVol->GetNode(4),
aVol->GetNode(5),
aVol->GetNode(2)));
BndBox.Add(facesHelper[i++].set(4,
aVol,
aVol->GetID(),
5,
aVol->GetNode(2),
aVol->GetNode(5),
aVol->GetNode(3),
aVol->GetNode(0)));
break;
// hexa8 volume
case 8:
// face 1 = N1, N2, N3, N4
// face 2 = N5, N8, N7, N6
// face 3 = N1, N5, N6, N2
// face 4 = N2, N6, N7, N3
// face 5 = N3, N7, N8, N4
// face 6 = N4, N8, N5, N1
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(),
2,
aVol->GetNode(4),
aVol->GetNode(7),
aVol->GetNode(6),
aVol->GetNode(5)));
BndBox.Add(facesHelper[i++].set(4,
aVol,
aVol->GetID(),
3,
aVol->GetNode(0),
aVol->GetNode(4),
aVol->GetNode(5),
aVol->GetNode(1)));
BndBox.Add(facesHelper[i++].set(4,
aVol,
aVol->GetID(),
4,
aVol->GetNode(1),
aVol->GetNode(5),
aVol->GetNode(6),
aVol->GetNode(2)));
BndBox.Add(facesHelper[i++].set(4,
aVol,
aVol->GetID(),
5,
aVol->GetNode(2),
aVol->GetNode(6),
aVol->GetNode(7),
aVol->GetNode(3)));
BndBox.Add(facesHelper[i++].set(4,
aVol,
aVol->GetID(),
6,
aVol->GetNode(3),
aVol->GetNode(7),
aVol->GetNode(4),
aVol->GetNode(0)));
break;
// tetra10 volume
case 10:
// face 1 = N1, N5, N2, N6, N3, N7
// face 2 = N1, N8, N4, N9, N2, N5
// face 3 = N2, N9, N4, N10, N3, N6
// face 4 = N3, N10, N4, N8, N1, N7
BndBox.Add(facesHelper[i++].set(6,
aVol,
aVol->GetID(),
1,
aVol->GetNode(0),
aVol->GetNode(4),
aVol->GetNode(1),
aVol->GetNode(5),
aVol->GetNode(2),
aVol->GetNode(6)));
BndBox.Add(facesHelper[i++].set(6,
aVol,
aVol->GetID(),
2,
aVol->GetNode(0),
aVol->GetNode(7),
aVol->GetNode(3),
aVol->GetNode(8),
aVol->GetNode(1),
aVol->GetNode(4)));
BndBox.Add(facesHelper[i++].set(6,
aVol,
aVol->GetID(),
3,
aVol->GetNode(1),
aVol->GetNode(8),
aVol->GetNode(3),
aVol->GetNode(9),
aVol->GetNode(2),
aVol->GetNode(5)));
BndBox.Add(facesHelper[i++].set(6,
aVol,
aVol->GetID(),
4,
aVol->GetNode(2),
aVol->GetNode(9),
aVol->GetNode(3),
aVol->GetNode(7),
aVol->GetNode(0),
aVol->GetNode(6)));
break;
// pyra13 volume
case 13:
// face 1 = N1, N6, N2, N7, N3, N8, N4, N9
// face 2 = N1, N10, N5, N11, N2, N6
// face 3 = N2, N11, N5, N12, N3, N7
// face 4 = N3, N12, N5, N13, N4, N8
// face 5 = N4, N13, N5, N10, N1, N9
BndBox.Add(facesHelper[i++].set(8,
aVol,
aVol->GetID(),
1,
aVol->GetNode(0),
aVol->GetNode(5),
aVol->GetNode(1),
aVol->GetNode(6),
aVol->GetNode(2),
aVol->GetNode(7),
aVol->GetNode(3),
aVol->GetNode(8)));
BndBox.Add(facesHelper[i++].set(6,
aVol,
aVol->GetID(),
2,
aVol->GetNode(0),
aVol->GetNode(9),
aVol->GetNode(4),
aVol->GetNode(10),
aVol->GetNode(1),
aVol->GetNode(5)));
BndBox.Add(facesHelper[i++].set(6,
aVol,
aVol->GetID(),
3,
aVol->GetNode(1),
aVol->GetNode(10),
aVol->GetNode(4),
aVol->GetNode(11),
aVol->GetNode(2),
aVol->GetNode(6)));
BndBox.Add(facesHelper[i++].set(6,
aVol,
aVol->GetID(),
4,
aVol->GetNode(2),
aVol->GetNode(11),
aVol->GetNode(4),
aVol->GetNode(12),
aVol->GetNode(3),
aVol->GetNode(7)));
BndBox.Add(facesHelper[i++].set(6,
aVol,
aVol->GetID(),
5,
aVol->GetNode(3),
aVol->GetNode(12),
aVol->GetNode(4),
aVol->GetNode(9),
aVol->GetNode(0),
aVol->GetNode(8)));
break;
// penta15 volume
case 15:
// face 1 = N1, N7, N2, N8, N3, N9
// face 2 = N4, N12, N6, N11, N5, N10
// face 3 = N1, N13, N4, N10, N5, N14, N2, N7
// face 4 = N2, N14, N5, N11, N6, N15, N3, N8
// face 5 = N3, N15, N6, N12, N4, N13, N1, N9
BndBox.Add(facesHelper[i++].set(6,
aVol,
aVol->GetID(),
1,
aVol->GetNode(0),
aVol->GetNode(6),
aVol->GetNode(1),
aVol->GetNode(7),
aVol->GetNode(2),
aVol->GetNode(8)));
BndBox.Add(facesHelper[i++].set(6,
aVol,
aVol->GetID(),
2,
aVol->GetNode(3),
aVol->GetNode(11),
aVol->GetNode(5),
aVol->GetNode(10),
aVol->GetNode(4),
aVol->GetNode(9)));
BndBox.Add(facesHelper[i++].set(8,
aVol,
aVol->GetID(),
3,
aVol->GetNode(0),
aVol->GetNode(12),
aVol->GetNode(3),
aVol->GetNode(9),
aVol->GetNode(4),
aVol->GetNode(13),
aVol->GetNode(1),
aVol->GetNode(6)));
BndBox.Add(facesHelper[i++].set(8,
aVol,
aVol->GetID(),
4,
aVol->GetNode(1),
aVol->GetNode(13),
aVol->GetNode(4),
aVol->GetNode(10),
aVol->GetNode(5),
aVol->GetNode(14),
aVol->GetNode(2),
aVol->GetNode(7)));
BndBox.Add(facesHelper[i++].set(8,
aVol,
aVol->GetID(),
5,
aVol->GetNode(2),
aVol->GetNode(14),
aVol->GetNode(5),
aVol->GetNode(11),
aVol->GetNode(3),
aVol->GetNode(12),
aVol->GetNode(0),
aVol->GetNode(8)));
break;
// hexa20 volume
case 20:
// face 1 = N1, N9, N2, N10, N3, N11, N4, N12
// face 2 = N5, N16, N8, N15, N7, N14, N6, N13
// face 3 = N1, N17, N5, N13, N6, N18, N2, N9
// face 4 = N2, N18, N6, N14, N7, N19, N3, N10
// face 5 = N3, N19, N7, N15, N8, N20, N4, N11
// face 6 = N4, N20, N8, N16, N5, N17, N1, N12
BndBox.Add(facesHelper[i++].set(8,
aVol,
aVol->GetID(),
1,
aVol->GetNode(0),
aVol->GetNode(8),
aVol->GetNode(1),
aVol->GetNode(9),
aVol->GetNode(2),
aVol->GetNode(10),
aVol->GetNode(3),
aVol->GetNode(11)));
BndBox.Add(facesHelper[i++].set(8,
aVol,
aVol->GetID(),
2,
aVol->GetNode(4),
aVol->GetNode(15),
aVol->GetNode(7),
aVol->GetNode(14),
aVol->GetNode(6),
aVol->GetNode(13),
aVol->GetNode(5),
aVol->GetNode(12)));
BndBox.Add(facesHelper[i++].set(8,
aVol,
aVol->GetID(),
3,
aVol->GetNode(0),
aVol->GetNode(16),
aVol->GetNode(4),
aVol->GetNode(12),
aVol->GetNode(5),
aVol->GetNode(17),
aVol->GetNode(1),
aVol->GetNode(8)));
BndBox.Add(facesHelper[i++].set(8,
aVol,
aVol->GetID(),
4,
aVol->GetNode(1),
aVol->GetNode(17),
aVol->GetNode(5),
aVol->GetNode(13),
aVol->GetNode(6),
aVol->GetNode(18),
aVol->GetNode(2),
aVol->GetNode(9)));
BndBox.Add(facesHelper[i++].set(8,
aVol,
aVol->GetID(),
5,
aVol->GetNode(2),
aVol->GetNode(18),
aVol->GetNode(6),
aVol->GetNode(14),
aVol->GetNode(7),
aVol->GetNode(19),
aVol->GetNode(3),
aVol->GetNode(10)));
BndBox.Add(facesHelper[i++].set(8,
aVol,
aVol->GetID(),
6,
aVol->GetNode(3),
aVol->GetNode(19),
aVol->GetNode(7),
aVol->GetNode(15),
aVol->GetNode(4),
aVol->GetNode(16),
aVol->GetNode(0),
aVol->GetNode(11)));
break;
// unknown volume type
default:
throw std::runtime_error("Node count not supported by ViewProviderFemMesh, "
"[4|5|6|8|10|13|15|20] are allowed");
}
}
}
int FaceSize = facesHelper.size();
if (FaceSize < MaxFacesShowInner) {
Base::Console().Log(" %f: Start eliminate internal faces SIMPLE\n",
Base::TimeElapsed::diffTimeF(Start, Base::TimeElapsed()));
// 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;
}
}
}
}
}
}
else {
Base::Console().Log(" %f: Start eliminate internal faces GRID\n",
Base::TimeElapsed::diffTimeF(Start, Base::TimeElapsed()));
BndBox.Enlarge(BndBox.CalcDiagonalLength() / 10000.0);
// calculate grid properties
double edge = pow(FaceSize, 1.0 / 3.0);
double edgeL = BndBox.LengthX() + BndBox.LengthY() + BndBox.LengthZ();
double gridFactor = 5.0;
double size = (edgeL / (3 * edge)) * gridFactor;
unsigned int NbrX = (unsigned int)(BndBox.LengthX() / size) + 1;
unsigned int NbrY = (unsigned int)(BndBox.LengthY() / size) + 1;
unsigned int NbrZ = (unsigned int)(BndBox.LengthZ() / size) + 1;
Base::Console().Log(" Size:F:%f, X:%i ,Y:%i ,Z:%i\n", gridFactor, NbrX, NbrY, NbrZ);
double Xmin = BndBox.MinX;
double Ymin = BndBox.MinY;
double Zmin = BndBox.MinZ;
double Xln = BndBox.LengthX() / NbrX;
double Yln = BndBox.LengthY() / NbrY;
double Zln = BndBox.LengthZ() / NbrZ;
std::vector<FemFaceGridItem> 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 (const auto& it : Grid) {
for (size_t l = 0; l < it.size(); l++) {
if (!it[l]->hide) {
for (size_t i = l + 1; i < it.size(); i++) {
if (it[l]->isSameFace(*(it[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::TimeElapsed::diffTimeF(Start, Base::TimeElapsed()));
// sort out double nodes and build up index map
std::map<const SMDS_MeshNode*, int> mapNodeIndex;
// 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 (auto Node : facesHelper[l].Nodes) {
if (Node) {
mapNodeIndex[Node] = 0;
}
else {
break;
}
}
}
}
}
Base::Console().Log(" %f: Start set point vector\n",
Base::TimeElapsed::diffTimeF(Start, Base::TimeElapsed()));
// set the point coordinates
coords->point.setNum(mapNodeIndex.size());
vNodeElementIdx.resize(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;
// set selection idx
vNodeElementIdx[i] = it->first->GetID();
}
coords->point.finishEditing();
// count triangle size
Base::Console().Log(" %f: Start count triangle size\n",
Base::TimeElapsed::diffTimeF(Start, Base::TimeElapsed()));
int triangleCount = 0;
for (int l = 0; l < FaceSize; l++) {
if (!facesHelper[l].hide) {
switch (facesHelper[l].Size) {
case 3:
triangleCount++;
break; // 3-node triangle face --> 1 triangle
case 4:
triangleCount += 2;
break; // 4-node quadrangle face --> 2 triangles
case 6:
triangleCount += 4;
break; // 6-node triangle face --> 4 triangles
case 8:
triangleCount += 6;
break; // 8-node quadrangle face --> 6 triangles
default:
throw std::runtime_error(
"Face with unknown node count found, only display mode nodes is supported "
"for this element (tiangleCount)");
}
}
}
Base::Console().Log(" NumTriangles:%i\n", triangleCount);
// 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: { // Seg2: N1, N2
int nIdx0 = mapNodeIndex[aEdge->GetNode(0)];
int nIdx1 = mapNodeIndex[aEdge->GetNode(1)];
insEdgeVec(EdgeMap, nIdx0, nIdx1);
break;
}
case 3: { // Seg3: N1, N2, N3 (N3 is middle Node)
int nIdx0 = mapNodeIndex[aEdge->GetNode(0)];
int nIdx1 = mapNodeIndex[aEdge->GetNode(1)];
int nIdx2 = mapNodeIndex[aEdge->GetNode(2)];
insEdgeVec(EdgeMap, nIdx0, nIdx2);
insEdgeVec(EdgeMap, nIdx2, nIdx1);
break;
}
}
}
}
Base::Console().Log(" %f: Start build up triangle vector\n",
Base::TimeElapsed::diffTimeF(Start, Base::TimeElapsed()));
// 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 non-hidden element faces, always assure CLOCKWISE triangle ordering to allow
// backface culling
for (int l = 0; l < FaceSize; l++) {
if (!facesHelper[l].hide) {
switch (facesHelper[l].Element->NbNodes()) {
// 3 nodes
case 3:
// tria3 face
switch (facesHelper[l].FaceNo) {
case 0: { // tria3 face, 3-node triangle
// 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)];
// create triangle number 1
// ---------------------------------------------- fill in the node
// indexes in CLOCKWISE order
indices[index++] = nIdx0;
indices[index++] = nIdx1;
indices[index++] = nIdx2;
indices[index++] = SO_END_FACE_INDEX;
// add the three edge segments for that triangle
insEdgeVec(EdgeMap, nIdx0, nIdx1);
insEdgeVec(EdgeMap, nIdx1, nIdx2);
insEdgeVec(EdgeMap, nIdx2, nIdx0);
// remember the element and face number for that triangle
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 0);
break;
}
default:
assert(0);
}
break;
// 4 nodes
case 4:
// quad4 face
// tetra4 volume, four 3-node triangles
switch (facesHelper[l].FaceNo) {
case 0: { // quad4 face, 4-node quadrangle
// 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)];
// create triangle number 1
// ---------------------------------------------- fill in the node
// indexes in CLOCKWISE order
indices[index++] = nIdx0;
indices[index++] = nIdx1;
indices[index++] = nIdx2;
indices[index++] = SO_END_FACE_INDEX;
// add the two edge segments for that triangle
insEdgeVec(EdgeMap, nIdx0, nIdx1);
insEdgeVec(EdgeMap, nIdx1, nIdx2);
// remember the element and face number for that triangle
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 0);
// create triangle number 2
// ----------------------------------------------
indices[index++] = nIdx2;
indices[index++] = nIdx3;
indices[index++] = nIdx0;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx2, nIdx3);
insEdgeVec(EdgeMap, nIdx3, nIdx0);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 0);
break;
}
case 1: { // tetra4 volume: face 1, 3-node triangle
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++] = nIdx0;
indices[index++] = nIdx1;
indices[index++] = nIdx2;
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;
}
case 2: { // tetra4 volume: face 2, 3-node triangle
int nIdx0 = mapNodeIndex[facesHelper[l].Element->GetNode(0)];
int nIdx1 = mapNodeIndex[facesHelper[l].Element->GetNode(3)];
int nIdx2 = mapNodeIndex[facesHelper[l].Element->GetNode(1)];
indices[index++] = nIdx0;
indices[index++] = nIdx1;
indices[index++] = nIdx2;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx0, nIdx1);
insEdgeVec(EdgeMap, nIdx1, nIdx2);
insEdgeVec(EdgeMap, nIdx2, nIdx0);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 1);
break;
}
case 3: { // tetra4 volume: face 3, 3-node triangle
int nIdx0 = mapNodeIndex[facesHelper[l].Element->GetNode(1)];
int nIdx1 = mapNodeIndex[facesHelper[l].Element->GetNode(3)];
int nIdx2 = mapNodeIndex[facesHelper[l].Element->GetNode(2)];
indices[index++] = nIdx0;
indices[index++] = nIdx1;
indices[index++] = nIdx2;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx0, nIdx1);
insEdgeVec(EdgeMap, nIdx1, nIdx2);
insEdgeVec(EdgeMap, nIdx2, nIdx0);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 2);
break;
}
case 4: { // tetra4 volume: face 4, 3-node triangle
int nIdx0 = mapNodeIndex[facesHelper[l].Element->GetNode(2)];
int nIdx1 = mapNodeIndex[facesHelper[l].Element->GetNode(3)];
int nIdx2 = mapNodeIndex[facesHelper[l].Element->GetNode(0)];
indices[index++] = nIdx0;
indices[index++] = nIdx1;
indices[index++] = nIdx2;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx0, nIdx1);
insEdgeVec(EdgeMap, nIdx1, nIdx2);
insEdgeVec(EdgeMap, nIdx2, nIdx0);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 3);
break;
}
default:
assert(0);
}
break;
// 5 nodes
case 5:
// pyra5 volume, one 4-node quadrangle and four 3-node triangles
switch (facesHelper[l].FaceNo) {
case 1: { // pyra5 volume: face 1, 4-node quadrangle
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++] = nIdx2;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx0, nIdx1);
insEdgeVec(EdgeMap, nIdx1, nIdx2);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 0);
indices[index++] = nIdx2;
indices[index++] = nIdx3;
indices[index++] = nIdx0;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx2, nIdx3);
insEdgeVec(EdgeMap, nIdx3, nIdx0);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 0);
break;
}
case 2: { // pyra5 volume: face 2, 3-node triangle
int nIdx0 = mapNodeIndex[facesHelper[l].Element->GetNode(0)];
int nIdx1 = mapNodeIndex[facesHelper[l].Element->GetNode(4)];
int nIdx2 = mapNodeIndex[facesHelper[l].Element->GetNode(1)];
indices[index++] = nIdx0;
indices[index++] = nIdx1;
indices[index++] = nIdx2;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx0, nIdx1);
insEdgeVec(EdgeMap, nIdx1, nIdx2);
insEdgeVec(EdgeMap, nIdx2, nIdx0);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 1);
break;
}
case 3: { // pyra5 volume: face 3, 3-node triangle
int nIdx0 = mapNodeIndex[facesHelper[l].Element->GetNode(1)];
int nIdx1 = mapNodeIndex[facesHelper[l].Element->GetNode(4)];
int nIdx2 = mapNodeIndex[facesHelper[l].Element->GetNode(2)];
indices[index++] = nIdx0;
indices[index++] = nIdx1;
indices[index++] = nIdx2;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx0, nIdx1);
insEdgeVec(EdgeMap, nIdx1, nIdx2);
insEdgeVec(EdgeMap, nIdx2, nIdx0);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 2);
break;
}
case 4: { // pyra5 volume: face 4, 3-node triangle
int nIdx0 = mapNodeIndex[facesHelper[l].Element->GetNode(2)];
int nIdx1 = mapNodeIndex[facesHelper[l].Element->GetNode(4)];
int nIdx2 = mapNodeIndex[facesHelper[l].Element->GetNode(3)];
indices[index++] = nIdx0;
indices[index++] = nIdx1;
indices[index++] = nIdx2;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx0, nIdx1);
insEdgeVec(EdgeMap, nIdx1, nIdx2);
insEdgeVec(EdgeMap, nIdx2, nIdx0);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 3);
break;
}
case 5: { // pyra5 volume: face 5, 3-node triangle
int nIdx0 = mapNodeIndex[facesHelper[l].Element->GetNode(3)];
int nIdx1 = mapNodeIndex[facesHelper[l].Element->GetNode(4)];
int nIdx2 = mapNodeIndex[facesHelper[l].Element->GetNode(0)];
indices[index++] = nIdx0;
indices[index++] = nIdx1;
indices[index++] = nIdx2;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx0, nIdx1);
insEdgeVec(EdgeMap, nIdx1, nIdx2);
insEdgeVec(EdgeMap, nIdx2, nIdx0);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 4);
break;
}
default:
assert(0);
}
break;
// 6 nodes
case 6:
// tria6 face
// penta6 volume, two 3-node triangle and three 4-node quadrangles
switch (facesHelper[l].FaceNo) {
case 0: { // tria6 face, 6-node triangle
// prefeche all node indexes of this face
int nIdx0 = mapNodeIndex[facesHelper[l].Element->GetNode(0)];
int nIdx1 = mapNodeIndex[facesHelper[l].Element->GetNode(3)];
int nIdx2 = mapNodeIndex[facesHelper[l].Element->GetNode(1)];
int nIdx3 = mapNodeIndex[facesHelper[l].Element->GetNode(4)];
int nIdx4 = mapNodeIndex[facesHelper[l].Element->GetNode(2)];
int nIdx5 = mapNodeIndex[facesHelper[l].Element->GetNode(5)];
// create triangle number 1
// ---------------------------------------------- fill in the node
// indexes in CLOCKWISE order
indices[index++] = nIdx5;
indices[index++] = nIdx0;
indices[index++] = nIdx1;
indices[index++] = SO_END_FACE_INDEX;
// add the two edge segments for that triangle
insEdgeVec(EdgeMap, nIdx5, nIdx0);
insEdgeVec(EdgeMap, nIdx0, nIdx1);
// remember the element and face number for that triangle
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 0);
// create triangle number 2
// ----------------------------------------------
indices[index++] = nIdx1;
indices[index++] = nIdx2;
indices[index++] = nIdx3;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx1, nIdx2);
insEdgeVec(EdgeMap, nIdx2, nIdx3);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 0);
// create triangle number 3
// ----------------------------------------------
indices[index++] = nIdx3;
indices[index++] = nIdx4;
indices[index++] = nIdx5;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx3, nIdx4);
insEdgeVec(EdgeMap, nIdx4, nIdx5);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 0);
// create triangle number 4
// ----------------------------------------------
indices[index++] = nIdx1;
indices[index++] = nIdx3;
indices[index++] = nIdx5;
indices[index++] = SO_END_FACE_INDEX;
// this triangle has no edge (inner triangle).
break;
}
case 1: { // penta6 volume: face 1, 3-node triangle
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++] = nIdx0;
indices[index++] = nIdx1;
indices[index++] = nIdx2;
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;
}
case 2: { // penta6 volume: face 2, 3-node triangle
int nIdx3 = mapNodeIndex[facesHelper[l].Element->GetNode(3)];
int nIdx5 = mapNodeIndex[facesHelper[l].Element->GetNode(5)];
int nIdx4 = mapNodeIndex[facesHelper[l].Element->GetNode(4)];
indices[index++] = nIdx3;
indices[index++] = nIdx5;
indices[index++] = nIdx4;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx3, nIdx5);
insEdgeVec(EdgeMap, nIdx5, nIdx4);
insEdgeVec(EdgeMap, nIdx4, nIdx3);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 1);
break;
}
case 3: { // penta6 volume: face 3, 4-node quadrangle
int nIdx0 = mapNodeIndex[facesHelper[l].Element->GetNode(0)];
int nIdx1 = mapNodeIndex[facesHelper[l].Element->GetNode(3)];
int nIdx2 = mapNodeIndex[facesHelper[l].Element->GetNode(4)];
int nIdx3 = mapNodeIndex[facesHelper[l].Element->GetNode(1)];
indices[index++] = nIdx0;
indices[index++] = nIdx1;
indices[index++] = nIdx2;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx0, nIdx1);
insEdgeVec(EdgeMap, nIdx1, nIdx2);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 2);
indices[index++] = nIdx2;
indices[index++] = nIdx3;
indices[index++] = nIdx0;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx2, nIdx3);
insEdgeVec(EdgeMap, nIdx3, nIdx0);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 2);
break;
}
case 4: { // penta6 volume: face 4, 4-node quadrangle
int nIdx0 = mapNodeIndex[facesHelper[l].Element->GetNode(1)];
int nIdx1 = mapNodeIndex[facesHelper[l].Element->GetNode(4)];
int nIdx2 = mapNodeIndex[facesHelper[l].Element->GetNode(5)];
int nIdx3 = mapNodeIndex[facesHelper[l].Element->GetNode(2)];
indices[index++] = nIdx0;
indices[index++] = nIdx1;
indices[index++] = nIdx2;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx0, nIdx1);
insEdgeVec(EdgeMap, nIdx1, nIdx2);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 3);
indices[index++] = nIdx2;
indices[index++] = nIdx3;
indices[index++] = nIdx0;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx2, nIdx3);
insEdgeVec(EdgeMap, nIdx3, nIdx0);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 3);
break;
}
case 5: { // penta6 volume: face 5, 4-node quadrangle
int nIdx0 = mapNodeIndex[facesHelper[l].Element->GetNode(2)];
int nIdx1 = mapNodeIndex[facesHelper[l].Element->GetNode(5)];
int nIdx2 = mapNodeIndex[facesHelper[l].Element->GetNode(3)];
int nIdx3 = mapNodeIndex[facesHelper[l].Element->GetNode(0)];
indices[index++] = nIdx0;
indices[index++] = nIdx1;
indices[index++] = nIdx2;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx0, nIdx1);
insEdgeVec(EdgeMap, nIdx1, nIdx2);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 4);
indices[index++] = nIdx2;
indices[index++] = nIdx3;
indices[index++] = nIdx0;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx2, nIdx3);
insEdgeVec(EdgeMap, nIdx3, nIdx0);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 4);
break;
}
default:
assert(0);
}
break;
// 8 nodes
case 8:
// quad8 face
// hexa8 volume, six 4-node quadrangles
switch (facesHelper[l].FaceNo) {
case 0: { // quad8 face, 8-node quadrangle
// prefeche all node indexes of this face
int nIdx0 = mapNodeIndex[facesHelper[l].Element->GetNode(0)];
int nIdx1 = mapNodeIndex[facesHelper[l].Element->GetNode(4)];
int nIdx2 = mapNodeIndex[facesHelper[l].Element->GetNode(1)];
int nIdx3 = mapNodeIndex[facesHelper[l].Element->GetNode(5)];
int nIdx4 = mapNodeIndex[facesHelper[l].Element->GetNode(2)];
int nIdx5 = mapNodeIndex[facesHelper[l].Element->GetNode(6)];
int nIdx6 = mapNodeIndex[facesHelper[l].Element->GetNode(3)];
int nIdx7 = mapNodeIndex[facesHelper[l].Element->GetNode(7)];
// create triangle number 1
// ---------------------------------------------- fill in the node
// indexes in CLOCKWISE order
indices[index++] = nIdx7;
indices[index++] = nIdx0;
indices[index++] = nIdx1;
indices[index++] = SO_END_FACE_INDEX;
// add the two edge segments for that triangle
insEdgeVec(EdgeMap, nIdx7, nIdx0);
insEdgeVec(EdgeMap, nIdx0, nIdx1);
// remember the element and face number for that triangle
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 0);
// create triangle number 2
// ----------------------------------------------
indices[index++] = nIdx1;
indices[index++] = nIdx2;
indices[index++] = nIdx3;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx1, nIdx2);
insEdgeVec(EdgeMap, nIdx2, nIdx3);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 0);
// create triangle number 3
// ----------------------------------------------
indices[index++] = nIdx3;
indices[index++] = nIdx4;
indices[index++] = nIdx5;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx3, nIdx4);
insEdgeVec(EdgeMap, nIdx4, nIdx5);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 0);
// create triangle number 4
// ----------------------------------------------
indices[index++] = nIdx5;
indices[index++] = nIdx6;
indices[index++] = nIdx7;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx5, nIdx6);
insEdgeVec(EdgeMap, nIdx6, nIdx7);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 0);
// create triangle number 5
// ----------------------------------------------
indices[index++] = nIdx7;
indices[index++] = nIdx1;
indices[index++] = nIdx3;
indices[index++] = SO_END_FACE_INDEX;
// this triangle has no edge (inner triangle)
// create triangle number 6
// ----------------------------------------------
indices[index++] = nIdx3;
indices[index++] = nIdx5;
indices[index++] = nIdx7;
indices[index++] = SO_END_FACE_INDEX;
// this triangle has no edge (inner triangle)
break;
}
case 1: { // hexa8 volume: face 1, 4-node quadrangle
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++] = nIdx2;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx0, nIdx1);
insEdgeVec(EdgeMap, nIdx1, nIdx2);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 0);
indices[index++] = nIdx2;
indices[index++] = nIdx3;
indices[index++] = nIdx0;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx2, nIdx3);
insEdgeVec(EdgeMap, nIdx3, nIdx0);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 0);
break;
}
case 2: { // hexa8 volume: face 2, 4-node quadrangle
int nIdx0 = mapNodeIndex[facesHelper[l].Element->GetNode(4)];
int nIdx1 = mapNodeIndex[facesHelper[l].Element->GetNode(7)];
int nIdx2 = mapNodeIndex[facesHelper[l].Element->GetNode(6)];
int nIdx3 = mapNodeIndex[facesHelper[l].Element->GetNode(5)];
indices[index++] = nIdx0;
indices[index++] = nIdx1;
indices[index++] = nIdx2;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx0, nIdx1);
insEdgeVec(EdgeMap, nIdx1, nIdx2);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 1);
indices[index++] = nIdx2;
indices[index++] = nIdx3;
indices[index++] = nIdx0;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx2, nIdx3);
insEdgeVec(EdgeMap, nIdx3, nIdx0);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 1);
break;
}
case 3: { // hexa8 volume: face 3, 4-node quadrangle
int nIdx0 = mapNodeIndex[facesHelper[l].Element->GetNode(0)];
int nIdx1 = mapNodeIndex[facesHelper[l].Element->GetNode(4)];
int nIdx2 = mapNodeIndex[facesHelper[l].Element->GetNode(5)];
int nIdx3 = mapNodeIndex[facesHelper[l].Element->GetNode(1)];
indices[index++] = nIdx0;
indices[index++] = nIdx1;
indices[index++] = nIdx2;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx0, nIdx1);
insEdgeVec(EdgeMap, nIdx1, nIdx2);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 2);
indices[index++] = nIdx2;
indices[index++] = nIdx3;
indices[index++] = nIdx0;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx2, nIdx3);
insEdgeVec(EdgeMap, nIdx3, nIdx0);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 2);
break;
}
case 4: { // hexa8 volume: face 4, 4-node quadrangle
int nIdx0 = mapNodeIndex[facesHelper[l].Element->GetNode(1)];
int nIdx1 = mapNodeIndex[facesHelper[l].Element->GetNode(5)];
int nIdx2 = mapNodeIndex[facesHelper[l].Element->GetNode(6)];
int nIdx3 = mapNodeIndex[facesHelper[l].Element->GetNode(2)];
indices[index++] = nIdx0;
indices[index++] = nIdx1;
indices[index++] = nIdx2;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx0, nIdx1);
insEdgeVec(EdgeMap, nIdx1, nIdx2);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 3);
indices[index++] = nIdx2;
indices[index++] = nIdx3;
indices[index++] = nIdx0;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx2, nIdx3);
insEdgeVec(EdgeMap, nIdx3, nIdx0);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 3);
break;
}
case 5: { // hexa8 volume: face 5, 4-node quadrangle
int nIdx0 = mapNodeIndex[facesHelper[l].Element->GetNode(2)];
int nIdx1 = mapNodeIndex[facesHelper[l].Element->GetNode(6)];
int nIdx2 = mapNodeIndex[facesHelper[l].Element->GetNode(7)];
int nIdx3 = mapNodeIndex[facesHelper[l].Element->GetNode(3)];
indices[index++] = nIdx0;
indices[index++] = nIdx1;
indices[index++] = nIdx2;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx0, nIdx1);
insEdgeVec(EdgeMap, nIdx1, nIdx2);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 4);
indices[index++] = nIdx2;
indices[index++] = nIdx3;
indices[index++] = nIdx0;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx2, nIdx3);
insEdgeVec(EdgeMap, nIdx3, nIdx0);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 4);
break;
}
case 6: { // hexa8 volume: face 6, 4-node quadrangle
int nIdx0 = mapNodeIndex[facesHelper[l].Element->GetNode(3)];
int nIdx1 = mapNodeIndex[facesHelper[l].Element->GetNode(7)];
int nIdx2 = mapNodeIndex[facesHelper[l].Element->GetNode(4)];
int nIdx3 = mapNodeIndex[facesHelper[l].Element->GetNode(0)];
indices[index++] = nIdx0;
indices[index++] = nIdx1;
indices[index++] = nIdx2;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx0, nIdx1);
insEdgeVec(EdgeMap, nIdx1, nIdx2);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 5);
indices[index++] = nIdx2;
indices[index++] = nIdx3;
indices[index++] = nIdx0;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx2, nIdx3);
insEdgeVec(EdgeMap, nIdx3, nIdx0);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 5);
break;
}
default:
assert(0);
}
break;
// 10 nodes
case 10:
// tetra10 volume, four 6-node triangles
switch (facesHelper[l].FaceNo) {
case 1: { // tetra10 volume: face 1, 6-node triangle
int nIdx0 = mapNodeIndex[facesHelper[l].Element->GetNode(0)];
int nIdx1 = mapNodeIndex[facesHelper[l].Element->GetNode(4)];
int nIdx2 = mapNodeIndex[facesHelper[l].Element->GetNode(1)];
int nIdx3 = mapNodeIndex[facesHelper[l].Element->GetNode(5)];
int nIdx4 = mapNodeIndex[facesHelper[l].Element->GetNode(2)];
int nIdx5 = mapNodeIndex[facesHelper[l].Element->GetNode(6)];
indices[index++] = nIdx5;
indices[index++] = nIdx0;
indices[index++] = nIdx1;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx5, nIdx0);
insEdgeVec(EdgeMap, nIdx0, nIdx1);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 0);
indices[index++] = nIdx1;
indices[index++] = nIdx2;
indices[index++] = nIdx3;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx1, nIdx2);
insEdgeVec(EdgeMap, nIdx2, nIdx3);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 0);
indices[index++] = nIdx3;
indices[index++] = nIdx4;
indices[index++] = nIdx5;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx3, nIdx4);
insEdgeVec(EdgeMap, nIdx4, nIdx5);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 0);
indices[index++] = nIdx1;
indices[index++] = nIdx3;
indices[index++] = nIdx5;
indices[index++] = SO_END_FACE_INDEX;
break;
}
case 2: { // tetra10 volume: face 2, 6-node triangle
int nIdx0 = mapNodeIndex[facesHelper[l].Element->GetNode(0)];
int nIdx1 = mapNodeIndex[facesHelper[l].Element->GetNode(7)];
int nIdx2 = mapNodeIndex[facesHelper[l].Element->GetNode(3)];
int nIdx3 = mapNodeIndex[facesHelper[l].Element->GetNode(8)];
int nIdx4 = mapNodeIndex[facesHelper[l].Element->GetNode(1)];
int nIdx5 = mapNodeIndex[facesHelper[l].Element->GetNode(4)];
indices[index++] = nIdx5;
indices[index++] = nIdx0;
indices[index++] = nIdx1;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx5, nIdx0);
insEdgeVec(EdgeMap, nIdx0, nIdx1);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 1);
indices[index++] = nIdx1;
indices[index++] = nIdx2;
indices[index++] = nIdx3;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx1, nIdx2);
insEdgeVec(EdgeMap, nIdx2, nIdx3);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 1);
indices[index++] = nIdx3;
indices[index++] = nIdx4;
indices[index++] = nIdx5;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx3, nIdx4);
insEdgeVec(EdgeMap, nIdx4, nIdx5);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 1);
indices[index++] = nIdx1;
indices[index++] = nIdx3;
indices[index++] = nIdx5;
indices[index++] = SO_END_FACE_INDEX;
break;
}
case 3: { // tetra10 volume: face 3, 6-node triangle
int nIdx0 = mapNodeIndex[facesHelper[l].Element->GetNode(1)];
int nIdx1 = mapNodeIndex[facesHelper[l].Element->GetNode(8)];
int nIdx2 = mapNodeIndex[facesHelper[l].Element->GetNode(3)];
int nIdx3 = mapNodeIndex[facesHelper[l].Element->GetNode(9)];
int nIdx4 = mapNodeIndex[facesHelper[l].Element->GetNode(2)];
int nIdx5 = mapNodeIndex[facesHelper[l].Element->GetNode(5)];
indices[index++] = nIdx5;
indices[index++] = nIdx0;
indices[index++] = nIdx1;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx5, nIdx0);
insEdgeVec(EdgeMap, nIdx0, nIdx1);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 2);
indices[index++] = nIdx1;
indices[index++] = nIdx2;
indices[index++] = nIdx3;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx1, nIdx2);
insEdgeVec(EdgeMap, nIdx2, nIdx3);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 2);
indices[index++] = nIdx3;
indices[index++] = nIdx4;
indices[index++] = nIdx5;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx3, nIdx4);
insEdgeVec(EdgeMap, nIdx4, nIdx5);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 2);
indices[index++] = nIdx1;
indices[index++] = nIdx3;
indices[index++] = nIdx5;
indices[index++] = SO_END_FACE_INDEX;
break;
}
case 4: { // tetra10 volume: face 4, 6-node triangle
int nIdx0 = mapNodeIndex[facesHelper[l].Element->GetNode(2)];
int nIdx1 = mapNodeIndex[facesHelper[l].Element->GetNode(9)];
int nIdx2 = mapNodeIndex[facesHelper[l].Element->GetNode(3)];
int nIdx3 = mapNodeIndex[facesHelper[l].Element->GetNode(7)];
int nIdx4 = mapNodeIndex[facesHelper[l].Element->GetNode(0)];
int nIdx5 = mapNodeIndex[facesHelper[l].Element->GetNode(6)];
indices[index++] = nIdx5;
indices[index++] = nIdx0;
indices[index++] = nIdx1;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx5, nIdx0);
insEdgeVec(EdgeMap, nIdx0, nIdx1);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 3);
indices[index++] = nIdx1;
indices[index++] = nIdx2;
indices[index++] = nIdx3;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx1, nIdx2);
insEdgeVec(EdgeMap, nIdx2, nIdx3);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 3);
indices[index++] = nIdx3;
indices[index++] = nIdx4;
indices[index++] = nIdx5;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx3, nIdx4);
insEdgeVec(EdgeMap, nIdx4, nIdx5);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 3);
indices[index++] = nIdx1;
indices[index++] = nIdx3;
indices[index++] = nIdx5;
indices[index++] = SO_END_FACE_INDEX;
break;
}
default:
assert(0);
}
break;
// 13 nodes
case 13:
// pyra13 volume, four 6-node triangle and one 8-node quadrangles
switch (facesHelper[l].FaceNo) {
case 1: { // pyra13 volume: face 1, 8-node quadrangles
int nIdx0 = mapNodeIndex[facesHelper[l].Element->GetNode(0)];
int nIdx1 = mapNodeIndex[facesHelper[l].Element->GetNode(5)];
int nIdx2 = mapNodeIndex[facesHelper[l].Element->GetNode(1)];
int nIdx3 = mapNodeIndex[facesHelper[l].Element->GetNode(6)];
int nIdx4 = mapNodeIndex[facesHelper[l].Element->GetNode(2)];
int nIdx5 = mapNodeIndex[facesHelper[l].Element->GetNode(7)];
int nIdx6 = mapNodeIndex[facesHelper[l].Element->GetNode(3)];
int nIdx7 = mapNodeIndex[facesHelper[l].Element->GetNode(8)];
indices[index++] = nIdx7;
indices[index++] = nIdx0;
indices[index++] = nIdx1;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx7, nIdx0);
insEdgeVec(EdgeMap, nIdx0, nIdx1);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 0);
indices[index++] = nIdx1;
indices[index++] = nIdx2;
indices[index++] = nIdx3;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx1, nIdx2);
insEdgeVec(EdgeMap, nIdx2, nIdx3);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 0);
indices[index++] = nIdx3;
indices[index++] = nIdx4;
indices[index++] = nIdx5;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx3, nIdx4);
insEdgeVec(EdgeMap, nIdx4, nIdx5);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 0);
indices[index++] = nIdx5;
indices[index++] = nIdx6;
indices[index++] = nIdx7;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx5, nIdx6);
insEdgeVec(EdgeMap, nIdx6, nIdx7);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 0);
indices[index++] = nIdx7;
indices[index++] = nIdx1;
indices[index++] = nIdx3;
indices[index++] = SO_END_FACE_INDEX;
indices[index++] = nIdx3;
indices[index++] = nIdx5;
indices[index++] = nIdx7;
indices[index++] = SO_END_FACE_INDEX;
break;
}
case 2: { // pyra13 volume: face 2, 6-node triangle
int nIdx0 = mapNodeIndex[facesHelper[l].Element->GetNode(0)];
int nIdx1 = mapNodeIndex[facesHelper[l].Element->GetNode(9)];
int nIdx2 = mapNodeIndex[facesHelper[l].Element->GetNode(4)];
int nIdx3 = mapNodeIndex[facesHelper[l].Element->GetNode(10)];
int nIdx4 = mapNodeIndex[facesHelper[l].Element->GetNode(1)];
int nIdx5 = mapNodeIndex[facesHelper[l].Element->GetNode(5)];
indices[index++] = nIdx5;
indices[index++] = nIdx0;
indices[index++] = nIdx1;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx5, nIdx0);
insEdgeVec(EdgeMap, nIdx0, nIdx1);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 3);
indices[index++] = nIdx1;
indices[index++] = nIdx2;
indices[index++] = nIdx3;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx1, nIdx2);
insEdgeVec(EdgeMap, nIdx2, nIdx3);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 3);
indices[index++] = nIdx3;
indices[index++] = nIdx4;
indices[index++] = nIdx5;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx3, nIdx4);
insEdgeVec(EdgeMap, nIdx4, nIdx5);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 3);
indices[index++] = nIdx1;
indices[index++] = nIdx3;
indices[index++] = nIdx5;
indices[index++] = SO_END_FACE_INDEX;
break;
}
case 3: { // pyra13 volume: face 3, 6-node triangle
int nIdx0 = mapNodeIndex[facesHelper[l].Element->GetNode(1)];
int nIdx1 = mapNodeIndex[facesHelper[l].Element->GetNode(10)];
int nIdx2 = mapNodeIndex[facesHelper[l].Element->GetNode(4)];
int nIdx3 = mapNodeIndex[facesHelper[l].Element->GetNode(11)];
int nIdx4 = mapNodeIndex[facesHelper[l].Element->GetNode(2)];
int nIdx5 = mapNodeIndex[facesHelper[l].Element->GetNode(6)];
indices[index++] = nIdx5;
indices[index++] = nIdx0;
indices[index++] = nIdx1;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx5, nIdx0);
insEdgeVec(EdgeMap, nIdx0, nIdx1);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 3);
indices[index++] = nIdx1;
indices[index++] = nIdx2;
indices[index++] = nIdx3;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx1, nIdx2);
insEdgeVec(EdgeMap, nIdx2, nIdx3);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 3);
indices[index++] = nIdx3;
indices[index++] = nIdx4;
indices[index++] = nIdx5;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx3, nIdx4);
insEdgeVec(EdgeMap, nIdx4, nIdx5);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 3);
indices[index++] = nIdx1;
indices[index++] = nIdx3;
indices[index++] = nIdx5;
indices[index++] = SO_END_FACE_INDEX;
break;
}
case 4: { // pyra13 volume: face 4, 6-node triangle
int nIdx0 = mapNodeIndex[facesHelper[l].Element->GetNode(2)];
int nIdx1 = mapNodeIndex[facesHelper[l].Element->GetNode(11)];
int nIdx2 = mapNodeIndex[facesHelper[l].Element->GetNode(4)];
int nIdx3 = mapNodeIndex[facesHelper[l].Element->GetNode(12)];
int nIdx4 = mapNodeIndex[facesHelper[l].Element->GetNode(3)];
int nIdx5 = mapNodeIndex[facesHelper[l].Element->GetNode(7)];
indices[index++] = nIdx5;
indices[index++] = nIdx0;
indices[index++] = nIdx1;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx5, nIdx0);
insEdgeVec(EdgeMap, nIdx0, nIdx1);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 3);
indices[index++] = nIdx1;
indices[index++] = nIdx2;
indices[index++] = nIdx3;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx1, nIdx2);
insEdgeVec(EdgeMap, nIdx2, nIdx3);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 3);
indices[index++] = nIdx3;
indices[index++] = nIdx4;
indices[index++] = nIdx5;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx3, nIdx4);
insEdgeVec(EdgeMap, nIdx4, nIdx5);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 3);
indices[index++] = nIdx1;
indices[index++] = nIdx3;
indices[index++] = nIdx5;
indices[index++] = SO_END_FACE_INDEX;
break;
}
case 5: { // pyra13 volume: face 5, 6-node triangle
int nIdx0 = mapNodeIndex[facesHelper[l].Element->GetNode(3)];
int nIdx1 = mapNodeIndex[facesHelper[l].Element->GetNode(12)];
int nIdx2 = mapNodeIndex[facesHelper[l].Element->GetNode(4)];
int nIdx3 = mapNodeIndex[facesHelper[l].Element->GetNode(9)];
int nIdx4 = mapNodeIndex[facesHelper[l].Element->GetNode(0)];
int nIdx5 = mapNodeIndex[facesHelper[l].Element->GetNode(8)];
indices[index++] = nIdx5;
indices[index++] = nIdx0;
indices[index++] = nIdx1;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx5, nIdx0);
insEdgeVec(EdgeMap, nIdx0, nIdx1);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 3);
indices[index++] = nIdx1;
indices[index++] = nIdx2;
indices[index++] = nIdx3;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx1, nIdx2);
insEdgeVec(EdgeMap, nIdx2, nIdx3);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 3);
indices[index++] = nIdx3;
indices[index++] = nIdx4;
indices[index++] = nIdx5;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx3, nIdx4);
insEdgeVec(EdgeMap, nIdx4, nIdx5);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 3);
indices[index++] = nIdx1;
indices[index++] = nIdx3;
indices[index++] = nIdx5;
indices[index++] = SO_END_FACE_INDEX;
break;
}
default:
assert(0);
}
break;
// 15 nodes
case 15:
// penta15 volume, two 6-node triangles and three 8-node quadrangles
switch (facesHelper[l].FaceNo) {
case 1: { // penta15 volume: face 1, 6-node triangle
int nIdx0 = mapNodeIndex[facesHelper[l].Element->GetNode(0)];
int nIdx1 = mapNodeIndex[facesHelper[l].Element->GetNode(6)];
int nIdx2 = mapNodeIndex[facesHelper[l].Element->GetNode(1)];
int nIdx3 = mapNodeIndex[facesHelper[l].Element->GetNode(7)];
int nIdx4 = mapNodeIndex[facesHelper[l].Element->GetNode(2)];
int nIdx5 = mapNodeIndex[facesHelper[l].Element->GetNode(8)];
indices[index++] = nIdx5;
indices[index++] = nIdx0;
indices[index++] = nIdx1;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx5, nIdx0);
insEdgeVec(EdgeMap, nIdx0, nIdx1);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 0);
indices[index++] = nIdx1;
indices[index++] = nIdx2;
indices[index++] = nIdx3;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx1, nIdx2);
insEdgeVec(EdgeMap, nIdx2, nIdx3);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 0);
indices[index++] = nIdx3;
indices[index++] = nIdx4;
indices[index++] = nIdx5;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx3, nIdx4);
insEdgeVec(EdgeMap, nIdx4, nIdx5);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 0);
indices[index++] = nIdx1;
indices[index++] = nIdx3;
indices[index++] = nIdx5;
indices[index++] = SO_END_FACE_INDEX;
break;
}
case 2: { // penta15 volume: face 2, 6-node triangle
int nIdx0 = mapNodeIndex[facesHelper[l].Element->GetNode(3)];
int nIdx1 = mapNodeIndex[facesHelper[l].Element->GetNode(11)];
int nIdx2 = mapNodeIndex[facesHelper[l].Element->GetNode(5)];
int nIdx3 = mapNodeIndex[facesHelper[l].Element->GetNode(10)];
int nIdx4 = mapNodeIndex[facesHelper[l].Element->GetNode(4)];
int nIdx5 = mapNodeIndex[facesHelper[l].Element->GetNode(9)];
indices[index++] = nIdx5;
indices[index++] = nIdx0;
indices[index++] = nIdx1;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx5, nIdx0);
insEdgeVec(EdgeMap, nIdx0, nIdx1);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 1);
indices[index++] = nIdx1;
indices[index++] = nIdx2;
indices[index++] = nIdx3;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx1, nIdx2);
insEdgeVec(EdgeMap, nIdx2, nIdx3);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 1);
indices[index++] = nIdx3;
indices[index++] = nIdx4;
indices[index++] = nIdx5;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx3, nIdx4);
insEdgeVec(EdgeMap, nIdx4, nIdx5);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 1);
indices[index++] = nIdx1;
indices[index++] = nIdx3;
indices[index++] = nIdx5;
indices[index++] = SO_END_FACE_INDEX;
break;
}
case 3: { // penta15 volume: face 3, 8-node quadrangle
int nIdx0 = mapNodeIndex[facesHelper[l].Element->GetNode(0)];
int nIdx1 = mapNodeIndex[facesHelper[l].Element->GetNode(12)];
int nIdx2 = mapNodeIndex[facesHelper[l].Element->GetNode(3)];
int nIdx3 = mapNodeIndex[facesHelper[l].Element->GetNode(9)];
int nIdx4 = mapNodeIndex[facesHelper[l].Element->GetNode(4)];
int nIdx5 = mapNodeIndex[facesHelper[l].Element->GetNode(13)];
int nIdx6 = mapNodeIndex[facesHelper[l].Element->GetNode(1)];
int nIdx7 = mapNodeIndex[facesHelper[l].Element->GetNode(6)];
indices[index++] = nIdx7;
indices[index++] = nIdx0;
indices[index++] = nIdx1;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx7, nIdx0);
insEdgeVec(EdgeMap, nIdx0, nIdx1);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 2);
indices[index++] = nIdx1;
indices[index++] = nIdx2;
indices[index++] = nIdx3;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx1, nIdx2);
insEdgeVec(EdgeMap, nIdx2, nIdx3);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 2);
indices[index++] = nIdx3;
indices[index++] = nIdx4;
indices[index++] = nIdx5;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx3, nIdx4);
insEdgeVec(EdgeMap, nIdx4, nIdx5);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 2);
indices[index++] = nIdx5;
indices[index++] = nIdx6;
indices[index++] = nIdx7;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx5, nIdx6);
insEdgeVec(EdgeMap, nIdx6, nIdx7);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 2);
indices[index++] = nIdx7;
indices[index++] = nIdx1;
indices[index++] = nIdx3;
indices[index++] = SO_END_FACE_INDEX;
indices[index++] = nIdx3;
indices[index++] = nIdx5;
indices[index++] = nIdx7;
indices[index++] = SO_END_FACE_INDEX;
break;
}
case 4: { // penta15 volume: face 4, 8-node quadrangle
int nIdx0 = mapNodeIndex[facesHelper[l].Element->GetNode(1)];
int nIdx1 = mapNodeIndex[facesHelper[l].Element->GetNode(13)];
int nIdx2 = mapNodeIndex[facesHelper[l].Element->GetNode(4)];
int nIdx3 = mapNodeIndex[facesHelper[l].Element->GetNode(10)];
int nIdx4 = mapNodeIndex[facesHelper[l].Element->GetNode(5)];
int nIdx5 = mapNodeIndex[facesHelper[l].Element->GetNode(14)];
int nIdx6 = mapNodeIndex[facesHelper[l].Element->GetNode(2)];
int nIdx7 = mapNodeIndex[facesHelper[l].Element->GetNode(7)];
indices[index++] = nIdx7;
indices[index++] = nIdx0;
indices[index++] = nIdx1;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx7, nIdx0);
insEdgeVec(EdgeMap, nIdx0, nIdx1);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 3);
indices[index++] = nIdx1;
indices[index++] = nIdx2;
indices[index++] = nIdx3;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx1, nIdx2);
insEdgeVec(EdgeMap, nIdx2, nIdx3);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 3);
indices[index++] = nIdx3;
indices[index++] = nIdx4;
indices[index++] = nIdx5;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx3, nIdx4);
insEdgeVec(EdgeMap, nIdx4, nIdx5);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 3);
indices[index++] = nIdx5;
indices[index++] = nIdx6;
indices[index++] = nIdx7;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx5, nIdx6);
insEdgeVec(EdgeMap, nIdx6, nIdx7);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 3);
indices[index++] = nIdx7;
indices[index++] = nIdx1;
indices[index++] = nIdx3;
indices[index++] = SO_END_FACE_INDEX;
indices[index++] = nIdx3;
indices[index++] = nIdx5;
indices[index++] = nIdx7;
indices[index++] = SO_END_FACE_INDEX;
break;
}
case 5: { // penta15 volume: face 5, 8-node quadrangle
int nIdx0 = mapNodeIndex[facesHelper[l].Element->GetNode(2)];
int nIdx1 = mapNodeIndex[facesHelper[l].Element->GetNode(14)];
int nIdx2 = mapNodeIndex[facesHelper[l].Element->GetNode(5)];
int nIdx3 = mapNodeIndex[facesHelper[l].Element->GetNode(11)];
int nIdx4 = mapNodeIndex[facesHelper[l].Element->GetNode(3)];
int nIdx5 = mapNodeIndex[facesHelper[l].Element->GetNode(12)];
int nIdx6 = mapNodeIndex[facesHelper[l].Element->GetNode(0)];
int nIdx7 = mapNodeIndex[facesHelper[l].Element->GetNode(8)];
indices[index++] = nIdx7;
indices[index++] = nIdx0;
indices[index++] = nIdx1;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx7, nIdx0);
insEdgeVec(EdgeMap, nIdx0, nIdx1);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 4);
indices[index++] = nIdx1;
indices[index++] = nIdx2;
indices[index++] = nIdx3;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx1, nIdx2);
insEdgeVec(EdgeMap, nIdx2, nIdx3);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 4);
indices[index++] = nIdx3;
indices[index++] = nIdx4;
indices[index++] = nIdx5;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx3, nIdx4);
insEdgeVec(EdgeMap, nIdx4, nIdx5);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 4);
indices[index++] = nIdx5;
indices[index++] = nIdx6;
indices[index++] = nIdx7;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx5, nIdx6);
insEdgeVec(EdgeMap, nIdx6, nIdx7);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 4);
indices[index++] = nIdx7;
indices[index++] = nIdx1;
indices[index++] = nIdx3;
indices[index++] = SO_END_FACE_INDEX;
indices[index++] = nIdx3;
indices[index++] = nIdx5;
indices[index++] = nIdx7;
indices[index++] = SO_END_FACE_INDEX;
break;
}
default:
assert(0);
}
break;
// 20 nodes
case 20:
// hexa20 volume, six 8-node quadrangles
switch (facesHelper[l].FaceNo) {
case 1: { // hexa20 volume: face 1
int nIdx0 = mapNodeIndex[facesHelper[l].Element->GetNode(0)];
int nIdx1 = mapNodeIndex[facesHelper[l].Element->GetNode(8)];
int nIdx2 = mapNodeIndex[facesHelper[l].Element->GetNode(1)];
int nIdx3 = mapNodeIndex[facesHelper[l].Element->GetNode(9)];
int nIdx4 = mapNodeIndex[facesHelper[l].Element->GetNode(2)];
int nIdx5 = mapNodeIndex[facesHelper[l].Element->GetNode(10)];
int nIdx6 = mapNodeIndex[facesHelper[l].Element->GetNode(3)];
int nIdx7 = mapNodeIndex[facesHelper[l].Element->GetNode(11)];
indices[index++] = nIdx7;
indices[index++] = nIdx0;
indices[index++] = nIdx1;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx7, nIdx0);
insEdgeVec(EdgeMap, nIdx0, nIdx1);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 0);
indices[index++] = nIdx1;
indices[index++] = nIdx2;
indices[index++] = nIdx3;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx1, nIdx2);
insEdgeVec(EdgeMap, nIdx2, nIdx3);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 0);
indices[index++] = nIdx3;
indices[index++] = nIdx4;
indices[index++] = nIdx5;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx3, nIdx4);
insEdgeVec(EdgeMap, nIdx4, nIdx5);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 0);
indices[index++] = nIdx5;
indices[index++] = nIdx6;
indices[index++] = nIdx7;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx5, nIdx6);
insEdgeVec(EdgeMap, nIdx6, nIdx7);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 0);
indices[index++] = nIdx7;
indices[index++] = nIdx1;
indices[index++] = nIdx3;
indices[index++] = SO_END_FACE_INDEX;
indices[index++] = nIdx3;
indices[index++] = nIdx5;
indices[index++] = nIdx7;
indices[index++] = SO_END_FACE_INDEX;
break;
}
case 2: { // hexa20 volume: face 2, 8-node quadrangle
int nIdx0 = mapNodeIndex[facesHelper[l].Element->GetNode(4)];
int nIdx1 = mapNodeIndex[facesHelper[l].Element->GetNode(15)];
int nIdx2 = mapNodeIndex[facesHelper[l].Element->GetNode(7)];
int nIdx3 = mapNodeIndex[facesHelper[l].Element->GetNode(14)];
int nIdx4 = mapNodeIndex[facesHelper[l].Element->GetNode(6)];
int nIdx5 = mapNodeIndex[facesHelper[l].Element->GetNode(13)];
int nIdx6 = mapNodeIndex[facesHelper[l].Element->GetNode(5)];
int nIdx7 = mapNodeIndex[facesHelper[l].Element->GetNode(12)];
indices[index++] = nIdx7;
indices[index++] = nIdx0;
indices[index++] = nIdx1;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx7, nIdx0);
insEdgeVec(EdgeMap, nIdx0, nIdx1);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 1);
indices[index++] = nIdx1;
indices[index++] = nIdx2;
indices[index++] = nIdx3;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx1, nIdx2);
insEdgeVec(EdgeMap, nIdx2, nIdx3);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 1);
indices[index++] = nIdx3;
indices[index++] = nIdx4;
indices[index++] = nIdx5;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx3, nIdx4);
insEdgeVec(EdgeMap, nIdx4, nIdx5);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 1);
indices[index++] = nIdx5;
indices[index++] = nIdx6;
indices[index++] = nIdx7;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx5, nIdx6);
insEdgeVec(EdgeMap, nIdx6, nIdx7);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 1);
indices[index++] = nIdx7;
indices[index++] = nIdx1;
indices[index++] = nIdx3;
indices[index++] = SO_END_FACE_INDEX;
indices[index++] = nIdx3;
indices[index++] = nIdx5;
indices[index++] = nIdx7;
indices[index++] = SO_END_FACE_INDEX;
break;
}
case 3: { // hexa20 volume: face 3, 8-node quadrangle
int nIdx0 = mapNodeIndex[facesHelper[l].Element->GetNode(0)];
int nIdx1 = mapNodeIndex[facesHelper[l].Element->GetNode(16)];
int nIdx2 = mapNodeIndex[facesHelper[l].Element->GetNode(4)];
int nIdx3 = mapNodeIndex[facesHelper[l].Element->GetNode(12)];
int nIdx4 = mapNodeIndex[facesHelper[l].Element->GetNode(5)];
int nIdx5 = mapNodeIndex[facesHelper[l].Element->GetNode(17)];
int nIdx6 = mapNodeIndex[facesHelper[l].Element->GetNode(1)];
int nIdx7 = mapNodeIndex[facesHelper[l].Element->GetNode(8)];
indices[index++] = nIdx7;
indices[index++] = nIdx0;
indices[index++] = nIdx1;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx7, nIdx0);
insEdgeVec(EdgeMap, nIdx0, nIdx1);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 2);
indices[index++] = nIdx1;
indices[index++] = nIdx2;
indices[index++] = nIdx3;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx1, nIdx2);
insEdgeVec(EdgeMap, nIdx2, nIdx3);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 2);
indices[index++] = nIdx3;
indices[index++] = nIdx4;
indices[index++] = nIdx5;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx3, nIdx4);
insEdgeVec(EdgeMap, nIdx4, nIdx5);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 2);
indices[index++] = nIdx5;
indices[index++] = nIdx6;
indices[index++] = nIdx7;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx5, nIdx6);
insEdgeVec(EdgeMap, nIdx6, nIdx7);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 2);
indices[index++] = nIdx7;
indices[index++] = nIdx1;
indices[index++] = nIdx3;
indices[index++] = SO_END_FACE_INDEX;
indices[index++] = nIdx3;
indices[index++] = nIdx5;
indices[index++] = nIdx7;
indices[index++] = SO_END_FACE_INDEX;
break;
}
case 4: { // hexa20 volume: face 4, 8-node quadrangle
int nIdx0 = mapNodeIndex[facesHelper[l].Element->GetNode(1)];
int nIdx1 = mapNodeIndex[facesHelper[l].Element->GetNode(17)];
int nIdx2 = mapNodeIndex[facesHelper[l].Element->GetNode(5)];
int nIdx3 = mapNodeIndex[facesHelper[l].Element->GetNode(13)];
int nIdx4 = mapNodeIndex[facesHelper[l].Element->GetNode(6)];
int nIdx5 = mapNodeIndex[facesHelper[l].Element->GetNode(18)];
int nIdx6 = mapNodeIndex[facesHelper[l].Element->GetNode(2)];
int nIdx7 = mapNodeIndex[facesHelper[l].Element->GetNode(9)];
indices[index++] = nIdx7;
indices[index++] = nIdx0;
indices[index++] = nIdx1;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx7, nIdx0);
insEdgeVec(EdgeMap, nIdx0, nIdx1);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 3);
indices[index++] = nIdx1;
indices[index++] = nIdx2;
indices[index++] = nIdx3;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx1, nIdx2);
insEdgeVec(EdgeMap, nIdx2, nIdx3);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 3);
indices[index++] = nIdx3;
indices[index++] = nIdx4;
indices[index++] = nIdx5;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx3, nIdx4);
insEdgeVec(EdgeMap, nIdx4, nIdx5);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 3);
indices[index++] = nIdx5;
indices[index++] = nIdx6;
indices[index++] = nIdx7;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx5, nIdx6);
insEdgeVec(EdgeMap, nIdx6, nIdx7);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 3);
indices[index++] = nIdx7;
indices[index++] = nIdx1;
indices[index++] = nIdx3;
indices[index++] = SO_END_FACE_INDEX;
indices[index++] = nIdx3;
indices[index++] = nIdx5;
indices[index++] = nIdx7;
indices[index++] = SO_END_FACE_INDEX;
break;
}
case 5: { // hexa20 volume: face 5, 8-node quadrangle
int nIdx0 = mapNodeIndex[facesHelper[l].Element->GetNode(2)];
int nIdx1 = mapNodeIndex[facesHelper[l].Element->GetNode(18)];
int nIdx2 = mapNodeIndex[facesHelper[l].Element->GetNode(6)];
int nIdx3 = mapNodeIndex[facesHelper[l].Element->GetNode(14)];
int nIdx4 = mapNodeIndex[facesHelper[l].Element->GetNode(7)];
int nIdx5 = mapNodeIndex[facesHelper[l].Element->GetNode(19)];
int nIdx6 = mapNodeIndex[facesHelper[l].Element->GetNode(3)];
int nIdx7 = mapNodeIndex[facesHelper[l].Element->GetNode(10)];
indices[index++] = nIdx7;
indices[index++] = nIdx0;
indices[index++] = nIdx1;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx7, nIdx0);
insEdgeVec(EdgeMap, nIdx0, nIdx1);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 4);
indices[index++] = nIdx1;
indices[index++] = nIdx2;
indices[index++] = nIdx3;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx1, nIdx2);
insEdgeVec(EdgeMap, nIdx2, nIdx3);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 4);
indices[index++] = nIdx3;
indices[index++] = nIdx4;
indices[index++] = nIdx5;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx3, nIdx4);
insEdgeVec(EdgeMap, nIdx4, nIdx5);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 4);
indices[index++] = nIdx5;
indices[index++] = nIdx6;
indices[index++] = nIdx7;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx5, nIdx6);
insEdgeVec(EdgeMap, nIdx6, nIdx7);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 4);
indices[index++] = nIdx7;
indices[index++] = nIdx1;
indices[index++] = nIdx3;
indices[index++] = SO_END_FACE_INDEX;
indices[index++] = nIdx3;
indices[index++] = nIdx5;
indices[index++] = nIdx7;
indices[index++] = SO_END_FACE_INDEX;
break;
}
case 6: { // hexa20 volume: face 6, 8-node quadrangle
int nIdx0 = mapNodeIndex[facesHelper[l].Element->GetNode(3)];
int nIdx1 = mapNodeIndex[facesHelper[l].Element->GetNode(19)];
int nIdx2 = mapNodeIndex[facesHelper[l].Element->GetNode(7)];
int nIdx3 = mapNodeIndex[facesHelper[l].Element->GetNode(15)];
int nIdx4 = mapNodeIndex[facesHelper[l].Element->GetNode(4)];
int nIdx5 = mapNodeIndex[facesHelper[l].Element->GetNode(16)];
int nIdx6 = mapNodeIndex[facesHelper[l].Element->GetNode(0)];
int nIdx7 = mapNodeIndex[facesHelper[l].Element->GetNode(11)];
indices[index++] = nIdx7;
indices[index++] = nIdx0;
indices[index++] = nIdx1;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx7, nIdx0);
insEdgeVec(EdgeMap, nIdx0, nIdx1);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 5);
indices[index++] = nIdx1;
indices[index++] = nIdx2;
indices[index++] = nIdx3;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx1, nIdx2);
insEdgeVec(EdgeMap, nIdx2, nIdx3);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 5);
indices[index++] = nIdx3;
indices[index++] = nIdx4;
indices[index++] = nIdx5;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx3, nIdx4);
insEdgeVec(EdgeMap, nIdx4, nIdx5);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 5);
indices[index++] = nIdx5;
indices[index++] = nIdx6;
indices[index++] = nIdx7;
indices[index++] = SO_END_FACE_INDEX;
insEdgeVec(EdgeMap, nIdx5, nIdx6);
insEdgeVec(EdgeMap, nIdx6, nIdx7);
vFaceElementIdx[indexIdx++] = ElemFold(facesHelper[l].ElementNumber, 5);
indices[index++] = nIdx7;
indices[index++] = nIdx1;
indices[index++] = nIdx3;
indices[index++] = SO_END_FACE_INDEX;
indices[index++] = nIdx3;
indices[index++] = nIdx5;
indices[index++] = nIdx7;
indices[index++] = SO_END_FACE_INDEX;
break;
}
default:
assert(0);
}
break;
// not implemented elements
default:
throw std::runtime_error(
"Element with unknown node count found (may be not implemented), only "
"display mode nodes is supported for this element (NodeCount)");
}
}
}
faces->coordIndex.finishEditing();
Base::Console().Log(" %f: Start build up edge vector\n",
Base::TimeElapsed::diffTimeF(Start, Base::TimeElapsed()));
// std::map<int,std::set<int> > EdgeMap;
// count edges
int EdgeSize = 0;
for (std::map<int, std::set<int>>::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<int, std::set<int>>::const_iterator it = EdgeMap.begin(); it != EdgeMap.end();
++it) {
for (std::set<int>::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::TimeElapsed::diffTimeF(Start, Base::TimeElapsed()));
}
// Python feature -----------------------------------------------------------------------
namespace Gui
{
/// @cond DOXERR
PROPERTY_SOURCE_TEMPLATE(FemGui::ViewProviderFemMeshPython, FemGui::ViewProviderFemMesh)
/// @endcond
// explicit template instantiation
template class FemGuiExport ViewProviderFeaturePythonT<ViewProviderFemMesh>;
} // namespace Gui