From: rkv Date: Fri, 30 May 2008 15:31:33 +0000 (+0000) Subject: Distribution curve visibility and filtering by scalars X-Git-Tag: TG_VISU_2008_2008-06-26~30 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=6f53d3e28e41751da1f8e548197b308e81795ca0;p=modules%2Fvisu.git Distribution curve visibility and filtering by scalars --- diff --git a/idl/VISU_Gen.idl b/idl/VISU_Gen.idl index 2497187f..d6ae2db1 100644 --- a/idl/VISU_Gen.idl +++ b/idl/VISU_Gen.idl @@ -553,6 +553,29 @@ module VISU { */ Orientation GetBarOrientation(); + // RKV : Begin + /*! + * Set the visibility of a distribution curve. + * \param theIs is used to switch on/off the visibility of a distribution curve. + */ + void SetIsDistributionVisible(in boolean theIs); + + //! Gets current visibility of a distribution curve + boolean GetIsDistributionVisible(); + + //! Gets current filtering by scalars mode + boolean IsFilteredByScalars(); + + /*! + * Sets scalar range - min and max boundaries of the scalar bar. + * \param theMin Min boundary of the scalar bar. + * \param theMax Max boundary of the scalar bar. + * \param theIsFilter if true then filter by scalars. + */ + void SetRangeAndFilter(in double theMin, in double theMax, in boolean theIsFilter); + + // RKV : End + /*! * Add group as geometry of presentation. * \param theMeshName - mesh name diff --git a/src/PIPELINE/Makefile.am b/src/PIPELINE/Makefile.am index 44925dee..c1f3441a 100644 --- a/src/PIPELINE/Makefile.am +++ b/src/PIPELINE/Makefile.am @@ -95,7 +95,8 @@ dist_libVisuPipeLine_la_SOURCES= \ VISU_SphereWidget.cxx \ VISU_WidgetCtrl.cxx \ VISU_ScalarBarCtrl.cxx \ - VISU_ScalarMapOnDeformedShapePL.cxx + VISU_ScalarMapOnDeformedShapePL.cxx \ + VISU_XYPlotActor.cxx libVisuPipeLine_la_CPPFLAGS= \ $(VTK_INCLUDES) \ diff --git a/src/PIPELINE/VISUPipeLine.cxx b/src/PIPELINE/VISUPipeLine.cxx index 2e9f12c0..dbe0955f 100644 --- a/src/PIPELINE/VISUPipeLine.cxx +++ b/src/PIPELINE/VISUPipeLine.cxx @@ -29,6 +29,7 @@ #include "VISU_IsoSurfacesPL.hxx" #include "VISU_CutPlanesPL.hxx" #include "VISU_CutLinesPL.hxx" +#include "VISU_ColoredPL.hxx" #include "VISU_DeformedShapePL.hxx" #include "VISU_VectorsPL.hxx" #include "VISU_StreamLinesPL.hxx" @@ -44,7 +45,9 @@ #include "VISU_Convertor.hxx" #include "VISU_ConvertorUtils.hxx" -typedef VISU_GaussPointsPL TPresent; +//typedef VISU_CutPlanesPL TPresent; +//typedef VISU_ScalarMapPL TPresent; +typedef VISU_CutLinesPL TPresent; #include #include @@ -60,10 +63,88 @@ typedef VISU_GaussPointsPL TPresent; #include +//RKV:Begin +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/*#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +*/ +//RKV:End + static int isOnlyMesh = false; //#define _DEBUG_ID_MAPPING_ +//RKV:Begin +/* +vtkActor* barChartActor() +{ + int numTuples = 6; + + vtkFloatArray *bitter = vtkFloatArray::New(); + bitter->SetNumberOfTuples(numTuples); + + for (int i=0; iSetTuple1(i, vtkMath::Random(7,100)); + } + + vtkDataObject *dobj = vtkDataObject::New(); + dobj->GetFieldData()->AddArray(bitter); + + vtkBarChartActor *actor = vtkBarChartActor::New(); + actor->SetInput(dobj); + actor->SetTitle("Bar Chart"); + actor->GetPositionCoordinate()->SetValue(0.05,0.05,0.0); + actor->GetPosition2Coordinate()->SetValue(0.95,0.85,0.0); + actor->GetProperty()->SetColor(1,1,1); + actor->GetLegendActor()->SetNumberOfEntries(numTuples); + for (int i=0; iSetBarColor(i,red,green,blue); + } + actor->SetBarLabel(0,"oil"); + actor->SetBarLabel(1,"gas"); + actor->SetBarLabel(2,"water"); + actor->SetBarLabel(3,"snake oil"); + actor->SetBarLabel(4,"tequila"); + actor->SetBarLabel(5,"beer"); + actor->LegendVisibilityOn(); + + // Set text colors (same as actor for backward compat with test) + actor->GetTitleTextProperty()->SetColor(1,1,0); + actor->GetLabelTextProperty()->SetColor(1,0,0); + return actor; +} +*/ +//RKV:End //---------------------------------------------------------------------------- template VISU_ColoredPL* @@ -140,6 +221,13 @@ CreateColoredPL(VISU_Convertor* theConvertor, theTimeStampNumber); aPresent->SetUnstructuredGridIDMapper(anUnstructuredGridIDMapper); + vtkFloatingPointType aRange[] = { 4, 5 }; +cout << "before filter limits set" << endl; + vtkObject::GlobalWarningDisplayOn(); + aPresent->DebugOn(); + aPresent->SetScalarRange(aRange, true); +cout << "after filter set" << endl; + //aPresent->ClearGeometry(); //{ // VISU::PUnstructuredGridIDMapper anIDMapper = @@ -160,6 +248,7 @@ CreateColoredPL(VISU_Convertor* theConvertor, // aPresent->AddGeometry(anIDMapper->GetOutput()); //} aPresent->Update(); +cout << "after update" << endl; return aPresent; } @@ -230,13 +319,13 @@ main(int argc, char** argv) // continue; const std::string& aFieldName = aFieldMapIter->first; const VISU::TValField& aValField = aField->myValField; - VISU::TValField::const_iterator aValFieldIter = aValField.begin(); - if(aValFieldIter == aValField.end()) return 0; + VISU::TValField::const_reverse_iterator aValFieldIter = aValField.rbegin(); + if(aValFieldIter == aValField.rend()) return 0; int aTimeStamp = aValFieldIter->first; vtkActor* anActor = vtkActor::New(); VISU_ColoredPL* aPresent = NULL; - if(anEntity != VISU::NODE_ENTITY){ + if(anEntity == VISU::NODE_ENTITY){ aPresent = CreateColoredPL(aConvertor, aMeshName, anEntity, @@ -289,11 +378,156 @@ main(int argc, char** argv) aMapper->Delete(); } + + + + +//RKV:Begin + vtkLookupTable* lut = vtkLookupTable::New(); + int nbColors = aPresent->GetNbColors(); + lut->SetNumberOfTableValues(nbColors); + vtkDataArray* dataArr; + if(VISU::IsDataOnCells(aPresent->GetInput())) { + dataArr = aPresent->GetInput()->GetCellData()->GetScalars(); + } else { + dataArr = aPresent->GetInput()->GetPointData()->GetScalars(); + } + vtkFloatingPointType aRange[2]; + dataArr->GetRange(aRange); + MSG(true, "Range[0]: "<SetTableRange(aRange); + lut->Build(); + MSG(true, "1\n"); + vtkIntArray* distr = vtkIntArray::New(); + distr->SetNumberOfValues(nbColors); + MSG(true, "Number of colors: "<FillComponent(0, 0.); + MSG(true, "2\n"); + int aNbVals = dataArr->GetNumberOfTuples(); + int idx = 0, cnt = 0; + + MSG(true, "3\n"); + for(vtkIdType aValId = 0; aValId < aNbVals; aValId++){ +// MSG(true, "Value: "<< *(dataArr->GetTuple(aValId))); + idx = lut->GetIndex(*(dataArr->GetTuple(aValId))); +// MSG(true, "Value index "<GetValue(idx); + distr->SetValue(idx, cnt + 1); + } + MSG(true, "4\n"); + distr->Modified(); + double range[2]; + distr->GetRange(range); + MSG(true, "DistrRange[0]: " << range[0]); + MSG(true, "DistrRange[1]: " << range[1]); + MSG(true, "5\n"); +// vtkPoints* points = vtkPoints::New(); +// aNbVals = distr->GetNumberOfTuples(); +// points->Allocate(aNbVals); +// double x[3] = {0., 0., 0.}; +/* for(vtkIdType aValId = 0; aValId < aNbVals; aValId++){ + x[0] = aValId; + points->InsertPoint(aValId, x); +*/// MSG(true, "Inserted point "<GetValue(aValId)); +// } +// points->SetData(distr); + +/* vtkPointSet* pset = vtkPolyData::New(); + pset->SetPoints(points); + pset->GetPointData()->SetScalars(distr); +*/ + vtkDataObject *dobj = vtkDataObject::New(); + dobj->GetFieldData()->AddArray(distr); + + vtkXYPlotActor* xyplot = vtkXYPlotActor::New(); +// xyplot->AddInput(pset); + xyplot->AddDataObjectInput(dobj); + xyplot->GetPositionCoordinate()->SetValue(0.0, 0.67, 0); + xyplot->GetPosition2Coordinate()->SetValue(1.0, 0.33, 0); // #relative to Position + xyplot->SetXValuesToIndex(); +// xyplot->SetXValuesToNormalizedArcLength(); +// xyplot->SetXValuesToArcLength(); +// xyplot->SetNumberOfXLabels(0); + xyplot->SetTitle(""); + xyplot->SetXTitle(""); + xyplot->SetYTitle("Distribution"); +// xyplot->ReverseYAxisOn(); +// xyplot->SetDataObjectPlotModeToRows(); + xyplot->SetLabelFormat("%.0f"); + xyplot->SetXRange(0, nbColors-1); + xyplot->SetYRange(range[0], range[1]); +/* int ny = floor(fabs(range[1] - range[0])); + MSG(true, "ny = "<SetNumberOfYLabels(ny); + MSG(true, "nbYLabels = "<GetNumberOfYLabels()); + } +*/ xyplot->GetProperty()->SetColor(1, 1, 1); + xyplot->GetProperty()->SetLineWidth(2); + xyplot->GetProperty()->SetDisplayLocationToForeground(); +/* vtkMatrix4x4 *m = vtkMatrix4x4::New(); + MSG(true, "5.1\n"); + m->Zero(); + MSG(true, "5.2\n"); + m->SetElement(0, 1, 1); + m->SetElement(1, 0, -1); + m->SetElement(2, 2, 1); + m->SetElement(3, 3, 1); + MSG(true, "5.3\n"); + xyplot->PokeMatrix(m); +*/ //# Set text prop color (same color for backward compat with test) + //# Assign same object to all text props + vtkTextProperty* tprop; + tprop = xyplot->GetTitleTextProperty(); + tprop->SetColor(xyplot->GetProperty()->GetColor()); + xyplot->SetAxisTitleTextProperty(tprop); + xyplot->SetAxisLabelTextProperty(tprop); + +//RKV:End + + + MSG(true, "6\n"); + +/*{ + vtkXYPlotWidget* aWidget = vtkXYPlotWidget::New(); + aWidget->SetInteractor( anInteractor ); + aWidget->SetXYPlotActor( xyplot ); + aWidget->SetEnabled( 1 ); +}*/ + + + vtkObject::GlobalWarningDisplayOn(); + VISU_ScalarBarActor * aScalarBar = VISU_ScalarBarActor::New(); + //vtkScalarBarActor * aScalarBar = vtkScalarBarActor::New(); + aPresent->SetNbColors(5); + aPresent->DebugOn(); + aPresent->Update(); aScalarBar->SetLookupTable(aPresent->GetBarTable()); - + aScalarBar->DebugOn(); + aScalarBar->SetDistribution(aPresent->GetDistribution()); + aScalarBar->DistributionVisibilityOn(); +// aScalarBar->SetOrientationToHorizontal(); +// aScalarBar->GetPositionCoordinate()->SetValue(.1, .6, 0); +// aScalarBar->GetPosition2Coordinate()->SetValue(.8, .3, 0); + +/*{ + vtkScalarBarWidget* aWidget = vtkScalarBarWidget::New(); + aWidget->SetInteractor( anInteractor ); + aWidget->SetScalarBarActor( aScalarBar ); + aWidget->SetEnabled( 1 ); +} +*/ aRenderer->AddActor(anActor); +// aRenderer->AddActor2D(xyplot); //RKV aRenderer->AddActor2D(aScalarBar); + + //aRenderer->AddActor2D(barChartActor()); //RKV aWindow->Render(); aRenderer->ResetCamera(); diff --git a/src/PIPELINE/VISU_ColoredPL.cxx b/src/PIPELINE/VISU_ColoredPL.cxx index dc254482..1190f67f 100644 --- a/src/PIPELINE/VISU_ColoredPL.cxx +++ b/src/PIPELINE/VISU_ColoredPL.cxx @@ -44,6 +44,7 @@ VISU_ColoredPL myFieldTransform(VISU_FieldTransform::New()), myThreshold(vtkThreshold::New()), // RKV myPassFilter(vtkPassThroughFilter::New()), // RKV + myDistribution(vtkDoubleArray::New()), // RKV myIsFiltered(false) // RKV { myMapperTable->Delete(); @@ -61,6 +62,7 @@ VISU_ColoredPL myThreshold->AllScalarsOn(); // RKV myThreshold->Delete(); // RKV myPassFilter->Delete(); // RKV + myDistribution->Delete(); // RKV } @@ -86,6 +88,7 @@ VISU_ColoredPL aTime = std::max(aTime, myThreshold->GetMTime()); } aTime = std::max(aTime, myPassFilter->GetMTime()); + aTime = std::max(aTime, myDistribution->GetMTime()); // RKV : End return aTime; @@ -207,6 +210,67 @@ VISU_ColoredPL myPassFilter->SetInput(myFieldTransform->GetOutput()); } } + +//---------------------------------------------------------------------------- +vtkDoubleArray* +VISU_ColoredPL +::GetDistribution() +{ + unsigned long int aTime = this->GetMTime(); + // If modified then update the distribution array + if (aTime > myDistribution->GetMTime()) { + // Set number of colors for the distribution + int nbColors = this->GetNbColors(); + this->myDistribution->SetNumberOfValues(nbColors); + // Initialize numbers of colored cells with zero + this->myDistribution->FillComponent(0, 0); + // Create a lookup table to compute a color of a cell + vtkLookupTable* lut = GetMapperTable(); + // Get scalar values from the input data to calculate their distribution within cells + vtkDataArray* dataArr; + // Dtermine where we have to take scalars from: cells data or points data. + if(VISU::IsDataOnCells(this->GetOutput())) { + dataArr = this->GetOutput()->GetCellData()->GetScalars(); + } else { + dataArr = this->GetOutput()->GetPointData()->GetScalars(); + } + // If scalars data array is not defined then create an empty one to avoid exceptions + if (dataArr == NULL) { + dataArr = vtkDoubleArray::New(); + } + + // Get range of scalars values +// vtkFloatingPointType aRange[2]; +// dataArr->GetRange(aRange); + + // Build the lookup table with the found range + // Get number of scalar values + int aNbVals = dataArr->GetNumberOfTuples(); + if (aNbVals > 0) { + // Count the number of scalar values for each color in the input data + int idx = 0; + double cnt = 0; + // For each scalar value + for(vtkIdType aValId = 0; aValId < aNbVals; aValId++){ + // Find the color index for this scalar value + idx = lut->GetIndex(*(dataArr->GetTuple(aValId))); + // Increment the distribution value for this color index + cnt = this->myDistribution->GetValue(idx); + this->myDistribution->SetValue(idx, cnt + 1); + } + // Compute relative values when 1 is according to the total number of scalar values + for(vtkIdType aValId = 0; aValId < nbColors; aValId++){ + cnt = this->myDistribution->GetValue(aValId); + this->myDistribution->SetValue(aValId, cnt / aNbVals); + } + } + this->myDistribution->Modified(); + + } + + return myDistribution; +} +//---------------------------------------------------------------------------- // RKV : End //---------------------------------------------------------------------------- diff --git a/src/PIPELINE/VISU_ColoredPL.hxx b/src/PIPELINE/VISU_ColoredPL.hxx index d66ba185..fe65499d 100644 --- a/src/PIPELINE/VISU_ColoredPL.hxx +++ b/src/PIPELINE/VISU_ColoredPL.hxx @@ -33,6 +33,7 @@ #include #include // RKV #include // RKV +#include // RKV class VISU_Extractor; class VISU_FieldTransform; @@ -85,6 +86,8 @@ public: // RKV : Begin //---------------------------------------------------------------------------- bool IsFiltered() {return myIsFiltered;}; + + vtkDoubleArray* GetDistribution(); // RKV // RKV : End //---------------------------------------------------------------------------- public: @@ -199,6 +202,7 @@ private: vtkSmartPointer myFieldTransform; vtkSmartPointer myThreshold; // RKV vtkSmartPointer myPassFilter; // RKV + vtkSmartPointer myDistribution; // RKV bool myIsFiltered; // RKV }; diff --git a/src/PIPELINE/VISU_ScalarBarActor.cxx b/src/PIPELINE/VISU_ScalarBarActor.cxx index 9adbc387..eba252be 100644 --- a/src/PIPELINE/VISU_ScalarBarActor.cxx +++ b/src/PIPELINE/VISU_ScalarBarActor.cxx @@ -38,6 +38,8 @@ #include #include #include +#include // RKV +#include // RKV using namespace std; @@ -109,6 +111,32 @@ VISU_ScalarBarActor::VISU_ScalarBarActor() this->TitleRatioHeight = 0; this->LabelRatioHeight = 0; this->BarRatioHeight = 0; + + // RKV : Begin + this->Distribution = vtkDoubleArray::New(); + this->DistributionObj = vtkDataObject::New(); + this->DistributionActor = VISU_XYPlotActor::New(); + this->DistributionActor->SetTitle(""); + this->DistributionActor->SetXTitle(""); + this->DistributionActor->SetYTitle(""); + this->DistributionActor->GetXAxisActor2D()->LabelVisibilityOff(); + this->DistributionActor->GetXAxisActor2D()->TitleVisibilityOff(); + this->DistributionActor->GetXAxisActor2D()->TickVisibilityOff(); +// this->DistributionActor->GetXAxisActor2D()->SetFontFactor(0.); + this->DistributionActor->SetNumberOfYLabels(1); +// this->DistributionActor->SetNumberOfXLabels(2); + this->DistributionActor->GetXAxisActor2D()->AdjustLabelsOff(); + this->DistributionActor->GetYAxisActor2D()->AdjustLabelsOff(); + this->DistributionActor->LegendOff(); + this->DistributionActor->SetLabelFormat("%4.3f"); + this->DistributionActor->SetXValuesToIndex(); +// this->DistributionActor->GetPositionCoordinate()->SetValue(0.0, 0.67, 0); +// this->DistributionActor->GetPosition2Coordinate()->SetValue(1.0, 0.33, 0); // #relative to Position + this->DistributionActor->GetPositionCoordinate()-> + SetReferenceCoordinate(this->PositionCoordinate); + this->DistributionVisibilityOff(); // Don't show the distribution curve by default + + // RKV : End } void VISU_ScalarBarActor::ReleaseGraphicsResources(vtkWindow *win) @@ -122,6 +150,7 @@ void VISU_ScalarBarActor::ReleaseGraphicsResources(vtkWindow *win) } } this->ScalarBarActor->ReleaseGraphicsResources(win); + this->DistributionActor->ReleaseGraphicsResources(win); // RKV } VISU_ScalarBarActor::~VISU_ScalarBarActor() @@ -146,10 +175,16 @@ VISU_ScalarBarActor::~VISU_ScalarBarActor() delete [] this->TextActors; } + // RKV : Begin + this->DistributionActor->Delete(); + this->DistributionObj->Delete(); + this->SetDistribution(NULL); + // RKV : End + this->ScalarBar->Delete(); this->ScalarBarMapper->Delete(); this->ScalarBarActor->Delete(); - + if (this->Title) { delete [] this->Title; @@ -172,6 +207,10 @@ int VISU_ScalarBarActor::RenderOverlay(vtkViewport *viewport) renderedSomething += this->TitleActor->RenderOverlay(viewport); } this->ScalarBarActor->RenderOverlay(viewport); + // RKV : Begin + if (this->DistributionVisibility) + this->DistributionActor->RenderOverlay(viewport); + // RKV : End if( this->TextActors == NULL) { vtkWarningMacro(<<"Need a mapper to render a scalar bar"); @@ -238,11 +277,19 @@ int VISU_ScalarBarActor::RenderOpaqueGeometry(vtkViewport *viewport) } // Check to see whether we have to rebuild everything + // RKV : Begin if (positionsHaveChanged || this->GetMTime() > this->BuildTime || this->LookupTable->GetMTime() > this->BuildTime || this->LabelTextProperty->GetMTime() > this->BuildTime || - this->TitleTextProperty->GetMTime() > this->BuildTime) + this->TitleTextProperty->GetMTime() > this->BuildTime || + this->Distribution->GetMTime() > this->BuildTime) + // RKV : End +/* RKV if (positionsHaveChanged || + this->GetMTime() > this->BuildTime || + this->LookupTable->GetMTime() > this->BuildTime || + this->LabelTextProperty->GetMTime() > this->BuildTime || + this->TitleTextProperty->GetMTime() > this->BuildTime)*/ { // Delete previously constructed objects @@ -276,6 +323,32 @@ int VISU_ScalarBarActor::RenderOpaqueGeometry(vtkViewport *viewport) colors->SetNumberOfComponents(3); colors->SetNumberOfTuples(numColors); +// RKV : Begin + // If the distribution is changed then recalculate the total + if (this->Distribution->GetMTime() > this->BuildTime) { + int aNbVals = this->Distribution->GetNumberOfTuples(); + double range[2]; + this->Distribution->GetRange(range); + this->DistributionActor->SetYRange(0, range[1]); +/* int total = 0; + for(vtkIdType aValId = 0; aValId < aNbVals; aValId++){ + total += this->Distribution->GetValue(aValId); + } + this->DistributionActor->SetYRange(0, total); +*/ + } + + this->DistributionActor->SetProperty(this->GetProperty()); + this->DistributionActor->GetProperty()->SetColor(1, 1, 1); + this->DistributionActor->GetProperty()->SetLineWidth(2); + this->DistributionActor->GetProperty()->SetDisplayLocationToForeground(); + vtkTextProperty* tprop; + tprop = this->DistributionActor->GetTitleTextProperty(); + tprop->SetColor(this->DistributionActor->GetProperty()->GetColor()); +// this->DistributionActor->SetAxisTitleTextProperty(tprop); +// this->DistributionActor->SetAxisLabelTextProperty(tprop); + +// RKV : End this->ScalarBarActor->SetProperty(this->GetProperty()); this->ScalarBar->Initialize(); this->ScalarBar->SetPoints(pts); @@ -394,6 +467,7 @@ int VISU_ScalarBarActor::RenderOpaqueGeometry(vtkViewport *viewport) this->TextActors[i]->SetPosition(barWidth+3, val - sizeTextData[1]/2); } + } else { @@ -405,7 +479,11 @@ int VISU_ScalarBarActor::RenderOpaqueGeometry(vtkViewport *viewport) val = (vtkFloatingPointType)i/(this->NumberOfLabels-1) * barWidth; this->TextActors[i]->SetPosition(val, barHeight + 0.05*size[1]); } + } + + // Compute the position of the distribution curve + this->PlaceDistribution(viewport, barWidth, barHeight); // RKV this->BuildTime.Modified(); } @@ -416,6 +494,10 @@ int VISU_ScalarBarActor::RenderOpaqueGeometry(vtkViewport *viewport) renderedSomething += this->TitleActor->RenderOpaqueGeometry(viewport); } this->ScalarBarActor->RenderOpaqueGeometry(viewport); + // RKV : Begin + if (this->DistributionVisibility) + this->DistributionActor->RenderOpaqueGeometry(viewport); + // RKV : End for (i=0; iNumberOfLabels; i++) { renderedSomething += this->TextActors[i]->RenderOpaqueGeometry(viewport); @@ -619,6 +701,58 @@ void VISU_ScalarBarActor::SizeTitle(int *titleSize, int *size, this->TitleMapper->GetSize(viewport, titleSize); } +// RKV : Begin +void VISU_ScalarBarActor::SetDistributionVisibility(int v) +{ + this->DistributionVisibility = v; + if (v) { + this->DistributionActor->VisibilityOn(); + } else { + this->DistributionActor->VisibilityOff(); + } +} + +void VISU_ScalarBarActor::SetDistribution(vtkDoubleArray *distr) +{ + this->Distribution = distr; + if (distr == NULL) return; + + this->DistributionObj->Initialize(); + this->DistributionObj->GetFieldData()->AddArray(this->Distribution); + this->DistributionActor->AddDataObjectInput(this->DistributionObj); + // Set ranges of axes for the distribution curve + this->DistributionActor->SetXRange(0, this->Distribution->GetNumberOfTuples()-1); + double range[2]; + this->Distribution->GetRange(range); + int aNbVals = this->Distribution->GetNumberOfTuples(); +// int total = 0; + if (this->GetDebug()) { + for(vtkIdType aValId = 0; aValId < aNbVals; aValId++){ +// if (this->GetDebug()) { + if (this->Distribution->GetValue(aValId) > 0) + vtkDebugMacro(<< "D(" << aValId << ") = " << this->Distribution->GetValue(aValId)); +// } +// total += this->Distribution->GetValue(aValId); + } + } +// this->DistributionActor->SetYRange(0, total); + this->DistributionActor->SetYRange(0, range[1]); + vtkDebugMacro(<< "max X = " << this->Distribution->GetNumberOfTuples()); + vtkDebugMacro(<< "Y = (" << range[0] << ", " << range[1] << ")"); +// vtkDebugMacro(<< "total = " << total); +} + +void VISU_ScalarBarActor::DebugOn() { + this->DistributionActor->DebugOn(); + Superclass::DebugOn(); +} + +void VISU_ScalarBarActor::DebugOff() { + this->DistributionActor->DebugOff(); + Superclass::DebugOff(); +} +// RKV : End + void VISU_ScalarBarActor::SetRatios(int titleRatioWidth, int titleRatioHeight, int labelRatioWidth, int labelRatioHeight, int barRatioWidth, int barRatioHeight) @@ -694,3 +828,91 @@ void VISU_ScalarBarActor::SizeBar(int& barSizeWidth, int& barSizeHeight, int *si else barSizeHeight = (int)(0.01*BarRatioHeight*size[1]); } +// RKV : Begin +//------------------------------------------------------------------------------ +/** Place the distribution plot actor in the viewport according to the + * scalar bar location and orientation */ +void VISU_ScalarBarActor::PlaceDistribution(vtkViewport *viewport, const int barWidth, const int barHeight) { + vtkDebugMacro(<< "barOrigin[0]=" << this->LastOrigin[0] << "; barOrigin[1]=" << this->LastOrigin[1]); + // Detect the side of the viewport where the curve should be placed by the bar origin. + double u = (double)(this->LastOrigin[0]), v = (double)(this->LastOrigin[1]), z=0; + viewport->ViewportToNormalizedViewport(u, v); + + if ( this->Orientation == VTK_ORIENT_VERTICAL ) { + // Position the distribution curve vertically + if (u > 0.5) { + // X - UP, Y - TO THE LEFT + this->DistributionActor->SetPlotLocation(VISU_XYPLOT_RIGHT); + // Curve to be placed on the left side of the bar + vtkDebugMacro(<< "Curve to be placed on the left side of the bar"); + // relative to the bar origin + u = 0; + v = 0; + viewport->ViewportToNormalizedViewport(u, v); + vtkDebugMacro(<< "u=" << u << "; v=" << v); + this->DistributionActor->GetPositionCoordinate()->SetValue(u, v, 0); + // relative to Position + u = - barWidth; + v = barHeight; + viewport->ViewportToNormalizedViewport(u, v); + vtkDebugMacro("u2=" << u << "; v2=" << v); + this->DistributionActor->GetPosition2Coordinate()->SetValue(u, v, 0); + } else { + // X - UP, Y - TO THE RIGHT + this->DistributionActor->SetPlotLocation(VISU_XYPLOT_LEFT); + // Curve to be placed on the right side of the bar + vtkDebugMacro(<< "Curve to be placed on the right side of the bar"); + // relative to the bar origin + u = barWidth; + v = 0; + viewport->ViewportToNormalizedViewport(u, v); + vtkDebugMacro(<< "u=" << u << "; v=" << v); + this->DistributionActor->GetPositionCoordinate()->SetValue(u, v, 0); + // relative to Position + u = barWidth; + v = barHeight; + viewport->ViewportToNormalizedViewport(u, v); + vtkDebugMacro("u2=" << u << "; v2=" << v); + this->DistributionActor->GetPosition2Coordinate()->SetValue(u, v, 0); + } + } else { + // Position the distribution curve horizontally + if (v > 0.5) { + // X - TO THE LEFT, Y - DOWN + this->DistributionActor->SetPlotLocation(VISU_XYPLOT_TOP); + // Curve to be placed below the bar + vtkDebugMacro(<< "Curve to be placed below the bar"); + // relative to the bar origin + u = 0; + v = 0; + viewport->ViewportToNormalizedViewport(u, v); + vtkDebugMacro(<< "u=" << u << "; v=" << v); + this->DistributionActor->GetPositionCoordinate()->SetValue(u, v, 0); + // relative to Position + u = barWidth; + v = - barHeight; + viewport->ViewportToNormalizedViewport(u, v); + vtkDebugMacro("u2=" << u << "; v2=" << v); + this->DistributionActor->GetPosition2Coordinate()->SetValue(u, v, 0); + } else { + // X - TO THE RIGHT, Y - UP + this->DistributionActor->SetPlotLocation(VISU_XYPLOT_BOTTOM); + // Curve to be placed on the top of the bar + vtkDebugMacro(<< "Curve to be placed on the top of the bar"); + // relative to the bar origin + u = 0; + v = barHeight; + viewport->ViewportToNormalizedViewport(u, v); + vtkDebugMacro(<< "u=" << u << "; v=" << v); + this->DistributionActor->GetPositionCoordinate()->SetValue(u, v, 0); + // relative to Position + u = barWidth; + v = barHeight; + viewport->ViewportToNormalizedViewport(u, v); + vtkDebugMacro("u2=" << u << "; v2=" << v); + this->DistributionActor->GetPosition2Coordinate()->SetValue(u, v, 0); + } + } +} +// RKV : End + diff --git a/src/PIPELINE/VISU_ScalarBarActor.hxx b/src/PIPELINE/VISU_ScalarBarActor.hxx index 3252e6e8..7f217381 100644 --- a/src/PIPELINE/VISU_ScalarBarActor.hxx +++ b/src/PIPELINE/VISU_ScalarBarActor.hxx @@ -29,8 +29,10 @@ #include "VISUPipeline.hxx" #include "VISU_LookupTable.hxx" +#include "VISU_XYPlotActor.hxx" #include +#include // RKV class vtkPolyData; class vtkPolyDataMapper2D; @@ -106,6 +108,24 @@ public: // Set/Get the labels text property. virtual void SetLabelTextProperty(vtkTextProperty *p); vtkGetObjectMacro(LabelTextProperty,vtkTextProperty); + +// RKV : Begin + // Description: + // Set/Get the values distribution array + virtual void SetDistribution(vtkDoubleArray *d); + vtkGetObjectMacro(Distribution,vtkDoubleArray); + + // Description: + // Set/Get the flag of distribution plot visibility + void SetDistributionVisibility(int v); + vtkGetMacro(DistributionVisibility, int); + void DistributionVisibilityOn() + {this->SetDistributionVisibility(1);}; + void DistributionVisibilityOff() {this->SetDistributionVisibility(0);}; + + void DebugOn(); + void DebugOff(); +// RKV : End // Description: // Set/Get the scalar bar dimention properties in persents. @@ -139,6 +159,13 @@ protected: VISU_LookupTable *LookupTable; vtkTextProperty *TitleTextProperty; vtkTextProperty *LabelTextProperty; + + /** Array for keeping the distribution of colors within cells. + * For each color index the appropriate element of the array contains + * a number of cells for this color.*/ + vtkDoubleArray *Distribution; // RKV + /** Visibility flag for the distribution plot */ + int DistributionVisibility; // RKV int MaximumNumberOfColors; int NumberOfLabels; @@ -167,6 +194,9 @@ private: vtkPolyDataMapper2D *ScalarBarMapper; vtkActor2D *ScalarBarActor; + vtkDataObject *DistributionObj; // RKV + VISU_XYPlotActor *DistributionActor; // RKV + vtkTimeStamp BuildTime; int LastSize[2]; int LastOrigin[2]; @@ -175,6 +205,10 @@ private: void SizeBar(int& barSizeWidth, int& barSizeHeight, int *size, vtkViewport *viewport, vtkFloatingPointType *range); + + /** Place the distribution plot actor in the viewport according to the + * scalar bar location and orientation */ + void PlaceDistribution(vtkViewport *viewport, const int barWidth, const int barHeight); private: VISU_ScalarBarActor(const VISU_ScalarBarActor&); // Not implemented. diff --git a/src/PIPELINE/VISU_XYPlotActor.cxx b/src/PIPELINE/VISU_XYPlotActor.cxx new file mode 100644 index 00000000..e7f912a3 --- /dev/null +++ b/src/PIPELINE/VISU_XYPlotActor.cxx @@ -0,0 +1,2271 @@ +// VISU OBJECT : interactive object for VISU entities implementation +// +// Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// +// +// +// File: VISU_XYPlotActor.cxx +// Author: Roman KOZLOV +// Module : VISU + +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile$ + + 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 "VISU_XYPlotActor.hxx" + +#include "vtkAppendPolyData.h" +#include "vtkAxisActor2D.h" +#include "vtkCellArray.h" +#include "vtkDataObjectCollection.h" +#include "vtkDataSetCollection.h" +#include "vtkFieldData.h" +#include "vtkDoubleArray.h" +#include "vtkGlyph2D.h" +#include "vtkGlyphSource2D.h" +#include "vtkIntArray.h" +#include "vtkLegendBoxActor.h" +#include "vtkMath.h" +#include "vtkObjectFactory.h" +#include "vtkPlane.h" +#include "vtkPlanes.h" +#include "vtkPointData.h" +#include "vtkPolyData.h" +#include "vtkPolyDataMapper2D.h" +#include "vtkProperty2D.h" +#include "vtkTextMapper.h" +#include "vtkTextProperty.h" +#include "vtkViewport.h" +#include "vtkTransformPolyDataFilter.h" // RKV +#include "vtkTransform.h" // RKV + +#define VTK_MAX_PLOTS 50 + +using namespace std; + +vtkCxxRevisionMacro(VISU_XYPlotActor, "$Revision$"); +vtkStandardNewMacro(VISU_XYPlotActor); + +vtkCxxSetObjectMacro(VISU_XYPlotActor,TitleTextProperty,vtkTextProperty); +vtkCxxSetObjectMacro(VISU_XYPlotActor,AxisLabelTextProperty,vtkTextProperty); +vtkCxxSetObjectMacro(VISU_XYPlotActor,AxisTitleTextProperty,vtkTextProperty); + +//---------------------------------------------------------------------------- +// Instantiate object +VISU_XYPlotActor::VISU_XYPlotActor() +{ + this->PositionCoordinate->SetCoordinateSystemToNormalizedViewport(); + this->PositionCoordinate->SetValue(0.25,0.25); + this->Position2Coordinate->SetValue(0.5, 0.5); + + this->InputList = vtkDataSetCollection::New(); + this->SelectedInputScalars = NULL; + this->SelectedInputScalarsComponent = vtkIntArray::New(); + this->DataObjectInputList = vtkDataObjectCollection::New(); + + this->Title = NULL; + this->XTitle = new char[7]; + sprintf(this->XTitle,"%s","X Axis"); + this->YTitle = new char[7]; + sprintf(this->YTitle,"%s","Y Axis"); + + this->XValues = VTK_XYPLOT_INDEX; + this->PlotLocation = VISU_XYPLOT_BOTTOM; // RKV + + this->NumberOfXLabels = 5; + this->NumberOfYLabels = 5; + + this->TitleTextProperty = vtkTextProperty::New(); + this->TitleTextProperty->SetBold(1); + this->TitleTextProperty->SetItalic(1); + this->TitleTextProperty->SetShadow(1); + this->TitleTextProperty->SetFontFamilyToArial(); + + this->AxisLabelTextProperty = vtkTextProperty::New(); + this->AxisLabelTextProperty->ShallowCopy(this->TitleTextProperty); + + this->AxisTitleTextProperty = vtkTextProperty::New(); + this->AxisTitleTextProperty->ShallowCopy(this->AxisLabelTextProperty); + + this->LabelFormat = new char[8]; + sprintf(this->LabelFormat,"%s","%-#6.3g"); + + this->Logx = 0; + + this->XRange[0] = 0.0; + this->XRange[1] = 0.0; + this->YRange[0] = 0.0; + this->YRange[1] = 0.0; + + this->Border = 5; + this->PlotLines = 1; + this->PlotPoints = 0; + this->PlotCurveLines = 0; + this->PlotCurvePoints = 0; + this->ExchangeAxes = 0; + this->ReverseXAxis = 0; + this->ReverseYAxis = 0; + + this->TitleMapper = vtkTextMapper::New(); + this->TitleActor = vtkActor2D::New(); + this->TitleActor->SetMapper(this->TitleMapper); + this->TitleActor->GetPositionCoordinate()->SetCoordinateSystemToViewport(); + + this->XAxis = vtkAxisActor2D::New(); + this->XAxis->GetPositionCoordinate()->SetCoordinateSystemToViewport(); + this->XAxis->GetPosition2Coordinate()->SetCoordinateSystemToViewport(); + this->XAxis->SetProperty(this->GetProperty()); + + this->YAxis = vtkAxisActor2D::New(); + this->YAxis->GetPositionCoordinate()->SetCoordinateSystemToViewport(); + this->YAxis->GetPosition2Coordinate()->SetCoordinateSystemToViewport(); + this->YAxis->SetProperty(this->GetProperty()); + + this->NumberOfInputs = 0; + this->PlotData = NULL; + this->PlotGlyph = NULL; + this->PlotAppend = NULL; + this->PlotTransform = NULL; // RKV + this->PlotMapper = NULL; + this->PlotActor = NULL; + + this->ViewportCoordinate[0] = 0.0; + this->ViewportCoordinate[1] = 0.0; + this->PlotCoordinate[0] = 0.0; + this->PlotCoordinate[1] = 0.0; + + this->DataObjectPlotMode = VTK_XYPLOT_COLUMN; + this->XComponent = vtkIntArray::New(); + this->XComponent->SetNumberOfValues(VTK_MAX_PLOTS); + this->YComponent = vtkIntArray::New(); + this->YComponent->SetNumberOfValues(VTK_MAX_PLOTS); + + this->LinesOn = vtkIntArray::New(); + this->LinesOn->SetNumberOfValues(VTK_MAX_PLOTS); + this->PointsOn = vtkIntArray::New(); + this->PointsOn->SetNumberOfValues(VTK_MAX_PLOTS); + for (int i=0; iXComponent->SetValue(i,0); + this->YComponent->SetValue(i,0); + this->LinesOn->SetValue(i,this->PlotLines); + this->PointsOn->SetValue(i,this->PlotPoints); + } + + this->Legend = 0; + this->LegendPosition[0] = 0.85; + this->LegendPosition[1] = 0.75; + this->LegendPosition2[0] = 0.15; + this->LegendPosition2[1] = 0.20; + this->LegendActor = vtkLegendBoxActor::New(); + this->LegendActor->GetPositionCoordinate()->SetCoordinateSystemToViewport(); + this->LegendActor->GetPosition2Coordinate()->SetCoordinateSystemToViewport(); + this->LegendActor->GetPosition2Coordinate()->SetReferenceCoordinate(NULL); + this->LegendActor->BorderOff(); + this->LegendActor->SetNumberOfEntries(VTK_MAX_PLOTS); //initial allocation + this->GlyphSource = vtkGlyphSource2D::New(); + this->GlyphSource->SetGlyphTypeToNone(); + this->GlyphSource->DashOn(); + this->GlyphSource->FilledOff(); + this->GlyphSize = 0.020; + + this->ClipPlanes = vtkPlanes::New(); + vtkPoints *pts = vtkPoints::New(); + pts->SetNumberOfPoints(4); + this->ClipPlanes->SetPoints(pts); + pts->Delete(); + vtkDoubleArray *n = vtkDoubleArray::New(); + n->SetNumberOfComponents(3); + n->SetNumberOfTuples(4); + this->ClipPlanes->SetNormals(n); + n->Delete(); + + this->CachedSize[0] = 0; + this->CachedSize[1] = 0; +} + +//---------------------------------------------------------------------------- +VISU_XYPlotActor::~VISU_XYPlotActor() +{ + // Get rid of the list of array names. + int num = this->InputList->GetNumberOfItems(); + if (this->SelectedInputScalars) + { + for (int i = 0; i < num; ++i) + { + if (this->SelectedInputScalars[i]) + { + delete [] this->SelectedInputScalars[i]; + this->SelectedInputScalars[i] = NULL; + } + } + delete [] this->SelectedInputScalars; + this->SelectedInputScalars = NULL; + } + this->SelectedInputScalarsComponent->Delete(); + this->SelectedInputScalarsComponent = NULL; + + // Now we can get rid of the inputs. + this->InputList->Delete(); + this->InputList = NULL; + + this->DataObjectInputList->Delete(); + this->DataObjectInputList = NULL; + + this->TitleMapper->Delete(); + this->TitleMapper = NULL; + this->TitleActor->Delete(); + this->TitleActor = NULL; + + this->SetTitle(0); + this->SetXTitle(0); + this->SetYTitle(0); + this->SetLabelFormat(0); + + this->XAxis->Delete(); + this->YAxis->Delete(); + + this->InitializeEntries(); + + this->LegendActor->Delete(); + this->GlyphSource->Delete(); + this->ClipPlanes->Delete(); + + this->XComponent->Delete(); + this->YComponent->Delete(); + + this->LinesOn->Delete(); + this->PointsOn->Delete(); + + this->SetTitleTextProperty(NULL); + this->SetAxisLabelTextProperty(NULL); + this->SetAxisTitleTextProperty(NULL); +} + +//---------------------------------------------------------------------------- +void VISU_XYPlotActor::InitializeEntries() +{ + if ( this->NumberOfInputs > 0 ) + { + for (int i=0; iNumberOfInputs; i++) + { + this->PlotData[i]->Delete(); + this->PlotGlyph[i]->Delete(); + this->PlotAppend[i]->Delete(); + this->PlotTransform[i]->Delete(); // RKV + this->PlotMapper[i]->Delete(); + this->PlotActor[i]->Delete(); + }//for all entries + delete [] this->PlotData; this->PlotData = NULL; + delete [] this->PlotGlyph; this->PlotGlyph = NULL; + delete [] this->PlotAppend; this->PlotAppend = NULL; + delete [] this->PlotTransform; this->PlotTransform = NULL; // RKV + delete [] this->PlotMapper; this->PlotMapper = NULL; + delete [] this->PlotActor; this->PlotActor = NULL; + this->NumberOfInputs = 0; + }//if entries have been defined +} + +//---------------------------------------------------------------------------- +// Add a dataset and array to the list of data to plot. +void VISU_XYPlotActor::AddInput(vtkDataSet *ds, const char *arrayName, int component) +{ + int idx, num; + char** newNames; + + // I cannot change the input list, because the user has direct + // access to the collection. I cannot store the index of the array, + // because the index might change from render to render ... + // I have to store the list of string array names. + + // I believe idx starts at 1 and goes to "NumberOfItems". + idx = this->InputList->IsItemPresent(ds); + if (idx > 0) + { // Return if arrays are the same. + if (arrayName == NULL && this->SelectedInputScalars[idx-1] == NULL && + component == this->SelectedInputScalarsComponent->GetValue(idx-1)) + { + return; + } + if (arrayName != NULL && this->SelectedInputScalars[idx-1] != NULL && + strcmp(arrayName, this->SelectedInputScalars[idx-1]) == 0 && + component == this->SelectedInputScalarsComponent->GetValue(idx-1)) + { + return; + } + } + + // The input/array/component must be a unique combination. Add it to our input list. + + // Now reallocate the list of strings and add the new value. + num = this->InputList->GetNumberOfItems(); + newNames = new char*[num+1]; + for (idx = 0; idx < num; ++idx) + { + newNames[idx] = this->SelectedInputScalars[idx]; + } + if (arrayName == NULL) + { + newNames[num] = NULL; + } + else + { + newNames[num] = new char[strlen(arrayName)+1]; + strcpy(newNames[num],arrayName); + } + delete [] this->SelectedInputScalars; + this->SelectedInputScalars = newNames; + + // Save the component in the int array. + this->SelectedInputScalarsComponent->InsertValue(num, component); + + // Add the data set to the collection + this->InputList->AddItem(ds); + + // In case of multiple use of a XYPlotActor the NumberOfEntries could be set + // to n. Then when a call to SetEntryString(n+1, bla) was done the string was lost + // Need to update the number of entries for the legend actor + this->LegendActor->SetNumberOfEntries(this->LegendActor->GetNumberOfEntries()+1); + + this->Modified(); +} + +//---------------------------------------------------------------------------- +void VISU_XYPlotActor::RemoveAllInputs() +{ + int idx, num; + + num = this->InputList->GetNumberOfItems(); + this->InputList->RemoveAllItems(); + + for (idx = 0; idx < num; ++idx) + { + if (this->SelectedInputScalars[idx]) + { + delete [] this->SelectedInputScalars[idx]; + this->SelectedInputScalars[idx] = NULL; + } + } + this->SelectedInputScalarsComponent->Reset(); + + this->DataObjectInputList->RemoveAllItems(); +} + +//---------------------------------------------------------------------------- +// Remove a dataset from the list of data to plot. +void VISU_XYPlotActor::RemoveInput(vtkDataSet *ds, const char *arrayName, int component) +{ + int idx, num; + vtkDataSet *input; + int found = -1; + + // This is my own find routine, because the array names have to match also. + num = this->InputList->GetNumberOfItems(); + vtkCollectionSimpleIterator dsit; + this->InputList->InitTraversal(dsit); + for (idx = 0; idx < num && found == -1; ++idx) + { + input = this->InputList->GetNextDataSet(dsit); + if (input == ds) + { + if (arrayName == NULL && this->SelectedInputScalars[idx] == NULL && + component == this->SelectedInputScalarsComponent->GetValue(idx)) + { + found = idx; + } + if (arrayName != NULL && this->SelectedInputScalars[idx] != NULL && + strcmp(arrayName, this->SelectedInputScalars[idx]) == 0 && + component == this->SelectedInputScalarsComponent->GetValue(idx)) + { + found = idx; + } + } + } + + if (found == -1) + { + return; + } + + this->Modified(); + // Collections index their items starting at 1. + this->InputList->RemoveItem(found); + + // Do not bother reallocating the SelectedInputScalars + // string array to make it smaller. + if (this->SelectedInputScalars[found]) + { + delete [] this->SelectedInputScalars[found]; + this->SelectedInputScalars[found] = NULL; + } + for (idx = found+1; idx < num; ++idx) + { + this->SelectedInputScalars[idx-1] = this->SelectedInputScalars[idx]; + this->SelectedInputScalarsComponent->SetValue(idx-1, + this->SelectedInputScalarsComponent->GetValue(idx)); + } + // Reseting the last item is not really necessary, + // but to be clean we do it anyway. + this->SelectedInputScalarsComponent->SetValue(num-1, -1); + this->SelectedInputScalars[num-1] = NULL; +} + +//---------------------------------------------------------------------------- +// Add a data object to the list of data to plot. +void VISU_XYPlotActor::AddDataObjectInput(vtkDataObject *in) +{ + if ( ! this->DataObjectInputList->IsItemPresent(in) ) + { + this->Modified(); + this->DataObjectInputList->AddItem(in); + } +} + +//---------------------------------------------------------------------------- +// Remove a data object from the list of data to plot. +void VISU_XYPlotActor::RemoveDataObjectInput(vtkDataObject *in) +{ + if ( this->DataObjectInputList->IsItemPresent(in) ) + { + this->Modified(); + this->DataObjectInputList->RemoveItem(in); + } +} + +//---------------------------------------------------------------------------- +// Plot scalar data for each input dataset. +int VISU_XYPlotActor::RenderOverlay(vtkViewport *viewport) +{ + int renderedSomething = 0; + + // Make sure input is up to date. + if ( this->InputList->GetNumberOfItems() < 1 && + this->DataObjectInputList->GetNumberOfItems() < 1 ) + { + vtkErrorMacro(<< "Nothing to plot!"); + return 0; + } + + renderedSomething += this->XAxis->RenderOverlay(viewport); + renderedSomething += this->YAxis->RenderOverlay(viewport); + if ( this->Title ) + { + renderedSomething += this->TitleActor->RenderOverlay(viewport); + } + for (int i=0; i < this->NumberOfInputs; i++) + { + renderedSomething += this->PlotActor[i]->RenderOverlay(viewport); + } + if ( this->Legend ) + { + renderedSomething += this->LegendActor->RenderOverlay(viewport); + } + + return renderedSomething; +} + +//---------------------------------------------------------------------------- +// Plot scalar data for each input dataset. +int VISU_XYPlotActor::RenderOpaqueGeometry(vtkViewport *viewport) +{ + unsigned long mtime, dsMtime; + vtkDataSet *ds; + vtkDataObject *dobj; + int numDS, numDO, renderedSomething=0; + + // Initialize + // Make sure input is up to date. + numDS = this->InputList->GetNumberOfItems(); + numDO = this->DataObjectInputList->GetNumberOfItems(); + if ( numDS > 0 ) + { + vtkDebugMacro(<<"Plotting input data sets"); + vtkCollectionSimpleIterator dsit; + for (mtime=0, this->InputList->InitTraversal(dsit); + (ds = this->InputList->GetNextDataSet(dsit)); ) + { + ds->Update(); + dsMtime = ds->GetMTime(); + if ( dsMtime > mtime ) + { + mtime = dsMtime; + } + } + } + else if ( numDO > 0 ) + { + vtkDebugMacro(<<"Plotting input data objects"); + vtkCollectionSimpleIterator doit; + for (mtime=0, this->DataObjectInputList->InitTraversal(doit); + (dobj = this->DataObjectInputList->GetNextDataObject(doit)); ) + { + dobj->Update(); + dsMtime = dobj->GetMTime(); + if ( dsMtime > mtime ) + { + mtime = dsMtime; + } + } + } + else + { + vtkErrorMacro(<< "Nothing to plot!"); + return 0; + } + + if (this->Title && this->Title[0] && !this->TitleTextProperty) + { + vtkErrorMacro(<< "Need a title text property to render plot title"); + return 0; + } + + // Check modified time to see whether we have to rebuild. + // Pay attention that GetMTime() has been redefined (see below) + + int *size=viewport->GetSize(); + if (mtime > this->BuildTime || + size[0] != this->CachedSize[0] || size[1] != this->CachedSize[1] || + this->GetMTime() > this->BuildTime || + (this->Title && this->Title[0] && + this->TitleTextProperty->GetMTime() > this->BuildTime) || + (this->AxisLabelTextProperty && + this->AxisLabelTextProperty->GetMTime() > this->BuildTime) || + (this->AxisTitleTextProperty && + this->AxisTitleTextProperty->GetMTime() > this->BuildTime)) + { + double range[2], yrange[2], xRange[2], yRange[2], interval, *lengths=NULL; + int pos[2], pos2[2], numTicks; + int stringSize[2]; + int num = ( numDS > 0 ? numDS : numDO ); + + vtkDebugMacro(<<"Rebuilding plot"); + this->CachedSize[0] = size[0]; + this->CachedSize[1] = size[1]; + + // RKV : Begin + if ((this->PlotLocation == VISU_XYPLOT_RIGHT) || (this->PlotLocation == VISU_XYPLOT_LEFT)) + this->ReverseYAxis = 1; + else + this->ReverseYAxis = 0; + // RKV : End + + // manage legend + vtkDebugMacro(<<"Rebuilding legend"); + if ( this->Legend ) + { + int legPos[2], legPos2[2]; + int *p1 = this->PositionCoordinate->GetComputedViewportValue(viewport); + int *p2 = this->Position2Coordinate->GetComputedViewportValue(viewport); + legPos[0] = (int)(p1[0] + this->LegendPosition[0]*(p2[0]-p1[0])); + legPos2[0] = (int)(legPos[0] + this->LegendPosition2[0]*(p2[0]-p1[0])); + legPos[1] = (int)(p1[1] + this->LegendPosition[1]*(p2[1]-p1[1])); + legPos2[1] = (int)(legPos[1] + this->LegendPosition2[1]*(p2[1]-p1[1])); + + this->LegendActor->GetPositionCoordinate()->SetValue( + (double)legPos[0], (double)legPos[1]); + this->LegendActor->GetPosition2Coordinate()->SetValue( + (double)legPos2[0], (double)legPos2[1]); + this->LegendActor->SetNumberOfEntries(num); + for (int i=0; iLegendActor->GetEntrySymbol(i) ) + { + this->LegendActor->SetEntrySymbol(i,this->GlyphSource->GetOutput()); + } + if ( ! this->LegendActor->GetEntryString(i) ) + { + static char legendString[12]; + sprintf(legendString, "%s%d", "Curve ", i); + this->LegendActor->SetEntryString(i,legendString); + } + } + + this->LegendActor->SetPadding(2); + this->LegendActor->GetProperty()->DeepCopy(this->GetProperty()); + this->LegendActor->ScalarVisibilityOff(); + } + + // Rebuid text props + // Perform shallow copy here since each individual axis can be + // accessed through the class API (i.e. each individual axis text prop + // can be changed). Therefore, we can not just assign pointers otherwise + // each individual axis text prop would point to the same text prop. + + if (this->AxisLabelTextProperty && + this->AxisLabelTextProperty->GetMTime() > this->BuildTime) + { + if (this->XAxis->GetTitleTextProperty()) + { + this->XAxis->GetLabelTextProperty()->ShallowCopy( + this->AxisLabelTextProperty); + } + if (this->YAxis->GetTitleTextProperty()) + { + this->YAxis->GetLabelTextProperty()->ShallowCopy( + this->AxisLabelTextProperty); + } + } + + if (this->AxisTitleTextProperty && + this->AxisTitleTextProperty->GetMTime() > this->BuildTime) + { + if (this->XAxis->GetTitleTextProperty()) + { + this->XAxis->GetTitleTextProperty()->ShallowCopy( + this->AxisTitleTextProperty); + } + if (this->YAxis->GetTitleTextProperty()) + { + this->YAxis->GetTitleTextProperty()->ShallowCopy( + this->AxisTitleTextProperty); + } + } + + // setup x-axis + vtkDebugMacro(<<"Rebuilding x-axis"); + + this->XAxis->SetTitle(this->XTitle); + this->XAxis->SetNumberOfLabels(this->NumberOfXLabels); + this->XAxis->SetProperty(this->GetProperty()); + + vtkDebugMacro(<<"xrange = (" << range[0] << ", " << range[1] << ")"); // RKV + lengths = new double[num]; + if ( numDS > 0 ) //plotting data sets + { + this->ComputeXRange(range, lengths); + } + else + { + this->ComputeDORange(range, yrange, lengths); + } + if ( this->XRange[0] < this->XRange[1] ) + { + range[0] = this->XRange[0]; + range[1] = this->XRange[1]; + } + +/* RKV vtkAxisActor2D::ComputeRange(range, xRange, this->NumberOfXLabels, + numTicks, interval); +*/ // RKV : Begin + vtkDebugMacro(<<"XRange = (" << XRange[0] << ", " << XRange[1] << ")"); + vtkDebugMacro(<<"xrange = (" << range[0] << ", " << range[1] << ")"); + xRange[0] = range[0]; + xRange[1] = range[1]; + // RKV : End + if ( !this->ExchangeAxes ) + { + this->XComputedRange[0] = xRange[0]; + this->XComputedRange[1] = xRange[1]; + if ( this->ReverseXAxis ) + { + this->XAxis->SetRange(range[1],range[0]); + } + else + { + this->XAxis->SetRange(range[0],range[1]); + } + } + else + { + this->XComputedRange[1] = xRange[0]; + this->XComputedRange[0] = xRange[1]; + if ( this->ReverseYAxis ) + { + this->XAxis->SetRange(range[0],range[1]); + } + else + { + this->XAxis->SetRange(range[1],range[0]); + } + } + + // setup y-axis + vtkDebugMacro(<<"Rebuilding y-axis"); + this->YAxis->SetTitle(this->YTitle); + this->YAxis->SetNumberOfLabels(this->NumberOfYLabels); + + vtkDebugMacro(<<"yrange = (" << yrange[0] << ", " << yrange[1] << ")"); // RKV + if ( this->YRange[0] >= this->YRange[1] ) + { + if ( numDS > 0 ) //plotting data sets + { + this->ComputeYRange(yrange); + } + } + else + { + yrange[0] = this->YRange[0]; + yrange[1] = this->YRange[1]; + } +/* RKV vtkAxisActor2D::ComputeRange(yrange, yRange, this->NumberOfYLabels, + numTicks, interval); +*/ + // RKV : Begin + vtkDebugMacro(<<"YRange = (" << YRange[0] << ", " << YRange[1] << ")"); + vtkDebugMacro(<<"yrange = (" << yrange[0] << ", " << yrange[1] << ")"); + yRange[0] = yrange[0]; + yRange[1] = yrange[1]; + // RKV : End + + if ( !this->ExchangeAxes ) + { + this->YComputedRange[0] = yRange[0]; + this->YComputedRange[1] = yRange[1]; + if ( this->ReverseYAxis ) + { + this->YAxis->SetRange(yrange[0],yrange[1]); + } + else + { + this->YAxis->SetRange(yrange[1],yrange[0]); + } + } + else + { + this->YComputedRange[1] = yRange[0]; + this->YComputedRange[0] = yRange[1]; + if ( this->ReverseXAxis ) + { + this->YAxis->SetRange(yrange[1],yrange[0]); + } + else + { + this->YAxis->SetRange(yrange[0],yrange[1]); + } + } + + + this->PlaceAxes(viewport, size, pos, pos2); + + // manage title + if (this->Title != NULL && this->Title[0]) + { + this->TitleMapper->SetInput(this->Title); + if (this->TitleTextProperty->GetMTime() > this->BuildTime) + { + this->TitleMapper->GetTextProperty()->ShallowCopy( + this->TitleTextProperty); + } + + vtkAxisActor2D::SetFontSize(viewport, + this->TitleMapper, + size, + 1.0, + stringSize); + + this->TitleActor->GetPositionCoordinate()->SetValue( + pos[0] + 0.5 * (pos2[0] - pos[0]) - stringSize[0] / 2.0, + pos2[1] - stringSize[1] / 2.0); + + this->TitleActor->SetProperty(this->GetProperty()); + } + + vtkDebugMacro(<<"Creating Plot Data"); + // Okay, now create the plot data and set up the pipeline + this->CreatePlotData(pos, pos2, xRange, yRange, lengths, numDS, numDO); + delete [] lengths; + + this->BuildTime.Modified(); + + }//if need to rebuild the plot + + vtkDebugMacro(<<"Rendering Axes"); + renderedSomething += this->XAxis->RenderOpaqueGeometry(viewport); + renderedSomething += this->YAxis->RenderOpaqueGeometry(viewport); + for (int i=0; i < this->NumberOfInputs; i++) + { + vtkDebugMacro(<<"Rendering plotactors"); + renderedSomething += this->PlotActor[i]->RenderOpaqueGeometry(viewport); + } + if ( this->Title ) + { + vtkDebugMacro(<<"Rendering titleactors"); + renderedSomething += this->TitleActor->RenderOpaqueGeometry(viewport); + } + if ( this->Legend ) + { + vtkDebugMacro(<<"Rendering legendeactors"); + renderedSomething += this->LegendActor->RenderOpaqueGeometry(viewport); + } + + return renderedSomething; +} + +//---------------------------------------------------------------------------- +const char *VISU_XYPlotActor::GetXValuesAsString() +{ + switch (this->XValues) + { + case VTK_XYPLOT_INDEX: + return "Index"; + case VTK_XYPLOT_ARC_LENGTH: + return "ArcLength"; + case VTK_XYPLOT_NORMALIZED_ARC_LENGTH: + return "NormalizedArcLength"; + default: + return "Value"; + } +} + +//---------------------------------------------------------------------------- +const char *VISU_XYPlotActor::GetDataObjectPlotModeAsString() +{ + if ( this->DataObjectPlotMode == VTK_XYPLOT_ROW ) + { + return "Plot Rows"; + } + else + { + return "Plot Columns"; + } +} + +//---------------------------------------------------------------------------- +// Release any graphics resources that are being consumed by this actor. +// The parameter window could be used to determine which graphic +// resources to release. +void VISU_XYPlotActor::ReleaseGraphicsResources(vtkWindow *win) +{ + this->TitleActor->ReleaseGraphicsResources(win); + this->XAxis->ReleaseGraphicsResources(win); + this->YAxis->ReleaseGraphicsResources(win); + for (int i=0; i < this->NumberOfInputs; i++) + { + this->PlotActor[i]->ReleaseGraphicsResources(win); + } + this->LegendActor->ReleaseGraphicsResources(win); +} + +//---------------------------------------------------------------------------- +unsigned long VISU_XYPlotActor::GetMTime() +{ + unsigned long mtime, mtime2; + mtime = this->vtkActor2D::GetMTime(); + + if (this->Legend) + { + mtime2 = this->LegendActor->GetMTime(); + if (mtime2 > mtime) + { + mtime = mtime2; + } + } + + return mtime; +} + +//---------------------------------------------------------------------------- +void VISU_XYPlotActor::PrintSelf(ostream& os, vtkIndent indent) +{ + vtkIndent i2 = indent.GetNextIndent(); + vtkDataSet *input; + char *array; + int component; + int idx, num; + + this->Superclass::PrintSelf(os,indent); + + vtkCollectionSimpleIterator dsit; + this->InputList->InitTraversal(dsit); + num = this->InputList->GetNumberOfItems(); + os << indent << "DataSetInputs: " << endl; + for (idx = 0; idx < num; ++idx) + { + input = this->InputList->GetNextDataSet(dsit); + array = this->SelectedInputScalars[idx]; + component = this->SelectedInputScalarsComponent->GetValue((vtkIdType)idx); + if (array == NULL) + { + os << i2 << "(" << input << ") Default Scalars, Component = " << component << endl; + } + else + { + os << i2 << "(" << input << ") " << array << ", Component = " << component << endl; + } + } + + os << indent << "Input DataObjects:\n"; + this->DataObjectInputList->PrintSelf(os,indent.GetNextIndent()); + + if (this->TitleTextProperty) + { + os << indent << "Title Text Property:\n"; + this->TitleTextProperty->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "Title Text Property: (none)\n"; + } + + if (this->AxisTitleTextProperty) + { + os << indent << "Axis Title Text Property:\n"; + this->AxisTitleTextProperty->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "Axis Title Text Property: (none)\n"; + } + + if (this->AxisLabelTextProperty) + { + os << indent << "Axis Label Text Property:\n"; + this->AxisLabelTextProperty->PrintSelf(os,indent.GetNextIndent()); + } + else + { + os << indent << "Axis Label Text Property: (none)\n"; + } + + os << indent << "Data Object Plot Mode: " << this->GetDataObjectPlotModeAsString() << endl; + + os << indent << "Title: " << (this->Title ? this->Title : "(none)") << "\n"; + os << indent << "X Title: " + << (this->XTitle ? this->XTitle : "(none)") << "\n"; + os << indent << "Y Title: " + << (this->YTitle ? this->YTitle : "(none)") << "\n"; + + os << indent << "X Values: " << this->GetXValuesAsString() << endl; + os << indent << "Log X Values: " << (this->Logx ? "On\n" : "Off\n"); + + os << indent << "Plot global-points: " << (this->PlotPoints ? "On\n" : "Off\n"); + os << indent << "Plot global-lines: " << (this->PlotLines ? "On\n" : "Off\n"); + os << indent << "Plot per-curve points: " << (this->PlotCurvePoints ? "On\n" : "Off\n"); + os << indent << "Plot per-curve lines: " << (this->PlotCurveLines ? "On\n" : "Off\n"); + os << indent << "Exchange Axes: " << (this->ExchangeAxes ? "On\n" : "Off\n"); + os << indent << "Reverse X Axis: " << (this->ReverseXAxis ? "On\n" : "Off\n"); + os << indent << "Reverse Y Axis: " << (this->ReverseYAxis ? "On\n" : "Off\n"); + + os << indent << "Number Of X Labels: " << this->NumberOfXLabels << "\n"; + os << indent << "Number Of Y Labels: " << this->NumberOfYLabels << "\n"; + + os << indent << "Label Format: " << this->LabelFormat << "\n"; + os << indent << "Border: " << this->Border << "\n"; + + os << indent << "X Range: "; + if ( this->XRange[0] >= this->XRange[1] ) + { + os << indent << "(Automatically Computed)\n"; + } + else + { + os << "(" << this->XRange[0] << ", " << this->XRange[1] << ")\n"; + } + + os << indent << "Y Range: "; + if ( this->XRange[0] >= this->YRange[1] ) + { + os << indent << "(Automatically Computed)\n"; + } + else + { + os << "(" << this->YRange[0] << ", " << this->YRange[1] << ")\n"; + } + + os << indent << "Viewport Coordinate: (" + << this->ViewportCoordinate[0] << ", " + << this->ViewportCoordinate[1] << ")\n"; + + os << indent << "Plot Coordinate: (" + << this->PlotCoordinate[0] << ", " + << this->PlotCoordinate[1] << ")\n"; + + os << indent << "Legend: " << (this->Legend ? "On\n" : "Off\n"); + os << indent << "Legend Position: (" + << this->LegendPosition[0] << ", " + << this->LegendPosition[1] << ")\n"; + os << indent << "Legend Position2: (" + << this->LegendPosition2[0] << ", " + << this->LegendPosition2[1] << ")\n"; + + os << indent << "Glyph Size: " << this->GlyphSize << endl; + + os << indent << "Legend Actor:"; + this->LegendActor->PrintSelf( os << endl, i2); + os << indent << "Glyph Source:"; + this->GlyphSource->PrintSelf( os << endl, i2); +} + +//---------------------------------------------------------------------------- +void VISU_XYPlotActor::ComputeXRange(double range[2], double *lengths) +{ + int dsNum; + vtkIdType numPts, ptId, maxNum; + double maxLength=0.0, xPrev[3], x[3]; + vtkDataSet *ds; + + range[0] = VTK_DOUBLE_MAX, range[1] = VTK_DOUBLE_MIN; + + vtkCollectionSimpleIterator dsit; + for ( dsNum=0, maxNum=0, this->InputList->InitTraversal(dsit); + (ds = this->InputList->GetNextDataSet(dsit)); dsNum++) + { + numPts = ds->GetNumberOfPoints(); + + if ( this->XValues != VTK_XYPLOT_INDEX ) + { + ds->GetPoint(0, xPrev); + for ( lengths[dsNum]=0.0, ptId=0; ptId < numPts; ptId++ ) + { + ds->GetPoint(ptId, x); + switch (this->XValues) + { + case VTK_XYPLOT_VALUE: + if (this->GetLogx() == 0) + { + if ( x[this->XComponent->GetValue(dsNum)] < range[0] ) + { + range[0] = x[this->XComponent->GetValue(dsNum)]; + } + if ( x[this->XComponent->GetValue(dsNum)] > range[1] ) + { + range[1] = x[this->XComponent->GetValue(dsNum)]; + } + } + else + { + //ensure range strictly > 0 for log + if ( (x[this->XComponent->GetValue(dsNum)]) < range[0] && + (x[this->XComponent->GetValue(dsNum)] > 0)) + { + range[0] = x[this->XComponent->GetValue(dsNum)]; + } + if ( (x[this->XComponent->GetValue(dsNum)] > range[1]) && + (x[this->XComponent->GetValue(dsNum)] > 0)) + { + range[1] = x[this->XComponent->GetValue(dsNum)]; + } + } + break; + default: + lengths[dsNum] += sqrt(vtkMath::Distance2BetweenPoints(x,xPrev)); + xPrev[0] = x[0]; xPrev[1] = x[1]; xPrev[2] = x[2]; + } + }//for all points + if ( lengths[dsNum] > maxLength ) + { + maxLength = lengths[dsNum]; + } + }//if need to visit all points + + else //if ( this->XValues == VTK_XYPLOT_INDEX ) + { + if ( numPts > maxNum ) + { + maxNum = numPts; + } + } + }//over all datasets + + // determine the range + switch (this->XValues) + { + case VTK_XYPLOT_ARC_LENGTH: + range[0] = 0.0; + range[1] = maxLength; + break; + case VTK_XYPLOT_NORMALIZED_ARC_LENGTH: + range[0] = 0.0; + range[1] = 1.0; + break; + case VTK_XYPLOT_INDEX: + range[0] = 0.0; + range[1] = (double)(maxNum - 1); + break; + case VTK_XYPLOT_VALUE: + if (this->GetLogx() == 1) + { + if (range[0] > range[1]) + { + range[0] = 0; + range[1] = 0; + } + else + { + range[0] = log10(range[0]); + range[1] = log10(range[1]); + } + } + break; //range computed in for loop above + default: + vtkErrorMacro(<< "Unkown X-Value option."); + return; + } +} + +//---------------------------------------------------------------------------- +void VISU_XYPlotActor::ComputeYRange(double range[2]) +{ + vtkDataSet *ds; + vtkDataArray *scalars; + double sRange[2]; + int count; + int component; + + range[0]=VTK_DOUBLE_MAX, range[1]=VTK_DOUBLE_MIN; + + vtkCollectionSimpleIterator dsit; + for ( this->InputList->InitTraversal(dsit), count = 0; + (ds = this->InputList->GetNextDataSet(dsit)); ++count) + { + scalars = ds->GetPointData()->GetScalars(this->SelectedInputScalars[count]); + component = this->SelectedInputScalarsComponent->GetValue(count); + if ( !scalars) + { + vtkErrorMacro(<<"No scalar data to plot!"); + continue; + } + if ( component < 0 || component >= scalars->GetNumberOfComponents()) + { + vtkErrorMacro(<<"Bad component!"); + continue; + } + + scalars->GetRange(sRange, component); + if ( sRange[0] < range[0] ) + { + range[0] = sRange[0]; + } + + if ( sRange[1] > range[1] ) + { + range[1] = sRange[1]; + } + }//over all datasets +} + +//---------------------------------------------------------------------------- +void VISU_XYPlotActor::ComputeDORange(double xrange[2], double yrange[2], + double *lengths) +{ + int i; + vtkDataObject *dobj; + vtkFieldData *field; + int doNum, numColumns; + vtkIdType numTuples, numRows, num, ptId, maxNum; + double maxLength=0.0, x, y, xPrev = 0.0; + vtkDataArray *array; + + xrange[0] = yrange[0] = VTK_DOUBLE_MAX; + xrange[1] = yrange[1] = -VTK_DOUBLE_MAX; + vtkCollectionSimpleIterator doit; + for ( doNum=0, maxNum=0, this->DataObjectInputList->InitTraversal(doit); + (dobj = this->DataObjectInputList->GetNextDataObject(doit)); doNum++) + { + lengths[doNum] = 0.0; + field = dobj->GetFieldData(); + numColumns = field->GetNumberOfComponents(); //number of "columns" + for (numRows = VTK_LARGE_ID, i=0; iGetNumberOfArrays(); i++) + { + array = field->GetArray(i); + numTuples = array->GetNumberOfTuples(); + if ( numTuples < numRows ) + { + numRows = numTuples; + } + } + + num = (this->DataObjectPlotMode == VTK_XYPLOT_ROW ? + numColumns : numRows); + + if ( this->XValues != VTK_XYPLOT_INDEX ) + { + // gather the information to form a plot + for ( ptId=0; ptId < num; ptId++ ) + { + if ( this->DataObjectPlotMode == VTK_XYPLOT_ROW ) + { + x = field->GetComponent(this->XComponent->GetValue(doNum), ptId); + } + else //if ( this->DataObjectPlotMode == VTK_XYPLOT_COLUMN ) + { + x = field->GetComponent(ptId, this->XComponent->GetValue(doNum)); + } + if ( ptId == 0 ) + { + xPrev = x; + } + + switch (this->XValues) + { + case VTK_XYPLOT_VALUE: + if (this->GetLogx() == 0) + { + if ( x < xrange[0] ) + { + xrange[0] = x; + } + if ( x > xrange[1] ) + { + xrange[1] = x; + } + } + else //ensure positive values + { + if ( (x < xrange[0]) && (x > 0) ) + { + xrange[0] = x; + } + if ( x > xrange[1] && (x > 0) ) + { + xrange[1] = x; + } + } + break; + default: + lengths[doNum] += fabs(x-xPrev); + xPrev = x; + } + }//for all points + if ( lengths[doNum] > maxLength ) + { + maxLength = lengths[doNum]; + } + }//if all data has to be visited + + else //if (this->XValues == VTK_XYPLOT_INDEX) + { + if ( num > maxNum ) + { + maxNum = num; + } + } + + // Get the y-values + for ( ptId=0; ptId < num; ptId++ ) + { + if ( this->DataObjectPlotMode == VTK_XYPLOT_ROW ) + { + y = field->GetComponent(this->YComponent->GetValue(doNum), ptId); + } + else //if ( this->DataObjectPlotMode == VTK_XYPLOT_COLUMN ) + { + y = field->GetComponent(ptId, this->YComponent->GetValue(doNum)); + } + if ( y < yrange[0] ) + { + yrange[0] = y; + } + if ( y > yrange[1] ) + { + yrange[1] = y; + } + }//over all y values + }//over all dataobjects + + // determine the range + switch (this->XValues) + { + case VTK_XYPLOT_ARC_LENGTH: + xrange[0] = 0.0; + xrange[1] = maxLength; + break; + case VTK_XYPLOT_NORMALIZED_ARC_LENGTH: + xrange[0] = 0.0; + xrange[1] = 1.0; + break; + case VTK_XYPLOT_INDEX: + xrange[0] = 0.0; + xrange[1] = (double)(maxNum - 1); + break; + case VTK_XYPLOT_VALUE: + if (this->GetLogx() == 1) + { + xrange[0] = log10(xrange[0]); + xrange[1] = log10(xrange[1]); + } + break; + default: + vtkErrorMacro(<< "Unknown X-Value option"); + return; + } +} + +//---------------------------------------------------------------------------- +/* RKV void VISU_XYPlotActor::CreatePlotData(int *pos, int *pos2, double xRange[2], + double yRange[2], double *lengths, + int numDS, int numDO) */ +// RKV : Begin +void VISU_XYPlotActor::CreatePlotData(int *pos, int *pos2Extern, double xRange[2], + double yRange[2], double *lengths, + int numDS, int numDO) +// RKV : End +{ + double xyz[3]; xyz[2] = 0.0; + int i, numLinePts, dsNum, doNum, num; + vtkIdType numPts, ptId, id; + double length, x[3], xPrev[3]; + vtkDataArray *scalars; + int component; + vtkDataSet *ds; + vtkCellArray *lines; + vtkPoints *pts; + int clippingRequired = 0; + + // Allocate resources for the polygonal plots + // + num = (numDS > numDO ? numDS : numDO); + this->InitializeEntries(); + this->NumberOfInputs = num; + this->PlotData = new vtkPolyData* [num]; + this->PlotGlyph = new vtkGlyph2D* [num]; + this->PlotAppend = new vtkAppendPolyData* [num]; + this->PlotTransform = new vtkTransformPolyDataFilter* [num]; // RKV + this->PlotMapper = new vtkPolyDataMapper2D* [num]; + this->PlotActor = new vtkActor2D* [num]; + + // RKV : Begin + // Prepare the transformation of the curve according to the plot location + vtkTransform *tf = vtkTransform::New(); + tf->Translate(pos[0], pos[1], 0); + if ((this->PlotLocation == VISU_XYPLOT_LEFT) || (this->PlotLocation == VISU_XYPLOT_RIGHT)) + tf->RotateZ(90); + tf->Translate(-pos[0], -pos[1], 0); + + // Compute the position2 to build the curve before the transformation + int pos2[2]; + vtkDebugMacro(<< "pos = (" << pos[0] << ", " << pos[1] << ")"); + vtkDebugMacro(<< "pos2 = (" << pos2Extern[0] << ", " << pos2Extern[1] << ")"); + if ((this->PlotLocation == VISU_XYPLOT_LEFT) || (this->PlotLocation == VISU_XYPLOT_RIGHT)) + { + pos2[0] = pos[0] + pos2Extern[1] - pos[1]; + pos2[1] = pos[1] + pos[0] - pos2Extern[0]; + } + else + { + pos2[0] = pos2Extern[0]; + pos2[1] = pos2Extern[1]; + } + // RKV : End + + for (i=0; iPlotData[i] = vtkPolyData::New(); + this->PlotGlyph[i] = vtkGlyph2D::New(); + this->PlotGlyph[i]->SetInput(this->PlotData[i]); + this->PlotGlyph[i]->SetScaleModeToDataScalingOff(); + this->PlotAppend[i] = vtkAppendPolyData::New(); + this->PlotAppend[i]->AddInput(this->PlotData[i]); + if ( this->LegendActor->GetEntrySymbol(i) != NULL && + this->LegendActor->GetEntrySymbol(i) != this->GlyphSource->GetOutput() ) + { + this->PlotGlyph[i]->SetSource(this->LegendActor->GetEntrySymbol(i)); + this->PlotGlyph[i]->SetScaleFactor(this->ComputeGlyphScale(i,pos,pos2)); + this->PlotAppend[i]->AddInput(this->PlotGlyph[i]->GetOutput()); + } + this->PlotMapper[i] = vtkPolyDataMapper2D::New(); + + // RKV : Begin + // Insert a transformation filter into the pipeline to + // take into account a plot location. + this->PlotTransform[i] = vtkTransformPolyDataFilter::New(); + this->PlotTransform[i]->SetInput(this->PlotAppend[i]->GetOutput()); + this->PlotTransform[i]->SetTransform(tf); + this->PlotMapper[i]->SetInput(this->PlotTransform[i]->GetOutput()); + // RKV : End + +// RKV this->PlotMapper[i]->SetInput(this->PlotAppend[i]->GetOutput()); + this->PlotMapper[i]->ScalarVisibilityOff(); + this->PlotActor[i] = vtkActor2D::New(); + this->PlotActor[i]->SetMapper(this->PlotMapper[i]); + this->PlotActor[i]->GetProperty()->DeepCopy(this->GetProperty()); + if ( this->LegendActor->GetEntryColor(i)[0] < 0.0 ) + { + this->PlotActor[i]->GetProperty()->SetColor( + this->GetProperty()->GetColor()); + } + else + { + this->PlotActor[i]->GetProperty()->SetColor( + this->LegendActor->GetEntryColor(i)); + } + } + + tf->Delete(); // RKV + + // Prepare to receive data + this->GenerateClipPlanes(pos,pos2); + for (i=0; iNumberOfInputs; i++) + { + lines = vtkCellArray::New(); + pts = vtkPoints::New(); + + lines->Allocate(10,10); + pts->Allocate(10,10); + this->PlotData[i]->SetPoints(pts); + this->PlotData[i]->SetVerts(lines); + this->PlotData[i]->SetLines(lines); + + pts->Delete(); + lines->Delete(); + } + + // Okay, for each input generate plot data. Depending on the input + // we use either dataset or data object. + // + if ( numDS > 0 ) + { + vtkCollectionSimpleIterator dsit; + for ( dsNum=0, this->InputList->InitTraversal(dsit); + (ds = this->InputList->GetNextDataSet(dsit)); dsNum++ ) + { + clippingRequired = 0; + numPts = ds->GetNumberOfPoints(); + scalars = ds->GetPointData()->GetScalars(this->SelectedInputScalars[dsNum]); + if ( !scalars) + { + continue; + } + component = this->SelectedInputScalarsComponent->GetValue(dsNum); + if ( component < 0 || component >= scalars->GetNumberOfComponents()) + { + continue; + } + + pts = this->PlotData[dsNum]->GetPoints(); + lines = this->PlotData[dsNum]->GetLines(); + lines->InsertNextCell(0); //update the count later + + ds->GetPoint(0, xPrev); + for ( numLinePts=0, length=0.0, ptId=0; ptId < numPts; ptId++ ) + { + xyz[1] = scalars->GetComponent(ptId, component); + ds->GetPoint(ptId, x); + switch (this->XValues) + { + case VTK_XYPLOT_NORMALIZED_ARC_LENGTH: + length += sqrt(vtkMath::Distance2BetweenPoints(x,xPrev)); + xyz[0] = length / lengths[dsNum]; + xPrev[0] = x[0]; xPrev[1] = x[1]; xPrev[2] = x[2]; + break; + case VTK_XYPLOT_INDEX: + xyz[0] = (double)ptId; + break; + case VTK_XYPLOT_ARC_LENGTH: + length += sqrt(vtkMath::Distance2BetweenPoints(x,xPrev)); + xyz[0] = length; + xPrev[0] = x[0]; xPrev[1] = x[1]; xPrev[2] = x[2]; + break; + case VTK_XYPLOT_VALUE: + xyz[0] = x[this->XComponent->GetValue(dsNum)]; + break; + default: + vtkErrorMacro(<< "Unknown X-Component option"); + } + + if ( this->GetLogx() == 1 ) + { + if (xyz[0] > 0) + { + xyz[0] = log10(xyz[0]); + // normalize and position + if ( xyz[0] < xRange[0] || xyz[0] > xRange[1] || + xyz[1] < yRange[0] || xyz[1] > yRange[1] ) + { + clippingRequired = 1; + } + + numLinePts++; + xyz[0] = pos[0] + + (xyz[0]-xRange[0])/(xRange[1]-xRange[0])*(pos2[0]-pos[0]); + xyz[1] = pos[1] + + (xyz[1]-yRange[0])/(yRange[1]-yRange[0])*(pos2[1]-pos[1]); + id = pts->InsertNextPoint(xyz); + lines->InsertCellPoint(id); + } + } + else + { + // normalize and position + if ( xyz[0] < xRange[0] || xyz[0] > xRange[1] || + xyz[1] < yRange[0] || xyz[1] > yRange[1] ) + { + clippingRequired = 1; + } + + numLinePts++; + xyz[0] = pos[0] + + (xyz[0]-xRange[0])/(xRange[1]-xRange[0])*(pos2[0]-pos[0]); + xyz[1] = pos[1] + + (xyz[1]-yRange[0])/(yRange[1]-yRange[0])*(pos2[1]-pos[1]); + id = pts->InsertNextPoint(xyz); + lines->InsertCellPoint(id); + } + }//for all input points + + lines->UpdateCellCount(numLinePts); + if ( clippingRequired ) + { + this->ClipPlotData(pos,pos2,this->PlotData[dsNum]); + } + }//loop over all input data sets + }//if plotting datasets + + else //plot data from data objects + { + vtkDataObject *dobj; + int numColumns; + vtkIdType numRows, numTuples; + vtkDataArray *array; + vtkFieldData *field; + vtkCollectionSimpleIterator doit; + for ( doNum=0, this->DataObjectInputList->InitTraversal(doit); + (dobj = this->DataObjectInputList->GetNextDataObject(doit)); + doNum++ ) + { + // determine the shape of the field + field = dobj->GetFieldData(); + numColumns = field->GetNumberOfComponents(); //number of "columns" + for (numRows = VTK_LARGE_ID, i=0; iGetNumberOfArrays(); i++) + { + array = field->GetArray(i); + numTuples = array->GetNumberOfTuples(); + if ( numTuples < numRows ) + { + numRows = numTuples; + } + } + + pts = this->PlotData[doNum]->GetPoints(); + lines = this->PlotData[doNum]->GetLines(); + lines->InsertNextCell(0); //update the count later + + numPts = (this->DataObjectPlotMode == VTK_XYPLOT_ROW ? + numColumns : numRows); + + // gather the information to form a plot + for ( numLinePts=0, length=0.0, ptId=0; ptId < numPts; ptId++ ) + { + if ( this->DataObjectPlotMode == VTK_XYPLOT_ROW ) + { + x[0] = field->GetComponent(this->XComponent->GetValue(doNum),ptId); + xyz[1] = field->GetComponent(this->YComponent->GetValue(doNum),ptId); + } + else //if ( this->DataObjectPlotMode == VTK_XYPLOT_COLUMN ) + { + x[0] = field->GetComponent(ptId, this->XComponent->GetValue(doNum)); + xyz[1] = field->GetComponent(ptId, this->YComponent->GetValue(doNum)); + } + + switch (this->XValues) + { + case VTK_XYPLOT_NORMALIZED_ARC_LENGTH: + length += fabs(x[0]-xPrev[0]); + xyz[0] = length / lengths[doNum]; + xPrev[0] = x[0]; + break; + case VTK_XYPLOT_INDEX: + xyz[0] = (double)ptId; + break; + case VTK_XYPLOT_ARC_LENGTH: + length += fabs(x[0]-xPrev[0]); + xyz[0] = length; + xPrev[0] = x[0]; + break; + case VTK_XYPLOT_VALUE: + xyz[0] = x[0]; + break; + default: + vtkErrorMacro(<< "Unknown X-Value option"); + } + + if ( this->GetLogx() == 1 ) + { + if (xyz[0] > 0) + { + xyz[0] = log10(xyz[0]); + // normalize and position + if ( xyz[0] < xRange[0] || xyz[0] > xRange[1] || + xyz[1] < yRange[0] || xyz[1] > yRange[1] ) + { + clippingRequired = 1; + } + numLinePts++; + xyz[0] = pos[0] + + (xyz[0]-xRange[0])/(xRange[1]-xRange[0])*(pos2[0]-pos[0]); + xyz[1] = pos[1] + + (xyz[1]-yRange[0])/(yRange[1]-yRange[0])*(pos2[1]-pos[1]); + id = pts->InsertNextPoint(xyz); + lines->InsertCellPoint(id); + } + } + else + { + // normalize and position + if ( xyz[0] < xRange[0] || xyz[0] > xRange[1] || + xyz[1] < yRange[0] || xyz[1] > yRange[1] ) + { + clippingRequired = 1; + } + numLinePts++; + xyz[0] = pos[0] + + (xyz[0]-xRange[0])/(xRange[1]-xRange[0])*(pos2[0]-pos[0]); + xyz[1] = pos[1] + + (xyz[1]-yRange[0])/(yRange[1]-yRange[0])*(pos2[1]-pos[1]); + id = pts->InsertNextPoint(xyz); + lines->InsertCellPoint(id); + } + }//for all input points + + lines->UpdateCellCount(numLinePts); + if ( clippingRequired ) + { + this->ClipPlotData(pos,pos2,this->PlotData[doNum]); + } + }//loop over all input data sets + } + + // Remove points/lines as directed by the user + for ( i = 0; i < num; i++) + { + if (!this->PlotCurveLines) + { + if ( !this->PlotLines ) + { + this->PlotData[i]->SetLines(NULL); + } + } + else + { + if ( this->GetPlotLines(i) == 0) + { + this->PlotData[i]->SetLines(NULL); + } + } + + if (!this->PlotCurvePoints) + { + if ( !this->PlotPoints || (this->LegendActor->GetEntrySymbol(i) && + this->LegendActor->GetEntrySymbol(i) != + this->GlyphSource->GetOutput())) + { + this->PlotData[i]->SetVerts(NULL); + } + } + else + { + if ( this->GetPlotPoints(i) == 0 || + (this->LegendActor->GetEntrySymbol(i) && + this->LegendActor->GetEntrySymbol(i) != + this->GlyphSource->GetOutput())) + { + this->PlotData[i]->SetVerts(NULL); + } + } + } +} + +//---------------------------------------------------------------------------- +// Position the axes taking into account the expected padding due to labels +// and titles. We want the result to fit in the box specified. This method +// knows something about how the vtkAxisActor2D functions, so it may have +// to change if that class changes dramatically. +// +void VISU_XYPlotActor::PlaceAxes(vtkViewport *viewport, int *size, + int pos[2], int pos2[2]) +{ + int titleSizeX[2], titleSizeY[2], labelSizeX[2], labelSizeY[2]; + double labelFactorX, labelFactorY; + double fontFactorX, fontFactorY; + double tickOffsetX, tickOffsetY; + double tickLengthX, tickLengthY; + + vtkAxisActor2D *axisX; + vtkAxisActor2D *axisY; + + char str1[512], str2[512]; + + if (this->ExchangeAxes) + { + axisX = this->YAxis; + axisY = this->XAxis; + } + else + { + axisX = this->XAxis; + axisY = this->YAxis; + } + + // RKV : Begin + // Take into account a location of the plot. + if ((this->PlotLocation == VISU_XYPLOT_LEFT) || (this->PlotLocation == VISU_XYPLOT_RIGHT)) + { + vtkAxisActor2D *axisBid; + axisBid = axisX; + axisX = axisY; + axisY = axisBid; + } + + // RKV : End + + fontFactorY = axisY->GetFontFactor(); + fontFactorX = axisX->GetFontFactor(); + + labelFactorY = axisY->GetLabelFactor(); + labelFactorX = axisX->GetLabelFactor(); + + // Create a dummy text mapper for getting font sizes + vtkTextMapper *textMapper = vtkTextMapper::New(); + vtkTextProperty *tprop = textMapper->GetTextProperty(); + + // Get the location of the corners of the box + int *p1 = this->PositionCoordinate->GetComputedViewportValue(viewport); + int *p2 = this->Position2Coordinate->GetComputedViewportValue(viewport); + + // Estimate the padding around the X and Y axes + tprop->ShallowCopy(axisX->GetTitleTextProperty()); + textMapper->SetInput(axisX->GetTitle()); + vtkAxisActor2D::SetFontSize( + viewport, textMapper, size, fontFactorX, titleSizeX); + + tprop->ShallowCopy(axisY->GetTitleTextProperty()); + textMapper->SetInput(axisY->GetTitle()); + vtkAxisActor2D::SetFontSize( + viewport, textMapper, size, fontFactorY, titleSizeY); + + // At this point the thing to do would be to actually ask the Y axis + // actor to return the largest label. + // In the meantime, let's try with the min and max + sprintf(str1, axisY->GetLabelFormat(), axisY->GetAdjustedRange()[0]); + sprintf(str2, axisY->GetLabelFormat(), axisY->GetAdjustedRange()[1]); + tprop->ShallowCopy(axisY->GetLabelTextProperty()); + textMapper->SetInput(strlen(str1) > strlen(str2) ? str1 : str2); + vtkAxisActor2D::SetFontSize( + viewport, textMapper, size, labelFactorY * fontFactorY, labelSizeY); + + // We do only care of the height of the label in the X axis, so let's + // use the min for example + sprintf(str1, axisX->GetLabelFormat(), axisX->GetAdjustedRange()[0]); + tprop->ShallowCopy(axisX->GetLabelTextProperty()); + textMapper->SetInput(str1); + vtkAxisActor2D::SetFontSize( + viewport, textMapper, size, labelFactorX * fontFactorX, labelSizeX); + + tickOffsetX = axisX->GetTickOffset(); + tickOffsetY = axisY->GetTickOffset(); + tickLengthX = axisX->GetTickLength(); + tickLengthY = axisY->GetTickLength(); + + // Okay, estimate the size +/* RKV pos[0] = (int)(p1[0] + titleSizeY[0] + 2.0 * tickOffsetY + tickLengthY + + labelSizeY[0] + this->Border); + + pos[1] = (int)(p1[1] + titleSizeX[1] + 2.0 * tickOffsetX + tickLengthX + + labelSizeX[1] + this->Border); + + pos2[0] = (int)(p2[0] - labelSizeY[0] / 2 - tickOffsetY - this->Border); + + pos2[1] = (int)(p2[1] - labelSizeX[1] / 2 - tickOffsetX - this->Border); + */ + // RKV : Begin + pos[0] = (int)(p1[0]); + + pos[1] = (int)(p1[1]); + + pos2[0] = (int)(p2[0]); + + pos2[1] = (int)(p2[1]); + // RKV : End + + // Now specify the location of the axes + axisX->GetPositionCoordinate()->SetValue( + (double)pos[0], (double)pos[1]); + axisX->GetPosition2Coordinate()->SetValue( + (double)pos2[0], (double)pos[1]); + axisY->GetPositionCoordinate()->SetValue( + (double)pos[0], (double)pos2[1]); + axisY->GetPosition2Coordinate()->SetValue( + (double)pos[0], (double)pos[1]); + + textMapper->Delete(); +} + +//---------------------------------------------------------------------------- +void VISU_XYPlotActor::ViewportToPlotCoordinate(vtkViewport *viewport, double &u, double &v) +{ + int *p0, *p1, *p2; + + // XAxis, YAxis are in viewport coordinates already + p0 = this->XAxis->GetPositionCoordinate()->GetComputedViewportValue(viewport); + p1 = this->XAxis->GetPosition2Coordinate()->GetComputedViewportValue(viewport); + p2 = this->YAxis->GetPositionCoordinate()->GetComputedViewportValue(viewport); + + u = ((u - p0[0]) / (double)(p1[0] - p0[0])) + *(this->XComputedRange[1] - this->XComputedRange[0]) + + this->XComputedRange[0]; + v = ((v - p0[1]) / (double)(p2[1] - p0[1])) + *(this->YComputedRange[1] - this->YComputedRange[0]) + + this->YComputedRange[0]; +} + +//---------------------------------------------------------------------------- +void VISU_XYPlotActor::PlotToViewportCoordinate(vtkViewport *viewport, + double &u, double &v) +{ + int *p0, *p1, *p2; + + // XAxis, YAxis are in viewport coordinates already + p0 = this->XAxis->GetPositionCoordinate()->GetComputedViewportValue(viewport); + p1 = this->XAxis->GetPosition2Coordinate()->GetComputedViewportValue(viewport); + p2 = this->YAxis->GetPositionCoordinate()->GetComputedViewportValue(viewport); + + u = (((u - this->XComputedRange[0]) + / (this->XComputedRange[1] - this->XComputedRange[0])) + * (double)(p1[0] - p0[0])) + p0[0]; + v = (((v - this->YComputedRange[0]) + / (this->YComputedRange[1] - this->YComputedRange[0])) + * (double)(p2[1] - p0[1])) + p0[1]; +} + +//---------------------------------------------------------------------------- +void VISU_XYPlotActor::ViewportToPlotCoordinate(vtkViewport *viewport) +{ + this->ViewportToPlotCoordinate(viewport, + this->ViewportCoordinate[0], + this->ViewportCoordinate[1]); +} + +//---------------------------------------------------------------------------- +void VISU_XYPlotActor::PlotToViewportCoordinate(vtkViewport *viewport) +{ + this->PlotToViewportCoordinate(viewport, + this->PlotCoordinate[0], + this->PlotCoordinate[1]); +} + +//---------------------------------------------------------------------------- +int VISU_XYPlotActor::IsInPlot(vtkViewport *viewport, double u, double v) +{ + int *p0, *p1, *p2; + + // Bounds of the plot are based on the axes... + p0 = this->XAxis->GetPositionCoordinate()->GetComputedViewportValue(viewport); + p1 = this->XAxis->GetPosition2Coordinate()->GetComputedViewportValue(viewport); + p2 = this->YAxis->GetPositionCoordinate()->GetComputedViewportValue(viewport); + + if (u >= p0[0] && u <= p1[0] && v >= p0[1] && v <= p2[1]) + { + return 1; + } + + return 0; +} + +//---------------------------------------------------------------------------- +void VISU_XYPlotActor::SetPlotLines(int i, int isOn) +{ + i = ( i < 0 ? 0 : (i >=VTK_MAX_PLOTS ? VTK_MAX_PLOTS-1 : i)); + int val = this->LinesOn->GetValue(i); + if ( val != isOn ) + { + this->Modified(); + this->LinesOn->SetValue(i, isOn); + } +} + +//---------------------------------------------------------------------------- +int VISU_XYPlotActor::GetPlotLines(int i) +{ + i = ( i < 0 ? 0 : (i >=VTK_MAX_PLOTS ? VTK_MAX_PLOTS-1 : i)); + return this->LinesOn->GetValue(i); +} + +//---------------------------------------------------------------------------- +void VISU_XYPlotActor::SetPlotPoints(int i, int isOn) +{ + i = ( i < 0 ? 0 : (i >=VTK_MAX_PLOTS ? VTK_MAX_PLOTS-1 : i)); + int val = this->PointsOn->GetValue(i); + if ( val != isOn ) + { + this->Modified(); + this->PointsOn->SetValue(i, isOn); + } +} + +//---------------------------------------------------------------------------- +int VISU_XYPlotActor::GetPlotPoints(int i) +{ + i = ( i < 0 ? 0 : (i >=VTK_MAX_PLOTS ? VTK_MAX_PLOTS-1 : i)); + return this->PointsOn->GetValue(i); +} + +//---------------------------------------------------------------------------- +void VISU_XYPlotActor::SetPlotColor(int i, double r, double g, double b) +{ + this->LegendActor->SetEntryColor(i, r, g, b); +} + +//---------------------------------------------------------------------------- +double *VISU_XYPlotActor::GetPlotColor(int i) +{ + return this->LegendActor->GetEntryColor(i); +} + +//---------------------------------------------------------------------------- +void VISU_XYPlotActor::SetPlotSymbol(int i,vtkPolyData *input) +{ + this->LegendActor->SetEntrySymbol(i, input); +} + +//---------------------------------------------------------------------------- +vtkPolyData *VISU_XYPlotActor::GetPlotSymbol(int i) +{ + return this->LegendActor->GetEntrySymbol(i); +} + +//---------------------------------------------------------------------------- +void VISU_XYPlotActor::SetPlotLabel(int i, const char *label) +{ + this->LegendActor->SetEntryString(i, label); +} + +//---------------------------------------------------------------------------- +const char *VISU_XYPlotActor::GetPlotLabel(int i) +{ + return this->LegendActor->GetEntryString(i); +} + +//---------------------------------------------------------------------------- +void VISU_XYPlotActor::GenerateClipPlanes(int *pos, int *pos2) +{ + double n[3], x[3]; + vtkPoints *pts=this->ClipPlanes->GetPoints(); + vtkDataArray *normals=this->ClipPlanes->GetNormals(); + + n[2] = x[2] = 0.0; + + //first + n[0] = 0.0; + n[1] = -1.0; + normals->SetTuple(0,n); + x[0] = (double)0.5*(pos[0]+pos2[0]); + x[1] = (double)pos[1]; + pts->SetPoint(0,x); + + //second + n[0] = 1.0; + n[1] = 0.0; + normals->SetTuple(1,n); + x[0] = (double)pos2[0]; + x[1] = (double)0.5*(pos[1]+pos2[1]); + pts->SetPoint(1,x); + + //third + n[0] = 0.0; + n[1] = 1.0; + normals->SetTuple(2,n); + x[0] = (double)0.5*(pos[0]+pos2[0]); + x[1] = (double)pos2[1]; + pts->SetPoint(2,x); + + //fourth + n[0] = -1.0; + n[1] = 0.0; + normals->SetTuple(3,n); + x[0] = (double)pos[0]; + x[1] = (double)0.5*(pos[1]+pos2[1]); + pts->SetPoint(3,x); +} + +//---------------------------------------------------------------------------- +double VISU_XYPlotActor::ComputeGlyphScale(int i, int *pos, int *pos2) +{ + vtkPolyData *pd=this->LegendActor->GetEntrySymbol(i); + pd->Update(); + double length=pd->GetLength(); + double sf = this->GlyphSize * sqrt((double)(pos[0]-pos2[0])*(pos[0]-pos2[0]) + + (pos[1]-pos2[1])*(pos[1]-pos2[1])) / length; + + return sf; +} + +//---------------------------------------------------------------------------- +//This assumes that there are multiple polylines +void VISU_XYPlotActor::ClipPlotData(int *pos, int *pos2, vtkPolyData *pd) +{ + vtkPoints *points=pd->GetPoints(); + vtkPoints *newPoints; + vtkCellArray *lines=pd->GetLines(); + vtkCellArray *newLines, *newVerts; + vtkIdType numPts=pd->GetNumberOfPoints(); + vtkIdType npts = 0; + vtkIdType newPts[2]; + vtkIdType *pts=0; + vtkIdType i, id; + int j; + double x1[3], x2[3], px[3], n[3], xint[3], t; + double p1[2], p2[2]; + + p1[0] = (double)pos[0]; p1[1] = (double)pos[1]; + p2[0] = (double)pos2[0]; p2[1] = (double)pos2[1]; + + newPoints = vtkPoints::New(); + newPoints->Allocate(numPts); + newVerts = vtkCellArray::New(); + newVerts->Allocate(lines->GetSize()); + newLines = vtkCellArray::New(); + newLines->Allocate(2*lines->GetSize()); + int *pointMap = new int [numPts]; + for (i=0; iInitTraversal(); lines->GetNextCell(npts,pts); ) + { + //loop over verts keeping only those that are not clipped + for (i=0; iGetPoint(pts[i], x1); + + if (x1[0] >= p1[0] && x1[0] <= p2[0] && x1[1] >= p1[1] && x1[1] <= p2[1] ) + { + id = newPoints->InsertNextPoint(x1); + pointMap[i] = id; + newPts[0] = id; + newVerts->InsertNextCell(1,newPts); + } + } + } + + //Loop over polylines clipping each line segment + for ( lines->InitTraversal(); lines->GetNextCell(npts,pts); ) + { + //loop over line segment making up the polyline + for (i=0; i<(npts-1); i++) + { + points->GetPoint(pts[i], x1); + points->GetPoint(pts[i+1], x2); + + //intersect each segment with the four planes + if ( (x1[0] < p1[0] && x2[0] < p1[0]) || (x1[0] > p2[0] && x2[0] > p2[0]) || + (x1[1] < p1[1] && x2[1] < p1[1]) || (x1[1] > p2[1] && x2[1] > p2[1]) ) + { + ;//trivial rejection + } + else if (x1[0] >= p1[0] && x2[0] >= p1[0] && x1[0] <= p2[0] && x2[0] <= p2[0] && + x1[1] >= p1[1] && x2[1] >= p1[1] && x1[1] <= p2[1] && x2[1] <= p2[1] ) + {//trivial acceptance + newPts[0] = pointMap[pts[i]]; + newPts[1] = pointMap[pts[i+1]]; + newLines->InsertNextCell(2,newPts); + } + else + { + if (x1[0] >= p1[0] && x1[0] <= p2[0] && x1[1] >= p1[1] && x1[1] <= p2[1] ) + {//first point in + newPts[0] = pointMap[pts[i]]; + } + else + {//second point in + newPts[0] = pointMap[pts[i+1]]; + } + for (j=0; j<4; j++) + { + this->ClipPlanes->GetPoints()->GetPoint(j, px); + this->ClipPlanes->GetNormals()->GetTuple(j, n); + if ( vtkPlane::IntersectWithLine(x1,x2,n,px,t,xint) && t >= 0 && t <= 1.0 ) + { + newPts[1] = newPoints->InsertNextPoint(xint); + break; + } + } + newLines->InsertNextCell(2,newPts); + } + } + } + delete [] pointMap; + + //Update the lines + pd->SetPoints(newPoints); + pd->SetVerts(newVerts); + pd->SetLines(newLines); + + newPoints->Delete(); + newVerts->Delete(); + newLines->Delete(); + +} + +//---------------------------------------------------------------------------- +void VISU_XYPlotActor::SetDataObjectXComponent(int i, int comp) +{ + i = ( i < 0 ? 0 : (i >=VTK_MAX_PLOTS ? VTK_MAX_PLOTS-1 : i)); + int val=this->XComponent->GetValue(i); + if ( val != comp ) + { + this->Modified(); + this->XComponent->SetValue(i,comp); + } +} + +//---------------------------------------------------------------------------- +int VISU_XYPlotActor::GetDataObjectXComponent(int i) +{ + i = ( i < 0 ? 0 : (i >=VTK_MAX_PLOTS ? VTK_MAX_PLOTS-1 : i)); + return this->XComponent->GetValue(i); +} + +//---------------------------------------------------------------------------- +void VISU_XYPlotActor::SetDataObjectYComponent(int i, int comp) +{ + i = ( i < 0 ? 0 : (i >=VTK_MAX_PLOTS ? VTK_MAX_PLOTS-1 : i)); + int val=this->YComponent->GetValue(i); + if ( val != comp ) + { + this->Modified(); + this->YComponent->SetValue(i,comp); + } +} + +//---------------------------------------------------------------------------- +int VISU_XYPlotActor::GetDataObjectYComponent(int i) +{ + i = ( i < 0 ? 0 : (i >=VTK_MAX_PLOTS ? VTK_MAX_PLOTS-1 : i)); + return this->YComponent->GetValue(i); +} + +//---------------------------------------------------------------------------- +void VISU_XYPlotActor::SetPointComponent(int i, int comp) +{ + i = ( i < 0 ? 0 : (i >=VTK_MAX_PLOTS ? VTK_MAX_PLOTS-1 : i)); + int val = this->XComponent->GetValue(i); + if ( val != comp ) + { + this->Modified(); + this->XComponent->SetValue(i,comp); + } +} + +//---------------------------------------------------------------------------- +int VISU_XYPlotActor::GetPointComponent(int i) +{ + i = ( i < 0 ? 0 : (i >=VTK_MAX_PLOTS ? VTK_MAX_PLOTS-1 : i)); + return this->XComponent->GetValue(i); +} + +//---------------------------------------------------------------------------- +double *VISU_XYPlotActor::TransformPoint(int pos[2], int pos2[2], + double x[3], double xNew[3]) +{ + // First worry about exchanging axes + if ( this->ExchangeAxes ) + { + double sx = (x[0]-pos[0]) / (pos2[0]-pos[0]); + double sy = (x[1]-pos[1]) / (pos2[1]-pos[1]); + xNew[0] = sy*(pos2[0]-pos[0]) + pos[0]; + xNew[1] = sx*(pos2[1]-pos[1]) + pos[1]; + xNew[2] = x[2]; + } + else + { + xNew[0] = x[0]; + xNew[1] = x[1]; + xNew[2] = x[2]; + } + + // Okay, now swap the axes around if reverse is on + if ( this->ReverseXAxis ) + { + xNew[0] = pos[0] + (pos2[0]-xNew[0]); + } + if ( this->ReverseYAxis ) + { + xNew[1] = pos[1] + (pos2[1]-xNew[1]); + } + + return xNew; +} + +//---------------------------------------------------------------------------- +void VISU_XYPlotActor::SetLabelFormat(const char* _arg) +{ + if (this->LabelFormat == NULL && _arg == NULL) + { + return; + } + + if (this->LabelFormat && _arg && (!strcmp(this->LabelFormat,_arg))) + { + return; + } + + if (this->LabelFormat) + { + delete [] this->LabelFormat; + } + + if (_arg) + { + this->LabelFormat = new char[strlen(_arg)+1]; + strcpy(this->LabelFormat,_arg); + } + else + { + this->LabelFormat = NULL; + } + + this->XAxis->SetLabelFormat(this->LabelFormat); + this->YAxis->SetLabelFormat(this->LabelFormat); + + this->Modified(); +} + +//---------------------------------------------------------------------------- +void VISU_XYPlotActor::PrintAsCSV(ostream &os) +{ + vtkDataArray *scalars; + vtkDataSet *ds; + vtkCollectionSimpleIterator dsit; + double s; + int dsNum,component; + for ( dsNum=0, this->InputList->InitTraversal(dsit); + (ds = this->InputList->GetNextDataSet(dsit)); dsNum++ ) + { + vtkIdType numPts = ds->GetNumberOfPoints(); + scalars = ds->GetPointData()->GetScalars(this->SelectedInputScalars[dsNum]); + component = this->SelectedInputScalarsComponent->GetValue(dsNum); + for ( vtkIdType ptId=0; ptId < numPts; ptId++ ) + { + s = scalars->GetComponent(ptId, component); + if( ptId == 0 ) + { + os << s; + } + else + { + os << "," << s; + } + } + os << endl; + } +} + diff --git a/src/PIPELINE/VISU_XYPlotActor.hxx b/src/PIPELINE/VISU_XYPlotActor.hxx new file mode 100644 index 00000000..5345d8e8 --- /dev/null +++ b/src/PIPELINE/VISU_XYPlotActor.hxx @@ -0,0 +1,607 @@ +// VISU OBJECT : interactive object for VISU entities implementation +// +// Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// +// +// File: VISU_XYPlotActor.hxx +// Author: Roman KOZLOV +// Module : VISU + +#ifndef VISU_XYPLOTACTOR_HXX_ +#define VISU_XYPLOTACTOR_HXX_ + +#include "VISUPipeline.hxx" + +/*========================================================================= + + Program: Visualization Toolkit + Module: $RCSfile$ + + 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. + +=========================================================================*/ +// .NAME vtkXYPlotActor - generate an x-y plot from input dataset(s) or field data +// .SECTION Description +// vtkXYPlotActor creates an x-y plot of data from one or more input data +// sets or field data. The class plots dataset scalar values (y-axis) against +// the points (x-axis). The x-axis values are generated by taking the point +// ids, computing a cumulative arc length, or a normalized arc length. More +// than one input data set can be specified to generate multiple plots. +// Alternatively, if field data is supplied as input, the class plots one +// component against another. (The user must specify which component to use +// as the x-axis and which for the y-axis.) +// +// To use this class to plot dataset(s), you must specify one or more +// input datasets containing scalar and point data. You'll probably also +// want to invoke a method to control how the point coordinates are converted +// into x values (by default point ids are used). +// +// To use this class to plot field data, you must specify one or more input +// data objects with its associated field data. You'll also want to specify +// which component to use as the x-axis and which to use as the y-axis. +// Note that when plotting field data, the x and y values are used directly +// (i.e., there are no options to normalize the components). +// +// Once you've set up the plot, you'll want to position it. The +// PositionCoordinate defines the lower-left location of the x-y plot +// (specified in normalized viewport coordinates) and the Position2Coordinate +// define the upper-right corner. (Note: the Position2Coordinate is relative +// to PositionCoordinate, so you can move the vtkXYPlotActor around the +// viewport by setting just the PositionCoordinate.) The combination of the +// two position coordinates specifies a rectangle in which the plot will lie. +// +// Optional features include the ability to specify axes labels, label +// format and plot title. You can also +// manually specify the x and y plot ranges (by default they are computed +// automatically). The Border instance variable is used to create space +// between the boundary of the plot window (specified by PositionCoordinate +// and Position2Coordinate) and the plot itself. +// +// The font property of the plot title can be modified through the +// TitleTextProperty attribute. +// The font property of the axes titles and labels can be modified through the +// AxisTitleTextProperty and AxisLabelTextProperty attributes. You may also +// use the GetXAxisActor2D or GetYAxisActor2D methods +// to access each individual axis actor to modify their font properties. +// In the same way, the GetLegendBoxActor method can be used to access +// the legend box actor to modify its font properties. +// +// There are several advanced features as well. You can assign per curve +// properties (such as color and a plot symbol). (Note that each input +// dataset and/or data object creates a single curve.) Another option is to +// add a plot legend that graphically indicates the correspondance between +// the curve, curve symbols, and the data source. You can also exchange the +// x and y axes if you prefer you plot orientation that way. + +// .SECTION Caveats +// If you are interested in plotting something other than scalar data, you +// can use the vtk data shuffling filters (e.g., +// vtkAttributeDataToFieldDataFilter and vtkFieldDataToAttributeDataFilter) +// to convert the data into scalar data and/or points. + +// .SECTION See Also +// vtkActor2D vtkTextMapper vtkScalarBarActor vtkAxisActor2D vtkCubeAxesActor2D +// vtkAttributeDataToFieldDataFilter vtkFieldDataToAttributeDataFilter +// vtkTextProperty + +#include "vtkActor2D.h" +#include "vtkTransformPolyDataFilter.h" // RKV + +#define VTK_XYPLOT_INDEX 0 +#define VTK_XYPLOT_ARC_LENGTH 1 +#define VTK_XYPLOT_NORMALIZED_ARC_LENGTH 2 +#define VTK_XYPLOT_VALUE 3 + +#define VTK_XYPLOT_ROW 0 +#define VTK_XYPLOT_COLUMN 1 + +class vtkAppendPolyData; +class vtkAxisActor2D; +class vtkDataObject; +class vtkDataObjectCollection; +class vtkDataSet; +class vtkDataSetCollection; +class vtkGlyph2D; +class vtkGlyphSource2D; +class vtkIntArray; +class vtkLegendBoxActor; +class vtkPlanes; +class vtkPolyData; +class vtkPolyDataMapper2D; +class vtkTextMapper; +class vtkTextProperty; + +// RKV : Begin +/** Location of the actor in the viewport. + * Axes and a curve is plotted according to the selected side. + * Axes origin is plotted at: + * VISU_XYPLOT_BOTTOM - the left bottom corner, + * VISU_XYPLOT_TOP - the left upper corner (Y axis is directed to the bottom), + * VISU_XYPLOT_LEFT - the left bottom corner (axes are exchanged), + * VISU_XYPLOT_RIGHT - the right bottom corner (X axis is directed to the top, Y - to the left) + */ +enum VISU_XYPlotLocation { VISU_XYPLOT_BOTTOM = 0, + VISU_XYPLOT_TOP, VISU_XYPLOT_LEFT, VISU_XYPLOT_RIGHT }; +// RKV : End + +class VISU_PIPELINE_EXPORT VISU_XYPlotActor : public vtkActor2D +{ +public: + vtkTypeRevisionMacro(VISU_XYPlotActor,vtkActor2D); + void PrintSelf(ostream& os, vtkIndent indent); + + // Description: + // Instantiate object with autorange computation; bold, italic, and shadows + // on; arial font family; the number of labels set to 5 for the x and y + // axes; a label format of "%-#6.3g"; and x coordinates computed from point + // ids. + static VISU_XYPlotActor *New(); + + //---Data Set Input---------------------------------------------------------- + // The following methods are used to plot input datasets. Datasets + // will be plotted if set as input; otherwise the input data objects + // will be plotted (if defined). + + // Description: + // Add a dataset to the list of data to append. The array name specifies + // which point array to plot. If the array name is NULL, then the default + // scalars are used. The array can have multiple components, but only the + // first component is ploted. + void AddInput(vtkDataSet *in, const char* arrayName, int component); + void AddInput(vtkDataSet *in) {this->AddInput(in, NULL, 0);} + + // Description: + // Remove a dataset from the list of data to append. + void RemoveInput(vtkDataSet *in, const char* arrayName, int component); + void RemoveInput(vtkDataSet *in) {this->RemoveInput(in, NULL, 0);} + + // Description: + // This removes all of the data set inputs, + // but does not change the data object inputs. + void RemoveAllInputs(); + + // Description: + // Return the list of inputs to this filter. + vtkDataSetCollection *GetInputList() {return this->InputList;} + + // Description: + // If plotting points by value, which component to use to determine the + // value. This sets a value per each input dataset (i.e., the ith dataset). + void SetPointComponent(int i, int comp); + int GetPointComponent(int i); + //---end Data Set Input----------------------------------------------------- + + // Description: + // Specify how the independent (x) variable is computed from the points. + // The independent variable can be the scalar/point index (i.e., point id), + // the accumulated arc length along the points, the normalized arc length, + // or by component value. If plotting datasets (e.g., points), the value + // that is used is specified by the PointComponent ivar. (Note: these + // methods also control how field data is plotted. Field data is usually + // plotted by value or index, if plotting length 1-dimensional length + // measures are used.) + vtkSetClampMacro(XValues,int,VTK_XYPLOT_INDEX,VTK_XYPLOT_VALUE); + vtkGetMacro(XValues,int); + void SetXValuesToIndex(){this->SetXValues(VTK_XYPLOT_INDEX);}; + void SetXValuesToArcLength() {this->SetXValues(VTK_XYPLOT_ARC_LENGTH);}; + void SetXValuesToNormalizedArcLength() + {this->SetXValues(VTK_XYPLOT_NORMALIZED_ARC_LENGTH);}; + void SetXValuesToValue() {this->SetXValues(VTK_XYPLOT_VALUE);}; + const char *GetXValuesAsString(); + + //---Data Object Input------------------------------------------------------ + // The following methods are used to plot input data objects. Datasets will + // be plotted in preference to data objects if set as input; otherwise the + // input data objects will be plotted (if defined). + + // Description: + // Add a dataset to the list of data to append. + void AddDataObjectInput(vtkDataObject *in); + + // Description: + // Remove a dataset from the list of data to append. + void RemoveDataObjectInput(vtkDataObject *in); + + // Description: + // Return the list of inputs to this filter. + vtkDataObjectCollection *GetDataObjectInputList() + {return this->DataObjectInputList;} + + // Description: + // Indicate whether to plot rows or columns. If plotting rows, then + // the dependent variables is taken from a specified row, + // versus rows (y). + vtkSetClampMacro(DataObjectPlotMode,int,VTK_XYPLOT_ROW,VTK_XYPLOT_COLUMN); + vtkGetMacro(DataObjectPlotMode,int); + void SetDataObjectPlotModeToRows() + {this->SetDataObjectPlotMode(VTK_XYPLOT_ROW);} + void SetDataObjectPlotModeToColumns() + {this->SetDataObjectPlotMode(VTK_XYPLOT_COLUMN);} + const char *GetDataObjectPlotModeAsString(); + + // Description: + // Specify which component of the input data object to use as the + // independent variable for the ith input data object. (This ivar is + // ignored if plotting the index.) Note that the value is interpreted + // differently depending on DataObjectPlotMode. If the mode is Rows, then + // the value of DataObjectXComponent is the row number; otherwise it's the + // column number. + void SetDataObjectXComponent(int i, int comp); + int GetDataObjectXComponent(int i); + + // Description: + // Specify which component of the input data object to use as the + // dependent variable for the ith input data object. (This ivar is + // ignored if plotting the index.) Note that the value is interpreted + // differently depending on DataObjectPlotMode. If the mode is Rows, then + // the value of DataObjectYComponent is the row number; otherwise it's the + // column number. + void SetDataObjectYComponent(int i, int comp); + int GetDataObjectYComponent(int i); + //---end Data Object Input-------------------------------------------------- + + //---Per Curve Properties--------------------------------------------------- + // The following methods are used to set properties on each curve that is + // plotted. Each input dataset (or data object) results in one curve. The + // methods that follow have an index i that corresponds to the input dataset + // or data object. + void SetPlotColor(int i, double r, double g, double b); + void SetPlotColor(int i, const double color[3]) { + this->SetPlotColor(i, color[0], color[1], color[2]); }; + double *GetPlotColor(int i); + void SetPlotSymbol(int i,vtkPolyData *input); + vtkPolyData *GetPlotSymbol(int i); + void SetPlotLabel(int i, const char *label); + const char *GetPlotLabel(int i); + + // Allow per-curve specification of line and point rendering. These override + // global settings PlotPoints and PlotLines. If not on, the default behavior + // is governed by PlotPoints and PlotLines ivars. + vtkGetMacro(PlotCurvePoints, int); + vtkSetMacro(PlotCurvePoints, int); + vtkBooleanMacro(PlotCurvePoints, int); + + vtkGetMacro(PlotCurveLines, int); + vtkSetMacro(PlotCurveLines, int); + vtkBooleanMacro(PlotCurveLines, int); + + void SetPlotLines(int i, int); + int GetPlotLines(int i); + + void SetPlotPoints(int i, int); + int GetPlotPoints(int i); + //---end Per Curve Properties----------------------------------------------- + + // Description: + // Enable/Disable exchange of the x-y axes (i.e., what was x becomes y, and + // vice-versa). Exchanging axes affects the labeling as well. + vtkSetMacro(ExchangeAxes, int); + vtkGetMacro(ExchangeAxes, int); + vtkBooleanMacro(ExchangeAxes, int); + + // Description: + // Normally the x-axis is plotted from minimum to maximum. Setting this instance + // variable causes the x-axis to be plotted from maximum to minimum. Note that + // boolean always applies to the x-axis even if ExchangeAxes is set. + vtkSetMacro(ReverseXAxis, int); + vtkGetMacro(ReverseXAxis, int); + vtkBooleanMacro(ReverseXAxis, int); + + // Description: + // Normally the y-axis is plotted from minimum to maximum. Setting this instance + // variable causes the y-axis to be plotted from maximum to minimum. Note that + // boolean always applies to the y-axis even if ExchangeAxes is set. + vtkSetMacro(ReverseYAxis, int); + vtkGetMacro(ReverseYAxis, int); + vtkBooleanMacro(ReverseYAxis, int); + + // Description: + // Retrieve handles to the legend box and glyph source. This is useful + // if you would like to change the default behavior of the legend box + // or glyph source. For example, the default glyph can be changed from + // a line to a vertex plus line, etc.) + vtkGetObjectMacro(LegendActor,vtkLegendBoxActor); + vtkGetObjectMacro(GlyphSource,vtkGlyphSource2D); + + // Description: + // Set/Get the title of the x-y plot, and the title along the + // x and y axes. + vtkSetStringMacro(Title); + vtkGetStringMacro(Title); + vtkSetStringMacro(XTitle); + vtkGetStringMacro(XTitle); + vtkSetStringMacro(YTitle); + vtkGetStringMacro(YTitle); + + // Description: + // Retrieve handles to the X and Y axis (so that you can set their text + // properties for example) + vtkAxisActor2D *GetXAxisActor2D() + {return this->XAxis;} + vtkAxisActor2D *GetYAxisActor2D() + {return this->YAxis;} + + // Description: + // Set the plot range (range of independent and dependent variables) + // to plot. Data outside of the range will be clipped. If the plot + // range of either the x or y variables is set to (v1,v2), where + // v1 == v2, then the range will be computed automatically. Note that + // the x-range values should be consistent with the way the independent + // variable is created (via INDEX, DISTANCE, or ARC_LENGTH). + vtkSetVector2Macro(XRange,double); + vtkGetVectorMacro(XRange,double,2); + vtkSetVector2Macro(YRange,double); + vtkGetVectorMacro(YRange,double,2); + void SetPlotRange(double xmin, double ymin, double xmax, double ymax) + {this->SetXRange(xmin,xmax); this->SetYRange(ymin,ymax);} + + // Description: + // Set/Get the number of annotation labels to show along the x and y axes. + // This values is a suggestion: the number of labels may vary depending + // on the particulars of the data. The convenience method + // SetNumberOfLables() sets the number of x and y labels to the same value. + vtkSetClampMacro(NumberOfXLabels, int, 0, 50); + vtkGetMacro(NumberOfXLabels, int); + vtkSetClampMacro(NumberOfYLabels, int, 0, 50); + vtkGetMacro(NumberOfYLabels, int); + void SetNumberOfLabels(int num) + {this->SetNumberOfXLabels(num); this->SetNumberOfYLabels(num);} + + // Description: + // Enable/Disable the creation of a legend. If on, the legend labels will + // be created automatically unless the per plot legend symbol has been + // set. + vtkSetMacro(Legend, int); + vtkGetMacro(Legend, int); + vtkBooleanMacro(Legend, int); + + // Description: + // Use these methods to control the position of the legend. The variables + // LegendPosition and LegendPosition2 define the lower-left and upper-right + // position of the legend. The coordinates are expressed as normalized + // values with respect to the rectangle defined by PositionCoordinate and + // Position2Coordinate. Note that LegendPosition2 is relative to + // LegendPosition. + vtkSetVector2Macro(LegendPosition,double); + vtkGetVector2Macro(LegendPosition,double); + vtkSetVector2Macro(LegendPosition2,double); + vtkGetVector2Macro(LegendPosition2,double); + + // Description: + // Set/Get the title text property. + virtual void SetTitleTextProperty(vtkTextProperty *p); + vtkGetObjectMacro(TitleTextProperty,vtkTextProperty); + + // Description: + // Set/Get the title text property of all axes. Note that each axis can + // be controlled individually through the GetX/YAxisActor2D() methods. + virtual void SetAxisTitleTextProperty(vtkTextProperty *p); + vtkGetObjectMacro(AxisTitleTextProperty,vtkTextProperty); + + // Description: + // Set/Get the labels text property of all axes. Note that each axis can + // be controlled individually through the GetX/YAxisActor2D() methods. + virtual void SetAxisLabelTextProperty(vtkTextProperty *p); + vtkGetObjectMacro(AxisLabelTextProperty,vtkTextProperty); + + // Description: + // Enable/Disable plotting of Log of x-values. + vtkSetMacro(Logx, int); + vtkGetMacro(Logx, int); + vtkBooleanMacro(Logx, int); + + // Description: + // Set/Get the format with which to print the labels on the scalar + // bar. + virtual void SetLabelFormat (const char* _arg); + vtkGetStringMacro(LabelFormat); + + // Description: + // Set/Get the spacing between the plot window and the plot. The value + // is specified in pixels. + vtkSetClampMacro(Border, int, 0, 50); + vtkGetMacro(Border, int); + + // Description: + // Set/Get whether the points are rendered. The point size can be set in + // the property object. This is a global flag which affects the plot only + // if per curve symbols are not defined. + vtkGetMacro(PlotPoints, int); + vtkSetMacro(PlotPoints, int); + vtkBooleanMacro(PlotPoints, int); + + // Description: + // Set/Get whether the lines are rendered. The line width can be set in + // the property object. + vtkGetMacro(PlotLines, int); + vtkSetMacro(PlotLines, int); + vtkBooleanMacro(PlotLines, int); + + // RKV : Begin + // Description: + // Set/Get the location in the viewport + vtkGetMacro(PlotLocation, VISU_XYPlotLocation); + vtkSetMacro(PlotLocation, VISU_XYPlotLocation); + // RKV : End + + // Description: + // Set/Get the factor that controls how big glyphs are in the plot. + // The number is expressed as a fraction of the length of the diagonal + // of the plot bounding box. + vtkSetClampMacro(GlyphSize, double, 0.0, 0.2); + vtkGetMacro(GlyphSize, double); + + // Description: + // Given a position within the viewport used by the plot, return the + // the plot coordinates (XAxis value, YAxis value) + void ViewportToPlotCoordinate(vtkViewport *viewport, double &u, double &v); + + // Description: + // An alternate form of ViewportToPlotCoordinate() above. This method + // inputs the viewport coordinate pair (defined by the ivar + // ViewportCoordinate)and then stores them in the ivar PlotCoordinate. + void ViewportToPlotCoordinate(vtkViewport *viewport); + vtkSetVector2Macro(PlotCoordinate,double); + vtkGetVector2Macro(PlotCoordinate,double); + + // Description: + // Given a plot coordinate, return the viewpoint position + void PlotToViewportCoordinate(vtkViewport *viewport, double &u, double &v); + + // Description: + // An alternate form of PlotToViewportCoordinate() above. This method + // inputs the plot coordinate pair (defined in the ivar PlotCoordinate) + // and then stores them in the ivar ViewportCoordinate. (This method + // can be wrapped.) + void PlotToViewportCoordinate(vtkViewport *viewport); + vtkSetVector2Macro(ViewportCoordinate,double); + vtkGetVector2Macro(ViewportCoordinate,double); + + // Description: + // Is the specified viewport position within the plot area (as opposed to the + // region used by the plot plus the labels)? + int IsInPlot(vtkViewport *viewport, double u, double v); + + // Description: + // Take into account the modified time of internal helper classes. + unsigned long GetMTime(); + + // Description: + // Write the XY Ploat Actor as a CSV (comma separated value) representation. + void PrintAsCSV(ostream &os); + +//BTX + // Description: + // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE + // DO NOT USE THIS METHOD OUTSIDE OF THE RENDERING PROCESS. + // Draw the x-y plot. + int RenderOpaqueGeometry(vtkViewport*); + int RenderOverlay(vtkViewport*); + int RenderTranslucentGeometry(vtkViewport *) {return 0;} + + // Description: + // Release any graphics resources that are being consumed by this actor. + // The parameter window could be used to determine which graphic + // resources to release. + void ReleaseGraphicsResources(vtkWindow *); +//ETX + +protected: + VISU_XYPlotActor(); + ~VISU_XYPlotActor(); + + vtkDataSetCollection *InputList; //list of data sets to plot + char** SelectedInputScalars; // list of data set arrays to plot + vtkIntArray* SelectedInputScalarsComponent; // list of componenents + vtkDataObjectCollection *DataObjectInputList; //list of data objects to plot + char *Title; + char *XTitle; + char *YTitle; + int XValues; + int NumberOfXLabels; + int NumberOfYLabels; + int Logx; + char *LabelFormat; + double XRange[2]; + double YRange[2]; + double XComputedRange[2]; //range actually used by plot + double YComputedRange[2]; //range actually used by plot + int Border; + int PlotLines; + int PlotPoints; + int PlotCurveLines; + int PlotCurvePoints; + int ExchangeAxes; + int ReverseXAxis; + int ReverseYAxis; + + vtkTextMapper *TitleMapper; + vtkActor2D *TitleActor; + vtkTextProperty *TitleTextProperty; + + vtkAxisActor2D *XAxis; + vtkAxisActor2D *YAxis; + + vtkTextProperty *AxisTitleTextProperty; + vtkTextProperty *AxisLabelTextProperty; + + double ViewportCoordinate[2]; + double PlotCoordinate[2]; + + //Handle data objects and datasets + int DataObjectPlotMode; + vtkIntArray *XComponent; + vtkIntArray *YComponent; + vtkIntArray *LinesOn; + vtkIntArray *PointsOn; + + //The data drawn within the axes. Each curve is one polydata. + //color is controlled by scalar data. The curves are appended + //together, possibly glyphed with point symbols. + int NumberOfInputs; + vtkPolyData **PlotData; + vtkGlyph2D **PlotGlyph; + vtkAppendPolyData **PlotAppend; + vtkTransformPolyDataFilter **PlotTransform; // RKV + vtkPolyDataMapper2D **PlotMapper; + vtkActor2D **PlotActor; + void InitializeEntries(); + + // Legends and plot symbols. The legend also keeps track of + // the symbols and such. + int Legend; + double LegendPosition[2]; + double LegendPosition2[2]; + vtkLegendBoxActor *LegendActor; + vtkGlyphSource2D *GlyphSource; + vtkPlanes *ClipPlanes; + double GlyphSize; + + // Keep track of changes. + VISU_XYPlotLocation PlotLocation; // RKV + int CachedSize[2]; + vtkTimeStamp BuildTime; + + void ComputeXRange(double range[2], double *lengths); + void ComputeYRange(double range[2]); + void ComputeDORange(double xrange[2], double yrange[2], double *lengths); + + virtual void CreatePlotData(int *pos, int *pos2, double xRange[2], + double yRange[2], double *norms, + int numDS, int numDO); + void PlaceAxes(vtkViewport *viewport, int *size, int pos[2], int pos2[2]); + void GenerateClipPlanes(int *pos, int *pos2); + double ComputeGlyphScale(int i, int *pos, int *pos2); + void ClipPlotData(int *pos, int *pos2, vtkPolyData *pd); + double *TransformPoint(int pos[2], int pos2[2], double x[3], double xNew[3]); + +private: + VISU_XYPlotActor(const VISU_XYPlotActor&); // Not implemented. + void operator=(const VISU_XYPlotActor&); // Not implemented. +}; + + +#endif /*VISU_XYPLOTACTOR_HXX_*/