Continued refactoring of the maps library.

This commit is contained in:
Severin Opel 2019-11-13 12:42:06 +01:00
parent 58cbd44a7b
commit 285e41434a
10 changed files with 193 additions and 118 deletions

View File

@ -5,7 +5,10 @@
<meta charset='UTF-8'>
<title>GeoGraphics</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'>
<script src="../../../dist/iwmlib.3rdparty.js"></script>
@ -67,11 +70,11 @@
wikimedia
], (sprites) => {
let osmMap = new ImageMap(sprites.get(osmworld), new MapData(new Projection.Mercator()), { cover: false })
let osmMap = new ImageMap(sprites.get(osmworld), new MapData(new Projection.Mercator()), { cover: true })
let wikimediaMap = new ImageMap(sprites.get(wikimedia), new MapData(new Projection.Robinson(10)), {
baseZoomHeight: sprites.get(osmworld).texture.height,
cover: false
cover: true
})
app.addMaps({
@ -89,7 +92,6 @@
function enableSwitch(button, app) {
button.addEventListener("click", () => {
let next = app.mapList.next()
console.log(app.mapList)
app.selectMap(next)
})
}

View File

@ -127,6 +127,14 @@ export class GeoGraphics {
return this._position
}
get layer() {
return this._layer ? this._layer : null
}
setLayer(layer) {
this._layer = layer
}
// get map() {
// if (
// this.graphics.layer &&

View File

@ -1,10 +1,8 @@
import { GeoMap } from './map.js'
import MapView from './mapview.js'
import { EventHandler } from './utils.js'
import { PIXILayer } from '../../../../src/layers/js/layer.js'
import Logging from '../../logging.js'
import { GeoGraphics } from './geographics.js'
import { MapList } from './maplist.js'
//import { GeoGraphics } from "../pixi/geographics.js"
/**
@ -13,7 +11,7 @@ import { GeoGraphics } from './geographics.js'
* of the Adaption.
*/
export class GeoLayer {
constructor(displayObject) {
constructor(displayObject, opts = {}) {
if (displayObject == null || !(displayObject instanceof PIXI.DisplayObject)) {
console.error(
`You need to provide a displayObject to make a ${this.constructor.name} out of it.`,
@ -22,15 +20,14 @@ export class GeoLayer {
return null
} else {
this.geographics = []
displayObject.map = this
// displayObject.map = this
this.displayObject = displayObject
this.layers = []
this.pixiAddChild = displayObject.addChild.bind(displayObject)
displayObject.addChild = (...elements) => {
elements.forEach(element => {
if (element instanceof GeoGraphics) {
element.setLayer(this)
this.geographics.push(element)
this.pixiAddChild(element.graphics)
} else {
@ -39,6 +36,62 @@ export class GeoLayer {
})
}
}
this.name = opts['name'] != null ? opts.name : 'Unnamed Layer'
this.parent = null
this.parentMapLayerTransformedHandler = new EventHandler('onParentMapLayerTransformed')
this.layers = []
this._visibility = { min: 0, max: Number.MAX_VALUE }
}
parentMapLayerTransformed(mapLayer) {
this.layers.forEach(layer => {
if (!(layer instanceof MapList)) {
layer.parentMapLayerTransformed()
}
})
this.parentMapLayerTransformedHandler.call(null, mapLayer)
this.rescaleChildren()
}
rescaleChildren() {
let map = this.map
if (this.rescale) {
if (map != null) {
let scale = map.image.scatter.scale
this.displayObject.children.forEach(graphics => {
graphics.scale.set(1 / scale, 1 / scale)
})
}
}
let mapLayer = this.mapLayer
if (this.visibility && mapLayer != null) {
const zoom = mapLayer.mapview.zoom
// TODO
// Currently I dont know what elemnts was.
// We just log an error and resolve this on a later point.
if (zoom > this.visibility.min && zoom < this.visibility.max) {
this.displayObject.children.forEach(it => (it.visible = true))
} else {
this.displayObject.children.forEach(it => (it.visible = false))
}
}
}
set visibility(value) {
let { min = 0, max = Infinity } = value
console.log(min)
this._visibility = { min, max }
}
get visibility() {
return this._visibility
}
addChild(element) {
@ -60,6 +113,8 @@ export class GeoLayer {
this.layers.forEach(layer => {
if (layer.adapt) layer.adapt(map)
})
this.rescaleChildren()
} else console.error('There was no map specified.', this)
}
@ -72,19 +127,54 @@ export class GeoLayer {
// } else super.place(geographic)
// }
removeFromParent() {
if (this.parent) {
this.parent.removeLayer(this)
}
}
removeLayer(layer) {
let idx = this.layers.indexOf(layer)
if (idx != -1) {
layer.parent = null
this.layers.splice(idx, 1)
if (layer.displayObject.parent) {
layer.displayObject.parent.removeChild(layer.displayObject)
}
} else console.warn('Tried to remove layer that was not set.', this, layer)
}
set parent(parent) {
this._parent = parent
}
get parent() {
return this._parent
}
addLayer(layer) {
if (layer instanceof GeoLayer || layer instanceof MapLayer) {
layer.removeFromParent()
this.layers.push(layer)
layer.parent = this
layer.parentChanged()
this.displayObject.addChild(layer.displayObject)
if (this.map) layer.geographics.forEach(geographics => geographics.adaptTo(this.map))
} else
console.error('Could not place layer. Only MapLayer and GeoLayers can be child layers of GeoLayers.', layer)
}
parentChanged() {
this.rescaleChildren()
}
//GeoLayers have to be children of a map layer,
// therefore we can recursively get the map.
get map() {
return this._mapLayer.map
return this.mapLayer ? this.mapLayer.map : null
}
get mapLayer() {
@ -120,18 +210,12 @@ export class MapLayer extends GeoLayer {
constructor(
scatterContainer,
displayObject,
{ onTransform = null, onChange = null, focus = null, zoom = null, viewport = null } = {}
{ onTransform = null, onChange = null, focus = null, zoom = null, viewport = null, mapList = null } = {}
) {
super(displayObject)
let onTransformListeners = [
() => {
this.labelVisibility()
}
]
if (onTransform) onTransformListeners.push(onTransform)
this.transformHandler = new EventHandler('onTransform', {
listeners: onTransformListeners
listeners: onTransform
})
this.scatterContainer = scatterContainer
@ -146,6 +230,7 @@ export class MapLayer extends GeoLayer {
viewport
})
this.mapList = mapList
this._map = null
// //TODO Implement error handling here.
@ -154,46 +239,6 @@ export class MapLayer extends GeoLayer {
this.dynamicElements = new Map()
}
labelVisibility() {
const visibility = this.childrenVisibility
if (visibility) {
const zoom = this.mapview.zoom
const min = visibility.min || 0
const max = visibility.max || Number.MAX_VALUE
// TODO
// Currently I dont know what elemnts was.
// We just log an error and resolve this on a later point.
if (this.elements) {
if (zoom > min && zoom < max) {
this.elements.forEach(it => (it.visible = true))
this.elements.forEach(it => {
const scale = 1 / it.parent.scale.x
// it.children are poi groups
// it.children[0] is the poi group of the tübingen poi
// it.children[0].children are the text containers (not PIXI.Text), about 20 pieces
if (it.children.length > 0) {
it.children[0].children.forEach(poi => {
if (poi.children.length === 1) {
poi.scale.set(scale, scale)
}
})
}
})
} else {
this.elements.forEach(it => (it.visible = false))
}
}else{
console.error("DEBUG: Elements was not defined.")
}
}
}
adapt() {
this.layers.forEach(layer => {
if (layer.adapt) layer.adapt(this.map)
@ -209,6 +254,7 @@ export class MapLayer extends GeoLayer {
transformed(e) {
this.mapview.transformed(this.map)
this.layers.forEach(layer => layer.parentMapLayerTransformed(this))
this.transformHandler.call(this)
}
@ -243,8 +289,7 @@ export class MapLayer extends GeoLayer {
useScatterAsContainer = true // If set to false, the normal container is used. This is necessary when using submaps and the container need to be a RigidContainer.*/
) {
if (map instanceof GeoMap) {
console.log("Change map to: " , map)
console.log('Change map to: ', map)
let oldMap = this.map
if (oldMap) oldMap.unload()
@ -252,10 +297,9 @@ export class MapLayer extends GeoLayer {
this.map.load()
this.scatterContainer.addChild(this.map.image)
console.log(this.map.image.parent)
this.mapview.apply(this.map)
map.image.addChild(this.displayObject)
this.mapview.update(this.map)
// A geolayer's displayObject is on the parent layer.
// A maplayer's displayobject is always the child of the map.

View File

@ -110,23 +110,26 @@
})
function ready(sprites) {
const cover = true
// When resources are loaded, the ImageMap can be instantiated.
let imageMap = new ImageMap(sprites.get(europe), europeData, {
coordsLogging: true,
maxScale: 1,
cover: false
cover
})
let testMapData = new DeepZoomMapData(new Projection.Mercator(), testConfig.tiles, {
app
})
let testMap = new DeepZoomMap(testMapData, Object.assign({}, testConfig.tiles, { app }), { cover: false })
let testMap = new DeepZoomMap(testMapData, Object.assign({}, testConfig.tiles, { app }), { cover })
app.addMap("test", testMap)
let osmMapData = new DeepZoomMapData(new Projection.Mercator(), osmConfig.tiles, {
app
})
let deepZoomMap = new DeepZoomMap(osmMapData, Object.assign({}, osmConfig.tiles, { app }), { cover: false })
let deepZoomMap = new DeepZoomMap(osmMapData, Object.assign({}, osmConfig.tiles, { app }), { cover })
app.addMap("osm", deepZoomMap)
// Finally apply the map to the MapApp

View File

@ -105,7 +105,7 @@ export default class MapApp extends PIXIApp {
super.setup()
// TODO get access to fps display
let fpsDisplay
let fpsDisplay = null
this.stage.children.forEach(element => {
if (element.refreshFps) fpsDisplay = element
})
@ -114,8 +114,7 @@ export default class MapApp extends PIXIApp {
this.ui = new PIXI.Container()
this.scene.addChild(this.ui)
if (this.fpsLogging && fpsDisplay) this.ui.addChild(fpsDisplay)
if (this.fpsLogging != null && fpsDisplay != null) this.ui.addChild(fpsDisplay)
if (this.coordsLogging) {
this.coordsDisplay = new CoordinateDisplay(this)
@ -216,11 +215,12 @@ export default class MapApp extends PIXIApp {
lastMap.flushHandlers()
}
this.map.onTransform.add(this.transformed.bind(this))
this.transformed()
this.onMapChanged.call(this, this.map)
this.map.onTransform.add(this.transformed.bind(this))
if (this.ui && this.ui.parent) {
const parent = this.ui.parent
parent.removeChild(this.ui)
@ -249,11 +249,6 @@ export default class MapApp extends PIXIApp {
this.overlayElements.set(layer, obj)
}
addMapOverlay(layer) {
this.mapLayer.place(layer)
}
/**
* Copies the current coordinates to the clipboard.
*/

View File

@ -27,7 +27,7 @@ export default class MapView {
return this._zoom
}
update(map) {
apply(map) {
map.moveTo(this._focus, this._zoom)
}
@ -36,7 +36,7 @@ export default class MapView {
this.updateFocusPoint(map)
}
applyCameraPosition(map) {
updatePosition(map) {
this.updateFocusPoint(map)
this.updateZoom(map)
}
@ -58,24 +58,39 @@ export default class MapView {
}
mapPointToWindowPoint(map, point) {
let container = map.image.parent
let windowPoint = { x: 0, y: 0 }
let _point = new PIXI.Point(
map.scatter.position.x + map.scatter.scale * point.x,
map.scatter.position.y + map.scatter.scale * point.y
)
if (map['image'] && map.image['parent']) {
let container = map.image.parent
return container.toGlobal(_point)
windowPoint = new PIXI.Point(
map.scatter.position.x + map.scatter.scale * point.x,
map.scatter.position.y + map.scatter.scale * point.y
)
windowPoint = container.toGlobal(windowPoint)
} else {
console.error(this._noParentError)
}
return windowPoint
}
windowPointToMapPoint(map, point) {
let offset = map.image.parent.toGlobal({ x: 0, y: 0 })
let _point = new PIXI.Point(
(point.x - map.scatter.position.x - offset.x) / map.scatter.scale,
(point.y - map.scatter.position.y - offset.y) / map.scatter.scale
)
let pointOnMap = { x: 0, y: 0 }
if (map['image'] && map.image['parent']) {
let offset = map.image.parent.toGlobal({ x: 0, y: 0 })
pointOnMap = new PIXI.Point(
(point.x - map.scatter.position.x - offset.x) / map.scatter.scale,
(point.y - map.scatter.position.y - offset.y) / map.scatter.scale
)
} else console.error(this._noParentError)
return _point
return pointOnMap
}
get _noParentError() {
return 'Cannot compute map point when map has no parent.'
}
/**

View File

@ -78,6 +78,7 @@ export default class Overlay {
scale: 1,
rescale: false,
popoverOffset: { x: 0, y: 0 },
zoomVisibility: { min: 0, max: Number.MAX_VALUE },
/**
* The following Attributes are taken from the TextStyle class
@ -187,6 +188,10 @@ export default class Overlay {
} = {}) {
const name = this.name[0].toUpperCase() + this.name.slice(1).toLowerCase() + ' Overlay'
let geoLayer = new GeoLayer(new PIXI.Container(), { name })
console.log(this)
geoLayer.visibility = this.zoomVisibility
if (this.rescale) geoLayer.rescale = this.rescale
this.items.forEach(item => {
if (!excludeItems(item)) {
@ -201,7 +206,6 @@ export default class Overlay {
})
return geoLayer
}
getItemProperty(item, property) {
let propertyValue = null
const propertyExistsOnItem = item[property] !== undefined
@ -508,7 +512,6 @@ export default class Overlay {
maxWidth: 350
})
if (geographics.map) {
const scale = 1 / geographics.map.scatter.scale
popup.scale.set(scale, scale)

View File

@ -243,7 +243,7 @@
let calculatedCoordinates = mercatorProjection.backward(relativePosition)
// Testcases for the backwards transformation.
Doctest.expect(coordinates, calculatedCoordinates)
Doctest.expectPointPrecision(coordinates, calculatedCoordinates)
let point = createPointAtPoisition(relativePosition)
mercatorMap.appendChild(point)
@ -317,7 +317,7 @@
let relativePosition = robinsonProjection.forward(position)
// Run Test Cases
Doctest.expect(robinsonTruth[key], relativePosition)
Doctest.expectPointPrecision(robinsonTruth[key], relativePosition,0)
let point = createPointAtPoisition(relativePosition)
robinsonMap.appendChild(point)

View File

@ -89,7 +89,7 @@ export class AdvancedScatterContainer extends ScatterContainer {
let interactionManager = this.renderer.plugins.interaction
let displayObject = interactionManager.hitTest(local, this)
console.log(displayObject.dontBlockScatter, displayObject.parent)
if (displayObject.dontBlockScatter && displayObject.parent != null) {
displayObject = interactionManager.hitTest(local, displayObject.parent)
}
@ -97,7 +97,7 @@ export class AdvancedScatterContainer extends ScatterContainer {
if (displayObject != null && displayObject.scatter != null) this.hitScatter = displayObject.scatter
if (this.claimEvents) event.claimedByScatter = this.hitScatter
console.log(displayObject)
return this.hitScatter
}
}
@ -331,26 +331,22 @@ export class CoverScatter extends AdvancedScatter {
this.debugGraphics.endFill()
}
if (this.cover) {
// The reference to the element handler needs to be stored,
// that we can remove it later on.
const eventHandler = this._applyInitialCover.bind(this, null, true)
this._applyInitialCover(eventHandler)
}
// if (this.cover) {
// // The reference to the element handler needs to be stored,
// // that we can remove it later on.
// this._applyInitialCover = this._applyInitialCover.bind(this)
// }
}
_applyInitialCover(eventHandler, removeListener = false) {
if (this.debug) console.log('ApplyInitialCover: ', parent)
if (removeListener) {
this.displayObject.off('added', eventHandler)
}
// _applyInitialCover() {
// if (this.debug) console.log('ApplyInitialCover: ', parent)
if (this.displayObject.parent)
this.forceCover(this.displayObject.parent.width, this.displayObject.parent.height)
else {
this.displayObject.on('added', eventHandler)
}
}
// if (this.displayObject.parent)
// this.forceCover(this.displayObject.parent.width, this.displayObject.parent.height)
// else {
// this.displayObject.on('added', eventHandler)
// }
// }
get boundaries() {
if (this._boundaries) return this._boundaries
@ -472,7 +468,11 @@ export class CoverScatter extends AdvancedScatter {
if (this.scalable && this.parent != null) {
if (this.cover) {
let minCoverScale = this.calculateMinCoverScale(this.parent.width, this.parent.height)
scale = scale < minCoverScale ? minCoverScale : scale
if (scale < minCoverScale) {
console.error('USE MIN COVER SCALE', minCoverScale, scale)
scale = minCoverScale
}
}
this.scale = scale
}
@ -528,7 +528,6 @@ export class MapObjectScatter extends CoverScatter {
)
super(displayObject, renderer, opts)
if (!renderer) {
console.error('Renderer was not set!')
return

View File

@ -331,8 +331,14 @@ export class EventHandler {
}
call(context, ...args) {
this.listeners.forEach(listener => listener.call(context, ...args))
this.onces.forEach(listener => listener.call(context, ...args))
if (context == null) {
this.listeners.forEach(listener => listener(...args))
this.onces.forEach(listener => listener(...args))
} else {
this.listeners.forEach(listener => listener.call(context, ...args))
this.onces.forEach(listener => listener.call(context, ...args))
}
this.onces = []
}