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;
|
},
|
};
|
});
|