在多边形网格中,求某一直线与多边形网格的交点,或者是判断它们是否有相交是极为常见的问题。这篇笔记就是使用OBB Tree来完成这样的需求。
vtkOBBTree
vtkOBBTree是用于生成有向包围盒(OBB)树的对象。一个有向的包围盒不一定是沿着坐标轴对齐的包围盒。OBB树是这种包围盒层次的树形结构,更深层次的OBB划分了更小的空间区域。
关于OBB Tree可以参考Gottschalk和Manocha在Siggraph `96的文章“OBBTree: A Hierarchical Structure for Rapid Interference Detection”,它是一个很好的参考资料。
用法
线段与多边形网格的交点
准确的说,这里的直线是线段,由一个起点和一个终点决定的。
设置多边形网格和线段的两个端点,结果返回交点和cell的id list.
auto intersectionPoints = vsp<vtkPoints>::New();
auto intersectioncells = vsp<vtkIdList>::New();
double tol = 1e-8;
auto obbTree = vsp<vtkOBBTree>::New();
obbTree->SetTolerance(tol);
obbTree->SetDataSet(sphereSource->GetOutput());
obbTree->BuildLocator();
obbTree->IntersectWithLine(lineP0, lineP1, intersectionPoints, intersectioncells);
提取cell
由于返回的是id list, 我们还需要用vtkExtractCells提取一下。
auto cellSource = vsp<vtkExtractCells>::New();
cellSource->SetInputConnection(sphereSource->GetOutputPort());
cellSource->SetCellList(intersectioncells);
示例
我们创建一个球体,求它与一线段的相交。
IntersectWithLine.cxx
#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
#include <vtkLineSource.h>
#include <vtkPoints.h>
#include <vtkIdList.h>
#include <vtkPointData.h>
#include <vtkLine.h>
#include <vtkOBBTree.h>
#include <vtkExtractCells.h>
#include <vtkPolyDataMapper.h>
#include <vtkDataSetMapper.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkProperty.h>
#include <vtkNamedColors.h>
#include <vtkPolyData.h>
#include <vtkVertexGlyphFilter.h>
#define vsp vtkSmartPointer
int main(int, char* [])
{
auto colors = vsp<vtkNamedColors>::New();
auto sphereSource = vsp<vtkSphereSource>::New();
sphereSource->Update();
double lineP0[3] = { -0.6, -0.6, -0.6 };
double lineP1[3] = { .6, .6, .6 };
auto lineSource = vsp<vtkLineSource>::New();
lineSource->SetPoint1(lineP0);
lineSource->SetPoint2(lineP1);
lineSource->Update();
auto intersectionPoints = vsp<vtkPoints>::New();
auto intersectioncells = vsp<vtkIdList>::New();
double tol = 1e-8;
auto obbTree = vsp<vtkOBBTree>::New();
obbTree->SetTolerance(tol);
obbTree->SetDataSet(sphereSource->GetOutput());
obbTree->BuildLocator();
obbTree->IntersectWithLine(lineP0, lineP1, intersectionPoints, intersectioncells);
auto pointsPolydata = vsp<vtkPolyData>::New();
pointsPolydata->SetPoints(intersectionPoints);
auto vertexFilter = vsp<vtkVertexGlyphFilter>::New();
vertexFilter->SetInputData(pointsPolydata);
vertexFilter->Update();
auto polydata = vsp<vtkPolyData>::New();
polydata->ShallowCopy(vertexFilter->GetOutput());
auto cellSource = vsp<vtkExtractCells>::New();
cellSource->SetInputConnection(sphereSource->GetOutputPort());
cellSource->SetCellList(intersectioncells);
auto sphereMapper = vsp<vtkPolyDataMapper>::New();
sphereMapper->SetInputData(sphereSource->GetOutput());
auto sphereActor = vsp<vtkActor>::New();
sphereActor->SetMapper(sphereMapper);
sphereActor->GetProperty()->SetRepresentationToWireframe();
auto lineMapper = vsp<vtkPolyDataMapper>::New();
lineMapper->SetInputData(lineSource->GetOutput());
auto lineActor = vsp<vtkActor>::New();
lineActor->SetMapper(lineMapper);
lineActor->GetProperty()->SetColor(colors->GetColor3d("red").GetData());
auto pointMapper = vsp<vtkPolyDataMapper>::New();
pointMapper->SetInputData(polydata);
auto pointActor = vsp<vtkActor>::New();
pointActor->SetMapper(pointMapper);
pointActor->GetProperty()->SetColor(colors->GetColor3d("blue").GetData());
pointActor->GetProperty()->SetPointSize(8);
auto cellMapper = vsp<vtkDataSetMapper>::New();
cellMapper->SetInputConnection(cellSource->GetOutputPort());
auto cellActor = vsp<vtkActor>::New();
cellActor->SetMapper(cellMapper);
cellActor->GetProperty()->SetColor(colors->GetColor3d("yellow").GetData());
auto renderer = vsp<vtkRenderer>::New();
auto renWinddow = vsp<vtkRenderWindow>::New();
auto interactor = vsp<vtkRenderWindowInteractor>::New();
renWinddow->SetSize(600, 600);
renWinddow->AddRenderer(renderer);
interactor->SetRenderWindow(renWinddow);
renderer->SetBackground(colors->GetColor3d("DarkOliveGreen").GetData());
renderer->AddActor(sphereActor);
renderer->AddActor(lineActor);
renderer->AddActor(pointActor);
renderer->AddActor(cellActor);
interactor->Initialize();
interactor->Start();
return EXIT_SUCCESS;
}
Ref
VTKExamples/Cxx/DataStructures/OBBTreeIntersectWithLine
VTKExamples/Cxx/DataStructures/OBBTreeExtractCells