The algorithm vtkOBBTree::ComputeOBB can help us to calculate the three axes defining the orientation of the OBB(oriented bounding box). It is very useful for us to get the model’s spatial features.
#include <iostream>
#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
#include <vtkActor.h>
#include <vtkConeSource.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkLight.h>
#include <vtkCamera.h>
#include <vtkOBBTree.h>
#include <vtkActor2D.h>
#include <stdio.h>
#include <vtkLineSource.h>
#include <vtkPolyDataMapper.h>
#include "tool.h"
#include <vtkSTLReader.h>
using namespace std;
#define vSP vtkSmartPointer
#define vSPNew(Var, Type) vSP<Type> Var = vSP<Type>::New();
int main()
{
setbuf( stdout, nullptr );
vSPNew( reader, vtkSTLReader );
reader->SetFileName( "~/Desktop/arch_u.stl" );
reader->Update();
vtkSmartPointer<vtkPolyDataMapper> mapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputData( reader->GetOutput() );
vtkSmartPointer<vtkActor> actor =
vtkSmartPointer<vtkActor>::New();
actor->SetMapper( mapper );
vtkSmartPointer<vtkRenderer> renderer =
vtkSmartPointer<vtkRenderer>::New();
renderer->AddActor(actor);
renderer->SetBackground( 0, 0, 0 );
vtkSmartPointer<vtkRenderWindow> renderWindow =
vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->AddRenderer( renderer );
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
renderWindowInteractor->SetRenderWindow( renderWindow );
renderer->ResetCamera();
PointStruct corner, max, mid, min, size;
PointStruct realSize;
vSPNew( obbTree, vtkOBBTree );
obbTree->ComputeOBB( reader->GetOutput(), corner.point, max.point, mid.point, min.point, size.point );
cout << "corner: (" << corner[0] << ", " << corner[1] << ", " << corner[2] << ")\n";
cout << "max: (" << max[0] << ", " << max[1] << ", " << max[2] << ")\n";
cout << "mid: (" << mid[0] << ", " << mid[1] << ", " << mid[2] << ")\n";
cout << "min: (" << min[0] << ", " << min[1] << ", " << min[2] << ")\n";
cout << "size: (" << size[0] << ", " << size[1] << ", " << size[2] << ")\n";
realSize[0] = max.Length();
realSize[1] = mid.Length();
realSize[2] = min.Length();
max.Unit();
mid.Unit();
min.Unit();
cout << "max: (" << max[0] << ", " << max[1] << ", " << max[2] << ")\n";
cout << "mid: (" << mid[0] << ", " << mid[1] << ", " << mid[2] << ")\n";
cout << "min: (" << min[0] << ", " << min[1] << ", " << min[2] << ")\n";
PointStruct tmp2(corner + max*size[0]);
vSPNew( line1, vtkLineSource );
line1->SetPoint1( corner.point );
line1->SetPoint2( (corner + max*realSize[0]).point );
cout << "corner1: " << corner;
cout << "corner2: " << tmp2;
line1->Update();
vSPNew( mapper1, vtkPolyDataMapper );
mapper1->SetInputData( line1->GetOutput() );
vSPNew( actor1, vtkActor );
actor1->SetMapper( mapper1 );
actor1->GetProperty()->SetColor( 1, 0, 0 );
actor1->GetProperty()->SetLineWidth(1);
renderer->AddActor( actor1 );
vSPNew( line2, vtkLineSource );
line2->SetPoint1( corner.point );
line2->SetPoint2( (corner + mid*realSize[1]).point );
line2->Update();
vSPNew( mapper2, vtkPolyDataMapper );
mapper2->SetInputData( line2->GetOutput() );
vSPNew( actor2, vtkActor );
actor2->SetMapper( mapper2 );
actor2->GetProperty()->SetColor( 0, 1, 0 );
actor2->GetProperty()->SetLineWidth(1);
renderer->AddActor( actor2 );
vSPNew( line3, vtkLineSource );
line3->SetPoint1( corner.point );
line3->SetPoint2( (corner + min*realSize[2]).point );
line3->Update();
vSPNew( mapper3, vtkPolyDataMapper );
mapper3->SetInputData( line3->GetOutput() );
vSPNew( actor3, vtkActor );
actor3->SetMapper( mapper3 );
actor3->GetProperty()->SetColor( 0, 0, 1 );
actor3->GetProperty()->SetLineWidth(1);
renderer->AddActor( actor3 );
renderWindow->Render();
renderWindowInteractor->Start();
return 0;
}
Output for Upper arch:
corner: (-39.4753, -5.01287, 25.2395)
max: (75.0509, -0.322946, 5.87045)
mid: (4.56893, 4.13678, -58.1839)
min: (-0.0429759, 34.3649, 2.43991)
size: (414.106, 288.631, 69.7376)
max: (0.996946, -0.00428989, 0.0779808)
mid: (0.0780887, 0.0707028, -0.994436)
min: (-0.00124743, 0.997488, 0.0708218)
corner1: PointStruct [-39.4753, -5.01287, 25.2395]
corner2: PointStruct [373.366, -6.78934, 57.5319]
If we rotate the original polydata, the OBB algorithm can also help us find correct axes.
vSPNew( trans, vtkTransform );
trans->RotateX( 90 );
trans->Update();
vSPNew( transformFilter, vtkTransformFilter );
transformFilter->SetInputData( reader->GetOutput() );
transformFilter->SetTransform( trans );
transformFilter->Update();
vtkSmartPointer<vtkPolyDataMapper> mapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputData( transformFilter->GetPolyDataOutput() );
[…] the arch to ignore other cells that normals are not equal to the min axes. You can read the article Explore The Orientation Of 3D Object about the min […]
[…] its center. I want to find the axes of the 3D model just as vtkOBBTree, relative article: Explore The Orientation Of 3D Object. But all points on the curve are in the same plane, so neither vtkOBBTree nor vtkHull can help […]
Hello, how do you define your # include “tool. h” and PointStruct?