def vector_field_to_data(g_id, name, pv_arr, units): # format is [[[px, py, pz], [vx, vy, vx]], ...] # UNLESS only one element? # convert to webGL object if len(numpy.shape(pv_arr)) == 2: pv_arr = [pv_arr] v_data = new_geom_object() v_data.vectors.lengths = [] v_data.vectors.colors = [] v_max = 0. v_min = sys.float_info.max for i in range(len(pv_arr)): p = pv_arr[i][0] v = pv_arr[i][1] n = linalg.norm(v) v_max = max(v_max, n) v_min = min(v_min, n) nv = (numpy.array(v) / (n if n > 0 else 1.)).tolist() v_data.vectors.vertices.extend(p) v_data.vectors.directions.extend(nv) v_data.vectors.magnitudes.append(n) v_data.vectors.range = [v_min, v_max] v_data.vectors.units = units return PKDict(name=name + '.Field', id=g_id, data=[v_data], bounds=radia.ObjGeoLim(g_id))
def geom_to_data(self, name=None, divide=True): #TODO(mvk): if no color, get color from parent if any? g_id = self.get_geom(name) n = (name if name is not None else str(g_id)) + '.Geom' pd = PKDict(name=n, id=g_id, data=[]) d = rs_utils.to_pkdict(radia.ObjDrwVTK(g_id, 'Axes->No')) n_verts = len(d.polygons.vertices) c = radia.ObjCntStuf(g_id) l = len(c) if not divide or l == 0: pd.data = [d] else: d_arr = [] n_s_verts = 0 # for g in get_geom_tree(g_id): for g in c: # for fully recursive array # for g in get_all_geom(geom): s_d = rs_utils.to_pkdict(radia.ObjDrwVTK(g, 'Axes->No')) n_s_verts += len(s_d.polygons.vertices) d_arr.append(s_d) # if the number of vertices of the container is more than the total # across its elements, a symmetry or other "additive" transformation has # been applied and we cannot get at the individual elements if n_verts > n_s_verts: d_arr = [d] pd.data = d_arr pd.bounds = radia.ObjGeoLim(g_id) return pd
def check_segments(self, container): """Loop through all the objects in a container and evaluate the segmentation. Good shapes will have a magnetisation perpendicular to one of the faces. So find the normal of each face and evaluate the dot product with the magnetisation, both normalised to 1. The best have a max dot product of 1. Theoretical min is 1/sqrt(3) though most will be above 1/sqrt(2).""" shapes = rad.ObjCntStuf(container) xmin, xmax, ymin, ymax, zmin, zmax = rad.ObjGeoLim(container) print(f'Checking {len(shapes)} shapes in {container}, extent: x {xmin:.1f} to {xmax:.1f}, y {ymin:.1f} to {ymax:.1f}, z {zmin:.1f} to {zmax:.1f}') dot_products = {} for shape in shapes: sub_shapes = rad.ObjCntStuf(shape) if len(sub_shapes) > 0: # this shape is a container dot_products.update(self.check_segments(shape)) # recurse and update dict else: # it's an atomic shape mag = rad.ObjM(shape)[0] # returns [[mx, my, mz]], select the first element i.e. [mx, my, mz] norm = np.linalg.norm(mag) # normalise so total is 1 if norm == 0: continue mag = mag / norm # Have to parse the information from rad.UtiDmp, no other way of getting polyhedron faces! info = rad.UtiDmp(shape).replace('{', '[').replace('}', ']') # convert from Mathematica list format in_face_list = False # print(info) lines = info.split('\n') description = lines[0].split(': ') # print(description) object_type = description[-1] # print('Type is', object_type) if object_type == 'RecMag': # cuboid with axes parallel to x, y, z # simply find the largest component of normalised magnetisation - the closer to 1, the better dot_products[shape] = max(abs(mag)) elif object_type == 'Polyhedron': # need to loop over the faces product_list = [] for line in lines[1:]: if in_face_list: if '[' not in line: # reached the end of the face list break points = np.array(eval(line.rstrip(','))) normal = np.cross(points[1] - points[0], points[2] - points[0]) product_list.append(np.dot(normal / np.linalg.norm(normal), mag)) # normalise->unit vector elif 'Face Vertices' in line: in_face_list = True dot_products[shape] = max(product_list) # max seems to be a reasonable figure of merit return dot_products
def geom_to_data(g_id, name=None, divide=True): def _to_pkdict(d): if not isinstance(d, dict): return d rv = PKDict() for k, v in d.items(): rv[k] = _to_pkdict(v) return rv n = (name if name is not None else str(g_id)) + '.Geom' pd = PKDict(name=n, id=g_id, data=[]) d = _to_pkdict(radia.ObjDrwVTK(g_id, 'Axes->No')) d.update(_geom_bnds(g_id)) n_verts = len(d.polygons.vertices) c = radia.ObjCntStuf(g_id) l = len(c) if not divide or l == 0: d.id = g_id pd.data = [d] else: d_arr = [] n_s_verts = 0 # for g in get_geom_tree(g_id): for g in c: # for fully recursive array # for g in get_all_geom(geom): s_d = _to_pkdict(radia.ObjDrwVTK(g, 'Axes->No')) s_d.update(_geom_bnds(g)) n_s_verts += len(s_d.polygons.vertices) s_d.id = g d_arr.append(s_d) # if the number of vertices of the container is more than the total # across its elements, a symmetry or other "additive" transformation has # been applied and we cannot get at the individual elements if n_verts > n_s_verts: d.id = g_id d_arr = [d] pd.data = d_arr pd.bounds = radia.ObjGeoLim(g_id) return pd
def _geom_bnds(g_id): bnds = radia.ObjGeoLim(g_id) return PKDict( center=[0.5 * (bnds[i + 1] + bnds[i]) for i in range(3)], size=[abs(bnds[i + 1] - bnds[i]) for i in range(3)], )
#rad.ObjDrwOpenGL(magDpl) #mag01sbd = rad.ObjDivMag(mag01, [[2,0.5],[3,0.2],[4,0.1]], 'pln', [[1,0.4,0.1],[0.4,1,0.2],[0,0,1]], 'Frame->Lab') #mag01sbd = rad.ObjDivMag(mag01, [[2,0.5],[3,0.2],[4,0.1]], 'Frame->Lab') #rad.ObjDrwOpenGL(mag01sbd) #mag01sbd = rad.ObjDivMagPln(mag01, [[2,0.5],[3,0.2],[4,0.1]], [1,0.4,0.1], [0.4,1,0.2], [0,0,1], 'Frame->Lab') mag01sbd = rad.ObjDivMagPln(mag01, [[2,0.5],[3,0.2],[4,0.1]]) #rad.ObjDrwOpenGL(mag01sbd) #mag00sbd = rad.ObjDivMag(mag00, [[2,0.5],[3,0.2],[4,0.1]], 'cyl', [[2.5,4,0],[0,0,1],[8,0,0],3], 'Frame->Lab') #mag00sbd = rad.ObjDivMagCyl(mag00, [[2,0.5],[3,0.2],[4,0.1]], [2.5,4,0], [0,0,1], [8,0,0], 3, 'Frame->Lab') print('Volume of 3D object:', rad.ObjGeoVol(mag01sbd)) print('Geom. Limits of 3D object:', rad.ObjGeoLim(mag01sbd)) #rad.ObjDrwOpenGL(mag01) trf01 = rad.TrfPlSym([0,10,0], [0,1,0]) trf02 = rad.TrfRot([0,10,0], [0,0,1], 1.) trf03 = rad.TrfTrsl([30,10,0]) trf04 = rad.TrfInv() trf05 = rad.TrfCmbL(trf01, trf04) trf06 = rad.TrfCmbR(trf01, trf04) #rad.TrfMlt(mag01, trf03, 3) rad.TrfOrnt(mag01, trf06) #rad.ObjDrwOpenGL(mag01)