Bin
2025-12-16 9e0b2ba2c317b1a86212f24cbae3195ad1f3dbfa
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
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;