import { Partitioner } from "./Partitioner" ; import { Direction , onDemand , opposite } from "bp/global" ; import { clone } from "bp/util" ; import { CornerType } from "bp/content/json" ; import type { JConnection , JJunction , JCorner , JOverlap , JPartition } from "bp/content/json" ; import type { Configuration , Pattern } from ".." ; import type { QuadrantDirection } from "bp/global" ; import type { Point , Vector } from "bp/math" ; /**
 * 第 0 欄位是  JCorner 本身，
 * 第 1 位表示它在當前  Partition 中的第幾個  Overlap ，
 * 第 2 位表示在該  Overlap 中的哪一個  Anchor type CornerMap = [ JCorner , number , number ] ; /**
 *  Partition 是  Configuration 底下的單一切割。
 *
 *  Partition 只會對應於單一的  Device ，它負責計算對應切割的相關數值。
 * 尋找  Device 部份的程式碼在於其基底類別  Partitioner 之中。
  @ shrewd export class Partition extends Partitioner implements ISerializable < JPartition > { /** 這個 Partition 所有的角落，檢索得到所屬的 Overlap 以及相位索引 */ public readonly $cornerMap : CornerMap [ ] = [ ] ; constructor ( config , data ) { super ( config , data ) ; for ( let [ i , o ] of data . overlaps . entries ( ) ) { for ( let [ j , c ] of o . c . entries ( ) ) { this . $cornerMap . push ( [ c , i , j ] ) ; } } } /** 所有的 CornerType . $side 或 CornerType . $intersection @ onDemand public get $intersectionCorners ( ) : readonly CornerMap [ ] { return this . $cornerMap . filter ( m => { let type = m [ 0 ] . type ; return type == CornerType . $side || type == CornerType . $intersection ; } ) ; } /** 所有向外連出的角落（ CornerType . $flap ）  @ onDemand public get $outCorners ( ) : readonly CornerMap [ ] { return this . $intersectionCorners . concat ( this . $cornerMap . filter ( m => m [ 0 ] . type == CornerType . $flap ) ) ; } /** 所有相關於 Gadget 移動約束條件的角落 */ @ onDemand public get $constraints ( ) : readonly CornerMap [ ] { return this . $cornerMap . filter ( m => { let type = m [ 0 ] . type ; return type == CornerType . $socket || type == CornerType . $internal || type == CornerType . $flap ; } ) ; } public $getOriginalDisplacement ( pattern ) { let overlap = this . $overlaps . find ( o => o . c [ 0 ] . type != CornerType . $coincide ) ! ; return pattern . $getConnectionTarget ( overlap . c [ 0 ] as JConnection ) . sub ( this . $configuration . $repository . $stretch . origin ) ; } @ shrewd private get _sideConnectionTarget ( ) : ReadonlyMap < JCorner , [ Point , Point ] > { this . $disposeEvent ( ) ; let result = new Map < JCorner , [ Point , Point ] > ( ) ; let flaps = this . $configuration . $sheet . $design . $flaps . $byId ; for ( let [ c , o , q1 ] of this . $intersectionCorners ) { let ov = this . $overlaps [ o ] ; let parent = this . _getParent ( ov ) ; if ( ! ov || ! parent ) debugger ; let [ c1 , c2 ] = [ parent . c [ 0 ] , parent . c [ 2 ] ] ; let [ f1 , f2 ] = [ flaps . get ( c1 . e ! ) ! , flaps . get ( c2 . e ! ) ! ] ; if ( ! f1 || ! f2 ) debugger ; let quad1 = f1 . $quadrants [ c1 . q ! ] , d1 = 0 ; let quad2 = f2 . $quadrants [ c2 . q ! ] , d2 = 0 ; if ( c . type == CornerType . $intersection ) { let oriented = ov . c [ 0 ] . e ! < 0 ; let tree = this . $configuration . $sheet . $design . $tree ; let n3 = tree . $node . get ( c . e ! ) ! ; let t = tree . $distTriple ( f1 . node , f2 . node , n3 ) ; if ( oriented ) d2 = t . d2 - f2 . radius ; else d1 = t . d1 - f1 . radius ; if ( isNaN ( d1 ) || isNaN ( d2 ) ) debugger ; } ov = this . _getExposedOverlap ( ov ) ; let p1 = quad1 . $getOverlapCorner ( ov , parent , q1 , d1 ) ; let p2 = quad2 . $getOverlapCorner ( ov , parent , opposite ( q1 ) , d2 ) ; result . set ( c , [ p1 , p2 ] ) ; } return result ; } /** 求出在一個具有 join 的  Partition 中，指定的  JOverlap 在扣掉其它所有 `JOverlap 之後還剩下什麼區域  private _getExposedOverlap ( ov ) { if ( this . $overlaps . length == 1 ) return ov ; let result = clone ( ov ) , parent = this . _getParent ( ov ) ; result . shift = result . shift ?? { x : 0 , y : 0 } ; for ( let o of this . $overlaps ) { if ( o != ov ) { let p = this . _getParent ( o ) ; let w = result . ox + result . shift . x ; let h = result . oy + result . shift . y ; if ( p . c [ 0 ] . e == parent . c [ 0 ] . e ) { if ( p . ox < parent . ox ) { result . ox = w - ( result . shift . x = Math . max ( result . shift . x , p . ox ) ) ; } if ( p . oy < parent . oy ) { result . oy = h - ( result . shift . y = Math . max ( result . shift . y , p . oy ) ) ; } } if ( p . c [ 2 ] . e == parent . c [ 2 ] . e ) { if ( p . ox < parent . ox ) { result . ox = parent . ox - Math . max ( p . ox , parent . ox - w ) - result . shift . x ; } if ( p . oy < parent . oy ) { result . oy = parent . oy - Math . max ( p . oy , parent . oy - h ) - result . shift . y ; } } } } return result ; } /** 取得一個  JOverlap 原本對應的  JJunction private _getParent ( ov ) { return this . $configuration . $repository . $structure [ ov . parent ] ; } param point param c param q public $getSideConnectionTarget ( point , c , q ? ) { let [ p1 , p2 ] = this . _sideConnectionTarget . get ( c ) ! ; if ( p1 . _x . gt ( p2 . _x ) ) [ p1 , p2 ] = [ p2 , p1 ] ; if ( q === undefined ) { if ( point . _x . le ( p1 . _x ) ) return p1 ; if ( point . _x . ge ( p2 . _x ) ) return p2 ; return null ; } else { return q == Direction . UR || q == Direction . LR ? p1 : p2 ; } } public toJSON ( ) { let result = { overlaps : this . $overlaps , strategy : this . _strategy , } ; let tree = this . $configuration . $design . $tree ; if ( tree . $jid ) { result . overlaps = clone ( result . overlaps ) ; for ( let o of result . overlaps ) { for ( let c of o . c ) { if ( c . e !== undefined && c . e >= 0 ) { c . e = tree . $node . get ( c . e ) ! . id ; } } } } return result ; } }