resqpy.surface.Surface

class resqpy.surface.Surface(parent_model, uuid=None, point_set=None, mesh=None, mesh_file=None, mesh_format=None, tsurf_file=None, quad_triangles=False, title=None, surface_role='map', crs_uuid=None, originator=None, extra_metadata={})

Bases: BaseSurface

Class for RESQML triangulated set surfaces.

Public Data Attributes:

resqml_type

represented_interpretation_uuid

Returns the uuid of the represented surface interpretation, or None.

Inherited from BaseResqpy

resqml_type

part

Standard part name corresponding to self.uuid.

root

XML node corresponding to self.uuid.

citation_title

Citation block title equivalent to self.title.

Commonly Used Methods:

__init__(parent_model[, uuid, point_set, ...])

Create an empty Surface object (RESQML TriangulatedSetRepresentation).

triangles_and_points()

Returns arrays representing combination of all the patches in the surface.

column_from_triangle_index(triangle_index)

For surface freshly built from fully defined mesh, returns (j, i) for given triangle index.

set_to_horizontal_plane(depth, box_xyz[, ...])

Populate this (empty) surface with a patch of two triangles.

write_hdf5([file_name, mode])

Create or append to an hdf5 file, writing datasets for the triangulated patches after caching arrays.

create_xml([ext_uuid, add_as_part, ...])

Creates a triangulated surface xml node from this surface object and optionally adds as part of model.

Methods:

from_tri_mesh(tri_mesh)

Create a Surface from a TriMesh.

set_represented_interpretation_root(interp_root)

Makes a note of the xml root of the represented interpretation.

extract_patches(surface_root)

Scan surface root for triangle patches, create TriangulatedPatch objects and build up patch_list.

set_model(parent_model)

Associate the surface with a resqml model (does not create xml or write hdf5 data).

triangle_count()

Return the numner of triangles in this surface.

node_count()

Return the number of nodes (points) used in this surface.

change_crs(required_crs)

Changes the crs of the surface, also sets a new uuid if crs changed.

set_to_trimmed_surface(large_surface[, ...])

Populate this (empty) surface with triangles and points which overlap with a trimming volume.

set_to_split_surface(large_surface, line, ...)

Populate this (empty) surface with a version of a larger surface split by an xy line.

distinct_edges()

Returns a numpy int array of shape (N, 2) being the ordered node pairs of distinct edges of triangles.

distinct_edges_and_counts()

Returns unique edges as pairs of point indices, and a count of uses of each edge.

set_from_triangles_and_points(triangles, points)

Populate this (empty) Surface object from an array of triangle corner indices and an array of points.

set_from_point_set(point_set[, ...])

Populate this (empty) Surface object with a Delaunay triangulation of points in a PointSet object.

make_all_clockwise_xy([reorient])

Reorders cached triangles data such that all triangles are clockwise when viewed from -ve z axis.

unit_adjusted_points()

Returns cached points or copy thereof with z values adjusted to xy units.

normal()

Returns a vector that is roughly normal to the surface.

set_from_irregular_mesh(mesh_xyz[, ...])

Populate this (empty) Surface object from an untorn mesh array of shape (N, M, 3).

set_from_sparse_mesh(mesh_xyz)

Populate this (empty) Surface object from a mesh array of shape (N, M, 3) with NaNs.

set_from_mesh_object(mesh[, quad_triangles])

Populate the (empty) Surface object from a Mesh object.

set_from_torn_mesh(mesh_xyz[, quad_triangles])

Populate this (empty) Surface object from a torn mesh array of shape (nj, ni, 2, 2, 3).

set_to_single_cell_faces_from_corner_points(cp)

Populates this (empty) surface to represent faces of a cell, from corner points of shape (2, 2, 2, 3).

set_to_multi_cell_faces_from_corner_points(cp)

Populates this (empty) surface to represent faces of a set of cells.

cell_axis_and_polarity_from_triangle_index(...)

For surface freshly built for cell faces, returns (cell_number, face_axis, polarity).

set_to_triangle(corners)

Populate this (empty) surface with a patch of one triangle.

set_to_triangle_pair(corners)

Populate this (empty) surface with a patch of two triangles.

set_to_sail(n, centre, radius, azimuth, ...)

Populate this (empty) surface with a patch representing a triangle wrapped on a sphere.

set_from_mesh_file(filename, format[, ...])

Populate this (empty) surface from a zmap or RMS text mesh file.

set_from_tsurf_file(filename)

Populate this (empty) surface from a GOCAD tsurf file.

set_from_zmap_file(filename[, quad_triangles])

Populate this (empty) surface from a zmap mesh file.

set_from_roxar_file(filename[, quad_triangles])

Populate this (empty) surface from an RMS text mesh file.

set_from_rms_file(filename[, quad_triangles])

Populate this (empty) surface from an RMS text mesh file.

vertical_rescale_points([ref_depth, ...])

Modify the z values of points by rescaling.

line_intersection(line_p, line_v[, line_segment])

Returns x,y,z of an intersection point of straight line with the surface, or None if no intersection found.

sample_z_at_xy_points(points[, ...])

Returns interpolated z values for an array of xy values.

normal_vectors([add_as_property])

Returns the normal vectors for each triangle in the surface.

axial_edge_crossings(axis[, value])

Returns list-like array of points interpolated from triangle edges that cross value in axis.

resampled_surface([title])

Creates a new triangulated set which is a resampled version of the current triangulated set.

Inherited from BaseSurface

create_interpretation_and_feature([kind, ...])

Creates xml and objects for a represented interpretaion and interpreted feature, if not already present.

Inherited from BaseResqpy

__init__(parent_model[, uuid, point_set, ...])

Create an empty Surface object (RESQML TriangulatedSetRepresentation).

try_reuse()

Look for an equivalent existing RESQML object and modify the uuid of this object if found.

create_xml([ext_uuid, add_as_part, ...])

Creates a triangulated surface xml node from this surface object and optionally adds as part of model.

append_extra_metadata(meta_dict)

Append a given dictionary of metadata to the existing metadata.

__eq__(other)

Implements equals operator; uses is_equivalent() otherwise compares class type and uuid.

__ne__(other)

Implements not equal operator.

__repr__()

String representation.


__init__(parent_model, uuid=None, point_set=None, mesh=None, mesh_file=None, mesh_format=None, tsurf_file=None, quad_triangles=False, title=None, surface_role='map', crs_uuid=None, originator=None, extra_metadata={})[source]

Create an empty Surface object (RESQML TriangulatedSetRepresentation).

Optionally populates from xml, point set or mesh.

Parameters
  • parent_model (model.Model object) – the model to which this surface belongs

  • uuid (uuid.UUID, optional) – if present, the surface is initialised from an existing RESQML object with this uuid

  • point_set (PointSet object, optional) – if present, the surface is initialised as a Delaunay triangulation of the points in the point set; ignored if extracting from xml

  • mesh (Mesh object, optional) – if present, the surface is initialised as a triangulation of the mesh; ignored if extracting from xml or if point_set is present

  • mesh_file (string, optional) – the path of an ascii file holding a mesh in RMS text or zmap+ format; ignored if extracting from xml or point_set or mesh is present

  • mesh_format (string, optional) – ‘rms’ or ‘zmap’; required if initialising from mesh_file

  • tsurf_file (string, optional) – the path of an ascii file holding details of triangles and points in GOCAD-Tsurf format; ignored if extraction from xml or point_set or mesh is present

  • quad_triangles (boolean, default False) – if initialising from mesh or mesh_file, each ‘square’ is represented by 2 triangles if quad_triangles is False, 4 triangles if True

  • title (string, optional) – used as the citation title for the new object, ignored if extracting from xml

  • surface_role (string, default 'map') – ‘map’ or ‘pick’; ignored if uuid is not None

  • crs_uuid (uuid.UUID, optional) – if present and not extracting from xml, is set as the crs uuid applicable to mesh etc. data

  • originator (str, optional) – the name of the person creating the object; defaults to login id; ignored when initialising from an existing RESQML object

  • extra_metadata (dict) – items in this dictionary are added as extra metadata; ignored when initialising from an existing RESQML object

Returns

a newly created surface object

Notes

there are 6 ways to initialise a surface object, in order of precendence: 1. extracting from xml 2. as a Delaunay triangulation of points in a PointSet 3. as a simple triangulation of a Mesh object 4. as a simple triangulation of a mesh in an ascii file 5. from a GOCAD-TSurf format file 5. as an empty surface if an empty surface is created, set_from… methods are available to then set for one of: - a horizontal plane - a single triangle - a ‘sail’ (a triangle wrapped onto a sphere) - etc. the quad_triangles option is only applied if initialising from a mesh or mesh_file that is fully defined (ie. no NaN’s)

append_extra_metadata(meta_dict)

Append a given dictionary of metadata to the existing metadata.

axial_edge_crossings(axis, value=0.0)[source]

Returns list-like array of points interpolated from triangle edges that cross value in axis.

Parameters
  • axis (int) – xyz axis; 0 for crossings in x axis, 1 for y, 2 for z

  • value (float, default 0.0) – the value in axis at which crossing points are sought

Returns

numpy float array of shape (N, 3) being interpolated triangle edge points with the crossing

value in axis; or None if no crossings found

cell_axis_and_polarity_from_triangle_index(triangle_index)[source]

For surface freshly built for cell faces, returns (cell_number, face_axis, polarity).

Parameters

triangle_index (int or numpy int array) – the triangle index (or array of indices) for which cell face information is required

Returns

triple int – (cell_number, axis, polarity)

Note

if the surface was built for a single cell, the returned cell number will be zero

change_crs(required_crs)[source]

Changes the crs of the surface, also sets a new uuid if crs changed.

Note

this method is usually used to change the coordinate system for a temporary resqpy object; to add as a new part, call write_hdf5() and create_xml() methods

property citation_title

Citation block title equivalent to self.title.

column_from_triangle_index(triangle_index)[source]

For surface freshly built from fully defined mesh, returns (j, i) for given triangle index.

argument:

triangle_index (int or numpy int array): the triangle index (or array of indices) for which column(s) is/are being sought

Returns

pair of ints or pair of numpy int arrays – the (j0, i0) indices of the column(s) which the triangle(s) is/are part of

Notes

this function will only work if the surface has been freshly constructed with data from a mesh without NaNs, otherwise (None, None) will be returned; the information needed to map from triangle to column is not persistently stored as part of a resqml surface; if triangle_index is a numpy int array, a pair of similarly shaped numpy arrays is returned

create_interpretation_and_feature(kind='horizon', name=None, interp_title_suffix=None, is_normal=True)

Creates xml and objects for a represented interpretaion and interpreted feature, if not already present.

create_xml(ext_uuid=None, add_as_part=True, add_relationships=True, crs_uuid=None, title=None, originator=None)[source]

Creates a triangulated surface xml node from this surface object and optionally adds as part of model.

Parameters
  • ext_uuid (uuid.UUID) – the uuid of the hdf5 external part holding the surface arrays

  • add_as_part (boolean, default True) – if True, the newly created xml node is added as a part in the model

  • add_relationships (boolean, default True) – if True, a relationship xml part is created relating the new triangulated representation part to the crs part (and optional interpretation part)

  • crs_uuid (optional) – the uuid of the coordinate reference system applicable to the surface points data; if None, the main crs for the model is assumed to apply

  • title (string) – used as the citation Title text; should be meaningful to a human

  • originator (string, optional) – the name of the human being who created the triangulated representation part; default is to use the login name

Returns

the newly created triangulated representation (surface) xml node

distinct_edges()[source]

Returns a numpy int array of shape (N, 2) being the ordered node pairs of distinct edges of triangles.

distinct_edges_and_counts()[source]

Returns unique edges as pairs of point indices, and a count of uses of each edge.

Returns

numpy int array of shape (N, 2), numpy int array of shape (N,) where 2D array is list-like sorted points index pairs for unique edges and 1D array contains corresponding edge usage count (usually 1 or 2)

Notes

first entry in each pair is always the lower of the two point indices; for well formed surfaces, the count should everywhere be zero or one; the function does not attempt to detect coincident points

extract_patches(surface_root)[source]

Scan surface root for triangle patches, create TriangulatedPatch objects and build up patch_list.

classmethod from_tri_mesh(tri_mesh)[source]

Create a Surface from a TriMesh.

line_intersection(line_p, line_v, line_segment=False)[source]

Returns x,y,z of an intersection point of straight line with the surface, or None if no intersection found.

make_all_clockwise_xy(reorient=False)[source]

Reorders cached triangles data such that all triangles are clockwise when viewed from -ve z axis.

Note

if reorient is set True, a copy of the points is first reoriented such that they lie roughly in the xy plane, and the clockwise-ness of the triangles is effected in that space

node_count()[source]

Return the number of nodes (points) used in this surface.

normal()[source]

Returns a vector that is roughly normal to the surface.

Notes

the result becomes more meaningless the less planar the surface is; even for a parfectly planar surface, the result is approximate; true normal vector is found when xy & z units differ

normal_vectors(add_as_property: bool = False) ndarray[source]

Returns the normal vectors for each triangle in the surface.

Parameters

add_as_property (bool) – if True, face_surface_normal_vectors_array is added as a property to the model.

Returns

normal_vectors_array (np.ndarray) – the normal vectors corresponding to each triangle in the surface.

property part

Standard part name corresponding to self.uuid.

property represented_interpretation_uuid

Returns the uuid of the represented surface interpretation, or None.

resampled_surface(title=None)[source]

Creates a new triangulated set which is a resampled version of the current triangulated set. Each existing triangle in the tset is divided equally into 4 new triangles.

Parameters

title (str) – a new title for the output triangulated set, if None the title will have the same title as the input triangulated set

Returns

resqpy.surface.Surface object, with extra_metadata (‘resampled from surface’ – <uuid>), where uuid is the origin surface uuid

property root

XML node corresponding to self.uuid.

sample_z_at_xy_points(points, multiple_handling='any')[source]

Returns interpolated z values for an array of xy values.

Parameters
  • points (numpy float array of shape (..., 2 or 3)) – xy points to sample surface at (z values ignored)

  • multiple_handling (str, default 'any') – one of ‘any’, ‘minimum’, ‘maximum’, ‘exception’

Returns

numpy float array of shape points.shape[ – -1] being z values interpolated from the surface z values

Notes

points must be in the same crs as the surface; NaN will be set for any points that do not intersect with the surface in the xy projection; multiple_handling argument controls behaviour when one sample point intersects surface more than once: ‘any’ a random one of the intersection z values is returned; ‘minimum’ or ‘maximum’: the numerical min or max of the z values is returned; ‘exception’: a ValueError is raised

set_from_irregular_mesh(mesh_xyz, quad_triangles=False)[source]

Populate this (empty) Surface object from an untorn mesh array of shape (N, M, 3).

Parameters
  • mesh_xyz (numpy float array of shape (N, M, 3)) – a 2D lattice of points in 3D space

  • quad_triangles – (boolean, optional, default False): if True, each quadrangle is represented by 4 triangles in the surface, with the mean of the 4 corner points used as a common centre node; if False (the default), only 2 triangles are used for each quadrangle; note that the 2 triangle mode gives a non-unique triangulated result

set_from_mesh_file(filename, format, quad_triangles=False)[source]

Populate this (empty) surface from a zmap or RMS text mesh file.

set_from_mesh_object(mesh, quad_triangles=False)[source]

Populate the (empty) Surface object from a Mesh object.

set_from_point_set(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, flange_radial_distance=None, flange_inner_ring=False, saucer_parameter=None, make_clockwise=False)[source]

Populate this (empty) Surface object with a Delaunay triangulation of points in a PointSet object.

Parameters
  • 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

  • flange_radial_distance (float, optional) – if present, the minimum absolute distance of flange points from centre of points; units are those of the crs

  • flange_inner_ring (bool, default False) – if True, an inner ring of points, with double flange point counr, is created at a radius just outside that of the furthest flung original point; this improves triangulation of the extended point set when the original has a non-convex hull

  • saucer_parameter (float, optional) – if present, and extend_with_flange is True, then the fractional distance from the centre of the points to its rim at which to sample the surface for extrapolation and thereby modify the recumbent z of flange points; 0 will usually give shallower and smoother saucer; larger values (must be less than one) will lead to stronger and more erratic saucer shape in flange

  • 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 triangle indicating flange triangles; if extent_with_flange is False, None

Notes

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’; when flange extension occurs, the radius is the greater of the values determined from the radial factor and radial distance arguments

set_from_rms_file(filename, quad_triangles=False)[source]

Populate this (empty) surface from an RMS text mesh file.

set_from_roxar_file(filename, quad_triangles=False)[source]

Populate this (empty) surface from an RMS text mesh file.

set_from_sparse_mesh(mesh_xyz)[source]

Populate this (empty) Surface object from a mesh array of shape (N, M, 3) with NaNs.

Parameters

mesh_xyz (numpy float array of shape (N, M, 3)) – a 2D lattice of points in 3D space, with NaNs in z

set_from_torn_mesh(mesh_xyz, quad_triangles=False)[source]

Populate this (empty) Surface object from a torn mesh array of shape (nj, ni, 2, 2, 3).

Parameters
  • mesh_xyz (numpy float array of shape (nj, ni, 2, 2, 3)) – corner points of 2D faces in 3D space

  • quad_triangles – (boolean, optional, default False): if True, each quadrangle (face) is represented by 4 triangles in the surface, with the mean of the 4 corner points used as a common centre node; if False (the default), only 2 triangles are used for each quadrangle; note that the 2 triangle mode gives a non-unique triangulated result

Note

this method uses a single patch to represent the torn surface, whereas strictly the RESQML standard requires speparate patches where parts of a surface are completely disconnected

set_from_triangles_and_points(triangles, points)[source]

Populate this (empty) Surface object from an array of triangle corner indices and an array of points.

set_from_tsurf_file(filename)[source]

Populate this (empty) surface from a GOCAD tsurf file.

set_from_zmap_file(filename, quad_triangles=False)[source]

Populate this (empty) surface from a zmap mesh file.

set_model(parent_model)[source]

Associate the surface with a resqml model (does not create xml or write hdf5 data).

set_represented_interpretation_root(interp_root)[source]

Makes a note of the xml root of the represented interpretation.

set_to_horizontal_plane(depth, box_xyz, border=0.0, quad_triangles=False)[source]

Populate this (empty) surface with a patch of two triangles.

Triangles define a flat, horizontal plane at a given depth.

Parameters
  • depth (float) – z value to use in all points in the triangulated patch

  • box_xyz (float[2, 3]) – the min, max values of x, y (&z) giving the area to be covered (z ignored)

  • border (float) – an optional border width added around the x,y area defined by box_xyz

  • quad_triangles (bool, default False) – if True, 4 triangles are used instead of 2

set_to_multi_cell_faces_from_corner_points(cp, quad_triangles=True)[source]

Populates this (empty) surface to represent faces of a set of cells.

From corner points of shape (N, 2, 2, 2, 3).

set_to_sail(n, centre, radius, azimuth, delta_theta)[source]

Populate this (empty) surface with a patch representing a triangle wrapped on a sphere.

set_to_single_cell_faces_from_corner_points(cp, quad_triangles=True)[source]

Populates this (empty) surface to represent faces of a cell, from corner points of shape (2, 2, 2, 3).

set_to_split_surface(large_surface, line, delta_xyz)[source]

Populate this (empty) surface with a version of a larger surface split by an xy line.

Parameters
  • large_surface (Surface) – the larger surface, a copy of which is to be split

  • line (numpy float array of shape (2, 3)) – the end points of a line (z will be ignored)

  • delta_xyz (numpy float array of shape (2, 3)) – an xyz offset to add to the points on the right and left sides of the line repspectively

Notes

this method can be used to introduce a tear into a surface, typically to represent a horizon being split by a planar fault with a throw

set_to_triangle(corners)[source]

Populate this (empty) surface with a patch of one triangle.

set_to_triangle_pair(corners)[source]

Populate this (empty) surface with a patch of two triangles.

Parameters

corners (numpy float array of shape [2, 2, 3] or [4, 3]) – 4 corners in logical ordering

set_to_trimmed_surface(large_surface, xyz_box=None, xy_polygon=None)[source]

Populate this (empty) surface with triangles and points which overlap with a trimming volume.

Parameters
  • large_surface (Surface) – the larger surface, a copy of which is to be trimmed

  • xyz_box (numpy float array of shape (2, 3), optional) – if present, a cuboid in xyz space against which to trim the surface

  • xy_polygon (closed convex resqpy.lines.Polyline, optional) – if present, an xy boundary against which to trim

Notes

at least one of xyz_box or xy_polygon must be present; if both are present, a triangle must have at least one point within both boundaries to survive the trimming; xyz_box and xy_polygon must be in the same crs as the large surface

triangle_count()[source]

Return the numner of triangles in this surface.

triangles_and_points()[source]

Returns arrays representing combination of all the patches in the surface.

Returns

Tuple (triangles, points)

  • triangles (int array of shape[:, 3]): integer indices into points array, being the nodes of the corners of the triangles

  • points (float array of shape[:, 3]): flat array of xyz points, indexed by triangles

try_reuse()

Look for an equivalent existing RESQML object and modify the uuid of this object if found.

Returns

boolean – True if an equivalent object was found, False if not

Note

by design this method may change this object’s uuid as a side effect

unit_adjusted_points()[source]

Returns cached points or copy thereof with z values adjusted to xy units.

vertical_rescale_points(ref_depth=None, scaling_factor=1.0)[source]

Modify the z values of points by rescaling.

Stretches the distance from reference depth by scaling factor.

write_hdf5(file_name=None, mode='a')[source]

Create or append to an hdf5 file, writing datasets for the triangulated patches after caching arrays.

title

Citation title

originator

Creator of object. By default, user id.

uuid

Unique identifier