def make_centroid(self):
     """Find the vertex centroid of the face, and turn it into a Vertex.
     
        Returns: Vertex([xc, yc, zc])
        """
     (xc, yc, zc) = self.find_centroid()
     return Vertex([xc, yc, zc])
    def project(self, plane='xy', new_frame=None):
        """Project a copy of the face onto a plane that is spanned by two
            axes. The projection is orthographic.
            
            If this face is not attached to the global coordinate frame, then
            the face returned by this function will be in terms of the local
            frame.
            
            TODO: A "new_frame" can be specified, which will make the 
            projection elements children of this frame. Otherwise, the 
            elements will be children of the global coordinate frame.
            
            TODO: Generalize this function for arbitrary projection plane. 
            """

        # Eliminate minus sign in front of the plane:
        if plane[0] == '-':
            plane = plane[1:]

        pj_xyz = []

        # Flatten the coordinates of each vertex onto the projection plane:
        for vertex in [self.p1, self.p2, self.p3, self.p4]:
            if plane == 'xy':
                pj_x = vertex.x
                pj_y = vertex.y
                pj_z = 0
            elif plane == 'xz':
                pj_x = vertex.x
                pj_y = 0
                pj_z = vertex.z
            elif plane == 'yz':
                pj_x = 0
                pj_y = vertex.y
                pj_z = vertex.z
            else:
                raise ValueError("No valid projection plane given to "
                                 "projection method! "
                                 "Valid options: 'xy', 'xz', 'yz'")
            pj_xyz.append(Vertex([pj_x, pj_y, pj_z], parenttype="face"))

        # Create the projected face using the projected vertices.
        if not new_frame:
            pj = Face(pj_xyz[0], pj_xyz[1], pj_xyz[2], pj_xyz[3])
        else:
            pj = Face(pj_xyz[0],
                      pj_xyz[1],
                      pj_xyz[2],
                      pj_xyz[3],
                      parenttype="frame")
            new_frame.add_face(pj)
        return pj
    def __init__(self,
                 head: Vertex,
                 tail: Vertex = Vertex([0, 0, 0]),
                 parenttype="global"):

        self.head = head  # Vertex
        self.tail = tail  # Vertex

        self.parenttype = "global"

        # Re-assign self.parenttype to check for validity of given parenttype
        if parenttype != "global":
            self.set_parenttype(parenttype)

        # Let child vertices know their parenttype is 'vector'
        for vertex in self.vertices():
            vertex.set_parenttype("vector")
 def project_face(self, face: Face, plane='xy', new_frame=None):
     """Project a copy of the face onto a plane that is spanned by two
         axes. The projection is orthographic. Coordinates will be in terms
         of the GLOBAL frame.
         
         TODO: A "new_frame" can be specified, which will make the 
         projection elements children of this frame. Otherwise, the 
         elements will be children of the global coordinate frame.
         
         TODO: Generalize this function for arbitrary projection plane. 
         """
     # Eliminate minus sign in front of the plane:    
     if plane[0] == '-':
         plane = plane[1:]
     
     pj_xyz = []
     
     for vertex in [face.p1, face.p2, face.p3, face.p4]:
         
         global_coords = self.vertex_xyz_global(vertex)
         
         if plane == 'xy':
             pj_x = global_coords[0]
             pj_y = global_coords[1]
             pj_z = 0
         elif plane == 'xz':
             pj_x = global_coords[0]
             pj_y = 0
             pj_z = global_coords[2]
         elif plane == 'yz':
             pj_x = 0
             pj_y = global_coords[1]
             pj_z = global_coords[2]
         else:
             raise ValueError("No valid projection plane given to "
                               "projection method! "
                               "Valid options: 'xy', 'xz', 'yz'")
         pj_xyz.append(Vertex([pj_x, pj_y, pj_z], parenttype="face"))
     
     # Create the projected face using the projected vertices.
     if not new_frame: 
         pj = Face(pj_xyz[0], pj_xyz[1], pj_xyz[2], pj_xyz[3],
                   parenttype="global")
     else:
         raise TypeError("new_frame functionality is not yet implemented.")
     return pj
Exemplo n.º 5
0
 def find_cuboid_centroid(self):
     """Locate the centroid of a cuboid geometry.
        Cuboids have eight corners, which this method checks first.
        """
     vertices = self.vertices()
     if len(vertices) != 8:
         raise ValueError("Tried to use method find_cuboid_centroid() "
                          "with a geometry containing {} vertices. "
                          "All cuboids must have exactly 8 vertices."
                          "".format(len(vertices)))
     xc = 0
     yc = 0
     zc = 0
     for vertex in vertices:
         xc += vertex.x / len(vertices)
         yc += vertex.y / len(vertices)
         zc += vertex.z / len(vertices)
     return Vertex(xc, yc, zc)
def plot_vertex(
    axes: plt.matplotlib.axes,
    vertex: Vertex,
    xyz_global=None,
    vertexfill=True,  # If False, vertex will not be plotted
    vertexcolour="#000",  # Specifies the vertex colour
    vertexsize=10,  # Size of the plotted vertex
    vertexalpha=1  # Opacity of the plotted vertex
):

    # print("[DEBUG] Plotting {}".format(vertex))

    # Check whether vertex should be plotted:
    if vertexfill:
        # If vertex is an orphan, use its local coordinates for plotting
        # if vertex.parenttype == "global":
        if not xyz_global.all():
            x, y, z = vertex.xyz()
        # If not, check and use xyz_global coordinates provided
        else:
            # Verifying type of xyz_global
            if (isinstance(xyz_global, list)
                    or isinstance(xyz_global, np.ndarray)):
                # Verifying length of xyz_global
                if len(xyz_global) == 3:
                    [x, y, z] = xyz_global
                else:
                    raise ValueError("Error: Tried to plot vertex using {}\
                                     coordinates, but exactly 3 are needed!\
                                     ".format(len(xyz_global)))
            # elif xyz_global == None:
            #     raise TypeError("Something went wrong with vertex plot!")
            else:
                raise TypeError("Error: Tried to plot vertex, but argument \
                                'xyz_global' was invalid type ({})!\
                                ".format(type(xyz_global)))

        axes.scatter(x, y, z, c=vertexcolour, s=vertexsize, alpha=vertexalpha)
 def rotate(self, a, b, c, cor=None, seq='321'):
     """ Rotates the frame around a point in the global frame
     .
         a, b, c is Euler angle of rotation around local x, y, z axes
             expressed in radians
             
         seq is a string with the rotation sequence, e.g. '321' for:
             Rz(c).Ry(b).Rx(a).vertex
             Default rotation sequence: '321' (zyx)
             
         cor is the centre of rotation, which can be specified as
             a Vertex, or a list or numpy.ndarray of local coordinates.
     """
     
     # ==== COR argument handling ====
     # Case: COR is given as a list/ndarray of coordinates  
     if (isinstance(cor, list) or isinstance(cor, np.ndarray)):
         if len(cor) == 3:
             cor = Vertex(list(cor))
             
     # Case: COR is given as a Vertex
     elif isinstance(cor, Vertex):
         pass
     
     # If COR is None, ignore now and handle later
     elif not cor:
         pass
         
     # All other cases
     else:
         raise TypeError("Error when rotating frame. Centre of rotation \
                         argument not provided correctly!")
     
     # ==== Define relevant rotation matrices ====
     Rx = np.array([[1,      0,       0],
                    [0, cos(a), -sin(a)],
                    [0, sin(a),  cos(a)]])
     
     Ry = np.array([[ cos(b), 0, sin(b)],
                    [      0, 1,      0],
                    [-sin(b), 0, cos(b)]])
     
     Rz = np.array([[cos(c), -sin(c), 0],
                    [sin(c),  cos(c), 0],
                    [     0,       0, 1]])
     
     # ==== Perform rotation ====
     for axis in reversed(seq):
         
         # If no Centre of Rotation (cor) is given, take frame origin.
         # If not, subtract coordinates of cor first before applying 
         # the rotation, and then reverse this afterwards.
         temp = (self.x, self.y, self.z)
         if cor:
             self.translate(-1*temp[0], -1*temp[1], -1*temp[2])
         
         if axis == '1':
             self.xdir = np.dot(Rx, self.xdir)
             self.ydir = np.dot(Rx, self.ydir)
             self.zdir = np.dot(Rx, self.zdir)
         if axis == '2':
             self.xdir = np.dot(Ry, self.xdir)
             self.ydir = np.dot(Ry, self.ydir)
             self.zdir = np.dot(Ry, self.zdir)
         if axis == '3':
             self.xdir = np.dot(Rz, self.xdir)
             self.ydir = np.dot(Rz, self.ydir)
             self.zdir = np.dot(Rz, self.zdir)
           
         # Reverse temporary translation.
         if cor:
             self.translate(1*temp[0], 1*temp[1], 1*temp[2])
     
     # Update the frame's direction cosine matrix:
     self.recalculate_dcm()
Exemplo n.º 8
0
 def find_centroid(self):
     """Find the vertex centroid of the face."""
     xc = 0.25 * (self.p1.x + self.p2.x + self.p3.x + self.p4.x)
     yc = 0.25 * (self.p1.y + self.p2.y + self.p3.y + self.p4.y)
     zc = 0.25 * (self.p1.z + self.p2.z + self.p3.z + self.p4.z)
     return Vertex(xc, yc, zc)
frame2 = Frame()

# p1 = Vertex(0,0,0,frame1)
# p2 = Vertex(1,0,0)
# p3 = Vertex(1,1,0)
# p4 = Vertex(0,1,0)
# p5 = Vertex(0,1,1)
# p6 = Vertex(0,0,1)

# f1 = Face(p1, p2, p3, p4, frame1)
# f2 = Face(p1, p4, p5, p6, frame1)

frame1.readout()

f1 = Face(Vertex(0, 0, 0), Vertex(1, 0, 0), Vertex(1, 1, 0), Vertex(0, 1, 0),
          frame1)

frame1.readout()

del (f1)

frame1.readout()

#%% ==== Plotting ====

# Toggle plotting functionality:
if False:

    # Setting up the plot:
    fig = plt.figure(figsize=(8, 8))
Exemplo n.º 10
0
""" === CHANGE ROTATION OF BODY HERE === """

# Note: choosing bdeg=90 will result in gimbal lock. 
adeg = 30 # Rotation around x axis in degrees
bdeg = 40  # Rotation around y axis in degrees
cdeg = 0   # Rotation around z axis in degrees

""" ==================================== """

a = d2r(adeg)
b = d2r(bdeg)
c = d2r(cdeg)


"""Basic Cubesat model:"""
p1 = Vertex(0.0, 0.0, 0.0)
p2 = Vertex(0.0, 0.0, 0.2)
p3 = Vertex(0.1, 0.0, 0.2)
p4 = Vertex(0.1, 0.0, 0.0)
p5 = Vertex(0.0, 0.1, 0.0)
p6 = Vertex(0.0, 0.1, 0.2)
p7 = Vertex(0.1, 0.1, 0.2)
p8 = Vertex(0.1, 0.1, 0.0)


# Manually calculate centroid of Cubesat geometry
# COR = Vertex(0.05, 0.05, 0.1)
# COR.translate(0.1, 0.1, 0.1)

# Define faces of Cubesat
fA = Face(p4, p3, p2, p1)
Exemplo n.º 11
0
import numpy as np
from numpy import sin, cos
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import mpl_toolkits.mplot3d as mp3d

from cp_vertex import Vertex
from cp_face import Face
from cp_geometry import Geometry
from cp_vector import Vector
from cp_frame import Frame
from cp_utilities import d2r  #, r2d
from cp_plotting import plot_global_tripod, plot_frame, \
    plot_vertex, plot_face, plot_geometry_perpendiculars, plot_illumination

p0 = Vertex([0.5, 0.5, 0.5])
p1 = Vertex([-0.05, -0.05, -0.1])
p2 = Vertex([-0.05, -0.05, 0.1])
p3 = Vertex([0.05, -0.05, 0.1])
p4 = Vertex([0.05, -0.05, -0.1])
p5 = Vertex([-0.05, 0.05, -0.1])
p6 = Vertex([-0.05, 0.05, 0.1])
p7 = Vertex([0.05, 0.05, 0.1])
p8 = Vertex([0.05, 0.05, -0.1])

fA = Face(p4, p3, p2, p1)
fB = Face(p2, p3, p7, p6)
fC = Face(p3, p4, p8, p7)
fD = Face(p4, p1, p5, p8)
fE = Face(p1, p2, p6, p5)
fF = Face(p5, p6, p7, p8)
if True:

    # Setting up the plot:
    fig = plt.figure(figsize=(10, 7))
    ax = mp3d.Axes3D(fig)
    """ TO CHANGE THE DEFAULT CAMERA VIEW, CHANGE THESE: """
    ax.view_init(elev=20, azim=-60)

    steps = 40
    angle_step = d2r(360 / steps)

    frame1 = Frame()
    frame1.translate(0.5, 0.5, 0.5)
    frame1.rotate(0, 0, d2r(1 * 360 / 12))

    p1 = Vertex(-0.05, -0.05, -0.1, frame1)
    p2 = Vertex(-0.05, -0.05, 0.1, frame1)
    p3 = Vertex(0.05, -0.05, 0.1, frame1)
    p4 = Vertex(0.05, -0.05, -0.1, frame1)
    p5 = Vertex(-0.05, 0.05, -0.1, frame1)
    p6 = Vertex(-0.05, 0.05, 0.1, frame1)
    p7 = Vertex(0.05, 0.05, 0.1, frame1)
    p8 = Vertex(0.05, 0.05, -0.1, frame1)

    fA = Face(p4, p3, p2, p1, frame1)
    fB = Face(p2, p3, p7, p6, frame1)
    fC = Face(p3, p4, p8, p7, frame1)
    fD = Face(p4, p1, p5, p8, frame1)
    fE = Face(p1, p2, p6, p5, frame1)
    fF = Face(p5, p6, p7, p8, frame1)
Exemplo n.º 13
0
#%% ==== Plotting ====

# Toggle plotting functionality:
if True:

    # Setting up the plot:
    fig = plt.figure(figsize=(10, 7))
    ax = mp3d.Axes3D(fig)
    """ TO CHANGE THE DEFAULT CAMERA VIEW, CHANGE THESE: """
    ax.view_init(elev=20, azim=-60)

    steps = 24
    angle_step = d2r(360 / steps)

    p0 = Vertex([0.5, 0.5, 0.5])
    p1 = Vertex([-0.05, -0.05, -0.1])
    p2 = Vertex([-0.05, -0.05, 0.1])
    p3 = Vertex([0.05, -0.05, 0.1])
    p4 = Vertex([0.05, -0.05, -0.1])
    p5 = Vertex([-0.05, 0.05, -0.1])
    p6 = Vertex([-0.05, 0.05, 0.1])
    p7 = Vertex([0.05, 0.05, 0.1])
    p8 = Vertex([0.05, 0.05, -0.1])

    fA = Face(p4, p3, p2, p1)
    fB = Face(p2, p3, p7, p6)
    fC = Face(p3, p4, p8, p7)
    fD = Face(p4, p1, p5, p8)
    fE = Face(p1, p2, p6, p5)
    fF = Face(p5, p6, p7, p8)
#%% ==== Plotting ====

# Toggle plotting functionality:
if True:

    # Setting up the plot:
    fig = plt.figure(figsize=(10, 7))
    ax = mp3d.Axes3D(fig)
    """ TO CHANGE THE DEFAULT CAMERA VIEW, CHANGE THESE: """
    ax.view_init(elev=20, azim=-50)

    steps = 64
    angle_step = d2r(360 / steps)

    p0 = Vertex([0.5, 0.5, 0.5])
    p1 = Vertex([-0.05, -0.05, -0.1])
    p2 = Vertex([-0.05, -0.05, 0.1])
    p3 = Vertex([0.05, -0.05, 0.1])
    p4 = Vertex([0.05, -0.05, -0.1])
    p5 = Vertex([-0.05, 0.05, -0.1])
    p6 = Vertex([-0.05, 0.05, 0.1])
    p7 = Vertex([0.05, 0.05, 0.1])
    p8 = Vertex([0.05, 0.05, -0.1])

    fA = Face(p4, p3, p2, p1)
    fB = Face(p2, p3, p7, p6)
    fC = Face(p3, p4, p8, p7)
    fD = Face(p4, p1, p5, p8)
    fE = Face(p1, p2, p6, p5)
    fF = Face(p5, p6, p7, p8)
 def add_vertex(self, vertex: Vertex):
     self.vertices.append(vertex)
     vertex.set_parenttype="frame"
Exemplo n.º 16
0
# Toggle plotting functionality:
if True:

    # Setting up the plot:
    fig = plt.figure(figsize=(10, 7))
    ax = mp3d.Axes3D(fig)
    """ TO CHANGE THE DEFAULT CAMERA VIEW, CHANGE THESE: """
    ax.view_init(elev=20, azim=-60)

    steps = 40
    angle_step = d2r(360 / steps)

    frame1 = Frame()

    vertex1 = Vertex(0.5, 0, 0, parent=frame1)
    vertex2 = Vertex(0.5, 0.5, 0, parent=frame1)

    def update(i):

        # Transforming frame1
        frame1.translate(2 / steps, 2 / steps, 2 / steps)
        # frame1.rotate(0,0,-2*np.pi/(steps))

        # Local transformation of vertex1 - rotate around vertex2
        vertex1.rotate(2 * np.pi / steps, 0, 0, cor=vertex2)

        # Setting up the axes object
        ax.clear()

        ax.set_title("Wireframe visualization. Frame: {}".format(str(i)))
 steps = 64
 # steps is a global variable, so we can access it outside the update()
 #   function. It should be noted that relying on global variables is
 #   bad practice, but I'm an adult and I'll do what I like!
 
 # Defining an angle step that ensures the CubeSat model rotates completely,
 #   but only once.
 angle_step = d2r(360/steps)
 
 
 """ ================= DEFINING THE GEOMETRIC OBJECTS ================= """
 # Defining the vertices that will be the corners of the cubesat. I 
 #   recommend that you keep the units in meters.
                                     #         ^ Z
                                     #         | 
 p1 = Vertex([-0.05, -0.05, -0.1])   #      2 ___ 6
 p2 = Vertex([-0.05, -0.05,  0.1])   #       |\3__\7 
 p3 = Vertex([ 0.05, -0.05,  0.1])   #       | |  |         Y
 p4 = Vertex([ 0.05, -0.05, -0.1])   #      1| | 5|  -------->
 p5 = Vertex([-0.05,  0.05, -0.1])   #        \|__|
 p6 = Vertex([-0.05,  0.05,  0.1])   #        4    8  
 p7 = Vertex([ 0.05,  0.05,  0.1])   #            \
 p8 = Vertex([ 0.05,  0.05, -0.1])   #             v X
 
 # Assembling the side panels of the Cubesat. Note that the order in which
 #   the points is specified DOES matter! (see definition of Face class)
 
                             #         ^ Z
                             #         | 
 fA = Face(p4, p3, p2, p1)   #     E  ___  
 fB = Face(p2, p3, p7, p6)   #       |\ B_\  
 def remove_vertex(self, vertex: Vertex):
     self.vertices.remove(vertex)
     vertex.set_parenttype="global"
 def make_cuboid_centroid(self):
     """Locates the centroid of a cuboid geometry and creates a
     Vertex at this point."""
     (xc, yc, zc) = self.find_cuboid_centroid()
     return Vertex([xc, yc, zc])