* #788 Add __repr__ and __str__ methods to Matrix * Shortened code with join & improved test * Renamed variable and fixed use of join * Replaced __getitem__ with transposed_list * Optimized repr and removed str methods * Cleanup comment * Increased geom.py code coverage to near 100% * Reformatted with black 19.10b0 defaults * Remove the typing import
This commit is contained in:
@ -47,6 +47,11 @@ class TestCadObjects(BaseTest):
|
||||
v9.z = 3.0
|
||||
self.assertTupleAlmostEquals((1, 2, 3), (v9.x, v9.y, v9.z), 4)
|
||||
|
||||
with self.assertRaises(TypeError):
|
||||
Vector("vector")
|
||||
with self.assertRaises(TypeError):
|
||||
Vector(1, 2, 3, 4)
|
||||
|
||||
def testVertex(self):
|
||||
"""
|
||||
Tests basic vertex functions
|
||||
@ -66,6 +71,46 @@ class TestCadObjects(BaseTest):
|
||||
# OCC uses some approximations
|
||||
self.assertAlmostEqual(bb1.xlen, 1.0, 1)
|
||||
|
||||
# Test adding to an existing bounding box
|
||||
v0 = Vertex.makeVertex(0, 0, 0)
|
||||
bb2 = v0.BoundingBox().add(v.BoundingBox())
|
||||
|
||||
bb3 = bb1.add(bb2)
|
||||
self.assertTupleAlmostEquals((2, 2, 2), (bb3.xlen, bb3.ylen, bb3.zlen), 7)
|
||||
|
||||
bb3 = bb2.add((3, 3, 3))
|
||||
self.assertTupleAlmostEquals((3, 3, 3), (bb3.xlen, bb3.ylen, bb3.zlen), 7)
|
||||
|
||||
bb3 = bb2.add(Vector(3, 3, 3))
|
||||
self.assertTupleAlmostEquals((3, 3, 3), (bb3.xlen, bb3.ylen, bb3.zlen), 7)
|
||||
|
||||
# Test 2D bounding boxes
|
||||
bb1 = (
|
||||
Vertex.makeVertex(1, 1, 0)
|
||||
.BoundingBox()
|
||||
.add(Vertex.makeVertex(2, 2, 0).BoundingBox())
|
||||
)
|
||||
bb2 = (
|
||||
Vertex.makeVertex(0, 0, 0)
|
||||
.BoundingBox()
|
||||
.add(Vertex.makeVertex(3, 3, 0).BoundingBox())
|
||||
)
|
||||
bb3 = (
|
||||
Vertex.makeVertex(0, 0, 0)
|
||||
.BoundingBox()
|
||||
.add(Vertex.makeVertex(1.5, 1.5, 0).BoundingBox())
|
||||
)
|
||||
# Test that bb2 contains bb1
|
||||
self.assertEqual(bb2, BoundBox.findOutsideBox2D(bb1, bb2))
|
||||
self.assertEqual(bb2, BoundBox.findOutsideBox2D(bb2, bb1))
|
||||
# Test that neither bounding box contains the other
|
||||
self.assertIsNone(BoundBox.findOutsideBox2D(bb1, bb3))
|
||||
|
||||
# Test creation of a bounding box from a shape - note the low accuracy comparison
|
||||
# as the box is a little larger than the shape
|
||||
bb1 = BoundBox._fromTopoDS(Solid.makeCylinder(1, 1).wrapped, optimal=False)
|
||||
self.assertTupleAlmostEquals((2, 2, 1), (bb1.xlen, bb1.ylen, bb1.zlen), 1)
|
||||
|
||||
def testEdgeWrapperCenter(self):
|
||||
e = self._make_circle()
|
||||
|
||||
@ -276,6 +321,20 @@ class TestCadObjects(BaseTest):
|
||||
point.toTuple(), (59 / 7, 55 / 7, 51 / 7), decimal_places
|
||||
)
|
||||
|
||||
def testVectorNotImplemented(self):
|
||||
v = Vector(1, 2, 3)
|
||||
with self.assertRaises(NotImplementedError):
|
||||
v.distanceToLine()
|
||||
with self.assertRaises(NotImplementedError):
|
||||
v.projectToLine()
|
||||
with self.assertRaises(NotImplementedError):
|
||||
v.distanceToPlane()
|
||||
|
||||
def testVectorSpecialMethods(self):
|
||||
v = Vector(1, 2, 3)
|
||||
self.assertEqual(repr(v), "Vector: (1.0, 2.0, 3.0)")
|
||||
self.assertEqual(str(v), "Vector: (1.0, 2.0, 3.0)")
|
||||
|
||||
def testMatrixCreationAndAccess(self):
|
||||
def matrix_vals(m):
|
||||
return [[m[r, c] for c in range(4)] for r in range(4)]
|
||||
@ -320,7 +379,9 @@ class TestCadObjects(BaseTest):
|
||||
]
|
||||
with self.assertRaises(ValueError):
|
||||
Matrix(invalid)
|
||||
|
||||
# Test input with invalid type
|
||||
with self.assertRaises(TypeError):
|
||||
Matrix("invalid")
|
||||
# Test input with invalid size / nested types
|
||||
with self.assertRaises(TypeError):
|
||||
Matrix([[1, 2, 3, 4], [1, 2, 3], [1, 2, 3, 4]])
|
||||
@ -340,6 +401,77 @@ class TestCadObjects(BaseTest):
|
||||
with self.assertRaises(IndexError):
|
||||
m["ab"]
|
||||
|
||||
# test __repr__ methods
|
||||
m = Matrix(vals4x4)
|
||||
mRepr = "Matrix([[1.0, 0.0, 0.0, 1.0],\n [0.0, 1.0, 0.0, 2.0],\n [0.0, 0.0, 1.0, 3.0],\n [0.0, 0.0, 0.0, 1.0]])"
|
||||
self.assertEqual(repr(m), mRepr)
|
||||
self.assertEqual(str(eval(repr(m))), mRepr)
|
||||
|
||||
def testMatrixFunctionality(self):
|
||||
# Test rotate methods
|
||||
def matrix_almost_equal(m, target_matrix):
|
||||
for r, row in enumerate(target_matrix):
|
||||
for c, target_value in enumerate(row):
|
||||
self.assertAlmostEqual(m[r, c], target_value)
|
||||
|
||||
root_3_over_2 = math.sqrt(3) / 2
|
||||
m_rotate_x_30 = [
|
||||
[1, 0, 0, 0],
|
||||
[0, root_3_over_2, -1 / 2, 0],
|
||||
[0, 1 / 2, root_3_over_2, 0],
|
||||
[0, 0, 0, 1],
|
||||
]
|
||||
mx = Matrix()
|
||||
mx.rotateX(30 * DEG2RAD)
|
||||
matrix_almost_equal(mx, m_rotate_x_30)
|
||||
|
||||
m_rotate_y_30 = [
|
||||
[root_3_over_2, 0, 1 / 2, 0],
|
||||
[0, 1, 0, 0],
|
||||
[-1 / 2, 0, root_3_over_2, 0],
|
||||
[0, 0, 0, 1],
|
||||
]
|
||||
my = Matrix()
|
||||
my.rotateY(30 * DEG2RAD)
|
||||
matrix_almost_equal(my, m_rotate_y_30)
|
||||
|
||||
m_rotate_z_30 = [
|
||||
[root_3_over_2, -1 / 2, 0, 0],
|
||||
[1 / 2, root_3_over_2, 0, 0],
|
||||
[0, 0, 1, 0],
|
||||
[0, 0, 0, 1],
|
||||
]
|
||||
mz = Matrix()
|
||||
mz.rotateZ(30 * DEG2RAD)
|
||||
matrix_almost_equal(mz, m_rotate_z_30)
|
||||
|
||||
# Test matrix multipy vector
|
||||
v = Vector(1, 0, 0)
|
||||
self.assertTupleAlmostEquals(
|
||||
mz.multiply(v).toTuple(), (root_3_over_2, 1 / 2, 0), 7
|
||||
)
|
||||
|
||||
# Test matrix multipy matrix
|
||||
m_rotate_xy_30 = [
|
||||
[root_3_over_2, 0, 1 / 2, 0],
|
||||
[1 / 4, root_3_over_2, -root_3_over_2 / 2, 0],
|
||||
[-root_3_over_2 / 2, 1 / 2, 3 / 4, 0],
|
||||
[0, 0, 0, 1],
|
||||
]
|
||||
mxy = mx.multiply(my)
|
||||
matrix_almost_equal(mxy, m_rotate_xy_30)
|
||||
|
||||
# Test matrix inverse
|
||||
vals4x4 = [[1, 2, 3, 4], [5, 1, 6, 7], [8, 9, 1, 10], [0, 0, 0, 1]]
|
||||
vals4x4_invert = [
|
||||
[-53 / 144, 25 / 144, 1 / 16, -53 / 144],
|
||||
[43 / 144, -23 / 144, 1 / 16, -101 / 144],
|
||||
[37 / 144, 7 / 144, -1 / 16, -107 / 144],
|
||||
[0, 0, 0, 1],
|
||||
]
|
||||
m = Matrix(vals4x4).inverse()
|
||||
matrix_almost_equal(m, vals4x4_invert)
|
||||
|
||||
def testTranslate(self):
|
||||
e = Edge.makeCircle(2, (1, 2, 3))
|
||||
e2 = e.translate(Vector(0, 0, 1))
|
||||
@ -394,6 +526,55 @@ class TestCadObjects(BaseTest):
|
||||
Plane(origin=(0, 0, 0), xDir=(1, 0, 0), normal=(0, 1, 1)),
|
||||
)
|
||||
|
||||
def testInvalidPlane(self):
|
||||
# Test plane creation error handling
|
||||
with self.assertRaises(ValueError):
|
||||
Plane.named("XX", (0, 0, 0))
|
||||
with self.assertRaises(ValueError):
|
||||
Plane(origin=(0, 0, 0), xDir=(0, 0, 0), normal=(0, 1, 1))
|
||||
with self.assertRaises(ValueError):
|
||||
Plane(origin=(0, 0, 0), xDir=(1, 0, 0), normal=(0, 0, 0))
|
||||
|
||||
def testPlaneMethods(self):
|
||||
# Test error checking
|
||||
p = Plane(origin=(0, 0, 0), xDir=(1, 0, 0), normal=(0, 1, 0))
|
||||
with self.assertRaises(ValueError):
|
||||
p.toLocalCoords("box")
|
||||
with self.assertRaises(NotImplementedError):
|
||||
p.mirrorInPlane([Solid.makeBox(1, 1, 1)], "Z")
|
||||
|
||||
# Test translation to local coordinates
|
||||
local_box = Workplane(p.toLocalCoords(Solid.makeBox(1, 1, 1)))
|
||||
local_box_vertices = [(v.X, v.Y, v.Z) for v in local_box.vertices().vals()]
|
||||
target_vertices = [
|
||||
(0, -1, 0),
|
||||
(0, 0, 0),
|
||||
(0, -1, 1),
|
||||
(0, 0, 1),
|
||||
(1, -1, 0),
|
||||
(1, 0, 0),
|
||||
(1, -1, 1),
|
||||
(1, 0, 1),
|
||||
]
|
||||
for i, target_point in enumerate(target_vertices):
|
||||
self.assertTupleAlmostEquals(target_point, local_box_vertices[i], 7)
|
||||
|
||||
# Test mirrorInPlane
|
||||
mirror_box = Workplane(p.mirrorInPlane([Solid.makeBox(1, 1, 1)], "Y")[0])
|
||||
mirror_box_vertices = [(v.X, v.Y, v.Z) for v in mirror_box.vertices().vals()]
|
||||
target_vertices = [
|
||||
(0, 0, 1),
|
||||
(0, 0, 0),
|
||||
(0, -1, 1),
|
||||
(0, -1, 0),
|
||||
(-1, 0, 1),
|
||||
(-1, 0, 0),
|
||||
(-1, -1, 1),
|
||||
(-1, -1, 0),
|
||||
]
|
||||
for i, target_point in enumerate(target_vertices):
|
||||
self.assertTupleAlmostEquals(target_point, mirror_box_vertices[i], 7)
|
||||
|
||||
def testLocation(self):
|
||||
|
||||
# Vector
|
||||
@ -418,6 +599,17 @@ class TestCadObjects(BaseTest):
|
||||
== loc3.wrapped.Transformation().TranslationPart().Z()
|
||||
)
|
||||
|
||||
# Test creation from the OCP.gp.gp_Trsf object
|
||||
loc4 = Location(gp_Trsf())
|
||||
self.assertTupleAlmostEquals(loc4.toTuple()[0], (0, 0, 0), 7)
|
||||
self.assertTupleAlmostEquals(loc4.toTuple()[1], (0, 0, 0), 7)
|
||||
|
||||
# Test error handling on creation
|
||||
with self.assertRaises(TypeError):
|
||||
Location((0, 0, 1))
|
||||
with self.assertRaises(TypeError):
|
||||
Location("xy_plane")
|
||||
|
||||
def testEdgeWrapperRadius(self):
|
||||
|
||||
# get a radius from a simple circle
|
||||
|
Reference in New Issue
Block a user