Open CASCADE自定义MeshVS_DataSource

本文介绍如何在OCC中自定义DataSource类以显示三角网格数据,包括使用myDataSource类处理点坐标数据和拓扑关系,实现自定义数据源以适应特定需求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

由MeshVS_DataSource派生自定义DataSource

OCC在DataExchange中提供了.stl数据格式的导入与导出方法。在该类型文件中,模型以三角网格形式存储,OCC为此定义了针对.stl格式文件的数据存储方式,即XSDRAWSTLVRML_DataSource。如下为导入.stl并为其定义显示生成器的方法:

	CFileDialog dlg(TRUE,
		NULL,
		NULL,
		OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
		L"stl Files (*.stl)|*.stl;|STL Files (*.STL)|*.STL;||",
		NULL);

	CString SHAREPATHValue;
	SHAREPATHValue.GetEnvironmentVariable(L"CSF_OCCTDataPath");
	CString initdir = (SHAREPATHValue + "\\stl");
	dlg.m_ofn.lpstrInitialDir = initdir;

	if (dlg.DoModal() != IDOK)
		return;

	// read the data and create a data source
	TCollection_AsciiString aFileName((const wchar_t*)dlg.GetPathName());
	Handle(Message_ProgressIndicator) aProgInd = Handle(Message_ProgressIndicator)();
	Handle(Poly_Triangulation) aSTLMesh = RWStl::ReadFile(aFileName, aProgInd);
	Handle(XSDRAWSTLVRML_DataSource) aDS = new XSDRAWSTLVRML_DataSource(aSTLMesh);         
	// create mesh
	Handle(MeshVS_Mesh) aMesh = new MeshVS_Mesh();
	aMesh->SetDataSource(aDS);
	// use builder
	Handle(MeshVS_MeshPrsBuilder) aBuilder = new MeshVS_MeshPrsBuilder(aMesh);
	aMesh->GetDrawer()->SetColor(MeshVS_DA_EdgeColor, Quantity_NOC_YELLOW);
	aMesh->AddBuilder(aBuilder, Standard_False);
	myAISContext->Display(aMesh, Standard_True);
	Fit();

如果不是读取STL文件,而是有三角网格的点坐标数据 std::vector< PointXYZ> CoordData 以及点之间的拓扑关系std::vector<std::vector> Ele2NodeData(比如三个点构成一个三角形的索引值),需要自己定义DataSource来显示网格。

struct PointXYZ
{
	double X;
	double Y;
	double Z;
	PointXYZ()
	{
		X = 0;
		Y = 0;
		Z = 0;
	}
};

根据XSDRAWSTLVRML_DataSource派生方法,自定义myDataSource类。添加对应的 myDataSource.h 与myDataSource.cpp,参考XSDRAWSTLVRML_DataSource类,只需要构造函数。具体如下:

// myDataSource.h
#pragma once

#include <Standard.hxx>
#include <Standard_Type.hxx>
#include <Standard_Real.hxx>
#include <Standard_Address.hxx>
#include <Standard_Boolean.hxx>
#include <Standard_Integer.hxx>
#include <TColStd_PackedMapOfInteger.hxx>
#include <TColStd_HArray2OfInteger.hxx>
#include <TColStd_HArray2OfReal.hxx>
#include <TColStd_Array1OfReal.hxx>
#include <TColStd_Array1OfInteger.hxx>
#include <MeshVS_EntityType.hxx>
#include <MeshVS_DataSource.hxx>
#include <Poly_Triangulation.hxx>
#include <vector>

class myDataSource;
DEFINE_STANDARD_HANDLE(myDataSource, MeshVS_DataSource)

class myDataSource: public MeshVS_DataSource
{
public:
	
	 myDataSource(std::vector< PointXYZ> CoordData, std::vector<std::vector<int>> Ele2NodeData);
	//! Returns geometry information about node ( if IsElement is False ) or element ( IsElement is True )
	//! by co-ordinates. For element this method must return all its nodes co-ordinates in the strict order: X, Y, Z and
	//! with nodes order is the same as in wire bounding the face or link. NbNodes is number of nodes of element.
	//! It is recommended to return 1 for node. Type is an element type.
	  Standard_Boolean GetGeom(const Standard_Integer ID, const Standard_Boolean IsElement, TColStd_Array1OfReal& Coords, Standard_Integer& NbNodes, MeshVS_EntityType& Type) const Standard_OVERRIDE;

	 //! This method is similar to GetGeom, but returns only element or node type. This method is provided for
	 //! a fine performance.
	  Standard_Boolean GetGeomType(const Standard_Integer ID, const Standard_Boolean IsElement, MeshVS_EntityType& Type) const Standard_OVERRIDE;

	 //! This method returns by number an address of any entity which represents element or node data structure.
	  Standard_Address GetAddr(const Standard_Integer ID, const Standard_Boolean IsElement) const Standard_OVERRIDE;

	 //! This method returns information about what node this element consist of.
	  virtual Standard_Boolean GetNodesByElement(const Standard_Integer ID, TColStd_Array1OfInteger& NodeIDs, Standard_Integer& NbNodes) const Standard_OVERRIDE;

	 //! This method returns map of all nodes the object consist of.
	  const TColStd_PackedMapOfInteger& GetAllNodes() const Standard_OVERRIDE;

	 //! This method returns map of all elements the object consist of.
	  const TColStd_PackedMapOfInteger& GetAllElements() const Standard_OVERRIDE;

	 //! This method calculates normal of face, which is using for correct reflection presentation.
	 //! There is default method, for advance reflection this method can be redefined.
	  virtual Standard_Boolean GetNormal(const Standard_Integer Id, const Standard_Integer Max, Standard_Real& nx, Standard_Real& ny, Standard_Real& nz) const Standard_OVERRIDE;



	DEFINE_STANDARD_RTTIEXT(myDataSource, MeshVS_DataSource)

protected:

private:
	TColStd_PackedMapOfInteger myNodes;
	TColStd_PackedMapOfInteger myElements;
	Handle(TColStd_HArray2OfInteger) myElemNodes;
	Handle(TColStd_HArray2OfReal) myNodeCoords;
	Handle(TColStd_HArray2OfReal) myElemNormals;
};


在构造函数myDataSource()中,需要赋值的主要有五个,即Private中所定义的参数。myNodes,myElements分别存储顶点、网格单元的索引号,要注意的是,起始序号从1开始。myNodeCoords是一个 CoordData.size() x 3 的矩阵,每一行为点的x,y,z坐标。myElemNodes存储每一个三角网格对应的顶点索引值。而myElemNormals为每一个三角网格的法向量,在需要区分三角网格正反面属性时有用。除了构造函数之外其他重写的函数不需要做改动。

// myDataSource.cpp
#include "myDataSource.h"
#include <vector>
#include <Precision.hxx>
#include <Standard_Type.hxx>
#include <TColgp_SequenceOfXYZ.hxx>
#include <TColStd_DataMapOfIntegerInteger.hxx>
#include <TColStd_DataMapOfIntegerReal.hxx>

IMPLEMENT_STANDARD_RTTIEXT(myDataSource, MeshVS_DataSource)

myDataSource::myDataSource(std::vector< PointXYZ> CoordData, std::vector<std::vector<int>> Ele2NodeData)
{
	myNodeCoords = new TColStd_HArray2OfReal(1, CoordData.size(), 1, 3);
		for (size_t i = 1; i <= CoordData.size(); i++)
		{
			myNodes.Add(i);
			myNodeCoords->SetValue(i, 1, CoordData[i-1].X);
			myNodeCoords->SetValue(i, 2, CoordData[i-1].Y);
			myNodeCoords->SetValue(i, 3, CoordData[i-1].Z);
		}
		myElemNormals = new TColStd_HArray2OfReal(1, Ele2NodeData.size(), 1, 3);
		myElemNodes = new TColStd_HArray2OfInteger(1, Ele2NodeData.size(), 1, 3);
	
		for (size_t i = 1; i <= Ele2NodeData.size(); i++)
		{
			myElements.Add(i);
			for (int j = 0; j < 3; j++)
			{
				Standard_Integer index = Ele2NodeData[i - 1][j];
				myElemNodes->SetValue(i, j + 1, index);
			}		
			myElemNormals->SetValue(i, 1, 0);
			myElemNormals->SetValue(i, 2, 0);
			myElemNormals->SetValue(i, 3, 1);
		}
}

//================================================================
// Function : GetGeom
// Purpose  :
//================================================================
Standard_Boolean myDataSource::GetGeom
(const Standard_Integer ID, const Standard_Boolean IsElement,
TColStd_Array1OfReal& Coords, Standard_Integer& NbNodes,
MeshVS_EntityType& Type) const
{
	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;
}

//================================================================
// Function : GetGeomType
// Purpose  :
//================================================================
Standard_Boolean myDataSource::GetGeomType
(const Standard_Integer,
const Standard_Boolean IsElement,
MeshVS_EntityType& Type) const
{
	if (IsElement)
	{
		Type = MeshVS_ET_Face;
		return Standard_True;
	}
	else
	{
		Type = MeshVS_ET_Node;
		return Standard_True;
	}
}

//================================================================
// Function : GetAddr
// Purpose  :
//================================================================
Standard_Address myDataSource::GetAddr
(const Standard_Integer, const Standard_Boolean) const
{
	return NULL;
}

//================================================================
// Function : GetNodesByElement
// Purpose  :
//================================================================
Standard_Boolean myDataSource::GetNodesByElement
(const Standard_Integer ID,
TColStd_Array1OfInteger& theNodeIDs,
Standard_Integer& /*theNbNodes*/) const
{

	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;
}

//================================================================
// Function : GetAllNodes
// Purpose  :
//================================================================
const TColStd_PackedMapOfInteger& myDataSource::GetAllNodes() const
{
	return myNodes;
}

//================================================================
// Function : GetAllElements
// Purpose  :
//================================================================
const TColStd_PackedMapOfInteger& myDataSource::GetAllElements() const
{
	return myElements;
}

//================================================================
// Function : GetNormal
// Purpose  :
//================================================================
Standard_Boolean myDataSource::GetNormal
(const Standard_Integer Id, const Standard_Integer Max,
Standard_Real& nx, Standard_Real& ny, Standard_Real& nz) const
{

	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;
}

前面所述为根据OCC提供源代码定义自己三角网格数据显示的方法,当需要显示体单元时,参考XSDRAWSTLVRML_DataSource3D类。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

leaf_csdn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值