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()

猜你喜欢

转载自blog.csdn.net/juluwangriyue/article/details/123858941
今日推荐