createVerticesFromGoogleEarthEnterpriseBuffer.js 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  1. /**
  2. * Cesium - https://github.com/CesiumGS/cesium
  3. *
  4. * Copyright 2011-2020 Cesium Contributors
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the "License");
  7. * you may not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. *
  18. * Columbus View (Pat. Pend.)
  19. *
  20. * Portions licensed separately.
  21. * See https://github.com/CesiumGS/cesium/blob/master/LICENSE.md for full licensing details.
  22. */
  23. define(['./when-8d13db60', './Check-70bec281', './Math-61ede240', './Cartographic-fe4be337', './Cartesian4-5af5bb24', './createTaskProcessorWorker', './Cartesian2-85064f09', './BoundingSphere-8f8a682c', './RuntimeError-ba10bc3e', './WebGLConstants-4c11ee5f', './ComponentDatatype-5862616f', './FeatureDetection-7bd32c34', './Transforms-878b6816', './buildModuleUrl-e7952659', './AttributeCompression-84a90a13', './IntersectionTests-ca40c01c', './Plane-b1361c67', './WebMercatorProjection-80c70558', './EllipsoidTangentPlane-0b4ce564', './OrientedBoundingBox-0ede1598', './TerrainEncoding-a807a704'], function (when, Check, _Math, Cartographic, Cartesian4, createTaskProcessorWorker, Cartesian2, BoundingSphere, RuntimeError, WebGLConstants, ComponentDatatype, FeatureDetection, Transforms, buildModuleUrl, AttributeCompression, IntersectionTests, Plane, WebMercatorProjection, EllipsoidTangentPlane, OrientedBoundingBox, TerrainEncoding) { 'use strict';
  24. var sizeOfUint16 = Uint16Array.BYTES_PER_ELEMENT;
  25. var sizeOfInt32 = Int32Array.BYTES_PER_ELEMENT;
  26. var sizeOfUint32 = Uint32Array.BYTES_PER_ELEMENT;
  27. var sizeOfFloat = Float32Array.BYTES_PER_ELEMENT;
  28. var sizeOfDouble = Float64Array.BYTES_PER_ELEMENT;
  29. function indexOfEpsilon(arr, elem, elemType) {
  30. elemType = when.defaultValue(elemType, _Math.CesiumMath);
  31. var count = arr.length;
  32. for (var i = 0; i < count; ++i) {
  33. if (elemType.equalsEpsilon(arr[i], elem, _Math.CesiumMath.EPSILON12)) {
  34. return i;
  35. }
  36. }
  37. return -1;
  38. }
  39. function createVerticesFromGoogleEarthEnterpriseBuffer(parameters, transferableObjects) {
  40. parameters.ellipsoid = Cartesian2.Ellipsoid.clone(parameters.ellipsoid);
  41. parameters.rectangle = Cartesian2.Rectangle.clone(parameters.rectangle);
  42. var statistics = processBuffer(parameters.buffer, parameters.relativeToCenter, parameters.ellipsoid,
  43. parameters.rectangle, parameters.nativeRectangle, parameters.exaggeration, parameters.skirtHeight,
  44. parameters.includeWebMercatorT, parameters.negativeAltitudeExponentBias, parameters.negativeElevationThreshold);
  45. var vertices = statistics.vertices;
  46. transferableObjects.push(vertices.buffer);
  47. var indices = statistics.indices;
  48. transferableObjects.push(indices.buffer);
  49. return {
  50. vertices : vertices.buffer,
  51. indices : indices.buffer,
  52. numberOfAttributes : statistics.encoding.getStride(),
  53. minimumHeight : statistics.minimumHeight,
  54. maximumHeight : statistics.maximumHeight,
  55. boundingSphere3D : statistics.boundingSphere3D,
  56. orientedBoundingBox : statistics.orientedBoundingBox,
  57. occludeePointInScaledSpace : statistics.occludeePointInScaledSpace,
  58. encoding : statistics.encoding,
  59. vertexCountWithoutSkirts : statistics.vertexCountWithoutSkirts,
  60. indexCountWithoutSkirts : statistics.indexCountWithoutSkirts,
  61. westIndicesSouthToNorth : statistics.westIndicesSouthToNorth,
  62. southIndicesEastToWest : statistics.southIndicesEastToWest,
  63. eastIndicesNorthToSouth : statistics.eastIndicesNorthToSouth,
  64. northIndicesWestToEast : statistics.northIndicesWestToEast
  65. };
  66. }
  67. var scratchCartographic = new Cartographic.Cartographic();
  68. var scratchCartesian = new Cartographic.Cartesian3();
  69. var minimumScratch = new Cartographic.Cartesian3();
  70. var maximumScratch = new Cartographic.Cartesian3();
  71. var matrix4Scratch = new BoundingSphere.Matrix4();
  72. function processBuffer(buffer, relativeToCenter, ellipsoid, rectangle, nativeRectangle, exaggeration, skirtHeight, includeWebMercatorT, negativeAltitudeExponentBias, negativeElevationThreshold) {
  73. var geographicWest;
  74. var geographicSouth;
  75. var geographicEast;
  76. var geographicNorth;
  77. var rectangleWidth, rectangleHeight;
  78. if (!when.defined(rectangle)) {
  79. geographicWest = _Math.CesiumMath.toRadians(nativeRectangle.west);
  80. geographicSouth = _Math.CesiumMath.toRadians(nativeRectangle.south);
  81. geographicEast = _Math.CesiumMath.toRadians(nativeRectangle.east);
  82. geographicNorth = _Math.CesiumMath.toRadians(nativeRectangle.north);
  83. rectangleWidth = _Math.CesiumMath.toRadians(rectangle.width);
  84. rectangleHeight = _Math.CesiumMath.toRadians(rectangle.height);
  85. } else {
  86. geographicWest = rectangle.west;
  87. geographicSouth = rectangle.south;
  88. geographicEast = rectangle.east;
  89. geographicNorth = rectangle.north;
  90. rectangleWidth = rectangle.width;
  91. rectangleHeight = rectangle.height;
  92. }
  93. // Keep track of quad borders so we can remove duplicates around the borders
  94. var quadBorderLatitudes = [geographicSouth, geographicNorth];
  95. var quadBorderLongitudes = [geographicWest, geographicEast];
  96. var fromENU = Transforms.Transforms.eastNorthUpToFixedFrame(relativeToCenter, ellipsoid);
  97. var toENU = BoundingSphere.Matrix4.inverseTransformation(fromENU, matrix4Scratch);
  98. var southMercatorY;
  99. var oneOverMercatorHeight;
  100. if (includeWebMercatorT) {
  101. southMercatorY = WebMercatorProjection.WebMercatorProjection.geodeticLatitudeToMercatorAngle(geographicSouth);
  102. oneOverMercatorHeight = 1.0 / (WebMercatorProjection.WebMercatorProjection.geodeticLatitudeToMercatorAngle(geographicNorth) - southMercatorY);
  103. }
  104. var dv = new DataView(buffer);
  105. var minHeight = Number.POSITIVE_INFINITY;
  106. var maxHeight = Number.NEGATIVE_INFINITY;
  107. var minimum = minimumScratch;
  108. minimum.x = Number.POSITIVE_INFINITY;
  109. minimum.y = Number.POSITIVE_INFINITY;
  110. minimum.z = Number.POSITIVE_INFINITY;
  111. var maximum = maximumScratch;
  112. maximum.x = Number.NEGATIVE_INFINITY;
  113. maximum.y = Number.NEGATIVE_INFINITY;
  114. maximum.z = Number.NEGATIVE_INFINITY;
  115. // Compute sizes
  116. var offset = 0;
  117. var size = 0;
  118. var indicesSize = 0;
  119. var quadSize;
  120. var quad;
  121. for (quad = 0; quad < 4; ++quad) {
  122. var o = offset;
  123. quadSize = dv.getUint32(o, true);
  124. o += sizeOfUint32;
  125. var x = _Math.CesiumMath.toRadians(dv.getFloat64(o, true) * 180.0);
  126. o += sizeOfDouble;
  127. if (indexOfEpsilon(quadBorderLongitudes, x) === -1) {
  128. quadBorderLongitudes.push(x);
  129. }
  130. var y = _Math.CesiumMath.toRadians(dv.getFloat64(o, true) * 180.0);
  131. o += sizeOfDouble;
  132. if (indexOfEpsilon(quadBorderLatitudes, y) === -1) {
  133. quadBorderLatitudes.push(y);
  134. }
  135. o += 2 * sizeOfDouble; // stepX + stepY
  136. var c = dv.getInt32(o, true); // Read point count
  137. o += sizeOfInt32;
  138. size += c;
  139. c = dv.getInt32(o, true); // Read index count
  140. indicesSize += c * 3;
  141. offset += quadSize + sizeOfUint32; // Jump to next quad
  142. }
  143. // Quad Border points to remove duplicates
  144. var quadBorderPoints = [];
  145. var quadBorderIndices = [];
  146. // Create arrays
  147. var positions = new Array(size);
  148. var uvs = new Array(size);
  149. var heights = new Array(size);
  150. var webMercatorTs = includeWebMercatorT ? new Array(size) : [];
  151. var indices = new Array(indicesSize);
  152. // Points are laid out in rows starting at SW, so storing border points as we
  153. // come across them all points will be adjacent.
  154. var westBorder = [];
  155. var southBorder = [];
  156. var eastBorder = [];
  157. var northBorder = [];
  158. // Each tile is split into 4 parts
  159. var pointOffset = 0;
  160. var indicesOffset = 0;
  161. offset = 0;
  162. for (quad = 0; quad < 4; ++quad) {
  163. quadSize = dv.getUint32(offset, true);
  164. offset += sizeOfUint32;
  165. var startQuad = offset;
  166. var originX = _Math.CesiumMath.toRadians(dv.getFloat64(offset, true) * 180.0);
  167. offset += sizeOfDouble;
  168. var originY = _Math.CesiumMath.toRadians(dv.getFloat64(offset, true) * 180.0);
  169. offset += sizeOfDouble;
  170. var stepX = _Math.CesiumMath.toRadians(dv.getFloat64(offset, true) * 180.0);
  171. var halfStepX = stepX * 0.5;
  172. offset += sizeOfDouble;
  173. var stepY = _Math.CesiumMath.toRadians(dv.getFloat64(offset, true) * 180.0);
  174. var halfStepY = stepY * 0.5;
  175. offset += sizeOfDouble;
  176. var numPoints = dv.getInt32(offset, true);
  177. offset += sizeOfInt32;
  178. var numFaces = dv.getInt32(offset, true);
  179. offset += sizeOfInt32;
  180. //var level = dv.getInt32(offset, true);
  181. offset += sizeOfInt32;
  182. // Keep track of quad indices to overall tile indices
  183. var indicesMapping = new Array(numPoints);
  184. for (var i = 0; i < numPoints; ++i) {
  185. var longitude = originX + dv.getUint8(offset++) * stepX;
  186. scratchCartographic.longitude = longitude;
  187. var latitude = originY + dv.getUint8(offset++) * stepY;
  188. scratchCartographic.latitude = latitude;
  189. var height = dv.getFloat32(offset, true);
  190. offset += sizeOfFloat;
  191. // In order to support old clients, negative altitude values are stored as
  192. // height/-2^32. Old clients see the value as really close to 0 but new clients multiply
  193. // by -2^32 to get the real negative altitude value.
  194. if (height !== 0 && height < negativeElevationThreshold) {
  195. height *= -Math.pow(2, negativeAltitudeExponentBias);
  196. }
  197. // Height is stored in units of (1/EarthRadius) or (1/6371010.0)
  198. height *= 6371010.0 * exaggeration;
  199. scratchCartographic.height = height;
  200. // Is it along a quad border - if so check if already exists and use that index
  201. if (indexOfEpsilon(quadBorderLongitudes, longitude) !== -1 ||
  202. indexOfEpsilon(quadBorderLatitudes, latitude) !== -1) {
  203. var index = indexOfEpsilon(quadBorderPoints, scratchCartographic, Cartographic.Cartographic);
  204. if (index === -1) {
  205. quadBorderPoints.push(Cartographic.Cartographic.clone(scratchCartographic));
  206. quadBorderIndices.push(pointOffset);
  207. } else {
  208. indicesMapping[i] = quadBorderIndices[index];
  209. continue;
  210. }
  211. }
  212. indicesMapping[i] = pointOffset;
  213. if (Math.abs(longitude - geographicWest) < halfStepX) {
  214. westBorder.push({
  215. index : pointOffset,
  216. cartographic : Cartographic.Cartographic.clone(scratchCartographic)
  217. });
  218. } else if (Math.abs(longitude - geographicEast) < halfStepX) {
  219. eastBorder.push({
  220. index : pointOffset,
  221. cartographic : Cartographic.Cartographic.clone(scratchCartographic)
  222. });
  223. } else if (Math.abs(latitude - geographicSouth) < halfStepY) {
  224. southBorder.push({
  225. index : pointOffset,
  226. cartographic : Cartographic.Cartographic.clone(scratchCartographic)
  227. });
  228. } else if (Math.abs(latitude - geographicNorth) < halfStepY) {
  229. northBorder.push({
  230. index : pointOffset,
  231. cartographic : Cartographic.Cartographic.clone(scratchCartographic)
  232. });
  233. }
  234. minHeight = Math.min(height, minHeight);
  235. maxHeight = Math.max(height, maxHeight);
  236. heights[pointOffset] = height;
  237. var pos = ellipsoid.cartographicToCartesian(scratchCartographic);
  238. positions[pointOffset] = pos;
  239. if (includeWebMercatorT) {
  240. webMercatorTs[pointOffset] = (WebMercatorProjection.WebMercatorProjection.geodeticLatitudeToMercatorAngle(latitude) - southMercatorY) * oneOverMercatorHeight;
  241. }
  242. BoundingSphere.Matrix4.multiplyByPoint(toENU, pos, scratchCartesian);
  243. Cartographic.Cartesian3.minimumByComponent(scratchCartesian, minimum, minimum);
  244. Cartographic.Cartesian3.maximumByComponent(scratchCartesian, maximum, maximum);
  245. var u = (longitude - geographicWest) / (geographicEast - geographicWest);
  246. u = _Math.CesiumMath.clamp(u, 0.0, 1.0);
  247. var v = (latitude - geographicSouth) / (geographicNorth - geographicSouth);
  248. v = _Math.CesiumMath.clamp(v, 0.0, 1.0);
  249. uvs[pointOffset] = new Cartesian2.Cartesian2(u, v);
  250. ++pointOffset;
  251. }
  252. var facesElementCount = numFaces * 3;
  253. for (var j = 0; j < facesElementCount; ++j, ++indicesOffset) {
  254. indices[indicesOffset] = indicesMapping[dv.getUint16(offset, true)];
  255. offset += sizeOfUint16;
  256. }
  257. if (quadSize !== (offset - startQuad)) {
  258. throw new RuntimeError.RuntimeError('Invalid terrain tile.');
  259. }
  260. }
  261. positions.length = pointOffset;
  262. uvs.length = pointOffset;
  263. heights.length = pointOffset;
  264. if (includeWebMercatorT) {
  265. webMercatorTs.length = pointOffset;
  266. }
  267. var vertexCountWithoutSkirts = pointOffset;
  268. var indexCountWithoutSkirts = indicesOffset;
  269. // Add skirt points
  270. var skirtOptions = {
  271. hMin : minHeight,
  272. lastBorderPoint : undefined,
  273. skirtHeight : skirtHeight,
  274. toENU : toENU,
  275. ellipsoid : ellipsoid,
  276. minimum : minimum,
  277. maximum : maximum
  278. };
  279. // Sort counter clockwise from NW corner
  280. // Corner points are in the east/west arrays
  281. westBorder.sort(function(a, b) {
  282. return b.cartographic.latitude - a.cartographic.latitude;
  283. });
  284. southBorder.sort(function(a, b) {
  285. return a.cartographic.longitude - b.cartographic.longitude;
  286. });
  287. eastBorder.sort(function(a, b) {
  288. return a.cartographic.latitude - b.cartographic.latitude;
  289. });
  290. northBorder.sort(function(a, b) {
  291. return b.cartographic.longitude - a.cartographic.longitude;
  292. });
  293. var percentage = 0.00001;
  294. addSkirt(positions, heights, uvs, webMercatorTs, indices, skirtOptions,
  295. westBorder, -percentage * rectangleWidth, true, -percentage * rectangleHeight);
  296. addSkirt(positions, heights, uvs, webMercatorTs, indices, skirtOptions,
  297. southBorder, -percentage * rectangleHeight, false);
  298. addSkirt(positions, heights, uvs, webMercatorTs, indices, skirtOptions,
  299. eastBorder, percentage * rectangleWidth, true, percentage * rectangleHeight);
  300. addSkirt(positions, heights, uvs, webMercatorTs, indices, skirtOptions,
  301. northBorder, percentage * rectangleHeight, false);
  302. // Since the corner between the north and west sides is in the west array, generate the last
  303. // two triangles between the last north vertex and the first west vertex
  304. if (westBorder.length > 0 && northBorder.length > 0) {
  305. var firstBorderIndex = westBorder[0].index;
  306. var firstSkirtIndex = vertexCountWithoutSkirts;
  307. var lastBorderIndex = northBorder[northBorder.length - 1].index;
  308. var lastSkirtIndex = positions.length - 1;
  309. indices.push(lastBorderIndex, lastSkirtIndex, firstSkirtIndex, firstSkirtIndex, firstBorderIndex, lastBorderIndex);
  310. }
  311. size = positions.length; // Get new size with skirt vertices
  312. var boundingSphere3D = BoundingSphere.BoundingSphere.fromPoints(positions);
  313. var orientedBoundingBox;
  314. if (when.defined(rectangle)) {
  315. orientedBoundingBox = OrientedBoundingBox.OrientedBoundingBox.fromRectangle(rectangle, minHeight, maxHeight, ellipsoid);
  316. }
  317. var occluder = new TerrainEncoding.EllipsoidalOccluder(ellipsoid);
  318. var occludeePointInScaledSpace = occluder.computeHorizonCullingPointPossiblyUnderEllipsoid(relativeToCenter, positions, minHeight);
  319. var aaBox = new EllipsoidTangentPlane.AxisAlignedBoundingBox(minimum, maximum, relativeToCenter);
  320. var encoding = new TerrainEncoding.TerrainEncoding(aaBox, skirtOptions.hMin, maxHeight, fromENU, false, includeWebMercatorT);
  321. var vertices = new Float32Array(size * encoding.getStride());
  322. var bufferIndex = 0;
  323. for (var k = 0; k < size; ++k) {
  324. bufferIndex = encoding.encode(vertices, bufferIndex, positions[k], uvs[k], heights[k], undefined, webMercatorTs[k]);
  325. }
  326. var westIndicesSouthToNorth = westBorder.map(function(vertex) { return vertex.index; }).reverse();
  327. var southIndicesEastToWest = southBorder.map(function(vertex) { return vertex.index; }).reverse();
  328. var eastIndicesNorthToSouth = eastBorder.map(function(vertex) { return vertex.index; }).reverse();
  329. var northIndicesWestToEast = northBorder.map(function(vertex) { return vertex.index; }).reverse();
  330. southIndicesEastToWest.unshift(eastIndicesNorthToSouth[eastIndicesNorthToSouth.length - 1]);
  331. southIndicesEastToWest.push(westIndicesSouthToNorth[0]);
  332. northIndicesWestToEast.unshift(westIndicesSouthToNorth[westIndicesSouthToNorth.length - 1]);
  333. northIndicesWestToEast.push(eastIndicesNorthToSouth[0]);
  334. return {
  335. vertices : vertices,
  336. indices : new Uint16Array(indices),
  337. maximumHeight : maxHeight,
  338. minimumHeight : minHeight,
  339. encoding : encoding,
  340. boundingSphere3D : boundingSphere3D,
  341. orientedBoundingBox : orientedBoundingBox,
  342. occludeePointInScaledSpace : occludeePointInScaledSpace,
  343. vertexCountWithoutSkirts : vertexCountWithoutSkirts,
  344. indexCountWithoutSkirts : indexCountWithoutSkirts,
  345. westIndicesSouthToNorth : westIndicesSouthToNorth,
  346. southIndicesEastToWest : southIndicesEastToWest,
  347. eastIndicesNorthToSouth : eastIndicesNorthToSouth,
  348. northIndicesWestToEast : northIndicesWestToEast
  349. };
  350. }
  351. function addSkirt(positions, heights, uvs, webMercatorTs, indices, skirtOptions,
  352. borderPoints, fudgeFactor, eastOrWest, cornerFudge) {
  353. var count = borderPoints.length;
  354. for (var j = 0; j < count; ++j) {
  355. var borderPoint = borderPoints[j];
  356. var borderCartographic = borderPoint.cartographic;
  357. var borderIndex = borderPoint.index;
  358. var currentIndex = positions.length;
  359. var longitude = borderCartographic.longitude;
  360. var latitude = borderCartographic.latitude;
  361. latitude = _Math.CesiumMath.clamp(latitude, -_Math.CesiumMath.PI_OVER_TWO, _Math.CesiumMath.PI_OVER_TWO); // Don't go over the poles
  362. var height = borderCartographic.height - skirtOptions.skirtHeight;
  363. skirtOptions.hMin = Math.min(skirtOptions.hMin, height);
  364. Cartographic.Cartographic.fromRadians(longitude, latitude, height, scratchCartographic);
  365. // Adjust sides to angle out
  366. if (eastOrWest) {
  367. scratchCartographic.longitude += fudgeFactor;
  368. }
  369. // Adjust top or bottom to angle out
  370. // Since corners are in the east/west arrays angle the first and last points as well
  371. if (!eastOrWest) {
  372. scratchCartographic.latitude += fudgeFactor;
  373. } else if (j === (count - 1)) {
  374. scratchCartographic.latitude += cornerFudge;
  375. } else if (j === 0) {
  376. scratchCartographic.latitude -= cornerFudge;
  377. }
  378. var pos = skirtOptions.ellipsoid.cartographicToCartesian(scratchCartographic);
  379. positions.push(pos);
  380. heights.push(height);
  381. uvs.push(Cartesian2.Cartesian2.clone(uvs[borderIndex])); // Copy UVs from border point
  382. if (webMercatorTs.length > 0) {
  383. webMercatorTs.push(webMercatorTs[borderIndex]);
  384. }
  385. BoundingSphere.Matrix4.multiplyByPoint(skirtOptions.toENU, pos, scratchCartesian);
  386. var minimum = skirtOptions.minimum;
  387. var maximum = skirtOptions.maximum;
  388. Cartographic.Cartesian3.minimumByComponent(scratchCartesian, minimum, minimum);
  389. Cartographic.Cartesian3.maximumByComponent(scratchCartesian, maximum, maximum);
  390. var lastBorderPoint = skirtOptions.lastBorderPoint;
  391. if (when.defined(lastBorderPoint)) {
  392. var lastBorderIndex = lastBorderPoint.index;
  393. indices.push(lastBorderIndex, currentIndex - 1, currentIndex, currentIndex, borderIndex, lastBorderIndex);
  394. }
  395. skirtOptions.lastBorderPoint = borderPoint;
  396. }
  397. }
  398. var createVerticesFromGoogleEarthEnterpriseBuffer$1 = createTaskProcessorWorker(createVerticesFromGoogleEarthEnterpriseBuffer);
  399. return createVerticesFromGoogleEarthEnterpriseBuffer$1;
  400. });