Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 18 additions & 3 deletions src/shapepy/bool2d/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,23 @@
operations between subsets
"""

from ..tools import Is
from .base import Future
from .boolean import intersect, unite
from .boolean import (
clean_bool2d,
intersect_bool2d,
invert_bool2d,
unite_bool2d,
xor_bool2d,
)
from .convert import from_any
from .lazy import is_lazy

Future.unite = unite
Future.intersect = intersect
Future.invert = invert_bool2d
Future.unite = unite_bool2d
Future.intersect = intersect_bool2d
Future.clean = clean_bool2d
Future.convert = from_any
Future.xor = xor_bool2d

Is.lazy = is_lazy
135 changes: 119 additions & 16 deletions src/shapepy/bool2d/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@
from __future__ import annotations

from abc import abstractmethod
from copy import copy
from typing import Iterable, Tuple, Union

from ..geometry.point import Point2D
from ..loggers import debug
from ..scalar.angle import Angle
from ..scalar.reals import Real
from .config import Config
from .density import Density


Expand All @@ -27,19 +27,29 @@ class SubSetR2:
def __init__(self):
pass

@abstractmethod
@debug("shapepy.bool2d.base")
def __invert__(self) -> SubSetR2:
"""Invert shape"""
result = Future.invert(self)
if Config.clean["inv"]:
result = Future.clean(result)
return result

@debug("shapepy.bool2d.base")
def __or__(self, other: SubSetR2) -> SubSetR2:
"""Union shapes"""
return Future.unite((self, other))
result = Future.unite((self, other))
if Config.clean["or"]:
result = Future.clean(result)
return result

@debug("shapepy.bool2d.base")
def __and__(self, other: SubSetR2) -> SubSetR2:
"""Intersection shapes"""
return Future.intersect((self, other))
result = Future.intersect((self, other))
if Config.clean["and"]:
result = Future.clean(result)
return result

@abstractmethod
def __copy__(self) -> SubSetR2:
Expand All @@ -51,27 +61,42 @@ def __deepcopy__(self, memo) -> SubSetR2:

def __neg__(self) -> SubSetR2:
"""Invert the SubSetR2"""
return ~self
result = Future.invert(self)
if Config.clean["neg"]:
result = Future.clean(result)
return result

@debug("shapepy.bool2d.base")
def __add__(self, other: SubSetR2):
"""Union of SubSetR2"""
return self | other
result = Future.unite((self, other))
if Config.clean["add"]:
result = Future.clean(result)
return result

@debug("shapepy.bool2d.base")
def __mul__(self, value: SubSetR2):
def __mul__(self, other: SubSetR2):
"""Intersection of SubSetR2"""
return self & value
result = Future.intersect((self, other))
if Config.clean["mul"]:
result = Future.clean(result)
return result

@debug("shapepy.bool2d.base")
def __sub__(self, value: SubSetR2):
def __sub__(self, other: SubSetR2):
"""Subtraction of SubSetR2"""
return self & (~value)
result = Future.intersect((self, Future.invert(other)))
if Config.clean["sub"]:
result = Future.clean(result)
return result

@debug("shapepy.bool2d.base")
def __xor__(self, other: SubSetR2):
"""XOR of SubSetR2"""
return (self - other) | (other - self)
result = Future.xor((self, other))
if Config.clean["xor"]:
result = Future.clean(result)
return result

def __repr__(self) -> str: # pragma: no cover
return str(self)
Expand All @@ -80,6 +105,23 @@ def __repr__(self) -> str: # pragma: no cover
def __hash__(self):
raise NotImplementedError

def clean(self) -> SubSetR2:
"""
Cleans the subset, changing its representation into a simpler form

Parameters
----------
:return: The same instance
:rtype: SubSetR2

Example use
-----------
>>> from shapepy import Primitive
>>> circle = Primitive.circle()
>>> circle.clean()
"""
return Future.clean(self)

@abstractmethod
def move(self, vector: Point2D) -> SubSetR2:
"""
Expand Down Expand Up @@ -206,17 +248,29 @@ def __deepcopy__(self, memo) -> EmptyShape:
return self

def __or__(self, other: SubSetR2) -> SubSetR2:
return copy(other)
return Future.convert(other)

def __and__(self, other: SubSetR2) -> SubSetR2:
def __add__(self, other: SubSetR2) -> SubSetR2:
return Future.convert(other)

def __and__(self, _: SubSetR2) -> SubSetR2:
return self

def __sub__(self, other: SubSetR2) -> SubSetR2:
def __mul__(self, _: SubSetR2) -> SubSetR2:
return self

def __sub__(self, _: SubSetR2) -> SubSetR2:
return self

def __neg__(self) -> SubSetR2:
return WholeShape()

def __invert__(self) -> SubSetR2:
return WholeShape()

def __xor__(self, other: SubSetR2) -> SubSetR2:
return Future.convert(other)

def __contains__(self, other: SubSetR2) -> bool:
return self is other

Expand Down Expand Up @@ -273,20 +327,32 @@ def __deepcopy__(self, memo) -> WholeShape:
def __or__(self, other: SubSetR2) -> WholeShape:
return self

def __add__(self, _: SubSetR2) -> WholeShape:
return self

def __and__(self, other: SubSetR2) -> SubSetR2:
return copy(other)
return Future.convert(other)

def __mul__(self, other: SubSetR2) -> WholeShape:
return Future.convert(other)

def __neg__(self) -> SubSetR2:
return EmptyShape()

def __invert__(self) -> SubSetR2:
return EmptyShape()

def __xor__(self, other: SubSetR2) -> SubSetR2:
return ~Future.convert(other)

def __contains__(self, other: SubSetR2) -> bool:
return True

def __str__(self) -> str:
return "WholeShape"

def __sub__(self, other: SubSetR2) -> SubSetR2:
return ~other
return ~Future.convert(other)

def __bool__(self) -> bool:
return True
Expand Down Expand Up @@ -332,6 +398,13 @@ class Future:
a circular import.
"""

@staticmethod
def convert(subset: SubSetR2) -> SubSetR2:
"""
Converts an object into a SubSetR2
"""
raise NotImplementedError

@staticmethod
def unite(subsets: Iterable[SubSetR2]) -> SubSetR2:
"""
Expand All @@ -351,3 +424,33 @@ def intersect(subsets: Iterable[SubSetR2]) -> SubSetR2:
in the `shapepy.bool2d.boolean.py` file
"""
raise NotImplementedError

@staticmethod
def invert(subset: SubSetR2) -> SubSetR2:
"""
Computes the complementar set of given SubSetR2 instance

This function is overrided by a function defined
in the `shapepy.bool2d.boolean.py` file
"""
raise NotImplementedError

@staticmethod
def xor(subset: SubSetR2) -> SubSetR2:
"""
Computes the exclusive union of given subsets

This function is overrided by a function defined
in the `shapepy.bool2d.boolean.py` file
"""
raise NotImplementedError

@staticmethod
def clean(subset: SubSetR2) -> SubSetR2:
"""
Cleans and simplifies given subset

This function is overrided by a function defined
in the `shapepy.bool2d.boolean.py` file
"""
raise NotImplementedError
Loading
Loading