Setting up your ViewOrientation3D

Here is a contribution from Mario Guttman of CASE, who already made various contributions here in the past. He says:

I have been purging my 2013 code of deprecated functions in preparation for my 2014 upgrade. One group of statements I have needed to replace are the view creations. They were previously using the Document.Create.NewView3D method and needed converting to the View3D.CreateIsometric with a separate ViewOrientation3D object defining the view direction.

Typically, in these kind of cases, I just search your blog for the answer. In this case I found a few references, for example your March 04, 2013 item on What's New in the Revit 2013 API – View API – View Creation. This, together with the wikihelp entry on the View3D class, describe the new syntax, but they don't really explain how you would create the values.

After searching the inner reaches of my brain for some ancient math skills I figured out the following:

Assuming that your user interface has produced two angular values (in degrees):

  /// <summary>
  /// The angle in the XY plane (azimuth),
  /// typically 0 to 360.
  /// </summary>
  double angleHorizD;
 
  /// <summary>
  /// The vertical tilt (altitude),
  /// typically -90 to 90.
  /// </summary>
  double angleVertD;

Then this utility function returns a unit vector in the specified direction:

  /// <summary>
  /// Return a unit vector in the specified direction.
  /// </summary>
  /// <param name="angleHorizD">Angle in XY plane 
  /// in degrees</param>
  /// <param name="angleVertD">Vertical tilt between 
  /// -90 and +90 degrees</param>
  /// <returns>Unit vector in the specified 
  /// direction.</returns>
  private XYZ VectorFromHorizVertAngles(
    double angleHorizD,
    double angleVertD )
  {
    // Convert degreess to radians.
 
    double degToRadian = Math.PI * 2 / 360;
    double angleHorizR = angleHorizD * degToRadian;
    double angleVertR = angleVertD * degToRadian;
 
    // Return unit vector in 3D
 
    double a = Math.Cos( angleVertR );
    double b = Math.Cos( angleHorizR );
    double c = Math.Sin( angleHorizR );
    double d = Math.Sin( angleVertR );
 
    return new XYZ( a * b, a * c, d );
  }

From this it is easy to create the ViewOrientation3D object as follows:

  XYZ eye = XYZ.Zero;
 
  XYZ forward = VectorFromHorizVertAngles(
    angleHorizD, angleVertD );
 
  XYZ up = VectorFromHorizVertAngles(
    angleHorizD, angleVertD + 90 );
 
  ViewOrientation3D viewOrientation3D
    = new ViewOrientation3D( eye, up, forward );

Although it is already explained in one of your other posts, just for completeness, here is the final step is to apply the orientation to the view:

  ViewFamilyType viewFamilyType3D
    = new FilteredElementCollector( doc )
      .OfClass( typeof( ViewFamilyType ) )
      .Cast<ViewFamilyType>()
      .FirstOrDefault<ViewFamilyType>(
        x => ViewFamily.ThreeDimensional
          == x.ViewFamily );
 
  View3D view3d = View3D.CreateIsometric(
    doc, viewFamilyType3D.Id );
 
  view3d.SetOrientation( viewOrientation3D );

I hope you find this useful.

Personally, I do indeed.

Many thanks to Mario for sharing!

Addendum

Colmag adds in his comment below:

Thank you for sharing this info, it's made life a whole lot easier in setting 3D view orientation.

It did take me a short while to work out the values to replicate top and bottom isometric views from each corner of the view cube, so I thought I'd share the values here for others. Looking at them listed out they are pretty obvious, but faced with a blank sheet things didn't seem so straight forward!

Many thanks to Colmag for this useful addition!

Addendum 2

K C Tang added a further simplification in his comment below:

I found that the formula above using ( a * b, a * c, d ) to calculate the return value from VectorFromHorizVertAngles can be further simplified, because:

  ( a * b, a * c, d )
    ≡ ( a * b / a , a * c / a, d / a )
    = (b, c, d/a)
    = (b, c, e),

where

  double e = Math.Tan( angleVertR ).

In words, the return value from VectorFromHorizVertAngles can be defined as:

Many thanks to K C Tang for this simplification and explanation highlighting the basic trigonometric relationships between the angles and the vectors involved so much better than the original version!