Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | 22x 22x 203x 22x 22x 22x 22x 22x 309x 309x 22x 81x 81x 22x | /** Latitude and longitude graticule with adaptive spacing. */
import {
type Box,
type GridGeometry,
type GridLabel,
type GridPath,
densify,
} from '../../geo/geometry'
export function graticule(view: Box): GridGeometry {
const choices = [30, 10, 5, 2, 1, 0.5, 0.25, 0.1, 0.05, 0.01]
const span = Math.max(view[2] - view[0], view[3] - view[1])
// Choices run largest first, so take the last (smallest) spacing that keeps about two dozen lines in view.
const spacing = choices.findLast(c => span / c <= 24) ?? 30
const paths: GridPath[] = []
const labels: GridLabel[] = []
const [w, s, e, n] = view
const decimals = spacing >= 1 ? 0 : spacing >= 0.1 ? 1 : 2
for (let lon = Math.ceil(w / spacing) * spacing; lon <= e; lon += spacing) {
paths.push({ path: densify([lon, s], [lon, n], (n - s) / 32), width: 0.75 })
labels.push({
position: [lon, s + (n - s) * 0.03],
text: `${lon.toFixed(decimals)}°`,
size: 10,
})
}
for (let lat = Math.ceil(s / spacing) * spacing; lat <= n; lat += spacing) {
paths.push({ path: densify([w, lat], [e, lat], (e - w) / 32), width: 0.75 })
labels.push({
position: [w + (e - w) * 0.03, lat],
text: `${lat.toFixed(decimals)}°`,
size: 10,
})
}
return { paths, labels }
}
|