Glendale.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  1. <?php
  2. namespace App\Libraries\BIM\Glendale;
  3. use App\BO\BIMFileBO;
  4. use App\Libraries\BIM\Abstracts\BIMAbstract;
  5. use App\Libraries\BIM\BIMDriverEnum;
  6. use App\Models\BimFile;
  7. use App\Models\Enums\BimFileConvertStatus;
  8. use App\Models\Enums\BimFileModelType;
  9. use Illuminate\Http\UploadedFile;
  10. use Illuminate\Support\Arr;
  11. use Illuminate\Support\Facades\Log;
  12. class Glendale extends BIMAbstract
  13. {
  14. //http://gisbimapi.glendale.top/#/serviceApi/BIM%E6%A8%A1%E5%9E%8B%E6%9C%8D%E5%8A%A1?id=%e6%ba%90%e6%96%87%e4%bb%b6%e7%9b%b8%e5%85%b3
  15. /**
  16. * 匹配Glendale的轻量化状态码
  17. * @param int $sourceStatus
  18. * @return int
  19. */
  20. public static function mapSourceStatus(int $sourceStatus): int
  21. {
  22. if ($sourceStatus == 100) {
  23. $convertStatus = BimFileConvertStatus::DONE->value;
  24. } elseif ($sourceStatus < 100 && $sourceStatus > 0) {
  25. $convertStatus = BimFileConvertStatus::CONVERTING->value;
  26. } else {
  27. $convertStatus = BimFileConvertStatus::IN_QUEUE->value;
  28. }
  29. return $convertStatus;
  30. }
  31. private function isPointCloudGISModel(string $ext): bool
  32. {
  33. return in_array($ext, ['las', 'laz', 'ply', 'xyz']);
  34. }
  35. private function isOSGBGISModel(string $gisType): bool
  36. {
  37. return $gisType == 'osgb';
  38. }
  39. private function replaceUrlToHttps(array $data = [], array $needReplaceFields = []): array
  40. {
  41. $stationUrl = config('bim.glendale.host');
  42. foreach ($needReplaceFields as $field) {
  43. if (isset($data[$field])) {
  44. $data[$field] = str_replace('http://159.75.168.101:18086', $stationUrl, $data[$field]);
  45. }
  46. }
  47. return $data;
  48. }
  49. /**
  50. * 构造query的input传参
  51. * @param \App\BO\BIMFileBO $bimFileBO
  52. * @param array $append
  53. * @return array
  54. */
  55. private function buildQueryParams(BimFileBO $bimFileBO, array $append = []): array
  56. {
  57. $defaultConfigJson = ExtensionModelConfig::getConfigOption($bimFileBO->extension);
  58. $configJson = array_merge($defaultConfigJson, $bimFileBO->configJson);
  59. $input = [
  60. 'name' => $bimFileBO->name,
  61. 'initiatingUser' => $bimFileBO->initiatingUser,
  62. 'uniqueCode' => $bimFileBO->uniqueCode,
  63. 'priority' => $bimFileBO->priority,
  64. 'isCAD' => $bimFileBO->isCAD,
  65. 'callbackInterfaceURL' => route('glendale.callback', ['tenant' => tenant('id')]),
  66. 'configJson' => $configJson,
  67. ];
  68. if (!empty($append)) {
  69. $input = array_merge($input, $append);
  70. }
  71. return [
  72. 'input' => json_encode($input)
  73. ];
  74. }
  75. /**
  76. * 指定url方式上传模型到引擎服务器
  77. * @param string $fileUrl
  78. * @param BimFileBO $bimFileBO
  79. * @return array
  80. */
  81. protected function uploadModelByUrl(BimFileBO $bimFileBO): array
  82. {
  83. $append = ['modelDownloadUrl' => $bimFileBO->modelDownloadUrl];
  84. $query = $this->buildQueryParams($bimFileBO, $append);
  85. Log::info('Glendale uploadModelByUrl', $query);
  86. return Client::getInstance()->post('/api/app/model/transcode-file', [
  87. 'query' => $query
  88. ]);
  89. }
  90. /**
  91. * 文件流方式上传模型到引擎服务器
  92. * @param \Illuminate\Http\UploadedFile $file
  93. * @param BimFileBO $bimFileBO
  94. * @return array
  95. */
  96. protected function uploadModelByStream(UploadedFile $file, BimFileBO $bimFileBO): array
  97. {
  98. return Client::getInstance()->post('/api/app/model/upload-file', [
  99. 'query' => $this->buildQueryParams($bimFileBO),
  100. 'multipart' => [
  101. ['name' => 'file', 'contents' => fopen($file, 'r+'), 'filename' => $bimFileBO->name]
  102. ],
  103. ]);
  104. }
  105. /**
  106. * 文件流方式上传点云GIS模型
  107. * @param \Illuminate\Http\UploadedFile $file
  108. * @param BimFileBO $bimFileBO
  109. * @return array|null
  110. */
  111. protected function uploadPointCloudModelByStream(UploadedFile $file, BimFileBO $bimFileBO)
  112. {
  113. $srs = $bimFileBO->pointCloudConfigJson['srs'] ?? '';
  114. $longitude = $bimFileBO->pointCloudConfigJson['longitude'] ?? null;
  115. $latitude = $bimFileBO->pointCloudConfigJson['latitude'] ?? null;
  116. throw_validation_if(empty($srs) && (empty($longitude) || empty($latitude)), 'srs or longitude & latitude is required');
  117. return Client::getInstance()->post('/api/app/gismodel/PointCloudUploadFile', [
  118. 'query' => $this->buildQueryParams($bimFileBO, ['pointCloudConfigJson' => $bimFileBO->pointCloudConfigJson]),
  119. 'multipart' => [
  120. ['name' => 'file', 'contents' => fopen($file, 'r+'), 'filename' => $bimFileBO->name]
  121. ],
  122. ]);
  123. }
  124. /**
  125. * 指定url方式上传点云GIS模型
  126. * @param \App\BO\BIMFileBO $bimFileBO
  127. * @return array|null
  128. */
  129. protected function uploadPointCloudModelByUrl(BimFileBO $bimFileBO)
  130. {
  131. $srs = $bimFileBO->pointCloudConfigJson['srs'] ?? '';
  132. $longitude = $bimFileBO->pointCloudConfigJson['longitude'] ?? null;
  133. $latitude = $bimFileBO->pointCloudConfigJson['latitude'] ?? null;
  134. throw_validation_if(empty($srs) && (empty($longitude) || empty($latitude)), 'srs or longitude & latitude is required');
  135. $append = [
  136. 'modelDownloadUrl' => $bimFileBO->modelDownloadUrl,
  137. 'pointCloudConfigJson' => $bimFileBO->pointCloudConfigJson
  138. ];
  139. return Client::getInstance()->post('/api/app/gismodel/OsgbUploadFileByUrl', [
  140. 'query' => $this->buildQueryParams($bimFileBO, $append)
  141. ]);
  142. }
  143. /**
  144. * 文件流方式上传OSGB GIS模型
  145. * @param \Illuminate\Http\UploadedFile $file
  146. * @param \App\BO\BIMFileBO $bimFileBO
  147. * @return array|null
  148. */
  149. protected function uploadOSGBModelByStream(UploadedFile $file, BimFileBO $bimFileBO)
  150. {
  151. return Client::getInstance()->post('/api/app/gismodel/OsgbUploadFile', [
  152. 'query' => $this->buildQueryParams($bimFileBO),
  153. 'multipart' => [
  154. ['name' => 'file', 'contents' => fopen($file, 'r+'), 'filename' => $bimFileBO->name]
  155. ],
  156. ]);
  157. }
  158. /**
  159. * 指定url方式上传OSGB GIS模型
  160. * @param \App\BO\BIMFileBO $bimFileBO
  161. * @return array|null
  162. */
  163. protected function uploadOSGBModelByUrl(BimFileBO $bimFileBO)
  164. {
  165. $append = ['modelDownloadUrl' => $bimFileBO->modelDownloadUrl];
  166. return Client::getInstance()->post('/api/app/gismodel/OsgbUploadFileByUrl', [
  167. 'query' => $this->buildQueryParams($bimFileBO, $append)
  168. ]);
  169. }
  170. /**
  171. * 上传文件
  172. * @param mixed $file
  173. * @param \App\BO\BIMFileBO $bimFileBO
  174. * @return array
  175. */
  176. public function uploadFile(?UploadedFile $file, BimFileBO $bimFileBO): array
  177. {
  178. try {
  179. if (!empty($bimFileBO->modelDownloadUrl)) { //url方式
  180. if ($this->isPointCloudGISModel($bimFileBO->extension)) { //点云
  181. $result = $this->uploadPointCloudModelByUrl($bimFileBO);
  182. } elseif ($this->isOSGBGISModel(gisType: $bimFileBO->gisType)) { //OSGB
  183. $result = $this->uploadOSGBModelByUrl($bimFileBO);
  184. } else { //普通BIM
  185. $result = $this->uploadModelByUrl($bimFileBO);
  186. }
  187. } else { //文件流方式
  188. if ($this->isPointCloudGISModel($bimFileBO->extension)) {
  189. $result = $this->uploadPointCloudModelByStream($file, $bimFileBO);
  190. } elseif ($this->isOSGBGISModel($bimFileBO->gisType)) {
  191. $result = $this->uploadOSGBModelByStream($file, bimFileBO: $bimFileBO);
  192. } else {
  193. $result = $this->uploadModelByStream($file, $bimFileBO);
  194. }
  195. }
  196. return [
  197. 'bim_data_set_id' => $result['datas']['lightweightName'],
  198. 'bim_file_id' => $result['datas']['lightweightName'],
  199. 'convert_status' => BimFileConvertStatus::IN_QUEUE->value,
  200. 'bim_driver' => BIMDriverEnum::GLENDALE->value,
  201. 'model_type' => $bimFileBO->modelType,
  202. ];
  203. } catch (\Throwable $th) {
  204. return ['error' => $th->getMessage()];
  205. }
  206. }
  207. public function downloadSourceFile()
  208. {
  209. // TODO: Implement downloadSourceFile() method.
  210. }
  211. public function findConvertStatus(string $dataSetId): array
  212. {
  213. $result = Client::getInstance()->post('/api/app/model/query-model-info', [
  214. 'query' => [
  215. 'LightweightName' => $dataSetId
  216. ]
  217. ]);
  218. $getStatus = function ($status) {
  219. if ($status >= 1 && $status <= 99) {
  220. return BimFileConvertStatus::CONVERTING->value;
  221. }
  222. if ($status <= 0) {
  223. return BimFileConvertStatus::FAILED_TO_ADD_QUEUE->value;
  224. }
  225. return BimFileConvertStatus::IN_QUEUE->value;
  226. };
  227. $status = match ($result['datas'][0]['status']) {
  228. 0, 1, 101 => BimFileConvertStatus::IN_QUEUE->value,
  229. 100 => BimFileConvertStatus::DONE->value,
  230. default => $getStatus($result['datas'][0]['status'])
  231. };
  232. return $this->convertStatusFormat($status, $result['datas'][0]['status']);
  233. }
  234. public function viewDataSetModel(array $dataSetIDS)
  235. {
  236. $result = Client::getInstance()->post('/api/app/model/query-model-info', [
  237. 'query' => [
  238. 'LightweightName' => $dataSetIDS[0]
  239. ]
  240. ]);
  241. return $result['datas'] ?? [];
  242. }
  243. /**
  244. * 获取某个模型信息
  245. * @param \App\Models\BimFile $bimFile
  246. * @return array
  247. */
  248. public function getModelDetail(BimFile $bimFile): array
  249. {
  250. $result = [];
  251. if (!$bimFile) {
  252. return $result;
  253. }
  254. if ($bimFile->model_type == BimFileModelType::GIS->value) {
  255. $result = Client::getInstance()->post('/api/app/gismodel/QueryModelInfo', [
  256. 'query' => [
  257. 'LightweightName' => $bimFile->bim_data_set_id
  258. ]
  259. ]);
  260. } else {
  261. $result = Client::getInstance()->post('/api/app/model/query-model-info', [
  262. 'query' => [
  263. 'LightweightName' => $bimFile->bim_data_set_id
  264. ]
  265. ]);
  266. }
  267. if (isset($result['datas'][0])) {
  268. $result = $result['datas'][0];
  269. }
  270. $result = $this->replaceUrlToHttps($result, ['modelAccessAddress', 'floorJsonURL']);
  271. return $result;
  272. }
  273. public function addToConvertQueue(string $dataSetId): array
  274. {
  275. return [];
  276. }
  277. /**
  278. * 获取模型多视图信息
  279. * @param string $lightweightName
  280. * @return array
  281. */
  282. public function getModel3DViews(string $lightweightName): array
  283. {
  284. $result = [];
  285. if (empty($lightweightName)) {
  286. return $result;
  287. }
  288. try {
  289. $res = Client::getInstance()->get('/api/app/model/model3DViews', [
  290. 'LightweightName' => $lightweightName
  291. ]);
  292. foreach ($res['datas'] as $data) {
  293. $result[] = $this->replaceUrlToHttps($data, ['accessAddress']);
  294. }
  295. } catch (\Throwable $th) {
  296. }
  297. return $result;
  298. }
  299. /**
  300. * 获取楼层节点下所有构件ID
  301. * @param string $lightweightName
  302. * @param string $glid
  303. * @return mixed
  304. */
  305. public function getFloorComponents(string $lightweightName, string $glid): array
  306. {
  307. $components = [];
  308. try {
  309. $res = Client::getInstance()->get('/api/app/model/GetModelTreeFeatureIdByPid', [
  310. 'LightweightName' => $lightweightName,
  311. 'Pid' => $glid,
  312. ]);
  313. $components = explode(',', $res['datas']);
  314. if (!$components || $res['datas'] == '') {
  315. $components = [];
  316. }
  317. } catch (\Throwable $th) {
  318. }
  319. return $components;
  320. }
  321. public function getAttributes(string $lightweightName, array $attributeIds)
  322. {
  323. try {
  324. $res = Client::getInstance()->get('api/app/model/property-data-by-externalid', [
  325. 'LightweightName' => $lightweightName,
  326. 'ExternalId' => implode(',', $attributeIds),
  327. ]);
  328. } catch (\Throwable $th) {
  329. return [];
  330. }
  331. return $res['datas'] ?? [];
  332. }
  333. /**
  334. * 获取有修改过的构件ID数组
  335. * @param array $conponentIds
  336. * @param array $attributes
  337. * @param array $newAttributes
  338. * @return array
  339. */
  340. public function getUpdatedComponentIds(array $conponentIds, array $attributes, array $newAttributes): array
  341. {
  342. $updatedIds = [];
  343. $attributes = collect($attributes);
  344. $newAttributes = collect($newAttributes);
  345. $attributesGroup = $attributes->groupBy('externalId');
  346. $newAttributesGroup = $newAttributes->groupBy('externalId');
  347. foreach ($conponentIds as $conponentId) {
  348. if (!isset($attributesGroup[$conponentId]) || !isset($newAttributesGroup[$conponentId])) {
  349. continue;
  350. }
  351. $conponents = $attributesGroup[$conponentId];
  352. $newConponents = $newAttributesGroup[$conponentId];
  353. if (!$conponents || !$newConponents) {
  354. continue;
  355. }
  356. if ($conponents->count() != $newConponents->count()) {
  357. $updatedIds[] = $conponentId;
  358. continue;
  359. }
  360. $fields = ['id', 'externalId', 'propertyTypeName', 'propertySetName', 'propertySetName', 'value', 'groupname'];
  361. $arr1 = [];
  362. $arr2 = [];
  363. $a = $conponents->sortBy('id');
  364. $b = $newConponents->sortBy('id');
  365. foreach ($a as $key => $value) {
  366. $arr1[] = Arr::only($value, $fields);
  367. }
  368. foreach ($b as $key => $value) {
  369. $arr2[] = Arr::only($value, $fields);
  370. }
  371. if (!array_are_equal($arr1, $arr2)) {
  372. $updatedIds[] = $conponentId;
  373. }
  374. }
  375. return $updatedIds;
  376. }
  377. /**
  378. * 把引擎数据同步过来
  379. * @param string $lightweightName
  380. * @return array|null
  381. */
  382. public function syncDB(string $lightweightName): array|null
  383. {
  384. $mysqlConfig = config('database.connections.mysql');
  385. $result = Client::getInstance()->post('/api/app/model/syncdbtodatabase', [
  386. 'query' => [
  387. 'LightweightName' => $lightweightName,
  388. 'DatabaseCategory' => 2, //1:SqlServer 2:MySql 3:DM8
  389. 'Server' => $mysqlConfig['host'],
  390. 'Database' => $mysqlConfig['database'],
  391. 'Uid' => $mysqlConfig['username'],
  392. 'PassWord' => $mysqlConfig['password'],
  393. 'Port' => $mysqlConfig['port'],
  394. 'DatabaseEngine' => 1, //数据库引擎,只针对Mysql, 0为MyISAM,1为InnoDB(阿里云服务器中引擎需要配置为InnoDB),默认值为0
  395. 'CallBackUrl' => route('glendale.sync-callback'),
  396. ]
  397. ]);
  398. return $result;
  399. }
  400. }