diff --git a/resources/assets/js/annotations/annotatorContainer.vue b/resources/assets/js/annotations/annotatorContainer.vue index 19369d2d7..da0d7523d 100644 --- a/resources/assets/js/annotations/annotatorContainer.vue +++ b/resources/assets/js/annotations/annotatorContainer.vue @@ -564,21 +564,8 @@ export default { dismissCrossOriginError() { this.crossOriginError = false; }, - handleInvalidShape(shape){ - let vertexCount; - switch(shape){ - case 'Polygon': - vertexCount = 'at least 3'; - break; - case 'Rectangle': - vertexCount = '4'; - break; - case 'LineString': - shape = 'Line'; - vertexCount = 'at least 2'; - break; - } - Messages.danger(`Invalid Shape. ${shape} needs ${vertexCount} non-overlapping vertices.`); + handleInvalidPolygon(){ + Messages.danger(`Invalid shape. Polygon needs at least 3 non-overlapping vertices.`); }, }, watch: { diff --git a/resources/assets/js/annotations/components/annotationCanvas.vue b/resources/assets/js/annotations/components/annotationCanvas.vue index 7aa193ec9..ae1f6c34a 100644 --- a/resources/assets/js/annotations/components/annotationCanvas.vue +++ b/resources/assets/js/annotations/components/annotationCanvas.vue @@ -510,14 +510,28 @@ export default { return this.convertPointsFromOlToDb(points); }, handleNewFeature(e) { - let validDrawing = this.hasValidPoints(e); - - if (this.hasSelectedLabel && validDrawing) { + if (this.hasSelectedLabel) { let geometry = e.feature.getGeometry(); - let dbPoints = this.getPoints(geometry); - let dbPointSet = this.removeDuplicatedPoints(dbPoints); - if(geometry.getType() === 'Polygon' && dbPoints.length !== dbPointSet.length){ - dbPoints = this.connectPolygonEnds(dbPoints); + let points = this.getPoints(geometry); + + if (geometry.getType() === 'Polygon') { + if (this.isInvalidPolygon(e)) { + this.$emit('has-invalid-polygon'); + this.annotationSource.once('change', () => { + if (this.annotationSource.hasFeature(e.feature)) { + this.annotationSource.removeFeature(e.feature); + } + }); + return; + } + + let curatedPointSet = this.removeDuplicatedPoints(points); + if (points.length !== curatedPointSet.length) { + points = curatedPointSet; + // link polygon start and end by adding polygon start at the end + points.push(points[0]); // x coordinate + points.push(points[1]); // y coordinate + } } e.feature.set('color', this.selectedLabel.color); @@ -535,52 +549,32 @@ export default { this.$emit('new', { shape: geometry.getType(), - points: dbPoints, + points: points, }, removeCallback); } else { - let source = this.annotationSource; - source.once('change', () => { - if (source.hasFeature(e.feature)) { - source.removeFeature(e.feature); - } - }); - this.$emit('has-invalid-shape', e.feature.getGeometry().getType()); + this.annotationSource.removeFeature(e.feature); } }, - hasValidPoints(e) { + isInvalidPolygon(e) { let geometry = e.feature.getGeometry(); let points = geometry.getCoordinates(); + return this.getPointStringSet(points[0]).size < 3; + + }, + removeDuplicatedPoints(points) { + let x = points.filter((_,i) => i%2==0); + let y = points.filter((_,i) => i%2==1); + let coordinates = x.map((xi,i) => {return [xi,y[i]];}); - switch (geometry.getType()) { - case 'LineString': - return this.getPointStringSet(points).size >= 2; - case 'Rectangle': - return this.getPointStringSet(points[0]).size === 4; - case 'Polygon': - return this.getPointStringSet(points[0]).size >= 3; - default: - return true; - } + let pointStringSet = Array.from(this.getPointStringSet(coordinates)); + return pointStringSet.map(xy => this.convertStringToPoint(xy)).flat(); }, getPointStringSet(points) { return new Set(points.map(xy => String([xy]))); }, - removeDuplicatedPoints(points) { - let pointMultiSet = []; - for (let i = 0; i < points.length; i += 2) { - pointMultiSet.push([points[i], points[i + 1]]); - } - let pointStringSet = Array.from(this.getPointStringSet(pointMultiSet)); - return pointStringSet.map(xy => this.convertStringToPoint(xy)).flat(); - }, convertStringToPoint(xy) { return xy.split(',').map(Number); }, - connectPolygonEnds(points) { - points.push(points[0]); - points.push(points[1]); - return points; - }, deleteSelectedAnnotations() { if (!this.modifyInProgress && this.hasSelectedAnnotations && confirm('Are you sure you want to delete all selected annotations?')) { this.$emit('delete', this.selectedAnnotations); diff --git a/resources/views/annotations/show.blade.php b/resources/views/annotations/show.blade.php index 6e0a57c11..1c55a6f41 100644 --- a/resources/views/annotations/show.blade.php +++ b/resources/views/annotations/show.blade.php @@ -95,7 +95,7 @@ v-on:delete="handleDeleteAnnotations" v-on:measuring="fetchImagesArea" v-on:requires-selected-label="handleRequiresSelectedLabel" - v-on:has-invalid-shape="handleInvalidShape" + v-on:has-invalid-polygon="handleInvalidPolygon" ref="canvas" inline-template> @include('annotations.show.annotationCanvas')