AlexLuya
(Alex Luya)
March 12, 2023, 4:06pm
1
Hello,use these code:
/*
* @Creator : alex
* @Create at : Jan 6, 2022 5:53:08 PM
* @Modified by : alex
* @Modified at : Jan 6, 2022 5:53:08 PM
* @Description : SphereCellNormal.cpp
*/
#include <vtkVersion.h>
#include <vtkSmartPointer.h>
#include <vtkSurfaceReconstructionFilter.h>
#include <vtkProgrammableSource.h>
#include <vtkContourFilter.h>
#include <vtkReverseSense.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkPolyData.h>
#include <vtkCamera.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkSphereSource.h>
#include <vtkXMLPolyDataReader.h>
#include <vtkUnstructuredGrid.h>
#include <vtkDataSetMapper.h>
#include <vtkPolyDataNormals.h>
#include <vtkPointData.h>
#include <vtkCellData.h>
#include <vtkArrowSource.h>
#include <vtkTransform.h>
#include <vtkTransformPolyDataFilter.h>
#include <vtkGlyph3D.h>
#include <vtkOBJReader.h>
int main(int argc, char *argv[]) {
vtkSmartPointer<vtkSphereSource> source = vtkSmartPointer<vtkSphereSource>::New();
source->SetPhiResolution(10);
source->SetThetaResolution(10);
// std::string filePath = "/home/alex/workspace/Geometry-Python/files/cube_ball.obj";
// auto source = vtkSmartPointer<vtkOBJReader>::New();
// source->SetFileName(filePath.c_str());
source->Update();
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection(source->GetOutputPort());
mapper->Update();
vtkSmartPointer<vtkActor> surfaceActor = vtkSmartPointer<vtkActor>::New();
surfaceActor->SetMapper(mapper);
vtkSmartPointer<vtkPolyDataNormals> pdNormals = vtkSmartPointer<vtkPolyDataNormals>::New();
pdNormals->SetInputConnection(source->GetOutputPort());
pdNormals->SplittingOff();
pdNormals->FlipNormalsOff();
// pdNormals->ComputePointNormalsOn();
// pdNormals->ComputePointNormalsOff();
pdNormals->ComputeCellNormalsOn();
pdNormals->ConsistencyOn();
pdNormals->AutoOrientNormalsOn();
pdNormals->Update();
auto arrow = vtkSmartPointer<vtkArrowSource>::New();
arrow->SetTipResolution(8);
arrow->SetTipLength(0.3);
arrow->SetTipRadius(0.1);
vtkSmartPointer<vtkGlyph3D> glyph = vtkSmartPointer<vtkGlyph3D>::New();
glyph->SetSourceConnection(arrow->GetOutputPort());
glyph->SetVectorModeToUseNormal();
glyph->SetInputData(pdNormals->GetOutput());
glyph->SetScaleFactor(0.2);
glyph->OrientOn();
glyph->SetScaleModeToDataScalingOff();
glyph->Update();
vtkSmartPointer<vtkPolyDataMapper> spikeMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
spikeMapper->SetInputConnection(glyph->GetOutputPort());
vtkSmartPointer<vtkActor> spikeActor = vtkSmartPointer<vtkActor>::New();
spikeActor->SetMapper(spikeMapper);
spikeActor->GetProperty()->SetColor(0.0, 0.79, 0.34);
// Create the RenderWindow, Renderer and both Actors
vtkSmartPointer<vtkRenderer> ren = vtkSmartPointer<vtkRenderer>::New();
vtkSmartPointer<vtkRenderWindow> renWin = vtkSmartPointer<vtkRenderWindow>::New();
renWin->AddRenderer(ren);
vtkSmartPointer<vtkRenderWindowInteractor> iren = vtkSmartPointer<vtkRenderWindowInteractor>::New();
iren->SetRenderWindow(renWin);
// Add the actors to the renderer, set the background and size
ren->AddActor(surfaceActor);
ren->AddActor(spikeActor);
ren->SetBackground(.2, .3, .4);
surfaceActor->GetProperty()->EdgeVisibilityOn();
surfaceActor->GetProperty()->SetColor(0, 0, 1);
surfaceActor->GetProperty()->SetEdgeColor(1, 1, 1);
renWin->Render();
iren->Start();
return EXIT_SUCCESS;
}
I can draw arrows to represent point normal?Questions is:
How to draw arrow for cell normal?
I mean each cell has only one arrow from the center of the cell,not 3(or N) arrows from each point.
Hi,
What happens if you enable pdNormals->ComputePointNormalsOff();
along pdNormals->ComputeCellNormalsOn()
?
regards,
PC
dgobbi
(David Gobbi)
March 13, 2023, 4:56pm
3
vtkCellCenters is a filter that takes as input any dataset and generates on output points at the center of the cells in the dataset. These points can be used for placing glyphs (vtkGlyph3D ) or labeling (vtkLabeledDataMapper ). (The center is the parametric center of the cell, not necessarily the geometric or bounding box center.) The cell attributes will be associated with the points on output.
This will get you halfway there.
1 Like
AlexLuya
(Alex Luya)
March 18, 2023, 4:30am
4
After these, all arrows poin toward to the right.
I have the same issue. Normals placed at the centers but all point in the same direction
dgobbi
(David Gobbi)
April 18, 2023, 4:19pm
6
How did you compute the normals? According to the class descriptions (I haven’t tried it), it should be something like this:
apply vtkPolyDataNormals
with ComputeCellNormalsOn()
apply vtkCellCenters
feed the output of vtkCellCenters
into vtkGlyph3D
import vtk
source = vtk.vtkPlatonicSolidSource()
source.SetSolidType(1)
source.Update()
centers = vtk.vtkCellCenters()
centers.SetInputConnection(source.GetOutputPort())
centers.Update()
normals = vtk.vtkPolyDataNormals()
normals.SetInputConnection(centers.GetOutputPort())
normals.ComputeCellNormalsOn()
normals.Update()
arrow = vtk.vtkArrowSource()
glyphs = vtk.vtkGlyph3D()
glyphs.SetInputConnection(normals.GetOutputPort())
glyphs.SetSourceConnection(arrow.GetOutputPort())
glyphs.SetScaleModeToScaleByVector()
glyphs.SetScaleFactor(1)
glyphs.SetInputArrayToProcess(
0, 0, 0, vtk.vtkDataObject.FIELD_ASSOCIATION_POINTS_THEN_CELLS, "Normals")
glyphs.Update()
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputConnection(glyphs.GetOutputPort())
actor = vtk.vtkActor()
actor.SetMapper(mapper)
renderer= vtk.vtkRenderer()
renderer.AddActor(actor)
win = vtk.vtkRenderWindow()
win.AddRenderer(renderer)
iren = vtk.vtkRenderWindowInteractor()
iren.SetRenderWindow(win)
iren.Start()
I am sure that I have done something stupid. I saw a few other posts where other people have encountered this issue. Perhaps when it is working, I could fix a bug in vtkPlatonicSource
and upload an example where normals are shown at cell centers. Interchanging the order of vtkCellCenters
and vtkPolyDataNormals
did no difference. The CellData are empty
dgobbi
(David Gobbi)
April 18, 2023, 4:49pm
8
Most VTK sources only produce point normals, not cell normals. So I think you will still need to compute the cell normals before using vtkCellCenters
.
I can see that cell normals are present and correct after vtkPolyDataNormals
but after vtkCellCenters
the cell data are empty. I will debug this - I may have hit a corner case where number of points equals number of cells
dgobbi
(David Gobbi)
April 18, 2023, 5:25pm
10
Try using glyphs.SetVectorModeToUseNormal()
, instead of glyphs.SetInputArrayToProcess()
. I don’t know why it matters, but it does.
import vtk
source = vtk.vtkPlatonicSolidSource()
source.SetSolidType(1)
source.Update()
normals = vtk.vtkPolyDataNormals()
normals.SetInputConnection(source.GetOutputPort())
normals.ComputeCellNormalsOn()
normals.Update()
centers = vtk.vtkCellCenters()
centers.SetInputConnection(normals.GetOutputPort())
centers.Update()
arrow = vtk.vtkArrowSource()
glyphs = vtk.vtkGlyph3D()
glyphs.SetInputConnection(centers.GetOutputPort())
glyphs.SetSourceConnection(arrow.GetOutputPort())
glyphs.SetScaleModeToScaleByVector()
glyphs.SetScaleFactor(1)
glyphs.SetVectorModeToUseNormal()
#glyphs.SetInputArrayToProcess(
# 0, 0, 0, vtk.vtkDataObject.FIELD_ASSOCIATION_POINTS_THEN_CELLS, "Normals")
glyphs.Update()
mapper = vtk.vtkPolyDataMapper()
mapper.SetInputConnection(glyphs.GetOutputPort())
actor = vtk.vtkActor()
actor.SetMapper(mapper)
renderer= vtk.vtkRenderer()
renderer.AddActor(actor)
win = vtk.vtkRenderWindow()
win.AddRenderer(renderer)
iren = vtk.vtkRenderWindowInteractor()
iren.SetRenderWindow(win)
iren.Start()
1 Like
dgobbi
(David Gobbi)
April 18, 2023, 5:31pm
12
You mean that the code that I posted does not work for you? That’s strange, because it works for me.
It works. The normals appear as normals for the new points and the original cell data is removed. It makes perfect sense. I was just expecting further points to be added as well as normals. But then it would be impossible to distinguish vertex points from points at the cell centers.
Inspecting the code, I can see that this also works
glyphs.SetInputArrayToProcess(1, 0, vtk.vtkDataObject.FIELD_ASSOCIATION_POINTS_THEN_CELLS, vtk.vtkDataSetAttributes.NORMALS)
This was a bit tricky. Thanks David