Glendale.php 15 KB

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