I have implemented a viewer using Autodesk Platform Services (former name Forge) on .NET Core. In the bucket I upload 2D drawings in .dwg format.
I enabled the markup feature in the viewer, so now I can make any markup on top of the .dwg
What I have for the moment looks like this:
I need to save this dwg with the markups I did, and either have it as a 2nd dwg inside the bucket or to override the original one.
The steps I have taken until now:
In javascript behind I can get the markups only as .svg format using the .generateData() on the MarkupsCore extension:
const markupCore = await viewer.loadExtension('Autodesk.Viewing.MarkupsCore');
let svgMarkup = markupCore.generateData();
After getting the svg mark up, I convert it in .dxf file.
I think I need to use the Design Automation API to import this dxf file into the dwg,
but I don't know how to handle this.
I have checked the following link on importing dxf into dwg but so far I can't find something for my case.
AutoDesk Design Automation tutorials on autocad
In case someone knows maybe another way on handling this, please let me know.
I think I need to use the Design Automation API to import this dxf file into the dwg, but I don't know how to handle this.
Yes that is correct, you may insert the dxf into the main drawing, you should be knowing scaling and position, so that will placed correctly on top your drawing.
Activity
{
"id": "{{ _.activityId }}",
"commandLine": [
"$(engine.path)\\accoreconsole.exe /i \"$(args[main].path)\" /s $(settings[script].path)"
],
"parameters": {
"main": {
"verb": "get",
"description": "test",
"required": true,
"localName": "$(inputFile)"
},
"overlay": {
"verb": "get",
"description": "",
"required": true,
"localName": "markups.dxf"
},
"result": {
"verb": "put",
"description": "",
"required": true,
"localName": "result.dwg"
}
},
"engine": "Autodesk.AutoCAD+24_1",
"description": "import markups",
"settings": {
"script": "-insert\nmarkups.dxf\n4,1,0\n1\n1\n0\nsaveas\n2018\nresult.dwg\n"
}
}
WorkiItem
{
"activityId": "{{ _.nickName }}.{{ _.activityId }}+{{ _.alias }}",
"arguments": {
"main": {
"url": "urn:adsk.objects:os.object:madlybuckets/main.dwg",
"verb": "get",
"headers": {
"Authorization": "Bearer {{ _.oAuthToken }}"
}
},
"overlay": {
"url": "urn:adsk.objects:os.object:madlybuckets/markups.dxf",
"verb": "get",
"headers": {
"Authorization": "Bearer {{ _.oAuthToken }}"
}
},
"result": {
"verb": "put",
"url": "urn:adsk.objects:os.object:madlybuckets/result.dwg",
"headers": {
"Authorization": "Bearer {{ _.oAuthToken }}"
}
}
}
}
Here the main.dwg, markups.dxf is uploaded to APS Object Storage Service so that I can directly use object id of uploaded files instead of passing the object URL to the workitem.
Related
How to programmatically create a new DWG file and load an existing DWG model into it using Autodesk Design Automation API for AutoCAD?
I am working on a project that requires me to automate the process of creating a new DWG file in AutoCAD and then load an existing DWG model into it using Autodesk Design Automation API. The goal is to automate the entire process without any manual intervention.
I am facing some difficulties in implementing the steps required to create a new DWG file and load an existing DWG model into it.
Can anyone provide a sample code or a detailed step-by-step explanation of how to programmatically create a new DWG file and load an existing DWG model into it using Autodesk Design Automation API for AutoCAD 2022? It would be great if the solution includes the necessary methods and properties to be used from the Autodesk Design Automation API.
I would highly appreciate any help or guidance in this matter.
input model dwg file
We have this ball valve model as input , we want to create a new dwg file add page border and load this existing dwg model inside page border using design automation api.
Expected Output :
expected output dwg file
I would encourage you to go through this tutorial https://tutorials.autodesk.io/tutorials/design-automation/, your objective should possible, you need to launch accoreconsole instance with your border drawing and insert the block from other drawing.
You can wrap the logic of importing blocks from external drawing in custom command .
Refer https://through-the-interface.typepad.com/through_the_interface/2006/08/import_blocks_f.html
Below is an example activty that importas "Microwave" block from "blocks.dwg" and inserts in "border.dwg"
Activity:
{
"id": "{{ _.activityId }}",
"commandLine": [
"$(engine.path)\\accoreconsole.exe \"$(args[main].path)\" /s $(settings[script].path)"
],
"parameters": {
"main": {
"verb": "get",
"description": "Main drawing to be loaded into AutoCAD.",
"required": true,
"localName": "border.dwg"
},
"blocks": {
"verb": "get",
"description": "The drawing which contains the blocks",
"required": true,
"localName": "blocks.dwg"
},
"BlockName": {
"verb": "read",
"description": "The block name to insert.",
"required": true
},
"BlockPosition": {
"verb": "read",
"description": "The position to insert block"
},
"ScaleX": {
"verb": "read",
"description": "The X scale factor",
"required": true
},
"ScaleY": {
"verb": "read",
"description": "The Y scale factor",
"required": true
},
"Rotation": {
"verb": "read",
"description": "The rotation angle of block",
"required": true
},
"result": {
"verb": "put",
"description": "",
"required": true,
"localName": "result.dwg"
}
},
"engine": "Autodesk.AutoCAD+23_1",
"description": "blah",
"settings": {
"script": "ImportBlocks\n"$(args[BlockName].value)\"\n\"$(args[BlockPosition].value)\"\n\"$(args[ScaleX].value)\"\n\"$(args[ScaleX].value)\"\n\"$(args[ScaleY].value)\"\n\"$(args[Rotation].value)\"\n_SAVEAS\n2018\nresult.dwg\n"
}
}
Workitem
{
"activityId": "{{ _.nickName }}.{{ _.activityId }}+{{ _.alias }}",
"arguments": {
"main": {
"verb": "get",
"url": "urn:adsk.objects:os.object:madlybuckets/main.dwg",
"headers": {
"Authorization": "Bearer {{ _.oAuthToken }}"
}
},
"blocks": {
"verb": "get",
"url": "urn:adsk.objects:os.object:madlybuckets/blocks.dwg",
"headers": {
"Authorization": "Bearer {{ _.oAuthToken }}"
}
},
"BlockName": "Microwave",
"BlockPosition": "198.241 162.455 0.0",
"ScaleX": "1.0",
"ScaleY": "1.0",
"Rotation": "0.0",
"result": {
"verb": "put",
"url": "urn:adsk.objects:os.object:madlybuckets/result.dwg",
"headers": {
"Authorization": "Bearer {{ _.oAuthToken }}"
}
}
}
}
}
I am integrating between Design automation and BIM 360 API in autodesk forge
I call step 7 Design automation
https://forge.autodesk.com/en/docs/design-automation/v3/tutorials/revit/step7-post-workitem/
{
"activityId": "YOUR_NICKNAME.DeleteWallsActivity+test",
"arguments": {
"rvtFile": {
"url": "SIGNED_URL_TO_INPUT_FILE",
"pathInZip": "PATH_TO_RVT_FILE_WITHIN_ZIP_FILE"
},
"result": {
"verb": "put",
"url": "SIGNED_URL_TO_RESULT"
}
}
}'
The param rvtFile.(url), i binding link download file by step 5 in Bim 360 Document
https://forge.autodesk.com/en/docs/bim360/v1/tutorials/document-management/download-document/
{
"activityId": "cbbdemo.DemoTestingActivity43+test",
"arguments": {
"rvtFile": {
"url": "https://developer.api.autodesk.com/oss/v2/buckets/wip.dm.prod/objects/11d42fe8-7612-4120-ad7d-a688e49143a1.rvt",
"localName": "testing.rvt",
},
"params": {
"url": "data:application/json,{'action' : 'generate','scaffoldName' : 'SM0918', 'space' : 300,'isGenFront' : true,'data' : ['138763','138533']}"
},
"result": {
"verb": "put",
"url": "https://developer.api.autodesk.com/oss/v2/signedresources/fbe64c4f-1073-49a7-810b-95658e51b361?region=US"
}
}
}
But when download file revit by API Bim 360 is failed because need token Authorization
So is there a way to download files from bim 360 without tokens?
Unfortunately, you cannot call the OSS API https://developer.api.autodesk.com/oss/v2/buckets/wip.dm.prod/objects/11d42fe8-7612-4120-ad7d-a688e49143a1.rvt without passing an access token.
The solution is to use a Signed URL to download the file, but since you're not the owner of the bucket wip.dm.prod. It's owned by BIM360 or ACC service itself. So you cannot create Signed URLs for objects stored on the wip.dm.prod bucket. So, at this moment, please pass a valid access token like the one below:
{
"activityId": "cbbdemo.DemoTestingActivity43+test",
"arguments": {
"rvtFile": {
"url": "https://developer.api.autodesk.com/oss/v2/buckets/wip.dm.prod/objects/11d42fe8-7612-4120-ad7d-a688e49143a1.rvt",
"localName": "testing.rvt",
"headers": {
"Authorization": "Bearer {{Bearer}}",
"Content-Type": "application/octet-stream"
}
},
"params": {
"url": "data:application/json,{'action' : 'generate','scaffoldName' : 'SM0918', 'space' : 300,'isGenFront' : true,'data' : ['138763','138533']}"
},
"result": {
"verb": "put",
"url": "https://developer.api.autodesk.com/oss/v2/signedresources/fbe64c4f-1073-49a7-810b-95658e51b361?region=US"
}
}
}
I am working on a project where I need to generate output Revit file based on the input json file in the Design automation API for Revit.
Since my input json string was large, I create a json file example "InputFile.json" and upload it to the cloud and pass the signed url to it to the work item and activity as input parameter, the generated output is a zip file example "OutputFile.zip" which is again uploaded to the cloud using the signed url.
My project works properly using this process. But since the name used for the input and output files are fixed, I am facing issue when I send continuous request, I get mismatched output.
Activity request
..
"parameters": {
"Inputs": {
"zip": false,
"ondemand": false,
"verb": "get",
"description": "Element parameters",
"required": true,
"localName": "InputFile.json"
},
"Result": {
"zip": true,
"ondemand": false,
"verb": "put",
"description": "new created element",
"required": true,
"localName": "OutputFile"
}
},
...
and the WorkItem request
...
"arguments":{
"Inputs":{
"url":"https://storage.googleapis.com/XXXXXXX/InputFile.json?XXXXXXXXXXXXXXXsigned-url"
},
"Result":{
"verb":"put",
"url":"https://storage.googleapis.com/XXXXXXX/OutputFile.zip?XXXXXXXXXXXXXXXsigned-url",
...
How can I pass dynamically generated names like "InputFile_[DATE].json" and "OutputFile_[DATE].zip"?
Thanks in advance
Regards
You should be able to replace the localName value when submitting the workitem by adding the "localName" attribute to your argument.
Example:
"arguments":{
"Inputs":{
"url":"https://storage.googleapis.com/XXXXXXX/InputFile.json?XXXXXXXXXXXXXXXsigned-url"
},
"Result":{
"verb":"put",
"url":"https://storage.googleapis.com/XXXXXXX/OutputFile.zip?XXXXXXXXXXXXXXXsigned-url",
"localName": "myOutputFileName"
}
}
Before the October eve, the information provided in the Revit console log allowed us to recover the return files.
Now this is not possible anymore!
Before:
"outputFile": {
"optional": true,
"localName": "OutputRvtFile.rvt",
"url": "https://developer.api.autodesk.com/oss/v2/buckets/caqg5kf4prwtqmmvrw_designautomation/objects/20190718115854_output_xxxxxxx.rvt",
"headers": {
"Authorization": "Bearer eyJh…."
},
"verb": "put"
},
Now :
"outputFile": {
"optional": true,
"localName": "OutputRvtFile.rvt",
"url": "https://developer.api.autodesk.com/Masked:tAUm....1RT08=",
"headers": {
"Authorization": "Masked:MT….E+zJONm3VU="
},
"verb": "put"
},
Before we had the file link as well as the varible Bearer but now there is more and the documentation has not been updated, or not found the latest news.
When I donwload the file, I have this element :
{ "developerMessage":"The requested resource does not exist.","userMessage":"","errorCode":"ERR-002","more info":"http://developer.api.autodesk.com/documentation/v1/errors/err-002"}
Could someone put me on the right road?
What is my problem?
Olivier,
The RVT output file's URL and authorization headers are the same URL and authorization headers you passed into Design Automation for Revit as part of your WorkItem payload.
Autodesk values your privacy and the security of your data in Design Automation. Your URLs and bearer tokens are being masked in Design Automation logs, including report.log, so that your sensitive data is not visible to Autodesk after your job is run.
Best,
Michael
I have an application that submits work items to Design Automation for Revit (Design Automation v3 beta). Most of the work items submitted work fine, but some versions of the models appear to fail to parse the "rvtFile" argument. This then leads to the cloud Revit process failing to run because the file name argument is wrong.
Body of Activity POST:
{
"id": "ExtractModelCategoriesActivity",
"commandLine": ["$(engine.path)\\\\revitcoreconsole.exe /i $(args[rvtFile].path) /al $(appbundles[ExtractModelCategories].path)"],
"parameters": {
"rvtFile": {
"zip": false,
"ondemand": false,
"verb": "get",
"description": "Input Revit model",
"required": true,
"localName": "$(rvtFile)"
},
"result": {
"zip": false,
"ondemand": false,
"verb": "put",
"description": "Model object categories by view",
"required": false,
"localName": "ModelCategories.json"
}
},
"engine": "Autodesk.Revit+2019",
"appbundles": ["alias_was_here.ExtractModelCategories+prod"],
"description": "Extract Model Categories to JSON Activity."
}
Body of Work Item POST:
{
"activityId": "alias_was_here.ExtractModelCategoriesActivity+prod",
"arguments": {
"rvtFile": {
"url": "https://developer.api.autodesk.com/oss/v2/buckets/wip.dm.prod/objects/83b5eb1e-c9b7-4938-ad4e-8efc4789d0e2.rvt?scopes=b360project.22109894-5897-4aa9-96ab-2e3310bc4ae9,global,O2tenant.5952590",
"Headers": {
"Authorization": "Bearer token_was_here"
}
},
"result": {
"verb": "put",
"url": "https://developer.api.autodesk.com/oss/v2/buckets/wip.dm.prod/objects/9dde6073-d490-4fd0-991e-4ff92af1957e.json",
"Headers": {
"Authorization": "Bearer token_was_here"
}
},
"onComplete": {
"verb": "post",
"url": "callback_url_was_here"
}
}
}
From the report.txt file for a successful submission:
[04/16/2019 12:03:50] Job information:
"CommandLine":[
"$(engine.path)\\\\revitcoreconsole.exe /i $(args[rvtFile].path) /al $(appbundles[ExtractModelCategories].path)"
]
"Settings":{
"dasreportfailedlimits": {
"value": "true",
"isEnvironmentVariable": true
}
}
"Id":"e23918d475a74145aade32ba8968e5c3"
"ActivityId":"alias_was_here.ExtractModelCategoriesActivity+prod"
"Engine.Id":"Autodesk.Revit!21"
"Apps": [
"App.Id":"alias_was_here.ExtractModelCategories!1"
]
"BoundArguments":{
"rvtFile": {
"localName": "$(rvtFile)",
"url": "https://developer.api.autodesk.com/oss/v2/buckets/wip.dm.prod/objects/839a11d8-51e9-42de-8936-28687feda65f.rvt?scopes=b360project.1949ed9d-e7fd-42b9-98f4-544fff3df42f,global,O2tenant.2971682",
"headers": {
"Authorization": "Bearer token_was_here"
}
},
"result": {
"localName": "ModelCategories.json",
"url": "https://developer.api.autodesk.com/oss/v2/buckets/wip.dm.prod/objects/dd19b8f6-ac51-45b9-8f42-51c7c6a9d257.json",
"headers": {
"Authorization": "Bearer token_was_here"
},
"verb": "put"
},
"onComplete": {
"ondemand": true,
"optional": true,
"url": "callback_was_here",
"verb": "post"
},
"onProgress": {
"ondemand": true,
"url": "https://wlnr5sjl3a.execute-api.us-east-1.amazonaws.com/Prod/v3/workitems/progress",
"headers": {
"Content-Type": "application/json",
"x-das-authorize": "awssigv4(us-east-1)",
"x-ads-token-data": "{\"access_token\":{\"client_id\":\"alias_was_here\"},\"scope\":\"bucket:create bucket:read data:read data:create data:write code:all\",\"expires_in\":3595,\"client_id\":\"alias_was_here\"}",
"x-ads-developer-email": "email_was_here"
},
"verb": "put"
}
}
- snip -
[04/16/2019 12:03:57] ### Command line arguments: /isolate HKEY_CURRENT_USER\SOFTWARE\AppDataLow\Software\Autodesk\CoreUser\WorkItem_e23918d475a74145aade32ba8968e5c3 "T:\Aces\Jobs\e23918d475a74145aade32ba8968e5c3\userdata" /exe "T:\Aces\AcesRoot\19.0\coreEngine\Exe\revitcoreconsole.exe" /i T:\Aces\Jobs\e23918d475a74145aade32ba8968e5c3\839a11d8-51e9-42de-8936-28687feda65f.rvt /al T:\Aces\Applications\779cf68955e15ce6704c72a62c734afe.alias_was_here.ExtractModelCategories[1].package.
- snip -
[04/16/2019 12:03:57] Echoing command line args:
[04/16/2019 12:03:57] 0:/i
[04/16/2019 12:03:57] 1:T:\Aces\Jobs\e23918d475a74145aade32ba8968e5c3\839a11d8-51e9-42de-8936-28687feda65f.rvt
- snip -
[04/16/2019 12:03:57] Running user application....
- snip -
[04/16/2019 12:04:22] Job finished with result Succeeded
[04/16/2019 12:04:22] Job Status:
{
"status": "success",
...
From the report.txt file for a failed submission:
[04/16/2019 12:04:44] Job information:
"CommandLine":[
"$(engine.path)\\\\revitcoreconsole.exe /i $(args[rvtFile].path) /al $(appbundles[ExtractModelCategories].path)"
]
"Settings":{
"dasreportfailedlimits": {
"value": "true",
"isEnvironmentVariable": true
}
}
"Id":"4db3208a1c4e429c846c4da385f2219d"
"ActivityId":"alias_was_here.ExtractModelCategoriesActivity+prod"
"Engine.Id":"Autodesk.Revit!21"
"Apps": [
"App.Id":"alias_was_here.ExtractModelCategories!1"
]
"BoundArguments":{
"rvtFile": {
"localName": "$(rvtFile)",
"url": "https://developer.api.autodesk.com/oss/v2/buckets/wip.dm.prod/objects/e597df42-07c7-41e1-aa0c-fa1abd179a4c.rvt?scopes=b360project.1949ed9d-e7fd-42b9-98f4-544fff3df42f,global,O2tenant.2971682",
"headers": {
"Authorization": "Bearer token was here"
}
},
"result": {
"localName": "ModelCategories.json",
"url": "https://developer.api.autodesk.com/oss/v2/buckets/wip.dm.prod/objects/6b59f894-bbf0-421a-bf0b-e80d7584ee33.json",
"headers": {
"Authorization": "Bearer token_was_here"
},
"verb": "put"
},
"onComplete": {
"ondemand": true,
"optional": true,
"url": "callback_was_here",
"verb": "post"
},
"onProgress": {
"ondemand": true,
"url": "https://wlnr5sjl3a.execute-api.us-east-1.amazonaws.com/Prod/v3/workitems/progress",
"headers": {
"Content-Type": "application/json",
"x-das-authorize": "awssigv4(us-east-1)",
"x-ads-token-data": "{\"access_token\":{\"client_id\":\"alias_was_here\"},\"scope\":\"bucket:create bucket:read data:read data:create data:write code:all\",\"expires_in\":3596,\"client_id\":\"alias_was_here\"}",
"x-ads-developer-email": "email_was here"
},
"verb": "put"
}
}
- snip -
[04/16/2019 12:04:56] ### Command line arguments: /isolate HKEY_CURRENT_USER\SOFTWARE\AppDataLow\Software\Autodesk\CoreUser\WorkItem_4db3208a1c4e429c846c4da385f2219d "T:\Aces\Jobs\4db3208a1c4e429c846c4da385f2219d\userdata" /exe "T:\Aces\AcesRoot\19.0\coreEngine\Exe\revitcoreconsole.exe" /i T:\Aces\Jobs\4db3208a1c4e429c846c4da385f2219d\$(rvtFile) /al T:\Aces\Applications\779cf68955e15ce6704c72a62c734afe.alias_was_here.ExtractModelCategories[1].package.
- snip -
[04/16/2019 12:04:56] Echoing command line args:
[04/16/2019 12:04:56] 0:/i
[04/16/2019 12:04:56] 1:T:\Aces\Jobs\4db3208a1c4e429c846c4da385f2219d\$(rvtFile)
[04/16/2019 12:04:56] Running user application....
[04/16/2019 12:05:02] Exception: Revit input file not found: T:\Aces\Jobs\4db3208a1c4e429c846c4da385f2219d\$(rvtFile)
- snip -
[04/16/2019 12:05:03] Job finished with result FailedExecution
[04/16/2019 12:05:03] Job Status:
{
"status": "failedInstructions",
...
As best I can tell, the format and structure of the body of both of the submissions is the same (these are version 10 and version 11 of the same model). However, for the failing work item, the Revit file name is not parsing and is still the string $(rvtFile) rather than the actual file name when DA processes the work item.
Any insight into the problem? Does the body of the submission have errors in it? How do I correct?
I am answering my own question based on what I have learned with the assistance of Zhong Wu with Autodesk:
This is currently an issue with the Design Automation for Revit API Beta. If the Revit model includes links to other models then the file downloaded to Design Automation is zipped and includes the main model and the linked file(s). Design Automation then fails because it expects a Revit file. This happens automatically on the API's side.
A work-around is to download the Revit file to another location utilizing the Data Management API. If the file provided by the Data Management API is a compressed file and not a Revit model, un-zip it. Then, place the uncompressed Revit file in a location accessible to Design Automation and post the work item referencing the location of the uncompressed file.
It is my understanding that a change request has been issued internally at Autodesk to improve the handling of compressed files. I have no timeline for this.
If I learn more, I will update this answer.
** UPDATE**
This was fixed by the Autodesk Forge team, and now runs for Revit files with links. Thank you!
Instead of using "localName": "$(rvtFile), could you use a static file name like "localName": "input.rvt"?