在Opencascade中,STL模型可以的可视化有两种方式:
一、STL模型加载为Shape对象,再可视化
1.1 STL模型加载为Shape对象
TopoDS_Shape aShape;
try
{
StlAPI_Reader reader;
reader.Read(aShape, theFile);
}
return aShape;
这种渲染STL模型的方式,优点是与Shape的可视化、Shape对象的选取方式保持了一致;缺点时,加载STL模型比较慢,尤其时模型数据比较大时尤其明显。
STL模型加载为Shape渲染,并选取三角面的效果:
![](https://img-blog.csdnimg.cn/5899e0b3444741b8bb4bccac113c362b.png)
二、STL模型使用MeshVS_Mesh可视化
STL模型使用MeshVS_Mesh渲染时,优点是加载速度快、缺点是渲染、选取逻辑与Shape是不一致的。
2.1 加载STL模型为Poly_Triangulation
Handle(Poly_Triangulation) aMesh;
try
{
aMesh = RWStl::ReadFile(utfFile.c_str());
}catch(...){}
return aMesh;
2.2 为MehsVS_Mesh对象准备数据源类
#include <MeshVS_DataSource.hxx>
#include <Poly_Triangulation.hxx>
#include <TColStd_HArray2OfInteger.hxx>
#include <TColStd_HArray2OfReal.hxx>
class AMeshVS_DataSource : public MeshVS_DataSource
{
DEFINE_STANDARD_RTTIEXT(AMeshVS_DataSource, MeshVS_DataSource)
public:
AMeshVS_DataSource(const Handle(Poly_Triangulation)& plyTri);
Standard_Boolean GetGeom(
const Standard_Integer ID,
const Standard_Boolean IsElement,
TColStd_Array1OfReal& Coords,
Standard_Integer& NbNodes,
MeshVS_EntityType& Type) const Standard_OVERRIDE;
Standard_Boolean GetGeomType(
const Standard_Integer ID,
const Standard_Boolean IsElement,
MeshVS_EntityType& Type) const Standard_OVERRIDE;
Standard_Address GetAddr(
const Standard_Integer ID,
const Standard_Boolean IsElement) const Standard_OVERRIDE;
Standard_Boolean GetNodesByElement(
const Standard_Integer ID,
TColStd_Array1OfInteger& NodeIDs,
Standard_Integer& NbNodes) const Standard_OVERRIDE;
const TColStd_PackedMapOfInteger& GetAllNodes() const Standard_OVERRIDE;
const TColStd_PackedMapOfInteger& GetAllElements() const Standard_OVERRIDE;
Standard_Boolean GetNormal(
const Standard_Integer Id,
const Standard_Integer Max,
Standard_Real& nx,
Standard_Real& ny,
Standard_Real& nz) const Standard_OVERRIDE;
private:
TColStd_PackedMapOfInteger myNodes;
TColStd_PackedMapOfInteger myElements;
Handle(TColStd_HArray2OfInteger) myElemNodes;
Handle(TColStd_HArray2OfReal) myNodeCoords;
Handle(TColStd_HArray2OfReal) myElemNormals;
};
#include "ameshvs_datasource.h"
#include <Precision.hxx>
IMPLEMENT_STANDARD_RTTIEXT(AMeshVS_DataSource, MeshVS_DataSource)
AMeshVS_DataSource::SinnMeshVS_DataSource(const Handle(Poly_Triangulation)& plyTri)
{
if( !plyTri.IsNull() )
{
const Standard_Integer aNbNodes = plyTri->NbNodes();
myNodeCoords = new TColStd_HArray2OfReal (1, aNbNodes, 1, 3);
for (Standard_Integer i = 1; i <= aNbNodes; i++)
{
myNodes.Add( i );
gp_Pnt xyz = plyTri->Node (i);
myNodeCoords->SetValue(i, 1, xyz.X());
myNodeCoords->SetValue(i, 2, xyz.Y());
myNodeCoords->SetValue(i, 3, xyz.Z());
}
const Standard_Integer aNbTris = plyTri->NbTriangles();
myElemNormals = new TColStd_HArray2OfReal(1, aNbTris, 1, 3);
myElemNodes = new TColStd_HArray2OfInteger(1, aNbTris, 1, 3);
for (Standard_Integer i = 1; i <= aNbTris; i++)
{
myElements.Add( i );
const Poly_Triangle aTri = plyTri->Triangle (i);
Standard_Integer V[3];
aTri.Get (V[0], V[1], V[2]);
const gp_Pnt aP1 = plyTri->Node (V[0]);
const gp_Pnt aP2 = plyTri->Node (V[1]);
const gp_Pnt aP3 = plyTri->Node (V[2]);
gp_Vec aV1(aP1, aP2);
gp_Vec aV2(aP2, aP3);
gp_Vec aN = aV1.Crossed(aV2);
if (aN.SquareMagnitude() > Precision::SquareConfusion())
aN.Normalize();
else
aN.SetCoord(0.0, 0.0, 0.0);
for (Standard_Integer j = 0; j < 3; j++)
{
myElemNodes->SetValue(i, j+1, V[j]);
}
myElemNormals->SetValue (i, 1, aN.X());
myElemNormals->SetValue (i, 2, aN.Y());
myElemNormals->SetValue (i, 3, aN.Z());
}
}
}
Standard_Boolean AMeshVS_DataSource::GetGeom(
const Standard_Integer ID,
const Standard_Boolean IsElement,
TColStd_Array1OfReal& Coords,
Standard_Integer& NbNodes,
MeshVS_EntityType& Type) const
{
if( myNodes.Extent() == 0 )
return Standard_False;
if( IsElement )
{//三角面
if( ID>=1 && ID<=myElements.Extent() )
{
Type = MeshVS_ET_Face;
NbNodes = 3;
for( Standard_Integer i = 1, k = 1; i <= 3; i++ )
{
Standard_Integer IdxNode = myElemNodes->Value(ID, i);
for(Standard_Integer j = 1; j <= 3; j++, k++ )
Coords(k) = myNodeCoords->Value(IdxNode, j);
}
return Standard_True;
}
else
return Standard_False;
}
else if( ID>=1 && ID<=myNodes.Extent() )
{//点
Type = MeshVS_ET_Node;
NbNodes = 1;
Coords( 1 ) = myNodeCoords->Value(ID, 1);
Coords( 2 ) = myNodeCoords->Value(ID, 2);
Coords( 3 ) = myNodeCoords->Value(ID, 3);
return Standard_True;
}
else
return Standard_False;
}
Standard_Boolean AMeshVS_DataSource::GetGeomType(
const Standard_Integer theID,
const Standard_Boolean IsElement,
MeshVS_EntityType& theType) const
{
if( myNodes.Extent() == 0 )
return Standard_False;
if (IsElement)
{
if (theID >= 1 && theID <= myElements.Extent())
{
theType = MeshVS_ET_Face;
return Standard_True;
}
}
else if (theID >= 1 && theID <= myNodes.Extent())
{
theType = MeshVS_ET_Node;
return Standard_True;
}
return Standard_False;
}
Standard_Address AMeshVS_DataSource::GetAddr(
const Standard_Integer /*ID*/,
const Standard_Boolean /*IsElement*/) const
{
return NULL;
}
Standard_Boolean AMeshVS_DataSource::GetNodesByElement(
const Standard_Integer ID,
TColStd_Array1OfInteger& theNodeIDs,
Standard_Integer& /*theNbNodes*/) const
{
if( myNodes.Extent() == 0 )
return Standard_False;
if (ID >= 1 && ID <= myElements.Extent() && theNodeIDs.Length() >= 3)
{
Standard_Integer aLow = theNodeIDs.Lower();
theNodeIDs(aLow) = myElemNodes->Value(ID, 1);
theNodeIDs(aLow + 1) = myElemNodes->Value(ID, 2);
theNodeIDs(aLow + 2) = myElemNodes->Value(ID, 3);
return Standard_True;
}
return Standard_False;
}
const TColStd_PackedMapOfInteger& AMeshVS_DataSource::GetAllNodes() const
{
return myNodes;
}
const TColStd_PackedMapOfInteger& AMeshVS_DataSource::GetAllElements() const
{
return myElements;
}
Standard_Boolean AMeshVS_DataSource::GetNormal(
const Standard_Integer Id,
const Standard_Integer Max,
Standard_Real& nx,
Standard_Real& ny,
Standard_Real& nz) const
{
if( myNodes.Extent() == 0 )
return Standard_False;
if (Id >= 1 && Id <= myElements.Extent() && Max >= 3)
{
nx = myElemNormals->Value(Id, 1);
ny = myElemNormals->Value(Id, 2);
nz = myElemNormals->Value(Id, 3);
return Standard_True;
}
else
return Standard_False;
}
2.3 渲染Poly_Triangulation
Handle(AMeshVS_Mesh) myAisObj = new AMeshVS_Mesh();
Handle(AMeshVS_DataSource) aDS = new AMeshVS_DataSource(myPlyTri/*Poly_Triangulation*/);
myAisObj->SetDataSource(aDS);
Handle(MeshVS_MeshPrsBuilder) aMeshPrsBuilder = new MeshVS_MeshPrsBuilder(myAisObj.operator->());
myAisObj->AddBuilder(aMeshPrsBuilder,Standard_True);
//点加入可选集
Handle(TColStd_HPackedMapOfInteger) aNodes = new TColStd_HPackedMapOfInteger();
const Standard_Integer aLen = aDS->GetAllNodes().Extent();
for ( Standard_Integer anIndex = 1; anIndex <= aLen; anIndex++ )
aNodes->ChangeMap().Add( anIndex );
myAisObj->SetSelectableNodes ( aNodes );
//显示模式
myAisObj->SetDisplayMode(MeshVS_DMF_Shading);
myAisObj->SetMeshSelMethod(MeshVS_MSM_PRECISE);
myAisObj->SetHilightMode(MeshVS_DMF_Shading);
myAisObj->SetTransparency(0.4);
//设置颜色
myAisObj->GetDrawer()->SetColor(MeshVS_DA_InteriorColor, Quantity_NOC_GOLD);
myAisObj->GetDrawer()->SetColor(MeshVS_DA_EdgeColor, Quantity_NOC_BROWN4);
//不显示点
myAisObj->GetDrawer()->SetBoolean(MeshVS_DA_DisplayNodes, Standard_False);
//显示边
myAisObj->GetDrawer()->SetBoolean(MeshVS_DA_ShowEdges, Standard_True);
2.4 设置三角网拾取渲染风格
AMeshVS_Mesh::AMeshVS_Mesh(const Standard_Boolean theIsAllowOverlapped)
:MeshVS_Mesh(theIsAllowOverlapped)
{
//点被选中的风格
mySelectionDrawer->SetInteger ( MeshVS_DA_MarkerType, Aspect_TOM_BALL );
mySelectionDrawer->SetColor ( MeshVS_DA_MarkerColor, Quantity_NOC_RED );
mySelectionDrawer->SetDouble ( MeshVS_DA_MarkerScale, 5.0 );
//三角面被选中的风格
mySelectionDrawer->SetColor ( MeshVS_DA_BeamColor,Quantity_NOC_RED);
mySelectionDrawer->SetDouble( MeshVS_DA_BeamWidth, 1.5 );
//设置整体拾取时的颜色
this->HilightAttributes()->SetTransparency(0.6);
this->HilightAttributes()->SetColor(Quantity_NOC_BLUE);
//点被检测到的风格
myHilightDrawer->SetInteger ( MeshVS_DA_MarkerType, Aspect_TOM_BALL );
myHilightDrawer->SetColor ( MeshVS_DA_MarkerColor, Quantity_NOC_GRAY80 );
myHilightDrawer->SetDouble ( MeshVS_DA_MarkerScale, 5.0 );
//设置整体被检测到时的透明度
this->myDynHilightDrawer->SetTransparency(0.6);
}
整体选择时的风格:
![](https://img-blog.csdnimg.cn/ccc9a7bac35a43559a74a0f31839ca44.png)
点被选取时的风格
![](https://img-blog.csdnimg.cn/b269d3320ff74901bd11ad944f7debcf.png)
三角面被选取的风格: