NavisWorks – SearchSet’s

With NavisWorks Simulate and Manage you can use Find Items panel to search across details. Usual flow – is to identify Category and properites which allow to find right element. Then design the query. If query is correct – you can proceed with result, if not you can adjust query. When you query is perfect, and for some reason you may need it again – sets are desinged to help you.

When you get collection of search sets – it might be userfull to export it and use same set with another NavisWorks models. So lets dive deeper it this matter.

NavisWorks Search Sets

Continue reading

How to create a Table and fill in its cells with .NET

originally this article was available at

https://adndevblog.typepad.com/autocad/2012/05/how-to-create-a-table-and-fill-in-its-cells-with-net.html

But now this source is not available anymore. So this is copy paste from web-archive for my own memory

05/16/2012

How to create a Table and fill in its cells with .NET

By Xiaodong Liang

The code below shows how to create a table and fill in its cells. Some obsolete methods of Table are still visible. You will receive a warning in compiling if using obsolete methods. Please use the newest methods.

[CommandMethod("testaddtable")]
public void testaddtable()
{
    Database  db =
        HostApplicationServices.WorkingDatabase;
 
    using (Transaction tr =
        db.TransactionManager.StartTransaction())
    {
        BlockTable bt =
            (BlockTable)tr.GetObject(db.BlockTableId,
                                    OpenMode.ForRead);
        ObjectId msId =
            bt[BlockTableRecord.ModelSpace];
        BlockTableRecord btr =
            (BlockTableRecord)tr.GetObject(msId,
                                OpenMode.ForWrite);
        // create a table
        Table tb = new Table();
        tb.TableStyle = db.Tablestyle;
        // row number
        Int32 RowsNum = 5;
        // column number
        Int32 ColumnsNum = 5;
        // row height
        double rowheight = 3;
        // column width
        double columnwidth = 20;

        // insert rows and columns
        tb.InsertRows(0, rowheight, RowsNum);
        tb.InsertColumns(0, columnwidth, ColumnsNum);
        tb.SetRowHeight(rowheight);
        tb.SetColumnWidth(columnwidth);

        Point3d eMax = db.Extmax;
        Point3d eMin = db.Extmin;
        double CenterY = (eMax.Y + eMin.Y) * 0.5;
        tb.Position = new Point3d(10, 10, 0);

        // fill in the cell one by one
        for (int i = 0; i < RowsNum; i++)
        {
            for (int j = 0; j < ColumnsNum; j++)
            {
                tb.Cells[i, j].TextHeight =  1;
                if (i == 0 && j == 0)
                    tb.Cells[i, j].TextString =
                        "The Title";
                else
                    tb.Cells[i, j].TextString =
                        i.ToString() + "," + j.ToString();
                tb.Cells[i,j].Alignment =
                    CellAlignment.MiddleCenter;
            }
        }

        tb.GenerateLayout();
        btr.AppendEntity(tb);
        tr.AddNewlyCreatedDBObject(tb, true);
        tr.Commit();
    }
}

NavisWorks C# Pick Point

Lest deep dive in Autodesk NavisWorks api.

First, we need a tool plugin with mouse down Interceptor:

using Autodesk.Navisworks.Api;
using Autodesk.Navisworks.Api.Plugins;

    [Plugin("PickModelPointPlugin", "ADSK")]
    class PickModelPointPlugin : ToolPlugin
    {
        public override bool MouseDown(View view, KeyModifiers modifiers,
                                         ushort button, int x, int y,
                                         double timeOffset)
        {
                // get current selection
                PickItemResult pickedResult = view.PickItemFromPoint(x, y);

                if (pickedResult != null)
                {
                    Autodesk.Navisworks.Api.Point3D clickedPoint =          
                                                        pickedResult.Point;

                // Sent to static exchange, to make click result available 
                // for Addin Plugins in namespace
                // convert to custom Point, to reduce coupling. 
                StaticExchange.PickedPoint = new cPoint(clickedPoint.X,
                                                        clickedPoint.Y,
                                                        clickedPoint.Z);
                }
            return base.MouseDown(view, modifiers, button, x, y, 
                                  timeOffset);
        }
    }

First, we need a tool plugin with mouse down Interceptor:

   class StaticExchange
    {
        public static event PointDelegate PointUpdate;
        public delegate void PointDelegate(PointEventArgs e);
        private static cPoint point;

        public static cPoint PickedPoint
        {
            get {
                    return point;
                }
            set {
                    point = value;
                    PointUpdate?.Invoke(new PointEventArgs(point));
                }
        }
    }

Obviously, we may need to do some actions as soon as user click on something. That`s why event delegate has been presented in StaticExchange.
Finally, in our Addin we call A plugin and await for result. In my case it’s a form with buttons, so on a button I bind click handler:

private async void btnPickNavisPoint_Click(object sender, EventArgs e)
{
      try { 
            //search for plugin availability 
            ToolPluginRecord toolPluginRecord =                    
                   (ToolPluginRecord)ANA.Application.Plugins
                       .FindPlugin("PickModelPointPlugin.ADSK");
        //set Plugin for execution                                
        ANA.Application.MainDocument.Tool
            .SetCustomToolPlugin(toolPluginRecord.LoadPlugin());
                //Subscribe on event
                StaticExchange.PointUpdate += onPointUpdate; 
                //Patiently wait for result
                Point3D result = await WaitForUserChoiceAsync();

                MessageBox.Show(
                    "Point: "+
                     "X:" + result.X.ToString("0.##") + " " +
                     "Y:" + result.Y.ToString("0.##") + " " +
                     "Z:" + result.Z.ToString("0.##") + " ");
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            finally
            {
                //Unsubscribe and switch back to Tool.Select
                StaticExchange.PointUpdate -= onPointUpdate; 
                ANA.Application.MainDocument.Tool.Value = Tool.Select;
            }
        }

And now final peace – where magic is live.

  1. Declare TaskCompletionSource,
  2. Wrap it into WaitUserChoice.
  3. In event handler call Source and pass argument.
        private TaskCompletionSource<Point3D> _userChoiceTcs;

        private async Task<Point3D> WaitForUserChoiceAsync()
        {
            // Create a new TaskCompletionSource for this operation
            _userChoiceTcs = new TaskCompletionSource<Point3D>();
            try
            {
                Point3D result = await _userChoiceTcs.Task;
                return result;
            }
            finally
            {
                // Clean up
                _userChoiceTcs = null;
            }
        }

        private void onPointUpdate(PointEventArgs p)
        {
            //Here come the user click result
            _userChoiceTcs?.TrySetResult(new Point3D(p.Point.X,
                p.Point.Y,
                p.Point.Z));
        }

As a result we got message with coordinates of clicked points, as soon as user click on some object.