def sail_point(centre, radius, a, d): # m = vec.rotation_3d_matrix((d, 0.0, 90.0 - a)) # m = vec.tilt_3d_matrix(a, d) v = np.array((0.0, radius, 0.0)) m = vec.rotation_matrix_3d_axial(0, d) v = vec.rotate_vector(m, v) m = vec.rotation_matrix_3d_axial(2, 90.0 + a) v = vec.rotate_vector(m, v) return centre + v
def test_rotation(): x = 47.3 y = -32.9 p = np.array((1234.2, 106.7, 742.5)) m = vec.rotation_3d_matrix((x, 0.0, y)) rm = vec.reverse_rotation_3d_matrix((x, 0.0, y)) pp = vec.rotate_vector(m, p) ppp = vec.rotate_vector(rm, pp) assert_array_almost_equal(p, ppp)
def global_to_local( self, xyz: PointType, global_z_inc_down: bool = True) -> Tuple[float, float, float]: """Convert a single xyz point from the parent coordinate reference system to this one.""" x, y, z = xyz if self.x_offset != 0.0: x -= self.x_offset if self.y_offset != 0.0: y -= self.y_offset if global_z_inc_down != self.z_inc_down: z = -z if self.z_offset != 0.0: z -= self.z_offset if self.rotated: (x, y, z) = vec.rotate_vector(self.rotation_matrix, np.array((x, y, z))) return (x, y, z)
def local_to_global( self, xyz: PointType, global_z_inc_down: bool = True) -> Tuple[float, float, float]: """Convert a single xyz point from this coordinate reference system to the parent one.""" if self.rotated: (x, y, z) = vec.rotate_vector(self.reverse_rotation_matrix, np.array(xyz)) else: (x, y, z) = xyz if self.x_offset != 0.0: x += self.x_offset if self.y_offset != 0.0: y += self.y_offset if self.z_offset != 0.0: z += self.z_offset if global_z_inc_down != self.z_inc_down: z = -z return (x, y, z)
def __calculate_trajectory_from_inclination_and_azimuth(self, survey): """ Calculate well trajectory from inclination and azimuth data.""" for sp in range(1, self.knot_count): i1 = survey.inclinations[sp - 1] i2 = survey.inclinations[sp] az1 = survey.azimuths[sp - 1] az2 = survey.azimuths[sp] delta_md = survey.measured_depths[sp] - survey.measured_depths[sp - 1] assert delta_md > 0.0 if i1 == i2 and az1 == az2: matrix = vec.rotation_3d_matrix( (180.0 - i1, -az1, 0.0)) # TODO: check sign of az1 delta_v = vec.rotate_vector(matrix, np.array([0.0, delta_md, 0.0])) else: i1 = maths.radians(i1) i2 = maths.radians(i2) az1 = maths.radians(az1) az2 = maths.radians(az2) sin_i1 = maths.sin(i1) sin_i2 = maths.sin(i2) cos_theta = min( max( maths.cos(i2 - i1) - sin_i1 * sin_i2 * (1.0 - maths.cos(az2 - az1)), -1.0), 1.0) theta = maths.acos(cos_theta) # theta = maths.acos(sin_i1 * sin_i2 * maths.cos(az2 - az1) + (maths.cos(i1) * maths.cos(i2))) assert theta != 0.0 # shouldn't happen as covered by if clause above half_rf = maths.tan(0.5 * theta) / theta delta_y = delta_md * half_rf * ((sin_i1 * maths.cos(az1)) + (sin_i2 * maths.cos(az2))) delta_x = delta_md * half_rf * ((sin_i1 * maths.sin(az1)) + (sin_i2 * maths.sin(az2))) delta_z = delta_md * half_rf * (maths.cos(i1) + maths.cos(i2)) delta_v = np.array((delta_x, delta_y, delta_z)) self.control_points[sp] = self.control_points[sp - 1] + delta_v
def reorient(points, rough=True, max_dip=None): """Returns a reoriented copy of a set of points, such that z axis is approximate normal to average plane of points. arguments: points (numpy float array of shape (..., 3)): the points to be reoriented rough (bool, default True): if True, the resulting orientation will be within around 10 degrees of the optimum; if False, that reduces to around 2.5 degrees of the optimum max_dip (float, optional): if present, the reorientation of perspective off vertical is limited to this angle in degrees returns: numpy float array of the same shape as points, numpy xyz vector, numpy 3x3 matrix; the array being a copy of points rotated in 3D space to minimise the z range; the vector is a normal vector to the original points; the matrix is rotation matrix used to transform the original points to the reoriented points notes: the original points array is not modified by this function; the function may typically be called prior to the Delauney triangulation, which uses an xy projection to determine the triangulation """ def z_range(p): return np.nanmax(p[..., 2]) - np.nanmin(p[..., 2]) def best_angles(points, mid_x, mid_y, steps, d_theta): best_range = None best_x_rotation = None best_y_rotation = None half_steps = float(steps - 1) / 2.0 for xi in range(steps): x_degrees = mid_x + (float(xi) - half_steps) * d_theta for yi in range(steps): y_degrees = mid_y + (float(yi) - half_steps) * d_theta rotation_m = vec.rotation_3d_matrix( (x_degrees, 0.0, y_degrees)) p = points.copy() rotated_p = vec.rotate_array(rotation_m, p) z_r = z_range(rotated_p) if best_range is None or z_r < best_range: best_range = z_r best_x_rotation = x_degrees best_y_rotation = y_degrees return (best_x_rotation, best_y_rotation) assert points.ndim >= 2 and points.shape[-1] == 3 # coarse iteration trying a few different angles best_x_rotation, best_y_rotation = best_angles(points, 0.0, 0.0, 7, 30.0) # finer iteration searching around the best coarse rotation best_x_rotation, best_y_rotation = best_angles(points, best_x_rotation, best_y_rotation, 5, 10.0) if not rough: # finer iteration searching around the best coarse rotation best_x_rotation, best_y_rotation = best_angles(points, best_x_rotation, best_y_rotation, 7, 2.5) rotation_m = vec.rotation_3d_matrix( (best_x_rotation, 0.0, best_y_rotation)) reverse_m = vec.reverse_rotation_3d_matrix( (best_x_rotation, 0.0, best_y_rotation)) # just the transpose of abpve! if max_dip is not None: v = vec.rotate_vector(reverse_m, np.array((0.0, 0.0, 1.0))) incl = vec.inclination(v) if incl > max_dip: azi = vec.azimuth(v) rotation_m = vec.tilt_3d_matrix( azi, max_dip ) # TODO: check whether any reverse direction errors here reverse_m = rotation_m.T p = points.copy() return vec.rotate_array(rotation_m, p), vec.rotate_vector(reverse_m, np.array((0.0, 0.0, 1.0))), rotation_m