VTK学习笔记(二十三)vtk空间几何变换
1、VTK相关的类有:
vtkTransform, vtkTransformFilter, vtkMatrix4x4等
相关的方法有:
• RotateX(angle)、RotateY(angle)、RotateZ(angle)
• RotateWXYZ(angle,x,y,z)
• Scale(x,y,z)
• Translate(x,y,z)
• SetMatrix(m)、GetMatrix(m)
• PostMultiply()、PreMultiply()
• SetPosition(x,y,z)、GetPosition(x,y,z)
• SetOrientation(x,y,z)、 GetOrientation(x,y,z)
• SetScale(sx,sy,sz)
• SetOrigin(x,y,z)、GetOrigin
空间变换类
vtkSmartPointer<vtkTransform> trans = vtkSmartPointer<vtkTransform>::New();
在VTK中,矩阵乘法默认是左乘(PreMultiply),在齐次矩阵符号中,M = M*A,其中M为当前变换矩阵,A为要应用矩阵(比如旋转矩阵或者平移矩阵)。
trans->PreMultiply();//M=M*A
源码中是这样解释的: vtkTransform.h的156行
* Sets the internal state of the transform to PreMultiply. All subsequent
* operations will occur before those already represented in the
* current transformation. In homogeneous matrix notation, M = M*A where
* M is the current transformation matrix and A is the applied matrix.
* The default is PreMultiply.
A就是指“All subsequent operations”,M就是指“those already represented in the current transformation”
我对before的理解就是A左乘M(A的左边乘上M)
当然,也可以设置矩阵乘法为右乘(PostMultiply),在齐次矩阵符号中,M = A*M,其中M为当前变换矩阵,A为要应用矩阵(比如旋转矩阵或者平移矩阵)。
trans->PostMultiply();//M=A*M
源码中是这样写的:
* Sets the internal state of the transform to PostMultiply. All subsequent
* operations will occur after those already represented in the
* current transformation. In homogeneous matrix notation, M = A*M where
* M is the current transformation matrix and A is the applied matrix.
* The default is PreMultiply.
我对after的理解就是A右乘M(A的右边乘上M)
实例分析:
三维物体的初始齐次矩阵为:
矩阵右乘(post后置),先旋转再平移
trans->PostMultiply();//M=A*M
trans->RotateZ(30);
trans->Translate(1, 0, 0);
#include <vtkLineSource.h>
#include <vtkPolyData.h>
#include <vtkSmartPointer.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkProperty.h>
#include <vtkAxesActor.h>
#include <vtkConeSource.h>
#include <vtkTextActor.h>
#include <vtkTextProperty.h>
#include <vtkTransform.h>
#include <vtkSphereSource.h>
#include "vtkAutoInit.h"
VTK_MODULE_INIT(vtkRenderingOpenGL2); // VTK was built with vtkRenderingOpenGL2
VTK_MODULE_INIT(vtkInteractionStyle);
VTK_MODULE_INIT(vtkRenderingFreeType)
int main(int, char *[])
{
vtkSmartPointer<vtkSphereSource> sphereSource =
vtkSmartPointer<vtkSphereSource>::New();
sphereSource->SetRadius(0.1);//设置半径
sphereSource->Update();
vtkSmartPointer<vtkPolyDataMapper> sphereMapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
sphereMapper->SetInputConnection(sphereSource->GetOutputPort());
vtkSmartPointer<vtkActor> sphereActor =
vtkSmartPointer<vtkActor>::New();
sphereActor->SetPosition(0, 0, 0);//设置演员的位置
sphereActor->SetMapper(sphereMapper);//设置演员的映射器
sphereActor->GetProperty()->SetColor(1, 0, 0);//设置演员的颜色
vtkSmartPointer<vtkConeSource> coneSource =
vtkSmartPointer<vtkConeSource>::New();
coneSource->SetRadius(.2);
coneSource->SetHeight(.5);
coneSource->SetCenter(0, 0, 0);
vtkSmartPointer<vtkPolyDataMapper> coneMapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
coneMapper->SetInputConnection(coneSource->GetOutputPort());
vtkSmartPointer<vtkActor> coneActor =
vtkSmartPointer<vtkActor>::New();
coneActor->SetMapper(coneMapper);
vtkSmartPointer<vtkActor> oriConeActor =
vtkSmartPointer<vtkActor>::New();
oriConeActor->SetMapper(coneMapper);
#define AXIS_LEN 1.
vtkSmartPointer<vtkAxesActor> oriAxesActor =
vtkSmartPointer<vtkAxesActor>::New();
oriAxesActor->SetPosition(0, 0, 0);
oriAxesActor->SetTotalLength(AXIS_LEN, AXIS_LEN, AXIS_LEN);
oriAxesActor->SetShaftType(0);
oriAxesActor->SetAxisLabels(0);
oriAxesActor->SetCylinderRadius(0.02);
vtkSmartPointer<vtkAxesActor> axesActor =
vtkSmartPointer<vtkAxesActor>::New();
axesActor->SetPosition(0, 0, 0);
axesActor->SetTotalLength(AXIS_LEN, AXIS_LEN, AXIS_LEN);
axesActor->SetShaftType(0);
axesActor->SetAxisLabels(0);
axesActor->SetCylinderRadius(0.02);
vtkSmartPointer<vtkTextActor> textActor =
vtkSmartPointer<vtkTextActor>::New();
textActor->SetPosition2(100, 40);
textActor->GetTextProperty()->SetFontSize(24);
textActor->GetTextProperty()->SetColor(1, 0, 0);
vtkSmartPointer<vtkTransform> trans =
vtkSmartPointer<vtkTransform>::New();
//trans->PostMultiply();//M=A*M
trans->PreMultiply();//M=M*A
trans->RotateZ(30);
//coneActor->SetPosition(1, 0, 0);永远M=M*A
trans->Translate(1, 0, 0);
//trans->RotateZ(30);
//trans->Translate(1, 0, 0);
//trans->RotateZ(30);
coneActor->SetUserTransform(trans);
textActor->SetInput("PostMultiply()\nTranslate(1, 0, 0)\nRotateZ(30)");
cout << "GetMatrix:" << endl;
if (coneActor->GetMatrix() != NULL)
{
coneActor->GetMatrix()->Print(cout);
}
else
{
cout << "NULL" << endl;
}
cout << "GetUserMatrix:" << endl;
if (coneActor->GetUserMatrix() != NULL)
{
coneActor->GetUserMatrix()->Print(cout);
}
else
{
cout << "NULL" << endl;
}
vtkSmartPointer<vtkRenderer> renderer1 =
vtkSmartPointer<vtkRenderer>::New();
vtkSmartPointer<vtkRenderer> renderer2 =
vtkSmartPointer<vtkRenderer>::New();
vtkSmartPointer<vtkRenderWindow> renderWindow =
vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->SetSize(800, 400);
renderWindow->AddRenderer(renderer1);
renderWindow->AddRenderer(renderer2);
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
renderWindowInteractor->SetRenderWindow(renderWindow);
double leftViewport[] = { 0.0, 0.0, 0.5, 1.0 };
double rightViewport[] = { 0.5, 0.0, 1.0, 1.0 };
renderer1->AddActor(oriAxesActor);
renderer1->AddActor(sphereActor);
renderer1->AddActor(oriConeActor);
renderer2->AddActor(axesActor);
renderer2->AddActor(sphereActor);
renderer2->AddActor(coneActor);
renderer2->AddActor2D(textActor);
renderer1->SetBackground(.3, .3, .5);
renderer2->SetBackground(.2, .4, .5);
renderer1->SetViewport(leftViewport);
renderer2->SetViewport(rightViewport);
renderWindow->Render();
renderWindowInteractor->Start();
return EXIT_SUCCESS;
}
参考:【VTK学习】空间几何变换
参考:三维空间几何变换原理[平移、旋转、错切]
参考:VTK中模型的旋转与平移
参考:VTK笔记——空间几何变换(Transform),平移、旋转和缩放
2、OrientedArrow.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import vtk
'''
There are two alternative ways to apply the transform.
1) Use vtkTransformPolyDataFilter to create a new transformed polydata.
This method is useful if the transformed polydata is needed
later in the pipeline
To do this, set USER_MATRIX = True
2) Apply the transform directly to the actor using vtkProp3D's SetUserMatrix.
No new data is produced.
To do this, set USER_MATRIX = False
'''
USER_MATRIX = True
def main():
colors = vtk.vtkNamedColors()
# Set the background color.
colors.SetColor("BkgColor", [26, 51, 77, 255])
# Create an arrow.
arrowSource = vtk.vtkArrowSource()
# Generate a random start and end point
startPoint = [0] * 3
endPoint = [0] * 3
rng = vtk.vtkMinimalStandardRandomSequence()
rng.SetSeed(8775070) # For testing.
for i in range(0, 3):
rng.Next()
startPoint[i] = rng.GetRangeValue(-10, 10)
rng.Next()
endPoint[i] = rng.GetRangeValue(-10, 10)
# Compute a basis
normalizedX = [0] * 3
normalizedY = [0] * 3
normalizedZ = [0] * 3
# The X axis is a vector from start to end
vtk.vtkMath.Subtract(endPoint, startPoint, normalizedX)
length = vtk.vtkMath.Norm(normalizedX)
vtk.vtkMath.Normalize(normalizedX)
# The Z axis is an arbitrary vector cross X
arbitrary = [0] * 3
for i in range(0, 3):
rng.Next()
arbitrary[i] = rng.GetRangeValue(-10, 10)
vtk.vtkMath.Cross(normalizedX, arbitrary, normalizedZ)
vtk.vtkMath.Normalize(normalizedZ)
# The Y axis is Z cross X
vtk.vtkMath.Cross(normalizedZ, normalizedX, normalizedY)
matrix = vtk.vtkMatrix4x4()
# Create the direction cosine matrix
matrix.Identity()
for i in range(0, 3):
matrix.SetElement(i, 0, normalizedX[i])
matrix.SetElement(i, 1, normalizedY[i])
matrix.SetElement(i, 2, normalizedZ[i])
# Apply the transforms
transform = vtk.vtkTransform()
transform.Translate(startPoint)
transform.Concatenate(matrix)
transform.Scale(length, length, length)
# Transform the polydata
transformPD = vtk.vtkTransformPolyDataFilter()
transformPD.SetTransform(transform)
transformPD.SetInputConnection(arrowSource.GetOutputPort())
# Create a mapper and actor for the arrow
mapper = vtk.vtkPolyDataMapper()
actor = vtk.vtkActor()
if USER_MATRIX:
mapper.SetInputConnection(arrowSource.GetOutputPort())
actor.SetUserMatrix(transform.GetMatrix())
else:
mapper.SetInputConnection(transformPD.GetOutputPort())
actor.SetMapper(mapper)
actor.GetProperty().SetColor(colors.GetColor3d("Cyan"))
# Create spheres for start and end point
sphereStartSource = vtk.vtkSphereSource()
sphereStartSource.SetCenter(startPoint)
sphereStartSource.SetRadius(0.8)
sphereStartMapper = vtk.vtkPolyDataMapper()
sphereStartMapper.SetInputConnection(sphereStartSource.GetOutputPort())
sphereStart = vtk.vtkActor()
sphereStart.SetMapper(sphereStartMapper)
sphereStart.GetProperty().SetColor(colors.GetColor3d("Yellow"))
sphereEndSource = vtk.vtkSphereSource()
sphereEndSource.SetCenter(endPoint)
sphereEndSource.SetRadius(0.8)
sphereEndMapper = vtk.vtkPolyDataMapper()
sphereEndMapper.SetInputConnection(sphereEndSource.GetOutputPort())
sphereEnd = vtk.vtkActor()
sphereEnd.SetMapper(sphereEndMapper)
sphereEnd.GetProperty().SetColor(colors.GetColor3d("Magenta"))
# Create a renderer, render window, and interactor
renderer = vtk.vtkRenderer()
renderWindow = vtk.vtkRenderWindow()
renderWindow.SetWindowName("Oriented Arrow")
renderWindow.AddRenderer(renderer)
renderWindowInteractor = vtk.vtkRenderWindowInteractor()
renderWindowInteractor.SetRenderWindow(renderWindow)
# Add the actor to the scene
renderer.AddActor(actor)
renderer.AddActor(sphereStart)
renderer.AddActor(sphereEnd)
renderer.SetBackground(colors.GetColor3d("BkgColor"))
# Render and interact
renderWindow.Render()
renderWindowInteractor.Start()
if __name__ == '__main__':
main()
3、EllipticalCylinderDemo.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import math
import vtk
def main():
nx, ny, nz = get_program_parameters()
colors = vtk.vtkNamedColors()
angle = 0
r1 = 50
r2 = 30
centerX = 10.0
centerY = 5.0
points = vtk.vtkPoints()
idx = 0
while angle <= 2.0 * vtk.vtkMath.Pi() + (vtk.vtkMath.Pi() / 60.0):
points.InsertNextPoint(r1 * math.cos(angle) + centerX,
r2 * math.sin(angle) + centerY,
0.0)
angle = angle + (vtk.vtkMath.Pi() / 60.0)
idx += 1
line = vtk.vtkPolyLine()
line.GetPointIds().SetNumberOfIds(idx)
for i in range(0, idx):
line.GetPointIds().SetId(i, i)
lines = vtk.vtkCellArray()
lines.InsertNextCell(line)
polyData = vtk.vtkPolyData()
polyData.SetPoints(points)
polyData.SetLines(lines)
extrude = vtk.vtkLinearExtrusionFilter()
extrude.SetInputData(polyData)
extrude.SetExtrusionTypeToNormalExtrusion()
extrude.SetVector(nx, ny, nz)
extrude.Update()
# Create an oriented arrow
startPoint = [0.0] * 3
endPoint = [0.0] * 3
startPoint[0] = centerX
startPoint[1] = centerY
startPoint[2] = 0.0
endPoint[0] = startPoint[0] + extrude.GetVector()[0]
endPoint[1] = startPoint[1] + extrude.GetVector()[1]
endPoint[2] = startPoint[2] + extrude.GetVector()[2]
# Compute a basis
normalizedX = [0.0] * 3
normalizedY = [0.0] * 3
normalizedZ = [0.0] * 3
# The X axis is a vector from start to end
vtk.vtkMath.Subtract(endPoint, startPoint, normalizedX)
length = vtk.vtkMath.Norm(normalizedX)
vtk.vtkMath.Normalize(normalizedX)
# The Z axis is an arbitrary vector cross X
arbitrary = [0.0] * 3
arbitrary[0] = vtk.vtkMath.Random(-10, 10)
arbitrary[1] = vtk.vtkMath.Random(-10, 10)
arbitrary[2] = vtk.vtkMath.Random(-10, 10)
vtk.vtkMath.Cross(normalizedX, arbitrary, normalizedZ)
vtk.vtkMath.Normalize(normalizedZ)
# The Y axis is Z cross X
vtk.vtkMath.Cross(normalizedZ, normalizedX, normalizedY)
matrix = vtk.vtkMatrix4x4()
# Create the direction cosine matrix
matrix.Identity()
for i in range(0, 3):
matrix.SetElement(i, 0, normalizedX[i])
matrix.SetElement(i, 1, normalizedY[i])
matrix.SetElement(i, 2, normalizedZ[i])
# Apply the transforms
transform = vtk.vtkTransform()
transform.Translate(startPoint)
transform.Concatenate(matrix)
transform.Scale(length, length, length)
arrowSource = vtk.vtkArrowSource()
arrowSource.SetTipResolution(31)
arrowSource.SetShaftResolution(21)
# Transform the polydata
transformPD = vtk.vtkTransformPolyDataFilter()
transformPD.SetTransform(transform)
transformPD.SetInputConnection(arrowSource.GetOutputPort())
# Create a mapper and actor for the arrow
arrowMapper = vtk.vtkPolyDataMapper()
arrowMapper.SetInputConnection(transformPD.GetOutputPort())
arrowActor = vtk.vtkActor()
arrowActor.SetMapper(arrowMapper)
arrowActor.GetProperty().SetColor(colors.GetColor3d("Tomato"))
tubes = vtk.vtkTubeFilter()
tubes.SetInputData(polyData)
tubes.SetRadius(2.0)
tubes.SetNumberOfSides(21)
lineMapper = vtk.vtkPolyDataMapper()
lineMapper.SetInputConnection(tubes.GetOutputPort())
lineActor = vtk.vtkActor()
lineActor.SetMapper(lineMapper)
lineActor.GetProperty().SetColor(colors.GetColor3d("Peacock"))
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputConnection(extrude.GetOutputPort())
actor = vtk.vtkActor()
actor.SetMapper(mapper)
actor.GetProperty().SetColor(colors.GetColor3d("Banana"))
actor.GetProperty().SetOpacity(.7)
ren = vtk.vtkRenderer()
ren.SetBackground(colors.GetColor3d("SlateGray"))
ren.AddActor(actor)
ren.AddActor(lineActor)
ren.AddActor(arrowActor)
renWin = vtk.vtkRenderWindow()
renWin.SetWindowName("Elliptical Cylinder Demo")
renWin.AddRenderer(ren)
renWin.SetSize(600, 600)
iren = vtk.vtkRenderWindowInteractor()
iren.SetRenderWindow(renWin)
style = vtk.vtkInteractorStyleTrackballCamera()
iren.SetInteractorStyle(style)
camera = vtk.vtkCamera()
camera.SetPosition(0, 1, 0)
camera.SetFocalPoint(0, 0, 0)
camera.SetViewUp(0, 0, 1)
camera.Azimuth(30)
camera.Elevation(30)
ren.SetActiveCamera(camera)
ren.ResetCamera()
ren.ResetCameraClippingRange()
renWin.Render()
iren.Start()
def get_program_parameters():
import argparse
description = 'Elliptical Cylinder Demo.'
epilogue = '''
The example shows the vtkPolyLine that forms the base of the elliptical cylinder
and an oriented arrow that represents the vector that vtkLinearExtrusionFilter
uses to create the cylinder.
The example takes an optional triple that defines the vector for the filter.
The length of the vector is the height of the cylinder.
'''
parser = argparse.ArgumentParser(description=description, epilog=epilogue,
formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument('-nx', nargs='?', const=0.0, default=0.0, type=float)
parser.add_argument('-ny', nargs='?', const=0.0, default=0.0, type=float)
parser.add_argument('-nz', nargs='?', const=100.0, default=100.0, type=float)
args = parser.parse_args()
return args.nx, args.ny, args.nz
if __name__ == '__main__':
main()
4、OrientedCylinder.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import vtk
'''
There are two alternative ways to apply the transform.
1) Use vtkTransformPolyDataFilter to create a new transformed polydata.
This method is useful if the transformed polydata is needed
later in the pipeline
To do this, set USER_MATRIX = True
2) Apply the transform directly to the actor using vtkProp3D's SetUserMatrix.
No new data is produced.
To do this, set USER_MATRIX = False
'''
USER_MATRIX = True
def main():
colors = vtk.vtkNamedColors()
# Set the background color.
colors.SetColor("BkgColor", [26, 51, 77, 255])
# Create a cylinder.
# Cylinder height vector is (0,1,0).
# Cylinder center is in the middle of the cylinder
cylinderSource = vtk.vtkCylinderSource()
cylinderSource.SetResolution(15)
# Generate a random start and end point
startPoint = [0] * 3
endPoint = [0] * 3
rng = vtk.vtkMinimalStandardRandomSequence()
rng.SetSeed(8775070) # For testing.
for i in range(0, 3):
rng.Next()
startPoint[i] = rng.GetRangeValue(-10, 10)
rng.Next()
endPoint[i] = rng.GetRangeValue(-10, 10)
# Compute a basis
normalizedX = [0] * 3
normalizedY = [0] * 3
normalizedZ = [0] * 3
# The X axis is a vector from start to end
vtk.vtkMath.Subtract(endPoint, startPoint, normalizedX)
length = vtk.vtkMath.Norm(normalizedX)
vtk.vtkMath.Normalize(normalizedX)
# The Z axis is an arbitrary vector cross X
arbitrary = [0] * 3
for i in range(0, 3):
rng.Next()
arbitrary[i] = rng.GetRangeValue(-10, 10)
vtk.vtkMath.Cross(normalizedX, arbitrary, normalizedZ)
vtk.vtkMath.Normalize(normalizedZ)
# The Y axis is Z cross X
vtk.vtkMath.Cross(normalizedZ, normalizedX, normalizedY)
matrix = vtk.vtkMatrix4x4()
# Create the direction cosine matrix
matrix.Identity()
for i in range(0, 3):
matrix.SetElement(i, 0, normalizedX[i])
matrix.SetElement(i, 1, normalizedY[i])
matrix.SetElement(i, 2, normalizedZ[i])
# Apply the transforms
transform = vtk.vtkTransform()
transform.Translate(startPoint) # translate to starting point
transform.Concatenate(matrix) # apply direction cosines
transform.RotateZ(-90.0) # align cylinder to x axis
transform.Scale(1.0, length, 1.0) # scale along the height vector
transform.Translate(0, .5, 0) # translate to start of cylinder
# Transform the polydata
transformPD = vtk.vtkTransformPolyDataFilter()
transformPD.SetTransform(transform)
transformPD.SetInputConnection(cylinderSource.GetOutputPort())
# Create a mapper and actor for the arrow
mapper = vtk.vtkPolyDataMapper()
actor = vtk.vtkActor()
if USER_MATRIX:
mapper.SetInputConnection(cylinderSource.GetOutputPort())
actor.SetUserMatrix(transform.GetMatrix())
else:
mapper.SetInputConnection(transformPD.GetOutputPort())
actor.SetMapper(mapper)
actor.GetProperty().SetColor(colors.GetColor3d("Cyan"))
# Create spheres for start and end point
sphereStartSource = vtk.vtkSphereSource()
sphereStartSource.SetCenter(startPoint)
sphereStartSource.SetRadius(0.8)
sphereStartMapper = vtk.vtkPolyDataMapper()
sphereStartMapper.SetInputConnection(sphereStartSource.GetOutputPort())
sphereStart = vtk.vtkActor()
sphereStart.SetMapper(sphereStartMapper)
sphereStart.GetProperty().SetColor(colors.GetColor3d("Yellow"))
sphereEndSource = vtk.vtkSphereSource()
sphereEndSource.SetCenter(endPoint)
sphereEndSource.SetRadius(0.8)
sphereEndMapper = vtk.vtkPolyDataMapper()
sphereEndMapper.SetInputConnection(sphereEndSource.GetOutputPort())
sphereEnd = vtk.vtkActor()
sphereEnd.SetMapper(sphereEndMapper)
sphereEnd.GetProperty().SetColor(colors.GetColor3d("Magenta"))
# Create a renderer, render window, and interactor
renderer = vtk.vtkRenderer()
renderWindow = vtk.vtkRenderWindow()
renderWindow.AddRenderer(renderer)
renderWindow.SetWindowName("Oriented Cylinder")
renderWindowInteractor = vtk.vtkRenderWindowInteractor()
renderWindowInteractor.SetRenderWindow(renderWindow)
# Add the actor to the scene
renderer.AddActor(actor)
renderer.AddActor(sphereStart)
renderer.AddActor(sphereEnd)
renderer.SetBackground(colors.GetColor3d("BkgColor"))
# Render and interact
renderWindow.Render()
renderWindowInteractor.Start()
if __name__ == '__main__':
main()
5、CollisionDetection.py
#!/usr/bin/env python
import time
import vtk
def get_program_parameters():
import argparse
description = 'Collision detection.'
epilogue = '''
This examples uses vtkCollisionDetectionFilter to find the intersection between a
fixed (solid white) and moving (red wireframe) sphere.
The animation places the moving sphere some distance from the fixed sphere and
moves the moving sphere until it contacts the fixed sphere.
Three collision modes are available and can be set as the first argument on the command line.
1. All contacts (0) finds all the contacting cell pairs with two points per collision.
2. First contact (1) quickly find the first contact point.
3. Half contacts (2) finds all the contacting cell pairs with one points per collision.
'''
parser = argparse.ArgumentParser(description=description, epilog=epilogue,
formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument('contactMode', nargs='?', default=0, type=int, help='Contact mode 0 (default), 1, or 2.')
args = parser.parse_args()
return args.contactMode
def main():
contactMode = get_program_parameters()
# Define colors
colors = vtk.vtkNamedColors()
sphere0 = vtk.vtkSphereSource()
sphere0.SetRadius(.29)
sphere0.SetPhiResolution(31)
sphere0.SetThetaResolution(31)
sphere0.SetCenter(0.0, 0, 0)
sphere1 = vtk.vtkSphereSource()
sphere1.SetPhiResolution(30)
sphere1.SetThetaResolution(30)
sphere1.SetRadius(0.3)
matrix1 = vtk.vtkMatrix4x4()
transform0 = vtk.vtkTransform()
collide = vtk.vtkCollisionDetectionFilter()
collide.SetInputConnection(0, sphere0.GetOutputPort())
collide.SetTransform(0, transform0)
collide.SetInputConnection(1, sphere1.GetOutputPort())
collide.SetMatrix(1, matrix1)
collide.SetBoxTolerance(0.0)
collide.SetCellTolerance(0.0)
collide.SetNumberOfCellsPerNode(2)
if contactMode == 0:
collide.SetCollisionModeToAllContacts()
elif contactMode == 1:
collide.SetCollisionModeToFirstContact()
else:
collide.SetCollisionModeToHalfContacts()
collide.GenerateScalarsOn()
# Visualize
mapper1 = vtk.vtkPolyDataMapper()
mapper1.SetInputConnection(collide.GetOutputPort(0))
mapper1.ScalarVisibilityOff()
actor1 = vtk.vtkActor()
actor1.SetMapper(mapper1)
actor1.GetProperty().BackfaceCullingOn()
actor1.SetUserTransform(transform0)
actor1.GetProperty().SetDiffuseColor(colors.GetColor3d("Tomato"))
actor1.GetProperty().SetRepresentationToWireframe()
mapper2 = vtk.vtkPolyDataMapper()
mapper2.SetInputConnection(collide.GetOutputPort(1))
actor2 = vtk.vtkActor()
actor2.SetMapper(mapper2)
actor2.GetProperty().BackfaceCullingOn()
actor2.SetUserMatrix(matrix1)
mapper3 = vtk.vtkPolyDataMapper()
mapper3.SetInputConnection(collide.GetContactsOutputPort())
mapper3.SetResolveCoincidentTopologyToPolygonOffset()
actor3 = vtk.vtkActor()
actor3.SetMapper(mapper3)
actor3.GetProperty().SetColor(colors.GetColor3d("Black"))
actor3.GetProperty().SetLineWidth(3.0)
txt = vtk.vtkTextActor()
txt.GetTextProperty().SetFontSize(18)
renderer = vtk.vtkRenderer()
renderer.UseHiddenLineRemovalOn()
renderer.AddActor(actor1)
renderer.AddActor(actor2)
renderer.AddActor(actor3)
renderer.AddActor(txt)
renderer.SetBackground(colors.GetColor3d("Gray"))
renderer.UseHiddenLineRemovalOn()
renderWindow = vtk.vtkRenderWindow()
renderWindow.SetSize(640, 480)
renderWindow.AddRenderer(renderer)
interactor = vtk.vtkRenderWindowInteractor()
interactor.SetRenderWindow(renderWindow)
# Move the first object
numSteps = 100
dx = 1.0 / float(numSteps) * 2.0
transform0.Translate(-numSteps * dx - .3, 0.0, 0.0)
renderWindow.Render()
renderer.GetActiveCamera().Azimuth(-60)
renderer.GetActiveCamera().Elevation(45)
renderer.GetActiveCamera().Dolly(1.2)
renderWindow.SetWindowName('CollisionDetection')
renderWindow.Render()
for i in range(0, numSteps):
transform0.Translate(dx, 0.0, 0.0)
renderer.ResetCameraClippingRange()
s = '{:s}: Number of contact cells is {:d}'.format(collide.GetCollisionModeAsString(),
collide.GetNumberOfContacts())
txt.SetInput(s)
renderWindow.Render()
if collide.GetNumberOfContacts() > 0:
break
# The total animation time is 3 seconds
time.sleep(3.0 / numSteps)
renderer.ResetCamera()
renderWindow.Render()
renderWindow.Render()
interactor.Start()
# In Field Data there will be an array named "ContactCells".
# This array indexes contacting cells (e.g.) index 10 of array 0
# points to a cell (triangle) which contacts/intersects a cell
# at index 10 of array 1.
# You can directly obtain these, see GetContactCells(int i)
# in the documentation.
# print(collide.GetOutput(0))
# print(collide.GetOutput(1))
if __name__ == '__main__':
main()