Reputation: 362
Using VTK in python i wrote some code to create an actor for objects that i want, e.g. for cylinder:
def cylinder_object(startPoint, endPoint, radius, my_color="DarkRed"):
USER_MATRIX = True
colors = vtk.vtkNamedColors()
cylinderSource = vtk.vtkCylinderSource()
cylinderSource.SetRadius(radius)
cylinderSource.SetResolution(50)
rng = vtk.vtkMinimalStandardRandomSequence()
rng.SetSeed(8775070) # For testing.8775070
# 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(my_color))
return actor
This function returns an actor where i can render it later using vtkRender
.
Now what i want is to first find whether two given cylinder Actors
are intersected or not and second find the intersection points.
Could i use the vtkTriangleFilter
on my cylinder and use the vtkOBBTree
and ray casting to find whether the intersection happens or not?
Here are two oriented cylinders that are intersected:
Upvotes: 3
Views: 2230
Reputation: 1145
First, you'll need to work on the vtkPolyData object (i.e. the geometry), not on the vtkActor. You'll probably need to use vtkTransformPolyDataFilter output as your vtkPolyData (as you did in the else statement - example here) rather than calling setUserMatrix.
You can use vtkBooleanOperationPolyDataFilter: an example can be found here (in C++, but I'm sure it can help) and here (in Python). If the resulting geometry is not empty, then the cylinders intersect.
If it does not fit your needs, you can convert the cylinders from polydata to imagedata (image volume, voxels) using vtkImplicitModeller; then computing the intersection volume is easier and more accurate (you can use vtkImageLogic). You can also convert the intersection back to vtkPolyData using vtkFlyingEdges3D (a fast version of vtkMarchingCubes).
Edit: as disussed in the comments, because there are many cylinders execution time is a matter. You could try to optimize the process by computing the distance between the axis of each pair of cylinders to detect IF they intersect and in case they do, compute the intersection as described in the first part of this answer. My idea is the following: compute the shortest distance between the segments (one method is described here, there's also the c++ code for segment-to-segment distance, that's what you need). Compare the distance with the sum of the radius of the two cylinders and if it's shorter, compute the intersection.
Upvotes: 1