@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 +1 -1
- package/src/KMUtil.js +70 -3
- package/src/KimapCore.browser.js +68 -2
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
|
@@ -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
|
-
|
|
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(
|
|
3026
|
+
var rawPath = aStarPathfinding(adjustedStart, adjustedEnd, obstacles, 0.2);
|
|
2961
3027
|
|
|
2962
3028
|
// 如果路径只有2个点(直线),直接返回
|
|
2963
3029
|
if (rawPath.length <= 2) {
|