import { Kamiya } from "./Kamiya" ; import { GOPS } from "./GOPS" ; import { Gadget , Piece } from "../models" ; import { Strategy } from "bp/content/json" ; import { Disposable } from "bp/class" ; import { clone } from "bp/util" ; import type { JPartition , JDevice , JGadget , JOverlap , JPiece , JQuadrilateral } from "bp/content/json" ; import type { Tree } from "bp/content/context" ; import type { Configuration } from ".." ; /**
 *  Partitioner 是  Partition 的基底類別，
 * 裡面定義了跟搜尋  Device 有關的方法。
  export class Partitioner extends Disposable { public readonly $configuration : Configuration ; public readonly $overlaps : readonly JOverlap [ ] ; protected readonly _strategy ? : Strategy ; constructor ( config , data ) { super ( config ) ; this . $configuration = config ; this . $overlaps = data . overlaps ; this . _strategy = data . strategy ; } param oriented public static $getMaxIntersectionDistance ( tree , r1 , r2 , oriented ) { let q = oriented ? 2 : 0 ; let n1 = tree . $node . get ( r1 . c [ q ] . e ! ) ! ; let n2 = tree . $node . get ( r2 . c [ q ] . e ! ) ! ; let n3 = tree . $node . get ( r1 . c [ 2 - q ] . e ! ) ! ; return tree . $distTriple ( n1 , n2 , n3 ) . d3 ; } public * $generate ( ) { let { _strategy : strategy } = this ; if ( this . $overlaps . length == 1 ) { let o = this . $overlaps [ 0 ] ; let j = this . $configuration . $repository . $structure [ o . parent ] ; if ( strategy == Strategy . $halfIntegral ) { for ( let g of Kamiya . _halfIntegral ( o , j . sx ) ) yield { gadgets : [ g ] } ; } if ( strategy == Strategy . $universal ) { for ( let g of Partitioner . _universalGPS ( o , j . sx ) ) yield { gadgets : [ g ] } ; } else { for ( let p of GOPS . $generate ( o . ox , o . oy , j . sx ) ) yield { gadgets : [ { pieces : [ p ] } ] } ; } } if ( this . $overlaps . length == 2 ) { let joiner = this . $configuration . $repository . getJoiner ( this . $overlaps ) ; if ( strategy == Strategy . $baseJoin ) { yield * joiner . $baseJoin ( ) ; } else if ( strategy == Strategy . $standardJoin ) { yield * joiner . $standardJoin ( ) ; } else { yield * joiner . $simpleJoin ( strategy ) ; } } } /** 通用型 GPS 策略；保證能在單 Overlap 的情況中找到 Pattern */ private static * _universalGPS ( o , sx ) { let d = 2 , found = false ; while ( ! found ) { let bigO = clone ( o ) ; bigO . ox *= d ; bigO . oy *= d ; for ( let p of GOPS . $generate ( bigO . ox , bigO . oy , sx * d ) ) { let p1 = Piece . $instantiate ( p ) . $shrink ( d ) ; if ( ! Number . isInteger ( p1 . v ) ) continue ; let { ox , oy , u , v } = p1 ; let p2 = { ox , oy , u : v , v : u } ; let pt1 = { x : 0 , y : 0 } , pt2 = { x : oy + u + v , y : ox + u + v } ; p1 . detours = [ [ pt1 , pt2 ] ] ; p2 . detours = [ [ pt2 , pt1 ] ] ; let x = p1 . oy + p1 . u + p1 . v , s = Math . ceil ( x ) - x ; let g = new Gadget ( { pieces : [ p1 , p2 ] } ) ; let gr = g . $reverseGPS ( ) ; yield g . $addSlack ( 2 , s ) ; yield gr . $addSlack ( 0 , s ) ; found = true ; } d += 2 ; } } }