rm-webgpu-compute-tasks 0.0.11 → 0.0.12
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/index.d.ts +2 -1
- package/src/index.js +199 -78
package/package.json
CHANGED
package/src/index.d.ts
CHANGED
|
@@ -419,7 +419,8 @@ declare function obstacleDetection_(opt: ICreateObstacleDetection): Promise<{
|
|
|
419
419
|
declare interface Option_2 {
|
|
420
420
|
base: string;
|
|
421
421
|
urls: string[];
|
|
422
|
-
|
|
422
|
+
maskSize?: number;
|
|
423
|
+
contractionSize?: number;
|
|
423
424
|
kernelSize?: number;
|
|
424
425
|
groundZ?: number;
|
|
425
426
|
}
|
package/src/index.js
CHANGED
|
@@ -2216,6 +2216,22 @@ async function trajectoryHandle(baseUrl, trajectoryData) {
|
|
|
2216
2216
|
pointCloudArray
|
|
2217
2217
|
};
|
|
2218
2218
|
}
|
|
2219
|
+
function getPointsCenter(arr) {
|
|
2220
|
+
let x = 0, y = 0, z = 0;
|
|
2221
|
+
for (let i = 0; i < arr.length; i += 3) {
|
|
2222
|
+
x += arr[i];
|
|
2223
|
+
y += arr[i + 1];
|
|
2224
|
+
z += arr[i + 2];
|
|
2225
|
+
}
|
|
2226
|
+
const count = arr.length / 3;
|
|
2227
|
+
return { x: x / count, y: y / count, z: z / count };
|
|
2228
|
+
}
|
|
2229
|
+
function getPointDistance(p1, p2) {
|
|
2230
|
+
const dx = p2.x - p1.x;
|
|
2231
|
+
const dy = p2.y - p1.y;
|
|
2232
|
+
const dz = p2.z - p1.z;
|
|
2233
|
+
return Math.sqrt(dx * dx + dy * dy + dz * dz);
|
|
2234
|
+
}
|
|
2219
2235
|
class OcclusionMaterial extends ShaderMaterial {
|
|
2220
2236
|
constructor(opt) {
|
|
2221
2237
|
super({
|
|
@@ -2650,8 +2666,8 @@ class PolyAreaIndexMaterial extends ShaderMaterial {
|
|
|
2650
2666
|
side: "none",
|
|
2651
2667
|
uniforms: {
|
|
2652
2668
|
imageSize: { value: new Vector2(width, height) }
|
|
2653
|
-
}
|
|
2654
|
-
topology: "point-list"
|
|
2669
|
+
}
|
|
2670
|
+
// topology: "point-list"
|
|
2655
2671
|
});
|
|
2656
2672
|
this.resultTexture = resultTexture;
|
|
2657
2673
|
}
|
|
@@ -2851,15 +2867,15 @@ const mainCode$1 = (
|
|
|
2851
2867
|
}
|
|
2852
2868
|
|
|
2853
2869
|
// 获取多边形当前坐标有没有点云(获取深度值判断也是一样的, 深度值和点云索引图一一对应)
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2870
|
+
let packedIndex = textureLoad(pcIndexMap, vec2<i32>(x, y), 0);
|
|
2871
|
+
let pointIndex = unPackUint(packedIndex);
|
|
2872
|
+
if(isEmpty(pointIndex)) {
|
|
2873
|
+
return;
|
|
2874
|
+
}
|
|
2859
2875
|
|
|
2860
2876
|
// 获取当前点云深度值
|
|
2861
|
-
|
|
2862
|
-
|
|
2877
|
+
let depthU32 = pcDepth[idx];
|
|
2878
|
+
let depthF32 = orderedUintToFloat(depthU32);
|
|
2863
2879
|
|
|
2864
2880
|
// 获取范围内最小深度值和对应点云索引
|
|
2865
2881
|
let maxDepth = 10000.0;
|
|
@@ -2894,9 +2910,9 @@ const mainCode$1 = (
|
|
|
2894
2910
|
}
|
|
2895
2911
|
|
|
2896
2912
|
// 判断当前点深度和最小深度的差值是否小于阈值
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2913
|
+
if(abs(depthF32 - minDepth) > depthTol) {
|
|
2914
|
+
return;
|
|
2915
|
+
}
|
|
2900
2916
|
|
|
2901
2917
|
let finalPackedIndex = textureLoad(pcIndexMap, minPcUv, 0);
|
|
2902
2918
|
let finalPointIndex = unPackUint(finalPackedIndex);
|
|
@@ -2933,6 +2949,50 @@ class SOPCComputeMaterial extends ComputeMaterial {
|
|
|
2933
2949
|
this.uniforms.result.value = this.result;
|
|
2934
2950
|
}
|
|
2935
2951
|
}
|
|
2952
|
+
function euclideanClusterExtraction(points, distanceThreshold = 0.2, minClusterSize = 1, maxClusterSize = Infinity) {
|
|
2953
|
+
const pointCount = points.length / 3;
|
|
2954
|
+
const visited = new Uint8Array(pointCount);
|
|
2955
|
+
const clusters = [];
|
|
2956
|
+
const thresholdSq = distanceThreshold * distanceThreshold;
|
|
2957
|
+
function distanceSq(a, b) {
|
|
2958
|
+
const ai = a * 3;
|
|
2959
|
+
const bi = b * 3;
|
|
2960
|
+
const dx = points[ai] - points[bi];
|
|
2961
|
+
const dy = points[ai + 1] - points[bi + 1];
|
|
2962
|
+
const dz = points[ai + 2] - points[bi + 2];
|
|
2963
|
+
return dx * dx + dy * dy + dz * dz;
|
|
2964
|
+
}
|
|
2965
|
+
function regionQuery(index) {
|
|
2966
|
+
const neighbors = [];
|
|
2967
|
+
for (let i = 0; i < pointCount; i++) {
|
|
2968
|
+
if (distanceSq(index, i) <= thresholdSq) {
|
|
2969
|
+
neighbors.push(i);
|
|
2970
|
+
}
|
|
2971
|
+
}
|
|
2972
|
+
return neighbors;
|
|
2973
|
+
}
|
|
2974
|
+
for (let i = 0; i < pointCount; i++) {
|
|
2975
|
+
if (visited[i]) continue;
|
|
2976
|
+
visited[i] = 1;
|
|
2977
|
+
const cluster = [];
|
|
2978
|
+
const queue = [i];
|
|
2979
|
+
while (queue.length > 0) {
|
|
2980
|
+
const current = queue.pop();
|
|
2981
|
+
cluster.push(current);
|
|
2982
|
+
const neighbors = regionQuery(current);
|
|
2983
|
+
for (const neighbor of neighbors) {
|
|
2984
|
+
if (!visited[neighbor]) {
|
|
2985
|
+
visited[neighbor] = 1;
|
|
2986
|
+
queue.push(neighbor);
|
|
2987
|
+
}
|
|
2988
|
+
}
|
|
2989
|
+
}
|
|
2990
|
+
if (cluster.length >= minClusterSize && cluster.length <= maxClusterSize) {
|
|
2991
|
+
clusters.push(cluster);
|
|
2992
|
+
}
|
|
2993
|
+
}
|
|
2994
|
+
return clusters;
|
|
2995
|
+
}
|
|
2936
2996
|
const beforeCcde = (
|
|
2937
2997
|
/* wgsl*/
|
|
2938
2998
|
`
|
|
@@ -2950,11 +3010,11 @@ const beforeCcde = (
|
|
|
2950
3010
|
let g = u32(color.g * 255.0);
|
|
2951
3011
|
let b = u32(color.b * 255.0);
|
|
2952
3012
|
let a = u32(color.a * 255.0);
|
|
2953
|
-
return (a << 24u) | (b << 16u) | (g << 8u)
|
|
3013
|
+
return (a << 24u) | (b << 16u) | (g << 8u) | r;
|
|
2954
3014
|
}
|
|
2955
3015
|
|
|
2956
3016
|
fn isEmpty(value: u32) -> bool {
|
|
2957
|
-
return value
|
|
3017
|
+
return value == 0xff000000 || value == 0x0 ;
|
|
2958
3018
|
}
|
|
2959
3019
|
`
|
|
2960
3020
|
);
|
|
@@ -2973,15 +3033,16 @@ const mainCode = (
|
|
|
2973
3033
|
// 当前像素
|
|
2974
3034
|
let center = unPackUint(textureLoad(map, vec2<i32>(x, y), 0));
|
|
2975
3035
|
|
|
2976
|
-
//
|
|
2977
|
-
if (
|
|
2978
|
-
result[idx] =
|
|
3036
|
+
// 如果当前就是空,直接空
|
|
3037
|
+
if ( isEmpty(center) ) {
|
|
3038
|
+
result[idx] = 0xff000000;
|
|
2979
3039
|
return;
|
|
2980
3040
|
}
|
|
2981
3041
|
|
|
2982
|
-
//
|
|
2983
|
-
var
|
|
3042
|
+
// 是否被腐蚀
|
|
3043
|
+
var eroded = false;
|
|
2984
3044
|
|
|
3045
|
+
// 遍历邻域
|
|
2985
3046
|
for (var ky = -half; ky <= half; ky = ky + 1) {
|
|
2986
3047
|
let ny = y + ky;
|
|
2987
3048
|
|
|
@@ -2998,22 +3059,27 @@ const mainCode = (
|
|
|
2998
3059
|
|
|
2999
3060
|
let neighbor = unPackUint(textureLoad(map, vec2<i32>(nx, ny), 0));
|
|
3000
3061
|
|
|
3001
|
-
//
|
|
3002
|
-
if (
|
|
3003
|
-
|
|
3062
|
+
// 只要有一个是空 → 腐蚀
|
|
3063
|
+
if (isEmpty(neighbor) || neighbor != center) {
|
|
3064
|
+
eroded = true;
|
|
3004
3065
|
break;
|
|
3005
3066
|
}
|
|
3006
3067
|
}
|
|
3007
3068
|
|
|
3008
|
-
if (
|
|
3069
|
+
if (eroded) {
|
|
3009
3070
|
break;
|
|
3010
3071
|
}
|
|
3011
3072
|
}
|
|
3012
3073
|
|
|
3013
|
-
|
|
3074
|
+
// 写结果
|
|
3075
|
+
if (eroded) {
|
|
3076
|
+
result[idx] = 0xff000000;
|
|
3077
|
+
} else {
|
|
3078
|
+
result[idx] = center;
|
|
3079
|
+
}
|
|
3014
3080
|
`
|
|
3015
3081
|
);
|
|
3016
|
-
class
|
|
3082
|
+
class ErodeMaskComputeMaterial extends ComputeMaterial {
|
|
3017
3083
|
constructor(width = 1920, height = 1200, texture, kernelSize = 3) {
|
|
3018
3084
|
super({
|
|
3019
3085
|
maxSize: [width, height],
|
|
@@ -3023,6 +3089,7 @@ class DilateMaskComputeMaterial extends ComputeMaterial {
|
|
|
3023
3089
|
map: { value: texture },
|
|
3024
3090
|
size: { value: new Vector2(width, height) },
|
|
3025
3091
|
kernelSize: { value: kernelSize },
|
|
3092
|
+
// 建议从3开始
|
|
3026
3093
|
result: {
|
|
3027
3094
|
value: new Uint32Array(width * height),
|
|
3028
3095
|
write: true
|
|
@@ -3031,49 +3098,96 @@ class DilateMaskComputeMaterial extends ComputeMaterial {
|
|
|
3031
3098
|
});
|
|
3032
3099
|
}
|
|
3033
3100
|
}
|
|
3034
|
-
function
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
const ai = a * 3;
|
|
3041
|
-
const bi = b * 3;
|
|
3042
|
-
const dx = points[ai] - points[bi];
|
|
3043
|
-
const dy = points[ai + 1] - points[bi + 1];
|
|
3044
|
-
const dz = points[ai + 2] - points[bi + 2];
|
|
3045
|
-
return dx * dx + dy * dy + dz * dz;
|
|
3046
|
-
}
|
|
3047
|
-
function regionQuery(index) {
|
|
3048
|
-
const neighbors = [];
|
|
3049
|
-
for (let i = 0; i < pointCount; i++) {
|
|
3050
|
-
if (distanceSq(index, i) <= thresholdSq) {
|
|
3051
|
-
neighbors.push(i);
|
|
3052
|
-
}
|
|
3053
|
-
}
|
|
3054
|
-
return neighbors;
|
|
3101
|
+
function ringTriangleGenerator(path, inner = 3, outer = 0) {
|
|
3102
|
+
if (path.length < 3) {
|
|
3103
|
+
return {
|
|
3104
|
+
outerPath: [],
|
|
3105
|
+
innerPath: []
|
|
3106
|
+
};
|
|
3055
3107
|
}
|
|
3056
|
-
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
const
|
|
3060
|
-
const
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3108
|
+
const len = path.length;
|
|
3109
|
+
let area = 0;
|
|
3110
|
+
for (let i = 0; i < len; i++) {
|
|
3111
|
+
const [x1, y1] = path[i];
|
|
3112
|
+
const [x2, y2] = path[(i + 1) % len];
|
|
3113
|
+
area += x1 * y2 - x2 * y1;
|
|
3114
|
+
}
|
|
3115
|
+
const isCCW = area > 0;
|
|
3116
|
+
const movePath = (distance) => {
|
|
3117
|
+
return path.map((curr, i) => {
|
|
3118
|
+
const prev = path[(i - 1 + len) % len];
|
|
3119
|
+
const next = path[(i + 1) % len];
|
|
3120
|
+
const dx1 = curr[0] - prev[0];
|
|
3121
|
+
const dy1 = curr[1] - prev[1];
|
|
3122
|
+
const l1 = Math.hypot(dx1, dy1) || 1;
|
|
3123
|
+
const dx2 = next[0] - curr[0];
|
|
3124
|
+
const dy2 = next[1] - curr[1];
|
|
3125
|
+
const l2 = Math.hypot(dx2, dy2) || 1;
|
|
3126
|
+
let nx1, ny1;
|
|
3127
|
+
let nx2, ny2;
|
|
3128
|
+
if (isCCW) {
|
|
3129
|
+
nx1 = dy1 / l1;
|
|
3130
|
+
ny1 = -dx1 / l1;
|
|
3131
|
+
nx2 = dy2 / l2;
|
|
3132
|
+
ny2 = -dx2 / l2;
|
|
3133
|
+
} else {
|
|
3134
|
+
nx1 = -dy1 / l1;
|
|
3135
|
+
ny1 = dx1 / l1;
|
|
3136
|
+
nx2 = -dy2 / l2;
|
|
3137
|
+
ny2 = dx2 / l2;
|
|
3070
3138
|
}
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3139
|
+
let nx = nx1 + nx2;
|
|
3140
|
+
let ny = ny1 + ny2;
|
|
3141
|
+
const nl = Math.hypot(nx, ny) || 1;
|
|
3142
|
+
nx /= nl;
|
|
3143
|
+
ny /= nl;
|
|
3144
|
+
return [
|
|
3145
|
+
curr[0] + nx * distance,
|
|
3146
|
+
curr[1] + ny * distance
|
|
3147
|
+
];
|
|
3148
|
+
});
|
|
3149
|
+
};
|
|
3150
|
+
return {
|
|
3151
|
+
outerPath: movePath(outer),
|
|
3152
|
+
innerPath: movePath(-inner)
|
|
3153
|
+
};
|
|
3154
|
+
}
|
|
3155
|
+
function ringPathsToMesh(outerPath, innerPath, z = 0) {
|
|
3156
|
+
const len = Math.min(outerPath.length, innerPath.length);
|
|
3157
|
+
if (len < 2) {
|
|
3158
|
+
return [];
|
|
3159
|
+
}
|
|
3160
|
+
const vertices = [];
|
|
3161
|
+
for (let i = 0; i < len; i++) {
|
|
3162
|
+
const next = (i + 1) % len;
|
|
3163
|
+
const o0 = outerPath[i];
|
|
3164
|
+
const o1 = outerPath[next];
|
|
3165
|
+
const i0 = innerPath[i];
|
|
3166
|
+
const i1 = innerPath[next];
|
|
3167
|
+
vertices.push(
|
|
3168
|
+
o0[0],
|
|
3169
|
+
o0[1],
|
|
3170
|
+
z,
|
|
3171
|
+
o1[0],
|
|
3172
|
+
o1[1],
|
|
3173
|
+
z,
|
|
3174
|
+
i0[0],
|
|
3175
|
+
i0[1],
|
|
3176
|
+
z
|
|
3177
|
+
);
|
|
3178
|
+
vertices.push(
|
|
3179
|
+
o1[0],
|
|
3180
|
+
o1[1],
|
|
3181
|
+
z,
|
|
3182
|
+
i1[0],
|
|
3183
|
+
i1[1],
|
|
3184
|
+
z,
|
|
3185
|
+
i0[0],
|
|
3186
|
+
i0[1],
|
|
3187
|
+
z
|
|
3188
|
+
);
|
|
3075
3189
|
}
|
|
3076
|
-
return
|
|
3190
|
+
return vertices;
|
|
3077
3191
|
}
|
|
3078
3192
|
async function load(base, urls) {
|
|
3079
3193
|
let points = await loadPCDCustom(base + "/data/rgb_global_map.pcd");
|
|
@@ -3082,7 +3196,7 @@ async function load(base, urls) {
|
|
|
3082
3196
|
const height = itemsFiles[0].imageSize[1];
|
|
3083
3197
|
return { points, itemsFiles, width, height };
|
|
3084
3198
|
}
|
|
3085
|
-
function getInfo(itemsFile, cindex) {
|
|
3199
|
+
function getInfo(itemsFile, cindex, contractionSize = 10) {
|
|
3086
3200
|
const width = itemsFile.imageSize[0];
|
|
3087
3201
|
const height = itemsFile.imageSize[1];
|
|
3088
3202
|
const T_wi = new THREE.Matrix4();
|
|
@@ -3105,9 +3219,9 @@ function getInfo(itemsFile, cindex) {
|
|
|
3105
3219
|
for (let i = 0; i < itemsFile.sam3Objects.length; i++) {
|
|
3106
3220
|
const item = itemsFile.sam3Objects[i];
|
|
3107
3221
|
const index = cindex * 200 + i + 1;
|
|
3108
|
-
item.coordinates
|
|
3109
|
-
|
|
3110
|
-
|
|
3222
|
+
const { innerPath, outerPath } = ringTriangleGenerator(item.coordinates, contractionSize, 0);
|
|
3223
|
+
const vertices = ringPathsToMesh(outerPath, innerPath, index);
|
|
3224
|
+
itemPosition.push(...vertices);
|
|
3111
3225
|
}
|
|
3112
3226
|
return {
|
|
3113
3227
|
cameraMat,
|
|
@@ -3121,7 +3235,8 @@ async function sopc_(opt) {
|
|
|
3121
3235
|
const {
|
|
3122
3236
|
base,
|
|
3123
3237
|
urls,
|
|
3124
|
-
|
|
3238
|
+
maskSize = 3,
|
|
3239
|
+
contractionSize = 10,
|
|
3125
3240
|
kernelSize = 15,
|
|
3126
3241
|
groundZ = 0
|
|
3127
3242
|
} = opt;
|
|
@@ -3133,14 +3248,14 @@ async function sopc_(opt) {
|
|
|
3133
3248
|
canvasWidth = window.innerWidth ?? canvasWidth;
|
|
3134
3249
|
canvasHeight = window.innerHeight ?? canvasHeight;
|
|
3135
3250
|
}
|
|
3136
|
-
const renderer = new Renderer(canvasWidth, canvasHeight, "rgba8unorm"), camera = new PerspectiveCamera(75, canvasWidth / canvasHeight, 1e-3, 100), { points: pointsArray, itemsFiles, width, height } = await load(base, urls), pointCount = pointsArray.length / 3, pcIndexMaterial = new PointCloudsIndexMaterial(width, height), polyAreaIndexMaterial = new PolyAreaIndexMaterial(width, height),
|
|
3251
|
+
const renderer = new Renderer(canvasWidth, canvasHeight, "rgba8unorm"), camera = new PerspectiveCamera(75, canvasWidth / canvasHeight, 1e-3, 100), { points: pointsArray, itemsFiles, width, height } = await load(base, urls), pointCount = pointsArray.length / 3, pcIndexMaterial = new PointCloudsIndexMaterial(width, height), polyAreaIndexMaterial = new PolyAreaIndexMaterial(width, height), erodeMaskComputeMaterial = new ErodeMaskComputeMaterial(width, height, polyAreaIndexMaterial.resultTexture, maskSize), sopcComputeMaterial = new SOPCComputeMaterial(width, height, pointCount, pcIndexMaterial.resultTexture, kernelSize), points = new Object3D(
|
|
3137
3252
|
new BufferGeometry().setAttribute("position", new THREE.BufferAttribute(pointsArray, 3)),
|
|
3138
3253
|
pcIndexMaterial
|
|
3139
3254
|
), mesh = new Object3D(
|
|
3140
3255
|
new BufferGeometry().setAttribute("position", new THREE.BufferAttribute(new Float32Array(), 3)),
|
|
3141
3256
|
polyAreaIndexMaterial
|
|
3142
3257
|
);
|
|
3143
|
-
camera.position.set(1, 1,
|
|
3258
|
+
camera.position.set(1, 1, 10);
|
|
3144
3259
|
pcIndexMaterial.groundZ = groundZ;
|
|
3145
3260
|
console.log("文件加载耗时:", performance.now() - t);
|
|
3146
3261
|
t = performance.now();
|
|
@@ -3150,7 +3265,7 @@ async function sopc_(opt) {
|
|
|
3150
3265
|
console.log("第" + i + "个没有物品");
|
|
3151
3266
|
continue;
|
|
3152
3267
|
}
|
|
3153
|
-
const { T_cw, cameraMat, itemPosition } = getInfo(itemsFile, i);
|
|
3268
|
+
const { T_cw, cameraMat, itemPosition } = getInfo(itemsFile, i, contractionSize);
|
|
3154
3269
|
mesh.geometry.setAttribute("position", new THREE.BufferAttribute(itemPosition, 3));
|
|
3155
3270
|
pcIndexMaterial.T_cw = T_cw;
|
|
3156
3271
|
pcIndexMaterial.cameraMat = cameraMat;
|
|
@@ -3161,9 +3276,9 @@ async function sopc_(opt) {
|
|
|
3161
3276
|
renderer.renderTarget = polyAreaIndexMaterial.resultTexture.view;
|
|
3162
3277
|
renderer.depthTarget = polyAreaIndexMaterial.resultTexture.depthView;
|
|
3163
3278
|
renderer.render([mesh], camera);
|
|
3164
|
-
renderer.compute(
|
|
3279
|
+
renderer.compute(erodeMaskComputeMaterial);
|
|
3165
3280
|
sopcComputeMaterial.setStorageBuffer("pcDepth", pcIndexMaterial.getStorageBuffer("depth"));
|
|
3166
|
-
sopcComputeMaterial.setStorageBuffer("polyAreaIndex",
|
|
3281
|
+
sopcComputeMaterial.setStorageBuffer("polyAreaIndex", erodeMaskComputeMaterial.getStorageBuffer("result"));
|
|
3167
3282
|
renderer.compute(sopcComputeMaterial);
|
|
3168
3283
|
}
|
|
3169
3284
|
const resultsBuffer = await readGPUBuffer(sopcComputeMaterial.getStorageBuffer("result"), pointCount * 4, Uint32Array);
|
|
@@ -3184,13 +3299,19 @@ async function sopc_(opt) {
|
|
|
3184
3299
|
}
|
|
3185
3300
|
const results = Array.from({ length: itemsFiles.length }, () => []);
|
|
3186
3301
|
const sort = (pointarr) => {
|
|
3187
|
-
let list = euclideanClusterExtraction(pointarr, 0.
|
|
3302
|
+
let list = euclideanClusterExtraction(pointarr, 0.2).sort((a, b) => b.length - a.length);
|
|
3188
3303
|
if (list.length === 1) return pointarr;
|
|
3189
|
-
|
|
3304
|
+
const maxCount = list[0].length;
|
|
3305
|
+
list = list.filter((item) => item.length > 4 && item.length / maxCount > 0.3);
|
|
3306
|
+
list = list.map((item) => item.flatMap((i) => [
|
|
3190
3307
|
pointarr[i * 3],
|
|
3191
3308
|
pointarr[i * 3 + 1],
|
|
3192
3309
|
pointarr[i * 3 + 2]
|
|
3193
|
-
]);
|
|
3310
|
+
]));
|
|
3311
|
+
const centers = list.map((item) => getPointsCenter(item));
|
|
3312
|
+
const maxCenter = centers[0];
|
|
3313
|
+
const distList = centers.map((center) => getPointDistance(center, maxCenter));
|
|
3314
|
+
return list.filter((_, i) => distList[i] < 0.4).flat();
|
|
3194
3315
|
};
|
|
3195
3316
|
map.forEach((arrMap, fileIndex) => {
|
|
3196
3317
|
arrMap.forEach((pointIndexs, itemIndex) => {
|