Creating a Merged Model Using Glue API
04/21/2015
This question came from Joe Augustino through a forum post. I finally managed to clean up a sample for a blog post.
Q. I'm having trouble creating a merged model. I tried it using the Test Harness, but it is returning "Bad Request" each time. I can manually create it in Glue UI. Can someone please check on this and verify?
A. I can confirm that the one in TestHarness does not work. It’s not up to date. We need clarification on this.
According to the documentation:
https://b4.autodesk.com/api/model/v1/merge/doc
Following are URL, request method, and required parameters.
Model Merge - Request
URL: https://b4.autodesk.com/api/model/v1/merge.{format}
Supported Request Methods: POST
Required Parameters (here I'm skipping common sign-in parameters):
- project_id
- model_name
- model_transformations
project_id is the project identifier that hold the model. model_name is the name of the merged model being created.
Now, the big question mark is the third one, model_transformations. Here is what's written in the reference guide:
"model_transformations: This is an array of JSON elements that represents all models that you want to merge. Each element contains model Id and transformation information for the model. If any of the sub-models are invalid or are merged models themselves, you will receive the HTTP response: 400 Bad Request
Values: Glue Model transformation format string in JSON format
Required: Yes"
Obviously, we need more explanation about the format of model_transformations.
In the following, I'm going to use Glue API Intro Labs2 as the base in building a sample.
model_transformations
Below is a description of the object (modelTransformationRequests) that need to be serialized into JSON for the model_transformations string:
new List<model_units_and_transformation>();
[Serializable]
public class model_units_and_transformation
{
public string Media { get; set; }
public model_transformation_info Transform { get; set; }
public string Type { get; set; }
public string Units { get; set; }
public int Version { get; set; }
}
[Serializable]
public class model_transformation_info
{
public double[] Rotation { get; set; }
public double[] Scale { get; set; }
public double[] Translation { get; set; }
public string Type { get; set; }
public int Version { get; set; }
}
where Media is model_version_id, which you can parse from the response from, for example, /model/v2/info request. We'll come to model/info later.
Model Merge - Sample Code
Given a model_transformations string, you can define Merge() or model/v1/merge call as follows:
{
string timeStamp = Utils.GetUNIXEpochTimestamp().ToString();
string signature = Utils.ComputeMD5Hash(apiKey + apiSecret + timeStamp);
// (1) Build request
// set base url and authenticatopm info.
var client = new RestClient();
client.BaseUrl = baseApiUrl;
// Set resource or end point
var request = new RestRequest();
request.Resource = "model/v1/merge.json";
request.Method = Method.POST;
// Add parameters
request.AddParameter("company_id", companyId);
request.AddParameter("api_key", apiKey);
request.AddParameter("timestamp", timeStamp);
request.AddParameter("sig", signature);
request.AddParameter("auth_token", authToken);
request.AddParameter("project_id", projectId);
request.AddParameter("model_name", modelName);
request.AddParameter("model_transformations", modelTransformations);
// MH: Test merge to a specific folder.
// This gets error. Need to be looked at.
//request.AddParameter("dest_folder_id", "xxx");
// (2) Execute request and get response
IRestResponse response = client.Execute(request);
// Save response. This is to see the response for our learning.
m_lastResponse = response;
if (response.StatusCode != HttpStatusCode.OK)
{
return null;
}
return"OK";
}
UI portion of the code might look something like below. Notice setupMergeParam() function, where we define model_transformations JSON string. We'll take a look how to obtain model_version_id later. For the time being, let's assume two model_version_id's are defined
private void buttonMerge_Click(object sender, EventArgs e)
{
string modelName = textBoxMergedModelName.Text;
// Set up model_transformations parameter
string modelTransformations = setupMergeParam(m_model_version_id1, m_model_version_id2);
textBoxRequest.Text = modelTransformations;
// Merge two models
string test = glueCall.Merge(m_authToken, m_project_id, modelName, modelTransformations);
}
// Composing model transformations here
private string setupMergeParam(string model1, string model2)
{
List<model_units_and_transformation> modelTransformationRequests =
new List<model_units_and_transformation>();
// Set trans info for model1
model_units_and_transformation item1 = new model_units_and_transformation();
item1 = initTransformation(item1);
item1.Media = model1;
modelTransformationRequests.Add(item1);
// Set trans info for model2
model_units_and_transformation item2 = new model_units_and_transformation();
item2 = initTransformation(item2);
item2.Media = model2;
modelTransformationRequests.Add(item2);
// Conver to JSON
JsonSerializer serial = new JsonSerializer();
string transString = serial.Serialize(modelTransformationRequests);
return transString;
}
// Set the initial value of model transformation
private model_units_and_transformation initTransformation(model_units_and_transformation item)
{
item.Media = "";
item.Transform = new model_transformation_info();
item.Transform.Rotation = new double[3];
item.Transform.Rotation[0] = 90.0;
item.Transform.Rotation[1] = 0.0;
item.Transform.Rotation[2] = 0.0;
item.Transform.Scale = new double[3];
item.Transform.Scale[0] = 1.0;
item.Transform.Scale[1] = 1.0;
item.Transform.Scale[2] = 1.0;
item.Transform.Translation = new double[3];
item.Transform.Translation[0] = 0.0;
item.Transform.Translation[1] = 0.0;
item.Transform.Translation[2] = 0.0;
item.Transform.Type = "ModelInstance";
item.Transform.Version = 0;
item.Type = "ModelInstance";
item.Units = "Millimeter";
item.Version = 1;
return item;
}
Note: for clarity of the main points, I have omitted the part that are intended for learning purpose from the above code, such as display of request and response. But it is included in the attached sample code.
Let's take a look at how to obtain model_version_id's next.
Model Info V2 - Request
model/v2/info call returns information of a given model id.
URL: https://b4.autodesk.com/api/model/v2/info.{format}
Supported Request Methods: GET
Required Parameters (here I'm skipping common sign-in parameters):
- model_id
Doc: https://b4.autodesk.com/api/model/v2/info/doc
Model Info V2 - Response
model/v2/info returns a long list of infomation. Please refer to the documentation page for the full sample listing. Here we show the excerpt from it to focus on the item that we are interested parsing in our context:
{
"version_history":[ ... ],
"action_id": "The action identifier used with the Display Component to view this Model",
"company_id": "The company identifier for this model",
"project_id": "The Project identifier for this model",
"model_id": "The master identifier for the model",
"model_version": 1,
"model_version_id": "The version identifier for this specific version of the model",
"model_name": "The name for the model",
"created_by": "The login_name of the creator of the model",
"created_by_first_name": "First name of the creator of the model",
"created_by_last_name": "Last name of the creator of the model",
"created_date": "The date the model was created",
"modified_by": "The login_name of the last user to modify the model",
"modified_date": "Date of last modification",
"parent_folder_id": "The parent folder for the model",
"file_parsed_status": 1,
"is_merged_model": 1,
"merged_model_available": 0,
...
}
For our purpose of merging models, we are interested in model_version_id.
Model Info V2 - Sample Code
Here is the sample code for ModelInfoV2() which calls model/v2/info:
{
string timeStamp = Utils.GetUNIXEpochTimestamp().ToString();
string signature = Utils.ComputeMD5Hash(apiKey + apiSecret + timeStamp);
// (1) Build request
// set base url and authenticatopm info.
var client = new RestClient();
client.BaseUrl = baseApiUrl;
// Set resource or end point
var request = new RestRequest();
request.Resource = "model/v2/info.json";
request.Method = Method.GET;
// Add parameters
request.AddParameter("company_id", companyId);
request.AddParameter("api_key", apiKey);
request.AddParameter("timestamp", timeStamp);
request.AddParameter("sig", signature);
request.AddParameter("auth_token", authToken);
request.AddParameter("model_id", modelId);
// (2) Execute request and get response
IRestResponse response = client.Execute(request);
// Save response. This is to see the response for our learning.
m_lastResponse = response;
if (response.StatusCode != HttpStatusCode.OK)
{
return null;
}
// Get a model version id.
JsonDeserializer deserial = new JsonDeserializer();
ModelInfo modelInfoResponse =
deserial.Deserialize<ModelInfo>(response);
string model_version_id = modelInfoResponse.model_version_id;
return model_version_id;
}
UI portion for Model Info v2 might look something like below:
private static string m_model_version_id1 = "";
private static string m_model_version_id2 = "";
// Get the model version id of the first model
private void buttonModelInfo1_Click(object sender, EventArgs e)
{
m_model_version_id1 = glueCall.ModelInfoV2(m_authToken, m_model_id);
}
// Get the model version id of the second model
private void buttonModelInfo2_Click(object sender, EventArgs e)
{
m_model_version_id2 = glueCall.ModelInfoV2(m_authToken, m_model_id);
}
Once again, for clarity of the main points, I have omitted parts, such as display of request and response. But it is included in the attached sample code.
Putting Together
After putting together the above code, the image of UI of the test app looks like this.
I have attached the sample project I have used here. Download 2 GlueAPIIntro_MergeTest
To test using this program,
- [Login] using Glue credentials.
- Use [Projects] and [Models] button till you find a right project and model to merge. By clicking the buttons, it increments the index of current project and model.
- When you see a right model to merge, select it by pressing [Model Info1] button.
- Repeat to set the second model.
- Finally press [Merge] button to execute merge.
- Go to the Glue UI and see if you see a merged model.
A little caveat: currently, we cannot specify the folder to merge. Specifying dest_folder_id does not work. You can work around by moving the model after it is created.
Many thanks to Joe for bringing up this topic, help testing it and suggesting the workaround.
Mikako