Capping the elliptical cylinder example

Hello all,

Given the Linear extrusion example, and the elliptical cylinder example, I produced an elliptical cylinder with a capped top and bottom. This is done by extruding towards the center of the ellipse then forwards.
The ellipse is functionally the same as the example:

double angle = 0;
double rx, ry;
double centerX, centerY;
double resolution = 18.0; // Better to be multiples of 6
rx = 20;
ry = 30;
centerX = 0.0;
centerY = 0.0;
double centerZ = -50.0;
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
int id = 0;
while (angle <= 2.0 * vtkMath::Pi() + (vtkMath::Pi() / resolution))
{
	points->InsertNextPoint(
		rx * cos(angle) + centerX,
		ry * sin(angle) + centerY,
		centerZ);
	angle = angle + (vtkMath::Pi() / resolution);
	++id;
}
   ...
vtkSmartPointer<vtkLinearExtrusionFilter> extrudeIn = vtkSmartPointer<vtkLinearExtrusionFilter>::New();
extrudeIn->SetInputData(polyData);
extrudeIn->SetExtrusionTypeToPointExtrusion();
extrudeIn->SetExtrusionPoint(0, 0, -50);
extrudeIn->SetScaleFactor(-1.0);
extrudeIn->Update();

vtkSmartPointer<vtkLinearExtrusionFilter> extrudeForward = vtkSmartPointer<vtkLinearExtrusionFilter>::New();
extrudeForward->SetInputConnection(extrudeIn->GetOutputPort());
extrudeForward->SetExtrusionTypeToVectorExtrusion();
extrudeForward->SetVector(0, 0, 100);
extrudeForward->Update();

where the polydata is functionally the same as elliptical cylinder example; the center of the ellipse is (0,0,-50), and extrudes forwards by 100 in z direction.

The problem:
when it extruded inwards, it creates a point in the center, and connects the points in the circumference with lines, and when extruded forwards, the lines form its own surfaces inside the cylinder:

How to avoid the lines being connected when extruding forwards?

An indirect solution would be to identify the interior lines and remove them, however I would need to convert the extrudeIn data back to vtkPoints and re-generate vtkPolyLine, and even then I don’t have a clue how to identify interior lines.

Source:
Look for the EllipticalCylinder() method
Cutter.cxx (12.3 KB) CMakeLists.txt (688 Bytes)

Hello, Friend,

Why do you do that way? To cap the ends of the cylinder you simply call CappingOn () on the vtkLinearExtrusionFilter object and do the extrusion once.

To achieve the same effect but without the artifact, your pipeline should be just like this:

vtkSmartPointer<vtkLinearExtrusionFilter> extrude = vtkSmartPointer<vtkLinearExtrusionFilter>::New();
extrude->SetInputData(polyData);
extrude->SetExtrusionTypeToVectorExtrusion();
extrude->SetVector(0, 0, 100);
extrude->CappingOn();
extrude->Update();

all the best,

Paulo

Hello, sorry for the long silence, I moved away from the project for a while, and had just got back to it recently.

Unfortunately, the SetCappingOn() made no difference, not sure if it is a bug or not on vtk’s part.

Regardless, turns out a simpler solution is indeed possible, simply create 2 ellipses (the caps), extrude the back one forwards, then combine them via the Combine Poly data example.

The result is this, with no enclosed surfaces.
image

Pipeline is as follows:

void CreateEllipse(vtkVector3d center, std::vector<vtkVector3d> &points, double radiusX, double radiusY, double zPosition, int resolution = 20)
{
	double stepAngleDeg = 360.0 / resolution;
	double stepAngleRad = stepAngleDeg * (vtkMath::Pi() / 180.0);

	for (double theta = 0; theta < 2 * vtkMath::Pi(); theta += stepAngleRad)
	{
		double x = center.GetX() + (std::cos(theta) * radiusX);
		double y = center.GetY() + (std::sin(theta) * radiusY);
		points.push_back(vtkVector3d(x, y, zPosition));
	
	}
}
....

// main
std::vector<vtkVector3d> backEllipse, frontEllipse;
double height = 200;
CreateEllipse(vtkVector3d(0, 0, 0), backEllipse, 35, 65, 0 - (height / 2.0));
CreateEllipse(vtkVector3d(0, 0, 0), frontEllipse, 35, 65, 0 + (height / 2.0));

vtkSmartPointer<vtkPolyData> backEllipsePolyData, frontEllipsePolyData;
ConstructPolyDataFromPoints(backEllipse, backEllipsePolyData);
ConstructPolyDataFromPoints(frontEllipse, frontEllipsePolyData);

vtkSmartPointer<vtkLinearExtrusionFilter> extrudeForward = vtkSmartPointer<vtkLinearExtrusionFilter>::New();
extrudeForward->SetInputData(backEllipsePolyData);
extrudeForward->SetExtrusionTypeToVectorExtrusion();
extrudeForward->SetVector(0, 0, height);
extrudeForward->CappingOn();
extrudeForward->Update();

//Append the two meshes
vtkSmartPointer<vtkAppendPolyData> appendFilter = vtkSmartPointer<vtkAppendPolyData>::New();
appendFilter->AddInputData(extrudeForward->GetOutput());
appendFilter->AddInputData(frontEllipsePolyData);

// Remove any duplicate points.
vtkSmartPointer<vtkCleanPolyData> cleanFilter = vtkSmartPointer<vtkCleanPolyData>::New();
cleanFilter->SetInputConnection(appendFilter->GetOutputPort());
cleanFilter->Update();

Hope this helps anyone in the future.

There is a one line solution for the elliptical cylinder example! I think this line was left out. (This solution is in Python but C++ should be analogous).

Below the line:
polyData.SetLines(lines)
add the line:
polyData.SetPolys(lines)

This creates a polygon which becomes the bottom cap and then the extrusion uses it to form the top cap. The results without and with the extra line of code are:

Note that the “tomato” color inside is no longer visible. Also the bottom cap (not shown) is “peacock” due to the color of the added line (lineActor) at the bottom edge.

The top cap can be turned off. Just add:
extrude.SetCapping(False)
before:
extrude.Update()

Note that the bottom “cap” still remains since it was created as a polygon separately whereas the top cap was formed by the extrusion and thus can be turned off using extrude.SetCapping().

If we turn don’t render the blue edge (and polygon) by commenting out:
# ren.AddActor(lineActor)
then extrude.SetCapping() will control both caps:

However when the caps are on, the bottom one will now be “tomato” (not shown).

To make the cylinder uniformly “banana” and to control the caps with extrude.SetCapping() simply comment out the back face color:
# actor.SetBackfaceProperty(back)

Hope that helps since I’ve found a number of inquiries about this, including my own.