11import {
2+ AbsoluteNumber ,
23 AbsolutePattern ,
34 AbsolutePoint ,
45 Boundaries ,
6+ NumberPair ,
57 Pattern ,
8+ PatternNumber ,
69 Point ,
10+ RelativeNumber ,
11+ RelativePattern ,
12+ RelativePoint ,
713 Size ,
814 State ,
9- asAbsolutePoint ,
15+ ViewportPoint
1016} from './types'
1117
12- const getBoundariesFromTwoPoints = ( [ x1 , y1 ] : Point , [ x2 , y2 ] : Point ) : Boundaries => {
18+ function min < N extends PatternNumber > ( a : N , b : N ) : N {
19+ return a < b ? a : b
20+ }
21+
22+ function max < N extends PatternNumber > ( a : N , b : N ) : N {
23+ return a > b ? a : b
24+ }
25+
26+ const getBoundariesFromTwoPoints = < N extends PatternNumber > ( [ x1 , y1 ] : Point < N > , [ x2 , y2 ] : Point < N > ) : Boundaries < N > => {
1327 return {
14- xMin : Math . min ( x1 , x2 ) ,
15- xMax : Math . max ( x1 , x2 ) ,
16- yMin : Math . min ( y1 , y2 ) ,
17- yMax : Math . max ( y1 , y2 ) ,
28+ xMin : min ( x1 , x2 ) ,
29+ xMax : max ( x1 , x2 ) ,
30+ yMin : min ( y1 , y2 ) ,
31+ yMax : max ( y1 , y2 ) ,
1832 }
1933}
2034
21- export const normalizePattern = ( pattern : Pattern ) : Pattern => {
35+ export const normalizePattern = < N extends PatternNumber > ( pattern : Pattern < N > ) : Pattern < N > => {
2236 const { xMin, xMax, yMin, yMax } = getBoundariesFromPattern ( pattern )
2337
2438 return {
@@ -27,11 +41,11 @@ export const normalizePattern = (pattern: Pattern): Pattern => {
2741 }
2842}
2943
30- export const getBoundariesFromPattern = ( pattern : Pattern ) : Boundaries => {
44+ export const getBoundariesFromPattern = < N extends PatternNumber > ( pattern : Pattern < N > ) : Boundaries < N > => {
3145 return getBoundariesFromTwoPoints ( pattern . anchor , pattern . target )
3246}
3347
34- export const pointIsInBoundaries = ( point : Point , boundaries : Boundaries ) : boolean => {
48+ export const pointIsInBoundaries = < N extends PatternNumber > ( point : Point < N > , boundaries : Boundaries < N > ) : boolean => {
3549 const { xMin, xMax, yMin, yMax } = boundaries
3650 const [ pointX , pointY ] = point
3751
@@ -45,45 +59,45 @@ const pointIsInPattern = (point: AbsolutePoint, pattern: AbsolutePattern): boole
4559export const mapPointToViewportSpace = (
4660 [ x , y ] : AbsolutePoint ,
4761 [ viewportWidth , viewportHeight ] : Size
48- ) : Point => {
49- return [ x * viewportWidth , y * viewportHeight ]
62+ ) : ViewportPoint => {
63+ return [ x * viewportWidth , y * viewportHeight ] satisfies NumberPair as ViewportPoint
5064}
5165
5266// ts-unused-exports:disable-next-line
5367export const mapPointFromViewportSpace = (
54- [ x , y ] : Point ,
68+ [ x , y ] : ViewportPoint ,
5569 [ viewportWidth , viewportHeight ] : Size
5670) : AbsolutePoint => {
57- return asAbsolutePoint ( [ x / viewportWidth , y / viewportHeight ] )
71+ return [ x / viewportWidth , y / viewportHeight ] satisfies NumberPair as AbsolutePoint
5872}
5973
60- const getRelativePointPosition = ( point : Point , pattern : Pattern ) : Point => {
74+ function getRelativePointPosition ( point : RelativePoint , pattern : AbsolutePattern | RelativePattern ) : RelativePoint {
6175 const [ x1 , y1 ] = pattern . anchor
6276 const [ x2 , y2 ] = pattern . target
6377 const [ x , y ] = point
6478
6579 const relativeX = ( x - x1 ) / ( x2 - x1 )
6680 const relativeY = ( y - y1 ) / ( y2 - y1 )
6781
68- return [ relativeX , relativeY ]
82+ return [ relativeX , relativeY ] satisfies NumberPair as RelativePoint
6983}
7084
71- export const getRelativePatternPosition = ( pattern : Pattern , basePattern : Pattern ) : Pattern => {
85+ export function getRelativePatternPosition ( pattern : RelativePattern , basePattern : AbsolutePattern | RelativePattern ) : RelativePattern {
7286 return {
7387 anchor : getRelativePointPosition ( pattern . anchor , basePattern ) ,
7488 target : getRelativePointPosition ( pattern . target , basePattern ) ,
7589 }
7690}
7791
78- const resolveRelativePointPosition = ( relativePoint : Point , pattern : Pattern ) : Point => {
92+ const resolveRelativePointPosition = < N extends RelativeNumber | AbsoluteNumber > ( relativePoint : RelativePoint , pattern : Pattern < N > ) : Point < N > => {
7993 const [ x1 , y1 ] = pattern . anchor
8094 const [ x2 , y2 ] = pattern . target
8195 const [ x , y ] = relativePoint
8296
8397 const resolvedX = x1 + x * ( x2 - x1 )
8498 const resolvedY = y1 + y * ( y2 - y1 )
8599
86- return [ resolvedX , resolvedY ]
100+ return [ resolvedX , resolvedY ] satisfies NumberPair as Point < N >
87101}
88102
89103export const getScreenSize = ( ctx : CanvasRenderingContext2D ) : Size => [ ctx . canvas . width , ctx . canvas . height ]
@@ -92,16 +106,16 @@ export const getMousePoint = (
92106 ctx : CanvasRenderingContext2D ,
93107 mouseEvent : React . MouseEvent < HTMLCanvasElement , MouseEvent >
94108) : AbsolutePoint => {
95- return mapPointFromViewportSpace ( [ mouseEvent . clientX , mouseEvent . clientY ] , getScreenSize ( ctx ) )
109+ const mousePosition = [ mouseEvent . clientX , mouseEvent . clientY ] satisfies NumberPair as ViewportPoint
110+
111+ return mapPointFromViewportSpace ( mousePosition , getScreenSize ( ctx ) )
96112}
97113
98- export function combinePatterns ( parent : AbsolutePattern , child : Pattern ) : AbsolutePattern
99- export function combinePatterns ( parent : Pattern , child : Pattern ) : Pattern
100- export function combinePatterns ( parent : Pattern , child : Pattern ) : Pattern {
114+ export function combinePatterns < ParentNumber extends RelativeNumber | AbsoluteNumber > ( parent : Pattern < ParentNumber > , child : RelativePattern ) : Pattern < ParentNumber > {
101115 return {
102116 anchor : resolveRelativePointPosition ( child . anchor , parent ) ,
103117 target : resolveRelativePointPosition ( child . target , parent ) ,
104- }
118+ }
105119}
106120
107121type NestedPath = number [ ]
@@ -115,7 +129,7 @@ const MAX_DEPTH = 4
115129
116130const findClickedPattern = (
117131 previousBasePattern : AbsolutePattern ,
118- patterns : Pattern [ ] ,
132+ patterns : RelativePattern [ ] ,
119133 point : AbsolutePoint ,
120134 path : number [ ] = [ ]
121135) : NestedPath | undefined => {
0 commit comments