1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
#for volume interference
from OCC.BRepGProp import *
from OCC.GProp import *
def shape_volume(shape): #should probably be a method of Shape
'''returns the volume of a TopoDS_Shape or Shape'''
tmp = GProp_GProps()
BRepGProp().VolumeProperties(shape, tmp)
volume = tmp.Mass()
return volume
def assembly_volume_estimate(parts):
'''returns the volume of an assembly given a list of parts
returns a sum of the volumes of each part
does not consider interference (see assembly_volume_actual)'''
total_volume = 0
for part in parts:
total_volume += part.volume()
return total_volume
def assembly_volume_actual(parts):
'''computes the actual volume of an assembly
interference between two parts tends to decrease the volume'''
#total_volume = assembly_volume_estimate(parts)
#box = BRepPrimAPI_MakeBox(Point(0,0,0), Point(1,1,1))
shape = None
#FIXME you should actually set no initial shape, and then make an initial shape in the for loop if there isn't one already
#shape = TopoDS_Shape() #start with nothing
for part in parts:
if shape is None:
shape = part.shapes[0]
else:
#is it ok to fuse non-touching objects into the same shape?
tmp_shape = BRepAlgoAPI_Fuse(shape, part.shapes[0])
shape = tmp_shape.Shape()
return shape_volume(shape)
def estimate_interference_volume(parts):
'''figures out how much volume should be missing from assembly_volume_actual compared to assembly_volume_estimate
not particularly special or enlightening'''
total_expected_missing_volume = 0
interfaces = []
for part in parts:
for interface in part.interfaces:
if interface.connected == True and interface not in interfaces:
#it's important to go over the interfaces as many times as they are mated
#because complementary interfaces should have complementary (positive, negative) volumes
#thus the total resulting volume should be zero if everything has a perfect fit
#if you disagree:
##no_go = False #it's ok
##mates = interface.connected
##for mate in mates:
## if mate in interfaces:
## no_go = True #not ok, it's already considered
##if not no_go:
total_expected_missing_volume += interface.volume
interfaces.append(interface) #so we don't count it twice
return total_expected_missing_volume
#this is the one you want to use after adding a part to an assembly
def estimate_collision_existence(parts, threshold=-1):
'''determines whether or not there is an illegal collision in the assembly.
threshold determines how much leeway you're willing to give the assembly. 0 means nothing should be out of place.
uses estimate_interference_volume, assembly_volume_actual, assembly_volume_estimate'''
assembly_volume = assembly_volume_estimate(parts)
estimated_interference = estimate_interference_volume(parts)
better_estimate = assembly_volume - estimated_interference
actual_volume = assembly_volume_actual(parts)
difference = actual_volume - better_estimate
if diff_diff >= threshold: return True
else: return False
print "estimated volume = ", estimated
print "estimated_interference = ", estimated_interference
print "difference = ", difference
print "threshold = ", threshold
if difference >= threshold:
return True
else:
return False
def common_volume(part1, part2):
'''returns the volume of the intersection of two parts'''
shape1 = part1.shapes[0]
shape2 = part2.shapes[0]
common = BRepAlgoAPI_Common(shape1, shape2).Shape() #this takes too long
tmp = GProp_GProps()
BRepGProp().VolumeProperties(common, tmp)
volume = tmp.Mass()
return volume
def part_collision(part1, part2, threshold=0.0):
'''determines whether or not two parts are colliding, given a threshold of maximum allowable intersection
returns True or False'''
volume = common_volume(part1, part2)
if volume > threshold: return True
else: return False
def _connection_interference(self, threshold=0.0): #call this as a method please
'''determines whether or not a connection has a geometric collision (only for the two mating parts) within a threshold
returns True or False'''
part1 = self.interface1.part
part2 = self.interface2.part
#the threshold should be the volume of interface1 + interface2 if we can isolate those regions
return part_collision(part1, part2, threshold=threshold)
Connection.interference = _connection_interference
def _volume(self):
'''determines the volume of the shape'''
tmp = GProp_GProps()
BRepGProp().VolumeProperties(self.shapes[0], tmp)
vol = tmp.Mass()
return vol
Part.volume = _volume
def deep_part_collider(parts):
'''given a list of parts, checks whether or not any of them geometrically overlap
returns a list of triples in the form: (volume, part1, part2) where volumetric interference was found'''
errors = []
for part in parts:
for part2 in parts:
volume = common_volume(part1, part2)
if volume > 0:
errors.append((volume, part1, part2))
return errors
|