@@ -47,6 +47,11 @@ def testVectorConstructors(self):
47
47
v9 .z = 3.0
48
48
self .assertTupleAlmostEquals ((1 , 2 , 3 ), (v9 .x , v9 .y , v9 .z ), 4 )
49
49
50
+ with self .assertRaises (TypeError ):
51
+ Vector ("vector" )
52
+ with self .assertRaises (TypeError ):
53
+ Vector (1 , 2 , 3 , 4 )
54
+
50
55
def testVertex (self ):
51
56
"""
52
57
Tests basic vertex functions
@@ -66,6 +71,46 @@ def testBasicBoundingBox(self):
66
71
# OCC uses some approximations
67
72
self .assertAlmostEqual (bb1 .xlen , 1.0 , 1 )
68
73
74
+ # Test adding to an existing bounding box
75
+ v0 = Vertex .makeVertex (0 , 0 , 0 )
76
+ bb2 = v0 .BoundingBox ().add (v .BoundingBox ())
77
+
78
+ bb3 = bb1 .add (bb2 )
79
+ self .assertTupleAlmostEquals ((2 , 2 , 2 ), (bb3 .xlen , bb3 .ylen , bb3 .zlen ), 7 )
80
+
81
+ bb3 = bb2 .add ((3 , 3 , 3 ))
82
+ self .assertTupleAlmostEquals ((3 , 3 , 3 ), (bb3 .xlen , bb3 .ylen , bb3 .zlen ), 7 )
83
+
84
+ bb3 = bb2 .add (Vector (3 , 3 , 3 ))
85
+ self .assertTupleAlmostEquals ((3 , 3 , 3 ), (bb3 .xlen , bb3 .ylen , bb3 .zlen ), 7 )
86
+
87
+ # Test 2D bounding boxes
88
+ bb1 = (
89
+ Vertex .makeVertex (1 , 1 , 0 )
90
+ .BoundingBox ()
91
+ .add (Vertex .makeVertex (2 , 2 , 0 ).BoundingBox ())
92
+ )
93
+ bb2 = (
94
+ Vertex .makeVertex (0 , 0 , 0 )
95
+ .BoundingBox ()
96
+ .add (Vertex .makeVertex (3 , 3 , 0 ).BoundingBox ())
97
+ )
98
+ bb3 = (
99
+ Vertex .makeVertex (0 , 0 , 0 )
100
+ .BoundingBox ()
101
+ .add (Vertex .makeVertex (1.5 , 1.5 , 0 ).BoundingBox ())
102
+ )
103
+ # Test that bb2 contains bb1
104
+ self .assertEqual (bb2 , BoundBox .findOutsideBox2D (bb1 , bb2 ))
105
+ self .assertEqual (bb2 , BoundBox .findOutsideBox2D (bb2 , bb1 ))
106
+ # Test that neither bounding box contains the other
107
+ self .assertIsNone (BoundBox .findOutsideBox2D (bb1 , bb3 ))
108
+
109
+ # Test creation of a bounding box from a shape - note the low accuracy comparison
110
+ # as the box is a little larger than the shape
111
+ bb1 = BoundBox ._fromTopoDS (Solid .makeCylinder (1 , 1 ).wrapped , optimal = False )
112
+ self .assertTupleAlmostEquals ((2 , 2 , 1 ), (bb1 .xlen , bb1 .ylen , bb1 .zlen ), 1 )
113
+
69
114
def testEdgeWrapperCenter (self ):
70
115
e = self ._make_circle ()
71
116
@@ -276,6 +321,20 @@ def testVectorProject(self):
276
321
point .toTuple (), (59 / 7 , 55 / 7 , 51 / 7 ), decimal_places
277
322
)
278
323
324
+ def testVectorNotImplemented (self ):
325
+ v = Vector (1 , 2 , 3 )
326
+ with self .assertRaises (NotImplementedError ):
327
+ v .distanceToLine ()
328
+ with self .assertRaises (NotImplementedError ):
329
+ v .projectToLine ()
330
+ with self .assertRaises (NotImplementedError ):
331
+ v .distanceToPlane ()
332
+
333
+ def testVectorSpecialMethods (self ):
334
+ v = Vector (1 , 2 , 3 )
335
+ self .assertEqual (repr (v ), "Vector: (1.0, 2.0, 3.0)" )
336
+ self .assertEqual (str (v ), "Vector: (1.0, 2.0, 3.0)" )
337
+
279
338
def testMatrixCreationAndAccess (self ):
280
339
def matrix_vals (m ):
281
340
return [[m [r , c ] for c in range (4 )] for r in range (4 )]
@@ -320,7 +379,9 @@ def matrix_vals(m):
320
379
]
321
380
with self .assertRaises (ValueError ):
322
381
Matrix (invalid )
323
-
382
+ # Test input with invalid type
383
+ with self .assertRaises (TypeError ):
384
+ Matrix ("invalid" )
324
385
# Test input with invalid size / nested types
325
386
with self .assertRaises (TypeError ):
326
387
Matrix ([[1 , 2 , 3 , 4 ], [1 , 2 , 3 ], [1 , 2 , 3 , 4 ]])
@@ -340,6 +401,77 @@ def matrix_vals(m):
340
401
with self .assertRaises (IndexError ):
341
402
m ["ab" ]
342
403
404
+ # test __repr__ methods
405
+ m = Matrix (vals4x4 )
406
+ 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]])"
407
+ self .assertEqual (repr (m ), mRepr )
408
+ self .assertEqual (str (eval (repr (m ))), mRepr )
409
+
410
+ def testMatrixFunctionality (self ):
411
+ # Test rotate methods
412
+ def matrix_almost_equal (m , target_matrix ):
413
+ for r , row in enumerate (target_matrix ):
414
+ for c , target_value in enumerate (row ):
415
+ self .assertAlmostEqual (m [r , c ], target_value )
416
+
417
+ root_3_over_2 = math .sqrt (3 ) / 2
418
+ m_rotate_x_30 = [
419
+ [1 , 0 , 0 , 0 ],
420
+ [0 , root_3_over_2 , - 1 / 2 , 0 ],
421
+ [0 , 1 / 2 , root_3_over_2 , 0 ],
422
+ [0 , 0 , 0 , 1 ],
423
+ ]
424
+ mx = Matrix ()
425
+ mx .rotateX (30 * DEG2RAD )
426
+ matrix_almost_equal (mx , m_rotate_x_30 )
427
+
428
+ m_rotate_y_30 = [
429
+ [root_3_over_2 , 0 , 1 / 2 , 0 ],
430
+ [0 , 1 , 0 , 0 ],
431
+ [- 1 / 2 , 0 , root_3_over_2 , 0 ],
432
+ [0 , 0 , 0 , 1 ],
433
+ ]
434
+ my = Matrix ()
435
+ my .rotateY (30 * DEG2RAD )
436
+ matrix_almost_equal (my , m_rotate_y_30 )
437
+
438
+ m_rotate_z_30 = [
439
+ [root_3_over_2 , - 1 / 2 , 0 , 0 ],
440
+ [1 / 2 , root_3_over_2 , 0 , 0 ],
441
+ [0 , 0 , 1 , 0 ],
442
+ [0 , 0 , 0 , 1 ],
443
+ ]
444
+ mz = Matrix ()
445
+ mz .rotateZ (30 * DEG2RAD )
446
+ matrix_almost_equal (mz , m_rotate_z_30 )
447
+
448
+ # Test matrix multipy vector
449
+ v = Vector (1 , 0 , 0 )
450
+ self .assertTupleAlmostEquals (
451
+ mz .multiply (v ).toTuple (), (root_3_over_2 , 1 / 2 , 0 ), 7
452
+ )
453
+
454
+ # Test matrix multipy matrix
455
+ m_rotate_xy_30 = [
456
+ [root_3_over_2 , 0 , 1 / 2 , 0 ],
457
+ [1 / 4 , root_3_over_2 , - root_3_over_2 / 2 , 0 ],
458
+ [- root_3_over_2 / 2 , 1 / 2 , 3 / 4 , 0 ],
459
+ [0 , 0 , 0 , 1 ],
460
+ ]
461
+ mxy = mx .multiply (my )
462
+ matrix_almost_equal (mxy , m_rotate_xy_30 )
463
+
464
+ # Test matrix inverse
465
+ vals4x4 = [[1 , 2 , 3 , 4 ], [5 , 1 , 6 , 7 ], [8 , 9 , 1 , 10 ], [0 , 0 , 0 , 1 ]]
466
+ vals4x4_invert = [
467
+ [- 53 / 144 , 25 / 144 , 1 / 16 , - 53 / 144 ],
468
+ [43 / 144 , - 23 / 144 , 1 / 16 , - 101 / 144 ],
469
+ [37 / 144 , 7 / 144 , - 1 / 16 , - 107 / 144 ],
470
+ [0 , 0 , 0 , 1 ],
471
+ ]
472
+ m = Matrix (vals4x4 ).inverse ()
473
+ matrix_almost_equal (m , vals4x4_invert )
474
+
343
475
def testTranslate (self ):
344
476
e = Edge .makeCircle (2 , (1 , 2 , 3 ))
345
477
e2 = e .translate (Vector (0 , 0 , 1 ))
@@ -394,6 +526,55 @@ def testPlaneNotEqual(self):
394
526
Plane (origin = (0 , 0 , 0 ), xDir = (1 , 0 , 0 ), normal = (0 , 1 , 1 )),
395
527
)
396
528
529
+ def testInvalidPlane (self ):
530
+ # Test plane creation error handling
531
+ with self .assertRaises (ValueError ):
532
+ Plane .named ("XX" , (0 , 0 , 0 ))
533
+ with self .assertRaises (ValueError ):
534
+ Plane (origin = (0 , 0 , 0 ), xDir = (0 , 0 , 0 ), normal = (0 , 1 , 1 ))
535
+ with self .assertRaises (ValueError ):
536
+ Plane (origin = (0 , 0 , 0 ), xDir = (1 , 0 , 0 ), normal = (0 , 0 , 0 ))
537
+
538
+ def testPlaneMethods (self ):
539
+ # Test error checking
540
+ p = Plane (origin = (0 , 0 , 0 ), xDir = (1 , 0 , 0 ), normal = (0 , 1 , 0 ))
541
+ with self .assertRaises (ValueError ):
542
+ p .toLocalCoords ("box" )
543
+ with self .assertRaises (NotImplementedError ):
544
+ p .mirrorInPlane ([Solid .makeBox (1 , 1 , 1 )], "Z" )
545
+
546
+ # Test translation to local coordinates
547
+ local_box = Workplane (p .toLocalCoords (Solid .makeBox (1 , 1 , 1 )))
548
+ local_box_vertices = [(v .X , v .Y , v .Z ) for v in local_box .vertices ().vals ()]
549
+ target_vertices = [
550
+ (0 , - 1 , 0 ),
551
+ (0 , 0 , 0 ),
552
+ (0 , - 1 , 1 ),
553
+ (0 , 0 , 1 ),
554
+ (1 , - 1 , 0 ),
555
+ (1 , 0 , 0 ),
556
+ (1 , - 1 , 1 ),
557
+ (1 , 0 , 1 ),
558
+ ]
559
+ for i , target_point in enumerate (target_vertices ):
560
+ self .assertTupleAlmostEquals (target_point , local_box_vertices [i ], 7 )
561
+
562
+ # Test mirrorInPlane
563
+ mirror_box = Workplane (p .mirrorInPlane ([Solid .makeBox (1 , 1 , 1 )], "Y" )[0 ])
564
+ mirror_box_vertices = [(v .X , v .Y , v .Z ) for v in mirror_box .vertices ().vals ()]
565
+ target_vertices = [
566
+ (0 , 0 , 1 ),
567
+ (0 , 0 , 0 ),
568
+ (0 , - 1 , 1 ),
569
+ (0 , - 1 , 0 ),
570
+ (- 1 , 0 , 1 ),
571
+ (- 1 , 0 , 0 ),
572
+ (- 1 , - 1 , 1 ),
573
+ (- 1 , - 1 , 0 ),
574
+ ]
575
+ for i , target_point in enumerate (target_vertices ):
576
+ self .assertTupleAlmostEquals (target_point , mirror_box_vertices [i ], 7 )
577
+
397
578
def testLocation (self ):
398
579
399
580
# Vector
@@ -418,6 +599,17 @@ def testLocation(self):
418
599
== loc3 .wrapped .Transformation ().TranslationPart ().Z ()
419
600
)
420
601
602
+ # Test creation from the OCP.gp.gp_Trsf object
603
+ loc4 = Location (gp_Trsf ())
604
+ self .assertTupleAlmostEquals (loc4 .toTuple ()[0 ], (0 , 0 , 0 ), 7 )
605
+ self .assertTupleAlmostEquals (loc4 .toTuple ()[1 ], (0 , 0 , 0 ), 7 )
606
+
607
+ # Test error handling on creation
608
+ with self .assertRaises (TypeError ):
609
+ Location ((0 , 0 , 1 ))
610
+ with self .assertRaises (TypeError ):
611
+ Location ("xy_plane" )
612
+
421
613
def testEdgeWrapperRadius (self ):
422
614
423
615
# get a radius from a simple circle
0 commit comments