canvas-website/src/default_gestures.ts

814 lines
19 KiB
TypeScript

import { Gesture } from "@/gestures"
import { Editor, TLDrawShape, TLShape, VecLike, createShapeId } from "tldraw"
const getShapesUnderGesture = (editor: Editor, gesture: TLDrawShape) => {
const bounds = editor.getShapePageBounds(gesture.id)
return editor.getShapesAtPoint(bounds?.center!, {
margin: (bounds?.width! + bounds?.height!) / 4,
}).filter((shape) => shape.id !== gesture.id)
}
/** Returns shapes arranged in a circle around the given origin */
const circleDistribution = (editor: Editor, shapes: TLShape[], origin: VecLike, radius: number): TLShape[] => {
const angleStep = (2 * Math.PI) / shapes.length;
return shapes.map((shape, index) => {
const { w, h } = editor.getShapeGeometry(shape.id).bounds
const angle = index * angleStep;
const pointOnCircle = {
x: origin.x + radius * Math.cos(angle),
y: origin.y + radius * Math.sin(angle),
};
const shapeAngle = angle + Math.PI / 2;
const pos = posFromRotatedCenter(pointOnCircle, w, h, shapeAngle);
return {
...shape,
x: pos.x,
y: pos.y,
rotation: shapeAngle,
};
});
}
/** Returns shapes arranged in a triangle around the given origin */
const triangleDistribution = (editor: Editor, shapes: TLShape[], origin: VecLike, radius: number): TLShape[] => {
const vertices = [
{ x: origin.x - radius, y: origin.y + radius }, // Bottom left
{ x: origin.x + radius, y: origin.y + radius }, // Bottom right
{ x: origin.x, y: origin.y - radius }, // Top middle
];
const totalShapes = shapes.length;
const shapesPerEdge = Math.ceil(totalShapes / 3);
return shapes.map((shape, index) => {
const edgeIndex = Math.floor(index / shapesPerEdge);
const edgeStart = vertices[edgeIndex];
const edgeEnd = vertices[(edgeIndex + 1) % 3];
const t = (index % shapesPerEdge) / shapesPerEdge;
const pointOnEdge = {
x: edgeStart.x + t * (edgeEnd.x - edgeStart.x),
y: edgeStart.y + t * (edgeEnd.y - edgeStart.y),
};
let shapeAngle;
if (index % shapesPerEdge === 0) {
// Shape is at a vertex, adjust angle to face away from the triangle
const vertex = vertices[edgeIndex];
shapeAngle = Math.atan2(vertex.y - origin.y, vertex.x - origin.x);
} else {
// Shape is on an edge
shapeAngle = Math.atan2(edgeEnd.y - edgeStart.y, edgeEnd.x - edgeStart.x);
}
const { w, h } = editor.getShapeGeometry(shape.id).bounds;
const pos = posFromRotatedCenter(pointOnEdge, w, h, shapeAngle);
return {
...shape,
x: pos.x,
y: pos.y,
rotation: shapeAngle,
};
});
}
/** Calculates the top-left position of a shape given a center point, width, height, and rotation (radians) */
/** its origin x/y and rotation are around the top-left corner of the shape */
const posFromRotatedCenter = (center: VecLike, w: number, h: number, rotation: number): VecLike => {
const halfWidth = w / 2;
const halfHeight = h / 2;
const cosTheta = Math.cos(rotation);
const sinTheta = Math.sin(rotation);
const topLeftX = center.x - (halfWidth * cosTheta - halfHeight * sinTheta);
const topLeftY = center.y - (halfWidth * sinTheta + halfHeight * cosTheta);
return { x: topLeftX, y: topLeftY };
}
export const DEFAULT_GESTURES: Gesture[] = [
{
name: "x",
onComplete(editor) {
editor.deleteShapes(editor.getSelectedShapes())
},
points: [
{ x: 87, y: 142 },
{ x: 89, y: 145 },
{ x: 91, y: 148 },
{ x: 93, y: 151 },
{ x: 96, y: 155 },
{ x: 98, y: 157 },
{ x: 100, y: 160 },
{ x: 102, y: 162 },
{ x: 106, y: 167 },
{ x: 108, y: 169 },
{ x: 110, y: 171 },
{ x: 115, y: 177 },
{ x: 119, y: 183 },
{ x: 123, y: 189 },
{ x: 127, y: 193 },
{ x: 129, y: 196 },
{ x: 133, y: 200 },
{ x: 137, y: 206 },
{ x: 140, y: 209 },
{ x: 143, y: 212 },
{ x: 146, y: 215 },
{ x: 151, y: 220 },
{ x: 153, y: 222 },
{ x: 155, y: 223 },
{ x: 157, y: 225 },
{ x: 158, y: 223 },
{ x: 157, y: 218 },
{ x: 155, y: 211 },
{ x: 154, y: 208 },
{ x: 152, y: 200 },
{ x: 150, y: 189 },
{ x: 148, y: 179 },
{ x: 147, y: 170 },
{ x: 147, y: 158 },
{ x: 147, y: 148 },
{ x: 147, y: 141 },
{ x: 147, y: 136 },
{ x: 144, y: 135 },
{ x: 142, y: 137 },
{ x: 140, y: 139 },
{ x: 135, y: 145 },
{ x: 131, y: 152 },
{ x: 124, y: 163 },
{ x: 116, y: 177 },
{ x: 108, y: 191 },
{ x: 100, y: 206 },
{ x: 94, y: 217 },
{ x: 91, y: 222 },
{ x: 89, y: 225 },
{ x: 87, y: 226 },
{ x: 87, y: 224 },
],
},
{
name: "rectangle",
onComplete(editor, gesture?: TLDrawShape) {
const bounds = editor.getShapePageBounds(gesture?.id!)
const { w, h, center } = bounds!
editor.createShape({
id: createShapeId(),
type: "geo",
x: center?.x! - w / 2,
y: center?.y! - h / 2,
isLocked: false,
props: {
fill: "solid",
w: w,
h: h,
geo: "rectangle",
dash: "draw",
size: "m",
font: "draw",
align: "middle",
verticalAlign: "middle",
growY: 0,
url: "",
scale: 1,
labelColor: "black",
richText: [] as any
},
})
},
points: [
{ x: 78, y: 149 },
{ x: 78, y: 153 },
{ x: 78, y: 157 },
{ x: 78, y: 160 },
{ x: 79, y: 162 },
{ x: 79, y: 164 },
{ x: 79, y: 167 },
{ x: 79, y: 169 },
{ x: 79, y: 173 },
{ x: 79, y: 178 },
{ x: 79, y: 183 },
{ x: 80, y: 189 },
{ x: 80, y: 193 },
{ x: 80, y: 198 },
{ x: 80, y: 202 },
{ x: 81, y: 208 },
{ x: 81, y: 210 },
{ x: 81, y: 216 },
{ x: 82, y: 222 },
{ x: 82, y: 224 },
{ x: 82, y: 227 },
{ x: 83, y: 229 },
{ x: 83, y: 231 },
{ x: 85, y: 230 },
{ x: 88, y: 232 },
{ x: 90, y: 233 },
{ x: 92, y: 232 },
{ x: 94, y: 233 },
{ x: 99, y: 232 },
{ x: 102, y: 233 },
{ x: 106, y: 233 },
{ x: 109, y: 234 },
{ x: 117, y: 235 },
{ x: 123, y: 236 },
{ x: 126, y: 236 },
{ x: 135, y: 237 },
{ x: 142, y: 238 },
{ x: 145, y: 238 },
{ x: 152, y: 238 },
{ x: 154, y: 239 },
{ x: 165, y: 238 },
{ x: 174, y: 237 },
{ x: 179, y: 236 },
{ x: 186, y: 235 },
{ x: 191, y: 235 },
{ x: 195, y: 233 },
{ x: 197, y: 233 },
{ x: 200, y: 233 },
{ x: 201, y: 235 },
{ x: 201, y: 233 },
{ x: 199, y: 231 },
{ x: 198, y: 226 },
{ x: 198, y: 220 },
{ x: 196, y: 207 },
{ x: 195, y: 195 },
{ x: 195, y: 181 },
{ x: 195, y: 173 },
{ x: 195, y: 163 },
{ x: 194, y: 155 },
{ x: 192, y: 145 },
{ x: 192, y: 143 },
{ x: 192, y: 138 },
{ x: 191, y: 135 },
{ x: 191, y: 133 },
{ x: 191, y: 130 },
{ x: 190, y: 128 },
{ x: 188, y: 129 },
{ x: 186, y: 129 },
{ x: 181, y: 132 },
{ x: 173, y: 131 },
{ x: 162, y: 131 },
{ x: 151, y: 132 },
{ x: 149, y: 132 },
{ x: 138, y: 132 },
{ x: 136, y: 132 },
{ x: 122, y: 131 },
{ x: 120, y: 131 },
{ x: 109, y: 130 },
{ x: 107, y: 130 },
{ x: 90, y: 132 },
{ x: 81, y: 133 },
{ x: 76, y: 133 },
],
},
{
name: "circle",
onComplete(editor, gesture?: TLDrawShape) {
const selection = getShapesUnderGesture(editor, gesture!)
editor.setSelectedShapes(selection)
editor.setHintingShapes(selection)
},
points: [
{ x: 127, y: 141 },
{ x: 124, y: 140 },
{ x: 120, y: 139 },
{ x: 118, y: 139 },
{ x: 116, y: 139 },
{ x: 111, y: 140 },
{ x: 109, y: 141 },
{ x: 104, y: 144 },
{ x: 100, y: 147 },
{ x: 96, y: 152 },
{ x: 93, y: 157 },
{ x: 90, y: 163 },
{ x: 87, y: 169 },
{ x: 85, y: 175 },
{ x: 83, y: 181 },
{ x: 82, y: 190 },
{ x: 82, y: 195 },
{ x: 83, y: 200 },
{ x: 84, y: 205 },
{ x: 88, y: 213 },
{ x: 91, y: 216 },
{ x: 96, y: 219 },
{ x: 103, y: 222 },
{ x: 108, y: 224 },
{ x: 111, y: 224 },
{ x: 120, y: 224 },
{ x: 133, y: 223 },
{ x: 142, y: 222 },
{ x: 152, y: 218 },
{ x: 160, y: 214 },
{ x: 167, y: 210 },
{ x: 173, y: 204 },
{ x: 178, y: 198 },
{ x: 179, y: 196 },
{ x: 182, y: 188 },
{ x: 182, y: 177 },
{ x: 178, y: 167 },
{ x: 170, y: 150 },
{ x: 163, y: 138 },
{ x: 152, y: 130 },
{ x: 143, y: 129 },
{ x: 140, y: 131 },
{ x: 129, y: 136 },
{ x: 126, y: 139 },
],
},
{
name: "check",
onComplete(editor, gesture?: TLDrawShape) {
const originPoint = { x: gesture?.x!, y: gesture?.y! }
const shapeAtOrigin = editor.getShapesAtPoint(originPoint, {
hitInside: true,
margin: 10,
})
for (const shape of shapeAtOrigin) {
if (shape.id === gesture?.id) continue
editor.updateShape({
...shape,
props: {
...shape.props,
color: "green",
},
})
}
},
points: [
{ x: 91, y: 185 },
{ x: 93, y: 185 },
{ x: 95, y: 185 },
{ x: 97, y: 185 },
{ x: 100, y: 188 },
{ x: 102, y: 189 },
{ x: 104, y: 190 },
{ x: 106, y: 193 },
{ x: 108, y: 195 },
{ x: 110, y: 198 },
{ x: 112, y: 201 },
{ x: 114, y: 204 },
{ x: 115, y: 207 },
{ x: 117, y: 210 },
{ x: 118, y: 212 },
{ x: 120, y: 214 },
{ x: 121, y: 217 },
{ x: 122, y: 219 },
{ x: 123, y: 222 },
{ x: 124, y: 224 },
{ x: 126, y: 226 },
{ x: 127, y: 229 },
{ x: 129, y: 231 },
{ x: 130, y: 233 },
{ x: 129, y: 231 },
{ x: 129, y: 228 },
{ x: 129, y: 226 },
{ x: 129, y: 224 },
{ x: 129, y: 221 },
{ x: 129, y: 218 },
{ x: 129, y: 212 },
{ x: 129, y: 208 },
{ x: 130, y: 198 },
{ x: 132, y: 189 },
{ x: 134, y: 182 },
{ x: 137, y: 173 },
{ x: 143, y: 164 },
{ x: 147, y: 157 },
{ x: 151, y: 151 },
{ x: 155, y: 144 },
{ x: 161, y: 137 },
{ x: 165, y: 131 },
{ x: 171, y: 122 },
{ x: 174, y: 118 },
{ x: 176, y: 114 },
{ x: 177, y: 112 },
{ x: 177, y: 114 },
{ x: 175, y: 116 },
{ x: 173, y: 118 },
],
},
{
name: "caret",
onComplete(editor) {
editor.alignShapes(editor.getSelectedShapes(), "top")
},
points: [
{ x: 79, y: 245 },
{ x: 79, y: 242 },
{ x: 79, y: 239 },
{ x: 80, y: 237 },
{ x: 80, y: 234 },
{ x: 81, y: 232 },
{ x: 82, y: 230 },
{ x: 84, y: 224 },
{ x: 86, y: 220 },
{ x: 86, y: 218 },
{ x: 87, y: 216 },
{ x: 88, y: 213 },
{ x: 90, y: 207 },
{ x: 91, y: 202 },
{ x: 92, y: 200 },
{ x: 93, y: 194 },
{ x: 94, y: 192 },
{ x: 96, y: 189 },
{ x: 97, y: 186 },
{ x: 100, y: 179 },
{ x: 102, y: 173 },
{ x: 105, y: 165 },
{ x: 107, y: 160 },
{ x: 109, y: 158 },
{ x: 112, y: 151 },
{ x: 115, y: 144 },
{ x: 117, y: 139 },
{ x: 119, y: 136 },
{ x: 119, y: 134 },
{ x: 120, y: 132 },
{ x: 121, y: 129 },
{ x: 122, y: 127 },
{ x: 124, y: 125 },
{ x: 126, y: 124 },
{ x: 129, y: 125 },
{ x: 131, y: 127 },
{ x: 132, y: 130 },
{ x: 136, y: 139 },
{ x: 141, y: 154 },
{ x: 145, y: 166 },
{ x: 151, y: 182 },
{ x: 156, y: 193 },
{ x: 157, y: 196 },
{ x: 161, y: 209 },
{ x: 162, y: 211 },
{ x: 167, y: 223 },
{ x: 169, y: 229 },
{ x: 170, y: 231 },
{ x: 173, y: 237 },
{ x: 176, y: 242 },
{ x: 177, y: 244 },
{ x: 179, y: 250 },
{ x: 181, y: 255 },
{ x: 182, y: 257 },
],
},
// {
// name: "zig-zag",
// points: [
// { x: 307, y: 216 },
// { x: 333, y: 186 },
// { x: 356, y: 215 },
// { x: 375, y: 186 },
// { x: 399, y: 216 },
// { x: 418, y: 186 },
// ],
// },
{
name: "v",
onComplete(editor) {
editor.alignShapes(editor.getSelectedShapes(), "bottom")
},
points: [
{ x: 89, y: 164 },
{ x: 90, y: 162 },
{ x: 92, y: 162 },
{ x: 94, y: 164 },
{ x: 95, y: 166 },
{ x: 96, y: 169 },
{ x: 97, y: 171 },
{ x: 99, y: 175 },
{ x: 101, y: 178 },
{ x: 103, y: 182 },
{ x: 106, y: 189 },
{ x: 108, y: 194 },
{ x: 111, y: 199 },
{ x: 114, y: 204 },
{ x: 117, y: 209 },
{ x: 119, y: 214 },
{ x: 122, y: 218 },
{ x: 124, y: 222 },
{ x: 126, y: 225 },
{ x: 128, y: 228 },
{ x: 130, y: 229 },
{ x: 133, y: 233 },
{ x: 134, y: 236 },
{ x: 136, y: 239 },
{ x: 138, y: 240 },
{ x: 139, y: 242 },
{ x: 140, y: 244 },
{ x: 142, y: 242 },
{ x: 142, y: 240 },
{ x: 142, y: 237 },
{ x: 143, y: 235 },
{ x: 143, y: 233 },
{ x: 145, y: 229 },
{ x: 146, y: 226 },
{ x: 148, y: 217 },
{ x: 149, y: 208 },
{ x: 149, y: 205 },
{ x: 151, y: 196 },
{ x: 151, y: 193 },
{ x: 153, y: 182 },
{ x: 155, y: 172 },
{ x: 157, y: 165 },
{ x: 159, y: 160 },
{ x: 162, y: 155 },
{ x: 164, y: 150 },
{ x: 165, y: 148 },
{ x: 166, y: 146 },
],
},
{
name: "delete",
onComplete(editor) {
editor.deleteShapes(editor.getSelectedShapes())
},
points: [
{ x: 123, y: 129 },
{ x: 123, y: 131 },
{ x: 124, y: 133 },
{ x: 125, y: 136 },
{ x: 127, y: 140 },
{ x: 129, y: 142 },
{ x: 133, y: 148 },
{ x: 137, y: 154 },
{ x: 143, y: 158 },
{ x: 145, y: 161 },
{ x: 148, y: 164 },
{ x: 153, y: 170 },
{ x: 158, y: 176 },
{ x: 160, y: 178 },
{ x: 164, y: 183 },
{ x: 168, y: 188 },
{ x: 171, y: 191 },
{ x: 175, y: 196 },
{ x: 178, y: 200 },
{ x: 180, y: 202 },
{ x: 181, y: 205 },
{ x: 184, y: 208 },
{ x: 186, y: 210 },
{ x: 187, y: 213 },
{ x: 188, y: 215 },
{ x: 186, y: 212 },
{ x: 183, y: 211 },
{ x: 177, y: 208 },
{ x: 169, y: 206 },
{ x: 162, y: 205 },
{ x: 154, y: 207 },
{ x: 145, y: 209 },
{ x: 137, y: 210 },
{ x: 129, y: 214 },
{ x: 122, y: 217 },
{ x: 118, y: 218 },
{ x: 111, y: 221 },
{ x: 109, y: 222 },
{ x: 110, y: 219 },
{ x: 112, y: 217 },
{ x: 118, y: 209 },
{ x: 120, y: 207 },
{ x: 128, y: 196 },
{ x: 135, y: 187 },
{ x: 138, y: 183 },
{ x: 148, y: 167 },
{ x: 157, y: 153 },
{ x: 163, y: 145 },
{ x: 165, y: 142 },
{ x: 172, y: 133 },
{ x: 177, y: 127 },
{ x: 179, y: 127 },
{ x: 180, y: 125 },
],
},
{
name: "pigtail",
onComplete(editor, gesture?: TLDrawShape) {
const shapes = getShapesUnderGesture(editor, gesture!)
editor.setSelectedShapes(shapes)
editor.setHintingShapes(shapes)
editor.animateShapes(shapes.map((shape) => ({
...shape,
rotation: shape.rotation + (Math.PI / -2),
})),
{
animation: {
duration: 600,
easing: (t) => t * t * (3 - 2 * t),
},
},
)
},
points: [
{ x: 81, y: 219 },
{ x: 84, y: 218 },
{ x: 86, y: 220 },
{ x: 88, y: 220 },
{ x: 90, y: 220 },
{ x: 92, y: 219 },
{ x: 95, y: 220 },
{ x: 97, y: 219 },
{ x: 99, y: 220 },
{ x: 102, y: 218 },
{ x: 105, y: 217 },
{ x: 107, y: 216 },
{ x: 110, y: 216 },
{ x: 113, y: 214 },
{ x: 116, y: 212 },
{ x: 118, y: 210 },
{ x: 121, y: 208 },
{ x: 124, y: 205 },
{ x: 126, y: 202 },
{ x: 129, y: 199 },
{ x: 132, y: 196 },
{ x: 136, y: 191 },
{ x: 139, y: 187 },
{ x: 142, y: 182 },
{ x: 144, y: 179 },
{ x: 146, y: 174 },
{ x: 148, y: 170 },
{ x: 149, y: 168 },
{ x: 151, y: 162 },
{ x: 152, y: 160 },
{ x: 152, y: 157 },
{ x: 152, y: 155 },
{ x: 152, y: 151 },
{ x: 152, y: 149 },
{ x: 152, y: 146 },
{ x: 149, y: 142 },
{ x: 148, y: 139 },
{ x: 145, y: 137 },
{ x: 141, y: 135 },
{ x: 139, y: 135 },
{ x: 134, y: 136 },
{ x: 130, y: 140 },
{ x: 128, y: 142 },
{ x: 126, y: 145 },
{ x: 122, y: 150 },
{ x: 119, y: 158 },
{ x: 117, y: 163 },
{ x: 115, y: 170 },
{ x: 114, y: 175 },
{ x: 117, y: 184 },
{ x: 120, y: 190 },
{ x: 125, y: 199 },
{ x: 129, y: 203 },
{ x: 133, y: 208 },
{ x: 138, y: 213 },
{ x: 145, y: 215 },
{ x: 155, y: 218 },
{ x: 164, y: 219 },
{ x: 166, y: 219 },
{ x: 177, y: 219 },
{ x: 182, y: 218 },
{ x: 192, y: 216 },
{ x: 196, y: 213 },
{ x: 199, y: 212 },
{ x: 201, y: 211 },
],
},
]
export const ALT_GESTURES: Gesture[] = [
{
name: "circle layout",
onComplete(editor, gesture?: TLDrawShape) {
const bounds = editor.getShapePageBounds(gesture?.id!)
const center = bounds?.center
const radius = Math.max(bounds?.width || 0, bounds?.height || 0) / 2
const selected = editor.getSelectedShapes()
const radialShapes = circleDistribution(editor, selected, center!, radius)
editor.animateShapes(radialShapes, {
animation: {
duration: 600,
easing: (t) => t * t * (3 - 2 * t),
},
})
},
points: [
{ x: 127, y: 141 },
{ x: 124, y: 140 },
{ x: 120, y: 139 },
{ x: 118, y: 139 },
{ x: 116, y: 139 },
{ x: 111, y: 140 },
{ x: 109, y: 141 },
{ x: 104, y: 144 },
{ x: 100, y: 147 },
{ x: 96, y: 152 },
{ x: 93, y: 157 },
{ x: 90, y: 163 },
{ x: 87, y: 169 },
{ x: 85, y: 175 },
{ x: 83, y: 181 },
{ x: 82, y: 190 },
{ x: 82, y: 195 },
{ x: 83, y: 200 },
{ x: 84, y: 205 },
{ x: 88, y: 213 },
{ x: 91, y: 216 },
{ x: 96, y: 219 },
{ x: 103, y: 222 },
{ x: 108, y: 224 },
{ x: 111, y: 224 },
{ x: 120, y: 224 },
{ x: 133, y: 223 },
{ x: 142, y: 222 },
{ x: 152, y: 218 },
{ x: 160, y: 214 },
{ x: 167, y: 210 },
{ x: 173, y: 204 },
{ x: 178, y: 198 },
{ x: 179, y: 196 },
{ x: 182, y: 188 },
{ x: 182, y: 177 },
{ x: 178, y: 167 },
{ x: 170, y: 150 },
{ x: 163, y: 138 },
{ x: 152, y: 130 },
{ x: 143, y: 129 },
{ x: 140, y: 131 },
{ x: 129, y: 136 },
{ x: 126, y: 139 },
],
},
{
name: "triangle layout",
onComplete(editor, gesture?: TLDrawShape) {
const bounds = editor.getShapePageBounds(gesture?.id!)
const center = bounds?.center
const radius = Math.max(bounds?.width || 0, bounds?.height || 0) / 2
const selected = editor.getSelectedShapes()
const radialShapes = triangleDistribution(editor, selected, center!, radius)
editor.animateShapes(radialShapes, {
animation: {
duration: 600,
easing: (t) => t * t * (3 - 2 * t),
},
})
},
points: [
{ x: 137, y: 139 },
{ x: 135, y: 141 },
{ x: 133, y: 144 },
{ x: 132, y: 146 },
{ x: 130, y: 149 },
{ x: 128, y: 151 },
{ x: 126, y: 155 },
{ x: 123, y: 160 },
{ x: 120, y: 166 },
{ x: 116, y: 171 },
{ x: 112, y: 177 },
{ x: 107, y: 183 },
{ x: 102, y: 188 },
{ x: 100, y: 191 },
{ x: 95, y: 195 },
{ x: 90, y: 199 },
{ x: 86, y: 203 },
{ x: 82, y: 206 },
{ x: 80, y: 209 },
{ x: 75, y: 213 },
{ x: 73, y: 213 },
{ x: 70, y: 216 },
{ x: 67, y: 219 },
{ x: 64, y: 221 },
{ x: 61, y: 223 },
{ x: 60, y: 225 },
{ x: 62, y: 226 },
{ x: 65, y: 225 },
{ x: 67, y: 226 },
{ x: 74, y: 226 },
{ x: 77, y: 227 },
{ x: 85, y: 229 },
{ x: 91, y: 230 },
{ x: 99, y: 231 },
{ x: 108, y: 232 },
{ x: 116, y: 233 },
{ x: 125, y: 233 },
{ x: 134, y: 234 },
{ x: 145, y: 233 },
{ x: 153, y: 232 },
{ x: 160, y: 233 },
{ x: 170, y: 234 },
{ x: 177, y: 235 },
{ x: 179, y: 236 },
{ x: 186, y: 237 },
{ x: 193, y: 238 },
{ x: 198, y: 239 },
{ x: 200, y: 237 },
{ x: 202, y: 239 },
{ x: 204, y: 238 },
{ x: 206, y: 234 },
{ x: 205, y: 230 },
{ x: 202, y: 222 },
{ x: 197, y: 216 },
{ x: 192, y: 207 },
{ x: 186, y: 198 },
{ x: 179, y: 189 },
{ x: 174, y: 183 },
{ x: 170, y: 178 },
{ x: 164, y: 171 },
{ x: 161, y: 168 },
{ x: 154, y: 160 },
{ x: 148, y: 155 },
{ x: 143, y: 150 },
{ x: 138, y: 148 },
{ x: 136, y: 148 },
],
},
]