[vtkusers] How to turn volume data into triangle data (Not triangle strip)

Jeffrey Meng mengjinjie at gmail.com
Fri Apr 1 15:46:08 EST 2005


Hi Amy, 

Thank you for your reply.

I transfered the data to triangles, and try to iterate through the
celldata, but the cell
data still seems like triangle strips, would you please have a quick
look at my source
listed below?

Thanks a million.

Best,
Jeffrey 

===============================================================
Command line parameter:  VTK_DATA_ROOT/headsq/Quarter

#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkVolume16Reader.h"
#include "vtkPolyDataMapper.h"
#include "vtkActor.h" 
#include "vtkOutlineFilter.h"
#include "vtkCamera.h"
#include "vtkStripper.h"
#include "vtkLookupTable.h"
#include "vtkImageDataGeometryFilter.h"
#include "vtkProperty.h"
#include "vtkPolyDataNormals.h"
#include "vtkContourFilter.h"
#include "vtkImageData.h"
#include "vtkImageMapToColors.h"
#include "vtkImageActor.h"
#include "vtkPolyData.h"
#include "vtkCellData.h"
#include "vtkPointData.h"
#include "vtkPointDataToCellData.h"
#include "vtkCellPicker.h"
#include "vtkCommand.h"
#include "vtkTriangleFilter.h"

class vtkMyCallback : public vtkCommand
{
public:
	static vtkMyCallback* New() 
    { 
		return new vtkMyCallback; 
	}
	
	void SetCellPicker(vtkCellPicker* pPicker)
	{
		_pCellPicker = pPicker;
	}

	virtual void Execute(vtkObject* caller, unsigned long, void*)
    {
		if (NULL == _pCellPicker)
		{
			return;
		}

		vtkRenderer* pRenderer = reinterpret_cast<vtkRenderer*>(caller);
		if (NULL == pRenderer)
		{
			return;
		}

		vtkRenderWindow* pRenderWindow = pRenderer->GetRenderWindow();
		if (NULL == pRenderWindow)
		{
			return;
		}

		if (_pCellPicker->GetCellId() < 0 ) 
		{
			printf("Cell ID = %d\n", _pCellPicker->GetCellId());
		} 
		else 
		{
			float coordinates[3] = {0.0f};
			_pCellPicker->GetSelectionPoint(coordinates);
			float x = coordinates[0];
			float y = coordinates[1];
			
			float* position = _pCellPicker->GetPickPosition();
			float xp = position[0]; 
			float yp = position[1];
			float zp = position[2];
			
            printf("Pick Position = %f\t%f\t%f\n", xp, yp, zp);
		}
		
		//pRenderWindow->Render();		
    }

private:
	vtkCellPicker* _pCellPicker;
};

int main (int argc, char **argv)
{
	if (argc < 2)
    {
		cout << "Usage: " << argv[0] << " DATADIR/headsq/quarter" << endl;
		return 1;
    }
	
    ////////////////////////////////////////////////////////////////////////////
    
	// Now we are creating three orthogonal planes passing through the
	// volume. Each plane uses a different texture map and therefore has
	// diferent coloration.
	
	// Start by creatin a black/white lookup table.
	vtkLookupTable* bwLut = vtkLookupTable::New();
    bwLut->SetTableRange(0, 2000);
    bwLut->SetSaturationRange(0, 0);
    bwLut->SetHueRange(0, 0);
    bwLut->SetValueRange(0, 1);
    bwLut->Build();
	
	// Now create a lookup table that consists of the full hue circle
	// (from HSV).
	vtkLookupTable* hueLut = vtkLookupTable::New();
    hueLut->SetTableRange(0, 2000);
    hueLut->SetHueRange(0, 1);
    hueLut->SetSaturationRange(1, 1);
    hueLut->SetValueRange(1, 1);
    hueLut->Build();
	
	// Finally, create a lookup table with a single hue but having a range
	// in the saturation of the hue.
	vtkLookupTable* satLut = vtkLookupTable::New();
    satLut->SetTableRange(0, 2000);
    satLut->SetHueRange(.6, .6);
    satLut->SetSaturationRange(0, 1);
    satLut->SetValueRange(1, 1);
    satLut->Build();	
	
	////////////////////////////////////////////////////////////////////////////
	
	// Create the renderer, the render window, and the interactor. The
	// renderer draws into the render window, the interactor enables
	// mouse- and keyboard-based interaction with the data within the
	// render window.
	//
	vtkRenderer* aRenderer = vtkRenderer::New();
	vtkRenderWindow* renWin = vtkRenderWindow::New();
    renWin->AddRenderer(aRenderer);
	
	vtkRenderWindowInteractor* iren = vtkRenderWindowInteractor::New();
    iren->SetRenderWindow(renWin);
	
	////////////////////////////////////////////////////////////////////////////
	
	// The following reader is used to read a series of 2D slices (images)
	// that compose the volume. The slice dimensions are set, and the
	// pixel spacing. The data Endianness must also be specified. The
	// reader usese the FilePrefix in combination with the slice number to
	// construct filenames using the format FilePrefix.%d. (In this case
	// the FilePrefix is the root name of the file: quarter.)
	vtkVolume16Reader* v16 = vtkVolume16Reader::New();
    v16->SetDataDimensions(64,64);
    v16->SetDataByteOrderToLittleEndian();
    v16->SetFilePrefix(argv[1]);
    v16->SetImageRange(1, 93);
    v16->SetDataSpacing(3.2, 3.2, 1.5);
	
	////////////////////////////////////////////////////////////////////////////
	
	// An isosurface, or contour value of 500 is known to correspond to
	// the skin of the patient. Once generated, a vtkPolyDataNormals
	// filter is is used to create normals for smooth surface shading
	// during rendering.  The triangle stripper is used to create triangle
	// strips from the isosurface; these render much faster on may
	// systems.
	vtkContourFilter* skinExtractor = vtkContourFilter::New();
    skinExtractor->SetInput(v16->GetOutput());
    skinExtractor->SetValue(0, 500);
	
	vtkPolyDataNormals* skinNormals = vtkPolyDataNormals::New();
    skinNormals->SetInput(skinExtractor->GetOutput());
    skinNormals->SetFeatureAngle(60.0);
	
	vtkStripper* skinStripper = vtkStripper::New();
    skinStripper->SetInput(skinNormals->GetOutput());
	
	vtkTriangleFilter* pTriangles = vtkTriangleFilter::New();
	pTriangles->SetInput(skinStripper->GetOutput());
	pTriangles->PassLinesOn();
	pTriangles->PassVertsOn();

    //*
	vtkPointDataToCellData* pPoint2Cell = vtkPointDataToCellData::New();
	pPoint2Cell->SetInput(pTriangles->GetOutput());
	pPoint2Cell->PassPointDataOn();
	//*/
	
	bool bUsePointData = false;
	
	vtkPolyDataMapper* skinMapper = vtkPolyDataMapper::New();
	if (bUsePointData)
	{
		skinMapper->SetInput(skinStripper->GetOutput());
	}
	else
	{
		skinMapper->SetInput(pPoint2Cell->GetPolyDataOutput());
		//skinMapper->SetInput(pTriangles->GetOutput());
	}
	
    skinMapper->ScalarVisibilityOn();
    skinMapper->SetLookupTable(hueLut);
	if (bUsePointData)
	{
		skinMapper->SetScalarModeToUsePointData();
	}
	else
	{
		skinMapper->SetScalarModeToUseCellData();
	}
    skinMapper->UseLookupTableScalarRangeOn();
    skinMapper->Update();   
	
    try
    {
        vtkPolyData* pPolyData = skinMapper->GetInput();
		printf("vtkPolyData Type = %s\n", skinMapper->GetInput()->GetClassName());
        
        vtkCellData* pCellData = pPolyData->GetCellData();
        vtkDataArray* pCellArray = pCellData->GetScalars(); 
        
        vtkPointData* pPointData = pPolyData->GetPointData();
        vtkDataArray* pPointArray = pPointData->GetScalars();       
		
		double scalar[] = {0.0};
		
        if (bUsePointData)
		{
			//int nComponents = pPointArray->GetNumberOfComponents();
			int nTuples = pPointArray->GetNumberOfTuples();
			
			//for (int i = 0; i < nComponents; ++i)
			{
				for (int j = 0; j < nTuples / 2; ++j)
				{
					//pPointArray->SetComponent(0, j, 0.0);
					pPointArray->SetTuple(j, scalar);
				}            
			}
			
			pPointArray->Modified();
		}
		else
		{
			int nTuples = pCellArray->GetNumberOfTuples();
			for (int i = 0; i < nTuples / 2; ++i)
			{
				pCellArray->SetTuple(i, scalar);
			}
			
			pCellArray->Modified();
		}

        pPolyData->Modified();
        skinMapper->Update();
    }
    catch (...)
    {
        printf("Exception thrown\n");
    }
	
	//------------------------------------------------------------------------\\
	// Create a cell picker
	//
	vtkCellPicker* pPicker = vtkCellPicker::New();
	vtkMyCallback* pPickCallback = vtkMyCallback::New();
	pPickCallback->SetCellPicker(pPicker);
	pPicker->AddObserver(vtkCommand::EndPickEvent, pPickCallback);


	vtkActor* skin = vtkActor::New();
    skin->SetMapper(skinMapper);
    skin->GetProperty()->SetDiffuseColor(1, .49, .25);
    skin->GetProperty()->SetSpecular(.3);
    skin->GetProperty()->SetSpecularPower(20);
	
	////////////////////////////////////////////////////////////////////////////
	
	// Create the first of the three planes. The filter vtkImageMapToColors
	// maps the data through the corresponding lookup table created above.  The
	// vtkImageActor is a type of vtkProp and conveniently displays an image on
	// a single quadrilateral plane. It does this using texture mapping and as
	// a result is quite fast. (Note: the input image has to be unsigned char
	// values, which the vtkImageMapToColors produces.) Note also that by
	// specifying the DisplayExtent, the pipeline requests data of this extent
	// and the vtkImageMapToColors only processes a slice of data.
	vtkImageMapToColors* saggitalColors = vtkImageMapToColors::New();
    saggitalColors->SetInput(v16->GetOutput());
    saggitalColors->SetLookupTable(bwLut);
	vtkImageActor* saggital = vtkImageActor::New();
    saggital->SetInput(saggitalColors->GetOutput());
    saggital->SetDisplayExtent(16, 16, 0, 63, 0, 92);
	
	// Create the second (axial) plane of the three planes. We use the
	// same approach as before except that the extent differs.
	vtkImageMapToColors *axialColors = vtkImageMapToColors::New();
    axialColors->SetInput(v16->GetOutput());
    axialColors->SetLookupTable(hueLut);
	vtkImageActor *axial = vtkImageActor::New();
    axial->SetInput(axialColors->GetOutput());
    axial->SetDisplayExtent(0,63, 0,63, 46,46);
	
	// Create the third (coronal) plane of the three planes. We use 
	// the same approach as before except that the extent differs.
	vtkImageMapToColors *coronalColors = vtkImageMapToColors::New();
    coronalColors->SetInput(v16->GetOutput());
    coronalColors->SetLookupTable(satLut);
	vtkImageActor *coronal = vtkImageActor::New();
    coronal->SetInput(coronalColors->GetOutput());
    coronal->SetDisplayExtent(0,63, 32,32, 0,92);
	
	// It is convenient to create an initial view of the data. The
	// FocalPoint and Position form a vector direction. Later on
	// (ResetCamera() method) this vector is used to position the camera
	// to look at the data in this direction.
	vtkCamera* aCamera = vtkCamera::New();
    aCamera->SetViewUp (0, 0, -1);
    aCamera->SetPosition (0, 1, 0);
    aCamera->SetFocalPoint (0, 0, 0);
    aCamera->ComputeViewPlaneNormal();
	
	// Actors are added to the renderer. 
	aRenderer->AddActor(saggital);
	aRenderer->AddActor(axial);
	aRenderer->AddActor(coronal);	
	aRenderer->AddActor(skin);
	
	// Set skin to semi-transparent.
	skin->GetProperty()->SetOpacity(0.5);
	
	// An initial camera view is created.  The Dolly() method moves 
	// the camera towards the FocalPoint, thereby enlarging the image.
	aRenderer->SetActiveCamera(aCamera);
	aRenderer->ResetCamera();
	aCamera->Dolly(1.5);
	
	// Set a background color for the renderer and set the size of the
	// render window (expressed in pixels).
	aRenderer->SetBackground(1,1,1);
	renWin->SetSize(300, 300);
	
	// Note that when camera movement occurs (as it does in the Dolly()
	// method), the clipping planes often need adjusting. Clipping planes
	// consist of two planes: near and far along the view direction. The 
	// near plane clips out objects in front of the plane; the far plane
	// clips out objects behind the plane. This way only what is drawn
	// between the planes is actually rendered.
	aRenderer->ResetCameraClippingRange();
	
	pPicker->Pick(85, 126, 0, aRenderer);

	// Interact with data
	iren->Initialize();
	iren->SetPicker(pPicker);
	iren->Start(); 
	
	// Cleanup
	v16->Delete();
	skinExtractor->Delete();
	skinNormals->Delete();
	skinStripper->Delete();
	skinMapper->Delete();
	skin->Delete();
	bwLut->Delete();
	hueLut->Delete();
	satLut->Delete();
	saggitalColors->Delete();
	saggital->Delete();
	axialColors->Delete();
	axial->Delete();
	coronalColors->Delete();
	coronal->Delete();
	aCamera->Delete();
	aRenderer->Delete();
	renWin->Delete();
	iren->Delete();
	
	return 0;
}


>Hi Jeffrey,
>
>vtkTriangleFilter is supposed to output triangles, not triangle strips.  If 
>this is not the behavior you are seeing, something is wrong.
>
>- Amy



More information about the vtkusers mailing list