mfg473705 using ilogic with design automation for inventor

30
Page 1 MFG473705 Using iLogic with Design Automation for Inventor to create a Configurator Sajith Subramanian Autodesk Description Inventor Design Automation, in general, allows the use of API’s to be executed in the cloud, similar to how they would work on the desktop, but without the need of any installed software or its dependent licenses. An additional advantage of Inventor Design Automation, which may be easily overlooked, is its capability to run iLogic scripts in the cloud. These scripts being embedded in the CAD file itself can be programmed to auto execute under certain conditions. This class speaks about taking advantage of this capability to combine Forge Design Automation with iLogic, creating a configurator by modifying an input Inventor File (IPT) in the cloud, using a web browser, according to the inputs provided by the user on an easy-to-use UI. The results can be immediately viewed on the browser itself, using the Forge Viewer and can also be downloaded in multiple formats such as IPT, IDW, and PDF. This web application sample uses latest web technologies and is OS independent and mobile device friendly. Speaker Sajith Subramanian - A qualified software engineer with over a decade of development experience with various CAD tools, he is part of the Manufacturing team at Autodesk, supporting and evangelizing API’s for Inventor, Fusion and Vault. Now an evangelist and an enthusiast on the Forge platform, he has published various code samples showcasing the combined use of desktop product API’s with our Forge platform. He now looks forward to making this transition from desktop to cloud as seamless as possible for fellow developer enthusiasts. Learning Objectives Create a web application that uses Forge Design Automation for Inventor that runs on a web browser without having the need of having locally installed software. Extract the added advantages of being able to run iLogic in the cloud. Immediately render and view the resulting output using the Forge Viewer. Drive dependent file formats like IPT, IDW and PDF.

Upload: others

Post on 24-Jan-2022

34 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: MFG473705 Using iLogic with Design Automation for Inventor

Page 1

MFG473705

Using iLogic with Design Automation for Inventor to create a Configurator Sajith Subramanian Autodesk

Description

Inventor Design Automation, in general, allows the use of API’s to be executed in the cloud, similar to how they would work on the desktop, but without the need of any installed software or its dependent licenses. An additional advantage of Inventor Design Automation, which may be easily overlooked, is its capability to run iLogic scripts in the cloud. These scripts being embedded in the CAD file itself can be programmed to auto execute under certain conditions. This class speaks about taking advantage of this capability to combine Forge Design Automation with iLogic, creating a configurator by modifying an input Inventor File (IPT) in the cloud, using a web browser, according to the inputs provided by the user on an easy-to-use UI. The results can be immediately viewed on the browser itself, using the Forge Viewer and can also be downloaded in multiple formats such as IPT, IDW, and PDF. This web application sample uses latest web technologies and is OS independent and mobile device friendly.

Speaker

Sajith Subramanian - A qualified software engineer with over a decade of development experience with various CAD tools, he is part of the Manufacturing team at Autodesk, supporting and evangelizing API’s for Inventor, Fusion and Vault. Now an evangelist and an enthusiast on the Forge platform, he has published various code samples showcasing the combined use of desktop product API’s with our Forge platform. He now looks forward to making this transition from desktop to cloud as seamless as possible for fellow developer enthusiasts.

Learning Objectives

• Create a web application that uses Forge Design Automation for Inventor that runs on a web browser without having the need of having locally installed software.

• Extract the added advantages of being able to run iLogic in the cloud.

• Immediately render and view the resulting output using the Forge Viewer. Drive dependent file formats like IPT, IDW and PDF.

Page 2: MFG473705 Using iLogic with Design Automation for Inventor

Page 2

Overview

To create a web application that will demonstrate how to create a configurator using Forge Design Automation for Inventor and iLogic, you start by creating an ASP.Net Core web application. We use .Net core so that it can run on other OS environments as well. This application provides a User Interface(UI) on a web browser, that allows the user to pick from various available configurations of an automotive rim. The selected configuration is then applied to the input template Ipt file using Forge Design Automation for Inventor, which in-turn triggers the iLogic rule embedded within this ipt file. The iLogic file then makes modifications to the design elements of the ipt file. The resulting ipt file and the drawing can be viewed immediately on the browser using the Viewer. The results are also stored in OSS (Object Storage Service), and is available for download in multiple formats, viz. ipt, idw and pdf.

FIGURE 1: HIGH-LEVEL WORKFLOW DIAGRAM

Page 3: MFG473705 Using iLogic with Design Automation for Inventor

Page 3

Setting up your Web Application

Step 1: Prerequisite - Creating a Forge account To use Forge API’s, you need to first create your forge account by signing up on the Forge Developer Portal. Figure 2 shows how to create an app. A step-by-step help is listed here: How to create a Forge App

FIGURE 2: CREATING AN APP

Page 4: MFG473705 Using iLogic with Design Automation for Inventor

Page 4

Step 2: Prerequisite – Setting up ngrok When Design Automation finishes modifying your model, it notifies back. As your machine is not exposed on the web, the ngrok tool create a temporary address to receive notifications. This tool is only required locally. You can download this tool here. After download, unzip it. Open the Windows Command Line Prompt (CMD) and navigate to the folder. Then run ngrok http 3000 -host-header="localhost:3000". Copy the forwarding URL value (in the form of http://1ab2c3d4.ngrok.com), as shown in Figure 3 below.

FIGURE 3: SETTING UP NGROK

Page 5: MFG473705 Using iLogic with Design Automation for Inventor

Page 5

Step 3: Creating the solution in Visual Studio You will need two projects within your solution. One project would be a ASP.Net Core while the other project would be your Inventor plug-in. Let’s start with the ASP.Net Core application first as shown below in Figure 4.

FIGURE 4: CREATING YOUR ASP.Net PROJECT

Page 6: MFG473705 Using iLogic with Design Automation for Inventor

Page 6

The second project is creating your Inventor plug-in. It is recommended to use the Design Automation template for creating the plug-in project. Let’s start by first downloading the Visual studio extension as shown in Figure 5.

FIGURE 5: DOWNLOADING THE EXTENSION

Page 7: MFG473705 Using iLogic with Design Automation for Inventor

Page 7

You can then add a new project using the template as shown in Figure 6. For a complete step-by-step guide for creating an Inventor plug-in, please refer here: Create an Inventor plug-in

FIGURE 6: ADDING THE INVENTOR PLUG-IN PROJECT

Page 8: MFG473705 Using iLogic with Design Automation for Inventor

Page 8

Step 4: Adding references

For adding the necessary references, right-click on the project in Solution Explorer, select ‘Manage NuGet Package’, then on Browse search for ‘Autodesk.Forge’ and install Autodesk.Forge. Similarly install ‘Autodesk.Forge.DesignAutomation’ and ‘Microsoft.AspNetCore.Mvc.NewtonsoftJson’ as shown below in Figure 7.

FIGURE 7: ADDING REFERENCES

For a complete step-by-step guide for creating a new project, please refer here: Create a .Net Core project

Page 9: MFG473705 Using iLogic with Design Automation for Inventor

Page 9

Step 5: Adding the environment variables Right-click on the project, go to Properties, then under Debug tab see the Environment Variables section. Finally, as this is running locally, uncheck Enable SSL option, as shown below in Figure 8.

FIGURE 8: ADDING ENVIRONMENT VARIABLES

Page 10: MFG473705 Using iLogic with Design Automation for Inventor

Page 10

Preparing your inputs

Step 1: Preparing your Inventor plug-in The plug-in refers to Inventor API code (similar to the plug-in which you use for Inventor desktop application) that you would want to execute in the cloud using Design Automation. Design Automation uses an App Bundle, in which you need to create a zipped folder with the PackageContents.xml and along with the required DLLs and its related files. For this class, you will learn how to open the input ipt file that is part of your AppBundle, modify the required properties, and save back the file. To do so, add the following lines of code to the SampleAutomation.cs file in the Inventor plug-in project created earlier, as shown below: public void RunWithArguments(Document doc, NameValueMap map) { try { StringBuilder traceInfo = new StringBuilder("RunWithArguments called with"); Trace.TraceInformation(map.Count.ToString()); // values in map are keyed on _1, _2, etc for (int i = 0; i < map.Count; i++) { traceInfo.Append(" and "); traceInfo.Append(map.Value["_" + (i + 1)]); } Trace.TraceInformation(traceInfo.ToString()); #region change parameters Trace.TraceInformation("Changing User params"); // load processing parameters string paramsJson = GetParametersToChange(map); Trace.TraceInformation("Inventor Parameters JSON: \"" + paramsJson + "\""); Dictionary<string, string> parameters = JsonConvert.DeserializeObject<Dictionary<string, string>>(paramsJson); // Get path of add-in dll string assemblyPath = System.IO.Path.GetDirectoryName(Assembly.

GetExecutingAssembly().Location); Trace.TraceInformation("Assembly Path = " + assemblyPath); // Path of template relative to the dll's path string iptPath = parameters["InputIPT"]; string idwPath = parameters["InputIDW"];

Page 11: MFG473705 Using iLogic with Design Automation for Inventor

Page 11

// Open template document string iptfullPath = System.IO.Path.Combine(assemblyPath, @"Rim\", iptPath); string idwfullPath = System.IO.Path.Combine(assemblyPath, @"Rim\", idwPath); Document iptDoc = m_inventorServer.Documents.Open(iptfullPath, false); Document idwDoc = m_inventorServer.Documents.Open(idwfullPath, false); var theParams = GetParameters(iptDoc); foreach (KeyValuePair<string, string> entry in parameters) { var parameterName = entry.Key; var value = entry.Value; Trace.TraceInformation("Parameter to change: {0}:{1}", parameterName, value); try { UserParameter param = theParams[parameterName]; try { param.Value = value; } catch { param.Expression = value; } } catch (Exception e) { Trace.TraceInformation("Cannot update '{0}' parameter. ({1})", parameterName, e.Message); } } iptDoc.Update(); Trace.TraceInformation("Part Doc updated."); var currDir = System.IO.Directory.GetCurrentDirectory(); var iptfileName = System.IO.Path.Combine(currDir, "Result.ipt"); // the name must be in sync with OutputIpt localName in Activity iptDoc.SaveAs(iptfileName, false); Trace.TraceInformation(" Part Doc saved."); idwDoc.Update(); Trace.TraceInformation("Drawing Doc updated."); var idwfileName = System.IO.Path.Combine(currDir, "Result.idw"); // the name must be in sync with OutputIdw localName in Activity idwDoc.SaveAs(idwfileName, false); var pdffilename = System.IO.Path.Combine(currDir, "Result.pdf"); // name must be in sync with OutputPDF localName in Activity idwDoc.SaveAs(pdffilename, true); Trace.TraceInformation(" Drawing Doc saved."); #endregion } catch (Exception ex) { Trace.TraceInformation(ex.Message); } }

Page 12: MFG473705 Using iLogic with Design Automation for Inventor

Page 12

Step 2: Preparing your input file with iLogic In your input Ipt file, Navigate to the iLogic rules and add your code in the iLogic editor. Also, do remember to set the Event trigger, so that it auto executes whenever a parameter is changed, as shown in Figure 9 below.

FIGURE 9: ADDING YOUR ILOGIC CODE TO THE INPUT FILE

Page 13: MFG473705 Using iLogic with Design Automation for Inventor

Page 13

Adding the code – Server!

Step 1: Creating the server Now that you have your inputs all set up with the necessary references, its time to add some code! In Program.cs and add the following namespaces: using Microsoft.AspNetCore; using Autodesk.Forge.DesignAutomation;

Modify the Main() method as shown below. This tells our application to load Forge Client ID & Secret from the environment variables defined above. public static void Main(string[] args) { CreateWebHostBuilder(args).ConfigureAppConfiguration(builder => { builder.AddForgeAlternativeEnvironmentVariables(); }).ConfigureServices((hostContext, services) => { services.AddDesignAutomation(hostContext.Configuration); }).Build().Run(); } In the Startup.cs and add the following namespace: using Microsoft.AspNetCore.Mvc;

Replace the content of the Startup class with the following code. public void ConfigureServices(IServiceCollection services) { services.AddMvc(options => options.EnableEndpointRouting = false).SetCompatibilityVersion(CompatibilityVersion.Version_3_0).AddNewtonsoftJson(); ; services.AddSignalR(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { app.UseRouting(); app.UseEndpoints(routes => { routes.MapHub<Controllers.DesignAutomationHub>("/api/signalr/designautomation"); }); app.UseFileServer(); app.UseMvc(); }

Page 14: MFG473705 Using iLogic with Design Automation for Inventor

Page 14

Step 2: Adding the Web Api Controllers We now proceed to creating our Web Api Controllers. We start by creating a controllers folder. Under the controllers folder we create two files: 1. OAuthController.cs 2. DesignAutomationController.cs The following segments explain the various steps involved in modifying our input ipt file using Design Automation for Inventor

a. Authenticate: The OAuthController would be responsible for fetching the access token. Add the below content to the OAuthController.cs file.

using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Autodesk.Forge; namespace InventorDA.Controllers { [ApiController] public class OAuthController : ControllerBase { private static dynamic InternalToken { get; set; } private static dynamic PublicToken { get; set; } /// <summary> /// Get access token with public (viewables:read) scope /// </summary> [HttpGet] [Route("api/forge/oauth/token")] public async Task<dynamic> GetPublicAsync() { if (PublicToken == null || PublicToken.ExpiresAt < DateTime.UtcNow) { PublicToken = await Get2LeggedTokenAsync(new Scope[] { Scope.ViewablesRead }) ; PublicToken.ExpiresAt =

DateTime.UtcNow.AddSeconds(PublicToken.expires_in);

} return PublicToken; }

Page 15: MFG473705 Using iLogic with Design Automation for Inventor

Page 15

/// <summary> /// Get access token with internal (write) scope /// </summary> public static async Task<dynamic> GetInternalAsync() { if (InternalToken == null || InternalToken.ExpiresAt < DateTime.UtcNow) { InternalToken = await Get2LeggedTokenAsync(new Scope[] {

Scope.BucketCreate, Scope.BucketRead, Scope.BucketDelete, Scope.DataRead, Scope.DataWrite, Scope.DataCreate, Scope.CodeAll });

InternalToken.ExpiresAt = DateTime.UtcNow.AddSeconds(InternalToken.expires_in);

} return InternalToken; } /// <summary> /// Get the access token from Autodesk /// </summary> private static async Task<dynamic> Get2LeggedTokenAsync(Scope[] scopes) {

TwoLeggedApi oauth = new TwoLeggedApi(); string grantType = "client_credentials"; dynamic bearer = await oauth.AuthenticateAsync( GetAppSetting("FORGE_CLIENT_ID"), GetAppSetting("FORGE_CLIENT_SECRET"), grantType, scopes); return bearer; }

/// <summary> /// Reads appsettings from web.config /// </summary> public static string GetAppSetting(string settingKey) { return Environment.GetEnvironmentVariable(settingKey); } } }

For further reading about authentication, please refer: Authentication

Page 16: MFG473705 Using iLogic with Design Automation for Inventor

Page 16

b. Creating a bucket:

You need to have the output ipt file placed in a location so that it can be further processed and translated to a Viewer friendly format. In this sample I use the Forge OSS (Object Storage Service), where files are stored as objects in buckets. Let’s go ahead and create the bucket using the following lines of code: private async Task<IActionResult> CreateBucket() {

dynamic oauth = await OAuthController.GetInternalAsync(); //Note that bucket keys must be of the form [-_.a-z0-9]{3,128} string bucketkey = "inventorilogicda" + nickName.ToLower(); BucketsApi bucketsApi = new BucketsApi(); bucketsApi.Configuration.AccessToken = oauth.access_token; dynamic buckets = await bucketsApi.GetBucketsAsync(); bool bucketExists = buckets.items.ToString().Contains(bucketkey); if (!bucketExists) { PostBucketsPayload postBucket = new PostBucketsPayload(bucketkey,

null, PostBucketsPayload.PolicyKeyEnum.Transient); dynamic newbucket = await bucketsApi.CreateBucketAsync(postBucket); } return Ok();

}

For further reading about buckets and OSS, please refer: OSS

c. Defining the activity: The activity is where we specify the action that needs to be executed. You can think of it as a ‘Function Definition’ where you define the specifics so that it can be called for execution at a later point in your code. The activity contains information such as which AppBundle to be used, input and output files etc. Let’s go ahead and define the activity using the below lines of code:

private async Task<dynamic> CreateActivity()

{ Page<string> appBundles = await designAutomation.GetAppBundlesAsync(); string appBundleID = string.Format("{0}.{1}+{2}", nickName, APPNAME, ALIAS); if (!appBundles.Data.Contains(appBundleID)) {

Page 17: MFG473705 Using iLogic with Design Automation for Inventor

Page 17

if (!System.IO.File.Exists(LocalAppPackageZip)) throw new Exception("Appbundle not found at " + LocalAppPackageZip); AppBundle appBundleSpec = new AppBundle() { Package = APPNAME, Engine = EngineName, Id = APPNAME, Description = string.Format("Description for {0}", APPNAME), }; AppBundle newApp = await _designAutomation.CreateAppBundleAsync(appBundleSpec); if (newApp == null) throw new Exception("Cannot create new app"); // create alias pointing to v1 Alias aliasSpec = new Alias() { Id = ALIAS, Version = 1 }; Alias newAlias = await _designAutomation.CreateAppBundleAliasAsync(APPNAME, aliasSpec); // upload the zip with .bundle RestClient uploadClient = new RestClient(newApp.UploadParameters.EndpointURL); RestRequest request = new RestRequest(string.Empty, Method.POST); request.AlwaysMultipartFormData = true; foreach (KeyValuePair<string, string> x in newApp.UploadParameters.FormData) request.AddParameter(x.Key, x.Value); request.AddFile("file", LocalAppPackageZip); request.AddHeader("Cache-Control", "no-cache"); await uploadClient.ExecuteTaskAsync(request); } Page<string> activities = await _designAutomation.GetActivitiesAsync(); string qualifiedActivityId = string.Format("{0}.{1}+{2}", nickName, ACTIVITY_NAME, ALIAS); if (!activities.Data.Contains(qualifiedActivityId)) { // define the activity string commandLine = string.Format("$(engine.path)\\inventorcoreconsole.exe /al \"$(appbundles[{0}].path)\" \"$(args[inputJson].path)\"", APPNAME); Activity activitySpec = new Activity() { Id = ACTIVITY_NAME, Appbundles = new List<string>() { string.Format("{0}.{1}+{2}", nickName, APPNAME, ALIAS) }, CommandLine = new List<string>() { commandLine }, Engine = EngineName, Parameters = new Dictionary<string, Parameter>() { { "inputJson", new Parameter() { Description = "input json", LocalName = "params.json", Ondemand = false, Required = false, Verb = Verb.Get, Zip = false } }, { "ResultIPT", new Parameter() { Description = "output IPT

Page 18: MFG473705 Using iLogic with Design Automation for Inventor

Page 18

file", LocalName = outputIPTFile, Ondemand = false, Required = true, Verb = Verb.Put, Zip = false } }, { "ResultIDW", new Parameter() { Description = "output IDW file", LocalName = outputIDWFile, Ondemand = false, Required = true, Verb = Verb.Put, Zip = false } }, { "ResultPDF", new Parameter() { Description = "output PDF file", LocalName = outputPDFile, Ondemand = false, Required = true, Verb = Verb.Put, Zip = false } } } }; Activity newActivity = await _designAutomation.CreateActivityAsync(activitySpec); // specify the alias for this Activity Alias aliasSpec = new Alias() { Id = ALIAS, Version = 1 }; Alias newAlias = await _designAutomation.CreateActivityAliasAsync(ACTIVITY_NAME, aliasSpec); return Ok(new { Activity = qualifiedActivityId }); } return Ok(new { Activity = "Activity already defined" }); }

For further reading about activities, please refer: Defining an Activity

d. Creating the Workitem: The Workitem is where you execute the specifics listed in the activity in the previous step. So, this is can be imagined as our ‘Function call’ for executing the activity.

Let’s go ahead and create the workitem using the following lines of code:

private async Task<IActionResult> CreateWorkItem(ModelAttributes param) { // OAuth token dynamic oauth = await OAuthController.GetInternalAsync(); string bucketkey = "inventorilogicda" + nickName.ToLower(); string qualifiedActivityId = string.Format("{0}.{1}+{2}", nickName, ACTIVITY_NAME, ALIAS); // input json dynamic inputJson = new JObject(); inputJson.Material = param.color; inputJson.Diameter = param.diameter; inputJson.Spoke_Design = param.rim; inputJson.Width = param.width;

Page 19: MFG473705 Using iLogic with Design Automation for Inventor

Page 19

inputJson.InputIPT = "RIM.ipt"; inputJson.InputIDW = "RIM.idw"; XrefTreeArgument inputJsonArgument = new XrefTreeArgument() { Url = "data:application/json, " + ((JObject)inputJson).ToString(Formatting.None).Replace("\"", "'") }; // output IPT file XrefTreeArgument outputIPTFileArgument = new XrefTreeArgument() { Url = string.Format("https://developer.api.autodesk.com/oss/v2 /buckets/{0}/objects/{1}", bucketkey, outputIPTFile), Verb = Verb.Put, Headers = new Dictionary<string, string>() { {"Authorization", "Bearer " + oauth.access_token } } }; // output IDW file XrefTreeArgument outputIDWFileArgument = new XrefTreeArgument() { Url = string.Format("https://developer.api.autodesk.com/oss/v2 /buckets/{0}/objects/{1}", bucketkey, outputIDWFile), Verb = Verb.Put, Headers = new Dictionary<string, string>() { {"Authorization", "Bearer " + oauth.access_token } } }; // output PDF file XrefTreeArgument outputPDFFileArgument = new XrefTreeArgument() { Url = string.Format("https://developer.api.autodesk.com/oss/v2/ buckets/{0}/objects/{1}", bucketkey, outputPDFile), Verb = Verb.Put, Headers = new Dictionary<string, string>() { {"Authorization", "Bearer " + oauth.access_token } } }; string callbackUrl = string.Format("{0}/api/forge/callback/ designautomation?id={1}", OAuthController.GetAppSetting ("FORGE_WEBHOOK_URL"), param.browserconnectionId); WorkItem workItemSpec = new WorkItem() { ActivityId = qualifiedActivityId,

Page 20: MFG473705 Using iLogic with Design Automation for Inventor

Page 20

Arguments = new Dictionary<string, IArgument>() { { "inputJson", inputJsonArgument }, { "ResultIPT", outputIPTFileArgument }, { "ResultIDW", outputIDWFileArgument }, { "ResultPDF", outputPDFFileArgument }, { "onComplete", new XrefTreeArgument { Verb = Verb.Post, Url = callbackUrl } } } }; WorkItemStatus workItemStatus = await _designAutomation.CreateWorkItemAsync(workItemSpec); return Ok(new { WorkItemId = workItemStatus.Id }); }

For further reading about Workitem, please refer: Execute the Workitem

e. OnCallback: When the workitem is done, Design Automation will callback our app (using the ngrok forwarding URL). This function will handle it and push a notification to the client (using SignalR Hub).

[HttpPost] [Route("/api/forge/callback/designautomation")] public async Task<IActionResult> OnCallback(string id) { try { dynamic oauth = await OAuthController.GetInternalAsync(); string bucketkey = "inventorilogicda" + nickName.ToLower(); ObjectsApi objectsApi = new ObjectsApi(); objectsApi.Configuration.AccessToken = oauth.access_token; dynamic objIPT = await objectsApi.GetObjectDetailsAsync(bucketkey, outputIPTFile); dynamic objIDW = await objectsApi.GetObjectDetailsAsync(bucketkey, outputIDWFile); dynamic urnIPT = TranslateObject(objIPT, outputIPTFile); dynamic urnIDW = TranslateObject(objIDW, outputIDWFile); await _hubContext.Clients.Client(id).SendAsync("onTranslate", (string)await urnIPT, (string) await urnIDW); dynamic signedIPTUrl = objectsApi.CreateSignedResourceAsyncWithHttpInfo(bucketkey, outputIPTFile, new PostBucketsSigned(10), "read"); dynamic signedIDWUrl =

Page 21: MFG473705 Using iLogic with Design Automation for Inventor

Page 21

objectsApi.CreateSignedResourceAsyncWithHttpInfo(bucketkey, outputIDWFile, new PostBucketsSigned(10), "read"); dynamic signedPDFUrl = objectsApi.CreateSignedResourceAsyncWithHttpInfo(bucketkey, outputPDFile, new PostBucketsSigned(10), "read"); await _hubContext.Clients.Client(id).SendAsync("downloadResult", (string)(await signedIPTUrl).Data.signedUrl, (string)(await signedIDWUrl).Data.signedUrl, (string)(await signedPDFUrl).Data.signedUrl); return Ok(); } catch (Exception e) { } return Ok(); }

f. Translate the model:

The output file is now translated to a viewer friendly format, so that it can be displayed using the Viewer.

Let’s go ahead translate the model using the following lines of code:

private async Task<dynamic> TranslateObject(dynamic objModel,string outputFileName) { dynamic oauth = await OAuthController.GetInternalAsync(); string objectIdBase64 = ToBase64(objModel.objectId); // prepare the payload List<JobPayloadItem> postTranslationOutput = new List<JobPayloadItem>() {

new JobPayloadItem( JobPayloadItem.TypeEnum.Svf, new List<JobPayloadItem.ViewsEnum>() { JobPayloadItem.ViewsEnum._2d, JobPayloadItem.ViewsEnum._3d })

}; JobPayload job; job = new JobPayload(

new JobPayloadInput(objectIdBase64,false, outputFileName), new JobPayloadOutput(postTranslationOutput)

); // start the translation DerivativesApi derivative = new DerivativesApi(); derivative.Configuration.AccessToken = oauth.access_token; dynamic jobPosted = await derivative.TranslateAsync(job,true);

Page 22: MFG473705 Using iLogic with Design Automation for Inventor

Page 22

// check if it is complete. dynamic manifest = null; do { System.Threading.Thread.Sleep(1000); // wait 1 second try { manifest = await derivative.GetManifestAsync(objectIdBase64); } catch (Exception) { } } while (manifest.progress != "complete"); return jobPosted.urn; }

For further reading about translating a file please refer: Translate the File

That’s it! This completes the server side of the code. Now let us go over to the Client side!

Page 23: MFG473705 Using iLogic with Design Automation for Inventor

Page 23

Adding the code – Client!

Step 1: Adding the Index.html We start by creating an Index.html file. This file is the entry point of our application. It comprises of HTML5, JavaScript along with the Bootstrap framework. Add the below code to this file. <!DOCTYPE html> <html> <head> <title>Autodesk Forge Tutorial</title> <meta charset="utf-8" /> <link rel="shortcut icon" href="https://github.com/Autodesk-Forge/learn.forge.viewmodels/raw/master/img/favicon.ico"> <!-- Common packages: jQuery, Bootstrap --> <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.4.1/css/bootstrap.min.css"> <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.4.1/js/bootstrap.min.js"></script> <!-- Autodesk Forge Viewer files --> <link rel="stylesheet" href="https://developer.api.autodesk.com/modelderivative/v2/viewers/7.*/style.min.css" type="text/css"> <script src="https://developer.api.autodesk.com/modelderivative/v2/viewers/7.*/viewer3D.min.js"></script> <script src="//unpkg.com/@aspnet/[email protected]/dist/browser/signalr.min.js"></script> <!-- this project files --> <link href="/css/main.css" rel="stylesheet" /> <script src="/js/DesignAutomation.js"></script> <script src="/js/ForgeViewer.js"></script> </head> <body> <!-- Fixed navbar by Bootstrap: https://getbootstrap.com/examples/navbar-fixed-top/ --> <nav class="navbar fixed-top navbar-light" style="background-color: #ddeffc;"> <div class="container-fluid"> <ul class="nav navbar-nav left"> <li> <a href="http://developer.autodesk.com" target="_blank"> <img alt="Autodesk Forge" src="//developer.static.autodesk.com/images/logo_forge-2-line.png" height="20"> </a> </li> </ul> <ul class="nav navbar-nav right">

Page 24: MFG473705 Using iLogic with Design Automation for Inventor

Page 24

<li> <a href="https://github.com/sajith-subramanian/forge-rimconfigurator- inventor" target="_blank"> <img src="/images/GitHub.png" height="20"> </a> </li> </ul> </div> </nav> <!-- End of navbar --> <div class="container-fluid fill"> <div class="row fill"> <div class="col-md-auto"> <div class="panel panel-default"> <div class="panel-heading"> <div class="form-group"> <label class="font-weight-bold" for="rimstyle">Rim Style</label> <select class="form-control" id="rimstyle"> <option value="Style1">Style - 1</option> <option value="Style2">Style - 2</option> <option value="Style3">Style - 3</option> </select> </div> <div class="form-group" style="padding-top:10px"> <label class="font-weight-bold" for="color">Color</label> <select class="form-control" id="color"> <option value="Titan">Titanium</option> <option value="Blue">Matte Blue</option> <option value="Blk">Glossy Black</option> </select> </div> <div class="form-group" style="padding-top:10px"> <label class="font-weight-bold" for="diameter">Diameter</label> <select class="form-control" id="diameter"> <option value="20">20</option> <option value="18">18</option> <option value="16">16</option> </select> </div> <div class="form-group" style="padding-top:10px"> <label class="font-weight-bold" for="width">Width</label> <select class="form-control" id="width"> <option value="10">10</option> <option value="8">8</option> <option value="6">6</option> </select> </div> <div class="col text-center" id="displayImage"> <p style="font-style:italic; margin:0 auto">Raster Image</p> <img id="img"> </div> <div style="padding-top:20px;">

Page 25: MFG473705 Using iLogic with Design Automation for Inventor

Page 25

<button type="button" id="preview" class="btn btn-primary btn-sm">Generate</button> <button type="button" id="download" class="btn btn-primary btn-sm" style="float:right">Download</button> </div> </div> </div> </div> <div class="col"> <div class=" col fill" id="forgeViewer3d" style="height:50%"></div> <div class="col fill" id="forgeViewer2d" style="height:50%"></div> </div> <div class="displayclass" id="displaytext"> <p>Generating Design...</p> </div> </div> </div> </body> </html>

Step 2: Adding the JavaScript files

We start by creating a js folder under the wwwroot folder. Under this js folder we create two files:

1. DesignAutomation.js 2. ForgeViewer.js

a. DesignAutomation.js: The DesignAutomation.js file is primarily used to execute Javascript functions on our webpage, and to post the user selected values to our WebApi Controller. Add the below code to this file. var rim, color, dia, width; var downloadiptURL, downloadidwURL, downloadpdfURL; var connection, connectionId; $(document).ready(function () { changeimage(); startConnection(); $('.form-group').change(changeimage); $('#preview').click(function () { deactivateUI(); $('#displaytext').show(); jQuery.post({

Page 26: MFG473705 Using iLogic with Design Automation for Inventor

Page 26

url: 'api/forge/params/designautomation', contentType: 'application/json', data: JSON.stringify({ 'rim': rim, 'color': color, 'diameter': dia, 'width': width, 'browserconnectionId': connectionId }), }); }); $('#download').click(function () { var urls = [downloadidwURL, downloadiptURL, downloadpdfURL]; var interval = setInterval(download, 1000, urls); function download() { var url = urls.pop(); var a = document.createElement("a"); location.href = url; if (urls.length == 0) { clearInterval(interval); } } }); }); function changeimage() { $('#displaytext').hide(); $('#forgeViewer3d').empty(); $('#forgeViewer2d').empty(); rim = $("#rimstyle").val(); color = $("#color").val(); dia = $("#diameter").val(); width = $("#width").val(); var filepath = "images/img.png"; filepath = filepath.replace("img", color + rim.substr(5, 5) + dia + width); $('#img').attr('src', filepath); } function startConnection(onReady) { if (connection && connection.connectionState) { if (onReady) onReady(); return; } connection = new signalR.HubConnectionBuilder().withUrl("/api/signalr/designautomation").build(); connection.start() .then(function () { connection.invoke('getConnectionId') .then(function (id) { connectionId = id; // we'll need this... if (onReady) onReady(); }); }); connection.on("downloadResult", function (urlipt, urlidw, urlpdf) { downloadiptURL = urlipt; downloadidwURL = urlidw; downloadpdfURL = urlpdf;

Page 27: MFG473705 Using iLogic with Design Automation for Inventor

Page 27

}); connection.on("onTranslate", function (urnipt, urnidw) { launchViewer(urnipt, urnidw); }); } function activateUI() { $('.panel :input').prop("disabled", false); } function deactivateUI() { $('.panel :input').prop("disabled", true);

}

b. ForgeViewer.js:

This file is responsible to handle the Viewer initialization. Add the below code to this file.

var viewer3d; var viewer2d; function launchViewer(urnipt, urnidw) { var options = { env: 'AutodeskProduction', getAccessToken: getForgeToken }; Autodesk.Viewing.Initializer(options, () => { viewer3d = new Autodesk.Viewing.GuiViewer3D(document.getElementById('forgeViewer3d')); viewer2d = new Autodesk.Viewing.GuiViewer3D(document.getElementById('forgeViewer2d')); viewer3d.start(); viewer2d.start(); viewer3d.addEventListener(Autodesk.Viewing.SELECTION_CHANGED_EVENT,function (event) { if (event.dbIdArray.length === 1) { viewer3d.getProperties(event.dbIdArray[0], function(data) { console.log(data.name) if (data.name.startsWith("Solid")) { var instanceTree = viewer3d.model.getData().instanceTree; var parentId = instanceTree.getNodeParentId(event.dbIdArray[0]) viewer3d.select([parentId]); } })

Page 28: MFG473705 Using iLogic with Design Automation for Inventor

Page 28

} }); viewer2d.addEventListener(Autodesk.Viewing.SELECTION_CHANGED_EVENT,function(event) { if (event.dbIdArray.length === 1) { viewer2d.getProperties(event.dbIdArray[0], function(data) { console.log(data.name) if (data.name.startsWith("Solid")) { var instanceTree = viewer2d.model.getData().instanceTree; var parentId = instanceTree.getNodeParentId(event.dbIdArray[0]) viewer2d.select([parentId]); } }) } }); Autodesk.Viewing.endpoint.HTTP_REQUEST_HEADERS['If-Modified-Since'] = 'Sat, 29 Oct 1994 19:43:31 GMT'; var iptdocumentId = 'urn:' + urnipt; Autodesk.Viewing.Document.load(iptdocumentId, function (doc) { var viewables = doc.getRoot().getDefaultGeometry(); viewer3d.loadDocumentNode(doc, viewables).then(i => { activateUI(); }); }, onDocumentLoadFailure); var idwdocumentId = 'urn:' + urnidw; Autodesk.Viewing.Document.load(idwdocumentId,function (doc) { var viewables = doc.getRoot().getDefaultGeometry(); viewer2d.loadDocumentNode(doc, viewables).then(i => { // documented loaded, any action? }); }, onDocumentLoadFailure); }); }; function onDocumentLoadFailure(viewerErrorCode) { console.error('onDocumentLoadFailure() - errorCode:' + viewerErrorCode); } function getForgeToken(callback) { fetch('/api/forge/oauth/token').then(res => { res.json().then(data => { callback(data.access_token, data.expires_in); }); });

}

Page 29: MFG473705 Using iLogic with Design Automation for Inventor

Page 29

That completes our code changes! When you hit play, the HTML interface should open up in the browser!

FIGURE 10: SCREENGRAB OF THE APPLICATION

Page 30: MFG473705 Using iLogic with Design Automation for Inventor

Page 30

Source code of the application

You can find the entire source of this application on GitHub at the following link: https://github.com/sajith-subramanian/forge-rimconfigurator-inventor The application is hosted on Heroku and can be accessed here: https://forge-rimconfigurator-inventor.herokuapp.com/

Review

We have learned how to create a web application that highlights the capabilities of Forge Design Automation for Inventor along with the added advantages of being able to run your iLogic code in the cloud. I hope this class was useful to you and encourages you to continue learning and experiment on various other workflows using the Forge APIs. Thank you for your time!

Additional Resources

Forge: Forge Blog: https://forge.autodesk.com/blog Learn Forge (Getting started): https://learnforge.autodesk.io/#/?id=learn-autodesk-forge

Inventor:

MFG Dev Blog: http://adndevblog.typepad.com/manufacturing/

Mod the Machine blog: http://modthemachine.typepad.com/ Inventor customization forum: https://forums.autodesk.com/t5/inventor customization/bd-p/120