|
|
import { v4 as uuidv4 } from 'uuid' import Flatten from '@flatten-js/core' import LabelProps from '@/domain/models/tasks/shared/LabelProps' import LineSegment from './LineSegment' import PolygonProps from './PolygonProps' import ValidationError from './errors' import Point = Flatten.Point import Vector = Flatten.Vector
const MINIMUM_NUMBER_OF_SIDES = 3
export default class Polygon { readonly id: string
readonly labelId: number
points: Point[] = []
constructor(labelId: number, points: number[] = [], id: string = uuidv4()) { if (points.length % 2 !== 0) { throw new ValidationError('Invalid number of points') } this.id = id this.labelId = labelId for (let i = 0; i < points.length; i += 2) { this.addPoint(points[i], points[i + 1]) } }
clone(): Polygon { return new Polygon(this.labelId, this.flattenedPoints, this.id) }
translate(x: number, y: number): void { const vector = new Vector(x, y) this.points = this.points.map((point) => point.translate(vector)) }
canBeClosed(): boolean { return this.points.length >= MINIMUM_NUMBER_OF_SIDES }
addPoint(x: number, y: number): void { const point = new Point(x, y) this.points.push(point) }
movePoint(index: number, x: number, y: number): void { const point = new Point(x, y) this.points[index] = point }
removePoint(index: number): void { if (this.points.length > MINIMUM_NUMBER_OF_SIDES) { this.points.splice(index, 1) } }
insertPoint(x: number, y: number, index: number): void { const point = new Point(x, y) this.points.splice(index, 0, point) }
toPoints(): Point[] { return this.points.map((point) => point.clone()) }
minMaxPoints(): [number, number, number, number] { const [minX, minY, maxX, maxY] = this.points.reduce( ([minx, miny, maxx, maxy], point) => [ Math.min(minx, point.x), Math.min(miny, point.y), Math.max(maxx, point.x), Math.max(maxy, point.y) ], [Infinity, Infinity, -Infinity, -Infinity] ) return [minX, minY, maxX, maxY] }
toProps(): PolygonProps { return { id: this.id, label: this.labelId, points: this.points.flatMap((point) => [point.x, point.y]) } }
getColor(labels: LabelProps[]): string { return labels.find((label) => label.id === this.labelId)!.color || '##ff0000' }
get lineSegments(): LineSegment[] { const lineSegments = [] for (let i = 0; i < this.points.length; i += 1) { const p1 = this.points[i] const p2 = this.points[(i + 1) % this.points.length] lineSegments.push(new LineSegment(p1, p2)) } return lineSegments }
get flattenedPoints(): number[] { return this.points.flatMap((point) => [point.x, point.y]) }
get numberOfSides(): number { return this.points.length } }
|