Commit 6690c9e9 authored by Mathieu Westphal's avatar Mathieu Westphal

Redesign the PlotLine and PlotPoint BadPoint algorithm

This fixes an issue with BadPoints hiding other points
Fix #17687

This redesign the algorithm so it is more consise
This also add a test and update a faulty baseline
parent 136f119d
......@@ -50,6 +50,7 @@ vtk_add_test_cxx(${vtk-module}CxxTests tests
TestBoxPlot2.cxx
TestCategoryLegend.cxx
TestColorTransferFunction.cxx
TestChartBadPoints.cxx
TestChartDouble.cxx
TestChartDoubleColors.cxx
TestChartMatrix.cxx
......
/*=========================================================================
Program: Visualization Toolkit
Module: TestChartBadPoints.cxx
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#include "vtkChartXY.h"
#include "vtkContextScene.h"
#include "vtkContextView.h"
#include "vtkDoubleArray.h"
#include "vtkNew.h"
#include "vtkPlotLine.h"
#include "vtkPlotPoints.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkTable.h"
//----------------------------------------------------------------------------
int TestChartBadPoints(int, char* [])
{
// Set up a 2D scene, add an XY chart to it
vtkNew<vtkContextView> view;
view->GetRenderWindow()->SetSize(400, 300);
vtkNew<vtkChartXY> chart;
view->GetScene()->AddItem(chart.GetPointer());
// Create a table with polyline points
vtkNew<vtkTable> table;
vtkNew<vtkDoubleArray> arrX;
arrX->SetName("X");
table->AddColumn(arrX.Get());
vtkNew<vtkDoubleArray> arrC;
arrC->SetName("f1");
table->AddColumn(arrC.Get());
table->SetNumberOfRows(7);
table->SetValue(0, 0, 0);
table->SetValue(1, 0, 1);
table->SetValue(2, 0, 2);
table->SetValue(3, 0, 3);
table->SetValue(4, 0, 4);
table->SetValue(5, 0, 5);
table->SetValue(6, 0, 6);
table->SetValue(0, 1, 1.7);
table->SetValue(1, 1, 1.9);
table->SetValue(2, 1, vtkMath::Nan());
table->SetValue(3, 1, 2);
table->SetValue(4, 1, vtkMath::Nan());
table->SetValue(5, 1, 2.3);
table->SetValue(6, 1, 2.1);
// Create a table with non-polyline points
vtkNew<vtkTable> table2;
vtkNew<vtkDoubleArray> arrX2;
arrX2->SetName("X");
table2->AddColumn(arrX2.Get());
vtkNew<vtkDoubleArray> arrC2;
arrC2->SetName("f1");
table2->AddColumn(arrC2.Get());
table2->SetNumberOfRows(12);
table2->SetValue(0, 0, 0);
table2->SetValue(1, 0, 1);
table2->SetValue(2, 0, 1);
table2->SetValue(3, 0, 2);
table2->SetValue(4, 0, 2);
table2->SetValue(5, 0, 3);
table2->SetValue(6, 0, 3);
table2->SetValue(7, 0, 4);
table2->SetValue(8, 0, 4);
table2->SetValue(9, 0, 5);
table2->SetValue(10, 0, 5);
table2->SetValue(11, 0, 6);
table2->SetValue(0, 1, 3.7);
table2->SetValue(1, 1, 3.9);
table2->SetValue(2, 1, 3.9);
table2->SetValue(3, 1, vtkMath::Nan());
table2->SetValue(4, 1, vtkMath::Nan());
table2->SetValue(5, 1, 4);
table2->SetValue(6, 1, 5);
table2->SetValue(7, 1, vtkMath::Nan());
table2->SetValue(8, 1, vtkMath::Nan());
table2->SetValue(9, 1, 5.3);
table2->SetValue(10, 1, 5.3);
table2->SetValue(11, 1, 4.3);
// Add multiple line and point plots
vtkNew<vtkPlotPoints> points;
chart->AddPlot(points.Get());
points->SetInputData(table.Get(), 0, 1);
points->SetMarkerSize(10.0);
vtkNew<vtkPlotLine> line;
chart->AddPlot(line.Get());
line->SetInputData(table.Get(), 0, 1);
vtkNew<vtkPlotLine> line2;
line2->SetPolyLine(false);
chart->AddPlot(line2.Get());
line2->SetInputData(table2.Get(), 0, 1);
// Render the scene and compare the image to a reference image
view->GetRenderWindow()->SetMultiSamples(0);
view->GetInteractor()->Initialize();
view->GetInteractor()->Start();
return EXIT_SUCCESS;
}
82a872f37c87f91e68b161e6f03bdf0e
618be98cca9191fb645ba4450c8457ed
......@@ -58,74 +58,38 @@ bool vtkPlotLine::Paint(vtkContext2D *painter)
float *points = static_cast<float *>(this->Points->GetVoidPointer(0));
const int pointSize = 2;
vtkIdType lastGood = 0;
vtkIdType bpIdx = 0;
vtkIdType lineIncrement = this->PolyLine ? 1 : 2;
vtkIdType nPoints = this->Points->GetNumberOfPoints();
vtkIdType nBadPoints = this->BadPoints->GetNumberOfTuples();
for (vtkIdType i = 0; i < this->BadPoints->GetNumberOfTuples(); i++)
while (lastGood < nPoints)
{
vtkIdType id = this->BadPoints->GetValue(i);
vtkIdType id = bpIdx < nBadPoints ?
this->BadPoints->GetValue(bpIdx) : this->Points->GetNumberOfPoints();
// With non polyline, we discard a line if any of its points are bad
if (!this->PolyLine && id % 2 == 1)
{
id--;
}
// render from last good point to one before this bad point
if (id - lastGood > 2)
if (id - lastGood > 1)
{
int start = lastGood + 1;
int start = lastGood;
int numberOfPoints = id - start;
if (!this->PolyLine)
{
// Start at the next point if the last bad point was the first point
// of a line segment.
if (start % 2 == 0)
{
++start;
--numberOfPoints;
}
// Stops at the previous point if the next bad point is the second point
// of a line segment.
if (numberOfPoints % 2 == 1)
{
--numberOfPoints;
}
}
if (this->PolyLine)
{
painter->DrawPoly(points + pointSize * start, numberOfPoints);
}
else if (start < this->Points->GetNumberOfPoints() && numberOfPoints > 0)
else
{
painter->DrawLines(points + pointSize * start, numberOfPoints);
}
}
lastGood = id;
}
// render any trailing good points
if (this->Points->GetNumberOfPoints() - lastGood > 2)
{
int start = lastGood + 1;
int numberOfPoints = this->Points->GetNumberOfPoints() - start;
if (!this->PolyLine)
{
// Start at the next point if the last bad point was the first point
// of a line segment.
if (start % 2 == 0)
{
++start;
--numberOfPoints;
}
// Stops at the previous point if the next bad point is the second point
// of a line segment.
if (numberOfPoints % 2 == 1)
{
--numberOfPoints;
}
}
if (this->PolyLine)
{
painter->DrawPoly(points + pointSize * start, numberOfPoints);
}
else if (start < this->Points->GetNumberOfPoints() && numberOfPoints > 0)
{
painter->DrawLines(points + pointSize * start, numberOfPoints);
}
lastGood = id + lineIncrement;
bpIdx++;
}
}
else
......
......@@ -195,33 +195,27 @@ bool vtkPlotPoints::Paint(vtkContext2D *painter)
if (this->BadPoints && this->BadPoints->GetNumberOfTuples() > 0)
{
vtkIdType lastGood = 0;
vtkIdType bpIdx = 0;
vtkIdType nPoints = this->Points->GetNumberOfPoints();
vtkIdType nBadPoints = this->BadPoints->GetNumberOfTuples();
for (vtkIdType i = 0; i < this->BadPoints->GetNumberOfTuples(); i++)
while (lastGood < nPoints)
{
vtkIdType id = this->BadPoints->GetValue(i);
vtkIdType id = bpIdx < nBadPoints ?
this->BadPoints->GetValue(bpIdx) : this->Points->GetNumberOfPoints();
// render from last good point to one before this bad point
if (id - lastGood > 2)
if (id - lastGood > 0)
{
painter->DrawMarkers(this->MarkerStyle, false,
points + 2 * (lastGood + 1),
id - lastGood - 1,
colors ? colors + 4 * (lastGood + 1) : nullptr,
points + 2 * (lastGood),
id - lastGood,
colors ? colors + 4 * (lastGood) : nullptr,
nColorComponents);
}
lastGood = id;
lastGood = id + 1;
bpIdx++;
}
// render any trailing good points
if (this->Points->GetNumberOfPoints() - lastGood > 2)
{
painter->DrawMarkers(this->MarkerStyle, false,
points + 2 * (lastGood + 1),
this->Points->GetNumberOfPoints() - lastGood - 1,
colors ? colors + 4 * (lastGood + 1) : nullptr,
nColorComponents);
}
}
else
{
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment