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):
129def euclidean_distance(a, b):
130    dx = a[0] - b[0]
131    dy = a[1] - b[1]
132    return sqrt(dx * dx + dy * dy)
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]