通过这个例子可以直观理解隐函数是什么、在空间中怎么分布、怎么布尔运算。
1.完整代码
#include<vtkBox.h>
#include<vtkNew.h>
#include<vtkActor.h>
#include<vtkSphere.h>
#include<vtkAutoInit.h>
#include<vtkProperty.h>
#include<vtkRenderer.h>
#include<vtkImageData.h>
#include<vtkContourFilter.h>
#include<vtkImplicitBoolean.h>
#include<vtkDataSetMapper.h>
#include<vtkRenderWindow.h>
#include<vtkPolyDataMapper.h>
#include<vtkSampleFunction.h>
#include<vtkRenderWindowInteractor.h>
#include<vtkActor2D.h>
#include<vtkTextActor.h>
#include<vtkTextProperty.h>
#include<vtkCommand.h>
#include<vtkSliderWidget.h>
#include<vtkSliderRepresentation2D.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2)
VTK_MODULE_INIT(vtkInteractionStyle)
VTK_MODULE_INIT(vtkRenderingFreeType)
#include<QString>
class myCallback: public vtkCommand
{
public:
static myCallback *New() {
return new myCallback;
}
void Execute(vtkObject *caller, unsigned long eventId, void *callData) override
{
vtkSliderWidget *widget = (vtkSliderWidget *)caller;
vtkSliderRepresentation2D *slider = (vtkSliderRepresentation2D *)widget->GetRepresentation();
m_contour1->SetValue(0, slider->GetValue());
m_contour2->SetValue(0, slider->GetValue());
m_contour3->SetValue(0, slider->GetValue());
}
vtkContourFilter *m_contour1;
vtkContourFilter *m_contour2;
vtkContourFilter *m_contour3;
private:
myCallback() {
m_contour1 = nullptr;
m_contour2 = nullptr;
m_contour3 = nullptr;
}
~myCallback() {}
};
#define Create(type,name)\
vtkNew<type> name;
int main()
{
//两个隐函数,方盒子和球
Create(vtkBox, box);
box->SetBounds(-1, 1, -1, 1, -1, 1);
Create(vtkSphere, sphere);
sphere->SetRadius(1);
sphere->SetCenter(1, 0, 0);
//隐函数布尔加
Create(vtkImplicitBoolean, add);
add->SetOperationTypeToUnion();
add->AddFunction(box);
add->AddFunction(sphere);
Create(vtkSampleFunction, addSample);
addSample->SetModelBounds(-5, 5, -5, 5, -5, 5);
addSample->SetSampleDimensions(50, 50, 50);
addSample->SetImplicitFunction(add);
Create(vtkContourFilter, contour1);
contour1->SetInputConnection(addSample->GetOutputPort());
contour1->SetValue(0, 0);
Create(vtkDataSetMapper, mapper1);
mapper1->SetInputConnection(contour1->GetOutputPort());
Create(vtkActor, actor1);
actor1->SetMapper(mapper1);
actor1->GetProperty()->SetEdgeVisibility(true);
//隐函数布尔异
Create(vtkImplicitBoolean, diff);
diff->SetOperationTypeToDifference();
diff->AddFunction(box);
diff->AddFunction(sphere);
Create(vtkSampleFunction, diffSample);
diffSample->SetModelBounds(-5, 5, -5, 5, -5, 5);
diffSample->SetSampleDimensions(50, 50, 50);
diffSample->SetImplicitFunction(diff);
Create(vtkContourFilter, contour2);
contour2->SetInputConnection(diffSample->GetOutputPort());
contour2->SetValue(0, 0);
Create(vtkDataSetMapper, mapper2);
mapper2->SetInputConnection(contour2->GetOutputPort());
Create(vtkActor, actor2);
actor2->SetMapper(mapper2);
actor2->GetProperty()->SetEdgeVisibility(true);
//隐函数布尔交
Create(vtkImplicitBoolean, section);
section->SetOperationTypeToIntersection();
section->AddFunction(box);
section->AddFunction(sphere);
Create(vtkSampleFunction, secSample);
secSample->SetModelBounds(-5, 5, -5, 5, -5, 5);
secSample->SetSampleDimensions(50, 50, 50);
secSample->SetImplicitFunction(section);
Create(vtkContourFilter, contour3);
contour3->SetInputConnection(secSample->GetOutputPort());
contour3->SetValue(0, 0);
Create(vtkDataSetMapper, mapper3);
mapper3->SetInputConnection(contour3->GetOutputPort());
Create(vtkActor, actor3);
actor3->SetMapper(mapper3);
actor3->GetProperty()->SetEdgeVisibility(true);
//左上角窗口
Create(vtkRenderer, render1);
render1->AddActor(actor1);
//render1->SetViewport(0, 0, 0.5, 1); 这里错了,难怪坐标系统混乱了
render1->SetViewport(0, 0.5, 0.5, 1);
//右上角窗口
Create(vtkRenderer, render2);
render2->AddActor(actor2);
render2->SetViewport(0.5, 0.5, 1, 1);
//右下角窗口
Create(vtkRenderer, render3);
render3->AddActor(actor3);
render3->SetViewport(0.5, 0, 1, 0.5);
//左上角窗口
Create(vtkRenderer, render4);
render4->SetViewport(0, 0, 0.5, 0.5);
Create(vtkRenderWindow, window);
window->AddRenderer(render1);
window->AddRenderer(render2);
window->AddRenderer(render3);
window->AddRenderer(render4);
Create(vtkRenderWindowInteractor, interactor);
interactor->SetRenderWindow(window);
//显示汉字的方式
Create(vtkTextProperty, textProperty);
textProperty->SetJustificationToCentered();
textProperty->SetVerticalJustificationToCentered();
textProperty->SetFontFamily(VTK_FONT_FILE);
textProperty->SetFontFile("C:/WINDOWS/FONTS/MSYHL.TTC");
//这里多renderer的坐标系统很迷惑,上面Render修改了,没有疑惑了
Create(vtkTextActor, topLeft);
topLeft->SetTextScaleModeToNone();
topLeft->SetTextProperty(textProperty);
topLeft->GetPositionCoordinate()->SetCoordinateSystemToNormalizedViewport();
topLeft->GetPositionCoordinate()->SetValue(0.2, 0.8);
topLeft->SetInput("布尔加");
render1->AddActor(topLeft);
Create(vtkTextActor, topRight);
topRight->SetTextScaleModeToNone();
topRight->SetTextProperty(textProperty);
topRight->GetPositionCoordinate()->SetCoordinateSystemToNormalizedViewport();
topRight->GetPositionCoordinate()->SetValue(0.2, 0.8);
topRight->SetInput("布尔减");
render2->AddActor(topRight);
Create(vtkTextActor, bottemRight);
bottemRight->SetTextScaleModeToNone();
bottemRight->SetTextProperty(textProperty);
bottemRight->GetPositionCoordinate()->SetCoordinateSystemToNormalizedViewport();
bottemRight->GetPositionCoordinate()->SetValue(0.2, 0.8);
bottemRight->SetInput("布尔交");
render3->AddActor(bottemRight);
//滑动条
Create(vtkSliderWidget, widget);
Create(vtkSliderRepresentation2D, slider);
slider->SetMinimumValue(-1);
slider->SetMaximumValue(5);
slider->SetValue(0);
widget->SetRepresentation(slider);
widget->SetAnimationModeToOff();
widget->SetInteractor(interactor);
widget->SetDefaultRenderer(render4);
//滑动条在右侧窗口不显示,有点疑惑,上面render修改了,这里没疑惑了
slider->GetPoint1Coordinate()->SetCoordinateSystemToNormalizedViewport();
slider->GetPoint1Coordinate()->SetValue(0.2, 0.5);
slider->GetPoint2Coordinate()->SetCoordinateSystemToNormalizedViewport();
slider->GetPoint2Coordinate()->SetValue(0.8, 0.5);
widget->EnabledOn();
//回调
Create(myCallback, callback);
callback->m_contour1 = contour1;
callback->m_contour2 = contour2;
callback->m_contour3 = contour3;
widget->AddObserver(vtkCommand::InteractionEvent, callback);
interactor->Start();
return 0;
}
1.隐函数的布尔运算
void SetOperationTypeToUnion(); //并集
void SetOperationTypeToIntersection(); //交集
void SetOperationTypeToDifference(); //差集
void SetOperationTypeToUnionOfMagnitudes(); //尚未理解
2.对隐函数空间采样
Create(vtkSampleFunction, diffSample);
diffSample->SetModelBounds(-5, 5, -5, 5, -5, 5); //采样空间范围
diffSample->SetSampleDimensions(50, 50, 50); //XYZ方向点数
diffSample->SetImplicitFunction(diff);
//输入隐函数,对空间中的点坐标按照隐函数规则进行计算
3.提取等值面
Create(vtkContourFilter, contour2);
contour2->SetInputConnection(diffSample->GetOutputPort());
contour2->SetValue(0, 0);
初始值是0,就是隐函数对应的默认特征。后面通过滑动条改变这个值,可以看到几何特征变大变小。其他值代表了对默认特征的偏离程度,负值向内,正值向外。
4.四个视口显示
//左上角窗口
Create(vtkRenderer, render1);
render1->AddActor(actor1);
render1->SetViewport(0, 0, 0.5, 1);
//右上角窗口
Create(vtkRenderer, render2);
render2->AddActor(actor2);
render2->SetViewport(0.5, 0.5, 1, 1);
//右下角窗口
Create(vtkRenderer, render3);
render3->AddActor(actor3);
render3->SetViewport(0.5, 0, 1, 0.5);
//左上角窗口
Create(vtkRenderer, render4);
render4->SetViewport(0, 0, 0.5, 0.5);
5.显示汉字需要特殊处理
//显示汉字的方式
Create(vtkTextProperty, textProperty);
textProperty->SetJustificationToCentered();
textProperty->SetVerticalJustificationToCentered();
textProperty->SetFontFamily(VTK_FONT_FILE);
textProperty->SetFontFile("C:/WINDOWS/FONTS/MSYHL.TTC");
5.1将字体家族设置为VTK_FONT_FILE,表示从文件获取
5.2获取电脑中的字体文件,此处是微软雅黑,C:/WINDOWS/FONTS/MSYHL.TTC
5.3这样处理之后就可以愉快的输入汉字了
6.多个Renderer中的定位很迷惑
topLeft->GetPositionCoordinate()->SetValue(0.2, 0.9);
topRight->GetPositionCoordinate()->SetValue(0.2, 0.8);
bottemRight->GetPositionCoordinate()->SetValue(0.2, 0.8);
slider->GetPoint1Coordinate()->SetValue(0.2, 0.5);
与单个renderer中理解的不一致,还没搞明白。
修正:问题不在这里,在于左上角的render写错了定位,修改后就没问题了。