Quantcast
Channel: Manufacturing DevBlog
Viewing all 516 articles
Browse latest View live

How to use GoExcel.FindRowStart

$
0
0

By Xiaodong Liang

Question
In an Excel file, the cells are defined as below. I wanted to get the row which aaa =111. I thought the first is to call
GoExcel.FindRowStart = 3, because GoExcel.FindRowStart is 2 in default. But, FindRow failed after FindRowStart = 3. It says:
Could not match the column title: "aaa"

clip_image002

GoExcel.Open("Book1.xlsx", "Sheet1")
GoExcel.FindRowStart=3
i=GoExcel.FindRow("Book1.xlsx", "Sheet1", "aaa", "=", 111)
MessageBox.Show(i.Tostring(), "Title")

Solution
There is another property: TitleRow. You also have to set that.  (Or you can set TitleRow only, and FindRowStart will be set automatically to TitleRow+ 1). Here’s a modified version of the rule:

GoExcel.Open("Book1.xlsx", "Sheet1")GoExcel.TitleRow=2GoExcel.FindRowStart=3
' or set TitleRow only if you are sure the start row is TitleRow +1 i=GoExcel.FindRow("Book1.xlsx", "Sheet1", "aaa", "=", 111)MessageBox.Show(i.Tostring(), "Title")

Copy iProperties of Model Document to Drawing Document When Placing View

$
0
0

By Xiaodong Liang

Question:
Within the document settings for a drawing, on the drawing tab, there is a button called "Copy Model iProperty Settings... " this brings you to the settings dialog box which has a check box to enable Copy Model iProperties. Checking the box will enable a list of iProperties found in the drawing which you would like to enable inventor to copy from the model to the drawing's iProperties.

I am looking for a way within the API to check the box highlighted in red and then any iProperties in the list.

image

Solution:
The DrawingSettings object has not exposed the relevant API to toogle the [Copy Model Properties]. But with current API, it is feasible to implement the copying when placing the drawing view. The following is a VBA code demo which watches the event of document changing. If it is “Create Drawing View”, get the model document of the drawing view, and copy the specific iProperties to the drawing document.

Module:

Private cls As clsDocEvent
Sub startcmd()
    Set cls = New clsDocEvent
End Sub

Sub Endcmd()
    Set cls = Nothing
End Sub

Event Class:

'document event
Private WithEvents DocEvts As DocumentEvents
'current drawing document
Private thisDrawingDoc As DrawingDocument


Private Sub Class_Initialize()
    'get the current document
    Set thisDrawingDoc = ThisApplication.ActiveDocument
    'get document event
    Set DocEvts = thisDrawingDoc.DocumentEvents
  
End Sub

Private Sub Class_Terminate()
    Set DocEvts = Nothing
End Sub

Private Sub DocEvts_OnChange(ByVal ReasonsForChange As CommandTypesEnum, _
            ByVal BeforeOrAfter As EventTimingEnum, _
            ByVal Context As NameValueMap, _
            HandlingCode As HandlingCodeEnum)


If BeforeOrAfter = kAfter Then
       
        'check the context
        Dim i As Integer
        Dim oEachObj As Variant
        For i = 1 To Context.Count
      
       On Error Resume Next
       Set oEachObj = Context.Item(i)
      
       If Err Then
         Dim oName As String
         oName = Context.Item(i)
        
         'if this is fired by placing drawing view
         If oName = "Create Drawing View" Then
           
            'get the document the drawing view refers to
            Dim oLastView As DrawingView
            Set oLastView = thisDrawingDoc.ActiveSheet.DrawingViews(thisDrawingDoc.ActiveSheet.DrawingViews.Count)
           
            Dim oRefDoc As Document
            Set oRefDoc = oLastView.ReferencedDocumentDescriptor.ReferencedDocument
           
            'copy some specific iProperties to the drawing document
           
            ' document title
             Dim oTitle As String
             oTitle = oRefDoc.PropertySets("Summary Information").ItemByPropId(kTitleSummaryInformation).value
             'copy to drawing document
             thisDrawingDoc.PropertySets("Summary Information").ItemByPropId(kTitleSummaryInformation).value = oTitle
           
            ' document description
              Dim oDesc As String
             oDesc = oRefDoc.PropertySets("Design Tracking Properties").ItemByPropId(kDescriptionDesignTrackingProperties).value
              'copy to drawing document
             thisDrawingDoc.PropertySets("Design Tracking Properties").ItemByPropId(kDescriptionDesignTrackingProperties).value = oDesc
         End If
        
         Err.Clear
       Else
          'if context item is also a NamedValueMap
       End If
    
    Next
  
    End If
End Sub

Getting properties of file interation with Vault Development Framework in Vault 2014 API

$
0
0
By Daniel Du

 

I am playing with the Vault Development Framwork(VDF) which is provided from Autodesk Vault 2014, here is a demo of getting file’s properties with VDF. I am doing in C#, and I just noticed that Wayne did a similar sample in VB.net here.

In Vault 2013 or earlier version, we can get properties with PropertyService PropertyManager. While in Vault 2014, with VDF we have a new way to do that, we can get the properties with PropertyManager, following code snippet demos how to login to Vault and get property manager. With VDF, it is easy to login vault with a built-in well designed UI, or a non-UI way if prefer:

////login with UI//VDF.Vault.Currency.Connections.Connection connection = VDF.Vault.Forms.Library.Login(new VDF.Vault.Forms.Settings.LoginSettings());//Another way to log into Vault without UI
VDF.Vault.Results.LogInResult results =
		VDF.Vault.Library.ConnectionManager.LogIn(
				"localhost", "Vault", "Administrator", "",
				VDF.Vault.Currency.Connections.AuthenticationFlags.Standard, null);
if (!results.Success)
{
	Console.WriteLine("Login failed. exit...");
	Console.ReadLine();
	return;
}
 
VDF.Vault.Currency.Connections.Connection connection = results.Connection;
 
VDF.Vault.Services.Connection.IPropertyManager propMgr = connection.PropertyManager;

 

In this sample, I firstly get all folders/file entities in vault, talking about this, the first idea comes to my head is to use FolderManager and FileManager, but with help of Daniel Dulzo, one of my Vault API expert colleauges, I will use

IEntityOperationManager, which can be accessed off of a connection object through the EntityOperations property, provides a set of methods that can be used on generic IEntity instances. So while I checked for a method to get child files in both the FileManager and the FolderManager, the method to get child entities actually exists on the IEntityOperationManager because it is generic to all entities.

 

OK, here are the code snippet:

 

using Autodesk.Connectivity.WebServices;
using System;
using System.Collections.Generic;
using System.Linq;
using VDF = Autodesk.DataManagement.Client.Framework;

namespace VaultLabs
{
  class Lab03
  {
    // We will collect Property Definitions here
    static VDF.Vault.Currency.Properties.PropertyDefinitionDictionary propDefs;

    // The entry point of the program
    //==========================================================================
    static void Main(string[] args)
    {
      try
      {

        ////login with UI
        //VDF.Vault.Currency.Connections.Connection connection
          = VDF.Vault.Forms.Library.Login(new VDF.Vault.Forms.Settings.LoginSettings());

        //Another way to log into Vault without UI
        VDF.Vault.Results.LogInResult results =
            VDF.Vault.Library.ConnectionManager.LogIn(
                "localhost", "Vault", "Administrator", "",
                VDF.Vault.Currency.Connections.AuthenticationFlags.Standard, null);
        if (!results.Success)
        {
          Console.WriteLine("Login failed. exit...");
          Console.ReadLine();
          return;
        }

        VDF.Vault.Currency.Connections.Connection connection = results.Connection;


        if (connection.IsConnected)
        {
          ReadProperties(connection);

          VDF.Vault.Currency.Entities.Folder folder = connection.FolderManager.RootFolder;

          PrintChildren(connection, folder);



          Console.ResetColor();
          Console.WriteLine("");
          Console.WriteLine("Press any key to exit...");
          Console.ReadKey();
        }



      }
      catch (Exception ex)
      {
        Console.WriteLine("ERROR: {0}", ex.Message);
      }
    } // Main()


    // Read all the Property Definitions for the "FILE" Entity Class
    //===============================================================================
    static void ReadProperties(VDF.Vault.Currency.Connections.Connection connection)
    {
      propDefs =
        connection.PropertyManager.GetPropertyDefinitions(
          VDF.Vault.Currency.Entities.EntityClassIds.Files,
          null,
          VDF.Vault.Currency.Properties.PropertyDefinitionFilter.IncludeUserDefined
        );


    }


    // Output information about each file in a folder along with its properties
    //===========================================================================
    static void PrintChildren(VDF.Vault.Currency.Connections.Connection connection,
          VDF.Vault.Currency.Entities.Folder parentFolder)
    {
      Console.ForegroundColor = ConsoleColor.Cyan;
      Console.WriteLine("{0}", parentFolder.FullName);


      IEnumerable<VDF.Vault.Currency.Entities.IEntity> entities = connection
        .EntityOperations.GetBrowseChildren(parentFolder);
      if (entities != null&& entities.Count<VDF.Vault.Currency.Entities.IEntity>() > 0)
      {
        foreach (var ent in entities)
        {
          if (ent is VDF.Vault.Currency.Entities.FileIteration)
          {
            VDF.Vault.Currency.Entities.FileIteration fileIteration
              = ent as VDF.Vault.Currency.Entities.FileIteration;

            Console.ForegroundColor = ConsoleColor.Green;
            Console.WriteLine(" {0}", fileIteration.EntityName);
            Console.ForegroundColor = ConsoleColor.Yellow;

            //Now print the properties of the file
            PrintProperties(connection, fileIteration);


          }
          else if (ent is VDF.Vault.Currency.Entities.Folder)
          {
            // Recursively print info about subfolders and files in them
            //-------------------------------------------------------------------------

            VDF.Vault.Currency.Entities.Folder folder
              = ent as VDF.Vault.Currency.Entities.Folder;
            PrintChildren(connection, folder);

          }
        }
      }

    }


    static void PrintProperties(VDF.Vault.Currency.Connections.Connection connection,
                      VDF.Vault.Currency.Entities.FileIteration fileInteration)
    {
      foreach (var key in propDefs.Keys)
      {
        // Print the Name from the Definition and the Value from the Property
        object propValue = connection.PropertyManager.GetPropertyValue(
                  fileInteration, propDefs[key], null);
        Console.WriteLine("  '{0}' = '{1}'",
                        key.ToString(),
                        propValue == null ? "" : propValue.ToString());
      }
    }


  } // class Lab03

} // namespace VaultLabs

Get Profile Path of Feature

$
0
0

By Xiaodong Liang

Typically, a feature is created from a profile. Assume we have got the feature, the Feature.Profile can return a set of connected curves (ProfilePath) used as input for a feature., ProfilePath.TextBoxPath tells if the profile is a TextBox, and ProfilePath.TextBox will return the TextBox object. The following is a code demo.

      PrivateSub Test()

        Try

            oApp =

                System.Runtime.InteropServices.Marshal.

                GetActiveObject("Inventor.Application")

 

            'assume a feature is selected

            Dim extFeature AsExtrudeFeature

            extFeature =

                oApp.ActiveDocument.SelectSet(1)

 

            Dim path AsProfilePath

            ForEach path In extFeature.Profile

                If path.TextBoxPath Then

                    ' if the profile is a textbox

                    'get the textbox object

                    Dim oTB AsTextBox = path.TextBox

                   

                Else

                    ' if it is from other sketch entities.

                    If path.Count > 0 Then

 

                        ForEach entity As

                        Inventor.ProfileEntityIn path

         'iterate each sketch entity in the path

                            If entity.CurveType =

            Curve2dTypeEnum.kLineSegmentCurve2d Then

 

                       'if it is a sketch line.

                      Dim oSkE AsSketchEntity =

                                    entity.SketchEntity

                      Dim oLine AsSketchLine =

                                    CType(oSkE, SketchLine)

                      Dim startpt As Inventor.Point2d =

                    oLine.StartSketchPoint.Geometry

                   Dim endpt As Inventor.Point2d =

                     oLine.EndSketchPoint.Geometry

 

                            EndIf

 

                            ''other sketch types

                            ''

 

                        Next

                    EndIf

                EndIf

            Next

        Catch ex AsException

 

        EndTry

 

    EndSub

Monitor User Configuration Changes Using Autodesk Vault API

$
0
0
By Daniel Du
 

As you know, it is possbile to write event handler to customize the business logic. These handlers will receive notification whenever a Vault client on that machine does an action that you subscribed to. For example if a program tries to check in a file, your code can get notified of that action.  Then you can proceed to block the operation or perform additional tasks.  As demoed in the “RestrictOperations” sample in Vault SDK, many services provide many events which can be hooked to do customization. One user is asking how to monitor user configiruation changes, for example, When a new user is created and added to a group, or when a existing user's ACL has been modified, a email notification should be sent to administrator, or create a configuration changes log into database.

It is natrual to look into AdminService or SecurtyService, expecting some specfic events like DocumentService, ItemService ,etc. Unfortunatly, AdminService or SecurtyService does not expose such specific events, but they do have some events:

Public Event PostInvokeEvents Subscribe to this event to get a notification after every web service call. 
Public Event PreInvokeEvents   Subscribe to this event to get a notification before every web service call. 

The event handler receives an argument of type WebServiceInvokeEventArgs containing data related to this event. The following WebServiceInvokeEventArgs properties provide information specific to this event.

MethodNameThe name of the method being called.
ParametersThe method parameters
ReturnValueThe return values. The first element will be the standard return. Elements after are from [out] parameters.

PostInvokeEvents will be triggered after every single service methods is call, PreInvokeEvents will be triggered before a service method is called. We can create our own event hander, in which we can check the MethodName so that we know which method is called, then take some necessory action to customize the business logic.

To monistor user related changes, we need to hook up AdminService.PreInvokeEvents or AdminService.PostInvokeEvents, for ACL changes, we need to hook up SecurityServices.PreInvokeEvents and SecurityService.PostInvokeEvents.

Here is a sample :

      //register events
      connection.WebServiceManager.AdminService.PreInvokeEvents += AdminService_PreInvokeEvents;
      connection.WebServiceManager.AdminService.PostInvokeEvents += AdminService_PostInvokeEvents;

      connection.WebServiceManager.SecurityService.PostInvokeEvents += SecurityService_PostInvokeEvents;
 
    void SecurityService_PostInvokeEvents(object sender, WebServiceInvokeEventArgs e)
    {
        //do something according to e.MethodName
    }

    void AdminService_PostInvokeEvents(object sender, WebServiceInvokeEventArgs e)
    {


      string para = "";
      for (int i = 0; i < e.Parameters.Length; i++)
      {
        para += e.Parameters[i].ToString() + "\n";
      }

      string msg = "MethodName : " + e.MethodName + "\n"
                + "Parameters :" + para + "\n"
                + "ReturnValue :" + e.ReturnValue + "\n";


      MessageBox.Show(msg + " Excution complete");

      // if a new use added
      if (e.MethodName == "AddUser")
      {
         MessageBox.Show("A new user is added.");
      }
    }

    void AdminService_PreInvokeEvents(object sender, WebServiceInvokeEventArgs e)
    {
      string para = "";
      for (int i = 0; i < e.Parameters.Length; i++)
      {
        para += e.Parameters[i].ToString() + "\n";
      }

      string msg = "MethodName : " + e.MethodName + "\n"
                + "Parameters :" + para + "\n"
                + "ReturnValue :" + e.ReturnValue + "\n";

      MessageBox.Show(msg + " will run.");

      if (e.MethodName == "AddUser")
      {
        MessageBox.Show("A new user will be added.");
      }
    }

Different capbilities of Vault API between different vault versions

$
0
0

By Daniel Du

As you know, We have different flavors of vault 2014( Basic, Workgroup, Professional), the difference of different vault version can be find here in product page. But I am always asked whether one specific API(or simple requirement) can be used on specific vault version, For example, does vault basic support adding UDP? I understand that customer always wants to minimize their investment.

For the most part, the differences in the APIs between the various flavors of Vault are made by including or excluding different supported services. The “Web Services” article in the SDK documentation, which gives an overview of all the different web services that make up the Vault web service API, has information about which services are available in which flavors of Vault. I make follow table for convenience.

 Vault BasicVault WorkgroupVault Professional
AdminService
Contains methods for manipulating users and groups.

AuthService
A service for authenticating to the Vault server.

 DocumentService
Contains methods for manipulating files and folders within a vault.
 FilestoreService
A service for uploading and downloading binary file data.

FilestoreVaultService
Information on the Knowledge Vaults.

KnowledgeVaultService
Contains methods for getting information about the vaults and options settings.

InformationService
Contains methods to determine information about the server and supported products

IdentificationService
Provides the locations of the data server and the filestore server.

ItemService
Contains methods for manipulating items.

BehaviorService
Contains methods for manipulating behaviors on Entities.

Limited

CategoryService
Contains methods for manipulating categories.

Limited

JobService
Contains methods for manipulating the job queue.

Limited

LifeCycleService
Contains methods for manipulating lifecycles on Entities.

Limited

PropertyService
Contains methods for manipulating properties on Entities.

Limited

ReplicationService
Contains methods for transfering ownerhsip between workgroups.

Limited

RevisionService
Contains methods for manipulating revision values and schemes for Entities.

Limited

SecurityService
Contains methods for setting security on specific Entities.

Limited

ReplicationService
Contains methods for transfering ownerhsip between workgroups.

LimitedLimited

DocumentServiceExtensions
Contains more methods for manipulating files and folders within a vault.

-

ChangeOrderService
Contains methods for creating and manipulating change orders.

--
 

CustomEntityService
Contains methods for creating and manipulating custom entities.

--

ForumService
Contains methods for posting messages.

--

ItemService
Contains methods for manipulating items.

--

PackageService
Contains methods for importing and exporting item data

--

WinAuthService
Contains methods for logging into and out of vaults using Windows credentials.

--

Furthurmore, we do provide a way to check which flavor of the server you are connected to. The web service API’s InformationService has a GetSupportedProducts() method which can be used to see which flavors of Vault the server supports. Alternatively, the VDF layer of the SDK provides some helpful features for checking if you’re working with the correct level of Vault. On the VDF’s IVaultConnectionManagerService, you can specify product requirements for your application using the SetProductRequirements() method. This will prevent your application from allowing a connection to be established to a Vault that doesn’t meet your applications minimum features. Also, you can use the same VDF server to check if a specific server supports certain versions of Vault with the IsProductSupported() method. Please read the SDK documentation for more details on these methods.

 
 

How to reverse an Insert Constraint Axes?

$
0
0

By Philippe Leefsma

The AxesOpposed property of an InsertConstraint is a ReadOnly property, however it is possible to workaround that limitation using the “ConvertToInsertConstraint” method.

Here is the VBA code for that. It assumes that the constraint(1) is an insert:

Sub ToggleInsertAxes()

    Dim doc As AssemblyDocument
    Set doc = ThisApplication.ActiveDocument
   
    Dim insert As InsertConstraint
    Set insert = doc.ComponentDefinition.Constraints(1)

    Call insert.ConvertToInsertConstraint( _
        insert.EntityOne, _
        insert.EntityTwo, _
        Not insert.AxesOpposed, _
        insert.Distance.value)
  
End Sub

column of BOM for “Area”of component

$
0
0

By Xiaodong Liang

Question:
Is there any way to get an area for the entire assembly on the BOM?  If you go to iProperties --> Physical it is shown there. But how to pull it from there and have it as Column in BOM? Can it be done using API ?

Solution:
Firstly, currently, no API to add/remove column of BOM. You have to add it manually in advance. The following is the steps to achieve your requirement. This also applies to Mass/Volume or other iProperties.

1. In the component file (such as a part), add one custom iProperty manually e.g. named  “Area”. The type is Text.

image

2. add a iLogic rule with the component file. It will get the Area value from iProperty, and update the custom iProperty.

image

'current documentdoc=ThisDoc.Document'unit manager of the documentoUOM=doc.UnitsOfMeasure'get the value of AreasurfaceArea=iProperties.Area'round the value with 4 valid numbers (optional)surfaceArea=Round(surfaceArea, 4)'convert the value to a string with the unit of the documentsurfaceArea=surfaceArea.ToString()+""+oUOM.GetStringFromType(oUOM.LengthUnits)+"^2"'update the custom property "Area" we creatediProperties.Value("Custom", "Area")=surfaceArea

3. add this rule with the iLogic trigger “Part Geometry Change”thus when the model changes, the rule will be executed automatically and update the custom property.

 

image

 

4. In the assembly >> BOM, add one custom column named “Area”.This column will read the custom property from the component.

image

 

image


Progressive Tooltip with Button

$
0
0

By Xiaodong Liang

Progressive Tooltip provides the expanded help tip with more various information.

image

 

Inventor 2011 has exposed the relevant API. The ControlDefinition.ProgressiveToolTip allows you to customize your button. Although we normally create button in an add-in, the following VBA code is a demo how the workflow could be. I have answered a forum question last year with such code. It adds a button in Part>>3D Model >> Work Features with the progressive tooltip.

Public Sub ProgressiveToolTips()   
   Dim g_FilePath As String
   g_FilePath = "C:\temp\"
 
    ' Create the button definition.
    Dim smallIcon As IPictureDisp
    Set smallIcon = LoadPicture(g_FilePath & "SmallProgTooltip.bmp")
   
    Dim largeIcon As IPictureDisp
    Set largeIcon = LoadPicture(g_FilePath & "LargeProgTooltip.bmp")
   
    Dim buttonDef As ButtonDefinition
    Set buttonDef = ThisApplication.CommandManager.ControlDefinitions.AddButtonDefinition("Sample1", "SampleCommand", kQueryOnlyCmdType, "", "Sample command to show progressive tool tips.", "Sample", smallIcon, largeIcon)
   
    ' Add a control to the Work Feature panel of the Model tab of the Part ribbon.
    Call ThisApplication.UserInterfaceManager.Ribbons.Item("Part").RibbonTabs.Item("id_TabModel").RibbonPanels.Item("id_PanelA_ModelWorkFeatures").CommandControls.AddButton(buttonDef, True)
   
    ' Define the progressive tooltip.  This would typically be done in the
    ' same section of code where the button definition is created but there's
    ' a problem with the beta version where the progressive tooltip can only
    ' be defined on a control has been created.
    With buttonDef.ProgressiveToolTip
        .Description = "The short description."
        .ExpandedDescription = "This is the long expaned version of the description that could have a more complete description to accompany the picture."
        Dim progImage As IPictureDisp
        Set progImage = LoadPicture(g_FilePath & "koala.jpg")
         .Image = progImage
        .IsProgressive = True
        .Title = "Sample1"
      
    End With
End Sub

 

image

Generate Permanent Link of Entities in Vault and Open in Thin Client

$
0
0

By Daniel Du

You probablay have noticed that Vault 2014 releases a new client – Thin Client with completely new UI. It is really a light one, you do not need to install anything on client side, a broswer is good enough. Thin Client performs read-access tasks in a vault, such as searching the vault and viewing file history using a web browser. If you have not noticed this, try it now, goto http://servername/AutodeskTC in your broswer, where servername is either the IP address or the name of the computer hosting Autodesk Data Management Server.

In this post, I will introduce how to integerate Vault Explorere and Vault ThinClient. I will create a Vault Explorer plugin, which enable users to right click a file or folder in Explorer and view it in Vault ThinClient. This is a just a demonstration, you may have better idea to use this permnent link, for example, save it into your database or ERP systems. In Autodesk Vault 2014 API, KnowledgeVaultService provides functions to get/set the persistent ID of entites.  GetPersistentIds and ResolvePersistentIds in the KnowledgeVaultService are the functions to use for converting between file IDs and the persistent IDs.  Keep in mind that there are two types of persistent IDs for files.  If EntPersistOpt is History, the Persistent ID is for a specific file version.  If EntPersistOpt is Latest, the Persistent ID is for the latest version of the file.  The caller has to know which type to use.  There is no way to tell the type by looking at the Persistent ID itself. Another tricky part is that, the PersistentId retrieved from Vault API is not the exact id of ThinClient URL, here is the core snippet of generating url of files and folders in ThinClient:

string[] ids = webMgr.KnowledgeVaultService.GetPersistentIds(
  VDF.Vault.Currency.Entities.EntityClassIds.Files,
  new long[] { file.Id },
  Autodesk.Connectivity.WebServices.EntPersistOpt.Latest);

string id = ids[0];
id = id.TrimEnd('=');
url = string.Format("{0}://{1}/AutodeskTC/{1}/{2}#/Entity/
Details?id=m{3}=&itemtype=File"
,
  serverUri.Scheme, serverUri.Host, currentConnection.Vault, id);

 

 

string[] ids = webMgr.KnowledgeVaultService.GetPersistentIds(
  VDF.Vault.Currency.Entities.EntityClassIds.Folder,
  new long[] { folder.Id },
  Autodesk.Connectivity.WebServices.EntPersistOpt.Latest);

string id = ids[0];
id = id.TrimEnd('=');
url = string.Format("{0}://{1}/AutodeskTC/{1}/{2}#/Entity/
Entities?folder=m{3}=&start=0"
,
  serverUri.Scheme, serverUri.Host, currentConnection.Vault, id);

 

Please note that there is “m” in front of the persistent ID, which may confuse you, but it is how it works :) Following is the comple code for this plugin:

 

using Autodesk.Connectivity.Explorer.Extensibility;
using Autodesk.Connectivity.Extensibility.Framework;
using Autodesk.Connectivity.WebServices;
using Autodesk.Connectivity.WebServicesTools;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Windows.Forms;
using VDF = Autodesk.DataManagement.Client.Framework;



[assembly: ApiVersion("6.0")]
[assembly: ExtensionId("76491449-B3FB-4570-81C4-17FE48BF50CB")]

namespace ThinClientUrlExtension
{
  public class ThinClientUrlGenerator : IExplorerExtension
  {

    VDF.Vault.Currency.Connections.Connection currentConnection;


    public IEnumerable<CommandSite> CommandSites()
    {

      CommandItem ThinClientUrlCmd = new CommandItem(
        "Autodesk.ADN.PermaLink", "View in Thin Client...")
      {
        NavigationTypes = new SelectionTypeId[] {
          SelectionTypeId.File,
          SelectionTypeId.FileVersion,
          SelectionTypeId.Folder },
        MultiSelectEnabled = false
      };

      ThinClientUrlCmd.Execute += ThinClientUrlCmd_Execute;
      CommandSite permaLinkFileContextSite = new CommandSite(
        "Autodesk.ADN.PermaLinkFileContext", "PermaLinkFileContext")
      {
        DeployAsPulldownMenu = false,
        Location = CommandSiteLocation.FileContextMenu
      };
      permaLinkFileContextSite.AddCommand(ThinClientUrlCmd);

      CommandSite permaLinkFolderContextSite = new CommandSite(
        "Autodesk.ADN.PermaLinkFolderContext", "PermaLinkFolderContext")
      {
        DeployAsPulldownMenu = false,
        Location = CommandSiteLocation.FolderContextMenu
      };
      permaLinkFolderContextSite.AddCommand(ThinClientUrlCmd);

      List<CommandSite> sites = new List<CommandSite>();
      sites.Add(permaLinkFileContextSite);
      sites.Add(permaLinkFolderContextSite);

      return sites;
    }

    void ThinClientUrlCmd_Execute(object sender, CommandItemEventArgs e)
    {

      WebServiceManager webMgr = currentConnection.WebServiceManager;

      ISelection selectedItem = e.Context.CurrentSelectionSet.FirstOrDefault<ISelection>();
      if (selectedItem != null)
      {
        Uri serverUri = new Uri(webMgr.InformationService.Url);
        string url;

        if (selectedItem.TypeId == SelectionTypeId.File)
        {
          File file = webMgr.DocumentService.GetLatestFileByMasterId(selectedItem.Id);
          if (file == null)
          {
            return;
          }

          string[] ids = webMgr.KnowledgeVaultService.GetPersistentIds(
            VDF.Vault.Currency.Entities.EntityClassIds.Files,
           new long[] { file.Id },
           Autodesk.Connectivity.WebServices.EntPersistOpt.Latest);

          string id = ids[0];
          id = id.TrimEnd('=');
          url = string.Format("{0}://{1}/AutodeskTC/{1}/{2}#/Entity/Details?id=m{3}=&itemtype=File",
               serverUri.Scheme, serverUri.Host, currentConnection.Vault, id);

          //Open with default broswer
          Process.Start(url);

          //copy url to clipboard
          Clipboard.SetText(url);
        }

        if (selectedItem.TypeId == SelectionTypeId.Folder)
        {
          Folder folder = webMgr.DocumentService.GetFolderById(selectedItem.Id);
          if (folder == null)
          {
            return;
          }

          string[] ids = webMgr.KnowledgeVaultService.GetPersistentIds(
            VDF.Vault.Currency.Entities.EntityClassIds.Folder,
            new long[] { folder.Id },
            Autodesk.Connectivity.WebServices.EntPersistOpt.Latest);

          string id = ids[0];
          id = id.TrimEnd('=');
          url = string.Format("{0}://{1}/AutodeskTC/{1}/{2}#/Entity/Entities?folder=m{3}=&start=0",
            serverUri.Scheme, serverUri.Host, currentConnection.Vault, id);

          //Open with default broswer
          Process.Start(url);

          //copy url to clipboard
          Clipboard.SetText(url);
        }



      }



    }

    public void OnLogOn(IApplication application)
    {
      currentConnection = application.Connection;

    }

    public IEnumerable<CustomEntityHandler> CustomEntityHandlers()
    {
      throw new NotImplementedException();
    }

    public IEnumerable<DetailPaneTab> DetailTabs()
    {
      throw new NotImplementedException();
    }

    public IEnumerable<string> HiddenCommands()
    {
      throw new NotImplementedException();
    }

    public void OnLogOff(IApplication application)
    {

    }

    public void OnShutdown(IApplication application)
    {

    }

    public void OnStartup(IApplication application)
    {

    }
  }
}

 

 

Let’s take a look at how it works:

 

image

image

image 

image

 

Hope it helps!

Connecting an Inventor plug-in to an external application using WCF

$
0
0

By Philippe Leefsma

We have many references on how to connect an Inventor plug-in to an external executable using COM, but as it becomes an antique technology as years are passing I though it would be useful to illustrate how to achieve the same (and potentially much more) using WCF.

The idea is to have a WCF server that is hosted by an Inventor .Net plug-in. One or several client executables running on the same machine will be able to connect to that server and exchange data. Eventually the server can also dispatch data send by one client to the other.

To make the thing more fun I created a little chat application where clients can send messages between each other. You will find the complete code attached with the download at the bottom of that blog post. For more details about the implementation, take a look at the initial post I created on our Cloud & Mobile blog:

Inter-process communication using WCF

The InventorServer plug-in is loaded in Inventor and can start processing requests from the clients:

inventor

Split Feature without SplitFeature

$
0
0

By Xiaodong Liang

SplitFeature is also a type of feature. But if you do not want to split a feature without SplitFeature, you could calcuate the new profiles and create the new splitting features. The following is a small code which converts an extrude feature to two extrude features with a middle line, and also creates a surface of the middle line to represent the split plane.

Assume the orignal extrude feature is based on a profile of a rectangle lines.

image

Sub test()

    Dim oPartDoc As PartDocument
    Set oPartDoc = ThisApplication.ActiveDocument
   
    Dim oDef As PartComponentDefinition
    Set oDef = oPartDoc.ComponentDefinition
   
    Dim oOldF As ExtrudeFeature
    Set oOldF = oDef.Features.ExtrudeFeatures(1)
   
    Dim oOldFDef As ExtrudeDefinition
    Set oOldFDef = oOldF.Definition
   
    Dim oPath As ProfilePath
    Set oPath = oOldFDef.Profile(1)
   
    Dim oSketchEnt As SketchEntity
    Dim oSketch As PlanarSketch
  
        
        Dim oSketchLine1 As SketchLine
        Set oSketchLine1 = oPath(1).SketchEntity
       
        Dim oSketchLine2 As SketchLine
        Set oSketchLine2 = oPath(2).SketchEntity
       
        Dim oSketchLine3 As SketchLine
        Set oSketchLine3 = oPath(3).SketchEntity
       
        Dim oSketchLine4 As SketchLine
        Set oSketchLine4 = oPath(4).SketchEntity
       
        'get sketch
        Set oSketch = oSketchLine1.Parent
       
        'get mid pt of line 1
        Dim oMidPtOfLine1 As Point2d
        Set oMidPtOfLine1 = oSketchLine1.Geometry.MidPoint
       
        'add sketch mid pt
        Dim oMidSketchPtLine1 As SketchPoint
        Set oMidSketchPtLine1 = oSketch.SketchPoints.Add(oMidPtOfLine1)
        Call oSketch.GeometricConstraints.AddCoincident(oMidSketchPtLine1, oSketchLine1)
       
        'get mid pt of line3 which is parallel to line 1
        Dim oMidPtOfLine3 As Point2d
        Set oMidPtOfLine3 = oSketchLine3.Geometry.MidPoint
       
        'add sketch mid pt
         Dim oMidSketchPtLine3 As SketchPoint
        Set oMidSketchPtLine3 = oSketch.SketchPoints.Add(oMidPtOfLine3)
         Call oSketch.GeometricConstraints.AddCoincident(oMidSketchPtLine3, oSketchLine3)
       
        ' create mid line
        Dim oMiddleLine As SketchLine
        Set oMiddleLine = oSketch.SketchLines.AddByTwoPoints(oMidPtOfLine1, oMidPtOfLine3)
     
        Call oMiddleLine.StartSketchPoint.Merge(oMidSketchPtLine1)
        Call oMiddleLine.EndSketchPoint.Merge(oMidSketchPtLine3)
       
        ' create new extrude 1: just change the old feature's profile
        Dim oNewPaths1 As ObjectCollection
        Set oNewPaths1 = ThisApplication.TransientObjects.CreateObjectCollection
        oNewPaths1.Add oSketchLine1
        oNewPaths1.Add oSketchLine2
        oNewPaths1.Add oSketchLine3
        oNewPaths1.Add oMiddleLine
       
        Dim oNewProfile1 As Profile
        Set oNewProfile1 = oSketch.Profiles.AddForSolid(False, oNewPaths1)

        oOldFDef.Profile = oNewProfile1
       
        'create the other extrude feature
         Dim oNewPaths2 As ObjectCollection
        Set oNewPaths2 = ThisApplication.TransientObjects.CreateObjectCollection
        oNewPaths2.Add oSketchLine1
        oNewPaths2.Add oSketchLine4
        oNewPaths2.Add oSketchLine3
        oNewPaths2.Add oMiddleLine
       
        Dim oNewProfile2 As Profile
        Set oNewProfile2 = oSketch.Profiles.AddForSolid(False, oNewPaths2)
        
        Dim oNewExtrudeDef As ExtrudeDefinition
        Set oNewExtrudeDef = oDef.Features.ExtrudeFeatures.CreateExtrudeDefinition(oNewProfile2, kJoinOperation)
        Call oNewExtrudeDef.SetDistanceExtent(1, kNegativeExtentDirection)
        Dim oNewExtrude As ExtrudeFeature
        Set oNewExtrude = oDef.Features.ExtrudeFeatures.Add(oNewExtrudeDef)
       
        'create surface on
          Dim oNewPaths3 As ObjectCollection
        Set oNewPaths3 = ThisApplication.TransientObjects.CreateObjectCollection
        oNewPaths3.Add oMiddleLine
       
        Dim oNewProfile3 As Profile
        Set oNewProfile3 = oSketch.Profiles.AddForSurface(oMiddleLine)
       
         Dim oSurfaceDef As ExtrudeDefinition
        Set oSurfaceDef = oDef.Features.ExtrudeFeatures.CreateExtrudeDefinition(oNewProfile3, kSurfaceOperation)
        Call oSurfaceDef.SetDistanceExtent(10, kSymmetricExtentDirection)
        Dim oSurface As ExtrudeFeature
        Set oSurface = oDef.Features.ExtrudeFeatures.Add(oSurfaceDef)

   
End Sub

 

After the code, the feature becomes:

image

Custom File Dialog with Open Express

$
0
0

By Xiaodong Liang

From Inventor 2014, you are allowed to open assembly in “Express Mode” which is essentially a light weight model. The benefits of this, are that you can open models faster and that you can open, and work with lots of complex geometry that may have previously been a bit too much for your graphics card to process.

           - from Clinton Brown's Blog

When you open an assembly, you can see an option [Open Express] which indicates whether opening in express mode or not.

image

 

API can override the built-in open dialog with the custom behaviors. But some developers found even though the custom dialog is opened correctly, the [Open Express] option is missed.

Actually, the issue is because the FileDialog.InsertMode property is true (this is the default value). We don't support opening in Express mode for insert (e.g. place component). If it is appropriate, this will happen automatically. The solution is to set the InsertMode to false prior to showing the dialog. Then the Express checkbox will be shown and enabled as appropriate. The API help reference is not well documented at this point.

In addition, when InsertMode = false, the custom file dialog will know the choice of the user of the option [Open Express]. But you need to tell Inventor if opening assembly in express or not. Otherwise, the assembly will still be opened in full mode.

The following is a VBA demo:

‘*****module******

Option Explicit

Private oEventHandler As Class1

Private Sub StartFileOpen()
   Set oEventHandler = New Class1
End Sub
  
Private Sub EndFileOpen()
    Set oEventHandler = Nothing
End Sub

‘****even class *******

Option Explicit

Private WithEvents oEvents As FileUIEvents
Private inCustomDlg As Boolean


Private Sub Class_Initialize()
Set oEvents = ThisApplication.FileUIEvents
inCustomDlg = False
End Sub


Private Sub Class_Terminate()
Set oEvents = Nothing
End Sub

Private Sub oEvents_OnFileOpenDialog(FileTypes() As String, ByVal ParentHWND As Long, FileName As String, ByVal Context As NameValueMap, HandlingCode As HandlingCodeEnum)

If inCustomDlg = False Then '  to avoid recursive callback
    inCustomDlg = True
    Dim oFileLocations As FileLocations
    Set oFileLocations = ThisApplication.FileLocations
   
    Dim FileOpenForm As FileDialog
    Call ThisApplication.CreateFileDialog(FileOpenForm)
    FileOpenForm.InsertMode = False
    FileOpenForm.InitialDirectory = oFileLocations.Workspace
    With FileOpenForm
            ' Set the initial Directory
            .InitialDirectory = oFileLocations.Workspace
            .DialogTitle = "My File Open"
            .Filter = "Part File (*.ipt)|*.ipt" _
                      & "|Assembly File (*.iam)|*.iam" _
                      & "|Presentation File (*.ipn)|*.ipn" _
                      & "|Drawing File (*.idw)|*.idw" _
                      & "|Design element File (*.ide)|*.ide" _

            .FilterIndex = 2    ' *.iam files
            .OptionsEnabled = True
            '.Flags = cdlOFNHideReadOnly
            .ShowOpen
        End With
        FileName = FileOpenForm.FileName
        If FileOpenForm.OptionValues.Count >= 6 Then
            ' assembly has 6 options
           
            Dim index As Integer
            Dim oKey As String
            For index = 1 To FileOpenForm.OptionValues.Count
            
                 oKey = FileOpenForm.OptionValues.Name(index)
                 If oKey = "OpenExpressMode" Then
                    ' this is a Boolean for OpenExpress/Don't open Express
                    If FileOpenForm.OptionValues.Item(index) Then
                        'if OpenExpress was specified, pass it back through the context
                        Context.Add "ExpressModeBehavior", "OpenExpress"
                    End If
                 End If
            Next
            
          
        End If

        If FileName = "" Then
            HandlingCode = kEventCanceled
        Else
            HandlingCode = kEventHandled
        End If
        inCustomDlg = False
End If
End Sub

Autodesk Vault Plug-in Wizard Helps Creating Vault Plug-in More Easily

$
0
0

By Daniel Du

 

As described in Vault SDK help file, it involves several steps to create a vault plug-in, including adding references, adding vcet.config file, setting additional assembly property and implementing some interfaces. You also need to copy the output files into vault extension folder manually. I found it a little complicated and time consuming, so I went ahead to create a vault plug-in wizard, which helps me creating vault explorer plug-in, custom job handlers, event handlers more easily. If you are interested in this tool, it can be downloaded here. Please note that it is not fully tested, and you are on your own risk to use this wizard.

 

After you installed this wizard, it should appear in your Visual Studio project templates. The template are available for both C# and VB.NET. This version is targeting Autodesk Vault 2014, so you need to select .Net Framework 4.0, if it does not appear, you probably selected wrong .net framework.

image

 

Now name your vault plug-in and specify the location as usual. By clicking OK, a wizard form will appear as below:

image

You need to check the Vault SDK path, Web Service Extension 3(WSE3) path and Vault Explorer execution path at first run, if it is not correct for you, you need to specify to the correct path and it will be saved for latter use. This wizard helps you creating vault explorer plug-in, custom job handlers or event handlers. With a customized vault explorer plug-in, you can add custom commands, add custom tabs, hide existing commands or subscribe to pre and post events when any Vault Explorer commands are executed. Jobserver is a nice feature that lets you distribute work across the network.  Instead of performing a task directly, a job can be queued up so that the work can be done elsewhere.  Vault comes with a few built-in job types, but the real power comes in creating your own. You can create your own job by choosing “Custom Job” in wizard. If you want to customize the business logic, you can write event handlers by choosing “Event Handler” in wizard.  These handlers will receive notification whenever a Vault client on that machine does an action that you subscribed to.

 

Then you can get a bare bone vault plug-in project with necessary files and adding necessary references.

image

The sample plug-in adds the default implementation of interfaces, you need to remove the ones you do not need. The Vault Explorer Plug-in also comes with a HelloWorld sample, you can modify it to create your own explorer plug-in based on it. Please note that if you rename the class name, you also need to change it in vaultplugin.vcet.config accordingly.

image

For all types of plug-in, a build event is added by wizard to help you copy the output dlls and vcet.config file to %ProgramData%/Autodesk/Vault 2014/Extensions/ folder. 

image

For Vault Explorer, the wizard also help us to setup the debug option, you can just press F5 to start Explorer for debugging.

image

 

So, that’s it, simple and easy, right ?

 

Finally all source code is uploaded to github, https://github.com/ADN-DevTech/Vault-Plugin-Wizard, I would be more than happy if you’d like to keep working on it or report issues there.

 

Have fun!

Modify Ribbon and Menu items

$
0
0

By Adam Nagy

Just like in other Autodesk products, in Inventor as well the same library is used to present a Ribbon interface: AdWindows.dll
This provides a public API under the namespace Autodesk.Windows

Here is an example of using it inside Revit: http://thebuildingcoder.typepad.com/blog/2011/02/pimp-my-autocad-or-revit-ribbon.html

It's not a fully supported approach though, since some functions like adding a command button to the Ribbon are not supported - it would be difficut to properly hook up a control created this way to an Inventor command. For that you would need to use the Inventor API.
So when using it, take care and make sure that everything is working as expected.

E.g. the following VB.NET code could be used to hide the Options button in the Application Menu:

AdWindows

' 1) Need to reference AdWindows.dll from' <Inventor Install Folder>\bin' 2) Set it to "Copy Local" = "False"
Dim menu As Autodesk.Windows.ApplicationMenu = 
  Autodesk.Windows.ComponentManager.ApplicationMenu
menu.OptionsButton.IsVisible = False 

Note: when referencing AdWindows.dll the project will require other dependencies as well that the compiler will warn you about. You'll simply have to add a reference to those Windows .NET assemblies as well: PresentationCore, PresentationFramework, WindowsBase and System.Xaml


Simple Exploration on CAM Simulation

$
0
0

By Xiaodong Liang

Autodesk provides solutions of CAM: Inventor CAM, CAM 360 etc. Some custom applications of Inventor would need to produce their own CAM process with the custom algorism. The most important step is to analogous to a machining operation.

I explored a bit with Inventor API. Basically, we need to get the update to date status of the base body that the tool has affected, by TransientBrep.DoBoolean, and display them by client graphics.

TransientBRep.DoBoolean( BlankBody As SurfaceBody,
                                         ToolBody As SurfaceBody,
                               BooleanType
As BooleanTypeEnum )

BlankBody: Input/Output SurfaceBody that will be modified as a result.
ToolBody: Input SurfaceBody that is used to operate on the blank body.
BooleanType: Input BooleanTypeEnum that specifies the type of Boolean operation to perform. Valid values are kBooleanTypeDifference, kBooleanTypeUnion, and kBooleanTypeIntersect.

In CAM simulation, the BooleanType is kBooleanTypeDifference which means the tool will remove the materials of the base body.

If you are not familiar with client graphics, I’d recommend with the tutorials we posted on Brian’s blog.

The following demo tests with the attached part in a standalone EXE, in which there are one plate which is base body and a small stick as a tool. The tool will move on X-Y plane and inside the base body along Z (depth = 1cm). It removes the material from the diameter = 4 cm and shrink to diameter = 0.

Download CamPart

Inventor.Application oInvApp;

Asset toolAppearance;

Asset baseAppearance;

void CamTest()

{

    //get active Inventor process

        oInvApp =

        System.Runtime.InteropServices.Marshal.

        GetActiveObject("Inventor.Application")

        as Inventor.Application;

 

    //get active document

    PartDocument oPartDoc =

        oInvApp.ActiveDocument asPartDocument;            

    PartComponentDefinition oPartDef =

        oPartDoc.ComponentDefinition;

 

    //Transient Brep object

    TransientBRep oTBrep =

        oInvApp.TransientBRep;

    //Transient Geometry

    TransientGeometry oTG=

        oInvApp.TransientGeometry;

 

    //base body

    SurfaceBody oBaseBody =

        oPartDef.SurfaceBodies[1];

    //tool body

    SurfaceBody oToolBody =

        oPartDef.SurfaceBodies[2];

 

    //make base body and tool body invisible

    //we just show client graphics

    oBaseBody.Visible = false;

    oToolBody.Visible = false;

 

    //make a copy of base body and tool body

    //we will use them as client graphics

    SurfaceBody oBaseBody_Copy =

        oTBrep.Copy(oBaseBody);

    SurfaceBody oToolBody_Copy =

        oTBrep.Copy(oToolBody);

 

    //Client Graphics

    ClientGraphics oClientGraphics;

    try

    {

        //delete if the Client Graphics exists

        oClientGraphics =

            oPartDef.ClientGraphicsCollection["CAMDemo"];

 

        // An existing client graphics object

        // was successfully obtained so clean up.

        oClientGraphics.Delete();

 

        // update the display to see the results.

        oApp.ActiveView.Update();              

    }

    catch

    {

        //get the appearance for tool

        toolAppearance =

            oPartDoc.Assets["Gold - Metal"];

 

        baseAppearance =

            oPartDoc.Assets["Plate"];

 

        // Create the ClientGraphics

        oClientGraphics =

            oPartDef.ClientGraphicsCollection.Add("CAMDemo");

 

        //add graphics node for base body

        GraphicsNode _oNode_BaseBody =

            oClientGraphics.AddNode(1);

        //add graphics of base body

        SurfaceGraphics _Gra_BaseBody =

            _oNode_BaseBody.AddSurfaceGraphics(oBaseBody_Copy);

        _oNode_BaseBody.Appearance = baseAppearance;    

 

        //add graphics node for tool body

        GraphicsNode _oNode_ToolBody =

            oClientGraphics.AddNode(2);

        //add graphics of tool body

        SurfaceGraphics _Gra_ToolBody =

            _oNode_ToolBody.AddSurfaceGraphics(oToolBody_Copy);

        _oNode_ToolBody.Appearance = toolAppearance;           

 

        //CAM Simulation starts:

 

        //move tool inside the base along Z

        Matrix oMovingM =

            oTG.CreateMatrix();

        oMovingM.SetTranslation(oTG.CreateVector(0, 0, -1));

 

        //move tool inside base body: depth = 1

        eachCAM(oMovingM, 

            ref oBaseBody_Copy,

            ref oToolBody_Copy,

            ref _oNode_BaseBody,

            ref _oNode_ToolBody,

            ref _Gra_BaseBody,

            ref _Gra_ToolBody);

 

        // diameter of the tool body

        double toolDia = 0.5;

 

        // how many circle loops the tool will move

        int loopCount = 10;               

        //from which diamater the tool starts to move

        double max_CAM_Dia = 4.0;          

 

        //last matrix of the tool body               

        Matrix oLastMovingM = oTG.CreateMatrix();

        oLastMovingM.SetToIdentity();

 

        //tool moves from max diameter to 0

        for (int circleLoop = loopCount;

            circleLoop > 0 ;

            circleLoop--)

        {

            //diameter of this loop

            double thisDia = max_CAM_Dia * circleLoop / loopCount;

            //the perimeter of this circle

            double perimeterofLoop = Math.PI * thisDia;

            //how many steps the tool needs to move for this loop

            int circleStepCount =

                (int)(perimeterofLoop / toolDia) *2;

                   

            //moving of each circle

            for (int angleIndex = 1;

                angleIndex < circleStepCount;

                angleIndex++)

            {              

                //get the location the tool will move to     

                double x = thisDia / 2.0 *

                    Math.Cos(angleIndex * Math.PI * 2 / circleStepCount);

                double y = thisDia/ 2.0 *

                    Math.Sin(angleIndex * Math.PI * 2 / circleStepCount );

                       

                //transform matrix

                Matrix oEachMovingM = oTG.CreateMatrix();

                oEachMovingM.SetTranslation(oTG.CreateVector(x, y, 0));

                //the last location of the tool affects

                //so invert and update with the new matrix

                oLastMovingM.Invert();

                oLastMovingM.TransformBy(oEachMovingM);                       

                oMovingM = oLastMovingM;

 

                //move

                eachCAM(oMovingM,                         

                    ref oBaseBody_Copy,

                    ref oToolBody_Copy,

                    ref _oNode_BaseBody,

                    ref _oNode_ToolBody,

                    ref _Gra_BaseBody,

                    ref _Gra_ToolBody);

                       

                //record the current matrix for next use

                oLastMovingM = oEachMovingM;

            }

        }

 

    } 

 

}

 

// each step of moving

void eachCAM(Matrix _oMovingM,                 

            refSurfaceBody _BaseBody,

            refSurfaceBody _ToolBody,

            refGraphicsNode _BaseBodyNode,

            refGraphicsNode _ToolBodyNode,                   

            refSurfaceGraphics _BaseGrap,

            refSurfaceGraphics _ToolGrap                  

            )

{

    TransientBRep oTBrep = oInvApp.TransientBRep;

 

    // we need to recreate the graphics.

        _BaseGrap.Delete();

        _ToolGrap.Delete();

           

    //transform the tool body

        oTBrep.Transform(_ToolBody, _oMovingM);            

    //remove material of the base body

        oTBrep.DoBoolean(_BaseBody, _ToolBody,

            BooleanTypeEnum.kBooleanTypeDifference);

 

            

    //add the update bodies again

        _BaseGrap = _BaseBodyNode.AddSurfaceGraphics(_BaseBody);

        _ToolGrap = _ToolBodyNode.AddSurfaceGraphics(_ToolBody);

    //assign the appearance to the tool graphics

             

        _BaseBodyNode.Appearance = baseAppearance;

        _ToolBodyNode.Appearance =toolAppearance;

    //update the view

        oInvApp.ActiveView.Update();

}

 

Untitled

 

Note: the residual images in this gif is caused by the video production.Tthere is no residual when working with Inventor.

Client feature visibility in design view representa​tions

$
0
0

By Xiaodong Liang

Question:
I have an assembly with a client feature that contains client graphics. I have exposed the visibility (ClientFeature.Definition.ClientGraphicsCollection​[1].Visible) to the user via a context menu option. Changing the visibility currently affects all view representations. Is there a way to associate the visibility with each design view representation?

Solution:
Client Feature is API specific. UI does not know it. So the default mechanism of design view representation does not cover the feature. But you can control this by RepresentationEvents. OnActivateDesignView. The following is a demo VBA, including a macro which creates the client feature.

 

‘****module: create client feature ************

Sub CGInClientFeatureTest()

Dim oDoc As AssemblyDocument

Set oDoc = ThisApplication.ActiveDocument

 

‘create client feature definition

Dim oClientFeatureDef As ClientFeatureDefinition

Set oClientFeatureDef = oDoc.ComponentDefinition.Features.ClientFeatures.CreateDefinition("ClientFeatureTest")

 

‘create client feature

Dim oClientFeature As ClientFeature

Set oClientFeature = oDoc.ComponentDefinition.Features.ClientFeatures.Add(oClientFeatureDef, "ClientIDString")

 

‘create graphics for client feature

Dim oCGCol As ClientGraphicsCollection

Set oCGCol = oClientFeatureDef.ClientGraphicsCollection

 

Dim oCG As ClientGraphics

On Error Resume Next

Set oCG = oCGCol.Item("CGWithCF")

If oCG Is Nothing Then

Set oCG = oCGCol.Add("CGWithCF")

End If

 

‘create node

Dim oSurfacesNode As GraphicsNode

Set oSurfacesNode = oCG.AddNode(1)

 

Dim oTransientBRep As TransientBRep

Set oTransientBRep = ThisApplication.TransientBRep

 

' Create a point representing the center of the bottom of the cone

Dim oBottom As Point

Set oBottom = ThisApplication.TransientGeometry.CreatePoint(0, 0, 0)

 

' Create a point representing the tip of the cone

Dim oTop As Point

Set oTop = ThisApplication.TransientGeometry.CreatePoint(0, 10, 0)

 

' Create a transient cone body

Dim oBody As SurfaceBody

Set oBody = oTransientBRep.CreateSolidCylinderCone(oBottom, oTop, 5, 5, 0)

 

' Reset the top point indicating the center of the top of the cylinder

Set oTop = ThisApplication.TransientGeometry.CreatePoint(0, -40, 0)

 

' Create a transient cylinder body

Dim oCylBody As SurfaceBody

Set oCylBody = oTransientBRep.CreateSolidCylinderCone(oBottom, oTop, 2.5, 2.5, 2.5)

 

' Union the cone and cylinder bodies

Call oTransientBRep.DoBoolean(oBody, oCylBody, kBooleanTypeUnion)

 

' Create client graphics based on the transient body

Dim oSurfaceGraphics As SurfaceGraphics

Set oSurfaceGraphics = oSurfacesNode.AddSurfaceGraphics(oBody)

 

ThisApplication.ActiveView.Update

End Sub

 

‘*******module: start/stop RepresentationEvents event*******

Dim oCls As clsREvents

Sub startE()

    Set oCls = New clsREvents

End Sub

 

Sub stopE()

    Set oCls = Nothing

End Sub

 

‘*****Class: RepresentationEvents**************

Private WithEvents ReEvts As RepresentationEvents

 

Private Sub Class_Initialize()

   

    Set ReEvts = ThisApplication.RepresentationEvents

End Sub

 

Private Sub Class_Terminate()

    Set ReEvts = Nothing

End Sub

 

 

Private Sub ReEvts_OnActivateDesignView(ByVal DocumentObject As Document, ByVal Representation As DesignViewRepresentation, ByVal BeforeOrAfter As EventTimingEnum, ByVal Context As NameValueMap, HandlingCode As HandlingCodeEnum)

 

    Dim oDoc As AssemblyDocument

Set oDoc = ThisApplication.ActiveDocument

 

‘get Client Feature

    Dim oClientFeature As ClientFeature

Set oClientFeature = oDoc.ComponentDefinition.Features.ClientFeatures(1)      

    

  If Representation.Name = "Master" Then

oClientFeature.Definition.ClientGraphicsCollection(1).Visible = kAllGraphicsVisible

  End If

 

  If Representation.Name = "View1" Then

oClientFeature.Definition.ClientGraphicsCollection(1).Visible = kNoGraphicsVisible

  End If 

 

End Sub

Untitled

Get Contour of WeldBead

$
0
0

By Xiaodong Liang

The WeldBead object provides the two faces which generates the weld, and also provides the faces that define the geometric result of the weld bead: WeldBead.BeadFaces

The following is a small demo that get the faces, add them as a client graphics.

Public Sub test()
   
    'get document and definition
    Dim oDoc As AssemblyDocument
    Set oDoc = ThisApplication.ActiveDocument
 
    Dim oCompDef As AssemblyComponentDefinition
    Set oCompDef = oDoc.ComponentDefinition
   
    'if this is a weld document
    If oCompDef.Type = kWeldmentComponentDefinitionObject Then
        Dim wcd As WeldmentComponentDefinition
        Set wcd = oCompDef
    Else
        Exit Sub
    End If
  
    ' get one weld bead
    Dim oWB As WeldBead
    Set oWB = wcd.Welds.WeldBeads(1)
 
    On Error Resume Next
    Dim oClientGraphics As ClientGraphics
    Set oClientGraphics = oCompDef.ClientGraphicsCollection.Item("weldbead")
    If Err.Number = 0 Then
        'delete the older client graphics, if any
        On Error GoTo 0
        oClientGraphics.Delete
        ThisApplication.ActiveView.Update
    End If
  
    Err.Clear
    On Error GoTo 0
  
   ' create a client graphics
    Set oClientGraphics = oCompDef.ClientGraphicsCollection.Add("weldbead")
  
    'add graphics node
    Dim oSurfacesNode As GraphicsNode
    Set oSurfacesNode = oClientGraphics.AddNode(1)
   
    'add the face of WeldBead.BeadFaces
    Dim oSurfaceGraphics As SurfaceGraphics
    Dim oEachWeldFace As Face
    For Each oEachWeldFace In oWB.BeadFaces
      Set oSurfaceGraphics = oSurfacesNode.AddSurfaceGraphics(oEachWeldFace)
    Next
   
    'set graphics' color. assume “Magenta” exists in the document
    oSurfacesNode.Appearance = oDoc.Assets("Magenta")
   
    'transform the client graphics to a location
     Dim oTransGeom As TransientGeometry
    Set oTransGeom = ThisApplication.TransientGeometry

    Dim oV As Vector
    Set oV = oTransGeom.CreateVector(10, 10, 10)

    Dim oM As Matrix
    Set oM = oTransGeom.CreateMatrix()
    Call oM.SetTranslation(oV)

    oSurfacesNode.Transformation = oM
   
    'update the view
    ThisApplication.ActiveView.Update

End Sub

image

Parent of Mirror Solid

$
0
0

By Xiaodong Liang

We have two choices when mirroring a solid, either the mirrored body is attached with the original solid, or a new solid is created.

image

We have two scenarios when mirroring a solid,

1) either the mirrored body is attached with the original solid

2) or a new solid is created

MirrorFeature.MirrorOfBody tells if the mirror feature is from a solid or the features. For scenario 1 above, MirrorFeature. SurfaceBody returns the original solid. For scenario 2, there is not direct API, but we can workaround it by checking the original face of the mirrored face, by which we can get the original solid.

The code below is a small demo. It assumes a mirror feature is selected. It covers the two scenarios.

Sub FindOriginalBody()

    Dim oPart As PartDocument

    Set oPart = ThisApplication.ActiveDocument

      Dim oPdef As PartComponentDefinition

    Set oPdef = oPart.ComponentDefinition

    Dim oMirrorF As MirrorFeature

    Set oMirrorF = ThisApplication.ActiveDocument.SelectSet(1)

    Dim oFPE As FeaturePatternElement

    Dim oMirrorMatrix As Matrix

    If oMirrorF.MirrorOfBody Then

        Dim oSB As SurfaceBody

‘set end of the feature below the mirror feature

       oMirrorF.SetEndOfPart True

       Set oSB = oMirrorF.SurfaceBody

‘set the end of feature back

oPdef.Features(oPdef.Features.Count).SetEndOfPart False

‘scenario 1

       ' if the mirror feature is built in the same solid

       If Not oSB Is Nothing Then

         Debug.Print "the original body for the mirror feature is:" & oSB.Name

          Exit Sub

       End If

‘scenario 2

       'if the mirror feature is built in a new solid       

       Dim oIdentityM As Matrix

      Set oIdentityM = ThisApplication.TransientGeometry.CreateMatrix

      oIdentityM.SetToIdentity   

‘ iterate each item of the mirror elements

       For Each oFPE In oMirrorF.PatternElements

         ' actually only two elements with Mirror feature.

          ' one is the original body, the other is the mirror           

          If oFPE.Transform.IsEqualTo(oIdentityM) = False Then

             ' this is the mirror element

            Set oMirrorMatrix = oFPE.Transform

          End If

       Next

         oMirrorMatrix.Invert

        Dim oEachF As Face

        Dim oEachBody As SurfaceBody

        ' MirrorFeature.Faces contains the faces of mirror feature only

        'just check one face

        Dim oFaceOnMirror As Face

        Set oFaceOnMirror = oMirrorF.Faces(1)

          Dim oPtInFace As Point

          Set oPtInFace = oFaceOnMirror.PointOnFace

          Call oPtInFace.TransformBy(oMirrorMatrix)

          On Error Resume Next

          'find which body contains the orignal face

          For Each oEachBody In oPdef.SurfaceBodies

                Dim oOrignFace As Face

                Set oOrignFace =
                    oEachBody.LocateUsingPoint(kFaceObject, oPtInFace)

                If Err.Number = 0 Then

                    If Not oOrignFace Is Nothing Then

                     Debug.Print "the original body for the mirror feature is:" & oEachBody.Name

                     'Exit For

                    End If

                    Err.Clear

                End If                

          Next

    End If

End Sub

Find Touching Area of Two Coplanar Faces

$
0
0

By Xiaodong Liang

Two planar faces which are coplanar are not always overlapped. To know if they are overlapped and the touching area, one workaround could be extrude the sketches based on the faces with a tiny distance, and use TransientBRep.DoBoolean to check if the bodies of the two extrude features are intersected.

The following is demo code. It assumes two planar faces are selected. One material named “Magenta” is available.

Note: in UI, if the two planar faces are within one surface body and are overlapped, they cannot be selected independently. So to make a demo, it assumes the two planar faces are from different bodies. Of course, you can distinguish two faces from one surface body in the workflow of code.

 PrivateSub Test()

 

        Try

            'get application

            oApp =

                System.Runtime.InteropServices.

                Marshal.GetActiveObject("Inventor.Application")

        Catch

        EndTry

 

        Dim oPartDoc AsPartDocument = oApp.ActiveDocument

        Dim oPartDef = oPartDoc.ComponentDefinition

 

        'get face1

        Dim oFace1 AsFace

        oFace1 = oPartDoc.SelectSet(1)

        'get face2

        Dim oFace2 AsFace

        oFace2 = oPartDoc.SelectSet(2)

 

        'if two faces are planar and coplanar

        If oFace1.SurfaceType =

                SurfaceTypeEnum.kPlaneSurface _

                    And oFace2.SurfaceType =

                    SurfaceTypeEnum.kPlaneSurface Then

 

            Dim oPlane1 AsPlane

            oPlane1 = oFace1.Geometry

            Dim oPlane2 AsPlane

            oPlane2 = oFace2.Geometry

 

            ' if normal of two faces are same

            If oPlane1.Normal.IsEqualTo(oPlane2.Normal) Then

 

                Dim extrudeDis AsDouble = 0.001

 

                'create the extrude feature from face1

                Dim oSketch1 AsPlanarSketch =

                    oPartDef.Sketches.Add(oFace1)

                Dim oEdgeInFace1 AsEdge

                ForEach oEdgeInFace1 In oFace1.Edges

                    oSketch1.AddByProjectingEntity(oEdgeInFace1)

                Next

                Dim oProfile1 AsProfile

                oProfile1 = oSketch1.Profiles.AddForSolid()

 

                Dim oExtrudeF1Def AsExtrudeDefinition

                oExtrudeF1Def =

                    oPartDef.Features.ExtrudeFeatures.

                    CreateExtrudeDefinition(oProfile1,

                        PartFeatureOperationEnum.kNewBodyOperation)

                oExtrudeF1Def.SetDistanceExtent(extrudeDis,

                        PartFeatureExtentDirectionEnum.kPositiveExtentDirection)

 

                Dim oExtrudeF1 AsExtrudeFeature

                oExtrudeF1 =

                    oPartDef.Features.ExtrudeFeatures.Add(oExtrudeF1Def)

 

                Dim oSB1 AsSurfaceBody

                oSB1 = oExtrudeF1.SurfaceBodies(1)

 

 

                'create the extrude feature from face2

                Dim oSketch2 AsPlanarSketch =

                    oPartDef.Sketches.Add(oFace2)

                Dim oEdgeInFace2 AsEdge

                ForEach oEdgeInFace2 In oFace2.Edges

                    oSketch2.AddByProjectingEntity(oEdgeInFace2)

                Next

 

                Dim oProfile2 AsProfile

                oProfile2 =

                    oSketch2.Profiles.AddForSolid()

 

                Dim oExtrudeF2Def AsExtrudeDefinition

                oExtrudeF2Def =

                    oPartDef.Features.ExtrudeFeatures.

                    CreateExtrudeDefinition(oProfile2,

                                 PartFeatureOperationEnum.kNewBodyOperation)

                oExtrudeF2Def.SetDistanceExtent(extrudeDis,

                                 PartFeatureExtentDirectionEnum.

                                  kPositiveExtentDirection)

 

                Dim oExtrudeF2 AsExtrudeFeature

                oExtrudeF2 =

                    oPartDef.Features.ExtrudeFeatures.Add(oExtrudeF2Def)

 

                Dim oSB2 AsSurfaceBody

                oSB2 = oExtrudeF2.SurfaceBodies(1)

 

                Dim oTransientB1 AsSurfaceBody =

                    oApp.TransientBRep.Copy(oSB1)

                Dim oTransientB2 AsSurfaceBody =

                    oApp.TransientBRep.Copy(oSB2)

 

                'check if bodies of the two extrude features are intersected

                oApp.TransientBRep.DoBoolean(oTransientB1,

                                   oTransientB2,

                                   BooleanTypeEnum.kBooleanTypeIntersect)

 

                If oTransientB1.Volume(0.01) > 0 Then

                    MsgBox("The two faces are overlapped!")

 

                    'create a client graphics to show the intersect area

                    Dim oClientGraphics AsClientGraphics

                    Try

                        oClientGraphics =

                            oPartDef.ClientGraphicsCollection.Item("overlap")

                        oClientGraphics.Delete()

                    Catch ex AsException

 

                    EndTry

 

                    oApp.ActiveView.Update()

 

                    oClientGraphics =

                        oPartDef.ClientGraphicsCollection.Add("overlap")

 

                    'add graphics node

                    Dim oSurfacesNode AsGraphicsNode

                    oSurfacesNode =

                        oClientGraphics.AddNode(1)

 

                    'add the face of WeldBead.BeadFaces

                    Dim oSurfaceGraphics AsSurfaceGraphics

                    oSurfaceGraphics =

                        oSurfacesNode.AddSurfaceGraphics(oTransientB1)

 

 

                    'set graphics' color. assume “Magenta” exists in the document

                    oSurfacesNode.Appearance =

                        oPartDoc.Assets("Magenta")

 

                    'transform the client graphics to a location

                    Dim oTransGeom AsTransientGeometry

                    oTransGeom =

                        oApp.TransientGeometry

 

                    Dim oV AsVector

                    oV = oTransGeom.CreateVector(1, 1, 1)

 

                    Dim oM AsMatrix

                    oM = oTransGeom.CreateMatrix()

                    Call oM.SetTranslation(oV)

 

                    oSurfacesNode.Transformation = oM

 

                    'update the view

                    oApp.ActiveView.Update()

 

 

                Else

                    MsgBox("The two faces are NOT overlapped!")

                EndIf

 

                oExtrudeF1.Delete()

                oExtrudeF2.Delete()

 

            Else

 

                MsgBox("the faces are NOT coplanar!")

            EndIf

 

        Else

 

            MsgBox("one of the faces are NOT planar!")

        EndIf

 

 

    EndSub

image

Viewing all 516 articles
Browse latest View live