VTK是一款十分优秀的可视化套件,开源且功能强大,基本上可以满足有限元领域的全部可视化需求。遗憾的是,VTK不支持CAD模型(如igs、stp格式的模型)的显示。
在网上搜索后可以发现,在不花钱的情况下,想要显示和处理CAD模型,基本上都得使用OpenCasCade,即OCC。OCC有自己的可视化系统,也可以集成在Qt中,网上也有相关的Demo。但对我而已,OCC自己的可视化系统还是太复杂了。为了一个简单的显示功能,专门去深入学习OCC的可视化系统还是太难为人了。如果能直接用VTK显示OCC的模型就好了。
万幸,OCC也知道很多人和我有一样的需求,在6.8版本开发了VIS(VTK Integration Services)功能,之后的版本就可以使用VTK进行模型的可视化了。
为了使用VIS功能,编译OCC的时候需要选择USE_VTK的选项,编译完成后,将生成TKIVtk、TKIVtkDraw的动态库和静态库。如果编译路径下有这两个库,说明VIS的功能是编译成功了。
编写一个最小案例看看显示效果。
CMakeLists.txt
cmake_minimum_required(VERSION 3.15)
project(occvtk LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(VTK_DIR "C:/Program Files/VTK/lib/cmake/vtk-9.1")
find_package(VTK COMPONENTS
vtkCommonCore
vtkFiltersCore
vtkCommonDataModel
vtkInteractionStyle
vtkRenderingContextOpenGL2
vtkRenderingCore
vtkRenderingFreeType
vtkRenderingGL2PSOpenGL2
vtkRenderingOpenGL2
QUIET
)
include_directories("C:/Program Files/OCCT/inc")
link_directories("C:/Program Files/OCCT/win64/vc14/lib")
add_executable(make_box make_box.cpp)
target_link_libraries(make_box
TKPrim TKIVtk TKMath TKernel
TKTopAlgo TKGeomAlgo TKV3d
${VTK_LIBRARIES})
make_box.cpp 文件
#include <BRepPrimAPI_MakeBox.hxx>
#include <IVtkTools_ShapeDataSource.hxx>
#include <vtkType.h>
#include <vtkAutoInit.h>
#include <vtkRenderWindow.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkPolyDataMapper.h>
#include <vtkInteractorStyleTrackballCamera.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2)
VTK_MODULE_INIT(vtkInteractionStyle)
int main()
{
BRepPrimAPI_MakeBox mkBox(1., 2., 3);
const TopoDS_Shape& shape = mkBox.Shape();
vtkNew<IVtkTools_ShapeDataSource> occSource;
occSource->SetShape(new IVtkOCC_Shape(shape));
vtkNew<vtkPolyDataMapper> mapper;
mapper->SetInputConnection(occSource->GetOutputPort());
vtkNew<vtkActor> actor;
actor->SetMapper(mapper);
vtkNew<vtkRenderer> ren;
ren->AddActor(actor);
vtkNew<vtkRenderWindow> renWin;
renWin->AddRenderer(ren);
renWin->SetSize(640, 640);
vtkNew<vtkInteractorStyleTrackballCamera> istyle;
vtkNew<vtkRenderWindowInteractor> iren;
iren->SetRenderWindow(renWin);
iren->SetInteractorStyle(istyle);
renWin->Render();
iren->Start();
return 0;
}
显示效果如下:
看着还不错。但模型中有一堆白线,有没有什么方法去掉呢。
经过搜索,发现这个白线叫什么iso line,可以通过IVtkOCC_ShapeMesher去掉。
查看上面的代码,是没有涉及到IVtkOCC_ShapeMesher的。继续查阅文档,发现VIS有两种接口,一种是high-level API,就是上面那种,另一种是low-level API,可以控制的东西更多一些。
现在试试low-level API。
在CMakeLists.txt文件中添加:
add_executable(make_box2 make_box2.cpp)
target_link_libraries(make_box2
TKPrim TKIVtk TKMath TKernel
TKTopAlgo TKGeomAlgo TKV3d
${VTK_LIBRARIES})
编写make_box2.cpp文件:
#include <BRepPrimAPI_MakeBox.hxx>
#include <IVtkVTK_ShapeData.hxx>
#include <IVtkOCC_ShapeMesher.hxx>
#include <vtkType.h>
#include <vtkAutoInit.h>
#include <vtkRenderWindow.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkPolyDataMapper.h>
#include <vtkInteractorStyleTrackballCamera.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2)
VTK_MODULE_INIT(vtkInteractionStyle)
int main()
{
BRepPrimAPI_MakeBox mkBox(1., 2., 3);
const TopoDS_Shape& shape = mkBox.Shape();
IVtkOCC_Shape::Handle aShapeImpl = new IVtkOCC_Shape(shape);
IVtkVTK_ShapeData::Handle aDataImpl = new IVtkVTK_ShapeData();
IVtk_IShapeMesher::Handle aMesher = new IVtkOCC_ShapeMesher(0.0001, 12.0*M_PI/180, 0, 0);
aMesher->Build(aShapeImpl, aDataImpl);
vtkPolyData* aPolyData = aDataImpl->getVtkPolyData();
vtkNew<vtkPolyDataMapper> mapper;
mapper->SetInputData(aPolyData);
vtkNew<vtkActor> actor;
actor->SetMapper(mapper);
vtkNew<vtkRenderer> ren;
ren->AddActor(actor);
vtkNew<vtkRenderWindow> renWin;
renWin->AddRenderer(ren);
renWin->SetSize(960, 800);
vtkNew<vtkInteractorStyleTrackballCamera> istyle;
vtkNew<vtkRenderWindowInteractor> iren;
iren->SetRenderWindow(renWin);
iren->SetInteractorStyle(istyle);
renWin->Render();
iren->Start();
return 0;
}
这一次的显示效果如下:
可以看到,白线没有了。
试一下显示stp文件。
在CMakeLists.txt文件中添加:
add_executable(import_step2 import_step2.cpp)
target_link_libraries(import_step2
TKSTEP TKIVtk TKV3d
TKGeomAlgo TKMath TKXSBase TKernel
${VTK_LIBRARIES})
import_step2.cpp文件:
#include <STEPControl_Reader.hxx>
#include <Standard_Integer.hxx>
#include <TopoDS_Shape.hxx>
#include <IFSelect_ReturnStatus.hxx>
#include <IFSelect_PrintCount.hxx>
#include <IVtkVTK_ShapeData.hxx>
#include <IVtkOCC_ShapeMesher.hxx>
#include <vtkType.h>
#include <vtkAutoInit.h>
#include <vtkRenderWindow.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkPolyDataMapper.h>
#include <vtkInteractorStyleTrackballCamera.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2)
VTK_MODULE_INIT(vtkInteractionStyle)
int main()
{
STEPControl_Reader reader;
IFSelect_ReturnStatus stat = reader.ReadFile("assembly_solid.stp");
IFSelect_PrintCount mode = IFSelect_CountByItem;
Standard_Integer NbRoots = reader.NbRootsForTransfer();
Standard_Integer num = reader.TransferRoots();
Standard_Integer NbTrans = reader.TransferRoots();
TopoDS_Shape result = reader.OneShape();
TopoDS_Shape shape = reader.Shape();
Handle_IVtkOCC_Shape aShapeImpl = new IVtkOCC_Shape(shape);
Handle_IVtkVTK_ShapeData aDataImpl = new IVtkVTK_ShapeData();
Handle_IVtk_IShapeMesher aMesher = new IVtkOCC_ShapeMesher(0.0001, 12.0 * M_PI / 180, 0, 0);
aMesher->Build(aShapeImpl, aDataImpl);
vtkPolyData* aPolyData = aDataImpl->getVtkPolyData();
vtkNew<vtkPolyDataMapper> mapper;
mapper->SetInputData(aPolyData);
vtkNew<vtkActor> actor;
actor->SetMapper(mapper);
vtkNew<vtkRenderer> ren;
ren->AddActor(actor);
vtkNew<vtkRenderWindow> renWin;
renWin->AddRenderer(ren);
renWin->SetSize(960, 800);
vtkNew<vtkInteractorStyleTrackballCamera> istyle;
vtkNew<vtkRenderWindowInteractor> iren;
iren->SetRenderWindow(renWin);
iren->SetInteractorStyle(istyle);
renWin->Render();
iren->Start();
return 0;
}
这个效果就不是很理想了,弧面被离散成了很多小面片,不是很光滑。
继续查看OCC的文档看看有什么解决方法,发现可以使用vtkPolyDataNormals进行光滑。试一下效果。
在CMakeLists.txt文件中添加:
add_executable(import_step3 import_step3.cpp)
target_link_libraries(import_step3
TKSTEP TKIVtk TKV3d TKGeomAlgo
TKMath TKXSBase TKernel
${VTK_LIBRARIES})
import_step3.cpp文件:
#include <STEPControl_Reader.hxx>
#include <Standard_Integer.hxx>
#include <TopoDS_Shape.hxx>
#include <IFSelect_ReturnStatus.hxx>
#include <IFSelect_PrintCount.hxx>
#include <IVtkVTK_ShapeData.hxx>
#include <IVtkOCC_ShapeMesher.hxx>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkPolyDataMapper.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkPolyDataNormals.h>
#include <vtkType.h>
#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2)
VTK_MODULE_INIT(vtkInteractionStyle)
int main()
{
STEPControl_Reader reader;
IFSelect_ReturnStatus stat = reader.ReadFile("assembly_solid.stp");
IFSelect_PrintCount mode = IFSelect_CountByItem;
Standard_Integer NbRoots = reader.NbRootsForTransfer();
Standard_Integer num = reader.TransferRoots();
Standard_Integer NbTrans = reader.TransferRoots();
TopoDS_Shape result = reader.OneShape();
TopoDS_Shape shape = reader.Shape();
Handle_IVtkOCC_Shape aShapeImpl = new IVtkOCC_Shape(shape);
Handle_IVtkVTK_ShapeData aDataImpl = new IVtkVTK_ShapeData();
Handle_IVtk_IShapeMesher aMesher = new IVtkOCC_ShapeMesher(0.0001, 3.0 * M_PI / 180, 0, 0);
aMesher->Build(aShapeImpl, aDataImpl);
vtkPolyData* aPolyData = aDataImpl->getVtkPolyData();
vtkNew<vtkPolyDataNormals> normalGenerator;
normalGenerator->SetInputData(aPolyData);
normalGenerator->Update();
vtkNew<vtkPolyDataMapper> mapper;
mapper->SetInputConnection(normalGenerator->GetOutputPort());
vtkNew<vtkActor> actor;
actor->SetMapper(mapper);
vtkNew<vtkRenderer> ren;
ren->AddActor(actor);
vtkNew<vtkRenderWindow> renWin;
renWin->AddRenderer(ren);
renWin->SetSize(960, 800);
vtkNew<vtkInteractorStyleTrackballCamera> istyle;
vtkNew<vtkRenderWindowInteractor> iren;
iren->SetRenderWindow(renWin);
iren->SetInteractorStyle(istyle);
renWin->Render();
iren->Start();
return 0;
}
这一次效果就好了很多,基本已经可以满足常规需求了。如果对显示效果还有更高要求,可以进一步修改IVtkOCC_ShapeMesher里的参数。
标签:VTK,iren,Shape,CAD,renWin,include,OCC,vtkNew From: https://www.cnblogs.com/vaughnhuang/p/17573273.html