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

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.9",
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) {
@@ -1736,7 +1736,8 @@
1736
1736
  var scaleX = size.x > 0 ? furniture.targetSize.width / size.x : 1;
1737
1737
  var scaleY = size.y > 0 ? furniture.targetSize.height / size.y : 1;
1738
1738
  var scaleZ = size.z > 0 ? furniture.targetSize.depth / size.z : 1;
1739
- var uniformScale = (scaleX + scaleY + scaleZ) / 3;
1739
+ // 使用X和Z的平均值作为统一缩放(保持水平比例,与3D预览一致)
1740
+ var uniformScale = (scaleX + scaleZ) / 2;
1740
1741
 
1741
1742
  // 应用归一化缩放和用户缩放
1742
1743
  var finalScale = uniformScale * furniture.scale.x;
@@ -1744,9 +1745,10 @@
1744
1745
 
1745
1746
  console.log('🔧 家具模型缩放:', {
1746
1747
  type: furniture.type,
1747
- originalSize: { x: size.x.toFixed(3), y: size.y.toFixed(3), z: size.z.toFixed(3) },
1748
+ originalSize: { x: size.x.toFixed(3), y: size.y.toFixed(3), z: size.z.toFixed(3), unit: '模型单位' },
1748
1749
  targetSize: furniture.targetSize,
1749
- uniformScale: uniformScale.toFixed(3),
1750
+ scaleFactors: { x: scaleX.toFixed(3), y: scaleY.toFixed(3), z: scaleZ.toFixed(3) },
1751
+ uniformScale: uniformScale.toFixed(3) + ' (平均X和Z)',
1750
1752
  userScale: furniture.scale.x,
1751
1753
  finalScale: finalScale.toFixed(3)
1752
1754
  });
@@ -2239,6 +2241,59 @@
2239
2241
  return Math.sqrt((a.x - b.x) * (a.x - b.x) + (a.z - b.z) * (a.z - b.z));
2240
2242
  }
2241
2243
 
2244
+ /**
2245
+ * 找到最近的可行位置(不在障碍物内)
2246
+ */
2247
+ function findNearestFreePointInternal(point, obstacles, searchRadius, step) {
2248
+ searchRadius = searchRadius || 2;
2249
+ step = step || 0.1;
2250
+
2251
+ // 如果当前点已经可行,直接返回
2252
+ if (!isPointInObstaclesInternal(point.x, point.z, obstacles)) {
2253
+ return point;
2254
+ }
2255
+
2256
+ console.log('点 (' + point.x.toFixed(2) + ', ' + point.z.toFixed(2) + ') 在障碍物内,搜索最近可行位置...');
2257
+
2258
+ // 螺旋搜索最近的可行点
2259
+ var bestPoint = null;
2260
+ var minDistance = Infinity;
2261
+
2262
+ // 使用圆形搜索模式
2263
+ var angles = 16; // 16个方向
2264
+ var radiusSteps = Math.ceil(searchRadius / step);
2265
+
2266
+ for (var r = 1; r <= radiusSteps; r++) {
2267
+ var currentRadius = r * step;
2268
+
2269
+ for (var a = 0; a < angles; a++) {
2270
+ var angle = (a / angles) * Math.PI * 2;
2271
+ var testX = point.x + Math.cos(angle) * currentRadius;
2272
+ var testZ = point.z + Math.sin(angle) * currentRadius;
2273
+
2274
+ // 检查这个点是否可行
2275
+ if (!isPointInObstaclesInternal(testX, testZ, obstacles)) {
2276
+ var dist = Math.sqrt(
2277
+ (testX - point.x) * (testX - point.x) + (testZ - point.z) * (testZ - point.z)
2278
+ );
2279
+
2280
+ if (dist < minDistance) {
2281
+ minDistance = dist;
2282
+ bestPoint = { x: testX, z: testZ };
2283
+ }
2284
+
2285
+ // 找到第一个可行点就返回(最近的)
2286
+ console.log('✅ 找到可行位置: (' + testX.toFixed(2) + ', ' + testZ.toFixed(2) + '), 距离: ' + dist.toFixed(2) + '米');
2287
+ return bestPoint;
2288
+ }
2289
+ }
2290
+ }
2291
+
2292
+ // 如果没找到可行点,返回原点(降级处理)
2293
+ console.warn('⚠️ 在' + searchRadius + '米范围内未找到可行位置,使用原点');
2294
+ return point;
2295
+ }
2296
+
2242
2297
  /**
2243
2298
  * 简化路径 - 移除不必要的中间点
2244
2299
  * @param {Array} path - 原始路径点 [{x, z}, ...]
@@ -2954,10 +3009,23 @@
2954
3009
  obstacles = (data && data.layers) ? KMUtil.extractObstaclesFromFloor(data, true) : KMUtil.extractObstacles(data, true);
2955
3010
  }
2956
3011
  if (obstacles.length === 0) return [start, end];
2957
- if (!pathIntersectsObstaclesInternal(start.x, start.z, end.x, end.z, obstacles, 0.1)) return [start, end];
3012
+
3013
+ // 调整起点和终点,确保它们不在障碍物内
3014
+ var adjustedStart = findNearestFreePointInternal(start, obstacles, 2, 0.1);
3015
+ var adjustedEnd = findNearestFreePointInternal(end, obstacles, 2, 0.1);
3016
+
3017
+ // 如果起点或终点被调整了,记录日志
3018
+ if (adjustedStart.x !== start.x || adjustedStart.z !== start.z) {
3019
+ console.log('起点已调整: (' + start.x.toFixed(2) + ', ' + start.z.toFixed(2) + ') → (' + adjustedStart.x.toFixed(2) + ', ' + adjustedStart.z.toFixed(2) + ')');
3020
+ }
3021
+ if (adjustedEnd.x !== end.x || adjustedEnd.z !== end.z) {
3022
+ console.log('终点已调整: (' + end.x.toFixed(2) + ', ' + end.z.toFixed(2) + ') → (' + adjustedEnd.x.toFixed(2) + ', ' + adjustedEnd.z.toFixed(2) + ')');
3023
+ }
3024
+
3025
+ if (!pathIntersectsObstaclesInternal(adjustedStart.x, adjustedStart.z, adjustedEnd.x, adjustedEnd.z, obstacles, 0.1)) return [adjustedStart, adjustedEnd];
2958
3026
 
2959
3027
  // 使用A*算法(与KMUtil.js一致,gridSize: 0.2米)
2960
- var rawPath = aStarPathfinding(start, end, obstacles, 0.2);
3028
+ var rawPath = aStarPathfinding(adjustedStart, adjustedEnd, obstacles, 0.2);
2961
3029
 
2962
3030
  // 如果路径只有2个点(直线),直接返回
2963
3031
  if (rawPath.length <= 2) {
@@ -898,7 +898,8 @@ KimapSDK.prototype._loadSingleFurniture = function(furniture, serverUrl) {
898
898
  var scaleX = size.x > 0 ? furniture.targetSize.width / size.x : 1;
899
899
  var scaleY = size.y > 0 ? furniture.targetSize.height / size.y : 1;
900
900
  var scaleZ = size.z > 0 ? furniture.targetSize.depth / size.z : 1;
901
- var uniformScale = (scaleX + scaleY + scaleZ) / 3;
901
+ // 使用X和Z的平均值作为统一缩放(保持水平比例,与3D预览一致)
902
+ var uniformScale = (scaleX + scaleZ) / 2;
902
903
 
903
904
  // 应用归一化缩放和用户缩放
904
905
  var finalScale = uniformScale * furniture.scale.x;