Exemplo n.º 1
0
 def try_one_half_t_regular(model,
                            extent_kji=(2, 2, 2),
                            dxyz=(1.0, 1.0, 1.0),
                            perm_kji=(1.0, 1.0, 1.0),
                            ntg=1.0,
                            darcy_constant=1.0,
                            rotate=None,
                            dip=None):
     ones = np.ones(extent_kji)
     grid = grr.RegularGrid(model, extent_kji=extent_kji, dxyz=dxyz)
     if dip is not None:  # dip positive x axis downwards
         r_matrix = vec.rotation_matrix_3d_axial(1, dip)
         p = grid.points_ref(masked=False)
         p[:] = vec.rotate_array(r_matrix, p)
     if rotate is not None:  # rotate anticlockwise in xy plane (viewed from above)
         r_matrix = vec.rotation_matrix_3d_axial(2, rotate)
         p = grid.points_ref(masked=False)
         p[:] = vec.rotate_array(r_matrix, p)
     half_t = rqtr.half_cell_t(grid,
                               perm_k=perm_kji[0] * ones,
                               perm_j=perm_kji[1] * ones,
                               perm_i=perm_kji[2] * ones,
                               ntg=ntg * ones,
                               darcy_constant=darcy_constant)
     expected = 2.0 * darcy_constant * np.array(
         (perm_kji[0] * dxyz[0] * dxyz[1] / dxyz[2],
          ntg * perm_kji[1] * dxyz[0] * dxyz[2] / dxyz[1],
          ntg * perm_kji[2] * dxyz[1] * dxyz[2] / dxyz[0]))
     assert np.all(np.isclose(half_t, expected.reshape(1, 1, 1, 3)))
Exemplo n.º 2
0
    def local_to_global_array(self,
                              xyz: np.ndarray,
                              global_z_inc_down: bool = True):
        """Convert in situ a numpy array of xyz points from this coordinate reference system to the parent one."""

        if self.rotated:
            a = vec.rotate_array(self.reverse_rotation_matrix, xyz)
            xyz[:] = a
        if self.x_offset != 0.0:
            xyz[..., 0] += self.x_offset
        if self.y_offset != 0.0:
            xyz[..., 1] += self.y_offset
        if self.z_offset != 0.0:
            xyz[..., 2] += self.z_offset
        if global_z_inc_down != self.z_inc_down:
            z = np.negative(xyz[..., 2])
            xyz[..., 2] = z
Exemplo n.º 3
0
 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)
Exemplo n.º 4
0
Arquivo: _xyz.py Projeto: bp/resqpy
def _global_to_local_crs(grid,
                         a,
                         crs_uuid=None,
                         global_xy_units=None,
                         global_z_units=None,
                         global_z_increasing_downward=None):
    """Converts array of points in situ from global coordinate system to established local one."""

    if crs_uuid is None:
        crs_uuid = grid.crs_uuid
        if crs_uuid is None:
            return a

    flat_a = a.reshape((
        -1,
        3))  # flattened view of array a as vector of (x, y, z) points, in situ

    crs = rqc.Crs(grid.model, uuid=crs_uuid)

    if global_xy_units is not None:
        bwam.convert_lengths(flat_a[:, 0], global_xy_units, crs.xy_units)  # x
        bwam.convert_lengths(flat_a[:, 1], global_xy_units, crs.xy_units)  # y
    if global_z_units is not None:
        bwam.convert_lengths(flat_a[:, 2], global_z_units, crs.z_units)  # z

    # This code assumes x, y, z offsets are in local crs units
    flat_a[:, 0] -= crs.x_offset
    flat_a[:, 1] -= crs.y_offset
    flat_a[:, 2] -= crs.z_offset

    # note: here negation is made in local crs; if z_offset is not zero, this might not be what is intended
    if global_z_increasing_downward is not None:
        if global_z_increasing_downward != crs.z_inc_down:
            flat_a[:, 2] = np.negative(flat_a[:, 2])

    if crs.rotated:
        flat_a[:] = vec.rotate_array(crs.reverse_rotation_matrix, flat_a)

    return flat_a.reshape(a.shape)
Exemplo n.º 5
0
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
Exemplo n.º 6
0
    def set_from_point_set(self,
                           point_set,
                           convexity_parameter=5.0,
                           reorient=False,
                           reorient_max_dip=None,
                           extend_with_flange=False,
                           flange_point_count=11,
                           flange_radial_factor=10.0,
                           make_clockwise=False):
        """Populate this (empty) Surface object with a Delaunay triangulation of points in a PointSet object.

        arguments:
           point_set (PointSet): the set of points to be triangulated to form a surface
           convexity_parameter (float, default 5.0): controls how likely the resulting triangulation is to be
              convex; reduce to 1.0 to allow slightly more concavities; increase to 100.0 or more for very little
              chance of even a slight concavity
           reorient (bool, default False): if True, a copy of the points is made and reoriented to minimise the
              z range (ie. z axis is approximate normal to plane of points), to enhace the triangulation
           reorient_max_dip (float, optional): if present, the reorientation of perspective off vertical is
              limited to this angle in degrees
           extend_with_flange (bool, default False): if True, a ring of points is added around the outside of the
              points before the triangulation, effectively extending the surface with a flange
           flange_point_count (int, default 11): the number of points to generate in the flange ring; ignored if
              extend_with_flange is False
           flange_radial_factor (float, default 10.0): distance of flange points from centre of points, as a
              factor of the maximum radial distance of the points themselves; ignored if extend_with_flange is False
           make_clockwise (bool, default False): if True, the returned triangles will all be clockwise when
              viewed in the direction -ve to +ve z axis; if reorient is also True, the clockwise aspect is
              enforced in the reoriented space

        returns:
           if extend_with_flange is True, numpy bool array with a value per triange indicating flange trianges;
           if extent_with_flange is False, None

        note:
           if extend_with_flange is True, then a boolean array is created for the surface, with a value per triangle,
           set to False (zero) for non-flange triangles and True (one) for flange triangles; this array is
           suitable for adding as a property for the surface, with indexable element 'faces'
        """

        p = point_set.full_array_ref()
        if reorient:
            p_xy, self.normal_vector, reorient_matrix = triangulate.reorient(
                p, max_dip=reorient_max_dip)
        else:
            p_xy = p
        if extend_with_flange:
            flange_points = triangulate.surrounding_xy_ring(
                p_xy, flange_point_count, flange_radial_factor)
            p_xy_e = np.concatenate((p_xy, flange_points), axis=0)
            if reorient:
                # reorient back extenstion points into original p space
                flange_points_reverse_oriented = vec.rotate_array(
                    reorient_matrix.T, flange_points)
                p_e = np.concatenate((p, flange_points_reverse_oriented),
                                     axis=0)
            else:
                p_e = p_xy_e
        else:
            p_xy_e = p_xy
            p_e = p
        log.debug('number of points going into dt: ' + str(len(p_xy_e)))
        success = False
        try:
            t = triangulate.dt(p_xy_e[:, :2],
                               container_size_factor=convexity_parameter,
                               algorithm="scipy")
            success = True
        except AssertionError:
            pass
        if not success:
            log.warning(
                'triangulation failed, trying again with tiny perturbation of points'
            )
            p_xy_e[:, :2] += (np.random.random((len(p_xy_e), 2)) - 0.5) * 0.001
            t = triangulate.dt(p_xy_e[:, :2],
                               container_size_factor=convexity_parameter * 1.1)
        log.debug('number of triangles: ' + str(len(t)))
        if make_clockwise:
            triangulate.make_all_clockwise_xy(t, p_e)  # modifies t in situ
        self.crs_uuid = point_set.crs_uuid
        self.set_from_triangles_and_points(t, p_e)
        if extend_with_flange:
            flange_array = np.zeros(len(t), dtype=bool)
            flange_array[:] = np.where(np.any(t >= len(p), axis=1), True,
                                       False)
            return flange_array
        return None