Skip to content

Commit

Permalink
feat(lb-annotation): Fix issues in calculatePointsInsideBox
Browse files Browse the repository at this point in the history
  • Loading branch information
lihqi committed Dec 1, 2023
1 parent aa804c9 commit 2bbacfa
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 93 deletions.
24 changes: 11 additions & 13 deletions packages/lb-annotation/src/core/pointCloud/cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ type TCacheInfo = {
src: string;
};

const generateIndexWorker = new GenerateIndexWorker({ type: 'module' });
export type TIndexMap = Map<string, { x: number; y: number; z: number }[]>;

export class PointCloudCache {
public pcdLoader: PCDLoader;
Expand All @@ -23,7 +23,7 @@ export class PointCloudCache {

private colorMap: Map<string, Float32Array>;

private cacheIndexMap: Map<string, Map<string, { x: number; y: number; z: number }[]>>;
private cacheIndexMap: Map<string, TIndexMap>;

private cacheList: Array<TCacheInfo> = [];

Expand Down Expand Up @@ -103,24 +103,21 @@ export class PointCloudCache {
}

/**
* Asynchronously loads an index map from a given source.
* If the index map is already cached, it returns the cached version.
* Otherwise, it creates a new worker to generate the index map,
* caches it for future use, and then returns it.
* Loads index map from cache or generates it in a worker.
*
* @param {string} src - The source from which to load the index map.
* @param {Float32Array} points - The points to be used in generating the index map.
* @returns {Promise} - A promise that resolves to the loaded index map.
* @param src The path to the source image.
* @param points The points of the source image.
* @returns A promise that resolves to the index map.
*/
public loadIndexMap = async (src: string, points: Float32Array) => {
const currentCacheIndexMap = this.cacheIndexMap.get(src);

if (currentCacheIndexMap) {
return currentCacheIndexMap;
}

return new Promise((resolve) => {
if (currentCacheIndexMap) {
return resolve(currentCacheIndexMap);
}
if (window.Worker) {
const generateIndexWorker = new GenerateIndexWorker({ type: 'module' });
generateIndexWorker.postMessage({
points,
});
Expand All @@ -129,6 +126,7 @@ export class PointCloudCache {
const { indexMap } = e.data;
this.cacheIndexMap.set(src, indexMap);
resolve(indexMap);
generateIndexWorker.terminate();
};
}
});
Expand Down
24 changes: 13 additions & 11 deletions packages/lb-annotation/src/core/pointCloud/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import MathUtils from '@/utils/MathUtils';
import ImgUtils from '@/utils/ImgUtils';
import { PCDLoader } from './PCDLoader';
import { OrbitControls } from './OrbitControls';
import { PointCloudCache } from './cache';
import { PointCloudCache, TIndexMap } from './cache';
import { getCuboidFromPointCloudBox, getHighlightIndexByPoints, mergeHighlightList } from './matrix';
import { PointCloudSegmentOperation } from './segmentation';
import PointCloudStore from './store';
Expand Down Expand Up @@ -1013,19 +1013,21 @@ export class PointCloud extends EventListener {
return mergeList;
};

public filterPreResult = async (src: string, config: any, boxParamsList: any) => {
public filterPreResult = async (src: string, config: any, boxParamsList: IPointCloudBox[]) => {
const { points } = await this.cacheInstance.loadPCDFile(src);
const indexMap = await this.cacheInstance.loadIndexMap(src, points as Float32Array);
const indexMap = (await this.cacheInstance.loadIndexMap(src, points as Float32Array)) as TIndexMap;

return new Promise((resolve) => {
const boxes = boxParamsList.map((boxParams: any) => {
const newBox = MathUtils.calculatePointsInsideBox(
indexMap as Map<string, { x: number; y: number; z: number }[]>,
boxParams,
);

const valid = newBox.count > config.lowerLimitPointsNumInBox;
return { ...newBox, valid };
const boxes = boxParamsList.map((boxParams: IPointCloudBox) => {
const count = MathUtils.calculatePointsInsideBox({
indexMap,
polygon: getCuboidFromPointCloudBox(boxParams).polygonPointList as IPolygonPoint[],
zScope: [boxParams.center.z - boxParams.depth / 2, boxParams.center.z + boxParams.depth / 2],
box: boxParams,
});
const valid = count >= config.lowerLimitPointsNumInBox;

return { ...boxParams, valid, count };
});
resolve(boxes);
});
Expand Down
92 changes: 26 additions & 66 deletions packages/lb-annotation/src/utils/MathUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@

// eslint-disable-next-line
import MathUtilsWorker from 'web-worker:./MathUtilsWorker.js';
import { IBasicLine, IBasicPoint, IPointCloudBox, TAnnotationViewData } from '@labelbee/lb-utils';
import { I3DSpaceCoord, IBasicLine, IBasicPoint, IPointCloudBox, TAnnotationViewData } from '@labelbee/lb-utils';
import { DEFAULT_FONT, DEFAULT_TEXT_MAX_WIDTH, ELineTypes, SEGMENT_NUMBER } from '@/constant/tool';
import { IPolygonData, IPolygonPoint } from '@/types/tool/polygon';
import { TIndexMap } from '@/core/pointCloud/cache';
import { createSmoothCurvePointsFromPointList, isInPolygon } from './tool/polygonTool';
import PolygonUtils from './tool/PolygonUtils';
import Vector from './VectorUtils';
Expand All @@ -33,9 +34,9 @@ enum CubePosition {
FullyInside = 2,
}

function getCubePosition(bigCube: Cube, smallCube: Cube): CubePosition {
function getCubePosition(polygon: IPolygonPoint[], zScope: [number, number], smallCube: Cube): CubePosition {
// 计算小立方体的8个顶点
const smallCubeVertices: Point[] = [
const smallCubeVertices: I3DSpaceCoord[] = [
{
x: smallCube.x - smallCube.width / 2,
y: smallCube.y - smallCube.height / 2,
Expand Down Expand Up @@ -82,7 +83,7 @@ function getCubePosition(bigCube: Cube, smallCube: Cube): CubePosition {
let insideCount = 0;
for (let i = 0; i < smallCubeVertices.length; i++) {
// eslint-disable-next-line
if (MathUtils.isPointInsideCube(smallCubeVertices[i], bigCube)) {
if (MathUtils.isPointInsideCube(smallCubeVertices[i], polygon, zScope)) {
insideCount++;
}
}
Expand All @@ -97,12 +98,6 @@ function getCubePosition(bigCube: Cube, smallCube: Cube): CubePosition {
return CubePosition.PartiallyInside; // 部分顶点在大立方体内,部分顶点在大立方体外
}

interface Point {
x: number;
y: number;
z: number;
}

interface Cube {
x: number;
y: number;
Expand All @@ -112,6 +107,13 @@ interface Cube {
depth: number;
}

interface ICalculatePointsInsideBoxParams {
indexMap: TIndexMap;
polygon: IPolygonPoint[];
zScope: [number, number];
box: IPointCloudBox;
}

export default class MathUtils {
/**
* 是否在指定范围内
Expand Down Expand Up @@ -739,21 +741,8 @@ export default class MathUtils {
return [fixedPoint, newSecondPoint, newThirdPoint, newFourthPoint];
}

public static calculatePointsInsideBox = (
indexMap: Map<string, { x: number; y: number; z: number }[]>,
box: IPointCloudBox,
) => {
const { center, width, height, depth } = box;
const { x, y, z } = center;

const boxCube = {
x,
y,
z,
width,
height,
depth,
};
public static calculatePointsInsideBox = (params: ICalculatePointsInsideBoxParams) => {
const { indexMap, polygon, zScope, box } = params;

let count = 0;

Expand All @@ -763,63 +752,34 @@ export default class MathUtils {
const cubicY = Number(keyArr[1]);
const cubicZ = Number(keyArr[2]);

const cubePosition = getCubePosition(boxCube, {
x: cubicX - 0.5,
y: cubicY - 0.5,
z: cubicZ - 0.5,
width: 1,
height: 1,
depth: 1,
});
const smallCube = { x: cubicX - 0.5, y: cubicY - 0.5, z: cubicZ - 0.5, width: 1, height: 1, depth: 1 };

const cubePosition = getCubePosition(polygon, zScope, smallCube);

if (cubePosition === CubePosition.FullyInside) {
count += point.length;
}

if (cubePosition === CubePosition.PartiallyInside) {
if (
cubePosition === CubePosition.PartiallyInside ||
(cubePosition === CubePosition.Outside && (box.width <= 1 || box.height <= 1))
) {
point.forEach((p) => {
if (MathUtils.isPointInsideCube(p, boxCube)) {
if (MathUtils.isPointInsideCube(p, polygon, zScope)) {
count++;
}
});
}
});

return { ...box, count };
return count;
};

public static isPointInsideCube(point: Point, cube: Cube): boolean {
const halfWidth = cube.width / 2;
const halfHeight = cube.height / 2;
const halfDepth = cube.depth / 2;

const xMin = cube.x - halfWidth;
const xMax = cube.x + halfWidth;
const yMin = cube.y - halfHeight;
const yMax = cube.y + halfHeight;
const zMin = cube.z - halfDepth;
const zMax = cube.z + halfDepth;

const polygon = [
{
x: xMin,
y: yMin,
},
{
x: xMax,
y: yMin,
},
{
x: xMax,
y: yMax,
},
{
x: xMin,
y: yMax,
},
];
public static isPointInsideCube(point: I3DSpaceCoord, polygon: IPolygonPoint[], zScope: [number, number]): boolean {
const [zMin, zMax] = zScope;

const inPolygon = isInPolygon({ x: point.x, y: point.y }, polygon);

if (inPolygon && point.z >= zMin && point.z <= zMax) {
return true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@ import {
SetPointCloudLoading,
SetLoadPCDFileLoading,
} from '@/store/annotation/actionCreators';
import { message } from 'antd';
import { useTranslation } from 'react-i18next';
import { useHistory } from './useHistory';
import { usePolygon } from './usePolygon';
import { IFileItem, IMappingImg } from '@/types/data';
Expand Down Expand Up @@ -654,7 +652,6 @@ export const usePointCloudViews = () => {
const { selectedBox, updateSelectedBox, updateSelectedBoxes, getPointCloudByID } = useSingleBox({
generateRects,
});
const { t } = useTranslation();

const selectedPointCloudBox = selectedBox?.info;

Expand Down

0 comments on commit 2bbacfa

Please sign in to comment.