docs: def get_rupture_surface(mag, nodal_plane, hypocenter, msr,
                          rupture_aspect_ratio, upper_seismogenic_depth,
                          lower_seismogenic_depth, mesh_spacing=1.0):
      """
      Create and return rupture surface object with given properties.
  
      :param mag:
          Magnitude value, used to calculate rupture dimensions,
          see :meth:`_get_rupture_dimensions`.
      :param nodal_plane:
          Instance of :class:`openquake.hazardlib.geo.nodalplane.NodalPlane`
          describing the rupture orientation.
      :param hypocenter:
          Point representing rupture's hypocenter.
      :returns:
          Instance of
          :class:`~openquake.hazardlib.geo.surface.planar.PlanarSurface`.
      """
      assert (upper_seismogenic_depth <= hypocenter.depth
              and lower_seismogenic_depth >= hypocenter.depth)
      rdip = math.radians(nodal_plane.dip)
  
      # precalculated azimuth values for horizontal-only and vertical-only
      # moves from one point to another on the plane defined by strike
      # and dip:
      azimuth_right = nodal_plane.strike
      azimuth_down = (azimuth_right + 90) % 360
      azimuth_left = (azimuth_down + 90) % 360
      azimuth_up = (azimuth_left + 90) % 360
  
      rup_length, rup_width = get_rupture_dimensions(
          mag, nodal_plane, msr, rupture_aspect_ratio, upper_seismogenic_depth,
          lower_seismogenic_depth)
      # calculate the height of the rupture being projected
      # on the vertical plane:
      rup_proj_height = rup_width * math.sin(rdip)
      # and it's width being projected on the horizontal one:
      rup_proj_width = rup_width * math.cos(rdip)
  
      # half height of the vertical component of rupture width
      # is the vertical distance between the rupture geometrical
      # center and it's upper and lower borders:
      hheight = rup_proj_height / 2
      # calculate how much shallower the upper border of the rupture
      # is than the upper seismogenic depth:
      vshift = upper_seismogenic_depth - hypocenter.depth + hheight
      # if it is shallower (vshift > 0) than we need to move the rupture
      # by that value vertically.
      if vshift < 0:
          # the top edge is below upper seismogenic depth. now we need
          # to check that we do not cross the lower border.
          vshift = lower_seismogenic_depth - hypocenter.depth - hheight
          if vshift > 0:
              # the bottom edge of the rupture is above the lower sesmogenic
              # depth. that means that we don't need to move the rupture
              # as it fits inside seismogenic layer.
              vshift = 0
          # if vshift < 0 than we need to move the rupture up by that value.
  
      # now we need to find the position of rupture's geometrical center.
      # in any case the hypocenter point must lie on the surface, however
      # the rupture center might be off (below or above) along the dip.
      rupture_center = hypocenter
      if vshift != 0:
          # we need to move the rupture center to make the rupture fit
          # inside the seismogenic layer.
          hshift = abs(vshift / math.tan(rdip))
          rupture_center = rupture_center.point_at(
              horizontal_distance=hshift, vertical_increment=vshift,
              azimuth=(azimuth_up if vshift < 0 else azimuth_down))
  
      # from the rupture center we can now compute the coordinates of the
      # four coorners by moving along the diagonals of the plane. This seems
      # to be better then moving along the perimeter, because in this case
      # errors are accumulated that induce distorsions in the shape with
      # consequent raise of exceptions when creating PlanarSurface objects
      # theta is the angle between the diagonal of the surface projection
      # and the line passing through the rupture center and parallel to the
      # top and bottom edges. Theta is zero for vertical ruptures (because
      # rup_proj_width is zero)
      theta = math.degrees(
          math.atan((rup_proj_width / 2.) / (rup_length / 2.)))
      hor_dist = math.sqrt(
          (rup_length / 2.) ** 2 + (rup_proj_width / 2.) ** 2)
      left_top = rupture_center.point_at(
          horizontal_distance=hor_dist,
          vertical_increment=-rup_proj_height / 2,
          azimuth=(nodal_plane.strike + 180 + theta) % 360)
      right_top = rupture_center.point_at(
          horizontal_distance=hor_dist,
          vertical_increment=-rup_proj_height / 2,
          azimuth=(nodal_plane.strike - theta) % 360)
      left_bottom = rupture_center.point_at(
          horizontal_distance=hor_dist,
          vertical_increment=rup_proj_height / 2,
          azimuth=(nodal_plane.strike + 180 - theta) % 360)
      right_bottom = rupture_center.point_at(
          horizontal_distance=hor_dist,
          vertical_increment=rup_proj_height / 2,
          azimuth=(nodal_plane.strike + theta) % 360)
      return PlanarSurface(nodal_plane.strike, nodal_plane.dip,
                           left_top, right_top, right_bottom, left_bottom)