Opencascade之STL可视化与选取渲染风格

在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渲染,并选取三角面的效果:

 

二、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);

}

整体选择时的风格:

点被选取时的风格

三角面被选取的风格:

 

 

 

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值