You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
379 lines
10 KiB
379 lines
10 KiB
2 years ago
|
/*=========================================================================
|
||
|
|
||
|
Program: Visualization Toolkit
|
||
|
Module: $RCSfile: vtkAssembly.cxx,v $
|
||
|
|
||
|
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
|
||
|
All rights reserved.
|
||
|
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
|
||
|
|
||
|
This software is distributed WITHOUT ANY WARRANTY; without even
|
||
|
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||
|
PURPOSE. See the above copyright notice for more information.
|
||
|
|
||
|
=========================================================================*/
|
||
|
#include "vtkAssembly.h"
|
||
|
#include "vtkActor.h"
|
||
|
#include "vtkAssemblyNode.h"
|
||
|
#include "vtkAssemblyPaths.h"
|
||
|
#include "vtkMath.h"
|
||
|
#include "vtkObjectFactory.h"
|
||
|
#include "vtkProp3DCollection.h"
|
||
|
#include "vtkRenderWindow.h"
|
||
|
#include "vtkVolume.h"
|
||
|
|
||
|
vtkCxxRevisionMacro(vtkAssembly, "$Revision: 1.57 $");
|
||
|
vtkStandardNewMacro(vtkAssembly);
|
||
|
|
||
|
// Construct object with no children.
|
||
|
vtkAssembly::vtkAssembly()
|
||
|
{
|
||
|
this->Parts = vtkProp3DCollection::New();
|
||
|
}
|
||
|
|
||
|
vtkAssembly::~vtkAssembly()
|
||
|
{
|
||
|
this->Parts->Delete();
|
||
|
this->Parts = NULL;
|
||
|
}
|
||
|
|
||
|
// Add a part to the list of Parts.
|
||
|
void vtkAssembly::AddPart(vtkProp3D *prop)
|
||
|
{
|
||
|
if ( ! this->Parts->IsItemPresent(prop) )
|
||
|
{
|
||
|
this->Parts->AddItem(prop);
|
||
|
this->Modified();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Remove a part from the list of parts,
|
||
|
void vtkAssembly::RemovePart(vtkProp3D *prop)
|
||
|
{
|
||
|
if ( this->Parts->IsItemPresent(prop) )
|
||
|
{
|
||
|
this->Parts->RemoveItem(prop);
|
||
|
this->Modified();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Shallow copy another assembly.
|
||
|
void vtkAssembly::ShallowCopy(vtkProp *prop)
|
||
|
{
|
||
|
vtkAssembly *a = vtkAssembly::SafeDownCast(prop);
|
||
|
if ( a != NULL )
|
||
|
{
|
||
|
this->Parts->RemoveAllItems();
|
||
|
vtkCollectionSimpleIterator pit;
|
||
|
a->Parts->InitTraversal(pit);
|
||
|
for (int i=0; i<0; i++)
|
||
|
{
|
||
|
this->Parts->AddItem(a->Parts->GetNextProp3D(pit));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Now do superclass
|
||
|
this->vtkProp3D::ShallowCopy(prop);
|
||
|
}
|
||
|
|
||
|
// Render this assembly and all its Parts. The rendering process is recursive.
|
||
|
// Note that a mapper need not be defined. If not defined, then no geometry
|
||
|
// will be drawn for this assembly. This allows you to create "logical"
|
||
|
// assemblies; that is, assemblies that only serve to group and transform
|
||
|
// its Parts.
|
||
|
int vtkAssembly::RenderTranslucentGeometry(vtkViewport *ren)
|
||
|
{
|
||
|
vtkProp3D *prop3D;
|
||
|
vtkAssemblyPath *path;
|
||
|
double fraction;
|
||
|
int renderedSomething = 0;
|
||
|
|
||
|
this->UpdatePaths();
|
||
|
|
||
|
// for allocating render time between components
|
||
|
// simple equal allocation
|
||
|
fraction = this->AllocatedRenderTime
|
||
|
/ (double)(this->Paths->GetNumberOfItems());
|
||
|
|
||
|
// render the Paths
|
||
|
vtkCollectionSimpleIterator sit;
|
||
|
for ( this->Paths->InitTraversal(sit); (path = this->Paths->GetNextPath(sit)); )
|
||
|
{
|
||
|
prop3D = (vtkProp3D *)path->GetLastNode()->GetViewProp();
|
||
|
if ( prop3D->GetVisibility() )
|
||
|
{
|
||
|
prop3D->SetAllocatedRenderTime(fraction, ren);
|
||
|
prop3D->PokeMatrix(path->GetLastNode()->GetMatrix());
|
||
|
renderedSomething += prop3D->RenderTranslucentGeometry(ren);
|
||
|
prop3D->PokeMatrix(NULL);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
renderedSomething = (renderedSomething > 0)?(1):(0);
|
||
|
|
||
|
return renderedSomething;
|
||
|
}
|
||
|
|
||
|
|
||
|
// Render this assembly and all its Parts. The rendering process is recursive.
|
||
|
// Note that a mapper need not be defined. If not defined, then no geometry
|
||
|
// will be drawn for this assembly. This allows you to create "logical"
|
||
|
// assemblies; that is, assemblies that only serve to group and transform
|
||
|
// its Parts.
|
||
|
int vtkAssembly::RenderOpaqueGeometry(vtkViewport *ren)
|
||
|
{
|
||
|
vtkProp3D *prop3D;
|
||
|
vtkAssemblyPath *path;
|
||
|
double fraction;
|
||
|
int renderedSomething = 0;
|
||
|
|
||
|
this->UpdatePaths();
|
||
|
|
||
|
// for allocating render time between components
|
||
|
// simple equal allocation
|
||
|
fraction = this->AllocatedRenderTime
|
||
|
/ (double)(this->Paths->GetNumberOfItems());
|
||
|
|
||
|
// render the Paths
|
||
|
vtkCollectionSimpleIterator sit;
|
||
|
for ( this->Paths->InitTraversal(sit); (path = this->Paths->GetNextPath(sit)); )
|
||
|
{
|
||
|
prop3D = (vtkProp3D *)path->GetLastNode()->GetViewProp();
|
||
|
if ( prop3D->GetVisibility() )
|
||
|
{
|
||
|
prop3D->PokeMatrix(path->GetLastNode()->GetMatrix());
|
||
|
prop3D->SetAllocatedRenderTime(fraction, ren);
|
||
|
renderedSomething += prop3D->RenderOpaqueGeometry(ren);
|
||
|
prop3D->PokeMatrix(NULL);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
renderedSomething = (renderedSomething > 0)?(1):(0);
|
||
|
|
||
|
return renderedSomething;
|
||
|
}
|
||
|
|
||
|
void vtkAssembly::ReleaseGraphicsResources(vtkWindow *renWin)
|
||
|
{
|
||
|
vtkProp3D *prop3D;
|
||
|
|
||
|
vtkCollectionSimpleIterator pit;
|
||
|
for ( this->Parts->InitTraversal(pit);
|
||
|
(prop3D = this->Parts->GetNextProp3D(pit)); )
|
||
|
{
|
||
|
prop3D->ReleaseGraphicsResources(renWin);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void vtkAssembly::GetActors(vtkPropCollection *ac)
|
||
|
{
|
||
|
vtkProp3D *prop3D;
|
||
|
vtkActor *actor;
|
||
|
vtkAssemblyPath *path;
|
||
|
|
||
|
this->UpdatePaths();
|
||
|
vtkCollectionSimpleIterator sit;
|
||
|
for ( this->Paths->InitTraversal(sit); (path = this->Paths->GetNextPath(sit)); )
|
||
|
{
|
||
|
prop3D = (vtkProp3D *)path->GetLastNode()->GetViewProp();
|
||
|
if ( (actor = vtkActor::SafeDownCast(prop3D)) != NULL )
|
||
|
{
|
||
|
ac->AddItem(actor);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void vtkAssembly::GetVolumes(vtkPropCollection *ac)
|
||
|
{
|
||
|
vtkProp3D *prop3D;
|
||
|
vtkVolume *volume;
|
||
|
vtkAssemblyPath *path;
|
||
|
|
||
|
this->UpdatePaths();
|
||
|
vtkCollectionSimpleIterator sit;
|
||
|
for ( this->Paths->InitTraversal(sit); (path = this->Paths->GetNextPath(sit)); )
|
||
|
{
|
||
|
prop3D = (vtkProp3D *)path->GetLastNode()->GetViewProp();
|
||
|
if ( (volume = vtkVolume::SafeDownCast(prop3D)) != NULL )
|
||
|
{
|
||
|
ac->AddItem(volume);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void vtkAssembly::InitPathTraversal()
|
||
|
{
|
||
|
this->UpdatePaths();
|
||
|
this->Paths->InitTraversal();
|
||
|
}
|
||
|
|
||
|
// Return the next part in the hierarchy of assembly Parts. This method
|
||
|
// returns a properly transformed and updated actor.
|
||
|
vtkAssemblyPath *vtkAssembly::GetNextPath()
|
||
|
{
|
||
|
if ( this->Paths )
|
||
|
{
|
||
|
return this->Paths->GetNextItem();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int vtkAssembly::GetNumberOfPaths()
|
||
|
{
|
||
|
this->UpdatePaths();
|
||
|
return this->Paths->GetNumberOfItems();
|
||
|
}
|
||
|
|
||
|
// Build the assembly paths if necessary. UpdatePaths()
|
||
|
// is only called when the assembly is at the root
|
||
|
// of the hierarchy; otherwise UpdatePaths() is called.
|
||
|
void vtkAssembly::UpdatePaths()
|
||
|
{
|
||
|
if ( this->GetMTime() > this->PathTime ||
|
||
|
(this->Paths != NULL && this->Paths->GetMTime() > this->PathTime) )
|
||
|
{
|
||
|
if ( this->Paths != NULL )
|
||
|
{
|
||
|
this->Paths->Delete();
|
||
|
this->Paths = NULL;
|
||
|
}
|
||
|
|
||
|
// Create the list to hold all the paths
|
||
|
this->Paths = vtkAssemblyPaths::New();
|
||
|
vtkAssemblyPath *path = vtkAssemblyPath::New();
|
||
|
|
||
|
//add ourselves to the path to start things off
|
||
|
path->AddNode(this,this->GetMatrix());
|
||
|
|
||
|
// Add nodes as we proceed down the hierarchy
|
||
|
vtkProp3D *prop3D;
|
||
|
vtkCollectionSimpleIterator pit;
|
||
|
for ( this->Parts->InitTraversal(pit);
|
||
|
(prop3D = this->Parts->GetNextProp3D(pit)); )
|
||
|
{
|
||
|
path->AddNode(prop3D,prop3D->GetMatrix());
|
||
|
|
||
|
// dive into the hierarchy
|
||
|
prop3D->BuildPaths(this->Paths,path);
|
||
|
|
||
|
// when returned, pop the last node off of the
|
||
|
// current path
|
||
|
path->DeleteLastNode();
|
||
|
}
|
||
|
|
||
|
path->Delete();
|
||
|
this->PathTime.Modified();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Build assembly paths from this current assembly. A path consists of
|
||
|
// an ordered sequence of props, with transformations properly concatenated.
|
||
|
void vtkAssembly::BuildPaths(vtkAssemblyPaths *paths, vtkAssemblyPath *path)
|
||
|
{
|
||
|
vtkProp3D *prop3D;
|
||
|
|
||
|
vtkCollectionSimpleIterator pit;
|
||
|
for ( this->Parts->InitTraversal(pit);
|
||
|
(prop3D = this->Parts->GetNextProp3D(pit)); )
|
||
|
{
|
||
|
path->AddNode(prop3D,prop3D->GetMatrix());
|
||
|
|
||
|
// dive into the hierarchy
|
||
|
prop3D->BuildPaths(paths,path);
|
||
|
|
||
|
// when returned, pop the last node off of the
|
||
|
// current path
|
||
|
path->DeleteLastNode();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Get the bounds for the assembly as (Xmin,Xmax,Ymin,Ymax,Zmin,Zmax).
|
||
|
double *vtkAssembly::GetBounds()
|
||
|
{
|
||
|
vtkProp3D *prop3D;
|
||
|
vtkAssemblyPath *path;
|
||
|
int i, n;
|
||
|
double *bounds, bbox[24];
|
||
|
int propVisible=0;
|
||
|
|
||
|
this->UpdatePaths();
|
||
|
|
||
|
// now calculate the new bounds
|
||
|
this->Bounds[0] = this->Bounds[2] = this->Bounds[4] = VTK_DOUBLE_MAX;
|
||
|
this->Bounds[1] = this->Bounds[3] = this->Bounds[5] = -VTK_DOUBLE_MAX;
|
||
|
|
||
|
vtkCollectionSimpleIterator sit;
|
||
|
for ( this->Paths->InitTraversal(sit); (path = this->Paths->GetNextPath(sit)); )
|
||
|
{
|
||
|
prop3D = (vtkProp3D *)path->GetLastNode()->GetViewProp();
|
||
|
if ( prop3D->GetVisibility() )
|
||
|
{
|
||
|
propVisible = 1;
|
||
|
prop3D->PokeMatrix(path->GetLastNode()->GetMatrix());
|
||
|
bounds = prop3D->GetBounds();
|
||
|
prop3D->PokeMatrix(NULL);
|
||
|
|
||
|
// fill out vertices of a bounding box
|
||
|
bbox[ 0] = bounds[1]; bbox[ 1] = bounds[3]; bbox[ 2] = bounds[5];
|
||
|
bbox[ 3] = bounds[1]; bbox[ 4] = bounds[2]; bbox[ 5] = bounds[5];
|
||
|
bbox[ 6] = bounds[0]; bbox[ 7] = bounds[2]; bbox[ 8] = bounds[5];
|
||
|
bbox[ 9] = bounds[0]; bbox[10] = bounds[3]; bbox[11] = bounds[5];
|
||
|
bbox[12] = bounds[1]; bbox[13] = bounds[3]; bbox[14] = bounds[4];
|
||
|
bbox[15] = bounds[1]; bbox[16] = bounds[2]; bbox[17] = bounds[4];
|
||
|
bbox[18] = bounds[0]; bbox[19] = bounds[2]; bbox[20] = bounds[4];
|
||
|
bbox[21] = bounds[0]; bbox[22] = bounds[3]; bbox[23] = bounds[4];
|
||
|
|
||
|
for (i = 0; i < 8; i++)
|
||
|
{
|
||
|
for (n = 0; n < 3; n++)
|
||
|
{
|
||
|
if (bbox[i*3+n] < this->Bounds[n*2])
|
||
|
{
|
||
|
this->Bounds[n*2] = bbox[i*3+n];
|
||
|
}
|
||
|
if (bbox[i*3+n] > this->Bounds[n*2+1])
|
||
|
{
|
||
|
this->Bounds[n*2+1] = bbox[i*3+n];
|
||
|
}
|
||
|
}//for each coordinate axis
|
||
|
}//for each point of box
|
||
|
}//if visible && prop3d
|
||
|
}//for each path
|
||
|
|
||
|
if ( ! propVisible )
|
||
|
{
|
||
|
vtkMath::UninitializeBounds(this->Bounds);
|
||
|
}
|
||
|
|
||
|
return this->Bounds;
|
||
|
}
|
||
|
|
||
|
unsigned long int vtkAssembly::GetMTime()
|
||
|
{
|
||
|
unsigned long mTime=this->vtkProp3D::GetMTime();
|
||
|
unsigned long time;
|
||
|
vtkProp3D *prop;
|
||
|
|
||
|
vtkCollectionSimpleIterator pit;
|
||
|
for (this->Parts->InitTraversal(pit);
|
||
|
(prop = this->Parts->GetNextProp3D(pit)); )
|
||
|
{
|
||
|
time = prop->GetMTime();
|
||
|
mTime = ( time > mTime ? time : mTime );
|
||
|
}
|
||
|
|
||
|
return mTime;
|
||
|
}
|
||
|
|
||
|
void vtkAssembly::PrintSelf(ostream& os, vtkIndent indent)
|
||
|
{
|
||
|
this->Superclass::PrintSelf(os,indent);
|
||
|
|
||
|
os << indent << "There are: " << this->Parts->GetNumberOfItems()
|
||
|
<< " parts in this assembly\n";
|
||
|
}
|
||
|
|