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.
		
		
		
		
		
			
		
			
				
					
					
						
							1433 lines
						
					
					
						
							42 KiB
						
					
					
				
			
		
		
	
	
							1433 lines
						
					
					
						
							42 KiB
						
					
					
				/*=========================================================================
 | 
						|
 | 
						|
  Program:   Visualization Toolkits
 | 
						|
  Module:    $RCSfile: vtkGenericStreamTracer.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 "vtkGenericStreamTracer.h"
 | 
						|
 | 
						|
#include "vtkCellArray.h"
 | 
						|
#include "vtkCellData.h"
 | 
						|
#include "vtkDoubleArray.h"
 | 
						|
#include "vtkGenericInterpolatedVelocityField.h"
 | 
						|
#include "vtkMath.h"
 | 
						|
#include "vtkObjectFactory.h"
 | 
						|
#include "vtkPointData.h"
 | 
						|
#include "vtkPolyData.h"
 | 
						|
#include "vtkPolyLine.h"
 | 
						|
#include "vtkRungeKutta2.h"
 | 
						|
#include "vtkRungeKutta4.h"
 | 
						|
#include "vtkRungeKutta45.h"
 | 
						|
#include "vtkGenericDataSet.h"
 | 
						|
#include "vtkGenericAttributeCollection.h"
 | 
						|
#include "vtkGenericAttribute.h"
 | 
						|
#include "vtkGenericAdaptorCell.h"
 | 
						|
#include <assert.h>
 | 
						|
 | 
						|
#include "vtkInformation.h"
 | 
						|
#include "vtkExecutive.h" // for GetExecutive()
 | 
						|
#include "vtkInformationVector.h"
 | 
						|
 | 
						|
vtkCxxRevisionMacro(vtkGenericStreamTracer, "$Revision: 1.3 $");
 | 
						|
vtkStandardNewMacro(vtkGenericStreamTracer);
 | 
						|
vtkCxxSetObjectMacro(vtkGenericStreamTracer,Integrator,vtkInitialValueProblemSolver);
 | 
						|
vtkCxxSetObjectMacro(vtkGenericStreamTracer,InterpolatorPrototype,vtkGenericInterpolatedVelocityField);
 | 
						|
 | 
						|
const double vtkGenericStreamTracer::EPSILON = 1.0E-12;
 | 
						|
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
vtkGenericStreamTracer::vtkGenericStreamTracer()
 | 
						|
{
 | 
						|
  this->SetNumberOfInputPorts(2);
 | 
						|
  
 | 
						|
  this->Integrator = vtkRungeKutta2::New();
 | 
						|
  this->IntegrationDirection = FORWARD;
 | 
						|
  for(int i=0; i<3; i++)
 | 
						|
    {
 | 
						|
    this->StartPosition[i] = 0.0;
 | 
						|
    }
 | 
						|
  this->MaximumPropagation.Unit = LENGTH_UNIT;
 | 
						|
  this->MaximumPropagation.Interval = 1.0;
 | 
						|
 | 
						|
  this->MinimumIntegrationStep.Unit = CELL_LENGTH_UNIT;
 | 
						|
  this->MinimumIntegrationStep.Interval = 1.0E-2;
 | 
						|
 | 
						|
  this->MaximumIntegrationStep.Unit = CELL_LENGTH_UNIT;
 | 
						|
  this->MaximumIntegrationStep.Interval = 1.0;
 | 
						|
 | 
						|
  this->InitialIntegrationStep.Unit = CELL_LENGTH_UNIT;
 | 
						|
  this->InitialIntegrationStep.Interval = 0.5;
 | 
						|
 | 
						|
  this->MaximumError = 1.0e-6;
 | 
						|
 | 
						|
  this->MaximumNumberOfSteps = 2000;
 | 
						|
 | 
						|
  this->TerminalSpeed = EPSILON;
 | 
						|
 | 
						|
  this->ComputeVorticity = 1;
 | 
						|
  this->RotationScale = 1.0;
 | 
						|
 | 
						|
  this->InputVectorsSelection = 0;
 | 
						|
 | 
						|
  this->LastUsedTimeStep = 0.0;
 | 
						|
 | 
						|
  this->GenerateNormalsInIntegrate = 1;
 | 
						|
 | 
						|
  this->InterpolatorPrototype = 0;
 | 
						|
}
 | 
						|
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
vtkGenericStreamTracer::~vtkGenericStreamTracer()
 | 
						|
{
 | 
						|
  this->SetIntegrator(0);
 | 
						|
  this->SetInputVectorsSelection(0);
 | 
						|
  this->SetInterpolatorPrototype(0);
 | 
						|
}
 | 
						|
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
void vtkGenericStreamTracer::SetSource(vtkDataSet *source)
 | 
						|
{
 | 
						|
  this->SetInputConnection(1, source->GetProducerPort());
 | 
						|
}
 | 
						|
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
vtkDataSet *vtkGenericStreamTracer::GetSource()
 | 
						|
{
 | 
						|
  if (this->GetNumberOfInputConnections(1) < 1) // because the port is optional
 | 
						|
    {
 | 
						|
    return 0;
 | 
						|
    }
 | 
						|
  return static_cast<vtkDataSet *>(this->GetExecutive()->GetInputData(1, 0));
 | 
						|
}
 | 
						|
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
void vtkGenericStreamTracer::AddInput(vtkGenericDataSet* input)
 | 
						|
{  
 | 
						|
  this->Superclass::AddInput(input);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
//----------------------------------------------------------------------------
 | 
						|
int vtkGenericStreamTracer
 | 
						|
::FillInputPortInformation(int port, vtkInformation* info)
 | 
						|
{ 
 | 
						|
  if(!this->Superclass::FillInputPortInformation(port, info))
 | 
						|
    {
 | 
						|
    return 0;
 | 
						|
    }
 | 
						|
  if(port==1)
 | 
						|
    {
 | 
						|
    info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet");
 | 
						|
    info->Set(vtkAlgorithm::INPUT_IS_OPTIONAL(),1);
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
    info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkGenericDataSet");
 | 
						|
    }
 | 
						|
  return 1;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
int vtkGenericStreamTracer::GetIntegratorType()
 | 
						|
{
 | 
						|
  if (!this->Integrator)
 | 
						|
    {
 | 
						|
    return NONE;
 | 
						|
    }
 | 
						|
  if (!strcmp(this->Integrator->GetClassName(), "vtkRungeKutta2"))
 | 
						|
    {
 | 
						|
    return RUNGE_KUTTA2;
 | 
						|
    }
 | 
						|
  if (!strcmp(this->Integrator->GetClassName(), "vtkRungeKutta4"))
 | 
						|
    {
 | 
						|
    return RUNGE_KUTTA4;
 | 
						|
    }
 | 
						|
  if (!strcmp(this->Integrator->GetClassName(), "vtkRungeKutta45"))
 | 
						|
    {
 | 
						|
    return RUNGE_KUTTA45;
 | 
						|
    }
 | 
						|
  return UNKNOWN;
 | 
						|
}
 | 
						|
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
void vtkGenericStreamTracer::SetIntegratorType(int type)
 | 
						|
{
 | 
						|
  vtkInitialValueProblemSolver* ivp=0;
 | 
						|
  switch (type)
 | 
						|
    {
 | 
						|
    case RUNGE_KUTTA2:
 | 
						|
      ivp = vtkRungeKutta2::New();
 | 
						|
      break;
 | 
						|
    case RUNGE_KUTTA4:
 | 
						|
      ivp = vtkRungeKutta4::New();
 | 
						|
      break;
 | 
						|
    case RUNGE_KUTTA45:
 | 
						|
      ivp = vtkRungeKutta45::New();
 | 
						|
      break;
 | 
						|
    default:
 | 
						|
      vtkWarningMacro("Unrecognized integrator type. Keeping old one.");
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  if (ivp)
 | 
						|
    {
 | 
						|
    this->SetIntegrator(ivp);
 | 
						|
    ivp->Delete();
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
void vtkGenericStreamTracer::SetIntervalInformation(
 | 
						|
  int unit,
 | 
						|
  vtkGenericStreamTracer::IntervalInformation& currentValues)
 | 
						|
{
 | 
						|
  if ( unit == currentValues.Unit )
 | 
						|
    {
 | 
						|
    return;
 | 
						|
    }
 | 
						|
 | 
						|
  if ( (unit < TIME_UNIT) || (unit > CELL_LENGTH_UNIT) )
 | 
						|
    {
 | 
						|
    vtkWarningMacro("Unrecognized unit. Using TIME_UNIT instead.");
 | 
						|
    currentValues.Unit = TIME_UNIT;
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
    currentValues.Unit = unit;
 | 
						|
    }
 | 
						|
 | 
						|
  this->Modified();
 | 
						|
}
 | 
						|
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
void vtkGenericStreamTracer::SetIntervalInformation(
 | 
						|
  int unit,
 | 
						|
  double interval, vtkGenericStreamTracer::IntervalInformation& currentValues)
 | 
						|
{
 | 
						|
  if ( (unit == currentValues.Unit) && (interval == currentValues.Interval) )
 | 
						|
    {
 | 
						|
    return;
 | 
						|
    }
 | 
						|
 | 
						|
  this->SetIntervalInformation(unit, currentValues);
 | 
						|
 | 
						|
  currentValues.Interval = interval;
 | 
						|
  this->Modified();
 | 
						|
}
 | 
						|
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
void vtkGenericStreamTracer::SetMaximumPropagation(int unit, double max)
 | 
						|
{
 | 
						|
  this->SetIntervalInformation(unit, max, this->MaximumPropagation);
 | 
						|
}
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
void vtkGenericStreamTracer::SetMaximumPropagation( double max)
 | 
						|
{
 | 
						|
  if ( max == this->MaximumPropagation.Interval )
 | 
						|
    {
 | 
						|
    return;
 | 
						|
    }
 | 
						|
  this->MaximumPropagation.Interval = max;
 | 
						|
  this->Modified();
 | 
						|
}
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
void vtkGenericStreamTracer::SetMaximumPropagationUnit(int unit)
 | 
						|
{
 | 
						|
  this->SetIntervalInformation(unit, this->MaximumPropagation);
 | 
						|
}
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
int vtkGenericStreamTracer::GetMaximumPropagationUnit()
 | 
						|
{
 | 
						|
  return this->MaximumPropagation.Unit;
 | 
						|
}
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
double vtkGenericStreamTracer::GetMaximumPropagation()
 | 
						|
{
 | 
						|
  return this->MaximumPropagation.Interval;
 | 
						|
}
 | 
						|
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
void vtkGenericStreamTracer::SetMinimumIntegrationStep(int unit, double step)
 | 
						|
{
 | 
						|
  this->SetIntervalInformation(unit, step, this->MinimumIntegrationStep);
 | 
						|
}
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
void vtkGenericStreamTracer::SetMinimumIntegrationStepUnit(int unit)
 | 
						|
{
 | 
						|
  this->SetIntervalInformation(unit, this->MinimumIntegrationStep);
 | 
						|
}
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
void vtkGenericStreamTracer::SetMinimumIntegrationStep(double step)
 | 
						|
{
 | 
						|
  if ( step == this->MinimumIntegrationStep.Interval )
 | 
						|
    {
 | 
						|
    return;
 | 
						|
    }
 | 
						|
  this->MinimumIntegrationStep.Interval = step;
 | 
						|
  this->Modified();
 | 
						|
}
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
int vtkGenericStreamTracer::GetMinimumIntegrationStepUnit()
 | 
						|
{
 | 
						|
  return this->MinimumIntegrationStep.Unit;
 | 
						|
}
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
double vtkGenericStreamTracer::GetMinimumIntegrationStep()
 | 
						|
{
 | 
						|
  return this->MinimumIntegrationStep.Interval;
 | 
						|
}
 | 
						|
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
void vtkGenericStreamTracer::SetMaximumIntegrationStep(int unit, double step)
 | 
						|
{
 | 
						|
  this->SetIntervalInformation(unit, step, this->MaximumIntegrationStep);
 | 
						|
}
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
void vtkGenericStreamTracer::SetMaximumIntegrationStepUnit(int unit)
 | 
						|
{
 | 
						|
  this->SetIntervalInformation(unit, this->MaximumIntegrationStep);
 | 
						|
}
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
void vtkGenericStreamTracer::SetMaximumIntegrationStep(double step)
 | 
						|
{
 | 
						|
  if ( step == this->MaximumIntegrationStep.Interval )
 | 
						|
    {
 | 
						|
    return;
 | 
						|
    }
 | 
						|
  this->MaximumIntegrationStep.Interval = step;
 | 
						|
  this->Modified();
 | 
						|
}
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
int vtkGenericStreamTracer::GetMaximumIntegrationStepUnit()
 | 
						|
{
 | 
						|
  return this->MaximumIntegrationStep.Unit;
 | 
						|
}
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
double vtkGenericStreamTracer::GetMaximumIntegrationStep()
 | 
						|
{
 | 
						|
  return this->MaximumIntegrationStep.Interval;
 | 
						|
}
 | 
						|
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
void vtkGenericStreamTracer::SetInitialIntegrationStep(int unit, double step)
 | 
						|
{
 | 
						|
  this->SetIntervalInformation(unit, step, this->InitialIntegrationStep);
 | 
						|
}
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
void vtkGenericStreamTracer::SetInitialIntegrationStepUnit(int unit)
 | 
						|
{
 | 
						|
  this->SetIntervalInformation(unit, this->InitialIntegrationStep);
 | 
						|
}
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
void vtkGenericStreamTracer::SetInitialIntegrationStep(double step)
 | 
						|
{
 | 
						|
  if ( step == this->InitialIntegrationStep.Interval )
 | 
						|
    {
 | 
						|
    return;
 | 
						|
    }
 | 
						|
  this->InitialIntegrationStep.Interval = step;
 | 
						|
  this->Modified();
 | 
						|
}
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
int vtkGenericStreamTracer::GetInitialIntegrationStepUnit()
 | 
						|
{
 | 
						|
  return this->InitialIntegrationStep.Unit;
 | 
						|
}
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
double vtkGenericStreamTracer::GetInitialIntegrationStep()
 | 
						|
{
 | 
						|
  return this->InitialIntegrationStep.Interval;
 | 
						|
}
 | 
						|
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
double vtkGenericStreamTracer::ConvertToTime(
 | 
						|
  vtkGenericStreamTracer::IntervalInformation& interval,
 | 
						|
  double cellLength,
 | 
						|
  double speed)
 | 
						|
{
 | 
						|
  double retVal = 0.0;
 | 
						|
  switch (interval.Unit)
 | 
						|
    {
 | 
						|
    case TIME_UNIT:
 | 
						|
      retVal = interval.Interval;
 | 
						|
      break;
 | 
						|
    case LENGTH_UNIT:
 | 
						|
      retVal = interval.Interval/speed; 
 | 
						|
      break;
 | 
						|
    case CELL_LENGTH_UNIT:
 | 
						|
      retVal = interval.Interval*cellLength/speed; 
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  return retVal;
 | 
						|
}
 | 
						|
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
double vtkGenericStreamTracer::ConvertToLength(
 | 
						|
  vtkGenericStreamTracer::IntervalInformation& interval,
 | 
						|
  double cellLength,
 | 
						|
  double speed)
 | 
						|
{
 | 
						|
  double retVal = 0.0;
 | 
						|
  switch (interval.Unit)
 | 
						|
    {
 | 
						|
    case TIME_UNIT:
 | 
						|
      retVal = interval.Interval * speed;
 | 
						|
      break;
 | 
						|
    case LENGTH_UNIT:
 | 
						|
      retVal = interval.Interval; 
 | 
						|
      break;
 | 
						|
    case CELL_LENGTH_UNIT:
 | 
						|
      retVal = interval.Interval*cellLength; 
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  return retVal;
 | 
						|
}
 | 
						|
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
double vtkGenericStreamTracer::ConvertToCellLength(
 | 
						|
  vtkGenericStreamTracer::IntervalInformation& interval,
 | 
						|
  double cellLength,
 | 
						|
  double speed)
 | 
						|
{
 | 
						|
  double retVal = 0.0;
 | 
						|
  switch (interval.Unit)
 | 
						|
    {
 | 
						|
    case TIME_UNIT:
 | 
						|
      retVal = (interval.Interval * speed)/cellLength;
 | 
						|
      break;
 | 
						|
    case LENGTH_UNIT:
 | 
						|
      retVal = interval.Interval/cellLength; 
 | 
						|
      break;
 | 
						|
    case CELL_LENGTH_UNIT:
 | 
						|
      retVal = interval.Interval; 
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  return retVal;
 | 
						|
}
 | 
						|
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
double vtkGenericStreamTracer::ConvertToUnit(
 | 
						|
  vtkGenericStreamTracer::IntervalInformation& interval, 
 | 
						|
  int unit, 
 | 
						|
  double cellLength, 
 | 
						|
  double speed)
 | 
						|
{
 | 
						|
  double retVal = 0.0;
 | 
						|
  switch (unit)
 | 
						|
    {
 | 
						|
    case TIME_UNIT:
 | 
						|
      retVal = ConvertToTime(interval, cellLength, speed);
 | 
						|
      break;
 | 
						|
    case LENGTH_UNIT:
 | 
						|
      retVal = ConvertToLength(interval, cellLength, speed);
 | 
						|
      break;
 | 
						|
    case CELL_LENGTH_UNIT:
 | 
						|
      retVal = ConvertToCellLength(interval, cellLength, speed);
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  return retVal;
 | 
						|
}
 | 
						|
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
void vtkGenericStreamTracer::ConvertIntervals(double& step,
 | 
						|
                                              double& minStep,
 | 
						|
                                              double& maxStep,
 | 
						|
                                              int direction,
 | 
						|
                                              double cellLength,
 | 
						|
                                              double speed)
 | 
						|
{
 | 
						|
  step = direction * this->ConvertToTime(
 | 
						|
    this->InitialIntegrationStep, cellLength, speed);
 | 
						|
  if ( this->MinimumIntegrationStep.Interval <= 0.0 )
 | 
						|
    {
 | 
						|
    minStep = step;
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
    minStep = this->ConvertToTime(this->MinimumIntegrationStep, cellLength,  
 | 
						|
                                  speed);
 | 
						|
    }
 | 
						|
  if ( this->MaximumIntegrationStep.Interval <= 0.0 )
 | 
						|
    {
 | 
						|
    maxStep = step;
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
    maxStep = this->ConvertToTime(this->MaximumIntegrationStep,cellLength, 
 | 
						|
                                  speed);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
void vtkGenericStreamTracer::CalculateVorticity(vtkGenericAdaptorCell* cell, 
 | 
						|
                                                double pcoords[3],
 | 
						|
                                                vtkGenericAttribute *attribute,
 | 
						|
                                                double vorticity[3])
 | 
						|
{
 | 
						|
  assert("pre: attribute_exists" && attribute!=0);
 | 
						|
  assert("pre: point_centered_attribute" && attribute->GetCentering()==vtkPointCentered);
 | 
						|
  assert("pre: vector_attribute" && attribute->GetType()==vtkDataSetAttributes::VECTORS);
 | 
						|
  
 | 
						|
  double derivs[9];
 | 
						|
  cell->Derivatives(0,pcoords,attribute,derivs);
 | 
						|
  
 | 
						|
  vorticity[0] = derivs[7] - derivs[5];
 | 
						|
  vorticity[1] = derivs[2] - derivs[6];
 | 
						|
  vorticity[2] = derivs[3] - derivs[1];
 | 
						|
}
 | 
						|
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
void vtkGenericStreamTracer::InitializeSeeds(
 | 
						|
  vtkDataArray*& seeds,
 | 
						|
  vtkIdList*& seedIds,
 | 
						|
  vtkIntArray*& integrationDirections)
 | 
						|
{
 | 
						|
  vtkDataSet* source = this->GetSource();
 | 
						|
  seedIds = vtkIdList::New();
 | 
						|
  integrationDirections = vtkIntArray::New();
 | 
						|
  seeds=0;
 | 
						|
 | 
						|
  if (source)
 | 
						|
    {
 | 
						|
    int i;
 | 
						|
    vtkIdType numSeeds = source->GetNumberOfPoints();
 | 
						|
    if (numSeeds > 0)
 | 
						|
      {
 | 
						|
      // For now, one thread will do all
 | 
						|
 | 
						|
      if (this->IntegrationDirection == BOTH)
 | 
						|
        {
 | 
						|
        seedIds->SetNumberOfIds(2*numSeeds);
 | 
						|
        for (i=0; i<numSeeds; i++)
 | 
						|
          {
 | 
						|
          seedIds->SetId(i, i);
 | 
						|
          seedIds->SetId(numSeeds + i, i);
 | 
						|
          }
 | 
						|
        }
 | 
						|
      else
 | 
						|
        {
 | 
						|
        seedIds->SetNumberOfIds(numSeeds);
 | 
						|
        for (i=0; i<numSeeds; i++)
 | 
						|
          {
 | 
						|
          seedIds->SetId(i, i);
 | 
						|
          }
 | 
						|
        }
 | 
						|
      // Check if the source is a PointSet
 | 
						|
      vtkPointSet* seedPts = vtkPointSet::SafeDownCast(source);
 | 
						|
      if (seedPts)
 | 
						|
        {
 | 
						|
        // If it is, use it's points as source
 | 
						|
        vtkDataArray* orgSeeds = seedPts->GetPoints()->GetData();
 | 
						|
        seeds = orgSeeds->NewInstance();
 | 
						|
        seeds->DeepCopy(orgSeeds);
 | 
						|
        }
 | 
						|
      else
 | 
						|
        {
 | 
						|
        // Else, create a seed source
 | 
						|
        seeds = vtkDoubleArray::New();
 | 
						|
        seeds->SetNumberOfComponents(3);
 | 
						|
        seeds->SetNumberOfTuples(numSeeds);
 | 
						|
        for (i=0; i<numSeeds; i++)
 | 
						|
          {
 | 
						|
          seeds->SetTuple(i, source->GetPoint(i));
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
    seeds = vtkDoubleArray::New();
 | 
						|
    seeds->SetNumberOfComponents(3);
 | 
						|
    seeds->InsertNextTuple(this->StartPosition);
 | 
						|
    seedIds->InsertNextId(0);
 | 
						|
    if (this->IntegrationDirection == BOTH)
 | 
						|
      {
 | 
						|
      seedIds->InsertNextId(0);
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
  if (seeds)
 | 
						|
    {
 | 
						|
    vtkIdType i;
 | 
						|
    vtkIdType numSeeds = seeds->GetNumberOfTuples();
 | 
						|
    if (this->IntegrationDirection == BOTH)
 | 
						|
      {
 | 
						|
      for(i=0; i<numSeeds; i++)
 | 
						|
        {
 | 
						|
        integrationDirections->InsertNextValue(FORWARD);
 | 
						|
        }
 | 
						|
      for(i=0; i<numSeeds; i++)
 | 
						|
        {
 | 
						|
        integrationDirections->InsertNextValue(BACKWARD);
 | 
						|
        }
 | 
						|
      }
 | 
						|
    else
 | 
						|
      {
 | 
						|
      for(i=0; i<numSeeds; i++)
 | 
						|
        {
 | 
						|
        integrationDirections->InsertNextValue(this->IntegrationDirection);
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
int vtkGenericStreamTracer::RequestData(
 | 
						|
  vtkInformation *vtkNotUsed(request),
 | 
						|
  vtkInformationVector **inputVector,
 | 
						|
  vtkInformationVector *outputVector)
 | 
						|
{
 | 
						|
  // get the info objects
 | 
						|
  vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
 | 
						|
  vtkInformation *outInfo = outputVector->GetInformationObject(0);
 | 
						|
 | 
						|
  // get the input and output
 | 
						|
  vtkGenericDataSet *input = vtkGenericDataSet::SafeDownCast(
 | 
						|
    inInfo->Get(vtkDataObject::DATA_OBJECT()));
 | 
						|
  vtkPolyData *output = vtkPolyData::SafeDownCast(
 | 
						|
    outInfo->Get(vtkDataObject::DATA_OBJECT()));
 | 
						|
 | 
						|
  vtkDataArray* seeds = 0;
 | 
						|
  vtkIdList* seedIds = 0;
 | 
						|
  vtkIntArray* integrationDirections = 0;
 | 
						|
  this->InitializeSeeds(seeds, seedIds, integrationDirections);
 | 
						|
  
 | 
						|
  if (seeds)
 | 
						|
    {
 | 
						|
    double lastPoint[3];
 | 
						|
    vtkGenericInterpolatedVelocityField* func;
 | 
						|
    if (this->CheckInputs(func, inputVector) != VTK_OK)
 | 
						|
      {
 | 
						|
      vtkDebugMacro("No appropriate inputs have been found. Can not execute.");
 | 
						|
      func->Delete();
 | 
						|
      seeds->Delete();
 | 
						|
      integrationDirections->Delete();
 | 
						|
      seedIds->Delete();
 | 
						|
      return 1;
 | 
						|
      }
 | 
						|
    this->Integrate(input,
 | 
						|
                    output,
 | 
						|
                    seeds, 
 | 
						|
                    seedIds, 
 | 
						|
                    integrationDirections, 
 | 
						|
                    lastPoint,
 | 
						|
                    func);
 | 
						|
    func->Delete();
 | 
						|
    seeds->Delete();
 | 
						|
    }
 | 
						|
 | 
						|
  integrationDirections->Delete();
 | 
						|
  seedIds->Delete();
 | 
						|
  return 1;
 | 
						|
}
 | 
						|
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
int vtkGenericStreamTracer::CheckInputs(
 | 
						|
  vtkGenericInterpolatedVelocityField*& func,
 | 
						|
  vtkInformationVector **inputVector
 | 
						|
  )
 | 
						|
{
 | 
						|
  // Set the function set to be integrated
 | 
						|
  if (!this->InterpolatorPrototype)
 | 
						|
    {
 | 
						|
    func = vtkGenericInterpolatedVelocityField::New();
 | 
						|
    }
 | 
						|
  else
 | 
						|
    {
 | 
						|
    func = this->InterpolatorPrototype->NewInstance();
 | 
						|
    func->CopyParameters(this->InterpolatorPrototype);
 | 
						|
    }
 | 
						|
  func->SelectVectors(this->InputVectorsSelection);
 | 
						|
 
 | 
						|
  // Add all the inputs ( except source, of course ) which
 | 
						|
  // have the appropriate vectors and compute the maximum
 | 
						|
  // cell size.
 | 
						|
  int numInputs = 0;
 | 
						|
  int numInputConnections = this->GetNumberOfInputConnections(0);
 | 
						|
  for (int i = 0; i < numInputConnections; i++)
 | 
						|
    {
 | 
						|
    vtkInformation *info = inputVector[0]->GetInformationObject(i);
 | 
						|
    vtkGenericDataSet* inp=0;
 | 
						|
  
 | 
						|
    if(info!=0)
 | 
						|
      {
 | 
						|
      inp = vtkGenericDataSet::SafeDownCast(
 | 
						|
        info->Get(vtkDataObject::DATA_OBJECT()));
 | 
						|
      }
 | 
						|
    if(inp!=0)
 | 
						|
      {
 | 
						|
    int attrib;
 | 
						|
      int attributeFound;
 | 
						|
      if(this->InputVectorsSelection!=0)
 | 
						|
        {
 | 
						|
        attrib=inp->GetAttributes()->FindAttribute(this->InputVectorsSelection);
 | 
						|
        
 | 
						|
        attributeFound=attrib>=0;
 | 
						|
        if(attributeFound)
 | 
						|
          {
 | 
						|
          attributeFound=(inp->GetAttributes()->GetAttribute(attrib)->GetType()==vtkDataSetAttributes::VECTORS)&&(inp->GetAttributes()->GetAttribute(attrib)->GetCentering()==vtkPointCentered);
 | 
						|
          }
 | 
						|
        }
 | 
						|
      else
 | 
						|
        {
 | 
						|
        // Find the first attribute, point centered and with vector type.
 | 
						|
        attrib=0;
 | 
						|
        attributeFound=0;
 | 
						|
        int c=inp->GetAttributes()->GetNumberOfAttributes();
 | 
						|
        while(attrib<c&&!attributeFound)
 | 
						|
          {
 | 
						|
          attributeFound=(inp->GetAttributes()->GetAttribute(attrib)->GetType()==vtkDataSetAttributes::VECTORS)&&(inp->GetAttributes()->GetAttribute(attrib)->GetCentering()==vtkPointCentered);
 | 
						|
          ++attrib;
 | 
						|
          }
 | 
						|
        if(attributeFound)
 | 
						|
          {
 | 
						|
          --attrib;
 | 
						|
          this->SetInputVectorsSelection(inp->GetAttributes()->GetAttribute(attrib)->GetName());
 | 
						|
          }
 | 
						|
        }
 | 
						|
      if (!attributeFound)
 | 
						|
        {
 | 
						|
        vtkDebugMacro("Input " << i << "does not contain a velocity vector.");
 | 
						|
        continue;
 | 
						|
        }
 | 
						|
      func->AddDataSet(inp);
 | 
						|
      numInputs++;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  if ( numInputs == 0 )
 | 
						|
    {
 | 
						|
    vtkDebugMacro("No appropriate inputs have been found. Can not execute.");
 | 
						|
    return VTK_ERROR;
 | 
						|
    }
 | 
						|
  return VTK_OK;
 | 
						|
}
 | 
						|
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
void vtkGenericStreamTracer::Integrate(
 | 
						|
  vtkGenericDataSet *input0,
 | 
						|
  vtkPolyData* output,
 | 
						|
  vtkDataArray* seedSource, 
 | 
						|
  vtkIdList* seedIds,
 | 
						|
  vtkIntArray* integrationDirections,
 | 
						|
  double lastPoint[3],
 | 
						|
  vtkGenericInterpolatedVelocityField* func)
 | 
						|
{ 
 | 
						|
  int i;
 | 
						|
  vtkIdType numLines = seedIds->GetNumberOfIds();
 | 
						|
 | 
						|
  // Useful pointers
 | 
						|
  vtkDataSetAttributes* outputPD = output->GetPointData();
 | 
						|
  vtkDataSetAttributes* outputCD = output->GetCellData();
 | 
						|
  vtkGenericDataSet* input;
 | 
						|
  vtkGenericAttribute* inVectors;
 | 
						|
  
 | 
						|
  int direction=1;
 | 
						|
 | 
						|
  if (this->GetIntegrator() == 0)
 | 
						|
    {
 | 
						|
    vtkErrorMacro("No integrator is specified.");
 | 
						|
    return;
 | 
						|
    }
 | 
						|
 | 
						|
  // Used in GetCell() 
 | 
						|
//  vtkGenericCell* cell = vtkGenericCell::New();
 | 
						|
  vtkGenericAdaptorCell *cell=0;
 | 
						|
  
 | 
						|
  // Create a new integrator, the type is the same as Integrator
 | 
						|
  vtkInitialValueProblemSolver* integrator = 
 | 
						|
    this->GetIntegrator()->NewInstance();
 | 
						|
  integrator->SetFunctionSet(func);
 | 
						|
 | 
						|
  // Since we do not know what the total number of points
 | 
						|
  // will be, we do not allocate any. This is important for
 | 
						|
  // cases where a lot of streamers are used at once. If we
 | 
						|
  // were to allocate any points here, potentially, we can
 | 
						|
  // waste a lot of memory if a lot of streamers are used.
 | 
						|
  // Always insert the first point
 | 
						|
  vtkPoints* outputPoints = vtkPoints::New();
 | 
						|
  vtkCellArray* outputLines = vtkCellArray::New();
 | 
						|
 | 
						|
  // We will keep track of time in this array
 | 
						|
  vtkDoubleArray* time = vtkDoubleArray::New();
 | 
						|
  time->SetName("IntegrationTime");
 | 
						|
 | 
						|
  // This array explains why the integration stopped
 | 
						|
  vtkIntArray* retVals = vtkIntArray::New();
 | 
						|
  retVals->SetName("ReasonForTermination");
 | 
						|
  
 | 
						|
  vtkDoubleArray* vorticity = 0;
 | 
						|
  vtkDoubleArray* rotation = 0;
 | 
						|
  vtkDoubleArray* angularVel = 0;
 | 
						|
  if (this->ComputeVorticity)
 | 
						|
    {
 | 
						|
    vorticity = vtkDoubleArray::New();
 | 
						|
    vorticity->SetName("Vorticity");
 | 
						|
    vorticity->SetNumberOfComponents(3);
 | 
						|
 | 
						|
    rotation = vtkDoubleArray::New();
 | 
						|
    rotation->SetName("Rotation");
 | 
						|
 | 
						|
    angularVel = vtkDoubleArray::New();
 | 
						|
    angularVel->SetName("AngularVelocity");
 | 
						|
    }
 | 
						|
  
 | 
						|
  // We will interpolate all point attributes of the input on
 | 
						|
  // each point of the output (unless they are turned off)
 | 
						|
  // Note that we are using only the first input, if there are more
 | 
						|
  // than one, the attributes have to match.
 | 
						|
  
 | 
						|
  // prepare the output attributes
 | 
						|
  vtkGenericAttributeCollection *attributes=input0->GetAttributes();
 | 
						|
  vtkGenericAttribute *attribute;
 | 
						|
  vtkDataArray *attributeArray;
 | 
						|
  
 | 
						|
  int c=attributes->GetNumberOfAttributes();
 | 
						|
  int attributeType;
 | 
						|
  
 | 
						|
  // Only point centered attributes will be interpolated.
 | 
						|
  // Cell centered attributes are not ignored and not copied in output:
 | 
						|
  // is a missing part in vtkStreamTracer? Need to ask to the Berk.
 | 
						|
  i=0;
 | 
						|
  while(i<c)
 | 
						|
    {
 | 
						|
    attribute=attributes->GetAttribute(i);
 | 
						|
    attributeType=attribute->GetType();
 | 
						|
    if(attribute->GetCentering()==vtkPointCentered)
 | 
						|
      {
 | 
						|
      attributeArray=vtkDataArray::CreateDataArray(attribute->GetComponentType());
 | 
						|
      attributeArray->SetNumberOfComponents(attribute->GetNumberOfComponents());
 | 
						|
      attributeArray->SetName(attribute->GetName());
 | 
						|
      outputPD->AddArray(attributeArray);
 | 
						|
      attributeArray->Delete();
 | 
						|
      
 | 
						|
      if(outputPD->GetAttribute(attributeType)==0)
 | 
						|
        {
 | 
						|
        outputPD->SetActiveAttribute(outputPD->GetNumberOfArrays()-1,
 | 
						|
                                     attributeType);
 | 
						|
        }
 | 
						|
      }
 | 
						|
    ++i;
 | 
						|
    }
 | 
						|
  double *values=new double[outputPD->GetNumberOfComponents()]; // point centered attributes at some point.
 | 
						|
  
 | 
						|
  
 | 
						|
  // Note:  It is an overestimation to have the estimate the same number of
 | 
						|
  // output points and input points.  We sill have to squeeze at end.
 | 
						|
 | 
						|
  vtkIdType numPtsTotal=0;
 | 
						|
  double velocity[3];
 | 
						|
 | 
						|
  int shouldAbort = 0;
 | 
						|
 | 
						|
  for(int currentLine = 0; currentLine < numLines; currentLine++)
 | 
						|
    {
 | 
						|
 | 
						|
    double progress = static_cast<double>(currentLine)/numLines;
 | 
						|
    this->UpdateProgress(progress);
 | 
						|
 | 
						|
    switch (integrationDirections->GetValue(currentLine))
 | 
						|
      {
 | 
						|
      case FORWARD:
 | 
						|
        direction = 1;
 | 
						|
        break;
 | 
						|
      case BACKWARD:
 | 
						|
        direction = -1;
 | 
						|
        break;
 | 
						|
      }
 | 
						|
 | 
						|
    // temporary variables used in the integration
 | 
						|
    double point1[3], point2[3], pcoords[3], vort[3], omega;
 | 
						|
    vtkIdType index, numPts=0;
 | 
						|
    
 | 
						|
    // Clear the last cell to avoid starting a search from
 | 
						|
    // the last point in the streamline
 | 
						|
    func->ClearLastCell();
 | 
						|
 | 
						|
    
 | 
						|
    // Initial point
 | 
						|
    seedSource->GetTuple(seedIds->GetId(currentLine), point1);
 | 
						|
    memcpy(point2, point1, 3*sizeof(double));
 | 
						|
    if (!func->FunctionValues(point1, velocity))
 | 
						|
      {
 | 
						|
      continue;
 | 
						|
      }
 | 
						|
 | 
						|
    numPts++;
 | 
						|
    numPtsTotal++;
 | 
						|
    vtkIdType nextPoint = outputPoints->InsertNextPoint(point1);
 | 
						|
    time->InsertNextValue(0.0);
 | 
						|
 | 
						|
    // We will always pass a time step to the integrator.
 | 
						|
    // If the user specifies a step size with another unit, we will 
 | 
						|
    // have to convert it to time.
 | 
						|
    IntervalInformation delT;
 | 
						|
    delT.Unit = TIME_UNIT;
 | 
						|
    delT.Interval = 0;
 | 
						|
    IntervalInformation aStep;
 | 
						|
    aStep.Unit = this->MaximumPropagation.Unit;
 | 
						|
    double propagation = 0.0, step, minStep=0, maxStep=0;
 | 
						|
    double stepTaken, accumTime=0;
 | 
						|
    double speed;
 | 
						|
    double cellLength;
 | 
						|
    int retVal=OUT_OF_TIME, tmp;
 | 
						|
 | 
						|
    // Make sure we use the dataset found
 | 
						|
    // by the vtkGenericInterpolatedVelocityField
 | 
						|
    input = func->GetLastDataSet();
 | 
						|
    
 | 
						|
    inVectors=input->GetAttributes()->GetAttribute(input->GetAttributes()->FindAttribute(this->InputVectorsSelection));
 | 
						|
    
 | 
						|
    // Convert intervals to time unit
 | 
						|
    cell=func->GetLastCell();
 | 
						|
    cellLength = sqrt(static_cast<double>(cell->GetLength2()));
 | 
						|
    speed = vtkMath::Norm(velocity);
 | 
						|
 | 
						|
    // Never call conversion methods if speed == 0
 | 
						|
    if (speed != 0.0)
 | 
						|
      {
 | 
						|
      this->ConvertIntervals(delT.Interval, minStep, maxStep, direction, 
 | 
						|
                             cellLength, speed);
 | 
						|
      }
 | 
						|
 | 
						|
    // Interpolate all point attributes on first point
 | 
						|
    func->GetLastLocalCoordinates(pcoords);
 | 
						|
    cell->InterpolateTuple(input->GetAttributes(),pcoords,
 | 
						|
                           values);
 | 
						|
    
 | 
						|
    double *p=values;
 | 
						|
    vtkDataArray *dataArray;
 | 
						|
    c=outputPD->GetNumberOfArrays();
 | 
						|
    int j=0;
 | 
						|
    while(j<c)
 | 
						|
      {
 | 
						|
      dataArray=outputPD->GetArray(j);
 | 
						|
      dataArray->InsertTuple(nextPoint,p);
 | 
						|
      ++j;
 | 
						|
      p=p+dataArray->GetNumberOfComponents();
 | 
						|
      }
 | 
						|
    
 | 
						|
    // Compute vorticity if required
 | 
						|
    // This can be used later for streamribbon generation.
 | 
						|
    if (this->ComputeVorticity)
 | 
						|
      {
 | 
						|
      // Here, we're assuming a linear cell by only taken values at
 | 
						|
      // corner points. there should be a subdivision step here instead.
 | 
						|
      // What is the criterium to stop the subdivision?
 | 
						|
      // Note: the original vtkStreamTracer is taking cell points, it means
 | 
						|
      // that for the quadratic cell, the standard stream tracer is more
 | 
						|
      // accurate than this one!
 | 
						|
      vtkGenericStreamTracer::CalculateVorticity(cell, pcoords, inVectors,
 | 
						|
                                                 vort);
 | 
						|
      
 | 
						|
      vorticity->InsertNextTuple(vort);
 | 
						|
      // rotation
 | 
						|
      // local rotation = vorticity . unit tangent ( i.e. velocity/speed )
 | 
						|
      if (speed != 0.0)
 | 
						|
        {
 | 
						|
          omega = vtkMath::Dot(vort, velocity);
 | 
						|
          omega /= speed;
 | 
						|
          omega *= this->RotationScale;
 | 
						|
        }
 | 
						|
      else
 | 
						|
        {
 | 
						|
          omega = 0.0;
 | 
						|
        }
 | 
						|
      angularVel->InsertNextValue(omega);
 | 
						|
      rotation->InsertNextValue(0.0);
 | 
						|
      }
 | 
						|
 | 
						|
    vtkIdType numSteps = 0;
 | 
						|
    double error = 0;
 | 
						|
    // Integrate until the maximum propagation length is reached, 
 | 
						|
    // maximum number of steps is reached or until a boundary is encountered.
 | 
						|
    // Begin Integration
 | 
						|
    while ( propagation < this->MaximumPropagation.Interval )
 | 
						|
      {
 | 
						|
 | 
						|
      if (numSteps > this->MaximumNumberOfSteps)
 | 
						|
        {
 | 
						|
        retVal = OUT_OF_STEPS;
 | 
						|
        break;
 | 
						|
        }
 | 
						|
 | 
						|
      if ( numSteps++ % 1000 == 1 )
 | 
						|
        {
 | 
						|
        progress = 
 | 
						|
          (currentLine + propagation / this->MaximumPropagation.Interval) /
 | 
						|
          numLines ;
 | 
						|
        this->UpdateProgress(progress);
 | 
						|
 | 
						|
        if (this->GetAbortExecute())
 | 
						|
          {
 | 
						|
          shouldAbort = 1;
 | 
						|
          break;
 | 
						|
          }
 | 
						|
        }
 | 
						|
 | 
						|
      // Never call conversion methods if speed == 0
 | 
						|
      if ( (speed == 0) || (speed <= this->TerminalSpeed) )
 | 
						|
        {
 | 
						|
        retVal = STAGNATION;
 | 
						|
        break;
 | 
						|
        }
 | 
						|
 | 
						|
      // If, with the next step, propagation will be larger than
 | 
						|
      // max, reduce it so that it is (approximately) equal to max.
 | 
						|
      aStep.Interval = fabs(this->ConvertToUnit(delT, 
 | 
						|
                                                this->MaximumPropagation.Unit,
 | 
						|
                                                cellLength, speed));
 | 
						|
      if ( (propagation + aStep.Interval) >  
 | 
						|
           this->MaximumPropagation.Interval )
 | 
						|
        {
 | 
						|
        aStep.Interval = this->MaximumPropagation.Interval - propagation;
 | 
						|
        if (delT.Interval >= 0)
 | 
						|
          {
 | 
						|
          delT.Interval = this->ConvertToTime(aStep, cellLength, speed);
 | 
						|
          }
 | 
						|
        else
 | 
						|
          {
 | 
						|
          delT.Interval = -1.0 * this->ConvertToTime(aStep, cellLength, speed);
 | 
						|
          }
 | 
						|
        maxStep = delT.Interval;
 | 
						|
        }
 | 
						|
      this->LastUsedTimeStep = delT.Interval;
 | 
						|
          
 | 
						|
      // Calculate the next step using the integrator provided
 | 
						|
      // Break if the next point is out of bounds.
 | 
						|
      if ((tmp=
 | 
						|
           integrator->ComputeNextStep(point1, point2, 0, delT.Interval, 
 | 
						|
                                       stepTaken, minStep, maxStep, 
 | 
						|
                                       this->MaximumError, error)) != 0)
 | 
						|
        {
 | 
						|
        retVal = tmp;
 | 
						|
        memcpy(lastPoint, point2, 3*sizeof(double));
 | 
						|
        break;
 | 
						|
        }
 | 
						|
 | 
						|
      accumTime += stepTaken;
 | 
						|
      // Calculate propagation (using the same units as MaximumPropagation
 | 
						|
      propagation += fabs(this->ConvertToUnit(delT, 
 | 
						|
                                              this->MaximumPropagation.Unit,
 | 
						|
                                              cellLength, speed));
 | 
						|
 | 
						|
 | 
						|
      // This is the next starting point
 | 
						|
      for(i=0; i<3; i++)
 | 
						|
        {
 | 
						|
        point1[i] = point2[i];
 | 
						|
        }
 | 
						|
 | 
						|
      // Interpolate the velocity at the next point
 | 
						|
      if ( !func->FunctionValues(point2, velocity) )
 | 
						|
        {
 | 
						|
        retVal = OUT_OF_DOMAIN;
 | 
						|
        memcpy(lastPoint, point2, 3*sizeof(double));
 | 
						|
        break;
 | 
						|
        }
 | 
						|
      
 | 
						|
      // Make sure we use the dataset found by the vtkInterpolatedVelocityField
 | 
						|
      input = func->GetLastDataSet();
 | 
						|
 | 
						|
      inVectors=input->GetAttributes()->GetAttribute(input->GetAttributes()->FindAttribute(this->InputVectorsSelection));
 | 
						|
      
 | 
						|
 | 
						|
      // Point is valid. Insert it.
 | 
						|
      numPts++;
 | 
						|
      numPtsTotal++;
 | 
						|
      nextPoint = outputPoints->InsertNextPoint(point1);
 | 
						|
      time->InsertNextValue(accumTime);
 | 
						|
 | 
						|
      // Calculate cell length and speed to be used in unit conversions
 | 
						|
      cell=func->GetLastCell();
 | 
						|
      cellLength = sqrt(static_cast<double>(cell->GetLength2()));
 | 
						|
    
 | 
						|
      speed = vtkMath::Norm(velocity);
 | 
						|
 | 
						|
      // Interpolate all point attributes on current point
 | 
						|
      func->GetLastLocalCoordinates(pcoords);
 | 
						|
      cell->InterpolateTuple(input->GetAttributes(),pcoords,
 | 
						|
                             values);
 | 
						|
      
 | 
						|
      p=values;
 | 
						|
      c=outputPD->GetNumberOfArrays();
 | 
						|
      j=0;
 | 
						|
      while(j<c)
 | 
						|
        {
 | 
						|
        dataArray=outputPD->GetArray(j);
 | 
						|
        dataArray->InsertTuple(nextPoint,p);
 | 
						|
        ++j;
 | 
						|
        p=p+dataArray->GetNumberOfComponents();
 | 
						|
        }
 | 
						|
 | 
						|
      // Compute vorticity if required
 | 
						|
      // This can be used later for streamribbon generation.
 | 
						|
      if (this->ComputeVorticity)
 | 
						|
        {        
 | 
						|
        vtkGenericStreamTracer::CalculateVorticity(cell, pcoords, inVectors,
 | 
						|
                                                 vort);
 | 
						|
        
 | 
						|
        vorticity->InsertNextTuple(vort);
 | 
						|
        // rotation
 | 
						|
        // angular velocity = vorticity . unit tangent ( i.e. velocity/speed )
 | 
						|
        // rotation = sum ( angular velocity * delT )
 | 
						|
        omega = vtkMath::Dot(vort, velocity);
 | 
						|
        omega /= speed;
 | 
						|
        omega *= this->RotationScale;
 | 
						|
        index = angularVel->InsertNextValue(omega);
 | 
						|
        rotation->InsertNextValue(rotation->GetValue(index-1) +
 | 
						|
                                  (angularVel->GetValue(index-1) + omega)/2 * 
 | 
						|
                                  (accumTime - time->GetValue(index-1)));
 | 
						|
        }
 | 
						|
 | 
						|
      // Never call conversion methods if speed == 0
 | 
						|
      if ( (speed == 0) || (speed <= this->TerminalSpeed) )
 | 
						|
        {
 | 
						|
        retVal = STAGNATION;
 | 
						|
        break;
 | 
						|
        }
 | 
						|
 | 
						|
      // Convert all intervals to time
 | 
						|
      this->ConvertIntervals(step, minStep, maxStep, direction, 
 | 
						|
                             cellLength, speed);
 | 
						|
 | 
						|
 | 
						|
      // If the solver is adaptive and the next time step (delT.Interval)
 | 
						|
      // that the solver wants to use is smaller than minStep or larger 
 | 
						|
      // than maxStep, re-adjust it. This has to be done every step
 | 
						|
      // because minStep and maxStep can change depending on the cell
 | 
						|
      // size (unless it is specified in time units)
 | 
						|
      if (integrator->IsAdaptive())
 | 
						|
        {
 | 
						|
        if (fabs(delT.Interval) < fabs(minStep))
 | 
						|
          {
 | 
						|
          delT.Interval = fabs(minStep) * delT.Interval/fabs(delT.Interval);
 | 
						|
          }
 | 
						|
        else if (fabs(delT.Interval) > fabs(maxStep))
 | 
						|
          {
 | 
						|
          delT.Interval = fabs(maxStep) * delT.Interval/fabs(delT.Interval);
 | 
						|
          }
 | 
						|
        }
 | 
						|
      else
 | 
						|
        {
 | 
						|
        delT.Interval = step;
 | 
						|
        }
 | 
						|
 | 
						|
      // End Integration
 | 
						|
      }
 | 
						|
 | 
						|
    if (shouldAbort)
 | 
						|
      {
 | 
						|
      break;
 | 
						|
      }
 | 
						|
 | 
						|
    if (numPts > 1)
 | 
						|
      {
 | 
						|
      outputLines->InsertNextCell(numPts);
 | 
						|
      for (i=numPtsTotal-numPts; i<numPtsTotal; i++)
 | 
						|
        {
 | 
						|
        outputLines->InsertCellPoint(i);
 | 
						|
        }
 | 
						|
      retVals->InsertNextValue(retVal);
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
  if (!shouldAbort)
 | 
						|
    {
 | 
						|
    // Create the output polyline
 | 
						|
    output->SetPoints(outputPoints);
 | 
						|
    outputPD->AddArray(time);
 | 
						|
    if (vorticity)
 | 
						|
      {
 | 
						|
      outputPD->AddArray(vorticity);
 | 
						|
      outputPD->AddArray(rotation);
 | 
						|
      outputPD->AddArray(angularVel);
 | 
						|
      }
 | 
						|
    
 | 
						|
    vtkIdType numPts = outputPoints->GetNumberOfPoints();
 | 
						|
    if ( numPts > 1 )
 | 
						|
      {
 | 
						|
      // Assign geometry and attributes
 | 
						|
      output->SetLines(outputLines);
 | 
						|
      if (this->GenerateNormalsInIntegrate)
 | 
						|
        {
 | 
						|
        this->GenerateNormals(output, 0);
 | 
						|
        }
 | 
						|
 | 
						|
      outputCD->AddArray(retVals);
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
  if (vorticity)
 | 
						|
    {
 | 
						|
    vorticity->Delete();
 | 
						|
    rotation->Delete();
 | 
						|
    angularVel->Delete();
 | 
						|
    }
 | 
						|
 | 
						|
 
 | 
						|
  retVals->Delete();
 | 
						|
 | 
						|
  outputPoints->Delete();
 | 
						|
  outputLines->Delete();
 | 
						|
 | 
						|
  time->Delete();
 | 
						|
 | 
						|
 | 
						|
  integrator->Delete();
 | 
						|
  
 | 
						|
  delete[] values;
 | 
						|
  
 | 
						|
  output->Squeeze();
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
void vtkGenericStreamTracer::GenerateNormals(vtkPolyData* output,
 | 
						|
                                             double* firstNormal)
 | 
						|
{
 | 
						|
  // Useful pointers
 | 
						|
  vtkDataSetAttributes* outputPD = output->GetPointData();
 | 
						|
 | 
						|
  vtkPoints* outputPoints = output->GetPoints();
 | 
						|
  vtkCellArray* outputLines = output->GetLines();
 | 
						|
 | 
						|
  vtkDataArray* rotation = outputPD->GetArray("Rotation");
 | 
						|
 | 
						|
  vtkIdType numPts = outputPoints->GetNumberOfPoints();
 | 
						|
  if ( numPts > 1 )
 | 
						|
    {
 | 
						|
    if (this->ComputeVorticity)
 | 
						|
      {
 | 
						|
      vtkPolyLine* lineNormalGenerator = vtkPolyLine::New();
 | 
						|
      vtkDoubleArray* normals = vtkDoubleArray::New();
 | 
						|
      normals->SetNumberOfComponents(3);
 | 
						|
      normals->SetNumberOfTuples(numPts);
 | 
						|
        
 | 
						|
      lineNormalGenerator->GenerateSlidingNormals(outputPoints,
 | 
						|
                                                  outputLines,
 | 
						|
                                                  normals,
 | 
						|
                                                  firstNormal);
 | 
						|
      lineNormalGenerator->Delete();
 | 
						|
 | 
						|
      int i, j;
 | 
						|
      double normal[3], local1[3], local2[3], theta, costheta, sintheta, length;
 | 
						|
      double velocity[3];
 | 
						|
      normals->SetName("Normals");
 | 
						|
      vtkDataArray* newVectors = 
 | 
						|
        outputPD->GetVectors(this->InputVectorsSelection);
 | 
						|
      for(i=0; i<numPts; i++)
 | 
						|
        {
 | 
						|
        normals->GetTuple(i, normal);
 | 
						|
        if (newVectors == NULL)
 | 
						|
          { // This should never happen.
 | 
						|
          vtkErrorMacro("Could not find output array.");
 | 
						|
          return;
 | 
						|
          }
 | 
						|
        newVectors->GetTuple(i, velocity);
 | 
						|
        // obtain two unit orthogonal vectors on the plane perpendicular to
 | 
						|
        // the streamline
 | 
						|
        for(j=0; j<3; j++) { local1[j] = normal[j]; }
 | 
						|
        length = vtkMath::Normalize(local1);
 | 
						|
        vtkMath::Cross(local1, velocity, local2);
 | 
						|
        vtkMath::Normalize(local2);
 | 
						|
        // Rotate the normal with theta
 | 
						|
        rotation->GetTuple(i, &theta);
 | 
						|
        costheta = cos(theta);
 | 
						|
        sintheta = sin(theta);
 | 
						|
        for(j=0; j<3; j++)
 | 
						|
          {
 | 
						|
          normal[j] = length* (costheta*local1[j] + sintheta*local2[j]);
 | 
						|
          }
 | 
						|
        normals->SetTuple(i, normal);
 | 
						|
        }
 | 
						|
      outputPD->AddArray(normals);
 | 
						|
      outputPD->SetActiveAttribute("Normals", vtkDataSetAttributes::VECTORS);
 | 
						|
      normals->Delete();
 | 
						|
      }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
// This is used by sub-classes in certain situations. It
 | 
						|
// does a lot less (for example, does not compute attributes)
 | 
						|
// than Integrate.
 | 
						|
void vtkGenericStreamTracer::SimpleIntegrate(
 | 
						|
  double seed[3], 
 | 
						|
  double lastPoint[3], 
 | 
						|
  double delt,
 | 
						|
  vtkGenericInterpolatedVelocityField* func)
 | 
						|
{
 | 
						|
  vtkIdType numSteps = 0;
 | 
						|
  vtkIdType maxSteps = 20;
 | 
						|
  double error = 0;
 | 
						|
  double stepTaken;
 | 
						|
  double point1[3], point2[3];
 | 
						|
  double velocity[3];
 | 
						|
  double speed;
 | 
						|
 | 
						|
  (void)seed; // Seed is not used
 | 
						|
 | 
						|
  memcpy(point1, lastPoint, 3*sizeof(double));
 | 
						|
 | 
						|
  // Create a new integrator, the type is the same as Integrator
 | 
						|
  vtkInitialValueProblemSolver* integrator = 
 | 
						|
    this->GetIntegrator()->NewInstance();
 | 
						|
  integrator->SetFunctionSet(func);
 | 
						|
 | 
						|
  while ( 1 )
 | 
						|
    {
 | 
						|
 | 
						|
    if (numSteps++ > maxSteps)
 | 
						|
      {
 | 
						|
      break;
 | 
						|
      }
 | 
						|
 | 
						|
    // Calculate the next step using the integrator provided
 | 
						|
    // Break if the next point is out of bounds.
 | 
						|
    if (integrator->ComputeNextStep(point1, point2, 0, delt, 
 | 
						|
                                     stepTaken, 0, 0, 0, error) != 0)
 | 
						|
      {
 | 
						|
      memcpy(lastPoint, point2, 3*sizeof(double));
 | 
						|
      break;
 | 
						|
      }
 | 
						|
 | 
						|
 | 
						|
    // This is the next starting point
 | 
						|
    for(int i=0; i<3; i++)
 | 
						|
      {
 | 
						|
      point1[i] = point2[i];
 | 
						|
      }
 | 
						|
 | 
						|
    // Interpolate the velocity at the next point
 | 
						|
    if ( !func->FunctionValues(point2, velocity) )
 | 
						|
      {
 | 
						|
      memcpy(lastPoint, point2, 3*sizeof(double));
 | 
						|
      break;
 | 
						|
      }
 | 
						|
 | 
						|
    speed = vtkMath::Norm(velocity);
 | 
						|
 | 
						|
    // Never call conversion methods if speed == 0
 | 
						|
    if ( (speed == 0) || (speed <= this->TerminalSpeed) )
 | 
						|
      {
 | 
						|
      break;
 | 
						|
      }
 | 
						|
 | 
						|
    memcpy(point1, point2, 3*sizeof(double));
 | 
						|
    // End Integration
 | 
						|
    }
 | 
						|
 | 
						|
  integrator->Delete();
 | 
						|
}
 | 
						|
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
void vtkGenericStreamTracer::PrintSelf(ostream& os,
 | 
						|
                                       vtkIndent indent)
 | 
						|
{
 | 
						|
  this->Superclass::PrintSelf(os,indent);
 | 
						|
  os << indent << "Start position: " 
 | 
						|
     << this->StartPosition[0] << " "
 | 
						|
     << this->StartPosition[1] << " "
 | 
						|
     << this->StartPosition[2] << endl;
 | 
						|
  os << indent << "Terminal speed: " << this->TerminalSpeed << endl;
 | 
						|
  os << indent << "Maximum propagation: " << this->MaximumPropagation.Interval
 | 
						|
     << " unit: ";
 | 
						|
  switch (this->MaximumPropagation.Unit)
 | 
						|
    {
 | 
						|
    case TIME_UNIT:
 | 
						|
      os << "time.";
 | 
						|
      break;
 | 
						|
    case LENGTH_UNIT:
 | 
						|
      os << "length.";
 | 
						|
      break;
 | 
						|
    case CELL_LENGTH_UNIT:
 | 
						|
      os << "cell length.";
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  os << endl;
 | 
						|
  
 | 
						|
  os << indent << "Min. integration step: " 
 | 
						|
     << this->MinimumIntegrationStep.Interval
 | 
						|
     << " unit: ";
 | 
						|
  switch (this->MinimumIntegrationStep.Unit)
 | 
						|
    {
 | 
						|
    case TIME_UNIT:
 | 
						|
      os << "time.";
 | 
						|
      break;
 | 
						|
    case LENGTH_UNIT:
 | 
						|
      os << "length.";
 | 
						|
      break;
 | 
						|
    case CELL_LENGTH_UNIT:
 | 
						|
      os << "cell length.";
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  os << endl;
 | 
						|
 | 
						|
  os << indent << "Max. integration step: " 
 | 
						|
     << this->MaximumIntegrationStep.Interval
 | 
						|
     << " unit: ";
 | 
						|
  switch (this->MaximumIntegrationStep.Unit)
 | 
						|
    {
 | 
						|
    case TIME_UNIT:
 | 
						|
      os << "time.";
 | 
						|
      break;
 | 
						|
    case LENGTH_UNIT:
 | 
						|
      os << "length.";
 | 
						|
      break;
 | 
						|
    case CELL_LENGTH_UNIT:
 | 
						|
      os << "cell length.";
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  os << endl;
 | 
						|
 | 
						|
  os << indent << "Initial integration step: " 
 | 
						|
     << this->InitialIntegrationStep.Interval
 | 
						|
     << " unit: ";
 | 
						|
  switch (this->InitialIntegrationStep.Unit)
 | 
						|
    {
 | 
						|
    case TIME_UNIT:
 | 
						|
      os << "time.";
 | 
						|
      break;
 | 
						|
    case LENGTH_UNIT:
 | 
						|
      os << "length.";
 | 
						|
      break;
 | 
						|
    case CELL_LENGTH_UNIT:
 | 
						|
      os << "cell length.";
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  os << endl;
 | 
						|
 | 
						|
  os << indent << "Integration direction: ";
 | 
						|
  switch (this->IntegrationDirection)
 | 
						|
    {
 | 
						|
    case FORWARD:
 | 
						|
      os << "forward.";
 | 
						|
      break;
 | 
						|
    case BACKWARD:
 | 
						|
      os << "backward.";
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  os << endl;
 | 
						|
 | 
						|
  os << indent << "Integrator: " << this->Integrator << endl;
 | 
						|
  os << indent << "Maximum error: " << this->MaximumError << endl;
 | 
						|
  os << indent << "Max. number of steps: " << this->MaximumNumberOfSteps 
 | 
						|
     << endl;
 | 
						|
  os << indent << "Vorticity computation: " 
 | 
						|
     << (this->ComputeVorticity ? " On" : " Off") << endl;
 | 
						|
  os << indent << "Rotation scale: " << this->RotationScale << endl;
 | 
						|
 | 
						|
  if (this->InputVectorsSelection)
 | 
						|
    {
 | 
						|
    os << indent << "InputVectorsSelection: " << this->InputVectorsSelection;
 | 
						|
    } 
 | 
						|
}
 | 
						|
 |