PageRenderTime 55ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/WpfCSharp/AutodeskReCapClient/AdskReCap.cs

https://github.com/PandazZ/Autodesk-ReCap-Samples
C# | 814 lines | 540 code | 57 blank | 217 comment | 67 complexity | 00b9fb152fdcf18883c749c7f8ee3b5a MD5 | raw file
Possible License(s): Apache-2.0, BSD-3-Clause
  1. // (C) Copyright 2014 by Autodesk, Inc.
  2. //
  3. // Permission to use, copy, modify, and distribute this software in
  4. // object code form for any purpose and without fee is hereby granted,
  5. // provided that the above copyright notice appears in all copies and
  6. // that both that copyright notice and the limited warranty and
  7. // restricted rights notice below appear in all supporting
  8. // documentation.
  9. //
  10. // AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
  11. // AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
  12. // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC.
  13. // DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
  14. // UNINTERRUPTED OR ERROR FREE.
  15. //- Written by Cyrille Fauvel, Autodesk Developer Network (ADN)
  16. //- http://www.autodesk.com/joinadn
  17. //- January 20th, 2014
  18. //
  19. using System;
  20. using System.Collections.Generic;
  21. using System.ComponentModel;
  22. using System.Linq;
  23. using System.Text;
  24. using System.IO;
  25. using System.Net;
  26. using System.Xml;
  27. using System.Xml.Linq;
  28. using System.Threading.Tasks;
  29. using System.Diagnostics;
  30. using RestSharp;
  31. using RestSharp.Authenticators;
  32. using RestSharp.Contrib;
  33. using Newtonsoft.Json;
  34. using Newtonsoft.Json.Linq;
  35. using Autodesk.ADN.Toolkit.RESTful;
  36. namespace Autodesk.ADN.Toolkit.ReCap {
  37. // The AdskRESTful _adskRESTClient is a temporary workaround while there is a RESTful
  38. // client incompatibilty in the DeleteScene API for ReCap.
  39. // In older release of the API, you needed to have, but this is not required anymore
  40. // request.AddParameter ("timestamp", AdskRESTful.timestamp ()) ;
  41. public static class EnumExtensions {
  42. public static string ToFriendlyString (this Enum en) {
  43. Type type =en.GetType() ;
  44. if ( type == typeof (AdskReCap.Format) )
  45. return (en.ToString ().TrimStart (new char [] { '_' })) ;
  46. return (en.ToString ()) ;
  47. }
  48. public static Enum ToReCapFormatEnum (this string formatSt) {
  49. AdskReCap.Format format =AdskReCap.Format.OBJ ;
  50. try {
  51. format =(AdskReCap.Format)Enum.Parse (typeof (AdskReCap.Format), formatSt, true) ;
  52. } catch {
  53. format =(AdskReCap.Format)Enum.Parse (typeof (AdskReCap.Format), "_" + formatSt, true) ;
  54. }
  55. return (format) ;
  56. }
  57. public static Enum ToEnum<T> (this string st) {
  58. return ((Enum)Enum.Parse (typeof (T), st, true)) ;
  59. }
  60. public static bool IsEnum<T> (this string st) {
  61. return (Enum.IsDefined (typeof (T), st)) ;
  62. }
  63. public static T? ToEnumSafe<T> (this string st) where T : struct {
  64. return (IsEnum<T> (st) ? (T?)Enum.Parse (typeof (T), st, true) : null) ;
  65. }
  66. }
  67. public class AdskReCap {
  68. #region Enums
  69. public enum NotificationType { ERROR, DONE } ;
  70. public enum Format { _3DP, RCP, FBX, IPM, LAS, OBJ, FYSC, RCS, RCM } ;
  71. [Description("'WorkerStatus' is a common field, that could be used as a parameter or can be a returned value. 'WorkerStatus' is the corresponding state of the photoscene.")]
  72. public enum WorkerStatus {
  73. [Description("the photoscene has just been created")]
  74. CREATED,
  75. [Description("image(s) had been uploaded to this photoscene")]
  76. SENT,
  77. [Description("the photoscene is finished. Client can get the result file.")]
  78. DONE,
  79. [Description("client had canceled the photoscene. If the photoscene has not already been processed, it will never be.")]
  80. CANCEL_BY_USER,
  81. [Description("the photoscene is currently processing")]
  82. PROCESSING,
  83. [Description("the photoscene is currently processing")]
  84. PROCESSING_ALL,
  85. [Description("the photoscene is currently processing")]
  86. RUNNING_KP,
  87. [Description("an error occured while processing the photoscene.")]
  88. ERROR
  89. } ;
  90. [Description("Error Code returned from the API")]
  91. public enum Error {
  92. [Description("No error")] NO_ERROR =0,
  93. [Description("General error")] ERROR =1,
  94. [Description("Database error")] DB_ERROR =2,
  95. [Description("Given ID doesn't match one in database")] DB_BAD_ID =3,
  96. [Description("Not yet implemented")] NOT_YET =4,
  97. [Description("The given type is not valid")] BAD_TYPE =5,
  98. [Description("The resource doesn't have an id")] EMPTY_RESOURCE_ID =6,
  99. [Description("The resource has an id but shouldn't")] NOT_EMPTY_RESOURCE_ID =7,
  100. [Description("The used resource is not correct")] BAD_RESOURCE =8,
  101. [Description("You need at least 3 images to process a photoscene")] NOT_ENOUGH_IMAGES =9,
  102. [Description("Given attribute already exists")] DB_ALREADY_EXISTS =10,
  103. [Description("Unknown")] UNKNOWN =11,
  104. [Description("Bad authentication")] BAD_AUTHENTICATION =12,
  105. [Description("Current user cannot access requested data")] SECURITY_ERROR =13,
  106. [Description("Given values are not correct")] BAD_VALUES =14,
  107. [Description("Given client doesn't exist or is invalid")] CLIENT_DOESNT_EXIST =15,
  108. [Description("Bad timestamp")] BAD_TIMESTAMP =16,
  109. [Description("Given FileID doesn t exist")] FILE_DOESNT_EXIST =17,
  110. [Description("The given image protocol is not correct")] BAD_IMAGE_PROTOCOL =18,
  111. [Description("The given Photoscene ID doesn t exist in the database")] BAD_SCENE_ID =19,
  112. [Description("The user is not correctly identified")] USER_NOT_IDENTIFIED =20,
  113. [Description("You don't have the credentials to use this function")] NO_CREDENTIALS =21,
  114. [Description("Your data is not ready")] NOT_READY =22,
  115. [Description("One file of the same kind already exists in the repository, you cannot overwrite it")] FILE_ALREADY_EXISTS =23,
  116. [Description("This photoscene has already been processed you cannot change the source file you must create a new Photoscene with this photoscene as reference")] SCENE_ALREADY_PROCESSED =24,
  117. [Description("You don't have currently the correct rights")] NO_RIGHTS =25,
  118. [Description("Processing message cannot be sent")] CANNOT_SEND_MESSAGE =26,
  119. [Description("This client is not valid. Please contact ReCap.Api (at) autodesk.com")] CLIENT_NOT_ACTIVATED =27,
  120. [Description("The scene name cannot be empty")] SCENE_NAME_EMPTY =28,
  121. [Description("This client cannot access the asked resource")] PERMISSION_DENIED =29,
  122. [Description("The reference photoscene ID is missing")] MISSING_REF_PID =30,
  123. [Description("Email address has not been entered for this user")] NO_EMAIL =31,
  124. [Description("Message doesn't exist")] ERROR_MSG_DOESNT_EXIST =32,
  125. [Description("An error occured while sending the notification")] ERROR_SENDING_NOTIFICATION =33,
  126. [Description("An error occured while copying the file")] CANT_COPY_FILE =34,
  127. [Description("Photoscene seems to have corrupted information (parameters, files) ...")] PHOTOSCENE_CORRUPTED =35,
  128. [Description("The given notification callback protocol is not correct")] BAD_NOTIFICATION_PROTOCOL =36,
  129. [Description("No callback has been defined")] NO_CALLBACK_DEFINED =37,
  130. [Description("Given user doesn't exist or is invalid")] USER_DOESNT_EXIST =38,
  131. [Description("The service was unable to create new photoscene")] CANNOT_ALLOCATE_PHOTOSCENEID =39,
  132. [Description("Given reference project ID doesn't match one in database")] BAD_REFERENCE_PROJECT_ID =40,
  133. [Description("The source file is unreachable.")] CANT_RETRIEVE_PHOTOSCENE_FILE =41,
  134. [Description("Source file seems to be corrupted. Your source file was probably saved in UTF-8 instead of UTF-16 (Unicode)")] CANT_READ_PHOTOSCENE_FILE =42,
  135. [Description("The namespace associated to client is not found.")] NAMESPACE_NOT_FOUND =43,
  136. [Description("Bad O2 Authentication (signature)")] BAD_O2_AUTHENTICATION =44,
  137. [Description("No OAuth header has been found")] OAUTH_HEADER_DOESNT_FIND =45,
  138. [Description("The specified project is not finished")] PROJECT_NOT_FINISHED =46,
  139. } ;
  140. [Description ("Error Code returned while getting Photoscene link or properties. These errors means the computation of the photoscene failed. (but the API request successed)")]
  141. public enum ComputationError {
  142. [Description("Photoscene has been created successfully")]
  143. RS_OK =0,
  144. [Description("Photoscene has been created successfully")]
  145. RS_OK1 =1,
  146. [Description("Photoscene computed but some images are missing to the final scene (images corrupted or failed to upload)")]
  147. RS_OK_MISSING_SHOTS =2,
  148. [Description("Some of the images appear to be taken from the same physical location. Images in a photo scene cannot be taken from a single position.")]
  149. RS_OK_PANORAMA =3,
  150. [Description("Some of the images could not be stitched.")]
  151. RS_OK_BAD_MATCHING =4,
  152. [Description("Not used")]
  153. NOTUSED5 =5,
  154. [Description("Not used")]
  155. NOTUSED6 =6,
  156. [Description("The application was unable to compute the Photoscene")]
  157. RS_ERROR =7,
  158. [Description("You must provide at least three images to compute the scene.")]
  159. RS_ERROR_NOT_ENOUGH_SHOTS =8,
  160. [Description("Some of the images are corrupt or failed to upload. Check your files and try resubmitting the scene.")]
  161. RS_ERROR_MISSING_SHOTS =9,
  162. [Description("No 3D information could be extracted from your images, as they appear to be taken from the same physical location. Images in a photo scene cannot be taken from a single position. Try capturing images of your subject from different positions and resubmit the scene.")]
  163. RS_ERROR_PANORAMA =10,
  164. [Description("No 3D information could be extracted from your images, as they do not appear to overlap. Images in a photo scene must overlap. Try capturing overlapping images of your subject and resubmit the scene.")]
  165. RS_ERROR_BAD_MATCHING =11,
  166. [Description("There was not enough overlap in your images.")]
  167. P_ERR_TOO_FEWPOINTS =12,
  168. [Description("Unable to create Photoscene from your selection region; however, a photo scene was successfully created using the extents of the scene.")]
  169. KP_ERR_BBOX_EMPTY =13,
  170. [Description("Not enough of your images could be stitched together.")]
  171. KP_ERR_TOOFEWCAMERAS =14,
  172. [Description("No Description")]
  173. KP_ERR_DOWNSIZENEEDED =15,
  174. } ;
  175. public enum MeshQuality {
  176. [Description ("for draft mesh (default)")]
  177. DRAFT =7,
  178. [Description ("for standard mesh")]
  179. STANDARD =8,
  180. [Description ("for a high quality mesh")]
  181. HIGH =9
  182. } ;
  183. public enum FileType {
  184. Image, Xref, Project, Thumbnail
  185. }
  186. #endregion
  187. #region Member variables
  188. protected string _clientID ;
  189. //protected Dictionary<string, string> _tokens =null ;
  190. private RestClient _restClient =null ;
  191. private AdskRESTful _adskRESTClient =null ; // Temporary workaround to the DeleteScene issue
  192. public IRestResponse _lastResponse =null ;
  193. #endregion
  194. public AdskReCap (string clientID, Dictionary<string, string> tokens, string apiURL ="http://rc-api-adn.autodesk.com/3.1/API/") {
  195. _clientID =clientID ;
  196. // @"oauth_consumer_key" @"oauth_consumer_secret" @"oauth_token" @"oauth_token_secret"
  197. //_tokens =tokens ;
  198. _restClient =new RestClient (apiURL) ;
  199. _restClient.Authenticator =OAuth1Authenticator.ForProtectedResource (
  200. tokens ["oauth_consumer_key"], tokens ["oauth_consumer_secret"],
  201. tokens ["oauth_token"], tokens ["oauth_token_secret"]
  202. ) ;
  203. // Temporary workaround to the DeleteScene issue
  204. _adskRESTClient =new AdskRESTful (apiURL, null) ;
  205. _adskRESTClient.addSubscriber (new AdskOauthPlugin (tokens)) ;
  206. }
  207. public AdskReCap (string clientID, string consumerKey, string consumerSecret, string oauth, string oauthSecret, string apiURL ="http://rc-api-adn.autodesk.com/3.1/API/") {
  208. _clientID =clientID ;
  209. // @"oauth_consumer_key" @"oauth_consumer_secret" @"oauth_token" @"oauth_token_secret"
  210. //_tokens =new Dictionary<string, string> () {
  211. // { "oauth_consumer_key", consumerKey }, { "oauth_consumer_secret", consumerSecret },
  212. // { "oauth_token", oauth }, { "oauth_token_secret", oauthSecret }
  213. //}) ;
  214. _restClient =new RestClient (apiURL) ;
  215. _restClient.Authenticator =OAuth1Authenticator.ForProtectedResource (
  216. consumerKey, consumerSecret, oauth, oauthSecret
  217. ) ;
  218. // Temporary workaround to the DeleteScene issue
  219. _adskRESTClient =new AdskRESTful (apiURL, null) ;
  220. _adskRESTClient.addSubscriber (new AdskOauthPlugin (new Dictionary<string, string> () {
  221. { "oauth_consumer_key", consumerKey }, { "oauth_consumer_secret", consumerSecret },
  222. { "oauth_token", oauth }, { "oauth_token_secret", oauthSecret }
  223. })) ;
  224. }
  225. #region ReCap API interface
  226. /// <summary>
  227. /// Return the server date and time
  228. /// </summary>
  229. /// <param name="json">true to receive the response in JSON format. Otherwise default is XML.</param>
  230. /// <returns><para>http://rc-api-adn.autodesk.com/3.1/api-docs/#!/service/get_date_get_1</para>
  231. /// <para>On Error: </para>
  232. /// </returns>
  233. public async Task<bool> ServerTime (bool json =false) {
  234. var request =new RestRequest ("service/date", Method.GET) ;
  235. request.AddParameter ("clientID", _clientID) ;
  236. request.AddParameter (json ? "json" : "xml", 1) ;
  237. Log (String.Format ("{0} {1} request sent", request.Method, request.Resource)) ;
  238. _lastResponse =await _restClient.ExecuteTaskAsync (request) ;
  239. Log ("service/date response: {0}", _lastResponse) ;
  240. return (isOk ()) ;
  241. }
  242. /// <summary>
  243. /// Return the server API version
  244. /// </summary>
  245. /// <param name="json">true to receive the response in JSON format. Otherwise default is XML.</param>
  246. /// <returns><para>http://rc-api-adn.autodesk.com/3.1/api-docs/</para>
  247. /// <para>On Error: </para>
  248. /// </returns>
  249. public async Task<bool> Version (bool json =false) {
  250. var request =new RestRequest ("version", Method.GET) ;
  251. request.AddParameter ("clientID", _clientID) ;
  252. request.AddParameter (json ? "json" : "xml", 1) ;
  253. Log (String.Format ("{0} {1} request sent", request.Method, request.Resource)) ;
  254. _lastResponse =await _restClient.ExecuteTaskAsync (request) ;
  255. Log ("version response: {0}", _lastResponse) ;
  256. return (isOk ()) ;
  257. }
  258. /// <summary>
  259. /// Return the ReCap userID
  260. /// </summary>
  261. /// <param name="json">true to receive the response in JSON format. Otherwise default is XML.</param>
  262. /// <returns><para>http://rc-api-adn.autodesk.com/3.1/api-docs/</para>
  263. /// <para>On Error: </para>
  264. /// </returns>
  265. public async Task<bool> User (string email, string o2id, bool json =false) {
  266. var request =new RestRequest ("user", Method.GET) ;
  267. request.AddParameter ("clientID", _clientID) ;
  268. request.AddParameter ("email", email) ;
  269. request.AddParameter ("O2ID", o2id) ;
  270. request.AddParameter (json ? "json" : "xml", 1) ;
  271. Log (String.Format ("{0} {1} request sent", request.Method, request.Resource)) ;
  272. _lastResponse =await _restClient.ExecuteTaskAsync (request) ;
  273. Log ("user response: {0}", _lastResponse) ;
  274. return (isOk ()) ;
  275. }
  276. /// <summary>
  277. /// Allow the client to set the template he wants to use in emails sent when photoscene is available.
  278. /// If a photoscene is in success state, the 'DONE' email will be sent, if not the 'ERROR' will be.
  279. /// </summary>
  280. /// <param name="emailType">Type of email template. Principal template are for DONE or ERROR projects.</param>
  281. /// <param name="msg">Content of email template. Do not exceed 1024 chars.</param>
  282. /// <param name="json">true to receive the response in JSON format. Otherwise default is XML.</param>
  283. /// <returns><para>http://rc-api-adn.autodesk.com/3.1/api-docs/#!/notification/setTemplateEmail_post_1</para>
  284. /// <para>On Error: BAD_RESOURCE, DB_ERROR</para>
  285. /// </returns>
  286. public async Task<bool> SetNotificationMessage (NotificationType emailType, string msg, bool json =false) {
  287. var request =new RestRequest ("notification/template", Method.POST) ;
  288. request.AddParameter ("clientID", _clientID) ;
  289. request.AddParameter ("emailType", emailType.ToString ()) ;
  290. request.AddParameter ("emailTxt", msg) ;
  291. request.AddParameter (json ? "json" : "xml", 1) ;
  292. Log (String.Format ("{0} {1} request sent", request.Method, request.Resource)) ;
  293. _lastResponse =await _restClient.ExecuteTaskAsync (request) ;
  294. Log ("notification/template response: {0}", _lastResponse) ;
  295. return (isOk ()) ;
  296. }
  297. /// <summary>
  298. /// Create a scene with basic parameters
  299. /// </summary>
  300. /// <param name="format">The scene format: 3DP (default), RCP, FBX, IPM, LAS, FYSC, RCS, RCM, OBJ (as a tar.gz package)</param>
  301. /// <param name="meshQuality">7 for draft mesh (default), 8 for standard and 9 for a high quality mesh.</param>
  302. /// <param name="json">true to receive the response in JSON format. Otherwise default is XML.</param>
  303. /// <returns><para>http://rc-api-adn.autodesk.com/3.1/api-docs/#!/photoscene/create_complete_photoscene_post_0</para>
  304. /// <para>On Error: BAD_SCENE_ID, EMPTY_RESOURCE_ID, BAD_RESOURCE, SCENE_NAME_EMPTY, USER_NOT_IDENTIFIED, CANNOT_ALLOCATE_PHOTOSCENE_ID, DB_ERROR</para>
  305. /// </returns>
  306. public async Task<bool> CreateSimplePhotoscene (Format format =Format._3DP, MeshQuality meshQuality =MeshQuality.DRAFT, bool json =false) {
  307. var request =new RestRequest ("photoscene", Method.POST) ;
  308. request.AddParameter ("clientID", _clientID) ;
  309. request.AddParameter ("format", format.ToFriendlyString ().ToLower ()) ;
  310. request.AddParameter ("meshquality", ((int)meshQuality).ToString ()) ;
  311. request.AddParameter ("scenename", string.Format ("MyPhotoScene{0}", AdskRESTful.timestamp ())) ;
  312. request.AddParameter (json ? "json" : "xml", 1) ;
  313. Log (String.Format ("{0} {1} request sent", request.Method, request.Resource)) ;
  314. _lastResponse =await _restClient.ExecuteTaskAsync (request) ;
  315. Log ("photoscene response: {0}", _lastResponse) ;
  316. return (isOk ()) ;
  317. }
  318. /// <summary>
  319. /// Create a scene with advanced parameters
  320. /// </summary>
  321. /// <param name="format">The scene format: 3DP (default), RCP, FBX, IPM, LAS, FYSC, RCS, RCM, OBJ (as a tar.gz package)</param>
  322. /// <param name="meshQuality">7 for draft mesh (default), 8 for standard and 9 for a high quality mesh.</param>
  323. /// <param name="options">.</param>
  324. /// <param name="json">true to receive the response in JSON format. Otherwise default is XML.</param>
  325. /// <returns><para>http://rc-api-adn.autodesk.com/3.1/api-docs/#!/photoscene/create_complete_photoscene_post_0</para>
  326. /// <para>On Error: BAD_SCENE_ID, EMPTY_RESOURCE_ID, BAD_RESOURCE, SCENE_NAME_EMPTY, USER_NOT_IDENTIFIED, CANNOT_ALLOCATE_PHOTOSCENE_ID, DB_ERROR</para>
  327. /// </returns>
  328. public async Task<bool> CreatePhotoscene (Format format, MeshQuality meshQuality, Dictionary<string, string> options, bool json =false) {
  329. var request =new RestRequest ("photoscene", Method.POST) ;
  330. request.AddParameter ("clientID", _clientID);
  331. request.AddParameter ("format", format.ToFriendlyString ().ToLower ()) ;
  332. request.AddParameter ("meshquality", ((int)meshQuality).ToString ()) ;
  333. request.AddParameter ("scenename", string.Format ("MyPhotoScene{0}", AdskRESTful.timestamp ())) ;
  334. foreach ( KeyValuePair<string, string> entry in options )
  335. request.AddParameter (entry.Key, entry.Value) ;
  336. request.AddParameter (json ? "json" : "xml", 1) ;
  337. Log (String.Format ("{0} {1} request sent", request.Method, request.Resource)) ;
  338. _lastResponse =await _restClient.ExecuteTaskAsync (request) ;
  339. Log ("photoscene response: {0}", _lastResponse) ;
  340. return (isOk ()) ;
  341. }
  342. /// <summary>
  343. /// Returns properties for all photoscenes ordered by creationDate desc using filter (attributeName/attributeValue).
  344. /// </summary>
  345. /// <param name="attributeName">'Advanced tool':to specify name of field in Database to apply 'attributeValue' to filter.</param>
  346. /// <param name="attributeValue">'Advanced tool':to specify value of field in Database to filter using 'attributeName' name.</param>
  347. /// <param name="json">true to receive the response in JSON format. Otherwise default is XML.</param>
  348. /// <returns><para>http://rc-api-adn.autodesk.com/3.1/api-docs/#!/photoscene/get_photoscene_properties_get_9</para>
  349. /// <para>On Error: </para>
  350. /// </returns>
  351. public async Task<bool> SceneList (string attributeName, string attributeValue, bool json =false) {
  352. var request =new RestRequest ("photoscene/properties", Method.GET) ;
  353. request.AddParameter ("clientID", _clientID) ;
  354. request.AddParameter ("attributeName", attributeName) ;
  355. request.AddParameter ("attributeValue", attributeValue) ;
  356. request.AddParameter (json ? "json" : "xml", 1) ;
  357. Log (String.Format ("{0} {1} request sent", request.Method, request.Resource)) ;
  358. _lastResponse =await _restClient.ExecuteTaskAsync (request) ;
  359. Log ("photoscene/properties response: {0}", _lastResponse) ; // Can be very big
  360. Log ("photoscene/properties response: <returned with a response>", "Response") ;
  361. return (isOk ()) ;
  362. }
  363. /// <summary>
  364. /// All the data associated to the given photoscene(s) and a list of files used for given photoscene(s).
  365. /// </summary>
  366. /// <param name="photosceneid">The ID of the photoscene to get properties.</param>
  367. /// <param name="json">true to receive the response in JSON format. Otherwise default is XML.</param>
  368. /// <returns><para>http://rc-api-adn.autodesk.com/3.1/api-docs/#!/photoscene/get_photoscene_properties_get_9</para>
  369. /// <para>On Error: BAD_SCENE_ID</para>
  370. /// </returns>
  371. public async Task<bool> SceneProperties (string photosceneid, bool json =false) {
  372. var request =new RestRequest (string.Format ("photoscene/{0}/properties", photosceneid), Method.GET) ;
  373. request.AddParameter ("clientID", _clientID) ;
  374. request.AddParameter (json ? "json" : "xml", 1) ;
  375. Log (String.Format ("{0} {1} request sent", request.Method, request.Resource)) ;
  376. _lastResponse =await _restClient.ExecuteTaskAsync (request) ;
  377. Log ("photoscene/.../properties response: {0}", _lastResponse) ;
  378. return (isOk ()) ;
  379. }
  380. /// <summary>
  381. /// All the data associated to the given photoscene(s) and a list of files used for given photoscene(s).
  382. /// </summary>
  383. /// <param name="photosceneid">The ID of the photoscene to get properties.</param>
  384. /// <param name="files">The list of image files to upload.</param>
  385. /// <param name="json">true to receive the response in JSON format. Otherwise default is XML.</param>
  386. /// <returns><para>http://rc-api-adn.autodesk.com/3.1/api-docs/#!/photoscene/get_photoscene_properties_get_9</para>
  387. /// <para>On Error: BAD_SCENE_ID, SCENE_ALREADY_PROCESSED, CANT_COPY_FILE, DB_ERROR, BAD_VALUES, PHOTOSCENE_CORRUPTED, BAD_IMAGE_PROTOCOL, DB_BAD_ID</para>
  388. /// </returns>
  389. public async Task<bool> UploadFiles(string photosceneid, Dictionary<string, string> files, bool json =false) {
  390. // ReCap returns the following if no file uploaded (or referenced), setup an error instead
  391. //<Response>
  392. // <Usage>0.81617307662964</Usage>
  393. // <Resource>/file</Resource>
  394. // <photosceneid> your scene ID </photosceneid>
  395. // <Files>
  396. //
  397. // </Files>
  398. //</Response>
  399. if ( files == null || files.Count == 0 ) {
  400. _lastResponse =null ;
  401. return (false) ;
  402. }
  403. var request =new RestRequest (string.Format ("file", photosceneid), Method.POST) ;
  404. request.Timeout =1 * 60 * 60 * 1000 ;
  405. request.AddParameter ("clientID", _clientID) ;
  406. request.AddParameter ("photosceneid", photosceneid) ;
  407. request.AddParameter ("type", "image") ;
  408. int n =0 ;
  409. foreach ( KeyValuePair<string, string> entry in files ) {
  410. string key =string.Format ("file[{0}]", n++) ;
  411. if ( File.Exists (entry.Value) ) {
  412. request.AddFile (key, entry.Value) ;
  413. } else if ( entry.Value.Substring (0, 4).ToLower () == "http" || entry.Value.Substring (0, 3).ToLower () == "ftp" ) {
  414. request.AddParameter (key, entry.Value) ;
  415. } else {
  416. byte [] img =Convert.FromBase64String (entry.Value) ;
  417. request.AddFile (key, img, entry.Key) ;
  418. }
  419. }
  420. request.AddParameter (json ? "json" : "xml", 1) ;
  421. Log (String.Format ("{0} {1} request sent", request.Method, request.Resource)) ;
  422. _lastResponse =await _restClient.ExecuteTaskAsync (request) ;
  423. Log ("file response: {0}", _lastResponse) ;
  424. return (isOk ()) ;
  425. }
  426. public RestRequestAsyncHandle UploadFilesAsync (string photosceneid, Dictionary<string, string> files, Action<IRestResponse, RestRequestAsyncHandle> callback) {
  427. // ReCap returns the following if no file uploaded (or referenced), setup an error instead
  428. //<Response>
  429. // <Usage>0.81617307662964</Usage>
  430. // <Resource>/file</Resource>
  431. // <photosceneid> your scene ID </photosceneid>
  432. // <Files>
  433. //
  434. // </Files>
  435. //</Response>
  436. if ( files == null || files.Count == 0 ) {
  437. _lastResponse =null ;
  438. return (null) ;
  439. }
  440. var request =new RestRequest (string.Format ("file", photosceneid), Method.POST) ;
  441. request.Timeout =1 * 60 * 60 * 1000 ;
  442. request.AddParameter ("clientID", _clientID) ;
  443. request.AddParameter ("photosceneid", photosceneid) ;
  444. request.AddParameter ("type", "image") ;
  445. int n =0 ;
  446. if ( files != null ) {
  447. foreach ( KeyValuePair<string, string> entry in files ) {
  448. string key =string.Format ("file[{0}]", n++) ;
  449. if ( File.Exists (entry.Value) ) {
  450. request.AddFile (key, entry.Value) ;
  451. } else if ( entry.Value.Substring (0, 4).ToLower () == "http" || entry.Value.Substring (0, 3).ToLower () == "ftp" ) {
  452. request.AddParameter (key, entry.Value) ;
  453. } else {
  454. byte [] img =Convert.FromBase64String (entry.Value) ;
  455. request.AddFile (key, img, entry.Key) ;
  456. }
  457. }
  458. }
  459. // Inline example
  460. //var asyncHandle =_restClient.ExecuteAsync (request, response => { if ( response.StatusCode == HttpStatusCode.OK ) {} else {} }) ;
  461. var asyncHandle =_restClient.ExecuteAsync (request, callback) ;
  462. System.Diagnostics.Debug.WriteLine ("async file call started") ;
  463. return (asyncHandle) ;
  464. }
  465. /// <summary>
  466. /// Launch the Photoscene process.
  467. /// This method has to be called after creating a Photoscene and uploading the images (if needed).
  468. /// You can monitor the progress of the processing using the GetPhotosceneProgress call.
  469. /// This method will always force the scene to be processed even if this photoscene has already been processed.
  470. /// </summary>
  471. /// <param name="photosceneid">The photoscene ID to identify photoscene.</param>
  472. /// <param name="json">true to receive the response in JSON format. Otherwise default is XML.</param>
  473. /// <returns><para>http://rc-api-adn.autodesk.com/3.1/api-docs/#!/photoscene/process_a_photoscene_post_3</para>
  474. /// <para>On Error: BAD_SCENE_ID, PERMISSION_DENIED, USER_NOT_IDENTIFIED, NOT_ENOUGH_IMAGES, CANT_COPY_FILE, CANT_READ_PHOTOSCENE_FILE, NO_RIGHTS, CANNOT_SEND_MESSAGE</para>
  475. /// </returns>
  476. public async Task<bool> ProcessScene (string photosceneid, bool json =false) {
  477. var request =new RestRequest (string.Format ("photoscene/{0}", photosceneid), Method.POST) ;
  478. request.AddParameter ("clientID", _clientID) ;
  479. request.AddParameter ("photosceneid", photosceneid) ;
  480. request.AddParameter ("forceReprocess", "1") ;
  481. request.AddParameter (json ? "json" : "xml", 1) ;
  482. Log (String.Format ("{0} {1} request sent", request.Method, request.Resource)) ;
  483. _lastResponse =await _restClient.ExecuteTaskAsync (request) ;
  484. Log ("(post) photoscene/... response: {0}", _lastResponse) ;
  485. return (isOk ()) ;
  486. }
  487. /// <summary>
  488. /// Returns the current progress percentage of a photoscene.
  489. /// </summary>
  490. /// <param name="photosceneid">The photoscene ID to identify photoscene.</param>
  491. /// <param name="json">true to receive the response in JSON format. Otherwise default is XML.</param>
  492. /// <returns><para>http://rc-api-adn.autodesk.com/3.1/api-docs/#!/photoscene/get_photoscene_progress_get_6</para>
  493. /// <para>On Error: BAD_SCENE_ID, EMPTY_RESOURCE_ID, PERMISSION_DENIED</para>
  494. /// </returns>
  495. public async Task<bool> SceneProgress (string photosceneid, bool json =false) {
  496. var request =new RestRequest (string.Format ("photoscene/{0}/progress", photosceneid), Method.GET) ;
  497. request.AddParameter ("clientID", _clientID) ;
  498. request.AddParameter ("photosceneid", photosceneid) ;
  499. request.AddParameter (json ? "json" : "xml", 1) ;
  500. Log (String.Format ("{0} {1} request sent", request.Method, request.Resource)) ;
  501. _lastResponse =await _restClient.ExecuteTaskAsync (request) ;
  502. Log ("photoscene/.../progress response: {0}", _lastResponse) ;
  503. return (isOk ()) ;
  504. }
  505. /// <summary>
  506. /// Return time in second to calculate the given photoscene.
  507. /// If the scene has not yet been computed, 0 is returned. the time in second to process the photoscene.
  508. /// </summary>
  509. /// <param name="photosceneid">The photoscene ID to identify photoscene.</param>
  510. /// <param name="json">true to receive the response in JSON format. Otherwise default is XML.</param>
  511. /// <returns><para>http://rc-api-adn.autodesk.com/3.1/api-docs/#!/photoscene/get_photoscene_processingtime_get_7</para>
  512. /// <para>On Error: BAD_SCENE_ID, EMPTY_RESOURCE_ID</para>
  513. /// </returns>
  514. public async Task<bool> ProcessingTime (string photosceneid, bool json =false) {
  515. var request =new RestRequest (string.Format ("photoscene/{0}/processingtime", photosceneid), Method.GET) ;
  516. request.AddParameter ("clientID", _clientID) ;
  517. request.AddParameter ("photosceneid", photosceneid) ;
  518. request.AddParameter (json ? "json" : "xml", 1) ;
  519. Log (String.Format ("{0} {1} request sent", request.Method, request.Resource)) ;
  520. _lastResponse =await _restClient.ExecuteTaskAsync (request) ;
  521. Log ("photoscene/.../processingtime response: {0}", _lastResponse) ;
  522. return (isOk ()) ;
  523. }
  524. /// <summary>
  525. /// Return the size on disc for all documents used to or created by given photoscene.
  526. /// </summary>
  527. /// <param name="photosceneid">The photoscene ID to identify photoscene.</param>
  528. /// <param name="json">true to receive the response in JSON format. Otherwise default is XML.</param>
  529. /// <returns><para>http://rc-api-adn.autodesk.com/3.1/api-docs/#!/photoscene/get_photoscene_processingtime_get_7</para>
  530. /// <para>On Error: BAD_SCENE_ID, EMPTY_RESOURCE_ID</para>
  531. /// </returns>
  532. public async Task<bool> FileSize (string photosceneid, bool json =false) {
  533. var request =new RestRequest (string.Format ("photoscene/{0}/filesize", photosceneid), Method.GET) ;
  534. request.AddParameter ("clientID", _clientID) ;
  535. request.AddParameter ("photosceneid", photosceneid) ;
  536. request.AddParameter (json ? "json" : "xml", 1) ;
  537. Log (String.Format ("{0} {1} request sent", request.Method, request.Resource)) ;
  538. _lastResponse =await _restClient.ExecuteTaskAsync (request) ;
  539. Log ("photoscene/.../filesize response: {0}", _lastResponse) ;
  540. return (isOk ()) ;
  541. }
  542. /// <summary>
  543. /// Return the given file
  544. /// </summary>
  545. /// <param name="fileid">The ID of the file to get</param>
  546. /// <param name="fileType">If provided only this specific type is search for. If not provided the API will
  547. /// try to do a best guess on the file type. Can be 'image' or 'xref'.</param>
  548. /// <param name="json">true to receive the response in JSON format. Otherwise default is XML.</param>
  549. /// <returns></returns>
  550. public async Task<bool> GetFile (string fileid, FileType fileType =FileType.Image, bool json =false) {
  551. var request = new RestRequest (string.Format ("file/{0}/get", fileid), Method.GET) ;
  552. request.AddParameter ("clientID", _clientID) ;
  553. request.AddParameter ("type", fileType.ToString ().ToLower ()) ;
  554. request.AddParameter (json ? "json" : "xml", 1) ;
  555. Log (String.Format ("{0} {1} request sent", request.Method, request.Resource)) ;
  556. _lastResponse =await _restClient.ExecuteTaskAsync (request) ;
  557. Log ("file/.../get response: {0}", _lastResponse) ;
  558. return (isOk ()) ;
  559. }
  560. /// <summary>
  561. /// Get the given Photoscene as a link.
  562. /// </summary>
  563. /// <param name="photosceneid">The photoscene ID to identify photoscene.</param>
  564. /// <param name="format">The scene format: 3DP (default), RCP, FBX, IPM, LAS, FYSC, RCS, RCM, OBJ (as a tar.gz package)</param>
  565. /// <param name="json">true to receive the response in JSON format. Otherwise default is XML.</param>
  566. /// <returns><para>http://rc-api-adn.autodesk.com/3.1/api-docs/#!/photoscene/get_photoscene_get_4</para>
  567. /// <para>On Error: BAD_SCENE_ID, EMPTY_RESOURCE_ID, NO_RIGTHS, NOT_READY</para>
  568. /// </returns>
  569. public async Task<bool> GetPointCloudArchive (string photosceneid, Format format, bool json =false) {
  570. var request =new RestRequest (string.Format ("photoscene/{0}", photosceneid), Method.GET) ;
  571. request.AddParameter ("clientID", _clientID) ;
  572. request.AddParameter ("photosceneid", photosceneid) ;
  573. request.AddParameter ("format", format.ToFriendlyString ().ToLower ()) ;
  574. request.AddParameter (json ? "json" : "xml", 1) ;
  575. Log (String.Format ("{0} {1} request sent", request.Method, request.Resource)) ;
  576. _lastResponse =await _restClient.ExecuteTaskAsync (request) ;
  577. Log ("photoscene/... response: {0}", _lastResponse) ;
  578. return (isOk ()) ;
  579. }
  580. /// <summary>
  581. /// Set the Photoscene status to CANCEL for no further processing
  582. /// </summary>
  583. /// <param name="photosceneid">The photoscene ID to identify photoscene.</param>
  584. /// <param name="json">true to receive the response in JSON format. Otherwise default is XML.</param>
  585. /// <returns><para>http://rc-api-adn.autodesk.com/3.1/api-docs/#!/photoscene/cancel_a_photoscene_post_10</para>
  586. /// <para>On Error: BAD_SCENE_ID, PERMISSION_DENIED</para>
  587. /// </returns>
  588. public async Task<bool> Cancel (string photosceneid, bool json =false) {
  589. var request =new RestRequest (string.Format ("photoscene/{0}/cancel", photosceneid), Method.POST) ;
  590. request.AddParameter ("clientID", _clientID) ;
  591. request.AddParameter ("photosceneid", photosceneid) ;
  592. request.AddParameter (json ? "json" : "xml", 1) ;
  593. Log (String.Format ("{0} {1} request sent", request.Method, request.Resource)) ;
  594. _lastResponse =await _restClient.ExecuteTaskAsync (request) ;
  595. Log ("photoscene/.../cancel response: {0}", _lastResponse) ;
  596. return (isOk ()) ;
  597. }
  598. /// <summary>
  599. /// Set the Photoscene status to CANCEL for no further processing
  600. /// </summary>
  601. /// <param name="photosceneid">The photoscene ID to identify photoscene.</param>
  602. /// <param name="clientError">The error to set to the photoscene.</param>
  603. /// <param name="json">true to receive the response in JSON format. Otherwise default is XML.</param>
  604. /// <returns><para>http://rc-api-adn.autodesk.com/3.1/api-docs/#!/photoscene/cancel_a_photoscene_post_10</para>
  605. /// <para>On Error: BAD_SCENE_ID, EMPTY_RESOURCE_ID, DB_ERROR</para>
  606. /// </returns>
  607. public async Task<bool> SetError (string photosceneid, string clientError, bool json =false) {
  608. var request =new RestRequest (string.Format ("photoscene/{0}/cancel", photosceneid), Method.POST) ;
  609. request.AddParameter ("clientID", _clientID) ;
  610. request.AddParameter ("photosceneid", photosceneid) ;
  611. request.AddParameter ("clientError", clientError) ;
  612. request.AddParameter (json ? "json" : "xml", 1) ;
  613. Log (String.Format ("{0} {1} request sent", request.Method, request.Resource)) ;
  614. _lastResponse =await _restClient.ExecuteTaskAsync (request) ;
  615. Log ("photoscene/.../error response: {0}", _lastResponse) ;
  616. return (isOk ()) ;
  617. }
  618. /// <summary>
  619. /// Delete the given photoscene and all the associated assets (images, output files, ...)
  620. /// </summary>
  621. /// <param name="photosceneid">The ID of the photoscene to get properties</param>
  622. /// <param name="json">true to receive the response in JSON format. Otherwise default is XML.</param>
  623. /// <returns><para>http://rc-api-adn.autodesk.com/3.1/api-docs/#!/photoscene/delete_photoscene_delete_5</para>
  624. /// <para>On Error: EMPTY_RESOURCE_ID, BAD_SCENE_ID</para>
  625. /// </returns>
  626. public async Task<bool> DeleteScene (string photosceneid, bool json =false) {
  627. var request =new RestRequest (string.Format ("photoscene/{0}", photosceneid), Method.DELETE) ;
  628. request.AlwaysMultipartFormData =true ;
  629. request.AddParameter ("clientID", _clientID) ;
  630. request.AddParameter (json ? "json" : "xml", 1) ;
  631. Log (String.Format ("{0} {1} request sent", request.Method, request.Resource)) ;
  632. _lastResponse =await _restClient.ExecuteTaskAsync (request) ;
  633. //var method =Enum.GetName (typeof (Method), Method.DELETE) ;
  634. //_lastResponse =_restClient.ExecuteAsPost (request, method) ; // sign as POST :(
  635. Log ("(delete) photoscene/... response: {0}", _lastResponse) ;
  636. return (isOk ()) ;
  637. }
  638. /// <summary>
  639. /// Delete the given photoscene and all the associated assets (images, output files, ...)
  640. /// </summary>
  641. /// <param name="photosceneid">The ID of the photoscene to get properties</param>
  642. /// <param name="json">true to receive the response in JSON format. Otherwise default is XML.</param>
  643. /// <returns><para>http://rc-api-adn.autodesk.com/3.1/api-docs/#!/photoscene/delete_photoscene_delete_5</para>
  644. /// <para>On Error: EMPTY_RESOURCE_ID, BAD_SCENE_ID</para>
  645. /// </returns>
  646. public bool DeleteSceneTempFix (string photosceneid) {
  647. _adskRESTClient.AlwaysMultipart =true ;
  648. _adskRESTClient.AlwaysSignParameters =true ;
  649. _adskRESTClient.clearAllParameters () ;
  650. _adskRESTClient.addParameters (new Dictionary<string, string> () {
  651. { "clientID", _clientID }
  652. }) ;
  653. HttpWebRequest req =_adskRESTClient.delete (string.Format ("photoscene/{0}", photosceneid), null) ;
  654. AdskRESTfulResponse response =_adskRESTClient.send (req) ;
  655. using ( StreamReader reader =new StreamReader (response.urlResponse.GetResponseStream ()) ) {
  656. // Get the response stream and write to console
  657. string text =reader.ReadToEnd () ;
  658. System.Diagnostics.Debug.WriteLine ("Successful Response: \r\n" + text) ;
  659. _lastResponse.StatusCode =response.urlResponse.StatusCode ;
  660. _lastResponse.Content =text ;
  661. _lastResponse.ContentLength =text.Length ;
  662. }
  663. _adskRESTClient.AlwaysMultipart =false ;
  664. _adskRESTClient.AlwaysSignParameters =false ;
  665. return (isOk ()) ;
  666. }
  667. #endregion
  668. #region Utilities
  669. public string ErrorMessage () {
  670. if ( _lastResponse == null )
  671. return ("") ;
  672. string errmsg ="" ;
  673. if ( _lastResponse.ErrorMessage != null && _lastResponse.ErrorMessage != "" ) {
  674. errmsg =_lastResponse.ErrorMessage ;
  675. } else {
  676. XmlDocument xmlDoc =xml () ;
  677. if ( xmlDoc != null ) {
  678. XmlNode errorCode =xmlDoc.SelectSingleNode ("/Response/Error/code") ;
  679. XmlNode results =xmlDoc.SelectSingleNode ("/Response/Error/msg") ;
  680. errmsg =string.Format ("{0} (# {1})", results.InnerText, errorCode.InnerText) ;
  681. } else {
  682. errmsg ="Not an XML response." ;
  683. }
  684. }
  685. return (errmsg) ;
  686. }
  687. public bool isXml () {
  688. if ( _lastResponse == null || _lastResponse.StatusCode != HttpStatusCode.OK )
  689. return (false) ;
  690. string st =this.ToString () ;
  691. return (st.IndexOf ("<?xml") != -1) ;
  692. }
  693. public XmlDocument xml () {
  694. if ( _lastResponse == null || _lastResponse.ErrorMessage != null )
  695. return (null) ;
  696. try {
  697. XmlDocument theDocument =new XmlDocument () ;
  698. theDocument.LoadXml (ToString ()) ;
  699. return (theDocument) ;
  700. } catch /*( Exception ex )*/ {
  701. Log ("Not a valid XML response.", "Error") ;
  702. return (null) ;
  703. }
  704. }
  705. public XDocument xmlLinq () {
  706. if ( _lastResponse == null || _lastResponse.ErrorMessage != null )
  707. return (null) ;
  708. try {
  709. XDocument theDocument =XDocument.Parse (ToString ()) ;
  710. return (theDocument) ;
  711. } catch /*( Exception ex )*/ {
  712. Log ("Not a valid XML response.", "Error") ;
  713. return (null) ;
  714. }
  715. }
  716. public JObject json () {
  717. if ( _lastResponse == null || _lastResponse.ErrorMessage != null )
  718. return (null) ;
  719. try {
  720. JObject theDocument =JObject.Parse (ToString ()) ;
  721. return (theDocument) ;
  722. } catch /*( Exception ex )*/ {
  723. Log ("Not a valid JSON response.", "Error") ;
  724. return (null) ;
  725. }
  726. }
  727. public AdskReCapResponse response () {
  728. if ( _lastResponse == null || _lastResponse.StatusCode != HttpStatusCode.OK )
  729. return (null) ;
  730. if ( isXml () )
  731. return (new AdskReCapResponse (xmlLinq ())) ;
  732. else
  733. return (new AdskReCapResponse (json ())) ;
  734. }
  735. public bool isOk () {
  736. if ( _lastResponse == null || _lastResponse.StatusCode != HttpStatusCode.OK )
  737. return (false) ;
  738. string st =this.ToString () ;
  739. return (st.IndexOf ("<error>") == -1 && st.IndexOf ("<Error>") == -1) ;
  740. }
  741. override public string ToString () {
  742. if ( _lastResponse == null )
  743. return ("<error>") ;
  744. return (_lastResponse.Content) ;
  745. }
  746. private static void Log (string format, IRestResponse message) {
  747. Log (string.Format (format, message.Content), "Response") ;
  748. }
  749. private static void Log (string msg) {
  750. Log (msg, "Request") ;
  751. }
  752. private static void Log (string msg, string category ="Info") {
  753. Trace.WriteLine ("ReCap: " + msg, category) ;
  754. }
  755. #endregion
  756. }
  757. }