import { Rect } from './Rect' ; import { Preconditions } from 'polar-shared/src/Preconditions' ; import { Point } from './Point' ; import { Line } from './util/Line' ; import { Styles } from './util/Styles' ; import { IRect } from 'polar-shared/src/util/rects/IRect' ; import { Objects } from "polar-shared/src/util/Objects" ; export class Rects { param rect { Rect | DOMRect } return static isVisible ( rect ) { return rect . height > 0 && rect . width > 0 ; } param rect { Rect } param scale { number } public static scale ( rect , scale ) { Preconditions . assertPresent ( rect , "rect" ) ; rect = Rects . validate ( rect ) ; rect = new Rect ( rect ) ; const result = { } ; Objects . typedKeys ( rect ) . forEach ( key => { result [ key ] = Math . floor ( < number > rect [ key ] * scale ) ; } ) ; return Rects . validate ( result ) ; } param rect { Object } return { Rect } public static validate ( rect ) { Preconditions . assertPresent ( rect . left , "left" ) ; Preconditions . assertPresent ( rect . top , "top" ) ; Preconditions . assertPresent ( rect . width , "width" ) ; Preconditions . assertPresent ( rect . height , "height" ) ; Preconditions . assertPresent ( rect . bottom , "bottom" ) ; Preconditions . assertPresent ( rect . right , "right" ) ; Preconditions . assertNumber ( rect . left , "left" ) ; Preconditions . assertNumber ( rect . top , "top" ) ; Preconditions . assertNumber ( rect . width , "width" ) ; Preconditions . assertNumber ( rect . height , "height" ) ; Preconditions . assertNumber ( rect . bottom , "bottom" ) ; Preconditions . assertNumber ( rect . right , "right" ) ; if ( ! ( rect instanceof Rect ) ) { return new Rect ( rect ) ; } else { return rect ; } } param point { Point } param rect { Rect } public static relativeTo ( point , rect ) { rect = Rects . validate ( rect ) ; rect = new Rect ( rect ) ; rect . left = rect . left + point . x ; rect . top = rect . top + point . y ; rect . right = rect . right + point . x ; rect . bottom = rect . bottom + point . y ; return Rects . validate ( rect ) ; } param rect { Rect } param dir { Object } param absolute { boolean } return { Rect } static move ( rect , dir , absolute ) { rect = new Rect ( rect ) ; if ( absolute ) { if ( dir . x !== undefined ) { rect . left = dir . x ; rect . right = rect . left + rect . width ; } if ( dir . y !== undefined ) { rect . top = dir . y ; rect . bottom = rect . top + rect . height ; } } else { if ( dir . x !== undefined ) { rect . left = rect . left + dir . x ; rect . right = rect . right + dir . x ; } if ( dir . y !== undefined ) { rect . bottom = rect . bottom + dir . y ; rect . top = rect . top + dir . y ; } } return Rects . validate ( rect ) ; } param a { Rect | Object } param b { Rect | Object } return { boolean } static intersect ( a , b ) { return ( a . left <= b . right && b . left <= a . right && a . top <= b . bottom && b . top <= a . bottom ) ; } param a { Rect } param b { Rect } return { boolean } static overlap ( a , b ) { return a . toLine ( "x" ) . overlaps ( b . toLine ( "x" ) ) || a . toLine ( "y" ) . overlaps ( b . toLine ( "y" ) ) ; } param a { Rect } param b { Rect } return { Rect } static intersection ( a , b ) { return Rects . createFromBasicRect ( { top : Math . max ( a . top , b . top ) , bottom : Math . min ( a . bottom , b . bottom ) , left : Math . max ( a . left , b . left ) , right : Math . min ( a . right , b . right ) , } ) ; } param a { Rect } param b { Rect } return { Array < string > } static intersectedPositions ( a , b ) { const result = [ ] ; if ( interval ( a . left , b . right , a . right ) ) { result . push ( "left" ) ; } if ( interval ( a . left , b . left , a . right ) ) { result . push ( "right" ) ; } if ( interval ( a . top , b . bottom , a . bottom ) ) { result . push ( "top" ) ; } if ( interval ( a . top , b . top , a . bottom ) ) { result . push ( "bottom" ) ; } return result ; } param a { Rect } param b { Rect } return { Object } static relativePositions ( a , b ) { Rects . validate ( a ) ; Rects . validate ( b ) ; const result = { } ; result . top = Math . abs ( a . top - b . bottom ) ; result . bottom = Math . abs ( a . bottom - b . top ) ; result . left = Math . abs ( a . left - a . right ) ; result . right = Math . abs ( a . right - b . left ) ; return result ; } param a { Rect } param b { Rect } static subtract ( a , b ) { a = Rects . validate ( a ) ; b = Rects . validate ( b ) ; const keys = [ "left" , "top" , "right" , "bottom" , "width" , "height" ] ; const result = { } ; keys . forEach ( key => { result [ key ] = < number > a [ key ] - < number > b [ key ] ; } ) ; return new Rect ( result ) ; } param a { Rect } param b { Rect } static add ( a , b ) { a = Rects . validate ( a ) ; b = Rects . validate ( b ) ; const keys = [ "left" , "top" , "right" , "bottom" , "width" , "height" ] ; const result = { } ; keys . forEach ( key => { result [ key ] = < number > a [ key ] + < number > b [ key ] ; } ) ; return new Rect ( result ) ; } param a { Rect } param b { Rect } return { Rect } static perc ( a , b ) { if ( a . width > b . width || a . height > b . height ) { throw new Error ( `Dimensions invalid ${ a . dimensions } vs ${ b . dimensions }` ) ; } const result = { left : 100 * ( a . left / b . width ) , right : 100 * ( a . right / b . width ) , top : 100 * ( a . top / b . height ) , bottom : 100 * ( a . bottom / b . height ) } ; return Rects . createFromBasicRect ( result ) ; } param rect { Rect | Object } return { Rect } public static createFromBasicRect ( rect ) { rect = new Rect ( rect ) ; if ( ! rect . bottom && "top" in rect && "height" in rect ) { rect . bottom = rect . top + rect . height ; } if ( ! rect . right && "left" in rect && "width" in rect ) { rect . right = rect . left + rect . width ; } if ( ! rect . height && "bottom" in rect && "top" in rect ) { rect . height = rect . bottom - rect . top ; } if ( ! rect . width && "right" in rect && "left" in rect ) { rect . width = rect . right - rect . left ; } return Rects . validate ( new Rect ( rect ) ) ; } /**
     * Create a new rect from the given lines
     */ static createFromLines ( xAxis , yAxis ) { Preconditions . assertPresent ( xAxis , "xAxis" ) ; Preconditions . assertPresent ( yAxis , "yAxis" ) ; Preconditions . assertEqual ( xAxis . axis , "x" , "xAxis.axis" ) ; Preconditions . assertEqual ( yAxis . axis , "y" , "yAxis.axis" ) ; return Rects . createFromBasicRect ( { left : xAxis . start , width : xAxis . length , top : yAxis . start , height : yAxis . length } ) ; } static createFromOffset ( element ) { return Rects . createFromBasicRect ( { left : element . offsetLeft , top : element . offsetTop , width : element . offsetWidth , height : element . offsetHeight , } ) ; } param element { HTMLElement } static fromElementStyle ( element ) { const rect = { left : Styles . parsePX ( element . style . left ) , top : Styles . parsePX ( element . style . top ) , width : Styles . parsePX ( element . style . width ) , height : Styles . parsePX ( element . style . height ) } ; return Rects . createFromBasicRect ( rect ) ; } } /**
 * Return true if the point is within the given min and max interval.
 *
 */ function interval ( min , point , max ) { return min <= point && point <= max ; } export interface Direction { readonly x ? : number ; readonly y ? : number ; }