def addObjectsByDuplication(N=1, createObjectFunction=bpy.ops.object.empty_add, GUI_loaded=False): ''' Until we figure out a way to allocate space for objects to add them faster, we work around the problem by using blender's duplicate function. This means the number of objects increases according to a 2^n series. .. note:: This function is currently unused... ''' ## progress indicator does not work when running from CLI if GUI_loaded: bpy.context.window_manager.progress_begin(0, 100) # we will store added objects in a list L = N * [0] current_idx = 0 # deselect all bpy.ops.object.select_all(action='DESELECT') # add first object createObjectFunction() L[current_idx] = bpy.context.object current_idx += 1 # duplicate while 2 * current_idx <= N: sub_start_time = time.time() bpy.ops.object.select_linked() print(('current_idx =', current_idx, 'selection =', len(bpy.context.selected_objects))) bpy.ops.object.duplicate_move_linked() L[current_idx:current_idx + len(bpy.context.selected_objects)] = bpy.context.selected_objects current_idx += len(bpy.context.selected_objects) if GUI_loaded: bpy.context.window_manager.progress_update(current_idx / N) else: print(('progress =', current_idx / N)) print('Elapsed time: ', round(time.time() - sub_start_time, 4), 'seconds') print('Last duplication...') selectObjects(L[0:N - current_idx]) bpy.ops.object.duplicate_move_linked() bpy.context.window_manager.progress_end() return (L)
def add_lattice_vectors(self, a0, a1, a2, name='lattice_vectors', shift_origin=False, cone_length=None, cone_radius=None, cylinder_radius=None): loadBasicMaterials() a0 = Vector(a0) a1 = Vector(a1) a2 = Vector(a2) centro = 0.5*(a0+a1+a2) if shift_origin: start_point = -centro else: start_point = Vector([0,0,0]) # get shortest arrow length arrow_length = min(a0.length, a1.length, a2.length) if not cone_length: cone_length = arrow_length/5.0 if not cone_radius: cone_radius = arrow_length/20.0 if not cylinder_radius: cylinder_radius = cone_radius/2.0 obj_a0 = add_arrow(self, start_point, start_point+a0, name='a0', cone_length=cone_length, cone_radius=cone_radius, cylinder_radius=cylinder_radius) bpy.ops.object.material_slot_add() obj_a0.material_slots[obj_a0.material_slots.__len__() - 1].material = bpy.data.materials['red'] obj_a1 = add_arrow(self, start_point, start_point+a1, name='a1', cone_length=cone_length, cone_radius=cone_radius, cylinder_radius=cylinder_radius) bpy.ops.object.material_slot_add() obj_a1.material_slots[obj_a1.material_slots.__len__() - 1].material = bpy.data.materials['green'] obj_a2 = add_arrow(self, start_point, start_point+a2, name='a2', cone_length=cone_length, cone_radius=cone_radius, cylinder_radius=cylinder_radius) bpy.ops.object.material_slot_add() obj_a2.material_slots[obj_a2.material_slots.__len__() - 1].material = bpy.data.materials['blue'] bpy.ops.object.add(type='EMPTY') obj_empty = bpy.context.active_object obj_empty.name = name selectObjects([obj_empty, obj_a0, obj_a1, obj_a2], active_object=obj_empty, context = bpy.context) bpy.ops.object.parent_set(type='OBJECT', keep_transform=True) return (obj_empty, obj_a0, obj_a1, obj_a2)
def add_photonic_wire(self, context): blender_object_list = [] if self.show_design: cyl = GeometryObjects.add_cylinder(self, [-0.5*self.length, 0, self.height + self.bend_radius], [0.5*self.length, 0, self.height + self.bend_radius], name='photonic wire', cylinder_radius=0.5*self.wire_diametre) cone1 = GeometryObjects.add_cone(self, [-0.5*self.length-self.bend_radius, 0, 0], [-0.5*self.length-self.bend_radius, 0, self.height], name='Cone1', radius1=0.5*self.cone_diametre, radius2=0.5*self.wire_diametre) cone2 = GeometryObjects.add_cone(self, [0.5*self.length+self.bend_radius, 0, 0], [0.5*self.length+self.bend_radius, 0, self.height], name='Cone2', radius1=0.5*self.cone_diametre, radius2=0.5*self.wire_diametre) bend1 = GeometryObjects.add_bend(centre=[0.5*self.length, 0, self.height], bend_radius=self.bend_radius, tube_radius=0.5*self.wire_diametre, name='bend2', angle_start_deg=0, angle_end_deg=90) bend2 = GeometryObjects.add_bend(centre=[-0.5*self.length, 0, self.height], bend_radius=self.bend_radius, tube_radius=0.5*self.wire_diametre, name='bend1', angle_start_deg=90, angle_end_deg=180) blender_object_list.extend([cyl, cone1, cone2, bend1, bend2]) if self.show_gwl: a = GeometryObjects.add_gwl_cone(self, [-0.5*self.length-self.bend_radius, 0, 0], [-0.5*self.length-self.bend_radius, 0, self.height], name='GWL_wire0_Cone1', radius1=0.5*self.cone_diametre, radius2=0.5*self.wire_diametre, cross_section_r0=self.cross_section_r0, cross_section_delta_r=self.cross_section_delta_r, cross_section_delta_theta=self.cross_section_delta_theta, longitudinal_delta=self.cone_delta) b = GeometryObjects.add_gwl_bend(centre=[-0.5*self.length, 0, self.height], bend_radius=self.bend_radius, tube_radius=0.5*self.wire_diametre, name='GWL_wire1_bend1', angle_start_deg=180, angle_end_deg=90, cross_section_r0=self.cross_section_r0, cross_section_delta_r=self.cross_section_delta_r, cross_section_delta_theta=self.cross_section_delta_theta, longitudinal_delta=self.bend_delta) c = GeometryObjects.add_gwl_cylinder(self, [-0.5*self.length, 0, self.height + self.bend_radius], [0.5*self.length, 0, self.height + self.bend_radius], name='GWL_wire2_photonic_wire', cylinder_radius=0.5*self.wire_diametre, cross_section_r0=self.cross_section_r0, cross_section_delta_r=self.cross_section_delta_r, cross_section_delta_theta=self.cross_section_delta_theta, longitudinal_delta=self.wire_delta) d = GeometryObjects.add_gwl_bend(centre=[0.5*self.length, 0, self.height], bend_radius=self.bend_radius, tube_radius=0.5*self.wire_diametre, name='GWL_wire3_bend2', angle_start_deg=90, angle_end_deg=0, cross_section_r0=self.cross_section_r0, cross_section_delta_r=self.cross_section_delta_r, cross_section_delta_theta=self.cross_section_delta_theta, longitudinal_delta=self.bend_delta) e = GeometryObjects.add_gwl_cone(self, [0.5*self.length+self.bend_radius, 0, self.height], [0.5*self.length+self.bend_radius, 0, 0], name='GWL_wire4_Cone2', radius2=0.5*self.cone_diametre, radius1=0.5*self.wire_diametre, cross_section_r0=self.cross_section_r0, cross_section_delta_r=self.cross_section_delta_r, cross_section_delta_theta=self.cross_section_delta_theta, longitudinal_delta=self.cone_delta) blender_object_list.extend([a,b,c,d,e]) if blender_object_list: selectObjects(blender_object_list) bpy.ops.object.transform_apply(location=True, rotation=True, scale=True) bpy.ops.object.parent_to_empty() obj = bpy.context.active_object obj.matrix_world = Matrix.Rotation(radians(self.rotation), 4, 'Z') obj.location = self.location # for obj in blender_object_list: # # setOrigin(obj, [0,0,0]) # # obj.rotation_euler = (0,0,0) # Note that you need to use radians rather than angles here # obj.matrix_world = Matrix.Rotation(radians(self.rotation), 4, 'Z') # obj.location = self.location return
def add_photonic_torus(self, context): blender_object_list = [] if self.show_design: b = GeometryObjects.add_bend(centre=[0, 0, 0], bend_radius=self.bend_radius, tube_radius=0.5 * self.wire_diametre, name='bend_design', angle_start_deg=self.angle_start_deg, angle_end_deg=self.angle_end_deg) blender_object_list.extend([b]) if self.show_gwl: b = GeometryObjects.add_gwl_bend( centre=[0, 0, 0], bend_radius=self.bend_radius, tube_radius=0.5 * self.wire_diametre, name='bend_GWL', angle_start_deg=self.angle_start_deg, angle_end_deg=self.angle_end_deg, cross_section_r0=self.cross_section_r0, cross_section_delta_r=self.cross_section_delta_r, cross_section_delta_theta=self.cross_section_delta_theta, longitudinal_delta=self.bend_delta) blender_object_list.extend([b]) if blender_object_list: selectObjects(blender_object_list) bpy.ops.object.transform_apply(location=True, rotation=True, scale=True) bpy.ops.object.parent_to_empty() obj = bpy.context.active_object obj.matrix_world = Matrix.Rotation(radians(self.rotation), 4, 'Z') obj.location = self.location return
def createBlenderObject(self, blender_operator, context): import bpy from blender_scripts.modules.GeometryObjects import add_cylinder, add_tetra, add_block from blender_scripts.modules.blender_utilities import selectObjects cursor_location3 = numpy.array(bpy.context.scene.cursor_location) bpy.ops.mesh.primitive_cylinder_add(radius=0.5 * self.disk_diametro, depth=self.disk_height) obj_disk = bpy.context.active_object obj_disk.name = 'CBD.disk' obj_wall_top = add_block( blender_operator, location3=numpy.array([0, 0.5 * self.getDiskDiametro(), 0]), size3=[ self.getDiskDiametro() + 2 * self.getWallLengthExtra(), self.getWallWidth(), self.getDiskHeight() + 2 * self.getWallHeightExtra() ], name='CBD.wall_top') obj_wall_top.parent = obj_disk obj_wall_bottom = add_block( blender_operator, location3=-numpy.array([0, 0.5 * self.getDiskDiametro(), 0]), size3=[ self.getDiskDiametro() + 2 * self.getWallLengthExtra(), self.getWallWidth(), self.getDiskHeight() + 2 * self.getWallHeightExtra() ], name='CBD.wall_bottom') obj_wall_bottom.parent = obj_disk obj_hole = add_block(blender_operator, location3=cursor_location3, size3=[ self.getHoleWidth(), self.getHoleLength(), 2 * self.getDiskHeight() ], name='CBD.hole') #obj_hole.parent = obj_disk bool_mod = obj_disk.modifiers.new('CBD.hole-modifier', 'BOOLEAN') bool_mod.operation = 'DIFFERENCE' bool_mod.object = obj_hole #obj_hole.hide = True selectObjects([obj_disk], active_object=obj_disk, context=bpy.context) bpy.ops.object.modifier_apply(modifier=bool_mod.name, apply_as='DATA') selectObjects([obj_hole], active_object=obj_hole, context=bpy.context) bpy.ops.object.delete() selectObjects([obj_disk], active_object=obj_disk, context=bpy.context) return (obj_disk)
def execute(self, context): # .. todo:: Support rotation as usual in object addons? # crystal axes e1 = [1,0,0] e2 = [0,1,0] e3 = [0,0,1] if self.cell_type == 'RCD': # .. todo:: set to cursor location (check how addCube & co initialize it -> It is set when object_data_add(context, mesh, operator=self) is called, which means ideally a mesh should be created and then passed to that function. It should take care of rotation&co too.) ## get cursor location for placement #cursor_location3 = numpy.array(bpy.context.scene.cursor_location) #self.setLocation(cursor_location3) location = Vector(self.location) obj_list = [] if self.shift_cell: obj_list.extend( add_tetra(self, location=location+self.size*Vector([3/4, 1/4, 1/4]), size=self.size/2, name='Tetra', cylinder_radius=self.radius) ) obj_list.extend( add_tetra(self, location=location+self.size*Vector([1/4, 3/4, 1/4]), size=self.size/2, name='Tetra', cylinder_radius=self.radius) ) obj_list.extend( add_tetra(self, location=location+self.size*Vector([1/4, 1/4, 3/4]), size=self.size/2, name='Tetra', cylinder_radius=self.radius) ) obj_list.extend( add_tetra(self, location=location+self.size*Vector([3/4, 3/4, 3/4]), size=self.size/2, name='Tetra', cylinder_radius=self.radius) ) else: obj_list.extend( add_tetra(self, location=location+self.size*Vector([1/4, 1/4, 1/4]), size=self.size/2, name='Tetra', cylinder_radius=self.radius) ) obj_list.extend( add_tetra(self, location=location+self.size*Vector([3/4, 3/4, 1/4]), size=self.size/2, name='Tetra', cylinder_radius=self.radius) ) obj_list.extend( add_tetra(self, location=location+self.size*Vector([3/4, 1/4, 3/4]), size=self.size/2, name='Tetra', cylinder_radius=self.radius) ) obj_list.extend( add_tetra(self, location=location+self.size*Vector([1/4, 3/4, 3/4]), size=self.size/2, name='Tetra', cylinder_radius=self.radius) ) common_mesh = obj_list[0].data for obj in obj_list[1:]: obj.data = common_mesh selectObjects(obj_list) bpy.ops.object.join() obj_blender = context.active_object obj_blender.name='RCD' setOrigin(obj_blender, self.location) bpy.ops.object.transform_apply(location=False, rotation=True, scale=False) e1 = self.size*Vector([1,0,0]) e2 = self.size*Vector([0,1,0]) e3 = self.size*Vector([0,0,1]) elif self.cell_type == 'RCD111_inverse': if self.shift_cell: STLfile = os.path.join(pathlib.Path.home(), 'Development/script_inception_public/src/blender_scripts/STL-files/RCD111_inverse_shifted_centred.stl') else: STLfile = os.path.join(pathlib.Path.home(), 'Development/script_inception_public/src/blender_scripts/STL-files/RCD111_inverse.stl') objName = bpy.path.display_name(os.path.basename(STLfile)) tris, tri_nors, pts = stl_utils.read_stl(STLfile) tri_nors = None axis_forward='Y' axis_up='Z' global_scale = 1 global_matrix = axis_conversion(from_forward=axis_forward, from_up=axis_up).to_4x4() * Matrix.Scale(global_scale, 4) print(global_matrix) blender_utils.create_and_link_mesh(objName, tris, tri_nors, pts, global_matrix) obj_blender = context.active_object # get cursor location for placement obj_blender.location = numpy.array(bpy.context.scene.cursor_location) obj_bfdtd = bfdtd.RCD.RCD_HexagonalLattice() obj_bfdtd.setOuterRadius(self.radius) obj_bfdtd.setCubicUnitCellSize(self.size) obj_bfdtd.setShifted(self.shift_cell) obj_bfdtd.setUnitCellType(2) e1, e2, e3 = obj_bfdtd.getLatticeVectors() else: if 'RCD111' in self.cell_type: obj_bfdtd = bfdtd.RCD.RCD_HexagonalLattice() else: obj_bfdtd = bfdtd.RCD.FRD_HexagonalLattice() obj_bfdtd.setOuterRadius(self.radius) obj_bfdtd.setCubicUnitCellSize(self.size) obj_bfdtd.setShifted(self.shift_cell) if 'v1' in self.cell_type: obj_bfdtd.setUnitCellType(1) else: obj_bfdtd.setUnitCellType(2) if self.RCD111_v2_advanced: obj_bfdtd.fillBox(self.RCD111_v2_location, self.RCD111_v2_size) # obj_bfdtd.fillBox([self.RCD111_v2_Nx, self.RCD111_v2_Ny, self.RCD111_v2_Nz], [self.RCD111_v2_Nx, self.RCD111_v2_Ny, self.RCD111_v2_Nz]) # obj_bfdtd.createRectangularArraySymmetrical(self.RCD111_v2_Nx, self.RCD111_v2_Ny, self.RCD111_v2_Nz) add_block(self, location3 = self.RCD111_v2_location, size3 = self.RCD111_v2_size, name='box_to_fill', wiremode=True) obj_blender = obj_bfdtd.createBlenderObject(self, context) e1, e2, e3 = obj_bfdtd.getLatticeVectors() obj_blender.name = self.cell_type if self.create_array: add_array_modifier(obj_blender, 'array-modifier-X', self.array_size_X, e1) add_array_modifier(obj_blender, 'array-modifier-Y', self.array_size_Y, e2) add_array_modifier(obj_blender, 'array-modifier-Z', self.array_size_Z, e3) # add unit-cell bounding box if self.add_unit_cell_BB: obj_lattice_cell = add_lattice_cell(self, e1, e2, e3, name='lattice_cell', shift_origin=self.shift_origin, wiremode=True) selectObjects([obj_blender, obj_lattice_cell], active_object=obj_lattice_cell, context = context) bpy.ops.object.parent_set(type='OBJECT', keep_transform=False) return {'FINISHED'}
def execute(self): print("running read_mpb...") filepath_basename = os.path.basename(self.filepath) with open(self.filepath) as infile: MPB_data_list = parse_MPB(infile) for idx, MPB_data_object in enumerate(MPB_data_list): print('=== dataset {} ==='.format(idx)) name = 'k-points-{}-{}'.format(filepath_basename, idx) # add lattice+reciprocal lattice basis vectors+cells (a0,a1,a2) = MPB_data_object.getLatticeVectors() (b0,b1,b2) = MPB_data_object.getReciprocalLatticeVectors() add_lattice_objects(self, a0, a1, a2, b0, b1, b2, name = name+'-lattice_objects', cone_length=self.cone_length, cone_radius=self.cone_radius, cylinder_radius=self.cylinder_radius) # add k-point path and sphere following it L = MPB_data_object.get_kpoints_in_cartesian_coordinates() if len(L)>0: for i in L: print(i) mesh = bpy.data.meshes.new(name) bm = bmesh.new() for v_co in L: bm.verts.new(v_co) bm.verts.ensure_lookup_table() for i in range(len(L)-1): bm.edges.new([bm.verts[i], bm.verts[i+1]]) bm.to_mesh(mesh) mesh.update() object_data_add(self.context, mesh, operator=self.operator) bpy.ops.object.convert(target='CURVE') k_points_path_object = self.context.active_object k_points_path_object.name = name+'-path' print('Adding animation...') k_points_path_object.data.use_path = True scene = self.context.scene k_points_path_object.data.path_duration = scene.frame_end - scene.frame_start bpy.ops.mesh.primitive_uv_sphere_add() S = self.context.active_object S.name = name+'-sphere' L = numpy.power(MPB_data_object.getReciprocalCellVolume(), 1/3) S.scale = 3*[L/20] # add a constraint to it constraint = S.constraints.new('FOLLOW_PATH') constraint.target = k_points_path_object #bpy.ops.object.constraint_add(type='FOLLOW_PATH') #C = S.constraints[-1] #C.target = k_points_path_object #selectObjects([S], active_object=S, context=self.context) #bpy.ops.constraint.followpath_path_animate(constraint="Follow Path", owner='OBJECT') override = {'constraint':constraint} bpy.ops.constraint.followpath_path_animate(override,constraint='Follow Path') selectObjects([k_points_path_object], active_object=k_points_path_object, context=self.context) else: print('no k-points found') print('FINISHED') return {'FINISHED'}
def importBristolFDTD_single_file(self, filename, filename_idx=None, prefix_zfill=0): ''' Import BristolFDTD geometry from .in,.geo or .inp and create corresponding structure in Blender. This function imports a single file. To import multiple files, use :py:func:`importBristolFDTD` ''' start_time = time.time() print('----->Importing bristol FDTD geometry: ' + filename) print(self.PrintSelf('\t')) #Blender.Window.WaitCursor(1); # save import path # Blender.Set('tempdir',os.path.dirname(filename)); #FILE = open(, 'w'); #pickle.dump(, FILE); #FILE.close(); with open(cfgfile, 'wb') as f: # Pickle the 'data' dictionary using the highest protocol available. pickle.dump(filename, f, pickle.HIGHEST_PROTOCOL) # create structured_entries structured_entries = readBristolFDTD(filename) ################## # GROUP SETUP ################## # create group corresponding to this file # deselect all bpy.ops.object.select_all(action='DESELECT') # Truncated to 63 characters because that seems to be the maximum string length Blender accepts for group names. # (allows keeping part of the path for better identification if multiple files use the same basename) if filename_idx is None: group_name = filename[-63:] else: group_name_prefix = str(filename_idx).zfill(prefix_zfill) + '-' group_name = group_name_prefix + filename[-( 63 - len(group_name_prefix)):] #if group_name in bpy.data.groups: #raise Exception('group already exists: {}\n{}'.format(group_name, bpy.data.groups)) # older version #bpy.ops.group.create(name=group_name) # This version ensures that a new group name is created if necessary and stores the new group in *current_group*. # current_group = bpy.data.groups.new(name=group_name) # blender<2.8 # group_name = current_group.name # blender<2.8 collection_current_file = blender_utilities.make_collection( group_name) # blender>=2.8 collection_meshes = blender_utilities.make_collection('meshes') collection_boxes = blender_utilities.make_collection('boxes') collection_excitations = blender_utilities.make_collection( 'excitations') collection_frequencySnapshots = blender_utilities.make_collection( 'frequencySnapshots') collection_timeSnapshots = blender_utilities.make_collection( 'timeSnapshots') collection_epsilonSnapshots = blender_utilities.make_collection( 'epsilonSnapshots') collection_spheres = blender_utilities.make_collection('spheres') collection_distorted = blender_utilities.make_collection('distorted') collection_blocks = blender_utilities.make_collection('blocks') collection_cylinders = blender_utilities.make_collection('cylinders') collection_probes = blender_utilities.make_collection('probes') ################## # we create an instance of the FDTDGeometryObjects class, which allows adding objects to the scene with shared materials (TODO: maybe find a better system?) FDTDGeometryObjects_obj = FDTDGeometryObjects() # Blender.Window.RedrawAll(); # This must be called before any SetActiveLayer calls! layerManager = LayerManagerObjects() # Box #Blender.Window.SetActiveLayer(1<<layerManager.DefaultLayers.index('box')); obj = FDTDGeometryObjects_obj.GEObox( structured_entries.box.name, Vector(structured_entries.box.lower), Vector(structured_entries.box.upper)) blender_utilities.setActiveObject(obj) # if bpy.app.version >= (2, 8, 0): # bpy.context.view_layer.objects.active = obj # else: # bpy.context.scene.objects.active = obj # if bpy.app.version >= (2, 8, 0): blender_utilities.addToCollection(obj, group_name, removeFromOthers=False) blender_utilities.addToCollection(obj, 'boxes', removeFromOthers=False) # blender_utilities.addToCollection(obj, 'cylinders', removeFromOthers=False) # blender_utilities.addToCollection(obj, 'cylinders', removeFromOthers=False) # blender_utilities.addToCollection(obj, 'probes', removeFromOthers=False) # blender_utilities.addToCollection(obj, collection_probes, removeFromOthers=False) # blender_utilities.addToCollection(obj, collection_spheres, removeFromOthers=True) # else: # bpy.ops.object.group_link(group=group_name) # bpy.ops.object.group_link(group='boxes') # mesh #Blender.Window.SetActiveLayer(1<<layerManager.DefaultLayers.index('mesh')); #FDTDGeometryObjects_obj.GEOmesh('mesh', False, structured_entries.delta_X_vector,structured_entries.delta_Y_vector,structured_entries.delta_Z_vector); #Blender.Window.SetActiveLayer(1<<layerManager.DefaultLayers.index('mesh')); obj = FDTDGeometryObjects_obj.GEOmesh( 'mesh', False, structured_entries.mesh.getXmeshDelta(), structured_entries.mesh.getYmeshDelta(), structured_entries.mesh.getZmeshDelta()) blender_utilities.setActiveObject(obj, context=bpy.context) blender_utilities.addToCollection(obj, group_name, removeFromOthers=False) blender_utilities.addToCollection(obj, 'meshes', removeFromOthers=False) # Time_snapshot (time or EPS) Ntsnaps = 0 for time_snapshot in structured_entries.time_snapshot_list: Ntsnaps += 1 snap_plane = time_snapshot.getPlaneLetter() probe_ident = structured_entries.flag.id_string.replace('\"', '') snap_time_number = 1 TimeSnapshotFileName, alphaID, pair = brisFDTD_ID_info.numID_to_alphaID_TimeSnapshot( Ntsnaps, snap_plane, probe_ident, snap_time_number) if time_snapshot.eps == 0: #Blender.Window.SetActiveLayer(1<<layerManager.DefaultLayers.index('time_snapshots_'+planeNumberName(time_snapshot.plane)[1])) obj = FDTDGeometryObjects_obj.GEOtime_snapshot( time_snapshot.name, time_snapshot.getPlaneLetter(), time_snapshot.P1, time_snapshot.P2) blender_utilities.setActiveObject(obj, context=bpy.context) blender_utilities.addToCollection(obj, group_name, removeFromOthers=False) blender_utilities.addToCollection(obj, 'timeSnapshots', removeFromOthers=False) else: #Blender.Window.SetActiveLayer(1<<layerManager.DefaultLayers.index('eps_snapshots_'+planeNumberName(time_snapshot.plane)[1])) obj = FDTDGeometryObjects_obj.GEOeps_snapshot( TimeSnapshotFileName, time_snapshot.getPlaneLetter(), time_snapshot.P1, time_snapshot.P2) #obj = FDTDGeometryObjects_obj.GEOeps_snapshot(time_snapshot.name, time_snapshot.plane, time_snapshot.P1, time_snapshot.P2) blender_utilities.setActiveObject(obj, context=bpy.context) blender_utilities.addToCollection(obj, group_name, removeFromOthers=False) blender_utilities.addToCollection(obj, 'epsilonSnapshots', removeFromOthers=False) # Frequency_snapshot # TODO: Finally get a correct system for filenames/comment names/etc implemented. getfilename() or something... Nfsnaps = 0 for frequency_snapshot in structured_entries.frequency_snapshot_list: #Blender.Window.SetActiveLayer(1<<layerManager.DefaultLayers.index('frequency_snapshots_'+planeNumberName(frequency_snapshot.plane)[1])); Nfsnaps += 1 snap_plane = frequency_snapshot.getPlaneLetter() probe_ident = structured_entries.flag.id_string.replace('\"', '') snap_time_number = 0 FrequencySnapshotFileName, alphaID, pair = brisFDTD_ID_info.numID_to_alphaID_FrequencySnapshot( Nfsnaps, snap_plane, probe_ident, snap_time_number, pre_2008_BFDTD_version=self.pre_2008_BFDTD_version) obj = FDTDGeometryObjects_obj.GEOfrequency_snapshot( FrequencySnapshotFileName, frequency_snapshot.getPlaneLetter(), frequency_snapshot.P1, frequency_snapshot.P2) #obj = FDTDGeometryObjects_obj.GEOfrequency_snapshot(frequency_snapshot.name, frequency_snapshot.plane, frequency_snapshot.P1, frequency_snapshot.P2) blender_utilities.setActiveObject(obj, context=bpy.context) blender_utilities.addToCollection(obj, group_name, removeFromOthers=False) blender_utilities.addToCollection(obj, 'frequencySnapshots', removeFromOthers=False) # Excitation #Blender.Window.SetActiveLayer(1<<layerManager.DefaultLayers.index('excitations')); for excitation in structured_entries.excitation_list: #Blender.Window.SetActiveLayer(1<<layerManager.DefaultLayers.index('excitations')); #print(Blender.Window.GetActiveLayer()) #print(excitation) obj = FDTDGeometryObjects_obj.GEOexcitation(excitation) blender_utilities.setActiveObject(obj, context=bpy.context) blender_utilities.addToCollection(obj, group_name, removeFromOthers=False) blender_utilities.addToCollection(obj, 'excitations', removeFromOthers=False) #FDTDGeometryObjects_obj.GEOexcitation(excitation.name, Vector(excitation.P1), Vector(excitation.P2)); # Probe #Blender.Window.SetActiveLayer(1<<layerManager.DefaultLayers.index('probes')); Nprobes = 0 for probe in structured_entries.probe_list: # print('probe = ',Vector(probe.position)) Nprobes += 1 ProbeFileName = 'p' + str( Nprobes).zfill(2) + structured_entries.flag.id_string.replace( '\"', '') + '.prn' #FDTDGeometryObjects_obj.GEOprobe(probe.name+' ('+ProbeFileName+')', Vector(probe.position)); obj = FDTDGeometryObjects_obj.GEOprobe(ProbeFileName, Vector(probe.position)) blender_utilities.setActiveObject(obj, context=bpy.context) blender_utilities.addToCollection(obj, group_name, removeFromOthers=False) blender_utilities.addToCollection(obj, 'probes', removeFromOthers=False) ################################################################## ### geometry loading if not self.no_geometry: if self.create_vertex_mesh: # just create a mesh of vertices representing object locations # .. todo:: just as with the lines for cylinders, this should be an option for spheres (i.e. different placeholders for each type of object) (also create different vertex mesh for each "material"/.geo file) L = structured_entries.getGeometryObjects() N = len(L) print('N(objects) = {}'.format(N)) verts = N * [Vector((0, 0, 0))] for idx, obj in enumerate(L): verts[idx] = Vector(obj.getLocation()) edges = [] faces = [] mesh = bpy.data.meshes.new(name="Object positions") mesh.from_pydata(verts, edges, faces) #object_data_add(bpy.context, mesh, operator=self) object_data_add(bpy.context, mesh) else: # Sphere #Blender.Window.SetActiveLayer(1<<layerManager.DefaultLayers.index('spheres')); for sphere in structured_entries.sphere_list: # variables centro = Vector(sphere.getLocation()) # initialise rotation_matrix rotation_matrix = Matrix() rotation_matrix.identity() # scale object #Sx=Blender.Mathutils.ScaleMatrix(abs(2*sphere.outer_radius),4,Blender.Mathutils.Vector(1,0,0)) #Sy=Blender.Mathutils.ScaleMatrix(abs(2*sphere.outer_radius),4,Blender.Mathutils.Vector(0,1,0)) #Sz=Blender.Mathutils.ScaleMatrix(abs(2*sphere.outer_radius),4,Blender.Mathutils.Vector(0,0,1)) #rotation_matrix *= Sx*Sy*Sz; # position object #T = Blender.Mathutils.TranslationMatrix(centro) #rotation_matrix *= T; # add rotations #for r in sphere.rotation_list: #rotation_matrix *= rotationMatrix(r.axis_point, r.axis_direction, r.angle_degrees); # create object obj = FDTDGeometryObjects_obj.GEOsphere( sphere.name, sphere.getLocation(), sphere.outer_radius, sphere.inner_radius, sphere.permittivity, sphere.conductivity) #FDTDGeometryObjects_obj.GEOsphere_matrix(sphere.name, rotation_matrix, sphere.outer_radius, sphere.inner_radius, sphere.permittivity, sphere.conductivity); #FDTDGeometryObjects_obj.GEOblock_matrix(sphere.name, rotation_matrix, sphere.permittivity, sphere.conductivity); blender_utilities.setActiveObject(obj, context=bpy.context) blender_utilities.addToCollection(obj, group_name, removeFromOthers=False) blender_utilities.addToCollection(obj, 'spheres', removeFromOthers=False) if self.import_blocks: # Block #Blender.Window.SetActiveLayer(1<<layerManager.DefaultLayers.index('blocks')) for block in structured_entries.block_list: # variables lower = Vector(block.getLowerAbsolute()) upper = Vector(block.getUpperAbsolute()) pos = 0.5 * (lower + upper) diag = 0.5 * (upper - lower) # initialise rotation_matrix rotation_matrix = Matrix() rotation_matrix.identity() # add rotations for r in block.rotation_list: rotation_matrix = rotationMatrix( r.axis_point, r.axis_direction, r.angle_degrees) * rotation_matrix # position object T = Matrix.Translation(pos) if bpy.app.version >= (2, 8, 0): rotation_matrix @= T else: rotation_matrix *= T ## scale object Sx = Matrix.Scale(abs(diag[0]), 4, Vector((1, 0, 0))) Sy = Matrix.Scale(abs(diag[1]), 4, Vector((0, 1, 0))) Sz = Matrix.Scale(abs(diag[2]), 4, Vector((0, 0, 1))) if bpy.app.version >= (2, 8, 0): rotation_matrix @= Sx @ Sy @ Sz else: rotation_matrix *= Sx * Sy * Sz # create object obj = FDTDGeometryObjects_obj.GEOblock_matrix( block.name, rotation_matrix, block.permittivity, block.conductivity) #FDTDGeometryObjects_obj.GEOblock(block.name, block.lower, block.upper, block.permittivity, block.conductivity) blender_utilities.setActiveObject(obj, context=bpy.context) blender_utilities.addToCollection( obj, group_name, removeFromOthers=False) blender_utilities.addToCollection( obj, 'blocks', removeFromOthers=False) # Distorted for distorted in structured_entries.distorted_list: # create object #print(distorted) obj = FDTDGeometryObjects_obj.GEOdistorted(distorted) blender_utilities.setActiveObject(obj, context=bpy.context) blender_utilities.addToCollection(obj, group_name, removeFromOthers=False) #bpy.ops.object.group_link(group=type(distorted).__name__) blender_utilities.addToCollection(obj, 'distorted', removeFromOthers=False) ######################### # Cylinders if self.import_cylinders: if self.cylinder_to_line_mesh: createLineMeshFromCylinders(structured_entries) else: ## progress indicator does not work when running from CLI if self.GUI_loaded: bpy.context.window_manager.progress_begin(0, 100) #Blender.Window.SetActiveLayer(1<<layerManager.DefaultLayers.index('cylinders')); if self.restrict_import_volume: if self.volume_specification_style == 'relative': import_volume_xmin = self.xmin * structured_entries.getSize( )[0] import_volume_xmax = self.xmax * structured_entries.getSize( )[0] import_volume_ymin = self.ymin * structured_entries.getSize( )[1] import_volume_ymax = self.ymax * structured_entries.getSize( )[1] import_volume_zmin = self.zmin * structured_entries.getSize( )[2] import_volume_zmax = self.zmax * structured_entries.getSize( )[2] else: import_volume_xmin = self.xmin import_volume_xmax = self.xmax import_volume_ymin = self.ymin import_volume_ymax = self.ymax import_volume_zmin = self.zmin import_volume_zmax = self.zmax truncated_cylinder_list = truncateGeoList( structured_entries.cylinder_list, import_volume_xmin, import_volume_xmax, import_volume_ymin, import_volume_ymax, import_volume_zmin, import_volume_zmax) if self.verbosity > 0: print(self) print( 'len(structured_entries.cylinder_list) = {}' .format( len(structured_entries.cylinder_list))) print( 'len(truncated_cylinder_list) = {}'.format( len(truncated_cylinder_list))) else: truncated_cylinder_list = structured_entries.cylinder_list if self.use_Nmax_objects: truncated_cylinder_list = truncated_cylinder_list[: self . Nmax_objects] # hack to create a lot of objects quickly using duplication. # .. todo:: replace/improve + implement for other objects # .. todo:: one mesh per material & .geo file, rather than multiple objects, while respecting appearance order, i.e. group sequences of same material objects into a single mesh. # cf: # https://blender.stackexchange.com/questions/7358/python-performance-with-blender-operators # https://blender.stackexchange.com/questions/39721/how-can-i-create-many-objects-quickly N = len(truncated_cylinder_list) if self.verbosity > 0: print( 'len(truncated_cylinder_list) = {}'.format(N)) if N > 0: N_added_max = 500 N_added = min(N_added_max, N) N_duplications = (N // N_added) - 1 N_remainder = N % N_added print('N', N) print('N_added_max', N_added_max) print('N_added', N_added) print('N_duplications', N_duplications) print('N_remainder', N_remainder) print('total = ' + str(N_added + N_duplications * N_added + N_remainder)) Nfill = len(str(N)) cyl_list = N * [0] # add all cylinders print('Adding all ' + str(N) + ' cylinders...') # normal add if self.GUI_loaded: bpy.context.window_manager.progress_update(0) for i in range(N_added + N_remainder): bpy.ops.mesh.primitive_cylinder_add( location=Vector([0, 0, 0]), rotation=(radians(-90), 0, 0)) bpy.ops.object.transform_apply( rotation=True ) # aligning cylinder to Y axis directly and applying rotation, to follow BFDTD standard cylinder orientation. cyl_list[i] = bpy.context.object if self.GUI_loaded: bpy.context.window_manager.progress_update( i / (N_added + N_remainder)) ## select items to duplicate selectObjects(cyl_list[0:N_added]) ## duplicate if self.GUI_loaded: bpy.context.window_manager.progress_update(0) for i in range(N_duplications): #'cyl.''{:0>-{Nfill}}'.format(i,Nfill=Nfill) bpy.ops.object.duplicate_move_linked() start_idx = N_added + N_remainder + i * N_added end_idx = start_idx + N_added print((start_idx, end_idx)) cyl_list[ start_idx: end_idx] = bpy.context.selected_objects if self.GUI_loaded: bpy.context.window_manager.progress_update( i / N_duplications) # set location/rotation/scale of cylinders print('Setting location/rotation/scale of all ' + str(N) + ' cylinders...') #for i, cylinder in enumerate(truncated_cylinder_list): #obj = cyl_list[i] if self.GUI_loaded: bpy.context.window_manager.progress_update(0) for i, cylinder in enumerate( truncated_cylinder_list): #for cylinder in truncated_cylinder_list: # initialise rotation_matrix rotation_matrix = Matrix() rotation_matrix.identity() scale = [ cylinder.outer_radius, cylinder.outer_radius, 0.5 * cylinder.height ] Sx = Matrix.Scale(scale[0], 4, [1, 0, 0]) Sy = Matrix.Scale(scale[1], 4, [0, 1, 0]) Sz = Matrix.Scale(scale[2], 4, [0, 0, 1]) #rotation_matrix *= Sx*Sy*Sz; # add rotations # TODO: Check it works correctly... for r in cylinder.rotation_list: rotation_matrix *= rotationMatrix( r.axis_point, r.axis_direction, r.angle_degrees) * rotation_matrix #r = cylinder.rotation_list[0] # position object T = Matrix.Translation( Vector([ cylinder.location[0], cylinder.location[1], cylinder.location[2] ])) rotation_matrix *= T # because FDTD cylinders are aligned with the Y axis by default #rotation_matrix *= rotationMatrix(Vector([0,0,0]), Vector([1,0,0]), -90) # create object #obj = FDTDGeometryObjects_obj.GEOcylinder_matrix(cylinder.name, rotation_matrix, cylinder.inner_radius, cylinder.outer_radius, cylinder.height, cylinder.permittivity, cylinder.conductivity) #obj = cyl_list[i] #GEOcylinder_matrix2(self, obj, name, rotation_matrix, inner_radius, outer_radius, height, permittivity, conductivity) obj = FDTDGeometryObjects_obj.GEOcylinder_matrix2( cyl_list[i], cylinder.name, rotation_matrix, cylinder.inner_radius, cylinder.outer_radius, cylinder.height, cylinder.permittivity, cylinder.conductivity) #obj = FDTDGeometryObjects_obj.GEOcylinder_matrix(cylinder.name, rotation_matrix, cylinder.inner_radius, cylinder.outer_radius, cylinder.height, cylinder.permittivity, cylinder.conductivity) #obj = FDTDGeometryObjects_obj.GEOcylinder_passedObj(cyl_list[i], cylinder.name, r.axis_point, r.axis_direction, r.angle_degrees, inner_radius, outer_radius, height, permittivity, conductivity) blender_utilities.setActiveObject( obj, context=bpy.context) blender_utilities.addToCollection( obj, group_name, removeFromOthers=False) blender_utilities.addToCollection( obj, 'cylinders', removeFromOthers=False) #angle_X = numpy.deg2rad(-90) #angle_X = -0.5*numpy.pi #angle_Y = 0 #angle_Z = 0 #FDTDGeometryObjects_obj.GEOcylinder(cylinder.name, cylinder.centro, cylinder.inner_radius, cylinder.outer_radius, cylinder.height, cylinder.permittivity, cylinder.conductivity, angle_X, angle_Y, angle_Z) if self.GUI_loaded: bpy.context.window_manager.progress_update( i / N) else: print('progress = {}'.format(i / N)) if self.GUI_loaded: bpy.context.window_manager.progress_end() ######################### if N > 0: end ################################################################## ######################### # Not yet implemented: # Flag # structured_entries.flag; # Boundaries # structured_entries.boundaries; ######################### # TODO: Save the layer settings somewhere for reuse #scene = Blender.Scene.GetCurrent() scene = bpy.context.scene layersOn = [ layerManager.DefaultLayers.index('spheres') + 1, layerManager.DefaultLayers.index('blocks') + 1, layerManager.DefaultLayers.index('cylinders') + 1 ] print(layersOn) #layersOn = [1,2,3] #print layersOn #Blender.Scene.GetCurrent().setLayers(layersOn) #scene.update(0); #Blender.Window.RedrawAll(); #Blender.Window.WaitCursor(0); #Blender.Scene.GetCurrent().setLayers([1,3,4,5,6,7,8,9,10]); print('...done') #print Blender.Get('scriptsdir') #Blender.Run(Blender.Get('scriptsdir')+'/layer_manager.py') #layer_manager_objects = layer_manager.LayerManagerObjects() #Draw.Register(layer_manager_objects.gui, layer_manager_objects.event, layer_manager_objects.button_event) #print '==========================' #print Blender.Window.GetScreens() #print Blender.Window.GetAreaID() #print Blender.Window.GetAreaSize() #print Blender.Text.Get() #print '==========================' #~ Blender.Window.FileSelector(algosomething, "Import Bristol FDTD file..."); #~ Blender.Run('~/.blender/scripts/bfdtd_import.py') print('Elapsed time: ', round(time.time() - start_time, 4), 'seconds')
def execute(self): print("running read_meep...") filepath_basename = os.path.basename(self.filepath) (root, ext) = os.path.splitext(self.filepath) if ext == '.ctl': (MEEP_data_list, geo_list) = MEEP.MEEP_parser.getInfoFromCTL(self.filepath) else: with open(self.filepath) as infile: MEEP_data_list = MEEP.MEEP_parser.parse_MEEP(infile) geo_list = MEEP.MEEP_parser.parseGeometry(infile) for idx, MEEP_data_object in enumerate(MEEP_data_list): print('=== dataset {} ==='.format(idx)) name = 'k-points-{}-{}'.format(filepath_basename, idx) # add lattice+reciprocal lattice basis vectors+cells (a0, a1, a2) = MEEP_data_object.getLatticeVectors() (b0, b1, b2) = MEEP_data_object.getReciprocalLatticeVectors() # add_lattice_objects(self, a0, a1, a2, b0, b1, b2, name = name+'-lattice_objects', # cone_length=self.cone_length, # cone_radius=self.cone_radius, # cylinder_radius=self.cylinder_radius) obj_lat_shifted_cell = add_lattice_cell( self, a0, a1, a2, name='lattice_cell-shifted', shift_origin=True, wiremode=True) # add k-point path and sphere following it L = MEEP_data_object.get_kpoints_in_cartesian_coordinates() if len(L) > 0: for i in L: print(i) mesh = bpy.data.meshes.new(name) bm = bmesh.new() for v_co in L: bm.verts.new(v_co) bm.verts.ensure_lookup_table() for i in range(len(L) - 1): bm.edges.new([bm.verts[i], bm.verts[i + 1]]) bm.to_mesh(mesh) mesh.update() object_data_add(self.context, mesh, operator=self.operator) bpy.ops.object.convert(target='CURVE') k_points_path_object = self.context.active_object k_points_path_object.name = name + '-path' print('Adding animation...') k_points_path_object.data.use_path = True scene = self.context.scene k_points_path_object.data.path_duration = scene.frame_end - scene.frame_start bpy.ops.mesh.primitive_uv_sphere_add() S = self.context.active_object S.name = name + '-sphere' L = numpy.power(MEEP_data_object.getReciprocalCellVolume(), 1 / 3) S.scale = 3 * [L / 20] # add a constraint to it constraint = S.constraints.new('FOLLOW_PATH') constraint.target = k_points_path_object #bpy.ops.object.constraint_add(type='FOLLOW_PATH') #C = S.constraints[-1] #C.target = k_points_path_object #selectObjects([S], active_object=S, context=self.context) #bpy.ops.constraint.followpath_path_animate(constraint="Follow Path", owner='OBJECT') override = {'constraint': constraint} bpy.ops.constraint.followpath_path_animate( override, constraint='Follow Path') selectObjects([k_points_path_object], active_object=k_points_path_object, context=self.context) else: print('no k-points found') # we create an instance of the FDTDGeometryObjects class, which allows adding objects to the scene with shared materials (TODO: maybe find a better system?) FDTDGeometryObjects_obj = FDTDGeometryObjects.FDTDGeometryObjects() FDTDGeometryObjects_obj.addGeometryObjects(geo_list) print('FINISHED') return {'FINISHED'}