Skip to content

Commit

Permalink
feat(pointcloud): adding the logic of switching annotation tools in p…
Browse files Browse the repository at this point in the history
…ointcloud
  • Loading branch information
wanghaiqing committed Mar 28, 2023
1 parent c0fd13d commit 6da4153
Show file tree
Hide file tree
Showing 14 changed files with 158 additions and 45 deletions.
3 changes: 3 additions & 0 deletions packages/lb-annotation/src/constant/tool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ export enum EToolName {
OCRRelation = 'OCRRelationTool',
/** 算法分割辅助工具 */
SegmentByRect = 'segmentByRectTool',
/** 点云多边形工具 */
PointCloudPolygon = 'pointCloudPolygon',
}

export enum ECheckModel {
Expand All @@ -71,6 +73,7 @@ export enum ERectPattern {
}

export type ToolName = EToolName | EVideoToolName | EPointCloudName;
export type THybridToolName = EToolName | Array<EToolName>;

export const TOOL_NAME: { [a: string]: string } = {
[EToolName.Rect]: '拉框',
Expand Down
4 changes: 2 additions & 2 deletions packages/lb-annotation/src/core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

import { ELang } from '@/constant/annotation';
import { getConfig, styleDefaultConfig } from '@/constant/defaultConfig';
import { EToolName } from '@/constant/tool';
import { EToolName, THybridToolName } from '@/constant/tool';
import { IPolygonData } from '@/types/tool/polygon';
import { HybridToolUtils, THybridToolName, ToolScheduler } from './scheduler';
import { HybridToolUtils, ToolScheduler } from './scheduler';

interface IProps {
container: HTMLElement;
Expand Down
89 changes: 71 additions & 18 deletions packages/lb-annotation/src/core/pointCloud/annotation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@
* @author Ron <[email protected]>
*/

import { IPointCloudBox, PointCloudUtils, IPointCloudConfig } from '@labelbee/lb-utils';
import { EPolygonPattern } from '@/constant/tool';
import { IPointCloudBox, IPointCloudConfig, PointCloudUtils } from '@labelbee/lb-utils';
import { EPolygonPattern, EToolName, THybridToolName } from '@/constant/tool';
import { CanvasScheduler } from '@/newCore';
import { IPolygonData } from '@/types/tool/polygon';
import { IPolygonData, IPolygonPoint } from '@/types/tool/polygon';
import { PointCloud } from '.';
import PointCloud2dOperation, { IPointCloud2dOperationProps } from '../toolOperation/pointCloud2dOperation';
import { HybridToolUtils, ToolScheduler } from '../scheduler';

interface IPointCloudAnnotationOperation {
updateData: (pcdPath: string, result: string) => void;
Expand All @@ -25,6 +26,7 @@ interface IPointCloudAnnotationProps {
config: IPointCloudConfig;

checkMode?: boolean;
toolName: THybridToolName;
}

const createEmptyImage = (size: { width: number; height: number }) => {
Expand All @@ -43,19 +45,33 @@ const createEmptyImage = (size: { width: number; height: number }) => {
export class PointCloudAnnotation implements IPointCloudAnnotationOperation {
public pointCloudInstance: PointCloud;

public pointCloud2dOperation: PointCloud2dOperation;
public pointCloud2dOperation!: PointCloud2dOperation;

public canvasScheduler: CanvasScheduler;

public toolScheduler: ToolScheduler;

public toolInstance: any; // 用于存储当前工具实例

public config: IPointCloudConfig;

constructor({ size, container, pcdPath, polygonOperationProps, config, checkMode }: IPointCloudAnnotationProps) {
constructor({
size,
container,
pcdPath,
polygonOperationProps,
config,
checkMode,
toolName,
}: IPointCloudAnnotationProps) {
const defaultOrthographic = this.getDefaultOrthographic(size);

const imgSrc = createEmptyImage(size);

const image = new Image();
image.src = imgSrc;

const toolScheduler = new ToolScheduler({ container, size, toolName });
const canvasScheduler = new CanvasScheduler({ container });

// 1. PointCloud initialization
Expand All @@ -73,11 +89,9 @@ export class PointCloudAnnotation implements IPointCloudAnnotationOperation {

// 2. PointCloud2dOperation initialization
const defaultPolygonProps = {
container,
size,
config: JSON.stringify(config),
imgNode: image,
isAppend: false,
checkMode,
// forbidOperation: true,
// forbidOperation: !!checkMode,
Expand All @@ -86,17 +100,39 @@ export class PointCloudAnnotation implements IPointCloudAnnotationOperation {
Object.assign(defaultPolygonProps, polygonOperationProps);
}

const polygonOperation = new PointCloud2dOperation(defaultPolygonProps);
// init operations
let toolList: EToolName[] = [];

polygonOperation.eventBinding();
polygonOperation.setPattern(EPolygonPattern.Rect);

canvasScheduler.createCanvas(polygonOperation.canvas, { size });
if (HybridToolUtils.isSingleTool(toolName)) {
toolList = [toolName] as EToolName[];
} else {
toolList = toolName as EToolName[];
}
toolList.forEach((tool, i) => {
let toolInstance;
if (tool === EToolName.PointCloudPolygon) {
const pointCloudPolygonOperation = toolScheduler.createOperation(tool, image, defaultPolygonProps);
pointCloudPolygonOperation.eventBinding();
pointCloudPolygonOperation.setPattern(EPolygonPattern.Rect);
this.toolInstance = pointCloudPolygonOperation;
this.toolInstance.eventBinding();
this.pointCloud2dOperation = pointCloudPolygonOperation;
} else {
toolInstance = toolScheduler.createOperation(tool, image, config);
}
if (i === toolList.length - 1) {
if (!this.toolInstance) {
this.toolInstance = toolInstance;
this.toolInstance.eventBinding();
}
// The last one by default is the topmost operation.
}
});

// 3. Data record
this.pointCloud2dOperation = polygonOperation;
this.pointCloudInstance = pointCloud;
this.canvasScheduler = canvasScheduler;
this.toolScheduler = toolScheduler;

this.config = config;
}
Expand Down Expand Up @@ -150,8 +186,11 @@ export class PointCloudAnnotation implements IPointCloudAnnotationOperation {
* Notice. It needs to update polygon if it shows polygon.
* (Like `ptCtx.topViewInstance.updatePolygonList(ptCtx.pointCloudBoxList);`)
*/
this.pointCloud2dOperation.setImgNode(image);
this.pointCloud2dOperation.initImgPos();
this.toolInstance.setImgNode(image);
this.toolInstance.initImgPos();

// this.pointCloud2dOperation.setImgNode(image);
// this.pointCloud2dOperation.initImgPos();
};

// It need to update directly
Expand All @@ -166,7 +205,7 @@ export class PointCloudAnnotation implements IPointCloudAnnotationOperation {
}

public updatePolygonList = (pointCloudDataList: IPointCloudBox[], extraList?: IPolygonData[]) => {
let polygonList = pointCloudDataList.map((v) => {
let polygonList = pointCloudDataList.map((v: IPointCloudBox) => {
const { polygon2d: pointList } = this.pointCloudInstance.getBoxTopPolygon2DCoordinate(v);
return {
id: v.id,
Expand All @@ -181,9 +220,9 @@ export class PointCloudAnnotation implements IPointCloudAnnotationOperation {
if (extraList) {
// Convert extraList(polygonList) from PointCloud coordinate to Canvas Coordinate
polygonList = polygonList.concat(
extraList.map((v) => ({
extraList.map((v: IPolygonData) => ({
...v,
pointList: v?.pointList?.map((point) =>
pointList: v?.pointList?.map((point: IPolygonPoint) =>
PointCloudUtils.transferWorld2Canvas(point, this.pointCloud2dOperation.size),
),
})),
Expand All @@ -208,6 +247,20 @@ export class PointCloudAnnotation implements IPointCloudAnnotationOperation {
this.addPolygonListOnTopView(result);
}

/**
* switch to chosen canvas。
*
*/
public switchToCanvas(toolName: EToolName) {
const newInstance = this.toolScheduler.switchToCanvas(toolName);
if (newInstance) {
newInstance.eventBinding();
this.toolInstance = newInstance;
return newInstance;
}
return this.toolInstance;
}

/**
* Init All Position
* 1. PointCloud camera change to topView
Expand Down
42 changes: 38 additions & 4 deletions packages/lb-annotation/src/core/scheduler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,13 @@
*/

import { getConfig, styleDefaultConfig } from '@/constant/defaultConfig';
import { EToolName } from '@/constant/tool';
import { EToolName, THybridToolName } from '@/constant/tool';
import { getCurrentOperation } from '@/utils/tool/EnhanceCommonToolUtils';
import { RectOperation } from './toolOperation/rectOperation';
import PolygonOperation from './toolOperation/polygonOperation';
import { BasicToolOperation } from './toolOperation/basicToolOperation';
import SegmentByRect from './toolOperation/segmentByRect';

export type THybridToolName = EToolName | Array<EToolName>;

interface IToolSchedulerOperation {}

interface IToolSchedulerProps {
Expand Down Expand Up @@ -71,6 +69,8 @@ export class ToolScheduler implements IToolSchedulerOperation {

private toolOperationDom: Array<HTMLElement> = [];

private toolOperationNameList: Array<EToolName> = [];

private size: ISize;

private config: string; // 定义 TODO!!
Expand Down Expand Up @@ -143,7 +143,6 @@ export class ToolScheduler implements IToolSchedulerOperation {
dom.style.height = `${height}px`;
const zIndex = this.toolOperationList.length + 1;
dom.style.zIndex = `${zIndex}`;

return dom;
}

Expand Down Expand Up @@ -221,6 +220,7 @@ export class ToolScheduler implements IToolSchedulerOperation {
this.container.appendChild(dom);

this.toolOperationList.push(toolInstance);
this.toolOperationNameList.push(tool);
this.toolOperationDom.push(dom);

return toolInstance;
Expand Down Expand Up @@ -278,6 +278,40 @@ export class ToolScheduler implements IToolSchedulerOperation {
return this.toolOperationList[0];
}

/**
* switch to canvas by given toolName
* TODO: change operationList to operationMap
*/
public switchToCanvas(toolName: EToolName) {
const chosenIndex = this.toolOperationNameList.indexOf(toolName);
if (chosenIndex < 0 || this.toolOperationList.length < 1 || chosenIndex > this.toolOperationDom.length - 1) {
return;
}
const lastOneIndex = this.toolOperationDom.length - 1;
const chosenDom = this.toolOperationDom[chosenIndex];
const lastOneDom = this.toolOperationDom[lastOneIndex];

if (!chosenDom || !lastOneDom) {
return;
}

const temp = lastOneDom.style.zIndex;
lastOneDom.style.zIndex = `${chosenDom.style.zIndex}`;
chosenDom.style.zIndex = `${temp}`;

// The original top-level operation clears the data
this.toolOperationList[lastOneIndex].clearActiveStatus?.();
this.toolOperationList[lastOneIndex].clearCursorLine?.();
this.toolOperationList[lastOneIndex].render();

// swap
this.toolOperationList = arraySwap(this.toolOperationList, lastOneIndex, chosenIndex);
this.toolOperationDom = arraySwap(this.toolOperationDom, lastOneIndex, chosenIndex);
this.toolOperationNameList = arraySwap(this.toolOperationNameList, lastOneIndex, chosenIndex);

return this.toolOperationList[lastOneIndex];
}

public destroyAllLayer() {
this.toolOperationList.forEach((toolInstance) => {
toolInstance.destroyCanvas();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import { ECheckModel, EToolName } from '@/constant/tool';
import ScribbleTool from '@/core/toolOperation/ScribbleTool';
import PointCloud2dOperation from '@/core/toolOperation/pointCloud2dOperation';
import CheckOperation from '../../core/toolOperation/checkOperation';
import PolygonOperation from '../../core/toolOperation/polygonOperation';
import RectOperationAsNewName from '../../core/toolOperation/rectOperation';
Expand Down Expand Up @@ -37,6 +38,8 @@ const getCurrentOperation = (toolName: EToolName | ECheckModel) => {
return TextToolOperation;
case EToolName.ScribbleTool:
return ScribbleTool;
case EToolName.PointCloudPolygon:
return PointCloud2dOperation;
default:
throw new Error('not match tool');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
MathUtils,
PointCloud,
PointCloudAnnotation,
THybridToolName,
} from '@labelbee/lb-annotation';
import { getClassName } from '@/utils/dom';
import { PointCloudContainer } from './PointCloudLayout';
Expand All @@ -34,6 +35,7 @@ import useSize from '@/hooks/useSize';
import EmptyPage from './components/EmptyPage';
import { useTranslation } from 'react-i18next';
import { LabelBeeContext } from '@/store/ctx';
import ToolUtils from '@/utils/ToolUtils';

/**
* 统一一下,将其拓展为 二维转换为 三维坐标的转换
Expand Down Expand Up @@ -185,6 +187,7 @@ const PointCloudSideView = ({ currentData, config, checkMode }: IA2MapStateProps
polygonOperationProps: { showDirectionLine: false, forbidAddNew: true },
config,
checkMode,
toolName: ToolUtils.getPointCloudToolList() as THybridToolName,
});
ptCtx.setBackViewInstance(pointCloudAnnotation);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ export interface IPointCloudContext extends IPointCloudContextInstances {
defaultAttribute: string;
setDefaultAttribute: (defaultAttribute: string) => void;

pointCloudPattern: EToolName.Rect | EToolName.Polygon;
setPointCloudPattern: (toolName: EToolName.Rect | EToolName.Polygon) => void;
pointCloudPattern: EToolName.Rect | EToolName.Polygon | EToolName.Point | EToolName.Line;
setPointCloudPattern: (toolName: EToolName.Rect | EToolName.Polygon | EToolName.Point | EToolName.Line) => void;
}

export const PointCloudContext = React.createContext<IPointCloudContext>({
Expand Down Expand Up @@ -107,7 +107,7 @@ export const PointCloudProvider: React.FC<{}> = ({ children }) => {
const [backViewInstance, setBackViewInstance] = useState<PointCloudAnnotation>();
const [mainViewInstance, setMainViewInstance] = useState<PointCloud>();
const [defaultAttribute, setDefaultAttribute] = useState('');
const [pointCloudPattern, setPointCloudPattern] = useState<EToolName.Rect | EToolName.Polygon>(
const [pointCloudPattern, setPointCloudPattern] = useState<EToolName.Rect | EToolName.Polygon | EToolName.Point | EToolName.Line>(
EToolName.Rect,
);
const history = useRef(new ActionsHistory()).current;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* @createdate 2022-07-11
* @author Ron <[email protected]>
*/
import { PointCloud, PointCloudAnnotation } from '@labelbee/lb-annotation';
import { PointCloud, PointCloudAnnotation, THybridToolName } from '@labelbee/lb-annotation';
import { getClassName } from '@/utils/dom';
import { PointCloudContainer } from './PointCloudLayout';
import React, { useEffect, useRef } from 'react';
Expand All @@ -18,6 +18,8 @@ import EmptyPage from './components/EmptyPage';
import useSize from '@/hooks/useSize';
import { useTranslation } from 'react-i18next';
import { LabelBeeContext } from '@/store/ctx';
import ToolUtils from '@/utils/ToolUtils';

/**
* Get the offset from canvas2d-coordinate to world coordinate
* @param currentPos
Expand Down Expand Up @@ -93,7 +95,8 @@ const PointCloudSideView: React.FC<IA2MapStateProps & IProps> = ({ config, check
size,
polygonOperationProps: { showDirectionLine: false, forbidAddNew: true },
config,
checkMode
checkMode,
toolName: ToolUtils.getPointCloudToolList() as THybridToolName,
});
ptCtx.setSideViewInstance(pointCloudAnnotation);
// };
Expand Down
Loading

0 comments on commit 6da4153

Please sign in to comment.