def xform_from_matrix(matrix): """Creates a Transform instance from a matrix represented as a list of 12 float values. """ transform = Transform(1.0) for i in range(0, len(matrix)): transform[i // 4, i % 4] = matrix[i] return transform
def get_frame_meshes(self, path, frame, ctx): """Retrieves all meshes required to render a specific frame of a path plan. Args: path (:obj:`list` of :class:`Configuration`): Represents a collision-free path to a goal pose. It is the output of the path planning generated by a :class:`Simulator` object. frame (:obj:`int`): Frame number to retrieve. ctx (:obj:`dict`): A dictionary to keep context. Within Grasshopper, this is normally the ``sc.sticky`` object. Returns: list: list of Rhino meshes that can be used to visualize the selected frame. """ first_start = timer() if self.debug else None shape_handles = self.simulator.get_all_visible_handles() if self.debug: LOG.debug('Execution time: get_all_visible_handles=%.2f', timer() - first_start) if 'rfl_meshes' not in ctx: ctx['rfl_meshes'] = self._get_rfl_meshes(shape_handles) frame_config = path[frame] start = timer() if self.debug else None self.simulator.set_robot_config(self.robot, frame_config) if self.debug: LOG.debug('Execution time: set_robot_config=%.2f', timer() - start) start = timer() if self.debug else None meshes = [] mesh_matrices = self.simulator.get_object_matrices(shape_handles) for handle, mesh_matrix in mesh_matrices.iteritems(): mesh = ctx['rfl_meshes'][handle].DuplicateShallow() mesh.Transform(xform_from_matrix(mesh_matrix)) meshes.append(mesh) if self.building_member: gripping_config = self.building_member_pickup_config if self.building_member_pickup_config else path[ 0] info = self._get_building_member_info(gripping_config) mesh = info['mesh'].DuplicateShallow() parent_transform = xform_from_matrix( mesh_matrices[info['parent_handle']]) relative_transform = info['relative_transform'] mesh.Transform( Transform.Multiply(parent_transform, relative_transform)) meshes.append(mesh) if self.debug: LOG.debug('Execution time: get all transformed meshes=%.2f', timer() - start) LOG.debug('Execution time: total=%.2f', timer() - first_start) return meshes
def compute_possible_children(self, part_id, conn_id, check_constraints = False): possible_children = [] current_part = self.aggregated_parts[part_id] if conn_id in current_part.active_connections: current_conn = current_part.connections[conn_id] for rule_id in current_conn.active_rules: rule = current_conn.rules_table[rule_id] next_part = self.parts[rule.part2] orientTransform = Transform.PlaneToPlane(next_part.connections[rule.conn2].flip_pln, current_conn.pln) ## boolean checks for all constraints coll_check = False add_coll_check = False valid_connections = [] missing_sup_check = False global_const_check = False if check_constraints: ## collision check self.possible_collisions = [] coll_check = self.collision_check(next_part, orientTransform) ## constraints check if self.mode == 1: ## only local constraints mode if coll_check == False and next_part.is_constrained: add_coll_check = self.additional_collider_check(next_part, orientTransform) if add_coll_check == False: missing_sup_check = self.missing_supports_check(next_part, orientTransform) elif self.mode == 2: ## onyl global constraints mode if coll_check == False and len(self.global_constraints) > 0: global_const_check = self.global_constraints_check(next_part, orientTransform) elif self.mode == 3: ## local+global constraints mode if coll_check == False: if len(self.global_constraints) > 0: global_const_check = self.global_constraints_check(next_part, orientTransform) if global_const_check == False and next_part.is_constrained: add_coll_check = self.additional_collider_check(next_part, orientTransform) if add_coll_check == False: missing_sup_check = self.missing_supports_check(next_part, orientTransform) if coll_check == False and add_coll_check == False and missing_sup_check == False and global_const_check == False: next_part_trans = next_part.transform(orientTransform) possible_children.append(next_part_trans) return possible_children else: return -1
def xform_from_transformation(transformation): """Creates a Rhino Transform instance from a :class:`Transformation`. Args: transformation (:class:`Transformation`): the transformation. Returns: (:class:`Rhino.Geometry.Transform`) """ transform = Transform(1.0) for i in range(0, 4): for j in range(0, 4): transform[i, j] = transformation[i, j] return transform
def xform_from_transformation(transformation): """Creates a Rhino Transform instance from a transformation object. Args: transformation (Transformation): the transformation. Returns: Transform: a Rhino class. """ transform = Transform(1.0) for i in range(0, 4): for j in range(0, 4): transform[i, j] = transformation[i, j] return transform
def xform_from_transformation_matrix(transformation_matrix): """Creates a Rhino Transform instance from 4x4 transformation matrix. Args: transformation_matrix (:obj:`list` of :obj:`list` of :obj:`float`): The 4x4 transformation matrix in row-major order. Returns: (:class:`Rhino.Geometry.Transform`) """ transform = Transform(1.0) for i in range(0, 4): for j in range(0, 4): transform[i, j] = transformation_matrix[i][j] return transform
def check_all_connections(self): for part in self.aggregated_parts: if len(part.active_connections) > 0: for conn_id in part.active_connections: conn = part.connections[conn_id] if len(conn.active_rules) > 0: for rule_id in conn.active_rules: next_rule = conn.rules_table[rule_id] next_part = self.parts[next_rule.part2] orientTransform = Transform.PlaneToPlane(next_part.connections[next_rule.conn2].flip_pln, conn.pln) _, coll_check, _, _, _ = self.check_all_constraints(next_part, orientTransform) if coll_check: conn.active_rules.remove(rule_id) if len(conn.active_rules) == 0: part.active_connections.remove(conn_id)
def xform_from_transformation_matrix(transformation_matrix): """Creates a Rhino Transform instance from 4x4 transformation matrix. Parameters ---------- transformation_matrix : :obj:`list` of :obj:`list` of :obj:`float` The 4x4 transformation matrix in row-major order. Returns ------- :class:`Rhino.Geometry.Transform` RhinoCommon Transform object """ transform = Transform(1.0) for i in range(0, 4): for j in range(0, 4): transform[i, j] = transformation_matrix[i][j] return transform
def xform_from_transformation(transformation): """Creates a Rhino Transform instance from a :class:`Transformation`. Parameters ---------- transformation (:class:`Transformation`): Compas transformation object Returns ------- :class:`Rhino.Geometry.Transform` RhinoCommon Transform object """ transform = Transform(1.0) for i in range(0, 4): for j in range(0, 4): transform[i, j] = transformation[i, j] return transform
def xform_from_transformation(transformation): """Creates a Rhino transformation from a COMPAS transformation. Parameters ---------- transformation : :class:`compas.geometry.Transformation` COMPAS transformation. Returns ------- :rhino:`Rhino.Geometry.Transform` """ transform = Transform(1.0) for i in range(0, 4): for j in range(0, 4): transform[i, j] = transformation[i, j] return transform
def xform_from_transformation_matrix(matrix): """Creates a Rhino transformation from a 4x4 transformation matrix. Parameters ---------- matrix : list[list[float]] The 4x4 transformation matrix in row-major order. Returns ------- :rhino:`Rhino.Geometry.Transform` """ transform = Transform(1.0) for i in range(0, 4): for j in range(0, 4): transform[i, j] = matrix[i][j] return transform
def compute_next_w_field(self, part): for i in xrange(len(part.active_connections) - 1, -1, -1): conn_id = part.active_connections[i] conn = part.connections[conn_id] for i2 in xrange(len(conn.active_rules) - 1, -1, -1): rule_id = conn.active_rules[i2] rule = conn.rules_table[rule_id] next_part = self.parts[rule.part2] next_center = Point3d(next_part.center) orientTransform = Transform.PlaneToPlane( next_part.connections[rule.conn2].flip_pln, conn.pln) next_center.Transform(orientTransform) if self.multiple_fields: f_name = next_part.field if self.field[f_name].bbox.Contains(next_center) == True: field_val = self.field[f_name].return_pt_val( next_center) queue_index = bisect.bisect_left( self.queue_values, field_val) queue_entry = (next_part.name, part.id, orientTransform) self.queue_values.insert(queue_index, field_val) self.aggregation_queue.insert(queue_index, queue_entry) self.queue_count += 1 else: if self.field.bbox.Contains(next_center) == True: field_val = self.field.return_pt_val(next_center) queue_index = bisect.bisect_left( self.queue_values, field_val) queue_entry = (next_part.name, part.id, orientTransform) self.queue_values.insert(queue_index, field_val) self.aggregation_queue.insert(queue_index, queue_entry) self.queue_count += 1
def aggregate_field(self, num): added = 0 loops = 0 while added < num: ## avoid endless loops loops += 1 if loops > num * 100: break ## if no part is present in the aggregation, add first random part if len(self.aggregated_parts) == 0 and self.prev_num == 0: first_part = self.parts[random.choice(self.parts.keys())] start_point = None if self.multiple_fields: f_name = first_part.field if (self.mode == 2 or self.mode == 3) and len(self.global_constraints) > 0: start_point = self.field[f_name].return_highest_pt( constraints=self.global_constraints) else: start_point = self.field[f_name].return_highest_pt() else: if (self.mode == 2 or self.mode == 3) and len(self.global_constraints) > 0: start_point = self.field.return_highest_pt( constraints=self.global_constraints) else: start_point = self.field.return_highest_pt() mov_vec = Vector3d.Subtract(Vector3d(start_point), Vector3d(first_part.center)) move_transform = Transform.Translation(mov_vec.X, mov_vec.Y, mov_vec.Z) first_part_trans = first_part.transform(move_transform) for conn in first_part_trans.connections: conn.generate_rules_table(self.rules) first_part_trans.id = 0 self.aggregated_parts.append(first_part_trans) ## compute all possible next parts and append to list self.compute_next_w_field(first_part_trans) added += 1 else: ## if no part is available, exit the aggregation routine and return an error message if self.queue_count == 0: msg = "Could not place " + str(num - added) + " parts" return msg next_data = self.aggregation_queue[self.queue_count - 1] next_part = self.parts[next_data[0]] next_center = Point3d(next_part.center) orientTransform = next_data[2] global_check, coll_check, add_coll_check, missing_sup_check, global_const_check = self.check_all_constraints( next_part, orientTransform) if not global_check: next_part_trans = next_part.transform(orientTransform) next_part_trans.reset_part(self.rules) for conn in next_part_trans.connections: conn.generate_rules_table(self.rules) next_part_trans.id = len(self.aggregated_parts) self.aggregated_parts[next_data[1]].children.append( next_part_trans.id) next_part_trans.parent = self.aggregated_parts[ next_data[1]].id self.aggregated_parts.append(next_part_trans) ## compute all possible next parts and append to list self.compute_next_w_field(next_part_trans) added += 1 ## TO FIX --> do not remove rules when only caused by missing supports self.aggregation_queue.pop() self.queue_values.pop() self.queue_count -= 1
def aggregate_rnd(self, num): added = 0 loops = 0 while added < num: loops += 1 if loops > num * 100: break ## if no part is present in the aggregation, add first random part if len(self.aggregated_parts) == 0: first_part = self.parts[random.choice(self.parts.keys())] first_part_trans = first_part.transform(Transform.Identity) for conn in first_part_trans.connections: conn.generate_rules_table(self.rules) first_part_trans.id = 0 self.aggregated_parts.append(first_part_trans) added += 1 ## otherwise add new random part else: next_rule = None part_01_id = -1 conn_01_id = -1 next_rule_id = -1 new_rule_attempts = 0 while new_rule_attempts < 10000: new_rule_attempts += 1 part_01_id = random.randint(0, len(self.aggregated_parts) - 1) part_01 = self.aggregated_parts[part_01_id] if len(part_01.active_connections) > 0: conn_01_id = part_01.active_connections[random.randint( 0, len(part_01.active_connections) - 1)] conn_01 = part_01.connections[conn_01_id] if len(conn_01.active_rules) > 0: next_rule_id = conn_01.active_rules[random.randint( 0, len(conn_01.active_rules) - 1)] next_rule = conn_01.rules_table[next_rule_id] break if next_rule is not None: next_part = self.parts[next_rule.part2] orientTransform = Transform.PlaneToPlane( next_part.connections[next_rule.conn2].flip_pln, conn_01.pln) global_check, coll_check, add_coll_check, missing_sup_check, global_const_check = self.check_all_constraints( next_part, orientTransform) if not global_check: next_part_trans = next_part.transform(orientTransform) next_part_trans.reset_part(self.rules) for i in range(len( next_part_trans.active_connections)): if next_part_trans.active_connections[ i] == next_rule.conn2: next_part_trans.active_connections.pop(i) break next_part_trans.id = len(self.aggregated_parts) ## parent-child tracking self.aggregated_parts[part_01_id].children.append( next_part_trans.id) next_part_trans.parent = self.aggregated_parts[ part_01_id].id self.aggregated_parts.append(next_part_trans) for i in range( len(self.aggregated_parts[part_01_id]. active_connections)): if self.aggregated_parts[ part_01_id].active_connections[ i] == conn_01_id: self.aggregated_parts[ part_01_id].active_connections.pop(i) break added += 1 ## TO FIX --> do not remove rules when only caused by missing supports else: ## remove rules if they cause collisions or overlappings for i in range( len(self.aggregated_parts[part_01_id]. connections[conn_01_id].active_rules)): if self.aggregated_parts[part_01_id].connections[ conn_01_id].active_rules[ i] == next_rule_id: self.aggregated_parts[part_01_id].connections[ conn_01_id].active_rules.pop(i) break ## check if the connection is still active (still active rules available) if len(self.aggregated_parts[part_01_id]. connections[conn_01_id].active_rules) == 0: for i in range( len(self.aggregated_parts[part_01_id]. active_connections)): if self.aggregated_parts[ part_01_id].active_connections[ i] == conn_01_id: self.aggregated_parts[ part_01_id].active_connections.pop(i) break else: ## if no part is available, exit the aggregation routine and return an error message msg = "Could not place " + str(num - added) + " parts" return msg
def aggregate_sequence(self, graph_rules): for rule in graph_rules: ## first part if len(self.aggregated_parts) == 0: aggr_rule = rule.split(">")[0] rule_parts = aggr_rule.split("_") part1 = str(rule_parts[0].split("|")[0]) conn1 = int(rule_parts[0].split("|")[1]) part2 = str(rule_parts[1].split("|")[0]) conn2 = int(rule_parts[1].split("|")[1]) rule_ids = rule.split(">")[1].split("_") first_part = self.parts[part1] first_part_trans = first_part.transform(Transform.Identity) first_part_trans.id = rule_ids[0] next_part = self.parts[part2] orientTransform = Transform.PlaneToPlane( next_part.connections[conn2].flip_pln, first_part.connections[conn1].pln) next_part_trans = next_part.transform(orientTransform) next_part_trans.id = rule_ids[1] ## check additional collider (for fabrication constraints) self.additional_collider_check(next_part, orientTransform) ## parent-child tracking first_part_trans.children.append(next_part_trans) next_part_trans.parent = first_part_trans self.aggregated_parts.append(first_part_trans) self.aggregated_parts.append(next_part_trans) first_part_trans.children.append(next_part_trans) else: aggr_rule = rule.split(">")[0] rule_parts = aggr_rule.split("_") part1_id = str(rule_parts[0].split("|")[0]) conn1 = int(rule_parts[0].split("|")[1]) part2 = str(rule_parts[1].split("|")[0]) conn2 = int(rule_parts[1].split("|")[1]) rule_ids = rule.split(">")[1].split("_") first_part = None for part in self.aggregated_parts: if part.id == part1_id: first_part = part break if first_part is not None: first_part.id = rule_ids[0] next_part = self.parts[part2] orientTransform = Transform.PlaneToPlane( next_part.connections[conn2].flip_pln, first_part.connections[conn1].pln) next_part_trans = next_part.transform(orientTransform) next_part_trans.id = rule_ids[1] ## parent-child tracking first_part.children.append(next_part_trans.id) next_part_trans.parent = first_part.id self.aggregated_parts.append(next_part_trans) else: pass ## implement error handling