import { types } from "mobx-state-tree";
|
import Registry from "../core/Registry";
|
import Tree from "../core/Tree";
|
import { AreaMixin } from "../mixins/AreaMixin";
|
import NormalizationMixin from "../mixins/Normalization";
|
import RegionsMixin from "../mixins/Regions";
|
import { RectRegionModel } from "./RectRegion";
|
import { KeyPointRegionModel } from "./KeyPointRegion";
|
import { AudioRegionModel } from "./AudioRegion";
|
import { PolygonRegionModel } from "./PolygonRegion";
|
import { VectorRegionModel } from "./VectorRegion";
|
import { EllipseRegionModel } from "./EllipseRegion";
|
import { RichTextRegionModel } from "./RichTextRegion";
|
import { BrushRegionModel } from "./BrushRegion";
|
import { TimelineRegionModel } from "./TimelineRegion";
|
import { TimeSeriesRegionModel } from "./TimeSeriesRegion";
|
import { ParagraphsRegionModel } from "./ParagraphsRegion";
|
import { VideoRectangleRegionModel } from "./VideoRectangleRegion";
|
import { BitmaskRegionModel } from "./BitmaskRegion";
|
import { CustomRegionModel } from "./CustomRegion";
|
|
// general Area type for classification Results which doesn't belong to any real Area
|
const ClassificationArea = types.compose(
|
"ClassificationArea",
|
RegionsMixin,
|
NormalizationMixin,
|
AreaMixin,
|
types
|
.model({
|
object: types.late(() => types.reference(types.union(...Registry.objectTypes()))),
|
// true only for global classifications
|
classification: true,
|
})
|
.views((self) => ({
|
get supportSuggestions() {
|
return false;
|
},
|
// it's required in some contexts when it's treated as a region
|
get type() {
|
return "";
|
},
|
}))
|
.actions(() => ({
|
serialize: () => ({}),
|
})),
|
);
|
|
const Area = types.union(
|
{
|
dispatcher(sn) {
|
// for some deserializations
|
if (sn.$treenode) return sn.$treenode.type;
|
|
for (const customTag of Registry.customTags) {
|
if (customTag.region && customTag.detector) {
|
if (customTag.detector(sn)) return customTag.region;
|
}
|
}
|
|
if (
|
!sn.points && // dirty hack to make it work with polygons, but may be the whole condition is not necessary at all
|
!sn.shape && // same for vector
|
// `sequence` and `ranges` are used for video regions
|
!sn.sequence &&
|
!sn.ranges &&
|
!sn.imageDataURL &&
|
sn.value &&
|
Object.values(sn.value).length <= 1
|
)
|
return ClassificationArea;
|
// may be a tag itself or just its name
|
const objectName = Tree.cleanUpId(sn.object.name || sn.object);
|
// we have to use current config to detect Object tag by name
|
const tag = window.Htx.annotationStore.names.get(objectName);
|
// provide value to detect Area by data
|
const available = Registry.getAvailableAreas(tag.type, sn);
|
// union of all available Areas for this Object type
|
|
// @todo dirty hack to distinguish two video types
|
if (tag.type === "video") {
|
if (sn.sequence || sn.value?.sequence) return VideoRectangleRegionModel;
|
return TimelineRegionModel;
|
}
|
|
if (!available.length) return ClassificationArea;
|
return types.union(...available, ClassificationArea);
|
},
|
},
|
AudioRegionModel,
|
ParagraphsRegionModel,
|
TimelineRegionModel,
|
TimeSeriesRegionModel,
|
RectRegionModel,
|
RichTextRegionModel,
|
KeyPointRegionModel,
|
EllipseRegionModel,
|
PolygonRegionModel,
|
VectorRegionModel,
|
BrushRegionModel,
|
BitmaskRegionModel,
|
VideoRectangleRegionModel,
|
ClassificationArea,
|
CustomRegionModel,
|
...Registry.customTags.map((t) => t.region).filter(Boolean),
|
);
|
|
export default Area;
|