Select only boundary edges of small holes

I’m using vtkFeatureEdges to extract boundary edges, but I would like to know if there is a simple way to extract only the edges where the contour of these edges has a size limit. It looks like feature edges treats every edge independently, but I need to select only the edges from small holes.

For example, in the image below I want to extract only the edges from the small holes (indicated by the yellow arrow), but I dont want the edges from the big hole and the “external” edges.

Well, I had found a solution for this. Probably not the most elegant solution, but solved my problem for now. I basically loop through all the regions and their edges to manually calculate the total length of each region, add the valid regions to a list, and then I loop through the regions again using only the ones from the list.

//extract boundary edges 
vtkFeatureEdges *featureEdges = vtkFeatureEdges::New();
featureEdges->SetInputData(meshPolydata);
featureEdges->BoundaryEdgesOn();
featureEdges->FeatureEdgesOff();
featureEdges->ManifoldEdgesOff();
featureEdges->NonManifoldEdgesOff();
featureEdges->Update();

/*int numberOfLines = featureEdges->GetOutput()->GetNumberOfLines();
std::cout << "Number of lines:" << numberOfLines << std::endl;*/

vtkSmartPointer<vtkPolyDataConnectivityFilter> regions = vtkSmartPointer<vtkPolyDataConnectivityFilter>::New();
regions->SetInputData(featureEdges->GetOutput());
regions->SetExtractionModeToAllRegions();
regions->Update();

int regionCount = regions->GetNumberOfExtractedRegions();

double maximumRegionLength = 1.0;	//set the maximum length of the region
std::vector<int> validRegionsList;	//define a list of valid regions

//loop through all the regions
for (int i = 0; i < regionCount; i++)
{
	//for each specific region...
	regions->SetInputData(featureEdges->GetOutput());
	regions->SetExtractionModeToSpecifiedRegions();
	regions->InitializeSpecifiedRegionList();
	regions->AddSpecifiedRegion(i);
	regions->ScalarConnectivityOff();
	regions->Update();

	//std::cout << "Region " << i << "size: " << regions->GetOutput()->GetNumberOfLines() << std::endl;

	//create a polydata to store the information of the region
	vtkSmartPointer<vtkPolyData> linesPolyData = vtkSmartPointer<vtkPolyData>::New();
	linesPolyData->SetPoints(regions->GetOutput()->GetPoints());
	linesPolyData->SetLines(regions->GetOutput()->GetLines());

	linesPolyData->GetLines()->InitTraversal();
	vtkSmartPointer<vtkIdList> idList = vtkSmartPointer<vtkIdList>::New();
	double regionLength = 0;

	//now loop through the data accumulating the length of each line of the region
	while (linesPolyData->GetLines()->GetNextCell(idList))
	{
		//std::cout << idList->GetNumberOfIds() << " vertices: ";
		std::vector<std::vector<double>> lineVertices; //size always 2

		for (vtkIdType pointId = 0; pointId < idList->GetNumberOfIds(); pointId++)
		{
			double point[3];
			linesPolyData->GetPoint(idList->GetId(pointId), point);
			
			//Show id and coordinates of the vertices for each line
			//std::cout << "[" << idList->GetId(pointId) << "]" << "(" << point[0] << ", "<< point[1] << ", " << point[2] << ") ";

			//add the two points of each line into a vector
			std::vector<double> pointArray;
			pointArray.push_back(point[0]); 
			pointArray.push_back(point[1]);
			pointArray.push_back(point[2]);
			lineVertices.push_back(pointArray);
		}

		//calculate the length of the line and accumulates it in regionLengh
		double lineLength = sqrt(pow(lineVertices[0][0] - lineVertices[1][0], 2) + pow(lineVertices[0][1] - lineVertices[1][1], 2) + pow(lineVertices[0][2] - lineVertices[1][2], 2));
		//std::cout << "- length: " << lineLength;
		regionLength += lineLength;
		//std::cout << std::endl;
	}
	//std::cout << "Total region length: " << regionLength << std::endl;

	//add the region to the list of valid regions if length is appropriated
	if (regionLength <= maximumRegionLength)
		validRegionsList.push_back(i);
}

std::cout << "Valid regions saved!" << std::endl;

//loop through the regions again, now selecting the ones with the required length
for (int i = 0; i < regionCount; i++)
{
	regions->SetInputData(featureEdges->GetOutput());
	regions->SetExtractionModeToSpecifiedRegions();
	regions->InitializeSpecifiedRegionList();
	regions->AddSpecifiedRegion(i);
	regions->ScalarConnectivityOff();
	regions->Update();

	//verify if current region is on the list of valid regions
	if (std::find(validRegionsList.begin(), validRegionsList.end(), i) != validRegionsList.end())
	{
		//use your valid regions with connectivityRegions->GetOutput() here!
	}
	else
		continue;
}
1 Like