mirror of
https://github.com/OpenFOAM/ThirdParty-6.git
synced 2025-12-08 06:57:43 +00:00
410 lines
14 KiB
C++
410 lines
14 KiB
C++
/*=========================================================================
|
|
|
|
Program: ParaView
|
|
Module: vtkGeometrySliceRepresentation.cxx
|
|
|
|
Copyright (c) Kitware, Inc.
|
|
All rights reserved.
|
|
See Copyright.txt or http://www.paraview.org/HTML/Copyright.html 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 "vtkGeometrySliceRepresentation.h"
|
|
|
|
#include "vtkActor.h"
|
|
#include "vtkAlgorithmOutput.h"
|
|
#include "vtkCompositePolyDataMapper2.h"
|
|
#include "vtkDataArray.h"
|
|
#include "vtkDataObject.h"
|
|
#include "vtkDoubleArray.h"
|
|
#include "vtkFieldData.h"
|
|
#include "vtkInformation.h"
|
|
#include "vtkInformationVector.h"
|
|
#include "vtkMath.h"
|
|
#include "vtkMatrix4x4.h"
|
|
#include "vtkNew.h"
|
|
#include "vtkObjectFactory.h"
|
|
#include "vtkOutlineSource.h"
|
|
#include "vtkPVCacheKeeper.h"
|
|
#include "vtkPVChangeOfBasisHelper.h"
|
|
#include "vtkPVGeometryFilter.h"
|
|
#include "vtkPVLODActor.h"
|
|
#include "vtkPVMultiSliceView.h"
|
|
#include "vtkPVOrthographicSliceView.h"
|
|
#include "vtkPolyDataMapper.h"
|
|
#include "vtkRenderer.h"
|
|
#include "vtkSmartPointer.h"
|
|
#include "vtkStringArray.h"
|
|
#include "vtkThreeSliceFilter.h"
|
|
#include "vtkVector.h"
|
|
|
|
#ifndef VTKGL2
|
|
# include "vtkHardwareSelectionPolyDataPainter.h"
|
|
#endif
|
|
#include <vector>
|
|
#include <cassert>
|
|
namespace
|
|
{
|
|
bool GetNormalsToBasisPlanes(vtkMatrix4x4* changeOfBasisMatrix, vtkVector3d sliceNormals[3])
|
|
{
|
|
if (!changeOfBasisMatrix)
|
|
{
|
|
sliceNormals[0] = vtkVector3d(1, 0, 0);
|
|
sliceNormals[1] = vtkVector3d(0, 1, 0);
|
|
sliceNormals[2] = vtkVector3d(0, 0, 1);
|
|
}
|
|
else
|
|
{
|
|
vtkVector3d axisBases[3];
|
|
vtkPVChangeOfBasisHelper::GetBasisVectors(changeOfBasisMatrix,
|
|
axisBases[0], axisBases[1], axisBases[2]);
|
|
for (int cc=0; cc < 3; cc++)
|
|
{
|
|
sliceNormals[cc] = axisBases[(cc+1)%3].Cross(axisBases[(cc+2)%3]);
|
|
sliceNormals[cc].Normalize();
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
class vtkGSRGeometryFilter : public vtkPVGeometryFilter
|
|
{
|
|
std::vector<double> SlicePositions[3];
|
|
public:
|
|
/// Set positions for slice locations along each of the basis axis.
|
|
void SetSlicePositions(int axis, const std::vector<double>& positions)
|
|
{
|
|
assert(axis >=0 && axis <= 2);
|
|
if (this->SlicePositions[axis] != positions)
|
|
{
|
|
this->SlicePositions[axis] = positions;
|
|
this->Modified();
|
|
}
|
|
}
|
|
|
|
static bool CacheBounds(vtkDataObject* dataObject, const double bounds[6])
|
|
{
|
|
vtkNew<vtkDoubleArray> boundsArray;
|
|
boundsArray->SetName("vtkGSRGeometryFilter_Bounds");
|
|
boundsArray->SetNumberOfComponents(6);
|
|
boundsArray->SetNumberOfTuples(1);
|
|
std::copy(bounds, bounds+6, boundsArray->GetPointer(0));
|
|
dataObject->GetFieldData()->AddArray(boundsArray.GetPointer());
|
|
return true;
|
|
}
|
|
static bool ExtractCachedBounds(vtkDataObject* dataObject, double bounds[6])
|
|
{
|
|
if (dataObject == NULL || dataObject->GetFieldData() == NULL)
|
|
{
|
|
return false;
|
|
}
|
|
vtkFieldData* fd = dataObject->GetFieldData();
|
|
// first try OrientedBoundingBox if present. These are more accurate when
|
|
// Basis is changed.
|
|
if (vtkPVChangeOfBasisHelper::GetBoundingBoxInBasis(dataObject, bounds))
|
|
{
|
|
return true;
|
|
}
|
|
if (fd->GetArray("vtkGSRGeometryFilter_Bounds") &&
|
|
fd->GetArray("vtkGSRGeometryFilter_Bounds")->GetNumberOfTuples() == 1 &&
|
|
fd->GetArray("vtkGSRGeometryFilter_Bounds")->GetNumberOfComponents() == 6)
|
|
{
|
|
fd->GetArray("vtkGSRGeometryFilter_Bounds")->GetTuple(0, bounds);
|
|
return (vtkMath::AreBoundsInitialized(bounds) == 1);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public:
|
|
static vtkGSRGeometryFilter* New();
|
|
vtkTypeMacro(vtkGSRGeometryFilter, vtkPVGeometryFilter);
|
|
|
|
virtual int RequestData(
|
|
vtkInformation *req, vtkInformationVector **inputVector,
|
|
vtkInformationVector *outputVector)
|
|
{
|
|
vtkSmartPointer<vtkDataObject> inputDO = vtkDataObject::GetData(inputVector[0]);
|
|
vtkSmartPointer<vtkMatrix4x4> changeOfBasisMatrix =
|
|
vtkPVChangeOfBasisHelper::GetChangeOfBasisMatrix(inputDO);
|
|
|
|
vtkVector3d sliceNormals[3];
|
|
GetNormalsToBasisPlanes(changeOfBasisMatrix, sliceNormals);
|
|
|
|
vtkNew<vtkThreeSliceFilter> slicer;
|
|
slicer->SetInputDataObject(inputDO);
|
|
slicer->SetCutOrigins(0, 0, 0);
|
|
for (int axis=0; axis<3; axis++)
|
|
{
|
|
slicer->SetNumberOfSlice(axis, static_cast<int>(this->SlicePositions[axis].size()));
|
|
slicer->SetCutNormal(axis, sliceNormals[axis].GetData());
|
|
for (size_t cc=0; cc < this->SlicePositions[axis].size(); cc++)
|
|
{
|
|
double position[4] = {0, 0, 0, 1};
|
|
position[axis] = this->SlicePositions[axis][cc];
|
|
// The of position specified in the UI is in the coordinate space defined
|
|
// by the changeOfBasisMatrix. We need to convert it to cartesian
|
|
// space.
|
|
if (changeOfBasisMatrix)
|
|
{
|
|
changeOfBasisMatrix->MultiplyPoint(position, position);
|
|
position[0] /= position[3];
|
|
position[1] /= position[3];
|
|
position[2] /= position[3];
|
|
position[3] = 1.0;
|
|
}
|
|
// project this point on slice normal since we're not directly
|
|
// specifying the slice point but the slice offset along the slice
|
|
// normal from the slice origin (which is (0,0,0)).
|
|
double offset = sliceNormals[axis].Dot(vtkVector3d(position));
|
|
slicer->SetCutValue(axis, static_cast<int>(cc), offset);
|
|
}
|
|
}
|
|
slicer->Update();
|
|
inputVector[0]->GetInformationObject(0)->Set(
|
|
vtkDataObject::DATA_OBJECT(), slicer->GetOutputDataObject(0));
|
|
int ret = this->Superclass::RequestData(req, inputVector, outputVector);
|
|
inputVector[0]->GetInformationObject(0)->Set(
|
|
vtkDataObject::DATA_OBJECT(), inputDO);
|
|
|
|
// Add input bounds to the ouput field data so it gets cached for use in
|
|
// vtkGeometrySliceRepresentation::RequestData().
|
|
vtkDataObject* output = vtkDataObject::GetData(outputVector, 0);
|
|
double inputBds[6];
|
|
vtkGeometryRepresentation::GetBounds(inputDO, inputBds, NULL);
|
|
vtkGSRGeometryFilter::CacheBounds(output, inputBds);
|
|
return ret;
|
|
}
|
|
|
|
protected:
|
|
vtkGSRGeometryFilter()
|
|
{
|
|
}
|
|
|
|
virtual ~vtkGSRGeometryFilter() {}
|
|
|
|
private:
|
|
vtkGSRGeometryFilter(const vtkGSRGeometryFilter&);
|
|
void operator=(vtkGSRGeometryFilter&);
|
|
};
|
|
vtkStandardNewMacro(vtkGSRGeometryFilter);
|
|
}
|
|
|
|
|
|
class vtkGeometrySliceRepresentation::vtkInternals
|
|
{
|
|
public:
|
|
double OriginalDataBounds[6];
|
|
vtkNew<vtkOutlineSource> OutlineSource;
|
|
vtkNew<vtkPolyDataMapper> OutlineMapper;
|
|
vtkNew<vtkActor> OutlineActor;
|
|
};
|
|
|
|
vtkStandardNewMacro(vtkGeometrySliceRepresentation);
|
|
//----------------------------------------------------------------------------
|
|
vtkGeometrySliceRepresentation::vtkGeometrySliceRepresentation()
|
|
: Internals(new vtkGeometrySliceRepresentation::vtkInternals())
|
|
{
|
|
this->GeometryFilter->Delete();
|
|
this->GeometryFilter = vtkGSRGeometryFilter::New();
|
|
this->SetupDefaults();
|
|
this->Mode = ALL_SLICES;
|
|
this->ShowOutline = false;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkGeometrySliceRepresentation::~vtkGeometrySliceRepresentation()
|
|
{
|
|
delete this->Internals;
|
|
this->Internals = NULL;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkGeometrySliceRepresentation::SetupDefaults()
|
|
{
|
|
vtkMath::UninitializeBounds(this->Internals->OriginalDataBounds);
|
|
this->Superclass::SetupDefaults();
|
|
vtkCompositePolyDataMapper2* mapper =
|
|
vtkCompositePolyDataMapper2::SafeDownCast(this->Mapper);
|
|
#ifdef VTKGL2
|
|
mapper->SetPointIdArrayName("-");
|
|
mapper->SetCellIdArrayName("vtkSliceOriginalCellIds");
|
|
mapper->SetCompositeIdArrayName("vtkSliceCompositeIndex");
|
|
#else
|
|
vtkHardwareSelectionPolyDataPainter* selPainter =
|
|
vtkHardwareSelectionPolyDataPainter::SafeDownCast(
|
|
mapper->GetSelectionPainter()->GetDelegatePainter());
|
|
selPainter->SetPointIdArrayName("-");
|
|
selPainter->SetCellIdArrayName("vtkSliceOriginalCellIds");
|
|
selPainter->SetCompositeIdArrayName("vtkSliceCompositeIndex");
|
|
#endif
|
|
|
|
this->Internals->OutlineMapper->SetInputConnection(
|
|
this->Internals->OutlineSource->GetOutputPort());
|
|
this->Internals->OutlineActor->SetMapper(
|
|
this->Internals->OutlineMapper.GetPointer());
|
|
this->Internals->OutlineActor->SetUseBounds(0);
|
|
this->Internals->OutlineActor->SetVisibility(0);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkGeometrySliceRepresentation::ProcessViewRequest(
|
|
vtkInformationRequestKey* request_type,
|
|
vtkInformation* inInfo, vtkInformation* outInfo)
|
|
{
|
|
if (this->GetVisibility() == false)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if (request_type == vtkPVView::REQUEST_UPDATE())
|
|
{
|
|
vtkGSRGeometryFilter* geomFilter = vtkGSRGeometryFilter::SafeDownCast(this->GeometryFilter);
|
|
assert(geomFilter);
|
|
|
|
// Propagate slice paramemeters from the view to the representation.
|
|
vtkPVMultiSliceView* view = vtkPVMultiSliceView::SafeDownCast(
|
|
inInfo->Get(vtkPVView::VIEW()));
|
|
if (view)
|
|
{
|
|
for (int mode=X_SLICE_ONLY; mode < ALL_SLICES; mode++)
|
|
{
|
|
if (this->Mode == mode || this->Mode == ALL_SLICES)
|
|
{
|
|
geomFilter->SetSlicePositions(mode, view->GetSlices(mode));
|
|
}
|
|
else
|
|
{
|
|
geomFilter->SetSlicePositions(mode, std::vector<double>());
|
|
}
|
|
}
|
|
if (geomFilter->GetMTime() > this->GetMTime())
|
|
{
|
|
this->MarkModified();
|
|
}
|
|
}
|
|
}
|
|
int retVal = this->Superclass::ProcessViewRequest(request_type, inInfo, outInfo);
|
|
if (retVal && request_type == vtkPVView::REQUEST_UPDATE())
|
|
{
|
|
vtkPVMultiSliceView* view = vtkPVMultiSliceView::SafeDownCast(
|
|
inInfo->Get(vtkPVView::VIEW()));
|
|
if (view)
|
|
{
|
|
vtkPVMultiSliceView::SetDataBounds(inInfo, this->Internals->OriginalDataBounds);
|
|
}
|
|
if (this->Mode != ALL_SLICES)
|
|
{
|
|
// i.e. being used in vtkPVOrthographicSliceView for showing the
|
|
// orthographic slices. We don't parallel rendering those orthographic
|
|
// views for now.
|
|
vtkPVRenderView::SetDeliverToClientAndRenderingProcesses(
|
|
inInfo, this, true, true);
|
|
}
|
|
}
|
|
if (request_type == vtkPVView::REQUEST_RENDER())
|
|
{
|
|
vtkAlgorithmOutput* producerPort = vtkPVRenderView::GetPieceProducer(inInfo, this);
|
|
vtkAlgorithm* algo = producerPort->GetProducer();
|
|
vtkDataObject* localData = algo->GetOutputDataObject(producerPort->GetIndex());
|
|
|
|
vtkSmartPointer<vtkMatrix4x4> changeOfBasisMatrix =
|
|
vtkPVChangeOfBasisHelper::GetChangeOfBasisMatrix(localData);
|
|
|
|
// This is called on the "rendering" nodes. We use this pass to communicate
|
|
// the "ModelTransformationMatrix" to the view.
|
|
if (vtkPVMultiSliceView* view = vtkPVMultiSliceView::SafeDownCast(
|
|
inInfo->Get(vtkPVView::VIEW())))
|
|
{
|
|
view->SetModelTransformationMatrix(changeOfBasisMatrix);
|
|
const char* titles[3] = {NULL, NULL, NULL};
|
|
vtkPVChangeOfBasisHelper::GetBasisName(localData, titles[0], titles[1], titles[2]);
|
|
for (int axis=0; axis < 3; ++axis)
|
|
{
|
|
if (titles[axis] != NULL)
|
|
{
|
|
vtkPVMultiSliceView::SetAxisTitle(inInfo, axis, titles[axis]);
|
|
}
|
|
}
|
|
double bds[6];
|
|
if (vtkGSRGeometryFilter::ExtractCachedBounds(localData, bds))
|
|
{
|
|
this->Internals->OutlineSource->SetBounds(bds);
|
|
this->Internals->OutlineActor->SetUserMatrix(changeOfBasisMatrix);
|
|
this->Internals->OutlineActor->SetVisibility(this->ShowOutline? 1 : 0);
|
|
}
|
|
else
|
|
{
|
|
this->Internals->OutlineActor->SetVisibility(0);
|
|
}
|
|
}
|
|
}
|
|
return retVal;
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkGeometrySliceRepresentation::RequestData(vtkInformation* request,
|
|
vtkInformationVector** inputVector, vtkInformationVector* outputVector)
|
|
{
|
|
vtkMath::UninitializeBounds(this->Internals->OriginalDataBounds);
|
|
if (this->Superclass::RequestData(request, inputVector, outputVector))
|
|
{
|
|
// If data-bounds are provided in the meta-data, we will report those to the
|
|
// slice view so that the slice view shows the data bounds to the user when
|
|
// setting up slices.
|
|
vtkDataObject* localData = this->CacheKeeper->GetOutputDataObject(0);
|
|
vtkGSRGeometryFilter::ExtractCachedBounds(
|
|
localData, this->Internals->OriginalDataBounds);
|
|
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool vtkGeometrySliceRepresentation::AddToView(vtkView* view)
|
|
{
|
|
vtkPVOrthographicSliceView* rview = vtkPVOrthographicSliceView::SafeDownCast(view);
|
|
if (rview && this->Mode != ALL_SLICES)
|
|
{
|
|
rview->GetRenderer(this->Mode + vtkPVOrthographicSliceView::SAGITTAL_VIEW_RENDERER)->AddActor(this->Actor);
|
|
}
|
|
else if (vtkPVRenderView* rvview = vtkPVRenderView::SafeDownCast(view))
|
|
{
|
|
rvview->GetRenderer()->AddActor(this->Internals->OutlineActor.GetPointer());
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
return this->Superclass::AddToView(view);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool vtkGeometrySliceRepresentation::RemoveFromView(vtkView* view)
|
|
{
|
|
vtkPVOrthographicSliceView* rview = vtkPVOrthographicSliceView::SafeDownCast(view);
|
|
if (rview && this->Mode != ALL_SLICES)
|
|
{
|
|
rview->GetRenderer(this->Mode + vtkPVOrthographicSliceView::SAGITTAL_VIEW_RENDERER)->RemoveActor(this->Actor);
|
|
}
|
|
else if (vtkPVRenderView* rvview = vtkPVRenderView::SafeDownCast(view))
|
|
{
|
|
rvview->GetRenderer()->RemoveActor(this->Internals->OutlineActor.GetPointer());
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
return this->Superclass::RemoveFromView(view);
|
|
}
|
|
//----------------------------------------------------------------------------
|
|
void vtkGeometrySliceRepresentation::PrintSelf(ostream& os, vtkIndent indent)
|
|
{
|
|
this->Superclass::PrintSelf(os, indent);
|
|
os << indent << "ShowOutline: " << this->ShowOutline << endl;
|
|
}
|