-
Notifications
You must be signed in to change notification settings - Fork 41
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #379 from specklesystems/dogukan/additional_geomet…
…ry_classes feat(specklepy): additional geometry classes
- Loading branch information
Showing
29 changed files
with
1,671 additions
and
267 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,34 @@ | ||
from specklepy.objects.geometry.arc import Arc | ||
from specklepy.objects.geometry.line import Line | ||
from specklepy.objects.geometry.mesh import Mesh | ||
from specklepy.objects.geometry.plane import Plane | ||
from specklepy.objects.geometry.point import Point | ||
from specklepy.objects.geometry.polyline import Polyline | ||
from specklepy.objects.geometry.vector import Vector | ||
from .arc import Arc | ||
from .box import Box | ||
from .circle import Circle | ||
from .control_point import ControlPoint | ||
from .ellipse import Ellipse | ||
from .line import Line | ||
from .mesh import Mesh | ||
from .plane import Plane | ||
from .point import Point | ||
from .point_cloud import PointCloud | ||
from .polycurve import Polycurve | ||
from .polyline import Polyline | ||
from .spiral import Spiral | ||
from .surface import Surface | ||
from .vector import Vector | ||
|
||
# re-export them at the geometry package level | ||
__all__ = ["Arc", "Line", "Mesh", "Plane", "Point", "Polyline", "Vector"] | ||
__all__ = [ | ||
"Arc", | ||
"Line", | ||
"Mesh", | ||
"Plane", | ||
"Point", | ||
"Polyline", | ||
"Vector", | ||
"Box", | ||
"Circle", | ||
"ControlPoint", | ||
"Ellipse", | ||
"PointCloud", | ||
"Polycurve", | ||
"Spiral", | ||
"Surface", | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
from dataclasses import dataclass | ||
|
||
from specklepy.objects.base import Base | ||
from specklepy.objects.geometry.plane import Plane | ||
from specklepy.objects.interfaces import IHasArea, IHasUnits, IHasVolume | ||
from specklepy.objects.primitive import Interval | ||
|
||
|
||
@dataclass(kw_only=True) | ||
class Box(Base, IHasUnits, IHasArea, IHasVolume, speckle_type="Objects.Geometry.Box"): | ||
""" | ||
a 3-dimensional box oriented on a plane | ||
""" | ||
|
||
basePlane: Plane | ||
xSize: Interval | ||
ySize: Interval | ||
zSize: Interval | ||
|
||
def __repr__(self) -> str: | ||
return ( | ||
f"{self.__class__.__name__}(" | ||
f"basePlane: {self.basePlane}, " | ||
f"xSize: {self.xSize}, " | ||
f"ySize: {self.ySize}, " | ||
f"zSize: {self.zSize}, " | ||
f"units: {self.units})" | ||
) | ||
|
||
@property | ||
def area(self) -> float: | ||
return 2 * ( | ||
self.xSize.length * self.ySize.length | ||
+ self.xSize.length * self.zSize.length | ||
+ self.ySize.length * self.zSize.length | ||
) | ||
|
||
@property | ||
def volume(self) -> float: | ||
return self.xSize.length * self.ySize.length * self.zSize.length |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import math | ||
from dataclasses import dataclass | ||
|
||
from specklepy.objects.base import Base | ||
from specklepy.objects.geometry.plane import Plane | ||
from specklepy.objects.geometry.point import Point | ||
from specklepy.objects.interfaces import ICurve, IHasArea, IHasUnits | ||
|
||
|
||
@dataclass(kw_only=True) | ||
class Circle(Base, IHasUnits, ICurve, IHasArea, speckle_type="Objects.Geometry.Circle"): | ||
""" | ||
a circular curve based on a plane | ||
""" | ||
|
||
plane: Plane | ||
center: Point | ||
radius: float | ||
|
||
def __repr__(self) -> str: | ||
return ( | ||
f"{self.__class__.__name__}(" | ||
f"plane: {self.plane}, " | ||
f"center: {self.center}, " | ||
f"radius: {self.radius}, " | ||
f"units: {self.units})" | ||
) | ||
|
||
@property | ||
def length(self) -> float: | ||
return 2 * math.pi * self.radius | ||
|
||
@property | ||
def area(self) -> float: | ||
return math.pi * self.radius**2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
from dataclasses import dataclass | ||
|
||
from specklepy.objects.geometry.point import Point | ||
|
||
|
||
@dataclass(kw_only=True) | ||
class ControlPoint(Point, speckle_type="Objects.Geometry.ControlPoint"): | ||
""" | ||
a single 3-dimensional point with weight | ||
""" | ||
|
||
weight: float | ||
|
||
def __repr__(self) -> str: | ||
return ( | ||
f"{self.__class__.__name__}(" | ||
f"x: {self.x}, " | ||
f"y: {self.y}, " | ||
f"z: {self.z}, " | ||
f"weight: {self.weight}, " | ||
f"units: {self.units})" | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
from dataclasses import dataclass | ||
|
||
from specklepy.objects.base import Base | ||
from specklepy.objects.geometry.plane import Plane | ||
from specklepy.objects.interfaces import ICurve, IHasArea, IHasUnits | ||
|
||
|
||
@dataclass(kw_only=True) | ||
class Ellipse( | ||
Base, IHasUnits, ICurve, IHasArea, speckle_type="Objects.Geometry.Ellipse" | ||
): | ||
""" | ||
an ellipse | ||
""" | ||
|
||
plane: Plane | ||
first_radius: float | ||
second_radius: float | ||
|
||
@property | ||
def length(self) -> float: | ||
return self.__dict__.get("_length", 0.0) | ||
|
||
@length.setter | ||
def length(self, value: float) -> None: | ||
self.__dict__["_length"] = value | ||
|
||
@property | ||
def area(self) -> float: | ||
return self.__dict__.get("_area", 0.0) | ||
|
||
@area.setter | ||
def area(self, value: float) -> None: | ||
self.__dict__["_area"] = value |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
from dataclasses import dataclass | ||
from typing import List | ||
|
||
from specklepy.objects.base import Base | ||
from specklepy.objects.geometry.point import Point | ||
from specklepy.objects.interfaces import IHasUnits | ||
|
||
|
||
@dataclass(kw_only=True) | ||
class PointCloud(Base, IHasUnits, speckle_type="Objects.Geometry.PointCloud"): | ||
""" | ||
a collection of 3-dimensional points | ||
""" | ||
|
||
points: List[Point] | ||
|
||
def __repr__(self) -> str: | ||
return ( | ||
f"{self.__class__.__name__}(" | ||
f"points: {len(self.points)}, " | ||
f"units: {self.units})" | ||
) | ||
|
||
# sizes and colors could be added in the future |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
from dataclasses import dataclass, field | ||
from typing import List | ||
|
||
from specklepy.objects.base import Base | ||
from specklepy.objects.geometry.line import Line | ||
from specklepy.objects.geometry.point import Point | ||
from specklepy.objects.geometry.polyline import Polyline | ||
from specklepy.objects.interfaces import ICurve, IHasArea, IHasUnits | ||
|
||
|
||
@dataclass(kw_only=True) | ||
class Polycurve( | ||
Base, IHasUnits, ICurve, IHasArea, speckle_type="Objects.Geometry.Polycurve" | ||
): | ||
""" | ||
a curve that is comprised of multiple curves connected | ||
""" | ||
|
||
segments: List[ICurve] = field(default_factory=list) | ||
|
||
def __repr__(self) -> str: | ||
return ( | ||
f"{self.__class__.__name__}(" | ||
f"segments: {len(self.segments)}, " | ||
f"closed: {self.is_closed()}, " | ||
f"units: {self.units})" | ||
) | ||
|
||
def is_closed(self, tolerance: float = 1e-6) -> bool: | ||
""" | ||
checks if the polycurve is closed | ||
(comparing start of first segment to end of last segment) | ||
""" | ||
if len(self.segments) < 1: | ||
return False | ||
|
||
first_segment = self.segments[0] | ||
last_segment = self.segments[-1] | ||
|
||
if not (hasattr(first_segment, "start") and hasattr(last_segment, "end")): | ||
return False | ||
|
||
start_pt = first_segment.start | ||
end_pt = last_segment.end | ||
|
||
if not (isinstance(start_pt, Point) and isinstance(end_pt, Point)): | ||
return False | ||
|
||
return start_pt.distance_to(end_pt) <= tolerance | ||
|
||
@property | ||
def length(self) -> float: | ||
return self.__dict__.get("_length", 0.0) | ||
|
||
@length.setter | ||
def length(self, value: float) -> None: | ||
self.__dict__["_length"] = value | ||
|
||
def calculate_length(self) -> float: | ||
""" | ||
calculate total length of all segments | ||
""" | ||
total_length = 0.0 | ||
for segment in self.segments: | ||
if hasattr(segment, "length"): | ||
total_length += segment.length | ||
return total_length | ||
|
||
@property | ||
def area(self) -> float: | ||
return self.__dict__.get("_area", 0.0) | ||
|
||
@area.setter | ||
def area(self, value: float) -> None: | ||
self.__dict__["_area"] = value | ||
|
||
@classmethod | ||
def from_polyline(cls, polyline: Polyline) -> "Polycurve": | ||
""" | ||
constructs a new polycurve instance from an existing polyline curve | ||
""" | ||
polycurve = cls(units=polyline.units) | ||
points = polyline.get_points() | ||
for i in range(len(points) - 1): | ||
line = Line(start=points[i], end=points[i + 1], units=polyline.units) | ||
polycurve.segments.append(line) | ||
|
||
if polyline.is_closed(): | ||
line = Line(start=points[-1], end=points[0], units=polyline.units) | ||
polycurve.segments.append(line) | ||
|
||
if hasattr(polyline, "_length"): | ||
polycurve.length = polyline.length | ||
if hasattr(polyline, "_area"): | ||
polycurve.area = polyline.area | ||
|
||
return polycurve |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
from dataclasses import dataclass | ||
|
||
from specklepy.objects.base import Base | ||
from specklepy.objects.geometry.plane import Plane | ||
from specklepy.objects.geometry.point import Point | ||
from specklepy.objects.geometry.vector import Vector | ||
from specklepy.objects.interfaces import ICurve, IHasArea, IHasUnits | ||
|
||
|
||
@dataclass(kw_only=True) | ||
class Spiral(Base, IHasUnits, ICurve, IHasArea, speckle_type="Objects.Geometry.Spiral"): | ||
""" | ||
a spiral | ||
""" | ||
|
||
start_point: Point | ||
end_point: Point | ||
plane: Plane # plane with origin at spiral center | ||
turns: float # total angle of spiral. | ||
pitch: float | ||
pitch_axis: Vector | ||
|
||
def __repr__(self) -> str: | ||
return ( | ||
f"{self.__class__.__name__}(" | ||
f"start_point: {self.start_point}, " | ||
f"end_point: {self.end_point}, " | ||
f"plane: {self.plane}, " | ||
f"turns: {self.turns}, " | ||
f"pitch: {self.pitch}, " | ||
f"pitch_axis: {self.pitch_axis}, " | ||
f"units: {self.units})" | ||
) | ||
|
||
@property | ||
def length(self) -> float: | ||
return self.__dict__.get("_length", 0.0) | ||
|
||
@length.setter | ||
def length(self, value: float) -> None: | ||
self.__dict__["_length"] = value | ||
|
||
@property | ||
def area(self) -> float: | ||
return self.__dict__.get("_area", 0.0) | ||
|
||
@area.setter | ||
def area(self, value: float) -> None: | ||
self.__dict__["_area"] = value |
Oops, something went wrong.