Hello,
I am using vtkGlyph2D to plot a vector field (e.g., vtkExample: VectorField) and using vtkImageMapToColors to plot color contour of a scalar field (e.g., vtkExample: ImageMapToColors). I put the actor for the vector field and actor for the color contour in the same renderer to create a 2D plot that has the vector field overlay on the color contour. However, I observed that when the vectors are over darker contour colors, they have white outline surrounding them. Please see the image below.
Image after zoom-in:
I set the diffusive and specular parameters both to zero in the vector actor, but it didn’t work. So it is not the lighting issue. I used different colors for the color contour other than the grayscale color in the figure above. The white outline still exists. I set the vectors to colors other than black. The white outline still exists.
Please advise on how to get rid of the white outlines. Thanks so much in advance!
Below please see the code:
#include <iostream>
#include <sstream>
#include <tuple>
#include <vtkArrowSource.h>
#include <vtkCamera.h>
#include <vtkDoubleArray.h>
#include <vtkExtractVectorComponents.h>
#include <vtkGlyph2D.h>
#include <vtkImageActor.h>
#include <vtkImageData.h>
#include <vtkImageMapToColors.h>
#include <vtkImageMapper.h>
#include <vtkImageSlice.h>
#include <vtkImageSliceMapper.h>
#include <vtkInteractorStyleImage.h>
#include <vtkLookupTable.h>
#include <vtkNamedColors.h>
#include <vtkNew.h>
#include <vtkPointData.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkTextProperty.h>
#include <vtkUnsignedCharArray.h>
int main(int, char*[])
{
// Define vector field parameters
double Nx = 20;
double Ny = 20;
double Nt = Nx * Ny;
double x_st = -400;
double y_st = -400;
double dx = 40;
double dy = 40;
double ratio_aspect = dx / dy;
double center_x = Nx * dx / 2;
double center_y = Ny * dy / 2;
double velo_ratio = 0.005;
double x_ed = x_st + (Nx - 1) * dx;
double y_ed = y_st + (Ny - 1) * dy;
vtkNew<vtkNamedColors> colors;
vtkColor3d backgroundColor = colors->GetColor3d("White");
// Create image data. "image" for vector field, "image1" for color contour
vtkNew<vtkImageData> image;
vtkNew<vtkImageData> image1;
// Specify the size of the image data.
image->SetDimensions(Nx, Ny, 1);
image->SetSpacing(ratio_aspect, 1.0, 1.0);
image->SetOrigin(0, 0, 0);
image1->SetDimensions(Nx, Ny, 1);
image1->AllocateScalars(VTK_FLOAT, 1);
image1->SetSpacing(ratio_aspect, 1.0, 1.0);
image1->SetOrigin(0, 0, 0);
//fill data to image data
int* dims = image->GetDimensions();
double dist, velo, x_phy, y_phy;
vtkSmartPointer<vtkDoubleArray> u = vtkSmartPointer<vtkDoubleArray>::New();
u->SetName("u");
u->SetNumberOfComponents(3);
u->SetNumberOfTuples(Nt);
for (auto z = 0; z < dims[2]; ++z)
{
for (auto y = 0; y < dims[1]; ++y)
{
for (auto x = 0; x < dims[0]; ++x)
{
int idx = z * Nt + y * Nx + x;
x_phy = x * dx - center_x;
y_phy = y * dy - center_y;
dist = sqrt(x_phy * x_phy + y_phy * y_phy);
velo = dist * velo_ratio;
auto pixel = static_cast<float*>(image1->GetScalarPointer(x, y, z));
if (abs(dist) < 1e-5)
{
pixel[0] = 0.0;
u->SetTuple3(idx, 0.0, 0.0, 0.0);
}
else
{
pixel[0] = y_phy / dist * velo;
u->SetTuple3(idx, y_phy / dist * velo, -x_phy / dist * velo, 0.0);
}
}
}
}
image->GetPointData()->SetVectors(u);
// Setup the arrows
vtkNew<vtkArrowSource> arrowSource;
arrowSource->Update();
vtkNew<vtkGlyph2D> glyphFilter;
glyphFilter->SetSourceConnection(arrowSource->GetOutputPort());
glyphFilter->OrientOn();
glyphFilter->SetScaleModeToScaleByVector();
glyphFilter->ScalingOn();
glyphFilter->SetVectorModeToUseVector();
glyphFilter->SetInputData(image);
glyphFilter->Update();
// color
// Map the scalar values in the image to colors with a lookup table:
vtkNew<vtkLookupTable> lookupTable;
lookupTable->SetHueRange(0, 0);
lookupTable->SetSaturationRange(0, 0);
lookupTable->SetValueRange(0.2, 1.0);
lookupTable->SetNumberOfColors(256);
lookupTable->SetHueRange(0.0, 0.667);
lookupTable->SetRange(image1->GetScalarRange());
lookupTable->Build();
// Pass the original image and the lookup table to a filter to create
// a color image:
vtkNew<vtkImageMapToColors> scalarValuesToColors;
scalarValuesToColors->SetLookupTable(lookupTable);
scalarValuesToColors->PassAlphaToOutputOn();
scalarValuesToColors->SetInputData(image1);
scalarValuesToColors->Update();
// Create color contour actor.
vtkNew<vtkImageActor> imageActor;
imageActor->GetMapper()->SetInputConnection(scalarValuesToColors->GetOutputPort());
// vector actor
vtkNew<vtkPolyDataMapper> vectorMapper;
vectorMapper->SetInputConnection(glyphFilter->GetOutputPort());
vtkNew<vtkActor> vectorActor;
vectorActor->SetMapper(vectorMapper);
vectorActor->GetProperty()->SetColor(colors->GetColor3d("Black").GetData());
// Setup renderer.
vtkNew<vtkRenderer> renderer;
renderer->AddViewProp(vectorActor);
renderer->AddActor(imageActor);
renderer->ResetCamera();
renderer->SetBackground(backgroundColor.GetData());
renderer->SetBackground(colors->GetColor3d("SlateGray").GetData());
// Setup render window.
vtkNew<vtkRenderWindow> renderWindow;
renderer->GetActiveCamera()->ParallelProjectionOn();
renderWindow->AddRenderer(renderer);
renderWindow->SetWindowName("VectorField and color contour");
// Setup render window interactor.
vtkNew<vtkRenderWindowInteractor> renderWindowInteractor;
vtkNew<vtkInteractorStyleImage> style;
renderWindowInteractor->SetInteractorStyle(style);
// Render and start interaction.
renderWindow->SetSize(1000, 1000);
renderWindowInteractor->SetRenderWindow(renderWindow);
renderer->ResetCamera();
renderWindow->Render();
renderWindowInteractor->Initialize();
renderWindowInteractor->Start();
return EXIT_SUCCESS;
}