# Implementation of module {shape}. # Last edited on 2021-09-23 15:25:41 by stolfi import shape import rootray import trafo import sys from math import sqrt, sin, cos, floor, ceil, inf, nan, pi class Shape_IMP: # Must be subclassed. pass def vacuum(): return None # ---------------------------------------------------------------------- def plenum(): return (1, None) # ---------------------------------------------------------------------- def unpack(S): if S == None: return 0, None, () elif isinstance(S, shape.Shape): return 0, None, (S,) else: assert type(S) is tuple assert len(S) >= 2 cbit = S[0] assert type(cbit) is int assert cbit == 0 or cbit == 1, "invalid {cbit}" if len(S) == 2: # The trafo is irrelevant if {S} is vacuum or plenum. TS = None SL = () else: TS = S[1] assert TS == None or isinstance(TS, trafo.Trafo) SL = S[2:] return cbit, TS, SL # ---------------------------------------------------------------------- def is_vacuum(S): cbit, TS, SL = unpack(S) if cbit == 0: if len(SL) == 0: return True if len(SL) == 1 and SL[0] != S and is_vacuum(SL[0]): return True else: if len(SL) == 0: return False if len(SL) == 1 and SL[0] != S and is_plenum(SL[0]): return True return False # ---------------------------------------------------------------------- def is_plenum(S): cbit, TS, SL = unpack(S) if cbit == 1: if len(SL) == 0: return True if len(SL) == 1 and SL[0] != S and is_vacuum(SL[0]): return True else: if len(SL) == 0: return False if len(SL) == 1 and SL[0] != S and is_plenum(SL[0]): return True return False # ---------------------------------------------------------------------- def complement(S): cbit, TS, SL = unpack(S) if cbit == 1 and TS == None and len(SL) == 1: return SL[0] elif len(SL) == 0: return (1-cbit, None) else: return (1-cbit, TS) + SL # ---------------------------------------------------------------------- def union(SL): assert type(SL) is list or type(SL) is tuple if len(SL) == 0: return vacuum() H = [] # List of the non-trivial shapes in {SL}. for Sk in SL: if is_vacuum(Sk): pass elif is_plenum(Sk): return plenum() else: H.append(Sk) if len(H) == 0: return vacuum() if len(H) == 1: return H[0] return (0,None) + tuple(H) # ---------------------------------------------------------------------- def intersection(SL): assert type(SL) is list or type(SL) is tuple if len(SL) == 0: return plenum() H = [] # List of complements of the non-trivial shapes in {SL}. for Sk in SL: if is_plenum(Sk): pass elif is_vacuum(Sk): return vacuum() else: H.append(complement(Sk)) if len(H) == 0: return plenum() if len(H) == 1: return complement(H[0]) return (1,None) + tuple(H) # ---------------------------------------------------------------------- def difference(S, SL): return complement(union((complement(S),) + tuple(SL))) # ---------------------------------------------------------------------- def transform(S,T): cbit, TS, SL = unpack(S) if len(SL) == 0: # Vacuum or plenum: return S else: Tnew = trafo.compose((TS, T)) return (cbit,Tnew) + SL # ---------------------------------------------------------------------- def simplify(S): if S == None or isinstance(S, shape.Shape): return S sys.stderr.write("??? {shape.simplify}: to be written ???\n") return S # ----------------------------------------------------------------------