blob: b3d7fe191d8b2c5196378e712f9b3f91d12a1d31 [file] [log] [blame]
<!DOCTYPE HTML>
<html lang="en">
<head>
<!-- Generated by javadoc (21) on Thu Oct 05 19:54:57 CEST 2023 -->
<title>TileMatrix (Apache SIS 1.4 API)</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="dc.created" content="2023-10-05">
<meta name="description" content="declaration: module: org.apache.sis.storage, package: org.apache.sis.storage.tiling, interface: TileMatrix">
<meta name="generator" content="javadoc/ClassWriterImpl">
<meta name="keywords" content="org.apache.sis.storage.tiling.TileMatrix interface">
<meta name="keywords" content="getIdentifier()">
<meta name="keywords" content="getResolution()">
<meta name="keywords" content="getTilingScheme()">
<meta name="keywords" content="getTileStatus()">
<meta name="keywords" content="getTile()">
<meta name="keywords" content="getTiles()">
<link rel="stylesheet" type="text/css" href="../../../../../../stylesheet.css" title="Style">
<link rel="stylesheet" type="text/css" href="../../../../../../sis.css" title="Style">
<link rel="stylesheet" type="text/css" href="../../../../../../script-dir/jquery-ui.min.css" title="Style">
<script type="text/javascript" src="../../../../../../script.js"></script>
<script type="text/javascript" src="../../../../../../script-dir/jquery-3.6.1.min.js"></script>
<script type="text/javascript" src="../../../../../../script-dir/jquery-ui.min.js"></script>
</head>
<body class="class-declaration-page">
<script type="text/javascript">var pathtoroot = "../../../../../../";
loadScripts(document, 'script');</script>
<noscript>
<div>JavaScript is disabled on your browser.</div>
</noscript>
<div class="flex-box">
<header role="banner" class="flex-header">
<nav role="navigation">
<!-- ========= START OF TOP NAVBAR ======= -->
<div class="top-nav" id="navbar-top"><button id="navbar-toggle-button" aria-controls="navbar-top" aria-expanded="false" aria-label="Toggle navigation links"><span class="nav-bar-toggle-icon">&nbsp;</span><span class="nav-bar-toggle-icon">&nbsp;</span><span class="nav-bar-toggle-icon">&nbsp;</span></button>
<div class="skip-nav"><a href="#skip-navbar-top" title="Skip navigation links">Skip navigation links</a></div>
<ul id="navbar-top-firstrow" class="nav-list" title="Navigation">
<li><a href="../../../../../../index.html">Overview</a></li>
<li><a href="../../../../../module-summary.html">Module</a></li>
<li><a href="package-summary.html">Package</a></li>
<li class="nav-bar-cell1-rev">Class</li>
<li><a href="package-tree.html">Tree</a></li>
<li><a href="../../../../../../deprecated-list.html">Deprecated</a></li>
<li><a href="../../../../../../index-all.html">Index</a></li>
<li><a href="../../../../../../help-doc.html#class">Help</a></li>
</ul>
<ul class="sub-nav-list-small">
<li>
<p>Summary:</p>
<ul>
<li>Nested</li>
<li>Field</li>
<li>Constr</li>
<li><a href="#method-summary">Method</a></li>
</ul>
</li>
<li>
<p>Detail:</p>
<ul>
<li>Field</li>
<li>Constr</li>
<li><a href="#method-detail">Method</a></li>
</ul>
</li>
</ul>
</div>
<div class="sub-nav">
<div id="navbar-sub-list">
<ul class="sub-nav-list">
<li>Summary:&nbsp;</li>
<li>Nested&nbsp;|&nbsp;</li>
<li>Field&nbsp;|&nbsp;</li>
<li>Constr&nbsp;|&nbsp;</li>
<li><a href="#method-summary">Method</a></li>
</ul>
<ul class="sub-nav-list">
<li>Detail:&nbsp;</li>
<li>Field&nbsp;|&nbsp;</li>
<li>Constr&nbsp;|&nbsp;</li>
<li><a href="#method-detail">Method</a></li>
</ul>
</div>
<div class="nav-list-search"><a href="../../../../../../search.html">SEARCH</a>
<input type="text" id="search-input" disabled placeholder="Search">
<input type="reset" id="reset-button" disabled value="reset">
</div>
</div>
<!-- ========= END OF TOP NAVBAR ========= -->
<span class="skip-nav" id="skip-navbar-top"></span></nav>
</header>
<div class="flex-content">
<main role="main">
<!-- ======== START OF CLASS DATA ======== -->
<div class="header">
<div class="sub-title"><span class="module-label-in-type">Module</span>&nbsp;<a href="../../../../../module-summary.html">org.apache.sis.storage</a></div>
<div class="sub-title"><span class="package-label-in-type">Package</span>&nbsp;<a href="package-summary.html">org.apache.sis.storage.tiling</a></div>
<h1 title="Interface TileMatrix" class="title">Interface TileMatrix</h1>
</div>
<section class="class-description" id="class-description">
<dl class="notes">
<dt>All Known Subinterfaces:</dt>
<dd><code><a href="WritableTileMatrix.html" title="interface in org.apache.sis.storage.tiling">Writable­Tile­Matrix</a></code></dd>
</dl>
<hr>
<div class="type-signature"><span class="modifiers">public interface </span><span class="element-name type-name-label">TileMatrix</span></div>
<div class="block">A collection of tiles with the same size and properties placed on a regular grid with no overlapping.
A tile matrix usually has 2 dimensions (width and height), but this API allows any number of dimensions.
The number of dimensions is given by <code>get­Tiling­Scheme()​.get­Dimension()</code>.
<p>Unless otherwise specified in the Javadoc,
all methods in this interface expect non-null arguments are return non-null values.</p></div>
<dl class="notes">
<dt>Since:</dt>
<dd>1.2</dd>
</dl>
</section>
<section class="summary">
<ul class="summary-list">
<!-- ========== METHOD SUMMARY =========== -->
<li>
<section class="method-summary" id="method-summary">
<h2>Method Summary</h2>
<div id="method-summary-table">
<div class="table-tabs" role="tablist" aria-orientation="horizontal"><button id="method-summary-table-tab0" role="tab" aria-selected="true" aria-controls="method-summary-table.tabpanel" tabindex="0" onkeydown="switchTab(event)" onclick="show('method-summary-table', 'method-summary-table', 3)" class="active-table-tab">All Methods</button><button id="method-summary-table-tab2" role="tab" aria-selected="false" aria-controls="method-summary-table.tabpanel" tabindex="-1" onkeydown="switchTab(event)" onclick="show('method-summary-table', 'method-summary-table-tab2', 3)" class="table-tab">Instance Methods</button><button id="method-summary-table-tab3" role="tab" aria-selected="false" aria-controls="method-summary-table.tabpanel" tabindex="-1" onkeydown="switchTab(event)" onclick="show('method-summary-table', 'method-summary-table-tab3', 3)" class="table-tab">Abstract Methods</button></div>
<div id="method-summary-table.tabpanel" role="tabpanel">
<div class="summary-table three-column-summary" aria-labelledby="method-summary-table-tab0">
<div class="table-header col-first">Modifier and Type</div>
<div class="table-header col-second">Method</div>
<div class="table-header col-last">Description</div>
<div class="col-first even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3"><code><a href="http://www.geoapi.org/3.0/javadoc/org.opengis.geoapi/org/opengis/util/GenericName.html" title="class or interface in org.opengis.util" class="external-link">Generic­Name</a></code></div>
<div class="col-second even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3"><code><a href="#getIdentifier()" class="member-name-link">get­Identifier</a>()</code></div>
<div class="col-last even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3">
<div class="block">Returns an alphanumeric identifier which is unique in the <a href="TileMatrixSet.html" title="interface in org.apache.sis.storage.tiling"><code>Tile­Matrix­Set</code></a> that contains
this <code>Tile­Matrix</code>.</div>
</div>
<div class="col-first odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3"><code>double[]</code></div>
<div class="col-second odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3"><code><a href="#getResolution()" class="member-name-link">get­Resolution</a>()</code></div>
<div class="col-last odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3">
<div class="block">Returns the resolution (in units of CRS axes) at which tiles in this matrix should be used.</div>
</div>
<div class="col-first even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3"><code><a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Optional.html" title="class or interface in java.util" class="external-link">Optional</a><wbr>&lt;<a href="Tile.html" title="interface in org.apache.sis.storage.tiling">Tile</a>&gt;</code></div>
<div class="col-second even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3"><code><a href="#getTile(long...)" class="member-name-link">get­Tile</a><wbr>(long...&nbsp;indices)</code></div>
<div class="col-last even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3">
<div class="block">Gets a tile at the given indices.</div>
</div>
<div class="col-first odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3"><code><a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/stream/Stream.html" title="class or interface in java.util.stream" class="external-link">Stream</a><wbr>&lt;<a href="Tile.html" title="interface in org.apache.sis.storage.tiling">Tile</a>&gt;</code></div>
<div class="col-second odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3"><code><a href="#getTiles(org.apache.sis.coverage.grid.GridExtent,boolean)" class="member-name-link">get­Tiles</a><wbr>(<a href="../../../../../../org.apache.sis.feature/org/apache/sis/coverage/grid/GridExtent.html" title="class in org.apache.sis.coverage.grid">Grid­Extent</a>&nbsp;indices­Ranges,
boolean&nbsp;parallel)</code></div>
<div class="col-last odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3">
<div class="block">Retrieves a stream of existing tiles in the specified region.</div>
</div>
<div class="col-first even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3"><code><a href="TileStatus.html" title="enum class in org.apache.sis.storage.tiling">Tile­Status</a></code></div>
<div class="col-second even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3"><code><a href="#getTileStatus(long...)" class="member-name-link">get­Tile­Status</a><wbr>(long...&nbsp;indices)</code></div>
<div class="col-last even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3">
<div class="block">Fetches information about whether a tile exists, is missing or failed to load.</div>
</div>
<div class="col-first odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3"><code><a href="../../../../../../org.apache.sis.feature/org/apache/sis/coverage/grid/GridGeometry.html" title="class in org.apache.sis.coverage.grid">Grid­Geometry</a></code></div>
<div class="col-second odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3"><code><a href="#getTilingScheme()" class="member-name-link">get­Tiling­Scheme</a>()</code></div>
<div class="col-last odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3">
<div class="block">Returns a description about how space is partitioned into individual tiled units.</div>
</div>
</div>
</div>
</div>
</section>
</li>
</ul>
</section>
<section class="details">
<ul class="details-list">
<!-- ============ METHOD DETAIL ========== -->
<li>
<section class="method-details" id="method-detail">
<h2>Method Details</h2>
<ul class="member-list">
<li>
<section class="detail" id="getIdentifier()">
<h3>getIdentifier</h3>
<div class="member-signature"><span class="return-type"><a href="http://www.geoapi.org/3.0/javadoc/org.opengis.geoapi/org/opengis/util/GenericName.html" title="class or interface in org.opengis.util" class="external-link">GenericName</a></span>&nbsp;<span class="element-name">getIdentifier</span>()</div>
<div class="block">Returns an alphanumeric identifier which is unique in the <a href="TileMatrixSet.html" title="interface in org.apache.sis.storage.tiling"><code>Tile­Matrix­Set</code></a> that contains
this <code>Tile­Matrix</code>. The identifier is often a zoom level (as a number encoded in ASCII),
but this is not mandatory.</div>
<dl class="notes">
<dt>Returns:</dt>
<dd>a unique (within <a href="TileMatrixSet.html" title="interface in org.apache.sis.storage.tiling"><code>Tile­Matrix­Set</code></a>) identifier.</dd>
</dl>
</section>
</li>
<li>
<section class="detail" id="getResolution()">
<h3>getResolution</h3>
<div class="member-signature"><span class="return-type">double[]</span>&nbsp;<span class="element-name">getResolution</span>()</div>
<div class="block">Returns the resolution (in units of CRS axes) at which tiles in this matrix should be used.
If the tiled data is a <a href="../../../../../../org.apache.sis.feature/org/apache/sis/coverage/grid/GridCoverage.html" title="class in org.apache.sis.coverage.grid"><code>Grid­Coverage</code></a>,
then the resolution is typically the size of pixels in units of CRS axes.
That resolution may be evaluated at some representative point such as coverage center
if the pixel size is not constant everywhere.
<p>The array length shall be the number of CRS dimensions, and value at index <var>i</var>
is the resolution along CRS dimension <var>i</var> in units of the CRS axis <var>i</var>.</p></div>
<dl class="notes">
<dt>Returns:</dt>
<dd>resolution (in units of CRS axes) at which tiles in this matrix should be used.</dd>
<dt>See Also:</dt>
<dd>
<ul class="tag-list-long">
<li><a href="../../../../../../org.apache.sis.feature/org/apache/sis/coverage/grid/GridGeometry.html#getResolution(boolean)"><code>Grid­Geometry​.get­Resolution(boolean)</code></a></li>
</ul>
</dd>
</dl>
</section>
</li>
<li>
<section class="detail" id="getTilingScheme()">
<h3>getTilingScheme</h3>
<div class="member-signature"><span class="return-type"><a href="../../../../../../org.apache.sis.feature/org/apache/sis/coverage/grid/GridGeometry.html" title="class in org.apache.sis.coverage.grid">GridGeometry</a></span>&nbsp;<span class="element-name">getTilingScheme</span>()</div>
<div class="block">Returns a description about how space is partitioned into individual tiled units.
The description contains the extent of valid tile indices, the spatial reference system,
and the conversion from tile indices to the spatial reference system coordinates.
The CRS <em>shall</em> be the same as <a href="TileMatrixSet.html#getCoordinateReferenceSystem()"><code>Tile­Matrix­Set​.get­Coordinate­Reference­System()</code></a>.
The "grid to CRS" transform <em>should</em> be defined and <em>should</em> be affine.
The grid geometry <em>shall</em> have a <a href="../../../../../../org.apache.sis.feature/org/apache/sis/coverage/grid/GridExtent.html" title="class in org.apache.sis.coverage.grid"><code>Grid­Extent</code></a> which gives the range of valid indices
that can be used in calls to <a href="#getTile(long...)"><code>get­Tile(long...)</code></a> and <a href="#getTileStatus(long...)"><code>get­Tile­Status(long...)</code></a> methods.
<p>The "grid to CRS" transform converts tile indices to "real world" coordinates.
This conversion can follow two conventions:</p>
<ul class="verbose">
<li>The <a href="http://www.geoapi.org/3.0/javadoc/org.opengis.geoapi/org/opengis/referencing/datum/PixelInCell.html#CELL_CORNER" title="class or interface in org.opengis.referencing.datum" class="external-link"><code>Pixel­In­Cell​.CELL_CORNER</code></a> convention maps tile indices to the extreme corner
(in the direction of smallest indices) of the bounding box of the tile.
In a two-dimensional space having the usual display axis orientations,
this is the top-left corner of the top-left pixel.</li>
<li>The <a href="http://www.geoapi.org/3.0/javadoc/org.opengis.geoapi/org/opengis/referencing/datum/PixelInCell.html#CELL_CENTER" title="class or interface in org.opengis.referencing.datum" class="external-link"><code>Pixel­In­Cell​.CELL_CENTER</code></a> convention maps tile indices to the median value
of the tile bounding box in all dimensions.</li>
</ul>
<h4 id="relationship-with-ogc-specification-heading">Relationship with OGC specification</h4>
OGC has a more generic definition of <cite>tiling scheme</cite>,
where the scheme specifies which space a uniquely identified tile occupies.
Reversely, the tiling scheme makes possible to find which unique identifier
corresponds to a space satisfying the geometric properties to be a tile.
In <code>Tile­Matrix</code>, the unique identifier of a tile is the sequence of
tile indices stored in a <code>long[]</code> array.
The space occupied by a tile can be computed by the above-cited "grid to CRS" transform.
Reversely the tile indices for a given space can be computed by the inverse of the "grid to CRS" transform.</div>
<dl class="notes">
<dt>Returns:</dt>
<dd>extent of valid tile indices (mandatory) and their relationship with "real world" coordinates (optional).</dd>
<dt>See Also:</dt>
<dd>
<ul class="tag-list-long">
<li><a href="TileMatrixSet.html#getCoordinateReferenceSystem()"><code>Tile­Matrix­Set​.get­Coordinate­Reference­System()</code></a></li>
</ul>
</dd>
</dl>
</section>
</li>
<li>
<section class="detail" id="getTileStatus(long...)">
<h3>getTileStatus</h3>
<div class="member-signature"><span class="return-type"><a href="TileStatus.html" title="enum class in org.apache.sis.storage.tiling">TileStatus</a></span>&nbsp;<span class="element-name">getTileStatus</span><wbr><span class="parameters">(long...&nbsp;indices)</span>
throws <span class="exceptions"><a href="../DataStoreException.html" title="class in org.apache.sis.storage">DataStoreException</a></span></div>
<div class="block">Fetches information about whether a tile exists, is missing or failed to load.
The accuracy of a tile status greatly varies with each protocol.
If the returned value is different than <a href="TileStatus.html#UNKNOWN"><code>Tile­Status​.UNKNOWN</code></a>, then:
<table class="sis">
<caption>Relationship between return value and tile fetching behavior}</caption>
<tr><th>Return value</th> <th>Consequence</th></tr>
<tr><td><a href="TileStatus.html#EXISTS"><code>TileStatus.EXISTS</code></a></td> <td><code>getTile(indices)</code> should return a non-empty value.</td></tr>
<tr><td><a href="TileStatus.html#MISSING"><code>TileStatus.MISSING</code></a></td> <td><code>getTile(indices)</code> should return an empty value.</td></tr>
<tr><td><a href="TileStatus.html#OUTSIDE_EXTENT"><code>TileStatus.OUTSIDE_EXTENT</code></a></td> <td><code>getTile(indices)</code> should throw <a href="../NoSuchDataException.html" title="class in org.apache.sis.storage"><code>No­Such­Data­Exception</code></a>.</td></tr>
<tr><td><a href="TileStatus.html#IN_ERROR"><code>TileStatus.IN_ERROR</code></a></td> <td><code>getTile(indices)</code> should throw <a href="../DataStoreException.html" title="class in org.apache.sis.storage"><code>Data­Store­Exception</code></a> (or a sub-type).</td></tr>
</table></div>
<dl class="notes">
<dt>Parameters:</dt>
<dd><code>indices</code> - indices of the requested tile (may be outside the tile matrix extent).</dd>
<dt>Returns:</dt>
<dd>information about the availability of the specified tile,
or <a href="TileStatus.html#OUTSIDE_EXTENT"><code>Tile­Status​.OUTSIDE_EXTENT</code></a> if the given indices are invalid.</dd>
<dt>Throws:</dt>
<dd><code><a href="../DataStoreException.html" title="class in org.apache.sis.storage">Data­Store­Exception</a></code> - if fetching the tile status failed.</dd>
<dt>See Also:</dt>
<dd>
<ul class="tag-list">
<li><a href="Tile.html#getStatus()"><code>Tile​.get­Status()</code></a></li>
</ul>
</dd>
</dl>
</section>
</li>
<li>
<section class="detail" id="getTile(long...)">
<h3>getTile</h3>
<div class="member-signature"><span class="return-type"><a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Optional.html" title="class or interface in java.util" class="external-link">Optional</a>&lt;<a href="Tile.html" title="interface in org.apache.sis.storage.tiling">Tile</a>&gt;</span>&nbsp;<span class="element-name">getTile</span><wbr><span class="parameters">(long...&nbsp;indices)</span>
throws <span class="exceptions"><a href="../DataStoreException.html" title="class in org.apache.sis.storage">DataStoreException</a></span></div>
<div class="block">Gets a tile at the given indices.</div>
<dl class="notes">
<dt>Parameters:</dt>
<dd><code>indices</code> - indices of the tile to fetch, as coordinates inside the matrix <a href="../../../../../../org.apache.sis.feature/org/apache/sis/coverage/grid/GridExtent.html" title="class in org.apache.sis.coverage.grid"><code>Grid­Extent</code></a>.</dd>
<dt>Returns:</dt>
<dd>the tile if it <a href="TileStatus.html#EXISTS">exists</a>,
or an empty value if the tile is <a href="TileStatus.html#MISSING">missing</a>.</dd>
<dt>Throws:</dt>
<dd><code><a href="../NoSuchDataException.html" title="class in org.apache.sis.storage">No­Such­Data­Exception</a></code> - if the given indices are
<a href="TileStatus.html#OUTSIDE_EXTENT">outside the matrix extent</a>.</dd>
<dd><code><a href="../DataStoreException.html" title="class in org.apache.sis.storage">Data­Store­Exception</a></code> - if fetching the tile failed for another reason.</dd>
</dl>
</section>
</li>
<li>
<section class="detail" id="getTiles(org.apache.sis.coverage.grid.GridExtent,boolean)">
<h3>getTiles</h3>
<div class="member-signature"><span class="return-type"><a href="https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/stream/Stream.html" title="class or interface in java.util.stream" class="external-link">Stream</a>&lt;<a href="Tile.html" title="interface in org.apache.sis.storage.tiling">Tile</a>&gt;</span>&nbsp;<span class="element-name">getTiles</span><wbr><span class="parameters">(<a href="../../../../../../org.apache.sis.feature/org/apache/sis/coverage/grid/GridExtent.html" title="class in org.apache.sis.coverage.grid">GridExtent</a>&nbsp;indicesRanges,
boolean&nbsp;parallel)</span>
throws <span class="exceptions"><a href="../DataStoreException.html" title="class in org.apache.sis.storage">DataStoreException</a></span></div>
<div class="block">Retrieves a stream of existing tiles in the specified region. The stream contains
the <a href="TileStatus.html#EXISTS">existing</a> tiles that are inside the given region
and excludes all <a href="TileStatus.html#MISSING">missing</a> tiles.
If a tile is <a href="TileStatus.html#IN_ERROR">in error</a>,
then the stream should nevertheless return a <a href="Tile.html" title="interface in org.apache.sis.storage.tiling"><code>Tile</code></a> instance
but its <a href="Tile.html#getResource()"><code>Tile​.get­Resource()</code></a> method should throw the exception.
<p>The <code>parallel</code> argument specifies whether a parallelized stream is desired.
If <code>false</code>, the stream is guaranteed to be sequential.
If <code>true</code>, the stream may or may not be parallel;
implementations are free to ignore this argument if they do not support parallelism.</p></div>
<dl class="notes">
<dt>Parameters:</dt>
<dd><code>indices­Ranges</code> - ranges of tile indices in all dimensions, or <code>null</code> for all tiles.</dd>
<dd><code>parallel</code> - <code>true</code> for a parallel stream (if supported), or <code>false</code> for a sequential stream.</dd>
<dt>Returns:</dt>
<dd>stream of tiles, excluding <a href="TileStatus.html#MISSING">missing</a> tiles.
Iteration order of the stream may vary from one implementation to another and from one call to another.</dd>
<dt>Throws:</dt>
<dd><code><a href="../DataStoreException.html" title="class in org.apache.sis.storage">Data­Store­Exception</a></code> - if the stream creation failed.</dd>
</dl>
</section>
</li>
</ul>
</section>
</li>
</ul>
</section>
<!-- ========= END OF CLASS DATA ========= -->
</main>
</div>
</div>
</body>
</html>