VTKExamples/CSharp/GeometricObjects/OrientedArrow

### Description

This example illustrates how to create and display an arrow that passes through two points.

It demonstrates two different ways to apply the transform:

# Use vtkTransformPolyDataFilter to create a new transformed polydata. This method is useful if the transformed polydata is needed later in the pipeline, e.g. vtkGlyph3DFilter.

# Apply the transform directly to the actor using vtkProp3D's SetUserMatrix. No new data is produced.

A tutorial on how to setup a Windows Forms Application utilizing ActiViz.NET can be found here: Setup a Windows Forms Application to use ActiViz.NET

### Code

OrientedArrow.cs

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Windows.Forms;
    using System.Diagnostics;

    using Kitware.VTK;

    namespace ActiViz.Examples {
       public partial class Form1 : Form {
          public Form1() {
             InitializeComponent();
          }

          private void renderWindowControl1_Load(object sender, EventArgs e) {
             try {
                OrientedArrow();
             }
             catch(Exception ex) {
                MessageBox.Show(ex.Message, "Exception", MessageBoxButtons.OK);
             }
          }

          private void OrientedArrow() {
             //Create an arrow.
             vtkArrowSource arrowSource = vtkArrowSource.New();

             // Generate a random start and end point
             vtkMath.RandomSeed(8775070);
             double[] startPoint = new double[]{
                vtkMath.Random(-10,10),
                vtkMath.Random(-10,10),
                vtkMath.Random(-10,10)
             };

             double[] endPoint = new double[]{
                vtkMath.Random(-10,10),
                vtkMath.Random(-10,10),
                vtkMath.Random(-10,10)
             };

             // Compute a basis
             double[] normalizedX = new double[3];
             double[] normalizedY = new double[3];
             double[] normalizedZ = new double[3];

             // The X axis is a vector from start to end
             myMath.Subtract(endPoint, startPoint, ref normalizedX);
             double length = myMath.Norm(normalizedX);
             myMath.Normalize(ref normalizedX);

             // The Z axis is an arbitrary vector cross X
             double[] arbitrary = new double[]{
                vtkMath.Random(-10,10),
                vtkMath.Random(-10,10),
                vtkMath.Random(-10,10)
             };
             myMath.Cross(normalizedX, arbitrary, ref normalizedZ);
             myMath.Normalize(ref normalizedZ);
             // The Y axis is Z cross X
             myMath.Cross(normalizedZ, normalizedX, ref normalizedY);
             vtkMatrix4x4 matrix = vtkMatrix4x4.New();

             // Create the direction cosine matrix
             matrix.Identity();
             for(int i = 0; i < 3; i++) {
                matrix.SetElement(i, 0, normalizedX[i]);
                matrix.SetElement(i, 1, normalizedY[i]);
                matrix.SetElement(i, 2, normalizedZ[i]);
             }

             // Apply the transforms
             vtkTransform transform = vtkTransform.New();
             transform.Translate(startPoint[0], startPoint[1], startPoint[2]);
             transform.Concatenate(matrix);
             transform.Scale(length, length, length);

             //Create a mapper and actor for the arrow
             vtkPolyDataMapper mapper = vtkPolyDataMapper.New();
             vtkActor actor = vtkActor.New();
    #if USER_MATRIX
             mapper.SetInputConnection(arrowSource.GetOutputPort());
             actor.SetUserMatrix(transform.GetMatrix());
    #else
             // Transform the polydata
             vtkTransformPolyDataFilter transformPD = vtkTransformPolyDataFilter.New();
             transformPD.SetTransform(transform);
             transformPD.SetInputConnection(arrowSource.GetOutputPort());
             mapper.SetInputConnection(transformPD.GetOutputPort());
    #endif
             actor.SetMapper(mapper);

             // Create spheres for start and end point
             vtkSphereSource sphereStartSource = vtkSphereSource.New();
             sphereStartSource.SetCenter(startPoint[0], startPoint[1], startPoint[2]);
             vtkPolyDataMapper sphereStartMapper = vtkPolyDataMapper.New();
             sphereStartMapper.SetInputConnection(sphereStartSource.GetOutputPort());
             vtkActor sphereStart = vtkActor.New();
             sphereStart.SetMapper(sphereStartMapper);
             sphereStart.GetProperty().SetColor(1.0, 1.0, .3);

             vtkSphereSource sphereEndSource = vtkSphereSource.New();
             sphereEndSource.SetCenter(endPoint[0], endPoint[1], endPoint[2]);
             vtkPolyDataMapper sphereEndMapper = vtkPolyDataMapper.New();
             sphereEndMapper.SetInputConnection(sphereEndSource.GetOutputPort());
             vtkActor sphereEnd = vtkActor.New();
             sphereEnd.SetMapper(sphereEndMapper);
             sphereEnd.GetProperty().SetColor(1.0, .3, .3);

             vtkRenderWindow renderWindow = renderWindowControl1.RenderWindow;
             vtkRenderer renderer = renderWindow.GetRenderers().GetFirstRenderer();
             renderer.SetBackground(0.2, 0.3, 0.4);
             renderer.AddActor(actor);
             renderer.AddActor(sphereStart);
             renderer.AddActor(sphereEnd);
             renderer.ResetCamera();
          }
       }

       // I'm using my own math class
       // reason: due to the fact that ActiViz wraps native, unmanaged functions in class vtkMath
       // many of the arguments like double arrays (for vector definition) has to be passed by an IntPtr.
       //
       // But there do exist some managed open source math libraries of professional quality, that it
       // should be not a problem at all using another math library for vector algebra.
       //
       // vtkmath could be used for vetor algebra, no doubt, but then functions which heavily relies on
       // vector algebra like dot or cross product, etc. would be full of Marshaling code.

       public class myMath {
          public static void Subtract(double[] a, double[] b, ref double[] c) {
             c[0] = a[0] - b[0];
             c[1] = a[1] - b[1];
             c[2] = a[2] - b[2];
          }

          public static double Norm(double[] x) {
             return Math.Sqrt(x[0] * x[0] + x[1] * x[1] + x[2] * x[2]);
          }

          public static void Normalize(ref double[] x) {
             double length = Norm(x);
             x[0] /= length;
             x[1] /= length;
             x[2] /= length;
          }

          public static void Cross(double[] x, double[] y, ref double[] z) {
             z[0] = ( x[1] * y[2] ) - ( x[2] * y[1] );
             z[1] = ( x[2] * y[0] ) - ( x[0] * y[2] );
             z[2] = ( x[0] * y[1] ) - ( x[1] * y[0] );
          }
       }

    }