Berlin Hackathon Results, 3D Viewer and Web News

We completed the Berlin hackathon last weekend, and many other noteworthy and exciting things are going on, concerning the Revit API, the 3D web viewers, web services and more:

Berlin Hackathon Projects and Winners

The Berlin hackathon completed and the winners were announced last weekend.

I took notes of four teams' project presentations:

The first place was awarded the US4 team. Here they are after Peter Schlipf presented them the main prize, four smart watches sponsored by Autodesk:

US4, TMUHack winners

The second place went to the MovieMemory team:

MovieMemory, TMUHack runners-up

They were awarded the neophonie prize, a drone helicopter with built-in camcorder.

Here they are during the live presentation of their newly created online movie memory game:

MovieMemory, TMUHack runners-up

You can try out MovieMemory live yourself right now. You need a partner to get going. Simply go to moviememory.de, copy the game link created and pass it on to your playing partner to start playing right away:

MovieMemory start page

Avoid Unnecessary Unit Conversion – Embrace the Natives

Here is some valuable and sound advice on working in native units and avoiding unnecessary conversions provided by Scott Wilson in his answers to the Revit API discussion thread on converting survey points:

Question: I am extracting four corners of a rectangular column. My code works perfectly in one project but not in another. The only difference between the two that I noticed is that the project and survey points are the same in the first, whereas they differ in the second.

Answer: From a quick look through the code, it looks like you might be mixing your dimensional units. Are the points out by a multiple of 304.8 by any chance?

Halfway through you are converting from feet to millimetres (parameter values h and b); later, you apply a transform (with its translation values in feet) to points created using these metric values. I suspect that the error is masked in your first project due to the translation from project to survey points being zero.

I'd suggest leaving all dimensions in feet until you need to display or export them.

Response: Yes I am multiplying by 304.8 as Revit returns the values in feet but the project is in millimetres.

What should I do to resolve the issue?

Answer: Why do you need to convert into metric during the calculation?

I can't see anywhere in the code snippet where you are displaying or exporting the interim values, so just leave them all in feet and let Revit work in its native units. If you need the output values in metric, convert them as the last step.

I also just noticed that you are converting the location point rotation into degrees and then round that to the nearest degree. You then convert this rounded value back into radians to perform some trig calcs. This is going to be quite inaccurate and inconsistent, just leave angles in raw radians without rounding.

Don't convert / mix units or perform rounding mid-way through a calculation, you are just asking for trouble. If you are uncomfortable working in feet and radians, I'd suggest making the effort to embrace them.

Many thanks to Scott for this recommendation, and for his numerous other great replies in the Revit API discussion forum!

Please everybody take heed of this very sound advice!

3D Viewer News

Theo Armour, initiator of the vA3C open source three.js AEC 3D model viewer posted an update on the current vA3C status and the following call to action:

The latest release of the vA3C Viewer is looking good.

It would be great to hear from you that something in this effort is worthwhile or useful to you.

Virtually everything we set out to do back in May is being done – sometimes elegantly, some times not so, but never mind.

Over the summer, I thought the work on the viewer would finish and I could get back to my 3D mapping work and etc.

In the last few weeks, those thoughts have kind of been exploded. I am coming to the realization that we asked for just the tip of the iceberg.

Metaphorically, the viewer is can be seen as theatrical stage set. The next step is to use this stage to produce theatre.

For example, you all know Oculus Rift, Google Cardboard, Magic Leap and the whole virtual reality thing is exploding.

A few weeks ago I built a Google cardboard three.js viewer template.

The intention is to build this capability into the vA3C Viewer.

But guess who used my templates and got there first? The Autodesk 360 Viewer!

My new friend (and Jeremy's colleague) Kean Walmsley was pointed in our direction by Jim Quanci and Cyrille Fauvel and started gearing up for the VR Hackathon.

Not only that, but he has already built demos on top of my voice recognition template and produced the series of further exciting results listed below.

And there's much, much more beyond this.

From my point of view, this all looks like the start of a classic Internet disruption by a small start-up.

The technology is there; the industry that needs disrupting (AEC) is obediently stagnating.

All that's needed is the founders...

Here is an overview if Kean's recent posts:

Too exciting to miss!

AutoCAD as a Web Service

After all the exciting 3D stuff listed above, Kean went on to write about making programmatic use of the AutoCAD core services via a web service.

This is another topic that every application developer should be thinking about and aware of.

Just as Theo points out, things are really taking off!

Collada STL ADVA Export Settings

Talking about the 3D viewer, I built my daughter Marie a new writing desk, and a friend of hers created this model of Maria's room to discuss our plan:

He had to explore a bit to get the Collada STL export setting right for the model to display correctly in the Autodesk View and Data API viewer; here they are:

Collada STL export settings for the Autodesk View and Data API

Custom User Settings Storage and RvtVa3c Update

Back to the Revit API and the vA3C viewer again, and based on the discussion with David and Theo on the failure to load a big model, I tried reducing the file size of the JSON geometry output produced by the RvtVa3c three.js and vA3C editor model exporter and added support for runtime reading of user settings and switching between indented and non-indented JSON.

The necessary switch is provided by the JsonConvert class defined by the Newtonsoft.Json library that I am using to serialise the classes collected from the custom exporter to JSON, and set like this in its call to serialise them:

  Formatting formatting
    = UserSettings.JsonIndented
      ? Formatting.Indented
      : Formatting.None;
 
  File.WriteAllText( _filename,
    JsonConvert.SerializeObject(
      _container, formatting, settings ) );

I implemented a new class UserSettings to provide a simple way for the end user to control this property.

I obviously considered using the built-in .NET user settings classes, but they interact rather heavily with the operating system and can be difficult to use in the context of a Revit add-in.

I also considered using a custom implementation, e.g. this custom settings class for WinForms by Jonathan Wood, the Black Belt Coder.

In the end, however, I preferred to avoid all hassles with other people's code and paradigms and simply write my own.

My UserSettings class checks whether a file with the same name and location as the Revit add-in exists, except the filename extension DLL is replaced by TXT. If so, it reads the user preferences from there. If not, it creates a new file using the default value that can easily be modified by the user.

To support its parsing of a Boolean value, I implemented this new utility method to read a true or false value from a string:

  /// <summary>
  /// Extract a true or false value from the given
  /// string, accepting yes/no, Y/N, true/false, T/F
  /// and 1/0. We are extremely tolerant, i.e., any
  /// value starting with one of the characters y, n,
  /// t or f is also accepted. Return false if no 
  /// valid Boolean value can be extracted.
  /// </summary>
  public static bool GetTrueOrFalse(
    string s,
    out bool val )
  {
    val = false;
 
    if( s.Equals( Boolean.TrueString,
      StringComparison.OrdinalIgnoreCase ) )
    {
      val = true;
      return true;
    }
    if( s.Equals( Boolean.FalseString,
      StringComparison.OrdinalIgnoreCase ) )
    {
      return true;
    }
    if( s.Equals( "1" ) )
    {
      val = true;
      return true;
    }
    if( s.Equals( "0" ) )
    {
      return true;
    }
    s = s.ToLower();
 
    if( 't' == s[0] || 'y' == s[0] )
    {
      val = true;
      return true;
    }
    if( 'f' == s[0] || 'n' == s[0] )
    {
      return true;
    }
    return false;
  }

That is used to determine the value of the UserSettings class JsonIndented property like this:

class UserSettings
{
  const string _JsonIndent = "JsonIndent";
 
  const string _error_msg_format
    = "Invalid settings in '{0}':\r\n\r\n{1}"
    + "\r\n\r\nPlease add {2} = {3} or {4}.";
 
  static bool SyntaxError( string path, string s )
  {
    Util.ErrorMsg( string.Format(
      _error_msg_format, path, s, _JsonIndent,
      Boolean.TrueString, Boolean.FalseString ) );
 
    return false;
  }
 
  public static bool JsonIndented
  {
    get
    {
      string path = Assembly.GetExecutingAssembly()
        .Location;
 
      path = Path.ChangeExtension( path, "txt" );
 
      if( !File.Exists( path ) )
      {
        File.WriteAllText( path,
          _JsonIndent + "=" + Boolean.TrueString );
 
        Util.ErrorMsg( string.Format(
          "Created a new user settings file at '{0}'.",
          path ) );
      }
 
      string s1 = File.ReadAllText( path );
 
      int i = s1.IndexOf( _JsonIndent );
 
      if( 0 > i )
      {
        return SyntaxError( path, s1 );
      }
 
      string s = s1.Substring( i
        + _JsonIndent.Length );
 
      i = s.IndexOf( '=' );
 
      if( 0 > i )
      {
        return SyntaxError( path, s1 );
      }
 
      s = s.Substring( i + 1 ).Trim();
 
      bool rc;
 
      if( !Util.GetTrueOrFalse( s, out rc ) )
      {
        return SyntaxError( path, s1 );
      }
 
      return rc;
    }
  }
}

Editing the automatically generated file and specifying an invalid Boolean value such as the string "a non-Boolean value" produces the following error message:

RvtVa3c invalid Boolean value error message

Please excuse the overkill :-)

The entire updated RvtVa3c custom exporter add-in implementation is provided in the RvtVa3c GitHub repository, and the version discussed above is release 2015.0.0.26.

Enjoy!