lunar-toolkit 0.1.0.dev11__tar.gz → 0.1.0.dev13__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/PKG-INFO +1 -1
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/cli/app.py +14 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/static/index.html +203 -15
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit.egg-info/PKG-INFO +1 -1
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/pyproject.toml +2 -2
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/LICENSE +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/README.md +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/__init__.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/asp.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/cli/__init__.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/cli/_jobs.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/cli/_status.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/cli/_utils.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/cli/build_db.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/cli/download.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/cli/kaguya.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/cli/ode_search.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/cli/pairs.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/cli/process.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/cli/query.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/cli/reference.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/cli/search.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/cli/serve.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/cli/sfs.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/cli/sfs_report.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/cli/shadowcam.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/cli/stereo.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/cli/workspace.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/config.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/constants.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/csm.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/downloader.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/geometry.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/isis.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/kaguya/__init__.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/kaguya/mi.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/kaguya/tc.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/lroc/__init__.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/lroc/cumindex.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/lroc/nac.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/observation.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/ode.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/provenance.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/reference.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/selection.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/sfs.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/sfs_products.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/sfs_report.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/shadowcam/__init__.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/shadowcam/sc.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/static/basemaps/lola_dem_global.tif +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/static/basemaps/lola_dem_north.tif +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/static/basemaps/lola_dem_south.tif +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/static/basemaps/lola_shade_global.jpg +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/static/basemaps/lola_shade_north.jpg +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/static/basemaps/lola_shade_south.jpg +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/static/basemaps/manifest.json +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/static/basemaps/wac_global.jpg +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/static/basemaps/wac_north.jpg +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/static/basemaps/wac_south.jpg +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/stereo.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/stereo_dem.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/tools.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/workspace.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit.egg-info/SOURCES.txt +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit.egg-info/dependency_links.txt +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit.egg-info/entry_points.txt +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit.egg-info/requires.txt +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit.egg-info/top_level.txt +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/setup.cfg +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/tests/test_aoi.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/tests/test_app.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/tests/test_build.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/tests/test_config.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/tests/test_csm.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/tests/test_download.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/tests/test_footprints.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/tests/test_integration.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/tests/test_kaguya.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/tests/test_kaguya_mi.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/tests/test_lbl.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/tests/test_ode.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/tests/test_reference.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/tests/test_selection.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/tests/test_sfs.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/tests/test_sfs_products.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/tests/test_sfs_report.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/tests/test_shadowcam.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/tests/test_static.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/tests/test_stereo.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/tests/test_tool_env.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/tests/test_tools.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/tests/test_update.py +0 -0
- {lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/tests/test_workspace.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: lunar-toolkit
|
|
3
|
-
Version: 0.1.0.
|
|
3
|
+
Version: 0.1.0.dev13
|
|
4
4
|
Summary: Find, download and process lunar orbital imagery (LROC, ShadowCam, Kaguya TC) and build stereo and shape-from-shading DEMs with ISIS + ASP
|
|
5
5
|
License-Expression: BSD-3-Clause
|
|
6
6
|
Keywords: moon,lroc,shadowcam,kaguya,isis,ames-stereo-pipeline,shape-from-shading,dem
|
|
@@ -144,9 +144,23 @@ def choose_backend(requested: str = "auto", platform: str | None = None) -> tupl
|
|
|
144
144
|
return "browser", None
|
|
145
145
|
|
|
146
146
|
|
|
147
|
+
def _quiet_qt_exit() -> None:
|
|
148
|
+
"""Drop Qt WebEngine's harmless "Release of profile requested" warning on window close."""
|
|
149
|
+
from qtpy.QtCore import qInstallMessageHandler
|
|
150
|
+
|
|
151
|
+
def handler(mode: Any, context: Any, message: str | None) -> None:
|
|
152
|
+
if message and "WebEnginePage still not deleted" not in message:
|
|
153
|
+
sys.stderr.write(message + "\n")
|
|
154
|
+
|
|
155
|
+
qInstallMessageHandler(handler)
|
|
156
|
+
|
|
157
|
+
|
|
147
158
|
def _run_webview(url: str, gui: str) -> None:
|
|
148
159
|
import webview
|
|
149
160
|
|
|
161
|
+
if gui == "qt":
|
|
162
|
+
_quiet_qt_exit()
|
|
163
|
+
|
|
150
164
|
from ..constants import DEFAULT_CACHE_DIR
|
|
151
165
|
|
|
152
166
|
webview.create_window(TITLE, url, width=SIZE[0], height=SIZE[1], min_size=MIN_SIZE)
|
|
@@ -191,10 +191,28 @@
|
|
|
191
191
|
.map .frame { fill: none; stroke: var(--plot-fg); stroke-width: 1; shape-rendering: crispEdges; }
|
|
192
192
|
.map .tick { fill: none; stroke: var(--plot-fg); stroke-width: 1; shape-rendering: crispEdges; }
|
|
193
193
|
.map .grid { fill: none; stroke: var(--plot-grid); stroke-width: 1; }
|
|
194
|
-
|
|
195
|
-
.map .
|
|
196
|
-
.map .
|
|
197
|
-
.
|
|
194
|
+
/* Fills share one group whose opacity applies once, so overlaps do not build up */
|
|
195
|
+
.map .fpfill { opacity: var(--fp-fill, 0.07); pointer-events: none; }
|
|
196
|
+
.map .fpfill path { fill: var(--fp-color, #3d8bfd); fill-rule: evenodd; stroke: none; }
|
|
197
|
+
.map .fp { fill: transparent; fill-rule: evenodd; stroke: var(--fp-color, #3d8bfd); stroke-opacity: var(--fp-line, 0.85); stroke-width: 0.9; stroke-dasharray: var(--fp-dash, 1.5 2.5); cursor: pointer; }
|
|
198
|
+
.map .fp:hover { stroke-opacity: 1; stroke-width: 1.5; stroke-dasharray: none; }
|
|
199
|
+
.map .fp.sel { fill: var(--fp-sel); fill-opacity: 0.2; stroke: var(--fp-sel); stroke-opacity: 1; stroke-width: 1.8; stroke-dasharray: none; }
|
|
200
|
+
.map .sketch { fill: var(--accent); fill-opacity: 0.12; stroke: var(--accent); stroke-width: 1.5; stroke-dasharray: 5 3; pointer-events: none; }
|
|
201
|
+
.map .sketch.pt { fill: var(--accent); fill-opacity: 1; stroke: #fff; stroke-dasharray: none; }
|
|
202
|
+
.mapcoord {
|
|
203
|
+
position: absolute; pointer-events: none; padding: 1px 5px; font: 11px "DejaVu Sans Mono", Consolas, monospace;
|
|
204
|
+
background: rgba(255, 255, 255, 0.85); border: 1px solid var(--border); color: #000; white-space: nowrap;
|
|
205
|
+
}
|
|
206
|
+
.mapcoord:empty { display: none; }
|
|
207
|
+
.panehead .tools { display: inline-flex; margin-right: 8px; }
|
|
208
|
+
.panehead .tools button { margin-right: -1px; }
|
|
209
|
+
.stylewrap { position: relative; }
|
|
210
|
+
.stylepop {
|
|
211
|
+
position: absolute; right: 0; top: 100%; z-index: 5; margin-top: 3px; padding: 6px 8px; display: grid;
|
|
212
|
+
grid-template-columns: auto auto; gap: 4px 8px; align-items: center; background: var(--window); border: 1px solid var(--border);
|
|
213
|
+
}
|
|
214
|
+
.stylepop select { width: auto; }
|
|
215
|
+
.mapbox.hide-fp .fp, .mapbox.hide-fp .fpfill, .mapbox.hide-region .region { display: none; }
|
|
198
216
|
.panehead .toggle { display: inline-flex; align-items: center; gap: 3px; margin-right: 8px; white-space: nowrap; }
|
|
199
217
|
.map .region { fill: none; fill-rule: evenodd; stroke: var(--region); stroke-width: 1.4; stroke-dasharray: 6 3; pointer-events: none; }
|
|
200
218
|
.map text { fill: var(--plot-label); font-size: 11px; pointer-events: none; }
|
|
@@ -1189,6 +1207,10 @@
|
|
|
1189
1207
|
};
|
|
1190
1208
|
}
|
|
1191
1209
|
|
|
1210
|
+
$('search-form').addEventListener('change', (e) => {
|
|
1211
|
+
if (e.target.id === 's-mode' || e.target.closest('[data-mode]')) showFormRegion();
|
|
1212
|
+
});
|
|
1213
|
+
document.addEventListener('keydown', (e) => { if (e.key === 'Escape') $('map')._cancel?.(); });
|
|
1192
1214
|
for (const p of ['s']) {
|
|
1193
1215
|
const sync = () => {
|
|
1194
1216
|
for (const node of $(`${p}-mode`).closest('fieldset').querySelectorAll('[data-mode]')) {
|
|
@@ -1236,6 +1258,67 @@
|
|
|
1236
1258
|
return el('label', { class: 'toggle' }, box, ` ${label}`);
|
|
1237
1259
|
}
|
|
1238
1260
|
|
|
1261
|
+
const MAP_TOOLS = {
|
|
1262
|
+
pan: ['Pan', 'Drag to pan, wheel to zoom, click a footprint for details'],
|
|
1263
|
+
box: ['Box', 'Drag a box on the map to set the search region'],
|
|
1264
|
+
circle: ['Circle', 'Drag from the centre to set a point and radius'],
|
|
1265
|
+
poly: ['Polygon', 'Click the polygon vertices, then double click or click the first point (Esc cancels)'],
|
|
1266
|
+
};
|
|
1267
|
+
const FP_LINES = { dotted: '1.5 2.5', dashed: '5 3', solid: 'none', none: 'none' };
|
|
1268
|
+
const FP_FILLS = { none: 0, light: 0.07, medium: 0.18 };
|
|
1269
|
+
const FP_COLORS = { blue: '#3d8bfd', yellow: '#ffd43b', cyan: '#22d3ee', magenta: '#e64980', navy: '#1f4a8a', white: '#ffffff' };
|
|
1270
|
+
|
|
1271
|
+
function applyFootprintStyle(container) {
|
|
1272
|
+
container.style.setProperty('--fp-dash', FP_LINES[mapPrefs.fpLine] ?? FP_LINES.dotted);
|
|
1273
|
+
container.style.setProperty('--fp-line', mapPrefs.fpLine === 'none' ? '0' : '0.85');
|
|
1274
|
+
container.style.setProperty('--fp-fill', String(FP_FILLS[mapPrefs.fpFill] ?? FP_FILLS.light));
|
|
1275
|
+
container.style.setProperty('--fp-color', FP_COLORS[mapPrefs.fpColor] ?? FP_COLORS.blue);
|
|
1276
|
+
}
|
|
1277
|
+
|
|
1278
|
+
// Footprint outline, fill and colour, in a small pop-up next to the Footprints toggle
|
|
1279
|
+
function footprintStyle(container) {
|
|
1280
|
+
applyFootprintStyle(container);
|
|
1281
|
+
const field = (key, label, options) => {
|
|
1282
|
+
const s = el('select', { 'aria-label': label }, ...Object.keys(options).map((o) => el('option', { value: o }, o)));
|
|
1283
|
+
s.value = mapPrefs[key];
|
|
1284
|
+
s.addEventListener('change', () => { mapPrefs[key] = s.value; saveMapPrefs(); applyFootprintStyle(container); });
|
|
1285
|
+
return [el('span', {}, label), s];
|
|
1286
|
+
};
|
|
1287
|
+
const pop = el('div', { class: 'stylepop', hidden: '' },
|
|
1288
|
+
...field('fpLine', 'Outline', FP_LINES), ...field('fpFill', 'Fill', FP_FILLS), ...field('fpColor', 'Colour', FP_COLORS));
|
|
1289
|
+
const button = el('button', { class: 'tool', type: 'button', title: 'Footprint outline, fill and colour' }, 'Style');
|
|
1290
|
+
button.addEventListener('click', (e) => { e.stopPropagation(); pop.hidden = !pop.hidden; });
|
|
1291
|
+
pop.addEventListener('click', (e) => e.stopPropagation());
|
|
1292
|
+
document.addEventListener('click', () => { pop.hidden = true; });
|
|
1293
|
+
return el('span', { class: 'stylewrap' }, button, pop);
|
|
1294
|
+
}
|
|
1295
|
+
|
|
1296
|
+
function greatCircleKm(lat1, lon1, lat2, lon2) {
|
|
1297
|
+
const h = Math.sin(((lat2 - lat1) * RAD) / 2) ** 2
|
|
1298
|
+
+ Math.cos(lat1 * RAD) * Math.cos(lat2 * RAD) * Math.sin(((lon2 - lon1) * RAD) / 2) ** 2;
|
|
1299
|
+
return 2 * MOON_RADIUS_KM * Math.asin(Math.min(1, Math.sqrt(h)));
|
|
1300
|
+
}
|
|
1301
|
+
|
|
1302
|
+
// Fill the search form's region from the map; its change event redraws the region
|
|
1303
|
+
function setFormRegion(mode, v) {
|
|
1304
|
+
const round = (x, d = 5) => String(Math.round(x * 10 ** d) / 10 ** d);
|
|
1305
|
+
if (mode === 'point') { $('s-lat').value = round(v.lat); $('s-lon').value = round(mod(v.lon, 360)); $('s-radius').value = round(v.radius, 3); }
|
|
1306
|
+
if (mode === 'box') for (const k of ['west', 'east', 'south', 'north']) $(`s-${k}`).value = round(v[k]);
|
|
1307
|
+
if (mode === 'aoi') $('s-aoi').value = v.aoi;
|
|
1308
|
+
$('s-mode').value = mode;
|
|
1309
|
+
$('s-mode').dispatchEvent(new Event('change', { bubbles: true }));
|
|
1310
|
+
setStatus('status', 'Search region set from the map | press Search');
|
|
1311
|
+
}
|
|
1312
|
+
|
|
1313
|
+
// Show the form's search region on the map (before any search, or over the current results)
|
|
1314
|
+
function showFormRegion() {
|
|
1315
|
+
let sel;
|
|
1316
|
+
try { sel = readRegion('s'); } catch { return; }
|
|
1317
|
+
const map = $('map');
|
|
1318
|
+
if (map._setRegion) map._setRegion(sel);
|
|
1319
|
+
else renderMap(map, { hemi: mapHemi(sel.region, []), region: sel, items: [] });
|
|
1320
|
+
}
|
|
1321
|
+
|
|
1239
1322
|
function renderMap(container, { hemi, region, items }) {
|
|
1240
1323
|
container._resize?.disconnect();
|
|
1241
1324
|
container._highlight = null;
|
|
@@ -1248,14 +1331,17 @@
|
|
|
1248
1331
|
const cinfo = el('span', { class: 'info' });
|
|
1249
1332
|
const pick = el('select', { 'aria-label': 'Basemap', title: 'Basemap under the footprints' });
|
|
1250
1333
|
const cbox = el('input', { type: 'checkbox' });
|
|
1334
|
+
const coord = el('div', { class: 'mapcoord' });
|
|
1335
|
+
const tools = el('span', { class: 'tools' }, ...Object.entries(MAP_TOOLS).map(([t, [label, title]]) =>
|
|
1336
|
+
el('button', { class: `tool${t === 'pan' ? ' on' : ''}`, type: 'button', 'data-tool': t, title }, label)));
|
|
1251
1337
|
const bar = el('div', { class: 'panehead' },
|
|
1252
1338
|
el('span', { class: 'title' }, 'Footprints'),
|
|
1253
1339
|
el('span', { class: 'info' }, hemi ? `Polar stereographic (${hemi === 'S' ? 'south' : 'north'}), R = ${MOON_RADIUS_KM} km`
|
|
1254
1340
|
: 'Lon/lat (equirectangular)', ` | ${items.length} footprint(s) | wheel zoom, drag pan`),
|
|
1255
1341
|
cinfo, spin,
|
|
1256
|
-
el('span', { class: 'right' }, pick, el('label', { class: 'toggle', title: 'Elevation contours (LOLA)' }, cbox, ' Contours'),
|
|
1257
|
-
layerToggle(container, 'fp', 'Footprints'), layerToggle(container, 'region', 'Region'), reset));
|
|
1258
|
-
container.replaceChildren(el('div', { class: 'map' }, bar, el('div', { class: 'plotarea' }, canvas, svg)));
|
|
1342
|
+
el('span', { class: 'right' }, tools, pick, el('label', { class: 'toggle', title: 'Elevation contours (LOLA)' }, cbox, ' Contours'),
|
|
1343
|
+
layerToggle(container, 'fp', 'Footprints'), footprintStyle(container), layerToggle(container, 'region', 'Region'), reset));
|
|
1344
|
+
container.replaceChildren(el('div', { class: 'map' }, bar, el('div', { class: 'plotarea' }, canvas, svg, coord)));
|
|
1259
1345
|
const clipId = `clip-${container.id}`;
|
|
1260
1346
|
const M = MARGIN;
|
|
1261
1347
|
|
|
@@ -1263,11 +1349,12 @@
|
|
|
1263
1349
|
const regionGeom = region ? region.shape(hemi) : [];
|
|
1264
1350
|
let geoms = items.map((it) => it.geom);
|
|
1265
1351
|
let kx = 1;
|
|
1352
|
+
let recenter = (g) => g;
|
|
1266
1353
|
if (!hemi) {
|
|
1267
1354
|
const mids = [...regionGeom, ...geoms.flat()].map((P) => { const b = bboxOf([P[0]]); return (b[0] + b[1]) / 2; });
|
|
1268
1355
|
const c = region ? (region.region.span < 360 ? region.region.west + region.region.span / 2 : 180)
|
|
1269
1356
|
: Math.atan2(sumOf(mids.map((m) => Math.sin(m * RAD))), sumOf(mids.map((m) => Math.cos(m * RAD)))) * DEG;
|
|
1270
|
-
|
|
1357
|
+
recenter = (g) => g.map((P) => { const b = bboxOf([P[0]]); return shiftX([P], -360 * Math.round(((b[0] + b[1]) / 2 - c) / 360))[0]; });
|
|
1271
1358
|
geoms = geoms.map(recenter);
|
|
1272
1359
|
const lats = [...regionGeom, ...geoms.flat()].flatMap((P) => P[0].map((p) => p[1]));
|
|
1273
1360
|
kx = Math.max(0.2, Math.cos(((minOf(lats) + maxOf(lats)) / 2) * RAD));
|
|
@@ -1275,7 +1362,7 @@
|
|
|
1275
1362
|
}
|
|
1276
1363
|
// Data coordinates: x right, y down
|
|
1277
1364
|
const toXY = (g) => g.map((P) => P.map((r) => r.map(([x, y]) => (hemi ? [x, -y] : [x * kx, -y]))));
|
|
1278
|
-
|
|
1365
|
+
let reg = toXY(regionGeom);
|
|
1279
1366
|
const fps = geoms.map(toXY);
|
|
1280
1367
|
const all = [...reg, ...fps.flat()].flat();
|
|
1281
1368
|
let [x0, x1, y0, y1] = all.length ? bboxOf(all) : [-1, 1, -1, 1];
|
|
@@ -1299,6 +1386,11 @@
|
|
|
1299
1386
|
const sgn = hemi === 'S' ? 1 : -1;
|
|
1300
1387
|
const rho = (la) => 2 * MOON_RADIUS_KM * 1000 * Math.tan(Math.PI / 4 + sgn * (la * RAD) / 2);
|
|
1301
1388
|
const latOf = (r) => sgn * (2 * Math.atan(r / (2 * MOON_RADIUS_KM * 1000)) - Math.PI / 2) * DEG;
|
|
1389
|
+
// Data coordinates (x right, y down) to [lon, lat]
|
|
1390
|
+
const toLonLat = ([x, y]) => (hemi ? [mod(Math.atan2(x, -sgn * y) * DEG, 360), latOf(Math.hypot(x, y))] : [x / kx, -y]);
|
|
1391
|
+
coord.style.left = `${M.l + 6}px`;
|
|
1392
|
+
coord.style.bottom = `${M.b + 6}px`;
|
|
1393
|
+
let tool = 'pan', sketch = null;
|
|
1302
1394
|
|
|
1303
1395
|
// Grid lines (clipped), graticule labels inside the plot, ticks + tick labels on the frame
|
|
1304
1396
|
function axes() {
|
|
@@ -1377,11 +1469,14 @@
|
|
|
1377
1469
|
const a = axes();
|
|
1378
1470
|
const order = fps.map((_, i) => i).filter((i) => i !== sel);
|
|
1379
1471
|
if (sel >= 0) order.push(sel);
|
|
1472
|
+
const ds = fps.map((g) => pathD(g));
|
|
1380
1473
|
svg.innerHTML = `<defs><clipPath id="${clipId}"><rect width="${W}" height="${H}"/></clipPath></defs>`
|
|
1381
1474
|
+ `<g transform="translate(${M.l} ${M.t})"><rect class="plot" width="${W}" height="${H}"/>`
|
|
1382
1475
|
+ `<g clip-path="url(#${clipId})">${a.grid}<g class="cslot"/>`
|
|
1383
|
-
+
|
|
1476
|
+
+ `<g class="fpfill">${ds.map((d) => `<path d="${d}"/>`).join('')}</g>`
|
|
1477
|
+
+ order.map((i) => `<path class="fp${i === sel ? ' sel' : ''}" data-i="${i}" d="${ds[i]}"><title>${esc(items[i].title)}</title></path>`).join('')
|
|
1384
1478
|
+ (reg.length ? `<path class="region" d="${pathD(reg)}"/>` : '')
|
|
1479
|
+
+ sketchSvg()
|
|
1385
1480
|
+ `</g><rect class="frame" x="0.5" y="0.5" width="${W - 1}" height="${H - 1}"/>`
|
|
1386
1481
|
+ `<path class="tick" d="${a.ticks}"/>${a.labels}</g>`;
|
|
1387
1482
|
svg.querySelector('.cslot').replaceWith(under.contours);
|
|
@@ -1401,9 +1496,58 @@
|
|
|
1401
1496
|
view.cx = x - (mx - W / 2) / view.k; view.cy = y - (my - H / 2) / view.k;
|
|
1402
1497
|
redraw();
|
|
1403
1498
|
}, { passive: false });
|
|
1499
|
+
const dataXY = (e) => { const [mx, my] = plotXY(e); return [view.cx + (mx - W / 2) / view.k, view.cy + (my - H / 2) / view.k]; };
|
|
1500
|
+
const screenDist = (p, q) => Math.hypot(p[0] - q[0], p[1] - q[1]) * view.k;
|
|
1501
|
+
// Drawn region in progress: box and circle while dragging, polygon vertices plus the pointer
|
|
1502
|
+
function sketchSvg() {
|
|
1503
|
+
if (!sketch) return '';
|
|
1504
|
+
const P = ([x, y]) => `${sx(x).toFixed(1)} ${sy(y).toFixed(1)}`;
|
|
1505
|
+
if (sketch.tool === 'box') {
|
|
1506
|
+
const [[ax, ay], [bx, by]] = [sketch.a, sketch.b];
|
|
1507
|
+
return `<path class="sketch" d="M${P([ax, ay])}L${P([bx, ay])}L${P([bx, by])}L${P([ax, by])}Z"/>`;
|
|
1508
|
+
}
|
|
1509
|
+
if (sketch.tool === 'circle') {
|
|
1510
|
+
const r = screenDist(sketch.a, sketch.b).toFixed(1);
|
|
1511
|
+
return `<circle class="sketch" cx="${sx(sketch.a[0]).toFixed(1)}" cy="${sy(sketch.a[1]).toFixed(1)}" r="${r}"/>`;
|
|
1512
|
+
}
|
|
1513
|
+
const pts = [...sketch.pts, sketch.hover].filter(Boolean);
|
|
1514
|
+
return `<path class="sketch" d="M${pts.map(P).join('L')}"/>`
|
|
1515
|
+
+ sketch.pts.map(([x, y]) => `<circle class="sketch pt" cx="${sx(x).toFixed(1)}" cy="${sy(y).toFixed(1)}" r="3"/>`).join('');
|
|
1516
|
+
}
|
|
1517
|
+
const setTool = (t) => {
|
|
1518
|
+
tool = t; sketch = null;
|
|
1519
|
+
for (const b of tools.children) b.classList.toggle('on', b.dataset.tool === t);
|
|
1520
|
+
if (t !== 'pan') setStatus('status', MAP_TOOLS[t][1]);
|
|
1521
|
+
redraw();
|
|
1522
|
+
};
|
|
1523
|
+
for (const b of tools.children) b.addEventListener('click', () => setTool(b.dataset.tool));
|
|
1524
|
+
// Densified ring in data coordinates -> lon/lat, so edges follow the map's straight lines
|
|
1525
|
+
const ringLonLat = (pts, n = hemi ? 16 : 1) => pts.flatMap((p, i) => {
|
|
1526
|
+
const q = pts[(i + 1) % pts.length];
|
|
1527
|
+
return Array.from({ length: n }, (_, j) => toLonLat([p[0] + ((q[0] - p[0]) * j) / n, p[1] + ((q[1] - p[1]) * j) / n]));
|
|
1528
|
+
});
|
|
1529
|
+
function finishSketch() {
|
|
1530
|
+
const sk = sketch;
|
|
1531
|
+
setTool('pan');
|
|
1532
|
+
if (!sk) return;
|
|
1533
|
+
if (sk.tool === 'circle') {
|
|
1534
|
+
const [lon, lat] = toLonLat(sk.a), [lon2, lat2] = toLonLat(sk.b);
|
|
1535
|
+
setFormRegion('point', { lat, lon, radius: greatCircleKm(lat, lon, lat2, lon2) });
|
|
1536
|
+
} else if (sk.tool === 'box' && !hemi) {
|
|
1537
|
+
const [[w, n], [e, s]] = [toLonLat([Math.min(sk.a[0], sk.b[0]), Math.min(sk.a[1], sk.b[1])]),
|
|
1538
|
+
toLonLat([Math.max(sk.a[0], sk.b[0]), Math.max(sk.a[1], sk.b[1])])];
|
|
1539
|
+
const full = e - w >= 360;
|
|
1540
|
+
setFormRegion('box', { west: full ? 0 : mod(w, 360), east: full ? 360 : mod(e, 360), south: s, north: n });
|
|
1541
|
+
} else {
|
|
1542
|
+
const pts = sk.tool === 'box' ? [sk.a, [sk.b[0], sk.a[1]], sk.b, [sk.a[0], sk.b[1]]] : sk.pts;
|
|
1543
|
+
const ring = ringLonLat(pts).map(([lon, lat]) => [mod(lon, 360), lat]);
|
|
1544
|
+
setFormRegion('aoi', { aoi: `POLYGON((${[...ring, ring[0]].map(([lon, lat]) => `${lon.toFixed(5)} ${lat.toFixed(5)}`).join(', ')}))` });
|
|
1545
|
+
}
|
|
1546
|
+
}
|
|
1547
|
+
container._cancel = () => { if (tool !== 'pan') setTool('pan'); };
|
|
1404
1548
|
const showCursor = (e) => {
|
|
1405
1549
|
const [mx, my] = plotXY(e);
|
|
1406
|
-
if (mx < 0 || my < 0 || mx > W || my > H) { $('cursor').textContent = ''; return; }
|
|
1550
|
+
if (mx < 0 || my < 0 || mx > W || my > H) { $('cursor').textContent = coord.textContent = ''; return; }
|
|
1407
1551
|
const x = view.cx + (mx - W / 2) / view.k, y = -(view.cy + (my - H / 2) / view.k);
|
|
1408
1552
|
let lat, lon, xy = '';
|
|
1409
1553
|
if (hemi) {
|
|
@@ -1413,31 +1557,68 @@
|
|
|
1413
1557
|
} else {
|
|
1414
1558
|
[lat, lon] = [y, mod(x / kx, 360)];
|
|
1415
1559
|
}
|
|
1416
|
-
$('cursor').textContent = Math.abs(lat) > 90 ? ''
|
|
1560
|
+
$('cursor').textContent = coord.textContent = Math.abs(lat) > 90 ? ''
|
|
1417
1561
|
: `Lat ${lat.toFixed(4)} Lon ${lon.toFixed(4)} E${xy}`;
|
|
1418
1562
|
};
|
|
1419
1563
|
let drag = null;
|
|
1420
1564
|
svg.addEventListener('pointerdown', (e) => {
|
|
1565
|
+
if (tool !== 'pan') {
|
|
1566
|
+
if (e.button !== 0) return;
|
|
1567
|
+
const p = dataXY(e);
|
|
1568
|
+
if (tool !== 'poly') sketch = { tool, a: p, b: p, down: true };
|
|
1569
|
+
else if (!sketch) sketch = { tool, pts: [p], hover: p };
|
|
1570
|
+
else if (sketch.pts.length >= 3 && screenDist(sketch.pts[0], p) < 8) { finishSketch(); return; }
|
|
1571
|
+
else sketch.pts.push(p);
|
|
1572
|
+
try { svg.setPointerCapture(e.pointerId); } catch { /* synthetic event */ }
|
|
1573
|
+
redraw();
|
|
1574
|
+
return;
|
|
1575
|
+
}
|
|
1421
1576
|
drag = { x: e.clientX, y: e.clientY, cx: view.cx, cy: view.cy, i: e.target.dataset?.i, moved: false };
|
|
1422
1577
|
try { svg.setPointerCapture(e.pointerId); } catch { /* synthetic event */ }
|
|
1423
1578
|
});
|
|
1424
1579
|
svg.addEventListener('pointermove', (e) => {
|
|
1425
1580
|
showCursor(e);
|
|
1581
|
+
if (sketch) {
|
|
1582
|
+
if (sketch.tool === 'poly') sketch.hover = dataXY(e);
|
|
1583
|
+
else if (sketch.down) sketch.b = dataXY(e);
|
|
1584
|
+
redraw();
|
|
1585
|
+
return;
|
|
1586
|
+
}
|
|
1426
1587
|
if (!drag) return;
|
|
1427
1588
|
const dx = e.clientX - drag.x, dy = e.clientY - drag.y;
|
|
1428
1589
|
if (Math.hypot(dx, dy) > 4) { drag.moved = true; svg.classList.add('dragging'); }
|
|
1429
1590
|
if (drag.moved) { touched = true; view.cx = drag.cx - dx / view.k; view.cy = drag.cy - dy / view.k; redraw(); }
|
|
1430
1591
|
});
|
|
1431
|
-
svg.addEventListener('pointerleave', () => { if (!drag) $('cursor').textContent = ''; });
|
|
1592
|
+
svg.addEventListener('pointerleave', () => { if (!drag) $('cursor').textContent = coord.textContent = ''; });
|
|
1432
1593
|
svg.addEventListener('pointerup', () => {
|
|
1594
|
+
if (sketch && sketch.tool !== 'poly') {
|
|
1595
|
+
if (screenDist(sketch.a, sketch.b) < 4) { sketch = null; redraw(); } else finishSketch();
|
|
1596
|
+
return;
|
|
1597
|
+
}
|
|
1433
1598
|
if (drag && !drag.moved && drag.i != null) items[Number(drag.i)].onclick();
|
|
1434
1599
|
drag = null;
|
|
1435
1600
|
svg.classList.remove('dragging');
|
|
1436
1601
|
});
|
|
1437
1602
|
const home0 = () => { view = null; touched = false; draw(); };
|
|
1438
|
-
svg.addEventListener('dblclick',
|
|
1603
|
+
svg.addEventListener('dblclick', () => {
|
|
1604
|
+
if (tool === 'poly' && sketch) {
|
|
1605
|
+
// The double click's own clicks added the last point twice
|
|
1606
|
+
sketch.pts = sketch.pts.filter((p, i, a) => !i || screenDist(p, a[i - 1]) > 3);
|
|
1607
|
+
if (sketch.pts.length >= 3) finishSketch();
|
|
1608
|
+
return;
|
|
1609
|
+
}
|
|
1610
|
+
if (tool === 'pan') home0();
|
|
1611
|
+
});
|
|
1439
1612
|
reset.addEventListener('click', home0);
|
|
1440
1613
|
container._highlight = (row) => { sel = items.findIndex((it) => it.row === row); draw(); };
|
|
1614
|
+
// A new search region from the form or the map, keeping the view and the results
|
|
1615
|
+
container._setRegion = (next) => {
|
|
1616
|
+
const h = mapHemi(next.region, []);
|
|
1617
|
+
if (h !== hemi) { renderMap(container, { hemi: h, region: next, items }); return; }
|
|
1618
|
+
region = next;
|
|
1619
|
+
reg = toXY(hemi ? next.shape(hemi) : recenter(next.shape(hemi)));
|
|
1620
|
+
redraw();
|
|
1621
|
+
};
|
|
1441
1622
|
let lastW = 0, lastH = 0;
|
|
1442
1623
|
container._resize = new ResizeObserver(() => {
|
|
1443
1624
|
const [w, h] = [svg.clientWidth, svg.clientHeight];
|
|
@@ -2657,7 +2838,11 @@
|
|
|
2657
2838
|
N: ['lola_dem_north'],
|
|
2658
2839
|
};
|
|
2659
2840
|
const BM_STRETCH = { min: 0, max: 255, gamma: 1 };
|
|
2660
|
-
|
|
2841
|
+
// Map preferences, remembered across searches and (when storage works) sessions
|
|
2842
|
+
const MAP_PREFS_KEY = 'lunar-toolkit-map';
|
|
2843
|
+
const mapPrefs = { basemap: 'wac', contours: false, fpLine: 'dotted', fpFill: 'light', fpColor: 'blue' };
|
|
2844
|
+
try { Object.assign(mapPrefs, JSON.parse(localStorage.getItem(MAP_PREFS_KEY) ?? '{}')); } catch { /* storage blocked */ }
|
|
2845
|
+
const saveMapPrefs = () => { try { localStorage.setItem(MAP_PREFS_KEY, JSON.stringify(mapPrefs)); } catch { /* storage blocked */ } };
|
|
2661
2846
|
const bmOpened = new Map(); // ref -> { promise, src, pending, failed }
|
|
2662
2847
|
let bmManifest = null, bmNotify = null;
|
|
2663
2848
|
const bmUrl = (file) => new URL(`basemaps/${file}`, window.location.href).href;
|
|
@@ -2760,12 +2945,14 @@
|
|
|
2760
2945
|
container.classList.toggle('has-basemap', choice() !== 'none');
|
|
2761
2946
|
pick.addEventListener('change', () => {
|
|
2762
2947
|
mapPrefs.basemap = pick.value;
|
|
2948
|
+
saveMapPrefs();
|
|
2763
2949
|
container.classList.toggle('has-basemap', pick.value !== 'none');
|
|
2764
2950
|
redraw();
|
|
2765
2951
|
});
|
|
2766
2952
|
cbox.checked = mapPrefs.contours;
|
|
2767
2953
|
cbox.addEventListener('change', () => {
|
|
2768
2954
|
mapPrefs.contours = cbox.checked;
|
|
2955
|
+
saveMapPrefs();
|
|
2769
2956
|
st.ckey = '';
|
|
2770
2957
|
if (!cbox.checked) { st.gen++; st.cbusy = false; st.contour = null; paths.forEach((p) => p.removeAttribute('d')); cinfo.textContent = ''; }
|
|
2771
2958
|
redraw();
|
|
@@ -3609,6 +3796,7 @@
|
|
|
3609
3796
|
|
|
3610
3797
|
// Boot
|
|
3611
3798
|
initSearchForm();
|
|
3799
|
+
showFormRegion();
|
|
3612
3800
|
initViewer();
|
|
3613
3801
|
initImages();
|
|
3614
3802
|
initSettings();
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: lunar-toolkit
|
|
3
|
-
Version: 0.1.0.
|
|
3
|
+
Version: 0.1.0.dev13
|
|
4
4
|
Summary: Find, download and process lunar orbital imagery (LROC, ShadowCam, Kaguya TC) and build stereo and shape-from-shading DEMs with ISIS + ASP
|
|
5
5
|
License-Expression: BSD-3-Clause
|
|
6
6
|
Keywords: moon,lroc,shadowcam,kaguya,isis,ames-stereo-pipeline,shape-from-shading,dem
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "lunar-toolkit"
|
|
7
|
-
version = "0.1.0.
|
|
7
|
+
version = "0.1.0.dev13"
|
|
8
8
|
description = "Find, download and process lunar orbital imagery (LROC, ShadowCam, Kaguya TC) and build stereo and shape-from-shading DEMs with ISIS + ASP"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -108,5 +108,5 @@ check_untyped_defs = true
|
|
|
108
108
|
no_implicit_optional = true
|
|
109
109
|
|
|
110
110
|
[[tool.mypy.overrides]]
|
|
111
|
-
module = ["duckdb.*", "shapely.*", "platformdirs.*", "pyarrow.*", "matplotlib.*", "rasterio.*"]
|
|
111
|
+
module = ["duckdb.*", "shapely.*", "platformdirs.*", "pyarrow.*", "matplotlib.*", "rasterio.*", "qtpy.*", "webview.*"]
|
|
112
112
|
ignore_missing_imports = true
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/static/basemaps/manifest.json
RENAMED
|
File without changes
|
{lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/static/basemaps/wac_global.jpg
RENAMED
|
File without changes
|
{lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/static/basemaps/wac_north.jpg
RENAMED
|
File without changes
|
{lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit/static/basemaps/wac_south.jpg
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit.egg-info/entry_points.txt
RENAMED
|
File without changes
|
|
File without changes
|
{lunar_toolkit-0.1.0.dev11 → lunar_toolkit-0.1.0.dev13}/lunar_toolkit.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|