@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 +1 -1
- package/src/KMUtil.js +70 -3
- package/src/KimapCore.browser.js +73 -5
- package/src/core/KimapSDK.js +2 -1
package/package.json
CHANGED
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(
|
|
974
|
-
return [
|
|
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(
|
|
1045
|
+
const rawPath = aStarPathfinding(adjustedStart, adjustedEnd, obstacles, 0.2);
|
|
979
1046
|
|
|
980
1047
|
// 如果路径只有2个点(直线),直接返回
|
|
981
1048
|
if (rawPath.length <= 2) {
|
package/src/KimapCore.browser.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
3028
|
+
var rawPath = aStarPathfinding(adjustedStart, adjustedEnd, obstacles, 0.2);
|
|
2961
3029
|
|
|
2962
3030
|
// 如果路径只有2个点(直线),直接返回
|
|
2963
3031
|
if (rawPath.length <= 2) {
|
package/src/core/KimapSDK.js
CHANGED
|
@@ -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
|
-
|
|
901
|
+
// 使用X和Z的平均值作为统一缩放(保持水平比例,与3D预览一致)
|
|
902
|
+
var uniformScale = (scaleX + scaleZ) / 2;
|
|
902
903
|
|
|
903
904
|
// 应用归一化缩放和用户缩放
|
|
904
905
|
var finalScale = uniformScale * furniture.scale.x;
|