Improved doctests.

This commit is contained in:
Severin Opel 2019-11-05 16:02:27 +01:00
parent 0a30712e31
commit ef16f2b12b
5 changed files with 184 additions and 127 deletions

View File

@ -26,6 +26,7 @@ export class GeoGraphics {
this.drawEndHandler = new EventHandler('onDrawEnd', { listeners: onDrawEnd }) this.drawEndHandler = new EventHandler('onDrawEnd', { listeners: onDrawEnd })
this._points = null this._points = null
this._position = null this._position = null
this.map = null
} }
clone() { clone() {
@ -91,6 +92,7 @@ export class GeoGraphics {
* Called by the containing geo layer, when the map changes. * Called by the containing geo layer, when the map changes.
*/ */
adaptTo(map) { adaptTo(map) {
this.map = map
this._points = this._adaptCoordinates(map) this._points = this._adaptCoordinates(map)
this._updatePosition() this._updatePosition()
this.draw() this.draw()

View File

@ -5,7 +5,12 @@
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<title>Overlay</title> <title>Overlay</title>
<link rel='stylesheet' href='../../3rdparty/highlight/styles/default.css'>
<script src="../../3rdparty/highlight/highlight.pack.js"></script>
<link rel="stylesheet" href="../../../fonts/material-icon-font/material-icons.css">
<link rel='stylesheet' href='../../3rdparty/highlight/styles/vs2015.css'>
<link rel='stylesheet' href='../../../css/doctest.css'> <link rel='stylesheet' href='../../../css/doctest.css'>
<script src="../../../dist/iwmlib.3rdparty.js"></script> <script src="../../../dist/iwmlib.3rdparty.js"></script>
@ -27,14 +32,14 @@
</head> </head>
<body onload="Doctest.run()"> <body onload="Doctest.run()">
<h1>Overlay</h1> <h1 class="title">Overlay</h1>
<p> <p class="description">
The overlayclass creates a convenient way to create and design The overlayclass creates a convenient way to create and design
complex map overlays. complex map overlays.
</p> </p>
<canvas id="view"> </canvas> <canvas id="view" class="center"> </canvas>
<script> <script>
window.pointApp = window.app = new MapApp({ let app = new MapApp({
view, view,
width: 512, width: 512,
height: 512, height: 512,
@ -42,8 +47,25 @@
}) })
var osmworld = '../assets/maps/osm/0/0/0.png' var osmworld = '../assets/maps/osm/0/0/0.png'
let worlOSMData = new MapData(new Projection.Mercator()) let worlOSMData = new MapData(new Projection.Mercator())
function setupMap(textures) {
// Create the map!
let map = new ImageMap(
new PIXI.Sprite(textures.get(osmworld)),
worlOSMData
)
// Setup the map in the mapapp.
app.setMap('osm', map)
app.setup().run()
}
</script> </script>
<script class="doctest">
<script class="doctest" data-collapsible data-collapsed data-title="Overlay Data">
/** /**
* To create an overlay you just need to create a JSON file. * To create an overlay you just need to create a JSON file.
@ -178,6 +200,9 @@
} }
] ]
} }
</script>
<script class="doctest" data-collapsible data-title="Overlay">
let overlay = new Overlay(exampleOverlayJSON) let overlay = new Overlay(exampleOverlayJSON)
@ -189,28 +214,14 @@
let overlayTextures = overlay.findAllTextures() let overlayTextures = overlay.findAllTextures()
let list = [osmworld].concat(overlayTextures) let list = [osmworld].concat(overlayTextures)
pointApp.loadTextures(list, textures => texturesLoaded(textures), { app.loadTextures(list, textures => texturesLoaded(textures), {
resolutionDependent: false resolutionDependent: false
}) })
function texturesLoaded(textures) { function texturesLoaded(textures) {
/** When all textures are loaded .... */ /** When all textures are loaded .... */
setupMap(textures)
// Create the map!
let worldOSMMap = new ImageMap(
new PIXI.Sprite(textures.get(osmworld)),
worlOSMData,
{
onLoaded: () => {
worldOSMMap.setFrame(frame)
}
}
)
// Setup the map in the mapapp.
pointApp.setMap('osm', worldOSMMap)
pointApp.setup().run()
//Retrieve all overlay textures. //Retrieve all overlay textures.
overlay.selectTextures(textures) overlay.selectTextures(textures)
@ -236,7 +247,7 @@
// When placed on the mapLayer, the PIXI Graphic elements, that // When placed on the mapLayer, the PIXI Graphic elements, that
// reside inside GeoGraphic Objects are placed automatically at the // reside inside GeoGraphic Objects are placed automatically at the
// correct coordinates of the map. // correct coordinates of the map.
pointApp.mapLayer.addLayer(exampleOverlayGeoLayer) app.mapLayer.addLayer(exampleOverlayGeoLayer)
// Just a helper function that clears the popups and removes // Just a helper function that clears the popups and removes

View File

@ -508,6 +508,12 @@ export default class Overlay {
maxWidth: 350 maxWidth: 350
}) })
if (geographics.map) {
const scale = 1 / geographics.map.scatter.scale
popup.scale.set(scale, scale)
}
popup.position.set( popup.position.set(
geographics.graphics.position.x - popup.width / 2, geographics.graphics.position.x - popup.width / 2,
geographics.graphics.position.y - popup.height - 20 geographics.graphics.position.y - popup.height - 20

View File

@ -4,16 +4,21 @@
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<title>Projections</title> <title>Projections</title>
<link rel="stylesheet" href="../../../3rdparty/highlight/styles/default.css" />
<link rel="stylesheet" href="../../../../css/doctest.css" /> <script src="../../../3rdparty/highlight/highlight.pack.js"></script>
<link rel="stylesheet" href="../../../../fonts/material-icon-font/material-icons.css">
<link rel='stylesheet' href='../../../3rdparty/highlight/styles/vs2015.css'>
<link rel='stylesheet' href='../../../../css/doctest.css'>
<script src="../../../../dist/iwmlib.3rdparty.js"></script> <script src="../../../../dist/iwmlib.3rdparty.js"></script>
<script src="../../../../dist/iwmlib.js"></script> <script src="../../../../dist/iwmlib.js"></script>
<script src="../../../../dist/iwmlib.pixi.js"></script> <script src="../../../../dist/iwmlib.pixi.js"></script>
<style> <style>
.inline-showcase { section {
display: flex; display: flex;
flex-direction: column;
} }
.map-example { .map-example {
@ -26,6 +31,7 @@
position: relative; position: relative;
/* inline-block create additional space around child elements. */ /* inline-block create additional space around child elements. */
display: inline-flex; display: inline-flex;
margin: 100px;
} }
.long { .long {
@ -42,15 +48,21 @@
transform: translate(-50%, -50%); transform: translate(-50%, -50%);
position: absolute; position: absolute;
width: 3px; width: 5px;
height: 3px; height: 5px;
background-color: red; background-color: red;
border-radius: 50%; border-radius: 50%;
} }
.small.point { .small.point {
width: 1px; width: 2px;
height: 1px; height: 2px;
}
.medium.point {
width: 4px;
height: 4px;
opacity: 0.5;
} }
.line { .line {
@ -73,33 +85,35 @@
<h2>Mercator Projection</h2> <h2>Mercator Projection</h2>
<p>The most commonly used projection is the mercator projection.</p> <p>The most commonly used projection is the mercator projection.</p>
<div id="mercatorMap" class="map-wrapper"> <div class="center">
<img src="../../../examples/osm/0/0/0.png" alt="" /> <div id="mercatorMap" class="map-wrapper">
<img src="../../assets/maps/osm/0/0/0.png" alt="" />
</div>
</div> </div>
<script> <script>
let boundaries = [ let boundaries = [
// { x: -90, y: -180 }, { x: -90, y: -180 },
// { x: 90, y: 180 }, { x: 90, y: 180 },
// { x: 0, y: 0 }, { x: 0, y: 0 },
// { x: 90, y: -180 }, { x: 90, y: -180 },
// Eastern Boundaries // Eastern Boundaries
// { x: -22, y: 180 }, { x: -22, y: 180 },
// { x: -43, y: 180 }, { x: -43, y: 180 },
// { x: -63, y: 180 }, { x: -63, y: 180 },
// { x: -73, y: 180 }, { x: -73, y: 180 },
// { x: -83, y: 180 }, { x: -83, y: 180 },
// { x: -87, y: 180 }, { x: -87, y: 180 },
// { x: 0, y: 180 }, { x: 0, y: 180 },
// { x: 22, y: 180 }, { x: 22, y: 180 },
// { x: 43, y: 180 }, { x: 43, y: 180 },
// { x: 63, y: 180 }, { x: 63, y: 180 },
// { x: 73, y: 180 }, { x: 73, y: 180 },
// { x: 83, y: 180 }, { x: 83, y: 180 },
{ x: 87, y: 180 }, { x: 87, y: 180 },
// { x: -90, y: 180 }, { x: -90, y: 180 },
// Western Boundaries // Western Boundaries
{ x: -22, y: -180 }, { x: -22, y: -180 },
@ -135,7 +149,6 @@
* *
*/ */
function createPointAtPoisition(position, className = '', style = {}) { function createPointAtPoisition(position, className = '', style = {}) {
console.log(position)
let point = document.createElement('div') let point = document.createElement('div')
point.className = 'point ' + className point.className = 'point ' + className
@ -168,9 +181,24 @@
function plotGridPoints(distance = 10, projection, parent) { function plotGridPoints(distance = 10, projection, parent) {
for (let lat = -90; lat <= 90; lat += distance) { for (let lat = -90; lat <= 90; lat += distance) {
for (let lng = -180; lng <= 180; lng += distance) { for (let lng = -180; lng <= 180; lng += distance) {
let color = "#0000ff"
let className = 'small'
if (lng == 180) {
color = '#ff0000'
lng = (lng == 180) ? 180 : lng
}
if (lng == -180) {
color = '#00ff00'
lng = (lng == 180) ? 180 : lng
className = "medium"
}
let relativePosition = projection.forward({ x: lat, y: lng }) let relativePosition = projection.forward({ x: lat, y: lng })
let point = createPointAtPoisition(relativePosition, 'small', { let point = createPointAtPoisition(relativePosition, className, {
backgroundColor: '#0000ff' backgroundColor: color
}) })
robinsonMap.appendChild(point) robinsonMap.appendChild(point)
} }
@ -179,25 +207,49 @@
</script> </script>
<script class="doctest" data-collapsible data-collapsed data-title="Test Data">
let mercatorTruth = {
abidjan: { x: 0.4861111111111111, y: 0.4860934491519468 },
canberra: { x: 0.9142264972222222, y: 0.6049626977761389 },
berlin: { x: 0.5371813638888889, y: 0.327930370913594 },
capetown: { x: 0.5511582277777778, y: 0.6002818272799257 },
moscow: { x: 0.604507775, y: 0.3126267957774014 },
washington: { x: 0.28602386944444447, y: 0.3825518808752881 },
rio: { x: 0.3797764166666667, y: 0.5652894059707362 },
tokio: { x: 0.8881426833333332, y: 0.39372656277794527 }
}
</script>
<script class="doctest"> <script class="doctest">
; (function () { ; (function () {
let mercatorProjection = new Projection.Mercator()
for (let position of Object.values(capitals)) { //First we define the appropriate projection:
let relativePosition = mercatorProjection.forward(position) let mercatorProjection = new Projection.Mercator()
let point = createPointAtPoisition(relativePosition)
mercatorMap.appendChild(point)
}
boundaries.forEach(coord => {
let relativePosition = mercatorProjection.forward(coord) for (let [name, coordinates] of Object.entries(capitals)) {
let point = createPointAtPoisition(relativePosition, 'small', {
backgroundColor: '#0000ff' // Every projection has a forward and a backward function.
})
mercatorMap.appendChild(point) // The forward function transforms coordinates in the form of
}) // {x: lat, y: lng} into relative screen coordinates in the form of {x,y}.
})() let relativePosition = mercatorProjection.forward(coordinates)
// Testcases for the forward transformation.
Doctest.expect(mercatorTruth[name], relativePosition)
// The backward function transforms relative positions on the screen
// to geographic coordinates.
let calculatedCoordinates = mercatorProjection.backward(relativePosition)
// Testcases for the backwards transformation.
Doctest.expect(coordinates, calculatedCoordinates)
let point = createPointAtPoisition(relativePosition)
mercatorMap.appendChild(point)
}
})()
</script> </script>
</section> </section>
<section id="robinson"> <section id="robinson">
@ -207,10 +259,47 @@
formula. It has severe distortions at the poles, but that distortion declines rapidly heading towards formula. It has severe distortions at the poles, but that distortion declines rapidly heading towards
the equator. the equator.
</p> </p>
<div class="center">
<div id="robinsonMap" class="map-wrapper"> <div id="robinsonMap" class="map-wrapper">
<img src="../../assets/maps/wikimedia-world-robinson/2000px-BlankMap-World.png" alt="" width="512" /> <img src="../../assets/maps/wikimedia-world-robinson/2000px-BlankMap-World.png" alt="" width="512" />
</div>
</div> </div>
<script class="doctest" data-collapsible data-collapsed data-title="Test Data">
let robinsonTruth = {
"abidjan": {
"x": 0.45839166666666664,
"y": 0.469
},
"canberra": {
"x": 0.8637961558795233,
"y": 0.71892906228
},
"berlin": {
"x": 0.5080051098978837,
"y": 0.17622420010000006
},
"capetown": {
"x": 0.522127677557207,
"y": 0.7103377776
},
"moscow": {
"x": 0.5636501036295355,
"y": 0.15721735316000007
},
"washington": {
"x": 0.27607293856102144,
"y": 0.25892488299999994
},
"rio": {
"x": 0.35541500995592845,
"y": 0.6418026800000001
},
"tokio": {
"x": 0.8386571387301243,
"y": 0.27869700196
}
}
</script>
<script class="doctest"> <script class="doctest">
; (function () { ; (function () {
@ -224,16 +313,15 @@
/** /**
* Create a point for each capital. * Create a point for each capital.
*/ */
for (let position of Object.values(capitals)) { for (let [key, position] of Object.entries(capitals)) {
let relativePosition = robinsonProjection.forward(position) let relativePosition = robinsonProjection.forward(position)
// Run Test Cases
Doctest.expect(robinsonTruth[key], relativePosition)
let point = createPointAtPoisition(relativePosition) let point = createPointAtPoisition(relativePosition)
robinsonMap.appendChild(point) robinsonMap.appendChild(point)
} }
drawZeroLongitude(robinsonProjection, robinsonMap)
plotGridPoints(5, robinsonProjection, robinsonMap)
})() })()
</script> </script>
</section> </section>

View File

@ -1,50 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<link rel="stylesheet" href="../../../3rdparty/highlight/styles/default.css" />
<link rel="stylesheet" href="../../../../css/doctest.css" />
<script src="../../../../dist/iwmlib.3rdparty.js"></script>
<script src="../../../../dist/iwmlib.js"></script>
<script src="../../../../dist/iwmlib.pixi.js"></script>
</head>
<body>
<section id="solution">
</section>
<script>
function write(msg) {
if (typeof msg === "object") {
msg = JSON.stringify(msg)
}
let log = document.createElement("p")
log.innerHTML = msg
solution.appendChild(log)
}
let coords = { x: -30, y: -30 }
write(coords)
let robinson = new Projection.Robinson()
let pixels = robinson.forward(coords)
write(pixels)
coords = robinson.backwards(pixels)
write(coords)
</script>
</body>
</html>