dx.vectormaputils.debug.js 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652
  1. /*!
  2. * DevExtreme (dx.vectormaputils.debug.js)
  3. * Version: 19.1.16
  4. * Build date: Tue Oct 18 2022
  5. *
  6. * Copyright (c) 2012 - 2022 Developer Express Inc. ALL RIGHTS RESERVED
  7. * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
  8. */
  9. "use strict";
  10. ! function(root, factory) {
  11. if ("function" === typeof define && define.amd) {
  12. define(function(require, exports, module) {
  13. factory(exports)
  14. })
  15. } else {
  16. if ("object" === typeof module && module.exports) {
  17. factory(exports)
  18. } else {
  19. var exports = root.DevExpress = root.DevExpress || {};
  20. exports = exports.viz = exports.viz || {};
  21. exports = exports.vectormaputils = {};
  22. factory(exports)
  23. }
  24. }
  25. }(this, function(exports) {
  26. function noop() {}
  27. function eigen(x) {
  28. return x
  29. }
  30. function isFunction(target) {
  31. return "function" === typeof target
  32. }
  33. function wrapSource(source) {
  34. var stream, buffer = wrapBuffer(source),
  35. position = 0;
  36. stream = {
  37. pos: function() {
  38. return position
  39. },
  40. skip: function(count) {
  41. position += count;
  42. return stream
  43. },
  44. ui8arr: function(length) {
  45. var i = 0,
  46. list = [];
  47. list.length = length;
  48. for (; i < length; ++i) {
  49. list[i] = stream.ui8()
  50. }
  51. return list
  52. },
  53. ui8: function() {
  54. var val = ui8(buffer, position);
  55. position += 1;
  56. return val
  57. },
  58. ui16LE: function() {
  59. var val = ui16LE(buffer, position);
  60. position += 2;
  61. return val
  62. },
  63. ui32LE: function() {
  64. var val = ui32LE(buffer, position);
  65. position += 4;
  66. return val
  67. },
  68. ui32BE: function() {
  69. var val = ui32BE(buffer, position);
  70. position += 4;
  71. return val
  72. },
  73. f64LE: function() {
  74. var val = f64LE(buffer, position);
  75. position += 8;
  76. return val
  77. }
  78. };
  79. return stream
  80. }
  81. function parseCore(source, roundCoordinates, errors) {
  82. var result, shapeData = source[0] ? parseShape(wrapSource(source[0]), errors) : {},
  83. dataBaseFileData = source[1] ? parseDBF(wrapSource(source[1]), errors) : {},
  84. features = buildFeatures(shapeData.shapes || [], dataBaseFileData.records || [], roundCoordinates);
  85. if (features.length) {
  86. result = {
  87. type: "FeatureCollection",
  88. features: features
  89. };
  90. result.bbox = shapeData.bBox
  91. } else {
  92. result = null
  93. }
  94. return result
  95. }
  96. function buildFeatures(shapeData, dataBaseFileData, roundCoordinates) {
  97. var i, shape, features = [],
  98. ii = features.length = ii = Math.max(shapeData.length, dataBaseFileData.length);
  99. for (i = 0; i < ii; ++i) {
  100. shape = shapeData[i] || {};
  101. features[i] = {
  102. type: "Feature",
  103. geometry: {
  104. type: shape.geoJSON_type || null,
  105. coordinates: shape.coordinates ? roundCoordinates(shape.coordinates) : []
  106. },
  107. properties: dataBaseFileData[i] || null
  108. }
  109. }
  110. return features
  111. }
  112. function createCoordinatesRounder(precision) {
  113. var factor = Number("1E" + precision);
  114. function round(x) {
  115. return Math.round(x * factor) / factor
  116. }
  117. function process(values) {
  118. return values.map(values[0].length ? process : round)
  119. }
  120. return process
  121. }
  122. function buildParseArgs(source) {
  123. source = source || {};
  124. return ["shp", "dbf"].map(function(key) {
  125. return function(done) {
  126. if (source.substr) {
  127. key = "." + key;
  128. sendRequest(source + (source.substr(-key.length).toLowerCase() === key ? "" : key), function(e, response) {
  129. done(e, response)
  130. })
  131. } else {
  132. done(null, source[key] || null)
  133. }
  134. }
  135. })
  136. }
  137. function parse(source, parameters, callback) {
  138. var result;
  139. when(buildParseArgs(source), function(errorArray, dataArray) {
  140. callback = isFunction(parameters) && parameters || isFunction(callback) && callback || noop;
  141. parameters = !isFunction(parameters) && parameters || {};
  142. var errors = [];
  143. errorArray.forEach(function(e) {
  144. e && errors.push(e)
  145. });
  146. result = parseCore(dataArray, parameters.precision >= 0 ? createCoordinatesRounder(parameters.precision) : eigen, errors);
  147. callback(result, errors.length ? errors : null)
  148. });
  149. return result
  150. }
  151. exports.parse = parse;
  152. function when(actions, callback) {
  153. var errorArray = [],
  154. dataArray = [],
  155. counter = 1,
  156. lock = true;
  157. actions.forEach(function(action, i) {
  158. ++counter;
  159. action(function(e, data) {
  160. errorArray[i] = e;
  161. dataArray[i] = data;
  162. massDone()
  163. })
  164. });
  165. lock = false;
  166. massDone();
  167. function massDone() {
  168. --counter;
  169. if (0 === counter && !lock) {
  170. callback(errorArray, dataArray)
  171. }
  172. }
  173. }
  174. function parseShape(stream, errors) {
  175. var timeStart, timeEnd, header, record, records = [];
  176. try {
  177. timeStart = new Date;
  178. header = parseShapeHeader(stream)
  179. } catch (e) {
  180. errors.push("shp: header parsing error: " + e.message + " / " + e.description);
  181. return
  182. }
  183. if (9994 !== header.fileCode) {
  184. errors.push("shp: file code: " + header.fileCode + " / expected: 9994")
  185. }
  186. if (1e3 !== header.version) {
  187. errors.push("shp: file version: " + header.version + " / expected: 1000")
  188. }
  189. try {
  190. while (stream.pos() < header.fileLength) {
  191. record = parseShapeRecord(stream, header.type, errors);
  192. if (record) {
  193. records.push(record)
  194. } else {
  195. break
  196. }
  197. }
  198. if (stream.pos() !== header.fileLength) {
  199. errors.push("shp: file length: " + header.fileLength + " / actual: " + stream.pos())
  200. }
  201. timeEnd = new Date
  202. } catch (e) {
  203. errors.push("shp: records parsing error: " + e.message + " / " + e.description)
  204. }
  205. return {
  206. bBox: header.bBox_XY,
  207. type: header.shapeType,
  208. shapes: records,
  209. errors: errors,
  210. time: timeEnd - timeStart
  211. }
  212. }
  213. function readPointShape(stream, record) {
  214. record.coordinates = readPointArray(stream, 1)[0]
  215. }
  216. function readPolyLineShape(stream, record) {
  217. var i, bBox = readBBox(stream),
  218. numParts = readInteger(stream),
  219. numPoints = readInteger(stream),
  220. parts = readIntegerArray(stream, numParts),
  221. points = readPointArray(stream, numPoints),
  222. rings = [];
  223. rings.length = numParts;
  224. for (i = 0; i < numParts; ++i) {
  225. rings[i] = points.slice(parts[i], parts[i + 1] || numPoints)
  226. }
  227. record.bBox = bBox;
  228. record.coordinates = rings
  229. }
  230. function readMultiPointShape(stream, record) {
  231. record.bBox = readBBox(stream);
  232. record.coordinates = readPointArray(stream, readInteger(stream))
  233. }
  234. function readPointMShape(stream, record) {
  235. record.coordinates = readPointArray(stream, 1)[0];
  236. record.coordinates.push(readDoubleArray(stream, 1)[0])
  237. }
  238. function readMultiPointMShape(stream, record) {
  239. var bBox = readBBox(stream),
  240. numPoints = readInteger(stream),
  241. points = readPointArray(stream, numPoints),
  242. mBox = readPair(stream),
  243. mValues = readDoubleArray(stream, numPoints);
  244. record.bBox = bBox;
  245. record.mBox = mBox;
  246. record.coordinates = merge_XYM(points, mValues, numPoints)
  247. }
  248. function readPolyLineMShape(stream, record) {
  249. var i, from, to, bBox = readBBox(stream),
  250. numParts = readInteger(stream),
  251. numPoints = readInteger(stream),
  252. parts = readIntegerArray(stream, numParts),
  253. points = readPointArray(stream, numPoints),
  254. mBox = readPair(stream),
  255. mValues = readDoubleArray(stream, numPoints),
  256. rings = [];
  257. rings.length = numParts;
  258. for (i = 0; i < numParts; ++i) {
  259. from = parts[i];
  260. to = parts[i + 1] || numPoints;
  261. rings[i] = merge_XYM(points.slice(from, to), mValues.slice(from, to), to - from)
  262. }
  263. record.bBox = bBox;
  264. record.mBox = mBox;
  265. record.coordinates = rings
  266. }
  267. function readPointZShape(stream, record) {
  268. record.coordinates = readPointArray(stream, 1)[0];
  269. record.push(readDoubleArray(stream, 1)[0], readDoubleArray(stream, 1)[0])
  270. }
  271. function readMultiPointZShape(stream, record) {
  272. var bBox = readBBox(stream),
  273. numPoints = readInteger(stream),
  274. points = readPointArray(stream, numPoints),
  275. zBox = readPair(stream),
  276. zValues = readDoubleArray(stream, numPoints),
  277. mBox = readPair(stream),
  278. mValue = readDoubleArray(stream, numPoints);
  279. record.bBox = bBox;
  280. record.zBox = zBox;
  281. record.mBox = mBox;
  282. record.coordinates = merge_XYZM(points, zValues, mValue, numPoints)
  283. }
  284. function readPolyLineZShape(stream, record) {
  285. var i, from, to, bBox = readBBox(stream),
  286. numParts = readInteger(stream),
  287. numPoints = readInteger(stream),
  288. parts = readIntegerArray(stream, numParts),
  289. points = readPointArray(stream, numPoints),
  290. zBox = readPair(stream),
  291. zValues = readDoubleArray(stream, numPoints),
  292. mBox = readPair(stream),
  293. mValues = readDoubleArray(stream, numPoints),
  294. rings = [];
  295. rings.length = numParts;
  296. for (i = 0; i < numParts; ++i) {
  297. from = parts[i];
  298. to = parts[i + 1] || numPoints;
  299. rings[i] = merge_XYZM(points.slice(from, to), zValues.slice(from, to), mValues.slice(from, to), to - from)
  300. }
  301. record.bBox = bBox;
  302. record.zBox = zBox;
  303. record.mBox = mBox;
  304. record.coordinates = rings
  305. }
  306. function readMultiPatchShape(stream, record) {
  307. var i, from, to, bBox = readBBox(stream),
  308. numParts = readInteger(stream),
  309. numPoints = readInteger(stream),
  310. parts = readIntegerArray(stream, numParts),
  311. partTypes = readIntegerArray(stream, numParts),
  312. points = readPointArray(stream, numPoints),
  313. zBox = readPair(stream),
  314. zValues = readDoubleArray(stream, numPoints),
  315. mBox = readPair(stream),
  316. rings = [];
  317. rings.length = numParts;
  318. for (i = 0; i < numParts; ++i) {
  319. from = parts[i];
  320. to = parts[i + 1] || numPoints;
  321. rings[i] = merge_XYZM(points.slice(from, to), zValues.slice(from, to), mValues.slice(from, to), to - from)
  322. }
  323. record.bBox = bBox;
  324. record.zBox = zBox;
  325. record.mBox = mBox;
  326. record.types = partTypes;
  327. record.coordinates = rings
  328. }
  329. var SHP_TYPES = {
  330. 0: "Null",
  331. 1: "Point",
  332. 3: "PolyLine",
  333. 5: "Polygon",
  334. 8: "MultiPoint",
  335. 11: "PointZ",
  336. 13: "PolyLineZ",
  337. 15: "PolygonZ",
  338. 18: "MultiPointZ",
  339. 21: "PointM",
  340. 23: "PolyLineM",
  341. 25: "PolygonM",
  342. 28: "MultiPointM",
  343. 31: "MultiPatch"
  344. };
  345. var SHP_RECORD_PARSERS = {
  346. 0: noop,
  347. 1: readPointShape,
  348. 3: readPolyLineShape,
  349. 5: readPolyLineShape,
  350. 8: readMultiPointShape,
  351. 11: readPointZShape,
  352. 13: readPolyLineZShape,
  353. 15: readPolyLineZShape,
  354. 18: readMultiPointZShape,
  355. 21: readPointMShape,
  356. 23: readPolyLineMShape,
  357. 25: readPolyLineMShape,
  358. 28: readMultiPointMShape,
  359. 31: readMultiPatchShape
  360. };
  361. var SHP_TYPE_TO_GEOJSON_TYPE_MAP = {
  362. Null: "Null",
  363. Point: "Point",
  364. PolyLine: "MultiLineString",
  365. Polygon: "Polygon",
  366. MultiPoint: "MultiPoint",
  367. PointZ: "Point",
  368. PolyLineZ: "MultiLineString",
  369. PolygonZ: "Polygon",
  370. MultiPointZ: "MultiPoint",
  371. PointM: "Point",
  372. PolyLineM: "MultiLineString",
  373. PolygonM: "Polygon",
  374. MultiPointM: "MultiPoint",
  375. MultiPatch: "MultiPatch"
  376. };
  377. function parseShapeHeader(stream) {
  378. var header = {};
  379. header.fileCode = stream.ui32BE();
  380. stream.skip(20);
  381. header.fileLength = stream.ui32BE() << 1;
  382. header.version = stream.ui32LE();
  383. header.type_number = stream.ui32LE();
  384. header.type = SHP_TYPES[header.type_number];
  385. header.bBox_XY = readBBox(stream);
  386. header.bBox_ZM = readPointArray(stream, 2);
  387. return header
  388. }
  389. function readInteger(stream) {
  390. return stream.ui32LE()
  391. }
  392. function readIntegerArray(stream, length) {
  393. var i, array = [];
  394. array.length = length;
  395. for (i = 0; i < length; ++i) {
  396. array[i] = readInteger(stream)
  397. }
  398. return array
  399. }
  400. function readDoubleArray(stream, length) {
  401. var i, array = [];
  402. array.length = length;
  403. for (i = 0; i < length; ++i) {
  404. array[i] = stream.f64LE()
  405. }
  406. return array
  407. }
  408. function readBBox(stream) {
  409. return readDoubleArray(stream, 4)
  410. }
  411. function readPair(stream) {
  412. return [stream.f64LE(), stream.f64LE()]
  413. }
  414. function readPointArray(stream, count) {
  415. var i, points = [];
  416. points.length = count;
  417. for (i = 0; i < count; ++i) {
  418. points[i] = readPair(stream)
  419. }
  420. return points
  421. }
  422. function merge_XYM(xy, m, length) {
  423. var i, array = [];
  424. array.length = length;
  425. for (i = 0; i < length; ++i) {
  426. array[i] = [xy[i][0], xy[i][1], m[i]]
  427. }
  428. return array
  429. }
  430. function merge_XYZM(xy, z, m, length) {
  431. var i, array = [];
  432. array.length = length;
  433. for (i = 0; i < length; ++i) {
  434. array[i] = [xy[i][0], xy[i][1], z[i], m[i]]
  435. }
  436. return array
  437. }
  438. function parseShapeRecord(stream, generalType, errors) {
  439. var record = {
  440. number: stream.ui32BE()
  441. },
  442. length = stream.ui32BE() << 1,
  443. pos = stream.pos(),
  444. type = stream.ui32LE();
  445. record.type_number = type;
  446. record.type = SHP_TYPES[type];
  447. record.geoJSON_type = SHP_TYPE_TO_GEOJSON_TYPE_MAP[record.type];
  448. if (record.type) {
  449. if (record.type !== generalType) {
  450. errors.push("shp: shape #" + record.number + " type: " + record.type + " / expected: " + generalType)
  451. }
  452. SHP_RECORD_PARSERS[type](stream, record);
  453. pos = stream.pos() - pos;
  454. if (pos !== length) {
  455. errors.push("shp: shape #" + record.number + " length: " + length + " / actual: " + pos)
  456. }
  457. } else {
  458. errors.push("shp: shape #" + record.number + " type: " + type + " / unknown");
  459. record = null
  460. }
  461. return record
  462. }
  463. function parseDBF(stream, errors) {
  464. var timeStart, timeEnd, header, parseData, records;
  465. try {
  466. timeStart = new Date;
  467. header = parseDataBaseFileHeader(stream, errors);
  468. parseData = prepareDataBaseFileRecordParseData(header, errors);
  469. records = parseDataBaseFileRecords(stream, header.numberOfRecords, header.recordLength, parseData, errors);
  470. timeEnd = new Date
  471. } catch (e) {
  472. errors.push("dbf: parsing error: " + e.message + " / " + e.description)
  473. }
  474. return {
  475. records: records,
  476. errors: errors,
  477. time: timeEnd - timeStart
  478. }
  479. }
  480. function parseDataBaseFileHeader(stream, errors) {
  481. var i, term, header = {
  482. versionNumber: stream.ui8(),
  483. lastUpdate: new Date(1900 + stream.ui8(), stream.ui8() - 1, stream.ui8()),
  484. numberOfRecords: stream.ui32LE(),
  485. headerLength: stream.ui16LE(),
  486. recordLength: stream.ui16LE(),
  487. fields: []
  488. };
  489. stream.skip(20);
  490. for (i = (header.headerLength - stream.pos() - 1) / 32; i > 0; --i) {
  491. header.fields.push(parseFieldDescriptor(stream))
  492. }
  493. term = stream.ui8();
  494. if (13 !== term) {
  495. errors.push("dbf: header terminator: " + term + " / expected: 13")
  496. }
  497. return header
  498. }
  499. var _fromCharCode = String.fromCharCode;
  500. function getAsciiString(stream, length) {
  501. return _fromCharCode.apply(null, stream.ui8arr(length))
  502. }
  503. function parseFieldDescriptor(stream) {
  504. var desc = {
  505. name: getAsciiString(stream, 11).replace(/\0*$/gi, ""),
  506. type: _fromCharCode(stream.ui8()),
  507. length: stream.skip(4).ui8(),
  508. count: stream.ui8()
  509. };
  510. stream.skip(14);
  511. return desc
  512. }
  513. var DBF_FIELD_PARSERS = {
  514. C: function(stream, length) {
  515. var str = getAsciiString(stream, length);
  516. try {
  517. str = decodeURIComponent(escape(str))
  518. } catch (e) {}
  519. return str.trim()
  520. },
  521. N: function(stream, length) {
  522. var str = getAsciiString(stream, length);
  523. return parseFloat(str, 10)
  524. },
  525. D: function(stream, length) {
  526. var str = getAsciiString(stream, length);
  527. return new Date(str.substring(0, 4), str.substring(4, 6) - 1, str.substring(6, 8))
  528. }
  529. };
  530. function DBF_FIELD_PARSER_DEFAULT(stream, length) {
  531. stream.skip(length);
  532. return null
  533. }
  534. function prepareDataBaseFileRecordParseData(header, errors) {
  535. var item, field, list = [],
  536. i = 0,
  537. ii = header.fields.length,
  538. totalLength = 0;
  539. for (i = 0; i < ii; ++i) {
  540. field = header.fields[i];
  541. item = {
  542. name: field.name,
  543. parser: DBF_FIELD_PARSERS[field.type],
  544. length: field.length
  545. };
  546. if (!item.parser) {
  547. item.parser = DBF_FIELD_PARSER_DEFAULT;
  548. errors.push("dbf: field " + field.name + " type: " + field.type + " / unknown")
  549. }
  550. totalLength += field.length;
  551. list.push(item)
  552. }
  553. if (totalLength + 1 !== header.recordLength) {
  554. errors.push("dbf: record length: " + header.recordLength + " / actual: " + (totalLength + 1))
  555. }
  556. return list
  557. }
  558. function parseDataBaseFileRecords(stream, recordCount, recordLength, parseData, errors) {
  559. var i, j, pos, record, pd, jj = parseData.length,
  560. records = [];
  561. for (i = 0; i < recordCount; ++i) {
  562. record = {};
  563. pos = stream.pos();
  564. stream.skip(1);
  565. for (j = 0; j < jj; ++j) {
  566. pd = parseData[j];
  567. record[pd.name] = pd.parser(stream, pd.length)
  568. }
  569. pos = stream.pos() - pos;
  570. if (pos !== recordLength) {
  571. errors.push("dbf: record #" + (i + 1) + " length: " + recordLength + " / actual: " + pos)
  572. }
  573. records.push(record)
  574. }
  575. return records
  576. }
  577. function wrapBuffer(arrayBuffer) {
  578. return new DataView(arrayBuffer)
  579. }
  580. function ui8(stream, position) {
  581. return stream.getUint8(position)
  582. }
  583. function ui16LE(stream, position) {
  584. return stream.getUint16(position, true)
  585. }
  586. function ui32LE(stream, position) {
  587. return stream.getUint32(position, true)
  588. }
  589. function ui32BE(stream, position) {
  590. return stream.getUint32(position, false)
  591. }
  592. function f64LE(stream, position) {
  593. return stream.getFloat64(position, true)
  594. }
  595. function sendRequest(url, callback) {
  596. var request = new XMLHttpRequest;
  597. request.addEventListener("load", function() {
  598. callback(this.response ? null : this.statusText, this.response)
  599. });
  600. request.open("GET", url);
  601. request.responseType = "arraybuffer";
  602. request.setRequestHeader("X-Requested-With", "XMLHttpRequest");
  603. request.send(null)
  604. }
  605. });