Transform Object with a Series of Moves

By Xiaodong Liang

Question:

I am trying to apply a series of moves with time delay to an object in Navisworks using OverridePermanentTransform and System.Threading.Thread.Sleep(), but Navisworks delays first then applies the moves at the same time.

Solution:

This is similar to the behavior discussed in the other article. The Navisworks screen refresh happens when the UI message loop delivers a paint event. If you have some code running that sits in a loop doing lots of work then there’s no way for the UI message loop to deliver a paint event.

I have practiced the way of Idle event. i.e. put your series of moves in the event. The following codes simulates a transformation: first move the selection along X+ with some distances, next rotate the objects along the axis (origin: center of the bundingbox; vector: 0,0,1). Finally, move the object along Z+ with some distances.

#region HelloWorld

using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Text;

//Add two new namespaces
using Autodesk.Navisworks.Api;
using Autodesk.Navisworks.Api.Plugins;

namespace BasicPlugIn
{
    [PluginAttribute("BasicPlugIn.ABasicPlugin",                 //Plugin name
                     "ADSK",                                     //4 character Developer ID or GUID
                     ToolTip = "BasicPlugIn.ABasicPlugin tool tip",//The tooltip for the item in the ribbon
                     DisplayName = "Hello World Plugin")]         //Display name for the Plugin in the Ribbon
    public class ABasicPlugin : AddInPlugin                     //Derives from AddInPlugin
    {
        public override int Execute(params string[] parameters)
        {
            Document doc =
                Autodesk.Navisworks.Api.Application.MainDocument;

            // current selection
            ModelItemCollection coll =
                doc.CurrentSelection.SelectedItems;
            if (coll.Count == 0)
            {
                MessageBox.Show("no selection!");
                return 0;
            }

            m_Index = 0;
            //delagate the event of Idle
            Autodesk.Navisworks.Api.Application.Idle +=
                new EventHandler<EventArgs>(Idle_EventHandler);

            return 0;
        }

        //simulation index
        int m_Index = 0;

        //move step
        double oMoveStep = 2;
        //rotate step
        double oRotateStep = 0.1;

        void Idle_EventHandler(object sender, EventArgs e)
        {
            //get handle of Navisworks window
            IntPtr hWnd =
                Autodesk.Navisworks.Api.Application.Gui.MainWindow.Handle;

            if (m_Index < 50)
            {
                if (m_Index <= 15)
                {
                    // move X+
                    moveObjAlongX();
                }
                if (m_Index <= 30 && m_Index > 15)
                {
                    //rotate the axis that (0,0,1) and
                    //origin is the center of the
                    //boundingbox of the collection
                    rotateObjAlongAxis();
                }

                if (m_Index <= 50 && m_Index > 30)
                {
                    // move Z+
                    moveObjAlongZ();
                }
                m_Index++;
            }
            else
            {
                //stop the event Idle
                Autodesk.Navisworks.Api.Application.Idle -=
                    Idle_EventHandler;
            }
        }

        #region "transform object"

        private void moveObjAlongX()
        {
            Document doc =
                Autodesk.Navisworks.Api.Application.MainDocument;

            // current selection
            ModelItemCollection coll =
                doc.CurrentSelection.SelectedItems;
            if (coll.Count == 0)
                return;

            //build a vector for moving
            Vector3D oNewVector3d =
                new Vector3D(oMoveStep, 0, 0);

            //create a transform from a matrix with a vector.
            Transform3D oNewOverrideTrans =
                Transform3D.CreateTranslation(oNewVector3d);

            doc.Models.OverridePermanentTransform(coll,
                oNewOverrideTrans,
                true);
        }

        private void rotateObjAlongAxis()
        {
            Document doc =
                Autodesk.Navisworks.Api.Application.MainDocument;

            // current selection
            ModelItemCollection coll =
                doc.CurrentSelection.SelectedItems;
            if (coll.Count == 0)
                return;

            //build the translation from boundingbox center to origin of WCS
            Point3D oCenterP =
                coll.BoundingBox().Center;
            Vector3D oMoveBackToOrig =
                new Vector3D(-oCenterP.X, -oCenterP.Y, -oCenterP.Z);
            Transform3D oMoveBackToOrigM =
                Transform3D.CreateTranslation(oMoveBackToOrig);

            // set the axis we will rotate around (0,0,1)
            UnitVector3D odeltaA =
                new UnitVector3D(0, 0, 1);
            // Create delta of Quaternion: axis is Z,
            Rotation3D delta =
                new Rotation3D(odeltaA, oRotateStep);

            //create a transform from a matrix with a rotation.
            Transform3D oNewOverrideTrans =
                new Transform3D(delta);

            //build final matrix
            Transform3D oFinalM =
                Transform3D.Multiply(oMoveBackToOrigM, oNewOverrideTrans);
            oFinalM =
                Transform3D.Multiply(oFinalM, oMoveBackToOrigM.Inverse());

            doc.Models.OverridePermanentTransform(coll, oFinalM, true);
        }

        private void moveObjAlongZ()
        {
            Document doc =
                Autodesk.Navisworks.Api.Application.MainDocument;

            // current selection
            ModelItemCollection coll =
                doc.CurrentSelection.SelectedItems;
            if (coll.Count == 0)
                return;

            //build a vector for moving along X+
            Vector3D oNewVector3d =
                new Vector3D(0, 0, oMoveStep);

            Matrix3 oNewIndentityM =
                new Matrix3();

            //create a transform from a matrix with a vector.
            Transform3D oNewOverrideTrans =
                new Transform3D(oNewIndentityM, oNewVector3d);

            doc.Models.OverridePermanentTransform(coll,
                oNewOverrideTrans,
                true);
        }
        #endregion
    }
}
#endregion

Untitled


Comments

One response to “Transform Object with a Series of Moves”

  1. how to consume that…using exe or dll?
    could you share how to implement it

Leave a Reply

Discover more from Autodesk Developer Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading