SFengParser.ts 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  1. /*
  2. * *********************************************************************************************************************
  3. *
  4. * !!
  5. * .F88X
  6. * X8888Y
  7. * .}888888N;
  8. * i888888N; .:! .I$WI:
  9. * R888888I .'N88~ i8}+8Y&8"l8i$8>8W~'>W8}8]KW+8IIN"8&
  10. * .R888888I .;N8888~ .X8' "8I.!,/8" !%NY8`"8I8~~8>,88I
  11. * +888888N; .8888888Y "&&8Y.}8,
  12. * ./888888N; .R888888Y .'}~ .>}'.`+> i}! "i' +/' .'i~ !11,.:">, .~]! .i}i
  13. * ~888888%: .I888888l .]88~`1/iY88Ii+1'.R$8$8]"888888888> Y8$ W8E X8E W8888'188Il}Y88$*
  14. * 18888888 E8888881 .]W%8$`R8X'&8%++N8i,8N%N8+l8%` .}8N:.R$RE%N88N%N$K$R 188,FE$8%~Y88I
  15. * .E888888I .i8888888' .:$8I;88+`E8R:/8N,.>881.`$8E/1/]N8X.Y8N`"KF&&FK!'88*."88K./$88%RN888+~
  16. * 8888888I .,N888888~ ~88i"8W,!N8*.I88.}888%F,i$88"F88" 888:E8X.>88!i88>`888*.}Fl1]*}1YKi'
  17. * i888888N' I888Y ]88;/EX*IFKFK88X K8R .l8W 88Y ~88}'88E&%8W.X8N``]88!.$8K .:W8I
  18. * .i888888N; I8Y .&8$ .X88! i881.:%888>I88 ;88] +88+.';;;;:.Y88X 18N.,88l .+88/
  19. * .:R888888I
  20. * .&888888I Copyright (c) 2009-2020. 博锐尚格科技股份有限公司
  21. * ~8888'
  22. * .!88~ All rights reserved.
  23. *
  24. * *********************************************************************************************************************
  25. */
  26. import { SItemFactory, SParser } from "@persagy-web/big/lib";
  27. // @ts-ignore
  28. import fengmap from "fengmap";
  29. import { Space } from "@persagy-web/big/lib/types/floor/Space";
  30. import { Column } from "@persagy-web/big/lib/types/floor/Column";
  31. import { VirtualWall } from "@persagy-web/big/lib/types/floor/VirtualWall";
  32. import { Wall } from "@persagy-web/big/lib/types/floor/Wall";
  33. import Axios from "axios";
  34. /**
  35. * 蜂鸟数据解析器
  36. *
  37. */
  38. export class SFengParser extends SParser {
  39. /** typeId 对应的类型 */
  40. static typeIdMap = {
  41. 100000: "Pavement",
  42. 200000: "FrontagePavement",
  43. 900000: "AuxiliarySurface",
  44. 300000: "SolidWall",
  45. 300001: "GlassWall",
  46. 300003: "PartitionWall",
  47. 300002: "BearingColumn",
  48. 800000: "ParkingSpace",
  49. 200004: "StraightLadder",
  50. 200003: "Escalator",
  51. 200103: "UplinkOnly",
  52. 200203: "DownOnly",
  53. 200005: "Stairs",
  54. 200002: "Toilet",
  55. 200001: "EntranceAndExit",
  56. 200006: "Cashier",
  57. 200007: "ATM",
  58. 200017: "AlarmPoint",
  59. 200018: "DressModification",
  60. 200019: "JewelryRepair",
  61. 200020: "Checkroom",
  62. 200014: "InformationDesk",
  63. 200009: "PublicPhone",
  64. 200008: "ServiceCentre",
  65. 200010: "Exit",
  66. 200011: "CargoLift",
  67. 200012: "Lounge",
  68. 200013: "CarPark",
  69. 200015: "MotherBabyRoom",
  70. 200016: "VIP",
  71. 200021: "WheelchairAccessible",
  72. 170006: "StraightLadder",
  73. 170008: "UpEscalator",
  74. 170007: "DownEscalator",
  75. 170003: "Escalator",
  76. 170001: "Stairs",
  77. 110001: "EntranceAndExit",
  78. 100001: "Restroom",
  79. 100004: "MenRestroom",
  80. 100005: "WomenRestroom",
  81. 100007: "AccessibleToilet",
  82. 140002: "ServiceCentre",
  83. 170002: "CargoLift",
  84. 150010: "Lounge",
  85. 100003: "MotherBabyRoom",
  86. 140004: "VIP",
  87. 170005: "WheelchairAccessible",
  88. 120001: "CarPark",
  89. 120008: "ParkingExit",
  90. 120009: "ParkingEntrance",
  91. 120010: "ParkingExitAndEntrance",
  92. 300005: "SwitchingStation",
  93. 300006: "DistributionRoom",
  94. 300007: "StrongElectricWell",
  95. 300008: "WeakCurrentWell",
  96. 300009: "AirConditionerEngineRoom",
  97. 300010: "RefrigerationRoom",
  98. 300011: "FreshAirRoom",
  99. 300012: "CompressorRoom",
  100. 300013: "HeatSourceMachineRoom",
  101. 300014: "DomesticWaterPumpHouse",
  102. 300015: "HighLevelWaterTankRoom",
  103. 300016: "SewageTreatmentRoom",
  104. 300017: "FirePumpHouse",
  105. 300018: "WetAlarmValveChamber",
  106. 300019: "PreActionAlarmValveChamber",
  107. 300020: "AirSupplyRoom",
  108. 300021: "ExhaustFanRoom",
  109. 300022: "MakeUpAirRoom",
  110. 300023: "BusinessManagementOffice",
  111. 300024: "NetworkRoom",
  112. 300025: "Substation",
  113. 300026: "GeneratorRoom",
  114. 300027: "TrusteeshipRoom",
  115. 300028: "HuiyunMachineRoom",
  116. 300029: "AlarmValveChamber",
  117. 300030: "ReclaimedWaterMachineRoom",
  118. 300031: "FireControlRoom",
  119. 300032: "OilSeparator",
  120. 300033: "GasBoilerRoom",
  121. 300034: "GasMeterRoom",
  122. 300035: "ElevatorMachineRoom",
  123. 300036: "StaffRestaurant",
  124. 300037: "DryGarbageRoom",
  125. 300038: "WetGarbageRoom",
  126. 300039: "ExpansionWaterTankRoom",
  127. 200023: "MensBathroom",
  128. 200022: "WomensToilet"
  129. };
  130. /** 蜂鸟:底图应用名称 */
  131. appName: string = "";
  132. /** 当前蜂鸟 map 的 id */
  133. mapId: string = "1000423_";
  134. /** 蜂鸟 map 绑定 dom 的 id */
  135. domId: string = "";
  136. /** 蜂鸟:底图应用秘钥 */
  137. key: string = "";
  138. /** 底图服务器地址 */
  139. serverUrl: string = "./data/";
  140. /** 底图主题 */
  141. mapThemeURL: string = "./";
  142. /** 蜂鸟图 */
  143. private fmap: fengmap.FMMap;
  144. /** 属于空间类型 typeid */
  145. spaceType: number[] = [
  146. 100000,
  147. 200000,
  148. 900000,
  149. 800000,
  150. 200004,
  151. 200003,
  152. 200103,
  153. 200203,
  154. 200005,
  155. 200002,
  156. 200006,
  157. 200007,
  158. 200017,
  159. 200018,
  160. 200019,
  161. 200020,
  162. 200014,
  163. 200009,
  164. 200008,
  165. 200011,
  166. 200012,
  167. 200013,
  168. 200015,
  169. 200016,
  170. 200021,
  171. 300004,
  172. 300005,
  173. 300006,
  174. 300007,
  175. 300008,
  176. 300009,
  177. 300010,
  178. 300011,
  179. 300012,
  180. 300013,
  181. 300014,
  182. 300015,
  183. 300016,
  184. 300017,
  185. 300018,
  186. 300019,
  187. 300020,
  188. 300021,
  189. 300022,
  190. 300023,
  191. 300024,
  192. 300025,
  193. 300026,
  194. 300027,
  195. 300028,
  196. 300029,
  197. 300030,
  198. 300031,
  199. 300032,
  200. 300033,
  201. 300034,
  202. 300035,
  203. 300036,
  204. 300037,
  205. 300038,
  206. 300039,
  207. 200023,
  208. 200022
  209. ];
  210. /** 属于柱子类型的 typeid */
  211. columnType: number[] = [300002];
  212. /** 属于墙类型的 typeid */
  213. wallType: number[] = [300000, 300001];
  214. /** 属于虚拟墙类型的 typeid */
  215. virtualWallType: number[] = [200001, 110001, 200010];
  216. /** poi 类型 */
  217. poiList: number[] = [
  218. 170006,
  219. 170008,
  220. 170007,
  221. 170003,
  222. 170001,
  223. 100001,
  224. 100004,
  225. 100005,
  226. 100007,
  227. 140002,
  228. 170002,
  229. 150010,
  230. 100003,
  231. 140004,
  232. 170005,
  233. 120001,
  234. 120008,
  235. 120009,
  236. 120010
  237. ];
  238. /** 当前地图的楼层 list(gname to gid映射关系) */
  239. gnameToGid = {};
  240. /** 当前地图的楼层 list */
  241. floorList = [];
  242. /** 当前底图的主题数据 */
  243. mapTheme: any;
  244. /** 底图版本号 */
  245. version: number | null = null;
  246. /** 顶楼地址 img */
  247. frImg: string = "";
  248. /** 构造体 */
  249. constructor(
  250. domId: string,
  251. mapServerURL: string,
  252. key: string,
  253. appName: string,
  254. factory: SItemFactory,
  255. mapThemeURL: string
  256. ) {
  257. super(factory);
  258. this.domId = domId;
  259. this.key = key;
  260. this.serverUrl = mapServerURL;
  261. this.mapThemeURL = mapThemeURL;
  262. this.appName = appName;
  263. } // Constructor
  264. /**
  265. * 解析数据
  266. *
  267. * @param groupId 当前楼层((前台传入为 gname ))
  268. * @param _fn 查询成功回调函数(返回参数为 FloorData )
  269. */
  270. parseData(groupId: string, _fn: Function): void {
  271. let obj = {};
  272. // 切换至当前楼层才可查询
  273. this.fmap.focusGroupID = groupId;
  274. // 创建搜索分析对象
  275. let searchAnalyser = new fengmap.FMSearchAnalyser(this.fmap);
  276. // 创建搜索请求体对象
  277. let searchReq = new fengmap.FMSearchRequest();
  278. const minx = this.fmap.minX;
  279. const maxy = this.fmap.maxY;
  280. searchReq.groupID = groupId;
  281. searchReq.type = "Model";
  282. searchAnalyser.query(searchReq, (result: any) => {
  283. let spaces: Space[] = [],
  284. columns: Column[] = [],
  285. walls: Wall[] = [],
  286. virtualWall: VirtualWall[] = [],
  287. pList: any[] = [];
  288. result.forEach((t: any) => {
  289. if (t.target) {
  290. let type = t.typeID;
  291. if (t.target._data && t.target._data.vertices) {
  292. let arr = t.target._data.vertices,
  293. outline = [];
  294. for (let i = 0; i < arr.length - 1; i += 2) {
  295. outline.push({
  296. X: arr[i] - minx,
  297. Y: arr[i + 1] - maxy
  298. });
  299. }
  300. if (this.spaceType.indexOf(type) > -1) {
  301. spaces.push({
  302. // @ts-ignore
  303. OutLine: [outline],
  304. Name: t.target.name,
  305. Location: {
  306. // @ts-ignore
  307. Points: [this.getAverageVal([outline])]
  308. },
  309. Type: t.typeID,
  310. // @ts-ignore
  311. Tag: SFengParser.typeIdMap[t.typeID],
  312. SourceId: t.FID,
  313. Height: t.target.height
  314. });
  315. } else if (this.columnType.indexOf(type) > -1) {
  316. // @ts-ignore
  317. columns.push({ OutLine: [outline] });
  318. } else if (this.wallType.indexOf(type) > -1) {
  319. const hasHole =
  320. t.target._data.holes &&
  321. t.target._data.holes.length;
  322. let holes = [];
  323. if (hasHole) {
  324. let tempArr = t.target._data.holes;
  325. for (let j = 0; j < tempArr.length; j++) {
  326. let holeChild = [];
  327. for (
  328. let i = 0;
  329. i < tempArr[j].length - 1;
  330. i += 2
  331. ) {
  332. holeChild.push({
  333. X: tempArr[j][i] - minx,
  334. Y: tempArr[j][i + 1] - maxy
  335. });
  336. }
  337. holes.push(holeChild);
  338. }
  339. }
  340. // @ts-ignore
  341. walls.push({ OutLine: [outline], HasHole: hasHole, Holes: holes });
  342. } else if (this.virtualWallType.indexOf(type) > -1) {
  343. // @ts-ignore
  344. virtualWall.push({ OutLine: [outline] });
  345. }
  346. }
  347. if (this.poiList.indexOf(type) > -1) {
  348. pList.push({
  349. Name: t.target.name,
  350. Pos: {
  351. X: t.mapCoord.x - minx,
  352. Y: t.mapCoord.y - maxy
  353. },
  354. Type: t.typeID,
  355. // @ts-ignore
  356. Tag: SFengParser.typeIdMap[t.typeID],
  357. Height: t.target.height,
  358. SourceId: t.ID
  359. });
  360. }
  361. }
  362. });
  363. obj = {
  364. Spaces: spaces,
  365. Columns: columns,
  366. Walls: walls,
  367. VirtualWalls: virtualWall,
  368. PList: pList
  369. };
  370. _fn(obj);
  371. });
  372. } // Function parseData()
  373. /**
  374. * 加载底图
  375. *
  376. * @param mapId 蜂鸟地图 id
  377. * @param _fn load 成功回调
  378. */
  379. loadMap(mapId: string, _fn: Function): void {
  380. this.fmap = new fengmap.FMMap({
  381. container: document.getElementById(this.domId),
  382. mapServerURL: this.serverUrl,
  383. appName: this.appName,
  384. key: this.key,
  385. mapThemeURL: this.mapThemeURL,
  386. defaultThemeName: mapId
  387. });
  388. this.fmap.openMapById(mapId, (err: any): void => {
  389. console.log("错误信息", err);
  390. });
  391. this.fmap.on("loadComplete", (): void => {
  392. if (this.mapId != mapId) {
  393. this.mapId = mapId;
  394. this.gnameToGid = {};
  395. this.floorList = [];
  396. // @ts-ignore
  397. this.fmap.listGroups.forEach(t => {
  398. // @ts-ignore
  399. this.gnameToGid[t.gname] = t.gid;
  400. // @ts-ignore
  401. this.floorList.push(t);
  402. });
  403. }
  404. _fn(this.gnameToGid, this.floorList);
  405. });
  406. } // Function loadMap()
  407. /**
  408. * 加载主题文件
  409. *
  410. * @param url 主题文件 url
  411. * @return promise promise 对象
  412. */
  413. loadTheme(url: string): Promise<void> {
  414. return new Promise((resolve, reject): void => {
  415. Axios({
  416. method: "get",
  417. url: url
  418. })
  419. .then((res: any) => {
  420. this.mapTheme = res.data;
  421. let data = res.data.storetheme;
  422. this.frImg = data[data.length - 1].image;
  423. // @ts-ignore
  424. resolve(this.frImg);
  425. })
  426. .catch((res: any) => {
  427. console.log(res);
  428. });
  429. });
  430. } // Function loadTheme()
  431. /**
  432. * 加载楼层地板
  433. *
  434. * @param groupId
  435. * @param _fn
  436. */
  437. loadFloor(groupId: string, _fn: Function): any {
  438. const minx = this.fmap.minX;
  439. const maxy = this.fmap.maxY;
  440. this.fmap.getDatasByAlias(Number(groupId), "extent", (res: any) => {
  441. let index = res.gdata.geo.indexOf("(");
  442. let str = res.gdata.geo.substring(index);
  443. str = str.replace(/\(/g, "[");
  444. str = str.replace(/\)/g, "]");
  445. str = str.replace(/\s/g, ",");
  446. const arr = JSON.parse(str);
  447. const aaa = [];
  448. for (let i = 0; i < arr.length; i++) {
  449. let a = arr[i];
  450. const bbb = [];
  451. for (let j = 0; j < a.length; j++) {
  452. let b = a[j];
  453. const ccc = [];
  454. for (let k = 0; k < b.length - 1; k += 2) {
  455. ccc.push({
  456. X: b[k] - minx,
  457. Y: b[k + 1] - maxy
  458. });
  459. }
  460. bbb.push(ccc);
  461. }
  462. aaa.push(bbb);
  463. }
  464. _fn({ OutLine: aaa });
  465. });
  466. } // Function loadFloor()
  467. /**
  468. * 计算平均值
  469. *
  470. * @param Outline 轮廓线束
  471. * @return object {X:X,Y:Y} x 的平均值, y 的平均值
  472. */
  473. private getAverageVal(Outline: { X: number; Y: number }[][]): object {
  474. let X = 0,
  475. Y = 0,
  476. len = Outline[0].length;
  477. Outline[0].map(item => {
  478. X += item.X;
  479. Y += item.Y;
  480. });
  481. X = Number((X / len).toFixed(2));
  482. Y = Number((Y / len).toFixed(2));
  483. return {
  484. X: X,
  485. Y: Y
  486. };
  487. }
  488. }