├── README.md ├── a.py ├── moveToCentroid.py ├── packman.py ├── pySTL.py └── slicer.py /README.md: -------------------------------------------------------------------------------- 1 | # 3d-binary-packing- 2 | # bin packing of irregular shapes using loose octrees 3 | 4 | **slicer**: slices mesh into smaller octrees 5 | 6 | **a**: inserts and detects collision between meshes 7 | 8 | **pySTL**: used to move meshes to centroid 9 | 10 | **packman**: main script that reads all meshes and feeds them to the algorithm 11 | -------------------------------------------------------------------------------- /a.py: -------------------------------------------------------------------------------- 1 | from sys import getsizeof 2 | from time import time 3 | 4 | def space(s1, c1, 5 | s2, c2, 6 | s3, c3, 7 | par, ch1): 8 | 9 | if par == "a": 10 | p1 = Node(s1, c1) 11 | if ch1 == "b": 12 | p2 = Node(s2, c2) 13 | p3 = Node(s3, c3) 14 | else: 15 | p2 = Node(s3, c3) 16 | p3 = Node(s2, c2) 17 | elif par == "b": 18 | p1 = Node(s2, c2) 19 | if ch1 == "a": 20 | p2 = Node(s1, c1) 21 | p3 = Node(s3, c3) 22 | else: 23 | p2 = Node(s3, c3) 24 | p3 = Node(s1, c1) 25 | else: 26 | p1 = Node(s3, c3) 27 | if ch1 == "a": 28 | p2 = Node(s1, c1) 29 | p3 = Node(s2, c2) 30 | else: 31 | p2 = Node(s2, c2) 32 | p3 = Node(s1, c1) 33 | 34 | return p1, p2, p3 35 | 36 | def comp_child(a1,a2,a3): 37 | vol_a1 = a1[0]* a1[1]* a1[2] 38 | vol_a2 = a2[0]* a2[1]* a2[2] 39 | vol_a3 = a3[0]* a3[1]* a3[2] 40 | 41 | # 1>2>3, 1>3>2, 3>1>2, 2>1>3, 2>3>1, 3>2>1 42 | if vol_a1 >= vol_a2: 43 | if vol_a1 >= vol_a3: # 1>2, 1>3 44 | par = "a" 45 | vol = vol_a1 46 | 47 | if vol_a2 >= vol_a3: # 1>2>3 48 | child1 = "b" 49 | 50 | child2 = "c" 51 | else: # 1>3>2 52 | child1 = "c" 53 | 54 | child2 = "b" 55 | 56 | else: #a3 is the biggest #1>2, 3>1 ,3>1>2 57 | par = "c" 58 | 59 | vol = vol_a3 60 | 61 | child1 = "a" 62 | 63 | child2 = "b" 64 | 65 | elif vol_a2 >= vol_a3: # 2>1, 2>3 66 | par = "b" 67 | 68 | vol = vol_a2 69 | 70 | if vol_a1 >= vol_a3: # 2>1>3 71 | child1 = "a" 72 | 73 | child2 = "c" 74 | else: # 2>3>1 75 | child1 = "c" 76 | 77 | child2 = "a" 78 | 79 | else: #1<2, 2<3 , 3>2>1 80 | par = "c" 81 | 82 | vol = vol_a3 83 | 84 | child1 = "b" 85 | 86 | child2 = "a" 87 | 88 | vol_arr = [vol_a1,vol_a2,vol_a3] 89 | check(vol_arr, 90 | [r(par),r(child1),r(child2)]) 91 | #print(vol_a1,vol_a2,vol_a3) 92 | #print(par,child1,child2) 93 | return vol, par, child1, child2 94 | 95 | def r(x): 96 | if x == "a": 97 | return 0 98 | if x == "b": 99 | return 1 100 | if x == "c": 101 | return 2 102 | 103 | def check(a,b): 104 | if( (a[b[0]] < a[b[1]]) or (a[b[1]] < a[b[2]]) ): 105 | print("error") 106 | 107 | 108 | def split(box, cont): 109 | # yellow 110 | s_a1= [cont.s[0], 111 | (cont.s[1] - box.s[1]), 112 | cont.s[2]] 113 | 114 | c_a1= [cont.c[0], 115 | cont.c[1] + box.s[1], 116 | cont.c[2]] 117 | # red 118 | s_a2= [(cont.s[0] - box.s[0]), 119 | box.s[1], 120 | box.s[2]] 121 | 122 | c_a2= [cont.c[0] + box.s[0], 123 | cont.c[1], 124 | cont.c[2]] 125 | # white 126 | s_a3= [cont.s[0], 127 | box.s[1], 128 | (cont.s[2] - box.s[2])] 129 | 130 | c_a3= [cont.c[0], 131 | cont.c[1], 132 | cont.c[2] + box.s[2]] 133 | 134 | vol_par_a, par_a, ch1_a, ch2_a = comp_child(s_a1, s_a2, s_a3) 135 | par_a, ch1_a, ch2_a = space(s_a1, c_a1, s_a2, c_a2, s_a3, c_a3, par_a, ch1_a) 136 | 137 | # white 138 | s_b1 = [cont.s[0], 139 | cont.s[1], 140 | (cont.s[2] - box.s[2])] 141 | 142 | c_b1 = [cont.c[0], 143 | cont.c[1], 144 | cont.c[2] + box.s[2]] 145 | # red 146 | s_b2 = [(cont.s[0] - box.s[0]), 147 | box.s[1], 148 | box.s[2]] 149 | 150 | c_b2 = [cont.c[0] + box.s[0], 151 | cont.c[1], 152 | cont.c[2]] 153 | # yellow 154 | s_b3 = [cont.s[0], 155 | (cont.s[1] - box.s[1]), 156 | box.s[2]] 157 | 158 | c_b3 = [cont.c[0], 159 | cont.c[1] + box.s[1], 160 | cont.c[2]] 161 | 162 | vol_par_b, par_b, ch1_b, ch2_b = comp_child(s_b1, s_b2, s_b3) 163 | par_b, ch1_b, ch2_b = space(s_b1, c_b1, s_b2, c_b2, s_b3, c_b3, par_b, ch1_b) 164 | 165 | # red 166 | s_c1 = [(cont.s[0] - box.s[0]), 167 | cont.s[1], 168 | cont.s[2]] 169 | 170 | c_c1 = [cont.c[0] + box.s[0], 171 | cont.c[1], 172 | cont.c[2]] 173 | # white 174 | s_c2 = [box.s[0], 175 | cont.s[1], 176 | cont.s[2] - box.s[2]] 177 | 178 | c_c2 = [cont.c[0], 179 | cont.c[1], 180 | cont.c[2] + box.s[2]] 181 | # yellow 182 | s_c3 = [box.s[0], 183 | (cont.s[1] - box.s[1]), 184 | box.s[2]] 185 | 186 | c_c3 = [cont.c[0], 187 | cont.c[1] + box.s[1], 188 | cont.c[2]] 189 | 190 | vol_par_c, par_c, ch1_c, ch2_c = comp_child(s_c1, s_c2, s_c3) 191 | par_c, ch1_c, ch2_c = space(s_c1, c_c1, s_c2, c_c2, s_c3, c_c3, par_c, ch1_c) 192 | 193 | # acb, abc, cab, bac, bca, cba 194 | if(vol_par_a <= vol_par_b): 195 | if(vol_par_a <= vol_par_c): # ac, c1: 978 | mid = len(arr)//2 #Finding the mid of the array 979 | L = arr[:mid] # Dividing the array elements 980 | R = arr[mid:] # into 2 halves 981 | 982 | mergeSort(L) # Sorting the first half 983 | mergeSort(R) # Sorting the second half 984 | 985 | i = j = k = 0 986 | 987 | # Copy data to temp arrays L[] and R[] 988 | while i < len(L) and j < len(R): 989 | if vol(L[i]) > vol(R[j]): 990 | arr[k] = L[i] 991 | i+=1 992 | else: 993 | arr[k] = R[j] 994 | j+=1 995 | k+=1 996 | 997 | # Checking if any element was left 998 | while i < len(L): 999 | arr[k] = L[i] 1000 | i+=1 1001 | k+=1 1002 | 1003 | while j < len(R): 1004 | arr[k] = R[j] 1005 | j+=1 1006 | k+=1 1007 | 1008 | def SorT(p): 1009 | tmp = p 1010 | arr = [] 1011 | while tmp != False: 1012 | if( tmp.s[0] == 0 or 1013 | tmp.s[1] == 0 or 1014 | tmp.s[2] == 0): 1015 | tmp = tmp.right 1016 | continue 1017 | 1018 | arr.append(tmp) 1019 | tmp = tmp.right 1020 | mergeSort(arr) 1021 | return convarr(arr) 1022 | 1023 | def convarr(a): 1024 | p = a[0] 1025 | tmp = p 1026 | for i in a[1:]: 1027 | i.right = False 1028 | i.left = False 1029 | tmp.right = i 1030 | tmp = tmp.right 1031 | return p 1032 | 1033 | # look for rectangles, if one of its sides is beyond a certain length,check adj and treat it as a box 1034 | # def combine(a): 1035 | # traverse tree, if origin fits , mark this as origin visited 1036 | 1037 | # convert mesh into [[size][position related to origin]] 1038 | # traverse tree, if origin fits, 1039 | # put each mesh in respective place: 1040 | # add origin coordinate to each mesh 1041 | # check if place is visited: 1042 | # check if mesh (origin plus size) added to all visited (origin plus size) is bigger than the cont: 1043 | # if bigger check adj fits: 1044 | # if not return False,shortage array 1045 | # if all fits 1046 | # mark place as visited and put our size and coords inside but no split 1047 | # insert consecutive points in pointer into container 1048 | def deep_copy(big_cont): 1049 | tmp_ptr = big_cont 1050 | copy_cont = Node([tmp_ptr.s[0],tmp_ptr.s[1],tmp_ptr.s[2]], 1051 | [tmp_ptr.c[0],tmp_ptr.c[1],tmp_ptr.c[2]]) 1052 | copy_cont.visited = True 1053 | tmp_ptr_cont = copy_cont 1054 | tmp_ptr = tmp_ptr.right 1055 | while tmp_ptr is not False: 1056 | tmp_ptr_cont.right = Node([tmp_ptr.s[0],tmp_ptr.s[1],tmp_ptr.s[2]], 1057 | [tmp_ptr.c[0],tmp_ptr.c[1],tmp_ptr.c[2]]) 1058 | 1059 | tmp_ptr_cont = tmp_ptr_cont.right 1060 | tmp_ptr = tmp_ptr.right 1061 | 1062 | return copy_cont 1063 | 1064 | def insert_origin(ptr, big_cont,var): 1065 | big_cont_ptr = big_cont 1066 | pr(big_cont) 1067 | #print(big_cont_ptr.visited) 1068 | tmp_cont = deep_copy(big_cont) 1069 | #print(big_cont_ptr.visited) 1070 | tmp_ptr = tmp_cont 1071 | #pr(tmp_ptr) 1072 | # check if max,min x,y,z can be placed if coord is in that place 1073 | # (max x, min y, min z),(max x,max y , min z) ...................... 1074 | # check_bounds(tmp_ptr, big_cont) 1075 | """ 1076 | while tmp_ptr is not False: 1077 | print(big_cont_ptr.visited) 1078 | if big_cont_ptr.visited is False: 1079 | print("aaaaaaaaaaaaaaa") 1080 | big_cont_ptr.visited = True 1081 | if within(Node([ptr[0], ptr[1], ptr[2]], 1082 | [tmp_ptr.c[0]+ptr[3], tmp_ptr.c[1]+ptr[4], tmp_ptr.c[2]+ptr[5]]), tmp_ptr, tmp_cont): 1083 | 1084 | return [tmp_ptr.c[0]+ptr[3], tmp_ptr.c[1]+ptr[4], tmp_ptr.c[2]+ptr[5]], tmp_cont 1085 | print("aaaaaaaaaaaaaaa") 1086 | big_cont_ptr = big_cont_ptr.right 1087 | tmp_ptr = tmp_ptr.right 1088 | """ 1089 | while tmp_ptr is not False: 1090 | """ 1091 | varr = var 1092 | x= tmp_ptr.c[0]+ptr[3] +varr 1093 | y= tmp_ptr.c[1]+ptr[4] +varr 1094 | z= tmp_ptr.c[2]+ptr[5] +varr 1095 | while( x < tmp_ptr.c[0]+tmp_ptr.s[0] and 1096 | y < tmp_ptr.c[1]+tmp_ptr.s[1] and 1097 | z < tmp_ptr.c[2]+tmp_ptr.s[2] ): 1098 | 1099 | x += varr 1100 | y += varr 1101 | z += varr 1102 | print("**********************") 1103 | print(varr) 1104 | print("**********************") 1105 | if within(Node([ptr[0], ptr[1], ptr[2]],[x, y, z]), 1106 | tmp_ptr, 1107 | tmp_cont): 1108 | return [x,y,z], tmp_cont,varr 1109 | 1110 | varr += 1 1111 | """ 1112 | varr = var 1113 | x= tmp_ptr.c[0]+ptr[3] +varr 1114 | y= tmp_ptr.c[1]+ptr[4] +varr 1115 | z= tmp_ptr.c[2]+ptr[5] +varr 1116 | 1117 | if within(Node([ptr[0], ptr[1], ptr[2]],[x, y, z]), 1118 | tmp_ptr, 1119 | tmp_cont): 1120 | return [x,y,z], tmp_cont 1121 | 1122 | tmp_ptr = tmp_ptr.right 1123 | return False,False 1124 | 1125 | def insert_consec(boxes, big_cont): 1126 | var = 0 1127 | origin_c ,orig_cont = insert_origin(boxes[0], big_cont,var) 1128 | if origin_c is False: 1129 | print("box too big..... stop eating thyroid") 1130 | return False 1131 | print("*********************************************************") 1132 | print("first origin done") 1133 | print(origin_c) 1134 | while insert_rest(origin_c, boxes[1:], orig_cont) is False : 1135 | print(origin_c) 1136 | #print(hex(id(orig_cont)),hex(id(big_cont))) 1137 | #print(boxes[0]) 1138 | origin_c, orig_cont = insert_origin(boxes[0], big_cont,var) 1139 | var += 1 1140 | print("************************origin_C*************") 1141 | print(origin_c) 1142 | #checkbounds() 1143 | if origin_c is False: 1144 | print("box couldn't fit after all retries") 1145 | return False 1146 | big_cont = orig_cont 1147 | #cleanup(big_cont) 1148 | print("done inserting") 1149 | print("final origin") 1150 | print(origin_c) 1151 | return orig_cont, origin_c 1152 | 1153 | # box_arr = [box.s0,box.s1,box.s2,box.c0,box.c1,box.c2] 1154 | def insert_rest(orig_c, box_arr,big_cont): 1155 | for box_ptr in box_arr: 1156 | box = Node([box_ptr[0], 1157 | box_ptr[1], 1158 | box_ptr[2]], 1159 | [orig_c[0] + box_ptr[3], 1160 | orig_c[1] + box_ptr[4], 1161 | orig_c[2] + box_ptr[5]]) 1162 | if fits_consec(box ,big_cont): 1163 | #clean(big_cont) 1164 | continue 1165 | else: 1166 | return False 1167 | 1168 | return True 1169 | 1170 | # iterates over the whole big_cont to find the cont with the 1171 | # right coords and dimensions to contain the box 1172 | def fits_consec(box, big_cont): 1173 | tmp_ptr = big_cont 1174 | while tmp_ptr is not False: 1175 | if within(box, tmp_ptr, big_cont): 1176 | return True 1177 | else: 1178 | tmp_ptr = tmp_ptr.right 1179 | 1180 | return False 1181 | 1182 | """ 1183 | def splitter(big_cont): 1184 | tmp = big_cont 1185 | while tmp is not False: 1186 | if len(tmp.child) > 0: 1187 | tmp_ptr = Node(tmp.s,tmp.c) 1188 | for child in tmp.child: 1189 | tmp_ptr = split(tmp_ptr,child) 1190 | 1191 | 1192 | def insert_child(cont,child): 1193 | ptr = cont 1194 | while ptr is not False: 1195 | if fits(ptr,child): 1196 | tmp = ptr.right 1197 | ptr.right = split(box,ptr) 1198 | ptr.right.right.right.right = tmp 1199 | # make its size zero and cleaner will remove it 1200 | # instead of dealing with the whole parent,child issue 1201 | ptr.s = [0,0,0] 1202 | return True 1203 | if fits(ptr.left,child): 1204 | tmp = ptr.right 1205 | ptr.right = split(box,ptr.left) 1206 | ptr.right.right.right.right = tmp 1207 | # make its size zero and cleaner will remove it 1208 | # instead of dealing with the whole parent,child issue 1209 | ptr.s = [0,0,0] 1210 | return True 1211 | ptr = ptr.right 1212 | return False 1213 | """ 1214 | def within(box, cont,big_cont): 1215 | print("box.c", box.c[0],box.c[1],box.c[2]) 1216 | print("box.s", box.s[0],box.s[1],box.s[2]) 1217 | print("cont.c", cont.c[0],cont.c[1],cont.c[2]) 1218 | print("cont.s", cont.s[0],cont.s[1],cont.s[2]) 1219 | 1220 | if( cont.c[0] <= box.c[0] <= cont.c[0] + cont.s[0] and 1221 | cont.c[1] <= box.c[1] <= cont.c[1] + cont.s[1] and 1222 | cont.c[2] <= box.c[2] <= cont.c[2] + cont.s[2] ): 1223 | 1224 | if( cont.c[0] <= box.c[0]+ box.s[0] <= cont.c[0] + cont.s[0] and 1225 | cont.c[1] <= box.c[1]+ box.s[1] <= cont.c[1] + cont.s[1] and 1226 | cont.c[2] <= box.c[2]+ box.s[2] <= cont.c[2] + cont.s[2] ): 1227 | 1228 | #cont.child.append([box.s[0],box.s[1],box.s[2],box.c[0],box.c[1],box.c[2]]) 1229 | 1230 | tmp = cont.right 1231 | cont.right = split(box,cont) 1232 | cont.right.right.right.right = tmp 1233 | # make its size zero and cleaner will remove it 1234 | # instead of dealing with the whole parent,child issue 1235 | cont.s = [0,0,0] 1236 | print("within") 1237 | return True 1238 | else: 1239 | # we make a box out of the remains 1240 | x_diff = box.c[0] + box.s[0] - (cont.c[0] + cont.s[0]) 1241 | y_diff = box.c[1] + box.s[1] - (cont.c[1] + cont.s[1]) 1242 | z_diff = box.c[2] + box.s[2] - (cont.c[2] + cont.s[2]) 1243 | 1244 | #probably box is not bigger than cont in all directions 1245 | if x_diff <= 0: 1246 | x_coor = box.c[0] 1247 | x_diff = box.s[0] 1248 | px_done = True 1249 | else: 1250 | x_coor = cont.c[0] + cont.s[0] 1251 | px_done = False 1252 | 1253 | if y_diff <= 0: 1254 | y_coor = box.c[1] 1255 | y_diff = box.s[1] 1256 | py_done = True 1257 | else: 1258 | y_coor = cont.c[1] + cont.s[1] 1259 | py_done = False 1260 | 1261 | if z_diff <= 0: 1262 | z_coor = box.c[2] 1263 | z_diff = box.s[2] 1264 | pz_done = True 1265 | else: 1266 | z_coor = cont.c[2] + cont.s[2] 1267 | pz_done = False 1268 | 1269 | diff_box = Node([x_diff, y_diff ,z_diff], 1270 | [x_coor, y_coor, z_coor]) 1271 | 1272 | adj_arr = adj_consec(cont,big_cont) 1273 | 1274 | if adj_arr is not False: 1275 | for i in adj_arr: 1276 | if i[1] == "px" : 1277 | if px_done is False: 1278 | if within(diff_box, i[0],big_cont): 1279 | #cont.child.append([box.c[0],box.c[1],box.c[2], box.s[0],box.s[1],box.s[2]]) 1280 | px_done = True 1281 | 1282 | if i[1] == "py" : 1283 | if py_done is False: 1284 | if within(diff_box, i[0],big_cont): 1285 | #cont.child.append([box.c[0],box.c[1],box.c[2], box.s[0],box.s[1],box.s[2]]) 1286 | py_done = True 1287 | 1288 | if i[1] == "pz" : 1289 | if pz_done is False: 1290 | if within(diff_box, i[0],big_cont): 1291 | #cont.child.append([box.c[0],box.c[1],box.c[2], box.s[0],box.s[1],box.s[2]]) 1292 | pz_done = True 1293 | 1294 | if px_done is True and py_done is True and pz_done is True: 1295 | return True 1296 | else: 1297 | return False 1298 | 1299 | else: 1300 | return False 1301 | else: 1302 | return False 1303 | 1304 | 1305 | 1306 | def adj_consec(cont, big_cont): 1307 | 1308 | arr = [] 1309 | ptr = big_cont 1310 | while ptr.right is not False: 1311 | 1312 | if( (cont.c[1] + cont.s[1] == ptr.c[1]) and 1313 | (ptr.c[0] <= cont.c[0] <= ptr.c[0] + ptr.s[0]) and 1314 | (ptr.c[2] <= cont.c[2] <= ptr.c[2] + ptr.s[2]) ): 1315 | 1316 | arr.append([ptr,"py"]) 1317 | 1318 | 1319 | if( (cont.c[0] + cont.s[0] == ptr.c[0]) and 1320 | (ptr.c[1] <= cont.c[1] <= ptr.c[1] + ptr.s[1]) and 1321 | (ptr.c[2] <= cont.c[2] <= ptr.c[2] + ptr.s[2]) ): 1322 | 1323 | arr.append([ptr,"px"]) 1324 | 1325 | 1326 | if( (cont.c[2] + cont.s[2] == ptr.c[2]) and 1327 | (ptr.c[0] <= cont.c[0] <= ptr.c[0] + ptr.s[0]) and 1328 | (ptr.c[1] <= cont.c[1] <= ptr.c[1] + ptr.s[1]) ): 1329 | 1330 | arr.append([ptr,"pz"]) 1331 | 1332 | ptr = ptr.right 1333 | print('adj_consec Done') 1334 | return arr 1335 | 1336 | def cleanup(big_cont): 1337 | tmp_ptr = big_cont 1338 | print("cleaninng") 1339 | while tmp_ptr is not False: 1340 | #tmp_ptr.child = [] 1341 | if( tmp_ptr.s[0] == 0 or 1342 | tmp_ptr.s[1] == 0 or 1343 | tmp_ptr.s[2] == 0): 1344 | 1345 | tmp_ptr = tmp_ptr.right 1346 | continue 1347 | tmp_ptr.visited = False 1348 | tmp_ptr = tmp_ptr.right 1349 | 1350 | def clean(big_cont): 1351 | tmp_ptr = big_cont 1352 | print("cleaning") 1353 | while tmp_ptr is not False: 1354 | #tmp_ptr.child = [] 1355 | if( tmp_ptr.s[0] == 0 or 1356 | tmp_ptr.s[1] == 0 or 1357 | tmp_ptr.s[2] == 0): 1358 | tmp_ptr = tmp_ptr.right 1359 | continue 1360 | if( tmp_ptr.s[0] == 300 and 1361 | tmp_ptr.s[1] == 300 and 1362 | tmp_ptr.s[2] == 300): 1363 | tmp_ptr = tmp_ptr.right 1364 | continue 1365 | return big_cont 1366 | """ 1367 | from a import insert,Node,split,pr,SorT,insert_consec 1368 | s = Node([20,20,20],[0,0,0]) 1369 | b1 = Node([5,5,5],[0,0,0]) 1370 | b3 = Node([2,2,2],[0,0,0]) 1371 | b4 = Node([1,1,1],[0,0,0]) 1372 | b2 = Node([19,14,4],[0,0,0]) 1373 | b5 = Node([2,2,2],[0,0,0]) 1374 | #from a import fit_py 1375 | #b1 = split(b3,b1) 1376 | #b4 = Node([3,4,3],[0,0,0]) 1377 | #s= fit_py(b1,b1.right,b4) 1378 | s = split(b1,s) 1379 | s= SorT(s) 1380 | m = insert(b2,s) 1381 | m = SorT(m) 1382 | h = insert(b3,m) 1383 | #pr(h) 1384 | h = SorT(h) 1385 | f = insert(b4,h) 1386 | #pr(f) 1387 | f = SorT(f) 1388 | n = insert(b5,f) 1389 | #pr(n) 1390 | #s.right.right= split(b2,s.right.right) 1391 | size = [] 1392 | positions = [] 1393 | a=f 1394 | while a is not False: 1395 | size.append(a.s) 1396 | positions.append(a.c) 1397 | a=a.right 1398 | 1399 | positions 1400 | size 1401 | 1402 | """ 1403 | """ 1404 | assuming b1 < b2 1405 | 1406 | if (b1.x + b1.xs < b2.x > b1.x or b2.x + b2.xs < b1.x > b2.x) and 1407 | (b1.y + b1.ys < b2.y > b1.y or b2.y + b2.ys < b1.y > b2.y): 1408 | 1409 | if (b1.x + b1.xs < b2.x > b1.x and b1.y + b1.ys < b2.y > b1.y): 1410 | if b1.z > b2.z: 1411 | b2_cz = b1.z 1412 | else: 1413 | b1_cz = b2.z 1414 | 1415 | if (i[0].x + i[0].xs < i[1].x > i[0].x and i[0].y + i[0].ys < i[1].y > i[0].y): 1416 | 1417 | if i[0].z > i[1].z: 1418 | i[1].czs = i[0].z - c.z 1419 | i[1].cz = c.z 1420 | i[0].czs = c.zs - (i[0].z - c.z + i[0].zs) 1421 | i[0].cz = i[0].z 1422 | 1423 | else: 1424 | i[0].czs = i[1].z - c.z 1425 | i[0].cz = c.z 1426 | i[1].czs = c.zs - (i[1].z - c.z + i[1].zs) 1427 | i[1].cz = i[1].z 1428 | 1429 | 1430 | 1431 | 1432 | if (b1.x + b1.xs < b2.x or b2.x + b2.xs < b1.x) and 1433 | (b1.y + b1.ys < b2.y or b2.y + b2.ys < b1.y): 1434 | 1435 | y is free 1436 | x is free 1437 | z is free 1438 | 1439 | if b1.x + b1.xs < b2.x and 1440 | b1.y + b1.ys < b2.y: 1441 | 1442 | x is free 1443 | y is free 1444 | z is free 1445 | 1446 | if b1.x + b1.xs < b2.x and 1447 | b1.y + b1.ys > b2.y: 1448 | 1449 | from a import insert,Node,split,pr,SorT 1450 | s = Node([200,200,300],[0,0,0]) 1451 | b1 = Node([70,45,90],[0,0,0]) 1452 | s = split(b1,s) 1453 | s= SorT(s) 1454 | b1 = Node([70,45,130],[0,0,0]) 1455 | a,b = insert(b1,s) 1456 | a=h 1457 | positions = [] 1458 | size = [] 1459 | visit = [] 1460 | while a is not False: 1461 | size.append(a.s) 1462 | positions.append(a.c) 1463 | visit.append(a.visited) 1464 | a=a.right 1465 | 1466 | 1467 | """ 1468 | 1469 | 1470 | -------------------------------------------------------------------------------- /moveToCentroid.py: -------------------------------------------------------------------------------- 1 | import pySTL 2 | from numpy import array 3 | import subprocess 4 | 5 | print("counting meshes") 6 | #induce a bash task , count number of meshes inside 7 | task = subprocess.Popen("ls -1 ../Mesh/| wc -l",shell=True,stdout=subprocess.PIPE) 8 | Mesh_No = task.stdout.read() 9 | Mesh_No = int(Mesh_No) 10 | 11 | mesh_arr = [] 12 | 13 | print("started moving all data to blender space coords representation") 14 | 15 | for i in range(1, Mesh_No): 16 | #Load a model from a file. 17 | model = pySTL.STLmodel('../Mesh/%d.stl'%i) 18 | 19 | #print model properties 20 | print("Volume " + str(model.get_volume())) 21 | c = model.get_centroid() 22 | print("Centroid " + "X: " + str(c[0]) + " Y:" + str(c[1]) + " Z:" + str(c[2])) 23 | 24 | 25 | #Translate the model so that the centroid is at the origin. 26 | model.translate(-c) 27 | 28 | model.write_text_stl('../Mesh/centered/%d.stl'%i) 29 | 30 | print("finished successfully") 31 | -------------------------------------------------------------------------------- /packman.py: -------------------------------------------------------------------------------- 1 | from stl import mesh 2 | from slicer import f,F 3 | from a import insert,Node,split,pr,SorT 4 | import math 5 | import numpy 6 | import stl 7 | from matplotlib import pyplot 8 | from mpl_toolkits import mplot3d 9 | 10 | import subprocess 11 | import math 12 | from random import shuffle 13 | 14 | N = 1 15 | 16 | Tol_x = 1 17 | Tol_y = 1 18 | Tol_z = 1 19 | 20 | big_cont = Node([1000,1000,1000],[0,0,0]) 21 | 22 | print("Hi Coralie") 23 | print("Do you want the output combination to be random each time?") 24 | xx= input() 25 | if xx == "y": 26 | Randomize = 1 27 | elif xx == "n": 28 | Randomize = 0 29 | 30 | print("counting meshes") 31 | #induce a bash task , count number of meshes inside 32 | task = subprocess.Popen("ls -1 ../Mesh/centered| wc -l",shell=True,stdout=subprocess.PIPE) 33 | Mesh_No = task.stdout.read() 34 | Mesh_No = int(Mesh_No)+1 35 | Mesh_No = list(range(1,Mesh_No)) 36 | 37 | if Randomize == 1: 38 | shuffle(Mesh_No) 39 | 40 | print("translating first mesh into mathematical representations") 41 | M = mesh.Mesh.from_file('../Mesh/centered/%d.stl'%Mesh_No[0]) 42 | _,CC,_ = M.get_mass_properties() 43 | M.translate(-CC) 44 | minx, maxx, miny, maxy, minz, maxz = F(M) 45 | M.translate([-1*minx,-1*miny,-1*minz]) 46 | M.points = M.points[M.points[:,2].argsort(axis=0)] 47 | box = Node([maxx-minx, maxy-miny, maxz-minz], 48 | [minx, miny, minz]) 49 | 50 | print("done translating, now inserting") 51 | cont = split(box, big_cont) 52 | print("done inserting first mesh") 53 | #print([maxx-minx, maxy-miny, maxz-minz],"first") 54 | 55 | mesh_arr = [M] 56 | SorT(cont) 57 | for _,i in enumerate(Mesh_No[1:]): 58 | print("translating mesh %d.stl into mathematical representation"%i) 59 | M = mesh.Mesh.from_file('../Mesh/centered/%d.stl'%i) 60 | _,CC,_ = M.get_mass_properties() 61 | M.translate(-CC) 62 | minx, maxx, miny, maxy, minz, maxz = F(M) 63 | M.translate([-1*minx,-1*miny,-1*minz]) 64 | M.points = M.points[M.points[:,2].argsort(axis=0)] 65 | box_dims = f(M) 66 | box = Node(box_dims[0:3], 67 | box_dims[3:]) 68 | print("inserting mesh %d.stl"%i) 69 | #print(box_dims) 70 | coor, rot = insert(box, cont) 71 | #print(coor,rot) 72 | SorT(cont) 73 | if rot is not False: 74 | if rot is 'z': 75 | M.rotate([0.0, 0.0, box_dims[2]/2], math.radians(90)) 76 | elif rot is 'y': 77 | M.rotate([0.0, box_dims[1]/2, 0.0], math.radians(90)) 78 | elif rot is 'x': 79 | M.rotate([box_dims[0]/2, 0.0, 0.0], math.radians(90)) 80 | 81 | _,CC,_ = M.get_mass_properties() 82 | M.translate(-CC) 83 | minx, maxx, miny, maxy, minz, maxz = F(M) 84 | M.translate([-1*minx,-1*miny,-1*minz]) 85 | M.points = M.points[M.points[:,2].argsort(axis=0)] 86 | 87 | if coor is False: 88 | print("can't insert mesh %d.stl"%i) 89 | print("probably a size issue") 90 | break 91 | M.translate([coor[0]*Tol_x/2,coor[1]*Tol_y/2,coor[2]*Tol_z/2]) 92 | 93 | mesh_arr.append(M) 94 | print("done inserting mesh %d.stl"%i) 95 | 96 | print("inserted %d meshes"%len(mesh_arr),"out of a total of %d meshes"%len(Mesh_No)) 97 | combined = mesh.Mesh(numpy.concatenate([mesh.data for mesh in mesh_arr])) 98 | task = subprocess.Popen("ls -1v ../Finale",shell=True,stdout=subprocess.PIPE) 99 | last_mesh = task.stdout.read() 100 | 101 | if len(last_mesh) == 0: 102 | combined.save('../Finale/combined_001.stl') 103 | print("saved file combined_001.stl into Finale folder") 104 | else: 105 | last_mesh = int(last_mesh[-8:-5]) 106 | combined.save('../Finale/combined_%03d.stl'%(last_mesh+1)) 107 | print("saved file combined_%03d.stl into Finale folder"%(last_mesh+1)) 108 | 109 | -------------------------------------------------------------------------------- /pySTL.py: -------------------------------------------------------------------------------- 1 | import struct 2 | import numpy as np 3 | from math import cos 4 | from math import sin 5 | 6 | #3 Utility methods to calculate rotation matrices. 7 | def rotationAboutX(phi): 8 | R = np.array([[1, 0, 0],[0, cos(phi), sin(phi)],[0, -sin(phi), cos(phi)]]) 9 | return R 10 | 11 | def rotationAboutY(phi): 12 | R = np.array([[cos(phi), 0, -sin(phi)],[0, 1, 0],[sin(phi), 0, cos(phi)]]) 13 | return R 14 | 15 | def rotationAboutZ(phi): 16 | R = np.array([[cos(phi), sin(phi), 0],[-sin(phi), cos(phi), 0],[0, 0, 1]]) 17 | return R 18 | 19 | #3d face on a model 20 | class triangle: 21 | 22 | def __init__(self,p1,p2,p3,n=None): 23 | #3 points of the triangle 24 | self.vertices=np.array(p1),np.array(p2),np.array(p3) 25 | 26 | #triangles normal 27 | if n != None: 28 | self.normal= n 29 | else: 30 | self.normal = np.array(self.calculate_normal(self.vertices[0],self.vertices[1],self.vertices[2])) 31 | 32 | def calculate_normal(self,p1,p2,p3): 33 | p12 = p2-p1 34 | p23 = p3-p2 35 | #calculate the cross product 36 | return np.cross(p12,p23) 37 | 38 | 39 | 40 | 41 | class STLmodel: 42 | 43 | def __init__(self,filename): 44 | self.filename = filename 45 | self.triangles=[] 46 | self.centroid = None 47 | self.volume = None 48 | self.load_stl() 49 | 50 | #return the faces of the triangles 51 | def get_triangles(self): 52 | if self.triangles: 53 | for face in self.triangles: 54 | yield face 55 | 56 | def get_centroid(self): 57 | if self.centroid == None: 58 | self.calculateCentroid() 59 | return self.centroid 60 | 61 | def get_volume(self): 62 | if self.volume == None: 63 | self.calculateCentroid() 64 | return self.volume 65 | 66 | 67 | def calculateCentroid(self): 68 | totalVolume=0 69 | currentVolume=0 70 | xCenter = 0 71 | yCenter = 0 72 | zCenter = 0 73 | #Each triangle forms a tetrahedron with the origin. 74 | #Calculate the size inside the volume of the model. Then add the 75 | #contributions to the centroid of the 3-d shape based on those volumes. 76 | for tri in self.triangles: 77 | p1 = tri.vertices[0] 78 | p2 = tri.vertices[1] 79 | p3 = tri.vertices[2] 80 | currentVolume = ((p1[0]*p2[1]*p3[2] - p1[0]*p3[1]*p2[2] - p2[0]*p1[1]*p3[2] + 81 | p2[0]*p3[1]*p1[2] + p3[0]*p1[1]*p2[2] - p3[0]*p2[1]*p1[2])/6) 82 | totalVolume += currentVolume 83 | xCenter += ((p1[0] + p2[0] + p3[0])/4) * currentVolume 84 | yCenter += ((p1[1] + p2[1] + p3[1])/4) * currentVolume 85 | zCenter += ((p1[2] + p2[2] + p3[2])/4) * currentVolume 86 | 87 | self.volume = totalVolume 88 | xCentroid = xCenter/totalVolume 89 | yCentroid = yCenter/totalVolume 90 | zCentroid = zCenter/totalVolume 91 | self.centroid = np.array([xCentroid,yCentroid,zCentroid]) 92 | 93 | 94 | 95 | #load stl file detects if the file is a text file or binary file 96 | def load_stl(self): 97 | #read start of file to determine if its a binay stl file or a ascii stl file 98 | if self.filename: 99 | fp=open(self.filename,'rb') 100 | h=fp.read(80) 101 | type=h[0:5] 102 | fp.close() 103 | 104 | if type=='solid': 105 | self.load_text_stl() 106 | #Many Binary Files also start with 'solid' unfortunately. 107 | #if we don't have any triangles after attempting an ascii read 108 | #let's try a binary read and see if that works 109 | if len(self.triangles) < 1: 110 | print('ASCII load did not find any triangles. Your binary .STL file probably starts with "solid". Trying a binary read instead') 111 | self.load_binary_stl() 112 | 113 | else: 114 | self.load_binary_stl() 115 | 116 | #If we don't have any triangles. Something went wrong. 117 | if len(self.triangles) < 1: 118 | print("No triangles found for file. This may not be a .stl file.") 119 | 120 | 121 | #read text stl match keywords to grab the points to build the model 122 | def load_text_stl(self): 123 | print("Attempting to read ASCII STL: "+str(self.filename)) 124 | fp=open(self.filename,'r') 125 | for line in fp: 126 | words=line.split() 127 | if len(words)>0: 128 | if words[0]=='solid': 129 | try: 130 | self.name=words[1] 131 | except IndexError: 132 | self.name="polyhedron" 133 | 134 | if words[0]=='facet': 135 | center=[0.0,0.0,0.0] 136 | vertices=[] 137 | normal=(float(words[2]),float(words[3]),float(words[4])) 138 | 139 | if words[0]=='vertex': 140 | vertices.append((float(words[1]),float(words[2]),float(words[3]))) 141 | 142 | 143 | if words[0]=='endloop': 144 | #make sure we got the correct number of values before storing 145 | if len(vertices)==3: 146 | self.triangles.append(triangle(vertices[0],vertices[1],vertices[2],normal)) 147 | fp.close() 148 | 149 | #load binary stl file check wikipedia for the binary layout of the file 150 | #we use the struct library to read in and convert binary data into a format we can use 151 | def load_binary_stl(self): 152 | print("Attempting to read binary STL: "+str(self.filename,)) 153 | fp=open(self.filename,'rb') 154 | h=fp.read(80) 155 | 156 | l=struct.unpack('I',fp.read(4))[0] 157 | count=0 158 | while True: 159 | try: 160 | p=fp.read(12) 161 | if len(p)==12: 162 | n=struct.unpack('f',p[0:4])[0],struct.unpack('f',p[4:8])[0],struct.unpack('f',p[8:12])[0] 163 | 164 | p=fp.read(12) 165 | if len(p)==12: 166 | p1=struct.unpack('f',p[0:4])[0],struct.unpack('f',p[4:8])[0],struct.unpack('f',p[8:12])[0] 167 | 168 | p=fp.read(12) 169 | if len(p)==12: 170 | p2=struct.unpack('f',p[0:4])[0],struct.unpack('f',p[4:8])[0],struct.unpack('f',p[8:12])[0] 171 | 172 | p=fp.read(12) 173 | if len(p)==12: 174 | p3=struct.unpack('f',p[0:4])[0],struct.unpack('f',p[4:8])[0],struct.unpack('f',p[8:12])[0] 175 | 176 | new_tri=(n,p1,p2,p3) 177 | 178 | if len(new_tri)==4: 179 | tri=triangle(p1,p2,p3,n) 180 | self.triangles.append(tri) 181 | count+=1 182 | fp.read(2) 183 | 184 | if len(p)==0: 185 | break 186 | except EOFError: 187 | break 188 | fp.close() 189 | 190 | def write_text_stl(self, filename): 191 | print("Writing STL to: " + filename) 192 | 193 | try: 194 | f = open(filename, 'wb') 195 | try: 196 | f.write('solid {:s}\n'.format(self.name)) 197 | except AttributeError: 198 | f.write('solid {:s}\n'.format('polyhedron')) 199 | 200 | for facet in self.triangles: 201 | normal = facet.normal 202 | f.write(' facet normal {0:.6E} {1:.6E} {2:.6E}\n'.format(normal[0], normal[1], normal[2])) 203 | f.write(' outer loop\n') 204 | for point in facet.vertices: 205 | f.write(' vertex {0:.6E} {1:.6E} {2:.6E}\n'.format(point[0], point[1], point[2])) 206 | f.write(' endloop\n') 207 | f.write(' endfacet\n') 208 | 209 | try: 210 | f.write('endsolid {:s}\n'.format(self.name)) 211 | except AttributeError: 212 | f.write('endsolid {:s}\n'.format('polyhedron')) 213 | 214 | f.close() 215 | except IOError: 216 | print("Couldn't complete write. IOError encountered.") 217 | 218 | 219 | 220 | #Pass this a numpy 3-array to translate all the points in the .stl file. 221 | def translate(self, p): 222 | for tri in self.triangles: 223 | for point in tri.vertices: 224 | point[0] += p[0] 225 | point[1] += p[1] 226 | point[2] += p[2] 227 | self.volume = None 228 | self.centroid = None 229 | 230 | #Pass this a numpy 2D array, not a numpy matrix a rotation object. 231 | def rotate(self, R): 232 | for tri in self.triangles: 233 | for point in tri.vertices: 234 | rotatedPoint = R.dot(point) 235 | point[0] = rotatedPoint[0] 236 | point[1] = rotatedPoint[1] 237 | point[2] = rotatedPoint[2] 238 | 239 | self.centroid = None 240 | self.volume = None 241 | 242 | def scale(self, scale): 243 | for tri in self.triangles: 244 | for point in tri.vertices: 245 | point[0] = scale*point[0] 246 | point[1] = scale*point[1] 247 | point[2] = scale*point[2] 248 | 249 | self.volume = None 250 | self.centroid = None 251 | 252 | 253 | -------------------------------------------------------------------------------- /slicer.py: -------------------------------------------------------------------------------- 1 | from stl import mesh 2 | import math 3 | import numpy 4 | import stl 5 | from matplotlib import pyplot 6 | from mpl_toolkits import mplot3d 7 | 8 | 9 | def F(obj): 10 | minx = maxx = miny = maxy = minz = maxz = None 11 | for p in obj.points: 12 | # p contains (x, y, z) 13 | if minx is None: 14 | minx = p[stl.Dimension.X] 15 | maxx = p[stl.Dimension.X] 16 | miny = p[stl.Dimension.Y] 17 | maxy = p[stl.Dimension.Y] 18 | minz = p[stl.Dimension.Z] 19 | maxz = p[stl.Dimension.Z] 20 | else: 21 | maxx = max(p[stl.Dimension.X], maxx) 22 | minx = min(p[stl.Dimension.X], minx) 23 | maxy = max(p[stl.Dimension.Y], maxy) 24 | miny = min(p[stl.Dimension.Y], miny) 25 | maxz = max(p[stl.Dimension.Z], maxz) 26 | minz = min(p[stl.Dimension.Z], minz) 27 | return minx, maxx, miny, maxy, minz, maxz 28 | 29 | def f(obj): 30 | minx = maxx = miny = maxy = minz = maxz = None 31 | for p in obj.points: 32 | # p contains (x, y, z) 33 | if minx is None: 34 | minx = p[stl.Dimension.X] 35 | maxx = p[stl.Dimension.X] 36 | miny = p[stl.Dimension.Y] 37 | maxy = p[stl.Dimension.Y] 38 | minz = p[stl.Dimension.Z] 39 | maxz = p[stl.Dimension.Z] 40 | if minx == 0: 41 | minx = 1000000 42 | if miny == 0: 43 | miny = 1000000 44 | if minz == 0: 45 | minz = 1000000 46 | else: 47 | mix = minx 48 | miy = miny 49 | miz = minz 50 | maxx = max(p[stl.Dimension.X], maxx) 51 | minx = min(p[stl.Dimension.X], minx) 52 | maxy = max(p[stl.Dimension.Y], maxy) 53 | miny = min(p[stl.Dimension.Y], miny) 54 | maxz = max(p[stl.Dimension.Z], maxz) 55 | minz = min(p[stl.Dimension.Z], minz) 56 | if minx == 0: 57 | minx = mix 58 | if miny == 0: 59 | miny = miy 60 | if minz == 0: 61 | minz = miz 62 | return [maxx-minx, maxy-miny, maxz-minz, 63 | minx, miny, minz] 64 | 65 | def split(s,x): 66 | step = int(len(s) /x) 67 | print(len(s),step) 68 | l = [] 69 | i = 0 70 | h = mesh.Mesh(s.data.copy()) 71 | h.points[step:] =0 72 | l.append(h) 73 | i = step 74 | for a in range(0,x-1): 75 | h = mesh.Mesh(s.data.copy()) 76 | h.points[:i] = 0 77 | h.points[i+step:] = 0 78 | l.append(h) 79 | i += step 80 | 81 | return l 82 | """ 83 | class Node: 84 | def __init__(self,a=[0]*3,b=[0]*3): 85 | self.s = a 86 | self.c = b 87 | self.left = False 88 | self.right = False 89 | self.Rotate = False 90 | self.occupied = False 91 | self.visited = False 92 | """ 93 | """ 94 | from slicer import split,f,F 95 | from stl import mesh 96 | from a import insert_consec,Node 97 | import math 98 | import numpy 99 | import stl 100 | from matplotlib import pyplot 101 | from mpl_toolkits import mplot3d 102 | 103 | N = 1 # no of boxes to split 104 | M = mesh.Mesh.from_file('centered/6.stl') 105 | _,CC,_ = M.get_mass_properties() 106 | M.translate(-CC) 107 | minx, maxx, miny, maxy, minz, maxz = F(M) 108 | M.translate([-1*minx,-1*miny,-1*minz]) 109 | M.points = M.points[M.points[:,2].argsort(axis=0)] 110 | s = split(M,N) 111 | 112 | boxes = [] 113 | for i in range(0,len(s)): 114 | boxes.append(f(s[i])) 115 | 116 | big_cont = Node([500,500,500],[0,0,0]) 117 | h=insert_consec(boxes,big_cont) 118 | 119 | N = 1 # no of boxes to split 120 | L = mesh.Mesh.from_file('centered/7.stl') 121 | _,CC,_ = M.get_mass_properties() 122 | L.translate(-CC) 123 | minx, maxx, miny, maxy, minz, maxz = F(L) 124 | L.translate([-1*minx,-1*miny,-1*minz]) 125 | L.points = L.points[L.points[:,2].argsort(axis=0)] 126 | s = split(L,N) 127 | 128 | h=insert_consec(boxes,h) 129 | 130 | N = 1 # no of boxes to split 131 | H = mesh.Mesh.from_file('centered/11.stl') 132 | _,CC,_ = H.get_mass_properties() 133 | H.translate(-CC) 134 | minx, maxx, miny, maxy, minz, maxz = F(H) 135 | H.translate([-1*minx,-1*miny,-1*minz]) 136 | H.points = H.points[H.points[:,2].argsort(axis=0)] 137 | s = split(H,N) 138 | 139 | boxes = [] 140 | for i in range(0,len(s)): 141 | boxes.append(f(s[i])) 142 | 143 | h=insert_consec(boxes,h) 144 | 145 | N = 1 # no of boxes to split 146 | A = mesh.Mesh.from_file('centered/8.stl') 147 | _,CC,_ = A.get_mass_properties() 148 | A.translate(-CC) 149 | minx, maxx, miny, maxy, minz, maxz = F(A) 150 | A.translate([-1*minx,-1*miny,-1*minz]) 151 | A.points = A.points[A.points[:,2].argsort(axis=0)] 152 | s = split(A,N) 153 | 154 | boxes = [] 155 | for i in range(0,len(s)): 156 | boxes.append(f(s[i])) 157 | 158 | h=insert_consec(boxes,h) 159 | 160 | N = 1 # no of boxes to split 161 | B = mesh.Mesh.from_file('centered/3.stl') 162 | _,CC,_ = B.get_mass_properties() 163 | B.translate(-CC) 164 | minx, maxx, miny, maxy, minz, maxz = F(B) 165 | B.translate([-1*minx,-1*miny,-1*minz]) 166 | B.points = B.points[B.points[:,2].argsort(axis=0)] 167 | s = split(B,N) 168 | 169 | boxes = [] 170 | for i in range(0,len(s)): 171 | boxes.append(f(s[i])) 172 | 173 | h=insert_consec(boxes,h) 174 | 175 | N = 1 # no of boxes to split 176 | C = mesh.Mesh.from_file('centered/10.stl') 177 | _,CC,_ = C.get_mass_properties() 178 | C.translate(-CC) 179 | minx, maxx, miny, maxy, minz, maxz = F(C) 180 | C.translate([-1*minx,-1*miny,-1*minz]) 181 | C.points = C.points[C.points[:,2].argsort(axis=0)] 182 | s = split(C,N) 183 | 184 | boxes = [] 185 | for i in range(0,len(s)): 186 | boxes.append(f(s[i])) 187 | 188 | h=insert_consec(boxes,h) 189 | 190 | N = 1 # no of boxes to split 191 | D = mesh.Mesh.from_file('centered/12.stl') 192 | _,CC,_ = D.get_mass_properties() 193 | D.translate(-CC) 194 | minx, maxx, miny, maxy, minz, maxz = F(D) 195 | D.translate([-1*minx,-1*miny,-1*minz]) 196 | D.points = D.points[D.points[:,2].argsort(axis=0)] 197 | s = split(D,N) 198 | 199 | boxes = [] 200 | for i in range(0,len(s)): 201 | boxes.append(f(s[i])) 202 | 203 | h=insert_consec(boxes,h) 204 | 205 | N = 1 # no of boxes to split 206 | E = mesh.Mesh.from_file('centered/13.stl') 207 | _,CC,_ = E.get_mass_properties() 208 | E.translate(-CC) 209 | minx, maxx, miny, maxy, minz, maxz = F(E) 210 | E.translate([-1*minx,-1*miny,-1*minz]) 211 | E.points = E.points[E.points[:,2].argsort(axis=0)] 212 | s = split(E,N) 213 | 214 | boxes = [] 215 | for i in range(0,len(s)): 216 | boxes.append(f(s[i])) 217 | 218 | h=insert_consec(boxes,h) 219 | 220 | M.translate([0,0,0]) 221 | H.translate([0,0,45]) 222 | L.translate([0,0,95]) 223 | A.translate([0,0,150]) 224 | B.translate([0,31,152]) 225 | C.translate([0,66,152]) 226 | D.translate([0,66,152]) 227 | E.translate([0,14,0]) 228 | 229 | #meshes = [M,L,H] 230 | combined = mesh.Mesh(numpy.concatenate([H.data]+[L.data]+[A.data]+[B.data]+[C.data]+[D.data]+[E.data])) 231 | combined.save('combined_lastt.stl') 232 | figure = pyplot.figure() 233 | axes = mplot3d.Axes3D(figure) 234 | for m in meshes: 235 | axes.add_collection3d(mplot3d.art3d.Poly3DCollection(m.vectors)) 236 | 237 | scale = numpy.concatenate([m.points for m in meshes]).flatten(-1) 238 | axes.auto_scale_xyz(scale,scale,scale) 239 | pyplot.show() 240 | 241 | combined = mesh.Mesh(numpy.concatenate([L.data]+[M.data]+[H.data]) 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | positions = [] 253 | size = [] 254 | for i in boxes: 255 | size.append([i[0],i[1],i[2]]) 256 | positions.append([i[3],i[4],i[5]]) 257 | 258 | 259 | 260 | orig = boxes[0] 261 | orig = Node([orig[1] - orig[0], 262 | orig[3] - orig[2], 263 | orig[5] - orig[4]], 264 | [0,0,0]) 265 | 266 | orig_c = insert_orig(orig) 267 | 268 | Node_boxes = [] 269 | for box in boxes[1:]: 270 | Node_boxes.append([box[1] - box[0], 271 | box[3] - box[2], 272 | box[5] - box[4], 273 | orig_c[0] + box[0], 274 | orig_c[1] + box[2], 275 | orig_c[2] + box[4]]) 276 | 277 | """ 278 | --------------------------------------------------------------------------------