From 1f56fd286c7d966c3ddece9e6991147d8c5b59d7 Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Mon, 29 Mar 2021 14:00:25 +0300 Subject: [PATCH] Added switcher to maintain poylgon crop behaviour (#2961) (#3021) * Added switcher to maintain poylgon crop behaviour (#2961) * Updated versions & changelog --- CHANGELOG.md | 1 + cvat-canvas/package-lock.json | 2 +- cvat-canvas/package.json | 2 +- cvat-canvas/src/typescript/canvasModel.ts | 15 +++++++---- cvat-canvas/src/typescript/editHandler.ts | 10 +++++-- cvat-ui/package-lock.json | 2 +- cvat-ui/package.json | 2 +- cvat-ui/src/actions/settings-actions.ts | 12 ++++++++- .../annotation-page/canvas/canvas-wrapper.tsx | 17 +++++++++--- .../header/settings-modal/styles.scss | 1 + .../settings-modal/workspace-settings.tsx | 26 +++++++++++++++---- .../annotation-page/canvas/canvas-wrapper.tsx | 9 +++++-- .../settings-modal/workspace-settings.tsx | 10 ++++++- cvat-ui/src/reducers/interfaces.ts | 1 + cvat-ui/src/reducers/settings-reducer.ts | 16 ++++++++++-- 15 files changed, 101 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b483fc0..3ce06562 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Ability of upload manifest for dataset with images () - Annotations filters UI using react-awesome-query-builder (https://github.com/openvinotoolkit/cvat/issues/1418) - [ICDAR](https://rrc.cvc.uab.es/?ch=2) format support () +- Added switcher to maintain poylgon crop behaviour () ### Changed diff --git a/cvat-canvas/package-lock.json b/cvat-canvas/package-lock.json index de4b537c..3da4a7eb 100644 --- a/cvat-canvas/package-lock.json +++ b/cvat-canvas/package-lock.json @@ -1,6 +1,6 @@ { "name": "cvat-canvas", - "version": "2.3.2", + "version": "2.4.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/cvat-canvas/package.json b/cvat-canvas/package.json index 3a83007c..cfd5365b 100644 --- a/cvat-canvas/package.json +++ b/cvat-canvas/package.json @@ -1,6 +1,6 @@ { "name": "cvat-canvas", - "version": "2.3.2", + "version": "2.4.0", "description": "Part of Computer Vision Annotation Tool which presents its canvas library", "main": "src/canvas.ts", "scripts": { diff --git a/cvat-canvas/src/typescript/canvasModel.ts b/cvat-canvas/src/typescript/canvasModel.ts index d4bb5cb2..4a9fc3bd 100644 --- a/cvat-canvas/src/typescript/canvasModel.ts +++ b/cvat-canvas/src/typescript/canvasModel.ts @@ -57,6 +57,7 @@ export interface Configuration { undefinedAttrValue?: string; showProjections?: boolean; forceDisableEditing?: boolean; + intelligentPolygonCrop?: boolean; } export interface DrawData { @@ -621,25 +622,29 @@ export class CanvasModelImpl extends MasterImpl implements CanvasModel { } public configure(configuration: Configuration): void { - if (typeof configuration.displayAllText !== 'undefined') { + if (typeof configuration.displayAllText === 'boolean') { this.data.configuration.displayAllText = configuration.displayAllText; } - if (typeof configuration.showProjections !== 'undefined') { + if (typeof configuration.showProjections === 'boolean') { this.data.configuration.showProjections = configuration.showProjections; } - if (typeof configuration.autoborders !== 'undefined') { + if (typeof configuration.autoborders === 'boolean') { this.data.configuration.autoborders = configuration.autoborders; } - if (typeof configuration.undefinedAttrValue !== 'undefined') { + if (typeof configuration.undefinedAttrValue === 'string') { this.data.configuration.undefinedAttrValue = configuration.undefinedAttrValue; } - if (typeof configuration.forceDisableEditing !== 'undefined') { + if (typeof configuration.forceDisableEditing === 'boolean') { this.data.configuration.forceDisableEditing = configuration.forceDisableEditing; } + if (typeof configuration.intelligentPolygonCrop === 'boolean') { + this.data.configuration.intelligentPolygonCrop = configuration.intelligentPolygonCrop; + } + this.notify(UpdateReasons.CONFIG_UPDATED); } diff --git a/cvat-canvas/src/typescript/editHandler.ts b/cvat-canvas/src/typescript/editHandler.ts index ed880024..3c97c776 100644 --- a/cvat-canvas/src/typescript/editHandler.ts +++ b/cvat-canvas/src/typescript/editHandler.ts @@ -27,6 +27,7 @@ export class EditHandlerImpl implements EditHandler { private editLine: SVG.PolyLine; private clones: SVG.Polygon[]; private autobordersEnabled: boolean; + private intelligentCutEnabled: boolean; private setupTrailingPoint(circle: SVG.Circle): void { const head = this.editedShape.attr('points').split(' ').slice(0, this.editData.pointID).join(' '); @@ -259,11 +260,11 @@ export class EditHandlerImpl implements EditHandler { this.editLine.remove(); this.editLine = null; - if (pointsCriteria && lengthCriteria) { + if (pointsCriteria && lengthCriteria && this.intelligentCutEnabled) { this.clones.push(this.canvas.polygon(firstPart.join(' '))); this.selectPolygon(this.clones[0]); // left indexes1 and - } else if (!pointsCriteria && !lengthCriteria) { + } else if (!pointsCriteria && !lengthCriteria && this.intelligentCutEnabled) { this.clones.push(this.canvas.polygon(secondPart.join(' '))); this.selectPolygon(this.clones[0]); } else { @@ -384,6 +385,7 @@ export class EditHandlerImpl implements EditHandler { ) { this.autoborderHandler = autoborderHandler; this.autobordersEnabled = false; + this.intelligentCutEnabled = false; this.onEditDone = onEditDone; this.canvas = canvas; this.editData = null; @@ -423,6 +425,10 @@ export class EditHandlerImpl implements EditHandler { } } } + + if (typeof configuration.intelligentPolygonCrop === 'boolean') { + this.intelligentCutEnabled = configuration.intelligentPolygonCrop; + } } public transform(geometry: Geometry): void { diff --git a/cvat-ui/package-lock.json b/cvat-ui/package-lock.json index 49b675fa..7cbf6812 100644 --- a/cvat-ui/package-lock.json +++ b/cvat-ui/package-lock.json @@ -1,6 +1,6 @@ { "name": "cvat-ui", - "version": "1.16.1", + "version": "1.17.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/cvat-ui/package.json b/cvat-ui/package.json index 17f80665..106b1f7b 100644 --- a/cvat-ui/package.json +++ b/cvat-ui/package.json @@ -1,6 +1,6 @@ { "name": "cvat-ui", - "version": "1.16.1", + "version": "1.17.0", "description": "CVAT single-page application", "main": "src/index.tsx", "scripts": { diff --git a/cvat-ui/src/actions/settings-actions.ts b/cvat-ui/src/actions/settings-actions.ts index 981deae9..32aa3d41 100644 --- a/cvat-ui/src/actions/settings-actions.ts +++ b/cvat-ui/src/actions/settings-actions.ts @@ -1,4 +1,4 @@ -// Copyright (C) 2020 Intel Corporation +// Copyright (C) 2020-2021 Intel Corporation // // SPDX-License-Identifier: MIT @@ -27,6 +27,7 @@ export enum SettingsActionTypes { CHANGE_AUTO_SAVE_INTERVAL = 'CHANGE_AUTO_SAVE_INTERVAL', CHANGE_AAM_ZOOM_MARGIN = 'CHANGE_AAM_ZOOM_MARGIN', SWITCH_AUTOMATIC_BORDERING = 'SWITCH_AUTOMATIC_BORDERING', + SWITCH_INTELLIGENT_POLYGON_CROP = 'SWITCH_INTELLIGENT_POLYGON_CROP', SWITCH_SHOWNIG_INTERPOLATED_TRACKS = 'SWITCH_SHOWNIG_INTERPOLATED_TRACKS', SWITCH_SHOWING_OBJECTS_TEXT_ALWAYS = 'SWITCH_SHOWING_OBJECTS_TEXT_ALWAYS', CHANGE_CANVAS_BACKGROUND_COLOR = 'CHANGE_CANVAS_BACKGROUND_COLOR', @@ -241,6 +242,15 @@ export function switchAutomaticBordering(automaticBordering: boolean): AnyAction }; } +export function switchIntelligentPolygonCrop(intelligentPolygonCrop: boolean): AnyAction { + return { + type: SettingsActionTypes.SWITCH_INTELLIGENT_POLYGON_CROP, + payload: { + intelligentPolygonCrop, + }, + }; +} + export function changeCanvasBackgroundColor(color: string): AnyAction { return { type: SettingsActionTypes.CHANGE_CANVAS_BACKGROUND_COLOR, diff --git a/cvat-ui/src/components/annotation-page/canvas/canvas-wrapper.tsx b/cvat-ui/src/components/annotation-page/canvas/canvas-wrapper.tsx index fcae62d5..5909816a 100644 --- a/cvat-ui/src/components/annotation-page/canvas/canvas-wrapper.tsx +++ b/cvat-ui/src/components/annotation-page/canvas/canvas-wrapper.tsx @@ -3,12 +3,12 @@ // SPDX-License-Identifier: MIT import React from 'react'; -import GlobalHotKeys, { KeyMap } from 'utils/mousetrap-react'; import Layout from 'antd/lib/layout'; import Slider from 'antd/lib/slider'; import Dropdown from 'antd/lib/dropdown'; import { PlusCircleOutlined, UpOutlined } from '@ant-design/icons'; +import GlobalHotKeys, { KeyMap } from 'utils/mousetrap-react'; import { ColorBy, GridColor, ObjectType, ContextMenuType, Workspace, ShapeType, } from 'reducers/interfaces'; @@ -61,6 +61,7 @@ interface Props { showAllInterpolationTracks: boolean; workspace: Workspace; automaticBordering: boolean; + intelligentPolygonCrop: boolean; keyMap: KeyMap; canvasBackgroundColor: string; switchableAutomaticBordering: boolean; @@ -98,7 +99,12 @@ interface Props { export default class CanvasWrapperComponent extends React.PureComponent { public componentDidMount(): void { const { - automaticBordering, showObjectsTextAlways, canvasInstance, workspace, + automaticBordering, + intelligentPolygonCrop, + showObjectsTextAlways, + canvasInstance, + workspace, + showProjections, } = this.props; // It's awful approach from the point of view React @@ -111,6 +117,8 @@ export default class CanvasWrapperComponent extends React.PureComponent { undefinedAttrValue: consts.UNDEFINED_ATTRIBUTE_VALUE, displayAllText: showObjectsTextAlways, forceDisableEditing: workspace === Workspace.REVIEW_WORKSPACE, + intelligentPolygonCrop, + showProjections, }); this.initialSetup(); @@ -147,6 +155,7 @@ export default class CanvasWrapperComponent extends React.PureComponent { showObjectsTextAlways, showAllInterpolationTracks, automaticBordering, + intelligentPolygonCrop, showProjections, canvasBackgroundColor, onFetchAnnotation, @@ -155,13 +164,15 @@ export default class CanvasWrapperComponent extends React.PureComponent { if ( prevProps.showObjectsTextAlways !== showObjectsTextAlways || prevProps.automaticBordering !== automaticBordering || - prevProps.showProjections !== showProjections + prevProps.showProjections !== showProjections || + prevProps.intelligentPolygonCrop !== intelligentPolygonCrop ) { canvasInstance.configure({ undefinedAttrValue: consts.UNDEFINED_ATTRIBUTE_VALUE, displayAllText: showObjectsTextAlways, autoborders: automaticBordering, showProjections, + intelligentPolygonCrop, }); } diff --git a/cvat-ui/src/components/header/settings-modal/styles.scss b/cvat-ui/src/components/header/settings-modal/styles.scss index f47a7d52..06fd21a9 100644 --- a/cvat-ui/src/components/header/settings-modal/styles.scss +++ b/cvat-ui/src/components/header/settings-modal/styles.scss @@ -25,6 +25,7 @@ .cvat-workspace-settings-auto-save, .cvat-workspace-settings-autoborders, +.cvat-workspace-settings-intelligent-polygon-cropping, .cvat-workspace-settings-show-text-always, .cvat-workspace-settings-show-interpolated { margin-bottom: 25px; diff --git a/cvat-ui/src/components/header/settings-modal/workspace-settings.tsx b/cvat-ui/src/components/header/settings-modal/workspace-settings.tsx index a66a0a3c..1aef81de 100644 --- a/cvat-ui/src/components/header/settings-modal/workspace-settings.tsx +++ b/cvat-ui/src/components/header/settings-modal/workspace-settings.tsx @@ -1,4 +1,4 @@ -// Copyright (C) 2020 Intel Corporation +// Copyright (C) 2020-2021 Intel Corporation // // SPDX-License-Identifier: MIT @@ -18,12 +18,14 @@ interface Props { showAllInterpolationTracks: boolean; showObjectsTextAlways: boolean; automaticBordering: boolean; + intelligentPolygonCrop: boolean; onSwitchAutoSave(enabled: boolean): void; onChangeAutoSaveInterval(interval: number): void; onChangeAAMZoomMargin(margin: number): void; onSwitchShowingInterpolatedTracks(enabled: boolean): void; onSwitchShowingObjectsTextAlways(enabled: boolean): void; onSwitchAutomaticBordering(enabled: boolean): void; + onSwitchIntelligentPolygonCrop(enabled: boolean): void; } export default function WorkspaceSettingsComponent(props: Props): JSX.Element { @@ -34,12 +36,14 @@ export default function WorkspaceSettingsComponent(props: Props): JSX.Element { showAllInterpolationTracks, showObjectsTextAlways, automaticBordering, + intelligentPolygonCrop, onSwitchAutoSave, onChangeAutoSaveInterval, onChangeAAMZoomMargin, onSwitchShowingInterpolatedTracks, onSwitchShowingObjectsTextAlways, onSwitchAutomaticBordering, + onSwitchIntelligentPolygonCrop, } = props; const minAutoSaveInterval = 1; @@ -111,9 +115,7 @@ export default function WorkspaceSettingsComponent(props: Props): JSX.Element { - {' '} Show text for an object on the canvas not only when the object is activated - {' '} @@ -131,12 +133,26 @@ export default function WorkspaceSettingsComponent(props: Props): JSX.Element { - {' '} Enable automatic bordering for polygons and polylines during drawing/editing - {' '} + + + { + onSwitchIntelligentPolygonCrop(event.target.checked); + }} + > + Intelligent polygon cropping + + + + Try to crop polygons automatically when editing + + Attribute annotation mode (AAM) zoom margin diff --git a/cvat-ui/src/containers/annotation-page/canvas/canvas-wrapper.tsx b/cvat-ui/src/containers/annotation-page/canvas/canvas-wrapper.tsx index 359c0598..4581c436 100644 --- a/cvat-ui/src/containers/annotation-page/canvas/canvas-wrapper.tsx +++ b/cvat-ui/src/containers/annotation-page/canvas/canvas-wrapper.tsx @@ -2,9 +2,9 @@ // // SPDX-License-Identifier: MIT -import { KeyMap } from 'utils/mousetrap-react'; import { connect } from 'react-redux'; +import { KeyMap } from 'utils/mousetrap-react'; import CanvasWrapperComponent from 'components/annotation-page/canvas/canvas-wrapper'; import { confirmCanvasReady, @@ -159,7 +159,11 @@ function mapStateToProps(state: CombinedState): StateToProps { resetZoom, }, workspace: { - aamZoomMargin, showObjectsTextAlways, showAllInterpolationTracks, automaticBordering, + aamZoomMargin, + showObjectsTextAlways, + showAllInterpolationTracks, + automaticBordering, + intelligentPolygonCrop, }, shapes: { opacity, colorBy, selectedOpacity, outlined, outlineColor, showBitmap, showProjections, @@ -207,6 +211,7 @@ function mapStateToProps(state: CombinedState): StateToProps { minZLayer, maxZLayer, automaticBordering, + intelligentPolygonCrop, workspace, keyMap, canvasBackgroundColor, diff --git a/cvat-ui/src/containers/header/settings-modal/workspace-settings.tsx b/cvat-ui/src/containers/header/settings-modal/workspace-settings.tsx index 9f615a35..2384c166 100644 --- a/cvat-ui/src/containers/header/settings-modal/workspace-settings.tsx +++ b/cvat-ui/src/containers/header/settings-modal/workspace-settings.tsx @@ -1,4 +1,4 @@ -// Copyright (C) 2020 Intel Corporation +// Copyright (C) 2020-2021 Intel Corporation // // SPDX-License-Identifier: MIT @@ -12,6 +12,7 @@ import { switchShowingInterpolatedTracks, switchShowingObjectsTextAlways, switchAutomaticBordering, + switchIntelligentPolygonCrop, } from 'actions/settings-actions'; import { CombinedState } from 'reducers/interfaces'; @@ -25,6 +26,7 @@ interface StateToProps { showAllInterpolationTracks: boolean; showObjectsTextAlways: boolean; automaticBordering: boolean; + intelligentPolygonCrop: boolean; } interface DispatchToProps { @@ -34,6 +36,7 @@ interface DispatchToProps { onSwitchShowingInterpolatedTracks(enabled: boolean): void; onSwitchShowingObjectsTextAlways(enabled: boolean): void; onSwitchAutomaticBordering(enabled: boolean): void; + onSwitchIntelligentPolygonCrop(enabled: boolean): void; } function mapStateToProps(state: CombinedState): StateToProps { @@ -45,6 +48,7 @@ function mapStateToProps(state: CombinedState): StateToProps { showAllInterpolationTracks, showObjectsTextAlways, automaticBordering, + intelligentPolygonCrop, } = workspace; return { @@ -54,6 +58,7 @@ function mapStateToProps(state: CombinedState): StateToProps { showAllInterpolationTracks, showObjectsTextAlways, automaticBordering, + intelligentPolygonCrop, }; } @@ -77,6 +82,9 @@ function mapDispatchToProps(dispatch: any): DispatchToProps { onSwitchAutomaticBordering(enabled: boolean): void { dispatch(switchAutomaticBordering(enabled)); }, + onSwitchIntelligentPolygonCrop(enabled: boolean): void { + dispatch(switchIntelligentPolygonCrop(enabled)); + }, }; } diff --git a/cvat-ui/src/reducers/interfaces.ts b/cvat-ui/src/reducers/interfaces.ts index 5c3f48c6..45af4585 100644 --- a/cvat-ui/src/reducers/interfaces.ts +++ b/cvat-ui/src/reducers/interfaces.ts @@ -518,6 +518,7 @@ export interface WorkspaceSettingsState { automaticBordering: boolean; showObjectsTextAlways: boolean; showAllInterpolationTracks: boolean; + intelligentPolygonCrop: boolean; } export interface ShapesSettingsState { diff --git a/cvat-ui/src/reducers/settings-reducer.ts b/cvat-ui/src/reducers/settings-reducer.ts index 876dd34b..cdc811d4 100644 --- a/cvat-ui/src/reducers/settings-reducer.ts +++ b/cvat-ui/src/reducers/settings-reducer.ts @@ -1,4 +1,4 @@ -// Copyright (C) 2020 Intel Corporation +// Copyright (C) 2020-2021 Intel Corporation // // SPDX-License-Identifier: MIT @@ -9,7 +9,9 @@ import { AuthActionTypes } from 'actions/auth-actions'; import { SettingsActionTypes } from 'actions/settings-actions'; import { AnnotationActionTypes } from 'actions/annotation-actions'; -import { SettingsState, GridColor, FrameSpeed, ColorBy } from './interfaces'; +import { + SettingsState, GridColor, FrameSpeed, ColorBy, +} from './interfaces'; const defaultState: SettingsState = { shapes: { @@ -28,6 +30,7 @@ const defaultState: SettingsState = { automaticBordering: false, showObjectsTextAlways: false, showAllInterpolationTracks: false, + intelligentPolygonCrop: true, }, player: { canvasBackgroundColor: '#ffffff', @@ -256,6 +259,15 @@ export default (state = defaultState, action: AnyAction): SettingsState => { }, }; } + case SettingsActionTypes.SWITCH_INTELLIGENT_POLYGON_CROP: { + return { + ...state, + workspace: { + ...state.workspace, + intelligentPolygonCrop: action.payload.intelligentPolygonCrop, + }, + }; + } case SettingsActionTypes.CHANGE_CANVAS_BACKGROUND_COLOR: { return { ...state,