venue-js 1.4.0-next.18 → 1.4.0-next.19

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.
package/dist/index.mjs CHANGED
@@ -410,6 +410,19 @@ var findContainingUnit = (poi, units) => {
410
410
  );
411
411
  return unit;
412
412
  };
413
+ var findContainingUnitAtPoint = (point2, levelId, units) => {
414
+ const unit = units.find(
415
+ (unit2) => {
416
+ try {
417
+ return unit2.properties.level_id === levelId && booleanPointInPolygon(point2, unit2);
418
+ } catch (e) {
419
+ console.log(`Cannot find containing unit of (point: ${point2}, levelId: ${levelId}):`, e.message);
420
+ return false;
421
+ }
422
+ }
423
+ );
424
+ return unit;
425
+ };
413
426
 
414
427
  // src/data/populator/index.ts
415
428
  var createPopulator = ({
@@ -582,6 +595,19 @@ var createPopulator = ({
582
595
  }
583
596
  };
584
597
  };
598
+ const populateSection = async (section) => {
599
+ const venue = await internalFindById(section.properties.venue_id);
600
+ const level = await internalFindById(section.properties.level_id);
601
+ return {
602
+ ...section,
603
+ properties: {
604
+ ...section.properties,
605
+ venue,
606
+ level: await populateLevel(level),
607
+ ordinal: level.properties.ordinal
608
+ }
609
+ };
610
+ };
585
611
  const populateRelationship = async (relationship) => {
586
612
  const originId = relationship.properties.origin?.id;
587
613
  const destinationId = relationship.properties.destination?.id;
@@ -599,19 +625,6 @@ var createPopulator = ({
599
625
  }
600
626
  };
601
627
  };
602
- const populateSection = async (section) => {
603
- const venue = await internalFindById(section.properties.venue_id);
604
- const level = await internalFindById(section.properties.level_id);
605
- return {
606
- ...section,
607
- properties: {
608
- ...section.properties,
609
- venue,
610
- level: await populateLevel(level),
611
- ordinal: level.properties.ordinal
612
- }
613
- };
614
- };
615
628
  const populateUnit = async (unit) => {
616
629
  const venue = await internalFindById(unit.properties.venue_id);
617
630
  const level = await internalFindById(unit.properties.level_id);
@@ -688,1366 +701,1649 @@ var createPopulator = ({
688
701
  };
689
702
  };
690
703
 
691
- // ../../node_modules/fuse.js/dist/fuse.mjs
692
- function isArray(value) {
693
- return !Array.isArray ? getTag(value) === "[object Array]" : Array.isArray(value);
694
- }
695
- var INFINITY = 1 / 0;
696
- function baseToString(value) {
697
- if (typeof value == "string") {
698
- return value;
699
- }
700
- let result = value + "";
701
- return result == "0" && 1 / value == -INFINITY ? "-0" : result;
702
- }
703
- function toString(value) {
704
- return value == null ? "" : baseToString(value);
705
- }
706
- function isString(value) {
707
- return typeof value === "string";
708
- }
709
- function isNumber(value) {
710
- return typeof value === "number";
711
- }
712
- function isBoolean(value) {
713
- return value === true || value === false || isObjectLike(value) && getTag(value) == "[object Boolean]";
714
- }
715
- function isObject(value) {
716
- return typeof value === "object";
717
- }
718
- function isObjectLike(value) {
719
- return isObject(value) && value !== null;
720
- }
721
- function isDefined(value) {
722
- return value !== void 0 && value !== null;
723
- }
724
- function isBlank(value) {
725
- return !value.trim().length;
726
- }
727
- function getTag(value) {
728
- return value == null ? value === void 0 ? "[object Undefined]" : "[object Null]" : Object.prototype.toString.call(value);
729
- }
730
- var INCORRECT_INDEX_TYPE = "Incorrect 'index' type";
731
- var LOGICAL_SEARCH_INVALID_QUERY_FOR_KEY = (key) => `Invalid value for key ${key}`;
732
- var PATTERN_LENGTH_TOO_LARGE = (max2) => `Pattern length exceeds max of ${max2}.`;
733
- var MISSING_KEY_PROPERTY = (name) => `Missing ${name} property in key`;
734
- var INVALID_KEY_WEIGHT_VALUE = (key) => `Property 'weight' in key '${key}' must be a positive integer`;
735
- var hasOwn = Object.prototype.hasOwnProperty;
736
- var KeyStore = class {
737
- constructor(keys) {
738
- this._keys = [];
739
- this._keyMap = {};
740
- let totalWeight = 0;
741
- keys.forEach((key) => {
742
- let obj = createKey(key);
743
- this._keys.push(obj);
744
- this._keyMap[obj.id] = obj;
745
- totalWeight += obj.weight;
746
- });
747
- this._keys.forEach((key) => {
748
- key.weight /= totalWeight;
749
- });
750
- }
751
- get(keyId) {
752
- return this._keyMap[keyId];
753
- }
754
- keys() {
755
- return this._keys;
756
- }
757
- toJSON() {
758
- return JSON.stringify(this._keys);
759
- }
704
+ // src/data/search/getSearchClient.ts
705
+ import Fuse from "fuse.js";
706
+
707
+ // src/data/search/utils/sanitizeInput.ts
708
+ var sanitizeInput = (str) => str.replace(/[\u200E\u200F\u202A-\u202E\u2066-\u2069]/g, "").replace(/[\-–—_./()]+/g, "").normalize("NFC").trim();
709
+
710
+ // src/data/search/getSearchClient.ts
711
+ var getSearchClient = ({ occupants, amenities }) => {
712
+ const fuseAmenities = new Fuse(amenities, {
713
+ threshold: 0.2,
714
+ keys: [
715
+ { name: "properties.name", "weight": 1, getFn: (obj) => Object.values(obj.properties.name || {}) },
716
+ { name: "properties.category", "weight": 1 }
717
+ ]
718
+ });
719
+ const fuseOccupants = new Fuse(occupants, {
720
+ threshold: 0.25,
721
+ // 0.2 is too strict (can't find Mo-Mo Paradise with "momo" search string)
722
+ includeScore: true,
723
+ shouldSort: true,
724
+ keys: [
725
+ { name: "properties.name", "weight": 4, getFn: (obj) => Object.values(obj.properties.name || {}) },
726
+ { name: "properties.keywords", "weight": 0.5 },
727
+ { name: "properties.category", "weight": 0.25 },
728
+ { name: "properties.local_category_names", "weight": 0.25 },
729
+ { name: "properties.description", "weight": 0.25, getFn: (occ) => Object.values(occ.properties.description || {}) },
730
+ { name: "properties.unit_name", "weight": 0.25 },
731
+ { name: "properties.kiosk_name", "weight": 0.25 }
732
+ ]
733
+ });
734
+ const search = (value) => {
735
+ const sanitizedValue = sanitizeInput(value);
736
+ const matchedAmenities = fuseAmenities.search(sanitizedValue);
737
+ const matchedOccupants = fuseOccupants.search(sanitizedValue);
738
+ return [...matchedAmenities, ...matchedOccupants];
739
+ };
740
+ return {
741
+ search
742
+ };
760
743
  };
761
- function createKey(key) {
762
- let path = null;
763
- let id = null;
764
- let src = null;
765
- let weight = 1;
766
- let getFn = null;
767
- if (isString(key) || isArray(key)) {
768
- src = key;
769
- path = createKeyPath(key);
770
- id = createKeyId(key);
771
- } else {
772
- if (!hasOwn.call(key, "name")) {
773
- throw new Error(MISSING_KEY_PROPERTY("name"));
774
- }
775
- const name = key.name;
776
- src = name;
777
- if (hasOwn.call(key, "weight")) {
778
- weight = key.weight;
779
- if (weight <= 0) {
780
- throw new Error(INVALID_KEY_WEIGHT_VALUE(name));
781
- }
744
+
745
+ // src/data/navigate/getNavigateClient.ts
746
+ import { booleanPointInPolygon as booleanPointInPolygon4 } from "@turf/boolean-point-in-polygon";
747
+
748
+ // src/data/navigate/graph/prepare.ts
749
+ import _6 from "lodash";
750
+ import DijstraGraph from "node-dijkstra";
751
+ import { distance as distance2 } from "@turf/distance";
752
+ import { center as turfCenter3 } from "@turf/center";
753
+
754
+ // src/data/navigate/graph/nodemap/createTraversalNodeMap.ts
755
+ import { distance as turfDistance } from "@turf/distance";
756
+ import { center as turfCenter } from "@turf/center";
757
+ import _ from "lodash";
758
+
759
+ // src/data/navigate/graph/constants.ts
760
+ var ROOM_BASEDISTANCE = 1e3;
761
+ var TERRACE_BASEDISTANCE = 1e3;
762
+ var ESCALATOR_BASEDISTANCE = 200;
763
+ var RAMP_BASEDISTANCE = 200;
764
+ var ELEVATOR_BASEDISTANCE = 500;
765
+ var STAIR_BASEDISTANCE = 1e5;
766
+ var BASE_POI_BASEDISTANCE = 9999999;
767
+ var DEFAULT_UNIT_BASEDISTANCE_OPTIONS = {
768
+ default: { baseDistance: 0 },
769
+ byCategory: {
770
+ room: { baseDistance: ROOM_BASEDISTANCE },
771
+ terrace: { baseDistance: TERRACE_BASEDISTANCE },
772
+ escalator: { baseDistance: ESCALATOR_BASEDISTANCE, scaleDistanceByLevel: false },
773
+ ramp: { baseDistance: RAMP_BASEDISTANCE, scaleDistanceByLevel: false },
774
+ elevator: { baseDistance: ELEVATOR_BASEDISTANCE, scaleDistanceByLevel: false },
775
+ stairs: {
776
+ baseDistance: STAIR_BASEDISTANCE,
777
+ scaleDistanceByLevel: true
778
+ },
779
+ "stairs.emergencyexit": {
780
+ baseDistance: STAIR_BASEDISTANCE,
781
+ scaleDistanceByLevel: true
782
782
  }
783
- path = createKeyPath(name);
784
- id = createKeyId(name);
785
- getFn = key.getFn;
786
783
  }
787
- return { path, id, weight, src, getFn };
788
- }
789
- function createKeyPath(key) {
790
- return isArray(key) ? key : key.split(".");
791
- }
792
- function createKeyId(key) {
793
- return isArray(key) ? key.join(".") : key;
794
- }
795
- function get(obj, path) {
796
- let list = [];
797
- let arr = false;
798
- const deepGet = (obj2, path2, index) => {
799
- if (!isDefined(obj2)) {
800
- return;
801
- }
802
- if (!path2[index]) {
803
- list.push(obj2);
804
- } else {
805
- let key = path2[index];
806
- const value = obj2[key];
807
- if (!isDefined(value)) {
808
- return;
809
- }
810
- if (index === path2.length - 1 && (isString(value) || isNumber(value) || isBoolean(value))) {
811
- list.push(toString(value));
812
- } else if (isArray(value)) {
813
- arr = true;
814
- for (let i = 0, len = value.length; i < len; i += 1) {
815
- deepGet(value[i], path2, index + 1);
816
- }
817
- } else if (path2.length) {
818
- deepGet(value, path2, index + 1);
819
- }
820
- }
821
- };
822
- deepGet(obj, isString(path) ? path.split(".") : path, 0);
823
- return arr ? list : list[0];
824
- }
825
- var MatchOptions = {
826
- // Whether the matches should be included in the result set. When `true`, each record in the result
827
- // set will include the indices of the matched characters.
828
- // These can consequently be used for highlighting purposes.
829
- includeMatches: false,
830
- // When `true`, the matching function will continue to the end of a search pattern even if
831
- // a perfect match has already been located in the string.
832
- findAllMatches: false,
833
- // Minimum number of characters that must be matched before a result is considered a match
834
- minMatchCharLength: 1
835
784
  };
836
- var BasicOptions = {
837
- // When `true`, the algorithm continues searching to the end of the input even if a perfect
838
- // match is found before the end of the same input.
839
- isCaseSensitive: false,
840
- // When `true`, the algorithm will ignore diacritics (accents) in comparisons
841
- ignoreDiacritics: false,
842
- // When true, the matching function will continue to the end of a search pattern even if
843
- includeScore: false,
844
- // List of properties that will be searched. This also supports nested properties.
845
- keys: [],
846
- // Whether to sort the result list, by score
847
- shouldSort: true,
848
- // Default sort function: sort by ascending score, ascending index
849
- sortFn: (a, b) => a.score === b.score ? a.idx < b.idx ? -1 : 1 : a.score < b.score ? -1 : 1
850
- };
851
- var FuzzyOptions = {
852
- // Approximately where in the text is the pattern expected to be found?
853
- location: 0,
854
- // At what point does the match algorithm give up. A threshold of '0.0' requires a perfect match
855
- // (of both letters and location), a threshold of '1.0' would match anything.
856
- threshold: 0.6,
857
- // Determines how close the match must be to the fuzzy location (specified above).
858
- // An exact letter match which is 'distance' characters away from the fuzzy location
859
- // would score as a complete mismatch. A distance of '0' requires the match be at
860
- // the exact location specified, a threshold of '1000' would require a perfect match
861
- // to be within 800 characters of the fuzzy location to be found using a 0.8 threshold.
862
- distance: 100
863
- };
864
- var AdvancedOptions = {
865
- // When `true`, it enables the use of unix-like search commands
866
- useExtendedSearch: false,
867
- // The get function to use when fetching an object's properties.
868
- // The default will search nested paths *ie foo.bar.baz*
869
- getFn: get,
870
- // When `true`, search will ignore `location` and `distance`, so it won't matter
871
- // where in the string the pattern appears.
872
- // More info: https://fusejs.io/concepts/scoring-theory.html#fuzziness-score
873
- ignoreLocation: false,
874
- // When `true`, the calculation for the relevance score (used for sorting) will
875
- // ignore the field-length norm.
876
- // More info: https://fusejs.io/concepts/scoring-theory.html#field-length-norm
877
- ignoreFieldNorm: false,
878
- // The weight to determine how much field length norm effects scoring.
879
- fieldNormWeight: 1
785
+
786
+ // src/data/navigate/graph/utils/getDistanceOption.ts
787
+ var getDistanceOptions = (options, category) => {
788
+ if (!options) return DEFAULT_UNIT_BASEDISTANCE_OPTIONS.byCategory[category];
789
+ return (category && options.byCategory?.[category]) ?? DEFAULT_UNIT_BASEDISTANCE_OPTIONS.byCategory[category] ?? options?.default ?? DEFAULT_UNIT_BASEDISTANCE_OPTIONS.default;
880
790
  };
881
- var Config = {
882
- ...BasicOptions,
883
- ...MatchOptions,
884
- ...FuzzyOptions,
885
- ...AdvancedOptions
791
+
792
+ // src/data/utils/trace.ts
793
+ var trace = (namespace, text, ms, color) => {
794
+ console.log(`[${namespace}] %c${text.padEnd(90)} ${ms !== void 0 ? `${ms.toFixed(1).padStart(6)} ms` : ``}`, color ? `color: ${color}` : void 0);
886
795
  };
887
- var SPACE = /[^ ]+/g;
888
- function norm(weight = 1, mantissa = 3) {
889
- const cache = /* @__PURE__ */ new Map();
890
- const m = Math.pow(10, mantissa);
891
- return {
892
- get(value) {
893
- const numTokens = value.match(SPACE).length;
894
- if (cache.has(numTokens)) {
895
- return cache.get(numTokens);
796
+
797
+ // src/data/navigate/graph/nodemap/createTraversalNodeMap.ts
798
+ var createTraversalNodeMap = (unitOpenings, options) => {
799
+ const { units } = options.data;
800
+ let counter = 0;
801
+ const calculateFeatureDistanceWithinUnit = (features, distanceOptions) => {
802
+ let relationshipGraph = {};
803
+ for (let currentIndex = 0; currentIndex < features.length; currentIndex++) {
804
+ const isLastItem = currentIndex + 1 === features.length;
805
+ if (isLastItem) break;
806
+ for (let j = currentIndex + 1; j < features.length; j++) {
807
+ const opening = features[currentIndex];
808
+ const feature2 = features[j];
809
+ try {
810
+ const distance5 = turfDistance(
811
+ turfCenter(opening.geometry),
812
+ turfCenter(feature2.geometry),
813
+ { units: "meters" }
814
+ ) + (distanceOptions?.baseDistance ?? 0);
815
+ if (opening.id === feature2.id) continue;
816
+ _.set(relationshipGraph, `${opening.id}.${feature2.id}`, distance5);
817
+ _.set(relationshipGraph, `${feature2.id}.${opening.id}`, distance5);
818
+ counter++;
819
+ } catch (error) {
820
+ continue;
821
+ }
896
822
  }
897
- const norm2 = 1 / Math.pow(numTokens, 0.5 * weight);
898
- const n = parseFloat(Math.round(norm2 * m) / m);
899
- cache.set(numTokens, n);
900
- return n;
901
- },
902
- clear() {
903
- cache.clear();
904
823
  }
824
+ return relationshipGraph;
905
825
  };
906
- }
907
- var FuseIndex = class {
908
- constructor({
909
- getFn = Config.getFn,
910
- fieldNormWeight = Config.fieldNormWeight
911
- } = {}) {
912
- this.norm = norm(fieldNormWeight, 3);
913
- this.getFn = getFn;
914
- this.isCreated = false;
915
- this.setIndexRecords();
916
- }
917
- setSources(docs = []) {
918
- this.docs = docs;
919
- }
920
- setIndexRecords(records = []) {
921
- this.records = records;
922
- }
923
- setKeys(keys = []) {
924
- this.keys = keys;
925
- this._keysMap = {};
926
- keys.forEach((key, idx) => {
927
- this._keysMap[key.id] = idx;
928
- });
929
- }
930
- create() {
931
- if (this.isCreated || !this.docs.length) {
932
- return;
933
- }
934
- this.isCreated = true;
935
- if (isString(this.docs[0])) {
936
- this.docs.forEach((doc, docIndex) => {
937
- this._addString(doc, docIndex);
938
- });
939
- } else {
940
- this.docs.forEach((doc, docIndex) => {
941
- this._addObject(doc, docIndex);
826
+ const t0 = performance.now();
827
+ const nodeMap = _.reduce(
828
+ unitOpenings,
829
+ (acc, openings, unitId) => {
830
+ const unit = units.find((unit2) => unit2.id === unitId);
831
+ const unitDistanceOption = getDistanceOptions(options.unitDistanceOptions, unit.properties.category);
832
+ return _.merge(
833
+ acc,
834
+ calculateFeatureDistanceWithinUnit(openings, unitDistanceOption)
835
+ );
836
+ },
837
+ {}
838
+ );
839
+ const t1 = performance.now();
840
+ trace("nav", ` \u2502 \u251C\u2500 add ${counter} traversal relationships`, t1 - t0);
841
+ return nodeMap;
842
+ };
843
+
844
+ // src/data/navigate/graph/nodemap/createElevatorNodeMap.ts
845
+ import _2 from "lodash";
846
+ var createElevatorNodeMap = (elevatorLikeRelationships, unitOpenings, options) => {
847
+ const t0 = performance.now();
848
+ const { levels, units } = options.data;
849
+ const distanceOptions = getDistanceOptions(options.unitDistanceOptions, "elevator");
850
+ const {
851
+ baseDistance = ELEVATOR_BASEDISTANCE,
852
+ scaleDistanceByLevel = false
853
+ } = distanceOptions;
854
+ let elevatorNodeMap = {};
855
+ let counter = 0;
856
+ for (const relationship of elevatorLikeRelationships) {
857
+ try {
858
+ const {
859
+ origin: originTypeAndId,
860
+ intermediary,
861
+ destination: destinationTypeAndId
862
+ } = relationship.properties;
863
+ const origin = units.find((unit) => unit.id === originTypeAndId.id);
864
+ if (!origin) return;
865
+ const originOpenings = compact(unitOpenings[origin.id]);
866
+ const originLevel = levels.find((level) => level.id === origin.properties.level_id);
867
+ const destination = units.find((unit) => unit.id === destinationTypeAndId.id);
868
+ const destinationOpenings = unitOpenings[destination.id];
869
+ const destinationOpeningAndLevels = destinationOpenings.map((opening) => {
870
+ const level = levels.find((level2) => level2.id === destination.properties.level_id);
871
+ return { opening, level };
942
872
  });
943
- }
944
- this.norm.clear();
945
- }
946
- // Adds a doc to the end of the index
947
- add(doc) {
948
- const idx = this.size();
949
- if (isString(doc)) {
950
- this._addString(doc, idx);
951
- } else {
952
- this._addObject(doc, idx);
953
- }
954
- }
955
- // Removes the doc at the specified index of the index
956
- removeAt(idx) {
957
- this.records.splice(idx, 1);
958
- for (let i = idx, len = this.size(); i < len; i += 1) {
959
- this.records[i].i -= 1;
960
- }
961
- }
962
- getValueForItemAtKeyId(item, keyId) {
963
- return item[this._keysMap[keyId]];
964
- }
965
- size() {
966
- return this.records.length;
967
- }
968
- _addString(doc, docIndex) {
969
- if (!isDefined(doc) || isBlank(doc)) {
970
- return;
971
- }
972
- let record = {
973
- v: doc,
974
- i: docIndex,
975
- n: this.norm.get(doc)
976
- };
977
- this.records.push(record);
978
- }
979
- _addObject(doc, docIndex) {
980
- let record = { i: docIndex, $: {} };
981
- this.keys.forEach((key, keyIndex) => {
982
- let value = key.getFn ? key.getFn(doc) : this.getFn(doc, key.path);
983
- if (!isDefined(value)) {
984
- return;
985
- }
986
- if (isArray(value)) {
987
- let subRecords = [];
988
- const stack = [{ nestedArrIndex: -1, value }];
989
- while (stack.length) {
990
- const { nestedArrIndex, value: value2 } = stack.pop();
991
- if (!isDefined(value2)) {
992
- continue;
873
+ const intermediaryOpeningAndLevels = intermediary.map((unitTypeAndId) => {
874
+ const openings = unitOpenings[unitTypeAndId.id];
875
+ const unit = units.find((unit2) => unit2.id === unitTypeAndId.id);
876
+ const level = levels.find((level2) => level2.id === unit.properties.level_id);
877
+ return openings.map((opening) => ({ opening, level }));
878
+ }).flat();
879
+ const connections = compact([...intermediaryOpeningAndLevels, ...destinationOpeningAndLevels]);
880
+ if (!originOpenings || originOpenings.length === 0) return;
881
+ for (const originOpening of originOpenings) {
882
+ for (const connection of connections) {
883
+ const { opening, level } = connection;
884
+ let distance5 = baseDistance;
885
+ if (scaleDistanceByLevel) {
886
+ const originOrdinal = originLevel.properties.ordinal;
887
+ const connectionOrdinal = level.properties.ordinal;
888
+ const levelDifference = Math.abs(originOrdinal - connectionOrdinal);
889
+ if (levelDifference > 0) distance5 *= levelDifference;
993
890
  }
994
- if (isString(value2) && !isBlank(value2)) {
995
- let subRecord = {
996
- v: value2,
997
- i: nestedArrIndex,
998
- n: this.norm.get(value2)
999
- };
1000
- subRecords.push(subRecord);
1001
- } else if (isArray(value2)) {
1002
- value2.forEach((item, k) => {
1003
- stack.push({
1004
- nestedArrIndex: k,
1005
- value: item
1006
- });
1007
- });
1008
- } else ;
891
+ _2.set(elevatorNodeMap, `${originOpening.id}.${opening.id}`, distance5);
892
+ _2.set(elevatorNodeMap, `${opening.id}.${originOpening.id}`, distance5);
893
+ counter++;
1009
894
  }
1010
- record.$[keyIndex] = subRecords;
1011
- } else if (isString(value) && !isBlank(value)) {
1012
- let subRecord = {
1013
- v: value,
1014
- n: this.norm.get(value)
1015
- };
1016
- record.$[keyIndex] = subRecord;
1017
895
  }
1018
- });
1019
- this.records.push(record);
1020
- }
1021
- toJSON() {
1022
- return {
1023
- keys: this.keys,
1024
- records: this.records
1025
- };
896
+ } catch (err) {
897
+ console.log(err);
898
+ console.log("cannot create elevatorNodeMap for ", { relationship });
899
+ }
1026
900
  }
901
+ const t1 = performance.now();
902
+ trace("nav", ` \u2502 \u251C\u2500 add ${counter} escalator relationships`, t1 - t0);
903
+ return elevatorNodeMap;
1027
904
  };
1028
- function createIndex(keys, docs, { getFn = Config.getFn, fieldNormWeight = Config.fieldNormWeight } = {}) {
1029
- const myIndex = new FuseIndex({ getFn, fieldNormWeight });
1030
- myIndex.setKeys(keys.map(createKey));
1031
- myIndex.setSources(docs);
1032
- myIndex.create();
1033
- return myIndex;
1034
- }
1035
- function parseIndex(data, { getFn = Config.getFn, fieldNormWeight = Config.fieldNormWeight } = {}) {
1036
- const { keys, records } = data;
1037
- const myIndex = new FuseIndex({ getFn, fieldNormWeight });
1038
- myIndex.setKeys(keys);
1039
- myIndex.setIndexRecords(records);
1040
- return myIndex;
1041
- }
1042
- function computeScore$1(pattern, {
1043
- errors = 0,
1044
- currentLocation = 0,
1045
- expectedLocation = 0,
1046
- distance = Config.distance,
1047
- ignoreLocation = Config.ignoreLocation
1048
- } = {}) {
1049
- const accuracy = errors / pattern.length;
1050
- if (ignoreLocation) {
1051
- return accuracy;
1052
- }
1053
- const proximity = Math.abs(expectedLocation - currentLocation);
1054
- if (!distance) {
1055
- return proximity ? 1 : accuracy;
1056
- }
1057
- return accuracy + proximity / distance;
1058
- }
1059
- function convertMaskToIndices(matchmask = [], minMatchCharLength = Config.minMatchCharLength) {
1060
- let indices = [];
1061
- let start = -1;
1062
- let end = -1;
1063
- let i = 0;
1064
- for (let len = matchmask.length; i < len; i += 1) {
1065
- let match = matchmask[i];
1066
- if (match && start === -1) {
1067
- start = i;
1068
- } else if (!match && start !== -1) {
1069
- end = i - 1;
1070
- if (end - start + 1 >= minMatchCharLength) {
1071
- indices.push([start, end]);
1072
- }
1073
- start = -1;
905
+
906
+ // src/data/navigate/graph/nodemap/createEscalatorNodeMap.ts
907
+ import set from "lodash/set";
908
+ var createEscalatorNodeMap = (relationships, options) => {
909
+ const t0 = performance.now();
910
+ const distanceOptions = getDistanceOptions(options.unitDistanceOptions, "escalator");
911
+ let counter = 0;
912
+ let nodeMap = {};
913
+ for (const relationship of relationships) {
914
+ const {
915
+ properties: { direction, origin, destination }
916
+ } = relationship;
917
+ set(nodeMap, `${origin.id}.${destination.id}`, distanceOptions.baseDistance);
918
+ if (direction === "undirected") {
919
+ set(nodeMap, `${destination.id}.${origin.id}`, distanceOptions.baseDistance);
1074
920
  }
921
+ counter++;
1075
922
  }
1076
- if (matchmask[i - 1] && i - start >= minMatchCharLength) {
1077
- indices.push([start, i - 1]);
1078
- }
1079
- return indices;
1080
- }
1081
- var MAX_BITS = 32;
1082
- function search(text, pattern, patternAlphabet, {
1083
- location = Config.location,
1084
- distance = Config.distance,
1085
- threshold = Config.threshold,
1086
- findAllMatches = Config.findAllMatches,
1087
- minMatchCharLength = Config.minMatchCharLength,
1088
- includeMatches = Config.includeMatches,
1089
- ignoreLocation = Config.ignoreLocation
1090
- } = {}) {
1091
- if (pattern.length > MAX_BITS) {
1092
- throw new Error(PATTERN_LENGTH_TOO_LARGE(MAX_BITS));
1093
- }
1094
- const patternLen = pattern.length;
1095
- const textLen = text.length;
1096
- const expectedLocation = Math.max(0, Math.min(location, textLen));
1097
- let currentThreshold = threshold;
1098
- let bestLocation = expectedLocation;
1099
- const computeMatches = minMatchCharLength > 1 || includeMatches;
1100
- const matchMask = computeMatches ? Array(textLen) : [];
1101
- let index;
1102
- while ((index = text.indexOf(pattern, bestLocation)) > -1) {
1103
- let score = computeScore$1(pattern, {
1104
- currentLocation: index,
1105
- expectedLocation,
1106
- distance,
1107
- ignoreLocation
1108
- });
1109
- currentThreshold = Math.min(score, currentThreshold);
1110
- bestLocation = index + patternLen;
1111
- if (computeMatches) {
1112
- let i = 0;
1113
- while (i < patternLen) {
1114
- matchMask[index + i] = 1;
1115
- i += 1;
923
+ const t1 = performance.now();
924
+ trace("nav", ` \u2502 \u251C\u2500 add ${counter} escalator relationships`, t1 - t0);
925
+ return nodeMap;
926
+ };
927
+
928
+ // src/data/navigate/graph/nodemap/createRampNodeMap.ts
929
+ import set2 from "lodash/set";
930
+ var createRampNodeMap = (relationships, options) => {
931
+ const t0 = performance.now();
932
+ const distanceOptions = getDistanceOptions(options.unitDistanceOptions, "ramp");
933
+ let counter = 0;
934
+ let nodeMap = {};
935
+ relationships.forEach((relationship) => {
936
+ const {
937
+ properties: { origin, destination }
938
+ } = relationship;
939
+ set2(nodeMap, `${origin.id}.${destination.id}`, distanceOptions.baseDistance);
940
+ set2(nodeMap, `${destination.id}.${origin.id}`, distanceOptions.baseDistance);
941
+ counter++;
942
+ });
943
+ const t1 = performance.now();
944
+ trace("nav", ` \u2502 \u251C\u2500 add ${counter} ramp relationships`, t1 - t0);
945
+ return nodeMap;
946
+ };
947
+
948
+ // src/data/navigate/graph/nodemap/createStairNodeMap.ts
949
+ import _3 from "lodash";
950
+ var createStairNodeMap = (elevatorLikeRelationships, unitOpenings, options) => {
951
+ const t0 = performance.now();
952
+ const { levels = [], openings = [], units = [] } = options.data;
953
+ const { baseDistance, scaleDistanceByLevel } = getDistanceOptions(options.unitDistanceOptions, "stairs");
954
+ let elevatorNodeMap = {};
955
+ let counter = 0;
956
+ for (const relationship of elevatorLikeRelationships) {
957
+ try {
958
+ const {
959
+ origin: { id: originId },
960
+ intermediary,
961
+ destination: { id: destinationId }
962
+ } = relationship.properties;
963
+ const origin = openings.find((opening) => opening.id === originId);
964
+ if (!origin) return;
965
+ const originLevel = levels.find((level) => level.id === origin.properties.level_id);
966
+ const destination = openings.find((opening) => opening.id === destinationId);
967
+ const destinationOpeningAndLevel = {
968
+ opening: destination,
969
+ level: levels.find((level) => level.id === destination.properties.level_id)
970
+ };
971
+ const intermediaryOpeningAndLevels = intermediary.map((unitTypeAndId) => {
972
+ const openings2 = unitOpenings[unitTypeAndId.id];
973
+ const unit = units.find((unit2) => unit2.id === unitTypeAndId.id);
974
+ const level = levels.find((level2) => level2.id === unit.properties.level_id);
975
+ return openings2.map((opening) => ({ opening, level }));
976
+ }).flat();
977
+ const connections = [...intermediaryOpeningAndLevels, destinationOpeningAndLevel];
978
+ if (!origin) return;
979
+ for (const connection of connections) {
980
+ const { opening, level } = connection;
981
+ let distance5 = baseDistance;
982
+ if (scaleDistanceByLevel) {
983
+ const originOrdinal = originLevel.properties.ordinal;
984
+ const connectionOrdinal = level.properties.ordinal;
985
+ const levelDifference = Math.abs(originOrdinal - connectionOrdinal);
986
+ if (levelDifference > 0) distance5 *= levelDifference;
987
+ }
988
+ _3.set(elevatorNodeMap, `${origin.id}.${opening.id}`, distance5);
989
+ _3.set(elevatorNodeMap, `${opening.id}.${origin.id}`, distance5);
990
+ counter++;
1116
991
  }
992
+ } catch (err) {
993
+ console.warn(
994
+ "Failed to create stairNodeMap",
995
+ {
996
+ relationshipId: relationship.id,
997
+ featureType: relationship.feature_type,
998
+ error: err instanceof Error ? err.message : err,
999
+ stack: err instanceof Error ? err.stack : void 0
1000
+ }
1001
+ );
1117
1002
  }
1118
1003
  }
1119
- bestLocation = -1;
1120
- let lastBitArr = [];
1121
- let finalScore = 1;
1122
- let binMax = patternLen + textLen;
1123
- const mask = 1 << patternLen - 1;
1124
- for (let i = 0; i < patternLen; i += 1) {
1125
- let binMin = 0;
1126
- let binMid = binMax;
1127
- while (binMin < binMid) {
1128
- const score2 = computeScore$1(pattern, {
1129
- errors: i,
1130
- currentLocation: expectedLocation + binMid,
1131
- expectedLocation,
1132
- distance,
1133
- ignoreLocation
1134
- });
1135
- if (score2 <= currentThreshold) {
1136
- binMin = binMid;
1137
- } else {
1138
- binMax = binMid;
1139
- }
1140
- binMid = Math.floor((binMax - binMin) / 2 + binMin);
1004
+ const t1 = performance.now();
1005
+ trace("nav", ` \u2502 \u251C\u2500 add ${counter} stairs relationships`, t1 - t0);
1006
+ return elevatorNodeMap;
1007
+ };
1008
+
1009
+ // src/data/navigate/graph/nodemap/createOccupantNodeMap.ts
1010
+ import _4 from "lodash";
1011
+ var createOccupantNodeMap = (occupants) => {
1012
+ const t0 = performance.now();
1013
+ let nodeMap = {};
1014
+ let counter = 0;
1015
+ occupants.forEach((occupant) => {
1016
+ const { unit_id, unit_ids = [], kiosk_id, kiosk_ids = [] } = occupant.properties;
1017
+ const occupantRoomIds = compact([unit_id, ...unit_ids]);
1018
+ const occupantKioskIds = compact([kiosk_id, ...kiosk_ids]);
1019
+ for (const roomId of occupantRoomIds) {
1020
+ _4.set(nodeMap, `${roomId}.${occupant.id}`, 1e-3);
1021
+ _4.set(nodeMap, `${occupant.id}.${roomId}`, 1e-3);
1022
+ counter++;
1141
1023
  }
1142
- binMax = binMid;
1143
- let start = Math.max(1, expectedLocation - binMid + 1);
1144
- let finish = findAllMatches ? textLen : Math.min(expectedLocation + binMid, textLen) + patternLen;
1145
- let bitArr = Array(finish + 2);
1146
- bitArr[finish + 1] = (1 << i) - 1;
1147
- for (let j = finish; j >= start; j -= 1) {
1148
- let currentLocation = j - 1;
1149
- let charMatch = patternAlphabet[text.charAt(currentLocation)];
1150
- if (computeMatches) {
1151
- matchMask[currentLocation] = +!!charMatch;
1152
- }
1153
- bitArr[j] = (bitArr[j + 1] << 1 | 1) & charMatch;
1154
- if (i) {
1155
- bitArr[j] |= (lastBitArr[j + 1] | lastBitArr[j]) << 1 | 1 | lastBitArr[j + 1];
1156
- }
1157
- if (bitArr[j] & mask) {
1158
- finalScore = computeScore$1(pattern, {
1159
- errors: i,
1160
- currentLocation,
1161
- expectedLocation,
1162
- distance,
1163
- ignoreLocation
1164
- });
1165
- if (finalScore <= currentThreshold) {
1166
- currentThreshold = finalScore;
1167
- bestLocation = currentLocation;
1168
- if (bestLocation <= expectedLocation) {
1169
- break;
1170
- }
1171
- start = Math.max(1, 2 * expectedLocation - bestLocation);
1024
+ for (const kioskId of occupantKioskIds) {
1025
+ _4.set(nodeMap, `${kioskId}.${occupant.id}`, 1e-3);
1026
+ _4.set(nodeMap, `${occupant.id}.${kioskId}`, 1e-3);
1027
+ counter++;
1028
+ }
1029
+ });
1030
+ const t1 = performance.now();
1031
+ trace("nav", ` \u2502 \u251C\u2500 add ${counter} occupants relationships`, t1 - t0);
1032
+ return nodeMap;
1033
+ };
1034
+
1035
+ // src/data/navigate/graph/nodemap/createPOINodeMaps.ts
1036
+ import { center as turfCenter2 } from "@turf/center";
1037
+ import { distance } from "@turf/distance";
1038
+ import _5 from "lodash";
1039
+ var createPOINodeMap = (features, getFeatureUnit, unitOpenings) => {
1040
+ const t0 = performance.now();
1041
+ let nodeMap = {};
1042
+ let counter = 0;
1043
+ features.forEach((feat) => {
1044
+ try {
1045
+ const locatedOnUnitId = getFeatureUnit(feat);
1046
+ const openings = unitOpenings[locatedOnUnitId];
1047
+ const center8 = turfCenter2(feat);
1048
+ for (const opening of openings) {
1049
+ try {
1050
+ const openingCenter = turfCenter2(opening);
1051
+ const dis = distance(center8, openingCenter, { units: "meters" }) + BASE_POI_BASEDISTANCE;
1052
+ _5.set(nodeMap, `${opening.id}.${feat.id}`, dis);
1053
+ _5.set(nodeMap, `${feat.id}.${opening.id}`, dis);
1054
+ counter++;
1055
+ } catch (err) {
1056
+ console.log(err, opening);
1172
1057
  }
1173
1058
  }
1059
+ } catch (err) {
1060
+ console.log(err);
1061
+ console.log(`cannot connect poi to openings`, err.message, { feat });
1174
1062
  }
1175
- const score = computeScore$1(pattern, {
1176
- errors: i + 1,
1177
- currentLocation: expectedLocation,
1178
- expectedLocation,
1179
- distance,
1180
- ignoreLocation
1181
- });
1182
- if (score > currentThreshold) {
1183
- break;
1184
- }
1185
- lastBitArr = bitArr;
1186
- }
1187
- const result = {
1188
- isMatch: bestLocation >= 0,
1189
- // Count exact matches (those with a score of 0) to be "almost" exact
1190
- score: Math.max(1e-3, finalScore)
1191
- };
1192
- if (computeMatches) {
1193
- const indices = convertMaskToIndices(matchMask, minMatchCharLength);
1194
- if (!indices.length) {
1195
- result.isMatch = false;
1196
- } else if (includeMatches) {
1197
- result.indices = indices;
1063
+ });
1064
+ const type = features.length > 0 ? features[0].feature_type : "-";
1065
+ const t1 = performance.now();
1066
+ trace("nav", ` \u2502 \u251C\u2500 add ${counter} ${type} relationships`, t1 - t0);
1067
+ return nodeMap;
1068
+ };
1069
+
1070
+ // src/data/navigate/graph/utils/mergeNodeMap.ts
1071
+ var mergeNodeMap = (nodeMaps) => {
1072
+ const out = {};
1073
+ for (const nodeMap of nodeMaps) {
1074
+ for (const from in nodeMap) {
1075
+ out[from] = {
1076
+ ...out[from] ?? {},
1077
+ ...nodeMap[from]
1078
+ };
1198
1079
  }
1199
1080
  }
1200
- return result;
1201
- }
1202
- function createPatternAlphabet(pattern) {
1203
- let mask = {};
1204
- for (let i = 0, len = pattern.length; i < len; i += 1) {
1205
- const char = pattern.charAt(i);
1206
- mask[char] = (mask[char] || 0) | 1 << len - i - 1;
1207
- }
1208
- return mask;
1209
- }
1210
- var stripDiacritics = String.prototype.normalize ? ((str) => str.normalize("NFD").replace(/[\u0300-\u036F\u0483-\u0489\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u0610-\u061A\u064B-\u065F\u0670\u06D6-\u06DC\u06DF-\u06E4\u06E7\u06E8\u06EA-\u06ED\u0711\u0730-\u074A\u07A6-\u07B0\u07EB-\u07F3\u07FD\u0816-\u0819\u081B-\u0823\u0825-\u0827\u0829-\u082D\u0859-\u085B\u08D3-\u08E1\u08E3-\u0903\u093A-\u093C\u093E-\u094F\u0951-\u0957\u0962\u0963\u0981-\u0983\u09BC\u09BE-\u09C4\u09C7\u09C8\u09CB-\u09CD\u09D7\u09E2\u09E3\u09FE\u0A01-\u0A03\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A70\u0A71\u0A75\u0A81-\u0A83\u0ABC\u0ABE-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AE2\u0AE3\u0AFA-\u0AFF\u0B01-\u0B03\u0B3C\u0B3E-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B62\u0B63\u0B82\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD7\u0C00-\u0C04\u0C3E-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C62\u0C63\u0C81-\u0C83\u0CBC\u0CBE-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CE2\u0CE3\u0D00-\u0D03\u0D3B\u0D3C\u0D3E-\u0D44\u0D46-\u0D48\u0D4A-\u0D4D\u0D57\u0D62\u0D63\u0D82\u0D83\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DF2\u0DF3\u0E31\u0E34-\u0E3A\u0E47-\u0E4E\u0EB1\u0EB4-\u0EB9\u0EBB\u0EBC\u0EC8-\u0ECD\u0F18\u0F19\u0F35\u0F37\u0F39\u0F3E\u0F3F\u0F71-\u0F84\u0F86\u0F87\u0F8D-\u0F97\u0F99-\u0FBC\u0FC6\u102B-\u103E\u1056-\u1059\u105E-\u1060\u1062-\u1064\u1067-\u106D\u1071-\u1074\u1082-\u108D\u108F\u109A-\u109D\u135D-\u135F\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17B4-\u17D3\u17DD\u180B-\u180D\u1885\u1886\u18A9\u1920-\u192B\u1930-\u193B\u1A17-\u1A1B\u1A55-\u1A5E\u1A60-\u1A7C\u1A7F\u1AB0-\u1ABE\u1B00-\u1B04\u1B34-\u1B44\u1B6B-\u1B73\u1B80-\u1B82\u1BA1-\u1BAD\u1BE6-\u1BF3\u1C24-\u1C37\u1CD0-\u1CD2\u1CD4-\u1CE8\u1CED\u1CF2-\u1CF4\u1CF7-\u1CF9\u1DC0-\u1DF9\u1DFB-\u1DFF\u20D0-\u20F0\u2CEF-\u2CF1\u2D7F\u2DE0-\u2DFF\u302A-\u302F\u3099\u309A\uA66F-\uA672\uA674-\uA67D\uA69E\uA69F\uA6F0\uA6F1\uA802\uA806\uA80B\uA823-\uA827\uA880\uA881\uA8B4-\uA8C5\uA8E0-\uA8F1\uA8FF\uA926-\uA92D\uA947-\uA953\uA980-\uA983\uA9B3-\uA9C0\uA9E5\uAA29-\uAA36\uAA43\uAA4C\uAA4D\uAA7B-\uAA7D\uAAB0\uAAB2-\uAAB4\uAAB7\uAAB8\uAABE\uAABF\uAAC1\uAAEB-\uAAEF\uAAF5\uAAF6\uABE3-\uABEA\uABEC\uABED\uFB1E\uFE00-\uFE0F\uFE20-\uFE2F]/g, "")) : ((str) => str);
1211
- var BitapSearch = class {
1212
- constructor(pattern, {
1213
- location = Config.location,
1214
- threshold = Config.threshold,
1215
- distance = Config.distance,
1216
- includeMatches = Config.includeMatches,
1217
- findAllMatches = Config.findAllMatches,
1218
- minMatchCharLength = Config.minMatchCharLength,
1219
- isCaseSensitive = Config.isCaseSensitive,
1220
- ignoreDiacritics = Config.ignoreDiacritics,
1221
- ignoreLocation = Config.ignoreLocation
1222
- } = {}) {
1223
- this.options = {
1224
- location,
1225
- threshold,
1226
- distance,
1227
- includeMatches,
1228
- findAllMatches,
1229
- minMatchCharLength,
1230
- isCaseSensitive,
1231
- ignoreDiacritics,
1232
- ignoreLocation
1233
- };
1234
- pattern = isCaseSensitive ? pattern : pattern.toLowerCase();
1235
- pattern = ignoreDiacritics ? stripDiacritics(pattern) : pattern;
1236
- this.pattern = pattern;
1237
- this.chunks = [];
1238
- if (!this.pattern.length) {
1239
- return;
1081
+ return out;
1082
+ };
1083
+
1084
+ // src/data/navigate/graph/utils/createUnitOpenings.ts
1085
+ import uniqBy from "lodash/uniqBy";
1086
+ var createUnitOpenings = (relationships, units, openings) => {
1087
+ const openingConnections = {};
1088
+ const relationshipMap = /* @__PURE__ */ new Map();
1089
+ relationships.forEach((relationship) => {
1090
+ const originId = relationship.properties.origin?.id || null;
1091
+ const destinationId = relationship.properties.destination?.id || null;
1092
+ if (!relationshipMap.has(originId)) {
1093
+ relationshipMap.set(originId, []);
1240
1094
  }
1241
- const addChunk = (pattern2, startIndex) => {
1242
- this.chunks.push({
1243
- pattern: pattern2,
1244
- alphabet: createPatternAlphabet(pattern2),
1245
- startIndex
1246
- });
1247
- };
1248
- const len = this.pattern.length;
1249
- if (len > MAX_BITS) {
1250
- let i = 0;
1251
- const remainder = len % MAX_BITS;
1252
- const end = len - remainder;
1253
- while (i < end) {
1254
- addChunk(this.pattern.substr(i, MAX_BITS), i);
1255
- i += MAX_BITS;
1256
- }
1257
- if (remainder) {
1258
- const startIndex = len - MAX_BITS;
1259
- addChunk(this.pattern.substr(startIndex), startIndex);
1260
- }
1261
- } else {
1262
- addChunk(this.pattern, 0);
1095
+ if (!relationshipMap.has(destinationId)) {
1096
+ relationshipMap.set(destinationId, []);
1263
1097
  }
1264
- }
1265
- searchIn(text) {
1266
- const { isCaseSensitive, ignoreDiacritics, includeMatches } = this.options;
1267
- text = isCaseSensitive ? text : text.toLowerCase();
1268
- text = ignoreDiacritics ? stripDiacritics(text) : text;
1269
- if (this.pattern === text) {
1270
- let result2 = {
1271
- isMatch: true,
1272
- score: 0
1273
- };
1274
- if (includeMatches) {
1275
- result2.indices = [[0, text.length - 1]];
1276
- }
1277
- return result2;
1098
+ relationshipMap.get(originId).push(relationship);
1099
+ relationshipMap.get(destinationId).push(relationship);
1100
+ });
1101
+ units.forEach((unit) => {
1102
+ const unitId = unit.id;
1103
+ const connectedRelationshop = relationshipMap.get(unitId) || [];
1104
+ const relationshipIntermediaryTypeAndId = connectedRelationshop.map(
1105
+ (relationship) => relationship.properties.intermediary[0]
1106
+ // Assuming intermediary is always an array
1107
+ );
1108
+ const relationshipIntermediary = relationshipIntermediaryTypeAndId.map(({ id }) => {
1109
+ return openings.find((opening) => opening.id === id);
1110
+ });
1111
+ openingConnections[unitId] = uniqBy(
1112
+ [...openingConnections[unitId] || [], ...relationshipIntermediary],
1113
+ "id"
1114
+ );
1115
+ });
1116
+ return openingConnections;
1117
+ };
1118
+
1119
+ // src/data/navigate/parsers.ts
1120
+ var parseOrdinalCoordinate = (id) => {
1121
+ return id.slice(0, -1).split(",").map(Number);
1122
+ };
1123
+
1124
+ // src/data/navigate/graph/prepare.ts
1125
+ var prepareGraph = (options) => {
1126
+ const {
1127
+ data: {
1128
+ amenities = [],
1129
+ anchors = [],
1130
+ occupants = [],
1131
+ relationships = [],
1132
+ openings = [],
1133
+ units = [],
1134
+ kiosks = [],
1135
+ levels = []
1278
1136
  }
1279
- const {
1280
- location,
1281
- distance,
1282
- threshold,
1283
- findAllMatches,
1284
- minMatchCharLength,
1285
- ignoreLocation
1286
- } = this.options;
1287
- let allIndices = [];
1288
- let totalScore = 0;
1289
- let hasMatches = false;
1290
- this.chunks.forEach(({ pattern, alphabet, startIndex }) => {
1291
- const { isMatch, score, indices } = search(text, pattern, alphabet, {
1292
- location: location + startIndex,
1293
- distance,
1294
- threshold,
1295
- findAllMatches,
1296
- minMatchCharLength,
1297
- includeMatches,
1298
- ignoreLocation
1299
- });
1300
- if (isMatch) {
1301
- hasMatches = true;
1302
- }
1303
- totalScore += score;
1304
- if (isMatch && indices) {
1305
- allIndices = [...allIndices, ...indices];
1137
+ } = options;
1138
+ const {
1139
+ traversal: traversalRelationships = [],
1140
+ escalator: escalatorRelationships = [],
1141
+ ramp: rampRelationships = [],
1142
+ elevator: elevatorRelationships = [],
1143
+ stairs: stairsRelationships = []
1144
+ } = _6.groupBy(relationships, "properties.category");
1145
+ const unitOpenings = createUnitOpenings(traversalRelationships, units, openings);
1146
+ const traversalNodeMap = createTraversalNodeMap(unitOpenings, options);
1147
+ const escalatorNodeMap = createEscalatorNodeMap(escalatorRelationships, options);
1148
+ const rampNodeMap = createRampNodeMap(rampRelationships, options);
1149
+ const elevatorNodeMap = createElevatorNodeMap(
1150
+ elevatorRelationships,
1151
+ unitOpenings,
1152
+ options
1153
+ );
1154
+ const stairNodeMap = createStairNodeMap(
1155
+ stairsRelationships,
1156
+ unitOpenings,
1157
+ options
1158
+ );
1159
+ const amenityNodeMap = createPOINodeMap(amenities, (amenity) => amenity.properties.unit_ids[0], unitOpenings);
1160
+ const anchorsNodeMap = createPOINodeMap(anchors, (anchor) => anchor.properties.unit_id, unitOpenings);
1161
+ const walkwayUnits = units.filter((unit) => unit.properties.category === "walkway");
1162
+ const kioskNodeMap = createPOINodeMap(kiosks, (kiosk) => findContainingUnit(kiosk, walkwayUnits)?.id, unitOpenings);
1163
+ const unitNodeMap = createPOINodeMap(units, (unit) => unit.id, unitOpenings);
1164
+ const occupantNodeMap = createOccupantNodeMap(occupants);
1165
+ const defaultGraph = new DijstraGraph(mergeNodeMap([
1166
+ traversalNodeMap,
1167
+ escalatorNodeMap,
1168
+ rampNodeMap,
1169
+ elevatorNodeMap,
1170
+ stairNodeMap,
1171
+ amenityNodeMap,
1172
+ anchorsNodeMap,
1173
+ kioskNodeMap,
1174
+ unitNodeMap,
1175
+ occupantNodeMap
1176
+ ]));
1177
+ const accessibleGraph = new DijstraGraph(mergeNodeMap([
1178
+ traversalNodeMap,
1179
+ rampNodeMap,
1180
+ elevatorNodeMap,
1181
+ amenityNodeMap,
1182
+ anchorsNodeMap,
1183
+ kioskNodeMap,
1184
+ unitNodeMap,
1185
+ occupantNodeMap
1186
+ ]));
1187
+ const addCoordinateOrdinalNode = (params, locatedOnUnit) => {
1188
+ const [lat, lng, ordinal] = parseOrdinalCoordinate(params);
1189
+ if (locatedOnUnit) {
1190
+ const openings2 = unitOpenings[locatedOnUnit.id];
1191
+ for (const opening of openings2) {
1192
+ const openingCenter = turfCenter3(opening);
1193
+ const dis = distance2([lat, lng], openingCenter, { units: "meters" });
1194
+ defaultGraph.addNode(params, { [opening.id]: dis }).addNode(opening.id, { [params]: dis });
1195
+ accessibleGraph.addNode(params, { [opening.id]: dis }).addNode(opening.id, { [params]: dis });
1306
1196
  }
1307
- });
1308
- let result = {
1309
- isMatch: hasMatches,
1310
- score: hasMatches ? totalScore / this.chunks.length : 1
1311
- };
1312
- if (hasMatches && includeMatches) {
1313
- result.indices = allIndices;
1314
1197
  }
1315
- return result;
1316
- }
1198
+ };
1199
+ return { defaultGraph, accessibleGraph, unitOpenings, addCoordinateOrdinalNode };
1317
1200
  };
1318
- var BaseMatch = class {
1319
- constructor(pattern) {
1320
- this.pattern = pattern;
1321
- }
1322
- static isMultiMatch(pattern) {
1323
- return getMatch(pattern, this.multiRegex);
1324
- }
1325
- static isSingleMatch(pattern) {
1326
- return getMatch(pattern, this.singleRegex);
1327
- }
1328
- search() {
1329
- }
1330
- };
1331
- function getMatch(pattern, exp) {
1332
- const matches = pattern.match(exp);
1333
- return matches ? matches[1] : null;
1334
- }
1335
- var ExactMatch = class extends BaseMatch {
1336
- constructor(pattern) {
1337
- super(pattern);
1338
- }
1339
- static get type() {
1340
- return "exact";
1341
- }
1342
- static get multiRegex() {
1343
- return /^="(.*)"$/;
1344
- }
1345
- static get singleRegex() {
1346
- return /^=(.*)$/;
1347
- }
1348
- search(text) {
1349
- const isMatch = text === this.pattern;
1350
- return {
1351
- isMatch,
1352
- score: isMatch ? 0 : 1,
1353
- indices: [0, this.pattern.length - 1]
1354
- };
1355
- }
1201
+
1202
+ // src/data/navigate/steps/createStepUtils.ts
1203
+ import { capitalize } from "lodash";
1204
+ import _intersectionBy from "lodash/intersectionBy";
1205
+ import { center as center6 } from "@turf/center";
1206
+
1207
+ // src/data/navigate/description/describe.ts
1208
+ var t = (template, locale, options) => {
1209
+ return template.replace(`{{intermediary}}`, options.intermediary ?? "").replace(`{{toward}}`, options.toward?.[locale] ?? "").replace(`{{landmark}}`, options.landmark?.[locale] ?? "");
1356
1210
  };
1357
- var InverseExactMatch = class extends BaseMatch {
1358
- constructor(pattern) {
1359
- super(pattern);
1360
- }
1361
- static get type() {
1362
- return "inverse-exact";
1363
- }
1364
- static get multiRegex() {
1365
- return /^!"(.*)"$/;
1366
- }
1367
- static get singleRegex() {
1368
- return /^!(.*)$/;
1369
- }
1370
- search(text) {
1371
- const index = text.indexOf(this.pattern);
1372
- const isMatch = index === -1;
1373
- return {
1374
- isMatch,
1375
- score: isMatch ? 0 : 1,
1376
- indices: [0, text.length - 1]
1377
- };
1378
- }
1211
+ var describeVerticalStep = (fromLevel, toLevel, intermediary) => {
1212
+ const dir = fromLevel.properties.ordinal < toLevel.properties.ordinal ? "up" : "down";
1213
+ const template = `Take the {{intermediary}} ${dir} to {{toward}}`;
1214
+ return {
1215
+ template,
1216
+ text: t(template, "en", { intermediary, toward: toLevel.properties.name })
1217
+ };
1379
1218
  };
1380
- var PrefixExactMatch = class extends BaseMatch {
1381
- constructor(pattern) {
1382
- super(pattern);
1383
- }
1384
- static get type() {
1385
- return "prefix-exact";
1386
- }
1387
- static get multiRegex() {
1388
- return /^\^"(.*)"$/;
1389
- }
1390
- static get singleRegex() {
1391
- return /^\^(.*)$/;
1392
- }
1393
- search(text) {
1394
- const isMatch = text.startsWith(this.pattern);
1395
- return {
1396
- isMatch,
1397
- score: isMatch ? 0 : 1,
1398
- indices: [0, this.pattern.length - 1]
1399
- };
1400
- }
1219
+ var describeHorizontalStep = (intermediary, toward, landmark) => {
1220
+ const template = `Follow the path ${intermediary === "walkway" ? `along the walkway` : `through {{intermediary}}`} ${toward ? `toward {{toward}}` : ``} ${landmark ? `near {{landmark}}` : ``}`.trim();
1221
+ return {
1222
+ text: t(template, "en", { intermediary, toward, landmark }),
1223
+ template
1224
+ };
1401
1225
  };
1402
- var InversePrefixExactMatch = class extends BaseMatch {
1403
- constructor(pattern) {
1404
- super(pattern);
1405
- }
1406
- static get type() {
1407
- return "inverse-prefix-exact";
1408
- }
1409
- static get multiRegex() {
1410
- return /^!\^"(.*)"$/;
1411
- }
1412
- static get singleRegex() {
1413
- return /^!\^(.*)$/;
1414
- }
1415
- search(text) {
1416
- const isMatch = !text.startsWith(this.pattern);
1417
- return {
1418
- isMatch,
1419
- score: isMatch ? 0 : 1,
1420
- indices: [0, text.length - 1]
1421
- };
1422
- }
1226
+
1227
+ // src/data/navigate/steps/path/index.ts
1228
+ import _7 from "lodash";
1229
+
1230
+ // src/data/navigate/constants.ts
1231
+ var OBSTACLE_FEATURE_TYPES = [
1232
+ "kiosk"
1233
+ /* , "fixture" */
1234
+ ];
1235
+ var OBSTACLE_CATEGORIES = [
1236
+ "fixture.water",
1237
+ "fixture.stage",
1238
+ "nonpublic",
1239
+ "opentobelow",
1240
+ "elevator",
1241
+ "escalator",
1242
+ "stairs",
1243
+ "stairs.emergencyexit",
1244
+ "room",
1245
+ "unspecified",
1246
+ "structure",
1247
+ "brick",
1248
+ "concrete",
1249
+ "drywall",
1250
+ "glass",
1251
+ "wood",
1252
+ "column"
1253
+ ];
1254
+ var WALKABLE_CATEGORY = [
1255
+ "walkway",
1256
+ "parking",
1257
+ "room",
1258
+ "terrace",
1259
+ "unenclosedarea",
1260
+ "vegetation",
1261
+ "unspecified"
1262
+ ];
1263
+
1264
+ // node_modules/@turf/helpers/dist/esm/index.js
1265
+ var earthRadius = 63710088e-1;
1266
+ var factors = {
1267
+ centimeters: earthRadius * 100,
1268
+ centimetres: earthRadius * 100,
1269
+ degrees: 360 / (2 * Math.PI),
1270
+ feet: earthRadius * 3.28084,
1271
+ inches: earthRadius * 39.37,
1272
+ kilometers: earthRadius / 1e3,
1273
+ kilometres: earthRadius / 1e3,
1274
+ meters: earthRadius,
1275
+ metres: earthRadius,
1276
+ miles: earthRadius / 1609.344,
1277
+ millimeters: earthRadius * 1e3,
1278
+ millimetres: earthRadius * 1e3,
1279
+ nauticalmiles: earthRadius / 1852,
1280
+ radians: 1,
1281
+ yards: earthRadius * 1.0936
1423
1282
  };
1424
- var SuffixExactMatch = class extends BaseMatch {
1425
- constructor(pattern) {
1426
- super(pattern);
1283
+ function feature(geom, properties, options = {}) {
1284
+ const feat = { type: "Feature" };
1285
+ if (options.id === 0 || options.id) {
1286
+ feat.id = options.id;
1427
1287
  }
1428
- static get type() {
1429
- return "suffix-exact";
1288
+ if (options.bbox) {
1289
+ feat.bbox = options.bbox;
1430
1290
  }
1431
- static get multiRegex() {
1432
- return /^"(.*)"\$$/;
1291
+ feat.properties = properties || {};
1292
+ feat.geometry = geom;
1293
+ return feat;
1294
+ }
1295
+ function point(coordinates, properties, options = {}) {
1296
+ if (!coordinates) {
1297
+ throw new Error("coordinates is required");
1433
1298
  }
1434
- static get singleRegex() {
1435
- return /^(.*)\$$/;
1299
+ if (!Array.isArray(coordinates)) {
1300
+ throw new Error("coordinates must be an Array");
1436
1301
  }
1437
- search(text) {
1438
- const isMatch = text.endsWith(this.pattern);
1439
- return {
1440
- isMatch,
1441
- score: isMatch ? 0 : 1,
1442
- indices: [text.length - this.pattern.length, text.length - 1]
1443
- };
1302
+ if (coordinates.length < 2) {
1303
+ throw new Error("coordinates must be at least 2 numbers long");
1444
1304
  }
1445
- };
1446
- var InverseSuffixExactMatch = class extends BaseMatch {
1447
- constructor(pattern) {
1448
- super(pattern);
1305
+ if (!isNumber(coordinates[0]) || !isNumber(coordinates[1])) {
1306
+ throw new Error("coordinates must contain numbers");
1449
1307
  }
1450
- static get type() {
1451
- return "inverse-suffix-exact";
1308
+ const geom = {
1309
+ type: "Point",
1310
+ coordinates
1311
+ };
1312
+ return feature(geom, properties, options);
1313
+ }
1314
+ function polygon(coordinates, properties, options = {}) {
1315
+ for (const ring of coordinates) {
1316
+ if (ring.length < 4) {
1317
+ throw new Error(
1318
+ "Each LinearRing of a Polygon must have 4 or more Positions."
1319
+ );
1320
+ }
1321
+ if (ring[ring.length - 1].length !== ring[0].length) {
1322
+ throw new Error("First and last Position are not equivalent.");
1323
+ }
1324
+ for (let j = 0; j < ring[ring.length - 1].length; j++) {
1325
+ if (ring[ring.length - 1][j] !== ring[0][j]) {
1326
+ throw new Error("First and last Position are not equivalent.");
1327
+ }
1328
+ }
1452
1329
  }
1453
- static get multiRegex() {
1454
- return /^!"(.*)"\$$/;
1330
+ const geom = {
1331
+ type: "Polygon",
1332
+ coordinates
1333
+ };
1334
+ return feature(geom, properties, options);
1335
+ }
1336
+ function lineString(coordinates, properties, options = {}) {
1337
+ if (coordinates.length < 2) {
1338
+ throw new Error("coordinates must be an array of two or more positions");
1455
1339
  }
1456
- static get singleRegex() {
1457
- return /^!(.*)\$$/;
1340
+ const geom = {
1341
+ type: "LineString",
1342
+ coordinates
1343
+ };
1344
+ return feature(geom, properties, options);
1345
+ }
1346
+ function featureCollection(features, options = {}) {
1347
+ const fc = { type: "FeatureCollection" };
1348
+ if (options.id) {
1349
+ fc.id = options.id;
1458
1350
  }
1459
- search(text) {
1460
- const isMatch = !text.endsWith(this.pattern);
1461
- return {
1462
- isMatch,
1463
- score: isMatch ? 0 : 1,
1464
- indices: [0, text.length - 1]
1465
- };
1351
+ if (options.bbox) {
1352
+ fc.bbox = options.bbox;
1466
1353
  }
1467
- };
1468
- var FuzzyMatch = class extends BaseMatch {
1469
- constructor(pattern, {
1470
- location = Config.location,
1471
- threshold = Config.threshold,
1472
- distance = Config.distance,
1473
- includeMatches = Config.includeMatches,
1474
- findAllMatches = Config.findAllMatches,
1475
- minMatchCharLength = Config.minMatchCharLength,
1476
- isCaseSensitive = Config.isCaseSensitive,
1477
- ignoreDiacritics = Config.ignoreDiacritics,
1478
- ignoreLocation = Config.ignoreLocation
1479
- } = {}) {
1480
- super(pattern);
1481
- this._bitapSearch = new BitapSearch(pattern, {
1482
- location,
1483
- threshold,
1484
- distance,
1485
- includeMatches,
1486
- findAllMatches,
1487
- minMatchCharLength,
1488
- isCaseSensitive,
1489
- ignoreDiacritics,
1490
- ignoreLocation
1491
- });
1354
+ fc.features = features;
1355
+ return fc;
1356
+ }
1357
+ function multiPoint(coordinates, properties, options = {}) {
1358
+ const geom = {
1359
+ type: "MultiPoint",
1360
+ coordinates
1361
+ };
1362
+ return feature(geom, properties, options);
1363
+ }
1364
+ function isNumber(num) {
1365
+ return !isNaN(num) && num !== null && !Array.isArray(num);
1366
+ }
1367
+ function isObject(input) {
1368
+ return input !== null && typeof input === "object" && !Array.isArray(input);
1369
+ }
1370
+
1371
+ // node_modules/@turf/invariant/dist/esm/index.js
1372
+ function getCoord(coord) {
1373
+ if (!coord) {
1374
+ throw new Error("coord is required");
1375
+ }
1376
+ if (!Array.isArray(coord)) {
1377
+ if (coord.type === "Feature" && coord.geometry !== null && coord.geometry.type === "Point") {
1378
+ return [...coord.geometry.coordinates];
1379
+ }
1380
+ if (coord.type === "Point") {
1381
+ return [...coord.coordinates];
1382
+ }
1492
1383
  }
1493
- static get type() {
1494
- return "fuzzy";
1384
+ if (Array.isArray(coord) && coord.length >= 2 && !Array.isArray(coord[0]) && !Array.isArray(coord[1])) {
1385
+ return [...coord];
1495
1386
  }
1496
- static get multiRegex() {
1497
- return /^"(.*)"$/;
1387
+ throw new Error("coord must be GeoJSON Point or an Array of numbers");
1388
+ }
1389
+ function getGeom(geojson) {
1390
+ if (geojson.type === "Feature") {
1391
+ return geojson.geometry;
1498
1392
  }
1499
- static get singleRegex() {
1500
- return /^(.*)$/;
1393
+ return geojson;
1394
+ }
1395
+ function getType(geojson, _name) {
1396
+ if (geojson.type === "FeatureCollection") {
1397
+ return "FeatureCollection";
1501
1398
  }
1502
- search(text) {
1503
- return this._bitapSearch.searchIn(text);
1399
+ if (geojson.type === "GeometryCollection") {
1400
+ return "GeometryCollection";
1504
1401
  }
1505
- };
1506
- var IncludeMatch = class extends BaseMatch {
1507
- constructor(pattern) {
1508
- super(pattern);
1509
- }
1510
- static get type() {
1511
- return "include";
1512
- }
1513
- static get multiRegex() {
1514
- return /^'"(.*)"$/;
1515
- }
1516
- static get singleRegex() {
1517
- return /^'(.*)$/;
1518
- }
1519
- search(text) {
1520
- let location = 0;
1521
- let index;
1522
- const indices = [];
1523
- const patternLen = this.pattern.length;
1524
- while ((index = text.indexOf(this.pattern, location)) > -1) {
1525
- location = index + patternLen;
1526
- indices.push([index, location - 1]);
1527
- }
1528
- const isMatch = !!indices.length;
1529
- return {
1530
- isMatch,
1531
- score: isMatch ? 0 : 1,
1532
- indices
1533
- };
1402
+ if (geojson.type === "Feature" && geojson.geometry !== null) {
1403
+ return geojson.geometry.type;
1534
1404
  }
1535
- };
1536
- var searchers = [
1537
- ExactMatch,
1538
- IncludeMatch,
1539
- PrefixExactMatch,
1540
- InversePrefixExactMatch,
1541
- InverseSuffixExactMatch,
1542
- SuffixExactMatch,
1543
- InverseExactMatch,
1544
- FuzzyMatch
1545
- ];
1546
- var searchersLen = searchers.length;
1547
- var SPACE_RE = / +(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/;
1548
- var OR_TOKEN = "|";
1549
- function parseQuery(pattern, options = {}) {
1550
- return pattern.split(OR_TOKEN).map((item) => {
1551
- let query = item.trim().split(SPACE_RE).filter((item2) => item2 && !!item2.trim());
1552
- let results = [];
1553
- for (let i = 0, len = query.length; i < len; i += 1) {
1554
- const queryItem = query[i];
1555
- let found = false;
1556
- let idx = -1;
1557
- while (!found && ++idx < searchersLen) {
1558
- const searcher = searchers[idx];
1559
- let token = searcher.isMultiMatch(queryItem);
1560
- if (token) {
1561
- results.push(new searcher(token, options));
1562
- found = true;
1563
- }
1564
- }
1565
- if (found) {
1566
- continue;
1567
- }
1568
- idx = -1;
1569
- while (++idx < searchersLen) {
1570
- const searcher = searchers[idx];
1571
- let token = searcher.isSingleMatch(queryItem);
1572
- if (token) {
1573
- results.push(new searcher(token, options));
1574
- break;
1575
- }
1576
- }
1577
- }
1578
- return results;
1579
- });
1405
+ return geojson.type;
1580
1406
  }
1581
- var MultiMatchSet = /* @__PURE__ */ new Set([FuzzyMatch.type, IncludeMatch.type]);
1582
- var ExtendedSearch = class {
1583
- constructor(pattern, {
1584
- isCaseSensitive = Config.isCaseSensitive,
1585
- ignoreDiacritics = Config.ignoreDiacritics,
1586
- includeMatches = Config.includeMatches,
1587
- minMatchCharLength = Config.minMatchCharLength,
1588
- ignoreLocation = Config.ignoreLocation,
1589
- findAllMatches = Config.findAllMatches,
1590
- location = Config.location,
1591
- threshold = Config.threshold,
1592
- distance = Config.distance
1593
- } = {}) {
1594
- this.query = null;
1595
- this.options = {
1596
- isCaseSensitive,
1597
- ignoreDiacritics,
1598
- includeMatches,
1599
- minMatchCharLength,
1600
- findAllMatches,
1601
- ignoreLocation,
1602
- location,
1603
- threshold,
1604
- distance
1605
- };
1606
- pattern = isCaseSensitive ? pattern : pattern.toLowerCase();
1607
- pattern = ignoreDiacritics ? stripDiacritics(pattern) : pattern;
1608
- this.pattern = pattern;
1609
- this.query = parseQuery(this.pattern, this.options);
1610
- }
1611
- static condition(_6, options) {
1612
- return options.useExtendedSearch;
1613
- }
1614
- searchIn(text) {
1615
- const query = this.query;
1616
- if (!query) {
1617
- return {
1618
- isMatch: false,
1619
- score: 1
1620
- };
1621
- }
1622
- const { includeMatches, isCaseSensitive, ignoreDiacritics } = this.options;
1623
- text = isCaseSensitive ? text : text.toLowerCase();
1624
- text = ignoreDiacritics ? stripDiacritics(text) : text;
1625
- let numMatches = 0;
1626
- let allIndices = [];
1627
- let totalScore = 0;
1628
- for (let i = 0, qLen = query.length; i < qLen; i += 1) {
1629
- const searchers2 = query[i];
1630
- allIndices.length = 0;
1631
- numMatches = 0;
1632
- for (let j = 0, pLen = searchers2.length; j < pLen; j += 1) {
1633
- const searcher = searchers2[j];
1634
- const { isMatch, indices, score } = searcher.search(text);
1635
- if (isMatch) {
1636
- numMatches += 1;
1637
- totalScore += score;
1638
- if (includeMatches) {
1639
- const type = searcher.constructor.type;
1640
- if (MultiMatchSet.has(type)) {
1641
- allIndices = [...allIndices, ...indices];
1642
- } else {
1643
- allIndices.push(indices);
1407
+
1408
+ // src/data/navigate/steps/path/index.ts
1409
+ import difference from "@turf/difference";
1410
+ import envelope from "@turf/envelope";
1411
+ import booleanOverlap from "@turf/boolean-overlap";
1412
+ import booleanIntersects from "@turf/boolean-intersects";
1413
+
1414
+ // ../../node_modules/@turf/meta/dist/esm/index.js
1415
+ function coordEach(geojson, callback, excludeWrapCoord) {
1416
+ if (geojson === null) return;
1417
+ var j, k, l, geometry, stopG, coords, geometryMaybeCollection, wrapShrink = 0, coordIndex = 0, isGeometryCollection, type = geojson.type, isFeatureCollection = type === "FeatureCollection", isFeature = type === "Feature", stop = isFeatureCollection ? geojson.features.length : 1;
1418
+ for (var featureIndex = 0; featureIndex < stop; featureIndex++) {
1419
+ geometryMaybeCollection = isFeatureCollection ? geojson.features[featureIndex].geometry : isFeature ? geojson.geometry : geojson;
1420
+ isGeometryCollection = geometryMaybeCollection ? geometryMaybeCollection.type === "GeometryCollection" : false;
1421
+ stopG = isGeometryCollection ? geometryMaybeCollection.geometries.length : 1;
1422
+ for (var geomIndex = 0; geomIndex < stopG; geomIndex++) {
1423
+ var multiFeatureIndex = 0;
1424
+ var geometryIndex = 0;
1425
+ geometry = isGeometryCollection ? geometryMaybeCollection.geometries[geomIndex] : geometryMaybeCollection;
1426
+ if (geometry === null) continue;
1427
+ coords = geometry.coordinates;
1428
+ var geomType = geometry.type;
1429
+ wrapShrink = excludeWrapCoord && (geomType === "Polygon" || geomType === "MultiPolygon") ? 1 : 0;
1430
+ switch (geomType) {
1431
+ case null:
1432
+ break;
1433
+ case "Point":
1434
+ if (callback(
1435
+ coords,
1436
+ coordIndex,
1437
+ featureIndex,
1438
+ multiFeatureIndex,
1439
+ geometryIndex
1440
+ ) === false)
1441
+ return false;
1442
+ coordIndex++;
1443
+ multiFeatureIndex++;
1444
+ break;
1445
+ case "LineString":
1446
+ case "MultiPoint":
1447
+ for (j = 0; j < coords.length; j++) {
1448
+ if (callback(
1449
+ coords[j],
1450
+ coordIndex,
1451
+ featureIndex,
1452
+ multiFeatureIndex,
1453
+ geometryIndex
1454
+ ) === false)
1455
+ return false;
1456
+ coordIndex++;
1457
+ if (geomType === "MultiPoint") multiFeatureIndex++;
1458
+ }
1459
+ if (geomType === "LineString") multiFeatureIndex++;
1460
+ break;
1461
+ case "Polygon":
1462
+ case "MultiLineString":
1463
+ for (j = 0; j < coords.length; j++) {
1464
+ for (k = 0; k < coords[j].length - wrapShrink; k++) {
1465
+ if (callback(
1466
+ coords[j][k],
1467
+ coordIndex,
1468
+ featureIndex,
1469
+ multiFeatureIndex,
1470
+ geometryIndex
1471
+ ) === false)
1472
+ return false;
1473
+ coordIndex++;
1474
+ }
1475
+ if (geomType === "MultiLineString") multiFeatureIndex++;
1476
+ if (geomType === "Polygon") geometryIndex++;
1477
+ }
1478
+ if (geomType === "Polygon") multiFeatureIndex++;
1479
+ break;
1480
+ case "MultiPolygon":
1481
+ for (j = 0; j < coords.length; j++) {
1482
+ geometryIndex = 0;
1483
+ for (k = 0; k < coords[j].length; k++) {
1484
+ for (l = 0; l < coords[j][k].length - wrapShrink; l++) {
1485
+ if (callback(
1486
+ coords[j][k][l],
1487
+ coordIndex,
1488
+ featureIndex,
1489
+ multiFeatureIndex,
1490
+ geometryIndex
1491
+ ) === false)
1492
+ return false;
1493
+ coordIndex++;
1494
+ }
1495
+ geometryIndex++;
1644
1496
  }
1497
+ multiFeatureIndex++;
1645
1498
  }
1646
- } else {
1647
- totalScore = 0;
1648
- numMatches = 0;
1649
- allIndices.length = 0;
1650
1499
  break;
1651
- }
1652
- }
1653
- if (numMatches) {
1654
- let result = {
1655
- isMatch: true,
1656
- score: totalScore / numMatches
1657
- };
1658
- if (includeMatches) {
1659
- result.indices = allIndices;
1660
- }
1661
- return result;
1500
+ case "GeometryCollection":
1501
+ for (j = 0; j < geometry.geometries.length; j++)
1502
+ if (coordEach(geometry.geometries[j], callback, excludeWrapCoord) === false)
1503
+ return false;
1504
+ break;
1505
+ default:
1506
+ throw new Error("Unknown Geometry Type");
1662
1507
  }
1663
1508
  }
1664
- return {
1665
- isMatch: false,
1666
- score: 1
1667
- };
1668
1509
  }
1669
- };
1670
- var registeredSearchers = [];
1671
- function register(...args) {
1672
- registeredSearchers.push(...args);
1673
1510
  }
1674
- function createSearcher(pattern, options) {
1675
- for (let i = 0, len = registeredSearchers.length; i < len; i += 1) {
1676
- let searcherClass = registeredSearchers[i];
1677
- if (searcherClass.condition(pattern, options)) {
1678
- return new searcherClass(pattern, options);
1679
- }
1511
+
1512
+ // ../../node_modules/@turf/bbox/dist/esm/index.js
1513
+ function bbox(geojson, options = {}) {
1514
+ if (geojson.bbox != null && true !== options.recompute) {
1515
+ return geojson.bbox;
1680
1516
  }
1681
- return new BitapSearch(pattern, options);
1682
- }
1683
- var LogicalOperator = {
1684
- AND: "$and",
1685
- OR: "$or"
1686
- };
1687
- var KeyType = {
1688
- PATH: "$path",
1689
- PATTERN: "$val"
1690
- };
1691
- var isExpression = (query) => !!(query[LogicalOperator.AND] || query[LogicalOperator.OR]);
1692
- var isPath = (query) => !!query[KeyType.PATH];
1693
- var isLeaf = (query) => !isArray(query) && isObject(query) && !isExpression(query);
1694
- var convertToExplicit = (query) => ({
1695
- [LogicalOperator.AND]: Object.keys(query).map((key) => ({
1696
- [key]: query[key]
1697
- }))
1698
- });
1699
- function parse(query, options, { auto = true } = {}) {
1700
- const next = (query2) => {
1701
- let keys = Object.keys(query2);
1702
- const isQueryPath = isPath(query2);
1703
- if (!isQueryPath && keys.length > 1 && !isExpression(query2)) {
1704
- return next(convertToExplicit(query2));
1517
+ const result = [Infinity, Infinity, -Infinity, -Infinity];
1518
+ coordEach(geojson, (coord) => {
1519
+ if (result[0] > coord[0]) {
1520
+ result[0] = coord[0];
1705
1521
  }
1706
- if (isLeaf(query2)) {
1707
- const key = isQueryPath ? query2[KeyType.PATH] : keys[0];
1708
- const pattern = isQueryPath ? query2[KeyType.PATTERN] : query2[key];
1709
- if (!isString(pattern)) {
1710
- throw new Error(LOGICAL_SEARCH_INVALID_QUERY_FOR_KEY(key));
1711
- }
1712
- const obj = {
1713
- keyId: createKeyId(key),
1714
- pattern
1715
- };
1716
- if (auto) {
1717
- obj.searcher = createSearcher(pattern, options);
1718
- }
1719
- return obj;
1522
+ if (result[1] > coord[1]) {
1523
+ result[1] = coord[1];
1524
+ }
1525
+ if (result[2] < coord[0]) {
1526
+ result[2] = coord[0];
1527
+ }
1528
+ if (result[3] < coord[1]) {
1529
+ result[3] = coord[1];
1720
1530
  }
1721
- let node = {
1722
- children: [],
1723
- operator: keys[0]
1724
- };
1725
- keys.forEach((key) => {
1726
- const value = query2[key];
1727
- if (isArray(value)) {
1728
- value.forEach((item) => {
1729
- node.children.push(next(item));
1730
- });
1731
- }
1732
- });
1733
- return node;
1734
- };
1735
- if (!isExpression(query)) {
1736
- query = convertToExplicit(query);
1737
- }
1738
- return next(query);
1739
- }
1740
- function computeScore(results, { ignoreFieldNorm = Config.ignoreFieldNorm }) {
1741
- results.forEach((result) => {
1742
- let totalScore = 1;
1743
- result.matches.forEach(({ key, norm: norm2, score }) => {
1744
- const weight = key ? key.weight : null;
1745
- totalScore *= Math.pow(
1746
- score === 0 && weight ? Number.EPSILON : score,
1747
- (weight || 1) * (ignoreFieldNorm ? 1 : norm2)
1748
- );
1749
- });
1750
- result.score = totalScore;
1751
1531
  });
1532
+ return result;
1752
1533
  }
1753
- function transformMatches(result, data) {
1754
- const matches = result.matches;
1755
- data.matches = [];
1756
- if (!isDefined(matches)) {
1757
- return;
1758
- }
1759
- matches.forEach((match) => {
1760
- if (!isDefined(match.indices) || !match.indices.length) {
1761
- return;
1762
- }
1763
- const { indices, value } = match;
1764
- let obj = {
1765
- indices,
1766
- value
1767
- };
1768
- if (match.key) {
1769
- obj.key = match.key.src;
1534
+ var index_default = bbox;
1535
+
1536
+ // src/data/navigate/steps/path/turf/shortestPath.ts
1537
+ import booleanPointInPolygon3 from "@turf/boolean-point-in-polygon";
1538
+ import distance3 from "@turf/distance";
1539
+ import scale from "@turf/transform-scale";
1540
+ import union from "@turf/union";
1541
+ import bboxPolygon from "@turf/bbox-polygon";
1542
+ import { cleanCoords } from "@turf/clean-coords";
1543
+ import PF from "pathfinding";
1544
+ import set3 from "lodash/set";
1545
+
1546
+ // src/data/navigate/steps/path/turf/stringPull.ts
1547
+ function stringPull(grid, path) {
1548
+ const isWalkable = (x, y) => grid.isInside(x, y) && grid.isWalkableAt(x, y);
1549
+ function hasLOS(a, b) {
1550
+ let x0 = a[0], y0 = a[1];
1551
+ const x1 = b[0], y1 = b[1];
1552
+ if (!isWalkable(x0, y0) || !isWalkable(x1, y1)) return false;
1553
+ const dx = Math.abs(x1 - x0);
1554
+ const dy = Math.abs(y1 - y0);
1555
+ const sx = x0 < x1 ? 1 : -1;
1556
+ const sy = y0 < y1 ? 1 : -1;
1557
+ let err = dx - dy;
1558
+ while (true) {
1559
+ if (!isWalkable(x0, y0)) return false;
1560
+ if (x0 === x1 && y0 === y1) break;
1561
+ const e2 = err * 2;
1562
+ let nx = x0;
1563
+ let ny = y0;
1564
+ let movedX = false;
1565
+ let movedY = false;
1566
+ if (e2 > -dy) {
1567
+ err -= dy;
1568
+ nx += sx;
1569
+ movedX = true;
1570
+ }
1571
+ if (e2 < dx) {
1572
+ err += dx;
1573
+ ny += sy;
1574
+ movedY = true;
1575
+ }
1576
+ if (movedX && movedY) {
1577
+ if (!isWalkable(nx, y0) || !isWalkable(x0, ny)) return false;
1578
+ }
1579
+ x0 = nx;
1580
+ y0 = ny;
1770
1581
  }
1771
- if (match.idx > -1) {
1772
- obj.refIndex = match.idx;
1582
+ return true;
1583
+ }
1584
+ if (path.length <= 2) return path;
1585
+ const out = [path[0]];
1586
+ let i = 0;
1587
+ while (i < path.length - 1) {
1588
+ let best = i + 1;
1589
+ for (let j = i + 2; j < path.length; j++) {
1590
+ if (hasLOS(path[i], path[j])) best = j;
1591
+ else break;
1773
1592
  }
1774
- data.matches.push(obj);
1775
- });
1593
+ out.push(path[best]);
1594
+ i = best;
1595
+ }
1596
+ return out;
1776
1597
  }
1777
- function transformScore(result, data) {
1778
- data.score = result.score;
1598
+
1599
+ // src/data/navigate/steps/path/turf/pruneSmallAngle.ts
1600
+ function pruneSmallAngles(path, minDeg = 10) {
1601
+ if (path.length <= 2) return path;
1602
+ const out = [path[0]];
1603
+ for (let i = 1; i < path.length - 1; i++) {
1604
+ const a = out[out.length - 1];
1605
+ const b = path[i];
1606
+ const c = path[i + 1];
1607
+ const abx = b[0] - a[0], aby = b[1] - a[1];
1608
+ const bcx = c[0] - b[0], bcy = c[1] - b[1];
1609
+ const dot = abx * bcx + aby * bcy;
1610
+ const ab = Math.hypot(abx, aby);
1611
+ const bc = Math.hypot(bcx, bcy);
1612
+ const angle = Math.acos(dot / (ab * bc)) * 180 / Math.PI;
1613
+ if (angle > minDeg) out.push(b);
1614
+ }
1615
+ out.push(path[path.length - 1]);
1616
+ return out;
1779
1617
  }
1780
- function format(results, docs, {
1781
- includeMatches = Config.includeMatches,
1782
- includeScore = Config.includeScore
1783
- } = {}) {
1784
- const transformers = [];
1785
- if (includeMatches) transformers.push(transformMatches);
1786
- if (includeScore) transformers.push(transformScore);
1787
- return results.map((result) => {
1788
- const { idx } = result;
1789
- const data = {
1790
- item: docs[idx],
1791
- refIndex: idx
1792
- };
1793
- if (transformers.length) {
1794
- transformers.forEach((transformer) => {
1795
- transformer(result, data);
1796
- });
1618
+
1619
+ // src/data/navigate/steps/path/turf/pruneShortSegments.ts
1620
+ function pruneShortSegments(path, minLen = 5) {
1621
+ const out = [path[0]];
1622
+ for (let i = 1; i < path.length; i++) {
1623
+ const [x0, y0] = out[out.length - 1];
1624
+ const [x1, y1] = path[i];
1625
+ if (Math.hypot(x1 - x0, y1 - y0) >= minLen) {
1626
+ out.push(path[i]);
1797
1627
  }
1798
- return data;
1799
- });
1628
+ }
1629
+ return out;
1800
1630
  }
1801
- var Fuse = class {
1802
- constructor(docs, options = {}, index) {
1803
- this.options = { ...Config, ...options };
1804
- if (this.options.useExtendedSearch && false) {
1805
- throw new Error(EXTENDED_SEARCH_UNAVAILABLE);
1631
+
1632
+ // src/data/navigate/steps/path/turf/clearance.ts
1633
+ function buildClearanceGrid(matrix) {
1634
+ const h = matrix.length;
1635
+ const w = matrix[0].length;
1636
+ const INF = 1e9;
1637
+ const dist = Array.from({ length: h }, () => Array(w).fill(INF));
1638
+ const q = [];
1639
+ for (let y = 0; y < h; y++) {
1640
+ for (let x = 0; x < w; x++) {
1641
+ if (matrix[y][x] === 1) {
1642
+ dist[y][x] = 0;
1643
+ q.push([x, y]);
1644
+ }
1806
1645
  }
1807
- this._keyStore = new KeyStore(this.options.keys);
1808
- this.setCollection(docs, index);
1809
1646
  }
1810
- setCollection(docs, index) {
1811
- this._docs = docs;
1812
- if (index && !(index instanceof FuseIndex)) {
1813
- throw new Error(INCORRECT_INDEX_TYPE);
1647
+ const dirs = [
1648
+ [1, 0],
1649
+ [-1, 0],
1650
+ [0, 1],
1651
+ [0, -1],
1652
+ [1, 1],
1653
+ [1, -1],
1654
+ [-1, 1],
1655
+ [-1, -1]
1656
+ ];
1657
+ let qi = 0;
1658
+ while (qi < q.length) {
1659
+ const [x, y] = q[qi++];
1660
+ const d0 = dist[y][x];
1661
+ for (const [dx, dy] of dirs) {
1662
+ const nx = x + dx, ny = y + dy;
1663
+ if (nx < 0 || ny < 0 || nx >= w || ny >= h) continue;
1664
+ const nd = d0 + 1;
1665
+ if (nd < dist[ny][nx]) {
1666
+ dist[ny][nx] = nd;
1667
+ q.push([nx, ny]);
1668
+ }
1814
1669
  }
1815
- this._myIndex = index || createIndex(this.options.keys, this._docs, {
1816
- getFn: this.options.getFn,
1817
- fieldNormWeight: this.options.fieldNormWeight
1818
- });
1819
1670
  }
1820
- add(doc) {
1821
- if (!isDefined(doc)) {
1822
- return;
1823
- }
1824
- this._docs.push(doc);
1825
- this._myIndex.add(doc);
1826
- }
1827
- remove(predicate = () => false) {
1828
- const results = [];
1829
- for (let i = 0, len = this._docs.length; i < len; i += 1) {
1830
- const doc = this._docs[i];
1831
- if (predicate(doc, i)) {
1832
- this.removeAt(i);
1833
- i -= 1;
1834
- len -= 1;
1835
- results.push(doc);
1671
+ return dist;
1672
+ }
1673
+ function snapPointToClearancePeak(p, clearance, isWalkableCell, radius = 4) {
1674
+ const [px, py] = p;
1675
+ let best = p;
1676
+ let bestScore = clearance[py]?.[px] ?? -Infinity;
1677
+ for (let dy = -radius; dy <= radius; dy++) {
1678
+ for (let dx = -radius; dx <= radius; dx++) {
1679
+ const x = px + dx;
1680
+ const y = py + dy;
1681
+ if (!isWalkableCell(x, y)) continue;
1682
+ const score = clearance[y][x];
1683
+ const penalty = Math.hypot(dx, dy) * 5e-3;
1684
+ const finalScore = score - penalty;
1685
+ if (finalScore > bestScore) {
1686
+ bestScore = finalScore;
1687
+ best = [x, y];
1836
1688
  }
1837
1689
  }
1838
- return results;
1839
- }
1840
- removeAt(idx) {
1841
- this._docs.splice(idx, 1);
1842
- this._myIndex.removeAt(idx);
1843
1690
  }
1844
- getIndex() {
1845
- return this._myIndex;
1691
+ return best;
1692
+ }
1693
+ function centerlineSnapPath(path, clearance, isWalkableCell, radius = 4) {
1694
+ const snapped = path.map((p) => snapPointToClearancePeak(p, clearance, isWalkableCell, radius));
1695
+ return snapped;
1696
+ }
1697
+
1698
+ // src/data/navigate/steps/path/turf/shortestPath.ts
1699
+ function shortestPath(start, end, options) {
1700
+ options = options || {};
1701
+ if (!isObject(options)) throw new Error("options is invalid");
1702
+ let resolution = options.resolution;
1703
+ const smoothenPath = options.smoothenPath;
1704
+ let obstacles = options.obstacles || featureCollection([]);
1705
+ if (!start) throw new Error("start is required");
1706
+ if (!end) throw new Error("end is required");
1707
+ if (resolution && !isNumber(resolution) || resolution <= 0)
1708
+ throw new Error("options.resolution must be a number, greater than 0");
1709
+ const startCoord = getCoord(start);
1710
+ const endCoord = getCoord(end);
1711
+ start = point(startCoord);
1712
+ end = point(endCoord);
1713
+ switch (getType(obstacles)) {
1714
+ case "FeatureCollection":
1715
+ if (obstacles.features.length === 0)
1716
+ return lineString([startCoord, endCoord]);
1717
+ break;
1718
+ case "Polygon":
1719
+ obstacles = featureCollection([feature(getGeom(obstacles))]);
1720
+ break;
1721
+ default:
1722
+ throw new Error("invalid obstacles");
1723
+ }
1724
+ const collection = obstacles;
1725
+ collection.features.push(start, end);
1726
+ const box = index_default(scale(bboxPolygon(index_default(collection)), 1.15));
1727
+ if (!resolution) {
1728
+ const width = distance3([box[0], box[1]], [box[2], box[1]], options);
1729
+ resolution = width / 100;
1730
+ }
1731
+ collection.features.pop();
1732
+ collection.features.pop();
1733
+ const [west, south, east, north] = box;
1734
+ const xFraction = resolution / distance3([west, south], [east, south], options);
1735
+ const cellWidth = xFraction * (east - west);
1736
+ const yFraction = resolution / distance3([west, south], [west, north], options);
1737
+ const cellHeight = yFraction * (north - south);
1738
+ const bboxHorizontalSide = east - west;
1739
+ const bboxVerticalSide = north - south;
1740
+ const columns = Math.floor(bboxHorizontalSide / cellWidth);
1741
+ const rows = Math.floor(bboxVerticalSide / cellHeight);
1742
+ const deltaX = (bboxHorizontalSide - columns * cellWidth) / 2;
1743
+ const deltaY = (bboxVerticalSide - rows * cellHeight) / 2;
1744
+ let closestToStart = null, closestToEnd = null, minDistStart = Infinity, minDistEnd = Infinity, currentY = north - deltaY, currentX = west + deltaX, row = 0, column = 0, distStart, distEnd, pt, isInsideObstacle;
1745
+ const roundLoopY = Math.ceil((currentY - south) / cellHeight);
1746
+ const roundLoopX = Math.ceil((east - currentX) / cellWidth);
1747
+ let totalRounds = roundLoopX * roundLoopY;
1748
+ const pointMatrix = [];
1749
+ const matrix = [];
1750
+ const obstacleTotal = collection.features.length;
1751
+ const obstacleFeatures = collection.features;
1752
+ let combinedObstacle = obstacleFeatures[0];
1753
+ let obstacleIndex = 0;
1754
+ for (obstacleIndex = 0; obstacleIndex < obstacleTotal; obstacleIndex++) {
1755
+ const nextObstacleFeature = obstacleFeatures[obstacleIndex + 1];
1756
+ if (!nextObstacleFeature) continue;
1757
+ try {
1758
+ combinedObstacle = union(
1759
+ featureCollection([combinedObstacle, nextObstacleFeature])
1760
+ );
1761
+ } catch (e) {
1762
+ console.log(e);
1763
+ }
1846
1764
  }
1847
- search(query, { limit = -1 } = {}) {
1848
- const {
1849
- includeMatches,
1850
- includeScore,
1851
- shouldSort,
1852
- sortFn,
1853
- ignoreFieldNorm
1854
- } = this.options;
1855
- let results = isString(query) ? isString(this._docs[0]) ? this._searchStringList(query) : this._searchObjectList(query) : this._searchLogical(query);
1856
- computeScore(results, { ignoreFieldNorm });
1857
- if (shouldSort) {
1858
- results.sort(sortFn);
1765
+ while (totalRounds--) {
1766
+ pt = point([currentX, currentY]);
1767
+ isInsideObstacle = booleanPointInPolygon3(pt, combinedObstacle);
1768
+ set3(matrix, `[${row}][${column}]`, isInsideObstacle ? 1 : 0);
1769
+ set3(pointMatrix, `[${row}][${column}]`, `${currentX}|${currentY}`);
1770
+ distStart = distance3(pt, start);
1771
+ if (!isInsideObstacle && distStart < minDistStart) {
1772
+ minDistStart = distStart;
1773
+ closestToStart = { x: column, y: row };
1859
1774
  }
1860
- if (isNumber(limit) && limit > -1) {
1861
- results = results.slice(0, limit);
1775
+ distEnd = distance3(pt, end);
1776
+ if (!isInsideObstacle && distEnd < minDistEnd) {
1777
+ minDistEnd = distEnd;
1778
+ closestToEnd = { x: column, y: row };
1779
+ }
1780
+ if (column < roundLoopX) {
1781
+ currentX += cellWidth;
1782
+ column++;
1783
+ continue;
1784
+ }
1785
+ if (row < roundLoopY) {
1786
+ currentY -= cellHeight;
1787
+ currentX = west + deltaX;
1788
+ column = 0;
1789
+ row++;
1862
1790
  }
1863
- return format(results, this._docs, {
1864
- includeMatches,
1865
- includeScore
1866
- });
1867
1791
  }
1868
- _searchStringList(query) {
1869
- const searcher = createSearcher(query, this.options);
1870
- const { records } = this._myIndex;
1871
- const results = [];
1872
- records.forEach(({ v: text, i: idx, n: norm2 }) => {
1873
- if (!isDefined(text)) {
1874
- return;
1875
- }
1876
- const { isMatch, score, indices } = searcher.searchIn(text);
1877
- if (isMatch) {
1878
- results.push({
1879
- item: text,
1880
- idx,
1881
- matches: [{ score, value: text, norm: norm2, indices }]
1882
- });
1883
- }
1792
+ const finder = new PF.AStarFinder({
1793
+ allowDiagonal: true,
1794
+ dontCrossCorners: true,
1795
+ heuristic: PF.Heuristic.euclidean
1796
+ });
1797
+ const grid = new PF.Grid(matrix);
1798
+ const startOnMatrix = [closestToStart.x, closestToStart.y];
1799
+ const endOnMatrix = [closestToEnd.x, closestToEnd.y];
1800
+ let result = finder.findPath(...startOnMatrix, ...endOnMatrix, grid);
1801
+ if (result.length > 0) {
1802
+ result = stringPull(grid, result);
1803
+ const clearanceGrid = buildClearanceGrid(matrix);
1804
+ const isWalkable = (x, y) => grid.isInside(x, y) && grid.isWalkableAt(x, y);
1805
+ result = centerlineSnapPath(result, clearanceGrid, isWalkable);
1806
+ result = stringPull(grid, result);
1807
+ result = pruneSmallAngles(result);
1808
+ result = pruneShortSegments(result);
1809
+ }
1810
+ result.pop();
1811
+ result.shift();
1812
+ const path = [startCoord];
1813
+ result.forEach((coord) => {
1814
+ const coords = pointMatrix[coord[1]][coord[0]].split("|");
1815
+ path.push([+coords[0], +coords[1]]);
1816
+ });
1817
+ path.push(endCoord);
1818
+ return cleanCoords(lineString(path));
1819
+ }
1820
+ var shortestPath_default = shortestPath;
1821
+
1822
+ // src/data/navigate/steps/path/index.ts
1823
+ var createStepPathUtils = (options) => {
1824
+ const resolution = options.resolution ?? 88e-5;
1825
+ const { units, kiosks, fixtures } = options.data;
1826
+ const possibleObstacleFeatures = [...units, ...kiosks, ...fixtures];
1827
+ const filterObstaclesByOrdinal = (levelId) => {
1828
+ return possibleObstacleFeatures.filter(({ feature_type, properties, geometry }) => {
1829
+ return properties.level_id === levelId && ["Polygon", "MultiPolygon"].includes(geometry.type) && (OBSTACLE_FEATURE_TYPES.includes(feature_type) || "category" in properties && OBSTACLE_CATEGORIES.includes(properties.category));
1884
1830
  });
1885
- return results;
1886
- }
1887
- _searchLogical(query) {
1888
- const expression = parse(query, this.options);
1889
- const evaluate = (node, item, idx) => {
1890
- if (!node.children) {
1891
- const { keyId, searcher } = node;
1892
- const matches = this._findMatches({
1893
- key: this._keyStore.get(keyId),
1894
- value: this._myIndex.getValueForItemAtKeyId(item, keyId),
1895
- searcher
1896
- });
1897
- if (matches && matches.length) {
1898
- return [
1899
- {
1900
- idx,
1901
- item,
1902
- matches
1903
- }
1904
- ];
1905
- }
1906
- return [];
1907
- }
1908
- const res = [];
1909
- for (let i = 0, len = node.children.length; i < len; i += 1) {
1910
- const child = node.children[i];
1911
- const result = evaluate(child, item, idx);
1912
- if (result.length) {
1913
- res.push(...result);
1914
- } else if (node.operator === LogicalOperator.AND) {
1915
- return [];
1916
- }
1917
- }
1918
- return res;
1919
- };
1920
- const records = this._myIndex.records;
1921
- const resultMap = {};
1922
- const results = [];
1923
- records.forEach(({ $: item, i: idx }) => {
1924
- if (isDefined(item)) {
1925
- let expResults = evaluate(expression, item, idx);
1926
- if (expResults.length) {
1927
- if (!resultMap[idx]) {
1928
- resultMap[idx] = { idx, item, matches: [] };
1929
- results.push(resultMap[idx]);
1930
- }
1931
- expResults.forEach(({ matches }) => {
1932
- resultMap[idx].matches.push(...matches);
1933
- });
1831
+ };
1832
+ const findObstaclesFromWalkway = (intermediaryUnit, exceptionIds = []) => {
1833
+ const result = featureCollection([]);
1834
+ if (!intermediaryUnit) return result;
1835
+ const walkwayLevelId = intermediaryUnit.properties.level_id;
1836
+ const obstacleOnLevel = filterObstaclesByOrdinal(walkwayLevelId).filter(
1837
+ (obstacle) => !exceptionIds.includes(obstacle.id)
1838
+ );
1839
+ const relatedObstacleWithIntermediary = obstacleOnLevel.reduce(
1840
+ (obstacles, feature2) => {
1841
+ if (
1842
+ // Prevent detecting itself as an obstacle
1843
+ // Ex. Unable to draw a line to amenity located with in a room as room is also consider as obstacle
1844
+ feature2.id !== intermediaryUnit.id && (booleanOverlap(intermediaryUnit, feature2) || booleanIntersects(intermediaryUnit, feature2))
1845
+ ) {
1846
+ const polygons = getType(feature2) === "Polygon" ? [polygon(feature2.geometry.coordinates, { id: feature2.id })] : feature2.geometry.coordinates.map((ring) => polygon(ring, { id: feature2.id }));
1847
+ obstacles.push(...polygons);
1934
1848
  }
1935
- }
1849
+ return obstacles;
1850
+ },
1851
+ []
1852
+ );
1853
+ const intermediaryExtends = envelope(intermediaryUnit);
1854
+ const walkwayPerimeter = difference(
1855
+ featureCollection([intermediaryExtends, intermediaryUnit])
1856
+ );
1857
+ result.features.push(...relatedObstacleWithIntermediary, walkwayPerimeter);
1858
+ return result;
1859
+ };
1860
+ const findPathOnArea = (originPoint, destinationPoint, options2) => {
1861
+ const { obstacles = featureCollection([]), resolution: resolution2, properties } = options2 || {};
1862
+ const stepPath = shortestPath_default(originPoint, destinationPoint, {
1863
+ obstacles,
1864
+ smoothenPath: false,
1865
+ resolution: resolution2
1936
1866
  });
1937
- return results;
1938
- }
1939
- _searchObjectList(query) {
1940
- const searcher = createSearcher(query, this.options);
1941
- const { keys, records } = this._myIndex;
1942
- const results = [];
1943
- records.forEach(({ $: item, i: idx }) => {
1944
- if (!isDefined(item)) {
1945
- return;
1946
- }
1947
- let matches = [];
1948
- keys.forEach((key, keyIndex) => {
1949
- matches.push(
1950
- ...this._findMatches({
1951
- key,
1952
- value: item[keyIndex],
1953
- searcher
1954
- })
1955
- );
1956
- });
1957
- if (matches.length) {
1958
- results.push({
1959
- idx,
1960
- item,
1961
- matches
1962
- });
1963
- }
1867
+ stepPath.properties = properties;
1868
+ return stepPath;
1869
+ };
1870
+ const findStepPath = (from, to, intermediaries) => {
1871
+ const t0 = performance.now();
1872
+ const relatedWalkablePlatform = intermediaries.find(
1873
+ (feature2) => WALKABLE_CATEGORY.includes(feature2.properties.category)
1874
+ );
1875
+ const exceptionFeatureIds = [];
1876
+ const obstacles = findObstaclesFromWalkway(
1877
+ relatedWalkablePlatform,
1878
+ _7.compact(exceptionFeatureIds)
1879
+ );
1880
+ const line = findPathOnArea(from, to, {
1881
+ resolution,
1882
+ obstacles
1964
1883
  });
1965
- return results;
1884
+ return line.geometry.coordinates;
1885
+ };
1886
+ return {
1887
+ findStepPath
1888
+ };
1889
+ };
1890
+
1891
+ // src/data/navigate/landmark/createLandmarkUtils.ts
1892
+ import { center as center3 } from "@turf/center";
1893
+ import distance4 from "@turf/distance";
1894
+ var NEARBY_DISTANCE = 30;
1895
+ var createLandmarkUtils = (options) => {
1896
+ const { data, findByIdSync } = options;
1897
+ const { occupants } = data;
1898
+ const occupantToLandmark = (occupant) => {
1899
+ const locationType = occupant.properties.unit_id ? "unit" : "kiosk";
1900
+ const locationId = locationType === "unit" ? occupant.properties.unit_id : occupant.properties.kiosk_id;
1901
+ const location = locationType === "unit" ? findByIdSync(locationId) : findByIdSync(locationId);
1902
+ const level = findByIdSync(location.properties.level_id);
1903
+ return {
1904
+ name: occupant.properties.name,
1905
+ point: center3(location.geometry).geometry.coordinates,
1906
+ level_id: location.properties.level_id,
1907
+ is_priority: occupant.properties.is_landmark,
1908
+ ordinal: level.properties.ordinal
1909
+ };
1910
+ };
1911
+ const landmarks = [
1912
+ ...occupants.map(occupantToLandmark)
1913
+ ];
1914
+ const findNearbyLandmarks = (point2, levelId) => {
1915
+ if (point2 === null || levelId === null) return [];
1916
+ return landmarks.map((landmark) => {
1917
+ const landmarkAndDistance = {
1918
+ landmark,
1919
+ d: distance4(point2, landmark.point, { units: "meters" })
1920
+ };
1921
+ return landmarkAndDistance;
1922
+ }).filter(({ landmark, d }) => d <= NEARBY_DISTANCE && landmark.level_id === levelId).sort((a, b) => {
1923
+ const aPriority = a.landmark.is_priority ? 0 : 1;
1924
+ const bPriority = b.landmark.is_priority ? 0 : 1;
1925
+ if (aPriority !== bPriority) return aPriority - bPriority;
1926
+ return a.d - b.d;
1927
+ }).map(({ landmark }) => landmark);
1928
+ };
1929
+ const findNearestLandmark = (point2, levelId) => {
1930
+ const nearbyLandmarks = findNearbyLandmarks(point2, levelId);
1931
+ const nearestLandmark = nearbyLandmarks.length > 0 ? nearbyLandmarks[0] : null;
1932
+ return nearestLandmark;
1933
+ };
1934
+ return { findNearbyLandmarks, findNearestLandmark };
1935
+ };
1936
+
1937
+ // src/data/navigate/steps/utils/extractStartPoint.ts
1938
+ import { center as center4 } from "@turf/center";
1939
+
1940
+ // src/data/navigate/steps/utils/featureIdGuard.ts
1941
+ var isOccupant = (id) => !!id && id.startsWith("occupant-");
1942
+ var isUnit = (id) => !!id && id.startsWith("unit-");
1943
+ var isKiosk = (id) => !!id && id.startsWith("kiosk-");
1944
+ var isOpening = (id) => !!id && id.startsWith("opening-");
1945
+
1946
+ // src/data/navigate/type-guard.ts
1947
+ function isCoordinateOrdinalString(id) {
1948
+ return /^-?\d+(\.\d+)?,-?\d+(\.\d+)?,-?\d+(\.\d+)?o$/.test(id);
1949
+ }
1950
+
1951
+ // src/data/navigate/steps/utils/extractStartPoint.ts
1952
+ var extractStartPoint = (path, options) => {
1953
+ const { findByIdSync } = options;
1954
+ const [a, b, c] = path;
1955
+ if (isOccupant(a) && isUnit(b) && isOpening(c)) {
1956
+ const occ = findByIdSync(a);
1957
+ const opening = findByIdSync(c);
1958
+ const level = findByIdSync(opening.properties.level_id);
1959
+ return [
1960
+ {
1961
+ id: occ.id,
1962
+ type: "start",
1963
+ name: occ.properties.name,
1964
+ point: center4(opening).geometry.coordinates,
1965
+ levelId: opening.properties.level_id,
1966
+ ordinal: level.properties.ordinal,
1967
+ source: { type: "opening", id: opening.id }
1968
+ },
1969
+ path.slice(3)
1970
+ ];
1966
1971
  }
1967
- _findMatches({ key, value, searcher }) {
1968
- if (!isDefined(value)) {
1969
- return [];
1972
+ if (isOccupant(a) && isKiosk(b)) {
1973
+ const occ = findByIdSync(a);
1974
+ const kiosk = findByIdSync(c);
1975
+ const level = findByIdSync(kiosk.properties.level_id);
1976
+ return [
1977
+ {
1978
+ id: occ.id,
1979
+ type: "start",
1980
+ name: occ.properties.name,
1981
+ point: center4(kiosk).geometry.coordinates,
1982
+ levelId: kiosk.properties.level_id,
1983
+ ordinal: level.properties.ordinal,
1984
+ source: { type: "kiosk", id: kiosk.id }
1985
+ },
1986
+ path.slice(2)
1987
+ ];
1988
+ }
1989
+ if (isCoordinateOrdinalString(a) && isOpening(b)) {
1990
+ const [lat, lng, ordinal] = parseOrdinalCoordinate(a);
1991
+ const opening = findByIdSync(b);
1992
+ return [
1993
+ {
1994
+ id: a,
1995
+ type: "start",
1996
+ name: { en: `Your location` },
1997
+ point: [lng, lat],
1998
+ levelId: opening.properties.level_id,
1999
+ ordinal,
2000
+ source: { type: "opening", id: opening.id }
2001
+ },
2002
+ path.slice(1)
2003
+ ];
2004
+ }
2005
+ return [null, path];
2006
+ };
2007
+
2008
+ // src/data/navigate/steps/utils/extractEndPint.ts
2009
+ import { center as center5 } from "@turf/center";
2010
+ var extractEndPoint = (path, options) => {
2011
+ const { findByIdSync } = options;
2012
+ const [c, b, a] = path.slice(-3);
2013
+ if (isOccupant(a) && isUnit(b) && isOpening(c)) {
2014
+ const occ = findByIdSync(a);
2015
+ const opening = findByIdSync(c);
2016
+ const level = findByIdSync(opening.properties.level_id);
2017
+ return [
2018
+ {
2019
+ id: occ.id,
2020
+ type: "end",
2021
+ name: occ.properties.name,
2022
+ point: center5(opening).geometry.coordinates,
2023
+ levelId: opening.properties.level_id,
2024
+ ordinal: level.properties.ordinal,
2025
+ source: { type: "opening", id: opening.id }
2026
+ },
2027
+ path.slice(0, -3)
2028
+ ];
2029
+ }
2030
+ if (isOccupant(a) && isKiosk(b)) {
2031
+ const occ = findByIdSync(a);
2032
+ const kiosk = findByIdSync(c);
2033
+ const level = findByIdSync(kiosk.properties.level_id);
2034
+ return [
2035
+ {
2036
+ id: occ.id,
2037
+ type: "end",
2038
+ name: occ.properties.name,
2039
+ point: center5(kiosk).geometry.coordinates,
2040
+ levelId: kiosk.properties.level_id,
2041
+ ordinal: level.properties.ordinal,
2042
+ source: { type: "kiosk", id: kiosk.id }
2043
+ },
2044
+ path.slice(0, -2)
2045
+ ];
2046
+ }
2047
+ if (isCoordinateOrdinalString(a)) {
2048
+ const [lat, lng, ordinal] = parseOrdinalCoordinate(a);
2049
+ const opening = findByIdSync(b);
2050
+ return [
2051
+ {
2052
+ id: a,
2053
+ type: "end",
2054
+ name: { en: `Your location` },
2055
+ point: [lng, lat],
2056
+ levelId: opening.properties.level_id,
2057
+ ordinal,
2058
+ source: { type: "opening", id: opening.id }
2059
+ },
2060
+ path.slice(0, -2)
2061
+ ];
2062
+ }
2063
+ return [null, path];
2064
+ };
2065
+
2066
+ // src/data/navigate/steps/utils/combineWalkwaySteps.ts
2067
+ import uniq from "lodash/uniq";
2068
+ var combineWalkwaySteps = (steps) => {
2069
+ let result = [];
2070
+ for (let i = 0; i < steps.length; i++) {
2071
+ const thisStep = steps[i];
2072
+ if (i === steps.length - 1) {
2073
+ result.push(thisStep);
2074
+ continue;
1970
2075
  }
1971
- let matches = [];
1972
- if (isArray(value)) {
1973
- value.forEach(({ v: text, i: idx, n: norm2 }) => {
1974
- if (!isDefined(text)) {
1975
- return;
1976
- }
1977
- const { isMatch, score, indices } = searcher.searchIn(text);
1978
- if (isMatch) {
1979
- matches.push({
1980
- score,
1981
- key,
1982
- value: text,
1983
- idx,
1984
- norm: norm2,
1985
- indices
1986
- });
1987
- }
2076
+ const nextStep = steps[i + 1];
2077
+ if (thisStep.intermediaryCategory === "walkway" && nextStep.intermediaryCategory === "walkway" && thisStep.from.source.type === "opening" && nextStep.from.source.type === "opening") {
2078
+ console.log({ i, len: steps.length, thisStep, nextStep });
2079
+ result.push({
2080
+ from: thisStep.from,
2081
+ to: nextStep.to,
2082
+ levelIds: uniq([...thisStep.levelIds, ...nextStep.levelIds]),
2083
+ ordinals: uniq([...thisStep.ordinals, ...nextStep.ordinals]),
2084
+ intermediaryCategory: "walkway",
2085
+ description: nextStep.description,
2086
+ path: [
2087
+ ...thisStep.path,
2088
+ ...nextStep.path
2089
+ ]
1988
2090
  });
2091
+ i++;
1989
2092
  } else {
1990
- const { v: text, n: norm2 } = value;
1991
- const { isMatch, score, indices } = searcher.searchIn(text);
1992
- if (isMatch) {
1993
- matches.push({ score, key, value: text, norm: norm2, indices });
1994
- }
2093
+ result.push(thisStep);
1995
2094
  }
1996
- return matches;
1997
2095
  }
2096
+ return result;
1998
2097
  };
1999
- Fuse.version = "7.1.0";
2000
- Fuse.createIndex = createIndex;
2001
- Fuse.parseIndex = parseIndex;
2002
- Fuse.config = Config;
2003
- {
2004
- Fuse.parseQuery = parse;
2005
- }
2006
- {
2007
- register(ExtendedSearch);
2008
- }
2009
2098
 
2010
- // src/data/search/utils/sanitizeInput.ts
2011
- var sanitizeInput = (str) => str.replace(/[\u200E\u200F\u202A-\u202E\u2066-\u2069]/g, "").replace(/[\-–—_./()]+/g, "").normalize("NFC").trim();
2099
+ // src/data/navigate/steps/createStepUtils.ts
2100
+ var createStepUtils = (options) => {
2101
+ const { data: { units, relationships }, findByIdSync } = options;
2102
+ const landmarkUtils = createLandmarkUtils(options);
2103
+ const stepPathUtils = createStepPathUtils({ ...options, resolution: 88e-5 });
2104
+ const findUnitBetweenOpenings = (originId, destinationId) => {
2105
+ const origin = findByIdSync(originId);
2106
+ const destination = findByIdSync(destinationId);
2107
+ const matchedOne = relationships.find((rel) => rel.properties.intermediary.map((int) => int.id).includes(origin.id));
2108
+ const matchOneUnits = [matchedOne.properties.origin, matchedOne.properties.destination];
2109
+ const matchedTwo = relationships.find((rel) => rel.properties.intermediary.map((int) => int.id).includes(destination.id));
2110
+ const matchTwoUnits = [matchedTwo.properties.origin, matchedTwo.properties.destination];
2111
+ const unitIds = _intersectionBy(matchOneUnits, matchTwoUnits, "id");
2112
+ return unitIds.map(({ id }) => findByIdSync(id));
2113
+ };
2114
+ const findHorizontalIntermediary = (from, to) => {
2115
+ if (from.source.type !== "opening") {
2116
+ const unit = findContainingUnitAtPoint(from.point, from.levelId, units);
2117
+ return unit ? [unit] : [];
2118
+ }
2119
+ if (to.source.type !== "opening") {
2120
+ const unit = findContainingUnitAtPoint(to.point, to.levelId, units);
2121
+ return unit ? [unit] : [];
2122
+ }
2123
+ return findUnitBetweenOpenings(from.source.id, to.source.id);
2124
+ };
2125
+ const findVerticalIntermediary = (from, to) => {
2126
+ const firstOpeningId = from.source.id;
2127
+ const secondOpeningId = to.source.id;
2128
+ const relationship = relationships.find((rel) => {
2129
+ return rel.properties.origin?.id === firstOpeningId && rel.properties.destination?.id === secondOpeningId || rel.properties.origin?.id === secondOpeningId && rel.properties.destination?.id === firstOpeningId;
2130
+ });
2131
+ const intermediaryTypeAndId = relationship.properties.intermediary;
2132
+ return intermediaryTypeAndId.map(({ id }) => findByIdSync(id));
2133
+ };
2134
+ const formatCategoryLabel = (category) => {
2135
+ return capitalize(category);
2136
+ };
2137
+ const getToward = (from, to, intermediary) => {
2138
+ if (to.type === "end") return to.name;
2139
+ const intermediaryIds = intermediary.map((int) => int.id);
2140
+ const relationship = relationships.find((rel) => rel.properties.intermediary.map((int) => int.id).includes(to.source.id));
2141
+ if (!relationship) return to.name;
2142
+ const candidates = [relationship.properties.origin.id, relationship.properties.destination.id];
2143
+ const nextUnitId = candidates.filter((id) => !intermediaryIds.includes(id))[0];
2144
+ if (!nextUnitId) return to.name;
2145
+ const nextUnit = findByIdSync(nextUnitId);
2146
+ return { en: formatCategoryLabel(`${nextUnit.properties.category}`) };
2147
+ };
2148
+ const toWaypoints = (path) => {
2149
+ const [startPoint, middleAndEndPoints] = extractStartPoint(path, options);
2150
+ const [endPoint, middlePoints] = extractEndPoint(middleAndEndPoints, options);
2151
+ const waypoints = middlePoints.map((openingId) => {
2152
+ const opening = findByIdSync(openingId);
2153
+ const level = findByIdSync(opening.properties.level_id);
2154
+ const coordinates = center6(opening).geometry.coordinates;
2155
+ const landmark = landmarkUtils.findNearestLandmark(coordinates, opening.properties.level_id);
2156
+ return {
2157
+ id: `${opening.properties.level_id}:${openingId}`,
2158
+ type: "between",
2159
+ point: coordinates,
2160
+ name: null,
2161
+ levelId: opening.properties.level_id,
2162
+ ordinal: level.properties.ordinal,
2163
+ hint: landmark ? { kind: "landmark", name: landmark.name } : void 0,
2164
+ source: { type: "opening", id: opening.id }
2165
+ };
2166
+ });
2167
+ return [startPoint, ...waypoints, endPoint];
2168
+ };
2169
+ const createHorizontalStep = (from, to) => {
2170
+ const intermediary = findHorizontalIntermediary(from, to);
2171
+ const intermediaryCategories = intermediary.map((unit) => unit.properties.category);
2172
+ const intermediaryCategory = intermediaryCategories.length > 0 ? intermediaryCategories[0] : "unspecified";
2173
+ const toward = getToward(from, to, intermediary);
2174
+ const landmark = to.hint?.kind === "landmark" ? to.hint.name : null;
2175
+ const path = stepPathUtils.findStepPath(from.point, to.point, intermediary);
2176
+ const step = {
2177
+ from,
2178
+ to,
2179
+ levelIds: [from.levelId],
2180
+ ordinals: [from.ordinal],
2181
+ intermediaryCategory,
2182
+ description: describeHorizontalStep(intermediaryCategory, toward, landmark),
2183
+ path: path.map((coord) => [...coord, from.ordinal * 9])
2184
+ };
2185
+ return step;
2186
+ };
2187
+ const createVerticalStep = (from, to) => {
2188
+ const intermediary = findVerticalIntermediary(from, to);
2189
+ const intermediaryCategories = intermediary.map((unit) => unit.properties.category);
2190
+ const intermediaryCategory = intermediaryCategories.length > 0 ? intermediaryCategories[0] : "unspecified";
2191
+ const fromLevel = findByIdSync(from.levelId);
2192
+ const toLevel = findByIdSync(to.levelId);
2193
+ return {
2194
+ from,
2195
+ to,
2196
+ levelIds: [from.levelId, to.levelId],
2197
+ ordinals: [from.ordinal, to.ordinal],
2198
+ intermediaryCategory,
2199
+ description: describeVerticalStep(fromLevel, toLevel, intermediaryCategory),
2200
+ path: [
2201
+ [...from.point, from.ordinal * 9],
2202
+ [...to.point, to.ordinal * 9]
2203
+ ]
2204
+ };
2205
+ };
2206
+ const isVertical = (from, to) => {
2207
+ const fromLevel = findByIdSync(from.levelId);
2208
+ const toLevel = findByIdSync(to.levelId);
2209
+ return !!fromLevel && !!toLevel && fromLevel.properties.ordinal !== toLevel.properties.ordinal;
2210
+ };
2211
+ const toSteps = (waypoints) => {
2212
+ let steps = [];
2213
+ const t0_allSteps = performance.now();
2214
+ for (let i = 0; i < waypoints.length - 1; i++) {
2215
+ const from = waypoints[i];
2216
+ const to = waypoints[i + 1];
2217
+ const t0 = performance.now();
2218
+ const step = isVertical(from, to) ? createVerticalStep(from, to) : createHorizontalStep(from, to);
2219
+ steps.push(step);
2220
+ const t1 = performance.now();
2221
+ trace("nav", ` \u2502 \u251C\u2500 #${i} ${from.id.padEnd(25)} \u2192 ${`(${step.intermediaryCategory})`.padEnd(12)} \u2192 ${to.id}`, t1 - t0);
2222
+ trace("nav", ` \u2502 \u2502 ${step.description.text}`, void 0, "#bada55");
2223
+ }
2224
+ const simplifySteps = combineWalkwaySteps(steps);
2225
+ const t1_allSteps = performance.now();
2226
+ trace("nav", " \u2502 \u2514\u2500 Total ", t1_allSteps - t0_allSteps);
2227
+ return simplifySteps;
2228
+ };
2229
+ return {
2230
+ // createSteps,
2231
+ toWaypoints,
2232
+ toSteps
2233
+ };
2234
+ };
2012
2235
 
2013
- // src/data/search/getSearchClient.ts
2014
- var getSearchClient = ({ occupants, amenities }) => {
2015
- const fuseAmenities = new Fuse(amenities, {
2016
- threshold: 0.2,
2017
- keys: [
2018
- { name: "properties.name", "weight": 1, getFn: (obj) => Object.values(obj.properties.name || {}) },
2019
- { name: "properties.category", "weight": 1 }
2020
- ]
2021
- });
2022
- const fuseOccupants = new Fuse(occupants, {
2023
- threshold: 0.25,
2024
- // 0.2 is too strict (can't find Mo-Mo Paradise with "momo" search string)
2025
- includeScore: true,
2026
- shouldSort: true,
2027
- keys: [
2028
- { name: "properties.name", "weight": 4, getFn: (obj) => Object.values(obj.properties.name || {}) },
2029
- { name: "properties.keywords", "weight": 0.5 },
2030
- { name: "properties.category", "weight": 0.25 },
2031
- { name: "properties.local_category_names", "weight": 0.25 },
2032
- { name: "properties.description", "weight": 0.25, getFn: (occ) => Object.values(occ.properties.description || {}) },
2033
- { name: "properties.unit_name", "weight": 0.25 },
2034
- { name: "properties.kiosk_name", "weight": 0.25 }
2035
- ]
2036
- });
2037
- const search2 = (value) => {
2038
- const sanitizedValue = sanitizeInput(value);
2039
- const matchedAmenities = fuseAmenities.search(sanitizedValue);
2040
- const matchedOccupants = fuseOccupants.search(sanitizedValue);
2041
- return [...matchedAmenities, ...matchedOccupants];
2236
+ // src/data/navigate/utils/timeDistance.ts
2237
+ import calculateLength from "@turf/length";
2238
+ var WALKING_SPEED = 1.4;
2239
+ var calculatePathLength = (feature2) => calculateLength(feature2, { units: "kilometers" }) * 1e3;
2240
+ var calculateTravelingDuration = (distance5) => {
2241
+ const duration = distance5 / WALKING_SPEED;
2242
+ const minutes = Math.round(duration / 60);
2243
+ return minutes > 0 ? minutes : 1;
2244
+ };
2245
+ var calculateTotalDistance = (steps = []) => {
2246
+ return steps.reduce((acc, { path }) => acc + calculatePathLength(lineString(path)), 0);
2247
+ };
2248
+ var calculateRoundedDistance = (distance5) => {
2249
+ return Math.round(distance5 - distance5 % 25);
2250
+ };
2251
+
2252
+ // src/data/navigate/utils/createFindByIdSync.ts
2253
+ var createFindByIdSync = (data) => {
2254
+ const { amenities = [], anchors = [], fixtures = [], levels = [], kiosks = [], relationships = [], occupants = [], openings = [], units } = data;
2255
+ const featureById = /* @__PURE__ */ new Map();
2256
+ const entries = [
2257
+ ...amenities,
2258
+ ...anchors,
2259
+ ...fixtures,
2260
+ ...levels,
2261
+ ...kiosks,
2262
+ ...relationships,
2263
+ ...occupants,
2264
+ ...openings,
2265
+ ...units
2266
+ ];
2267
+ for (const f of entries) featureById.set(f.id, f);
2268
+ const findByIdSync = (id) => {
2269
+ return featureById.get(id);
2270
+ };
2271
+ return { findByIdSync };
2272
+ };
2273
+
2274
+ // src/data/navigate/getNavigateClient.ts
2275
+ var getNavigateClient = (options) => {
2276
+ const { data } = options;
2277
+ const { levels, units } = data;
2278
+ trace("nav", "\u2713 prepare");
2279
+ const t0 = performance.now();
2280
+ trace("nav", " \u251C\u2500 createGraph (dijkstra)");
2281
+ const { defaultGraph, accessibleGraph, addCoordinateOrdinalNode } = prepareGraph({ data });
2282
+ const t1 = performance.now();
2283
+ trace("nav", " \u2502 \u2514\u2500 Total ", t1 - t0);
2284
+ const t2 = performance.now();
2285
+ const { findByIdSync } = createFindByIdSync(data);
2286
+ const t3 = performance.now();
2287
+ trace("nav", " \u2514\u2500 findByIdSync", t3 - t2);
2288
+ const findCoordinateOrdinalUnit = (params) => {
2289
+ const [lat, lng, ordinal] = parseOrdinalCoordinate(params);
2290
+ const levelIdsWithOrdinal = levels.filter((level) => level.properties.ordinal === ordinal).map((level) => level.id);
2291
+ const unit = units.find((unit2) => levelIdsWithOrdinal.includes(unit2.properties.level_id) && booleanPointInPolygon4([lat, lng], unit2));
2292
+ return unit;
2293
+ };
2294
+ const stepUtils = createStepUtils({ ...options, findByIdSync });
2295
+ const findRoute = async (routeOriginParam, routeDestinationParam, options2) => {
2296
+ if (!routeOriginParam || !routeDestinationParam) return null;
2297
+ const graph = options2?.mode === "accessible" ? accessibleGraph : defaultGraph;
2298
+ if (isCoordinateOrdinalString(routeOriginParam)) {
2299
+ const walkwayUnit = findCoordinateOrdinalUnit(routeOriginParam);
2300
+ addCoordinateOrdinalNode(routeOriginParam, walkwayUnit);
2301
+ }
2302
+ if (isCoordinateOrdinalString(routeDestinationParam)) {
2303
+ const walkwayUnit = findCoordinateOrdinalUnit(routeDestinationParam);
2304
+ addCoordinateOrdinalNode(routeDestinationParam, walkwayUnit);
2305
+ }
2306
+ try {
2307
+ trace("nav", "\u2713 findRoute", 0);
2308
+ const t02 = performance.now();
2309
+ const path = graph.path(routeOriginParam, routeDestinationParam);
2310
+ const t12 = performance.now();
2311
+ trace("nav", " \u251C\u2500 path (dijkstra)", t12 - t02);
2312
+ const waypoints = stepUtils.toWaypoints(path);
2313
+ console.log({ waypoints });
2314
+ const t22 = performance.now();
2315
+ trace("nav", " \u251C\u2500 toWaypoints", t22 - t12);
2316
+ trace("nav", " \u251C\u2500 toSteps", 0);
2317
+ const steps = stepUtils.toSteps(waypoints);
2318
+ const t32 = performance.now();
2319
+ const totalDistance = calculateTotalDistance(steps);
2320
+ const roundedDistance = calculateRoundedDistance(totalDistance);
2321
+ const duration = calculateTravelingDuration(totalDistance);
2322
+ const t4 = performance.now();
2323
+ trace("nav", " \u2514\u2500 postProcess", t4 - t32);
2324
+ return {
2325
+ // origin: routeOrigin,
2326
+ // destination: routeDestination,
2327
+ description: null,
2328
+ distance: roundedDistance,
2329
+ duration,
2330
+ steps
2331
+ };
2332
+ } catch (error) {
2333
+ console.log(error);
2334
+ throw error;
2335
+ }
2042
2336
  };
2043
2337
  return {
2044
- search: search2
2338
+ findRoute,
2339
+ findByIdSync
2045
2340
  };
2046
2341
  };
2047
2342
 
2048
2343
  // src/data/getDataClient.ts
2049
2344
  var getDataClient = (options) => {
2050
2345
  let searchClient;
2346
+ let navigateClient;
2051
2347
  const observers = /* @__PURE__ */ new Map();
2052
2348
  const queryClient = options.queryClient ?? new QueryClient();
2053
2349
  const { mode = "delivery", projectId, apiKey, baseUrl, previewToken } = options;
@@ -2170,6 +2466,24 @@ var getDataClient = (options) => {
2170
2466
  }
2171
2467
  return searchClient.search(txt);
2172
2468
  };
2469
+ const navigateFn = async (origin, destination) => {
2470
+ if (!navigateClient) {
2471
+ const [levels, occupants, openings, relationships, units, fixtures, kiosks, amenities, anchors] = await Promise.all([
2472
+ filterByType("level"),
2473
+ filterByType("occupant"),
2474
+ filterByType("opening"),
2475
+ filterByType("relationship"),
2476
+ filterByType("unit"),
2477
+ filterByType("fixture"),
2478
+ filterByType("kiosk"),
2479
+ filterByType("amenity"),
2480
+ filterByType("anchor")
2481
+ ]);
2482
+ const haystack = { levels, occupants, openings, relationships, units, fixtures, kiosks, amenities, anchors };
2483
+ navigateClient = getNavigateClient({ data: haystack });
2484
+ }
2485
+ return navigateClient.findRoute(origin, destination);
2486
+ };
2173
2487
  return {
2174
2488
  projectId,
2175
2489
  queryClient,
@@ -2181,7 +2495,8 @@ var getDataClient = (options) => {
2181
2495
  _internalFindById: internalFindById,
2182
2496
  filterByType,
2183
2497
  findById,
2184
- search: searchFn
2498
+ search: searchFn,
2499
+ navigate: navigateFn
2185
2500
  };
2186
2501
  };
2187
2502
 
@@ -2196,115 +2511,9 @@ import {
2196
2511
  } from "maptalks-gl";
2197
2512
  import "@maptalks/transcoders.draco";
2198
2513
  import TWEEN from "@tweenjs/tween.js";
2199
- import _5 from "lodash";
2200
-
2201
- // node_modules/@turf/helpers/dist/esm/index.js
2202
- var earthRadius = 63710088e-1;
2203
- var factors = {
2204
- centimeters: earthRadius * 100,
2205
- centimetres: earthRadius * 100,
2206
- degrees: 360 / (2 * Math.PI),
2207
- feet: earthRadius * 3.28084,
2208
- inches: earthRadius * 39.37,
2209
- kilometers: earthRadius / 1e3,
2210
- kilometres: earthRadius / 1e3,
2211
- meters: earthRadius,
2212
- metres: earthRadius,
2213
- miles: earthRadius / 1609.344,
2214
- millimeters: earthRadius * 1e3,
2215
- millimetres: earthRadius * 1e3,
2216
- nauticalmiles: earthRadius / 1852,
2217
- radians: 1,
2218
- yards: earthRadius * 1.0936
2219
- };
2220
- function feature(geom, properties, options = {}) {
2221
- const feat = { type: "Feature" };
2222
- if (options.id === 0 || options.id) {
2223
- feat.id = options.id;
2224
- }
2225
- if (options.bbox) {
2226
- feat.bbox = options.bbox;
2227
- }
2228
- feat.properties = properties || {};
2229
- feat.geometry = geom;
2230
- return feat;
2231
- }
2232
- function point(coordinates, properties, options = {}) {
2233
- if (!coordinates) {
2234
- throw new Error("coordinates is required");
2235
- }
2236
- if (!Array.isArray(coordinates)) {
2237
- throw new Error("coordinates must be an Array");
2238
- }
2239
- if (coordinates.length < 2) {
2240
- throw new Error("coordinates must be at least 2 numbers long");
2241
- }
2242
- if (!isNumber2(coordinates[0]) || !isNumber2(coordinates[1])) {
2243
- throw new Error("coordinates must contain numbers");
2244
- }
2245
- const geom = {
2246
- type: "Point",
2247
- coordinates
2248
- };
2249
- return feature(geom, properties, options);
2250
- }
2251
- function polygon(coordinates, properties, options = {}) {
2252
- for (const ring of coordinates) {
2253
- if (ring.length < 4) {
2254
- throw new Error(
2255
- "Each LinearRing of a Polygon must have 4 or more Positions."
2256
- );
2257
- }
2258
- if (ring[ring.length - 1].length !== ring[0].length) {
2259
- throw new Error("First and last Position are not equivalent.");
2260
- }
2261
- for (let j = 0; j < ring[ring.length - 1].length; j++) {
2262
- if (ring[ring.length - 1][j] !== ring[0][j]) {
2263
- throw new Error("First and last Position are not equivalent.");
2264
- }
2265
- }
2266
- }
2267
- const geom = {
2268
- type: "Polygon",
2269
- coordinates
2270
- };
2271
- return feature(geom, properties, options);
2272
- }
2273
- function lineString(coordinates, properties, options = {}) {
2274
- if (coordinates.length < 2) {
2275
- throw new Error("coordinates must be an array of two or more positions");
2276
- }
2277
- const geom = {
2278
- type: "LineString",
2279
- coordinates
2280
- };
2281
- return feature(geom, properties, options);
2282
- }
2283
- function featureCollection(features, options = {}) {
2284
- const fc = { type: "FeatureCollection" };
2285
- if (options.id) {
2286
- fc.id = options.id;
2287
- }
2288
- if (options.bbox) {
2289
- fc.bbox = options.bbox;
2290
- }
2291
- fc.features = features;
2292
- return fc;
2293
- }
2294
- function multiPoint(coordinates, properties, options = {}) {
2295
- const geom = {
2296
- type: "MultiPoint",
2297
- coordinates
2298
- };
2299
- return feature(geom, properties, options);
2300
- }
2301
- function isNumber2(num) {
2302
- return !isNaN(num) && num !== null && !Array.isArray(num);
2303
- }
2304
-
2305
- // src/IndoorMap/IndoorMap.ts
2306
- import turfDistance from "@turf/distance";
2307
- import turfCenter3 from "@turf/center";
2514
+ import _13 from "lodash";
2515
+ import turfDistance2 from "@turf/distance";
2516
+ import turfCenter6 from "@turf/center";
2308
2517
  import { PerspectiveCamera } from "three";
2309
2518
  import { ThreeLayer as ThreeLayer5 } from "maptalks.three";
2310
2519
 
@@ -2383,7 +2592,7 @@ var VENUE_EVENTS = {
2383
2592
  };
2384
2593
 
2385
2594
  // src/IndoorMap/utils/createElements.js
2386
- import _4 from "lodash";
2595
+ import _12 from "lodash";
2387
2596
  import {
2388
2597
  Polygon,
2389
2598
  MultiPolygon,
@@ -2393,7 +2602,7 @@ import {
2393
2602
  MultiLineString,
2394
2603
  ui
2395
2604
  } from "maptalks";
2396
- import turfCenter from "@turf/center";
2605
+ import turfCenter4 from "@turf/center";
2397
2606
  import turfBuffer from "@turf/buffer";
2398
2607
  import {
2399
2608
  TextureLoader as TextureLoader2,
@@ -2413,7 +2622,7 @@ import {
2413
2622
  SpriteMaterial,
2414
2623
  Sprite
2415
2624
  } from "three";
2416
- import _ from "lodash";
2625
+ import _9 from "lodash";
2417
2626
  var OPTIONS = {
2418
2627
  altitude: 25,
2419
2628
  scale: 15e-5,
@@ -2439,14 +2648,14 @@ var Billboard = class extends BaseObject {
2439
2648
  this._initOptions(options);
2440
2649
  const {
2441
2650
  altitude = OPTIONS.altitude,
2442
- scale: scale2 = OPTIONS.scale,
2651
+ scale: scale3 = OPTIONS.scale,
2443
2652
  alphaTest = OPTIONS.alphaTest,
2444
2653
  legColor = OPTIONS.legColor,
2445
2654
  showLeg = OPTIONS.showLeg
2446
2655
  } = options;
2447
2656
  this.properties = { ...properties };
2448
2657
  this._createGroup();
2449
- const divider = _.clamp(window.innerWidth / 375 / 1.75, 1, 1.7);
2658
+ const divider = _9.clamp(window.innerWidth / 375 / 1.75, 1, 1.7);
2450
2659
  if (showLeg) {
2451
2660
  const lineMaterial = new LineBasicMaterial({
2452
2661
  color: legColor,
@@ -2473,17 +2682,17 @@ var Billboard = class extends BaseObject {
2473
2682
  const sprite = new Sprite(material);
2474
2683
  sprite.material.sizeAttenuation = false;
2475
2684
  sprite.scale.set(
2476
- scale2 * naturalWidth / divider,
2477
- scale2 * naturalHeight / divider,
2685
+ scale3 * naturalWidth / divider,
2686
+ scale3 * naturalHeight / divider,
2478
2687
  1
2479
2688
  );
2480
2689
  this.getObject3d().add(sprite);
2481
2690
  });
2482
2691
  const z = layer.altitudeToVector3(altitude, altitude).x;
2483
2692
  const position = layer.coordinateToVector3(coordinate, z);
2484
- _.set(this.properties, "default.position", position);
2485
- _.set(this.properties, "default.altitude", altitude);
2486
- _.set(this.properties, "default.scale", scale2);
2693
+ _9.set(this.properties, "default.position", position);
2694
+ _9.set(this.properties, "default.altitude", altitude);
2695
+ _9.set(this.properties, "default.scale", scale3);
2487
2696
  this.getObject3d().position.copy(position);
2488
2697
  }
2489
2698
  setLineHeight(altitude) {
@@ -2499,7 +2708,7 @@ var Billboard = class extends BaseObject {
2499
2708
  // src/IndoorMap/object3d/SpriteMarker.ts
2500
2709
  import { BaseObject as BaseObject2 } from "maptalks.three";
2501
2710
  import { Sprite as Sprite2, SpriteMaterial as SpriteMaterial2 } from "three";
2502
- import _2 from "lodash";
2711
+ import _10 from "lodash";
2503
2712
  var DEFAULT_SCALE = 0.05;
2504
2713
  var DEFAULT_ALTITUDE = 0;
2505
2714
  var DEFAULT_ALPHATEST = 0.3;
@@ -2523,23 +2732,23 @@ var SpriteMarker = class extends BaseObject2 {
2523
2732
  this._createGroup();
2524
2733
  const {
2525
2734
  altitude = DEFAULT_OPTIONS.altitude,
2526
- scale: scale2 = DEFAULT_OPTIONS.scale,
2735
+ scale: scale3 = DEFAULT_OPTIONS.scale,
2527
2736
  highlight = DEFAULT_OPTIONS.highlight,
2528
2737
  alphaTest = DEFAULT_OPTIONS.alphaTest
2529
2738
  } = options;
2530
2739
  this.properties = { ...properties };
2531
2740
  const modifiedAltitude = altitude + 2;
2532
- this.#default = { options: { scale: scale2, altitude: modifiedAltitude }, material };
2533
- this.#highlight = _2.merge({}, DEFAULT_OPTIONS.highlight, highlight);
2741
+ this.#default = { options: { scale: scale3, altitude: modifiedAltitude }, material };
2742
+ this.#highlight = _10.merge({}, DEFAULT_OPTIONS.highlight, highlight);
2534
2743
  if (material && material instanceof SpriteMaterial2)
2535
2744
  material.alphaTest = alphaTest;
2536
2745
  const sprite = new Sprite2(material);
2537
- sprite.scale.set(scale2, scale2, scale2);
2746
+ sprite.scale.set(scale3, scale3, scale3);
2538
2747
  const obj3d = this.getObject3d();
2539
2748
  obj3d.add(sprite);
2540
2749
  const z = layer.altitudeToVector3(modifiedAltitude, modifiedAltitude).x;
2541
2750
  const position = layer.coordinateToVector3(coordinate, z);
2542
- _2.set(this.properties, "default.position", position);
2751
+ _10.set(this.properties, "default.position", position);
2543
2752
  this.getObject3d().position.copy(position);
2544
2753
  }
2545
2754
  // Different objects need to implement their own methods
@@ -2680,15 +2889,15 @@ var NavigationPath = class extends BaseObject3 {
2680
2889
  };
2681
2890
 
2682
2891
  // src/IndoorMap/utils/geometry.ts
2683
- import center3 from "@turf/center";
2684
- import _3 from "lodash";
2892
+ import center7 from "@turf/center";
2893
+ import _11 from "lodash";
2685
2894
  import turfLineOffset from "@turf/line-offset";
2686
2895
  var getCenterFromGeometry = (geometry) => {
2687
2896
  try {
2688
2897
  const { type = null, coordinates = null } = geometry;
2689
2898
  if (!type || !coordinates) return null;
2690
- const centerPoint = center3(geometry);
2691
- return _3.get(centerPoint, "geometry.coordinates");
2899
+ const centerPoint = center7(geometry);
2900
+ return _11.get(centerPoint, "geometry.coordinates");
2692
2901
  } catch (error) {
2693
2902
  return null;
2694
2903
  }
@@ -2734,8 +2943,8 @@ var createSVGPathFromMarkerSymbol = (style) => {
2734
2943
  markerFill,
2735
2944
  markerPath
2736
2945
  } = style;
2737
- const scale2 = markerWidth / 24;
2738
- return `<path d="${markerPath}" style="transform:translate(${markerDx}px, ${markerDy}px) scale(${scale2})" fill="${markerFill}"/>`;
2946
+ const scale3 = markerWidth / 24;
2947
+ return `<path d="${markerPath}" style="transform:translate(${markerDx}px, ${markerDy}px) scale(${scale3})" fill="${markerFill}"/>`;
2739
2948
  };
2740
2949
 
2741
2950
  // src/IndoorMap/utils/createElements.js
@@ -2839,7 +3048,7 @@ var createWaterFixture = (feature2, style, options = {}) => {
2839
3048
  const { geometry, properties } = feature2;
2840
3049
  const { allowOverride, inheritFillColorToLine, zIndex } = options;
2841
3050
  const symbolStyle = { ...style };
2842
- if (allowOverride) _4.merge(symbolStyle, properties.style);
3051
+ if (allowOverride) _12.merge(symbolStyle, properties.style);
2843
3052
  if (inheritFillColorToLine) symbolStyle.lineColor = symbolStyle.polygonFill;
2844
3053
  return new GeometryType[geometry.type](geometry.coordinates, {
2845
3054
  properties: {
@@ -2855,7 +3064,7 @@ var createVegetationFixture = (feature2, style, options = {}) => {
2855
3064
  const { geometry, properties } = feature2;
2856
3065
  const { allowOverride, inheritFillColorToLine, zIndex } = options;
2857
3066
  const symbolStyle = { ...style };
2858
- if (allowOverride) _4.merge(symbolStyle, properties.style);
3067
+ if (allowOverride) _12.merge(symbolStyle, properties.style);
2859
3068
  if (inheritFillColorToLine) symbolStyle.lineColor = symbolStyle.polygonFill;
2860
3069
  return new GeometryType[geometry.type](geometry.coordinates, {
2861
3070
  properties: {
@@ -2872,8 +3081,8 @@ var createObstructionalFixture = (feature2, style = {}, options = {}) => {
2872
3081
  const { model3d } = properties;
2873
3082
  const { allowOverride, inheritFillColorToLine, zIndex } = options;
2874
3083
  const symbolStyle = { ...style };
2875
- if (!_4.isEmpty(model3d)) return;
2876
- if (allowOverride) _4.merge(symbolStyle, properties.style);
3084
+ if (!_12.isEmpty(model3d)) return;
3085
+ if (allowOverride) _12.merge(symbolStyle, properties.style);
2877
3086
  if (inheritFillColorToLine) symbolStyle.lineColor = symbolStyle.polygonFill;
2878
3087
  if (geometry.type === "LineString") {
2879
3088
  const polygon2 = createPolygonFromLineString(geometry);
@@ -2943,7 +3152,7 @@ var createPrincipalOpening = (feature2, style, options = {}) => {
2943
3152
  const { geometry, properties } = feature2;
2944
3153
  const { allowOverride, zIndex } = options;
2945
3154
  const symbolStyle = { ...style };
2946
- if (allowOverride) _4.merge(symbolStyle, properties.style);
3155
+ if (allowOverride) _12.merge(symbolStyle, properties.style);
2947
3156
  try {
2948
3157
  return new LineString(geometry.coordinates, {
2949
3158
  properties: {
@@ -2960,7 +3169,7 @@ var createEmergencyExitOpening = (feature2, style, options = {}) => {
2960
3169
  const { geometry, properties } = feature2;
2961
3170
  const { allowOverride, zIndex } = options;
2962
3171
  const symbolStyle = { ...style };
2963
- if (allowOverride) _4.merge(symbolStyle, properties.style);
3172
+ if (allowOverride) _12.merge(symbolStyle, properties.style);
2964
3173
  try {
2965
3174
  return new LineString(geometry.coordinates, {
2966
3175
  properties: {
@@ -2977,7 +3186,7 @@ var createPedestrianOpening = (feature2, style, options = {}) => {
2977
3186
  const { geometry, properties, id } = feature2;
2978
3187
  const { allowOverride, zIndex } = options;
2979
3188
  const symbolStyle = { ...style };
2980
- if (allowOverride) _4.merge(symbolStyle, properties.style);
3189
+ if (allowOverride) _12.merge(symbolStyle, properties.style);
2981
3190
  try {
2982
3191
  return new LineString(geometry.coordinates, {
2983
3192
  properties: {
@@ -3015,9 +3224,9 @@ var create3DMarker = (coordinates, options, material, threeLayer, markerProperti
3015
3224
  };
3016
3225
  var getExtrudeConfigByFeature = (baseExtrudeConfig, feature2 = {}) => {
3017
3226
  const { feature_type: featureType } = feature2;
3018
- const featureExtrudeConfig = _4.get(feature2, "properties.extrude");
3019
- const featureCategory = _4.get(feature2, "properties.category");
3020
- const baseFeatureExtrudeConfig = _4.get(
3227
+ const featureExtrudeConfig = _12.get(feature2, "properties.extrude");
3228
+ const featureCategory = _12.get(feature2, "properties.category");
3229
+ const baseFeatureExtrudeConfig = _12.get(
3021
3230
  baseExtrudeConfig,
3022
3231
  `${featureType}.${featureCategory || featureType}`
3023
3232
  );
@@ -3075,50 +3284,50 @@ var createStyledUIMarkerElement = ({
3075
3284
  var styledFeatureGenerator = (mapTheme) => {
3076
3285
  const getElementSymbol = (key) => {
3077
3286
  const [featureType] = key.split(".");
3078
- const featureTypeTheme = _4.get(mapTheme, `${featureType}.geometry.symbol`);
3287
+ const featureTypeTheme = _12.get(mapTheme, `${featureType}.geometry.symbol`);
3079
3288
  if (featureType === key) return featureTypeTheme;
3080
- const categoryTheme = _4.get(mapTheme, `${key}.geometry.symbol`);
3081
- return _4.merge({}, featureTypeTheme, categoryTheme);
3289
+ const categoryTheme = _12.get(mapTheme, `${key}.geometry.symbol`);
3290
+ return _12.merge({}, featureTypeTheme, categoryTheme);
3082
3291
  };
3083
3292
  const getLabelSymbol = (key) => {
3084
3293
  const [featureType] = key.split(".");
3085
- const featureTypeTheme = _4.get(mapTheme, `${featureType}.label`);
3086
- const categoryTheme = _4.get(mapTheme, `${key}.label`);
3087
- const mergedSymbol = _4.merge({}, featureTypeTheme, categoryTheme);
3088
- let symbols = _4.values(_4.map(mergedSymbol, "symbol"));
3294
+ const featureTypeTheme = _12.get(mapTheme, `${featureType}.label`);
3295
+ const categoryTheme = _12.get(mapTheme, `${key}.label`);
3296
+ const mergedSymbol = _12.merge({}, featureTypeTheme, categoryTheme);
3297
+ let symbols = _12.values(_12.map(mergedSymbol, "symbol"));
3089
3298
  const markerIndexToMove = symbols.findIndex(
3090
3299
  ({ elementType }) => elementType === "label.marker"
3091
3300
  );
3092
3301
  if (markerIndexToMove >= 0) {
3093
- const markerSymbolToMove = _4.pullAt(symbols, markerIndexToMove)[0];
3302
+ const markerSymbolToMove = _12.pullAt(symbols, markerIndexToMove)[0];
3094
3303
  symbols.push(markerSymbolToMove);
3095
3304
  }
3096
3305
  return symbols;
3097
3306
  };
3098
3307
  const getUIMarkerSymbol = (key) => {
3099
3308
  const [featureType] = key.split(".");
3100
- const featureTypeTheme = _4.get(mapTheme, `${featureType}.ui.marker`);
3101
- const categoryTheme = _4.get(mapTheme, `${key}.ui.marker`);
3102
- const mergedSymbol = _4.merge({}, featureTypeTheme, categoryTheme);
3103
- const symbol = _4.get(mergedSymbol, "symbol");
3309
+ const featureTypeTheme = _12.get(mapTheme, `${featureType}.ui.marker`);
3310
+ const categoryTheme = _12.get(mapTheme, `${key}.ui.marker`);
3311
+ const mergedSymbol = _12.merge({}, featureTypeTheme, categoryTheme);
3312
+ const symbol = _12.get(mergedSymbol, "symbol");
3104
3313
  return symbol;
3105
3314
  };
3106
3315
  const getUIMarkerOptions = (key) => {
3107
3316
  const [featureType] = key.split(".");
3108
- const featureTypeTheme = _4.get(mapTheme, `${featureType}.ui.marker`);
3109
- const categoryTheme = _4.get(mapTheme, `${key}.ui.marker`);
3110
- const mergedSymbol = _4.merge({}, featureTypeTheme, categoryTheme);
3111
- const options = _4.get(mergedSymbol, "options");
3317
+ const featureTypeTheme = _12.get(mapTheme, `${featureType}.ui.marker`);
3318
+ const categoryTheme = _12.get(mapTheme, `${key}.ui.marker`);
3319
+ const mergedSymbol = _12.merge({}, featureTypeTheme, categoryTheme);
3320
+ const options = _12.get(mergedSymbol, "options");
3112
3321
  return options;
3113
3322
  };
3114
3323
  const getLabelOptions = (key) => {
3115
3324
  const [featureType] = key.split(".");
3116
- const featureTypeSymbol = _4.get(mapTheme, `${featureType}.label`);
3117
- const categorySymbol = _4.get(mapTheme, `${key}.label`);
3118
- const mergedSymbol = _4.merge({}, featureTypeSymbol, categorySymbol);
3119
- return _4.reduce(
3325
+ const featureTypeSymbol = _12.get(mapTheme, `${featureType}.label`);
3326
+ const categorySymbol = _12.get(mapTheme, `${key}.label`);
3327
+ const mergedSymbol = _12.merge({}, featureTypeSymbol, categorySymbol);
3328
+ return _12.reduce(
3120
3329
  mergedSymbol,
3121
- (acc, symbol) => ({ ...acc, ..._4.get(symbol, "options", {}) }),
3330
+ (acc, symbol) => ({ ...acc, ..._12.get(symbol, "options", {}) }),
3122
3331
  {}
3123
3332
  );
3124
3333
  };
@@ -3133,13 +3342,13 @@ var styledFeatureGenerator = (mapTheme) => {
3133
3342
  };
3134
3343
  const generateSpriteHighlightMarkerOption = () => {
3135
3344
  return SPRITE_HIGHLIGHT_MARKER_FEATURE.reduce((acc, featCate) => {
3136
- const categoryKey = _4.last(featCate.split("-"));
3345
+ const categoryKey = _12.last(featCate.split("-"));
3137
3346
  const defaultLabelSymbol = getLabelSymbol(categoryKey);
3138
3347
  const highlightLabelSymbol = getLabelSymbol(featCate);
3139
3348
  const [defaultBase, defaultIcon] = defaultLabelSymbol;
3140
3349
  const [highlightBase, highlightIcon] = highlightLabelSymbol;
3141
- const base = _4.merge({}, defaultBase, highlightBase);
3142
- const icon = _4.merge({}, defaultIcon, highlightIcon);
3350
+ const base = _12.merge({}, defaultBase, highlightBase);
3351
+ const icon = _12.merge({}, defaultIcon, highlightIcon);
3143
3352
  const material = createSpriteMaterialByLabelSymbol([base, icon]);
3144
3353
  const options = getLabelOptions(featCate);
3145
3354
  return { ...acc, [featCate]: { material, options } };
@@ -3149,32 +3358,32 @@ var styledFeatureGenerator = (mapTheme) => {
3149
3358
  const spriteHighlightMarkerOptionObj = generateSpriteHighlightMarkerOption();
3150
3359
  const getElementOptions = (key) => {
3151
3360
  const [featureType] = key.split(".");
3152
- const featureTypeOptions = _4.get(
3361
+ const featureTypeOptions = _12.get(
3153
3362
  mapTheme,
3154
3363
  `${featureType}.geometry.options`
3155
3364
  );
3156
- const categoryOptions = _4.get(mapTheme, `${key}.geometry.options`);
3157
- return _4.merge({}, featureTypeOptions, categoryOptions);
3365
+ const categoryOptions = _12.get(mapTheme, `${key}.geometry.options`);
3366
+ return _12.merge({}, featureTypeOptions, categoryOptions);
3158
3367
  };
3159
3368
  const createOccupantMarker = (feature2, locatedFeature, mapConfig) => {
3160
3369
  const { textMarkerType, featureExtrudeConfig } = getFeatureMarkerConfig(
3161
3370
  feature2,
3162
3371
  mapConfig
3163
3372
  );
3164
- const markerHeight = _4.get(featureExtrudeConfig, "height", 0);
3373
+ const markerHeight = _12.get(featureExtrudeConfig, "height", 0);
3165
3374
  const { properties, id, feature_type } = feature2;
3166
3375
  if (!properties.anchor) return;
3167
- const mainLocationId = _4.get(properties, "unit.id") || _4.get(properties, "kiosk.id");
3376
+ const mainLocationId = _12.get(properties, "unit.id") || _12.get(properties, "kiosk.id");
3168
3377
  const isMainLocationFeature = mainLocationId === locatedFeature?.id;
3169
3378
  const { geometry: mainLocationGeometry } = properties?.anchor;
3170
- const geometry = isMainLocationFeature ? mainLocationGeometry : turfCenter(locatedFeature)?.geometry;
3379
+ const geometry = isMainLocationFeature ? mainLocationGeometry : turfCenter4(locatedFeature)?.geometry;
3171
3380
  const baseProperties = {
3172
3381
  id,
3173
3382
  feature_type,
3174
3383
  category: properties.category,
3175
3384
  altitude: getAltitude(properties)
3176
3385
  };
3177
- const occupantName = _4.isEmpty(properties.short_name) ? properties.name : properties.short_name;
3386
+ const occupantName = _12.isEmpty(properties.short_name) ? properties.name : properties.short_name;
3178
3387
  if (locatedFeature) {
3179
3388
  const { feature_type: feature_type2, properties: properties2 } = locatedFeature;
3180
3389
  const { category } = properties2;
@@ -3188,21 +3397,21 @@ var styledFeatureGenerator = (mapTheme) => {
3188
3397
  }
3189
3398
  return requestedType;
3190
3399
  };
3191
- const logoUrl = _4.get(properties, "logo.url");
3192
- const requestedRenderType = _4.get(properties, "render_type", "Name");
3400
+ const logoUrl = _12.get(properties, "logo.url");
3401
+ const requestedRenderType = _12.get(properties, "render_type", "Name");
3193
3402
  const renderType = getValidatedRenderType(requestedRenderType, logoUrl);
3194
3403
  if (renderType === "Label") return null;
3195
3404
  const renderPriority = properties.render_priority || 3;
3196
- const labelSymbol = getLabelSymbol(`occupant-${_4.toLower(renderType)}`);
3197
- const markerSymbol = _4.last(labelSymbol);
3198
- const coordinates = _4.get(geometry, "coordinates");
3405
+ const labelSymbol = getLabelSymbol(`occupant-${_12.toLower(renderType)}`);
3406
+ const markerSymbol = _12.last(labelSymbol);
3407
+ const coordinates = _12.get(geometry, "coordinates");
3199
3408
  const priorityLabelSymbol = getLabelSymbol(
3200
- `occupant-${_4.toLower(renderType)}-${renderPriority}`
3409
+ `occupant-${_12.toLower(renderType)}-${renderPriority}`
3201
3410
  );
3202
- const priorityMarkerSymbol = _4.last(priorityLabelSymbol) || {};
3411
+ const priorityMarkerSymbol = _12.last(priorityLabelSymbol) || {};
3203
3412
  switch (renderType) {
3204
3413
  case "Logo":
3205
- _4.set(priorityMarkerSymbol, "markerFile", logoUrl);
3414
+ _12.set(priorityMarkerSymbol, "markerFile", logoUrl);
3206
3415
  return new Marker(coordinates, {
3207
3416
  properties: {
3208
3417
  altitude: getAltitude(properties) + markerHeight,
@@ -3263,13 +3472,13 @@ var styledFeatureGenerator = (mapTheme) => {
3263
3472
  });
3264
3473
  }
3265
3474
  const uiMarkerSymbol = getUIMarkerSymbol(
3266
- `occupant-${_4.toLower(renderType)}`
3475
+ `occupant-${_12.toLower(renderType)}`
3267
3476
  );
3268
3477
  const uiMarkerPrioritySymbol = getUIMarkerSymbol(
3269
- `occupant-${_4.toLower(renderType)}-${renderPriority}`
3478
+ `occupant-${_12.toLower(renderType)}-${renderPriority}`
3270
3479
  );
3271
3480
  const uiMarkerPriorityOptions = getUIMarkerOptions(
3272
- `occupant-${_4.toLower(renderType)}-${renderPriority}`
3481
+ `occupant-${_12.toLower(renderType)}-${renderPriority}`
3273
3482
  );
3274
3483
  const style = { ...uiMarkerSymbol, ...uiMarkerPrioritySymbol };
3275
3484
  return new ui.UIMarker(coordinates, {
@@ -3291,7 +3500,7 @@ var styledFeatureGenerator = (mapTheme) => {
3291
3500
  const { category, ordinal, style = {} } = properties;
3292
3501
  const elementStyle = getElementSymbol(`${feature_type}.${category}`);
3293
3502
  const { allowOverride } = getElementOptions(`${feature_type}.${category}`);
3294
- if (allowOverride) _4.merge(elementStyle, style);
3503
+ if (allowOverride) _12.merge(elementStyle, style);
3295
3504
  const { polygonFill: color } = elementStyle;
3296
3505
  const featureProperty = {
3297
3506
  id,
@@ -3380,9 +3589,9 @@ var styledFeatureGenerator = (mapTheme) => {
3380
3589
  feature2,
3381
3590
  mapConfig
3382
3591
  );
3383
- const markerHeight = _4.get(featureExtrudeConfig, "height");
3592
+ const markerHeight = _12.get(featureExtrudeConfig, "height");
3384
3593
  const { id, properties } = feature2;
3385
- const geometry = _4.get(feature2, "geometry") || _4.get(feature2, "properties.anchor.geometry");
3594
+ const geometry = _12.get(feature2, "geometry") || _12.get(feature2, "properties.anchor.geometry");
3386
3595
  const coordinates = getCenterFromGeometry(geometry);
3387
3596
  const symbol = getElementSymbol("pin-marker");
3388
3597
  try {
@@ -3402,10 +3611,10 @@ var styledFeatureGenerator = (mapTheme) => {
3402
3611
  feature2,
3403
3612
  mapConfig
3404
3613
  );
3405
- const markerHeight = _4.get(featureExtrudeConfig, "height", 0);
3614
+ const markerHeight = _12.get(featureExtrudeConfig, "height", 0);
3406
3615
  const { properties, id } = feature2;
3407
3616
  const { geometry } = properties.anchor;
3408
- const logoUrl = _4.get(properties, "logo.url");
3617
+ const logoUrl = _12.get(properties, "logo.url");
3409
3618
  const coordinates = getCenterFromGeometry(geometry);
3410
3619
  const [markerBase, markerLabel] = getLabelSymbol(
3411
3620
  "highlighted-logo-marker"
@@ -3475,7 +3684,7 @@ var styledFeatureGenerator = (mapTheme) => {
3475
3684
  feature2,
3476
3685
  mapConfig
3477
3686
  );
3478
- const markerHeight = _4.get(featureExtrudeConfig, "height");
3687
+ const markerHeight = _12.get(featureExtrudeConfig, "height");
3479
3688
  const { id, feature_type, properties } = feature2;
3480
3689
  if (!properties.anchor) return;
3481
3690
  const markerProperties = {
@@ -3485,8 +3694,8 @@ var styledFeatureGenerator = (mapTheme) => {
3485
3694
  altitude: getAltitude(properties) + markerHeight
3486
3695
  };
3487
3696
  const { geometry } = properties?.anchor;
3488
- const coordinates = _4.get(geometry, "coordinates");
3489
- const logoUrl = _4.get(properties, "logo.url");
3697
+ const coordinates = _12.get(geometry, "coordinates");
3698
+ const logoUrl = _12.get(properties, "logo.url");
3490
3699
  if (markerSymbol) {
3491
3700
  return new Marker(coordinates, {
3492
3701
  properties: markerProperties,
@@ -3501,8 +3710,8 @@ var styledFeatureGenerator = (mapTheme) => {
3501
3710
  });
3502
3711
  }
3503
3712
  const labelSymbol = getLabelSymbol("highlight-occupant-logo");
3504
- const priorityMarkerSymbol = _4.last(labelSymbol) || {};
3505
- _4.set(priorityMarkerSymbol, "markerFile", logoUrl);
3713
+ const priorityMarkerSymbol = _12.last(labelSymbol) || {};
3714
+ _12.set(priorityMarkerSymbol, "markerFile", logoUrl);
3506
3715
  return new Marker(coordinates, {
3507
3716
  properties: markerProperties,
3508
3717
  symbol: labelSymbol
@@ -3510,14 +3719,14 @@ var styledFeatureGenerator = (mapTheme) => {
3510
3719
  },
3511
3720
  createHighlight2DAmenityMarkerFrom3DMarker: (feature2, mapConfig) => {
3512
3721
  const { coordinates, units, kiosk } = feature2;
3513
- const amenityLocatedUnit = _4.first(units);
3722
+ const amenityLocatedUnit = _12.first(units);
3514
3723
  const unitConfig = getExtrudeConfigByFeature(
3515
3724
  mapConfig,
3516
3725
  amenityLocatedUnit
3517
3726
  );
3518
- const unitHeight = _4.get(unitConfig, "height", 0);
3727
+ const unitHeight = _12.get(unitConfig, "height", 0);
3519
3728
  const kioskConfig = getExtrudeConfigByFeature(mapConfig, kiosk);
3520
- const kioskHeight = _4.get(kioskConfig, "height", 0);
3729
+ const kioskHeight = _12.get(kioskConfig, "height", 0);
3521
3730
  const markerHeight = unitHeight + kioskHeight;
3522
3731
  const symbol = getElementSymbol("highlight-amenity-marker");
3523
3732
  return new Marker(coordinates, {
@@ -3593,7 +3802,7 @@ var styledFeatureGenerator = (mapTheme) => {
3593
3802
  }
3594
3803
  },
3595
3804
  createLineStringFromGeometries: (geometries) => {
3596
- const mergedCoordinates = _4(geometries).map((geometry) => {
3805
+ const mergedCoordinates = _12(geometries).map((geometry) => {
3597
3806
  switch (geometry.type) {
3598
3807
  case "Point":
3599
3808
  return [
@@ -3671,7 +3880,7 @@ var styledFeatureGenerator = (mapTheme) => {
3671
3880
  const {
3672
3881
  logo,
3673
3882
  altitude,
3674
- scale: scale2,
3883
+ scale: scale3,
3675
3884
  alphaTest,
3676
3885
  legColor,
3677
3886
  showLeg,
@@ -3685,7 +3894,7 @@ var styledFeatureGenerator = (mapTheme) => {
3685
3894
  };
3686
3895
  const options = {
3687
3896
  altitude,
3688
- scale: scale2,
3897
+ scale: scale3,
3689
3898
  alphaTest,
3690
3899
  legColor,
3691
3900
  showLeg,
@@ -3702,29 +3911,29 @@ var styledFeatureGenerator = (mapTheme) => {
3702
3911
  create3DAmenityMarker: (feature2, threeLayer, config) => {
3703
3912
  const { geometry, properties, feature_type, id } = feature2;
3704
3913
  const { category, units, kiosk, is_clickable } = properties;
3705
- const amenityLocatedUnit = _4.first(units);
3706
- const isLocatedUnitModel3dAvailable = !_4.isEmpty(
3914
+ const amenityLocatedUnit = _12.first(units);
3915
+ const isLocatedUnitModel3dAvailable = !_12.isEmpty(
3707
3916
  amenityLocatedUnit?.properties?.model3d
3708
3917
  );
3709
- const isLocatedKioskModel3dAvailable = !_4.isEmpty(
3918
+ const isLocatedKioskModel3dAvailable = !_12.isEmpty(
3710
3919
  kiosk?.properties?.model3d
3711
3920
  );
3712
3921
  const unitConfig = getExtrudeConfigByFeature(config, amenityLocatedUnit);
3713
- const unitHeight = isLocatedUnitModel3dAvailable ? 0 : _4.get(unitConfig, "height", 0);
3922
+ const unitHeight = isLocatedUnitModel3dAvailable ? 0 : _12.get(unitConfig, "height", 0);
3714
3923
  const kioskConfig = getExtrudeConfigByFeature(config, kiosk);
3715
- const kioskHeight = isLocatedKioskModel3dAvailable ? 0 : _4.get(kioskConfig, "height", 0);
3716
- const coordinates = _4.get(geometry, "coordinates");
3924
+ const kioskHeight = isLocatedKioskModel3dAvailable ? 0 : _12.get(kioskConfig, "height", 0);
3925
+ const coordinates = _12.get(geometry, "coordinates");
3717
3926
  const markerProperties = {
3718
3927
  ...properties,
3719
3928
  coordinates,
3720
3929
  id,
3721
3930
  feature_type
3722
3931
  };
3723
- const material = _4.get(
3932
+ const material = _12.get(
3724
3933
  spriteMarkerMaterialObj,
3725
3934
  `${feature_type}.${category}`
3726
3935
  );
3727
- const highlightOptions = _4.get(
3936
+ const highlightOptions = _12.get(
3728
3937
  spriteHighlightMarkerOptionObj,
3729
3938
  `${PREFIX_HIGHLIGHTED_SYMBOL_KEY}-${feature_type}.${category}`
3730
3939
  );
@@ -3747,24 +3956,24 @@ var styledFeatureGenerator = (mapTheme) => {
3747
3956
  const { category, unit, kiosk } = properties;
3748
3957
  const amenityLocation = kiosk || unit;
3749
3958
  const locationConfig = getExtrudeConfigByFeature(config, amenityLocation);
3750
- const coordinates = _4.get(geometry, "coordinates");
3959
+ const coordinates = _12.get(geometry, "coordinates");
3751
3960
  const markerProperties = {
3752
3961
  ...properties,
3753
3962
  coordinates,
3754
3963
  id,
3755
3964
  feature_type
3756
3965
  };
3757
- const material = _4.get(
3966
+ const material = _12.get(
3758
3967
  spriteMarkerMaterialObj,
3759
3968
  `${feature_type}.${category}`
3760
3969
  );
3761
- const highlightOptions = _4.get(
3970
+ const highlightOptions = _12.get(
3762
3971
  spriteHighlightMarkerOptionObj,
3763
3972
  `${PREFIX_HIGHLIGHTED_SYMBOL_KEY}-${feature_type}.${category}`
3764
3973
  );
3765
3974
  const options = {
3766
3975
  scale: 0.05,
3767
- altitude: _4.get(locationConfig, "height", 0),
3976
+ altitude: _12.get(locationConfig, "height", 0),
3768
3977
  highlight: highlightOptions
3769
3978
  };
3770
3979
  return create3DMarker(
@@ -3780,24 +3989,24 @@ var styledFeatureGenerator = (mapTheme) => {
3780
3989
  const { category, unit, kiosk } = properties;
3781
3990
  const amenityLocation = kiosk || unit;
3782
3991
  const locationConfig = getExtrudeConfigByFeature(config, amenityLocation);
3783
- const coordinates = _4.get(geometry, "coordinates");
3992
+ const coordinates = _12.get(geometry, "coordinates");
3784
3993
  const markerProperties = {
3785
3994
  ...properties,
3786
3995
  coordinates,
3787
3996
  id,
3788
3997
  feature_type
3789
3998
  };
3790
- const material = _4.get(
3999
+ const material = _12.get(
3791
4000
  spriteMarkerMaterialObj,
3792
4001
  `${feature_type}.${category}`
3793
4002
  );
3794
- const highlightOptions = _4.get(
4003
+ const highlightOptions = _12.get(
3795
4004
  spriteHighlightMarkerOptionObj,
3796
4005
  `${PREFIX_HIGHLIGHTED_SYMBOL_KEY}-${feature_type}.${category}`
3797
4006
  );
3798
4007
  const options = {
3799
4008
  scale: 0.05,
3800
- altitude: _4.get(locationConfig, "height", 0),
4009
+ altitude: _12.get(locationConfig, "height", 0),
3801
4010
  highlight: highlightOptions
3802
4011
  };
3803
4012
  return create3DMarker(
@@ -3809,13 +4018,13 @@ var styledFeatureGenerator = (mapTheme) => {
3809
4018
  );
3810
4019
  },
3811
4020
  createExtrudedUnit: (unit, threeLayer, options) => {
3812
- const extrudeHeight = _4.get(options, "height");
4021
+ const extrudeHeight = _12.get(options, "height");
3813
4022
  if (!extrudeHeight) return;
3814
4023
  const unitProperty = getFeatureProperties(unit);
3815
4024
  const options3d = {
3816
4025
  // TODO: Move to extrude config later
3817
4026
  offset: -0.1,
3818
- altitude: _4.get(options, "altitude", 0)
4027
+ altitude: _12.get(options, "altitude", 0)
3819
4028
  };
3820
4029
  const color = unitProperty.defaultColor;
3821
4030
  if (color === "transparent") return;
@@ -3858,14 +4067,14 @@ var EXCEPT_AMENITY_LOCATION_CATEGORIES = [
3858
4067
  "unspecified"
3859
4068
  ];
3860
4069
  var getLocationByAmenity = (feature2) => {
3861
- const unit = _4.get(feature2, "properties.units[0]", null);
3862
- const unitCategory = _4.get(unit, "properties.category");
4070
+ const unit = _12.get(feature2, "properties.units[0]", null);
4071
+ const unitCategory = _12.get(unit, "properties.category");
3863
4072
  if (!unit) return feature2.id;
3864
4073
  return EXCEPT_AMENITY_LOCATION_CATEGORIES.includes(unitCategory) ? feature2 : unit;
3865
4074
  };
3866
4075
  var getLocationByOccupant = (feature2) => {
3867
- const kiosk = _4.get(feature2, "properties.kiosk", null);
3868
- const unit = _4.get(feature2, "properties.anchor.properties.unit", null);
4076
+ const kiosk = _12.get(feature2, "properties.kiosk", null);
4077
+ const unit = _12.get(feature2, "properties.anchor.properties.unit", null);
3869
4078
  return kiosk || unit;
3870
4079
  };
3871
4080
  var getLocationIdByFeature = (feature2) => {
@@ -3893,10 +4102,10 @@ var getFeatureByLocationId = (id, features = []) => {
3893
4102
  });
3894
4103
  };
3895
4104
  var isClickableFeature = (feature2) => {
3896
- const isClickable = _4.get(feature2, "properties.is_clickable");
4105
+ const isClickable = _12.get(feature2, "properties.is_clickable");
3897
4106
  switch (feature2?.feature_type) {
3898
4107
  case "amenity":
3899
- return _4.isNull(isClickable) ? true : isClickable;
4108
+ return _12.isNull(isClickable) ? true : isClickable;
3900
4109
  case "occupant":
3901
4110
  return true;
3902
4111
  default:
@@ -3914,15 +4123,15 @@ var getLocationByFeature = (feature2) => {
3914
4123
  }
3915
4124
  };
3916
4125
  var getRelatedLocationsByOccupant = (feature2) => {
3917
- const kiosks = _4.get(feature2, "properties.kiosks", []);
3918
- const units = _4.get(feature2, "properties.units", []);
4126
+ const kiosks = _12.get(feature2, "properties.kiosks", []);
4127
+ const units = _12.get(feature2, "properties.units", []);
3919
4128
  return [...kiosks, ...units];
3920
4129
  };
3921
4130
  var getRelatedLocationsByAmenity = (feature2) => {
3922
- const units = _4.get(feature2, "properties.units", []);
4131
+ const units = _12.get(feature2, "properties.units", []);
3923
4132
  if (units.length === 0) return [feature2];
3924
4133
  return units.filter((unit) => {
3925
- const unitCategory = _4.get(unit, "properties.category");
4134
+ const unitCategory = _12.get(unit, "properties.category");
3926
4135
  return !EXCEPT_AMENITY_LOCATION_CATEGORIES.includes(unitCategory);
3927
4136
  });
3928
4137
  };
@@ -3948,8 +4157,8 @@ var getRelatedLocationsByFeature = (feature2) => {
3948
4157
  };
3949
4158
  var getOrdinalByLocationId = (locationId, feature2) => {
3950
4159
  if (!feature2) return null;
3951
- const mainUnit = _4.get(feature2, "properties.unit");
3952
- const mainKiosk = _4.get(feature2, "properties.kiosk");
4160
+ const mainUnit = _12.get(feature2, "properties.unit");
4161
+ const mainKiosk = _12.get(feature2, "properties.kiosk");
3953
4162
  const relatedLocations = getRelatedLocationsByFeature(feature2);
3954
4163
  const allLocations = [mainUnit, mainKiosk, ...relatedLocations].filter(
3955
4164
  Boolean
@@ -3957,7 +4166,7 @@ var getOrdinalByLocationId = (locationId, feature2) => {
3957
4166
  const targetLocation = allLocations.find(
3958
4167
  (location) => location.id === locationId
3959
4168
  );
3960
- return targetLocation ? _4.get(targetLocation, "properties.level.properties.ordinal") || _4.get(targetLocation, "properties.ordinal") : null;
4169
+ return targetLocation ? _12.get(targetLocation, "properties.level.properties.ordinal") || _12.get(targetLocation, "properties.ordinal") : null;
3961
4170
  };
3962
4171
 
3963
4172
  // src/IndoorMap/utils/math.ts
@@ -3970,140 +4179,16 @@ var getBearingBetweenPoints = (origin, destination) => {
3970
4179
  return Math.floor(radToDegree(theta));
3971
4180
  };
3972
4181
  var getSuitablyValueBetweenBearings = (newBearing, currentBearing) => {
3973
- const difference = Math.abs(newBearing - currentBearing);
3974
- if (difference > 180)
4182
+ const difference2 = Math.abs(newBearing - currentBearing);
4183
+ if (difference2 > 180)
3975
4184
  return newBearing > 0 ? newBearing - 360 : newBearing + 360;
3976
4185
  return newBearing;
3977
4186
  };
3978
4187
 
3979
4188
  // src/IndoorMap/camera/CameraManager.ts
3980
4189
  import { Extent } from "maptalks";
3981
-
3982
- // ../../node_modules/@turf/meta/dist/esm/index.js
3983
- function coordEach(geojson, callback, excludeWrapCoord) {
3984
- if (geojson === null) return;
3985
- var j, k, l, geometry, stopG, coords, geometryMaybeCollection, wrapShrink = 0, coordIndex = 0, isGeometryCollection, type = geojson.type, isFeatureCollection = type === "FeatureCollection", isFeature = type === "Feature", stop = isFeatureCollection ? geojson.features.length : 1;
3986
- for (var featureIndex = 0; featureIndex < stop; featureIndex++) {
3987
- geometryMaybeCollection = isFeatureCollection ? geojson.features[featureIndex].geometry : isFeature ? geojson.geometry : geojson;
3988
- isGeometryCollection = geometryMaybeCollection ? geometryMaybeCollection.type === "GeometryCollection" : false;
3989
- stopG = isGeometryCollection ? geometryMaybeCollection.geometries.length : 1;
3990
- for (var geomIndex = 0; geomIndex < stopG; geomIndex++) {
3991
- var multiFeatureIndex = 0;
3992
- var geometryIndex = 0;
3993
- geometry = isGeometryCollection ? geometryMaybeCollection.geometries[geomIndex] : geometryMaybeCollection;
3994
- if (geometry === null) continue;
3995
- coords = geometry.coordinates;
3996
- var geomType = geometry.type;
3997
- wrapShrink = excludeWrapCoord && (geomType === "Polygon" || geomType === "MultiPolygon") ? 1 : 0;
3998
- switch (geomType) {
3999
- case null:
4000
- break;
4001
- case "Point":
4002
- if (callback(
4003
- coords,
4004
- coordIndex,
4005
- featureIndex,
4006
- multiFeatureIndex,
4007
- geometryIndex
4008
- ) === false)
4009
- return false;
4010
- coordIndex++;
4011
- multiFeatureIndex++;
4012
- break;
4013
- case "LineString":
4014
- case "MultiPoint":
4015
- for (j = 0; j < coords.length; j++) {
4016
- if (callback(
4017
- coords[j],
4018
- coordIndex,
4019
- featureIndex,
4020
- multiFeatureIndex,
4021
- geometryIndex
4022
- ) === false)
4023
- return false;
4024
- coordIndex++;
4025
- if (geomType === "MultiPoint") multiFeatureIndex++;
4026
- }
4027
- if (geomType === "LineString") multiFeatureIndex++;
4028
- break;
4029
- case "Polygon":
4030
- case "MultiLineString":
4031
- for (j = 0; j < coords.length; j++) {
4032
- for (k = 0; k < coords[j].length - wrapShrink; k++) {
4033
- if (callback(
4034
- coords[j][k],
4035
- coordIndex,
4036
- featureIndex,
4037
- multiFeatureIndex,
4038
- geometryIndex
4039
- ) === false)
4040
- return false;
4041
- coordIndex++;
4042
- }
4043
- if (geomType === "MultiLineString") multiFeatureIndex++;
4044
- if (geomType === "Polygon") geometryIndex++;
4045
- }
4046
- if (geomType === "Polygon") multiFeatureIndex++;
4047
- break;
4048
- case "MultiPolygon":
4049
- for (j = 0; j < coords.length; j++) {
4050
- geometryIndex = 0;
4051
- for (k = 0; k < coords[j].length; k++) {
4052
- for (l = 0; l < coords[j][k].length - wrapShrink; l++) {
4053
- if (callback(
4054
- coords[j][k][l],
4055
- coordIndex,
4056
- featureIndex,
4057
- multiFeatureIndex,
4058
- geometryIndex
4059
- ) === false)
4060
- return false;
4061
- coordIndex++;
4062
- }
4063
- geometryIndex++;
4064
- }
4065
- multiFeatureIndex++;
4066
- }
4067
- break;
4068
- case "GeometryCollection":
4069
- for (j = 0; j < geometry.geometries.length; j++)
4070
- if (coordEach(geometry.geometries[j], callback, excludeWrapCoord) === false)
4071
- return false;
4072
- break;
4073
- default:
4074
- throw new Error("Unknown Geometry Type");
4075
- }
4076
- }
4077
- }
4078
- }
4079
-
4080
- // ../../node_modules/@turf/bbox/dist/esm/index.js
4081
- function bbox(geojson, options = {}) {
4082
- if (geojson.bbox != null && true !== options.recompute) {
4083
- return geojson.bbox;
4084
- }
4085
- const result = [Infinity, Infinity, -Infinity, -Infinity];
4086
- coordEach(geojson, (coord) => {
4087
- if (result[0] > coord[0]) {
4088
- result[0] = coord[0];
4089
- }
4090
- if (result[1] > coord[1]) {
4091
- result[1] = coord[1];
4092
- }
4093
- if (result[2] < coord[0]) {
4094
- result[2] = coord[0];
4095
- }
4096
- if (result[3] < coord[1]) {
4097
- result[3] = coord[1];
4098
- }
4099
- });
4100
- return result;
4101
- }
4102
- var index_default = bbox;
4103
-
4104
- // src/IndoorMap/camera/CameraManager.ts
4105
- import scale from "@turf/transform-scale";
4106
- import bboxPolygon from "@turf/bbox-polygon";
4190
+ import scale2 from "@turf/transform-scale";
4191
+ import bboxPolygon2 from "@turf/bbox-polygon";
4107
4192
  var CameraManager = class {
4108
4193
  map;
4109
4194
  constructor(map, options) {
@@ -4129,7 +4214,7 @@ var CameraManager = class {
4129
4214
  }
4130
4215
  getFeatureExtent = (feature2, scaleFactor = 1) => {
4131
4216
  const [minX, minY, maxX, maxY] = index_default(
4132
- scale(bboxPolygon(index_default(feature2)), scaleFactor)
4217
+ scale2(bboxPolygon2(index_default(feature2)), scaleFactor)
4133
4218
  );
4134
4219
  return new Extent(minX, minY, maxX, maxY);
4135
4220
  };
@@ -4167,7 +4252,7 @@ var CameraManager = class {
4167
4252
 
4168
4253
  // src/IndoorMap/renderer/RendererManager.ts
4169
4254
  import { min, compact as compact2, isFunction } from "lodash";
4170
- import { center as turfCenter2 } from "@turf/center";
4255
+ import { center as turfCenter5 } from "@turf/center";
4171
4256
  import * as THREE4 from "three";
4172
4257
 
4173
4258
  // src/IndoorMap/renderer/3d/Element3DRenderer.ts
@@ -4175,7 +4260,7 @@ import * as maptalks4 from "maptalks-gl";
4175
4260
  import * as THREE from "three";
4176
4261
  import { BaseObject as BaseObject5 } from "maptalks.three";
4177
4262
  import turfBuffer2 from "@turf/buffer";
4178
- import { cleanCoords } from "@turf/clean-coords";
4263
+ import { cleanCoords as cleanCoords2 } from "@turf/clean-coords";
4179
4264
  import { polygonToLine } from "@turf/polygon-to-line";
4180
4265
  import { nearestPointOnLine } from "@turf/nearest-point-on-line";
4181
4266
  import { length } from "@turf/length";
@@ -4191,7 +4276,7 @@ import {
4191
4276
  PlaneGeometry
4192
4277
  } from "three";
4193
4278
  import { largestRect } from "d3plus-shape";
4194
- import { max, merge, isNumber as isNumber3, isArray as isArray2, range } from "lodash";
4279
+ import { max, merge, isNumber as isNumber2, isArray, range } from "lodash";
4195
4280
  var OPTIONS3 = {
4196
4281
  // Allowing click through and prevent interaction
4197
4282
  interactive: false,
@@ -4265,22 +4350,22 @@ var getMaterial = (text, flatLabelOptions) => {
4265
4350
  texts = wrapText(ctx, text, maxWidth);
4266
4351
  }
4267
4352
  let textWidth = max(texts.map((text2) => ctx.measureText(text2).width));
4268
- let scale2 = 1;
4269
- while (scale2 > 0 && textWidth + 2 * margin > SIZE) {
4270
- scale2 -= scaleStep;
4271
- ctx.font = `${fontWeight} ${scale2 * fontSize}px "${fontFamily}", Arial`;
4353
+ let scale3 = 1;
4354
+ while (scale3 > 0 && textWidth + 2 * margin > SIZE) {
4355
+ scale3 -= scaleStep;
4356
+ ctx.font = `${fontWeight} ${scale3 * fontSize}px "${fontFamily}", Arial`;
4272
4357
  textWidth = max(texts.map((text2) => ctx.measureText(text2).width));
4273
4358
  }
4274
- const center4 = { x: 0.5 * SIZE, y: 0.5 * SIZE };
4275
- if (scale2 > scaleMin) {
4276
- const totalHeight = texts.length * (fontSize * scale2 * lineHeight);
4277
- const startY = center4.y - totalHeight / 2 + fontSize * scale2 * lineHeight * 0.5;
4359
+ const center8 = { x: 0.5 * SIZE, y: 0.5 * SIZE };
4360
+ if (scale3 > scaleMin) {
4361
+ const totalHeight = texts.length * (fontSize * scale3 * lineHeight);
4362
+ const startY = center8.y - totalHeight / 2 + fontSize * scale3 * lineHeight * 0.5;
4278
4363
  texts.forEach((text2, index) => {
4279
- const yOffset = startY + index * (fontSize * scale2 * lineHeight);
4364
+ const yOffset = startY + index * (fontSize * scale3 * lineHeight);
4280
4365
  if (strokeStyle && lineWidth) {
4281
- ctx.strokeText(text2, center4.x, yOffset);
4366
+ ctx.strokeText(text2, center8.x, yOffset);
4282
4367
  }
4283
- ctx.fillText(text2, center4.x, yOffset);
4368
+ ctx.fillText(text2, center8.x, yOffset);
4284
4369
  });
4285
4370
  }
4286
4371
  const texture = new Texture(canvas);
@@ -4337,7 +4422,7 @@ var GroundLabel = class extends BaseObject4 {
4337
4422
  strokeStyle,
4338
4423
  lineWidth
4339
4424
  });
4340
- const rectAngles = isArray2(angle) ? angle : [angle];
4425
+ const rectAngles = isArray(angle) ? angle : [angle];
4341
4426
  material.needsUpdate = true;
4342
4427
  const rect = largestRect(bound, {
4343
4428
  cache: true,
@@ -4357,8 +4442,8 @@ var GroundLabel = class extends BaseObject4 {
4357
4442
  const basePosition = layer.coordinateToVector3([cx, cy], z);
4358
4443
  this.#originalPosition = basePosition.clone();
4359
4444
  const finalPosition = this.#calculateFinalPosition(basePosition);
4360
- const scale2 = width / 6456122659e-13;
4361
- const finalScale = maxFontScale && scale2 > maxFontScale ? maxFontScale : scale2;
4445
+ const scale3 = width / 6456122659e-13;
4446
+ const finalScale = maxFontScale && scale3 > maxFontScale ? maxFontScale : scale3;
4362
4447
  this.getObject3d().scale.set(finalScale, finalScale, finalScale);
4363
4448
  this.getObject3d().position.copy(finalPosition);
4364
4449
  this.getObject3d().rotation.z = Math.PI / 180 * this.#angle;
@@ -4410,32 +4495,32 @@ var GroundLabel = class extends BaseObject4 {
4410
4495
  return { x: this.#offsetX, y: this.#offsetY };
4411
4496
  }
4412
4497
  set offsetX(value) {
4413
- if (isNumber3(value)) {
4498
+ if (isNumber2(value)) {
4414
4499
  this.#offsetX = value;
4415
4500
  this.#updatePosition();
4416
4501
  }
4417
4502
  }
4418
4503
  set offsetY(value) {
4419
- if (isNumber3(value)) {
4504
+ if (isNumber2(value)) {
4420
4505
  this.#offsetY = value;
4421
4506
  this.#updatePosition();
4422
4507
  }
4423
4508
  }
4424
4509
  set angle(newAngle) {
4425
- if (isNumber3(newAngle)) {
4510
+ if (isNumber2(newAngle)) {
4426
4511
  this.#angle = newAngle;
4427
4512
  this.getObject3d().rotation.z = Math.PI / 180 * this.#angle;
4428
4513
  }
4429
4514
  }
4430
4515
  setOffset(offsetX, offsetY) {
4431
- if (isNumber3(offsetX) && isNumber3(offsetY)) {
4516
+ if (isNumber2(offsetX) && isNumber2(offsetY)) {
4432
4517
  this.#offsetX = offsetX;
4433
4518
  this.#offsetY = offsetY;
4434
4519
  this.#updatePosition();
4435
4520
  }
4436
4521
  }
4437
4522
  addOffset(deltaX, deltaY) {
4438
- if (isNumber3(deltaX) && isNumber3(deltaY)) {
4523
+ if (isNumber2(deltaX) && isNumber2(deltaY)) {
4439
4524
  this.#offsetX += deltaX;
4440
4525
  this.#offsetY += deltaY;
4441
4526
  this.#updatePosition();
@@ -4537,6 +4622,7 @@ var Element3DRenderer = class extends EventTarget {
4537
4622
  threeLayer;
4538
4623
  scene;
4539
4624
  lineMaterial;
4625
+ navigationLineMaterial;
4540
4626
  materialByColorMap;
4541
4627
  // Renderer is Ready
4542
4628
  isReady = false;
@@ -4548,6 +4634,7 @@ var Element3DRenderer = class extends EventTarget {
4548
4634
  this.threeLayer = groupLayer.getLayer("three");
4549
4635
  this.gltfLayer = groupLayer.getLayer("gltf");
4550
4636
  this.lineMaterial = new THREE.LineBasicMaterial({ color: "#000" });
4637
+ this.navigationLineMaterial = new THREE.LineBasicMaterial({ color: "#f00" });
4551
4638
  this.render();
4552
4639
  }
4553
4640
  animation() {
@@ -4663,7 +4750,7 @@ var Element3DRenderer = class extends EventTarget {
4663
4750
  const polygons = unit.geometry.type === "Polygon" ? [unit.geometry.coordinates] : unit.geometry.coordinates;
4664
4751
  return polygons.map((plg) => {
4665
4752
  return plg.map((ring) => {
4666
- const roomWall = cleanCoords(polygonToLine(polygon([ring])));
4753
+ const roomWall = cleanCoords2(polygonToLine(polygon([ring])));
4667
4754
  if (openings.length === 0) {
4668
4755
  const color = "#ababab";
4669
4756
  const material = this.getOrCreateMaterialByColor(color);
@@ -4750,8 +4837,8 @@ var Element3DRenderer = class extends EventTarget {
4750
4837
  this.threeLayer.addMesh(groundLabel);
4751
4838
  return groundLabel;
4752
4839
  }
4753
- async createModel3d(center4, url) {
4754
- const marker = new maptalks4.GLTFMarker(center4, {
4840
+ async createModel3d(center8, url) {
4841
+ const marker = new maptalks4.GLTFMarker(center8, {
4755
4842
  symbol: {
4756
4843
  url
4757
4844
  }
@@ -4812,11 +4899,23 @@ var Element3DRenderer = class extends EventTarget {
4812
4899
  }
4813
4900
  }
4814
4901
  }
4902
+ drawNavigation = (route) => {
4903
+ const lines = [];
4904
+ route.steps.map((step) => {
4905
+ const lineString2 = new maptalks4.LineString(step.path);
4906
+ const line = this.threeLayer.toPath(lineString2, { altitude: 0.2, cornerRadius: 1, width: 1, asynchronous: true }, this.navigationLineMaterial);
4907
+ lines.push(line);
4908
+ });
4909
+ this.threeLayer.addMesh(lines);
4910
+ };
4815
4911
  render() {
4816
4912
  this.threeLayer._needsUpdate = !this.threeLayer._needsUpdate;
4817
4913
  if (this.threeLayer._needsUpdate) {
4818
4914
  this.threeLayer.redraw();
4819
4915
  }
4916
+ if (this.navigationLineMaterial?.map?.offset) {
4917
+ this.navigationLineMaterial.map.offset.x -= 2e-3;
4918
+ }
4820
4919
  requestAnimationFrame(this.render.bind(this));
4821
4920
  }
4822
4921
  };
@@ -4956,6 +5055,8 @@ var Element2DRenderer = class extends EventTarget {
4956
5055
  }
4957
5056
  };
4958
5057
  }
5058
+ drawNavigation(route) {
5059
+ }
4959
5060
  };
4960
5061
 
4961
5062
  // src/IndoorMap/renderer/2d/Marker2DRenderer.ts
@@ -5001,7 +5102,7 @@ import * as THREE3 from "three";
5001
5102
  import { Coordinate as Coordinate2, Util as Util4 } from "maptalks";
5002
5103
  import * as THREE2 from "three";
5003
5104
  import { BaseObject as BaseObject6 } from "maptalks.three";
5004
- import { isNil, set } from "lodash";
5105
+ import { isNil, set as set4 } from "lodash";
5005
5106
 
5006
5107
  // src/IndoorMap/renderer/utils/interpolateStops.ts
5007
5108
  var interpolateStops = ({ stops }, zoom) => {
@@ -5011,8 +5112,8 @@ var interpolateStops = ({ stops }, zoom) => {
5011
5112
  const [z1, v1] = stops[i];
5012
5113
  const [z2, v2] = stops[i + 1];
5013
5114
  if (zoom >= z1 && zoom <= z2) {
5014
- const t = (zoom - z1) / (z2 - z1);
5015
- return v1 + t * (v2 - v1);
5115
+ const t2 = (zoom - z1) / (z2 - z1);
5116
+ return v1 + t2 * (v2 - v1);
5016
5117
  }
5017
5118
  }
5018
5119
  };
@@ -5157,7 +5258,7 @@ var TextSpriteMarker = class extends BaseObject6 {
5157
5258
  const altitude = (options.altitude || 0) + this.#altitudeOffset;
5158
5259
  const z = layer.altitudeToVector3(altitude, altitude).x;
5159
5260
  const position = layer.coordinateToVector3(this._coordinate, z);
5160
- set(this.properties, "default.position", position);
5261
+ set4(this.properties, "default.position", position);
5161
5262
  this.getObject3d().position.copy(position);
5162
5263
  }
5163
5264
  _animation() {
@@ -5332,10 +5433,10 @@ var angleBetweenLineStrings = (line1, line2) => {
5332
5433
  };
5333
5434
 
5334
5435
  // src/IndoorMap/renderer/utils/findUnitOnPoint.ts
5335
- import { booleanPointInPolygon as booleanPointInPolygon3 } from "@turf/boolean-point-in-polygon";
5436
+ import { booleanPointInPolygon as booleanPointInPolygon5 } from "@turf/boolean-point-in-polygon";
5336
5437
  var findUnitOnPoint = (units, point2) => {
5337
5438
  try {
5338
- return units.find((unit) => booleanPointInPolygon3(point2, polygon(unit.geometry.coordinates)));
5439
+ return units.find((unit) => booleanPointInPolygon5(point2, polygon(unit.geometry.coordinates)));
5339
5440
  } catch (err) {
5340
5441
  return null;
5341
5442
  }
@@ -5422,6 +5523,7 @@ var RendererManager = class extends EventTarget {
5422
5523
  options.onRendererReady();
5423
5524
  }
5424
5525
  _this.#createElements();
5526
+ _this.elementRenderer.createModel3d([100.54724407, 13.72699081], "https://s3.venue.in.th/all_park_f95ac5be3c.gltf");
5425
5527
  setTimeout(() => {
5426
5528
  findBadMeshes(scene);
5427
5529
  }, 3e3);
@@ -5538,7 +5640,7 @@ var RendererManager = class extends EventTarget {
5538
5640
  const thatLevelOpening = bothOpenings.find((opening) => opening.properties.ordinal !== thisOrdinal);
5539
5641
  const angle = 180 * (1 / Math.PI) * angleBetweenLineStrings(thisLevelOpening.geometry.coordinates, thatLevelOpening.geometry.coordinates);
5540
5642
  const direction = thisOrdinal < thatLevelOpening.properties.ordinal ? "up" : "down";
5541
- const escalatorEntryPoint = turfCenter2(thisLevelOpening).geometry.coordinates;
5643
+ const escalatorEntryPoint = turfCenter5(thisLevelOpening).geometry.coordinates;
5542
5644
  const element = await this.elementRenderer.createEscalator(escalator, escalatorEntryPoint, { direction, angle });
5543
5645
  if (element) {
5544
5646
  const _elements = Array.isArray(element) ? element : [element];
@@ -5550,8 +5652,8 @@ var RendererManager = class extends EventTarget {
5550
5652
  }
5551
5653
  const groundLabels = await this.#dataClient.filterByType("label");
5552
5654
  for (const label of groundLabels) {
5553
- const center4 = turfCenter2(polygon(label.geometry.coordinates)).geometry.coordinates;
5554
- const unit = findUnitOnPoint(units, center4);
5655
+ const center8 = turfCenter5(polygon(label.geometry.coordinates)).geometry.coordinates;
5656
+ const unit = findUnitOnPoint(units, center8);
5555
5657
  if (unit) {
5556
5658
  const element = this.elementRenderer.createGroundLabel(label, unit);
5557
5659
  if (element) {
@@ -5644,6 +5746,9 @@ var RendererManager = class extends EventTarget {
5644
5746
  this.markerRenderer.removeMarker(marker);
5645
5747
  }
5646
5748
  }
5749
+ drawNavigation(route) {
5750
+ this.elementRenderer.drawNavigation(route);
5751
+ }
5647
5752
  };
5648
5753
 
5649
5754
  // src/IndoorMap/IndoorMap.ts
@@ -5721,7 +5826,7 @@ var IndoorMap = class extends EventTarget {
5721
5826
  };
5722
5827
  constructor(elementId, options) {
5723
5828
  super();
5724
- const combinedOptions = _5.merge({}, defaultOptions, options);
5829
+ const combinedOptions = _13.merge({}, defaultOptions, options);
5725
5830
  this.options = combinedOptions;
5726
5831
  const {
5727
5832
  onMapReady,
@@ -5768,7 +5873,7 @@ var IndoorMap = class extends EventTarget {
5768
5873
  this.dataClient = options.dataClient;
5769
5874
  }
5770
5875
  setOptions(options) {
5771
- const combinedOptions = _5.merge({}, defaultOptions, options);
5876
+ const combinedOptions = _13.merge({}, defaultOptions, options);
5772
5877
  this.options = combinedOptions;
5773
5878
  const maptalksOptions = parseMaptalksOptions(combinedOptions);
5774
5879
  this.map.setOptions(maptalksOptions);
@@ -5778,10 +5883,10 @@ var IndoorMap = class extends EventTarget {
5778
5883
  if (!this.options.camera?.defaultView?.center) {
5779
5884
  this.#dataClient.filterByType("venue").then((venues) => {
5780
5885
  this.#venues = venues;
5781
- const venueCenters = turfCenter3(featureCollection(venues));
5886
+ const venueCenters = turfCenter6(featureCollection(venues));
5782
5887
  const [x, y] = venueCenters.geometry.coordinates;
5783
- const center4 = new Coordinate4(x, y);
5784
- this.camera.setView({ center: center4, pitch: 60, zoom: 19 });
5888
+ const center8 = new Coordinate4(x, y);
5889
+ this.camera.setView({ center: center8, pitch: 60, zoom: 19 });
5785
5890
  });
5786
5891
  }
5787
5892
  }
@@ -5794,7 +5899,7 @@ var IndoorMap = class extends EventTarget {
5794
5899
  handleMapClick = ({ coordinate }) => {
5795
5900
  const { x, y } = coordinate;
5796
5901
  console.log(
5797
- `[Coordinates]: x: ${_5.round(x, 8)} y: ${_5.round(
5902
+ `[Coordinates]: x: ${_13.round(x, 8)} y: ${_13.round(
5798
5903
  y,
5799
5904
  8
5800
5905
  )}, [Bearing]: ${this.map.getBearing()}, [Pitch]: ${this.map.getPitch()}`
@@ -5880,7 +5985,7 @@ var IndoorMap = class extends EventTarget {
5880
5985
  if (this.#isClicked) return;
5881
5986
  this.#isClicked = true;
5882
5987
  const onClickElement = this.#onClickElement;
5883
- if (!_5.isFunction(onClickElement)) return;
5988
+ if (!_13.isFunction(onClickElement)) return;
5884
5989
  this.#onClickElement(e);
5885
5990
  this.#isClicked = false;
5886
5991
  };
@@ -5900,16 +6005,16 @@ var IndoorMap = class extends EventTarget {
5900
6005
  for (const feature2 of this.#features) {
5901
6006
  try {
5902
6007
  const { feature_type: featureType, properties, id } = feature2;
5903
- const layerName = _5.get(
6008
+ const layerName = _13.get(
5904
6009
  LAYER_FEATURE_TYPE_OBJ,
5905
6010
  featureType,
5906
6011
  featureType
5907
6012
  );
5908
6013
  const layer = this.map.getLayer(layerName);
5909
6014
  let geometry;
5910
- const category = _5.get(feature2, "properties.category");
5911
- const extrudeConfig = _5.get(this.#mapConfig, "extrude");
5912
- const textMarkerType = _5.get(
6015
+ const category = _13.get(feature2, "properties.category");
6016
+ const extrudeConfig = _13.get(this.#mapConfig, "extrude");
6017
+ const textMarkerType = _13.get(
5913
6018
  this.#mapConfig,
5914
6019
  "text_marker_type",
5915
6020
  "ui-marker"
@@ -5941,7 +6046,7 @@ var IndoorMap = class extends EventTarget {
5941
6046
  case "opening": {
5942
6047
  switch (category) {
5943
6048
  case "emergencyexit":
5944
- const { geometry: geometry2 } = turfCenter3(feature2);
6049
+ const { geometry: geometry2 } = turfCenter6(feature2);
5945
6050
  const markerFeature = {
5946
6051
  ...feature2,
5947
6052
  geometry: geometry2
@@ -6024,9 +6129,9 @@ var IndoorMap = class extends EventTarget {
6024
6129
  const mapCenter = this.map.getCenter();
6025
6130
  const result = this.#venues.reduce((closest, venue) => {
6026
6131
  const { display_point: displayPoint } = venue.properties;
6027
- const distance = turfDistance(displayPoint, [mapCenter.x, mapCenter.y]);
6028
- if (!closest || distance < closest.distance) {
6029
- return { venueId: venue.id, distance };
6132
+ const distance5 = turfDistance2(displayPoint, [mapCenter.x, mapCenter.y]);
6133
+ if (!closest || distance5 < closest.distance) {
6134
+ return { venueId: venue.id, distance: distance5 };
6030
6135
  }
6031
6136
  return closest;
6032
6137
  }, null);
@@ -6076,15 +6181,15 @@ var IndoorMap = class extends EventTarget {
6076
6181
  }
6077
6182
  }
6078
6183
  updateUserLocationSymbolByLocale(locale) {
6079
- const userLocationGeometry = _5.get(
6184
+ const userLocationGeometry = _13.get(
6080
6185
  this.#elements,
6081
6186
  `${USER_LOCATION_ELEMENT_ID}.geometry`
6082
6187
  );
6083
6188
  if (!userLocationGeometry) return;
6084
6189
  const currentSymbol = userLocationGeometry.getSymbol();
6085
6190
  const localeSymbolToUpdate = currentSymbol.map((symbol) => {
6086
- const localeSymbol = _5.get(symbol, `${LOCALE_SYMBOL_KEY}.${locale}`) || _5.get(symbol, `${LOCALE_SYMBOL_KEY}.default`);
6087
- if (!_5.isPlainObject(localeSymbol)) return symbol;
6191
+ const localeSymbol = _13.get(symbol, `${LOCALE_SYMBOL_KEY}.${locale}`) || _13.get(symbol, `${LOCALE_SYMBOL_KEY}.default`);
6192
+ if (!_13.isPlainObject(localeSymbol)) return symbol;
6088
6193
  return {
6089
6194
  ...symbol,
6090
6195
  ...localeSymbol
@@ -6158,14 +6263,14 @@ var IndoorMap = class extends EventTarget {
6158
6263
  * END of User Location
6159
6264
  ****************************/
6160
6265
  showGeometryByElementId = (elementId) => {
6161
- const geometry = _5.get(
6266
+ const geometry = _13.get(
6162
6267
  this.#elements,
6163
6268
  `${elementId}.geometry`
6164
6269
  );
6165
6270
  if (geometry) geometry.show();
6166
6271
  };
6167
6272
  hideGeometryByElementId = (elementId) => {
6168
- const geometry = _5.get(this.#elements, `${elementId}.geometry`);
6273
+ const geometry = _13.get(this.#elements, `${elementId}.geometry`);
6169
6274
  if (geometry) geometry.hide();
6170
6275
  };
6171
6276
  setSpriteMarkersOpacity = (opacity = 1) => {
@@ -6204,7 +6309,7 @@ var IndoorMap = class extends EventTarget {
6204
6309
  * Navigation
6205
6310
  ****************************/
6206
6311
  combineNearbyLineStrings(lineStrings, options = { properties: {}, distance: 3e-4 }) {
6207
- const { properties = {}, distance = 3e-4 } = options || {};
6312
+ const { properties = {}, distance: distance5 = 3e-4 } = options || {};
6208
6313
  const combinedLineStrings = [];
6209
6314
  const accLine = [];
6210
6315
  if (lineStrings.length === 1) return lineStrings;
@@ -6212,14 +6317,14 @@ var IndoorMap = class extends EventTarget {
6212
6317
  const line = lineStrings[i];
6213
6318
  const coords = line.geometry.coordinates;
6214
6319
  const prevLine = lineStrings[i - 1];
6215
- const firstCoord = _5.first(coords);
6320
+ const firstCoord = _13.first(coords);
6216
6321
  const isFirstLine = i === 0;
6217
6322
  if (isFirstLine) {
6218
6323
  accLine.push(...coords);
6219
6324
  continue;
6220
6325
  }
6221
- const prevLastCoord = _5.last(prevLine.geometry.coordinates);
6222
- const isNearby = turfDistance(point(firstCoord), point(prevLastCoord)) < distance;
6326
+ const prevLastCoord = _13.last(prevLine.geometry.coordinates);
6327
+ const isNearby = turfDistance2(point(firstCoord), point(prevLastCoord)) < distance5;
6223
6328
  if (!isNearby) {
6224
6329
  const remainingLines = lineStrings.slice(i);
6225
6330
  const res = this.combineNearbyLineStrings(remainingLines, properties);
@@ -6239,8 +6344,8 @@ var IndoorMap = class extends EventTarget {
6239
6344
  create3DStepPath
6240
6345
  } = this.#styler;
6241
6346
  const routeMarkerLayer = this.map.getLayer(HIGHLIGHT_LAYER_NAME);
6242
- const linesByOrdinal = _5(stepGeometries).filter(({ geometry }) => geometry.type === "LineString").groupBy("properties.ordinal").value();
6243
- const joinedLines = _5(linesByOrdinal).reduce((acc, lines, key) => {
6347
+ const linesByOrdinal = _13(stepGeometries).filter(({ geometry }) => geometry.type === "LineString").groupBy("properties.ordinal").value();
6348
+ const joinedLines = _13(linesByOrdinal).reduce((acc, lines, key) => {
6244
6349
  const joined = this.combineNearbyLineStrings(lines, {
6245
6350
  properties: { ordinal: +key }
6246
6351
  });
@@ -6268,14 +6373,14 @@ var IndoorMap = class extends EventTarget {
6268
6373
  stepElement = createOriginMarker(stepGeometry).addTo(routeMarkerLayer);
6269
6374
  break;
6270
6375
  case "destination-marker":
6271
- const extrudeConfig = _5.get(this.#mapConfig, "extrude");
6376
+ const extrudeConfig = _13.get(this.#mapConfig, "extrude");
6272
6377
  if (destinationFeature.feature_type === "occupant") {
6273
- const stepId = _5.get(stepGeometry, "id");
6378
+ const stepId = _13.get(stepGeometry, "id");
6274
6379
  const normalizedDestinationFeature = {
6275
6380
  ...destinationFeature,
6276
6381
  id: stepId
6277
6382
  };
6278
- const logoUrl = _5.get(
6383
+ const logoUrl = _13.get(
6279
6384
  normalizedDestinationFeature,
6280
6385
  "properties.logo.url"
6281
6386
  );
@@ -6320,15 +6425,15 @@ var IndoorMap = class extends EventTarget {
6320
6425
  const routeMarkerLayer = this.map.getLayer(
6321
6426
  HIGHLIGHT_LAYER_NAME
6322
6427
  );
6323
- const originMarkerGeometry = _5.get(
6428
+ const originMarkerGeometry = _13.get(
6324
6429
  this.#elements,
6325
6430
  `${ORIGIN_MARKER_ID}.geometry`
6326
6431
  );
6327
- const destinationMarkerGeometry = _5.get(
6432
+ const destinationMarkerGeometry = _13.get(
6328
6433
  this.#elements,
6329
6434
  `${DESTINATION_MARKER_ID}.geometry`
6330
6435
  );
6331
- const geometriesToRemove = _5.compact([
6436
+ const geometriesToRemove = _13.compact([
6332
6437
  originMarkerGeometry,
6333
6438
  destinationMarkerGeometry
6334
6439
  ]);
@@ -6339,7 +6444,7 @@ var IndoorMap = class extends EventTarget {
6339
6444
  (obj) => !(obj instanceof NavigationPath)
6340
6445
  );
6341
6446
  const objects = this.#navigationGeometries || {};
6342
- _5.forEach(objects, (obj) => {
6447
+ _13.forEach(objects, (obj) => {
6343
6448
  if (!obj) return;
6344
6449
  this.#navigationGeometries[obj.properties.id] = null;
6345
6450
  obj.remove();
@@ -6376,7 +6481,7 @@ var IndoorMap = class extends EventTarget {
6376
6481
  }
6377
6482
  if (this.threeLayer) {
6378
6483
  const currentView = this.camera.getView();
6379
- const objectOpacity = _5.clamp(38 - 2 * currentView.zoom, 0, 1);
6484
+ const objectOpacity = _13.clamp(38 - 2 * currentView.zoom, 0, 1);
6380
6485
  this.#objects.forEach((object) => {
6381
6486
  object.getObject3d().traverse((child) => {
6382
6487
  if (child.isMesh) child.material.opacity = objectOpacity;
@@ -6386,7 +6491,7 @@ var IndoorMap = class extends EventTarget {
6386
6491
  });
6387
6492
  if (this.#billboardObjects) {
6388
6493
  this.#billboardObjects.forEach((object) => {
6389
- const objectScale = _5.clamp(
6494
+ const objectScale = _13.clamp(
6390
6495
  20 - 1 * currentView.zoom,
6391
6496
  1,
6392
6497
  1.05
@@ -6395,7 +6500,7 @@ var IndoorMap = class extends EventTarget {
6395
6500
  });
6396
6501
  }
6397
6502
  if (this.#isLayersFadingOnZoom) {
6398
- const layerOpacity = _5.clamp(1 - objectOpacity, 0, 1);
6503
+ const layerOpacity = _13.clamp(1 - objectOpacity, 0, 1);
6399
6504
  LAYERS.forEach((layerKey) => {
6400
6505
  const layer = this.map.getLayer(layerKey);
6401
6506
  if (layer) layer.setOpacity(layerOpacity);