0926/2078

Setting up your ViewOrientation3D

Originally Published in

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!

  • Horizontal Angles:

  • Left Front = 45

  • Front Right = 135

  • Right Back = 225

  • Back Left = 310

  • Vertical Angles:

  • -30 = Top

  • 30 = Bottom

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:

  • cos (horizontal angle) for X
  • sin (horizontal angle) for Y
  • tan (vertical angle) for Z

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!