Adjusted initial camera position, enabled 'Reset zoom' option for 3D canvas (#5395)

main
Boris Sekachev 3 years ago committed by GitHub
parent 01fec6fb72
commit 772f0cd117
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -27,6 +27,7 @@ from online detectors & interactors) (<https://github.com/opencv/cvat/pull/4543>
- 3D canvas now can be dragged in IDLE mode (<https://github.com/opencv/cvat/pull/5385>) - 3D canvas now can be dragged in IDLE mode (<https://github.com/opencv/cvat/pull/5385>)
- Datumaro version is upgraded to 0.3 (dev) (<https://github.com/opencv/cvat/pull/4984>) - Datumaro version is upgraded to 0.3 (dev) (<https://github.com/opencv/cvat/pull/4984>)
- Allowed trailing slashes in the SDK host address (<https://github.com/opencv/cvat/pull/5057>) - Allowed trailing slashes in the SDK host address (<https://github.com/opencv/cvat/pull/5057>)
- Adjusted initial camera position, enabled 'Reset zoom' option for 3D canvas (<https://github.com/opencv/cvat/pull/5395>)
- Enabled authentication via email (<https://github.com/opencv/cvat/pull/5037>) - Enabled authentication via email (<https://github.com/opencv/cvat/pull/5037>)
### Deprecated ### Deprecated

@ -1,6 +1,6 @@
{ {
"name": "cvat-canvas3d", "name": "cvat-canvas3d",
"version": "0.0.2", "version": "0.0.3",
"description": "Part of Computer Vision Annotation Tool which presents its canvas3D library", "description": "Part of Computer Vision Annotation Tool which presents its canvas3D library",
"main": "src/canvas3d.ts", "main": "src/canvas3d.ts",
"scripts": { "scripts": {

@ -1,4 +1,5 @@
// Copyright (C) 2021-2022 Intel Corporation // Copyright (C) 2021-2022 Intel Corporation
// Copyright (C) 2022 CVAT.ai Corporation
// //
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
@ -13,6 +14,7 @@ import {
MouseInteraction, MouseInteraction,
ShapeProperties, ShapeProperties,
GroupData, GroupData,
Configuration,
} from './canvas3dModel'; } from './canvas3dModel';
import { import {
Canvas3dView, Canvas3dViewImpl, ViewsDOM, CameraAction, Canvas3dView, Canvas3dViewImpl, ViewsDOM, CameraAction,
@ -94,6 +96,10 @@ class Canvas3dImpl implements Canvas3d {
this.model.configureShapes(shapeProperties); this.model.configureShapes(shapeProperties);
} }
public configure(configuration: Configuration): void {
this.model.configure(configuration);
}
public activate(clientID: number | null, attributeID: number | null = null): void { public activate(clientID: number | null, attributeID: number | null = null): void {
this.model.activate(String(clientID), attributeID); this.model.activate(String(clientID), attributeID);
} }

@ -1,9 +1,10 @@
// Copyright (C) 2021-2022 Intel Corporation // Copyright (C) 2021-2022 Intel Corporation
// Copyright (C) 2022 CVAT.ai Corporation
// //
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
import { import {
Canvas3dModel, Mode, DrawData, ActiveElement, FocusData, GroupData, Canvas3dModel, Mode, DrawData, ActiveElement, FocusData, GroupData, Configuration,
} from './canvas3dModel'; } from './canvas3dModel';
export interface Canvas3dController { export interface Canvas3dController {
@ -12,6 +13,7 @@ export interface Canvas3dController {
readonly selected: any; readonly selected: any;
readonly focused: FocusData; readonly focused: FocusData;
readonly groupData: GroupData; readonly groupData: GroupData;
readonly configuration: Configuration;
readonly imageIsDeleted: boolean; readonly imageIsDeleted: boolean;
mode: Mode; mode: Mode;
group(groupData: GroupData): void; group(groupData: GroupData): void;
@ -56,6 +58,10 @@ export class Canvas3dControllerImpl implements Canvas3dController {
return this.model.groupData; return this.model.groupData;
} }
public get configuration(): Configuration {
return this.model.configuration;
}
public group(groupData: GroupData): void { public group(groupData: GroupData): void {
this.model.group(groupData); this.model.group(groupData);
} }

@ -1,4 +1,5 @@
// Copyright (C) 2021-2022 Intel Corporation // Copyright (C) 2021-2022 Intel Corporation
// Copyright (C) 2022 CVAT.ai Corporation
// //
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
@ -19,6 +20,10 @@ export interface GroupData {
grouped?: []; grouped?: [];
} }
export interface Configuration {
resetZoom?: boolean;
}
export interface Image { export interface Image {
renderWidth: number; renderWidth: number;
renderHeight: number; renderHeight: number;
@ -80,6 +85,7 @@ export enum UpdateReasons {
SHAPE_ACTIVATED = 'shape_activated', SHAPE_ACTIVATED = 'shape_activated',
GROUP = 'group', GROUP = 'group',
FITTED_CANVAS = 'fitted_canvas', FITTED_CANVAS = 'fitted_canvas',
CONFIG_UPDATED = 'config_updated',
} }
export enum Mode { export enum Mode {
@ -112,6 +118,7 @@ export interface Canvas3dDataModel {
selected: any; selected: any;
shapeProperties: ShapeProperties; shapeProperties: ShapeProperties;
groupData: GroupData; groupData: GroupData;
configuration: Configuration;
} }
export interface Canvas3dModel { export interface Canvas3dModel {
@ -119,6 +126,7 @@ export interface Canvas3dModel {
data: Canvas3dDataModel; data: Canvas3dDataModel;
readonly imageIsDeleted: boolean; readonly imageIsDeleted: boolean;
readonly groupData: GroupData; readonly groupData: GroupData;
readonly configuration: Configuration;
setup(frameData: any, objectStates: any[]): void; setup(frameData: any, objectStates: any[]): void;
isAbleToChangeFrame(): boolean; isAbleToChangeFrame(): boolean;
draw(drawData: DrawData): void; draw(drawData: DrawData): void;
@ -126,6 +134,7 @@ export interface Canvas3dModel {
dragCanvas(enable: boolean): void; dragCanvas(enable: boolean): void;
activate(clientID: string | null, attributeID: number | null): void; activate(clientID: string | null, attributeID: number | null): void;
configureShapes(shapeProperties: any): void; configureShapes(shapeProperties: any): void;
configure(configuration: Configuration): void;
fit(): void; fit(): void;
group(groupData: GroupData): void; group(groupData: GroupData): void;
destroy(): void; destroy(): void;
@ -177,6 +186,9 @@ export class Canvas3dModelImpl extends MasterImpl implements Canvas3dModel {
selectedOpacity: 60, selectedOpacity: 60,
colorBy: 'Label', colorBy: 'Label',
}, },
configuration: {
resetZoom: false,
},
}; };
} }
@ -327,6 +339,14 @@ export class Canvas3dModelImpl extends MasterImpl implements Canvas3dModel {
this.notify(UpdateReasons.GROUP); this.notify(UpdateReasons.GROUP);
} }
public configure(configuration: Configuration): void {
if (typeof configuration.resetZoom === 'boolean') {
this.data.configuration.resetZoom = configuration.resetZoom;
}
this.notify(UpdateReasons.CONFIG_UPDATED);
}
public configureShapes(shapeProperties: ShapeProperties): void { public configureShapes(shapeProperties: ShapeProperties): void {
this.data.drawData.enabled = false; this.data.drawData.enabled = false;
this.data.mode = Mode.IDLE; this.data.mode = Mode.IDLE;
@ -341,6 +361,10 @@ export class Canvas3dModelImpl extends MasterImpl implements Canvas3dModel {
this.notify(UpdateReasons.FITTED_CANVAS); this.notify(UpdateReasons.FITTED_CANVAS);
} }
public get configuration(): Configuration {
return { ...this.data.configuration };
}
public get groupData(): GroupData { public get groupData(): GroupData {
return { ...this.data.groupData }; return { ...this.data.groupData };
} }

@ -40,19 +40,17 @@ export interface RayCast {
mouseVector: THREE.Vector2; mouseVector: THREE.Vector2;
} }
export interface Views { export type Views = {
perspective: RenderView; [key in ViewType]: RenderView;
top: RenderView; };
side: RenderView;
front: RenderView;
}
export interface CubeObject { export type CubeObject = {
perspective: THREE.Mesh; [key in ViewType]: THREE.Mesh;
top: THREE.Mesh; };
side: THREE.Mesh;
front: THREE.Mesh; export type ViewsDOM = {
} [key in ViewType]: HTMLCanvasElement;
};
export interface RenderView { export interface RenderView {
renderer: THREE.WebGLRenderer; renderer: THREE.WebGLRenderer;
@ -62,25 +60,23 @@ export interface RenderView {
rayCaster?: RayCast; rayCaster?: RayCast;
} }
export interface ViewsDOM {
perspective: HTMLCanvasElement;
top: HTMLCanvasElement;
side: HTMLCanvasElement;
front: HTMLCanvasElement;
}
export class Canvas3dViewImpl implements Canvas3dView, Listener { export class Canvas3dViewImpl implements Canvas3dView, Listener {
private controller: Canvas3dController; private controller: Canvas3dController;
private views: Views; private views: Views;
private clock: THREE.Clock; private clock: THREE.Clock;
private speed: number; private speed: number;
private cube: CuboidModel; private cube: CuboidModel;
private highlighted: boolean;
private selected: CubeObject;
private isPerspectiveBeingDragged: boolean; private isPerspectiveBeingDragged: boolean;
private model: Canvas3dModel & Master; private model: Canvas3dModel & Master;
private action: any; private action: any;
private globalHelpers: any; private globalHelpers: any;
private cameraSettings: {
[key in ViewType]: {
position: [number, number, number],
lookAt: [number, number, number],
up: [number, number, number],
}
};
private set mode(value: Mode) { private set mode(value: Mode) {
this.controller.mode = value; this.controller.mode = value;
@ -95,9 +91,7 @@ export class Canvas3dViewImpl implements Canvas3dView, Listener {
this.clock = new THREE.Clock(); this.clock = new THREE.Clock();
this.speed = CONST.MOVEMENT_FACTOR; this.speed = CONST.MOVEMENT_FACTOR;
this.cube = new CuboidModel('line', '#ffffff'); this.cube = new CuboidModel('line', '#ffffff');
this.highlighted = false;
this.isPerspectiveBeingDragged = false; this.isPerspectiveBeingDragged = false;
this.selected = this.cube;
this.model = model; this.model = model;
this.globalHelpers = { this.globalHelpers = {
top: { top: {
@ -113,6 +107,30 @@ export class Canvas3dViewImpl implements Canvas3dView, Listener {
rotate: [], rotate: [],
}, },
}; };
this.cameraSettings = {
perspective: {
position: [-15, 0, 8],
lookAt: [10, 0, 0],
up: [0, 0, 1],
},
top: {
position: [0, 0, 8],
lookAt: [0, 0, 0],
up: [0, 0, 1],
},
side: {
position: [0, 8, 0],
lookAt: [0, 0, 0],
up: [0, 0, 1],
},
front: {
position: [8, 0, 0],
lookAt: [0, 0, 0],
up: [0, 0, 1],
},
};
this.action = { this.action = {
loading: false, loading: false,
oldState: '', oldState: '',
@ -408,11 +426,6 @@ export class Canvas3dViewImpl implements Canvas3dView, Listener {
// setting up the camera and adding it in the scene // setting up the camera and adding it in the scene
this.views.perspective.camera = new THREE.PerspectiveCamera(50, aspectRatio, 1, 500); this.views.perspective.camera = new THREE.PerspectiveCamera(50, aspectRatio, 1, 500);
this.views.perspective.camera.position.set(-15, 0, 4);
this.views.perspective.camera.up.set(0, 0, 1);
this.views.perspective.camera.lookAt(10, 0, 0);
this.views.perspective.camera.name = 'cameraPerspective';
this.views.top.camera = new THREE.OrthographicCamera( this.views.top.camera = new THREE.OrthographicCamera(
(-aspectRatio * viewSize) / 2 - 2, (-aspectRatio * viewSize) / 2 - 2,
(aspectRatio * viewSize) / 2 + 2, (aspectRatio * viewSize) / 2 + 2,
@ -421,12 +434,6 @@ export class Canvas3dViewImpl implements Canvas3dView, Listener {
-50, -50,
50, 50,
); );
this.views.top.camera.position.set(0, 0, 5);
this.views.top.camera.lookAt(0, 0, 0);
this.views.top.camera.up.set(0, 0, 1);
this.views.top.camera.name = 'cameraTop';
this.views.side.camera = new THREE.OrthographicCamera( this.views.side.camera = new THREE.OrthographicCamera(
(-aspectRatio * viewSize) / 2, (-aspectRatio * viewSize) / 2,
(aspectRatio * viewSize) / 2, (aspectRatio * viewSize) / 2,
@ -435,11 +442,6 @@ export class Canvas3dViewImpl implements Canvas3dView, Listener {
-50, -50,
50, 50,
); );
this.views.side.camera.position.set(0, 5, 0);
this.views.side.camera.lookAt(0, 0, 0);
this.views.side.camera.up.set(0, 0, 1);
this.views.side.camera.name = 'cameraSide';
this.views.front.camera = new THREE.OrthographicCamera( this.views.front.camera = new THREE.OrthographicCamera(
(-aspectRatio * viewSize) / 2, (-aspectRatio * viewSize) / 2,
(aspectRatio * viewSize) / 2, (aspectRatio * viewSize) / 2,
@ -448,10 +450,18 @@ export class Canvas3dViewImpl implements Canvas3dView, Listener {
-50, -50,
50, 50,
); );
this.views.front.camera.position.set(3, 0, 0);
this.views.front.camera.up.set(0, 0, 1); for (const cameraType of [
this.views.front.camera.lookAt(0, 0, 0); ViewType.PERSPECTIVE,
this.views.front.camera.name = 'cameraFront'; ViewType.TOP,
ViewType.SIDE,
ViewType.FRONT,
]) {
this.views[cameraType].camera.position.set(...this.cameraSettings[cameraType].position);
this.views[cameraType].camera.lookAt(...this.cameraSettings[cameraType].lookAt);
this.views[cameraType].camera.up.set(...this.cameraSettings[cameraType].up);
this.views[cameraType].camera.name = `camera${cameraType[0].toUpperCase()}${cameraType.slice(1)}`;
}
Object.keys(this.views).forEach((view: string): void => { Object.keys(this.views).forEach((view: string): void => {
const viewType = this.views[view as keyof Views]; const viewType = this.views[view as keyof Views];
@ -1024,6 +1034,26 @@ export class Canvas3dViewImpl implements Canvas3dView, Listener {
} }
private addScene(points: any): void { private addScene(points: any): void {
const getcameraSettingsToFitScene = (
camera: THREE.PerspectiveCamera,
boundingBox: THREE.Box3,
): [number, number, number] => {
const offset = 5;
const width = boundingBox.max.x - boundingBox.min.x;
const height = boundingBox.max.y - boundingBox.min.y;
// find the maximum width or height, compute z to approximately fit the scene
const maxDim = Math.max(width, height);
const fov = camera.fov * (Math.PI / 180);
const cameraZ = Math.abs((maxDim / 8) * Math.tan(fov * 2));
return [
boundingBox.min.x + offset,
boundingBox.max.y + offset,
cameraZ + offset,
];
};
// eslint-disable-next-line no-param-reassign // eslint-disable-next-line no-param-reassign
points.material.size = 0.05; points.material.size = 0.05;
points.material.color.set(new THREE.Color(0xffffff)); points.material.color.set(new THREE.Color(0xffffff));
@ -1032,30 +1062,20 @@ export class Canvas3dViewImpl implements Canvas3dView, Listener {
controls.mouseButtons.wheel = CameraControls.ACTION.DOLLY; controls.mouseButtons.wheel = CameraControls.ACTION.DOLLY;
const material = points.material.clone(); const material = points.material.clone();
const sphereCenter = points.geometry.boundingSphere.center; // const { radius, center: sphereCenter } = points.geometry.boundingSphere;
const { radius } = points.geometry.boundingSphere;
if (!this.views.perspective.camera) return; if (!this.views.perspective.camera) return;
const xRange = -radius / 2 < this.views.perspective.camera.position.x - sphereCenter.x &&
radius / 2 > this.views.perspective.camera.position.x - sphereCenter.x; if (this.model.configuration.resetZoom) {
const yRange = -radius / 2 < this.views.perspective.camera.position.y - sphereCenter.y && points.geometry.computeBoundingBox();
radius / 2 > this.views.perspective.camera.position.y - sphereCenter.y; this.cameraSettings.perspective.position = getcameraSettingsToFitScene(
const zRange = -radius / 2 < this.views.perspective.camera.position.z - sphereCenter.z && this.views.perspective.camera as THREE.PerspectiveCamera, points.geometry.boundingBox,
radius / 2 > this.views.perspective.camera.position.z - sphereCenter.z; );
let newX = 0; this.positionAllViews(
let newY = 0; this.action.frameCoordinates.x,
let newZ = 0; this.action.frameCoordinates.y,
if (!xRange) { this.action.frameCoordinates.z,
newX = sphereCenter.x; false,
} );
if (!yRange) {
newY = sphereCenter.y;
}
if (!zRange) {
newZ = sphereCenter.z;
}
if (newX || newY || newZ) {
this.action.frameCoordinates = { x: newX, y: newY, z: newZ };
this.positionAllViews(newX, newY, newZ, false);
} }
[ViewType.TOP, ViewType.SIDE, ViewType.FRONT].forEach((view: ViewType): void => { [ViewType.TOP, ViewType.SIDE, ViewType.FRONT].forEach((view: ViewType): void => {
@ -1161,16 +1181,26 @@ export class Canvas3dViewImpl implements Canvas3dView, Listener {
this.views.side.controls && this.views.side.controls &&
this.views.front.controls this.views.front.controls
) { ) {
this.views.perspective.controls.setLookAt(x - 8, y - 8, z + 3, x, y, z, animation); this.views.perspective.controls.setLookAt(
this.views.top.camera.position.set(x, y, z + 8); x + this.cameraSettings.perspective.position[0],
this.views.top.camera.lookAt(x, y, z); y - this.cameraSettings.perspective.position[1],
this.views.top.camera.zoom = CONST.FOV_DEFAULT; z + this.cameraSettings.perspective.position[2],
this.views.side.camera.position.set(x, y + 8, z); x, y, z, animation,
this.views.side.camera.lookAt(x, y, z); );
this.views.side.camera.zoom = CONST.FOV_DEFAULT;
this.views.front.camera.position.set(x + 8, y, z); for (const cameraType of [
this.views.front.camera.lookAt(x, y, z); ViewType.TOP,
this.views.front.camera.zoom = CONST.FOV_DEFAULT; ViewType.SIDE,
ViewType.FRONT,
]) {
this.views[cameraType].camera.position.set(
x + this.cameraSettings[cameraType].position[0],
y + this.cameraSettings[cameraType].position[1],
z + this.cameraSettings[cameraType].position[2],
);
this.views[cameraType].camera.lookAt(x, y, z);
this.views[cameraType].camera.zoom = CONST.FOV_DEFAULT;
}
} }
} }
@ -1298,8 +1328,7 @@ export class Canvas3dViewImpl implements Canvas3dView, Listener {
try { try {
this.detachCamera(null); this.detachCamera(null);
// eslint-disable-next-line no-empty // eslint-disable-next-line no-empty
} catch (e) { } catch (e) { } finally {
} finally {
this.action.detachCam = false; this.action.detachCam = false;
} }
} }

@ -1,6 +1,6 @@
{ {
"name": "cvat-ui", "name": "cvat-ui",
"version": "1.44.3", "version": "1.44.4",
"description": "CVAT single-page application", "description": "CVAT single-page application",
"main": "src/index.tsx", "main": "src/index.tsx",
"scripts": { "scripts": {

@ -1,4 +1,5 @@
// Copyright (C) 2021-2022 Intel Corporation // Copyright (C) 2021-2022 Intel Corporation
// Copyright (C) 2022 CVAT.ai Corporation
// //
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
@ -34,11 +35,9 @@ interface Props {
canvasInstance: Canvas3d | Canvas; canvasInstance: Canvas3d | Canvas;
jobInstance: any; jobInstance: any;
frameData: any; frameData: any;
curZLayer: number;
annotations: any[]; annotations: any[];
contextMenuVisibility: boolean; contextMenuVisibility: boolean;
activeLabelID: number; activeLabelID: number;
activatedStateID: number | null;
activeObjectType: ObjectType; activeObjectType: ObjectType;
onSetupCanvas: () => void; onSetupCanvas: () => void;
onGroupObjects: (enabled: boolean) => void; onGroupObjects: (enabled: boolean) => void;
@ -52,9 +51,8 @@ interface Props {
onDragCanvas: (enabled: boolean) => void; onDragCanvas: (enabled: boolean) => void;
onShapeDrawn: () => void; onShapeDrawn: () => void;
workspace: Workspace; workspace: Workspace;
automaticBordering: boolean;
showObjectsTextAlways: boolean;
frame: number; frame: number;
resetZoom: boolean;
} }
interface ViewSize { interface ViewSize {
@ -184,6 +182,7 @@ const CanvasWrapperComponent = (props: Props): ReactElement => {
frame, frame,
jobInstance, jobInstance,
activeLabelID, activeLabelID,
resetZoom,
activeObjectType, activeObjectType,
onShapeDrawn, onShapeDrawn,
onCreateAnnotations, onCreateAnnotations,
@ -258,6 +257,7 @@ const CanvasWrapperComponent = (props: Props): ReactElement => {
canvasInstanceDOM.perspective.addEventListener('canvas.canceled', onCanvasCancel); canvasInstanceDOM.perspective.addEventListener('canvas.canceled', onCanvasCancel);
canvasInstanceDOM.perspective.addEventListener('canvas.dragstart', onCanvasDragStart); canvasInstanceDOM.perspective.addEventListener('canvas.dragstart', onCanvasDragStart);
canvasInstanceDOM.perspective.addEventListener('canvas.dragstop', onCanvasDragDone); canvasInstanceDOM.perspective.addEventListener('canvas.dragstop', onCanvasDragDone);
canvasInstance.configure({ resetZoom });
}; };
const keyControlsKeyDown = (key: KeyboardEvent): void => { const keyControlsKeyDown = (key: KeyboardEvent): void => {
@ -336,6 +336,10 @@ const CanvasWrapperComponent = (props: Props): ReactElement => {
}; };
}, []); }, []);
useEffect(() => {
canvasInstance.configure({ resetZoom });
}, [resetZoom]);
const updateShapesView = (): void => { const updateShapesView = (): void => {
(canvasInstance as Canvas3d).configureShapes({ (canvasInstance as Canvas3d).configureShapes({
opacity, opacity,

@ -1,4 +1,5 @@
// Copyright (C) 2021-2022 Intel Corporation // Copyright (C) 2021-2022 Intel Corporation
// Copyright (C) 2022 CVAT.ai Corporation
// //
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
@ -20,60 +21,33 @@ import {
} from 'actions/annotation-actions'; } from 'actions/annotation-actions';
import { import {
ActiveControl,
ColorBy, ColorBy,
CombinedState, CombinedState,
ContextMenuType, ContextMenuType,
GridColor,
ObjectType, ObjectType,
Workspace, Workspace,
} from 'reducers'; } from 'reducers';
import { Canvas3d } from 'cvat-canvas3d-wrapper'; import { Canvas3d } from 'cvat-canvas3d-wrapper';
import { Canvas } from 'cvat-canvas-wrapper'; import { Canvas } from 'cvat-canvas-wrapper';
import { KeyMap } from '../../../utils/mousetrap-react';
interface StateToProps { interface StateToProps {
canvasInstance: Canvas3d | Canvas;
jobInstance: any;
frameData: any;
curZLayer: number;
annotations: any[];
sidebarCollapsed: boolean;
activatedStateID: number | null;
activatedAttributeID: number | null;
frameIssues: any[] | null;
frameAngle: number;
frameFetching: boolean;
frame: number;
opacity: number; opacity: number;
colorBy: ColorBy;
selectedOpacity: number; selectedOpacity: number;
outlined: boolean; outlined: boolean;
outlineColor: string; outlineColor: string;
showBitmap: boolean; colorBy: ColorBy;
showProjections: boolean; frameFetching: boolean;
grid: boolean; canvasInstance: Canvas3d | Canvas;
gridSize: number; jobInstance: any;
gridColor: GridColor; frameData: any;
gridOpacity: number; annotations: any[];
contextMenuVisibility: boolean;
activeLabelID: number; activeLabelID: number;
activeObjectType: ObjectType; activeObjectType: ObjectType;
brightnessLevel: number;
contrastLevel: number;
saturationLevel: number;
resetZoom: boolean;
aamZoomMargin: number;
contextMenuVisibility: boolean;
showObjectsTextAlways: boolean;
showAllInterpolationTracks: boolean;
workspace: Workspace; workspace: Workspace;
minZLayer: number; frame: number;
maxZLayer: number; resetZoom: boolean;
automaticBordering: boolean;
switchableAutomaticBordering: boolean;
keyMap: KeyMap;
canvasBackgroundColor: string;
} }
interface DispatchToProps { interface DispatchToProps {
@ -94,7 +68,6 @@ function mapStateToProps(state: CombinedState): StateToProps {
const { const {
annotation: { annotation: {
canvas: { canvas: {
activeControl,
instance: canvasInstance, instance: canvasInstance,
contextMenu: { visible: contextMenuVisibility }, contextMenu: { visible: contextMenuVisibility },
}, },
@ -102,85 +75,39 @@ function mapStateToProps(state: CombinedState): StateToProps {
job: { instance: jobInstance }, job: { instance: jobInstance },
player: { player: {
frame: { data: frameData, number: frame, fetching: frameFetching }, frame: { data: frameData, number: frame, fetching: frameFetching },
frameAngles,
}, },
annotations: { annotations: {
states: annotations, states: annotations,
activatedStateID,
activatedAttributeID,
zLayer: { cur: curZLayer, min: minZLayer, max: maxZLayer },
}, },
sidebarCollapsed,
workspace, workspace,
}, },
settings: { settings: {
player: { player: {
canvasBackgroundColor,
grid,
gridSize,
gridColor,
gridOpacity,
brightnessLevel,
contrastLevel,
saturationLevel,
resetZoom, resetZoom,
}, },
workspace: {
aamZoomMargin, showObjectsTextAlways, showAllInterpolationTracks, automaticBordering,
},
shapes: { shapes: {
opacity, colorBy, selectedOpacity, outlined, outlineColor, showBitmap, showProjections, opacity, colorBy, selectedOpacity, outlined, outlineColor,
}, },
}, },
review: { frameIssues, issuesHidden },
shortcuts: { keyMap },
} = state; } = state;
return { return {
canvasInstance, canvasInstance,
jobInstance, jobInstance,
frameData, frameData,
curZLayer,
contextMenuVisibility, contextMenuVisibility,
annotations, annotations,
sidebarCollapsed,
frameIssues:
issuesHidden || ![Workspace.REVIEW_WORKSPACE, Workspace.STANDARD].includes(workspace) ? null : frameIssues,
frameAngle: frameAngles[frame - jobInstance.startFrame],
frameFetching, frameFetching,
frame, frame,
activatedStateID,
activatedAttributeID,
opacity, opacity,
colorBy, colorBy,
selectedOpacity, selectedOpacity,
outlined, outlined,
outlineColor, outlineColor,
showBitmap,
showProjections,
grid,
gridSize,
gridColor,
gridOpacity,
activeLabelID, activeLabelID,
activeObjectType, activeObjectType,
brightnessLevel,
contrastLevel,
saturationLevel,
resetZoom, resetZoom,
aamZoomMargin,
showObjectsTextAlways,
showAllInterpolationTracks,
minZLayer,
maxZLayer,
automaticBordering,
workspace, workspace,
keyMap,
canvasBackgroundColor,
switchableAutomaticBordering:
activeControl === ActiveControl.DRAW_POLYGON ||
activeControl === ActiveControl.DRAW_POLYLINE ||
activeControl === ActiveControl.EDIT,
}; };
} }
@ -212,7 +139,7 @@ function mapDispatchToProps(dispatch: any): DispatchToProps {
dispatch(updateCanvasContextMenu(false, 0, 0)); dispatch(updateCanvasContextMenu(false, 0, 0));
} }
dispatch(activateObject(activatedStateID, null)); dispatch(activateObject(activatedStateID, null, null));
}, },
onEditShape(enabled: boolean): void { onEditShape(enabled: boolean): void {
dispatch(editShape(enabled)); dispatch(editShape(enabled));

@ -1,7 +1,10 @@
// Copyright (C) 2021-2022 Intel Corporation // Copyright (C) 2021-2022 Intel Corporation
// Copyright (C) 2022 CVAT.ai Corporation
// //
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
/* eslint-disable cypress/no-unnecessary-waiting */
/// <reference types="cypress" /> /// <reference types="cypress" />
import { taskName, labelName } from '../../support/const_canvas3d'; import { taskName, labelName } from '../../support/const_canvas3d';
@ -10,24 +13,24 @@ context('Canvas 3D functionality. Grouping.', () => {
const caseId = '83'; const caseId = '83';
const screenshotsPath = 'cypress/screenshots/canvas3d_functionality/case_83_canvas3d_functionality_cuboid_grouping.js'; const screenshotsPath = 'cypress/screenshots/canvas3d_functionality/case_83_canvas3d_functionality_cuboid_grouping.js';
const firstCuboidCreationParams = { const firstCuboidCreationParams = {
labelName: labelName, labelName,
x: 480, x: 480,
y: 160, y: 150,
}; };
const secondCuboidCreationParams = { const secondCuboidCreationParams = {
labelName: labelName, labelName,
x: 480, x: 480,
y: 270, y: 200,
}; };
const thirdCuboidCreationParams = { const thirdCuboidCreationParams = {
labelName: labelName, labelName,
x: 430, x: 530,
y: 220, y: 150,
}; };
const fourthCuboidCreationParams = { const fourthCuboidCreationParams = {
labelName: labelName, labelName,
x: 530, x: 530,
y: 220, y: 200,
}; };
const yellowHex = 'fcbe03'; const yellowHex = 'fcbe03';
const yellowRgb = '252, 190, 3'; const yellowRgb = '252, 190, 3';
@ -48,7 +51,7 @@ context('Canvas 3D functionality. Grouping.', () => {
} }
before(() => { before(() => {
cy.openTask(taskName) cy.openTask(taskName);
cy.openJob(); cy.openJob();
cy.wait(1000); // Waiting for the point cloud to display cy.wait(1000); // Waiting for the point cloud to display
cy.create3DCuboid(firstCuboidCreationParams); cy.create3DCuboid(firstCuboidCreationParams);
@ -61,8 +64,8 @@ context('Canvas 3D functionality. Grouping.', () => {
describe(`Testing case "${caseId}"`, () => { describe(`Testing case "${caseId}"`, () => {
it('Grouping two cuboids.', () => { it('Grouping two cuboids.', () => {
cy.get('.cvat-group-control').click(); cy.get('.cvat-group-control').click();
cy.get('.cvat-canvas3d-perspective').trigger('mousemove', 480, 270).click(480, 270); cy.get('.cvat-canvas3d-perspective').trigger('mousemove', 480, 200).click(480, 200);
cy.get('.cvat-canvas3d-perspective').trigger('mousemove', 430, 220).click(430, 220); cy.get('.cvat-canvas3d-perspective').trigger('mousemove', 530, 150).click(530, 150);
cy.get('.cvat-group-control').click(); cy.get('.cvat-group-control').click();
cy.changeAppearance('Group'); cy.changeAppearance('Group');
cy.get('#cvat-objects-sidebar-state-item-1').invoke('attr', 'style').then((bgColorItem1) => { cy.get('#cvat-objects-sidebar-state-item-1').invoke('attr', 'style').then((bgColorItem1) => {
@ -102,8 +105,8 @@ context('Canvas 3D functionality. Grouping.', () => {
it('Reset group.', () => { it('Reset group.', () => {
cy.customScreenshot('.cvat-canvas3d-perspective', 'canvas3d_perspective_before_reset_group'); cy.customScreenshot('.cvat-canvas3d-perspective', 'canvas3d_perspective_before_reset_group');
cy.get('.cvat-group-control').click(); cy.get('.cvat-group-control').click();
cy.get('.cvat-canvas3d-perspective').trigger('mousemove', 480, 270).click(480, 270); cy.get('.cvat-canvas3d-perspective').trigger('mousemove', 480, 200).click(480, 200);
cy.get('.cvat-canvas3d-perspective').trigger('mousemove', 430, 220).click(430, 220); cy.get('.cvat-canvas3d-perspective').trigger('mousemove', 530, 150).click(530, 150);
cy.get('body').type('{Shift}g'); cy.get('body').type('{Shift}g');
cy.get('#cvat-objects-sidebar-state-item-2').invoke('attr', 'style').then((bgColorItem2) => { cy.get('#cvat-objects-sidebar-state-item-2').invoke('attr', 'style').then((bgColorItem2) => {
expect(bgColorItem).to.be.equal(bgColorItem2); expect(bgColorItem).to.be.equal(bgColorItem2);

@ -1,7 +1,10 @@
// Copyright (C) 2021-2022 Intel Corporation // Copyright (C) 2021-2022 Intel Corporation
// Copyright (C) 2022 CVAT.ai Corporation
// //
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
/* eslint-disable cypress/no-unnecessary-waiting */
/// <reference types="cypress" /> /// <reference types="cypress" />
import { taskName, labelName } from '../../support/const_canvas3d'; import { taskName, labelName } from '../../support/const_canvas3d';
@ -10,13 +13,13 @@ context('Canvas 3D functionality. Opacity. Outlined borders.', () => {
const caseId = '82'; const caseId = '82';
const screenshotsPath = 'cypress/screenshots/canvas3d_functionality_2/case_82_canvas3d_functionality_cuboid_opacity_outlined_borders.js'; const screenshotsPath = 'cypress/screenshots/canvas3d_functionality_2/case_82_canvas3d_functionality_cuboid_opacity_outlined_borders.js';
const cuboidCreationParams = { const cuboidCreationParams = {
labelName: labelName, labelName,
x: 500, x: 500,
y: 250, y: 250,
}; };
before(() => { before(() => {
cy.openTask(taskName) cy.openTask(taskName);
cy.openJob(); cy.openJob();
cy.wait(1000); // Waiting for the point cloud to display cy.wait(1000); // Waiting for the point cloud to display
cy.create3DCuboid(cuboidCreationParams); cy.create3DCuboid(cuboidCreationParams);
@ -64,6 +67,11 @@ context('Canvas 3D functionality. Opacity. Outlined borders.', () => {
it('Enable/disable outlined borders.', () => { it('Enable/disable outlined borders.', () => {
cy.get('.cvat-appearance-outlinded-borders-checkbox').find('[type="checkbox"]').check().should('be.checked'); cy.get('.cvat-appearance-outlinded-borders-checkbox').find('[type="checkbox"]').check().should('be.checked');
cy.get('.cvat-appearance-outlined-borders-button').click();
cy.get('.cvat-label-color-picker').should('exist').and('be.visible').within(() => {
cy.get('div[title="#ff007c"]').click();
cy.contains('Ok').click();
});
cy.customScreenshot('.cvat-canvas3d-perspective', 'canvas3d_perspective_enable_outlined_borders'); cy.customScreenshot('.cvat-canvas3d-perspective', 'canvas3d_perspective_enable_outlined_borders');
cy.compareImagesAndCheckResult( cy.compareImagesAndCheckResult(
`${screenshotsPath}/canvas3d_perspective_enable_outlined_borders.png`, `${screenshotsPath}/canvas3d_perspective_enable_outlined_borders.png`,

Loading…
Cancel
Save