Cloned library of VTK-5.0.0 with extra build files for internal package management.
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.
 
 
 
 
 
 

251 lines
7.3 KiB

/*=========================================================================
Program: Visualization Toolkit
Module: $RCSfile: vtkCellCenterDepthSort.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.
=========================================================================*/
/*
* Copyright 2003 Sandia Corporation.
* Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
* license for use of this work by or on behalf of the
* U.S. Government. Redistribution and use in source and binary forms, with
* or without modification, are permitted provided that this Notice and any
* statement of authorship are reproduced on all copies.
*/
#include "vtkCellCenterDepthSort.h"
#include "vtkObjectFactory.h"
#include "vtkIdTypeArray.h"
#include "vtkDataSet.h"
#include "vtkCamera.h"
#include "vtkMatrix4x4.h"
#include "vtkFloatArray.h"
#include "vtkCell.h"
#include "vtkMath.h"
#include "vtkSortDataArray.h"
#include <vtkstd/stack>
#include <vtkstd/utility>
#include <vtkstd/algorithm>
//-----------------------------------------------------------------------------
typedef vtkstd::pair<vtkIdType, vtkIdType> vtkIdPair;
class vtkCellCenterDepthSortStack
{
public:
vtkstd::stack<vtkIdPair> Stack;
};
//-----------------------------------------------------------------------------
vtkCxxRevisionMacro(vtkCellCenterDepthSort, "$Revision: 1.1 $");
vtkStandardNewMacro(vtkCellCenterDepthSort);
vtkCellCenterDepthSort::vtkCellCenterDepthSort()
{
this->SortedCells = vtkIdTypeArray::New();
this->SortedCells->SetNumberOfComponents(1);
this->SortedCellPartition = vtkIdTypeArray::New();
this->SortedCells->SetNumberOfComponents(1);
this->CellCenters = vtkFloatArray::New();
this->CellCenters->SetNumberOfComponents(3);
this->CellDepths = vtkFloatArray::New();
this->CellDepths->SetNumberOfComponents(1);
this->CellPartitionDepths = vtkFloatArray::New();
this->CellPartitionDepths->SetNumberOfComponents(1);
this->ToSort = new vtkCellCenterDepthSortStack;
}
vtkCellCenterDepthSort::~vtkCellCenterDepthSort()
{
this->SortedCells->Delete();
this->SortedCellPartition->Delete();
this->CellCenters->Delete();
this->CellDepths->Delete();
this->CellPartitionDepths->Delete();
delete this->ToSort;
}
void vtkCellCenterDepthSort::PrintSelf(ostream &os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
}
float *vtkCellCenterDepthSort::ComputeProjectionVector()
{
vtkDebugMacro("ComputeProjectionVector");
if (this->Camera == NULL)
{
vtkErrorMacro("Must set camera before sorting cells.");
static float v[3] = { 0.0, 0.0, 0.0};
return v;
}
double focalPoint[4];
double position[4];
this->Camera->GetFocalPoint(focalPoint); focalPoint[3] = 1.0;
this->Camera->GetPosition(position); position[3] = 1.0;
this->InverseModelTransform->MultiplyPoint(focalPoint, focalPoint);
this->InverseModelTransform->MultiplyPoint(position, position);
static float vector[3];
if (this->Direction == vtkVisibilitySort::BACK_TO_FRONT)
{
// Sort back to front.
vector[0] = position[0] - focalPoint[0];
vector[1] = position[1] - focalPoint[1];
vector[2] = position[2] - focalPoint[2];
}
else
{
// Sort front to back.
vector[0] = focalPoint[0] - position[0];
vector[1] = focalPoint[1] - position[1];
vector[2] = focalPoint[2] - position[2];
}
vtkDebugMacro("Returning: " << vector[0] << ", " << vector[1] << ", "
<< vector[2]);
return vector;
}
void vtkCellCenterDepthSort::ComputeCellCenters()
{
vtkIdType numcells = this->Input->GetNumberOfCells();
this->CellCenters->SetNumberOfTuples(numcells);
float *center = this->CellCenters->GetPointer(0);
double dcenter[3];
double *weights = new double[this->Input->GetMaxCellSize()]; //Dummy array.
for (vtkIdType i = 0; i < numcells; i++)
{
vtkCell *cell = this->Input->GetCell(i);
double pcenter[3];
int subId;
subId = cell->GetParametricCenter(pcenter);
cell->EvaluateLocation(subId, pcenter, dcenter, weights);
center[0] = dcenter[0]; center[1] = dcenter[1]; center[2] = dcenter[2];
center += 3;
}
delete[] weights;
}
void vtkCellCenterDepthSort::ComputeDepths()
{
float *vector = this->ComputeProjectionVector();
vtkIdType numcells = this->Input->GetNumberOfCells();
float *center = this->CellCenters->GetPointer(0);
float *depth = this->CellDepths->GetPointer(0);
for (vtkIdType i = 0; i < numcells; i++)
{
*(depth++) = vtkMath::Dot(center, vector);
center += 3;
}
}
void vtkCellCenterDepthSort::InitTraversal()
{
vtkDebugMacro("InitTraversal");
vtkIdType numcells = this->Input->GetNumberOfCells();
if ( (this->LastSortTime < this->Input->GetMTime())
|| (this->LastSortTime < this->MTime) )
{
vtkDebugMacro("Building cell centers array.");
// Data may have changed. Recompute cell centers.
this->ComputeCellCenters();
this->CellDepths->SetNumberOfTuples(numcells);
this->SortedCells->SetNumberOfTuples(numcells);
}
vtkDebugMacro("Filling SortedCells to initial values.");
vtkIdType *id = this->SortedCells->GetPointer(0);
for (vtkIdType i = 0; i < numcells; i++)
{
*(id++) = i;
}
vtkDebugMacro("Calculating depths.");
this->ComputeDepths();
while (!this->ToSort->Stack.empty()) this->ToSort->Stack.pop();
this->ToSort->Stack.push(vtkIdPair(0, numcells));
this->LastSortTime.Modified();
}
vtkIdTypeArray *vtkCellCenterDepthSort::GetNextCells()
{
if (this->ToSort->Stack.empty())
{
// Already sorted and returned everything.
return NULL;
}
vtkIdType *cellIds = this->SortedCells->GetPointer(0);
float *cellDepths = this->CellDepths->GetPointer(0);
vtkIdPair partition;
partition = this->ToSort->Stack.top(); this->ToSort->Stack.pop();
while (partition.second - partition.first > this->MaxCellsReturned)
{
vtkIdType left = partition.first;
vtkIdType right = partition.second - 1;
float pivot = cellDepths[(vtkIdType)vtkMath::Random(left, right)];
while (left <= right)
{
while ((left <= right) && (cellDepths[left] < pivot)) left++;
while ((left <= right) && (cellDepths[right] > pivot)) right--;
if (left > right) break;
vtkstd::swap(cellIds[left], cellIds[right]);
vtkstd::swap(cellDepths[left], cellDepths[right]);
left++; right--;
}
this->ToSort->Stack.push(vtkIdPair(left, partition.second));
partition.second = left;
}
if (partition.second <= partition.first)
{
// Got a partition of zero size. Just recurse to get the next one.
return this->GetNextCells();
}
vtkIdType firstcell = partition.first;
vtkIdType numcells = partition.second - partition.first;
this->SortedCellPartition->SetArray(cellIds + firstcell, numcells, 1);
this->SortedCellPartition->SetNumberOfTuples(numcells);
this->CellPartitionDepths->SetArray(cellDepths + firstcell, numcells, 1);
this->CellPartitionDepths->SetNumberOfTuples(numcells);
vtkSortDataArray::Sort(this->CellPartitionDepths, this->SortedCellPartition);
return this->SortedCellPartition;
}