SDKUtility
1# coding: utf-8 2import os 3from LSBoundingBox import LSBoundingBox 4from random import random 5from math import cos, sin, floor, sqrt, pi, ceil 6 7 8class OBJHelper(object): 9 10 @staticmethod 11 def get_obj_bound(obj_path): 12 bound_box = LSBoundingBox() 13 f = open(obj_path) 14 for line in f: 15 if line.startswith("v"): 16 (x, y, z) = list(map(lambda xx: float(xx), line[1:].strip().split(" "))) 17 if x < bound_box.minX: 18 bound_box.minX = x 19 if y < bound_box.minY: 20 bound_box.minY = y 21 if z < bound_box.minZ: 22 bound_box.minZ = z 23 if x > bound_box.maxX: 24 bound_box.maxX = x 25 if y > bound_box.maxY: 26 bound_box.maxY = y 27 if z > bound_box.maxZ: 28 bound_box.maxZ = z 29 f.close() 30 return bound_box 31 32 @staticmethod 33 def seperate_obj(obj_path, translate_to_origin="no", return_group_names=False, selected_groups=None): 34 """ 35 36 :param obj_path: 37 :param translate_to_origin: 38 :param return_group_names: 39 :param selected_groups: return only the selected groups 40 :return: 41 """ 42 vertice = [] 43 facets = {} 44 f = open(obj_path) 45 curr_group = "group" 46 for line in f: 47 if line.startswith("v"): 48 arr = line.strip().split() 49 if arr[0] == "v": 50 vertice.append(list(map(lambda x: float(x), arr[1:]))) 51 if line.startswith("g"): 52 curr_group = line[1:].strip() 53 facets[curr_group] = [] 54 if line.startswith("f"): 55 if curr_group not in facets: 56 facets[curr_group] = [line] 57 else: 58 facets[curr_group].append(line) 59 f.close() 60 61 # translate 62 if translate_to_origin == "xyz" or translate_to_origin == "xy": 63 offsetx, offsety, offsetz = 0, 0, 0 64 bound_box = LSBoundingBox() 65 for (x, y, z) in vertice: 66 if x < bound_box.minX: 67 bound_box.minX = x 68 if y < bound_box.minY: 69 bound_box.minY = y 70 if z < bound_box.minZ: 71 bound_box.minZ = z 72 if x > bound_box.maxX: 73 bound_box.maxX = x 74 if y > bound_box.maxY: 75 bound_box.maxY = y 76 if z > bound_box.maxZ: 77 bound_box.maxZ = z 78 offsetx = -0.5 * (bound_box.minX + bound_box.maxX) 79 offsey = bound_box.minY 80 offsetz = -0.5 * (bound_box.minZ + bound_box.maxZ) 81 if translate_to_origin == "xy": 82 offsey = 0 83 for i in range(len(vertice)): 84 vertice[i][0] = vertice[i][0] + offsetx 85 vertice[i][1] = vertice[i][1] + offsety 86 vertice[i][2] = vertice[i][2] + offsetz 87 88 dirpath, tmpfilename = os.path.split(obj_path) 89 shotname, extension = os.path.splitext(tmpfilename) 90 group_paths = [] 91 group_names = [] 92 for group_name in facets: 93 if (selected_groups is not None) and (group_name not in selected_groups): 94 continue 95 if len(facets[group_name]) == 0: 96 continue 97 new_facets_indice = [-1 for i in range(len(vertice))] 98 new_num = 1 99 group_obj_file_path = os.path.join(dirpath, shotname + "_" + group_name + ".obj") 100 group_paths.append(group_obj_file_path) 101 group_names.append(group_name) 102 f = open(group_obj_file_path, "w") 103 f.write("g " + group_name + "\n") 104 group_facets = facets[group_name] 105 for facetstr in group_facets: 106 arr = facetstr[1:].strip().split(" ") 107 if "" in arr: 108 continue 109 indice = list(map(lambda x: int(x.split("/")[0]), arr)) 110 new_indice = [-1 for i in range(len(indice))] 111 for i in range(len(indice)): 112 index = indice[i] 113 v = vertice[index-1] 114 if new_facets_indice[index-1] == -1: 115 f.write("v %f %f %f\n" % (v[0], v[1], v[2])) 116 new_facets_indice[index - 1] = new_num 117 new_indice[i] = new_num 118 new_num = new_num + 1 119 else: 120 new_indice[i] = new_facets_indice[index-1] 121 f.write("f " + ' '.join(list(map(lambda x: str(x), new_indice))) + "\n") 122 f.close() 123 if return_group_names: 124 return group_paths, group_names 125 return group_paths 126 127 128def euclidean_distance(a, b): 129 dx = a[0] - b[0] 130 dy = a[1] - b[1] 131 return sqrt(dx * dx + dy * dy) 132 133 134class SamplingUtils: 135 @staticmethod 136 def poisson_disc_samples(width, height, r, k=5, distance=euclidean_distance, random=random): 137 tau = 2 * pi 138 cellsize = r / sqrt(2) 139 140 grid_width = int(ceil(width / cellsize)) 141 grid_height = int(ceil(height / cellsize)) 142 grid = [None] * (grid_width * grid_height) 143 144 def grid_coords(p): 145 return int(floor(p[0] / cellsize)), int(floor(p[1] / cellsize)) 146 147 def fits(p, gx, gy): 148 yrange = list(range(max(gy - 2, 0), min(gy + 3, grid_height))) 149 for x in range(max(gx - 2, 0), min(gx + 3, grid_width)): 150 for y in yrange: 151 g = grid[x + y * grid_width] 152 if g is None: 153 continue 154 if distance(p, g) <= r: 155 return False 156 return True 157 158 p = width * random(), height * random() 159 queue = [p] 160 grid_x, grid_y = grid_coords(p) 161 grid[grid_x + grid_y * grid_width] = p 162 163 while queue: 164 qi = int(random() * len(queue)) 165 qx, qy = queue[qi] 166 queue[qi] = queue[-1] 167 queue.pop() 168 for _ in range(k): 169 alpha = tau * random() 170 d = r * sqrt(3 * random() + 1) 171 px = qx + d * cos(alpha) 172 py = qy + d * sin(alpha) 173 if not (0 <= px < width and 0 <= py < height): 174 continue 175 p = (px, py) 176 grid_x, grid_y = grid_coords(p) 177 if not fits(p, grid_x, grid_y): 178 continue 179 queue.append(p) 180 grid[grid_x + grid_y * grid_width] = p 181 return [p for p in grid if p is not None] 182 183 184if __name__ == "__main__": 185 print(OBJHelper.seperate_obj(r"D:\LESS\app\Database\3D_Objects\Trees\RAMI\ww_10.obj", translate_to_origin="xy"))
class
OBJHelper:
9class OBJHelper(object): 10 11 @staticmethod 12 def get_obj_bound(obj_path): 13 bound_box = LSBoundingBox() 14 f = open(obj_path) 15 for line in f: 16 if line.startswith("v"): 17 (x, y, z) = list(map(lambda xx: float(xx), line[1:].strip().split(" "))) 18 if x < bound_box.minX: 19 bound_box.minX = x 20 if y < bound_box.minY: 21 bound_box.minY = y 22 if z < bound_box.minZ: 23 bound_box.minZ = z 24 if x > bound_box.maxX: 25 bound_box.maxX = x 26 if y > bound_box.maxY: 27 bound_box.maxY = y 28 if z > bound_box.maxZ: 29 bound_box.maxZ = z 30 f.close() 31 return bound_box 32 33 @staticmethod 34 def seperate_obj(obj_path, translate_to_origin="no", return_group_names=False, selected_groups=None): 35 """ 36 37 :param obj_path: 38 :param translate_to_origin: 39 :param return_group_names: 40 :param selected_groups: return only the selected groups 41 :return: 42 """ 43 vertice = [] 44 facets = {} 45 f = open(obj_path) 46 curr_group = "group" 47 for line in f: 48 if line.startswith("v"): 49 arr = line.strip().split() 50 if arr[0] == "v": 51 vertice.append(list(map(lambda x: float(x), arr[1:]))) 52 if line.startswith("g"): 53 curr_group = line[1:].strip() 54 facets[curr_group] = [] 55 if line.startswith("f"): 56 if curr_group not in facets: 57 facets[curr_group] = [line] 58 else: 59 facets[curr_group].append(line) 60 f.close() 61 62 # translate 63 if translate_to_origin == "xyz" or translate_to_origin == "xy": 64 offsetx, offsety, offsetz = 0, 0, 0 65 bound_box = LSBoundingBox() 66 for (x, y, z) in vertice: 67 if x < bound_box.minX: 68 bound_box.minX = x 69 if y < bound_box.minY: 70 bound_box.minY = y 71 if z < bound_box.minZ: 72 bound_box.minZ = z 73 if x > bound_box.maxX: 74 bound_box.maxX = x 75 if y > bound_box.maxY: 76 bound_box.maxY = y 77 if z > bound_box.maxZ: 78 bound_box.maxZ = z 79 offsetx = -0.5 * (bound_box.minX + bound_box.maxX) 80 offsey = bound_box.minY 81 offsetz = -0.5 * (bound_box.minZ + bound_box.maxZ) 82 if translate_to_origin == "xy": 83 offsey = 0 84 for i in range(len(vertice)): 85 vertice[i][0] = vertice[i][0] + offsetx 86 vertice[i][1] = vertice[i][1] + offsety 87 vertice[i][2] = vertice[i][2] + offsetz 88 89 dirpath, tmpfilename = os.path.split(obj_path) 90 shotname, extension = os.path.splitext(tmpfilename) 91 group_paths = [] 92 group_names = [] 93 for group_name in facets: 94 if (selected_groups is not None) and (group_name not in selected_groups): 95 continue 96 if len(facets[group_name]) == 0: 97 continue 98 new_facets_indice = [-1 for i in range(len(vertice))] 99 new_num = 1 100 group_obj_file_path = os.path.join(dirpath, shotname + "_" + group_name + ".obj") 101 group_paths.append(group_obj_file_path) 102 group_names.append(group_name) 103 f = open(group_obj_file_path, "w") 104 f.write("g " + group_name + "\n") 105 group_facets = facets[group_name] 106 for facetstr in group_facets: 107 arr = facetstr[1:].strip().split(" ") 108 if "" in arr: 109 continue 110 indice = list(map(lambda x: int(x.split("/")[0]), arr)) 111 new_indice = [-1 for i in range(len(indice))] 112 for i in range(len(indice)): 113 index = indice[i] 114 v = vertice[index-1] 115 if new_facets_indice[index-1] == -1: 116 f.write("v %f %f %f\n" % (v[0], v[1], v[2])) 117 new_facets_indice[index - 1] = new_num 118 new_indice[i] = new_num 119 new_num = new_num + 1 120 else: 121 new_indice[i] = new_facets_indice[index-1] 122 f.write("f " + ' '.join(list(map(lambda x: str(x), new_indice))) + "\n") 123 f.close() 124 if return_group_names: 125 return group_paths, group_names 126 return group_paths
@staticmethod
def
get_obj_bound(obj_path):
11 @staticmethod 12 def get_obj_bound(obj_path): 13 bound_box = LSBoundingBox() 14 f = open(obj_path) 15 for line in f: 16 if line.startswith("v"): 17 (x, y, z) = list(map(lambda xx: float(xx), line[1:].strip().split(" "))) 18 if x < bound_box.minX: 19 bound_box.minX = x 20 if y < bound_box.minY: 21 bound_box.minY = y 22 if z < bound_box.minZ: 23 bound_box.minZ = z 24 if x > bound_box.maxX: 25 bound_box.maxX = x 26 if y > bound_box.maxY: 27 bound_box.maxY = y 28 if z > bound_box.maxZ: 29 bound_box.maxZ = z 30 f.close() 31 return bound_box
@staticmethod
def
seperate_obj( obj_path, translate_to_origin='no', return_group_names=False, selected_groups=None):
33 @staticmethod 34 def seperate_obj(obj_path, translate_to_origin="no", return_group_names=False, selected_groups=None): 35 """ 36 37 :param obj_path: 38 :param translate_to_origin: 39 :param return_group_names: 40 :param selected_groups: return only the selected groups 41 :return: 42 """ 43 vertice = [] 44 facets = {} 45 f = open(obj_path) 46 curr_group = "group" 47 for line in f: 48 if line.startswith("v"): 49 arr = line.strip().split() 50 if arr[0] == "v": 51 vertice.append(list(map(lambda x: float(x), arr[1:]))) 52 if line.startswith("g"): 53 curr_group = line[1:].strip() 54 facets[curr_group] = [] 55 if line.startswith("f"): 56 if curr_group not in facets: 57 facets[curr_group] = [line] 58 else: 59 facets[curr_group].append(line) 60 f.close() 61 62 # translate 63 if translate_to_origin == "xyz" or translate_to_origin == "xy": 64 offsetx, offsety, offsetz = 0, 0, 0 65 bound_box = LSBoundingBox() 66 for (x, y, z) in vertice: 67 if x < bound_box.minX: 68 bound_box.minX = x 69 if y < bound_box.minY: 70 bound_box.minY = y 71 if z < bound_box.minZ: 72 bound_box.minZ = z 73 if x > bound_box.maxX: 74 bound_box.maxX = x 75 if y > bound_box.maxY: 76 bound_box.maxY = y 77 if z > bound_box.maxZ: 78 bound_box.maxZ = z 79 offsetx = -0.5 * (bound_box.minX + bound_box.maxX) 80 offsey = bound_box.minY 81 offsetz = -0.5 * (bound_box.minZ + bound_box.maxZ) 82 if translate_to_origin == "xy": 83 offsey = 0 84 for i in range(len(vertice)): 85 vertice[i][0] = vertice[i][0] + offsetx 86 vertice[i][1] = vertice[i][1] + offsety 87 vertice[i][2] = vertice[i][2] + offsetz 88 89 dirpath, tmpfilename = os.path.split(obj_path) 90 shotname, extension = os.path.splitext(tmpfilename) 91 group_paths = [] 92 group_names = [] 93 for group_name in facets: 94 if (selected_groups is not None) and (group_name not in selected_groups): 95 continue 96 if len(facets[group_name]) == 0: 97 continue 98 new_facets_indice = [-1 for i in range(len(vertice))] 99 new_num = 1 100 group_obj_file_path = os.path.join(dirpath, shotname + "_" + group_name + ".obj") 101 group_paths.append(group_obj_file_path) 102 group_names.append(group_name) 103 f = open(group_obj_file_path, "w") 104 f.write("g " + group_name + "\n") 105 group_facets = facets[group_name] 106 for facetstr in group_facets: 107 arr = facetstr[1:].strip().split(" ") 108 if "" in arr: 109 continue 110 indice = list(map(lambda x: int(x.split("/")[0]), arr)) 111 new_indice = [-1 for i in range(len(indice))] 112 for i in range(len(indice)): 113 index = indice[i] 114 v = vertice[index-1] 115 if new_facets_indice[index-1] == -1: 116 f.write("v %f %f %f\n" % (v[0], v[1], v[2])) 117 new_facets_indice[index - 1] = new_num 118 new_indice[i] = new_num 119 new_num = new_num + 1 120 else: 121 new_indice[i] = new_facets_indice[index-1] 122 f.write("f " + ' '.join(list(map(lambda x: str(x), new_indice))) + "\n") 123 f.close() 124 if return_group_names: 125 return group_paths, group_names 126 return group_paths
Parameters
- obj_path:
- translate_to_origin:
- return_group_names:
- selected_groups: return only the selected groups
Returns
def
euclidean_distance(a, b):
class
SamplingUtils:
135class SamplingUtils: 136 @staticmethod 137 def poisson_disc_samples(width, height, r, k=5, distance=euclidean_distance, random=random): 138 tau = 2 * pi 139 cellsize = r / sqrt(2) 140 141 grid_width = int(ceil(width / cellsize)) 142 grid_height = int(ceil(height / cellsize)) 143 grid = [None] * (grid_width * grid_height) 144 145 def grid_coords(p): 146 return int(floor(p[0] / cellsize)), int(floor(p[1] / cellsize)) 147 148 def fits(p, gx, gy): 149 yrange = list(range(max(gy - 2, 0), min(gy + 3, grid_height))) 150 for x in range(max(gx - 2, 0), min(gx + 3, grid_width)): 151 for y in yrange: 152 g = grid[x + y * grid_width] 153 if g is None: 154 continue 155 if distance(p, g) <= r: 156 return False 157 return True 158 159 p = width * random(), height * random() 160 queue = [p] 161 grid_x, grid_y = grid_coords(p) 162 grid[grid_x + grid_y * grid_width] = p 163 164 while queue: 165 qi = int(random() * len(queue)) 166 qx, qy = queue[qi] 167 queue[qi] = queue[-1] 168 queue.pop() 169 for _ in range(k): 170 alpha = tau * random() 171 d = r * sqrt(3 * random() + 1) 172 px = qx + d * cos(alpha) 173 py = qy + d * sin(alpha) 174 if not (0 <= px < width and 0 <= py < height): 175 continue 176 p = (px, py) 177 grid_x, grid_y = grid_coords(p) 178 if not fits(p, grid_x, grid_y): 179 continue 180 queue.append(p) 181 grid[grid_x + grid_y * grid_width] = p 182 return [p for p in grid if p is not None]
@staticmethod
def
poisson_disc_samples( width, height, r, k=5, distance=<function euclidean_distance>, random=<built-in method random of Random object>):
136 @staticmethod 137 def poisson_disc_samples(width, height, r, k=5, distance=euclidean_distance, random=random): 138 tau = 2 * pi 139 cellsize = r / sqrt(2) 140 141 grid_width = int(ceil(width / cellsize)) 142 grid_height = int(ceil(height / cellsize)) 143 grid = [None] * (grid_width * grid_height) 144 145 def grid_coords(p): 146 return int(floor(p[0] / cellsize)), int(floor(p[1] / cellsize)) 147 148 def fits(p, gx, gy): 149 yrange = list(range(max(gy - 2, 0), min(gy + 3, grid_height))) 150 for x in range(max(gx - 2, 0), min(gx + 3, grid_width)): 151 for y in yrange: 152 g = grid[x + y * grid_width] 153 if g is None: 154 continue 155 if distance(p, g) <= r: 156 return False 157 return True 158 159 p = width * random(), height * random() 160 queue = [p] 161 grid_x, grid_y = grid_coords(p) 162 grid[grid_x + grid_y * grid_width] = p 163 164 while queue: 165 qi = int(random() * len(queue)) 166 qx, qy = queue[qi] 167 queue[qi] = queue[-1] 168 queue.pop() 169 for _ in range(k): 170 alpha = tau * random() 171 d = r * sqrt(3 * random() + 1) 172 px = qx + d * cos(alpha) 173 py = qy + d * sin(alpha) 174 if not (0 <= px < width and 0 <= py < height): 175 continue 176 p = (px, py) 177 grid_x, grid_y = grid_coords(p) 178 if not fits(p, grid_x, grid_y): 179 continue 180 queue.append(p) 181 grid[grid_x + grid_y * grid_width] = p 182 return [p for p in grid if p is not None]