React UI: cuboid interpolation and cuboid drawing from rectangles (#1560)

* Added backend cuboid interpolation and cuboid drawing from rectangles
* Added CHANELOG.md
* Fixed cuboid front edges stroke width
* PR fixes
main
Dmitry Kalinin 6 years ago committed by GitHub
parent 42fb305d67
commit 5816494694
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- cvat-ui: added cookie policy drawer for login page (<https://github.com/opencv/cvat/pull/1511>) - cvat-ui: added cookie policy drawer for login page (<https://github.com/opencv/cvat/pull/1511>)
- Added `datumaro_project` export format (https://github.com/opencv/cvat/pull/1352) - Added `datumaro_project` export format (https://github.com/opencv/cvat/pull/1352)
- Ability to configure user agreements for the user registration form (https://github.com/opencv/cvat/pull/1464) - Ability to configure user agreements for the user registration form (https://github.com/opencv/cvat/pull/1464)
- Added cuboid interpolation and cuboid drawing from rectangles (<https://github.com/opencv/cvat/pull/1560>)
### Changed ### Changed
- Downloaded file name in annotations export became more informative (https://github.com/opencv/cvat/pull/1352) - Downloaded file name in annotations export became more informative (https://github.com/opencv/cvat/pull/1352)

@ -37,6 +37,11 @@ Canvas itself handles:
EXTREME_POINTS = 'By 4 points' EXTREME_POINTS = 'By 4 points'
} }
enum CuboidDrawingMethod {
CLASSIC = 'From rectangle',
CORNER_POINTS = 'By 4 points',
}
enum Mode { enum Mode {
IDLE = 'idle', IDLE = 'idle',
DRAG = 'drag', DRAG = 'drag',
@ -59,6 +64,7 @@ Canvas itself handles:
enabled: boolean; enabled: boolean;
shapeType?: string; shapeType?: string;
rectDrawingMethod?: RectDrawingMethod; rectDrawingMethod?: RectDrawingMethod;
cuboidDrawingMethod?: CuboidDrawingMethod;
numberOfPoints?: number; numberOfPoints?: number;
initialState?: any; initialState?: any;
crosshair?: boolean; crosshair?: boolean;

@ -1,6 +1,6 @@
{ {
"name": "cvat-canvas", "name": "cvat-canvas",
"version": "1.0.0", "version": "1.1.0",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {

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

@ -11,6 +11,7 @@ import {
CanvasModel, CanvasModel,
CanvasModelImpl, CanvasModelImpl,
RectDrawingMethod, RectDrawingMethod,
CuboidDrawingMethod,
Configuration, Configuration,
} from './canvasModel'; } from './canvasModel';
@ -159,5 +160,6 @@ export {
CanvasVersion, CanvasVersion,
Configuration, Configuration,
RectDrawingMethod, RectDrawingMethod,
CuboidDrawingMethod,
Mode as CanvasMode, Mode as CanvasMode,
}; };

@ -46,6 +46,11 @@ export enum RectDrawingMethod {
EXTREME_POINTS = 'By 4 points' EXTREME_POINTS = 'By 4 points'
} }
export enum CuboidDrawingMethod {
CLASSIC = 'From rectangle',
CORNER_POINTS = 'By 4 points',
}
export interface Configuration { export interface Configuration {
autoborders?: boolean; autoborders?: boolean;
displayAllText?: boolean; displayAllText?: boolean;
@ -57,6 +62,7 @@ export interface DrawData {
enabled: boolean; enabled: boolean;
shapeType?: string; shapeType?: string;
rectDrawingMethod?: RectDrawingMethod; rectDrawingMethod?: RectDrawingMethod;
cuboidDrawingMethod?: CuboidDrawingMethod;
numberOfPoints?: number; numberOfPoints?: number;
initialState?: any; initialState?: any;
crosshair?: boolean; crosshair?: boolean;

@ -11,6 +11,8 @@ const SIZE_THRESHOLD = 3;
const POINTS_STROKE_WIDTH = 1.5; const POINTS_STROKE_WIDTH = 1.5;
const POINTS_SELECTED_STROKE_WIDTH = 4; const POINTS_SELECTED_STROKE_WIDTH = 4;
const MIN_EDGE_LENGTH = 3; const MIN_EDGE_LENGTH = 3;
const CUBOID_ACTIVE_EDGE_STROKE_WIDTH = 2.5;
const CUBOID_UNACTIVE_EDGE_STROKE_WIDTH = 1.75;
const UNDEFINED_ATTRIBUTE_VALUE = '__undefined__'; const UNDEFINED_ATTRIBUTE_VALUE = '__undefined__';
export default { export default {
@ -23,5 +25,7 @@ export default {
POINTS_STROKE_WIDTH, POINTS_STROKE_WIDTH,
POINTS_SELECTED_STROKE_WIDTH, POINTS_SELECTED_STROKE_WIDTH,
MIN_EDGE_LENGTH, MIN_EDGE_LENGTH,
CUBOID_ACTIVE_EDGE_STROKE_WIDTH,
CUBOID_UNACTIVE_EDGE_STROKE_WIDTH,
UNDEFINED_ATTRIBUTE_VALUE, UNDEFINED_ATTRIBUTE_VALUE,
}; };

@ -22,6 +22,7 @@ import {
Geometry, Geometry,
RectDrawingMethod, RectDrawingMethod,
Configuration, Configuration,
CuboidDrawingMethod,
} from './canvasModel'; } from './canvasModel';
import { cuboidFrom4Points } from './cuboid'; import { cuboidFrom4Points } from './cuboid';
@ -227,7 +228,8 @@ export class DrawHandlerImpl implements DrawHandler {
// Or when no drawn points, but we call cancel() drawing // Or when no drawn points, but we call cancel() drawing
// We check if it is activated with remember function // We check if it is activated with remember function
if (this.drawInstance.remember('_paintHandler')) { if (this.drawInstance.remember('_paintHandler')) {
if (this.drawData.shapeType !== 'rectangle') { if (this.drawData.shapeType !== 'rectangle'
&& this.drawData.cuboidDrawingMethod !== CuboidDrawingMethod.CLASSIC) {
// Check for unsaved drawn shapes // Check for unsaved drawn shapes
this.drawInstance.draw('done'); this.drawInstance.draw('done');
} }
@ -451,7 +453,7 @@ export class DrawHandlerImpl implements DrawHandler {
this.drawPolyshape(); this.drawPolyshape();
} }
private drawCuboid(): void { private drawCuboidBy4Points(): void {
this.drawInstance = (this.canvas as any).polyline() this.drawInstance = (this.canvas as any).polyline()
.addClass('cvat_canvas_shape_drawing').attr({ .addClass('cvat_canvas_shape_drawing').attr({
'stroke-width': consts.BASE_STROKE_WIDTH / this.geometry.scale, 'stroke-width': consts.BASE_STROKE_WIDTH / this.geometry.scale,
@ -459,6 +461,29 @@ export class DrawHandlerImpl implements DrawHandler {
this.drawPolyshape(); this.drawPolyshape();
} }
private drawCuboid(): void {
this.drawInstance = this.canvas.rect();
this.drawInstance.on('drawstop', (e: Event): void => {
const bbox = (e.target as SVGRectElement).getBBox();
const [xtl, ytl, xbr, ybr] = this.getFinalRectCoordinates(bbox);
const { shapeType } = this.drawData;
this.release();
if (this.canceled) return;
if ((xbr - xtl) * (ybr - ytl) >= consts.AREA_THRESHOLD) {
const d = { x: (xbr - xtl) * 0.1, y: (ybr - ytl)*0.1}
this.onDrawDone({
shapeType,
points: cuboidFrom4Points([xtl, ybr, xbr, ybr, xbr, ytl, xbr + d.x, ytl - d.y]),
}, Date.now() - this.startTimestamp);
}
}).on('drawupdate', (): void => {
this.shapeSizeElement.update(this.drawInstance);
}).addClass('cvat_canvas_shape_drawing').attr({
'stroke-width': consts.BASE_STROKE_WIDTH / this.geometry.scale,
});
}
private pastePolyshape(): void { private pastePolyshape(): void {
this.drawInstance.on('done', (e: CustomEvent): void => { this.drawInstance.on('done', (e: CustomEvent): void => {
const targetPoints = this.drawInstance const targetPoints = this.drawInstance
@ -679,7 +704,12 @@ export class DrawHandlerImpl implements DrawHandler {
} else if (this.drawData.shapeType === 'points') { } else if (this.drawData.shapeType === 'points') {
this.drawPoints(); this.drawPoints();
} else if (this.drawData.shapeType === 'cuboid') { } else if (this.drawData.shapeType === 'cuboid') {
this.drawCuboid(); if (this.drawData.cuboidDrawingMethod === CuboidDrawingMethod.CORNER_POINTS) {
this.drawCuboidBy4Points();
} else {
this.drawCuboid();
this.shapeSizeElement = displayShapeSize(this.canvas, this.text);
}
} }
this.setupDrawEvents(); this.setupDrawEvents();
} }

@ -248,8 +248,8 @@ function getTopDown(edgeIndex: EdgeIndex): number[] {
this.bot = this.polygon(this.cuboidModel.bot.points); this.bot = this.polygon(this.cuboidModel.bot.points);
this.top = this.polygon(this.cuboidModel.top.points); this.top = this.polygon(this.cuboidModel.top.points);
this.right = this.polygon(this.cuboidModel.right.points); this.right = this.polygon(this.cuboidModel.right.points);
this.dorsal = this.polygon(this.cuboidModel.dorsal.points);
this.left = this.polygon(this.cuboidModel.left.points); this.left = this.polygon(this.cuboidModel.left.points);
this.dorsal = this.polygon(this.cuboidModel.dorsal.points);
this.face = this.polygon(this.cuboidModel.front.points); this.face = this.polygon(this.cuboidModel.front.points);
}, },
@ -631,6 +631,7 @@ function getTopDown(edgeIndex: EdgeIndex): number[] {
this.cuboidModel.dr.points = [topPoint, botPoint]; this.cuboidModel.dr.points = [topPoint, botPoint];
this.updateViewAndVM(); this.updateViewAndVM();
this.fire(new CustomEvent('resizing', event));
}).on('dragend', (event: CustomEvent) => { }).on('dragend', (event: CustomEvent) => {
this.fire(new CustomEvent('resizedone', event)); this.fire(new CustomEvent('resizedone', event));
}); });
@ -658,6 +659,7 @@ function getTopDown(edgeIndex: EdgeIndex): number[] {
this.cuboidModel.dl.points = [topPoint, botPoint]; this.cuboidModel.dl.points = [topPoint, botPoint];
this.updateViewAndVM(true); this.updateViewAndVM(true);
this.fire(new CustomEvent('resizing', event));
}).on('dragend', (event: CustomEvent) => { }).on('dragend', (event: CustomEvent) => {
this.fire(new CustomEvent('resizedone', event)); this.fire(new CustomEvent('resizedone', event));
});; });;
@ -856,16 +858,17 @@ function getTopDown(edgeIndex: EdgeIndex): number[] {
const edges = [this.frontLeftEdge, this.frontRightEdge, this.frontTopEdge, this.frontBotEdge] const edges = [this.frontLeftEdge, this.frontRightEdge, this.frontTopEdge, this.frontBotEdge]
const width = this.attr('stroke-width'); const width = this.attr('stroke-width');
edges.forEach((edge: SVG.Element) => { edges.forEach((edge: SVG.Element) => {
edge.attr('stroke-width', width * (this.strokeOffset || 1.75)); edge.attr('stroke-width', width * (this.strokeOffset || consts.CUBOID_UNACTIVE_EDGE_STROKE_WIDTH));
}); });
this.on('mouseover', () => { this.on('mouseover', () => {
edges.forEach((edge: SVG.Element) => { edges.forEach((edge: SVG.Element) => {
this.strokeOffset = 2.5; this.strokeOffset = this.node.classList.contains('cvat_canvas_shape_activated')
? consts.CUBOID_ACTIVE_EDGE_STROKE_WIDTH : consts.CUBOID_UNACTIVE_EDGE_STROKE_WIDTH;
edge.attr('stroke-width', width * this.strokeOffset); edge.attr('stroke-width', width * this.strokeOffset);
}) })
}).on('mouseout', () => { }).on('mouseout', () => {
edges.forEach((edge: SVG.Element) => { edges.forEach((edge: SVG.Element) => {
this.strokeOffset = 1.75; this.strokeOffset = consts.CUBOID_UNACTIVE_EDGE_STROKE_WIDTH;
edge.attr('stroke-width', width * this.strokeOffset); edge.attr('stroke-width', width * this.strokeOffset);
}) })
}); });

@ -1,6 +1,6 @@
{ {
"name": "cvat-core", "name": "cvat-core",
"version": "2.0.0", "version": "2.0.1",
"description": "Part of Computer Vision Tool which presents an interface for client-side integration", "description": "Part of Computer Vision Tool which presents an interface for client-side integration",
"main": "babel.config.js", "main": "babel.config.js",
"scripts": { "scripts": {

@ -1402,7 +1402,7 @@
} }
} }
class CuboidShape extends PolyShape { class CuboidShape extends Shape {
constructor(data, clientID, color, injection) { constructor(data, clientID, color, injection) {
super(data, clientID, color, injection); super(data, clientID, color, injection);
this.shapeType = ObjectShape.CUBOID; this.shapeType = ObjectShape.CUBOID;
@ -1967,7 +1967,7 @@
} }
} }
class CuboidTrack extends PolyTrack { class CuboidTrack extends Track {
constructor(data, clientID, color, injection) { constructor(data, clientID, color, injection) {
super(data, clientID, color, injection); super(data, clientID, color, injection);
this.shapeType = ObjectShape.CUBOID; this.shapeType = ObjectShape.CUBOID;
@ -1976,6 +1976,22 @@
checkNumberOfPoints(this.shapeType, shape.points); checkNumberOfPoints(this.shapeType, shape.points);
} }
} }
interpolatePosition(leftPosition, rightPosition, offset) {
const positionOffset = leftPosition.points.map((point, index) => (
rightPosition.points[index] - point
))
return {
points: leftPosition.points.map((point ,index) => (
point + positionOffset[index] * offset
)),
occluded: leftPosition.occluded,
outside: leftPosition.outside,
zOrder: leftPosition.zOrder,
};
}
} }
RectangleTrack.distance = RectangleShape.distance; RectangleTrack.distance = RectangleShape.distance;
@ -1983,7 +1999,6 @@
PolylineTrack.distance = PolylineShape.distance; PolylineTrack.distance = PolylineShape.distance;
PointsTrack.distance = PointsShape.distance; PointsTrack.distance = PointsShape.distance;
CuboidTrack.distance = CuboidShape.distance; CuboidTrack.distance = CuboidShape.distance;
CuboidTrack.interpolatePosition = RectangleTrack.interpolatePosition;
module.exports = { module.exports = {
RectangleShape, RectangleShape,

@ -1,6 +1,6 @@
{ {
"name": "cvat-ui", "name": "cvat-ui",
"version": "1.1.3", "version": "1.1.4",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {

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

@ -11,7 +11,7 @@ import Radio, { RadioChangeEvent } from 'antd/lib/radio';
import Tooltip from 'antd/lib/tooltip'; import Tooltip from 'antd/lib/tooltip';
import Text from 'antd/lib/typography/Text'; import Text from 'antd/lib/typography/Text';
import { RectDrawingMethod } from 'cvat-canvas-wrapper'; import { RectDrawingMethod, CuboidDrawingMethod } from 'cvat-canvas-wrapper';
import { ShapeType } from 'reducers/interfaces'; import { ShapeType } from 'reducers/interfaces';
import { clamp } from 'utils/math'; import { clamp } from 'utils/math';
import DEXTRPlugin from './dextr-plugin'; import DEXTRPlugin from './dextr-plugin';
@ -21,12 +21,14 @@ interface Props {
labels: any[]; labels: any[];
minimumPoints: number; minimumPoints: number;
rectDrawingMethod?: RectDrawingMethod; rectDrawingMethod?: RectDrawingMethod;
cuboidDrawingMethod?: CuboidDrawingMethod;
numberOfPoints?: number; numberOfPoints?: number;
selectedLabeID: number; selectedLabeID: number;
repeatShapeShortcut: string; repeatShapeShortcut: string;
onChangeLabel(value: string): void; onChangeLabel(value: string): void;
onChangePoints(value: number | undefined): void; onChangePoints(value: number | undefined): void;
onChangeRectDrawingMethod(event: RadioChangeEvent): void; onChangeRectDrawingMethod(event: RadioChangeEvent): void;
onChangeCuboidDrawingMethod(event: RadioChangeEvent): void;
onDrawTrack(): void; onDrawTrack(): void;
onDrawShape(): void; onDrawShape(): void;
} }
@ -39,16 +41,18 @@ function DrawShapePopoverComponent(props: Props): JSX.Element {
selectedLabeID, selectedLabeID,
numberOfPoints, numberOfPoints,
rectDrawingMethod, rectDrawingMethod,
cuboidDrawingMethod,
repeatShapeShortcut, repeatShapeShortcut,
onDrawTrack, onDrawTrack,
onDrawShape, onDrawShape,
onChangeLabel, onChangeLabel,
onChangePoints, onChangePoints,
onChangeRectDrawingMethod, onChangeRectDrawingMethod,
onChangeCuboidDrawingMethod,
} = props; } = props;
const trackDisabled = shapeType === ShapeType.POLYGON || shapeType === ShapeType.POLYLINE const trackDisabled = shapeType === ShapeType.POLYGON || shapeType === ShapeType.POLYLINE
|| shapeType === ShapeType.CUBOID || (shapeType === ShapeType.POINTS && numberOfPoints !== 1); || (shapeType === ShapeType.POINTS && numberOfPoints !== 1);
return ( return (
<div className='cvat-draw-shape-popover-content'> <div className='cvat-draw-shape-popover-content'>
@ -117,6 +121,39 @@ function DrawShapePopoverComponent(props: Props): JSX.Element {
</> </>
) )
} }
{
shapeType === ShapeType.CUBOID && (
<>
<Row>
<Col>
<Text className='cvat-text-color'> Drawing method </Text>
</Col>
</Row>
<Row type='flex' justify='space-around'>
<Col>
<Radio.Group
style={{ display: 'flex' }}
value={cuboidDrawingMethod}
onChange={onChangeCuboidDrawingMethod}
>
<Radio
value={CuboidDrawingMethod.CLASSIC}
style={{ width: 'auto' }}
>
From rectangle
</Radio>
<Radio
value={CuboidDrawingMethod.CORNER_POINTS}
style={{ width: 'auto' }}
>
By 4 Points
</Radio>
</Radio.Group>
</Col>
</Row>
</>
)
}
{ {
shapeType !== ShapeType.RECTANGLE && shapeType !== ShapeType.CUBOID && ( shapeType !== ShapeType.RECTANGLE && shapeType !== ShapeType.CUBOID && (
<Row type='flex' justify='space-around' align='middle'> <Row type='flex' justify='space-around' align='middle'>

@ -8,7 +8,7 @@ import { RadioChangeEvent } from 'antd/lib/radio';
import { CombinedState, ShapeType, ObjectType } from 'reducers/interfaces'; import { CombinedState, ShapeType, ObjectType } from 'reducers/interfaces';
import { rememberObject } from 'actions/annotation-actions'; import { rememberObject } from 'actions/annotation-actions';
import { Canvas, RectDrawingMethod } from 'cvat-canvas-wrapper'; import { Canvas, RectDrawingMethod, CuboidDrawingMethod } from 'cvat-canvas-wrapper';
import DrawShapePopoverComponent from 'components/annotation-page/standard-workspace/controls-side-bar/draw-shape-popover'; import DrawShapePopoverComponent from 'components/annotation-page/standard-workspace/controls-side-bar/draw-shape-popover';
interface OwnProps { interface OwnProps {
@ -73,6 +73,7 @@ type Props = StateToProps & DispatchToProps;
interface State { interface State {
rectDrawingMethod?: RectDrawingMethod; rectDrawingMethod?: RectDrawingMethod;
cuboidDrawingMethod?: CuboidDrawingMethod;
numberOfPoints?: number; numberOfPoints?: number;
selectedLabelID: number; selectedLabelID: number;
} }
@ -85,10 +86,13 @@ class DrawShapePopoverContainer extends React.PureComponent<Props, State> {
const { shapeType } = props; const { shapeType } = props;
const defaultLabelID = props.labels[0].id; const defaultLabelID = props.labels[0].id;
const defaultRectDrawingMethod = RectDrawingMethod.CLASSIC; const defaultRectDrawingMethod = RectDrawingMethod.CLASSIC;
const defaultCuboidDrawingMethod = CuboidDrawingMethod.CLASSIC;
this.state = { this.state = {
selectedLabelID: defaultLabelID, selectedLabelID: defaultLabelID,
rectDrawingMethod: shapeType === ShapeType.RECTANGLE rectDrawingMethod: shapeType === ShapeType.RECTANGLE
? defaultRectDrawingMethod : undefined, ? defaultRectDrawingMethod : undefined,
cuboidDrawingMethod: shapeType === ShapeType.CUBOID
? defaultCuboidDrawingMethod : undefined,
}; };
if (shapeType === ShapeType.POLYGON) { if (shapeType === ShapeType.POLYGON) {
@ -111,6 +115,7 @@ class DrawShapePopoverContainer extends React.PureComponent<Props, State> {
const { const {
rectDrawingMethod, rectDrawingMethod,
cuboidDrawingMethod,
numberOfPoints, numberOfPoints,
selectedLabelID, selectedLabelID,
} = this.state; } = this.state;
@ -119,6 +124,7 @@ class DrawShapePopoverContainer extends React.PureComponent<Props, State> {
canvasInstance.draw({ canvasInstance.draw({
enabled: true, enabled: true,
rectDrawingMethod, rectDrawingMethod,
cuboidDrawingMethod,
numberOfPoints, numberOfPoints,
shapeType, shapeType,
crosshair: [ShapeType.RECTANGLE, ShapeType.CUBOID].includes(shapeType), crosshair: [ShapeType.RECTANGLE, ShapeType.CUBOID].includes(shapeType),
@ -134,6 +140,12 @@ class DrawShapePopoverContainer extends React.PureComponent<Props, State> {
}); });
}; };
private onChangeCuboidDrawingMethod = (event: RadioChangeEvent): void => {
this.setState({
cuboidDrawingMethod: event.target.value,
})
}
private onDrawShape = (): void => { private onDrawShape = (): void => {
this.onDraw(ObjectType.SHAPE); this.onDraw(ObjectType.SHAPE);
}; };
@ -157,6 +169,7 @@ class DrawShapePopoverContainer extends React.PureComponent<Props, State> {
public render(): JSX.Element { public render(): JSX.Element {
const { const {
rectDrawingMethod, rectDrawingMethod,
cuboidDrawingMethod,
selectedLabelID, selectedLabelID,
numberOfPoints, numberOfPoints,
} = this.state; } = this.state;
@ -175,10 +188,12 @@ class DrawShapePopoverContainer extends React.PureComponent<Props, State> {
selectedLabeID={selectedLabelID} selectedLabeID={selectedLabelID}
numberOfPoints={numberOfPoints} numberOfPoints={numberOfPoints}
rectDrawingMethod={rectDrawingMethod} rectDrawingMethod={rectDrawingMethod}
cuboidDrawingMethod={cuboidDrawingMethod}
repeatShapeShortcut={normalizedKeyMap.SWITCH_DRAW_MODE} repeatShapeShortcut={normalizedKeyMap.SWITCH_DRAW_MODE}
onChangeLabel={this.onChangeLabel} onChangeLabel={this.onChangeLabel}
onChangePoints={this.onChangePoints} onChangePoints={this.onChangePoints}
onChangeRectDrawingMethod={this.onChangeRectDrawingMethod} onChangeRectDrawingMethod={this.onChangeRectDrawingMethod}
onChangeCuboidDrawingMethod={this.onChangeCuboidDrawingMethod}
onDrawTrack={this.onDrawTrack} onDrawTrack={this.onDrawTrack}
onDrawShape={this.onDrawShape} onDrawShape={this.onDrawShape}
/> />

@ -7,6 +7,7 @@ import {
CanvasMode, CanvasMode,
CanvasVersion, CanvasVersion,
RectDrawingMethod, RectDrawingMethod,
CuboidDrawingMethod,
} from 'cvat-canvas/src/typescript/canvas'; } from 'cvat-canvas/src/typescript/canvas';
function isAbleToChangeFrame(canvas: Canvas): boolean { function isAbleToChangeFrame(canvas: Canvas): boolean {
@ -19,5 +20,6 @@ export {
CanvasMode, CanvasMode,
CanvasVersion, CanvasVersion,
RectDrawingMethod, RectDrawingMethod,
CuboidDrawingMethod,
isAbleToChangeFrame, isAbleToChangeFrame,
}; };

@ -495,7 +495,7 @@ class TrackManager(ObjectManager):
# TODO: Need to modify a client and a database (append "outside" shapes for polytracks) # TODO: Need to modify a client and a database (append "outside" shapes for polytracks)
if not prev_shape["outside"] and (prev_shape["type"] == ShapeType.RECTANGLE if not prev_shape["outside"] and (prev_shape["type"] == ShapeType.RECTANGLE
or prev_shape["type"] == ShapeType.POINTS): or prev_shape["type"] == ShapeType.POINTS or prev_shape["type"] == ShapeType.CUBOID):
shape = copy(prev_shape) shape = copy(prev_shape)
shape["frame"] = end_frame shape["frame"] = end_frame
shapes.extend(interpolate(prev_shape, shape)) shapes.extend(interpolate(prev_shape, shape))

Loading…
Cancel
Save