Our current use case is to construct a piece-wise constant vtkColorTransferFunction, which I achieve by adding duplicate points for any x value where the function changes value: i.e., going from a constant green interval to a constant red interval would require the two points (x, 0, 1, 0) and (x, 1, 0, 0). If these two points then change order, I end up with a function that instead changes smoothly from green to red over the supposedly red interval, and then reverts to green again at the start of the next interval.
Perhaps this is not the optimal way to construct a piece-wise function in VTK, so we are happy also for pointers towards more suitable classes, but might have no other options due to also wanting to incorporate other types of functions into the same vtkColorTransferFunction.
Small code example (unfortunately quite a few nodes included, since the sorting changes with e.g. total number of nodes):
auto colorFunction = vtkSmartPointer<vtkColorTransferFunction>::New();
colorFunction->AllowDuplicateScalarsOn();
colorFunction->AddRGBPoint(0, 0, 0, 0);
colorFunction->AddRGBPoint(0.5, 0, 0, 0);
colorFunction->AddRGBPoint(0.5, 0, 1, 0);
colorFunction->AddRGBPoint(0.7, 0, 1, 0);
colorFunction->AddRGBPoint(0.7, 0, 0, 0);
colorFunction->AddRGBPoint(0.8, 0, 0, 0);
colorFunction->AddRGBPoint(0.8, 1, 0, 0);
colorFunction->AddRGBPoint(1.0, 1, 0, 0);
colorFunction->AddRGBPoint(1.0, 0.734069, 0.171569, 0.171569);
colorFunction->AddRGBPoint(1.1, 0.734069, 0.171569, 0.171569);
colorFunction->AddRGBPoint(1.1, 0.392157, 0.392157, 0.392157);
colorFunction->AddRGBPoint(1.15, 0.392157, 0.392157, 0.392157);
colorFunction->AddRGBPoint(1.15, 0.249554, 0.249554, 0.613191);
colorFunction->AddRGBPoint(1.2, 0.249554, 0.249554, 0.613191);
colorFunction->AddRGBPoint(1.2, 0, 0, 1);
colorFunction->AddRGBPoint(1.5, 0, 0, 1);
colorFunction->AddRGBPoint(1.4, 0, 0, 0);
colorFunction->AddRGBPoint(20, 0, 0, 0);
colorFunction->Print(std::cout);
auto colorFunction2 = vtkSmartPointer<vtkColorTransferFunction>::New();
colorFunction2->AllowDuplicateScalarsOn();
colorFunction2->DeepCopy(colorFunction);
colorFunction2->Print(std::cout);
Gives the following output:
0 X: 0 R: 0 G: 0 B: 0 Sharpness: 0 Midpoint: 0.5
1 X: 0.5 R: 0 G: 0 B: 0 Sharpness: 0 Midpoint: 0.5
2 X: 0.5 R: 0 G: 1 B: 0 Sharpness: 0 Midpoint: 0.5
3 X: 0.7 R: 0 G: 1 B: 0 Sharpness: 0 Midpoint: 0.5
4 X: 0.7 R: 0 G: 0 B: 0 Sharpness: 0 Midpoint: 0.5
5 X: 0.8 R: 0 G: 0 B: 0 Sharpness: 0 Midpoint: 0.5
6 X: 0.8 R: 1 G: 0 B: 0 Sharpness: 0 Midpoint: 0.5
7 X: 1 R: 0.734069 G: 0.171569 B: 0.171569 Sharpness: 0 Midpoint: 0.5
8 X: 1 R: 1 G: 0 B: 0 Sharpness: 0 Midpoint: 0.5
9 X: 1.1 R: 0.734069 G: 0.171569 B: 0.171569 Sharpness: 0 Midpoint: 0.5
10 X: 1.1 R: 0.392157 G: 0.392157 B: 0.392157 Sharpness: 0 Midpoint: 0.5
11 X: 1.15 R: 0.392157 G: 0.392157 B: 0.392157 Sharpness: 0 Midpoint: 0.5
12 X: 1.15 R: 0.249554 G: 0.249554 B: 0.613191 Sharpness: 0 Midpoint: 0.5
13 X: 1.2 R: 0.249554 G: 0.249554 B: 0.613191 Sharpness: 0 Midpoint: 0.5
14 X: 1.2 R: 0 G: 0 B: 1 Sharpness: 0 Midpoint: 0.5
15 X: 1.4 R: 0 G: 0 B: 0 Sharpness: 0 Midpoint: 0.5
16 X: 1.5 R: 0 G: 0 B: 1 Sharpness: 0 Midpoint: 0.5
17 X: 20 R: 0 G: 0 B: 0 Sharpness: 0 Midpoint: 0.5
0 X: 0 R: 0 G: 0 B: 0 Sharpness: 0 Midpoint: 0.5
1 X: 0.5 R: 0 G: 0 B: 0 Sharpness: 0 Midpoint: 0.5
2 X: 0.5 R: 0 G: 1 B: 0 Sharpness: 0 Midpoint: 0.5
3 X: 0.7 R: 0 G: 1 B: 0 Sharpness: 0 Midpoint: 0.5
4 X: 0.7 R: 0 G: 0 B: 0 Sharpness: 0 Midpoint: 0.5
5 X: 0.8 R: 0 G: 0 B: 0 Sharpness: 0 Midpoint: 0.5
6 X: 0.8 R: 1 G: 0 B: 0 Sharpness: 0 Midpoint: 0.5
7 X: 1 R: 1 G: 0 B: 0 Sharpness: 0 Midpoint: 0.5
8 X: 1 R: 0.734069 G: 0.171569 B: 0.171569 Sharpness: 0 Midpoint: 0.5
9 X: 1.1 R: 0.734069 G: 0.171569 B: 0.171569 Sharpness: 0 Midpoint: 0.5
10 X: 1.1 R: 0.392157 G: 0.392157 B: 0.392157 Sharpness: 0 Midpoint: 0.5
11 X: 1.15 R: 0.392157 G: 0.392157 B: 0.392157 Sharpness: 0 Midpoint: 0.5
12 X: 1.15 R: 0.249554 G: 0.249554 B: 0.613191 Sharpness: 0 Midpoint: 0.5
13 X: 1.2 R: 0.249554 G: 0.249554 B: 0.613191 Sharpness: 0 Midpoint: 0.5
14 X: 1.2 R: 0 G: 0 B: 1 Sharpness: 0 Midpoint: 0.5
15 X: 1.4 R: 0 G: 0 B: 0 Sharpness: 0 Midpoint: 0.5
16 X: 1.5 R: 0 G: 0 B: 1 Sharpness: 0 Midpoint: 0.5
17 X: 20 R: 0 G: 0 B: 0 Sharpness: 0 Midpoint: 0.5
Note how nodes 7 and 8 end up in “reversed” order upon initial insertion, but then end up permuted once more when DeepCopied.