Hello,
I’m trying to extract triangles from a PolyData object depending on the direction in which the triangle faces. These PolyData objects are shaped like a slice of pineapple. Round with a hole in the middle and much wider than high. This shape I want to divide into four areas. The top plane, the bottom plane, the inside wall and the outside wall. The triangles from the top and bottom I get through checking if the triangle’s normal vector faces up or downward. The triangles on the side I get through calculating the distance between on of the triangle points and the center of the slice. If this distance is greater than a threshold the triangle is part of the outer wall. If the distance is smaller than the threshold it is part of the inner wall.
When I try to push the resulting triangles back into a polydata structure the resulting meshes don’t look like anything I would expect. It seems as if the triangles just get stacked on one another. Any ideas what I do wrong, or what I can do?
Best regards, Armin
vtkSmartPointer<vtkPolyData> areaDataTop = vtkSmartPointer<vtkPolyData>::New();
vtkSmartPointer<vtkPolyData> areaDataBottom = vtkSmartPointer<vtkPolyData>::New();
vtkSmartPointer<vtkPolyData> areaDataOuter = vtkSmartPointer<vtkPolyData>::New();
vtkSmartPointer<vtkPolyData> areaDataInner = vtkSmartPointer<vtkPolyData>::New();
void divideIntoAreas(vtkSmartPointer<vtkPolyData> slice, double3 sliceMainAxis, double threshold) {	
	vtkSmartPointer<vtkCellArray> trianglesTop = vtkSmartPointer<vtkCellArray>::New();
	vtkSmartPointer<vtkCellArray> trianglesBottom = vtkSmartPointer<vtkCellArray>::New();
	vtkSmartPointer<vtkCellArray> trianglesOuter = vtkSmartPointer<vtkCellArray>::New();
	vtkSmartPointer<vtkCellArray> trianglesInner = vtkSmartPointer<vtkCellArray>::New();
	vtkSmartPointer<vtkPoints> pointsTop = vtkSmartPointer<vtkPoints>::New();
	vtkSmartPointer<vtkPoints> pointsBottom = vtkSmartPointer<vtkPoints>::New();
	vtkSmartPointer<vtkPoints> pointsOuter = vtkSmartPointer<vtkPoints>::New();
	vtkSmartPointer<vtkPoints> pointsInner = vtkSmartPointer<vtkPoints>::New();
	double3 sliceMidPoint;
	double pointFromSlice[3];
	// calculate the middle of the slice
	for (int i = 0; i < slice->GetNumberOfPoints(); i++) {
		slice->GetPoint(i, pointFromSlice);
		sliceMidPoint.x += pointFromSlice[0];
		sliceMidPoint.y += pointFromSlice[1];
		sliceMidPoint.z += pointFromSlice[2];
	}
	sliceMidPoint.x /= slice->GetNumberOfPoints();
	sliceMidPoint.y /= slice->GetNumberOfPoints();
	sliceMidPoint.z /= slice->GetNumberOfPoints();
	// iterate over all cells in the slice
	for (int i = 0; i < slice->GetNumberOfCells(); i++) {
		double normal[3], angle, p0[3], p1[3], p2[3];
		
		// get normal from points of the triangle
		normal = getNormalFromCell(slice->GetCell(i));
		// calculate the angle between the normal of a cell and the heart main axis
		angle = vtkMath::DegreesFromRadians(vtkMath::AngleBetweenVectors(sliceMainAxis, normal));
		// fetch cell and cast it to a triangle
		vtkSmartPointer<vtkCell> cell = slice->GetCell(i);
		vtkSmartPointer<vtkTriangle> triangle = vtkTriangle::SafeDownCast(cell);
		// get the points of the current cell (a triangle)
		triangle->GetPoints()->GetPoint(0, p0);
		triangle->GetPoints()->GetPoint(1, p1);
		triangle->GetPoints()->GetPoint(2, p2);
		// decide to which area the cell belongs
		if ((angle >= -15.0) && (angle <= 15.0)) {
			// point is on the top of the slice
			// insert into a cellArray
			trianglesTop->InsertNextCell(cell);
			// insert points into a points-collection
			pointsTop->InsertNextPoint(p0);
			pointsTop->InsertNextPoint(p1);
			pointsTop->InsertNextPoint(p2);
		} else if ((angle >= 165.0) || (angle <= -165.0)) {
			// point is on the bottom of the slice
			// insert triangle into a cellArray
			trianglesBottom->InsertNextCell(cell);
			// insert points into a points-collection
			pointsBottom->InsertNextPoint(p0);
			pointsBottom->InsertNextPoint(p1);
			pointsBottom->InsertNextPoint(p2);
		} else if (std::isnan(angle)) {
			// angle is "nan"
			throw std::runtime_error("divideIntoAreas(): The angle is NaN.\n");
		} else {
			// point is on the sides
			
			// decide if inner or outer wall based on distance to the sliceMidPoint
			// convert one of the edge-points to double3
			double3 edgePoint;
			edgePoint.x = p0[0];
			edgePoint.y = p0[1];
			edgePoint.z = p0[2];
			if (calcDistance(edgePoint, sliceMidPoint) > treshold) {
				// cell is part of the outer wall
				// insert triangle into a cellArray
				trianglesOuter->InsertNextCell(cell);
				// insert points into a points-collection
				pointsOuter->InsertNextPoint(p0);
				pointsOuter->InsertNextPoint(p1);
				pointsOuter->InsertNextPoint(p2);
			} else {
				// cell is part of the inner wall
				// insert triangle into a cellArray
				trianglesInner->InsertNextCell(cell);
				// insert points into a points-collection
				pointsInner->InsertNextPoint(p0);
				pointsInner->InsertNextPoint(p1);
				pointsInner->InsertNextPoint(p2);
			}
		} //end if
	} //end for
	// add the geometry and topology to the areas
	areaDataTop->SetPoints(pointsTop);
	areaDataTop->SetPolys(trianglesTop);
	areaDataBottom->SetPoints(pointsBottom);
	areaDataBottom->SetPolys(trianglesBottom);
	
	areaDataOuter->SetPoints(pointsOuter);
	areaDataOuter->SetPolys(trianglesOuter);
	
	areaDataInner->SetPoints(pointsInner);
	areaDataInner->SetPolys(trianglesInner);
 }
A input slice file and the resulting areas (written to file with a vtkXMLPolyDataWriter) are found here: https://filebin.net/u4fjq7by5cqeucps