Immediately resolve complement operators for regions (#3145)

This commit is contained in:
Paul Romano 2024-10-10 12:58:15 -05:00 committed by GitHub
parent 579777a3e5
commit 91fd60be69
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 24 additions and 31 deletions

View file

@ -778,12 +778,6 @@ class XConeOneSided(CompositeSurface):
def __neg__(self):
return -self.cone & (+self.plane if self.up else -self.plane)
def __pos__(self):
if self.up:
return (+self.cone & +self.plane) | -self.plane
else:
return (+self.cone & -self.plane) | +self.plane
class YConeOneSided(CompositeSurface):
"""One-sided cone parallel the y-axis
@ -836,7 +830,6 @@ class YConeOneSided(CompositeSurface):
self.up = up
__neg__ = XConeOneSided.__neg__
__pos__ = XConeOneSided.__pos__
class ZConeOneSided(CompositeSurface):
@ -890,7 +883,6 @@ class ZConeOneSided(CompositeSurface):
self.up = up
__neg__ = XConeOneSided.__neg__
__pos__ = XConeOneSided.__pos__
class Polygon(CompositeSurface):

View file

@ -1,3 +1,4 @@
from __future__ import annotations
from abc import ABC, abstractmethod
from collections.abc import MutableSequence
from copy import deepcopy
@ -30,8 +31,9 @@ class Region(ABC):
def __or__(self, other):
return Union((self, other))
def __invert__(self):
return Complement(self)
@abstractmethod
def __invert__(self) -> Region:
pass
@abstractmethod
def __contains__(self, point):
@ -442,6 +444,9 @@ class Intersection(Region, MutableSequence):
self.append(other)
return self
def __invert__(self) -> Union:
return Union(~n for n in self)
# Implement mutable sequence protocol by delegating to list
def __getitem__(self, key):
return self._nodes[key]
@ -530,6 +535,9 @@ class Union(Region, MutableSequence):
self.append(other)
return self
def __invert__(self) -> Intersection:
return Intersection(~n for n in self)
# Implement mutable sequence protocol by delegating to list
def __getitem__(self, key):
return self._nodes[key]
@ -603,7 +611,7 @@ class Complement(Region):
"""
def __init__(self, node):
def __init__(self, node: Region):
self.node = node
def __contains__(self, point):
@ -622,6 +630,9 @@ class Complement(Region):
"""
return point not in self.node
def __invert__(self) -> Region:
return self.node
def __str__(self):
return '~' + str(self.node)
@ -637,18 +648,7 @@ class Complement(Region):
@property
def bounding_box(self) -> BoundingBox:
# Use De Morgan's laws to distribute the complement operator so that it
# only applies to surface half-spaces, thus allowing us to calculate the
# bounding box in the usual recursive manner.
if isinstance(self.node, Union):
temp_region = Intersection(~n for n in self.node)
elif isinstance(self.node, Intersection):
temp_region = Union(~n for n in self.node)
elif isinstance(self.node, Complement):
temp_region = self.node.node
else:
temp_region = ~self.node
return temp_region.bounding_box
return (~self.node).bounding_box
def get_surfaces(self, surfaces=None):
"""Recursively find and return all the surfaces referenced by the node

View file

@ -1,3 +1,4 @@
from __future__ import annotations
from abc import ABC, abstractmethod
from collections.abc import Iterable
from copy import deepcopy
@ -2631,7 +2632,7 @@ class Halfspace(Region):
else:
return Union((self, other))
def __invert__(self):
def __invert__(self) -> Halfspace:
return -self.surface if self.side == '+' else +self.surface
def __contains__(self, point):

View file

@ -12,7 +12,7 @@
</materials>
<geometry>
<cell id="1" material="1" region="1 -2 3 -4 10 -9" universe="1"/>
<cell id="2" material="2" region="~(1 -2 3 -4) (5 -6 7 -8) 10 -9" universe="1"/>
<cell id="2" material="2" region="(-1 | 2 | -3 | 4) (5 -6 7 -8) 10 -9" universe="1"/>
<surface coeffs="-5.0" id="1" name="minimum x" type="x-plane"/>
<surface coeffs="5.0" id="2" name="maximum x" type="x-plane"/>
<surface coeffs="-5.0" id="3" name="minimum y" type="y-plane"/>

View file

@ -12,7 +12,7 @@
</materials>
<geometry>
<cell id="1" material="1" region="1 -2 3 -4 10 -9" universe="1"/>
<cell id="2" material="2" region="~(1 -2 3 -4) (5 -6 7 -8) 10 -9" universe="1"/>
<cell id="2" material="2" region="(-1 | 2 | -3 | 4) (5 -6 7 -8) 10 -9" universe="1"/>
<surface coeffs="-5.0" id="1" name="minimum x" type="x-plane"/>
<surface coeffs="5.0" id="2" name="maximum x" type="x-plane"/>
<surface coeffs="-5.0" id="3" name="minimum y" type="y-plane"/>

View file

@ -12,7 +12,7 @@
</materials>
<geometry>
<cell id="1" material="1" region="1 -2 3 -4 10 -9" universe="1"/>
<cell id="2" material="2" region="~(1 -2 3 -4) (5 -6 7 -8) 10 -9" universe="1"/>
<cell id="2" material="2" region="(-1 | 2 | -3 | 4) (5 -6 7 -8) 10 -9" universe="1"/>
<surface coeffs="-5.0" id="1" name="minimum x" type="x-plane"/>
<surface coeffs="5.0" id="2" name="maximum x" type="x-plane"/>
<surface coeffs="-5.0" id="3" name="minimum y" type="y-plane"/>

View file

@ -9,7 +9,7 @@
<geometry>
<cell id="1" material="void" region="-1 2 -3" universe="1"/>
<cell id="2" material="1" region="-1 3 -4" universe="1"/>
<cell id="3" material="void" region="~(-1 2 -4)" universe="1"/>
<cell id="3" material="void" region="1 | -2 | 4" universe="1"/>
<surface boundary="vacuum" coeffs="0.0 0.0 1.0" id="1" type="x-cylinder"/>
<surface boundary="vacuum" coeffs="-1.0" id="2" type="x-plane"/>
<surface coeffs="1.0" id="3" type="x-plane"/>

View file

@ -9,7 +9,7 @@
<geometry>
<cell id="1" material="void" region="-1 2 -3" universe="1"/>
<cell id="2" material="1" region="-1 3 -4" universe="1"/>
<cell id="3" material="void" region="~(-1 2 -4)" universe="1"/>
<cell id="3" material="void" region="1 | -2 | 4" universe="1"/>
<surface boundary="vacuum" coeffs="0.0 0.0 1.0" id="1" type="x-cylinder"/>
<surface boundary="vacuum" coeffs="-1.0" id="2" type="x-plane"/>
<surface coeffs="1.0" id="3" type="x-plane"/>

View file

@ -12,7 +12,7 @@
</materials>
<geometry>
<cell id="1" material="1" region="1 -2 3 -4 10 -9" universe="1"/>
<cell id="2" material="2" region="~(1 -2 3 -4) (5 -6 7 -8) 10 -9" universe="1"/>
<cell id="2" material="2" region="(-1 | 2 | -3 | 4) (5 -6 7 -8) 10 -9" universe="1"/>
<surface coeffs="-5.0" id="1" name="minimum x" type="x-plane"/>
<surface coeffs="5.0" id="2" name="maximum x" type="x-plane"/>
<surface coeffs="-5.0" id="3" name="minimum y" type="y-plane"/>

View file

@ -106,7 +106,7 @@ def test_complement(reset):
assert_unbounded(outside_equiv)
# string represention
assert str(inside) == '~(1 | -2 | 3)'
assert str(inside) == '(-1 2 -3)'
# evaluate method
assert (0, 0, 0) in inside