bruce-models 4.6.4 → 4.6.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2208,129 +2208,6 @@ var Color;
2208
2208
  Color.ColorFromStr = ColorFromStr;
2209
2209
  })(Color || (Color = {}));
2210
2210
 
2211
- /**
2212
- * Describes vector geometry that Bruce uses.
2213
- */
2214
- var Geometry;
2215
- (function (Geometry) {
2216
- let EPolygonRingType;
2217
- (function (EPolygonRingType) {
2218
- EPolygonRingType["Boundaries"] = "out";
2219
- EPolygonRingType["Hole"] = "in";
2220
- })(EPolygonRingType = Geometry.EPolygonRingType || (Geometry.EPolygonRingType = {}));
2221
- /**
2222
- * Turns an array of points into string vector geometry that Bruce can use.
2223
- * This is used for saving polyline and polygon data.
2224
- * @param points
2225
- * @returns
2226
- */
2227
- function LineStrFromPoints(points) {
2228
- if (!points.length) {
2229
- throw ("points is empty.");
2230
- }
2231
- let carto = points[0];
2232
- let lineString = `${carto.longitude},${carto.latitude}` + (carto.altitude != null ? `,${carto.altitude}` : "");
2233
- for (let i = 1; i < points.length; i++) {
2234
- carto = points[i];
2235
- lineString += ` ${carto.longitude},${carto.latitude}` + (carto.altitude != null ? `,${carto.altitude}` : "");
2236
- }
2237
- return lineString;
2238
- }
2239
- Geometry.LineStrFromPoints = LineStrFromPoints;
2240
- /**
2241
- * Removes same points that occur in a row.
2242
- * This will not modify the original array.
2243
- * @param positions
2244
- * @returns
2245
- */
2246
- function RemoveRepeatPoints(positions) {
2247
- const filteredList = [];
2248
- for (let i = 0; i < positions.length; i++) {
2249
- const pos = positions[i];
2250
- const lastPos = filteredList.length > 0 ? filteredList[filteredList.length - 1] : null;
2251
- if (!lastPos || (pos.latitude != lastPos.latitude || pos.longitude != lastPos.longitude || pos.altitude != lastPos.altitude)) {
2252
- filteredList.push(pos);
2253
- }
2254
- }
2255
- return filteredList;
2256
- }
2257
- Geometry.RemoveRepeatPoints = RemoveRepeatPoints;
2258
- /**
2259
- * Parses a string of points into an array of points.
2260
- * @param pointsStr
2261
- * @returns
2262
- */
2263
- function ParsePoints(pointsStr) {
2264
- pointsStr = pointsStr.replace(/[^\d.,-\s]/g, "");
2265
- let splitterCoordinates = " ";
2266
- let splitterAxis = ",";
2267
- const commaIndex = pointsStr.indexOf(",");
2268
- const spaceIndex = pointsStr.indexOf(" ");
2269
- if ((spaceIndex > -1 && commaIndex > spaceIndex) || commaIndex <= -1) {
2270
- splitterCoordinates = ",";
2271
- splitterAxis = " ";
2272
- }
2273
- let points = pointsStr.trim().split(splitterCoordinates);
2274
- points = points.filter(a => a != "");
2275
- const result = [];
2276
- for (let i = 0; i < points.length; i++) {
2277
- const pointData = points[i];
2278
- const coords = pointData.trim().split(splitterAxis);
2279
- if (coords.length == 2 || coords.length == 3) {
2280
- const longitude = Number(coords[0]);
2281
- const latitude = Number(coords[1]);
2282
- const altitude = Number(coords.length >= 3 ? coords[2] : 0);
2283
- if (longitude != null && latitude != null) {
2284
- result.push({
2285
- altitude: altitude,
2286
- latitude: latitude,
2287
- longitude: longitude
2288
- });
2289
- }
2290
- else {
2291
- console.warn("Invalid point data detected.", pointData);
2292
- }
2293
- }
2294
- }
2295
- return result;
2296
- }
2297
- Geometry.ParsePoints = ParsePoints;
2298
- /**
2299
- * Parses both string and object Bruce geometry.
2300
- * String geometry is legacy Bruce data.
2301
- * @param geometry
2302
- * @returns
2303
- */
2304
- function ParseGeometry(geometry) {
2305
- if (typeof geometry == "string") {
2306
- let positions = [];
2307
- const geometryParsed = (geometry || "").split(";");
2308
- for (let i = 0; i < geometryParsed.length; i++) {
2309
- const data = geometryParsed[i];
2310
- const points = ParsePoints(data);
2311
- if (points && points.length > 0) {
2312
- positions = positions.concat(points);
2313
- }
2314
- }
2315
- positions = RemoveRepeatPoints(positions);
2316
- const newGeometry = {};
2317
- if (positions.length > 0) {
2318
- const topPoint = positions[0];
2319
- newGeometry.Point = `${topPoint.latitude},${topPoint.longitude}` + (topPoint.altitude != null ? `,${topPoint.altitude}` : "");
2320
- if (positions.length > 1) {
2321
- newGeometry.Polygon = [{ Facing: EPolygonRingType.Boundaries, LinearRing: LineStrFromPoints(positions) }];
2322
- }
2323
- if (positions.length > 2) {
2324
- newGeometry.LineString = LineStrFromPoints(positions);
2325
- }
2326
- }
2327
- return newGeometry;
2328
- }
2329
- return geometry;
2330
- }
2331
- Geometry.ParseGeometry = ParseGeometry;
2332
- })(Geometry || (Geometry = {}));
2333
-
2334
2211
  var ObjectUtils;
2335
2212
  (function (ObjectUtils) {
2336
2213
  const DEFAULT_LENGTH = 36;
@@ -2966,28 +2843,6 @@ var PathUtils;
2966
2843
  PathUtils.ParseLegacy = ParseLegacy;
2967
2844
  })(PathUtils || (PathUtils = {}));
2968
2845
 
2969
- /**
2970
- * Describes an expectation on what should be rendered for a menu item-
2971
- * between a min-max distance of an entity to the camera.
2972
- */
2973
- var ZoomControl;
2974
- (function (ZoomControl) {
2975
- /**
2976
- * Available display types for a menu item.
2977
- */
2978
- let EDisplayType;
2979
- (function (EDisplayType) {
2980
- // Hidden means it will not be rendered.
2981
- EDisplayType["Hidden"] = "hidden";
2982
- // Point will try render a point based on any available Entity data.
2983
- EDisplayType["Point"] = "point";
2984
- // Geometry means it will try render multi-geometry, polygon, polyline, or point in order of priority.
2985
- EDisplayType["Geometry"] = "geometry";
2986
- // 3D means it will try render 3D model, multi-geometry, polygon, polyline, or point in order of priority.
2987
- EDisplayType["Model3D"] = "3d";
2988
- })(EDisplayType = ZoomControl.EDisplayType || (ZoomControl.EDisplayType = {}));
2989
- })(ZoomControl || (ZoomControl = {}));
2990
-
2991
2846
  var EntityHistoricData;
2992
2847
  (function (EntityHistoricData) {
2993
2848
  /**
@@ -3946,132 +3801,6 @@ var Entity;
3946
3801
  return Object.assign(Object.assign({}, baseEntity), { "Bruce": bruce });
3947
3802
  }
3948
3803
  Entity.Assert = Assert;
3949
- /**
3950
- * Helper method that returns a geojson object for a given set of Entities.
3951
- * @param params
3952
- * @returns
3953
- */
3954
- function ToGeoJson(params) {
3955
- const { entities, excludeAltitude, altitude, includeUserData, allowedDisplayTypes } = params;
3956
- const features = [];
3957
- const allowPoint = allowedDisplayTypes == null || allowedDisplayTypes.includes(ZoomControl.EDisplayType.Point);
3958
- const allowGeometry = allowedDisplayTypes == null || allowedDisplayTypes.includes(ZoomControl.EDisplayType.Geometry);
3959
- const cloneObj = (obj) => {
3960
- return JSON.parse(JSON.stringify(obj));
3961
- };
3962
- const areCoordinatesEqual = (coord1, coord2) => {
3963
- return coord1[0] === coord2[0] && coord1[1] === coord2[1] && (coord1[2] === coord2[2] || (coord1.length < 3 && coord2.length < 3));
3964
- };
3965
- const removeConsecutiveDuplicates = (coordinates) => {
3966
- return coordinates.filter((coord, index, array) => {
3967
- return index === 0 || !areCoordinatesEqual(coord, array[index - 1]);
3968
- });
3969
- };
3970
- const closePolygonCoordinates = (coordinates) => {
3971
- if (coordinates.length > 0 && !areCoordinatesEqual(coordinates[0], coordinates[coordinates.length - 1])) {
3972
- const firstPointCopy = [...coordinates[0]];
3973
- coordinates.push(firstPointCopy);
3974
- }
3975
- return coordinates;
3976
- };
3977
- const populateProperties = (feature, entity) => {
3978
- let properties = null;
3979
- // All properties.
3980
- if (includeUserData != false) {
3981
- properties = cloneObj(entity);
3982
- // The GeoJSON is supposed to represent the geometry attribute.
3983
- delete properties.Bruce.VectorGeometry;
3984
- delete properties.Bruce.Boundaries;
3985
- }
3986
- // Only specific internal properties.
3987
- else {
3988
- const bClone = cloneObj(entity.Bruce);
3989
- // The GeoJSON is supposed to represent the geometry attribute.
3990
- delete bClone.VectorGeometry;
3991
- delete bClone.Boundaries;
3992
- properties = {
3993
- Bruce: bClone
3994
- };
3995
- }
3996
- feature.properties = properties;
3997
- };
3998
- const processGeometry = (geometry, entity) => {
3999
- var _a, _b;
4000
- const feature = {
4001
- type: "Feature",
4002
- properties: {},
4003
- geometry: null
4004
- };
4005
- populateProperties(feature, entity);
4006
- if (((_a = geometry.MultiGeometry) === null || _a === void 0 ? void 0 : _a.length) && allowGeometry) {
4007
- geometry.MultiGeometry.forEach(geo => processGeometry(geo, entity));
4008
- return;
4009
- }
4010
- else if (((_b = geometry.Polygon) === null || _b === void 0 ? void 0 : _b.length) && allowGeometry) {
4011
- const sortedPolygons = geometry.Polygon.sort((a, b) => a.Facing === Geometry.EPolygonRingType.Boundaries ? -1 : 1);
4012
- const coordinates = sortedPolygons.map(polygonRing => closePolygonCoordinates(removeConsecutiveDuplicates(polygonRing.LinearRing.split(' ').map(coord => {
4013
- const [lon, lat, alt] = coord.split(',').map(Number);
4014
- return excludeAltitude ? [lon, lat] : [lon, lat, altitude !== undefined ? altitude : (alt !== undefined ? alt : [])];
4015
- }))));
4016
- // Check if the polygon has at least 4 points.
4017
- const isValidPolygon = coordinates.every(polygon => polygon.length >= 4);
4018
- if (!isValidPolygon) {
4019
- // Perhaps try other geometry instead of returning?
4020
- return;
4021
- }
4022
- feature.geometry = {
4023
- type: "Polygon",
4024
- coordinates: coordinates,
4025
- };
4026
- }
4027
- else if (geometry.LineString && (allowedDisplayTypes == null || allowedDisplayTypes.includes(ZoomControl.EDisplayType.Geometry))) {
4028
- const coordinates = removeConsecutiveDuplicates(geometry.LineString.split(' ').map(coord => {
4029
- const [lon, lat, alt] = coord.split(',').map(Number);
4030
- return excludeAltitude ? [lon, lat] : [lon, lat, altitude !== undefined ? altitude : (alt !== undefined ? alt : [])];
4031
- }));
4032
- // Check if the polyline has at least 2 points.
4033
- if (coordinates.length < 2) {
4034
- // Perhaps try other geometry instead of returning?
4035
- return;
4036
- }
4037
- feature.geometry = {
4038
- type: "LineString",
4039
- coordinates,
4040
- };
4041
- }
4042
- else if (geometry.Point && allowPoint) {
4043
- const [lon, lat, alt] = geometry.Point.split(',').map(Number);
4044
- const coordinates = excludeAltitude ? [lon, lat] : [lon, lat, altitude !== undefined ? altitude : (alt !== undefined ? alt : [])];
4045
- feature.geometry = {
4046
- type: "Point",
4047
- coordinates,
4048
- };
4049
- }
4050
- if (feature.geometry) {
4051
- features.push(feature);
4052
- }
4053
- };
4054
- entities.forEach(entity => {
4055
- var _a, _b, _c;
4056
- if (!((_a = entity === null || entity === void 0 ? void 0 : entity.Bruce) === null || _a === void 0 ? void 0 : _a.ID)) {
4057
- return;
4058
- }
4059
- let geometry = entity.Bruce.VectorGeometry;
4060
- if (!geometry && (((_b = entity.Bruce.Location) === null || _b === void 0 ? void 0 : _b.longitude) && ((_c = entity.Bruce.Location) === null || _c === void 0 ? void 0 : _c.latitude))) {
4061
- geometry = {
4062
- Point: `${entity.Bruce.Location.longitude},${entity.Bruce.Location.latitude}` + (entity.Bruce.Location.altitude != null ? `,${entity.Bruce.Location.altitude}` : ""),
4063
- };
4064
- }
4065
- if (geometry) {
4066
- processGeometry(geometry, entity);
4067
- }
4068
- });
4069
- return {
4070
- type: "FeatureCollection",
4071
- features,
4072
- };
4073
- }
4074
- Entity.ToGeoJson = ToGeoJson;
4075
3804
  /**
4076
3805
  * Returns cache identifier for an entity record.
4077
3806
  * Example: {
@@ -4213,12 +3942,12 @@ function parseLegacyPath(path) {
4213
3942
  path = path.replace("${", "");
4214
3943
  path = path.replace("}", "");
4215
3944
  }
3945
+ // Split by backslashes.
3946
+ paths.push(PathUtils.Parse(path));
4216
3947
  // Split by dots.
4217
3948
  paths.push(PathUtils.ParseLegacy(path));
4218
3949
  // Take string as is.
4219
3950
  paths.push([path]);
4220
- // Split by backslashes.
4221
- paths.push(PathUtils.Parse(path));
4222
3951
  // Remove duplicates.
4223
3952
  const tmpPaths = [];
4224
3953
  for (let i = 0; i < paths.length; i++) {
@@ -4512,11 +4241,17 @@ var Calculator;
4512
4241
  entity: entity,
4513
4242
  path: attrPath
4514
4243
  });
4515
- const isValueNum = !isNaN(+eValue);
4244
+ let isValueNum = !isNaN(+eValue);
4245
+ if (eValue == null) {
4246
+ isValueNum = false;
4247
+ }
4516
4248
  for (let i = 0; i < value.values.length; i++) {
4517
4249
  const option = value.values[i];
4518
4250
  const mapValue = option.fieldValue;
4519
- const isMapValueNum = !isNaN(+mapValue);
4251
+ let isMapValueNum = !isNaN(+mapValue);
4252
+ if (isMapValueNum == null) {
4253
+ isMapValueNum = false;
4254
+ }
4520
4255
  if (isValueNum && (isMapValueNum || mapValue.includes("-"))) {
4521
4256
  if (+mapValue == +eValue) {
4522
4257
  return option.appliedValue;
@@ -4647,6 +4382,474 @@ var Calculator;
4647
4382
  Calculator.GetInputValue = GetInputValue;
4648
4383
  })(Calculator || (Calculator = {}));
4649
4384
 
4385
+ /**
4386
+ * GeoJSON data structures.
4387
+ */
4388
+ var GeoJson;
4389
+ (function (GeoJson) {
4390
+ let EType;
4391
+ (function (EType) {
4392
+ EType["Point"] = "Point";
4393
+ EType["MultiPoint"] = "MultiPoint";
4394
+ EType["LineString"] = "LineString";
4395
+ EType["MultiLineString"] = "MultiLineString";
4396
+ EType["Polygon"] = "Polygon";
4397
+ EType["MultiPolygon"] = "MultiPolygon";
4398
+ EType["GeometryCollection"] = "GeometryCollection";
4399
+ EType["Feature"] = "Feature";
4400
+ EType["FeatureCollection"] = "FeatureCollection";
4401
+ })(EType = GeoJson.EType || (GeoJson.EType = {}));
4402
+ })(GeoJson || (GeoJson = {}));
4403
+
4404
+ /**
4405
+ * Describes vector geometry that Bruce uses.
4406
+ */
4407
+ var Geometry;
4408
+ (function (Geometry) {
4409
+ let EPolygonRingType;
4410
+ (function (EPolygonRingType) {
4411
+ EPolygonRingType["Boundaries"] = "out";
4412
+ EPolygonRingType["Hole"] = "in";
4413
+ })(EPolygonRingType = Geometry.EPolygonRingType || (Geometry.EPolygonRingType = {}));
4414
+ /**
4415
+ * Turns an array of points into string vector geometry that Bruce can use.
4416
+ * This is used for saving polyline and polygon data.
4417
+ * @param points
4418
+ * @returns
4419
+ */
4420
+ function LineStrFromPoints(points) {
4421
+ if (!points.length) {
4422
+ throw ("points is empty.");
4423
+ }
4424
+ let carto = points[0];
4425
+ let lineString = `${carto.longitude},${carto.latitude}` + (carto.altitude != null ? `,${carto.altitude}` : "");
4426
+ for (let i = 1; i < points.length; i++) {
4427
+ carto = points[i];
4428
+ lineString += ` ${carto.longitude},${carto.latitude}` + (carto.altitude != null ? `,${carto.altitude}` : "");
4429
+ }
4430
+ return lineString;
4431
+ }
4432
+ Geometry.LineStrFromPoints = LineStrFromPoints;
4433
+ /**
4434
+ * Removes same points that occur in a row.
4435
+ * This will not modify the original array.
4436
+ * @param positions
4437
+ * @returns
4438
+ */
4439
+ function RemoveRepeatPoints(positions) {
4440
+ const filteredList = [];
4441
+ for (let i = 0; i < positions.length; i++) {
4442
+ const pos = positions[i];
4443
+ const lastPos = filteredList.length > 0 ? filteredList[filteredList.length - 1] : null;
4444
+ if (!lastPos || (pos.latitude != lastPos.latitude || pos.longitude != lastPos.longitude || pos.altitude != lastPos.altitude)) {
4445
+ filteredList.push(pos);
4446
+ }
4447
+ }
4448
+ return filteredList;
4449
+ }
4450
+ Geometry.RemoveRepeatPoints = RemoveRepeatPoints;
4451
+ /**
4452
+ * Parses a string of points into an array of points.
4453
+ * @param pointsStr
4454
+ * @returns
4455
+ */
4456
+ function ParsePoints(pointsStr) {
4457
+ pointsStr = pointsStr.replace(/[^\d.,-\s]/g, "");
4458
+ let splitterCoordinates = " ";
4459
+ let splitterAxis = ",";
4460
+ const commaIndex = pointsStr.indexOf(",");
4461
+ const spaceIndex = pointsStr.indexOf(" ");
4462
+ if ((spaceIndex > -1 && commaIndex > spaceIndex) || commaIndex <= -1) {
4463
+ splitterCoordinates = ",";
4464
+ splitterAxis = " ";
4465
+ }
4466
+ let points = pointsStr.trim().split(splitterCoordinates);
4467
+ points = points.filter(a => a != "");
4468
+ const result = [];
4469
+ for (let i = 0; i < points.length; i++) {
4470
+ const pointData = points[i];
4471
+ const coords = pointData.trim().split(splitterAxis);
4472
+ if (coords.length == 2 || coords.length == 3) {
4473
+ const longitude = Number(coords[0]);
4474
+ const latitude = Number(coords[1]);
4475
+ const altitude = Number(coords.length >= 3 ? coords[2] : 0);
4476
+ if (longitude != null && latitude != null) {
4477
+ result.push({
4478
+ altitude: altitude,
4479
+ latitude: latitude,
4480
+ longitude: longitude
4481
+ });
4482
+ }
4483
+ else {
4484
+ console.warn("Invalid point data detected.", pointData);
4485
+ }
4486
+ }
4487
+ }
4488
+ return result;
4489
+ }
4490
+ Geometry.ParsePoints = ParsePoints;
4491
+ /**
4492
+ * Parses both string and object Bruce geometry.
4493
+ * String geometry is legacy Bruce data.
4494
+ * @param geometry
4495
+ * @returns
4496
+ */
4497
+ function ParseGeometry(geometry) {
4498
+ if (typeof geometry == "string") {
4499
+ let positions = [];
4500
+ const geometryParsed = (geometry || "").split(";");
4501
+ for (let i = 0; i < geometryParsed.length; i++) {
4502
+ const data = geometryParsed[i];
4503
+ const points = ParsePoints(data);
4504
+ if (points && points.length > 0) {
4505
+ positions = positions.concat(points);
4506
+ }
4507
+ }
4508
+ positions = RemoveRepeatPoints(positions);
4509
+ const newGeometry = {};
4510
+ if (positions.length > 0) {
4511
+ const topPoint = positions[0];
4512
+ newGeometry.Point = `${topPoint.latitude},${topPoint.longitude}` + (topPoint.altitude != null ? `,${topPoint.altitude}` : "");
4513
+ if (positions.length > 1) {
4514
+ newGeometry.Polygon = [{ Facing: EPolygonRingType.Boundaries, LinearRing: LineStrFromPoints(positions) }];
4515
+ }
4516
+ if (positions.length > 2) {
4517
+ newGeometry.LineString = LineStrFromPoints(positions);
4518
+ }
4519
+ }
4520
+ return newGeometry;
4521
+ }
4522
+ return geometry;
4523
+ }
4524
+ Geometry.ParseGeometry = ParseGeometry;
4525
+ /**
4526
+ * Converts Bruce geometry to GeoJSON.
4527
+ * @param geometry
4528
+ * @returns returns GeoJSON or null if conversion failed or resulted in an empty object.
4529
+ */
4530
+ function ToGeoJsonFeature(params) {
4531
+ const { geometry, properties, altitude } = params;
4532
+ // Primary collection of geometries.
4533
+ // We will return a single feature that contains many geometries.
4534
+ // That way we can attach properties to the top-level.
4535
+ const collection = [];
4536
+ // Returns if two coordinates are equal.
4537
+ const areCoordinatesEqual = (coord1, coord2) => {
4538
+ return coord1[0] === coord2[0] && coord1[1] === coord2[1] && coord1[2] === coord2[2];
4539
+ };
4540
+ // Removes consecutive duplicate coordinates.
4541
+ const removeConsecutiveDuplicates = (coordinates) => {
4542
+ return coordinates.filter((coord, index) => {
4543
+ return index === 0 || !areCoordinatesEqual(coord, coordinates[index - 1]);
4544
+ });
4545
+ };
4546
+ // Ensures that the polygon is closed.
4547
+ const closePolygonCoordinates = (coordinates) => {
4548
+ return coordinates.map(ring => {
4549
+ if (!areCoordinatesEqual(ring[0], ring[ring.length - 1])) {
4550
+ ring.push(ring[0]);
4551
+ }
4552
+ return ring;
4553
+ });
4554
+ };
4555
+ /**
4556
+ * Processes Bruce geometry.
4557
+ * Called recursively for MultiGeometry.
4558
+ * @param geometry
4559
+ * @returns if a geometry was processed and added.
4560
+ */
4561
+ const processGeometry = (geometry) => {
4562
+ var _a, _b;
4563
+ let jGeometry = null;
4564
+ // We add in order of priority while ignoring anything lower priority.
4565
+ // This mimics how we render Bruce geometry.
4566
+ if ((_a = geometry.MultiGeometry) === null || _a === void 0 ? void 0 : _a.length) {
4567
+ let passed = false;
4568
+ geometry.MultiGeometry.forEach(geo => {
4569
+ if (processGeometry(geo)) {
4570
+ passed = true;
4571
+ }
4572
+ });
4573
+ if (passed) {
4574
+ return true;
4575
+ }
4576
+ }
4577
+ if (!jGeometry && ((_b = geometry.Polygon) === null || _b === void 0 ? void 0 : _b.length)) {
4578
+ // Sorts polygons so that boundaries come first.
4579
+ const sortedPolygons = geometry.Polygon.sort((a, b) => a.Facing === Geometry.EPolygonRingType.Boundaries ? -1 : 1);
4580
+ // Converts polygons to GeoJSON coordinates.
4581
+ // This will close the polygon if it's not already closed and remove consecutive duplicates.
4582
+ const coordinates = closePolygonCoordinates(sortedPolygons.map(polygon => {
4583
+ return removeConsecutiveDuplicates(polygon.LinearRing.split(' ').map(coord => {
4584
+ const [lon, lat, alt] = coord.split(',').map(Number);
4585
+ return (altitude != null ? [lon, lat, altitude] : [lon, lat, alt !== undefined ? alt : 0]);
4586
+ }));
4587
+ }));
4588
+ if (coordinates.every(polygon => polygon.length >= 4)) {
4589
+ jGeometry = {
4590
+ coordinates: coordinates,
4591
+ type: GeoJson.EType.Polygon
4592
+ };
4593
+ }
4594
+ }
4595
+ if (!jGeometry && geometry.LineString) {
4596
+ const coordinates = removeConsecutiveDuplicates(geometry.LineString.split(' ').map(coord => {
4597
+ const [lon, lat, alt] = coord.split(',').map(Number);
4598
+ return (altitude != null ? [lon, lat, altitude] : [lon, lat, alt !== undefined ? alt : 0]);
4599
+ }));
4600
+ if (coordinates.length >= 2) {
4601
+ jGeometry = {
4602
+ coordinates: coordinates,
4603
+ type: GeoJson.EType.LineString
4604
+ };
4605
+ }
4606
+ }
4607
+ if (!jGeometry && geometry.Point) {
4608
+ const [lon, lat, alt] = geometry.Point.split(',').map(Number);
4609
+ const coordinates = altitude != null ? [lon, lat, altitude] : [lon, lat, alt !== undefined ? alt : 0];
4610
+ jGeometry = {
4611
+ coordinates: coordinates,
4612
+ type: GeoJson.EType.Point
4613
+ };
4614
+ }
4615
+ if (jGeometry) {
4616
+ collection.push(jGeometry);
4617
+ return true;
4618
+ }
4619
+ // Nothing :(
4620
+ return false;
4621
+ };
4622
+ // Add all geometries to the collection.
4623
+ processGeometry(geometry);
4624
+ // Nothing was produced.
4625
+ if (!collection.length) {
4626
+ return null;
4627
+ }
4628
+ // Just 1 item. We can have a single feature rather than geometry collection.
4629
+ if (collection.length === 1) {
4630
+ const geoJson = {
4631
+ type: GeoJson.EType.Feature,
4632
+ geometry: collection[0],
4633
+ properties: properties || {}
4634
+ };
4635
+ return geoJson;
4636
+ }
4637
+ // Construct the base feature and append the collection.
4638
+ const geoJson = {
4639
+ type: GeoJson.EType.Feature,
4640
+ geometry: {
4641
+ type: GeoJson.EType.GeometryCollection,
4642
+ geometries: collection
4643
+ },
4644
+ properties: properties || {}
4645
+ };
4646
+ return geoJson;
4647
+ }
4648
+ Geometry.ToGeoJsonFeature = ToGeoJsonFeature;
4649
+ /**
4650
+ * Converts GeoJSON to Bruce geometry.
4651
+ * @param geoJson
4652
+ * @returns
4653
+ */
4654
+ function FromGeoJson(params) {
4655
+ var _a;
4656
+ const { geoJson } = params;
4657
+ // Don't process if there's no geometry.
4658
+ if (geoJson.type === GeoJson.EType.FeatureCollection) {
4659
+ if (!geoJson.features.length) {
4660
+ return null;
4661
+ }
4662
+ }
4663
+ // We start by populating multi-geometry.
4664
+ // If we end up with only 1 level then we'll return the single geometry.
4665
+ const full = {
4666
+ MultiGeometry: []
4667
+ };
4668
+ // Merged properties added to as we go.
4669
+ const properties = {};
4670
+ // Traverse a geojson hierarchy and generate a Bruce multi-geometry from it.
4671
+ // This will append to the "full" object as it goes.
4672
+ const traverse = (feature) => {
4673
+ // Geometry collections don't have coords so we have to cast as any.
4674
+ const { type, coordinates, properties } = feature.geometry;
4675
+ // Unknown thing. Ignoring.
4676
+ if (!type) {
4677
+ return;
4678
+ }
4679
+ // No coordinates. Ignoring.
4680
+ if (!coordinates) {
4681
+ return;
4682
+ }
4683
+ // Simple properties merge.
4684
+ // Doesn't handle nested properties very well.
4685
+ if (properties) {
4686
+ Object.assign(properties, properties);
4687
+ }
4688
+ // We'll first match cases of nested collections and handle them early.
4689
+ // Then we'll be left with simple geometry cases.
4690
+ if (type === GeoJson.EType.GeometryCollection) {
4691
+ const collection = feature;
4692
+ for (let i = 0; i < collection.geometries.length; i++) {
4693
+ const geo = collection.geometries[i];
4694
+ traverse({
4695
+ type: GeoJson.EType.Feature,
4696
+ geometry: geo,
4697
+ properties: feature.properties
4698
+ });
4699
+ }
4700
+ return;
4701
+ }
4702
+ else if (type === GeoJson.EType.FeatureCollection) {
4703
+ const collection = feature;
4704
+ for (let i = 0; i < collection.features.length; i++) {
4705
+ traverse(collection.features[i]);
4706
+ }
4707
+ return;
4708
+ }
4709
+ const geometry = {};
4710
+ switch (type) {
4711
+ case GeoJson.EType.Polygon:
4712
+ if (!geometry.Polygon) {
4713
+ geometry.Polygon = [];
4714
+ }
4715
+ coordinates.forEach((polygon, index) => {
4716
+ const linearRing = polygon.map(coord => coord.join(',')).join(' ');
4717
+ geometry.Polygon.push({
4718
+ LinearRing: linearRing,
4719
+ Facing: index === 0 ? Geometry.EPolygonRingType.Boundaries : Geometry.EPolygonRingType.Hole
4720
+ });
4721
+ });
4722
+ break;
4723
+ case GeoJson.EType.LineString:
4724
+ geometry.LineString = coordinates.map((coord) => coord.join(',')).join(' ');
4725
+ break;
4726
+ case GeoJson.EType.Point:
4727
+ geometry.Point = coordinates.join(',');
4728
+ break;
4729
+ case GeoJson.EType.MultiPolygon:
4730
+ if (!geometry.MultiGeometry) {
4731
+ geometry.MultiGeometry = [];
4732
+ }
4733
+ coordinates.forEach((multiPolygon) => {
4734
+ const multiPolygonGeometry = { Polygon: [] };
4735
+ multiPolygon.forEach((polygon, index) => {
4736
+ const linearRing = polygon.map(coord => coord.join(',')).join(' ');
4737
+ multiPolygonGeometry.Polygon.push({
4738
+ LinearRing: linearRing,
4739
+ Facing: index === 0 ? Geometry.EPolygonRingType.Boundaries : Geometry.EPolygonRingType.Hole
4740
+ });
4741
+ });
4742
+ geometry.MultiGeometry.push(multiPolygonGeometry);
4743
+ });
4744
+ break;
4745
+ case GeoJson.EType.MultiLineString:
4746
+ if (!geometry.MultiGeometry) {
4747
+ geometry.MultiGeometry = [];
4748
+ }
4749
+ coordinates.forEach((multiLineString) => {
4750
+ geometry.MultiGeometry.push({
4751
+ LineString: multiLineString.map((coord) => coord.join(',')).join(' ')
4752
+ });
4753
+ });
4754
+ break;
4755
+ case GeoJson.EType.MultiPoint:
4756
+ if (!geometry.MultiGeometry) {
4757
+ geometry.MultiGeometry = [];
4758
+ }
4759
+ coordinates.forEach((multiPoint) => {
4760
+ geometry.MultiGeometry.push({
4761
+ Point: multiPoint.join(',')
4762
+ });
4763
+ });
4764
+ break;
4765
+ default:
4766
+ return;
4767
+ }
4768
+ // Nothing to do. Nothing was made.
4769
+ if (Object.keys(geometry).length === 0) {
4770
+ return;
4771
+ }
4772
+ full.MultiGeometry.push(geometry);
4773
+ };
4774
+ // Traverse all features.
4775
+ if (geoJson.type === GeoJson.EType.Feature) {
4776
+ traverse(geoJson);
4777
+ }
4778
+ else {
4779
+ (_a = geoJson.features) === null || _a === void 0 ? void 0 : _a.forEach(traverse);
4780
+ }
4781
+ // If we only have 1 geometry then we'll return it directly.
4782
+ if (full.MultiGeometry.length === 1) {
4783
+ return {
4784
+ geometry: full.MultiGeometry[0],
4785
+ properties: properties
4786
+ };
4787
+ }
4788
+ // If we have multiple but only 1 of each type then that's standard Bruce stuff.
4789
+ // Eg: 1 point, 1 line, 1 polygon is a very normal Bruce geometry.
4790
+ const countsPerType = {
4791
+ Point: 0,
4792
+ LineString: 0,
4793
+ Polygon: 0
4794
+ };
4795
+ full.MultiGeometry.forEach(geo => {
4796
+ if (geo.Point) {
4797
+ countsPerType.Point++;
4798
+ }
4799
+ else if (geo.LineString) {
4800
+ countsPerType.LineString++;
4801
+ }
4802
+ else if (geo.Polygon) {
4803
+ countsPerType.Polygon++;
4804
+ }
4805
+ });
4806
+ if (countsPerType.Point === 1 && countsPerType.LineString === 1 && countsPerType.Polygon === 1) {
4807
+ const merged = {};
4808
+ const addToMerged = (geo) => {
4809
+ if (geo.Point) {
4810
+ merged.Point = geo.Point;
4811
+ }
4812
+ else if (geo.LineString) {
4813
+ merged.LineString = geo.LineString;
4814
+ }
4815
+ else if (geo.Polygon) {
4816
+ merged.Polygon = geo.Polygon;
4817
+ }
4818
+ };
4819
+ full.MultiGeometry.forEach(addToMerged);
4820
+ return {
4821
+ geometry: merged,
4822
+ properties: properties
4823
+ };
4824
+ }
4825
+ // If there are many polygons but only 1 line and/or 1 point then we'll put those singles into the top-level.
4826
+ // Eg: 5 polygons, 1 point, 1 line. That should be a single geometry.
4827
+ if (countsPerType.Polygon > 1 && (countsPerType.LineString <= 1 && countsPerType.Point <= 1)) {
4828
+ const semiMerged = {};
4829
+ const addToSemiMerged = (geo) => {
4830
+ if (geo.Point) {
4831
+ semiMerged.Point = geo.Point;
4832
+ }
4833
+ else if (geo.LineString) {
4834
+ semiMerged.LineString = geo.LineString;
4835
+ }
4836
+ };
4837
+ semiMerged.MultiGeometry = full.MultiGeometry.filter(geo => geo.Polygon);
4838
+ full.MultiGeometry.forEach(addToSemiMerged);
4839
+ return {
4840
+ geometry: semiMerged,
4841
+ properties: properties
4842
+ };
4843
+ }
4844
+ // More than 1 of each, then return the full multi-geometry as-is.
4845
+ return {
4846
+ geometry: full,
4847
+ properties: properties
4848
+ };
4849
+ }
4850
+ Geometry.FromGeoJson = FromGeoJson;
4851
+ })(Geometry || (Geometry = {}));
4852
+
4650
4853
  var Bounds;
4651
4854
  (function (Bounds) {
4652
4855
  /**
@@ -8735,6 +8938,28 @@ var ProgramKey;
8735
8938
  ProgramKey.GetListCacheKey = GetListCacheKey;
8736
8939
  })(ProgramKey || (ProgramKey = {}));
8737
8940
 
8941
+ /**
8942
+ * Describes an expectation on what should be rendered for a menu item-
8943
+ * between a min-max distance of an entity to the camera.
8944
+ */
8945
+ var ZoomControl;
8946
+ (function (ZoomControl) {
8947
+ /**
8948
+ * Available display types for a menu item.
8949
+ */
8950
+ let EDisplayType;
8951
+ (function (EDisplayType) {
8952
+ // Hidden means it will not be rendered.
8953
+ EDisplayType["Hidden"] = "hidden";
8954
+ // Point will try render a point based on any available Entity data.
8955
+ EDisplayType["Point"] = "point";
8956
+ // Geometry means it will try render multi-geometry, polygon, polyline, or point in order of priority.
8957
+ EDisplayType["Geometry"] = "geometry";
8958
+ // 3D means it will try render 3D model, multi-geometry, polygon, polyline, or point in order of priority.
8959
+ EDisplayType["Model3D"] = "3d";
8960
+ })(EDisplayType = ZoomControl.EDisplayType || (ZoomControl.EDisplayType = {}));
8961
+ })(ZoomControl || (ZoomControl = {}));
8962
+
8738
8963
  /**
8739
8964
  * Converts legacy records into something easier to work with alongside the newer ones.
8740
8965
  * On save we'll convert back to the legacy format.
@@ -13796,7 +14021,7 @@ var DataSource;
13796
14021
  })(DataSource || (DataSource = {}));
13797
14022
 
13798
14023
  // This is updated with the package.json version on build.
13799
- const VERSION = "4.6.4";
14024
+ const VERSION = "4.6.6";
13800
14025
 
13801
- export { VERSION, AnnDocument, CustomForm, AbstractApi, Api, BruceApi, GlobalApi, GuardianApi, ApiGetters, Calculator, Bounds, BruceEvent, CacheControl, Camera, Cartes, Carto, Color, DelayQueue, Geometry, UTC, BruceVariable, LRUCache, EntityAttachmentType, EntityAttachment, EntityComment, EntityLink, EntityLod, EntityLodCategory, EntityRelationType, EntityRelation, EntitySource, EntityTag, EntityType, Entity, EntityCoords, EntityTypeVisualSettings, EntityAttribute, EntityHistoricData, EntityTableView, Comment, ClientFile, ProgramKey, ZoomControl, MenuItem, ProjectViewBookmark, ProjectView, ProjectViewLegacyTile, ProjectViewTile, ProjectViewLegacy, ProjectViewLegacyBookmark, PendingAction, MessageBroker, HostingLocation, Style, Tileset, Permission, Session, UserGroup, User, Account, AccountInvite, AccountFeatures, AccountLimits, EncryptUtils, MathUtils, ObjectUtils, PathUtils, UrlUtils, DataLab, ImportCad, ImportCsv, ImportJson, ImportKml, ImportedFile, Markup, Uploader, Plugin, ENVIRONMENT, DataSource };
14026
+ export { VERSION, AnnDocument, CustomForm, AbstractApi, Api, BruceApi, GlobalApi, GuardianApi, ApiGetters, Calculator, Bounds, BruceEvent, CacheControl, Camera, Cartes, Carto, Color, DelayQueue, Geometry, UTC, BruceVariable, LRUCache, GeoJson, EntityAttachmentType, EntityAttachment, EntityComment, EntityLink, EntityLod, EntityLodCategory, EntityRelationType, EntityRelation, EntitySource, EntityTag, EntityType, Entity, EntityCoords, EntityTypeVisualSettings, EntityAttribute, EntityHistoricData, EntityTableView, Comment, ClientFile, ProgramKey, ZoomControl, MenuItem, ProjectViewBookmark, ProjectView, ProjectViewLegacyTile, ProjectViewTile, ProjectViewLegacy, ProjectViewLegacyBookmark, PendingAction, MessageBroker, HostingLocation, Style, Tileset, Permission, Session, UserGroup, User, Account, AccountInvite, AccountFeatures, AccountLimits, EncryptUtils, MathUtils, ObjectUtils, PathUtils, UrlUtils, DataLab, ImportCad, ImportCsv, ImportJson, ImportKml, ImportedFile, Markup, Uploader, Plugin, ENVIRONMENT, DataSource };
13802
14027
  //# sourceMappingURL=bruce-models.es5.js.map