Skip to content

Commit

Permalink
Merge pull request #565 from Original-Recipe/feat-topViewVisibleOptimize
Browse files Browse the repository at this point in the history
feat: Select the top view frame to display logic optimization
  • Loading branch information
lihqi authored Sep 23, 2024
2 parents dac900b + e332591 commit edc8c90
Show file tree
Hide file tree
Showing 11 changed files with 175 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,23 @@ import { IPointCloud2DRectOperationViewRect } from '@labelbee/lb-utils';
import EKeyCode from '@/constant/keyCode';
import { RectOperation } from './rectOperation';
import reCalcRect from './utils/reCalcRect';
import AxisUtils from '@/utils/tool/AxisUtils';

class PointCloud2DRectOperation extends RectOperation {
// Whether it is in check mode
public checkMode?: Boolean;

public highLightRectList: IRect[] = [];

constructor(props: any) {
super(props);
this.checkMode = props.checkMode;
this.highLightRectList = [];
}

// Set highlighted point cloud 2D rectangular box list
public setHighLightRectList(rectList: IRect[]) {
this.highLightRectList = rectList;
}

// Disable creating new rect in checkMode
Expand Down Expand Up @@ -83,11 +92,40 @@ class PointCloud2DRectOperation extends RectOperation {
return true;
}

public renderDrawingRect(rect: IPointCloud2DRectOperationViewRect & IRect, zoom = this.zoom, isZoom = false) {
public renderDrawingRect(
rect: IPointCloud2DRectOperationViewRect & IRect,
zoom = this.zoom,
isZoom = false,
isPointCloud2DHighlight = false,
) {
// 是否使用强制默认值,如: lineDash: [3]
const shouldNotUseForceValue = rect?.boxID || rect?.lineDash;

super.renderDrawingRect(shouldNotUseForceValue ? rect : { ...rect, lineDash: [3] }, zoom, isZoom);
super.renderDrawingRect(
shouldNotUseForceValue ? rect : { ...rect, lineDash: [3] },
zoom,
isZoom,
isPointCloud2DHighlight,
);
}

// The rendering function actually triggers the rendering of the parent class in the end
public renderPointCloud2DHighlight(): void {
const { renderEnhance = {} } = this;

if (this.highLightRectList) {
this.highLightRectList.forEach((rect: IRect) => {
this.renderDrawingRect(rect as IPointCloud2DRectOperationViewRect & IRect, this.zoom, false, true);

if (renderEnhance.selectedRender) {
renderEnhance.selectedRender(
this.canvas,
AxisUtils.changeRectByZoom(rect, this.zoom, this.currentPos),
this.getRenderStyle(rect),
);
}
});
}
}

/*
Expand Down
10 changes: 8 additions & 2 deletions packages/lb-annotation/src/core/toolOperation/rectOperation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ class RectOperation extends BasicToolOperation {
/** Whether or not add rect */
private enableAddRect = true;

public renderPointCloud2DHighlight(): void {}

constructor(props: IRectOperationProps) {
super(props);
this._drawOutSideTarget = props.drawOutSideTarget || false;
Expand Down Expand Up @@ -1646,7 +1648,7 @@ class RectOperation extends BasicToolOperation {
* @param zoom 缩放比例
* @param isZoom 是否进行缩放
*/
public renderDrawingRect(rect: IRect, zoom = this.zoom, isZoom = false) {
public renderDrawingRect(rect: IRect, zoom = this.zoom, isZoom = false, isPointCloud2DHighlight = false) {
if (this.ctx && rect) {
const { ctx, style } = this;
// 不看图形信息
Expand Down Expand Up @@ -1715,7 +1717,8 @@ class RectOperation extends BasicToolOperation {
// 高亮同textAttribute 的其他框
isSameTextAttribute ||
rect.id === this.selectedRectID ||
this.isMultiMoveMode
this.isMultiMoveMode ||
isPointCloud2DHighlight
) {
DrawUtils.drawRectWithFill(this.canvas, transformRect, { color: fillColor });
}
Expand Down Expand Up @@ -1817,6 +1820,9 @@ class RectOperation extends BasicToolOperation {
}
});
}

// After selecting the top view, it is necessary to highlight the 2D box of the corresponding 2D view
this.renderPointCloud2DHighlight();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { useUpdateRectList } from './useUpdateRectList';
import { TAfterImgOnLoad } from '../AnnotationView';
import _ from 'lodash';
import { useToolStyleContext } from '@/hooks/useToolStyle';
import useToolConfigStore from '@/store/toolConfig';

interface IPointCloud2DRectOperationViewProps {
mappingData?: IMappingImg;
Expand All @@ -50,6 +51,7 @@ const PointCloud2DRectOperationView = (props: IPointCloud2DRectOperationViewProp
afterImgOnLoad,
shouldExcludePointCloudBoxListUpdate,
} = props;
const { selectBoxVisibleSwitch } = useToolConfigStore();

const imageUrl = mappingData?.url ?? '';
const fallbackUrl = mappingData?.fallbackUrl ?? '';
Expand Down Expand Up @@ -217,12 +219,29 @@ const PointCloud2DRectOperationView = (props: IPointCloud2DRectOperationViewProp

// Case 2: Only show the selected ids
const clonedSelectedIDs = selectedIDs.slice(0);
const img2dResult = selectSpecifiedRectsFromTopViewSelectedIds(
clonedSelectedIDs,
rectListByBoxList,
rectListInImage,
);
const img2dResult = selectBoxVisibleSwitch
? selectSpecifiedRectsFromTopViewSelectedIds(
clonedSelectedIDs,
rectListByBoxList,
rectListInImage,
)
: [...rectListByBoxList, ...rectListInImage];

let highLightList: any = [];

// When the switch is turned off, highlight the 2D box of the corresponding 2D view in the selected top-down view
if (!selectBoxVisibleSwitch && selectedIDs?.length) {
highLightList = rectListByBoxList.filter((item) => {
// When selecting a rectangle, filter out the selected rectangle
if (selectedRectID) {
return selectedIDs.includes(item.boxID) && !selectedRectID.includes(item.boxID);
} else {
return selectedIDs.includes(item.boxID);
}
});
}

operation.current?.setHighLightRectList(highLightList);
operation.current?.setResult(img2dResult);
if (rightClickRectId) {
operation.current?.setSelectedRectID(rightClickRectId);
Expand Down Expand Up @@ -381,6 +400,10 @@ const PointCloud2DRectOperationView = (props: IPointCloud2DRectOperationViewProp
instance.setStyle(newStyle);
}, [toolStyle]);

useEffect(() => {
updateRectList();
}, [selectBoxVisibleSwitch]);

return (
<Spin spinning={loading}>
<div ref={ref} style={{ position: 'relative', ...size }} />
Expand Down
9 changes: 9 additions & 0 deletions packages/lb-components/src/store/toolConfig/baseToolConfig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { StateCreator } from 'zustand';
import { BaseStore } from './types';

const baseToolStateCreator: StateCreator<BaseStore> = (set, get) => ({
onlyLoadFirstData: false,
setOnlyLoadFirstData: (onlyLoadFirstData) => set((state) => ({ onlyLoadFirstData })),
});

export default baseToolStateCreator;
14 changes: 6 additions & 8 deletions packages/lb-components/src/store/toolConfig/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import { create } from 'zustand';
import { ToolConfigStore } from './types';
import baseToolStateCreator from './baseToolConfig';
import pointCloudToolStateCreator from './pointCloudToolConfig';

interface toolConfigStore {
onlyLoadFirstData: boolean;
setOnlyLoadFirstData: (onlyLoadFirstData: boolean) => void;
}

const useToolConfigStore = create<toolConfigStore>((set) => ({
onlyLoadFirstData: false,
setOnlyLoadFirstData: (onlyLoadFirstData) => set((state) => ({ onlyLoadFirstData })),
const useToolConfigStore = create<ToolConfigStore>((set, get, api) => ({
...baseToolStateCreator(set, get, api),
...pointCloudToolStateCreator(set, get, api),
}));

export default useToolConfigStore;
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { StateCreator } from 'zustand';
import { PointCloudToolConfigStore } from './types';

const pointCloudToolStateCreator: StateCreator<PointCloudToolConfigStore> = (set, get) => ({
selectBoxVisibleSwitch: false,
setSelectBoxVisibleSwitch: (selectBoxVisibleSwitch: boolean) =>
set(() => ({ selectBoxVisibleSwitch })),
});

export default pointCloudToolStateCreator;
14 changes: 14 additions & 0 deletions packages/lb-components/src/store/toolConfig/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Define basic generic types that will be used by all state modules
export interface BaseStore {
onlyLoadFirstData: boolean;
setOnlyLoadFirstData: (onlyLoadFirstData: boolean) => void;
}

// Define point cloud type: PointCloudToolConfig Store
export interface PointCloudToolConfigStore {
selectBoxVisibleSwitch: boolean;
setSelectBoxVisibleSwitch: (selectBoxVisibleSwitch: boolean) => void;
}

// Import all types into toolConfig Store through inheritance
export interface ToolConfigStore extends BaseStore, PointCloudToolConfigStore {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
.switchBox{
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 20px;
}

.switchLeft{
display: flex;
align-items: center;
}

.switchTitle{
margin-right: 8px;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React, { useEffect } from 'react';
import { Switch, Tooltip } from 'antd';
import useToolConfigStore from '@/store/toolConfig';
import { useTranslation } from 'react-i18next';
import { QuestionCircleOutlined } from '@ant-design/icons';
import styles from './index.module.scss';

const selectBoxVisibleSwitch: React.FC = () => {
const { t } = useTranslation();
const { selectBoxVisibleSwitch, setSelectBoxVisibleSwitch } = useToolConfigStore();

useEffect(() => {
// After the page rendering is completed, the default value for selectBoxVisibleSwitch is set to false
setSelectBoxVisibleSwitch(false);
}, []);

const onChange = (value: boolean) => {
setSelectBoxVisibleSwitch(value);
};

return (
<div className={styles.switchBox}>
<div className={styles.switchLeft}>
<div className={styles.switchTitle}>{t('SelectBoxToDisplayIndependently')}</div>
<Tooltip
placement='top'
title={<div style={{ width: '210px' }}>{t('SelectBoxSwitchTips')}</div>}
>
<QuestionCircleOutlined />
</Tooltip>
</div>
<Switch defaultChecked={false} checked={selectBoxVisibleSwitch} onChange={onChange} />
</div>
);
};

export default selectBoxVisibleSwitch;
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import AnnotatedBox from './components/annotatedBox';
import RectRotateSensitivitySlider from './components/rectRotateSensitivitySlider';
import FindTrackIDIndex from './components/findTrackIDIndex';
import FirstFrameDataSwitch from './components/firstFrameDataSwitch';
import SelectBoxVisibleSwitch from './components/selectBoxVisibleSwitch';
import { IFileItem } from '@/types/data';
import {
IInputList,
Expand Down Expand Up @@ -514,6 +515,7 @@ const PointCloudToolSidebar: React.FC<IProps> = ({
<Divider style={{ margin: 0 }} />
<RectRotateSensitivitySlider />
{stepInfo.loadPreStep > 0 && <FirstFrameDataSwitch />}
<SelectBoxVisibleSwitch />
</div>
) : (
<div />
Expand Down
8 changes: 6 additions & 2 deletions packages/lb-utils/src/i18n/resources.json
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,9 @@
"Disconnect": "disconnect",
"Image2DBoxScale": "Image 2D Box Scale",
"SelectedRect": "Selected Rect",
"OnlyLoadTheFirstFramePreAnnotation": "Only load the first frame pre annotation"
"OnlyLoadTheFirstFramePreAnnotation": "Only load the first frame pre annotation",
"SelectBoxToDisplayIndependently": "Select box to display independently",
"SelectBoxSwitchTips": "After turning on the switch, select the box in the top view, and the image view will only display the corresponding 2D box, making it easier to view the corresponding relationship in the top view"
},
"cn": {
"TextInput": "文本输入",
Expand Down Expand Up @@ -749,6 +751,8 @@
"Disconnect": "断开",
"Image2DBoxScale": "图片2D框体缩小处理",
"SelectedRect": "选中框体",
"OnlyLoadTheFirstFramePreAnnotation": "仅载入第一帧预标注"
"OnlyLoadTheFirstFramePreAnnotation": "仅载入第一帧预标注",
"SelectBoxToDisplayIndependently": "选中框独立显示",
"SelectBoxSwitchTips": "开启开关后,选中俯视图的框体,图片视图仅显示对应的2D框体,便于查看俯视图的对应关系"
}
}

0 comments on commit edc8c90

Please sign in to comment.