/*!
 * @kt/ktmap
 * https://ktcode.keytop.cn/front-framework/ktmap
 * (c) 2022 @wangzhifeng
 * Released under the MIT License.
 */
(function webpackUniversalModuleDefinition(root, factory) {
	if(typeof exports === 'object' && typeof module === 'object')
		module.exports = factory(require("vue"));
	else if(typeof define === 'function' && define.amd)
		define([], factory);
	else if(typeof exports === 'object')
		exports["ktmap"] = factory(require("vue"));
	else
		root["ktmap"] = factory(root["Vue"]);
})((typeof self !== 'undefined' ? self : this), function(__WEBPACK_EXTERNAL_MODULE__203__) {
return /******/ (function() { // webpackBootstrap
/******/ 	"use strict";
/******/ 	var __webpack_modules__ = ({

/***/ 206:
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {

module.exports = __webpack_require__.p + "assets/model/arrow/scene.efcad740.gltf";

/***/ }),

/***/ 954:
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {

module.exports = __webpack_require__.p + "assets/model/arrow_2/scene.df68fd37.gltf";

/***/ }),

/***/ 968:
/***/ (function(module) {

module.exports = "data:image/png;base64, ";

/***/ }),

/***/ 294:
/***/ (function(module, __unused_webpack_exports, __webpack_require__) {

module.exports = __webpack_require__.p + "assets/img/test.ea6fe232.jpeg";

/***/ }),

/***/ 972:
/***/ (function(module) {

module.exports = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAjCAYAAACD1LrRAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAARISURBVHgBzVdtaFtlFH5uetsmWZY0pWm3ZvZLhA23dgoV/GW1nYgoY/6QDoSuiIRRFOZQsGt+hOFAEWUqiEz8mOLU4aYUrDB0Y9pYBFltVwcTBt3akDVb0nwsTZrk3p2T3Rtu892Qwp7Lk3vf+557nnvO+77nvgE0kGW5g3ieGJCri7PEduSDIlptQS0CWnFBvZAk6SdBEPby9URwGu/7xjEdm0dKllAJ6gQRO/R2jLbsw57N3ertC6TxpFZYpLdJ8MW50AyGr3+CqBxHNWDU1eOzBxx4xrybm8skbKNzUqe+oGp47ObZqokyolIc7y2Nq80GVUsVrlV7rsQXUW38uzKvbdYQaSDupVt9AazKyYyFTTSj37QLgoB1Qabjt/AsfMlwup2ClC0MMWObB/2mnTjYtAe/hC5hPXjW/Eja43fL7oI2qnDemARBh8ux63hn6WesB211TeSweJp02AAkaLiSlOANF9ZRdMe27oddtKbbTu8POBP8u8QzVYBEA3oltogv20fQUWdDOLVSsvCownL+bhmSjLLwTeAPnPRfxMf2l7FVbChmmvZYdHJN0Gz+PTyXvu41PIg3mp/H/vkPM8vjsO052GrNGXueUFbRiPGuN9H3vwuR/IVIpxXOi+VUlH6jadGPtg3j0OLJNWtyLrYAc8KQadfQKug1dGEh6cdqiclVVBhKpO+2voTDnq/xV/Tqmr5fw9OZa47W2fICrq0u4XWy1RaiLKxJdd6RbKox4duO1xCTkjhCXxktFhMBvHLjU0UUOLrlRbTWNuKQ5yuE0pkqjqJj7CcHn98+j6c398Dl/ZFSH8n0RaWExlLAXHwBb988gxU5gXJQNNUSHcdvTaBOJ2K48Qm85TmFgHQnx45r86nAJNaDkuuYP2tHKdrbyQiObztQshSWCzH3ho7K3drFzwVizPs9Ht/0EAou+SKoE3ITm1NAug0F9mR0uO9crUAW2F5vLygspFKp9MeTi4JRqEe1wL6ObNlXUBixWOw/PvPe6Iu2g+jRt+dNUbmoIdePGjpxos2BAdpMMILB4DmtjWC1Wi1jY2NPJZPJkLxBYN+jo6P9pMc1NjNDjcROh8Ox1+PxXJSriEQiEfb5fJfYt16v7ySdTSyc2d4SLcRm5Y1qs1M3NDTUOjg4uHtgYOBVURRN2j6KJjIzM3N6ZGTk9NTUlFplZCUyXiJcVXgO3SIG+BHt8/WKcBdxB/Fh4k7NuYf4mNPpPJAdlcvlGqK+XiJvnndpnmNu52wSbYpGTiEQlEiNStQNFouFtxTMRpPJ1Kw46HG73R+oorOzsyfoHv9V6CC2sK3CBobiy6j4Lll9hCzy7OdtKY8PL8puv9//j9frvcARGgwGu9InKrbZz+egBuVBVphSKMTj8cuTk5N/0pjeoDH2070V3BvPsmpMJYWXI+LJpW49QsSIIrrh4JTy1sPY19dXeZWpEAXH777GXafq3MOcWpbiAAAAAElFTkSuQmCC";

/***/ }),

/***/ 973:
/***/ (function(module) {

module.exports = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAjCAYAAACD1LrRAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAR1SURBVHgBzVZ/aJRlHP887917tzuX2zmdtTWmElSkTodbhTFnjaiBCRE26I+FUCNWQf8Ejk2YSf8USJEIBUUGBUllQRKVNaXNLdnmNlEK6p+teTm963TO2/vr6fu873Pnu9vd7sdO8AMf3vf5+fn+ep/3AVzgnK8j/kqM8uLiG2It0kGKFlvQjahbnCVeLMs6zhjbLd7Nye+gjx+EdXWELDJREBQflNAmqFsPwFPdmujtI42dbmEvWaPbolPfQzv1PLhxA0WBdwX8TZ/DU/OMaP1HwmvoaShy2JeYp53bXzxRAdpLHzuYaJUntLyyQ02M8Oj57Jt5gvDc2wpG3lg3pmCFTy453YqMLFhNZEJYhFu5NUtDdmE/5e0peDa8AD53CfGvNyw9f2GdCOGkIEc+IOO4qVE9nADlDIUgEeo8VitQG9+jRwD62Tdg1e5xugNVYCtqnHfOwWMXKb/XswrnDBaoBL8ZhjHxNm08B+PCu2AVDfDv/Ao8cs4xraIe2vA+mH9/VgRhUVD37YX55xEYo93JbqWyCeojh6Gd3AUrOmb3+bZ/QilQltwuizCDUvscrEs/Ung/sHPrLhPlniehbnsH+lAnrLlp8rTBWRWsQjYkhNMXF50+al0PrBo60KiIjKFXkxXKQnVQH34f+pmXKfSXUdJ6Bjz+r7SXwRQ5Tg/uFmaZPGbBGnjUcjpCe0kz7tizdgfURz+EfmoPOIXU1/QFtP69sC6fRg5Q3MIZbDPo1DkA5qHDRvHb5tk5bSRPh14n00l0+6f2nBxFk8gqbF48lGw64T0MfbCTDo5J+Fp+gD78JqzJb5EHFoQ6bY5ZxTb4NlMFywplq7ZC63sW3DIc0aFXqPB+QSFYMsee8o00gw6K0f2OdXNTgH81/I8dhTbWW7CoWzgjOH0m1pUhx7q77qecfgxtZB+sf05gOcgiTOVzd7N9IAiId23gJfL0ZywXi4XFD4uKSsCYPG6LJ3Js/HGEvP8deUPxZRROFpdCBWRdPes0tBiMv45iuVBEraT2ySczTdP+lXhFFdMPvmigvdT6tzIKIx6PX7Dn1eyCb8eX9OnUpw1RzmAeKKsb6FSj+1bV03ZXLBb7acGUUChU1t3d/bhhGNf4bYLYu6ur6wnSWwnX5xskru/o6Ng9PT19mhcRuq5fn5mZGRV7l5SUrCcdkcfkvUUUWRmxUlqkpkauvb29qq2tbUtLS8trXq+31D1G3syOj48f6+zsPDY4ODgru7n0zCKKq7OooSvEqFjiXu+XwuLm9iDxIeJG17OO2NjT0/Niqle9vb3tNCZ+xluIm1zrBB8Q0SSukRqLTkkmPQ1Kr8vLyspC9BRcVVpaWik3qBsYGDiUEJ2YmPiI+jYT1xHXirmS5QJyr6DcO+vdjqVQVL+4lor8VAuhSCQyHA6H+4SHgUCgWo555dzU9YvgQW7gkqYkm5+fP9/f3/8b5XSSchyhvptw8pnTVbmQS7HwSBTXStm+RpyVorcdIqQBYrC5uTnvK/JykTF/dzT+Bwhr7+UIEIWiAAAAAElFTkSuQmCC";

/***/ }),

/***/ 905:
/***/ (function(module) {

module.exports = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAjCAYAAACD1LrRAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAQUSURBVHgBzVZbbBRVGP7OzO7spZe9SFulElgsicSWSxNMVJQFG40myqPVl+WtD40PPlpbTZVEHzT6buIlGmLkATXRSAihENvUGCp2KyReEFMoC4VdWpaw3Zmdw3+mZ9rZbrc7uywJX/Jl5vznP/83/38ucwAHOOebiCeIGV5fHCFuxGqQovUWdCLjFGf2i2ma3zHG9ov3wvQP0CcPwrw+QV9UQE1QNCiRLnh3vgu1/UXbOkIae53CHvoa3RK9+CPyJ18BN26hLvA0wPfMIagbXhatGyTcQk9Dkd2a7Zc/83b9RAUolv7HQbsVtrU80uC1e3hmqmIs1rQFassT4IzBvHIKPPvfmv5mesLZVEUIkbEot7LslUdF+NdB7UjAt/tzqLFXK/sXrxMhvCTIUQ3yGRoegHHx55oXn11q5npE0yPQdn8N/c+PgNxlyATAmrfA2/kmvTDamiaMs5+A30iWDaOgSijhLhjJ92Fe+AZmaoR43LKrLU/R3Mdozk9CadoM9YHuNeN44BKsYSNYtBvm9JGyPjx7AcY/X0Bp24NKWFOYBR+m0nZQSa9Ce/or6GfeKe73t8H33HEwbwNtkjCMvz+DW9jCqy4u9aF9tGpfI68m6FMfwqTDpXh0wBLNHd272F7IwAW4U7jM4lLouHsexqVjVMbz9hgrU6h+q/xWJCpxFVCcwquicO1X5CfesrYM00JLZdF6foLiiy76XD+NWrCmMJ87Ryv4XIldiOaOxinT/1EDikpd8QARfxolKreIFsbdwvUBom59g/ZnbHHLnD8EfjuFu4H7fUwnUoH2qPHvl6gHXAuL2VA7DkB5MF7RUyUfM3UC1QkzMnGjxKwnP4Da+iTcwLwyAmP6+2WDopUVXlpcSnQnXXl+K3Hk83/BINYCJdxZapNPVigUblpfsm3Quq7UDRTL2/1eWWHkcrmzlt+Gl6Dt+db6IaxWItdgKpR1u6CJ+9b6FyzT3NzcsSKXSCQSGhwc3GcYxjy/RxCxBwYGniW9Zji2b5AY6+vr2z8zM3OK1xG6rt+cnZ39XcT2+/0x0hHzyJaut8QQsVV+kXdl5RKJxPre3t4dPT09r3s8nkZnH2WTnZycPNzf3394fHw8K81cZmYSxdVZrKFrRPELK9o2Pim8mbiV+Bix0/HcTnx8aGjowMqshoeHE9S3i7iD2OUYJ/ioqCaxRWqUnJJMZhqUWYdDoVCEnoLRxsbGVhlg+9jY2Me2aDKZ/JRs24ibiG3CVzIsIGMFZeyKRzNbQbH6xa1OzE+7EEqn06dTKbp0UYaBQKBd9nmk78rxJVDhDlyyIMkWFhamRkdHf6E5naY5TpPtNhbn09VV2f21dhkiI7G4mmV7npiVovccoqQBYjAej1fxo6kPys7ffY07u+e0y92piJwAAAAASUVORK5CYII=";

/***/ }),

/***/ 654:
/***/ (function(module) {

module.exports = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAjCAYAAACD1LrRAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAONSURBVHgBzVZLSFRRGP7veH2MTY7jK3IqNaLsqYW19rVqkdEDXEQTFLiQaNdCZhbSInATuIto1S6JigKDoKQasUUIGmVEUDQM2uToOKJj87h9f3PuzHWe9+oUffBxH+ec/zv/f/7/nEOkgaIojeBLcEEpLB6CDZQJQrTQglosaMUl9SUWiz2SJKmH372/iFzfiGZWiIJR2jA6K4mu7yCqL0n8GoNGh1ZYxmzCquj5j5sT1GJrEdHI/oT4IoRr8YyYRHtiTkOewoky2Jbra+KzUtVShYvVlheLVHDMrK77RAxIkikeblOugaesRBeqiUI6IlEKs8M/iNzLyX8pEWRhksWHksMW2cuJngaIRucpLy5uJ6opxcty7n6qsER5EBCzu9aQvc9NVMIK6YNMBrAFbOIsDaS3Xa6Kt+uFIWGGB4nyOEPIz1rIEAwLd6IKn1Wl/68qIkPQlVwqvODpT9nbdVaiohXOm1xdCOWufNPDIh8zEz0I5exl0grnxJOfREd3ElWjrN6KxOKKsWHbmQsnw9WCyc2jZl/rcF2XsAfG52BwEok1GiSqQHyGUFYy1nUJ3jmxBitQL8FmWI/+gdyR+dNq0n7oRRtC6kXBXvlCtIqRew2naFI47xpr8RleNiOs55DdjYi5J0KGYTLSGXlDNeAqhO4ivHvg6TBOM44X/7casKU7SB6E9gwsn0zZKA6Yk+9lWPN7OvbzjMJ8cGc6j2/74iwU0pJrn5kKjg5rdmEpGo0G+eVGQ9zrQoFt8b0rmzCFQqEP/LQjS+83Z56lUcE2S9wW22QEAoHn2j6SzWazOp3OzkgksqT8JbDtgYGBLuhVkKZ8sRlSU19fX4/X632lFBDhcDjo8/km2XZZWVkTxY9tKXG9pXgZ1okZFaeGzuFw1Pf29rZ2d3dflWV5XVHBm+WpqamR/v7+kYmJCfXSowjPYiBfnTmHsOvTAg/Rji8VwrtB3ITpIHhI82wBT7hcrkupXg0ODjrQdhxsBQ9rxjGbOZpgrdBI2yUl4Wm58LrSarXa8GRWWSyWOmGgZXx8/JYqOj09fQf/joCN4DbuK1jJELbKhe28W7OUQs5+LjJeHzsL+f3+d7Ozs2Psodlstos2WfRNHZ8GvRWrCEYFpbW1tfdut/sN1vQ71tiPf3xtj5HOk87QqSTAHnFyVYjvJYrfomP0D8Ah5c21vL29fQOn8eaQdf3+a/wG6zVqvjXs5jQAAAAASUVORK5CYII=";

/***/ }),

/***/ 994:
/***/ (function(module) {

module.exports = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAjCAYAAACD1LrRAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAPoSURBVHgBzVZbbBRVGP7OzOy0XRe227Q0aUVBQoLhUiC20Qe0Sl80UeKL9smaGFOTamI08aFpiVXeDPGBGB98VR/kQWP0CRKuLQ13WiDAAy+QptCyS5cCuzuXw39mzwwzOyyzC8PlS76ZOf/55//O5Z9/DuAD53wFcR8xx+PF38SX8SBI0bgF/cj5xZn7YNv2P4yxbeLZuvIvjKkdsG+cpBFZeCQoOpTMeiQ2/QC18z3Xup803vYLazQawxG9+j9KBz4GN28jFmgvoOHNP6Eu/0C0bpJwG91NRXbrrl/p9Pb4RAUolnFmh9tqdrVc4YTbw3NnETfs7El/UyUyDeXlVu57lYJvCRdGvoyhJnBezgtu+mxWpTA0t6tanMRrP4G19tDolIoBsfKAbDNk50YexpEvwBcvVwvrCVedjnlhFxq2/IHisW8oAXKeXWl7A+pLH8I48V1woF3bYc3sBb9zFQ+DhigU5mnV7gD5S+DFG56ZN7SCl26CL1wIuDs+hWvhLauAgmeE+oTVJmhrxdIGd0Zd9QnU1Z/jITsWQmRy+cGSL0IRheDir55Nad8CvWcXPSRQzF+sJYyj5c44eqhMh771Pyit3Uh07/ReseePUYH4Hsa5nbDnJlEDFO9SE3iJSulHsC7/DuP4t/AWySqQ+FHY18cjE8qP6Kz2a+fOwJj4LGR3ROsIIy6Kv/E0EVlAkOxwshmpVbTNLZ6ZNbZTuU+DLVkdcGfaErK3lkstNyOFqzus+RKMMlZ//ZdgB1OckqnTLy9oVij7O2n5D9VUMqvCOPo1TFX8vOr45Kl+84hECwtXLhE9c9PEY0HRwyY3vGdo2YS4oTSvC9vknVmWdUs8aBtGnONKbKBYic0/VhVGoVA47/gtfx/6W3+BtWx+4BLVDEo8UeVE8qkd7zqmhYWFPQGXTCaTHhkZecc0zTx/QhCxh4eHt5LeUvg+3yRx5eDg4LaZmZmDPEYYhnFrbm7ulIjd2Ni4knTEPnoHKZHdaeIyOaJE5coNDAx09Pf3b+zr6/tK07SUv49mszg1NbV7aGho9+Tk5KI0czkzmyiOziKH5oniGBP4TBqk8CvEV4lriet89y5iz+jo6KeVsxobGxugvm7iRuJ633uCa8RqEtukRqhKMjnTpJx1czqdztBdsCWVSi2TAbomJiZ+dkWnp6d/I9sG4gpiu/CVbBaQsZIyduTvl1VQZL84lor96RRC2Wz2xOzs7H4xw6ampk7Zp0nfyvdDUFEbuKQlyYrF4tnx8fHDtKdXaI+zZLuL8n7WdppB/RAzEsm1VLbzxEUp+sQhlpT+lUj29vbWdZiIA1X377nGPZd3qM922EcPAAAAAElFTkSuQmCC";

/***/ }),

/***/ 203:
/***/ (function(module) {

module.exports = __WEBPACK_EXTERNAL_MODULE__203__;

/***/ })

/******/ 	});
/************************************************************************/
/******/ 	// The module cache
/******/ 	var __webpack_module_cache__ = {};
/******/ 	
/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {
/******/ 		// Check if module is in cache
/******/ 		var cachedModule = __webpack_module_cache__[moduleId];
/******/ 		if (cachedModule !== undefined) {
/******/ 			return cachedModule.exports;
/******/ 		}
/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = __webpack_module_cache__[moduleId] = {
/******/ 			// no module.id needed
/******/ 			// no module.loaded needed
/******/ 			exports: {}
/******/ 		};
/******/ 	
/******/ 		// Execute the module function
/******/ 		__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/ 	
/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}
/******/ 	
/************************************************************************/
/******/ 	/* webpack/runtime/compat get default export */
/******/ 	!function() {
/******/ 		// getDefaultExport function for compatibility with non-harmony modules
/******/ 		__webpack_require__.n = function(module) {
/******/ 			var getter = module && module.__esModule ?
/******/ 				function() { return module['default']; } :
/******/ 				function() { return module; };
/******/ 			__webpack_require__.d(getter, { a: getter });
/******/ 			return getter;
/******/ 		};
/******/ 	}();
/******/ 	
/******/ 	/* webpack/runtime/define property getters */
/******/ 	!function() {
/******/ 		// define getter functions for harmony exports
/******/ 		__webpack_require__.d = function(exports, definition) {
/******/ 			for(var key in definition) {
/******/ 				if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ 					Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ 				}
/******/ 			}
/******/ 		};
/******/ 	}();
/******/ 	
/******/ 	/* webpack/runtime/hasOwnProperty shorthand */
/******/ 	!function() {
/******/ 		__webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }
/******/ 	}();
/******/ 	
/******/ 	/* webpack/runtime/make namespace object */
/******/ 	!function() {
/******/ 		// define __esModule on exports
/******/ 		__webpack_require__.r = function(exports) {
/******/ 			if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ 				Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ 			}
/******/ 			Object.defineProperty(exports, '__esModule', { value: true });
/******/ 		};
/******/ 	}();
/******/ 	
/******/ 	/* webpack/runtime/publicPath */
/******/ 	!function() {
/******/ 		__webpack_require__.p = "";
/******/ 	}();
/******/ 	
/************************************************************************/
var __webpack_exports__ = {};
// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk.
!function() {
// ESM COMPAT FLAG
__webpack_require__.r(__webpack_exports__);

// EXPORTS
__webpack_require__.d(__webpack_exports__, {
  "default": function() { return /* binding */ entry_lib; }
});

;// CONCATENATED MODULE: ../../node_modules/@vue/cli-service/lib/commands/build/setPublicPath.js
/* eslint-disable no-var */
// This file is imported into lib/wc client bundles.

if (typeof window !== 'undefined') {
  var currentScript = window.document.currentScript
  if (false) { var getCurrentScript; }

  var src = currentScript && currentScript.src.match(/(.+\/)[^/]+\.js(\?.*)?$/)
  if (src) {
    __webpack_require__.p = src[1] // eslint-disable-line
  }
}

// Indicate to webpack that this file can be concatenated
/* harmony default export */ var setPublicPath = (null);

;// CONCATENATED MODULE: ../../node_modules/@babel/runtime/helpers/esm/defineProperty.js
function _defineProperty(obj, key, value) {
  if (key in obj) {
    Object.defineProperty(obj, key, {
      value: value,
      enumerable: true,
      configurable: true,
      writable: true
    });
  } else {
    obj[key] = value;
  }

  return obj;
}
;// CONCATENATED MODULE: external "three"
var external_three_namespaceObject = require("three");
;// CONCATENATED MODULE: external "element-resize-detector"
var external_element_resize_detector_namespaceObject = require("element-resize-detector");
var external_element_resize_detector_default = /*#__PURE__*/__webpack_require__.n(external_element_resize_detector_namespaceObject);
;// CONCATENATED MODULE: external "lodash/debounce"
var debounce_namespaceObject = require("lodash/debounce");
var debounce_default = /*#__PURE__*/__webpack_require__.n(debounce_namespaceObject);
;// CONCATENATED MODULE: external "tween.js"
var external_tween_js_namespaceObject = require("tween.js");
var external_tween_js_default = /*#__PURE__*/__webpack_require__.n(external_tween_js_namespaceObject);
;// CONCATENATED MODULE: external "camera-controls"
var external_camera_controls_namespaceObject = require("camera-controls");
var external_camera_controls_default = /*#__PURE__*/__webpack_require__.n(external_camera_controls_namespaceObject);
;// CONCATENATED MODULE: ./src/core/map/myCameraControls.ts




const _v3A = new external_three_namespaceObject.Vector3();

class MyCameraControls extends (external_camera_controls_default()) {
  constructor(...args) {
    super(...args);

    _defineProperty(this, "truckYDisabled", false);

    _defineProperty(this, "_truckInternal", (deltaX, deltaY, dragToOffset) => {
      const _this = this;

      const offset = _v3A.copy(_this._camera.position).sub(_this._target); // @ts-ignore


      const fov = _this._camera.getEffectiveFOV() * external_three_namespaceObject.MathUtils.DEG2RAD;
      const targetDistance = offset.length() * Math.tan(fov * 0.5);
      const truckX = _this.truckSpeed * deltaX * targetDistance / _this._elementRect.width;
      const pedestalY = _this.truckSpeed * deltaY * targetDistance / _this._elementRect.width;

      if (_this.verticalDragToForward) {
        dragToOffset ? _this.setFocalOffset(_this._focalOffsetEnd.x + truckX, _this._focalOffsetEnd.y, _this._focalOffsetEnd.z, true) : _this.truck(truckX, 0, true);

        _this.forward(-pedestalY, true);
      } else {
        dragToOffset ? _this.setFocalOffset(_this._focalOffsetEnd.x + truckX, _this._focalOffsetEnd.y + pedestalY, _this._focalOffsetEnd.z, true) : _this.truck(this.truckYDisabled ? 0 : truckX, pedestalY, true);
      } // const offset = _v3A.copy(this._camera.position).sub(this._target);
      // // half of the fov is center to top of screen
      // // @ts-ignore
      // const fov = this._camera.getEffectiveFOV() * MathUtils.DEG2RAD;
      // const targetDistance = offset.length() * Math.tan(fov * 0.5);
      // const truckX =
      //   (this.truckSpeed * deltaX * targetDistance) / this._elementRect.w;
      // const truckY =
      //   (this.truckSpeed * deltaY * targetDistance) / this._elementRect.w;
      // this.truck(this.truckYDisabled ? 0 : truckX, truckY, true);

    });
  }

}
;// CONCATENATED MODULE: ./src/core/utils.ts
 // let timer = 0
// export const reDraw = (time = 3000) => {
//   // @ts-ignore
//   CameraControls.viewChanged = true
//   clearTimeout(timer)
//   timer = setTimeout(() => {
//     // @ts-ignore
//     CameraControls.viewChanged = false
//   }, time)
// }

/**
 * @desc 射线拾取
 */

function getIntersects({
  event,
  $map,
  scene,
  camera,
  objects
}) {
  const {
    top,
    left
  } = $map.getBoundingClientRect(); // 声明raycaster和mouse变量

  const raycaster = new external_three_namespaceObject.Raycaster();
  const mouse = new external_three_namespaceObject.Vector2(); // 通过鼠标点击的位置计算出raycaster所需要的点的位置，以屏幕中心为原点，值的范围为-1到1.

  mouse.x = (event.clientX - left) / $map.clientWidth * 2 - 1;
  mouse.y = -((event.clientY - top) / $map.clientHeight) * 2 + 1; // 通过鼠标点的位置和当前相机的矩阵计算出raycaster

  raycaster.setFromCamera(mouse, camera); // 获取raycaster直线和所有模型相交的数组集合，注意：true表示返回的值会递归，找到更深层次的模型

  const intersects = raycaster.intersectObjects(objects || scene.children, true); // 2d 场景下会存在bug，就是选择点的时候，跑到中心点去了，数组第一个是对象 AxesHelper 导致的，这里进行过滤
  // intersects = intersects.filter(item => !(item.object instanceof AxesHelper))
  // if (filter) {
  //   intersects = filter(intersects)
  // }

  return intersects;
}
/**
 * @desc 射线拾取对象，获取世界坐标
 * objects 传入需要被射线拾取的物体。精准判断情况，不传入 objects， 获取被射线拾取的所有对象，然后再判断第一个对象是否被命中，即可判断当前是否点击了想要的对象。
 * @return 返回第一个点和所有被射线拾取的对象
 */

function getWorldPosition({
  event,
  $map,
  scene,
  camera,
  objects
}) {
  const intersects = getIntersects({
    event,
    $map,
    scene,
    camera,
    objects
  });
  const points = intersects.map(item => item.point);
  const worldPosition = new external_three_namespaceObject.Vector3();

  if (points.length > 0) {
    worldPosition.set(points[0].x, points[0].y, points[0].z);
    return {
      worldPosition,
      intersects
    };
  }

  return {};
}
/**
 * @desc 根据 name 获取对应的对象集合
 */

function utils_getObjectsByName(name, parent) {
  // scene.getObjectByName 只会返回第一个
  // return scene.getObjectByName(name);
  // 不能深层遍历
  // return scene.children.filter(item => item.name === name);
  // 较优算法
  const arr = [];
  parent.traverse(item => {
    if (item.name === name) arr.push(item);
  });
  return arr;
}
function getPointBetweenPoints({
  p1,
  p2,
  // +1 把终点加入
  segment = Math.abs(Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2))) + 1,
  // 从 0 开始，把起点加入
  i = 0
}) {
  return {
    point: new Vector2((p2.x - p1.x) / segment * i + p1.x, (p2.y - p1.y) / segment * i + p1.y),
    segment
  };
}
/**
 * @desc 计算两个坐标连线后的倾斜角度
 */

function getAngle(p1, p2) {
  const radian = Math.atan2(p2.y - p1.y, p2.x - p1.x);
  const angle = radian * (180 / Math.PI);
  return {
    radian,
    angle
  };
}
const CLS_PREFIX = 'ktmap';
;// CONCATENATED MODULE: external "stats.js"
var external_stats_js_namespaceObject = require("stats.js");
var external_stats_js_default = /*#__PURE__*/__webpack_require__.n(external_stats_js_namespaceObject);
;// CONCATENATED MODULE: ./src/core/map/createStats.ts

function createStats(container) {
  const stats = new (external_stats_js_default())();
  stats.showPanel(0); // 0: fps, 1: ms, 2: mb, 3+: custom

  document.querySelector(`.${container}__stats-wrapper`)?.remove();
  document.getElementById(container)?.appendChild(stats.dom);
  stats.dom.className = `.${container}__stats-wrapper`;
  stats.dom.style.cssText = 'position: absolute; bottom: 0px; right: 0px; cursor: pointer; opacity: 0.9; z-index: 10000;';
  return stats;
}
;// CONCATENATED MODULE: external "mitt"
var external_mitt_namespaceObject = require("mitt");
var external_mitt_default = /*#__PURE__*/__webpack_require__.n(external_mitt_namespaceObject);
;// CONCATENATED MODULE: ./src/core/parkingLayer/index.type.ts
/**
 * @desc 统一配置对象的 name 属性
 */
var index_type_OBJECT_NAME;

(function (OBJECT_NAME) {
  OBJECT_NAME["level"] = "level";
  OBJECT_NAME["floor"] = "floor";
  OBJECT_NAME["park"] = "park";
  OBJECT_NAME["parkBorder"] = "parkBorder";
  OBJECT_NAME["pillar"] = "pillar";
  OBJECT_NAME["machine"] = "machine";
  OBJECT_NAME["connector"] = "connector";
})(index_type_OBJECT_NAME || (index_type_OBJECT_NAME = {}));

var ICONNECTOR;

(function (ICONNECTOR) {
  ICONNECTOR[ICONNECTOR["zhiti"] = 1] = "zhiti";
  ICONNECTOR[ICONNECTOR["futi"] = 2] = "futi";
  ICONNECTOR[ICONNECTOR["louti"] = 3] = "louti";
  ICONNECTOR[ICONNECTOR["churukou"] = 4] = "churukou";
})(ICONNECTOR || (ICONNECTOR = {}));
;// CONCATENATED MODULE: ./src/core/parkingLayer/utils.ts



const material = {
  MeshLambertMaterial: external_three_namespaceObject.MeshLambertMaterial,
  MeshStandardMaterial: external_three_namespaceObject.MeshStandardMaterial,
  MeshPhysicalMaterial: external_three_namespaceObject.MeshPhysicalMaterial,
  MeshPhongMaterial: external_three_namespaceObject.MeshPhongMaterial,
  MeshBasicMaterial: external_three_namespaceObject.MeshBasicMaterial,
  LineBasicMaterial: external_three_namespaceObject.LineBasicMaterial,
  SpriteMaterial: external_three_namespaceObject.SpriteMaterial
};
const OBJECT_BASE_CONF = {
  floor: {
    name: 'floor',
    material: 'MeshLambertMaterial',
    color: '#fff',
    transparent: true,
    opacity: 1
  },
  park: {
    name: 'park',
    material: 'MeshLambertMaterial',
    color: '#44c3b4',
    transparent: true,
    opacity: 1 // depthWrite: false,
    // depthTest: false,

  },
  parkBorder: {
    name: 'parkBorder',
    material: 'LineBasicMaterial',
    color: '#f6ffed',
    transparent: true,
    opacity: 1
  },
  pillar: {
    name: 'pillar',
    material: 'MeshLambertMaterial',
    color: '#e7e7e7',
    // depthWrite: false,
    transparent: true,
    opacity: 1
  },
  machine: {
    name: 'machine',
    material: 'SpriteMaterial'
  },
  // 通行设施
  connector: {
    name: 'connector',
    material: 'SpriteMaterial'
  }
};
/**
 * @desc 数组坐标转换为 threejs 坐标
 */

const arrayPoints23Points = points => {
  const shapePoints = [];
  let point;

  for (let i = 0, len = points.length; i < len; i += 2) {
    point = new external_three_namespaceObject.Vector2(+points[i], +points[i + 1]);
    shapePoints.push(point);
  }

  return shapePoints;
};
/**
 * @desc 赋值 Material 的时候去掉一些没有必要的属性
 */

const deletePropertyForMaterial = conf => {
  const newConf = JSON.parse(JSON.stringify(conf));
  Reflect.deleteProperty(newConf, 'material');
  Reflect.deleteProperty(newConf, 'renderOrder');
  Reflect.deleteProperty(newConf, 'depth');
  return newConf;
};
const renderOrderConf = [['floor'], ['park'], ['parkBorder'], ['pillar'], ['machine', 'connector']];
/**
 * @desc 根据楼层索引返回新的 renderOrder 保证遮盖了比它低的楼层物体
 */

const getRenderOrderPlusByLevel = level => renderOrderConf.length * level;

const getRenderOrder = name => {
  const index = renderOrderConf.findIndex(item => item.find(itemj => itemj === name));
  return index > -1 ? index : 0;
};
/**
 * ！！！需要替换掉
 * @desc 皮肤颜色，初始化时候需要判断本地存储然后把颜色值赋值给 OBJECT_BASE_CONF
 */


const THEME = {
  normal: {
    floor: {
      color: '#484f5a'
    },
    park: {
      color: '#689f79'
    },
    parkBorder: {
      color: '#fff'
    },
    pillar: {
      color: '#fff'
    },
    machine: {
      color: ''
    },
    connector: {
      color: ''
    }
  }
};
const currTheme = THEME.normal;

for (const key of Object.keys(OBJECT_BASE_CONF)) {
  // @ts-ignore
  OBJECT_BASE_CONF[key].color = currTheme[key].color; // @ts-ignore 初始化 渲染顺序 renderOrder

  OBJECT_BASE_CONF[key].renderOrder = getRenderOrder(key);
}
/**
 * @desc 获取当前楼层整体对象
 */


function getCurrentLevelObj(currentLevel, parent) {
  currentLevel = parseInt(currentLevel);
  const levelObj = getObjectsByName(OBJECT_NAME.level, parent).find(_ => _.userData.zIndex === currentLevel);
  return levelObj;
}
function getDollys(targetMesh, controls, offset = 5) {
  if (!targetMesh) {
    return {
      fitDistance: 0,
      dollys: [0]
    };
  }

  const bb = new external_three_namespaceObject.Box3().setFromObject(targetMesh);
  const fitDistance = controls.getDistanceToFitBox(bb.max.x - bb.min.x, bb.max.y - bb.min.y, bb.max.z - bb.min.z);
  const minDollys = [...new Array(offset)].map((_, i) => fitDistance / (i + 2)).reverse();
  const maxDollys = [...new Array(offset)].map((_, i) => fitDistance * (i + 2));
  const dollys = [...minDollys, fitDistance, ...maxDollys];
  return {
    fitDistance,
    dollys
  };
}
;// CONCATENATED MODULE: ./src/core/map/map.ts



 // @ts-ignore








const subsetOfTHREE = {
  MOUSE: external_three_namespaceObject.MOUSE,
  Vector2: external_three_namespaceObject.Vector2,
  Vector3: external_three_namespaceObject.Vector3,
  Vector4: external_three_namespaceObject.Vector4,
  Quaternion: external_three_namespaceObject.Quaternion,
  Matrix4: external_three_namespaceObject.Matrix4,
  Spherical: external_three_namespaceObject.Spherical,
  Box3: external_three_namespaceObject.Box3,
  Sphere: external_three_namespaceObject.Sphere,
  Raycaster: external_three_namespaceObject.Raycaster,
  MathUtils: {
    DEG2RAD: external_three_namespaceObject.MathUtils.DEG2RAD,
    clamp: external_three_namespaceObject.MathUtils.clamp
  }
};
class _Map {
  constructor(container, {
    style = 'normal',
    showStats = false,
    viewMode = '3D'
  } = {}) {
    _defineProperty(this, "container", void 0);

    _defineProperty(this, "options", void 0);

    _defineProperty(this, "stats", void 0);

    _defineProperty(this, "scene", void 0);

    _defineProperty(this, "camera", void 0);

    _defineProperty(this, "$map", void 0);

    _defineProperty(this, "renderer", void 0);

    _defineProperty(this, "updateSizeMap", new Map());

    _defineProperty(this, "emitter", external_mitt_default()());

    _defineProperty(this, "timer", 0);

    _defineProperty(this, "viewChanged", false);

    _defineProperty(this, "cameraControls", void 0);

    _defineProperty(this, "reDraw", (time = 3000) => {
      this.viewChanged = true;
      clearTimeout(this.timer);
      this.timer = setTimeout(() => {
        this.viewChanged = false;
      }, time);
    });

    this.container = container;
    this.options = {
      style,
      showStats,
      viewMode
    };
    const {
      scene,
      camera,
      cameraControls,
      $map,
      renderer
    } = this.init();
    this.scene = scene;
    this.camera = camera;
    this.cameraControls = cameraControls;
    this.$map = $map;
    this.renderer = renderer; // 配置相机相关的参数

    this.reset();
    this.setShowStats(showStats); // this.marker.updateSize();
  }

  getScene() {
    return this.scene;
  }
  /**
   * @desc 二封 scene.add
   * to do：
   * - 需要判断新增的 layer 是否重名，判断 name 属性
   */


  add(...object) {
    const {
      camera,
      $map,
      scene,
      cameraControls,
      reDraw
    } = this;
    let obj = object[0]; // https://blog.csdn.net/sujun10/article/details/64924125
    // switch (obj?.constructor?.name) {
    // @ts-ignore

    switch (obj?.MY_NAME) {
      case 'PoisLayer':
        obj = obj; // 判断如果当前如果添加的是一个 marker 就需要添加到一个数组，后续会根据这个数组循环 updateSize
        // 注入需要的参数

        obj._inject(this);

        obj._init();

        this.updateSizeMap.set(obj, obj._updateSize.bind(obj));
        console.log('add-this.updateSizeMap :>> ', this.updateSizeMap);
        break;

      case 'ParkingLayer':
        obj = obj; // 判断如果当前如果添加的是一个 marker 就需要添加到一个数组，后续会根据这个数组循环 updateSize

        obj._inject(this);

        obj._init();

        this.updateSizeMap.set(obj, obj._updateSize.bind(obj));
        console.log('add-this.updateSizeMap :>> ', this.updateSizeMap);
        break;

      default:
        // @ts-ignore
        this.scene.add(...object);
        break;
    }

    this.reDraw();
    console.log('add-current-scene :>> ', this.scene);
    return this;
  }

  remove(...object) {
    let obj = object[0]; // switch (obj?.constructor?.name) {
    // @ts-ignore

    switch (obj?.MY_NAME) {
      case 'PoisLayer':
        obj = obj; // 判断如果当前如果添加的是一个 marker 就需要添加到一个数组，后续会根据这个数组循环 updateSize

        this.updateSizeMap.delete(obj);
        console.log('delete-this.updateSizeMap :>> ', this.updateSizeMap);
        this.scene.remove(obj._group);
        break;

      default:
        // @ts-ignore
        this.scene.remove(...object);
        break;
    }

    this.reDraw();
    console.log('add-current-scene :>> ', this.scene);
    return this;
  }

  on(type, handler, ext) {
    // mitt 监听
    this.emitter.on(type, handler);

    switch (type) {
      case 'click':
        {
          // 做长按兼容
          document.onmousedown = ev => {
            // 右键可拖拽画布，保持 controls 原来功能
            if (ev.which === 3) return;
            const time = +new Date();

            document.onmouseup = () => {
              const newTime = +new Date();

              if (newTime - time > 300) {} else {
                const {
                  scene,
                  camera,
                  $map
                } = this;
                const obj = getWorldPosition({
                  event: ev,
                  scene,
                  camera,
                  $map,
                  objects: ext?.objects?.()
                });
                this.emitter.emit('click', Object.assign(ev, obj));
              }
            };
          }; // document.getElementById(this.container)!.onclick = ev => {
          //   const { scene, camera, $map } = this;
          //   const worldPosition = getWorldPosition({
          //     event: ev,
          //     scene,
          //     camera,
          //     $map,
          //     objects: ext?.objects
          //   });
          //   this.emitter.emit('click', Object.assign(ev, { worldPosition }));
          // };


          break;
        }

      default:
        break;
    }

    return this;
  }

  off(type, handler) {
    switch (type) {
      case 'click':
        document.getElementById(this.container).onclick = null;
        break;

      default:
        break;
    }

    this.emitter.off(type, handler);
    return this;
  }
  /**
   * @desc 重渲染，为了提高性能，往场景添加元素，需要调用 redraw
   * 箭头函数，保证 this 指向正确
   */


  /**
   * @desc 初始化地图：场景，相机，灯光，渲染器，rendererResize，轨道控制器
   */
  init() {
    const $map = document.getElementById(this.container); // #region 场景

    const scene = new external_three_namespaceObject.Scene(); // #endregion
    // #region 相机

    const width = $map.clientWidth;
    const height = $map.clientHeight;
    const k = width / height;
    /**
     * 后面两个参数的概念，就像人的眼睛
     * 第三个参数想象成距离人的眼睛，多近才会看不到，比如 0.1，表示小于0.1，人才会看不到
     * 第四个参数想象成距离人的眼睛，多远才会看不到，比如 10000，表示大于10000，人才会看不到
     */
    // const camera = new THREE.PerspectiveCamera(45, k, 0.01, 83150);
    // 最后一个参数是要进行判断，还是说直接设置一个很大的值？？
    // const camera = new THREE.PerspectiveCamera(45, k, 0.01, 1000000);
    // const camera = new PerspectiveCamera(45, k, 0.01, Math.pow(10, 100));

    const camera = new external_three_namespaceObject.PerspectiveCamera(45, k, 0.01, Math.pow(10, 100)); // const camera = new PerspectiveCamera(45, k, 0.01, Math.pow(10, 100));
    // const camera = new PerspectiveCamera(45, k, Math.pow(0.01, 100), 100);
    // const camera = new THREE.PerspectiveCamera(45, k, 0.01, 2000);
    // 把z轴向上

    camera.up.x = 0;
    camera.up.y = 0;
    camera.up.z = 1; // 设置相机方向(指向的场景对象)
    // camera.position.set(0, -736903.9005224737, 425451.6653335355)

    camera.lookAt(scene.position); // #endregion
    // #region 灯光

    const light = new external_three_namespaceObject.HemisphereLight('#ffffff', '#e7e7e7', 1.0);
    light.name = 'light';
    light.position.set(-100, -100, 0);
    scene.add(light); // #endregion
    // #region 渲染器

    const renderer = new external_three_namespaceObject.WebGLRenderer({
      // 抗锯齿，开启来会比较卡，按情况开启
      antialias: true,
      alpha: true,
      logarithmicDepthBuffer: true
    });
    renderer.setSize($map.clientWidth, $map.clientHeight); // 设置背景颜色

    renderer.setClearColor('#e7f2fe', 1); // renderer.setClearColor(0xd3df56, 1) // 设置背景颜色
    // 暗黑模式
    // renderer.setClearColor(THEME.dark.renderer.color, 1); //设置背景颜色

    renderer.setPixelRatio(window.devicePixelRatio);
    $map.appendChild(renderer.domElement);
    renderer.render(scene, camera); // #endregion
    // #region rendererResize

    const onWindowResize = debounce_default()(() => {
      const width = $map.clientWidth;
      const height = $map.clientHeight;
      camera.aspect = width / height;
      camera.updateProjectionMatrix();
      renderer.setSize(width, height);
      this.reDraw();
    }, 100);
    const observer = external_element_resize_detector_default()();
    observer.listenTo($map, onWindowResize); // #endregion
    // #region 相机控制器

    const cameraControls = this.createCameraControls(scene, camera, renderer, () => {
      for (const [, value] of this.updateSizeMap) {
        value?.();
      }
    }); // #endregion
    // 地图渲染完毕
    // emitter.emit('complete')

    return {
      scene,
      camera,
      cameraControls,
      $map,
      renderer
    };
  }
  /**
   * @desc 相机控制器
   */


  createCameraControls(scene, camera, renderer, updateFn) {
    MyCameraControls.install({
      THREE: subsetOfTHREE
    });
    const clock = new external_three_namespaceObject.Clock();
    const controls = new MyCameraControls(camera, renderer.domElement);

    const _this = this;

    (function anim() {
      _this.stats?.begin(); // snip

      const delta = clock.getDelta();
      const hasControlsUpdated = controls.update(delta);
      external_tween_js_default().update(); // you can skip this condition to render though
      // 不再把 viewChanged 放置 CameraControls 作为静态属性，这样子不能保证多例，因为静态属性会共享一个副本
      // if (hasControlsUpdated || CameraControls.viewChanged) {

      if (hasControlsUpdated || _this.viewChanged) {
        renderer.render(scene, camera); // 一些会受到相机改变影响的方法

        updateFn();
      }

      _this.stats?.end();
      requestAnimationFrame(anim);
    })();

    renderer.render(scene, camera);
    return controls;
  }
  /**
   * @desc 恢复到相机的初始状态
   */


  reset() {
    const {
      cameraControls,
      camera
    } = this; // 休息阈值，默认 0.0025，调整会影响到 await 的过渡时长
    // controls.restThreshold = 0.0025;
    // controls.restThreshold = 0.01;
    // controls.restThreshold = 10;
    // 阻尼惯性，默认 0.05，调整会影响到 await 的过渡时长

    cameraControls.dampingFactor = 0.05 * 2; // 拖动时的阻尼惯性，默认 0.25

    cameraControls.draggingDampingFactor = 0.25 * 2; // controls.azimuthRotateSpeed = 1 * 2;
    // controls.polarRotateSpeed = 1 * 2;
    // controls.dollySpeed = 1 * 1.5;

    cameraControls.dollySpeed = 1 * 1.5; // 如果为true，表示前后（远近）

    cameraControls.verticalDragToForward = true; // 上下

    cameraControls.minPolarAngle = 0;
    cameraControls.maxPolarAngle = Math.PI; // dolly

    cameraControls.minDistance = 0;
    cameraControls.maxDistance = Infinity; // 左右

    cameraControls.minAzimuthAngle = -Infinity;
    cameraControls.maxAzimuthAngle = Infinity; // 改变相机 fov

    camera.fov = 45;
    camera.updateProjectionMatrix();
    return this;
  }

  destroy() {}
  /**
   * @desc 添加地图上的控件，如二三维切换器，缩放器等
   */


  addControl(control) {
    control._inject(this) // 初始化挂载
    ._init();

    return this;
  }
  /**
   * @desc 添加地图上的辅助对象，如灯光线条或者
   */


  addHelper() {
    return this;
  } // #region 一些控制地图的方法
  // 皮肤变化


  setStyle(style) {
    // this.options.style = style
    return this;
  }

  setShowStats(showStats) {
    if (showStats) {
      this.stats = createStats(this.container);
      this.reDraw();
    }

    return this;
  } // 维度变化


  setViewMode(viewMode) {
    this.options.viewMode = viewMode;
    viewMode === '3D' ? this.fitToBox3d() : this.fitToBox2d();
    return this;
  } // mesh 获取当前楼层为基准


  fitToBox2d() {
    const _getTarget = () => {
      const allLevelObjs = utils_getObjectsByName(index_type_OBJECT_NAME.level, this.scene); // 最高楼层

      return allLevelObjs[allLevelObjs.length - 1];
    }; // const levelObj = getCurrentLevelObj(unref(currentLotInfo).zIndex)


    const target = _getTarget();

    const {
      fitDistance,
      dollys
    } = getDollys(target, this.cameraControls);
    const enableTransition = true; // 控制水平垂直旋转

    this.cameraControls.minPolarAngle = this.cameraControls.maxPolarAngle = this.cameraControls.minAzimuthAngle = this.cameraControls.maxAzimuthAngle = 0; // @ts-ignore

    this.cameraControls.dollyTo(fitDistance, enableTransition);
    this.cameraControls.rotateTo(0, 0, enableTransition); // moveTo 到合适的位置
    // this.cameraControls.moveTo(0, 0, levelObj?.position.z!, true)

    this.cameraControls.moveTo(0, 0, 0, true);
  }

  fitToBox3d() {
    // 开启只能上下移动的模式
    // this.cameraControls.truckYDisabled = true
    // this.cameraControls.verticalDragToForward = false
    const _getTarget = () => {
      const allLevelObjs = utils_getObjectsByName(index_type_OBJECT_NAME.level, this.scene); // 最高楼层

      return allLevelObjs[allLevelObjs.length - 1];
    };

    const enableTransition = true; // [多层] to do... 判断以面积最小的楼层来设置 dollys
    // if (stateLevelSwitcher.mode === 'multi') {
    //   // 上下旋转范围
    //   global.controls.minPolarAngle = Math.PI * (60 / 180)
    //   global.controls.maxPolarAngle = Math.PI * (60 / 180)
    // } else {
    //   // 上下旋转范围
    //   global.controls.minPolarAngle = 0
    //   global.controls.maxPolarAngle = Math.PI * (60 / 180)
    // }
    // 控制上下旋转
    // this.cameraControls.maxPolarAngle = Math.PI * (60 / 180); // radians
    // 左右

    this.cameraControls.minAzimuthAngle = -Infinity;
    this.cameraControls.maxAzimuthAngle = Infinity;

    const target = _getTarget();

    const {
      fitDistance,
      dollys
    } = getDollys(target, this.cameraControls);

    if (fitDistance) {
      this.cameraControls.dollyTo(fitDistance, enableTransition);
    }

    this.cameraControls.rotateTo(0, Math.PI * (60 / 180), enableTransition);
    this.cameraControls.moveTo(0, 0, 0, true);
  }

}
;// CONCATENATED MODULE: ./src/core/map/index.ts

/* harmony default export */ var map = (_Map);
;// CONCATENATED MODULE: ./src/core/base/base.ts


/**
 * @desc 基类，注入地图需要的对象
 */
class Base {
  constructor() {
    _defineProperty(this, "map", void 0);
  }

  _inject(map) {
    this.map = map;
    return this;
  }

}
;// CONCATENATED MODULE: ./src/core/poisLayer/poiMarker.ts



class PoiMarker extends Base {
  constructor(options) {
    super();

    _defineProperty(this, "options", void 0);

    _defineProperty(this, "_scale", void 0);

    _defineProperty(this, "sprite", void 0);

    this.options = options;
  } // 重写父类 _inject


  _inject(map, _scale) {
    super._inject(map);

    this._scale = _scale;
    return this;
  }

  async _create() {
    const canvas = await this.generateCanvas(this.options);
    this.sprite = this.makeCanvasSprite(canvas, this.options);
    return this.sprite;
  }

  setPosition(position) {
    this.sprite && this.sprite.position.copy(position);
    this.map.reDraw();
  }

  generateCanvas({
    icon,
    scale = 1
  }) {
    const canvas = document.createElement('canvas');
    const context = canvas.getContext('2d');
    return new Promise((resolve, reject) => {
      const img = new Image();

      img.onload = () => {
        const w = img.width * scale;
        const h = img.height * scale; // 根据文字内容获取宽度

        canvas.width = w * this._scale;
        canvas.height = h * this._scale; // canvas.width = w;
        // canvas.height = h;

        context.drawImage(img, 0, 0, canvas.width, canvas.height);
        resolve(canvas);
      };

      img.src = icon;
    });
  }

  makeCanvasSprite(canvas, {
    name,
    renderOrder,
    position
  }) {
    const texture = new external_three_namespaceObject.Texture(canvas);
    texture.needsUpdate = true;
    const spriteMaterial = new external_three_namespaceObject.SpriteMaterial({
      map: texture,
      transparent: true,
      depthTest: false,
      // depthTest: this.depthTest,
      depthWrite: false
    });
    const sprite = new external_three_namespaceObject.Sprite(spriteMaterial); // sprite.name = OBJECT_NAME.POILabel

    sprite.name = name; // sprite.userData.name = name

    sprite.renderOrder = renderOrder;
    sprite.center = new external_three_namespaceObject.Vector2(0.5, 0);
    sprite.position.copy(position); // sprite.position.z += 10
    // this.group.add(sprite)
    // reDraw()

    return sprite;
  }

}
;// CONCATENATED MODULE: ./src/core/poisLayer/poisLayer.ts



class PoisLayer extends Base {
  constructor({
    name = '',
    collision = false
  }) {
    super();

    _defineProperty(this, "MY_NAME", 'PoisLayer');

    _defineProperty(this, "_scale", 4);

    _defineProperty(this, "options", void 0);

    _defineProperty(this, "_group", void 0);

    this.options = {
      name,
      collision
    };
    this._group = new external_three_namespaceObject.Object3D();
    this._group.name = name;
  }

  _init() {
    this.map.scene.add(this._group);
  }

  async add(...poiMarker) {
    for (const item of poiMarker) {
      item._inject(this.map, this._scale);

      const marker = await item._create();

      this._group.add(marker);
    }

    this.map.reDraw();
    return this;
  }

  remove(...poiMarker) {
    for (const item of poiMarker) {
      item?.sprite?.geometry?.dispose?.();
      item?.sprite?.material?.dispose?.();
      item?.sprite && this._group.remove(item?.sprite);
    }

    this.map.reDraw();
    return this;
  }
  /**
   * @desc 暴露出更新size方法，使其可以在 cameraControls 控制时候更新
   */


  _updateSize() {
    const sprites = this._group ? this._group.children : [];
    if (sprites.length === 0) return; //  是否需要碰撞检测

    if (this.options.collision) {
      for (let i = 0; i < sprites.length; i++) {
        const sprite = sprites[i];
        sprite.visible = true;
      }
    }

    for (let i = 0; i < sprites.length; i++) {
      const compareSprite = sprites[i]; // @ts-ignore

      const canvas = compareSprite.material.map.image;

      if (canvas) {
        const position = compareSprite.position;
        const scale = this.getPoiScale(position, {
          w: canvas.width,
          h: canvas.height
        }); // 缩小 4 倍在 retina 屏幕会比较高清

        compareSprite.scale.set(scale[0] / this._scale, scale[1] / this._scale, 1.0); // 是否需要碰撞检测

        if (this.options.collision && compareSprite.visible) {
          for (let j = i + 1; j < sprites.length; j++) {
            const sprite = sprites[j];

            if (this.isMarkerCollision(compareSprite, sprite)) {
              sprite.visible = false;
            }
          }
        }
      }
    }
  }

  getPoiScale(position, poiRect) {
    const distance = this.map.camera.position.distanceTo(position); // 相机和标注点的距离

    const top = Math.tan(this.map.camera.fov / 2 * Math.PI / 180) * distance; // camera.fov 相机的拍摄距离
    // var meterPerPixel = (2 * top) / window.innerHeight;

    const meterPerPixel = 2 * top / this.map.$map.clientHeight;
    const scaleX = poiRect.w * meterPerPixel;
    const scaleY = poiRect.h * meterPerPixel;
    return [scaleX, scaleY, 1.0];
  }
  /**
   * @desc 检测两个标注sprite是否碰撞
   */


  isMarkerCollision(compareSprite, sprite) {
    const comparePosition = this.toScreenPos([compareSprite.position.x, compareSprite.position.y, compareSprite.position.z], this.map.camera);
    const spritePosition = this.toScreenPos([sprite.position.x, sprite.position.y, sprite.position.z], this.map.camera);
    const image1 = compareSprite.material.map.image;
    const image2 = sprite.material.map.image;
    const w1 = image1.width / this._scale;
    const h1 = image1.height / this._scale;
    const x1 = comparePosition.x - w1 / 2;
    const y1 = comparePosition.y - h1 / 2;
    const w2 = image2 ? image2.width / this._scale : 0;
    const h2 = image2 ? image2.height / this._scale : 0;
    const x2 = spritePosition.x - w2 / 2; // 点2左下角的xy点

    const y2 = spritePosition.y - h2 / 2;

    if (x1 >= x2 && x1 >= x2 + w2) {
      return false;
    } else if (x1 <= x2 && x1 + w1 <= x2) {
      return false;
    } else if (y1 >= y2 && y1 >= y2 + h2) {
      return false;
    } else if (y1 <= y2 && y1 + h1 <= y2) {
      return false;
    } else {
      return true;
    }
  }
  /**
   * @desc three世界坐标转为屏幕坐标
   */


  toScreenPos(position, camera) {
    const worldVector = new external_three_namespaceObject.Vector3(position[0], position[1], position[2]);
    const standardVector = worldVector.project(camera); // 世界坐标转标准设备坐标

    const a = this.map.$map.clientWidth / 2;
    const b = this.map.$map.clientHeight / 2;
    const x = Math.round(standardVector.x * a + a); // 标准设备坐标转屏幕坐标

    const y = Math.round(-standardVector.y * b + b); // 标准设备坐标转屏幕坐标

    return {
      x: x,
      y: y
    };
  }

}
;// CONCATENATED MODULE: ./src/core/poisLayer/index.ts



;// CONCATENATED MODULE: ./src/core/parkingLayer/parkingLayer.ts





 // import Facility from './facility'

var FACILITY_ICON;

(function (FACILITY_ICON) {
  FACILITY_ICON[FACILITY_ICON["futi"] = __webpack_require__(973)] = "futi";
  FACILITY_ICON[FACILITY_ICON["machine"] = __webpack_require__(654)] = "machine";
  FACILITY_ICON[FACILITY_ICON["louti"] = __webpack_require__(905)] = "louti";
  FACILITY_ICON[FACILITY_ICON["zhiti"] = __webpack_require__(994)] = "zhiti";
  FACILITY_ICON[FACILITY_ICON["churukou"] = __webpack_require__(972)] = "churukou";
})(FACILITY_ICON || (FACILITY_ICON = {}));

class ParkingLayer extends Base {
  // 基础配置

  /**
   * @desc 绘制策略
   */
  constructor({
    name: _name = '',
    data: _data,
    poiCollision = true
  }) {
    super();

    _defineProperty(this, "MY_NAME", 'ParkingLayer');

    _defineProperty(this, "options", void 0);

    _defineProperty(this, "info", new Map());

    _defineProperty(this, "floorIdSort", []);

    _defineProperty(this, "basicSetting", {
      // 50米
      floorHeight: 50,
      // 1:1mm
      coordinateScale: 1
    });

    _defineProperty(this, "drawObjectStrategy", {
      floor: (data, renderOrderPlus, height) => {
        const zHeight = this.getZHeight(height);
        const item = data && data[0];
        if (!item) return [];
        const conf = OBJECT_BASE_CONF[index_type_OBJECT_NAME.floor];
        const newConf = deletePropertyForMaterial(conf);
        const mat = new material[conf.material]({ ...newConf
        });
        const points = arrayPoints23Points(item.outline);
        const shape = new external_three_namespaceObject.Shape(points);
        const mesh = new external_three_namespaceObject.Mesh();
        mesh.material = mat; // const updateGeometry = (depth?: number) => {
        //   depth = depth ?? zHeight
        //   // 拉伸造型
        //   const geo = new ExtrudeGeometry(
        //     // 二维轮廓
        //     shape,
        //     {
        //       // 拉伸长度
        //       depth,
        //       // 无倒角
        //       bevelEnabled: false
        //     }
        //   )
        //   // @ts-ignore
        //   mesh.material.depthTest = !(depth === 0)
        //   return generateGeometry(mesh, geo)
        // }
        // updateGeometry()

        const geo = new external_three_namespaceObject.ExtrudeGeometry( // 二维轮廓
        shape, {
          // 拉伸长度
          depth: zHeight,
          // 无倒角
          bevelEnabled: false
        });
        mesh.geometry = geo;
        mesh.name = index_type_OBJECT_NAME.floor; // // 自定义赋值该对象的相关，添加闭包方法 generateGeometryFn ，为了更新灵活
        // mesh.userData = { ...item, zHeight, updateGeometry }

        mesh.userData = { ...item,
          zHeight
        };
        mesh.renderOrder = conf.renderOrder + renderOrderPlus;
        return [mesh];
      },
      park: (data, renderOrderPlus, height, zIndex) => {
        const zHeight = this.getZHeight(height);
        const item = data[0];
        if (!item) return [];
        const conf = OBJECT_BASE_CONF[index_type_OBJECT_NAME.park];
        const newConf = deletePropertyForMaterial(conf);
        const mat = new material[conf.material]({ ...newConf
        });
        let points;
        const meshs = [];

        for (const item of data) {
          points = arrayPoints23Points(item.outline);
          const shape = new external_three_namespaceObject.Shape(points);
          const mesh = new external_three_namespaceObject.Mesh();
          const line = new external_three_namespaceObject.LineSegments();
          mesh.material = mat;
          const conf2 = OBJECT_BASE_CONF[index_type_OBJECT_NAME.parkBorder];
          const newConf2 = deletePropertyForMaterial(conf2);
          const matLine = new material[conf2.material](newConf2);
          line.material = matLine; // const updateGeometry = (depth?: number) => {
          //   depth = depth ?? zHeight
          //   // 拉伸造型
          //   const geo = new ExtrudeGeometry(
          //     // 二维轮廓
          //     shape,
          //     {
          //       // 拉伸长度
          //       depth,
          //       // 无倒角
          //       bevelEnabled: false
          //     }
          //   )
          //   generateGeometry(line, new EdgesGeometry(geo, 20))
          //   // @ts-ignore
          //   mesh.material.depthTest = !(depth === 0)
          //   return generateGeometry(mesh, geo)
          // }
          // updateGeometry()

          const geo = new external_three_namespaceObject.ExtrudeGeometry( // 二维轮廓
          shape, {
            // 拉伸长度
            depth: zHeight,
            // 无倒角
            bevelEnabled: false
          });
          mesh.geometry = geo; // line.geometry = new EdgesGeometry(geo, 20)

          line.geometry = new external_three_namespaceObject.EdgesGeometry(geo);
          mesh.name = index_type_OBJECT_NAME.park; // mesh.position.z += 10
          // line.position.z += 15

          line.renderOrder = conf2.renderOrder + renderOrderPlus;
          mesh.renderOrder = conf.renderOrder + renderOrderPlus; // const parkInfo = unref(currentExtraInfo).info?.park || {}
          // const extraInfo = parkInfo[item.id] || {}

          mesh.userData = {
            id: item.id,
            type: item.type,
            zHeight,
            zIndex // updateGeometry,
            // ...extraInfo

          };
          meshs.push(mesh, line);
        }

        return meshs;
      },
      pillar: (data, renderOrderPlus, height) => {
        const item = data[0];
        if (!item) return [];
        const zHeight = this.getZHeight(height);
        const conf = OBJECT_BASE_CONF[index_type_OBJECT_NAME.pillar];
        const newConf = deletePropertyForMaterial(conf);
        const mat = new material[conf.material]({ ...newConf
        });
        const meshs = [];

        const draw = item => {
          const mesh = new external_three_namespaceObject.Mesh();
          const points = arrayPoints23Points(item.outline);
          const shape = new external_three_namespaceObject.Shape(points);
          mesh.material = mat; // // 闭包，替换成这样的方式，方便可以动态更新一些 geometry 的属性
          // const updateGeometry = (depth?: number) => {
          //   depth = depth ?? zHeight
          //   // 拉伸造型
          //   const geo = new ExtrudeGeometry(
          //     // 二维轮廓
          //     shape,
          //     {
          //       // 拉伸长度
          //       depth,
          //       // 无倒角
          //       bevelEnabled: false
          //     }
          //   )
          //   // @ts-ignore
          //   mesh.material.depthTest = !(depth === 0)
          //   return generateGeometry(mesh, geo)
          // }
          // updateGeometry()

          const geo = new external_three_namespaceObject.ExtrudeGeometry( // 二维轮廓
          shape, {
            // 拉伸长度
            depth: zHeight,
            // 无倒角
            bevelEnabled: false
          });
          mesh.geometry = geo; // 自定义赋值该对象的相关，添加闭包方法 updateGeometry ，为了更新灵活
          // mesh.userData = { ...item, updateGeometry }

          mesh.userData = { ...item
          };
          mesh.name = index_type_OBJECT_NAME.pillar;
          mesh.renderOrder = conf.renderOrder + renderOrderPlus;
          meshs.push(mesh);
        };

        for (const item of data) draw(item);

        return meshs;
      }
    });

    _defineProperty(this, "facilityLayer", void 0);

    _defineProperty(this, "_nextTick", () => {});

    _defineProperty(this, "_updateSize", () => {});

    _defineProperty(this, "drawFacility", (floorInfo, zIndex, zHeight) => {
      const tempArr = [];
      const data = floorInfo.floorData.filter(_ => _.type === 'machine' || _.type.includes('connector'));

      for (const {
        type,
        outline
      } of data) {
        const name = type === 'machine' ? type : ICONNECTOR[Number(type.split('_')[1])]; // 因为楼层的原因，所以 renderOrder 要计算正确，才能显示完美

        const renderOrderMachine = OBJECT_BASE_CONF[type === 'machine' ? type : 'connector'].renderOrder + getRenderOrderPlusByLevel(zIndex);
        const position = new external_three_namespaceObject.Vector3(+outline[0], +outline[1], zHeight);
        tempArr.push(new PoiMarker({
          name,
          icon: FACILITY_ICON[name],
          // scale: 1 / 16,
          renderOrder: renderOrderMachine,
          position
        }));
      } // 添加到图层


      this.facilityLayer.add(...tempArr);
      console.log('this.scene :>> ', this.map.scene);
    });

    this.options = {
      name: _name,
      data: _data,
      poiCollision
    };
  }

  nextTick(cb) {
    if (cb) {
      this._nextTick = cb;
      return undefined;
    } else {
      return new Promise(resolve => this._nextTick = resolve);
    }
  }

  async _init() {
    // 创建放置交通设施图标图层
    this.facilityLayer = new PoisLayer({
      name: 'facilityLayer',
      // collision: false
      collision: this.options.poiCollision
    }); // const { scene, camera, $map, cameraControls, reDraw } = this.map

    this.facilityLayer._inject(this.map)._init(); // 赋值 _updateSize，提供给外部调用


    this._updateSize = this.facilityLayer._updateSize.bind(this.facilityLayer);

    if (typeof this.options.data === 'function') {
      try {
        const res = await this.options.data();
        const {
          coordinateScale,
          floorDatas
        } = res; // #region 准备相关数据，由于后续添加对象使用

        this.floorIdSort = floorDatas.map(_ => _.sort).sort((a, b) => a - b);
        this.basicSetting.coordinateScale = coordinateScale; // #endregion

        this.createFloors(floorDatas); // 触发回调

        this._nextTick();
      } catch (error) {}
    } else {
      // 直接传递一个 json 数据
      console.log('this.options.data :>> ', this.options.data); // 触发回调

      this._nextTick();
    }
  }
  /**
   * @desc 获取物体需要的高度
   */


  getZHeight(height) {
    return height * 1000 / this.basicSetting.coordinateScale;
  }
  /**
   * @desc 【待优化？】对楼层数据进行加工
   */


  createFloorBefore(item) {
    // 这里的 data 是新增的属性用来渲染找车机的，之前都是通过url获取的
    const {
      id,
      sort,
      floorName,
      url,
      jsonData: extraInfo,
      data
    } = item;
    const height = {};
    Object.entries(extraInfo).forEach(item => {
      const [type, data] = item; // @ts-ignore

      height[type] = data?.h || 0;
    });
    const floorInfo = {
      id,
      floorName,
      height,
      sort,
      floorData: data
    };
    data.length && this.createFloor(floorInfo);
  }
  /**
   * @desc 创建所有楼层入口
   */


  createFloors(data) {
    for (const item of data) {
      this.createFloorBefore(item);
    }

    const {
      reDraw,
      options
    } = this.map;
    reDraw();

    if (options.viewMode === '2D') {
      this.map.fitToBox2d();
    } else if (options.viewMode === '3D') {
      this.map.fitToBox3d();
    } // // 自适应
    // const _getTarget = () => {
    //   const allLevelObjs = getObjectsByName(OBJECT_NAME.level, this.map.scene)
    //   // 最高楼层
    //   return allLevelObjs[allLevelObjs.length - 1]
    // }
    // const target = _getTarget()
    // const { fitDistance, dollys } = getDollys(target, this.map.cameraControls)
    // console.log('dollys :>> ', fitDistance, dollys)
    // this.map.cameraControls.dollyTo(fitDistance, true)

  }
  /**
   * @desc 创建单层
   */


  createFloor(floorInfo) {
    // const floorIdSort = computed(
    //   () => (store.state as AllStates).mapModule.floorIdSort
    // )
    // const extraInfoMapArr = computed(
    //   () => (store.state as AllStates).mapModule.extraInfoMapArr
    // )
    const {
      floorHeight,
      coordinateScale
    } = this.basicSetting; // const { jsonData: mapData, height, id, sort, floorName: name } = floorInfo

    const {
      floorData,
      height,
      id,
      sort,
      floorName: name
    } = floorInfo; // const curLevelInfo =
    //   unref(extraInfoMapArr).length &&
    //   unref(extraInfoMapArr).find((f: any) => f.id === id)
    // currentExtraInfo.value = curLevelInfo

    const zIndex = this.floorIdSort.indexOf(sort);
    const renderOrderPlus = getRenderOrderPlusByLevel(zIndex);
    const zHeight = zIndex * (floorHeight * 1000) / coordinateScale;
    const dataFloor = floorData.filter(_ => _.type === index_type_OBJECT_NAME.floor);
    const meshFloors = this.drawObjectStrategy.floor(dataFloor, renderOrderPlus, height[index_type_OBJECT_NAME.floor]);
    const dataPark = floorData.filter(_ => _.type === index_type_OBJECT_NAME.park);
    const meshParks = this.drawObjectStrategy.park(dataPark, renderOrderPlus, height[index_type_OBJECT_NAME.park], zIndex);
    const dataPillar = floorData.filter(_ => _.type === index_type_OBJECT_NAME.pillar);
    const meshPillars = this.drawObjectStrategy.pillar(dataPillar, renderOrderPlus, height[index_type_OBJECT_NAME.pillar]);
    const floorGroup = new external_three_namespaceObject.Object3D();
    const conf = OBJECT_BASE_CONF[index_type_OBJECT_NAME.floor];
    meshFloors.length && floorGroup.add(...meshFloors);
    meshParks.length && floorGroup.add(...meshParks);
    meshPillars.length && floorGroup.add(...meshPillars); // 绘制通行设施

    this.drawFacility(floorInfo, zIndex, zHeight);
    floorGroup.name = index_type_OBJECT_NAME.level;
    floorGroup.renderOrder = conf.renderOrder + renderOrderPlus;
    floorGroup.position.z = zHeight;
    floorGroup.userData = {
      id,
      name,
      zIndex,
      zHeight,
      sort
    }; // global.scene.add(floorObj)

    this.map.scene.add(floorGroup); // global.positoinZs.push(zHeight)
    // store.commit('mapModule/ADD_FLOOR_LIST', {
    //   name,
    //   zIndex
    // })
    // // 创建标签
    // const parkHeight =
    //   (height[OBJECT_NAME.park] * 1000) / global.basicSetting.coordinateScale
    // // drawNameSprites(floorObj, parkHeight, zIndex);
    // reDraw()
  }
  /**
   * @desc 绘制通行设施
   */


}
;// CONCATENATED MODULE: ./src/core/parkingLayer/index.ts

/* harmony default export */ var parkingLayer = (ParkingLayer);
// EXTERNAL MODULE: external {"commonjs":"vue","commonjs2":"vue","root":"Vue"}
var external_commonjs_vue_commonjs2_vue_root_Vue_ = __webpack_require__(203);
;// CONCATENATED MODULE: ./src/core/controls/components/utils.ts

const DEFAULT_CLS = (name = '*') => `ktmap-controls__${name}`;
/**
 * @desc 动态挂载组件
 */

const createConstrols = $container => {
  let $constrols = $container.querySelector('.ktmap-controls');

  if (!$constrols) {
    $constrols = document.createElement('div');
    $constrols.className = 'ktmap-controls';
    $constrols.addEventListener('click', e => {
      e.stopPropagation();
    });
    $container.appendChild($constrols);
  }

  return $constrols;
};

function mountComponent(RootComponent, container) {
  const $container = document.getElementById(container);
  const $constrols = createConstrols($container);
  const app = (0,external_commonjs_vue_commonjs2_vue_root_Vue_.createApp)(RootComponent);
  const root = document.createElement('div');
  $constrols.appendChild(root);
  return {
    instance: app.mount(root),

    unmount() {
      app.unmount(); // document.body.removeChild(root)

      $constrols.removeChild(root);
    }

  };
}
;// CONCATENATED MODULE: ../../node_modules/cache-loader/dist/cjs.js??clonedRuleSet-87.use[0]!../../node_modules/thread-loader/dist/cjs.js!../../node_modules/babel-loader/lib/index.js!../../node_modules/ts-loader/index.js??clonedRuleSet-87.use[3]!../../node_modules/cache-loader/dist/cjs.js??ruleSet[0].use[0]!../../node_modules/vue-loader/dist/index.js??ruleSet[0].use[1]!./src/core/controls/components/viewMode/ViewMode.vue?vue&type=script&setup=true&lang=ts




/* harmony default export */ var ViewModevue_type_script_setup_true_lang_ts = (/*#__PURE__*/(0,external_commonjs_vue_commonjs2_vue_root_Vue_.defineComponent)({
  props: {
    map: {
      type: Object,
      required: true
    },
    viewMode: {
      type: String,
      default: '3D'
    },
    teleportTo: {
      type: String,
      default: 'body'
    }
  },
  emits: ['update:viewMode'],

  setup(__props, {
    emit: emits
  }) {
    const props = __props;
    (0,external_commonjs_vue_commonjs2_vue_root_Vue_.onMounted)(() => {
      console.log('onMounted :>> ', 'onMounted');
    });

    const handleChange = () => {
      console.log('props :>> ', props);
      const mode = props.viewMode.toUpperCase() === '2D' ? '3D' : '2D';
      emits('update:viewMode', mode);
      props.map.setViewMode(mode);
    };

    return (_ctx, _cache) => {
      return (0,external_commonjs_vue_commonjs2_vue_root_Vue_.openBlock)(), (0,external_commonjs_vue_commonjs2_vue_root_Vue_.createBlock)(external_commonjs_vue_commonjs2_vue_root_Vue_.Teleport, {
        to: __props.teleportTo
      }, [(0,external_commonjs_vue_commonjs2_vue_root_Vue_.createElementVNode)("button", {
        class: (0,external_commonjs_vue_commonjs2_vue_root_Vue_.normalizeClass)([(0,external_commonjs_vue_commonjs2_vue_root_Vue_.unref)(DEFAULT_CLS)('view-mode'), "foo"]),
        onClick: handleChange
      }, " 切换" + (0,external_commonjs_vue_commonjs2_vue_root_Vue_.toDisplayString)(__props.viewMode), 3)], 8, ["to"]);
    };
  }

}));
;// CONCATENATED MODULE: ./src/core/controls/components/viewMode/ViewMode.vue?vue&type=script&setup=true&lang=ts
 
;// CONCATENATED MODULE: ./src/core/controls/components/viewMode/ViewMode.vue



const __exports__ = ViewModevue_type_script_setup_true_lang_ts;

/* harmony default export */ var ViewMode = (__exports__);
;// CONCATENATED MODULE: ./src/core/controls/components/viewMode/function-call.tsx





function createInstance(map) {
  const {
    container
  } = map;
  const {
    instance,
    unmount
  } = mountComponent({
    setup(props, ctx) {
      const state = (0,external_commonjs_vue_commonjs2_vue_root_Vue_.reactive)({
        viewMode: '2D'
      });
      const state2 = {
        teleportTo: `#${container} .ktmap-controls`,
        map
      };
      const emits = {
        'onUpdate:viewMode'(val) {
          state.viewMode = val;
        }

      }; // const destroy = () => {
      //   unmount()
      // }

      ctx.expose({ ...(0,external_commonjs_vue_commonjs2_vue_root_Vue_.toRefs)(state)
      });
      return () => (0,external_commonjs_vue_commonjs2_vue_root_Vue_.createVNode)(ViewMode, (0,external_commonjs_vue_commonjs2_vue_root_Vue_.mergeProps)(state, state2, emits), null);
    }

  }, container);
  return instance;
}

const Comp = map => {
  const instance = createInstance(map);
  return instance;
}; // Comp.init = (container: string) => {
//   const instance = createInstance(container)
//   return instance
// }
// // @ts-ignore
// RNInput.install = (app: App) => {
//   app.component(RNInputComp.name, RNInputComp)
//   app.config.globalProperties.$rnInput = RNInput
// }


/* harmony default export */ var function_call = (Comp);
;// CONCATENATED MODULE: ./src/core/controls/components/viewMode/index.ts


class viewMode_ViewMode extends Base {
  constructor() {
    super();
  }

  _init() {
    function_call(this.map);
  }

}
;// CONCATENATED MODULE: ../../node_modules/cache-loader/dist/cjs.js??clonedRuleSet-87.use[0]!../../node_modules/thread-loader/dist/cjs.js!../../node_modules/babel-loader/lib/index.js!../../node_modules/ts-loader/index.js??clonedRuleSet-87.use[3]!../../node_modules/cache-loader/dist/cjs.js??ruleSet[0].use[0]!../../node_modules/vue-loader/dist/index.js??ruleSet[0].use[1]!./src/core/controls/components/layerMode/LayerMode.vue?vue&type=script&setup=true&lang=ts




/* harmony default export */ var LayerModevue_type_script_setup_true_lang_ts = (/*#__PURE__*/(0,external_commonjs_vue_commonjs2_vue_root_Vue_.defineComponent)({
  props: {
    map: {
      type: Object,
      required: true
    },
    viewMode: {
      type: String,
      default: '3D'
    },
    teleportTo: {
      type: String,
      default: 'body'
    }
  },
  emits: ['update:viewMode'],

  setup(__props, {
    emit: emits
  }) {
    const props = __props;
    (0,external_commonjs_vue_commonjs2_vue_root_Vue_.onMounted)(() => {
      console.log('onMounted :>> ', 'onMounted');
    });

    const handleChange = () => {
      console.log('props :>> ', props);
      const mode = props.viewMode.toUpperCase() === '2D' ? '3D' : '2D';
      emits('update:viewMode', mode);
      props.map.setViewMode(mode);
    };

    return (_ctx, _cache) => {
      return (0,external_commonjs_vue_commonjs2_vue_root_Vue_.openBlock)(), (0,external_commonjs_vue_commonjs2_vue_root_Vue_.createBlock)(external_commonjs_vue_commonjs2_vue_root_Vue_.Teleport, {
        to: __props.teleportTo
      }, [(0,external_commonjs_vue_commonjs2_vue_root_Vue_.createElementVNode)("button", {
        class: (0,external_commonjs_vue_commonjs2_vue_root_Vue_.normalizeClass)([(0,external_commonjs_vue_commonjs2_vue_root_Vue_.unref)(DEFAULT_CLS)('layer-mode'), "foo"]),
        onClick: handleChange
      }, " 切换" + (0,external_commonjs_vue_commonjs2_vue_root_Vue_.toDisplayString)('单层'), 2)], 8, ["to"]);
    };
  }

}));
;// CONCATENATED MODULE: ./src/core/controls/components/layerMode/LayerMode.vue?vue&type=script&setup=true&lang=ts
 
;// CONCATENATED MODULE: ./src/core/controls/components/layerMode/LayerMode.vue



const LayerMode_exports_ = LayerModevue_type_script_setup_true_lang_ts;

/* harmony default export */ var LayerMode = (LayerMode_exports_);
;// CONCATENATED MODULE: ./src/core/controls/components/layerMode/function-call.tsx





function function_call_createInstance(map) {
  const {
    container
  } = map;
  const {
    instance,
    unmount
  } = mountComponent({
    setup(props, ctx) {
      const state = (0,external_commonjs_vue_commonjs2_vue_root_Vue_.reactive)({// viewMode: '2D' as IViewMode
      });
      const state2 = {
        teleportTo: `#${container} .ktmap-controls`,
        map
      };
      const emits = {// 'onUpdate:viewMode'(val: any) {
        //   // state.viewMode = val
        // }
      }; // const destroy = () => {
      //   unmount()
      // }

      ctx.expose({ ...(0,external_commonjs_vue_commonjs2_vue_root_Vue_.toRefs)(state)
      });
      return () => (0,external_commonjs_vue_commonjs2_vue_root_Vue_.createVNode)(LayerMode, (0,external_commonjs_vue_commonjs2_vue_root_Vue_.mergeProps)(state, state2, emits), null);
    }

  }, container);
  return instance;
}

const function_call_Comp = map => {
  const instance = function_call_createInstance(map);
  return instance;
}; // Comp.init = (container: string) => {
//   const instance = createInstance(container)
//   return instance
// }
// // @ts-ignore
// RNInput.install = (app: App) => {
//   app.component(RNInputComp.name, RNInputComp)
//   app.config.globalProperties.$rnInput = RNInput
// }


/* harmony default export */ var layerMode_function_call = (function_call_Comp);
;// CONCATENATED MODULE: ./src/core/controls/components/layerMode/index.ts


class layerMode_LayerMode extends Base {
  constructor() {
    super();
  }

  _init() {
    layerMode_function_call(this.map);
  }

}
;// CONCATENATED MODULE: ./src/core/controls/index.ts



;// CONCATENATED MODULE: ./src/core/find/walking/walking.ts

class Walking {
  constructor({
    map
  }) {
    _defineProperty(this, "options", void 0);

    this.options = {
      map
    };
  }

  search(startPoint, endPoint, cb) {}

}
;// CONCATENATED MODULE: ./src/core/find/walking/index.ts

/* harmony default export */ var walking = (Walking);
;// CONCATENATED MODULE: external "hold-event"
var external_hold_event_namespaceObject = require("hold-event");
;// CONCATENATED MODULE: external "three/examples/jsm/loaders/GLTFLoader.js"
var GLTFLoader_js_namespaceObject = require("three/examples/jsm/loaders/GLTFLoader.js");
// EXTERNAL MODULE: ./src/core/ar/assets/model/arrow/scene.gltf
var arrow_scene = __webpack_require__(206);
// EXTERNAL MODULE: ./src/core/ar/assets/model/arrow_2/scene.gltf
var arrow_2_scene = __webpack_require__(954);
;// CONCATENATED MODULE: ./src/core/aStar/utils.ts
const getNearKeyPoint = (keyPoints, point) => {
  let nearPoint;
  let diff = Infinity;
  let tmpPoint, tmpDiff;

  for (let i = 0; i < keyPoints.length; i++) {
    tmpPoint = keyPoints[i];
    tmpDiff = Math.abs(tmpPoint.x - point.x) + Math.abs(tmpPoint.y - point.y);

    if (tmpDiff < diff) {
      diff = tmpDiff;
      nearPoint = tmpPoint;
    }
  }

  return nearPoint;
};
/**
 * @desc 计算最佳线路时，需要转换数据
 */

function standardKeyPointsChanger(path) {
  // 转换 v1 的邻近点规则
  const keyPoints = [];
  const map = {};

  for (const item of path) {
    const node1 = map[JSON.stringify(item.begin)];
    const node2 = map[JSON.stringify(item.end)];

    if (!node1) {
      // 初始化
      map[JSON.stringify(item.begin)] = {
        id: JSON.stringify(item.begin),
        x: item.begin[0],
        y: item.begin[1],
        neighbours: [{
          id: JSON.stringify(item.end),
          d: item.distance
        }]
      };
    } else {
      // 继续添加 neighbours
      node1.neighbours.push({
        id: JSON.stringify(item.end),
        d: item.distance
      });
    }

    if (!node2) {
      // 初始化
      map[JSON.stringify(item.end)] = {
        id: JSON.stringify(item.end),
        x: item.end[0],
        y: item.end[1],
        neighbours: [{
          id: JSON.stringify(item.begin),
          d: item.distance
        }]
      };
    } else {
      // 继续添加 neighbours
      node2.neighbours.push({
        id: JSON.stringify(item.begin),
        d: item.distance
      });
    }
  }

  for (const key of Object.keys(map)) {
    keyPoints.push(map[key]);
  }

  return keyPoints;
}
/**
 * @desc 截取精度
 */

function myTruncate(point, precision = 3) {
  const [x, y] = point;

  if (isNaN(+x) || isNaN(+y)) {
    return [];
  } // 精度缩小


  return [parseFloat((+x).toFixed(precision)), parseFloat((+y).toFixed(precision))];
}
function getDistance(p1, p2) {
  return Math.abs(Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2)));
}
/**
 * @desc 把字符串转换成 float
 */

function parsePath(path) {
  const _parseArr = arr => {
    return [parseFloat(arr[0]), parseFloat(arr[1])];
  };

  for (const item of path) {
    Object.assign(item, {
      begin: _parseArr(item.begin),
      end: _parseArr(item.end),
      distance: parseFloat(item.distance)
    });
  }

  return path;
}
;// CONCATENATED MODULE: ./src/core/aStar/aStar.ts



/**
 * @desc A star
 */

class AStar {
  constructor(path) {
    _defineProperty(this, "path", void 0);

    _defineProperty(this, "sc", void 0);

    _defineProperty(this, "keyPoints", void 0);

    _defineProperty(this, "keyPointMap", void 0);

    _defineProperty(this, "openList", void 0);

    _defineProperty(this, "closeList", void 0);

    _defineProperty(this, "invalidList", void 0);

    _defineProperty(this, "searchCount", void 0);

    _defineProperty(this, "beginTime", void 0);

    _defineProperty(this, "endTime", void 0);

    _defineProperty(this, "beginNode", void 0);

    _defineProperty(this, "endNode", void 0);

    _defineProperty(this, "beginVertical", void 0);

    _defineProperty(this, "endVertical", void 0);

    this.path = path; // 转换 path 的字符串为数字

    this.path = parsePath(this.path); // 单节点预估成本

    this.sc = 1;
    this.keyPoints = standardKeyPointsChanger(this.path);
    this.keyPointMap = {}; // 将列表转换map对象

    for (let i = 0; i < this.keyPoints.length; i++) {
      const p = this.keyPoints[i];
      this.keyPointMap[p.id] = p;
    }

    this.openList = [];
    this.closeList = [];
    this.invalidList = [];
    this.searchCount = 0;
    this.beginTime = new Date();
    this.endTime = new Date();
  }

  shortestPath(beginNode, endNode) {
    const result = [];
    this.openList = []; // 已经知道，但未走过的节点

    this.closeList = []; // 走过的节点

    this.invalidList = []; // 失效的点

    this.searchCount = 0;
    this.beginTime = new Date();
    beginNode.parent = null;
    beginNode.d = 0;
    this.beginNode = beginNode;
    this.endNode = endNode;
    this.closeList.push(this.beginNode);

    while (true) {
      if (this.closeList.length === 0) {
        break;
      }

      this.searchCount++;
      let currNode = this.closeList[this.closeList.length - 1];

      if (currNode.id === endNode.id) {
        // 已经抵达目的地, 按照parent往回追溯，返回结果
        while (currNode && currNode != null) {
          result.unshift(currNode);
          currNode = currNode.parent;
        }

        break;
      }

      if (currNode.neighbours && currNode.neighbours.length > 0) {
        for (let i = 0; i < currNode.neighbours.length; i++) {
          const nb = currNode.neighbours[i];
          const tmpNode = this.keyPointMap[nb.id]; // 周围节点必须满足三个条件：
          // 1.这个点是合法的，什么叫合法？这里简单的就是可以通行的，不能是障碍物

          if (!tmpNode || this.contain(this.invalidList, tmpNode)) {
            continue;
          } // 2.这个点不能在close表中


          if (this.contain(this.closeList, tmpNode)) {
            continue;
          } // 3.这个点不能在open表中


          if (this.contain(this.openList, tmpNode)) {
            continue;
          }

          tmpNode.d = nb.d; // 相邻点距离

          tmpNode.parent = currNode;
          tmpNode.cost = this.f(tmpNode);
          this.openList.push(tmpNode);
        }
      }

      if (this.openList.length > 0) {
        // 计算open列表cost值最低的节点minNode
        let minNode = null;

        for (let i = 0; i < this.openList.length; i++) {
          const tmp = this.openList[i];

          if (minNode == null || minNode.cost > tmp.cost) {
            minNode = tmp;
          }
        } // minNode从open表中删除加入close表


        this.remove(this.openList, minNode);
        this.closeList.push(minNode);
      } else {
        // 如果openList没有节点了，那么取上一个closeList中的节点，继续循环
        // 该节点没有有效的邻近节点，移到失效列表
        this.invalidList.push(currNode);
        this.remove(this.closeList, currNode);
      }

      if (this.searchCount > 500000) {
        // 避免死循环
        break;
      }
    }

    this.endTime = new Date();
    return result;
  }

  contain(nodes, node) {
    let result = false;
    nodes.forEach(function (item) {
      if (item.id === node.id) {
        result = true;
      }
    });
    return result;
  }

  remove(nodes, node) {
    let move = false;

    for (let i = 0; i < nodes.length; i++) {
      if (move) {
        nodes[i - 1] = nodes[i];
      }

      if (node.id === nodes[i].id) {
        move = true;
      }
    }

    if (move) {
      nodes.length -= 1;
    }
  } // 节点代价


  f(n) {
    return this.g(n) + this.h(n);
  } // 初始节点到n节点的明确代价


  g(n) {
    let result = 0;
    let currNode = n;

    while (currNode && currNode != null) {
      result += currNode.d;
      currNode = currNode.parent;
    }

    return result;
  } // 是n节点到目标点的预估代价；


  h(n) {
    return this.euclidianCost(n, this.endNode);
  } // //麦哈顿估算法
  // manhattanCost(begin, end) {
  //   return (
  //     Math.abs(begin.x - end.x) * this.sc + Math.abs(begin.y + end.y) * this.sc
  //   );
  // }
  // 几何估价法


  euclidianCost(begin, end) {
    const dx = begin.x - end.x;
    const dy = begin.y - end.y;
    return Math.sqrt(dx * dx + dy * dy) * this.sc;
  } // //对角线估价法
  // diagonalCost(begin, end) {
  //   var dx = Math.abs(begin.x - end.x);
  //   var dy = Math.abs(begin.y - end.y);
  //   var diag = Math.min(dx, dy);
  //   var straight = dx + dy;
  //   return this.sc * diag + this.sc * (straight - 2 * diag);
  // }


  getNearest(point, isBegin = true) {
    // const _name = (val: string) => `${val}_${isBegin ? 'begin' : 'end'}`;
    // removeObjectByName(_name('rnFindPointNear'), pointGroup.value.pointGroup);
    // removeObjectByName(
    //   _name('rnFindPointVertical'),
    //   pointGroup.value.pointGroup
    // );
    // removeObjectByName(_name('rnFindLineNear'));
    let nearItem;
    let tempItem;
    let nearPoint;
    let vertical;
    let dist = Infinity;

    for (let i = 0; i < this.path.length; i++) {
      tempItem = this.path[i];
      const {
        dist: tempDist,
        point: tempPoint,
        vertical: tempVertical
      } = this.nearestPointOnLine(tempItem.begin, tempItem.end, point);

      if (tempDist < dist) {
        dist = tempDist;
        nearPoint = tempPoint;
        nearItem = tempItem;
        vertical = tempVertical;
      }
    } // this.drawNearLine(nearItem.begin, nearItem.end, _name('rnFindLineNear'));
    // this.drawNearPoint(nearPoint as [number, number], _name('rnFindPointNear'));
    // vertical &&
    //   this.drawVertical(
    //     vertical as [number, number],
    //     _name('rnFindPointVertical')
    //   );


    return {
      point: nearPoint,
      vertical
    };
  }
  /**
   * @desc 最佳线路计算
   */


  calcShortestPath(begin, end) {
    const {
      point: beginPoint,
      vertical: beginVertical
    } = this.getNearest(begin, true);
    const {
      point: endPoint,
      vertical: endVertical
    } = this.getNearest(end, false); // 更新起点/终点垂点

    this.beginVertical = beginVertical;
    this.endVertical = endVertical;
    const standardBeginPoint = this.keyPoints.find(_ => _.id === JSON.stringify(beginPoint));
    const standardEndPoint = this.keyPoints.find(_ => _.id === JSON.stringify(endPoint));
    let result = this.shortestPath(standardBeginPoint, standardEndPoint); // 进行线路优化

    result = this.trackOptimize(result);
    return result;
  }
  /**
   * @desc 线路优化
   */


  trackOptimize(trackPoints) {
    if (trackPoints.length >= 2) {
      // 加工，判断头尾是否加上垂点
      // 有垂点才进行判断追加，没有垂点，就不进行添加
      if (this.beginVertical) {
        const beginV = new external_three_namespaceObject.Vector2(this.beginVertical[0], this.beginVertical[1]);

        if (this.isInLine(trackPoints[0], trackPoints[1], beginV, 2)) {
          console.log('起点垂点在导航线上，shift 去除连接起点，后续 unshift 起点垂点');
          trackPoints.shift();
        }

        trackPoints.unshift(beginV);
      }

      if (this.endVertical) {
        const endV = new external_three_namespaceObject.Vector2(this.endVertical[0], this.endVertical[1]);

        if (this.isInLine(trackPoints[trackPoints.length - 1], trackPoints[trackPoints.length - 2], endV, 2)) {
          console.log('终点垂点在导航线上，pop 去除连接终点，后续 push 终点垂点');
          trackPoints.pop();
        }

        trackPoints.push(endV);
      }
    }

    return trackPoints;
  }
  /**
   * @desc 获取点到各个线段上最近的一条线段和相关信息
   * 需要返回距离，来筛选最近的线段
   * dist：一般来说是点和垂点的距离 dist。但是需要判断如果垂点在直线外部，就计算点到线段两端的距离 min dist
   * 拿到 dist 循环筛选出最近的即可。
   * point：表示距离点最近的线段端点，主要用来a星算法
   * vertical：表示垂点，主要用来补充线段
   */


  nearestPointOnLine(begin, end, p) {
    const _getNearPointByLineBeginEnd = () => {
      const arr = [{
        point: begin,
        dist: getDistance(new external_three_namespaceObject.Vector2(begin[0], begin[1]), new external_three_namespaceObject.Vector2(p[0], p[1]))
      }, {
        point: end,
        dist: getDistance(new external_three_namespaceObject.Vector2(end[0], end[1]), new external_three_namespaceObject.Vector2(p[0], p[1]))
      }];
      arr.sort((a, b) => a.dist - b.dist);
      return arr[0];
    };

    let point = [0, 0];
    let vertical = null;
    let dist = 0; // 获取垂足

    const {
      x,
      y
    } = this.getVerticalPoint(new external_three_namespaceObject.Vector2(begin[0], begin[1]), new external_three_namespaceObject.Vector2(end[0], end[1]), new external_three_namespaceObject.Vector2(p[0], p[1])); // 判断垂足是否在线上，在线上直接返回，不在线上，返回距离垂足最近的点

    const isInline = this.isInLine(new external_three_namespaceObject.Vector2(begin[0], begin[1]), new external_three_namespaceObject.Vector2(end[0], end[1]), new external_three_namespaceObject.Vector2(x, y), 2);

    const {
      point: _point,
      dist: _dist
    } = _getNearPointByLineBeginEnd();

    point = _point;

    if (isInline) {
      vertical = [x, y];
      dist = getDistance(new external_three_namespaceObject.Vector2(p[0], p[1]), new external_three_namespaceObject.Vector2(x, y));
    } else {
      vertical = null;
      point = _point;
      dist = _dist;
    }

    return {
      vertical,
      point,
      dist
    };
  }
  /**
   * @desc 求点C在由点A、点B组成的直线的垂点
   */


  getVerticalPoint(p1, p2, p) {
    // 直线方程：Ax + By + C = 0
    const A = p2.y - p1.y;
    const B = p1.x - p2.x;
    const C = p2.x * p1.y - p1.x * p2.y;
    const tmp = A * A + B * B;
    let x = (B * B * p.x - A * B * p.y - A * C) / tmp; // 垂点的X坐标

    let y = (A * A * p.y - A * B * p.x - B * C) / tmp; // 垂点的Y坐标
    // 缩小精度

    const [x1, y1] = myTruncate([x, y]);
    x = x1;
    y = y1;
    return {
      x,
      y
    };
  }
  /**
   * @desc 计算两个坐标连线后的倾斜角度
   */


  getAngle(p1, p2) {
    const radian = Math.atan2(p2.y - p1.y, p2.x - p1.x);
    const angle = radian * (180 / Math.PI);
    return {
      radian,
      angle
    };
  }
  /**
   * @desc 判断p是否在p1和p2的线段内
   */


  isInLine(p1, p2, p, offsetAngle = 0) {
    if (!p1 || !p2 || !p) {
      return false;
    } // 允许一定的上下偏差，由于一些精度计算原因，可能点无法被识别在线段上


    const diffAngle = Math.floor(this.getAngle(p1, p).angle) - Math.floor(this.getAngle(p, p2).angle);

    if (offsetAngle === 0) {
      return diffAngle === 0;
    } else {
      // [-offsetAngle,offsetAngle]
      return diffAngle >= -offsetAngle && diffAngle <= offsetAngle;
    }
  }

}
;// CONCATENATED MODULE: ./src/core/aStar/index.ts

/* harmony default export */ var aStar = (AStar);
// EXTERNAL MODULE: ./src/core/ar/assets/imgs/test.jpeg
var test = __webpack_require__(294);
// EXTERNAL MODULE: ./src/core/ar/assets/imgs/ic_arrow.png
var ic_arrow = __webpack_require__(968);
;// CONCATENATED MODULE: ./src/core/ar/ar.ts




 // @ts-ignore








class AR {
  constructor({
    map,
    data
  }) {
    _defineProperty(this, "options", void 0);

    _defineProperty(this, "_nextTick", []);

    _defineProperty(this, "aStar", void 0);

    _defineProperty(this, "arrowGroupCache", void 0);

    _defineProperty(this, "beginCache", []);

    _defineProperty(this, "endCache", []);

    _defineProperty(this, "trackPointsCache", []);

    console.log('test-img :>> ', test);
    this.options = {
      map,
      data
    };
    this.init();
  } // constructor({ name = '', data, poiCollision = true }: IOptions) {
  //   super();
  //   this.options = { name, data, poiCollision };
  // }


  nextTick(cb) {
    if (cb) {
      this._nextTick.push(cb);

      return undefined;
    } else {
      return new Promise(resolve => this._nextTick.push(resolve));
    }
  }

  async init() {
    // - 设置透明，为了 AR 效果
    const {
      map,
      map: {
        cameraControls,
        scene,
        $map,
        renderer,
        reDraw,
        container
      }
    } = this.options; // renderer.setClearAlpha(0);
    // - 获取数据绘制基础路网

    this.drawRoadNet();
    const path = await this.nextTick();
    this.aStar = new aStar(path); // - 隐藏所有物体，除了箭头
    // console.log('scene :>> ', scene);
    // for (const item of scene.children) {
    //   if (['level', 'ar_track'].includes(item.name)) {
    //     item.visible = false;
    //   }
    // }
    // - 调用h5相机

    this.callCamera(); // - 切换第一人称视角
    // this.changeFirstPerson();
    // - 监听手机罗盘，目前用小程序的 hash 方式

    this.deviceOrientationHandler(); // - 监听 hash 变化，和地图进行交互

    this.onHashChange(query => {
      // 改变画布的位置
      const {
        direction
      } = query;
      const $compass = this.getCompass();
      $compass.innerText = `罗盘角度：${(+direction).toFixed(2)}`; // cameraControls.normalizeRotations();
      // cameraControls.rotateAzimuthTo(Math.PI * (+direction / 180), true);
      // cameraControls.rotateTo(
      //   Math.PI * ((360 - direction) / 180),
      //   Math.PI * (90 / 180),
      //   true
      // );
      // cameraControls.rotateTo(
      //   Math.PI * ((360 - direction) / 180),
      //   Math.PI * (90 / 180),
      //   true
      // );
      // direction.toFixed(0);

      cameraControls.rotateTo(Math.PI * ((360 - direction) / 180), Math.PI * (90 / 180), true); // 关键代码，在 0 到 360 度之间标准化相机方位角旋转。

      cameraControls.normalizeRotations();
      console.log('direction :>> ', direction);
    }); // #region 测试
    // 测试移动
    // this['test.move']();

    this['test.markBeginAndEnd'](); // #endregion
    // - 根据路网绘制箭头，./参考/提示箭头.png

    this.getArrow(); // this.getRoadNetArrowV2();

    reDraw(); // 初始化一些控件

    const $btnChangeMode = this['dev.addControl'](`${container}-ar__change-mode`, '切换视角', {
      top: '0px'
    });
    let third = false;

    const _changeMode = async () => {
      if (!third) {
        await this.changeFirstPerson();
        third = true;
      } else {
        map.reset().setViewMode('3D');
        third = false;
      }

      map.reDraw();
    };

    $btnChangeMode.onclick = _changeMode; // // ARDemo
    // const $btnARDemo = this['dev.addControl'](
    //   `${container}-ar__demo`,
    //   'AR-demo',
    //   { top: '50px' }
    // );
    // $btnARDemo.onclick = async (ev: any) => {
    //   // await _changeMode();
    //   // 模拟用户在移动，实时更新箭头方向
    //   // this['dev.ARDemo']();
    // };

    this['dev.ARDemo']();
  }
  /**
   * @desc 模拟AR
   * 判断第一个箭头是否有在当前视野，没有的话给出提示箭头
   * https://www.cnblogs.com/minnong/p/12017035.html
   * https://stackoverflow.com/questions/66972302/check-in-which-direction-of-camera-the-object-is-in-threejs
   */


  'dev.ARDemo'() {
    const {
      map: {
        cameraControls,
        container,
        scene,
        camera
      }
    } = this.options; // 初始化一些控件

    const $btnUp = this['dev.addControl'](`${container}-ar__up`, 'up', {
      top: '50px'
    });
    const $btnDown = this['dev.addControl'](`${container}-ar__down`, 'down', {
      top: '100px'
    });
    const $btnLeft = this['dev.addControl'](`${container}-ar__left`, 'left', {
      top: '150px'
    });
    const $btnRight = this['dev.addControl'](`${container}-ar__right`, 'right', {
      top: '200px'
    }); // register keyboard

    const KEYCODE = {
      // W: 87,
      // A: 65,
      // S: 83,
      // D: 68,
      ARROW_LEFT: 37,
      ARROW_UP: 38,
      ARROW_RIGHT: 39,
      ARROW_DOWN: 40
    };
    const holdUpKey = new external_hold_event_namespaceObject.KeyboardKeyHold(KEYCODE.ARROW_UP // 16.666
    );
    const holdDownKey = new external_hold_event_namespaceObject.KeyboardKeyHold(KEYCODE.ARROW_DOWN // 16.666
    );
    const holdLeftKey = new external_hold_event_namespaceObject.KeyboardKeyHold(KEYCODE.ARROW_LEFT // 16.666
    );
    const holdRightKey = new external_hold_event_namespaceObject.KeyboardKeyHold(KEYCODE.ARROW_RIGHT // 16.666
    ); // register elem

    const holdUp = new external_hold_event_namespaceObject.ElementHold($btnUp);
    const holdDown = new external_hold_event_namespaceObject.ElementHold($btnDown);
    const holdLeft = new external_hold_event_namespaceObject.ElementHold($btnLeft);
    const holdRight = new external_hold_event_namespaceObject.ElementHold($btnRight);
    const factorForward = 10;
    const target = new external_three_namespaceObject.Vector3();
    holdUp.addEventListener(external_hold_event_namespaceObject.HOLD_EVENT_TYPE.HOLDING, event => {
      cameraControls.forward(factorForward * event.deltaTime, false);
      cameraControls.getTarget(target); // 更新用户起点，重新计算最佳线路，重新绘制箭头

      this.search([target.x, target.y], this.endCache);
    });
    holdDown.addEventListener(external_hold_event_namespaceObject.HOLD_EVENT_TYPE.HOLDING, event => {
      cameraControls.forward(-factorForward * event.deltaTime, false);
      cameraControls.getTarget(target); // 更新用户起点，重新计算最佳线路，重新绘制箭头

      this.search([target.x, target.y], this.endCache);
    });
    holdUpKey.addEventListener(external_hold_event_namespaceObject.HOLD_EVENT_TYPE.HOLDING, event => {
      cameraControls.forward(factorForward * event.deltaTime, false);
      cameraControls.getTarget(target); // 更新用户起点，重新计算最佳线路，重新绘制箭头

      this.search([target.x, target.y], this.endCache);
    });
    holdDownKey.addEventListener(external_hold_event_namespaceObject.HOLD_EVENT_TYPE.HOLDING, event => {
      cameraControls.forward(-factorForward * event.deltaTime, false);
      cameraControls.getTarget(target); // 更新用户起点，重新计算最佳线路，重新绘制箭头

      this.search([target.x, target.y], this.endCache);
    });

    const _rotate = (event, direction) => {
      const $arrow = this.getArrow();
      let n = factorRotate * external_three_namespaceObject.MathUtils.DEG2RAD * event.deltaTime;
      n = direction === 'left' ? n : -n;
      cameraControls.rotate(n, 0, true); // 第一个箭头的位置

      const firstArrow = utils_getObjectsByName('ar_roadNetArrow', scene)[0]; // firstArrow.forEach((item, i) => {
      //   if (i === 0) {
      //     item.visible = true;
      //   } else {
      //     item.visible = false;
      //   }
      // });
      // console.log('firstArrow :>> ', firstArrow[0]);

      let status = 'none';

      if (firstArrow) {
        const tempV = firstArrow.position.clone().applyMatrix4(camera.matrixWorldInverse).applyMatrix4(camera.projectionMatrix);

        if (Math.abs(tempV.x) > 1 || Math.abs(tempV.y) > 1 || Math.abs(tempV.z) > 1) {
          status = 'out'; // 在视野外了
          // console.log('在视野外了 :>> ', '在视野外了');
        } else {
          status = 'in'; // 在视野内了
          // console.log('在视野内 :>> ', '在视野内');
        } // given obj1...
        // const temp = obj1.position.clone();


        const temp = firstArrow.position.clone();
        camera.worldToLocal(temp);

        if (status === 'out') {
          if (temp.x >= 0) {
            $arrow.turnRight(); // console.log('right half of the screen!');
          } else if (temp.x < 0) {
            $arrow.turnLeft(); // console.log('left half of the screen!');
          }
        } else {
          $arrow.hide();
        } // else {
        //   console.log('The object is in the exact middle!');
        // }

      }
    };

    const factorRotate = 0.1;
    holdLeft.addEventListener(external_hold_event_namespaceObject.HOLD_EVENT_TYPE.HOLDING, event => {
      _rotate(event, 'left');
    });
    holdRight.addEventListener(external_hold_event_namespaceObject.HOLD_EVENT_TYPE.HOLDING, event => {
      _rotate(event, 'right');
    });
    holdLeftKey.addEventListener(external_hold_event_namespaceObject.HOLD_EVENT_TYPE.HOLDING, event => {
      _rotate(event, 'left');
    });
    holdRightKey.addEventListener(external_hold_event_namespaceObject.HOLD_EVENT_TYPE.HOLDING, event => {
      _rotate(event, 'right');
    });
  }
  /**
   * @desc ar-demo
   */
  // private 'dev.ARDemoV1'() {
  //   const {
  //     map: { cameraControls }
  //   } = this.options;
  //   const self = this;
  //   /**
  //    * @desc 创建补间动画
  //    */
  //   const createTween = (oldT: Vector3, newT: Vector3, cb: () => void) => {
  //     // 需要执行动画的路线形成数组，然后进行移动，
  //     const t = new TWEEN.Tween({
  //       x: oldT.x,
  //       y: oldT.y,
  //       z: oldT.z
  //     })
  //       // time = distance / speed，保持每段距离都匀速
  //       .to(
  //         { x: newT.x, y: newT.y, z: newT.z },
  //         this.getDistance(oldT, newT) / 3
  //       )
  //       .easing(TWEEN.Easing.Linear.None)
  //       .onStart(function () {
  //         // 动画过程中不能操作画布相关
  //         // cameraControls.enabled = false;
  //         const { radian } = getAngle(oldT, newT);
  //         // to do 上下旋转，当前先一段45度，一段30度切换的方式
  //         // 扣掉90°表示垂直向上
  //         // cameraControls.rotateTo(radian - Math.PI / 2, Math.PI / 4, true);
  //         cameraControls.rotateTo(
  //           radian + Math.PI / 2,
  //           Math.PI * (90 / 180),
  //           true
  //         );
  //         // // 导航指标的指向
  //         // naviPointer.rotation.z = radian - Math.PI / 2;
  //         // 正常化 controls 的角度，控制在0-360°之间，否则会累积角度
  //         cameraControls.normalizeRotations();
  //       })
  //       .onUpdate(function (values: number) {
  //         // @ts-ignore
  //         const object = this;
  //         cameraControls.moveTo(object.x, object.y, object.z, true);
  //         // 实时更新计算箭头位置
  //         self.drawRoadNetArrows(newTrackPoints);
  //         // naviPointer.position.set(object.x, object.y, object.z);
  //         // reDraw();
  //       })
  //       .onComplete(function () {
  //         // 到最后一个动画走完才会开启控制
  //         cb();
  //         // last && (controls.enabled = true);
  //       });
  //     return t;
  //   };
  //   const startAnimation = (trackPoints: Vector3[]) => {
  //     let cb: () => void = () => {};
  //     // @ts-ignore
  //     const p = new Promise(resolve => (cb = resolve));
  //     const tweens: any[] = [];
  //     for (let i = 1; i < trackPoints.length; i++) {
  //       tweens.push(
  //         createTween(
  //           trackPoints[i - 1],
  //           trackPoints[i],
  //           // tweens 的最后一个才会进行 promise 的 resolve 回调
  //           i === trackPoints.length - 1 ? cb : () => {}
  //         )
  //       );
  //     }
  //     for (let i = 1; i < tweens.length; i++) {
  //       tweens[i - 1].chain(tweens[i]);
  //     }
  //     // 动画开始
  //     tweens[0].start();
  //     return p;
  //   };
  //   // this.changeFirstPerson();
  //   startAnimation(this.trackPointsCache);
  // }


  getVideo() {
    const {
      map: {
        $map,
        container
      }
    } = this.options;
    const id = `${container}-ar__video`;
    let $video = document.getElementById(id);

    if (!$video) {
      // 动态append $video
      $video = document.createElement('video');
      $video.id = id;
      $video.className = `${CLS_PREFIX}-ar__video`;
      $video.setAttribute('webkit-playsinline', 'webkit-playsinline');
      $video.setAttribute('playsinline', 'playsinline');
      $video.setAttribute('x5-playsinline', 'x5-playsinline');
      $map.appendChild($video);
    }

    return $video;
  }
  /**
   * @desc 调用相机
   */


  callCamera() {
    // 这里直接先判断环境，不是https 就不开启了
    if (location.protocol !== 'https:') {
      return;
    }

    const {
      map: {
        $map,
        container
      }
    } = this.options;
    const $video = this.getVideo(); // 访问用户媒体设备的兼容方法

    function getUserMedia(constraints, success, error) {
      if (navigator.mediaDevices.getUserMedia) {
        // 最新的标准API
        navigator.mediaDevices.getUserMedia(constraints).then(success).catch(error); // @ts-ignore
      } else if (navigator.webkitGetUserMedia) {
        // webkit核心浏览器
        // @ts-ignore
        navigator.webkitGetUserMedia(constraints, success, error); // @ts-ignore
      } else if (navigator.mozGetUserMedia) {
        // firfox浏览器
        // @ts-ignore
        navigator.mozGetUserMedia(constraints, success, error); // @ts-ignore
      } else if (navigator.getUserMedia) {
        // 旧版API
        // @ts-ignore
        navigator.getUserMedia(constraints, success, error);
      }
    }

    function success(stream) {
      // 兼容webkit核心浏览器
      const CompatibleURL = window.URL || window.webkitURL; // 将视频流设置为video元素的源
      // console.log(stream);
      // video.src = CompatibleURL.createObjectURL(stream);

      $video.srcObject = stream; // ios 不会自动播放，需要有触发事件，所以这里无效

      $video.play();
    }

    function error(error) {
      console.log(`访问用户媒体设备失败${error.name}, ${error.message}`);
    } // 开始


    if ( // @ts-ignore
    navigator.mediaDevices.getUserMedia || // @ts-ignore
    navigator.getUserMedia || // @ts-ignore
    navigator.webkitGetUserMedia || // @ts-ignore
    navigator.mozGetUserMedia) {
      // 调用用户媒体设备, 访问摄像头
      getUserMedia({
        video: {
          // width: 100, height: 320,
          // width: window.innerWidth,
          // height: window.innerHeight,
          // 默认前置摄像头
          facingMode: location.hash.indexOf('environment') !== -1 ? {
            exact: 'environment'
          } : 'user'
        }
      }, success, error);
    } else {// alert('不支持访问用户媒体');
    } // // 在webview中添加代码
    // let hash;
    // // 监听hash变化
    // window.addEventListener(
    //   'popstate',
    //   function () {
    //     // 有hash值时返回上一个页面，并储存hash。
    //     // 因为返回了上一个页面，会立马进入else分支。
    //     // 将存好的hash渲染到页面
    //     if (location.hash) {
    //       hash = location.hash.split('#')[1];
    //       history.back();
    //     } else {
    //       // hash值最好是编码后的数据
    //       // document.getElementsByTagName('body')[0].innerHTML = '解码后参数：' + decodeURIComponent(hash);
    //     }
    //     video.play();
    //   },
    //   false
    // );

  }

  async drawRoadNet() {
    const {
      data
    } = this.options; // 目前直接获取到改楼层对应的路网数据

    if (typeof data === 'function') {
      try {
        const res = await data();

        this._drawRoadNet(res);

        for (const fn of this._nextTick) {
          fn?.(res);
        }
      } catch (error) {}
    } else {
      this._drawRoadNet(data);

      for (const fn of this._nextTick) {
        fn?.(data);
      }
    }
  }

  initAStar() {// this.keyPoints = standardKeyPointsChanger(this.path);
    // this.aStar = new AStar();
    //  // 路网最佳线路计算开始，目前只考虑一层
    //  let { point: userPoint } = this.userPoint;
    //  let { point: parkPoint } = this.parkPoint;
    //  userPoint = myTruncate([userPoint.x, userPoint.y]);
    //  parkPoint = myTruncate([parkPoint.x, parkPoint.y]);
    //  // 得到绘制轨迹的点集合
    //  let trackPoints = this.calcShortestPath(userPoint, parkPoint);
    //  console.log(
    //    'trackPoints-before :>> ',
    //    JSON.parse(JSON.stringify(trackPoints))
    //  );
    //  trackPoints = this.trackOptimize(trackPoints);
    //  console.log(
    //    'trackPoints-optimize :>> ',
    //    JSON.parse(JSON.stringify(trackPoints))
    //  );
    //  // 开始绘制
    //  removeObjectByName(OBJECT_NAME.track);
    //  if (trackPoints.length >= 2) {
    //    this.drawTrackByPoints(trackPoints);
    //  } else {
    //    console.warn('线段长度小于2，无法进行绘制');
    //  }
  }
  /**
   * @desc 拿到路网数据，绘制基础路网
   */


  _drawRoadNet(data) {
    const {
      map: {
        reDraw
      }
    } = this.options; // const json = {
    //   begin: ['-132214.271', '38721.291'],
    //   distance: '22512.083490543166',
    //   end: ['-122146.552', '18585.876'],
    //   entry: 0,
    //   id: 1,
    //   type: 'path'
    // };

    for (const item of data) {
      item.begin[0] = +item.begin[0];
      item.begin[1] = +item.begin[1];
      item.end[0] = +item.end[0];
      item.end[1] = +item.end[1];
      const {
        begin,
        end,
        id
      } = item;
      this.drawNormalLine([new external_three_namespaceObject.Vector3(...begin, 0), new external_three_namespaceObject.Vector3(...end, 0)], {
        name: 'ar_roadNetPath',
        color: 'red'
      });
    }

    reDraw();
  }
  /**
   * @desc 绘制普通线段
   */


  drawNormalLine(points, // end: [number, number],
  ext) {
    const {
      map: {
        scene
      }
    } = this.options;
    const line = new external_three_namespaceObject.Line(new external_three_namespaceObject.BufferGeometry().setFromPoints(points), new external_three_namespaceObject.LineBasicMaterial({
      // visible: false,
      color: ext?.color || 'red',
      opacity: 1,
      transparent: true,
      depthTest: false
    }));
    line.name = ext?.name || ''; // line.renderOrder = 998;

    line.userData = {// id,
      // begin,
      // end
    };
    scene.add(line);
  }
  /**
   * @desc 第一视角切换
   */


  async changeFirstPerson() {
    const {
      map: {
        camera,
        cameraControls,
        reDraw
      }
    } = this.options; // 地板目前有1米，车位目前有1.5米，墙3米，假设人1.8米

    const floorHeight = 1 * 1000;
    const personHeight = 1.8 * 1000; // const personHeight = 5 * 1000;
    // 画布移动因子
    // 阻尼惯性，默认 0.05，调整会影响到 await 的过渡时长
    // cameraControls.dampingFactor = 0.05 * 2;

    cameraControls.dampingFactor = 0.05 / 1.25; // cameraControls.dampingFactor = 0.05 / 2;
    // 地图控制在90°

    const limitRadian = Math.PI * (90 / 180);
    const height = floorHeight + personHeight; // const height = 1000 + 500;
    // const limitDolly = -1;

    const limitDolly = -personHeight; // const limitDolly = -5000;
    // const limitDolly = -height;
    // const limitDolly = -1;
    // const limitDolly = 0.1;
    // const limitDolly = 100000;
    // 在"第一人称"， cameraControls.setPosition和dolly功能是一样的
    // 上下旋转

    cameraControls.minPolarAngle = limitRadian;
    cameraControls.maxPolarAngle = limitRadian; // // dolly

    cameraControls.minDistance = limitDolly;
    cameraControls.maxDistance = limitDolly; // 左右

    cameraControls.minAzimuthAngle = -Infinity;
    cameraControls.maxAzimuthAngle = Infinity; // cameraControls.enabled = false;
    // 禁止拖拽
    // cameraControls.truckSpeed = 0;
    // 改变相机 fov

    camera.fov = 60;
    camera.updateProjectionMatrix();
    cameraControls.dollyTo(limitDolly, false); // moveTo 为变量，需要根据实时定位来变化

    if (this.beginCache.length > 0) {
      cameraControls.moveTo(this.beginCache[0], this.beginCache[1], height);
    } else {
      cameraControls.moveTo(0, 0, height);
    } // moveTo 到用户所站的位置
    // cameraControls.moveTo(6015.380734193866, -3760.4037080452727, height);


    await cameraControls.rotateTo(0, limitRadian, false);
  }

  deviceOrientationHandler() {
    // const _deviceOrientationHandler = (evt: any) => {
    //   const { alpha, beta, gamma } = evt;
    //   // Z轴方向，X轴方向，Y轴方向
    //   console.log('{ alpha, beta, gamma } :>> ', { alpha, beta, gamma });
    // };
    const ua = navigator.userAgent.toLowerCase();
    console.log('uauauaua :>> ', ua);

    const deviceOrientationHandler = evt => {
      console.log('evtevtevt :>> ', evt); // document.getElementById('alpha').innerHTML = Math.round(
      //   360 - event.alpha
      // );
      // $('#compass').css(
      //   'transform',
      //   'rotate(-' + Math.round(360 - event.alpha) + 'deg)'
      // );
    };

    if (/android/.test(ua)) {
      window.addEventListener('deviceorientationabsolute', deviceOrientationHandler, false);
    } else {
      window.addEventListener('deviceorientation', deviceOrientationHandler, false); // function deviceOrientationHandler(evt: any) {
      //   console.log('evtevtevt :>> ', evt);
      //   // document.getElementById('alpha').innerHTML = Math.round(
      //   //   360 - event.alpha
      //   // );
      //   // $('#compass').css(
      //   //   'transform',
      //   //   'rotate(-' + Math.round(360 - event.alpha) + 'deg)'
      //   // );
      // }
      // function DeviceOrientationHandler(event) {
      //   document.getElementById('alpha').innerHTML = event.webkitCompassHeading;
      //   $('#compass').css(
      //     'transform',
      //     'rotate(-' + event.webkitCompassHeading + 'deg)'
      //   );
      // }
    }
  }

  onHashChange(cb) {
    // 本地测试，模拟小程序罗盘
    // let n = 0;
    // location.href = `${location.origin}#direction=first&environment=true`;
    // setInterval(() => {
    //   location.href = `${location.origin}#direction=${n}&environment=true`;
    //   n++;
    // }, 3000);
    const firstHash = location.hash;
    let newHash = '';

    const getQuery = query => {
      return query.split('&').reduce((prev, cur) => {
        const [k, v] = cur.split('=');
        return { ...prev,
          [k]: v
        };
      }, {});
    };

    window.addEventListener('popstate', function () {
      if (location.hash !== firstHash) {
        newHash = location.hash;
        history.back();
      } else {
        const query = getQuery(newHash.split('#')[1]);
        console.log('queryqueryquery :>> ', query);
        cb?.(query);
      } // newHash = location.hash;
      // const query = getQuery(newHash.split('#')[1]);
      // cb?.(query);

    }, false);
  }
  /**
   * @desc 获取箭头指向模型
   */


  getRoadNetArrow() {
    const {
      map: {
        scene,
        reDraw
      }
    } = this.options;
    const floorHeight = 1 * 1000;
    const personHeight = 1.8 * 1000;
    const ARROW_HEIGHT = floorHeight; // position = new Vector3(position.x, position.y, ARROW_HEIGHT);

    if (this.arrowGroupCache) {
      const arrowGroupClone = this.arrowGroupCache.clone();
      return arrowGroupClone;
    }

    return new Promise((resolve, reject) => {
      // 获取到 mesh 用来改变属性
      const _getMesh = arrow => {
        return arrow.children[0]?.children[0]?.children[0]?.children[0];
      };

      const loader = new GLTFLoader_js_namespaceObject.GLTFLoader();
      loader.load(arrow_scene, ({
        scene: arrow
      }) => {
        const SCALE = 20;
        const multiplyFactor = 20; // - 获取 mesh 改变颜色

        const mesh = _getMesh(arrow);

        arrow.name = 'ar_roadNetArrow'; // 创建一个新的Object3D，包含箭头和线框

        const arrowGroup = new external_three_namespaceObject.Object3D();
        arrowGroup.name = 'ar_roadNetArrow'; // scene.add(arrowGroup);
        // arrowGroup.rotateZ(Math.PI * (90 / 180));
        // 添加线框

        const arrowBorder = new external_three_namespaceObject.LineSegments();
        const matLine = new external_three_namespaceObject.LineBasicMaterial({
          color: '#fff',
          opacity: 1,
          linewidth: 2,
          transparent: true // depthTest: false

        });
        arrowBorder.material = matLine;
        arrowBorder.geometry = new external_three_namespaceObject.EdgesGeometry(mesh.geometry);
        arrowBorder.rotateX(-Math.PI * (90 / 180));
        arrowBorder.scale.multiply(new external_three_namespaceObject.Vector3(multiplyFactor, multiplyFactor, multiplyFactor)); // arrowBorder.scale.addScalar(SCALE);
        // 添加到一个新的组
        // arrowGroup.add(arrow, arrowBorder);

        arrowGroup.add(arrow); // @ts-ignore

        mesh.material.color.set('#366ef6'); // mesh.rotateX(Math.PI * (90 / 180));
        // - 合适的大小，控制在屏幕的 1/3
        // arrow.scale.addScalar(SCALE);

        arrow.scale.multiply(new external_three_namespaceObject.Vector3(multiplyFactor, multiplyFactor, multiplyFactor)); // - 初始化向上，也就是正北
        // arrow.rotateZ(Math.PI * (90 / 180));
        // 加入缓存
        // this.arrowGroupCache = arrowGroup;
        // const arrowGroupCache = this.arrowGroupCache.clone();
        // resolve(arrowGroupCache);

        this.arrowGroupCache = arrow;
        const arrowGroupCache = this.arrowGroupCache.clone();
        resolve(arrowGroupCache);
      }, undefined, error => {
        console.error(error);
        reject(error);
      });
    });
  }
  /**
   * @desc 获取箭头指向模型
   */


  getRoadNetArrowV2() {
    const {
      map: {
        scene,
        reDraw
      }
    } = this.options;

    if (this.arrowGroupCache) {
      const arrowGroupClone = this.arrowGroupCache.clone();
      return arrowGroupClone;
    }

    return new Promise((resolve, reject) => {
      // 获取到 mesh 用来改变属性
      const _getMesh = obj => {
        if (obj instanceof external_three_namespaceObject.Mesh) {
          return obj;
        } else {
          return _getMesh(obj.children[0]);
        }
      };

      const loader = new GLTFLoader_js_namespaceObject.GLTFLoader();
      loader.load(arrow_2_scene, ({
        scene: arrow
      }) => {
        const SCALE = 1000; // const multiplyFactor = 10000;
        // const multiplyFactor = 5000;
        // - 获取 mesh 改变颜色
        // const mesh = _getMesh(arrow);

        arrow.name = 'ar_roadNetArrow'; // @ts-ignore
        // mesh.material.color.set('#366ef6');
        // arrow.scale.multiply(
        //   new Vector3(multiplyFactor, multiplyFactor, multiplyFactor)
        // );

        arrow.scale.addScalar(SCALE);
        this.arrowGroupCache = arrow;
        const arrowGroupCache = this.arrowGroupCache.clone();
        resolve(arrowGroupCache);
      }, undefined, error => {
        console.error(error);
        reject(error);
      });
    });
  } // private updateMeshArrowDirection(arrowMesh: Mesh, arrowBorder: LineSegments) {
  //   const {
  //     map: { scene, reDraw }
  //   } = this.options;
  //   reDraw();
  // }


  getCompass() {
    const {
      map: {
        $map,
        container
      }
    } = this.options;
    const id = `${container}-ar__compass`;
    let $elem = document.getElementById(id);

    if (!$elem) {
      // 动态append $video
      $elem = document.createElement('div');
      $elem.id = id;
      $elem.className = `${CLS_PREFIX}-ar__compass`;
      $elem.style.position = 'fixed';
      $elem.style.zIndex = '998';
      $elem.style.left = '0';
      $elem.style.top = '0';
      $map.appendChild($elem);
    }

    return $elem;
  }

  'test.move'() {
    const {
      map: {
        camera,
        cameraControls,
        reDraw
      }
    } = this.options;
    const oldT = new external_three_namespaceObject.Vector3(0, 0, 2800);
    const newT = new external_three_namespaceObject.Vector3(0, 10000, 2800);
    const t = new (external_tween_js_default()).Tween({
      x: oldT.x,
      y: oldT.y,
      z: oldT.z
    }) // time = distance / speed，保持每段距离都匀速
    .to({
      x: newT.x,
      y: newT.y,
      z: newT.z
    }, 5000).easing((external_tween_js_default()).Easing.Linear.None).onStart(function () {}).onUpdate(function (values) {
      // @ts-ignore
      const object = this;
      cameraControls.moveTo(object.x, object.y, object.z, true);
      reDraw();
    }).onComplete(function () {});
    t.start();
  }
  /**
   * @desc 添加一个箭头
   */


  getArrow() {
    const {
      map,
      map: {
        $map,
        container
      }
    } = this.options;
    const id = `${container}-ar__arrow`;
    let $elem = document.getElementById(id);

    if (!$elem) {
      $elem = document.createElement('div');
      $elem.style.display = 'none';
      $elem.id = id;
      $elem.className = `${CLS_PREFIX}-ar__arrow`;
      const $img = document.createElement('img');
      $img.src = ic_arrow;
      const $span = document.createElement('span');
      $span.innerText = '往这边看';
      $elem.append($img, $span);
      $map.appendChild($elem);
    }

    const turnLeft = () => {
      $elem && ($elem.style.display = 'flex');
      $elem?.classList.remove('right');
      $elem?.classList.add('left');
    };

    const turnRight = () => {
      $elem && ($elem.style.display = 'flex');
      $elem?.classList.remove('left');
      $elem?.classList.add('right');
    };

    const hide = () => {
      $elem && ($elem.style.display = 'none');
    };

    return {
      $elem,
      turnLeft,
      turnRight,
      hide
    };
  }
  /**
   * @desc 添加一个按钮
   */


  'dev.addControl'(id, text, style = {}) {
    const {
      map,
      map: {
        $map,
        container
      }
    } = this.options; // const id = `${container}-ar__demo`;

    let $elem = document.getElementById(id);

    if (!$elem) {
      $elem = document.createElement('button');
      $elem.id = id;
      $elem.innerText = text;
      Object.assign($elem.style, {
        position: 'fixed',
        zIndex: '998',
        top: '0',
        right: '0' // userSelect: 'none'
        // '-webkitUserSelect': 'none'

      }, style);
      $map.appendChild($elem);
    }

    return $elem;
  }
  /**
   * @desc 选择起点和终点
   */


  'test.markBeginAndEnd'() {}
  /**
   * @desc 线段延长后的端点
   * @param p1 起点
   * @param p2 终点
   * @param d 需要新增距离
   * @returns 新的终点坐标
   */


  getExtendedEndPoint(p1, p2, d) {
    const vec2 = new external_three_namespaceObject.Vector2();

    const _d = vec2.copy(p2).sub(p1).length() + d;

    let temp = vec2.copy(p2).sub(p1).normalize();
    temp = temp.multiplyScalar(_d);
    temp = temp.add(p1);
    return temp;
  }

  getDistance(p1, p2) {
    return Math.abs(Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2)));
  }
  /**
   * @desc 根据 最佳线路 绘制箭头指向
   * 箭头绘制逻辑：
   * - 起/终点，是用户的真实位置，所以要补充两端箭头分别在头尾
   * - 只绘制部分箭头，不绘制全路网
   * - 只绘制前方 MAX 米，存在两种场景，1.箭头都是直线 2.箭头有几处拐弯，”拐弯提醒是比较重要的“
   * - 需要距离起点一点距离 DIST 米进行绘制，保证用户可以在第一视角看到”第一个箭头“
   */


  async drawRoadNetArrows(trackPoints) {
    const {
      map: {
        scene,
        reDraw
      }
    } = this.options;
    /**
     * @desc 根据起点和终点还有和起点的距离 获取路径中的某个点
     */

    const _getTrackPoint = (p1, p2, len) => {
      const p1p2Len = Math.abs(Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2)));
      const cos = (p2.x - p1.x) / p1p2Len;
      const sin = (p2.y - p1.y) / p1p2Len;
      return new external_three_namespaceObject.Vector2(p1.x + len * cos, p1.y + len * sin);
    };

    const MAX = 30 * 1000;
    const MIN = 5 * 1000;
    let p1;
    let p2; // 地板目前有1米，车位目前有1.5米，墙3米，假设人1.8米

    const floorHeight = 1 * 1000;
    const personHeight = 1.8 * 1000; // arrowTemp 只是用来计算一些需要的数据

    const arrowTemp = await this.getRoadNetArrowV2();
    const aabb = new external_three_namespaceObject.Box3().setFromObject(arrowTemp); // const ARROW_LEN = aabb.max.y - aabb.min.y;

    let ARROW_LEN = aabb.max.x - aabb.min.x; // ARROW_LEN = ARROW_LEN + ARROW_LEN * 1.5;

    ARROW_LEN = ARROW_LEN + ARROW_LEN * 0.8; // const box3 = new Box3Helper(aabb, 'red');
    // scene.add(box3);
    // 先把自身的 z 清除设置为 -z，实际的 z 轴就是后面累加的值

    const ARROW_POSITION_Z = -aabb.min.z + floorHeight;
    console.log('aabb :>> ', aabb); // // 箭头数组组
    // const arrowArrGroup = new Object3D();
    // arrowArrGroup.name = 'ar_arrowArrGroup';
    // scene.add(arrowArrGroup);
    // const _getMesh = (arrow: Group) => {
    //   return arrow.children[0]?.children[0]?.children[0]?.children[0]
    //     ?.children[0] as Mesh;
    // };
    // 判断前方 MAX 米会涉及到几条 path
    // 模拟AR，模拟手机摇晃

    const getNewTrackPoints = (dist, trackPoints) => {
      const newTrackPoints = []; // 累加大于 MAX 就停止

      let total = 0;
      let prevTotal = 0;
      let d = 0;
      let index = -1;

      for (let i = 0, len = trackPoints.length; i < len; i++) {
        p1 = trackPoints[i];

        if (trackPoints[i + 1]) {
          p2 = trackPoints[i + 1];
          d = this.getDistance(p1, p2);
          total += d;
          console.log(`第${i + 1}段距离 :>> `, this.getDistance(p1, p2)); // 小于就直接 push

          if (total < dist) {
            // 记录之前的总长度
            prevTotal += d;
            newTrackPoints.push(p1);
          } else {
            // 记录当前的位置
            index = i;
            console.log('index :>> ', index);
            console.log('之前总长度 :>> ', prevTotal); // 扣除掉累加的 total

            const newEnd = _getTrackPoint(p1, p2, dist - prevTotal); // 处理


            newTrackPoints.push(p1, newEnd); // 跳出循环

            break;
          }
        } else {
          // 所有线段累加都没有超过 MAX 这里就要补充最后一个点，使其完整
          newTrackPoints.push(p1);
        }
      }

      return {
        newTrackPoints,
        index
      };
    };

    const {
      newTrackPoints: newTrackPoints1,
      index
    } = getNewTrackPoints(MIN, trackPoints);

    if (index !== -1) {
      // 把起点路线的最后一个点放在合适的位置
      trackPoints.splice(index, 1, newTrackPoints1[newTrackPoints1.length - 1]); // 删掉多余的开始的点

      trackPoints = trackPoints.slice(index);
    }

    const {
      newTrackPoints
    } = getNewTrackPoints(MAX, trackPoints);
    console.log('newTrackPoints :>> ', newTrackPoints);

    for (let i = 0, len = newTrackPoints.length; i < len; i++) {
      if (newTrackPoints[i + 1]) {
        p1 = newTrackPoints[i];
        p2 = newTrackPoints[i + 1];
        const p1p2Len = Math.abs(Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2))); // // 控制箭头绘制数量，只在前方 MAX米 绘制箭头
        // if (p1p2Len > MAX) {
        //   // https://blog.csdn.net/weixin_45565771/article/details/106714600
        //   const cos = (p2.x - p1.x) / p1p2Len;
        //   const sin = (p2.y - p1.y) / p1p2Len;
        //   p2 = new Vector2(p1.x + MAX * cos, p1.y + MAX * sin);
        //   p1p2Len = MAX;
        // }
        // 角度

        const {
          radian
        } = getAngle(new external_three_namespaceObject.Vector2(p1.x, p1.y), new external_three_namespaceObject.Vector2(p2.x, p2.y)); // const arrowNum = Math.ceil(p1p2Len / ARROW_LEN);

        const arrowNum = Math.floor(p1p2Len / ARROW_LEN); // const arrowNum = Math.round(p1p2Len / ARROW_LEN);

        console.log('arrowNumarrowNumarrowNum :>> ', arrowNum); // gap 跳过几个进行绘制，使其有间隔

        const gap = 0; // 第一条 path 的第一个第二个不进行绘制，因为第一视角下，会看不到
        // for (let j = i === 0 ? 3 : 0; j < arrowNum; j += gap + 1) {

        for (let j = i === 0 ? 1 : 0; j < arrowNum; j += gap + 1) {
          // for (let j = 0; j < arrowNum; j += gap + 1) {
          const arrow = await this.getRoadNetArrowV2(); // 位置

          const x = (p2.x - p1.x) / arrowNum * j + p1.x;
          const y = (p2.y - p1.y) / arrowNum * j + p1.y;
          arrow.position.copy(new external_three_namespaceObject.Vector3(x, y, ARROW_POSITION_Z));
          arrow.rotateZ(radian); // arrow.rotateY(-Math.PI * (30 / 180));

          scene.add(arrow); // const tempaabb = new Box3().setFromObject(arrow);
          // const tempBox3 = new Box3Helper(tempaabb, 'red');
          // scene.add(tempBox3);
          // 添加到一个组，然后控制这个组的倾斜角
          // arrowArrGroup.add(arrow);
        } // box3.rotateZ(radian);
        // box3.rotateY(-Math.PI * (20 / 180));
        // box3.rotateZ(Math.PI * (20 / 180));
        // box3.position.setZ(5000);
        // arrowArrGroup.rotateY(-Math.PI * (30 / 180));
        // arrowArrGroup.rotateX(Math.PI * (30 / 180));
        // arrowArrGroup.rotateZ(radian);
        // arrowArrGroup.rotateY(Math.PI * (10 / 180));
        // arrowArrGroup.position.setZ(1000);
        // const aabb2 = new Box3().setFromObject(arrowArrGroup);
        // const box3 = new Box3Helper(aabb2, 'red');
        // scene.add(box3);


        reDraw();
      }
    }
  }
  /**
   * @desc 线路计算
   */


  search(begin, end, _cb) {
    begin = myTruncate(begin);
    end = myTruncate(end); // 缓存

    this.beginCache = begin;
    this.endCache = end;
    const {
      map: {
        scene
      }
    } = this.options;

    if (begin.length > 0 && end.length > 0) {
      // 模拟测试
      // begin = [0, 0];
      // begin = [6015.380734193866, -3760.4037080452727];
      // end = [-23497.355, 28685.989];
      // 得到绘制轨迹的点集合
      const trackPoints = this.aStar.calcShortestPath(begin, end);
      const {
        map: {
          scene,
          reDraw
        }
      } = this.options; // 先删除已经存在的线段

      const tracks = utils_getObjectsByName('ar_track', scene);
      scene.remove(...tracks); // 删除已经存在的箭头对象

      const roadNetArrows = utils_getObjectsByName('ar_roadNetArrow', scene);
      scene.remove(...roadNetArrows);
      reDraw();

      if (trackPoints.length >= 2) {
        const points = []; // 绘制简单的线段

        for (const item of trackPoints) {
          // @ts-ignore
          points.push(new external_three_namespaceObject.Vector3(item.x, item.y, 0));
        }

        this.drawNormalLine(points, {
          name: 'ar_track',
          color: 'blue'
        }); // 在线路上绘制指示箭头，加入用户的真实起点，要连接用户到路网上

        const newTrackPoints = this.trackPointsCache = [new external_three_namespaceObject.Vector2(begin[0], begin[1]), ...trackPoints];
        this.drawRoadNetArrows(newTrackPoints);
        _cb?.('complete', trackPoints);
      } else {
        console.warn('线段长度小于2，无法进行绘制');
        _cb?.('error', '线段长度小于2，无法进行绘制');
      }

      reDraw();
    }
  }

}
;// CONCATENATED MODULE: ./src/core/ar/index.ts

/* harmony default export */ var ar = (AR);
;// CONCATENATED MODULE: ./src/index.ts

 // import Helper from './core/helper'





const KTMap = {
  Map: map,
  PoisLayer: PoisLayer,
  PoiMarker: PoiMarker,
  ParkingLayer: parkingLayer,
  ViewMode: viewMode_ViewMode,
  LayerMode: layerMode_LayerMode,
  Walking: walking,
  AR: ar
};
/* harmony default export */ var src_0 = (KTMap);
;// CONCATENATED MODULE: ../../node_modules/@vue/cli-service/lib/commands/build/entry-lib.js


/* harmony default export */ var entry_lib = (src_0);


}();
/******/ 	return __webpack_exports__;
/******/ })()
;
});
//# sourceMappingURL=ktmap.umd.js.map