@kimap/indoor-positioning-sdk-vue2 4.2.7 → 4.2.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kimap/indoor-positioning-sdk-vue2",
3
- "version": "4.2.7",
3
+ "version": "4.2.8",
4
4
  "description": "Vue2自包含室内定位SDK - 完全兼容Webpack3+Babel6 | Vue2 Self-Contained Indoor Positioning SDK",
5
5
  "main": "index.js",
6
6
  "files": [
package/src/KMUtil.js CHANGED
@@ -805,6 +805,61 @@
805
805
  return Math.sqrt((a.x - b.x) ** 2 + (a.z - b.z) ** 2);
806
806
  }
807
807
 
808
+ /**
809
+ * 找到最近的可行位置(不在障碍物内)
810
+ * @param {Object} point - 原始点 {x, z}
811
+ * @param {Array} obstacles - 障碍物列表
812
+ * @param {number} searchRadius - 搜索半径(米),默认2米
813
+ * @param {number} step - 搜索步长(米),默认0.1米
814
+ * @returns {Object} 可行的点 {x, z}
815
+ */
816
+ function findNearestFreePoint(point, obstacles, searchRadius = 2, step = 0.1) {
817
+ // 如果当前点已经可行,直接返回
818
+ if (!isPointInObstacles(point.x, point.z, obstacles)) {
819
+ return point;
820
+ }
821
+
822
+ console.log(`点 (${point.x.toFixed(2)}, ${point.z.toFixed(2)}) 在障碍物内,搜索最近可行位置...`);
823
+
824
+ // 螺旋搜索最近的可行点
825
+ let bestPoint = null;
826
+ let minDistance = Infinity;
827
+
828
+ // 使用圆形搜索模式
829
+ const angles = 16; // 16个方向
830
+ const radiusSteps = Math.ceil(searchRadius / step);
831
+
832
+ for (let r = 1; r <= radiusSteps; r++) {
833
+ const currentRadius = r * step;
834
+
835
+ for (let a = 0; a < angles; a++) {
836
+ const angle = (a / angles) * Math.PI * 2;
837
+ const testX = point.x + Math.cos(angle) * currentRadius;
838
+ const testZ = point.z + Math.sin(angle) * currentRadius;
839
+
840
+ // 检查这个点是否可行
841
+ if (!isPointInObstacles(testX, testZ, obstacles)) {
842
+ const dist = Math.sqrt(
843
+ (testX - point.x) ** 2 + (testZ - point.z) ** 2
844
+ );
845
+
846
+ if (dist < minDistance) {
847
+ minDistance = dist;
848
+ bestPoint = { x: testX, z: testZ };
849
+ }
850
+
851
+ // 找到第一个可行点就返回(最近的)
852
+ console.log(`✅ 找到可行位置: (${testX.toFixed(2)}, ${testZ.toFixed(2)}), 距离: ${dist.toFixed(2)}米`);
853
+ return bestPoint;
854
+ }
855
+ }
856
+ }
857
+
858
+ // 如果没找到可行点,返回原点(降级处理)
859
+ console.warn(`⚠️ 在${searchRadius}米范围内未找到可行位置,使用原点`);
860
+ return point;
861
+ }
862
+
808
863
  /**
809
864
  * 简化路径 - 移除不必要的中间点
810
865
  * 使用Douglas-Peucker算法的简化版本
@@ -969,13 +1024,25 @@
969
1024
  return [start, end];
970
1025
  }
971
1026
 
1027
+ // 调整起点和终点,确保它们不在障碍物内
1028
+ const adjustedStart = findNearestFreePoint(start, obstacles, 2, 0.1);
1029
+ const adjustedEnd = findNearestFreePoint(end, obstacles, 2, 0.1);
1030
+
1031
+ // 如果起点或终点被调整了,记录日志
1032
+ if (adjustedStart.x !== start.x || adjustedStart.z !== start.z) {
1033
+ console.log(`起点已调整: (${start.x.toFixed(2)}, ${start.z.toFixed(2)}) → (${adjustedStart.x.toFixed(2)}, ${adjustedStart.z.toFixed(2)})`);
1034
+ }
1035
+ if (adjustedEnd.x !== end.x || adjustedEnd.z !== end.z) {
1036
+ console.log(`终点已调整: (${end.x.toFixed(2)}, ${end.z.toFixed(2)}) → (${adjustedEnd.x.toFixed(2)}, ${adjustedEnd.z.toFixed(2)})`);
1037
+ }
1038
+
972
1039
  // 检查直线是否可行(margin: 0.1米 = 10cm)
973
- if (!pathIntersectsObstacles(start.x, start.z, end.x, end.z, obstacles, 0.1)) {
974
- return [start, end];
1040
+ if (!pathIntersectsObstacles(adjustedStart.x, adjustedStart.z, adjustedEnd.x, adjustedEnd.z, obstacles, 0.1)) {
1041
+ return [adjustedStart, adjustedEnd];
975
1042
  }
976
1043
 
977
1044
  // 使用A*算法规划路径(gridSize: 0.2米 = 20cm)
978
- const rawPath = aStarPathfinding(start, end, obstacles, 0.2);
1045
+ const rawPath = aStarPathfinding(adjustedStart, adjustedEnd, obstacles, 0.2);
979
1046
 
980
1047
  // 如果路径只有2个点(直线),直接返回
981
1048
  if (rawPath.length <= 2) {
@@ -2239,6 +2239,59 @@
2239
2239
  return Math.sqrt((a.x - b.x) * (a.x - b.x) + (a.z - b.z) * (a.z - b.z));
2240
2240
  }
2241
2241
 
2242
+ /**
2243
+ * 找到最近的可行位置(不在障碍物内)
2244
+ */
2245
+ function findNearestFreePointInternal(point, obstacles, searchRadius, step) {
2246
+ searchRadius = searchRadius || 2;
2247
+ step = step || 0.1;
2248
+
2249
+ // 如果当前点已经可行,直接返回
2250
+ if (!isPointInObstaclesInternal(point.x, point.z, obstacles)) {
2251
+ return point;
2252
+ }
2253
+
2254
+ console.log('点 (' + point.x.toFixed(2) + ', ' + point.z.toFixed(2) + ') 在障碍物内,搜索最近可行位置...');
2255
+
2256
+ // 螺旋搜索最近的可行点
2257
+ var bestPoint = null;
2258
+ var minDistance = Infinity;
2259
+
2260
+ // 使用圆形搜索模式
2261
+ var angles = 16; // 16个方向
2262
+ var radiusSteps = Math.ceil(searchRadius / step);
2263
+
2264
+ for (var r = 1; r <= radiusSteps; r++) {
2265
+ var currentRadius = r * step;
2266
+
2267
+ for (var a = 0; a < angles; a++) {
2268
+ var angle = (a / angles) * Math.PI * 2;
2269
+ var testX = point.x + Math.cos(angle) * currentRadius;
2270
+ var testZ = point.z + Math.sin(angle) * currentRadius;
2271
+
2272
+ // 检查这个点是否可行
2273
+ if (!isPointInObstaclesInternal(testX, testZ, obstacles)) {
2274
+ var dist = Math.sqrt(
2275
+ (testX - point.x) * (testX - point.x) + (testZ - point.z) * (testZ - point.z)
2276
+ );
2277
+
2278
+ if (dist < minDistance) {
2279
+ minDistance = dist;
2280
+ bestPoint = { x: testX, z: testZ };
2281
+ }
2282
+
2283
+ // 找到第一个可行点就返回(最近的)
2284
+ console.log('✅ 找到可行位置: (' + testX.toFixed(2) + ', ' + testZ.toFixed(2) + '), 距离: ' + dist.toFixed(2) + '米');
2285
+ return bestPoint;
2286
+ }
2287
+ }
2288
+ }
2289
+
2290
+ // 如果没找到可行点,返回原点(降级处理)
2291
+ console.warn('⚠️ 在' + searchRadius + '米范围内未找到可行位置,使用原点');
2292
+ return point;
2293
+ }
2294
+
2242
2295
  /**
2243
2296
  * 简化路径 - 移除不必要的中间点
2244
2297
  * @param {Array} path - 原始路径点 [{x, z}, ...]
@@ -2954,10 +3007,23 @@
2954
3007
  obstacles = (data && data.layers) ? KMUtil.extractObstaclesFromFloor(data, true) : KMUtil.extractObstacles(data, true);
2955
3008
  }
2956
3009
  if (obstacles.length === 0) return [start, end];
2957
- if (!pathIntersectsObstaclesInternal(start.x, start.z, end.x, end.z, obstacles, 0.1)) return [start, end];
3010
+
3011
+ // 调整起点和终点,确保它们不在障碍物内
3012
+ var adjustedStart = findNearestFreePointInternal(start, obstacles, 2, 0.1);
3013
+ var adjustedEnd = findNearestFreePointInternal(end, obstacles, 2, 0.1);
3014
+
3015
+ // 如果起点或终点被调整了,记录日志
3016
+ if (adjustedStart.x !== start.x || adjustedStart.z !== start.z) {
3017
+ console.log('起点已调整: (' + start.x.toFixed(2) + ', ' + start.z.toFixed(2) + ') → (' + adjustedStart.x.toFixed(2) + ', ' + adjustedStart.z.toFixed(2) + ')');
3018
+ }
3019
+ if (adjustedEnd.x !== end.x || adjustedEnd.z !== end.z) {
3020
+ console.log('终点已调整: (' + end.x.toFixed(2) + ', ' + end.z.toFixed(2) + ') → (' + adjustedEnd.x.toFixed(2) + ', ' + adjustedEnd.z.toFixed(2) + ')');
3021
+ }
3022
+
3023
+ if (!pathIntersectsObstaclesInternal(adjustedStart.x, adjustedStart.z, adjustedEnd.x, adjustedEnd.z, obstacles, 0.1)) return [adjustedStart, adjustedEnd];
2958
3024
 
2959
3025
  // 使用A*算法(与KMUtil.js一致,gridSize: 0.2米)
2960
- var rawPath = aStarPathfinding(start, end, obstacles, 0.2);
3026
+ var rawPath = aStarPathfinding(adjustedStart, adjustedEnd, obstacles, 0.2);
2961
3027
 
2962
3028
  // 如果路径只有2个点(直线),直接返回
2963
3029
  if (rawPath.length <= 2) {