import { LineType , Rect , RefLineMeta , BoundingRect , RefLinePosition , Delta , MOVE_DIR , MatchedLine , } from "./types" ; export function toNumber ( v , numDigits = 0 ) { return + v . toFixed ( numDigits ) ; } export function deg2rad ( deg ) { return deg * ( Math . PI / 180 ) ; } param x param y param cx param cy param deg return example export function coordinateRotation ( x , y , cx , cy , deg ) { const rad = deg * ( Math . PI / 180 ) ; const x1 = x - cx ; const y1 = y - cy ; const x2 = x1 * Math . cos ( rad ) - y1 * Math . sin ( rad ) ; const y2 = x1 * Math . sin ( rad ) + y1 * Math . cos ( rad ) ; return [ x2 + cx , y2 + cy ] ; } param rect export function getBoundingRectCoordinate ( rect ) { let { width , height , left , top , rotate = 0 } = rect ; if ( rotate % 360 === 0 ) { return [ left , top , left + width , top + height ] ; } const cx = left + width / 2 ; const cy = top + height / 2 ; const topLeft = coordinateRotation ( left , top , cx , cy , rotate ) ; const topRight = coordinateRotation ( left + width , top , cx , cy , rotate ) ; const bottomLeft = coordinateRotation ( left , top + height , cx , cy , rotate ) ; const bottomRight = coordinateRotation ( left + width , top + height , cx , cy , rotate ) ; const xX = [ topLeft [ 0 ] , topRight [ 0 ] , bottomLeft [ 0 ] , bottomRight [ 0 ] ] ; const yY = [ topLeft [ 1 ] , topRight [ 1 ] , bottomLeft [ 1 ] , bottomRight [ 1 ] ] ; const xMin = Math . min ( ... xX ) ; const yMin = Math . min ( ... yY ) ; const xMax = Math . max ( ... xX ) ; const yMax = Math . max ( ... yY ) ; return [ xMin , yMin , xMax , yMax ] ; } param rect export function getBoundingRect ( rect ) { const coords = getBoundingRectCoordinate ( rect ) ; const xMin = coords [ 0 ] ; const yMin = coords [ 1 ] ; const xMax = coords [ 2 ] ; const yMax = coords [ 3 ] ; return { left : xMin , top : yMin , right : xMax , bottom : yMax , width : xMax - xMin , height : yMax - yMin , } ; } export function getRectRefLines < T extends Rect = Rect > ( rect ) { const lines = [ ] ; const boundingRect = getBoundingRect ( rect ) ; const width = boundingRect . width ; const height = boundingRect . height ; const mx = boundingRect . left + ( width === 1 ? 0 : boundingRect . width / 2 ) ; const my = boundingRect . top + ( height === 1 ? 0 : boundingRect . height / 2 ) ; return [ { type : "vertical" , position : "vl" , offset : boundingRect . left , start : boundingRect . top , end : boundingRect . bottom , rect , } , { type : "vertical" , position : "vc" , offset : mx , start : boundingRect . top , end : boundingRect . bottom , rect , } , { type : "vertical" , position : "vr" , offset : width === 1 ? boundingRect . left : boundingRect . right , start : boundingRect . top , end : boundingRect . bottom , rect , } , { type : "horizontal" , position : "ht" , offset : boundingRect . top , start : boundingRect . left , end : boundingRect . right , rect , } , { type : "horizontal" , position : "hc" , offset : my , start : boundingRect . left , end : boundingRect . right , rect , } , { type : "horizontal" , position : "hb" , offset : height === 1 ? boundingRect . top : boundingRect . bottom , start : boundingRect . left , end : boundingRect . right , rect , } , ] ; } export function groupBy < T > ( values , getKey ) { const keys = [ ] ; const group = Object . create ( null ) ; values . forEach ( value => { const key = getKey ( value ) ; if ( ! group [ key ] ) { group [ key ] = [ ] ; keys . push ( key ) ; } group [ key ] . push ( value ) ; } ) ; return { group , keys , } ; } export function find < T > ( values , predicate ) { for ( let i = 0 ; i < values . length ; i ++ ) { if ( predicate ( values [ i ] ) ) { return values [ i ] ; } } return null ; } export function getLineTypeFromPosition ( position ) { const map = { vl : "vertical" , vc : "vertical" , vr : "vertical" , ht : "horizontal" , hc : "horizontal" , hb : "horizontal" , } ; return map [ position ] ; } export function getMoveDir ( delta ) { if ( delta . left > 0 ) { return MOVE_DIR . MOVE_LEFT ; } if ( delta . left < 0 ) { return MOVE_DIR . MOVE_RIGHT ; } if ( delta . top < 0 ) { return MOVE_DIR . MOVE_TOP ; } if ( delta . top > 0 ) { return MOVE_DIR . MOVE_BOTTOM ; } return MOVE_DIR . NONE ; } param type param refLineMetaList param opts returns export function mergeRefLineMeta < T extends Rect > ( type , refLineMetaList , opts ? ) { const isVertical = type === "vertical" ; if ( ! refLineMetaList . length ) { return { type , left : 0 , top : 0 , size : 0 , refLineMetaList : [ ] , } ; } const offset = refLineMetaList [ 0 ] . offset ; const start = Math . min ( ... refLineMetaList . map ( rLine => rLine . start ) , opts ?. start == undefined ? Infinity : opts . start ) ; const end = Math . max ( ... refLineMetaList . map ( rLine => rLine . end ) , opts ?. end == undefined ? - Infinity : opts . end ) ; const startPoint = isVertical ? [ offset , start ] : [ start , offset ] ; return { type , left : startPoint [ 0 ] , top : startPoint [ 1 ] , size : end - start , refLineMetaList : [ ... refLineMetaList ] , } ; } param line param matched returns export function getMatchedLine < T extends Rect > ( line , matched ) { if ( ! matched . length ) return null ; const current = line . rect ; const boundingRect = getBoundingRect ( current ) ; const isVertical = line . type === "vertical" ; const refLineMetaList = matched ; if ( ! refLineMetaList . length ) return null ; return mergeRefLineMeta ( line . type , refLineMetaList , { start : isVertical ? boundingRect . top : boundingRect . left , end : isVertical ? boundingRect . bottom : boundingRect . right , } ) ; } export function isNil < T > ( value ) { return value == null ; }