[vtkusers] Question about surface normal

David Doria daviddoria+vtk at gmail.com
Thu Nov 5 09:16:46 EST 2009


On Thu, Nov 5, 2009 at 9:07 AM, Luca Pamparana <luca.pamparana at gmail.com> wrote:
> Hello everyone,
>
> Started playing with vtk recently and have a simple code that simply
> draws a 2D plane in 3D space. I am using vtkPolyData class and using a
> vtkActor to render it.
>
> This might be more of a geometry question. So, what I want to do is
> have the surface normal point to a given point in 3D space. For
> example, I might want the normal to point to the origin of my 3D
> scene. Does anyone know how I might be able to calculate that.
>
> Here is the bit of code that I have so far, which I have hacked
> together after looking at some VTK examples.
>
>
> // Code starts
> #include "vtkPoints.h"
> #include "vtkCellArray.h"
> #include "vtkPolyData.h"
> #include "vtkPolyDataMapper.h"
> #include "vtkActor.h"
> #include "vtkRenderWindow.h"
> #include "vtkRenderWindowInteractor.h"
> #include "vtkRenderer.h"
> #include "vtkProperty.h"
>
>
> int main()
> {
>    vtkPolyData * geometry = vtkPolyData::New();
>    vtkPoints * testPoints = vtkPoints::New();
>    testPoints->Allocate(4);
>    vtkCellArray *testPolys = vtkCellArray::New();
>    testPolys->Allocate(testPolys->EstimateSize(1,4));
>    double x[3];
>    vtkIdType pts[4];
>    x[0] = -2.5;
>    x[1] = -2.5;
>    x[2] = -2.5;
>    testPoints->InsertNextPoint(x);
>    x[0] = 2.5;
>    x[1] = -2.5;
>    x[2] = -2.5;
>    testPoints->InsertNextPoint(x);
>    x[0] = -2.5;
>    x[1] = 2.5;
>    x[2] = -2.5;
>    testPoints->InsertNextPoint(x);
>    x[0] = 2.5;
>    x[1] = 2.5;
>    x[2] = -2.5;
>    testPoints->InsertNextPoint(x);
>
>    pts[0] = 0; pts[1] = 2; pts[2] = 3; pts[3] = 1;
>    testPolys->InsertNextCell(4,pts);
>    geometry->SetPoints(testPoints);
>    testPoints->Delete();
>    testPolys->Squeeze();
>    geometry->SetPolys(testPolys);
>    testPolys->Delete();
>
>    vtkRenderer *renderer = vtkRenderer::New();
>    vtkRenderWindow *renWin = vtkRenderWindow::New();
>    renWin->AddRenderer(renderer);
>    vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
>    iren->SetRenderWindow(renWin);
>
>    vtkPolyDataMapper * testMapper = vtkPolyDataMapper::New();
>    testMapper->SetInput(geometry);
>
>    vtkActor * testActor = vtkActor::New();
>    testActor->SetMapper(testMapper);
>    testActor->GetProperty()->SetColor(1, 0, 0);
>    renderer->AddActor(testActor);
>    renderer->SetBackground(1,1,1);
>    renWin->SetSize(300,300);
>
>    renWin->Render();
>
>    iren->Start();
>
>    testActor->Delete();
>    testMapper->Delete();
>    iren->Delete();
>    renWin->Delete();
>    renderer->Delete();
>    return 0;
> }
> // Code ends
>
> Looking forward to your help.
>
> Sincerely,
>
> Luc

Luc

In this simple case, could you consider using a plane? Then you can
specify the normal directly
http://www.vtk.org/Wiki/Plane

See this example for a little bit cleaner way of adding points/cells
to a polydata. It also demonstrates the vtkSmartPointer so you don't
have to do your own memory management.
http://www.vtk.org/Wiki/Polygon

This could also be a very helpful function for you (maybe we can add
this to vtkMath or somewhere?). It takes two vectors and finds the
transformation that brings the first to the second using a landmark
transform:


vtkTransform* AlignRays(double* Ray1, double* Ray2)
{
  //This function takes two rays and finds the matrix M between them
(from Ray1 to Ray2)
  vtkMath::Normalize(Ray1);
  vtkMath::Normalize(Ray2);

  vtkLandmarkTransform* LandmarkTransform = vtkLandmarkTransform::New();
  vtkPoints* SourcePoints = vtkPoints::New();
  vtkPoints* TargetPoints = vtkPoints::New();

  double Origin[3] = {0.0, 0.0, 0.0};

  //setup ray 1
  SourcePoints->InsertNextPoint(Origin);
  SourcePoints->InsertNextPoint(Ray1);

  TargetPoints->InsertNextPoint(Origin);
  TargetPoints->InsertNextPoint(Ray2);

  LandmarkTransform->SetSourceLandmarks(SourcePoints);
  LandmarkTransform->SetTargetLandmarks(TargetPoints);
  LandmarkTransform->SetModeToRigidBody();
  LandmarkTransform->Update();

  vtkMatrix4x4* M = LandmarkTransform->GetMatrix();

  vtkTransform* Transform = vtkTransform::New();
  Transform->SetMatrix(M);

  //clean up
  SourcePoints->Delete();
  TargetPoints->Delete();
  LandmarkTransform->Delete();

  return Transform;
		
}

Good luck.

David



More information about the vtkusers mailing list