import { ff } from "@humansignal/core"; import { isAlive, types } from "mobx-state-tree"; import BaseTool, { DEFAULT_DIMENSIONS } from "./Base"; import ToolMixin from "../mixins/Tool"; import { MultipleClicksDrawingTool } from "../mixins/DrawingTool"; import { NodeViews } from "../components/Node/Node"; import { observe } from "mobx"; const _Tool = types .model("PolygonTool", { group: "segmentation", shortcut: "tool:polygon", }) .views((self) => { const Super = { createRegionOptions: self.createRegionOptions, isIncorrectControl: self.isIncorrectControl, isIncorrectLabel: self.isIncorrectLabel, }; return { get getActivePolygon() { const poly = self.currentArea; if (poly && !isAlive(poly)) return null; if (poly && poly.closed) return null; if (poly === undefined) return null; if (poly && poly.type !== "polygonregion") return null; return poly; }, get tagTypes() { return { stateTypes: "polygonlabels", controlTagTypes: ["polygonlabels", "polygon"], }; }, get viewTooltip() { return "Polygon region"; }, get iconComponent() { return self.dynamic ? NodeViews.PolygonRegionModel.altIcon : NodeViews.PolygonRegionModel.icon; }, get defaultDimensions() { return DEFAULT_DIMENSIONS.polygon; }, createRegionOptions({ x, y }) { return Super.createRegionOptions({ points: [[x, y]], width: 10, closed: false, }); }, isIncorrectControl() { return Super.isIncorrectControl() && self.current() === null; }, isIncorrectLabel() { return !self.current() && Super.isIncorrectLabel(); }, canStart() { return self.current() === null; }, current() { return self.getActivePolygon; }, }; }) .actions((self) => { let disposer; let closed; return { handleToolSwitch(tool) { self.stopListening(); if (self.getCurrentArea()?.isDrawing && tool.toolName !== "ZoomPanTool") { const shape = self.getCurrentArea()?.toJSON(); if (shape?.points?.length > 2) self.finishDrawing(); else self.cleanupUncloseableShape(); } }, listenForClose() { closed = false; disposer = observe( self.getCurrentArea(), "closed", () => { if (self.getCurrentArea()?.closed && !closed) { self.finishDrawing(); } }, true, ); }, stopListening() { if (disposer) disposer(); }, closeCurrent() { self.stopListening(); if (closed) return; closed = true; self.getCurrentArea().closePoly(); }, startDrawing(x, y) { const point = self.control?.getSnappedPoint({ x, y }); self.mode = "drawing"; self.currentArea = self.createRegion(self.createRegionOptions({ x: point.x, y: point.y }), true); self.setDrawing(true); if (!ff.isActive(ff.FF_MULTIPLE_LABELS_REGIONS)) { self.applyActiveStates(self.currentArea); } }, _finishDrawing() { const { currentArea, control } = self; self.currentArea.notifyDrawingFinished(); self.setDrawing(false); self.currentArea = null; self.mode = "viewing"; self.annotation.afterCreateResult(currentArea, control); }, setDrawing(drawing) { self.currentArea?.setDrawing(drawing); self.annotation.setIsDrawing(drawing); }, deleteRegion() { const { currentArea } = self; self.setDrawing(false); self.currentArea = null; if (currentArea) { currentArea.deleteRegion(); } }, }; }); const Polygon = types.compose(_Tool.name, ToolMixin, BaseTool, MultipleClicksDrawingTool, _Tool); export { Polygon };