vkf_terrain Module

Maps and terrain: a celestial body drawn from map layers by Rocky (https://github.com/pelicanmapping/rocky; optional: rocky_available()), e.g. the Earth from tile services, or the Moon with NASA's imagery and LOLA's elevation. An addition to OpenFrames, which has only textured spheres.

The body is centered on its frame's origin, in body-fixed axes (z through the north pole, x through longitude 0), so the frame's attitude turns it. Its shape and coordinates come from Rocky's tiling profile: '' (Rocky's default) or 'global-geodetic' for the Earth (WGS84), 'moon' for the Moon (a sphere of 1737.4 km), or another of Rocky's profiles. Rocky works in meters; the body is drawn at units_per_meter scene units per meter (default 1e-3: kilometers, as vkframes' examples).

Layers (add_image_layer, add_elevation_layer) are tiled sources Rocky pages in as the view needs them: a TMS service (LAYER_TMS), a file or service GDAL reads (LAYER_GDAL; a file is found with find_data_file, e.g. data/'s moon_lola_ldem16.tif from pixi run -e rocky moon-data), or a {z}/{x}/{y} URL template of geodetic tiles on the body (LAYER_GEODETIC: 2 x 1 tiles at level 0, rows from the top, as WMTS and NASA's Moon Trek) or of web Mercator tiles (LAYER_MERCATOR: OpenStreetMap-style). Elevation is in meters (ELEVATION_HEIGHTS) or encoded in RGB (ELEVATION_MAPBOX, ELEVATION_TERRARIUM). Layers can be added before or after the body is shown.

Lighting: lit by the scene's lights as a Sphere (a frame's light source, e.g. the Sun, or the window's light; set_lighting(.false.) shows the imagery as it is). The frame's color is the color where no imagery covers the body.

The map is made for a window that shows the body (Rocky's tiles are loaded through that window's viewer, and the map is drawn in that window only); when that window closes, it is made again for one still open (other windows then show it). Headless (no viewer), the body has no map.


Uses

  • module~~vkf_terrain~~UsesGraph module~vkf_terrain vkf_terrain iso_c_binding iso_c_binding module~vkf_terrain->iso_c_binding module~vkf_files vkf_files module~vkf_terrain->module~vkf_files module~vkf_frames vkf_frames module~vkf_terrain->module~vkf_frames module~vkf_layer vkf_layer module~vkf_terrain->module~vkf_layer module~vkf_math vkf_math module~vkf_terrain->module~vkf_math module~vkf_pick vkf_pick module~vkf_terrain->module~vkf_pick module~vkf_frames->iso_c_binding module~vkf_frames->module~vkf_layer module~vkf_frames->module~vkf_math module~vkf_frames->module~vkf_pick module~vkf_follower vkf_follower module~vkf_frames->module~vkf_follower module~vkf_geometry vkf_geometry module~vkf_frames->module~vkf_geometry module~vkf_text vkf_text module~vkf_frames->module~vkf_text module~vkf_trajectory vkf_trajectory module~vkf_frames->module~vkf_trajectory module~vkf_layer->iso_c_binding iso_fortran_env iso_fortran_env module~vkf_math->iso_fortran_env module~vkf_pick->module~vkf_math module~vkf_follower->module~vkf_math module~vkf_follower->module~vkf_trajectory module~vkf_geometry->iso_c_binding module~vkf_geometry->module~vkf_layer module~vkf_geometry->module~vkf_math module~vkf_text->iso_c_binding module~vkf_text->module~vkf_files module~vkf_text->module~vkf_layer module~vkf_text->module~vkf_math module~vkf_trajectory->iso_c_binding module~vkf_trajectory->module~vkf_math module~vkf_trajectory->iso_fortran_env

Used by

  • module~~vkf_terrain~~UsedByGraph module~vkf_terrain vkf_terrain module~vkf_shadow vkf_shadow module~vkf_shadow->module~vkf_terrain module~vkframes vkframes module~vkframes->module~vkf_terrain module~vkframes->module~vkf_shadow

Variables

Type Visibility Attributes Name Initial
integer, public, parameter :: ELEVATION_HEIGHTS = 0

elevation encodings heights in meters

integer, public, parameter :: ELEVATION_MAPBOX = 1

Mapbox Terrain-RGB

integer, public, parameter :: ELEVATION_TERRARIUM = 2

Terrarium RGB

integer, public, parameter :: LAYER_GDAL = 1

a file or service GDAL reads

integer, public, parameter :: LAYER_GEODETIC = 2

a {z}/{x}/{y} URL template of geodetic tiles

integer, public, parameter :: LAYER_MERCATOR = 3

a {z}/{x}/{y} URL template of web Mercator tiles

integer, public, parameter :: LAYER_TMS = 0

layer sources (see the module documentation) a TMS service

real(kind=wp), private, parameter :: earth_radius = 6378137.0_wp

m (WGS84)

real(kind=wp), private, parameter :: moon_radius = 1737400.0_wp

m


Interfaces

public interface TerrainBody

The TerrainBody constructor: TerrainBody(...) makes one (see new_terrain_body for its arguments).

  • private function new_terrain_body(name, profile, units_per_meter, color) result(b)

    A body named name in Rocky's tiling profile profile (default '': the Earth; 'moon': the Moon), drawn at units_per_meter scene units per meter (default 1e-3), in color color where it has no imagery ([r, g, b] or [r, g, b, a]; default the frame's).

    Arguments

    Type IntentOptional Attributes Name
    character(len=*), intent(in) :: name

    the frame's name

    character(len=*), intent(in), optional :: profile

    Rocky's tiling profile (default '')

    real(kind=wp), intent(in), optional :: units_per_meter

    scene units per meter (default 1e-3)

    real(kind=wp), intent(in), optional :: color(:)

    [r, g, b] or [r, g, b, a] (0 to 1)

    Return Value type(TerrainBody)


Derived Types

type, private ::  MapLayer

A map layer as given (applied when the map is made).

Components

Type Visibility Attributes Name Initial
logical, public :: elevation = .false.

(true: an elevation layer; false: an image layer)

integer, public :: encoding = ELEVATION_HEIGHTS

(elevation: an ELEVATION_* constant)

integer, public :: source = LAYER_TMS

a LAYER_* constant

character(len=:), public, allocatable :: uri

URL, URL template or file

type, public, extends(ReferenceFrame) ::  TerrainBody

A body drawn from map layers by Rocky (see the module documentation).

Components

Type Visibility Attributes Name Initial
type(MapLayer), private, allocatable :: layers(:)

(capacity): the layers, in the order added

logical, private :: lighting_ = .true.

lit by the scene's lights

type(c_ptr), private :: map = c_null_ptr

Rocky's map node (null: not made)

type(c_ptr), private :: map_group = c_null_ptr

the group the map is in (once shown)

integer, private :: n_layers = 0

number of layers

character(len=:), private, allocatable :: profile_

Rocky's tiling profile ('': the Earth)

real(kind=wp), private :: units_per_meter_ = 1.0e-3_wp

scene units per meter

Constructor

The TerrainBody constructor: TerrainBody(...) makes one (see new_terrain_body for its arguments).

private function new_terrain_body (name, profile, units_per_meter, color)

A body named name in Rocky's tiling profile profile (default '': the Earth; 'moon': the Moon), drawn at units_per_meter scene units per meter (default 1e-3), in color color where it has no imagery ([r, g, b] or [r, g, b, a]; default the frame's).

Type-Bound Procedures

procedure, public :: add_child
procedure, public :: add_elevation_layer
procedure, public :: add_image_layer
procedure, public :: attitude
procedure, public :: axes_labels_shown
procedure, public :: axes_shown
procedure, public :: axis_label
procedure, public :: body_radius
procedure, public :: bound => terrain_bound
procedure, public :: build_contents => terrain_build_contents
procedure, public :: child
procedure, public :: child_index
procedure, public :: color
procedure, public :: contents_shown
procedure, public :: detach
procedure, public :: elevation
procedure, public :: follow
procedure, public :: follow_frame
procedure, public :: follower
procedure, public :: frame_info => terrain_frame_info
procedure, public :: frame_string
procedure, public :: has_light_source
procedure, public :: is_following
procedure, public :: label_alignment
procedure, public :: label_font
procedure, public :: label_size
procedure, public :: late_update
procedure, public :: light_ambient
procedure, public :: light_diffuse
procedure, public :: light_source_enabled
procedure, public :: light_specular
procedure, public :: lighting
procedure, public :: local_matrix
procedure, public :: local_matrix_at
procedure, public :: motion_key
procedure, public :: move_x_axis
procedure, public :: move_y_axis
procedure, public :: move_z_axis
procedure, public :: name
procedure, public :: name_label_on_top
procedure, public :: name_label_shown
procedure, public :: node
procedure, public :: num_children
procedure, public :: num_layers
procedure, public :: num_parents
procedure, public :: parent
procedure, public :: parent_index
procedure, public :: pick => terrain_pick
procedure, public :: pickable
procedure, public :: position
procedure, public :: position_of
procedure, public :: profile
procedure, public :: realize
procedure, public :: remove_child
procedure, public :: reposition_axes
procedure, public :: set_attitude
procedure, public :: set_color
procedure, public :: set_label_alignment
procedure, public :: set_label_font
procedure, public :: set_label_size
procedure, public :: set_light_ambient
procedure, public :: set_light_diffuse
procedure, public :: set_light_source_enabled
procedure, public :: set_light_specular
procedure, public :: set_lighting
procedure, public :: set_name
procedure, public :: set_name_label_on_top
procedure, public :: set_pickable
procedure, public :: set_position
procedure, public :: set_x_label
procedure, public :: set_y_label
procedure, public :: set_z_label
procedure, public :: show_axes
procedure, public :: show_axes_labels
procedure, public :: show_contents
procedure, public :: show_decorations
procedure, public :: show_name_label
procedure, public :: sync
procedure, public :: unfollow
procedure, public :: units_per_meter
procedure, public :: update => terrain_update
procedure, public :: world_matrix
procedure, public :: world_matrix_at

Functions

private pure function body_radius(self)

The body's equatorial radius in scene units (from its profile: the Moon's for 'moon', else the Earth's).

Arguments

Type IntentOptional Attributes Name
class(TerrainBody), intent(in) :: self

Return Value real(kind=wp)

private function elevation(self, lat, lon, found) result(h)

The height of the terrain (scene units, above the body's sphere or ellipsoid) at latitude and longitude lat, lon (degrees), from the last elevation layer added that is a file (LAYER_GDAL), read directly (also before the body is shown); found is false (and the height 0) without such a layer or data there, or without Rocky.

Arguments

Type IntentOptional Attributes Name
class(TerrainBody), intent(in) :: self
real(kind=wp), intent(in) :: lat

latitude and longitude (degrees)

real(kind=wp), intent(in) :: lon

latitude and longitude (degrees)

logical, intent(out), optional :: found

false if there is no height there

Return Value real(kind=wp)

private pure function lighting(self)

True if the body is lit by the scene's lights.

Arguments

Type IntentOptional Attributes Name
class(TerrainBody), intent(in) :: self

Return Value logical

private function new_terrain_body(name, profile, units_per_meter, color) result(b)

A body named name in Rocky's tiling profile profile (default '': the Earth; 'moon': the Moon), drawn at units_per_meter scene units per meter (default 1e-3), in color color where it has no imagery ([r, g, b] or [r, g, b, a]; default the frame's).

Arguments

Type IntentOptional Attributes Name
character(len=*), intent(in) :: name

the frame's name

character(len=*), intent(in), optional :: profile

Rocky's tiling profile (default '')

real(kind=wp), intent(in), optional :: units_per_meter

scene units per meter (default 1e-3)

real(kind=wp), intent(in), optional :: color(:)

[r, g, b] or [r, g, b, a] (0 to 1)

Return Value type(TerrainBody)

private pure function num_layers(self)

Number of layers (image and elevation).

Arguments

Type IntentOptional Attributes Name
class(TerrainBody), intent(in) :: self

Return Value integer

private function profile(self) result(p)

Rocky's tiling profile ('': Rocky's default, the Earth).

Arguments

Type IntentOptional Attributes Name
class(TerrainBody), intent(in) :: self

Return Value character(len=:), allocatable

public function rocky_available()

Whether vkframes was built with Rocky (the rocky pixi environment).

Arguments

None

Return Value logical

private function terrain_frame_info(self) result(info)

The kind of frame: 'TerrainBody'.

Arguments

Type IntentOptional Attributes Name
class(TerrainBody), intent(in) :: self

Return Value character(len=:), allocatable

private pure function units_per_meter(self)

Scene units per meter the body is drawn at.

Arguments

Type IntentOptional Attributes Name
class(TerrainBody), intent(in) :: self

Return Value real(kind=wp)


Subroutines

private subroutine add_elevation_layer(self, uri, source, encoding)

Add an elevation layer: uri of a source kind (LAYER_; default LAYER_TMS), heights in meters or encoding (ELEVATION_; default ELEVATION_HEIGHTS).

Arguments

Type IntentOptional Attributes Name
class(TerrainBody), intent(inout) :: self
character(len=*), intent(in) :: uri

a URL, URL template or file

integer, intent(in), optional :: source

a LAYER_* constant (default LAYER_TMS)

integer, intent(in), optional :: encoding

an ELEVATION_* constant (default ELEVATION_HEIGHTS)

private subroutine add_image_layer(self, uri, source)

Add an image layer: uri (a URL, URL template or file) of a source kind (LAYER_*; default LAYER_TMS). Layers added later are drawn on top.

Arguments

Type IntentOptional Attributes Name
class(TerrainBody), intent(inout) :: self
character(len=*), intent(in) :: uri

a URL, URL template or file

integer, intent(in), optional :: source

a LAYER_* constant (default LAYER_TMS)

private subroutine add_layer(self, layer)

Keep layer, and add it to the map if it is made.

Arguments

Type IntentOptional Attributes Name
type(TerrainBody), intent(inout) :: self
type(MapLayer), intent(in) :: layer

the layer as given

private subroutine apply_layer(self, layer)

Add layer to the map (a file found on VKFRAMES_DATA_PATH).

Arguments

Type IntentOptional Attributes Name
type(TerrainBody), intent(inout) :: self
type(MapLayer), intent(in) :: layer

the layer to add

private subroutine apply_settings(self)

Give the lighting and the frame's color to the map (if made).

Arguments

Type IntentOptional Attributes Name
type(TerrainBody), intent(inout) :: self

private subroutine make_map(self, viewer)

The map (in the contents group) for viewer, with the settings and layers.

Arguments

Type IntentOptional Attributes Name
type(TerrainBody), intent(inout) :: self
type(c_ptr), intent(in) :: viewer

a window's viewer handle

private subroutine set_lighting(self, lit)

Light the body with the scene's lights (default), or show its imagery as it is.

Arguments

Type IntentOptional Attributes Name
class(TerrainBody), intent(inout) :: self
logical, intent(in) :: lit

true: lit by the scene's lights; false: imagery as it is

private subroutine terrain_bound(self, center, radius)

The body's bounding sphere (frame coordinates): its equatorial radius, at the origin.

Arguments

Type IntentOptional Attributes Name
class(TerrainBody), intent(in) :: self
real(kind=wp), intent(out) :: center(3)

the bounding sphere, frame coordinates (scene units)

real(kind=wp), intent(out) :: radius

the bounding sphere, frame coordinates (scene units)

private subroutine terrain_build_contents(self, viewer, group)

The map, made for the viewer showing the body (none headless or without Rocky).

Arguments

Type IntentOptional Attributes Name
class(TerrainBody), intent(inout) :: self
type(c_ptr), intent(in) :: viewer

a window's viewer handle (null: headless)

type(c_ptr), intent(in) :: group

the group node to build under

private subroutine terrain_pick(self, cam, to_root, hits, n)

Picked on a sphere of the body's radius (not the terrain's heights), with the latitude and longitude of the point hit; else the frame's origin.

Arguments

Type IntentOptional Attributes Name
class(TerrainBody), intent(in), target :: self
type(PickCamera), intent(in) :: cam

the cursor's ray and the pick's settings

real(kind=wp), intent(in) :: to_root(4,4)

the frame's transform to the root frame

type(PickHit), intent(inout), allocatable :: hits(:)

hits so far (grown as needed)

integer, intent(inout) :: n

number of hits in hits

private recursive subroutine terrain_update(self, t)

Each frame: if the map's window has closed (the map was released with it), the map again for a window still open (compiled for the windows running), then the frame's update.

Arguments

Type IntentOptional Attributes Name
class(TerrainBody), intent(inout), target :: self
real(kind=wp), intent(in) :: t

simulation time (s)