最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

vector - Plane equations in python - Stack Overflow

programmeradmin0浏览0评论

I'm setting out a rigid body in python (cuboid) with a defined height, width, depth and centre position. I want to find the normal to each face of the cuboid, and then the bound plane equations for each. I've set out some code that looks to be returning what I want in terms of the normal vector, is there a more efficient way to do this? I know I've been a bit loose with how I've used the matrices but is the general idea of this okay?

My code is as follows. I've set out a couple of rotation functions at the start, one for rotation around y and one for rotation around x. The next step will be combining these into 1, just haven't got around to it yet. I then set out a class for the rigid body, which contains functions that determine the centrepoint of each face, the vertices of each face and then the normal equation of each face. Currently it does work, when the angles of rotation are zero I get -x for front and back, -y for left and right and -z for top and bottom as the normal vectors. Is this is a good way to find the normals? I want to be using this for some monte carlo modelling in time where the angles and position are changing for each t

import numpy as np

def rotation_xy(theta, vector):
    theta = np.radians(theta)
    R = np.array([[np.cos(theta), -np.sin(theta), 0], [np.sin(theta), np.cos(theta), 0], [0, 0, 1]])
    vector_rotated = np.dot(R, vector)

    return vector_rotated

def rotation_xz(phi, vector):
    phi = np.radians(phi)
    R = np.array([[np.cos(phi), 0,np.sin(phi)], [0, 1, 0], [-np.sin(phi), 0, np.cos(phi)]])
    #vector_rotated = np.dot(R, vector)
    vector_rotated = np.dot(R, vector)

    return vector_rotated
    
class paddle():
    def __init__(self, height, width, depth, centre, theta = 0, phi = 0):
        self.height = height
        self.width = width
        self.depth = depth
        self.centre = centre
        self.theta = theta
        self.phi = phi

        self.faces = self.calculate_faces()
        
    def calculate_faces(self):
        """ 
        Calculate the plane equations for each face
        """
        half_width = self.width/2
        half_height = self.height/2
        half_depth = self.depth/2

        face_offsets = {
            "front": np.array([half_depth, 0, 0]),
            "back": np.array([-half_depth, 0, 0]),
            "left": np.array([0, -half_width, 0]),
            "right": np.array([0, half_width, 0]),
            "top": np.array([0, 0, half_height]),
            "bottom": np.array([0, 0, -half_height]),
        }
        
        plane_equations = {}
        for face_name, offset in face_offsets.items():
            # Get the four vertices for the current face dynamically
            corners = self.get_face_vertices(offset, half_width, half_height, half_depth)
            # Calculate the normal vector and D value in Ax + By + Cz + D = 0
            normal_vector, D = self.get_normal_and_D(corners, self.theta, self.phi)
            plane_equations[face_name] = (normal_vector, D)
        return plane_equations

    
    def get_face_vertices(self, offset, half_width, half_height, half_depth):
        """
        Calculate the 4 vertices of the selected face
        Uses the face offset to determine these
        If offset is non-zeo in x, then vertices are at constant x, changing y and z 
        -> Done dynamically through matrices
        for example, for the front face the offset matrix is
            [0 ,0    ,0]
            [0 ,+/-1 ,0]
            [0 ,0    ,+/-1]
        """
        face_array = np.array([half_width, half_height, half_depth])
        non_zero_indices = np.where(offset !=0)[0] # offset indices that are non-zero
        zero_indices = np.where(offset == 0)[0] # offset indices that are zero
        offset_matrix = np.eye(3)
        offset_matrix[non_zero_indices,: ] = 0
        start = self.centre 
        corners = []
        corners.append(start + np.dot(face_array, (offset_matrix * -np.eye(3))))
        corners.append(start + np.dot(face_array, offset_matrix))
        for a in zero_indices:
            offset_matrix = np.eye(3)
            offset_matrix[non_zero_indices,: ] = 0
            offset_matrix[a,a] = -1
            corners.append(start + np.dot(face_array, offset_matrix))
        return corners
    
    def get_normal_and_D(self, vertices, theta, phi):
        """
        Calculate the normal vector and D value for the plane equation.
        Uses the first 3 vertices to compute the normal.
        """
        # Get two vectors from the vertices
        v1 = vertices[1] - vertices[0]  # Vector from corner 1 to corner 2
        v2 = vertices[3] - vertices[0]  # Vector from corner 1 to corner 4
        v1, v2 = rotation_xy(theta, v1), rotation_xz(theta, v2) # rotate around z axis
        v1, v2 = rotation_xz(phi, v1), rotation_xz(phi, v2) # rotate around y axis 
        normal_vector = np.cross(v1, v2)  # Cross product to get normal vector
        normal_vector = normal_vector / np.linalg.norm(normal_vector)  # Normalize the vector

        # Calculate D for the plane equation: Ax + By + Cz + D = 0
        D = -np.dot(normal_vector, self.centre)

        return normal_vector, D

paddle = paddle(height=1, width=0.1, depth=0.04, centre=np.array([0, 0, 0]))
plane_equations = paddle.calculate_faces()
for face, (normal, D) in plane_equations.items():
    print(f"Plane equation for {face} face: {normal[0]}x + {normal[1]}y + {normal[2]}z + {D}")
    print(normal)

发布评论

评论列表(0)

  1. 暂无评论