mirror of
https://expo.survex.com/repositories/troggle/.git
synced 2024-11-21 23:01:52 +00:00
518 lines
18 KiB
HTML
518 lines
18 KiB
HTML
{% extends "base.html" %}
|
|
{% block title %}Cave Entrances and other locations in UTM{% endblock %}
|
|
|
|
{% block content %}
|
|
|
|
<style>
|
|
th, td {
|
|
padding-left: 5px;
|
|
padding-right: 5px;
|
|
}
|
|
</style>
|
|
<h1>Entrance locations</h1>
|
|
|
|
<p>This table is of all the survex stations in troggle: i.e. only those survey stations which have been identified with an Entrance by manually editing the Entrance data.</p>
|
|
|
|
<p>The SRTM altitude is that measured at a nearby reference point.
|
|
The horizontal distance between the survey station and the SRTM reference point is shown in the "SRTM ref" column.
|
|
It is always less than 35m for our dataset. Differences between the recorded altitude
|
|
and the SRTM altitude are in <b>bold</b> if the discrepancy is more than 60m vertically.</p>
|
|
|
|
<p>Unless otherwise specified data is expressed in UTM in WGS84 datum. Coordinates are expresed in meters.</p>
|
|
|
|
<p>Click on column headings to sort.</p>
|
|
|
|
<table cellpadding="6" cellspacing="8" class="table-sort">
|
|
<tr><th>Survex Station</th><th>x [m]</th><th>y [m]</th><th>lat. [deg]</th><th>long. [deg]</th><th>alt [m]</th><th>SRTM<br> alt</th><th>SRTM [m]<br> ref</th><th>Used on <br />this Entrance</th><th>Cave</th></tr>
|
|
{% for s in stations %}
|
|
<tr>
|
|
<td style="text-align:left; " id="{{s.name|safe}}"> <a href="/entrances#{{s.name|safe}}">{{s.name|safe}}</a> </td>
|
|
<td style="text-align:right; width:10"> {{s.x|floatformat:2}} </td>
|
|
<td style="text-align:right; width:10"> {{s.y|floatformat:2}} </td>
|
|
<!--
|
|
<td style="text-align:right; width:10"> <em>{{s.lat|floatformat:6}} </em></td>
|
|
<td style="text-align:right; width:10"> <em>{{s.long|floatformat:6}} </em></td>
|
|
-->
|
|
|
|
<td>{% if s.lat %}
|
|
<a href="https://www.openstreetmap.org/?mlat={{ s.lat|floatformat:7}}&mlon={{s.long|floatformat:7}}"><em>{{s.lat|floatformat:6}} </em>{% endif %}</td>
|
|
|
|
<td>{% if s.lat %}
|
|
<a href="https://www.openstreetmap.org/?mlat={{ s.lat|floatformat:7}}&mlon={{s.long|floatformat:7}}"><em>{{s.long|floatformat:6}} </em>{% endif %}</td>
|
|
|
|
|
|
<td style="text-align:right; "> {{s.z|floatformat:0}} </td>
|
|
<td style="text-align:right; "> {{s.srtm_diff.0|safe}} </td>
|
|
<td style="text-align:right; "> {{s.srtm_diff.1|floatformat:0}} </td>
|
|
<td style="text-align:right;" > <small><a href="/cave/{{s.entrance.firstcave|safe}}">{{s.entrance|safe}}</a></small> </td>
|
|
<td style="text-align:right;" > <small>
|
|
{% if s.entrance.firstcave.official_name %}
|
|
{{s.entrance.firstcave.official_name|safe}}
|
|
{% else %}
|
|
<em>{{s.entrance.firstcave|safe}}</em>
|
|
{% endif %}</small>
|
|
</td>
|
|
</tr>
|
|
{% empty %}
|
|
<td colspan="3"> NO STATION DATA - This is due to survex (cavern) failing on the entire dataset.
|
|
<br>See <a href="/dataissues">DataIssues</a> 'survex' section .
|
|
<br>Resolve the survex errors and do a full databasereset import.
|
|
<br>You should look at the .log and .err files produced by survex in the :loser: repo folder first.
|
|
<br>
|
|
<br>Probably, the generaton of the .3d file has failed, so the .pos file is not generated.
|
|
<br> Look for a message like this 'Failed to find /mnt/d/EXPO/loser/1623-and-1626-no-schoenberg-hs.3d so aborting generation of new .pos, using old one if present'
|
|
</td>
|
|
{% endfor %}
|
|
</table>
|
|
|
|
|
|
|
|
<h3>These caves have GPS data directly on them, not via survex survey stations</h3>
|
|
<p>Because these are only vague locations identified from aerial photos, they have not
|
|
been surveyed to.
|
|
<table>
|
|
<tr><th>Cave</th>
|
|
<th>Alt</th>
|
|
<th>GPS Lat</th><th>GPS Long</th>
|
|
<th>best Lat</th><th>best Long</th>
|
|
</tr>
|
|
{% for ent in gpsents %}
|
|
<tr>
|
|
<td style="text-align:left">
|
|
{% for c in ent.cavelist %}
|
|
<a href="/{{c.url}}">
|
|
{% if c.official_name %}
|
|
{{c.official_name|safe}}
|
|
{% else %}
|
|
<em>{{c|safe}}</em>
|
|
{% endif %}</a><br>
|
|
{% endfor %}</td>
|
|
|
|
<td style="text-align:right">{{ent.alt|floatformat:1}}</td>
|
|
<td style="text-align:right">{{ent.lat_wgs84|floatformat:6}}</td>
|
|
<td style="text-align:right">{{ent.long_wgs84|floatformat:6}}</td>
|
|
<td style="text-align:right">{{ent.lat|floatformat:6}}</td>
|
|
<td style="text-align:right">{{ent.long|floatformat:6}}</td>
|
|
|
|
</tr>
|
|
{% endfor %}
|
|
</table>
|
|
|
|
<h3>All entrances in Trogggle</h3>
|
|
<p> See also <a href="/entrances">Entrances list</a>.
|
|
<p>But the Entrances - the objects in the troggle system - are not identical to the dataset Survey Stations which is the combined set of survex data. They are only linked - and only implicitly - by the station name, e.g. '1623.gps00.p78' which refers to a *fix line in one of the survex files (in the fixedpts/ folder). Each Entrance can have two stations associated with it: the tag station and the other station.
|
|
|
|
<p>
|
|
Coordinate systems in Austria are explained in:<br>
|
|
<a href="/handbook/survey/lasers.htm">Geographical fixed points on Loser</a><br>
|
|
<a href="/handbook/survey/coord2.html">GPS and coordinate systems</a><br>
|
|
<a href="/handbook/survey/coord.htm">Basic Coordinate Systems</a>.
|
|
<br>
|
|
|
|
<a href="/stations">Troggle UTM and lat./lomg. and altitude report</a><br>
|
|
<a href="/entrances">Troggle entrances</a><br>
|
|
|
|
<h3>These stations have the altitude set equal to SRTM</h3>
|
|
{% for s in stations %}
|
|
{% if '>0<' in s.srtm_diff.0 %}
|
|
{{s}} {{s.srtm_diff.0|safe}} ref={{s.srtm_diff.1|floatformat:0}} <br />
|
|
{% endif %}
|
|
{% endfor %}
|
|
|
|
<!--
|
|
This script is added for ease of use.
|
|
You can safely delete it.
|
|
|
|
Radost Waszkiewicz (2023)
|
|
-->
|
|
<script>
|
|
/*
|
|
table-sort-js
|
|
Author: Lee Wannacott
|
|
Licence: MIT License Copyright (c) 2021 Lee Wannacott
|
|
*/
|
|
|
|
function tableSortJs(testingTableSortJS = false, domDocumentWindow = document) {
|
|
function getHTMLTables() {
|
|
if (testingTableSortJS === true) {
|
|
const getTagTable = domDocumentWindow.getElementsByTagName("table");
|
|
return [getTagTable];
|
|
} else {
|
|
const getTagTable = document.getElementsByTagName("table");
|
|
return [getTagTable];
|
|
}
|
|
}
|
|
|
|
const [getTagTable] = getHTMLTables();
|
|
const columnIndexAndTableRow = {};
|
|
const fileSizeColumnTextAndRow = {};
|
|
for (let table of getTagTable) {
|
|
if (table.classList.contains("table-sort")) {
|
|
makeTableSortable(table);
|
|
}
|
|
}
|
|
|
|
function makeTableSortable(sortableTable) {
|
|
let createTableHead;
|
|
let tableBody;
|
|
if (sortableTable.getElementsByTagName("thead").length === 0) {
|
|
if (testingTableSortJS === true) {
|
|
createTableHead = domDocumentWindow.createElement("thead");
|
|
} else {
|
|
createTableHead = document.createElement("thead");
|
|
}
|
|
createTableHead.appendChild(sortableTable.rows[0]);
|
|
sortableTable.insertBefore(createTableHead, sortableTable.firstChild);
|
|
if (sortableTable.querySelectorAll("tbody").length > 1) {
|
|
tableBody = sortableTable.querySelectorAll("tbody")[1];
|
|
} else {
|
|
tableBody = sortableTable.querySelector("tbody");
|
|
}
|
|
} else {
|
|
tableBody = sortableTable.querySelector("tbody");
|
|
}
|
|
|
|
const tableHead = sortableTable.querySelector("thead");
|
|
const tableHeadHeaders = tableHead.querySelectorAll("th");
|
|
|
|
for (let [columnIndex, th] of tableHeadHeaders.entries()) {
|
|
if (!th.classList.contains("disable-sort")) {
|
|
th.style.cursor = "pointer";
|
|
makeEachColumnSortable(th, columnIndex, tableBody, sortableTable);
|
|
}
|
|
}
|
|
}
|
|
|
|
function makeEachColumnSortable(th, columnIndex, tableBody, sortableTable) {
|
|
const desc = th.classList.contains("order-by-desc");
|
|
let tableArrows = sortableTable.classList.contains("table-arrows");
|
|
const [arrowUp, arrowDown] = [" ▲", " ▼"];
|
|
const fillValue = "!X!Y!Z!";
|
|
|
|
if (desc && tableArrows) {
|
|
th.insertAdjacentText("beforeend", arrowDown);
|
|
} else if (tableArrows) {
|
|
th.insertAdjacentText("beforeend", arrowUp);
|
|
}
|
|
|
|
function sortDataAttributes(tableRows, columnData) {
|
|
for (let [i, tr] of tableRows.entries()) {
|
|
const dataAttributeTd = tr.querySelectorAll("td").item(columnIndex)
|
|
.dataset.sort;
|
|
columnData.push(`${dataAttributeTd}#${i}`);
|
|
columnIndexAndTableRow[columnData[i]] = tr.innerHTML;
|
|
}
|
|
}
|
|
|
|
function sortFileSize(tableRows, columnData) {
|
|
const numberWithUnitType =
|
|
/[.0-9]+(\s?B|\s?KB|\s?KiB|\s?MB|\s?MiB|\s?GB|\s?GiB|T\s?B|\s?TiB)/i;
|
|
const unitType =
|
|
/(\s?B|\s?KB|\s?KiB|\s?MB|\s?MiB|\s?GB|G\s?iB|\s?TB|\s?TiB)/i;
|
|
const fileSizes = {
|
|
Kibibyte: 1024,
|
|
Mebibyte: 1.049e6,
|
|
Gibibyte: 1.074e9,
|
|
Tebibyte: 1.1e12,
|
|
Pebibyte: 1.126e15,
|
|
Kilobyte: 1000,
|
|
Megabyte: 1e6,
|
|
Gigabyte: 1e9,
|
|
Terabyte: 1e12,
|
|
};
|
|
function removeUnitTypeConvertToBytes(fileSizeTd, _replace, i) {
|
|
fileSizeTd = fileSizeTd.replace(unitType, "");
|
|
fileSizeTd = fileSizeTd.replace(
|
|
fileSizeTd,
|
|
fileSizeTd * fileSizes[_replace]
|
|
);
|
|
if (i) {
|
|
columnData.push(`${fileSizeTd}#${i}`);
|
|
}
|
|
return fileSizeTd;
|
|
}
|
|
for (let [i, tr] of tableRows.entries()) {
|
|
let fileSizeTd = tr
|
|
.querySelectorAll("td")
|
|
.item(columnIndex).textContent;
|
|
if (fileSizeTd.match(numberWithUnitType)) {
|
|
if (fileSizeTd.match(/\s?KB/i)) {
|
|
removeUnitTypeConvertToBytes(fileSizeTd, "Kilobyte", i);
|
|
} else if (fileSizeTd.match(/\s?KiB/i)) {
|
|
removeUnitTypeConvertToBytes(fileSizeTd, "Kibibyte", i);
|
|
} else if (fileSizeTd.match(/\s?MB/i)) {
|
|
// TODO: figure out why refactoring this line breaks test.
|
|
fileSizeTd = removeUnitTypeConvertToBytes(fileSizeTd, "Megabyte");
|
|
columnData.push(`${fileSizeTd}#${i}`);
|
|
} else if (fileSizeTd.match(/\s?MiB/i)) {
|
|
removeUnitTypeConvertToBytes(fileSizeTd, "Mebibyte", i);
|
|
} else if (fileSizeTd.match(/\s?GB/i)) {
|
|
removeUnitTypeConvertToBytes(fileSizeTd, "Gigabyte", i);
|
|
} else if (fileSizeTd.match(/\s?GiB/i)) {
|
|
removeUnitTypeConvertToBytes(fileSizeTd, "Gibibyte", i);
|
|
} else if (fileSizeTd.match(/\s?TB/i)) {
|
|
removeUnitTypeConvertToBytes(fileSizeTd, "Terabyte", i);
|
|
} else if (fileSizeTd.match(/\s?TiB/i)) {
|
|
removeUnitTypeConvertToBytes(fileSizeTd, "Tebibyte", i);
|
|
} else if (fileSizeTd.match(/\s?B/i)) {
|
|
fileSizeTd = fileSizeTd.replace(unitType, "");
|
|
columnData.push(`${fileSizeTd}#${i}`);
|
|
}
|
|
} else {
|
|
columnData.push(`${fillValue}#${i}`);
|
|
}
|
|
}
|
|
}
|
|
|
|
let [timesClickedColumn, columnIndexesClicked] = [0, []];
|
|
|
|
function rememberSort(timesClickedColumn, columnIndexesClicked) {
|
|
// if user clicked different column from first column reset times clicked.
|
|
columnIndexesClicked.push(columnIndex);
|
|
if (timesClickedColumn === 1 && columnIndexesClicked.length > 1) {
|
|
const lastColumnClicked =
|
|
columnIndexesClicked[columnIndexesClicked.length - 1];
|
|
const secondLastColumnClicked =
|
|
columnIndexesClicked[columnIndexesClicked.length - 2];
|
|
if (lastColumnClicked !== secondLastColumnClicked) {
|
|
timesClickedColumn = 0;
|
|
columnIndexesClicked.shift();
|
|
}
|
|
}
|
|
}
|
|
|
|
function getColSpanData(sortableTable, colSpanData, colSpanSum) {
|
|
sortableTable.querySelectorAll("th").forEach((th, index) => {
|
|
colSpanData[index] = th.colSpan;
|
|
if (index === 0) colSpanSum[index] = th.colSpan;
|
|
else colSpanSum[index] = colSpanSum[index - 1] + th.colSpan;
|
|
});
|
|
}
|
|
|
|
function getTableData(tableProperties) {
|
|
const {
|
|
tableRows,
|
|
columnData,
|
|
isFileSize,
|
|
isDataAttribute,
|
|
colSpanData,
|
|
colSpanSum,
|
|
} = tableProperties;
|
|
for (let [i, tr] of tableRows.entries()) {
|
|
let tdTextContent = tr
|
|
.querySelectorAll("td")
|
|
.item(
|
|
colSpanData[columnIndex] === 1
|
|
? colSpanSum[columnIndex] - 1
|
|
: colSpanSum[columnIndex] - colSpanData[columnIndex]
|
|
).textContent;
|
|
if (tdTextContent.length === 0) {
|
|
tdTextContent = "";
|
|
}
|
|
if (tdTextContent.trim() !== "") {
|
|
if (isFileSize) {
|
|
fileSizeColumnTextAndRow[columnData[i]] = tr.innerHTML;
|
|
}
|
|
if (!isFileSize && !isDataAttribute) {
|
|
columnData.push(`${tdTextContent}#${i}`);
|
|
columnIndexAndTableRow[`${tdTextContent}#${i}`] = tr.innerHTML;
|
|
}
|
|
} else {
|
|
// Fill in blank table cells dict key with filler value.
|
|
columnData.push(`${fillValue}#${i}`);
|
|
columnIndexAndTableRow[`${fillValue}#${i}`] = tr.innerHTML;
|
|
}
|
|
}
|
|
|
|
const isPunctSort = th.classList.contains("punct-sort");
|
|
const isAlphaSort = th.classList.contains("alpha-sort");
|
|
function sortAscending(a, b) {
|
|
if (a.includes(`${fillValue}#`)) {
|
|
return 1;
|
|
} else if (b.includes(`${fillValue}#`)) {
|
|
return -1;
|
|
} else {
|
|
return a.localeCompare(
|
|
b,
|
|
navigator.languages[0] || navigator.language,
|
|
{ numeric: !isAlphaSort, ignorePunctuation: !isPunctSort }
|
|
);
|
|
}
|
|
}
|
|
|
|
function sortDescending(a, b) {
|
|
return sortAscending(b, a);
|
|
}
|
|
|
|
function clearArrows(arrowUp = "▲", arrowDown = "▼") {
|
|
th.innerHTML = th.innerHTML.replace(arrowUp, "");
|
|
th.innerHTML = th.innerHTML.replace(arrowDown, "");
|
|
}
|
|
|
|
if (columnData[0] === undefined) {
|
|
return;
|
|
}
|
|
|
|
function changeTableArrow(arrowDirection) {
|
|
if (tableArrows) {
|
|
clearArrows(arrowUp, arrowDown);
|
|
th.insertAdjacentText("beforeend", arrowDirection);
|
|
}
|
|
}
|
|
|
|
function sortColumn(sortDirection) {
|
|
columnData.sort(sortDirection, {
|
|
numeric: !isAlphaSort,
|
|
ignorePunctuation: !isPunctSort,
|
|
});
|
|
}
|
|
|
|
if (timesClickedColumn === 1) {
|
|
if (desc) {
|
|
changeTableArrow(arrowDown);
|
|
sortColumn(sortDescending);
|
|
} else {
|
|
changeTableArrow(arrowUp);
|
|
sortColumn(sortAscending);
|
|
}
|
|
} else if (timesClickedColumn === 2) {
|
|
timesClickedColumn = 0;
|
|
if (desc) {
|
|
changeTableArrow(arrowUp);
|
|
sortColumn(sortAscending);
|
|
} else {
|
|
changeTableArrow(arrowDown);
|
|
sortColumn(sortDescending);
|
|
}
|
|
}
|
|
}
|
|
|
|
function updateTable(tableProperties) {
|
|
const { tableRows, columnData, isFileSize } = tableProperties;
|
|
for (let [i, tr] of tableRows.entries()) {
|
|
if (isFileSize) {
|
|
tr.innerHTML = fileSizeColumnTextAndRow[columnData[i]];
|
|
let fileSizeInBytesHTML = tr
|
|
.querySelectorAll("td")
|
|
.item(columnIndex).innerHTML;
|
|
const fileSizeInBytesText = tr
|
|
.querySelectorAll("td")
|
|
.item(columnIndex).textContent;
|
|
const fileSizes = {
|
|
Kibibyte: 1024,
|
|
Mebibyte: 1.049e6,
|
|
Gibibyte: 1.074e9,
|
|
Tebibyte: 1.1e12,
|
|
Pebibyte: 1.126e15,
|
|
};
|
|
// Remove the unique identifyer for duplicate values(#number).
|
|
columnData[i] = columnData[i].replace(/#[0-9]*/, "");
|
|
const fileSize = columnData[i];
|
|
if (fileSize < fileSizes.Kibibyte) {
|
|
fileSizeInBytesHTML = fileSizeInBytesHTML.replace(
|
|
fileSizeInBytesText,
|
|
`${parseFloat(fileSize).toFixed(2)} B`
|
|
);
|
|
} else if (
|
|
fileSize >= fileSizes.Kibibyte &&
|
|
fileSize < fileSizes.Mebibyte
|
|
) {
|
|
fileSizeInBytesHTML = fileSizeInBytesHTML.replace(
|
|
fileSizeInBytesText,
|
|
`${(fileSize / fileSizes.Kibibyte).toFixed(2)} KiB`
|
|
);
|
|
} else if (
|
|
fileSize >= fileSizes.Mebibyte &&
|
|
fileSize < fileSizes.Gibibyte
|
|
) {
|
|
fileSizeInBytesHTML = fileSizeInBytesHTML.replace(
|
|
fileSizeInBytesText,
|
|
`${(fileSize / fileSizes.Mebibyte).toFixed(2)} MiB`
|
|
);
|
|
} else if (
|
|
fileSize >= fileSizes.Gibibyte &&
|
|
fileSize < fileSizes.Tebibyte
|
|
) {
|
|
fileSizeInBytesHTML = fileSizeInBytesHTML.replace(
|
|
fileSizeInBytesText,
|
|
`${(fileSize / fileSizes.Gibibyte).toFixed(2)} GiB`
|
|
);
|
|
} else if (
|
|
fileSize >= fileSizes.Tebibyte &&
|
|
fileSize < fileSizes.Pebibyte
|
|
) {
|
|
fileSizeInBytesHTML = fileSizeInBytesHTML.replace(
|
|
fileSizeInBytesText,
|
|
`${(fileSize / fileSizes.Tebibyte).toFixed(2)} TiB`
|
|
);
|
|
} else {
|
|
fileSizeInBytesHTML = fileSizeInBytesHTML.replace(
|
|
fileSizeInBytesText,
|
|
"NaN"
|
|
);
|
|
}
|
|
tr.querySelectorAll("td").item(columnIndex).innerHTML =
|
|
fileSizeInBytesHTML;
|
|
} else if (!isFileSize) {
|
|
tr.innerHTML = columnIndexAndTableRow[columnData[i]];
|
|
}
|
|
}
|
|
}
|
|
|
|
th.addEventListener("click", function () {
|
|
const [columnData, colSpanData, colSpanSum] = [[], {}, {}];
|
|
|
|
const visibleTableRows = Array.prototype.filter.call(
|
|
tableBody.querySelectorAll("tr"),
|
|
(tr) => {
|
|
return tr.style.display !== "none";
|
|
}
|
|
);
|
|
|
|
const isDataAttribute = th.classList.contains("data-sort");
|
|
if (isDataAttribute) {
|
|
sortDataAttributes(visibleTableRows, columnData);
|
|
}
|
|
|
|
const isFileSize = th.classList.contains("file-size-sort");
|
|
if (isFileSize) {
|
|
sortFileSize(visibleTableRows, columnData);
|
|
}
|
|
|
|
const isRememberSort = sortableTable.classList.contains("remember-sort");
|
|
if (!isRememberSort) {
|
|
rememberSort(timesClickedColumn, columnIndexesClicked);
|
|
}
|
|
|
|
timesClickedColumn += 1;
|
|
|
|
getColSpanData(sortableTable, colSpanData, colSpanSum);
|
|
const tableProperties = {
|
|
tableRows: visibleTableRows,
|
|
columnData,
|
|
isFileSize,
|
|
isDataAttribute,
|
|
colSpanData,
|
|
colSpanSum,
|
|
};
|
|
getTableData(tableProperties);
|
|
updateTable(tableProperties);
|
|
});
|
|
}
|
|
}
|
|
|
|
if (
|
|
document.readyState === "complete" ||
|
|
document.readyState === "interactive"
|
|
) {
|
|
tableSortJs();
|
|
} else if (document.readyState === "loading") {
|
|
document.addEventListener("DOMContentLoaded", tableSortJs, false);
|
|
}
|
|
if (typeof module == "object") {
|
|
module.exports = tableSortJs;
|
|
}
|
|
</script>
|
|
|
|
{% endblock %}
|