42
42
import warnings
43
43
44
44
from collections .abc import Iterable , Sequence
45
- from math import degrees , pi , radians , isclose
45
+ from math import degrees , log10 , pi , radians , isclose
46
46
from typing import Any , overload , TypeAlias , TYPE_CHECKING
47
47
48
48
import OCP .TopAbs as TopAbs_ShapeEnum
88
88
logger = logging .getLogger ("build123d" )
89
89
90
90
TOLERANCE = 1e-6
91
+ TOL_DIGITS = abs (int (log10 (TOLERANCE )))
91
92
TOL = 1e-2
92
93
DEG2RAD = pi / 180.0
93
94
RAD2DEG = 180 / pi
@@ -445,11 +446,17 @@ def __eq__(self, other: object) -> bool:
445
446
"""Vectors equal operator =="""
446
447
if not isinstance (other , Vector ):
447
448
return NotImplemented
448
- return self .wrapped .IsEqual (other .wrapped , 0.00001 , 0.00001 )
449
+ return self .wrapped .IsEqual (other .wrapped , TOLERANCE , TOLERANCE )
449
450
450
451
def __hash__ (self ) -> int :
451
452
"""Hash of Vector"""
452
- return hash ((round (self .X , 6 ), round (self .Y , 6 ), round (self .Z , 6 )))
453
+ return hash (
454
+ (
455
+ round (self .X , TOL_DIGITS - 1 ),
456
+ round (self .Y , TOL_DIGITS - 1 ),
457
+ round (self .Z , TOL_DIGITS - 1 ),
458
+ )
459
+ )
453
460
454
461
def __copy__ (self ) -> Vector :
455
462
"""Return copy of self"""
@@ -690,6 +697,16 @@ def __deepcopy__(self, _memo) -> Axis:
690
697
"""Return deepcopy of self"""
691
698
return Axis (self .position , self .direction )
692
699
700
+ def __hash__ (self ) -> int :
701
+ """Hash of Axis"""
702
+ return hash (
703
+ (
704
+ round (v , TOL_DIGITS - 1 )
705
+ for vector in [self .position , self .direction ]
706
+ for v in vector
707
+ )
708
+ )
709
+
693
710
def __repr__ (self ) -> str :
694
711
"""Display self"""
695
712
return f"({ self .position .to_tuple ()} ,{ self .direction .to_tuple ()} )"
@@ -1660,7 +1677,25 @@ def __eq__(self, other: object) -> bool:
1660
1677
radians (other .orientation .Y ),
1661
1678
radians (other .orientation .Z ),
1662
1679
)
1663
- return self .position == other .position and quaternion1 .IsEqual (quaternion2 )
1680
+ # Test quaternions with tolerance
1681
+ q_values = [
1682
+ [get_value () for get_value in (q .X , q .Y , q .Z , q .W )]
1683
+ for q in (quaternion1 , quaternion2 )
1684
+ ]
1685
+ quaternion_eq = all (
1686
+ isclose (v1 , v2 , abs_tol = TOLERANCE ) for v1 , v2 in zip (* q_values )
1687
+ )
1688
+ return self .position == other .position and quaternion_eq
1689
+
1690
+ def __hash__ (self ) -> int :
1691
+ """Hash of Location"""
1692
+ return hash (
1693
+ (
1694
+ round (v , TOL_DIGITS - 1 )
1695
+ for vector in [self .position , self .orientation ]
1696
+ for v in vector
1697
+ )
1698
+ )
1664
1699
1665
1700
def __neg__ (self ) -> Location :
1666
1701
"""Flip the orientation without changing the position operator -"""
@@ -2563,8 +2598,8 @@ def __eq__(self, other: object):
2563
2598
return NotImplemented
2564
2599
2565
2600
# equality tolerances
2566
- eq_tolerance_origin = 1e-6
2567
- eq_tolerance_dot = 1e-6
2601
+ eq_tolerance_origin = TOLERANCE
2602
+ eq_tolerance_dot = TOLERANCE
2568
2603
2569
2604
return (
2570
2605
# origins are the same
@@ -2575,6 +2610,16 @@ def __eq__(self, other: object):
2575
2610
and abs (self .x_dir .dot (other .x_dir ) - 1 ) < eq_tolerance_dot
2576
2611
)
2577
2612
2613
+ def __hash__ (self ) -> int :
2614
+ """Hash of Plane"""
2615
+ return hash (
2616
+ (
2617
+ round (v , TOL_DIGITS - 1 )
2618
+ for vector in [self .origin , self .x_dir , self .z_dir ]
2619
+ for v in vector
2620
+ )
2621
+ )
2622
+
2578
2623
def __neg__ (self ) -> Plane :
2579
2624
"""Reverse z direction of plane operator -"""
2580
2625
return Plane (self .origin , self .x_dir , - self .z_dir )
0 commit comments