Context menu options for cuboids (#1554)

main
Dmitry Kalinin 6 years ago committed by GitHub
parent d1b2960b3d
commit c4e769d5cf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,4 @@
<svg width="1em" height="1em" viewBox="0 0 256 256" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M213 32L240 64H220V192H240L212.5 224L185 192H205V64H185L213 32Z" fill="black"/>
<path d="M32 64L33.1578 56.5899L24.5 55.2371V64H32ZM32 192H24.5V200.628L33.0444 199.427L32 192ZM160 174L161.044 181.427L167.5 180.519V174H160ZM160 84H167.5V77.5809L161.158 76.5899L160 84ZM24.5 64V192H39.5V64H24.5ZM33.0444 199.427L161.044 181.427L158.956 166.573L30.9556 184.573L33.0444 199.427ZM161.158 76.5899L33.1578 56.5899L30.8422 71.4101L158.842 91.4101L161.158 76.5899ZM167.5 174V84H152.5V174H167.5Z" fill="black"/>
</svg>

After

Width:  |  Height:  |  Size: 658 B

@ -29,6 +29,7 @@ import {
NextIcon, NextIcon,
BackgroundIcon, BackgroundIcon,
ForegroundIcon, ForegroundIcon,
ResetPerspectiveIcon,
} from 'icons'; } from 'icons';
import { ObjectType, ShapeType } from 'reducers/interfaces'; import { ObjectType, ShapeType } from 'reducers/interfaces';
import { clamp } from 'utils/math'; import { clamp } from 'utils/math';
@ -38,6 +39,7 @@ function ItemMenu(
serverID: number | undefined, serverID: number | undefined,
locked: boolean, locked: boolean,
objectType: ObjectType, objectType: ObjectType,
shapeType: ShapeType,
copyShortcut: string, copyShortcut: string,
pasteShortcut: string, pasteShortcut: string,
propagateShortcut: string, propagateShortcut: string,
@ -50,6 +52,8 @@ function ItemMenu(
createURL: (() => void), createURL: (() => void),
toBackground: (() => void), toBackground: (() => void),
toForeground: (() => void), toForeground: (() => void),
switchCuboidOrientation: (() => void),
resetCuboidPerspective: (() => void),
): JSX.Element { ): JSX.Element {
return ( return (
<Menu className='cvat-object-item-menu'> <Menu className='cvat-object-item-menu'>
@ -72,7 +76,22 @@ function ItemMenu(
</Button> </Button>
</Tooltip> </Tooltip>
</Menu.Item> </Menu.Item>
{ objectType !== ObjectType.TAG && ( {shapeType === ShapeType.CUBOID && (
<Menu.Item>
<Button type='link' icon='retweet' onClick={switchCuboidOrientation}>
Switch orientation
</Button>
</Menu.Item>
)}
{shapeType === ShapeType.CUBOID && (
<Menu.Item>
<Button type='link' onClick={resetCuboidPerspective}>
<Icon component={ResetPerspectiveIcon}/>
Reset perspective
</Button>
</Menu.Item>
)}
{objectType !== ObjectType.TAG && (
<Menu.Item> <Menu.Item>
<Tooltip title={`${toBackgroundShortcut}`}> <Tooltip title={`${toBackgroundShortcut}`}>
<Button type='link' onClick={toBackground}> <Button type='link' onClick={toBackground}>
@ -82,7 +101,7 @@ function ItemMenu(
</Tooltip> </Tooltip>
</Menu.Item> </Menu.Item>
)} )}
{ objectType !== ObjectType.TAG && ( {objectType !== ObjectType.TAG && (
<Menu.Item> <Menu.Item>
<Tooltip title={`${toForegroundShortcut}`}> <Tooltip title={`${toForegroundShortcut}`}>
<Button type='link' onClick={toForeground}> <Button type='link' onClick={toForeground}>
@ -125,6 +144,7 @@ interface ItemTopComponentProps {
labelID: number; labelID: number;
labels: any[]; labels: any[];
objectType: ObjectType; objectType: ObjectType;
shapeType: ShapeType;
type: string; type: string;
locked: boolean; locked: boolean;
copyShortcut: string; copyShortcut: string;
@ -140,6 +160,8 @@ interface ItemTopComponentProps {
createURL(): void; createURL(): void;
toBackground(): void; toBackground(): void;
toForeground(): void; toForeground(): void;
switchCuboidOrientation(): void;
resetCuboidPerspective(): void;
} }
function ItemTopComponent(props: ItemTopComponentProps): JSX.Element { function ItemTopComponent(props: ItemTopComponentProps): JSX.Element {
@ -149,6 +171,7 @@ function ItemTopComponent(props: ItemTopComponentProps): JSX.Element {
labelID, labelID,
labels, labels,
objectType, objectType,
shapeType,
type, type,
locked, locked,
copyShortcut, copyShortcut,
@ -164,6 +187,8 @@ function ItemTopComponent(props: ItemTopComponentProps): JSX.Element {
createURL, createURL,
toBackground, toBackground,
toForeground, toForeground,
switchCuboidOrientation,
resetCuboidPerspective,
} = props; } = props;
return ( return (
@ -191,6 +216,7 @@ function ItemTopComponent(props: ItemTopComponentProps): JSX.Element {
serverID, serverID,
locked, locked,
objectType, objectType,
shapeType,
copyShortcut, copyShortcut,
pasteShortcut, pasteShortcut,
propagateShortcut, propagateShortcut,
@ -203,6 +229,8 @@ function ItemTopComponent(props: ItemTopComponentProps): JSX.Element {
createURL, createURL,
toBackground, toBackground,
toForeground, toForeground,
switchCuboidOrientation,
resetCuboidPerspective,
)} )}
> >
<Icon type='more' /> <Icon type='more' />
@ -727,6 +755,8 @@ interface Props {
changeAttribute(attrID: number, value: string): void; changeAttribute(attrID: number, value: string): void;
changeColor(color: string): void; changeColor(color: string): void;
collapse(): void; collapse(): void;
switchCuboidOrientation(): void;
resetCuboidPerspective(): void;
} }
function objectItemsAreEqual(prevProps: Props, nextProps: Props): boolean { function objectItemsAreEqual(prevProps: Props, nextProps: Props): boolean {
@ -804,6 +834,8 @@ function ObjectItemComponent(props: Props): JSX.Element {
changeAttribute, changeAttribute,
changeColor, changeColor,
collapse, collapse,
switchCuboidOrientation,
resetCuboidPerspective,
} = props; } = props;
const type = objectType === ObjectType.TAG ? ObjectType.TAG.toUpperCase() const type = objectType === ObjectType.TAG ? ObjectType.TAG.toUpperCase()
@ -842,6 +874,7 @@ function ObjectItemComponent(props: Props): JSX.Element {
labels={labels} labels={labels}
objectType={objectType} objectType={objectType}
type={type} type={type}
shapeType={shapeType}
locked={locked} locked={locked}
copyShortcut={normalizedKeyMap.COPY_SHAPE} copyShortcut={normalizedKeyMap.COPY_SHAPE}
pasteShortcut={normalizedKeyMap.PASTE_SHAPE} pasteShortcut={normalizedKeyMap.PASTE_SHAPE}
@ -856,6 +889,8 @@ function ObjectItemComponent(props: Props): JSX.Element {
createURL={createURL} createURL={createURL}
toBackground={toBackground} toBackground={toBackground}
toForeground={toForeground} toForeground={toForeground}
switchCuboidOrientation={switchCuboidOrientation}
resetCuboidPerspective={resetCuboidPerspective}
/> />
<ItemButtons <ItemButtons
shapeType={shapeType} shapeType={shapeType}

@ -25,6 +25,8 @@ import {
import ObjectStateItemComponent from 'components/annotation-page/standard-workspace/objects-side-bar/object-item'; import ObjectStateItemComponent from 'components/annotation-page/standard-workspace/objects-side-bar/object-item';
import {shift} from 'utils/math';
interface OwnProps { interface OwnProps {
clientID: number; clientID: number;
} }
@ -404,6 +406,53 @@ class ObjectItemContainer extends React.PureComponent<Props> {
} }
} }
private switchCuboidOrientation = (): void => {
function cuboidOrientationIsLeft(points: number[]): boolean {
return points[12] > points[0];
}
const {objectState} = this.props;
this.resetCuboidPerspective(false);
objectState.points = shift(objectState.points,
cuboidOrientationIsLeft(objectState.points) ? 4 : -4);
this.commit();
}
private resetCuboidPerspective = (commit: boolean = true): void => {
function cuboidOrientationIsLeft(points: number[]): boolean {
return points[12] > points[0];
}
const {objectState} = this.props;
const {points} = objectState;
const minD = {
x: (points[6] - points[2])*0.001,
y: (points[3] - points[1])*0.001,
}
if (cuboidOrientationIsLeft(points)) {
points[14] = points[10] + points[2] - points[6] + minD.x;
points[15] = points[11] + points[3] - points[7];
points[8] = points[10] + points[4] - points[6];
points[9] = points[11] + points[5] - points[7] + minD.y;
points[12] = points[14] + points[0] - points[2];
points[13] = points[15] + points[1] - points[3] + minD.y;
} else {
points[10] = points[14] + points[6] - points[2] - minD.x;
points[11] = points[15] + points[7] - points[3];
points[12] = points[14] + points[0] - points[2];
points[13] = points[15] + points[1] - points[3] + minD.y;
points[8] = points[12] + points[4] - points[0] - minD.x;
points[9] = points[13] + points[5] - points[1];
}
objectState.points = points;
if (commit) this.commit();
}
private commit(): void { private commit(): void {
const { const {
objectState, objectState,
@ -507,6 +556,8 @@ class ObjectItemContainer extends React.PureComponent<Props> {
changeLabel={this.changeLabel} changeLabel={this.changeLabel}
changeAttribute={this.changeAttribute} changeAttribute={this.changeAttribute}
collapse={this.collapse} collapse={this.collapse}
switchCuboidOrientation={this.switchCuboidOrientation}
resetCuboidPerspective={() => this.resetCuboidPerspective()}
/> />
); );
} }

@ -40,6 +40,7 @@ import SVGObjectInsideIcon from './assets/object-inside-icon.svg';
import SVGBackgroundIcon from './assets/background-icon.svg'; import SVGBackgroundIcon from './assets/background-icon.svg';
import SVGForegroundIcon from './assets/foreground-icon.svg'; import SVGForegroundIcon from './assets/foreground-icon.svg';
import SVGCubeIcon from './assets/cube-icon.svg'; import SVGCubeIcon from './assets/cube-icon.svg';
import SVGResetPerspectiveIcon from './assets/reset-perspective.svg';
export const CVATLogo = React.memo( export const CVATLogo = React.memo(
(): JSX.Element => <SVGCVATLogo />, (): JSX.Element => <SVGCVATLogo />,
@ -149,3 +150,6 @@ export const ForegroundIcon = React.memo(
export const CubeIcon = React.memo( export const CubeIcon = React.memo(
(): JSX.Element => <SVGCubeIcon />, (): JSX.Element => <SVGCubeIcon />,
); );
export const ResetPerspectiveIcon = React.memo(
(): JSX.Element => <SVGResetPerspectiveIcon />,
);

@ -2,3 +2,11 @@
export function clamp(value: number, min: number, max: number): number { export function clamp(value: number, min: number, max: number): number {
return Math.max(Math.min(value, max), min); return Math.max(Math.min(value, max), min);
} }
export function shift<T>(array: Array<T>, k: number): Array<T> {
if (k % array.length !== 0) {
return array.slice(k % array.length).concat(array.slice(0,k % array.length));
} else {
return array;
}
}
Loading…
Cancel
Save