JavaFX и Mapsforge - PullRequest
       84

JavaFX и Mapsforge

0 голосов
/ 01 марта 2019

Очень необходимо встраивать автономные карты в настольное приложение.Лучшее, на что я смотрю - это Mapsforge.Но я столкнулся с небольшой проблемой.Я использую JavaFX (Kotlin - TornadoFX) и не могу использовать используемый там AWT.Я пытаюсь сделать это через JPanel и Swingnode.Карта не показана.

Мой код, если необходимо:

class MyApp : App(SecondView::class, Styles::class) {

    private val GRAPHIC_FACTORY = AwtGraphicFactory.INSTANCE
    private val SHOW_DEBUG_LAYERS = false
    private val SHOW_RASTER_MAP = false

    override fun start(stage: Stage) {

        val swingNode = SwingNode()

        createSwingContent(swingNode)

        val pane = StackPane()
        pane.children.add(swingNode)

        stage.title = "Swing in KotlinFX"
        stage.scene = Scene(pane, 800.0, 600.0)
        stage.show()

    }

    private fun createSwingContent(swingNode: SwingNode) {
        SwingUtilities.invokeLater {

            val jPanel = JPanel()


            //это с main
            org.mapsforge.core.util.Parameters.NUMBER_OF_THREADS = 2
            org.mapsforge.core.util.Parameters.SQUARE_FRAME_BUFFER = false

            var hillsCfg:HillsRenderConfig? = null

            var args = arrayOf("/Users/dev/Documents/maps/world.map")

            var demFolder = getDemFolder(args)
            if (demFolder!=null) {
                var tileSource = MemoryCachingHgtReaderTileSource(demFolder, DiffuseLightShadingAlgorithm(), AwtGraphicFactory.INSTANCE)
                tileSource.isEnableInterpolationOverlap = true
                hillsCfg = HillsRenderConfig(tileSource)
                hillsCfg.indexOnThread()
                args = Arrays.copyOfRange(args,1,args.size)
            }

            var mapFiles = if (SHOW_RASTER_MAP) {null} else {getMapFiles(args)}

            val mapView = createMapView()
            mapView.model.mapViewPosition.mapPosition = MapPosition(LatLong(0.0, 0.0),14.toByte())
            val boundingBox = addLayers(mapView, mapFiles,hillsCfg)

            jPanel.add(mapView)
            swingNode.content = jPanel
        }
    }

    private fun addLayers(mapView: MapView, mapFiles: List<File>?, hillsRenderConfig: HillsRenderConfig?): BoundingBox {
        val layers = mapView.layerManager.layers

        val tileSize = if (SHOW_RASTER_MAP) 256 else 512

        // Tile cache
        val tileCache = AwtUtil.createTileCache(
                tileSize,
                mapView.model.frameBufferModel.overdrawFactor,
                1024,
                File(System.getProperty("java.io.tmpdir"), UUID.randomUUID().toString()))

        val boundingBox: BoundingBox
        if (SHOW_RASTER_MAP) {
            // Raster
            mapView.model.displayModel.setFixedTileSize(tileSize)
            val tileSource = OpenStreetMapMapnik.INSTANCE
            val tileDownloadLayer = createTileDownloadLayer(tileCache, mapView.model.mapViewPosition, tileSource)
            layers.add(tileDownloadLayer)
            tileDownloadLayer.start()
            mapView.setZoomLevelMin(tileSource.zoomLevelMin)
            mapView.setZoomLevelMax(tileSource.zoomLevelMax)
            boundingBox = BoundingBox(LatLongUtils.LATITUDE_MIN, LatLongUtils.LONGITUDE_MIN, LatLongUtils.LATITUDE_MAX, LatLongUtils.LONGITUDE_MAX)
        } else {
            // Vector
            mapView.model.displayModel.setFixedTileSize(tileSize)
            val mapDataStore = MultiMapDataStore(MultiMapDataStore.DataPolicy.RETURN_ALL)
            if (mapFiles!=null) {
                for (file in mapFiles) {
                    mapDataStore.addMapDataStore(MapFile(file), false, false)
                }
            }
            val tileRendererLayer = createTileRendererLayer(tileCache, mapDataStore, mapView.model.mapViewPosition, hillsRenderConfig)
            layers.add(tileRendererLayer)
            boundingBox = mapDataStore.boundingBox()
        }

        // Debug
        if (SHOW_DEBUG_LAYERS) {
            layers.add(TileGridLayer(GRAPHIC_FACTORY, mapView.model.displayModel))
            layers.add(TileCoordinatesLayer(GRAPHIC_FACTORY, mapView.model.displayModel))
        }


        return boundingBox
    }

    private fun createMapView(): MapView {
        val mapView = MapView()
        mapView.mapScaleBar.isVisible = true
        if (SHOW_DEBUG_LAYERS) {
            mapView.fpsCounter.isVisible = true
        }

        return mapView
    }

    private fun createTileDownloadLayer(tileCache: TileCache, mapViewPosition: IMapViewPosition, tileSource: TileSource): TileDownloadLayer {
        return object : TileDownloadLayer(tileCache, mapViewPosition, tileSource, GRAPHIC_FACTORY) {
            fun onTap(tapLatLong: LatLong, layerXY: Point, tapXY: Point): Boolean {
                println("Tap on: $tapLatLong")
                return true
            }

            override fun onTap(tapLatLong: LatLong?, layerXY: org.mapsforge.core.model.Point?, tapXY: org.mapsforge.core.model.Point?): Boolean {
                println("Tap1 on: $tapLatLong")
                return super.onTap(tapLatLong, layerXY, tapXY)
            }
        }
    }

    private fun createTileRendererLayer(tileCache: TileCache, mapDataStore: MapDataStore, mapViewPosition: IMapViewPosition, hillsRenderConfig: HillsRenderConfig?): TileRendererLayer {
        val tileRendererLayer = object : TileRendererLayer(tileCache, mapDataStore, mapViewPosition, false, true, false, GRAPHIC_FACTORY, hillsRenderConfig) {
            override fun onTap(tapLatLong: LatLong?, layerXY: org.mapsforge.core.model.Point?, tapXY: org.mapsforge.core.model.Point?): Boolean {
                println("TAP on: $tapLatLong")
                return true
            }
        }
        tileRendererLayer.setXmlRenderTheme(InternalRenderTheme.DEFAULT)
        return tileRendererLayer
    }

    private fun getDemFolder(args: Array<String>): File? {
        if (args.size == 0) {
            return if (SHOW_RASTER_MAP) {
                null
            } else {
                throw IllegalArgumentException("missing argument: <mapFile>")
            }
        }

        val demFolder = File(args[0])
        return if (demFolder.exists() && demFolder.isDirectory && demFolder.canRead()) {
            demFolder
        } else null
    }

    private fun getMapFiles(args:Array<String>): List<File> {
        if (args.size == 0) {
            throw IllegalStateException("missing argument: <mapFile>")
        }
        var result = ArrayList<File>()
        for (arg in args) {
            var mapFile = File(arg)
            if (!mapFile.exists()) {
                throw IllegalArgumentException("file does not exist: " + mapFile);
            } else if (!mapFile.isFile()) {
                throw IllegalArgumentException("not a file: " + mapFile);
            } else if (!mapFile.canRead()) {
                throw IllegalArgumentException("cannot read file: " + mapFile);
            }
            result.add(mapFile)
        }

        return result
    }


}

Или есть какое-то простое использование карт для JavaX и Openstreetmap?

...