基于Numpy从数值属性推导正八面体各面缩写名称及关联属性的实现方案
基于Numpy从数值属性推导正八面体各面缩写名称及关联属性的实现方案
嘿,我来帮你搞定正八面体面名称和数值属性关联的问题,咱们一步步来捋清楚实现思路和代码:
一、建立符号元组与面名称的映射关系
首先明确规则:面名称的格式是[NS][WE][AP],对应三个轴的符号:
- 第一个字符(NS)对应Z轴:
N是Z正方向(+1),S是Z负方向(-1) - 第二个字符(WE)对应Y轴:
E是Y正方向(+1),W是Y负方向(-1) - 第三个字符(AP)对应X轴:
A是X正方向(+1),P是X负方向(-1)
先定义基础映射字典,再写转换函数:
import numpy as np # 轴符号与字母的基础映射 axis_sign_to_char = { 'z': {1: 'N', -1: 'S'}, 'y': {1: 'E', -1: 'W'}, 'x': {1: 'A', -1: 'P'} } # 字母到轴符号的反向映射 axis_char_to_sign = { 'z': {'N': 1, 'S': -1}, 'y': {'E': 1, 'W': -1}, 'x': {'A': 1, 'P': -1} } def sign_tuple_to_name(sign_tuple): """将(x_sign, y_sign, z_sign)元组转换为面名称(如NEA)""" x_s, y_s, z_s = sign_tuple return ( axis_sign_to_char['z'][z_s] + axis_sign_to_char['y'][y_s] + axis_sign_to_char['x'][x_s] ) def name_to_sign_tuple(name): """将面名称(如NEA)转换为(x_sign, y_sign, z_sign)元组""" z_char, y_char, x_char = name return ( axis_char_to_sign['x'][x_char], axis_char_to_sign['y'][y_char], axis_char_to_sign['z'][z_char] )
二、生成{符号元组: 面名称}的完整映射字典
用你原来生成符号组合的代码,遍历所有8种可能的符号元组,生成映射字典:
# 生成所有8种坐标符号组合(x, y, z) s = [-1, 1] sign_tuples = np.stack(np.meshgrid(s, s, s), axis=-1).reshape((-1, 3)).tolist() # 转换为整数元组(避免numpy浮点数的问题) sign_tuples = [tuple(int(s) for s in st) for st in sign_tuples] # 构建符号元组到面名称的字典 sign_to_name = {st: sign_tuple_to_name(st) for st in sign_tuples} # 打印验证一下 for st, name in sign_to_name.items(): print(f"符号元组{st} → 面名称{name}")
运行后你会看到每个符号组合对应的正确名称,比如(1,1,1)对应NEA,(-1,1,-1)对应SEP,完全符合你举的例子~
三、关联旋转矩阵与面名称
你提到旋转矩阵的最后一行包含坐标符号信息,我们可以提取最后一行的符号,然后和上面的映射字典关联:
# 你的旋转矩阵定义(保留原代码) z_rotate = ( ((-1, 0, 1), ( 1, -2, 1), ( 1, 1, 1)), # NEA (( 0, -1, -1), (-2, 1, -1), ( 1, 1, -1)), # SEA (( 0, -1, 1), ( 2, 1, 1), (-1, 1, 1)), # NEP (( 1, 0, -1), (-1, -2, -1), (-1, 1, -1)), # SEP (( 0, 1, 1), (-2, -1, 1), ( 1, -1, 1)), # NWA ((-1, 0, -1), ( 1, 2, -1), ( 1, -1, -1)), # SWA (( 1, 0, 1), (-1, 2, 1), (-1, -1, 1)), # NWP (( 0, 1, -1), ( 2, -1, -1), (-1, -1, -1)) # SWP )/np.sqrt((2, 6, 3))[:, np.newaxis] # 提取每个旋转矩阵最后一行的符号,转换为整数元组 rot_signs = [tuple(int(np.sign(val)) for val in row) for row in z_rotate[:, -1]] # 构建旋转矩阵索引到面名称的映射,或者直接建立{名称: 旋转矩阵}字典 name_to_rot_matrix = {} for idx, sign_tuple in enumerate(rot_signs): name = sign_to_name[sign_tuple] name_to_rot_matrix[name] = z_rotate[idx] # 验证:比如获取NEA对应的旋转矩阵 print("NEA对应的旋转矩阵:\n", name_to_rot_matrix['NEA'])
这样你就可以通过面名称直接获取对应的旋转矩阵,不用手动对应索引啦。
四、(进阶)从原型矩阵推导所有旋转矩阵
既然正八面体具有高度对称性,我们可以不用手动定义8个矩阵,而是从一个原型(比如NEA的矩阵)通过对称变换生成其他矩阵:
核心思路是:每个面都可以通过对原型面进行轴翻转、镜像等变换得到,对应的旋转矩阵也可以通过乘以变换矩阵来生成。举个简单的例子:
- 要得到SEA面(Z负方向),可以对原型矩阵进行Z轴翻转,也就是把矩阵中涉及Z的符号反转
- 要得到NWA面(Y负方向),可以对原型矩阵进行Y轴翻转
这里给出一个简化的实现思路(你可以根据实际需求调整):
# 定义NEA面的原型旋转矩阵 nea_prototype = np.array([ (-1, 0, 1), ( 1, -2, 1), ( 1, 1, 1) ]) / np.sqrt((2, 6, 3))[:, np.newaxis] # 定义对称变换的符号组合(对应X、Y、Z轴的翻转:1=不翻转,-1=翻转) symmetry_signs = [ (1,1,1), # NEA (1,1,-1), # SEA (-1,1,1), # NEP (-1,1,-1),# SEP (1,-1,1), # NWA (1,-1,-1),# SWA (-1,-1,1),# NWP (-1,-1,-1)# SWP ] # 通过原型矩阵生成所有旋转矩阵 generated_rot_matrices = [] for x_sym, y_sym, z_sym in symmetry_signs: # 对原型矩阵的每个元素应用对称变换(根据轴的翻转调整符号) transformed = nea_prototype * np.array([[x_sym, y_sym, z_sym], [x_sym, y_sym, z_sym], [x_sym, y_sym, z_sym]]) generated_rot_matrices.append(transformed) # 转换为numpy数组 generated_rot_matrices = np.array(generated_rot_matrices) # 验证:和你原来的z_rotate对比,应该完全一致(考虑浮点精度) print("生成的矩阵与原矩阵是否一致:", np.allclose(generated_rot_matrices, z_rotate))
这个方法利用了正八面体的对称性,省去了手动编写8个矩阵的麻烦,而且完全符合你想要的“从原型推导”的需求~
备注:内容来源于stack exchange,提问作者Konchog
相关产品推荐
相关产品推荐

