File size: 3,598 Bytes
92189dd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
108
109
110
111
112
113
114
115
116
117
118
/**
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import {SegmentationPoint} from '@/common/tracker/Tracker';
import stylex from '@stylexjs/stylex';
import {useMemo} from 'react';
import useResizeObserver from 'use-resize-observer';
import useVideo from '../editor/useVideo';

const styles = stylex.create({
  container: {
    position: 'absolute',
    width: '100%',
    height: '100%',
    pointerEvents: 'none',
  },
});

type Props = {
  points: SegmentationPoint[];
  onRemovePoint: (point: SegmentationPoint) => void;
};

export function PointsLayer({points, onRemovePoint}: Props) {
  const video = useVideo();
  const videoCanvas = useMemo(() => video?.getCanvas(), [video]);

  const {
    ref,
    width: containerWidth = 1,
    height: containerHeight = 1,
  } = useResizeObserver<SVGElement>();

  const canvasWidth = videoCanvas?.width ?? 1;
  const canvasHeight = videoCanvas?.height ?? 1;

  const sizeMultiplier = useMemo(() => {
    const widthMultiplier = canvasWidth / containerWidth;
    const heightMultiplier = canvasHeight / containerHeight;

    return Math.max(widthMultiplier, heightMultiplier);
  }, [canvasWidth, canvasHeight, containerWidth, containerHeight]);

  const pointRadius = useMemo(() => 8 * sizeMultiplier, [sizeMultiplier]);
  const pointStroke = useMemo(() => 2 * sizeMultiplier, [sizeMultiplier]);

  return (
    <svg
      ref={ref}
      {...stylex.props(styles.container)}
      xmlns="http://www.w3.org/2000/svg"
      viewBox={`0 0 ${canvasWidth} ${canvasHeight}`}>
      {/*
       * This is a debug element to verify the SVG element overlays
       * perfectly with the canvas element.
       */}
      {/*
      <rect
        fill="rgba(255, 255, 0, 0.5)"
        width={decodedVideo?.width}
        height={decodedVideo?.height}
      />
      */}
      {/* Render points */}
      {points.map((point, idx) => {
        const isAdd = point[2] === 1;
        return (
          <g key={idx} className="cursor-pointer">
            <circle
              className="stroke-white hover:stroke-gray-400"
              pointerEvents="visiblePainted"
              cx={point[0]}
              cy={point[1]}
              r={pointRadius}
              fill={isAdd ? '#000000' : '#E6193B'}
              strokeWidth={pointStroke}
              onClick={event => {
                event.stopPropagation();
                onRemovePoint(point);
              }}
            />
            <line
              x1={point[0] - pointRadius / 2}
              y1={point[1]}
              x2={point[0] + pointRadius / 2}
              y2={point[1]}
              strokeWidth={pointStroke}
              stroke="white"
            />
            {isAdd && (
              <line
                x1={point[0]}
                y1={point[1] - pointRadius / 2}
                x2={point[0]}
                y2={point[1] + pointRadius / 2}
                strokeWidth={pointStroke}
                stroke="white"
              />
            )}
          </g>
        );
      })}
    </svg>
  );
}