@@ -249,7 +249,9 @@ export const findClickedScreenOrPattern = (
249249 const screen = screens [ i ] !
250250 const clickedPath = findClickedPattern (
251251 screen ,
252- patterns . map ( p => p . pattern ) ,
252+ patterns . map (
253+ p => applyMatrixAndOffsetToRectangle ( p . matrix , p . offset , screen ) as unknown as RelativePattern
254+ ) ,
253255 point
254256 )
255257
@@ -278,3 +280,76 @@ export function randomId(): string {
278280 // todo: use uuid or something
279281 return Math . random ( ) . toString ( 36 ) . substring ( 2 , 15 )
280282}
283+
284+ export function getMatrixAndOffsetFromRectangle ( { anchor, target } : RelativePattern ) : {
285+ matrix : [ a : number , b : number , c : number , d : number ]
286+ offset : [ x : number , y : number ]
287+ } {
288+ const [ x1 , y1 ] = anchor
289+ const [ x2 , y2 ] = target
290+
291+ // The transformation is: newX = x1 + relativeX * (x2 - x1), newY = y1 + relativeY * (y2 - y1)
292+ // This can be written as a matrix transformation:
293+ // [newX] = [(x2-x1) 0 ] [relativeX] + [x1]
294+ // [newY] [0 (y2-y1)] [relativeY] [y1]
295+
296+ const scaleX = x2 - x1
297+ const scaleY = y2 - y1
298+ const offsetX = x1
299+ const offsetY = y1
300+
301+ const matrix = [ scaleX , 0 , 0 , scaleY ] satisfies [ a : number , b : number , c : number , d : number ]
302+ const offset = [ offsetX , offsetY ] satisfies [ x : number , y : number ]
303+
304+ return { matrix, offset }
305+ }
306+
307+ function applyMatrixAndOffsetToPoint < ParentNumber extends PatternNumber > (
308+ matrix : [ a : number , b : number , c : number , d : number ] ,
309+ offset : [ x : number , y : number ] ,
310+ point : Point < ParentNumber >
311+ ) : Point < ParentNumber > {
312+ const [ a , b , c , d ] = matrix
313+ const [ dx , dy ] = offset
314+ const [ x , y ] = point
315+
316+ return [ x * a + y * c + dx , x * b + y * d + dy ] as Point < ParentNumber >
317+ }
318+
319+ export function applyMatrixAndOffsetToRectangle < ParentNumber extends PatternNumber > (
320+ matrix : [ a : number , b : number , c : number , d : number ] ,
321+ offset : [ x : number , y : number ] ,
322+ rectangle : Pattern < ParentNumber >
323+ ) : Pattern < ParentNumber > {
324+ const { anchor, target } = rectangle
325+
326+ return {
327+ anchor : applyMatrixAndOffsetToPoint ( matrix , offset , anchor ) ,
328+ target : applyMatrixAndOffsetToPoint ( matrix , offset , target ) ,
329+ }
330+ }
331+
332+ export function combineTransformations (
333+ matrix1 : [ a : number , b : number , c : number , d : number ] ,
334+ offset1 : [ x : number , y : number ] ,
335+ matrix2 : [ a : number , b : number , c : number , d : number ] ,
336+ offset2 : [ x : number , y : number ]
337+ ) : { matrix : [ a : number , b : number , c : number , d : number ] ; offset : [ x : number , y : number ] } {
338+ const [ a1 , b1 , c1 , d1 ] = matrix1
339+ const [ a2 , b2 , c2 , d2 ] = matrix2
340+ const [ x1 , y1 ] = offset1
341+ const [ x2 , y2 ] = offset2
342+
343+ const matrix = [ a1 * a2 + c1 * b2 , b1 * a2 + d1 * b2 , a1 * c2 + c1 * d2 , b1 * c2 + d1 * d2 ] satisfies [
344+ a : number ,
345+ b : number ,
346+ c : number ,
347+ d : number ,
348+ ]
349+ const offset = [ a1 * x2 + c1 * y2 + x1 , b1 * x2 + d1 * y2 + y1 ] satisfies [ x : number , y : number ]
350+
351+ return {
352+ matrix,
353+ offset,
354+ }
355+ }
0 commit comments