Exemple #1
0
    def __init__(self, r, g, b, a, px, py, pz, ux, uy, uz, vx, vy, vz):
        '''
        Constructor
        '''
        self.position = VertexBuffer(12)

        # Upper left
        self.position.add_point(
            Vector3(px - ux - vx, py - uy - vy, pz - uz - vz))

        # upper left
        self.position.add_point(
            Vector3(px - ux + vx, py - uy + vy, pz - uz + vz))

        # lower right
        self.position.add_point(
            Vector3(px + ux - vx, py + uy - vy, pz + uz - vz))

        # upper right
        self.position.add_point(
            Vector3(px + ux + vx, py + uy + vy, pz + uz + vz))

        self.r = r
        self.g = g
        self.b = b
        self.a = a
Exemple #2
0
    def draw_internal(self, gl):
        if self.render_state.night_vision_mode:
            return

        gl.glEnableClientState(gl.GL_VERTEX_ARRAY)
        gl.glEnableClientState(gl.GL_COLOR_ARRAY)
        gl.glDisableClientState(gl.GL_TEXTURE_COORD_ARRAY)

        gl.glEnable(gl.GL_CULL_FACE)
        gl.glFrontFace(gl.GL_CW)
        gl.glCullFace(gl.GL_BACK)

        gl.glShadeModel(gl.GL_SMOOTH)

        gl.glPushMatrix()

        # Rotate the sky box to the position of the sun.
        cp = cross_product(Vector3(0, 1, 0), self.sun_pos)
        cp = normalized(cp)
        angle = 180.0 / math.pi * math.acos(self.sun_pos.y)
        gl.glRotatef(angle, cp.x, cp.y, cp.z)

        self.vertex_buffer.set(gl)
        self.color_buffer.set(gl)

        self.index_buffer.draw(gl, gl.GL_TRIANGLES)

        gl.glPopMatrix()
Exemple #3
0
def matrix_vector_multiply(m, v):
    '''
    multiply m * v where m is a matrix and v is a vector
    '''
    return Vector3(m.xx * v.x + m.xy * v.y + m.xz * v.z,
                   m.yx * v.x + m.yy * v.y + m.yz * v.z,
                   m.zx * v.x + m.zy * v.y + m.zz * v.z)
Exemple #4
0
def vector_product(v1, v2):
    '''
    given two vector3 objects perform the vector product
    '''
    term1 = v1.y * v2.z - v1.z * v2.y
    term2 = -v1.x * v2.z + v1.z * v2.x
    term3 = v1.x * v2.y - v1.y * v2.x
    return Vector3(term1, term2, term3)
Exemple #5
0
 def set_view_up_direction(self, viewer_up):
     if abs(viewer_up.y) < 0.999:
         cp = cross_product(viewer_up, Vector3(0, 0, 0))
         cp = normalized(cp)
         self.geo_to_viewer_transform = create_rotation(math.acos(viewer_up.y), cp)
     else:
         self.geo_to_viewer_transform = create_identity()
         
     self.must_update_transformed_orientation = True
Exemple #6
0
 def __init__(self, layer_id, new_texture_manager):
     '''
     Constructor
     '''
     RendererObjectManager.__init__(self, layer_id, new_texture_manager)
     self.width = 2
     self.height = 2
     self.geo_to_viewer_transform = create_identity()
     self.look_dir = Vector3(0, 0, 0)
     self.up_dir = Vector3(0, 1, 0)
     self.transformed_look_dir = Vector3(0, 0, 0)
     self.transformed_up_dir = Vector3(0, 1, 0)
     
     #search_helper = SearchHelper()
     self.dark_quad = None
     #self.search_arrow = SearchArrow()
     #crosshair = CrosshairOverlay()
     
     
Exemple #7
0
 def __init__(self, geo_coord, new_id, up_v=Vector3(0.0, 1.0, 0.0), im_scale=1):
     '''
     Constructor
     '''
     Source.__init__(self, colors.WHITE, geo_coord)
     self.is_blank = False
     self.requires_blending = False
     self.pixmap_image = None
     self.image_scale = im_scale
     self.set_up_vector(up_v)
     self.set_image_id(new_id)
Exemple #8
0
 def update_view(self, gl):
     # Get a vector perpendicular to both, pointing to the right, by taking
     # lookDir cross up.
     look_dir = self.render_state.look_dir.copy()
     up_dir = self.render_state.up_dir.copy()
     right = cross_product(look_dir, up_dir)
     
     if self.DEBUG_MODE != None:
         from src.units.Vector3 import Vector3
         look_dir = Vector3(Debug.LOOKDIRVECTORS[self.DEBUG_MODE][0], 
                            Debug.LOOKDIRVECTORS[self.DEBUG_MODE][1], 
                            Debug.LOOKDIRVECTORS[self.DEBUG_MODE][2])
         up_dir = Vector3(Debug.UPDIRVECTORS[self.DEBUG_MODE][0], 
                          Debug.UPDIRVECTORS[self.DEBUG_MODE][1], 
                          Debug.UPDIRVECTORS[self.DEBUG_MODE][2])
         right = Vector3(Debug.RIGHTVECTORS[self.DEBUG_MODE][0], 
                         Debug.RIGHTVECTORS[self.DEBUG_MODE][1], 
                         Debug.RIGHTVECTORS[self.DEBUG_MODE][2])
     
     self.view_matrix = Matrix4x4.create_view(look_dir, up_dir, right)
     
     gl.glMatrixMode(gl.GL_MODELVIEW)
     adjust_matrix = Matrix4x4.Matrix4x4([0.0, 0.0, -1.0, 0.0,
                                          0.0, 1.0, -0.0, 0.0,
                                          1.0, 0.0, -0.0, 0.0,
                                          0.0, 0.0, 0.0, 1.0])
     matrix = Matrix4x4.multiply_MM(self.view_matrix, adjust_matrix)
     
     # Invert the left/right rotation of the matrix
     matrix.values[2] *= -1
     matrix.values[8] *= -1
     
     # Invert these so that we don't rotate in and out of the unit sphere
     matrix.values[1] *= -1
     matrix.values[4] *= -1
     
     matrix = np.array(matrix.values, dtype=np.float32)
     #matrix = np.array(self.view_matrix.values, dtype=np.float32)
     gl.glLoadMatrixf(matrix)
Exemple #9
0
 def __init__(self, mag_dec_calc):
     '''
     Constructor
     '''
     self.auto_update_pointing = True
     self.field_of_view = 45  #Degrees
     self.location = LatLong(0, 0)
     self.clock = RealClock()
     self.celestial_coords_last_updated = -1
     
     # provides correction from true North to magnetic North 
     self.magnetic_declination_calc = mag_dec_calc
     
     #The pointing comprises a vector into the phone's screen expressed in
     #celestial coordinates combined with a perpendicular vector along the
     #phone's longer side.
     self.pointing = Pointing()
     
     #The sensor acceleration in the phone's coordinate system.
     self.acceleration = ApplicationConstants.INITIAL_DOWN
     
     #The sensor magnetic field in the phone's coordinate system.
     self.magnetic_field = ApplicationConstants.INITIAL_SOUTH
     
     #North along the ground in celestial coordinates.
     self.true_north_celestial = Vector3(1, 0, 0);
     
     #Up in celestial coordinates.
     self.up_celestial = Vector3(0, 1, 0)
     
     #East in celestial coordinates.
     self.true_east_celestial = self.AXIS_OF_EARTHS_ROTATION
     
     #[North, Up, East]^-1 in phone coordinates.
     self.axes_phone_inverse_matrix = get_identity_matrix();
     
     #[North, Up, East] in celestial coordinates. */
     self.axes_magnetic_celestial_matrix = get_identity_matrix();
Exemple #10
0
    def __init__(self, sky_renderer, new_layer, new_texture_manager):
        '''
        Constructor
        '''
        RendererObjectManager.__init__(self, new_layer, new_texture_manager)

        self.label_maker = None
        self.labels = []
        self.sky_region_map = SkyRegionMap()

        # These are intermediate variables set in beginDrawing() and used in
        # draw() to make the transformations more efficient
        self.label_offset = Vector3(0, 0, 0)
        self.dot_product_threshold = None

        self.texture_ref = None

        # A quad with size 1 on each size, so we just need to multiply
        # by the label's width and height to get it to the right size for each
        # label.
        vertices = [
            -0.5,
            -0.5,  # lower left
            -0.5,
            0.5,  # upper left
            0.5,
            -0.5,  # lower right
            0.5,
            0.5
        ]  # upper right
        # make the vertices fixed point? byte buffer?
        self.quad_buffer = np.array(vertices, dtype=np.float32)

        # We want to initialize the labels of a sky region to an empty list.
        def construct_method():
            return []

        self.sky_region_map.region_data_factory = \
            SkyRegionMap.RegionDataFactory(construct_method)
Exemple #11
0
    def draw_label(self, gl, label):
        look_dir = self.render_state.look_dir
        if look_dir.x * label.x + look_dir.y * label.y + \
                look_dir.z * label.z < self.dot_product_threshold:
            return

        # Offset the label to be underneath the given position (so a label will
        # always appear underneath a star no matter how the phone is rotated)
        v = Vector3(label.x - self.label_offset.x * label.offset,
                    label.y - self.label_offset.y * label.offset,
                    label.z - self.label_offset.z * label.offset)

        screen_pos = transform_vector(self.render_state.transform_to_screen, v)

        # We want this to align consistently with the pixels on the screen, so we
        # snap to the nearest x/y coordinate, and add a magic offset of less than
        # half a pixel.  Without this, rounding error can cause the bottom and
        # top of a label to be one pixel off, which results in a noticeable
        # distortion in the text.
        MAGIC_OFFSET = 0.25
        screen_pos.x = int(screen_pos.x) + MAGIC_OFFSET
        screen_pos.y = int(screen_pos.y) + MAGIC_OFFSET

        gl.glPushMatrix()

        gl.glTranslatef(screen_pos.x, screen_pos.y, 0)
        gl.glRotatef((180.0 / math.pi) * self.render_state.up_angle, 0, 0, -1)
        gl.glScalef(label.width_in_pixels, label.height_in_pixels, 1)

        gl.glVertexPointer(2, gl.GL_FLOAT, 0, self.quad_buffer)
        gl.glTexCoordPointer(2, gl.GL_FLOAT, 0, label.text_coords)
        if self.render_state.night_vision_mode:
            gl.glColor4ub(0xFF, 0, 0, label.a)
        else:
            gl.glColor4ub(label.r, label.g, label.b, 128)

        gl.glDrawArrays(gl.GL_TRIANGLE_STRIP, 0, 4)

        gl.glPopMatrix()
Exemple #12
0
def scale(v, factor):
    return Vector3(v.x * factor, v.y * factor, v.z * factor)
Exemple #13
0
    zs = axis.z * sin_d

    xm = axis.x * one_minus_cos_d
    ym = axis.y * one_minus_cos_d
    zm = axis.z * one_minus_cos_d

    xym = axis.x * ym
    yzm = axis.y * zm
    zxm = axis.z * xm

    return Matrix33(axis.x * xm + cos_d, xym + zs, zxm - ys, xym - zs,
                    axis.y * ym + cos_d, yzm + xs, zxm + ys, yzm - xs,
                    axis.z * zm + cos_d)


if __name__ == "__main__":
    '''
    For debugging purposes
    '''
    import time
    import units.LatLong as LL
    from units.RaDec import RaDec

    M = calculate_rotation_matrix(90, Vector3(1, 0, 0))
    print M.xx, M.xy, M.xz
    print M.yx, M.yy, M.yz
    print M.zx, M.zy, M.zz
    ra, dec = calculate_RADec_of_zenith(time.gmtime(), LL.LatLong(20, 16))
    radec = RaDec(ra, dec)
    print radec.ra, radec.dec
Exemple #14
0
    def update_objects(self, points, update_type):
        #only_update_points = True
        # We only care about updates to positions, ignore any other updates.
        if self.update_type.Reset in update_type:
            #only_update_points = False
            pass
        elif self.update_type.UpdatePositions in update_type:
            # Sanity check: make sure the number of points is unchanged.
            if len(points) != self.num_points:
                return
        else:
            return
        
        self.num_points = len(points)
        
        self.sky_regions.clear()
        
        if Debug.ALLREGIONS == "YES": self.COMPUTE_REGIONS = False
        
        region = SkyRegionMap.CATCHALL_REGION_ID
        if self.COMPUTE_REGIONS: 
            # Find the region for each point, and put it in a separate list
            # for that region.
            for point in points:
                if len(points) < self.MINIMUM_NUM_POINTS_FOR_REGIONS:
                    region = SkyRegionMap.CATCHALL_REGION_ID
                else:
                    region = self.sky_regions.get_object_region(point.geocentric_coords)
                # self.sky_regions.get_region_data(region) is a RegionData instance
                data_for_region = self.sky_regions.get_region_data(region)
                data_for_region.sources.append(point)
        else:
            self.sky_regions.get_region_data(region).sources = points

        # Generate the resources for all of the regions.
        for data in self.sky_regions.region_data.values():
            
            num_vertices = 4 * len(data.sources)
            num_indices = 6 * len(data.sources)
            
            data.vertex_buffer.reset(num_vertices)
            data.color_buffer.reset(num_vertices)
            data.text_coord_buffer.reset(num_vertices)
            data.index_buffer.reset(num_indices)
            
            up = Vector3(0, 1, 0)
            
            # By inspecting the perspective projection matrix, you can show that,
            # to have a quad at the center of the screen to be of size k by k
            # pixels, the width and height are both:
            # k * tan(fovy / 2) / screenHeight
            # This is not difficult to derive.  Look at the transformation matrix
            # in SkyRenderer if you're interested in seeing why this is true.
            # I'm arbitrarily deciding that at a 60 degree field of view, and 480
            # pixels high, a size of 1 means "1 pixel," so calculate size_factor
            # based on this.  These numbers mostly come from the fact that that's
            # what I think looks reasonable.
            fovy_in_radians = 60 * math.pi / 180.0
            size_factor = math.tan(fovy_in_radians * 0.5) / 480
            
            bottom_left_pos = Vector3(0, 0, 0)
            top_left_pos = Vector3(0, 0, 0)
            bottom_right_pos = Vector3(0, 0, 0)
            top_right_pos = Vector3(0, 0, 0)
            
            su = Vector3(0, 0, 0)
            sv = Vector3(0, 0, 0)
            
            index = 0
            
            star_width_in_texels = 1.0 / self.NUM_STARS_IN_TEXTURE
            
            for p_source in data.sources:
                color = 0xFF000000 | int(p_source.color)  # Force alpha to 0xff
                if Debug.COLOR == "WHITE ONLY":
                    color = 0xFFFFFFFF
                bottom_left = index
                top_left = index + 1
                bottom_right = index + 2
                top_right = index + 3
                index += 4
                
                # First triangle
                data.index_buffer.add_index(bottom_left)
                data.index_buffer.add_index(top_left)
                data.index_buffer.add_index(bottom_right)
                
                # Second triangle
                data.index_buffer.add_index(top_right);
                data.index_buffer.add_index(bottom_right);
                data.index_buffer.add_index(top_left);
                
                # PointSource.getPointShape().getImageIndex(); is always 0
                star_index = 0
                
                tex_offset_u = star_width_in_texels * star_index
                
                data.text_coord_buffer.add_text_coord(tex_offset_u, 1);
                data.text_coord_buffer.add_text_coord(tex_offset_u, 0);
                data.text_coord_buffer.add_text_coord(tex_offset_u + star_width_in_texels, 1);
                data.text_coord_buffer.add_text_coord(tex_offset_u + star_width_in_texels, 0);
                
                pos = p_source.geocentric_coords
                u = normalized(cross_product(pos, up))
                v = cross_product(u, pos)
                
                s = p_source.size * size_factor
                
                su.assign(s*u.x, s*u.y, s*u.z)
                sv.assign(s*v.x, s*v.y, s*v.z)
                
                bottom_left_pos.assign(pos.x - su.x - sv.x, pos.y - su.y - sv.y, pos.z - su.z - sv.z)
                top_left_pos.assign(pos.x - su.x + sv.x, pos.y - su.y + sv.y, pos.z - su.z + sv.z)
                bottom_right_pos.assign(pos.x + su.x - sv.x, pos.y + su.y - sv.y, pos.z + su.z - sv.z)
                top_right_pos.assign(pos.x + su.x + sv.x, pos.y + su.y + sv.y, pos.z + su.z + sv.z)
                
                # Add the vertices
                data.vertex_buffer.add_point(bottom_left_pos)
                data.color_buffer.add_color(color)
                
                data.vertex_buffer.add_point(top_left_pos)
                data.color_buffer.add_color(color)
                
                data.vertex_buffer.add_point(bottom_right_pos)
                data.color_buffer.add_color(color)
                
                data.vertex_buffer.add_point(top_right_pos)
                data.color_buffer.add_color(color)
                
            data.sources = None
Exemple #15
0
class AstronomerModel(object):
    '''
    Class responsible to modelling the astronomer
    
    This class has state on the location and orientation of the astronomer
    in space and performs calculations for obtaining directions and time.
    
    As stated in the android version: 
    
    There are 3 frames of reference:
    Celestial - a frame fixed against the background stars with
    x, y, z axes pointing to (RA = 90, DEC = 0), (RA = 0, DEC = 0), DEC = 90
    Phone - a frame fixed in the phone with x across the short side, y across
    the long side, and z coming out of the phone screen.
    Local - a frame fixed in the astronomer's local position. x is due east
    along the ground y is due north along the ground, and z points towards the
    zenith.
    
    We calculate the local frame in phone coords, and in celestial coords and
    calculate a transform between the two.
    In the following, N, E, U correspond to the local
    North, East and Up vectors (ie N, E along the ground, Up to the Zenith)
    
    In Phone Space: axesPhone = [N, E, U]
    
    In Celestial Space: axesSpace = [N, E, U]
    
    We find T such that axesCelestial = T * axesPhone
    
    Then, [viewDir, viewUp]_celestial = T * [viewDir, viewUp]_phone
    
    where the latter vector is trivial to calculate.
    '''
    
    POINTING_DIR_IN_PHONE_COORDS = Vector3(0, 0, -1)
    SCREEN_UP_IN_PHONE_COORDS = Vector3(0, 1, 0)
    AXIS_OF_EARTHS_ROTATION = Vector3(0, 0, 1)
    MINIMUM_TIME_BETWEEN_CELESTIAL_COORD_UPDATES_MILLIS = 60000.0

    def get_time(self):
        '''
        return a time struct of the current GM time
        '''
        return time.gmtime(self.clock.get_time())

    def set_location(self, lat_long):
        self.location = lat_long
        self.calculate_local_north_and_up_in_celestial_coords(True)
        
    def set_phone_sensor_values(self, accel, mag_field):
        self.acceleration.assign(vector3=accel)
        self.magnetic_field.assign(vector3=mag_field)
        
    def get_north(self):
        '''
        In celestial coordinates
        '''
        self.calculate_local_north_and_up_in_celestial_coords(False)
        return get_instance_from_vector3(self.true_north_celestial)
        
    def get_south(self):
        '''
        In celestial coordinates
        '''
        self.calculate_local_north_and_up_in_celestial_coords(False)
        v = Geometry.scale_vector(self.true_north_celestial, -1)
        return get_instance_from_vector3(v)
    
    def get_zenith(self):
        '''
        In celestial coordinates
        '''
        self.calculate_local_north_and_up_in_celestial_coords(False)
        return get_instance_from_vector3(self.up_celestial)
    
    def get_nadir(self):
        '''
        In celestial coordinates
        '''
        self.calculate_local_north_and_up_in_celestial_coords(False)
        v = Geometry.scale_vector(self.up_celestial, -1)
        return get_instance_from_vector3(v)
    
    def get_east(self):
        '''
        In celestial coordinates
        '''
        self.calculate_local_north_and_up_in_celestial_coords(False)
        return get_instance_from_vector3(self.true_east_celestial)
    
    def get_west(self):
        '''
        In celestial coordinates
        '''
        self.calculate_local_north_and_up_in_celestial_coords(False)
        v = Geometry.scale_vector(self.true_east_celestial, -1)
        return get_instance_from_vector3(v)
    
    def set_mag_dec_calc(self, calculator):
        self.magnetic_declination_calc = calculator
        self.calculate_local_north_and_up_in_celestial_coords(True)
        
    def calculate_pointing(self):
        '''
        update the direction that the phone is pointing and the up vector
        perpendicular to the phone (in celestial coords).
        '''
        if not (self.auto_update_pointing): 
            return
        
        transform = Geometry.matrix_multiply(self.axes_magnetic_celestial_matrix, \
                                             self.axes_phone_inverse_matrix)

        view_in_space_space = \
            Geometry.matrix_vector_multiply(transform, self.POINTING_DIR_IN_PHONE_COORDS)
        screen_up_in_space_space = \
            Geometry.matrix_vector_multiply(transform, self.SCREEN_UP_IN_PHONE_COORDS)
            
        self.pointing.update_line_of_sight(view_in_space_space)
        self.pointing.update_perpendicular(screen_up_in_space_space)
        
    def calculate_local_north_and_up_in_celestial_coords(self, force_update):
        current_time = self.get_time_in_millis()
        diff = math.fabs(current_time - self.celestial_coords_last_updated)
        if (not force_update) and diff < self.MINIMUM_TIME_BETWEEN_CELESTIAL_COORD_UPDATES_MILLIS:
            return
        
        self.celestial_coords_last_updated = current_time
        self.update_magnetic_correction()
        up_ra, up_dec = Geometry.calculate_RADec_of_zenith(self.get_time(), self.location)
        self.up_celestial = get_instance(up_ra, up_dec)
        z = self.AXIS_OF_EARTHS_ROTATION
        z_dotu = Geometry.scalar_product(self.up_celestial, z)
        self.true_north_celestial = \
            Geometry.add_vectors(z, Geometry.scale_vector(self.up_celestial, -z_dotu))
        self.true_north_celestial.normalize()
        self.true_east_celestial = Geometry.vector_product(self.true_north_celestial, \
                                                           self.up_celestial)
        
        # Apply magnetic correction.  Rather than correct the phone's axes for
        # the magnetic declination, it's more efficient to rotate the
        # celestial axes by the same amount in the opposite direction.
        declination = self.magnetic_declination_calc.get_declination()
        rotation_matrix = Geometry.calculate_rotation_matrix(declination, self.up_celestial)
        magnetic_north_celestial = Geometry.matrix_vector_multiply(rotation_matrix, \
                                                                   self.true_north_celestial)
        magnetic_east_celestial = Geometry.vector_product(magnetic_north_celestial, \
                                                          self.up_celestial)
        self.axes_magnetic_celestial_matrix = get_colmatrix_from_vectors(magnetic_north_celestial, \
                                                                         self.up_celestial, \
                                                                         magnetic_east_celestial)
        
    def calculate_local_north_and_up_in_phone_coords(self):
        down = self.acceleration.copy()
        down.normalize()
        # Magnetic field goes *from* North to South, so reverse it.
        magnetic_field_to_north = self.magnetic_field.copy()
        magnetic_field_to_north.scale(-1)
        magnetic_field_to_north.normalize()
        
        # This is the vector to magnetic North *along the ground*.
        v2 = Geometry.scale_vector(down, -Geometry.scalar_product(magnetic_field_to_north, \
                                                                  down))
        magnetic_north_phone = Geometry.add_vectors(magnetic_field_to_north, v2)
        magnetic_north_phone.normalize()
        up_phone = Geometry.scale_vector(down, -1)
        magnetic_east_phone = Geometry.vector_product(magnetic_north_phone, up_phone)

        # The matrix is orthogonal, so transpose it to find its inverse.
        # Easiest way to do that is to construct it from row vectors instead
        # of column vectors.        
        self.axes_phone_inverse_matrix = \
            get_rowmatrix_from_vectors(magnetic_north_phone, 
                                       up_phone, 
                                       magnetic_east_phone)
    
    def update_magnetic_correction(self):
        self.magnetic_declination_calc.set_location_and_time(\
            self.location, self.get_time_in_millis())
    
    def get_pointing(self):
        self.calculate_local_north_and_up_in_phone_coords()
        self.calculate_pointing()
        return self.pointing
    
    def set_pointing(self, line_of_sight, perpendicular):
        '''
        Takes 2 vector3 objects as parameters
        '''
        self.pointing.update_line_of_sight(line_of_sight)
        self.pointing.update_perpendicular(perpendicular)

    def set_clock(self, clock):
        '''
        clock must have a get_time() method
        '''
        self.clock = clock
        self.calculate_local_north_and_up_in_celestial_coords(True)
        
    def get_time_in_millis(self):
        return int(self.clock.get_time() * 1000)

    def __init__(self, mag_dec_calc):
        '''
        Constructor
        '''
        self.auto_update_pointing = True
        self.field_of_view = 45  #Degrees
        self.location = LatLong(0, 0)
        self.clock = RealClock()
        self.celestial_coords_last_updated = -1
        
        # provides correction from true North to magnetic North 
        self.magnetic_declination_calc = mag_dec_calc
        
        #The pointing comprises a vector into the phone's screen expressed in
        #celestial coordinates combined with a perpendicular vector along the
        #phone's longer side.
        self.pointing = Pointing()
        
        #The sensor acceleration in the phone's coordinate system.
        self.acceleration = ApplicationConstants.INITIAL_DOWN
        
        #The sensor magnetic field in the phone's coordinate system.
        self.magnetic_field = ApplicationConstants.INITIAL_SOUTH
        
        #North along the ground in celestial coordinates.
        self.true_north_celestial = Vector3(1, 0, 0);
        
        #Up in celestial coordinates.
        self.up_celestial = Vector3(0, 1, 0)
        
        #East in celestial coordinates.
        self.true_east_celestial = self.AXIS_OF_EARTHS_ROTATION
        
        #[North, Up, East]^-1 in phone coordinates.
        self.axes_phone_inverse_matrix = get_identity_matrix();
        
        #[North, Up, East] in celestial coordinates. */
        self.axes_magnetic_celestial_matrix = get_identity_matrix();
Exemple #16
0
def scale_vector(v3, scale):
    '''
    return new scaled vector
    '''
    return Vector3(scale * v3.x, scale * v3.y, scale * v3.z)
Exemple #17
0
def add_vectors(v1, v2):
    '''
    return a new vector whos coordinates are the sum of the 
    two input vectors
    '''
    return Vector3(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z)
Exemple #18
0
    class MeteorRadiantSource(AbstractAstronomicalSource):
        '''
        Meteor Showers extend AstronomicalSource so that they can
        be rendered in the same way as other Astronomical sources.
        '''
        # G1 bug not present in PyOpenGL
        LABEL_COLOR = 0x817ef6
        UP = Vector3(0.0, 1.0, 0.0)
        UPDATE_FREQ_MS = 1 * MILLISECONDS_PER_DAY
        SCALE_FACTOR = 0.03

        def get_names(self):
            return self.search_names

        def get_search_location(self):
            return self.shower.radiant

        def update_shower(self):
            self.last_update_time_Ms = mktime(self.model.get_time())
            # We will only show the shower if it's the right time of year.
            now = self.model.get_time()
            # Standardize on the same year as we stored for the showers.
            now = dt.datetime(MeteorShowerLayer.ANY_OLD_YEAR, now.tm_mon,
                              now.tm_mday, 0, 0, 0).timetuple()

            self.the_image.set_up_vector(self.UP)
            if mktime(self.shower.start) < mktime(now) and \
                    mktime(self.shower.end) > mktime(now):
                self.label.label = self.name
                percent_to_peak = 0
                if (mktime(now) < mktime(self.shower.peak)):
                    percent_to_peak = (mktime(now) - mktime(self.shower.start)) / \
                        (mktime(self.shower.peak) - mktime(self.shower.start))
                else:
                    percent_to_peak = (mktime(self.shower.end) - mktime(now)) / \
                        (mktime(self.shower.end) - mktime(self.shower.peak))

                # Not sure how best to calculate number of meteors - use linear interpolation for now.
                number_of_meteors_per_hour = self.shower.peak_meteors_per_hour * percent_to_peak

                if number_of_meteors_per_hour > MeteorShowerLayer.METEOR_THRESHOLD_PER_HR:
                    self.the_image.set_image_id("meteor2_screen")
                else:
                    self.the_image.set_image_id("meteor1_screen")

            else:
                self.label.label = " "
                self.the_image.set_image_id("blank")

        def initialize(self):
            self.update_shower()
            return self

        #override(AbstractAstronomicalSource)
        def update(self):
            update_types = set()
            if abs(mktime(self.model.get_time()) -
                   self.last_update_time_Ms) > self.UPDATE_FREQ_MS:
                self.update_shower()
                update_types = set([RendererObjectManager().update_type.Reset])

            return update_types

        #override(AbstractAstronomicalSource)
        def get_images(self):
            return self.image_sources

        #override(AbstractAstronomicalSource)
        def get_labels(self):
            return self.label_sources

        def __init__(self, model, shower):
            '''
            constructor
            '''
            AbstractAstronomicalSource.__init__(self)
            self.image_sources = []
            self.label_sources = []

            self.lastUpdateTimeMs = 0
            self.search_names = []

            self.model = model
            self.shower = shower
            self.name = shower.name_id

            start_date = datetime.fromtimestamp(mktime(
                shower.start)).strftime('%m/%d')
            end_date = datetime.fromtimestamp(mktime(
                shower.end)).strftime('%m/%d')
            self.search_names.append(self.name + " (" + start_date + "-" +
                                     end_date + ")")

            # blank is a 1pxX1px image that should be invisible.
            # We'd prefer not to show any image except on the shower dates, but there
            # appears to be a bug in the renderer/layer interface in that Update values are not
            # respected.  Ditto the label.

            self.the_image = ImageSource(shower.radiant, "blank", self.UP,
                                         self.SCALE_FACTOR)
            self.image_sources.append(self.the_image)
            self.label = TextSource(self.name, self.LABEL_COLOR,
                                    shower.radiant)
            self.label_sources.append(self.label)
Exemple #19
0
def sum_vectors(v1, v2):
    return Vector3(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z)
Exemple #20
0
def negate(v):
    return Vector3(-v.x, -v.y, -v.z)
Exemple #21
0
    def update_objects(self, image_sources, update_types):
        '''
        takes a list of image sources and creates new buffers
        for these sources.
        '''

        # hack to get rid of blank meteor showers.
        image_sources = [img for img in image_sources if not img.is_blank]

        if self.update_type.Reset not in update_types and \
                len(image_sources) != len(self.images):
            return
        self.updates = self.updates | update_types  # set union

        num_vertices = len(image_sources) * 4
        vb = self.vertex_buffer
        vb.reset(num_vertices)

        tcb = self.text_coord_buffer
        tcb.reset(num_vertices)

        images = []
        reset = (self.update_type.Reset
                 in update_types) or (self.update_type.UpdateImages
                                      in update_types)
        if reset:
            images = [None] * len(image_sources)
        else:
            images = self.images

        if reset:
            for i in range(0, len(image_sources)):
                ims = image_sources[i]

                images[i] = self.Image()
                images[i].name = "no url"
                images[i].use_blending = False
                images[i].pixmap = ims.pixmap_image

        # Update the positions in the position and tex coord buffers.
        if reset or self.update_type.UpdatePositions in update_types:
            for i in range(0, len(image_sources)):
                ims = image_sources[i]
                xyz = ims.geocentric_coords
                px = xyz.x
                py = xyz.y
                pz = xyz.z

                u = ims.get_horizontal_corner()
                ux = u[0]
                uy = u[1]
                uz = u[2]

                v = ims.get_verical_corner()
                vx = v[0]
                vy = v[1]
                vz = v[2]

                # lower left
                vb.add_point(Vector3(px - ux - vx, py - uy - vy, pz - uz - vz))
                tcb.add_text_coord(0, 1)

                # upper left
                vb.add_point(Vector3(px - ux + vx, py - uy + vy, pz - uz + vz))
                tcb.add_text_coord(0, 0)

                # lower right
                vb.add_point(Vector3(px + ux - vx, py + uy - vy, pz + uz - vz))
                tcb.add_text_coord(1, 1)

                # upper right
                vb.add_point(Vector3(px + ux + vx, py + uy + vy, pz + uz + vz))
                tcb.add_text_coord(1, 0)

        # We already set the image in reset, so only set them here if we're
        # not doing a reset.
        if self.update_type.UpdateImages in update_types:
            for i in range(0, len(image_sources)):
                ims = image_sources[i]
                images[i].pixmap = ims.pixmap_image
        self.images = images
        self.queue_for_reload(False)
Exemple #22
0
def multiply_MV(mat, v):
    m = mat.values[:]
    return Vector3(m[0] * v.x + m[4] * v.y + m[8] * v.z + m[12],
                   m[1] * v.x + m[5] * v.y + m[9] * v.z + m[13],
                   m[2] * v.x + m[6] * v.y + m[10] * v.z + m[14])
Exemple #23
0
// language and additionally, may contain components and ideas that are 
// not found in the original source code.


   Copyright 2013 Neil Borle and Paul Lu

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.


Created on 2013-05-22

@author: Neil Borle
'''

from src.units.Vector3 import Vector3

APP_NAME = "SkyPython"
#Default value for 'south' in phone coords when the app starts
INITIAL_SOUTH = Vector3(0, -1, 0)
#Default value for 'down' in phone coords when the app starts
INITIAL_DOWN = Vector3(0, -1, -9)
Exemple #24
0
class PlanetSource(AbstractAstronomicalSource):
    '''
    An extension of AstronomicalSource for planets so that
    the elements of each planet can be rendered in a standard
    way.
    '''
    PLANET_SIZE = 3
    PLANET_COLOR = 0x14817EF6
    # The G1 rendering bug does not appear in this python code.
    PLANET_LABEL_COLOR = 0x817EF6
    SHOW_PLANETARY_IMAGES = "show_planetary_images"
    UP = Vector3(0.0, 1.0, 0.0)

    def get_names(self):
        return self.names.append(self.name)

    def update_coords(self, t_struct):
        self.last_update_time_Ms = time.mktime(t_struct)

        p = Planet(planet_enum.SUN, res[planet_enum.SUN][0],
                   res[planet_enum.SUN][1], res[planet_enum.SUN][2])
        self.sun_coords = get_instance(t_struct=t_struct, planet=p)

        ra_dec = radec_get_instance(earth_coord=self.sun_coords,
                                    planet=self.planet,
                                    time=t_struct)
        self.current_coords.update_from_ra_dec(ra_dec.ra, ra_dec.dec)
        for imgsrc in self.image_sources:
            imgsrc.set_up_vector(self.sun_coords)

    def initialize(self):
        time = self.model.get_time()
        self.update_coords(time)
        self.image_id = self.planet.get_image_resource_id(time)

        if self.planet.id == planet_enum.MOON:
            self.image_sources.append(
                ImageSource(self.current_coords, self.image_id,
                            self.sun_coords,
                            self.planet.get_planetary_image_size()))
        else:
            if USE_PLANETARY_IMAGES or self.planet.id == planet_enum.SUN:
                self.image_sources.append(
                    ImageSource(self.current_coords, self.image_id, self.UP,
                                self.planet.get_planetary_image_size()))
            else:
                self.point_sources.append(
                    PointSource(self.PLANET_COLOR, self.PLANET_SIZE,
                                self.current_coords))
        self.label_sources.append(
            TextSource(self.name, self.PLANET_LABEL_COLOR,
                       self.current_coords))

        return self

    #override(AbstractAstronomicalSource)
    def update(self):
        updates = set()

        model_time = self.model.get_time()
        if abs(time.mktime(model_time) -
               self.last_update_time_Ms) > self.planet.get_update_frequency_Ms:
            updates = updates | set(
                [RendererObjectManager().update_type.UpdatePositions])
            # update location
            self.update_coords(model_time)

            # For moon only:
            if self.planet.id == planet_enum.MOON and self.image_sources != []:
                # Update up vector.
                self.image_sources[0].set_up_vector(self.sun_coords)

                # update image:
                new_image_id = self.planet.get_image_resource_id(model_time)
                if new_image_id != self.image_id:
                    self.image_id = new_image_id
                    self.image_sources[0].image_id = new_image_id
                    updates = updates | set(
                        [RendererObjectManager().update_type.UpdateImages])

        return updates

    #override(AbstractAstronomicalSource)
    def get_points(self):
        return self.point_sources

    #override(AbstractAstronomicalSource)
    def get_labels(self):
        return self.label_sources

    #override(AbstractAstronomicalSource)
    def get_images(self):
        return self.image_sources

    def __init__(self, planet, model):
        '''
        Constructor
        '''
        AbstractAstronomicalSource.__init__(self)

        self.point_sources = []
        self.image_sources = []
        self.label_sources = []
        self.planet = planet
        self.model = model
        self.name = planet.name_resource_id
        self.current_coords = GeocentricCoordinates(0, 0, 0)
        self.sun_coords = None
        self.image_id = -1

        self.last_update_time_Ms = 0
Exemple #25
0
def zero():
    return Vector3(0, 0, 0)
Exemple #26
0
def cross_product(p1, p2):
    return Vector3(p1.y * p2.z - p1.z * p2.y, -p1.x * p2.z + p1.z * p2.x,
                   p1.x * p2.y - p1.y * p2.x)
Exemple #27
0
    def __init__(self, layer_id, texture_manager):
        '''
        Constructor
        '''
        RendererObjectManager.__init__(self, layer_id, texture_manager)

        self.vertex_buffer = VertexBuffer(0, True)
        self.color_buffer = ColorBuffer(0, True)
        self.index_buffer = IndexBuffer(0, True)
        self.sun_pos = GeocentricCoordinates(0, 1, 0)

        num_vertices = self.NUM_VERTEX_BANDS * self.NUM_STEPS_IN_BAND
        num_indices = (self.NUM_VERTEX_BANDS - 1) * self.NUM_STEPS_IN_BAND * 6
        self.vertex_buffer.reset(num_vertices)
        self.color_buffer.reset(num_vertices)
        self.index_buffer.reset(num_indices)

        sin_angles = [0.0] * self.NUM_STEPS_IN_BAND
        cos_angles = [0.0] * self.NUM_STEPS_IN_BAND

        angle_in_band = 0
        d_angle = 2 * math.pi / float(self.NUM_STEPS_IN_BAND - 1)
        for i in range(0, self.NUM_STEPS_IN_BAND):
            sin_angles[i] = math.sin(angle_in_band)
            cos_angles[i] = math.cos(angle_in_band)
            angle_in_band += d_angle

        band_step = 2.0 / float((self.NUM_VERTEX_BANDS - 1) + self.EPSILON)

        vb = self.vertex_buffer
        cb = self.color_buffer
        band_pos = 1
        for band in range(0, self.NUM_VERTEX_BANDS):
            a, r, g, b = 0, 0, 0, 0

            if band_pos > 0:
                intensity = long(band_pos * 20 + 50) & 0xFFFFFFFF
                a = 0xFF
                r = (intensity << 16) & 0x00FF0000
                g = (intensity << 16) & 0x0000FF00
                b = (intensity << 16) & 0x000000FF
            else:
                intensity = long(band_pos * 40 + 40) & 0xFFFFFFFF
                color = (intensity << 16) | (intensity << 8) | (intensity)
                a = 0xFF
                r = color & 0x00FF0000
                g = color & 0x0000FF00
                b = color & 0x000000FF

            band_pos -= band_step

            sin_phi = math.sqrt(1 -
                                band_pos * band_pos) if band_pos > -1 else 0
            for i in range(0, self.NUM_STEPS_IN_BAND):
                vb.add_point(
                    Vector3(cos_angles[i] * sin_phi, band_pos,
                            sin_angles[i] * sin_phi))
                cb.add_color(a, r, g, b)

        ib = self.index_buffer

        # Set the indices for the first band.
        top_band_start = 0
        bottom_band_start = self.NUM_STEPS_IN_BAND
        for triangle_band in range(0, self.NUM_VERTEX_BANDS - 1):
            for offset_from_start in range(0, self.NUM_STEPS_IN_BAND - 1):
                # Draw one quad as two triangles.
                top_left = (top_band_start + offset_from_start)
                top_right = (top_left + 1)

                bottom_left = (bottom_band_start + offset_from_start)
                bottom_right = (bottom_left + 1)

                # First triangle
                ib.add_index(top_left)
                ib.add_index(bottom_right)
                ib.add_index(bottom_left)

                # Second triangle
                ib.add_index(top_right)
                ib.add_index(bottom_right)
                ib.add_index(top_left)

            # Last quad: connect the end with the beginning.

            # Top left, bottom right, bottom left
            ib.add_index((top_band_start + self.NUM_STEPS_IN_BAND - 1))
            ib.add_index(bottom_band_start)
            ib.add_index((bottom_band_start + self.NUM_STEPS_IN_BAND - 1))

            # Top right, bottom right, top left
            ib.add_index(top_band_start)
            ib.add_index(bottom_band_start)
            ib.add_index((top_band_start + self.NUM_STEPS_IN_BAND - 1))

            top_band_start += self.NUM_STEPS_IN_BAND
            bottom_band_start += self.NUM_STEPS_IN_BAND