Commit b117a066 authored by Mathieu Westphal's avatar Mathieu Westphal

Adding surface streamlines

Adding surface streamlines support to vtk by :
Using a higher tolarance (*10)
2D Check of cell inclusion
Surface vortivity
Snapping stream lines point to surface

New version of the surface stream tracer

New version of the surface streamer tracer, the main point are :
1. Use of a surface tolerance scale at 1.E-5, to ensure even adaptative algorithm like RungeKutta4-5 works, however it is still possible to create dataset wich will not comply with this,
A Hard edge with a big vector will always make it fails at some point, is is more visible with surface streamlines but could occur with volume streamlines as well

2. A new version of FindCell, with a surface specific part wich almmost always find a cell, except when we are really out of domain.
It is ensured by always checking findPoint return

3. Still use surface vector

4. Snap using new version of FindCell

Note: Style is not yet considered, do not loose any time review the style.

Correcting style in new code
parent 869c3b5a
vtk_add_test_cxx(${vtk-module}CxxTests tests
TestBSPTree.cxx
TestStreamTracer.cxx,NO_VALID
TestStreamTracerSurface.cxx
TestAMRInterpolatedVelocityField.cxx,NO_VALID
TestParticleTracers.cxx,NO_VALID
)
......
/*=========================================================================
Program: Visualization Toolkit
Module: TestDistancePolyDataFilter.cxx
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 "vtkActor.h"
#include "vtkArrayCalculator.h"
#include "vtkDataSetMapper.h"
#include "vtkMath.h"
#include "vtkNew.h"
#include "vtkProperty.h"
#include "vtkPolyData.h"
#include "vtkPoints.h"
#include "vtkPointSource.h"
#include "vtkRegressionTestImage.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkRTAnalyticSource.h"
#include "vtkStreamTracer.h"
#include "vtkWarpScalar.h"
int TestStreamTracerSurface(int argc, char* argv[])
{
vtkNew<vtkRTAnalyticSource> wavelet;
wavelet->SetWholeExtent(-10, 100, -10, 100, 0, 0);
vtkNew<vtkWarpScalar> warp;
warp->SetScaleFactor(0.1);
warp->SetInputConnection(wavelet->GetOutputPort());
vtkNew<vtkArrayCalculator> calc;
calc->AddScalarArrayName("RTData");
calc->SetFunction("abs(RTData)*iHat + abs(RTData)*jHat");
calc->SetInputConnection(warp->GetOutputPort());
calc->Update();
vtkNew<vtkPoints> points;
vtkDataSet* calcData = calc->GetOutput();
vtkIdType nLine = sqrt(calcData->GetNumberOfPoints());
for (vtkIdType i = 0; i < nLine; i += 10)
{
points->InsertNextPoint(calcData->GetPoint(i * (nLine - 1) + nLine));
}
vtkNew<vtkPolyData> pointsPolydata;
pointsPolydata->SetPoints(points.Get());
vtkNew<vtkStreamTracer> stream;
stream->SurfaceStreamlinesOn();
stream->SetMaximumPropagation(210);
stream->SetIntegrationDirection(vtkStreamTracer::BOTH);
stream->SetInputConnection(calc->GetOutputPort());
stream->SetSourceData(pointsPolydata.Get());
vtkNew<vtkDataSetMapper> streamMapper;
streamMapper->SetInputConnection(stream->GetOutputPort());
streamMapper->ScalarVisibilityOff();
vtkNew<vtkDataSetMapper> surfaceMapper;
surfaceMapper->SetInputConnection(calc->GetOutputPort());
vtkNew<vtkActor> streamActor;
streamActor->SetMapper(streamMapper.Get());
streamActor->GetProperty()->SetColor(1,1,1);
streamActor->GetProperty()->SetLineWidth(4.);
streamActor->SetPosition(0,0,1);
vtkNew<vtkActor> surfaceActor;
surfaceActor->SetMapper(surfaceMapper.Get());
surfaceActor->GetProperty()->SetRepresentationToSurface();
vtkNew<vtkRenderer> renderer;
renderer->AddActor(surfaceActor.GetPointer());
renderer->AddActor(streamActor.GetPointer());
renderer->ResetCamera();
renderer->SetBackground(1., 1., 1.);
vtkNew<vtkRenderWindow> renWin;
renWin->AddRenderer(renderer.GetPointer());
renWin->SetMultiSamples(0);
renWin->SetSize(300, 300);
vtkNew<vtkRenderWindowInteractor> iren;
iren->SetRenderWindow(renWin.GetPointer());
int retVal = vtkRegressionTestImage(renWin.GetPointer());
if (retVal == vtkRegressionTester::DO_INTERACTOR)
{
iren->Start();
}
return !retVal;
}
......@@ -142,6 +142,17 @@ public:
vtkSetMacro( NormalizeVector, bool );
vtkGetMacro( NormalizeVector, bool );
// Description:
// If set to true, the first three point of the cell will be used to compute a normal to the cell,
// this normal will then be removed from the vorticity so the resulting vector in tangent to the cell.
vtkSetMacro(ForceSurfaceTangentVector, bool);
vtkGetMacro(ForceSurfaceTangentVector, bool);
// Description:
// If set to true, cell within tolerance factor will always be found, except for edges.
vtkSetMacro(SurfaceDataset, bool);
vtkGetMacro(SurfaceDataset, bool);
// Description:
// Import parameters. Sub-classes can add more after chaining.
virtual void CopyParameters( vtkAbstractInterpolatedVelocityField * from )
......@@ -150,7 +161,7 @@ public:
// Description:
// Evaluate the velocity field f at point (x, y, z).
virtual int FunctionValues( double * x, double * f ) = 0;
virtual int FunctionValues(double * x, double * f) = 0;
// Description:
// Set the last cell id to -1 to incur a global cell search for the next point.
......@@ -167,16 +178,20 @@ protected:
~vtkAbstractInterpolatedVelocityField();
static const double TOLERANCE_SCALE;
static const double SURFACE_TOLERANCE_SCALE;
int CacheHit;
int CacheMiss;
int WeightsSize;
bool Caching;
bool NormalizeVector;
bool ForceSurfaceTangentVector;
bool SurfaceDataset;
int VectorsType;
char * VectorsSelection;
double * Weights;
double LastPCoords[3];
int LastSubId;
vtkIdType LastCellId;
vtkDataSet * LastDataSet;
vtkGenericCell * Cell;
......@@ -195,7 +210,21 @@ protected:
// for cell location. In vtkCellLocatorInterpolatedVelocityField, this function
// is invoked just to handle vtkImageData and vtkRectilinearGrid that are not
// assigned with any vtkAbstractCellLocatot-type cell locator.
virtual int FunctionValues( vtkDataSet * ds, double * x, double * f );
// If activated, returned vector will be tangential to the first
// three point of the cell
virtual int FunctionValues(vtkDataSet * ds, double * x, double * f);
// Description:
// Check that all three pcoords are between 0 and 1 included.
virtual bool CheckPCoords(double pcoords[3]);
// Description
// Try to find the cell closest to provided x point in provided dataset,
// By first testing inclusion in it's cached cell and neighbor
// Then testing globally
// Then , only if surfacic is activated finding the closest cell
// using FindPoint and comparing distance with tolerance
virtual bool FindAndUpdateCell(vtkDataSet* ds, double* x);
//BTX
friend class vtkTemporalInterpolatedVelocityField;
......
......@@ -101,6 +101,23 @@ int vtkInterpolatedVelocityField::FunctionValues( double * x, double * f )
return retVal;
}
//----------------------------------------------------------------------------
int vtkInterpolatedVelocityField::SnapPointOnCell(double* pOrigin, double* pSnap)
{
if( this->LastDataSet == NULL )
{
return 0;
}
if (!this->FindAndUpdateCell(this->LastDataSet, pOrigin))
{
return 0;
}
double dist2;
this->GenCell->EvaluatePosition
(pOrigin, pSnap, this->LastSubId, this->LastPCoords, dist2, this->Weights);
return 1;
}
//----------------------------------------------------------------------------
void vtkInterpolatedVelocityField::PrintSelf( ostream & os, vtkIndent indent )
{
......
......@@ -78,6 +78,10 @@ public:
// Evaluate the velocity field f at point (x, y, z).
virtual int FunctionValues( double * x, double * f );
// Description:
// Project the provided point on current cell, current dataset.
virtual int SnapPointOnCell(double* pOrigin, double* pProj);
// Description:
// Set the cell id cached by the last evaluation within a specified dataset.
virtual void SetLastCellId( vtkIdType c, int dataindex );
......
......@@ -700,6 +700,24 @@ void vtkStreamTracer::Integrate(vtkPointData *input0Data,
this->GetIntegrator()->NewInstance();
integrator->SetFunctionSet(func);
// Check Surface option
vtkInterpolatedVelocityField* surfaceFunc = NULL;
if (this->SurfaceStreamlines == true)
{
surfaceFunc = vtkInterpolatedVelocityField::SafeDownCast(func);
if (surfaceFunc == NULL)
{
vtkWarningMacro(<< "Surface Streamlines works only with Point Locator "
"Interpolated Velocity Field, setting it off");
this->SetSurfaceStreamlines(false);
}
else
{
surfaceFunc->SetForceSurfaceTangentVector(true);
surfaceFunc->SetSurfaceDataset(true);
}
}
// 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
......@@ -951,9 +969,21 @@ void vtkStreamTracer::Integrate(vtkPointData *input0Data,
}
// This is the next starting point
for(i=0; i<3; i++)
if (this->SurfaceStreamlines && surfaceFunc != NULL)
{
point1[i] = point2[i];
if (surfaceFunc->SnapPointOnCell(point2, point1) != 1)
{
retVal = OUT_OF_DOMAIN;
memcpy(lastPoint, point2, 3*sizeof(double));
break;
}
}
else
{
for (i=0; i<3; i++)
{
point1[i] = point2[i];
}
}
// Interpolate the velocity at the next point
......
......@@ -244,6 +244,12 @@ public:
vtkSetMacro(TerminalSpeed, double);
vtkGetMacro(TerminalSpeed, double);
// Description:
// Set/Unset the streamlines to be computed on a surface
vtkGetMacro(SurfaceStreamlines, bool);
vtkSetMacro(SurfaceStreamlines, bool);
vtkBooleanMacro(SurfaceStreamlines, bool);
//BTX
enum
{
......@@ -384,6 +390,9 @@ protected:
bool ComputeVorticity;
double RotationScale;
// Compute streamlines only on surface.
bool SurfaceStreamlines;
vtkAbstractInterpolatedVelocityField * InterpolatorPrototype;
vtkCompositeDataSet* InputData;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment