智慧水务管理系统 - 精河县供水工程综合管理平台

I3SSymbology.js 9.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. import Color from "../Core/Color.js";
  2. import defined from "../Core/defined.js";
  3. import srgbToLinear from "../Core/srgbToLinear.js";
  4. /**
  5. * This class implements an I3S symbology for I3S Layers.
  6. * <p>
  7. * Do not construct this directly, instead access symbology through {@link I3SLayer}.
  8. * </p>
  9. * @alias I3SSymbology
  10. * @internalConstructor
  11. */
  12. function I3SSymbology(layer) {
  13. this._layer = layer;
  14. this._defaultSymbology = undefined;
  15. this._valueFields = [];
  16. this._uniqueValueHash = undefined;
  17. this._classBreaksHash = undefined;
  18. this._parseLayerSymbology();
  19. }
  20. Object.defineProperties(I3SSymbology.prototype, {
  21. /**
  22. * Gets the default symbology data.
  23. * @memberof I3SSymbology.prototype
  24. * @type {object}
  25. * @readonly
  26. */
  27. defaultSymbology: {
  28. get: function () {
  29. return this._defaultSymbology;
  30. },
  31. },
  32. });
  33. function convertColor(color, transparency) {
  34. // color is represented as a three or four-element array, values range from 0 through 255.
  35. // transparency value has to lie between 100 (full transparency) and 0 (full opacity).
  36. const convertedColor = [];
  37. for (let i = 0; i < color.length; i++) {
  38. const floatColor = Color.byteToFloat(color[i]);
  39. if (i < 3) {
  40. convertedColor.push(srgbToLinear(floatColor));
  41. } else {
  42. convertedColor.push(floatColor);
  43. }
  44. }
  45. if (convertedColor.length === 3) {
  46. if (defined(transparency)) {
  47. convertedColor.push(1.0 - transparency / 100.0);
  48. } else {
  49. convertedColor.push(1.0);
  50. }
  51. }
  52. return convertedColor;
  53. }
  54. function parseSymbol(symbol, isColorCaptured) {
  55. const symbology = {
  56. edges: undefined,
  57. material: undefined,
  58. };
  59. if (defined(symbol) && defined(symbol.symbolLayers)) {
  60. for (let i = 0; i < symbol.symbolLayers.length; i++) {
  61. const symbolLayer = symbol.symbolLayers[i];
  62. if (symbolLayer.type === "Fill") {
  63. const edges = symbolLayer.edges;
  64. const outline = symbolLayer.outline;
  65. if (defined(edges)) {
  66. symbology.edges = {};
  67. if (defined(edges.color)) {
  68. symbology.edges.color = convertColor(
  69. edges.color,
  70. edges.transparency,
  71. );
  72. }
  73. } else if (defined(outline)) {
  74. symbology.edges = {};
  75. if (defined(outline.color)) {
  76. symbology.edges.color = convertColor(
  77. outline.color,
  78. outline.transparency,
  79. );
  80. }
  81. }
  82. if (!isColorCaptured) {
  83. const material = symbolLayer.material;
  84. if (defined(material)) {
  85. symbology.material = {
  86. colorMixMode: material.colorMixMode,
  87. };
  88. if (defined(material.color)) {
  89. symbology.material.color = convertColor(
  90. material.color,
  91. material.transparency,
  92. );
  93. }
  94. }
  95. }
  96. break;
  97. }
  98. }
  99. }
  100. return symbology;
  101. }
  102. function buildUniqueValueHash(renderer, isColorCaptured) {
  103. if (defined(renderer.uniqueValueGroups)) {
  104. const valueHash = {};
  105. for (
  106. let groupIndex = 0;
  107. groupIndex < renderer.uniqueValueGroups.length;
  108. groupIndex++
  109. ) {
  110. const classes = renderer.uniqueValueGroups[groupIndex].classes;
  111. if (defined(classes)) {
  112. for (let classIndex = 0; classIndex < classes.length; classIndex++) {
  113. const classSymbology = parseSymbol(
  114. classes[classIndex].symbol,
  115. isColorCaptured,
  116. );
  117. const values = classes[classIndex].values;
  118. for (let valueIndex = 0; valueIndex < values.length; valueIndex++) {
  119. const fieldValues = values[valueIndex];
  120. let hash = valueHash;
  121. for (
  122. let fieldIndex = 0;
  123. fieldIndex < fieldValues.length;
  124. fieldIndex++
  125. ) {
  126. const fieldValue = fieldValues[fieldIndex];
  127. if (fieldIndex === fieldValues.length - 1) {
  128. hash[fieldValue] = classSymbology;
  129. } else {
  130. if (!defined(hash[fieldValue])) {
  131. hash[fieldValue] = {};
  132. }
  133. hash = hash[fieldValue];
  134. }
  135. }
  136. }
  137. }
  138. }
  139. }
  140. return valueHash;
  141. }
  142. if (defined(renderer.uniqueValueInfos)) {
  143. const valueHash = {};
  144. for (
  145. let infoIndex = 0;
  146. infoIndex < renderer.uniqueValueInfos.length;
  147. infoIndex++
  148. ) {
  149. const info = renderer.uniqueValueInfos[infoIndex];
  150. valueHash[info.value] = parseSymbol(info.symbol, isColorCaptured);
  151. }
  152. return valueHash;
  153. }
  154. return undefined;
  155. }
  156. function buildClassBreaksHash(renderer, isColorCaptured) {
  157. if (defined(renderer.classBreakInfos)) {
  158. const classBreakInfos = [...renderer.classBreakInfos];
  159. classBreakInfos.sort(function (a, b) {
  160. const aMax = a.classMaxValue ?? a.classMinValue;
  161. const bMax = b.classMaxValue ?? b.classMinValue;
  162. return aMax - bMax;
  163. });
  164. const valueHash = {
  165. ranges: [],
  166. symbols: [],
  167. };
  168. if (defined(renderer.minValue)) {
  169. valueHash.ranges.push(renderer.minValue);
  170. valueHash.symbols.push(undefined);
  171. }
  172. for (let infoIndex = 0; infoIndex < classBreakInfos.length; infoIndex++) {
  173. const info = classBreakInfos[infoIndex];
  174. if (defined(info.classMinValue)) {
  175. if (
  176. valueHash.ranges.length === 0 ||
  177. info.classMinValue > valueHash.ranges[valueHash.ranges.length - 1]
  178. ) {
  179. valueHash.ranges.push(info.classMinValue);
  180. valueHash.symbols.push(undefined);
  181. }
  182. }
  183. if (defined(info.classMaxValue)) {
  184. if (
  185. valueHash.ranges.length === 0 ||
  186. info.classMaxValue > valueHash.ranges[valueHash.ranges.length - 1]
  187. ) {
  188. valueHash.ranges.push(info.classMaxValue);
  189. valueHash.symbols.push(parseSymbol(info.symbol, isColorCaptured));
  190. }
  191. }
  192. }
  193. valueHash.symbols.push(undefined);
  194. return valueHash;
  195. }
  196. return undefined;
  197. }
  198. /**
  199. * @private
  200. */
  201. I3SSymbology.prototype._parseLayerSymbology = function () {
  202. const drawingInfo = this._layer.data.drawingInfo;
  203. if (defined(drawingInfo) && defined(drawingInfo.renderer)) {
  204. const cachedDrawingInfo = this._layer.data.cachedDrawingInfo;
  205. const isColorCaptured =
  206. defined(cachedDrawingInfo) && cachedDrawingInfo.color === true;
  207. const renderer = drawingInfo.renderer;
  208. if (renderer.type === "simple") {
  209. this._defaultSymbology = parseSymbol(renderer.symbol, isColorCaptured);
  210. } else if (renderer.type === "uniqueValue") {
  211. this._defaultSymbology = parseSymbol(
  212. renderer.defaultSymbol,
  213. isColorCaptured,
  214. );
  215. this._valueFields.push(renderer.field1);
  216. if (defined(renderer.field2)) {
  217. this._valueFields.push(renderer.field2);
  218. }
  219. if (defined(renderer.field3)) {
  220. this._valueFields.push(renderer.field3);
  221. }
  222. this._uniqueValueHash = buildUniqueValueHash(renderer, isColorCaptured);
  223. } else if (renderer.type === "classBreaks") {
  224. this._defaultSymbology = parseSymbol(
  225. renderer.defaultSymbol,
  226. isColorCaptured,
  227. );
  228. this._valueFields.push(renderer.field);
  229. this._classBreaksHash = buildClassBreaksHash(renderer, isColorCaptured);
  230. }
  231. }
  232. };
  233. function findHashForUniqueValues(hash, values, hashLevel, valueIndex) {
  234. const levelValues = values[hashLevel];
  235. if (valueIndex < levelValues.length) {
  236. const hashValue = levelValues[valueIndex];
  237. const innerHash = hash[hashValue];
  238. if (defined(innerHash) && ++hashLevel < values.length) {
  239. return findHashForUniqueValues(innerHash, values, hashLevel, valueIndex);
  240. }
  241. return innerHash;
  242. }
  243. return undefined;
  244. }
  245. function bisect(array, value) {
  246. let low = 0;
  247. let high = array.length;
  248. if (low < high) {
  249. do {
  250. const mid = (low + high) >>> 1;
  251. if (array[mid] < value) {
  252. low = mid + 1;
  253. } else {
  254. high = mid;
  255. }
  256. } while (low < high);
  257. }
  258. return low;
  259. }
  260. function findHashForClassBreaks(hash, values, valueIndex) {
  261. const value = values[valueIndex];
  262. const range = bisect(hash.ranges, value);
  263. return hash.symbols[range];
  264. }
  265. /**
  266. * @private
  267. */
  268. I3SSymbology.prototype._getSymbology = async function (node) {
  269. const symbology = {
  270. default: this._defaultSymbology,
  271. };
  272. if (this._valueFields.length > 0) {
  273. const promises = [];
  274. for (let i = 0; i < this._valueFields.length; i++) {
  275. promises.push(node.loadField(this._valueFields[i]));
  276. }
  277. await Promise.all(promises);
  278. const fieldsValues = [];
  279. for (let i = 0; i < this._valueFields.length; i++) {
  280. fieldsValues.push(node.fields[this._valueFields[i]].values);
  281. }
  282. let featureHashFn;
  283. if (defined(this._uniqueValueHash)) {
  284. featureHashFn = (featureIndex) =>
  285. findHashForUniqueValues(
  286. this._uniqueValueHash,
  287. fieldsValues,
  288. 0,
  289. featureIndex,
  290. );
  291. } else if (defined(this._classBreaksHash)) {
  292. featureHashFn = (featureIndex) =>
  293. findHashForClassBreaks(
  294. this._classBreaksHash,
  295. fieldsValues[0],
  296. featureIndex,
  297. );
  298. }
  299. if (defined(featureHashFn)) {
  300. const firstFieldValues = fieldsValues[0];
  301. for (
  302. let featureIndex = 0;
  303. featureIndex < firstFieldValues.length;
  304. featureIndex++
  305. ) {
  306. const featureSymbology = featureHashFn(featureIndex);
  307. if (defined(featureSymbology)) {
  308. symbology[featureIndex] = featureSymbology;
  309. }
  310. }
  311. }
  312. }
  313. return symbology;
  314. };
  315. export default I3SSymbology;