Add extreme clicking method in cvat-canvas and cvat-ui (#1127)

* Add extreme clicking method in cvat-canvas and cvat-ui

* Fix bugs and issues, update readme

* Fix error after rebasing develop
main
Jijoong Kim 6 years ago committed by GitHub
parent 20ed049111
commit d9fe71260b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -40,6 +40,7 @@ Canvas itself handles:
interface DrawData {
enabled: boolean;
shapeType?: string;
rectDrawingMethod?: string;
numberOfPoints?: number;
initialState?: any;
crosshair?: boolean;

@ -40,6 +40,7 @@ export interface ActiveElement {
export interface DrawData {
enabled: boolean;
shapeType?: string;
rectDrawingMethod?: string;
numberOfPoints?: number;
initialState?: any;
crosshair?: boolean;

@ -160,7 +160,8 @@ export class DrawHandlerImpl implements DrawHandler {
if (!this.drawData.initialState) {
const { drawInstance } = this;
this.drawInstance = null;
if (this.drawData.shapeType === 'rectangle') {
if (this.drawData.shapeType === 'rectangle'
&& this.drawData.rectDrawingMethod !== 'by_four_points') {
drawInstance.draw('cancel');
} else {
drawInstance.draw('done');
@ -200,6 +201,45 @@ export class DrawHandlerImpl implements DrawHandler {
});
}
private drawBoxBy4Points(): void {
let numberOfPoints = 0;
this.drawInstance = (this.canvas as any).polygon()
.addClass('cvat_canvas_shape_drawing').attr({
'stroke-width': 0,
opacity: 0,
}).on('drawstart', () => {
// init numberOfPoints as one on drawstart
numberOfPoints = 1;
}).on('drawpoint', (e: CustomEvent) => {
// increase numberOfPoints by one on drawpoint
numberOfPoints += 1;
// finish if numberOfPoints are exactly four
if (numberOfPoints === 4) {
const bbox = (e.target as SVGPolylineElement).getBBox();
const [xtl, ytl, xbr, ybr] = this.getFinalRectCoordinates(bbox);
if ((xbr - xtl) * (ybr - ytl) >= consts.AREA_THRESHOLD) {
this.onDrawDone({
shapeType: this.drawData.shapeType,
points: [xtl, ytl, xbr, ybr],
});
} else {
this.onDrawDone(null);
}
}
}).on('undopoint', () => {
if (numberOfPoints > 0) {
numberOfPoints -= 1;
}
}).off('drawdone').on('drawdone', () => {
// close drawing mode without drawing rect
this.onDrawDone(null);
});
this.drawPolyshape();
}
private drawPolyshape(): void {
this.drawInstance.attr({
z_order: Number.MAX_SAFE_INTEGER,
@ -536,13 +576,18 @@ export class DrawHandlerImpl implements DrawHandler {
this.pastePoints(stringifiedPoints);
}
}
this.setupPasteEvents();
} else {
if (this.drawData.shapeType === 'rectangle') {
this.drawBox();
// Draw instance was initialized after drawBox();
this.shapeSizeElement = displayShapeSize(this.canvas, this.text);
if (this.drawData.rectDrawingMethod === 'by_four_points') {
// draw box by extreme clicking
this.drawBoxBy4Points();
} else {
// default box drawing
this.drawBox();
// Draw instance was initialized after drawBox();
this.shapeSizeElement = displayShapeSize(this.canvas, this.text);
}
} else if (this.drawData.shapeType === 'polygon') {
this.drawPolygon();
} else if (this.drawData.shapeType === 'polyline') {
@ -550,7 +595,6 @@ export class DrawHandlerImpl implements DrawHandler {
} else if (this.drawData.shapeType === 'points') {
this.drawPoints();
}
this.setupDrawEvents();
}
}

@ -583,6 +583,7 @@ export function drawShape(
labelID: number,
objectType: ObjectType,
points?: number,
rectDrawingMethod?: string,
): AnyAction {
let activeControl = ActiveControl.DRAW_RECTANGLE;
if (shapeType === ShapeType.POLYGON) {
@ -601,6 +602,7 @@ export function drawShape(
objectType,
points,
activeControl,
rectDrawingMethod,
},
};
}

@ -6,22 +6,27 @@ import {
Select,
Button,
InputNumber,
Radio,
} from 'antd';
import { RadioChangeEvent } from 'antd/lib/radio';
import Text from 'antd/lib/typography/Text';
import {
ShapeType,
RectDrawingMethod,
} from 'reducers/interfaces';
interface Props {
shapeType: ShapeType;
rectDrawingMethod: RectDrawingMethod;
labels: any[];
minimumPoints: number;
numberOfPoints?: number;
selectedLabeID: number;
onChangeLabel(value: string): void;
onChangePoints(value: number | undefined): void;
onChangeRectDrawingMethod(event: RadioChangeEvent): void;
onDrawTrack(): void;
onDrawShape(): void;
}
@ -37,6 +42,7 @@ function DrawShapePopoverComponent(props: Props): JSX.Element {
onDrawShape,
onChangeLabel,
onChangePoints,
onChangeRectDrawingMethod,
} = props;
return (
@ -71,7 +77,37 @@ function DrawShapePopoverComponent(props: Props): JSX.Element {
</Col>
</Row>
{
shapeType !== ShapeType.RECTANGLE && (
shapeType === ShapeType.RECTANGLE ? (
<>
<Row>
<Col>
<Text className='cvat-text-color'> Drawing method </Text>
</Col>
</Row>
<Row type='flex' justify='space-around'>
<Col>
<Radio.Group
style={{ display: 'flex' }}
defaultValue={RectDrawingMethod.BY_TWO_POINTS}
onChange={onChangeRectDrawingMethod}
>
<Radio
value={RectDrawingMethod.BY_TWO_POINTS}
style={{ width: 'auto' }}
>
By 2 Points
</Radio>
<Radio
value={RectDrawingMethod.BY_FOUR_POINTS}
style={{ width: 'auto' }}
>
By 4 Points
</Radio>
</Radio.Group>
</Col>
</Row>
</>
) : (
<Row type='flex' justify='space-around' align='middle'>
<Col span={14}>
<Text className='cvat-text-color'> Number of points: </Text>

@ -1,10 +1,12 @@
import React from 'react';
import { connect } from 'react-redux';
import { RadioChangeEvent } from 'antd/lib/radio';
import {
CombinedState,
ShapeType,
ObjectType,
RectDrawingMethod,
} from 'reducers/interfaces';
import {
@ -23,6 +25,7 @@ interface DispatchToProps {
labelID: number,
objectType: ObjectType,
points?: number,
rectDrawingMethod?: string,
): void;
}
@ -39,8 +42,9 @@ function mapDispatchToProps(dispatch: any): DispatchToProps {
labelID: number,
objectType: ObjectType,
points?: number,
rectDrawingMethod?: string,
): void {
dispatch(drawShape(shapeType, labelID, objectType, points));
dispatch(drawShape(shapeType, labelID, objectType, points, rectDrawingMethod));
},
};
}
@ -67,6 +71,7 @@ function mapStateToProps(state: CombinedState, own: OwnProps): StateToProps {
type Props = StateToProps & DispatchToProps;
interface State {
rectDrawingMethod?: string;
numberOfPoints?: number;
selectedLabelID: number;
}
@ -77,6 +82,7 @@ class DrawShapePopoverContainer extends React.PureComponent<Props, State> {
super(props);
const defaultLabelID = props.labels[0].id;
const defaultRectDrawingMethod = RectDrawingMethod.BY_TWO_POINTS;
this.state = {
selectedLabelID: defaultLabelID,
};
@ -91,6 +97,9 @@ class DrawShapePopoverContainer extends React.PureComponent<Props, State> {
if (shapeType === ShapeType.POINTS) {
this.minimumPoints = 1;
}
if (shapeType === ShapeType.RECTANGLE) {
this.state.rectDrawingMethod = defaultRectDrawingMethod;
}
}
private onDraw(objectType: ObjectType): void {
@ -101,6 +110,7 @@ class DrawShapePopoverContainer extends React.PureComponent<Props, State> {
} = this.props;
const {
rectDrawingMethod,
numberOfPoints,
selectedLabelID,
} = this.state;
@ -108,6 +118,7 @@ class DrawShapePopoverContainer extends React.PureComponent<Props, State> {
canvasInstance.cancel();
canvasInstance.draw({
enabled: true,
rectDrawingMethod,
numberOfPoints,
shapeType,
crosshair: shapeType === ShapeType.RECTANGLE,
@ -117,6 +128,12 @@ class DrawShapePopoverContainer extends React.PureComponent<Props, State> {
objectType, numberOfPoints);
}
private onChangeRectDrawingMethod = (event: RadioChangeEvent): void => {
this.setState({
rectDrawingMethod: event.target.value,
});
};
private onDrawShape = (): void => {
this.onDraw(ObjectType.SHAPE);
};
@ -163,6 +180,7 @@ class DrawShapePopoverContainer extends React.PureComponent<Props, State> {
numberOfPoints={numberOfPoints}
onChangeLabel={this.onChangeLabel}
onChangePoints={this.onChangePoints}
onChangeRectDrawingMethod={this.onChangeRectDrawingMethod}
onDrawTrack={this.onDrawTrack}
onDrawShape={this.onDrawShape}
/>

@ -338,6 +338,7 @@ export default (state = defaultState, action: AnyAction): AnnotationState => {
objectType,
points,
activeControl,
rectDrawingMethod,
} = action.payload;
return {
@ -355,6 +356,7 @@ export default (state = defaultState, action: AnyAction): AnnotationState => {
activeNumOfPoints: points,
activeObjectType: objectType,
activeShapeType: shapeType,
activeRectDrawingMethod: rectDrawingMethod,
},
};
}

@ -239,6 +239,11 @@ export enum ActiveControl {
EDIT = 'edit',
}
export enum RectDrawingMethod {
BY_TWO_POINTS = 'by_two_points',
BY_FOUR_POINTS = 'by_four_points'
}
export enum ShapeType {
RECTANGLE = 'rectangle',
POLYGON = 'polygon',
@ -297,6 +302,7 @@ export interface AnnotationState {
};
drawing: {
activeShapeType: ShapeType;
activeRectDrawingMethod?: RectDrawingMethod;
activeNumOfPoints?: number;
activeLabelID: number;
activeObjectType: ObjectType;

Loading…
Cancel
Save