From a28b85cca58cbb11041146181c9312fde0b7c246 Mon Sep 17 00:00:00 2001
From: Elod Csirmaz A 3D primitive, cube.
-Creates a cube in the first octant. When center is true, the cube is centered on the origin. See https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/The_OpenSCAD_Language#cube A 3D primitive, cube. See https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/The_OpenSCAD_Language#cube Creates a cube in the first octant. When Represents a point or vector in arbitrary dimensions Represents a point or vector in arbitrary number of dimensions Ensure coords is an instance of Point (idempotent) Ensure Use Use Use Use Use Add another point / vector Return whether the current point / vector and Return the angle between two vectors in degrees or radians Return the angle between two vectors in degrees or radians Return the cross product Return the cross product of the current vector and Return the dot product Return the dot product of the current vector and Return whether the current point / vector and Return whether the current vector is greater or equal to Return whether the current vector is greater than Return whether the current vector is smaller or equal to Return whether the current vector is smaller than Return a normalized version of the vector (scaled to length 1) Render the object into OpenSCAD code Render the point / vector into OpenSCAD code Render the point / vector into STL Rotate. coords is a list of 2 coordinate indices that we rotate Rotate the current vector Scale the current vector/point by a scalar Scale the current point / vector by the scalar Subtract another point / vector Return the slope of a vector in degrees or radians Return the slope of a vector in degrees or radians A 3D primitive, a polyhedron defined by a list of points and faces.
-Faces are defined by lists of point indices. The points of a face must be listed clockwise when
-looking at the face from the outside inward.
-Nonplanar faces should be triangulated by OpenSCAD. See https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/The_OpenSCAD_Language#polyhedron
center: bool = False)
center
is True, the cube is centered on the origin.Arguments
+
+
x, y, z
sizes
Expand source code
class Cube(Object):
"""A 3D primitive, cube.
- Creates a cube in the first octant. When center is true, the cube is centered on the origin.
-
+
See https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/The_OpenSCAD_Language#cube
"""
def __init__(self, size: TUnion[list, Point], center: bool = False):
+ """
+ Creates a cube in the first octant. When `center` is True, the cube is centered on the origin.
+
+ Arguments:
+ - size: a Point object or a list of `x, y, z` sizes
+ - center: if True, the cube is centered on the origin
+ """
self.size = Point.c(size)
self.center = center
diff --git a/point.html b/point.html
index e8f3cf6..993c848 100644
--- a/point.html
+++ b/point.html
@@ -37,44 +37,47 @@ hljs.highlightAll();
class Point
-(coords)
+(coords: List[float])
Expand source code
class Point:
- """Represents a point or vector in arbitrary dimensions"""
+ """Represents a point or vector in arbitrary number of dimensions"""
- def __init__(self, coords):
+ def __init__(self, coords: List[float]):
self.c = np.array(coords, dtype=NP_TYPE)
@classmethod
- def c(cls, coords: TUnion[list, 'Point']) -> 'Point':
- """Ensure coords is an instance of Point (idempotent)"""
+ def c(cls, coords: TUnion[list[float], 'Point']) -> 'Point':
+ """Ensure `coords` is an instance of Point (idempotent)"""
if isinstance(coords, Point):
return coords
return Point(coords)
def render(self) -> str:
- """Render the object into OpenSCAD code"""
+ """Render the point / vector into OpenSCAD code"""
return "[" + (",".join([str(c) for c in self.c])) + "]"
def render_stl(self) -> str:
+ """Render the point / vector into STL"""
return " ".join([str(c) for c in self.c])
def scale(self, x: float) -> 'Point':
- """Scale the current vector/point by a scalar"""
+ """Scale the current point / vector by the scalar `x`"""
return self.__class__(self.c * x)
def add(self, p: 'Point') -> 'Point':
+ """Add another point / vector `p` to the current one"""
assert isinstance(p, Point)
assert self.dim() == p.dim()
return self.__class__(self.c + p.c)
def sub(self, p: 'Point') -> 'Point':
+ """Subtract another point / vector `p` from the current one"""
assert isinstance(p, Point)
assert self.dim() == p.dim()
return self.__class__(self.c - p.c)
@@ -92,17 +95,18 @@ hljs.highlightAll();
return np.sqrt(np.square(self.c).sum())
def norm(self) -> 'Point':
+ """Return a normalized version of the vector (scaled to length 1)"""
l = self.length()
if l == 0:
- raise Exception("normalising 0 vector")
+ raise Exception("Attempted to normalise 0 vector")
return self.__class__(self.c / self.length())
def dot(self, p: 'Point') -> float:
- """Return the dot product"""
+ """Return the dot product of the current vector and `p`"""
return np.dot(self.c, p.c)
def cross(self, p: 'Point') -> 'Point':
- """Return the cross product"""
+ """Return the cross product of the current vector and `p`"""
assert self.dim() == 3
assert p.dim() == 3
return Point([
@@ -113,25 +117,36 @@ hljs.highlightAll();
])
def eq(self, p: 'Point') -> bool:
+ """Return whether the current point / vector and `p` are equal"""
return (self.c == p.c).all()
def lt(self, p: 'Point') -> bool:
+ """Return whether the current vector is smaller than `p` in each dimension"""
return (self.c < p.c).all()
def le(self, p: 'Point') -> bool:
+ """Return whether the current vector is smaller or equal to `p` in each dimension"""
return (self.c <= p.c).all()
def gt(self, p: 'Point') -> bool:
+ """Return whether the current vector is greater than `p` in each dimension"""
return (self.c > p.c).all()
def ge(self, p: 'Point') -> bool:
+ """Return whether the current vector is greater or equal to `p` in each dimension"""
return (self.c >= p.c).all()
def allclose(self, p: 'Point') -> bool:
+ """Return whether the current point / vector and `p` are close to each other"""
return self.c.shape == p.c.shape and np.allclose(self.c, p.c)
def angle(self, p: 'Point', mode: str = "deg") -> float:
- """Return the angle between two vectors in degrees or radians"""
+ """Return the angle between two vectors in degrees or radians
+
+ Arguments:
+ - p: a Point object
+ - mode: "deg" | "rad"
+ """
r = self.dot(p)
r = r / self.length() / p.length()
r = math.acos(r)
@@ -142,7 +157,11 @@ hljs.highlightAll();
raise ValueError("Unknown mode")
def z_slope(self, mode: str = "deg") -> float:
- """Return the slope of a vector in degrees or radians"""
+ """Return the slope of a vector in degrees or radians
+
+ Arguments:
+ - mode: "deg" | "rad"
+ """
r = self.c[2] / self.length()
r = math.asin(r)
if mode == "rad":
@@ -152,7 +171,12 @@ hljs.highlightAll();
raise ValueError("Unknown mode")
def rotate(self, coords, angle: float) -> 'Point':
- """Rotate. coords is a list of 2 coordinate indices that we rotate"""
+ """Rotate the current vector
+
+ Arguments:
+ - coords: A list of 2 coordinate indices to rotate
+ - angle: the angle to rotate by, in degrees
+ """
assert len(coords) == 2
ca, cb = coords
s = np.sin(angle / 180. * np.pi)
@@ -165,26 +189,33 @@ hljs.highlightAll();
# Operator overloading
def __add__(self, other):
+ """Use `p1 + p2` to add two vectors"""
return self.add(other)
def __radd__(self, other):
+ """Use `p1 + p2` to add two vectors"""
assert isinstance(other, Point)
return other.add(self)
def __sub__(self, other):
+ """Use `p1 - p2` to subtract two vectors"""
return self.sub(other)
def __rsub__(self, other):
+ """Use `p1 - p2` to subtract two vectors"""
assert isinstance(other, Point)
return other.sub(self)
def __mul__(self, other):
+ """Use `p * x` to scale a vector"""
return self.scale(other)
def __rmul__(self, other):
+ """Use `x * p` to scale a vector"""
return self.scale(other)
def __neg__(self):
+ """Use `-p` to negate a vector"""
return self.scale(-1.)
Static methods
@@ -193,34 +224,69 @@ hljs.highlightAll();
def c(coords: list | ForwardRef('Point')) ‑> Point
coords
is an instance of Point (idempotent)Methods
+
+def __add__(self, other)
+
p1 + p2
to add two vectors
+def __mul__(self, other)
+
p * x
to scale a vector
+def __neg__(self)
+
-p
to negate a vector
+def __rmul__(self, other)
+
x * p
to scale a vector
+def __sub__(self, other)
+
p1 - p2
to subtract two vectors
def add(self,
p: Point) ‑> Point
p
to the current one
def allclose(self,
p: Point) ‑> bool
p
are close to each other
def angle(self,
p: Point,
mode: str = 'deg') ‑> float
Arguments
+
+
def cross(self,
p: Point) ‑> Point
p
def dim(self) ‑> int
@@ -232,25 +298,25 @@ hljs.highlightAll();
def dot(self,
p: Point) ‑> float
p
def eq(self,
p: Point) ‑> bool
p
are equal
def ge(self,
p: Point) ‑> bool
p
in each dimension
def gt(self,
p: Point) ‑> bool
p
in each dimension
def is_zero(self) ‑> bool
@@ -262,7 +328,7 @@ hljs.highlightAll();
def le(self,
p: Point) ‑> bool
p
in each dimension
def length(self) ‑> float
@@ -274,49 +340,58 @@ hljs.highlightAll();
def lt(self,
p: Point) ‑> bool
p
in each dimension
def norm(self) ‑> Point
def render(self) ‑> str
def render_stl(self) ‑> str
def rotate(self, coords, angle: float) ‑> Point
Arguments
+
+
def scale(self, x: float) ‑> Point
x
def sub(self,
p: Point) ‑> Point
p
from the current one
def z_slope(self, mode: str = 'deg') ‑> float
Arguments
+
+
Point
+
__add__
__mul__
__neg__
__rmul__
__sub__
add
allclose
angle
See https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/The_OpenSCAD_Language#polyhedron
+class Polyhedron(Object):
"""A 3D primitive, a polyhedron defined by a list of points and faces.
- Faces are defined by lists of point indices. The points of a face must be listed clockwise when
- looking at the face from the outside inward.
- Nonplanar faces should be triangulated by OpenSCAD.
+ Nonplanar faces will be triangulated by OpenSCAD.
See https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/The_OpenSCAD_Language#polyhedron
"""
def __init__(self, points: List[TUnion[list, Point]], faces: List[list], convexity: int = 10):
+ """
+ Arguments:
+ - points: a list of Point objects or coordinate tuples defining the vertices
+ - faces: defines the faces as a list of lists of vertex indices. The points of a face must be listed clockwise when looking at the face from the outside inward.
+ """
self.points = [Point.c(p) for p in points]
self.faces = faces
self.convexity = convexity