import { getParent, types } from "mobx-state-tree"; import { ImageSelectionPoint } from "./ImageSelectionPoint"; import { FF_DEV_3793, isFF } from "../../../utils/feature-flags"; import { RELATIVE_STAGE_HEIGHT, RELATIVE_STAGE_WIDTH } from "../../../components/ImageView/Image"; export const ImageSelection = types .model({ start: types.maybeNull(ImageSelectionPoint), end: types.maybeNull(ImageSelectionPoint), }) .views((self) => { return { get obj() { return getParent(self); }, get annotation() { return self.obj.annotation; }, get highlightedNodeExists() { return !!self.annotation.highlightedNode; }, get isActive() { return self.start && self.end; }, get x() { return Math.min(self.start.x * self.scale, self.end.x * self.scale); }, get y() { return Math.min(self.start.y * self.scale, self.end.y * self.scale); }, get width() { return Math.abs(self.end.x * self.scale - self.start.x * self.scale); }, get height() { return Math.abs(self.end.y * self.scale - self.start.y * self.scale); }, get scale() { return self.obj.zoomScale; }, get bbox() { const { start, end } = self; return self.isActive ? { left: Math.min(start.x, end.x), top: Math.min(start.y, end.y), right: Math.max(start.x, end.x), bottom: Math.max(start.y, end.y), } : null; }, get onCanvasBbox() { if (!self.isActive) return null; const { start, end } = self; return { left: self.obj.internalToCanvasX(Math.min(start.x, end.x)), top: self.obj.internalToCanvasY(Math.min(start.y, end.y)), right: self.obj.internalToCanvasX(Math.max(start.x, end.x)), bottom: self.obj.internalToCanvasY(Math.max(start.y, end.y)), }; }, get onCanvasRect() { if (!isFF(FF_DEV_3793)) return self; if (!self.isActive) return null; const bbox = self.onCanvasBbox; return { x: bbox.left, y: bbox.top, width: bbox.right - bbox.left, height: bbox.bottom - bbox.top, }; }, includesBbox(bbox) { if (!self.isActive || !bbox) return false; const isLeftOf = self.bbox.left <= bbox.left; const isAbove = self.bbox.top <= bbox.top; const isRightOf = self.bbox.right >= bbox.right; const isBelow = self.bbox.bottom >= bbox.bottom; return isLeftOf && isAbove && isRightOf && isBelow; }, intersectsBbox(bbox) { if (!self.isActive || !bbox) return false; const selfCenterX = (self.bbox.left + self.bbox.right) / 2; const selfCenterY = (self.bbox.top + self.bbox.bottom) / 2; const selfWidth = self.bbox.right - self.bbox.left; const selfHeight = self.bbox.bottom - self.bbox.top; const targetCenterX = (bbox.left + bbox.right) / 2; const targetCenterY = (bbox.top + bbox.bottom) / 2; const targetWidth = bbox.right - bbox.left; const targetHeight = bbox.bottom - bbox.top; return ( Math.abs(selfCenterX - targetCenterX) * 2 < selfWidth + targetWidth && Math.abs(selfCenterY - targetCenterY) * 2 < selfHeight + targetHeight ); }, get selectionBorders() { if (self.isActive || !self.obj.selectedRegions.length) return null; const initial = isFF(FF_DEV_3793) ? { left: RELATIVE_STAGE_WIDTH, top: RELATIVE_STAGE_HEIGHT, right: 0, bottom: 0 } : { left: self.obj.stageWidth, top: self.obj.stageHeight, right: 0, bottom: 0 }; const bbox = self.obj.selectedRegions.reduce((borders, region) => { return region.bboxCoords ? { left: Math.min(borders.left, region.bboxCoords.left), top: Math.min(borders.top, region.bboxCoords.top), right: Math.max(borders.right, region.bboxCoords.right), bottom: Math.max(borders.bottom, region.bboxCoords.bottom), } : borders; }, initial); if (!isFF(FF_DEV_3793)) return bbox; return { left: self.obj.internalToCanvasX(bbox.left), top: self.obj.internalToCanvasY(bbox.top), right: self.obj.internalToCanvasX(bbox.right), bottom: self.obj.internalToCanvasY(bbox.bottom), }; }, }; }) .actions((self) => { return { setStart(point) { self.start = point; }, setEnd(point) { self.end = point; }, }; });