Hey ! I’m working on a project of two steps but i need some help with grasshopper because i’m just learning.
-
I’m trying to cut a brep -modelised at first on rhino (let’s say a cube)- into small cubes (or points) but I’m struggling to actually cut them and not the surfaces.
-
Because I want after that to do a random selection of those cubes that are in contact of each others in order to highlight news 3D forms. I will add some variables like the number of selection, or the number of cubes in Z direction for example but i think i can manage that. (hopefully ahah)
I don’t know if I should work only with the components of grasshopper (i think it’s do-able) or add a python script.
A friend helped me coding a program that is working and doing mostly what i want but it would be better if i can translate it on grasshopper.
If you can help me even with just a part it would be very appreciated ! I hope it’s clear and if you have any questions please ask.
Here is the code and the result showed through polyscope.
import numpy as np
import polyscope as ps
from copy import deepcopy
import random as rd
DIR = [(0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 0, 1), (0, 1, 0), (1, 0, 0), (0, 0, -1), (0, 0, -1), (0, 0, -1), (0, 0, -1), (0, -1, 0), (-1, 0, 0)]
ps.init()
def init_cube_points(side_length):
points = set()
for i in range(side_length + 1):
for j in range(side_length + 1):
for k in range(side_length + 1):
points.add((i, j, k))
return points
def translate_point(point, vec):
return (point[0] + vec[0], point[1] + vec[1], point[2] + vec[2])
def vec_from_points(p_1, p_2):
return (p_2[0] - p_1[0], p_2[1] - p_1[1], p_2[2] - p_1[2])
class point_cloud:
def __init__(
self,
points=None,
):
self._origin = (0, 0, 0)
if points is not None:
self._points = points
else:
self._points = set()
def get_points(self):
return {translate_point(p, self._origin) for p in self._points}
def get_origin(self):
return self._origin
def get_relative_bounding_box(self):
x_max, y_max, z_max = 0, 0, 0
for p in self._points:
if p[0] > x_max:
x_max = p[0]
if p[1] > y_max:
y_max = p[1]
if p[2] > z_max:
z_max = p[2]
return (x_max, y_max, z_max)
def translate(self, vec):
self._origin = translate_point(self._origin, vec)
def is_intersecting_with(self, pc):
translate_vec = vec_from_points(pc._origin, self._origin)
for p in self._points:
if translate_point(p, translate_vec) in pc._points:
return True
return False
def is_removable(self, pc):
bounding_box = self.get_relative_bounding_box()
act_origin = (0, 0, 0)
def parcours(
self,
pc,
prev_origin,
act_origin,
bounding_box,
):
if prev_origin is not None:
translate_vec = vec_from_points(prev_origin, act_origin)
else:
translate_vec = (0, 0, 0)
pc_copy = deepcopy(pc)
pc_copy.translate(translate_vec)
if self.is_intersecting_with(pc_copy):
return False
if (
abs(act_origin[0]) > bounding_box[0]
or abs(act_origin[1]) > bounding_box[1]
or abs(act_origin[2]) > bounding_box[2]
):
return True
for d in DIR:
pot_next_origin = translate_point(act_origin, d)
pc_next = deepcopy(pc_copy)
if prev_origin is None or pot_next_origin != prev_origin:
if parcours(
self, pc_next, act_origin, pot_next_origin, bounding_box
):
return True
return False
return parcours(self, pc, None, act_origin, bounding_box)
def to_numpy_points(self):
return np.array(list(self.get_points()))
def separate_point_cloud(self, n_remove):
bounding_box = self.get_relative_bounding_box()
object_to_remove = []
points_copy = deepcopy(self._points)
point_list = list(self._points)
rd.shuffle(point_list)
for p in point_list:
if (
0 in p
or p[0] == bounding_box[0]
or p[1] == bounding_box[1]
or p[2] == bounding_box[2]
):
starting_point = p
object_to_remove.append(starting_point)
points_copy.remove(starting_point)
break
cpt = 0
while len(object_to_remove) != n_remove and cpt < 100000:
cpt += 1
rd_point = rd.choice(object_to_remove)
rd_d = rd.choice(DIR)
pot_neigh = translate_point(rd_point, rd_d)
if pot_neigh in points_copy:
points_copy.remove(pot_neigh)
object_to_remove.append(pot_neigh)
# if not point_cloud(points_copy).is_removable(
# point_cloud(set(object_to_remove))
# ):
# points_copy.add(object_to_remove.pop())
return point_cloud(set(object_to_remove)), point_cloud(points_copy)
# Lenght of the big cube side
side_length = 10
# Size of removed objects
object_removed_size = 450
# Number of pieces to extract
num_object = 3
points = init_cube_points(side_length)
cube = point_cloud(points)
for i in range(num_object):
removed_object, cube_left = cube.separate_point_cloud(object_removed_size)
# while not removed_object.is_removable(cube_left):
# removed_object, cube_left = cube.separate_point_cloud(object_removed_size)
cube_even = ps.register_point_cloud(f"Object {i}", removed_object.to_numpy_points())
cube = cube_left
ps.init()
cube_left = ps.register_point_cloud("Cube left", cube_left.to_numpy_points())
ps.show()