import { EventList } from "../list/EventList" ; import { StatusList } from "../list/StatusList" ; import type { Segment , XEvent } from "../types" ; /** Core */ export abstract class Core { protected events = new EventList ( ) ; protected abstract mergeFill ( ev , eve ) ; /** calculate fill flags */ protected abstract calculateFill ( ev , below , polyInverted1 , polyInverted2 ) ; protected calculate ( primaryPolyInverted , secondaryPolyInverted ) { let status = new StatusList ( ) ; let segments = [ ] ; while ( ! this . events . isEmpty ( ) ) { let ev = this . events . getHead ( ) ; if ( ev . isStart ) { let surrounding = status . findSurrounding ( ev ) ; let above = surrounding . before ; let below = surrounding . after ; let eve = this . events . checkBothIntersections ( ev , above , below ) ; if ( eve ) { this . mergeFill ( ev , eve ) ; this . events . remove ( ev . other ! ) ; this . events . remove ( ev ) ; } if ( this . events . getHead ( ) !== ev ) { continue ; } this . calculateFill ( ev , below , primaryPolyInverted , secondaryPolyInverted ) ; ev . other ! . status = surrounding . insert ( ev ) ; } else { let st = ev . status ; if ( st === null ) { throw new Error ( 'PolyBool: Zero-length segment detected; your epsilon is probably too small or too large' ) ; } let i = status . getIndex ( st ) ; if ( i > 0 && i < status . nodes . length - 1 ) { let before = status . nodes [ i - 1 ] , after = status . nodes [ i + 1 ] ; this . events . checkIntersection ( before , after ) ; } status . remove ( st ) ; if ( ! ev . primary ) { let s = ev . seg . fill ; ev . seg . fill = ev . seg . otherFill ! ; ev . seg . otherFill = s ; } segments . push ( ev . seg ) ; } this . events . nodes . shift ( ) ; } return segments ; } }