Skip to content

Commit d3db54d

Browse files
author
Boris Sekachev
authored
Fixed: Issues disappear when using a zoom (#4189)
* Fixed: Issues disappear when using a zoom * Fixed creating issues for ellipses and rotated shapes * Updated version & changelog
1 parent bc4ff49 commit d3db54d

21 files changed

+169
-119
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
5858
- Bug: canvas is busy when start playing, start resizing a shape and do not release the mouse cursor (<https://github.com/openvinotoolkit/cvat/pull/4151>)
5959
- Bug: could not receive frame N. TypeError: Cannot read properties of undefined (reding "filename") (<https://github.com/openvinotoolkit/cvat/pull/4187>)
6060
- Fixed tus upload error over https (<https://github.com/openvinotoolkit/cvat/pull/4154>)
61+
- Issues disappear when rescale a browser (<https://github.com/openvinotoolkit/cvat/pull/4189>)
6162
- Auth token key is not returned when registering without email verification (<https://github.com/openvinotoolkit/cvat/pull/4092>)
6263

6364
### Security

cvat-canvas/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ Standard JS events are used.
184184
- canvas.zoomstart
185185
- canvas.zoomstop
186186
- canvas.zoom
187+
- canvas.reshape
187188
- canvas.fit
188189
- canvas.dragshape => {id: number}
189190
- canvas.roiselected => {points: number[]}

cvat-canvas/package-lock.json

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cvat-canvas/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "cvat-canvas",
3-
"version": "2.12.2",
3+
"version": "2.13.0",
44
"description": "Part of Computer Vision Annotation Tool which presents its canvas library",
55
"main": "src/canvas.ts",
66
"scripts": {

cvat-canvas/src/scss/canvas.scss

-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,6 @@ polyline.cvat_shape_drawing_opacity {
7474
}
7575

7676
.cvat_canvas_issue_region {
77-
display: none;
7877
stroke-width: 0;
7978
}
8079

cvat-canvas/src/typescript/canvas.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2019-2021 Intel Corporation
1+
// Copyright (C) 2019-2022 Intel Corporation
22
//
33
// SPDX-License-Identifier: MIT
44

@@ -29,7 +29,7 @@ const CanvasVersion = pjson.version;
2929
interface Canvas {
3030
html(): HTMLDivElement;
3131
setup(frameData: any, objectStates: any[], zLayer?: number): void;
32-
setupIssueRegions(issueRegions: Record<number, number[]>): void;
32+
setupIssueRegions(issueRegions: Record<number, { hidden: boolean; points: number[] }>): void;
3333
activate(clientID: number | null, attributeID?: number): void;
3434
rotate(rotationAngle: number): void;
3535
focus(clientID: number, padding?: number): void;
@@ -77,7 +77,7 @@ class CanvasImpl implements Canvas {
7777
this.model.setup(frameData, objectStates, zLayer);
7878
}
7979

80-
public setupIssueRegions(issueRegions: Record<number, number[]>): void {
80+
public setupIssueRegions(issueRegions: Record<number, { hidden: boolean; points: number[] }>): void {
8181
this.model.setupIssueRegions(issueRegions);
8282
}
8383

cvat-canvas/src/typescript/canvasController.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2019-2020 Intel Corporation
1+
// Copyright (C) 2019-2022 Intel Corporation
22
//
33
// SPDX-License-Identifier: MIT
44

@@ -19,7 +19,7 @@ import {
1919

2020
export interface CanvasController {
2121
readonly objects: any[];
22-
readonly issueRegions: Record<number, number[]>;
22+
readonly issueRegions: Record<number, { hidden: boolean; points: number[] }>;
2323
readonly zLayer: number | null;
2424
readonly focusData: FocusData;
2525
readonly activeElement: ActiveElement;
@@ -123,7 +123,7 @@ export class CanvasControllerImpl implements CanvasController {
123123
return this.model.zLayer;
124124
}
125125

126-
public get issueRegions(): Record<number, number[]> {
126+
public get issueRegions(): Record<number, { hidden: boolean; points: number[] }> {
127127
return this.model.issueRegions;
128128
}
129129

cvat-canvas/src/typescript/canvasModel.ts

+7-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2019-2021 Intel Corporation
1+
// Copyright (C) 2019-2022 Intel Corporation
22
//
33
// SPDX-License-Identifier: MIT
44

@@ -172,7 +172,7 @@ export enum Mode {
172172
export interface CanvasModel {
173173
readonly imageBitmap: boolean;
174174
readonly image: Image | null;
175-
readonly issueRegions: Record<number, number[]>;
175+
readonly issueRegions: Record<number, { hidden: boolean; points: number[] }>;
176176
readonly objects: any[];
177177
readonly zLayer: number | null;
178178
readonly gridSize: Size;
@@ -193,7 +193,7 @@ export interface CanvasModel {
193193
move(topOffset: number, leftOffset: number): void;
194194

195195
setup(frameData: any, objectStates: any[], zLayer: number): void;
196-
setupIssueRegions(issueRegions: Record<number, number[]>): void;
196+
setupIssueRegions(issueRegions: Record<number, { hidden: boolean; points: number[] }>): void;
197197
activate(clientID: number | null, attributeID: number | null): void;
198198
rotate(rotationAngle: number): void;
199199
focus(clientID: number, padding: number): void;
@@ -234,7 +234,7 @@ export class CanvasModelImpl extends MasterImpl implements CanvasModel {
234234
gridSize: Size;
235235
left: number;
236236
objects: any[];
237-
issueRegions: Record<number, number[]>;
237+
issueRegions: Record<number, { hidden: boolean; points: number[] }>;
238238
scale: number;
239239
top: number;
240240
zLayer: number | null;
@@ -353,6 +353,7 @@ export class CanvasModelImpl extends MasterImpl implements CanvasModel {
353353

354354
this.notify(UpdateReasons.FITTED_CANVAS);
355355
this.notify(UpdateReasons.OBJECTS_UPDATED);
356+
this.notify(UpdateReasons.ISSUE_REGIONS_UPDATED);
356357
}
357358

358359
public bitmap(enabled: boolean): void {
@@ -445,7 +446,7 @@ export class CanvasModelImpl extends MasterImpl implements CanvasModel {
445446
});
446447
}
447448

448-
public setupIssueRegions(issueRegions: Record<number, number[]>): void {
449+
public setupIssueRegions(issueRegions: Record<number, { hidden: boolean; points: number[] }>): void {
449450
this.data.issueRegions = issueRegions;
450451
this.notify(UpdateReasons.ISSUE_REGIONS_UPDATED);
451452
}
@@ -756,7 +757,7 @@ export class CanvasModelImpl extends MasterImpl implements CanvasModel {
756757
return this.data.image;
757758
}
758759

759-
public get issueRegions(): Record<number, number[]> {
760+
public get issueRegions(): Record<number, { hidden: boolean; points: number[] }> {
760761
return { ...this.data.issueRegions };
761762
}
762763

cvat-canvas/src/typescript/canvasView.ts

+13-2
Original file line numberDiff line numberDiff line change
@@ -606,7 +606,7 @@ export class CanvasViewImpl implements CanvasView, Listener {
606606
}
607607
}
608608

609-
private setupIssueRegions(issueRegions: Record<number, number[]>): void {
609+
private setupIssueRegions(issueRegions: Record<number, { hidden: boolean; points: number[] }>): void {
610610
for (const issueRegion of Object.keys(this.drawnIssueRegions)) {
611611
if (!(issueRegion in issueRegions) || !+issueRegion) {
612612
this.drawnIssueRegions[+issueRegion].remove();
@@ -616,7 +616,7 @@ export class CanvasViewImpl implements CanvasView, Listener {
616616

617617
for (const issueRegion of Object.keys(issueRegions)) {
618618
if (issueRegion in this.drawnIssueRegions) continue;
619-
const points = this.translateToCanvas(issueRegions[+issueRegion]);
619+
const points = this.translateToCanvas(issueRegions[+issueRegion].points);
620620
if (points.length === 2) {
621621
this.drawnIssueRegions[+issueRegion] = this.adoptedContent
622622
.circle((consts.BASE_POINT_SIZE * 3 * 2) / this.geometry.scale)
@@ -656,6 +656,10 @@ export class CanvasViewImpl implements CanvasView, Listener {
656656
'stroke-width': `${consts.BASE_STROKE_WIDTH / this.geometry.scale}`,
657657
});
658658
}
659+
660+
if (issueRegions[+issueRegion].hidden) {
661+
this.drawnIssueRegions[+issueRegion].style({ display: 'none' });
662+
}
659663
}
660664
}
661665

@@ -1263,8 +1267,15 @@ export class CanvasViewImpl implements CanvasView, Listener {
12631267
} else if (reason === UpdateReasons.FITTED_CANVAS) {
12641268
// Canvas geometry is going to be changed. Old object positions aren't valid any more
12651269
this.setupObjects([]);
1270+
this.setupIssueRegions({});
12661271
this.moveCanvas();
12671272
this.resizeCanvas();
1273+
this.canvas.dispatchEvent(
1274+
new CustomEvent('canvas.reshape', {
1275+
bubbles: false,
1276+
cancelable: true,
1277+
}),
1278+
);
12681279
} else if ([UpdateReasons.IMAGE_ZOOMED, UpdateReasons.IMAGE_FITTED].includes(reason)) {
12691280
this.moveCanvas();
12701281
this.transformCanvas();

cvat-ui/package-lock.json

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cvat-ui/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "cvat-ui",
3-
"version": "1.33.2",
3+
"version": "1.33.3",
44
"description": "CVAT single-page application",
55
"main": "src/index.tsx",
66
"scripts": {

cvat-ui/src/components/annotation-page/canvas/canvas-context-menu.tsx

+25-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2021 Intel Corporation
1+
// Copyright (C) 2021-2022 Intel Corporation
22
//
33
// SPDX-License-Identifier: MIT
44

@@ -10,6 +10,7 @@ import { MenuInfo } from 'rc-menu/lib/interface';
1010

1111
import ObjectItemContainer from 'containers/annotation-page/standard-workspace/objects-side-bar/object-item';
1212
import { Workspace } from 'reducers/interfaces';
13+
import { rotatePoint } from 'utils/math';
1314
import consts from 'consts';
1415

1516
interface Props {
@@ -106,7 +107,29 @@ export default function CanvasContextMenu(props: Props): JSX.Element | null {
106107
);
107108
if (param.key === ReviewContextMenuKeys.OPEN_ISSUE) {
108109
if (state) {
109-
onStartIssue(state.points);
110+
let { points } = state;
111+
if (['ellipse', 'rectangle'].includes(state.shapeType)) {
112+
const [cx, cy] = state.shapeType === 'ellipse' ? state.points : [
113+
(state.points[0] + state.points[2]) / 2,
114+
(state.points[1] + state.points[3]) / 2,
115+
];
116+
const [rx, ry] = [state.points[2] - cx, cy - state.points[3]];
117+
points = state.shapeType === 'ellipse' ? [
118+
state.points[0] - rx,
119+
state.points[1] - ry,
120+
state.points[0] + rx,
121+
state.points[1] + ry,
122+
] : state.points;
123+
124+
points = [
125+
[points[0], points[1]],
126+
[points[2], points[1]],
127+
[points[2], points[3]],
128+
[points[0], points[3]],
129+
].map(([x, y]: number[]) => rotatePoint(x, y, state.rotation, cx, cy)).flat();
130+
}
131+
132+
onStartIssue(points);
110133
}
111134
} else if (param.key === ReviewContextMenuKeys.QUICK_ISSUE_POSITION) {
112135
if (state) {

cvat-ui/src/components/annotation-page/canvas/canvas-wrapper.tsx

-24
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ interface Props {
3232
activatedStateID: number | null;
3333
activatedAttributeID: number | null;
3434
annotations: any[];
35-
frameIssues: any[] | null;
3635
frameData: any;
3736
frameAngle: number;
3837
frameFetching: boolean;
@@ -136,7 +135,6 @@ export default class CanvasWrapperComponent extends React.PureComponent<Props> {
136135
});
137136

138137
this.initialSetup();
139-
this.updateIssueRegions();
140138
this.updateCanvas();
141139
}
142140

@@ -148,7 +146,6 @@ export default class CanvasWrapperComponent extends React.PureComponent<Props> {
148146
outlined,
149147
outlineColor,
150148
showBitmap,
151-
frameIssues,
152149
frameData,
153150
frameAngle,
154151
annotations,
@@ -256,10 +253,6 @@ export default class CanvasWrapperComponent extends React.PureComponent<Props> {
256253
}
257254
}
258255

259-
if (prevProps.frameIssues !== frameIssues) {
260-
this.updateIssueRegions();
261-
}
262-
263256
if (
264257
prevProps.annotations !== annotations ||
265258
prevProps.frameData !== frameData ||
@@ -684,23 +677,6 @@ export default class CanvasWrapperComponent extends React.PureComponent<Props> {
684677
}
685678
}
686679

687-
private updateIssueRegions(): void {
688-
const { frameIssues } = this.props;
689-
const { canvasInstance } = this.props as { canvasInstance: Canvas };
690-
if (frameIssues === null) {
691-
canvasInstance.setupIssueRegions({});
692-
} else {
693-
const regions = frameIssues.reduce((acc: Record<number, number[]>, issue: any): Record<
694-
number,
695-
number[]
696-
> => {
697-
acc[issue.id] = issue.position;
698-
return acc;
699-
}, {});
700-
canvasInstance.setupIssueRegions(regions);
701-
}
702-
}
703-
704680
private updateCanvas(): void {
705681
const {
706682
curZLayer, annotations, frameData, canvasInstance,

cvat-ui/src/components/annotation-page/review-workspace/controls-side-bar/issue-control.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2020-2021 Intel Corporation
1+
// Copyright (C) 2020-2022 Intel Corporation
22
//
33
// SPDX-License-Identifier: MIT
44

@@ -16,7 +16,7 @@ interface Props {
1616
selectIssuePosition(enabled: boolean): void;
1717
}
1818

19-
function ResizeControl(props: Props): JSX.Element {
19+
function CreateIssueControl(props: Props): JSX.Element {
2020
const { activeControl, canvasInstance, selectIssuePosition } = props;
2121

2222
return (
@@ -43,4 +43,4 @@ function ResizeControl(props: Props): JSX.Element {
4343
);
4444
}
4545

46-
export default React.memo(ResizeControl);
46+
export default React.memo(CreateIssueControl);

0 commit comments

Comments
 (0)