openlayers / ol-cesium

OpenLayers - Cesium integration
http://openlayers.org/ol-cesium/
BSD 2-Clause "Simplified" License
1.01k stars 329 forks source link

Errors using small TMS tileset #299

Open dilignt opened 8 years ago

dilignt commented 8 years ago

I've got a small TMS tileset that I've created a ol3 map with. The tilemap resource file uses pixel coordinates,

<?xml version="1.0" encoding="utf-8"?>
<TileMap version="1.0.0" tilemapservice="http://tms.osgeo.org/1.0.0">
  <Title>Small TMS set</Title>
  <Abstract></Abstract>
  <SRS></SRS>
  <BoundingBox minx="-4949.00000000000000" miny="0.00000000000000" maxx="0.00000000000000" maxy="7000.00000000000000"/>
  <Origin x="-4949.00000000000000" y="0.00000000000000"/>
  <TileFormat width="256" height="256" mime-type="image/jpeg" extension="jpg"/>
  <TileSets profile="raster">
    <TileSet href="0" units-per-pixel="32.00000000000000" order="0"/>
    <TileSet href="1" units-per-pixel="16.00000000000000" order="1"/>
    <TileSet href="2" units-per-pixel="8.00000000000000" order="2"/>
    <TileSet href="3" units-per-pixel="4.00000000000000" order="3"/>
    <TileSet href="4" units-per-pixel="2.00000000000000" order="4"/>
    <TileSet href="5" units-per-pixel="1.00000000000000" order="5"/>
  </TileSets>
</TileMap>

The code I've used to create the ol3 map is

var res = 32;
var levels = 6;
var x = 7000;
var y = 4949;
var extent = [0,0,x,y];
var resolutions = [32, 16, 8, 4, 2, 1];

var mapLayer = new ol.layer.Tile({
    preload: Infinity,
    source: new ol.source.TileImage({
        crossOrigin: null,
        extent: extent,
        tileGrid: new ol.tilegrid.TileGrid({
            extent: extent,
            origin: [0,0],
            resolutions: resolutions
        }),
        tileUrlFunction: function(c) {
            if (c === null) return undefined;
            return  host + '/'+ c[0] +'/'+ c[1] +'/'+ c[2] +'.jpg';
        }
    })
});

var map = new ol.Map({
  layers: [
    mapLayer
  ],
  target: 'map2d',
  controls: ol.control.defaults({
    attributionOptions:
      collapsible: false
    })
  }),
    view :  new ol.View ({
        center: [x/2, y/2],
        resolution: 16,
        resolutions: resolutions,
        extent: extent,
        constrainRotation: true
    })
});

This ol3 map works great. I'm now trying to view the map using ol3-cesium with a SceneMode of COLUMBUS_VIEW with the following code

var ol3d = new olcs.OLCesium({map: map, target: 'map3d' });
var scene = ol3d.getCesiumScene();
scene.mode = Cesium.SceneMode.COLUMBUS_VIEW;
ol3d.setEnabled(true);

I had to change the scene3DOnly parameter to false in the build when olcs is initialising the scene to get the code to run.

The ol3-cesium view is not rendering correctly - there are loads of missing image tile errors, and the 3d scene is not showing. What am I missing - is there some conversion that needs to happen, or some bounding rectangle that needs to be configured somewhere? Is it possible to use small TMS tilesets in ol3-cesium with columbus view?

Any help gratefully appreciated - many thanks in advance

gberaudo commented 8 years ago

@dilignt, if you remove you columbus changes, does the tileset appears in 3D?

dilignt commented 8 years ago

Thanks for your reply @gberaudo

No - I can't get any 3d view with those changes removed, it's just a blue screen. Looking at the console it seems that none of the images can be found because the path is being formatted Incorrectly. eg

An error occurred in "kh": Failed to obtain image tile X: 1 Y: 0 Level: 1.
An error occurred in "kh": Failed to obtain image tile X: 1 Y: 1 Level: 1

on Line 424 of Cesium.js it is looking for the images in paths host/1/1/-1.jpg and host/1/1/-2.jpg but the images are actually at host/1/1/0.jpg and host/1/1/1.jpg. All of the tiles have the same error in Cesium, but they are fine in ol3. Do you know what needs to change so that the images can be found correctly?

gberaudo commented 8 years ago

@dilignt, in 2D, OL3 is displaying your map while in 3D it is Cesium. You are using a custom tilegrid in OL3 but there is no support for this in OL3-Cesium. In a general case, I think it would require reprojection.

Tiles are requested by Cesium in src/core/olimageryprovider.js requestImage(). You may try to adapt the code there.

Alternatively, you may try using a standard tilegrid, and restrict the layer to your extent: http://openlayers.org/en/master/apidoc/ol.source.XYZ.html http://openlayers.org/en/master/apidoc/ol.layer.Layer.html For this to work, you will need to generate you tileset on a global tilegrid.

dilignt commented 8 years ago

Thanks - I tried changing requestImage() and the tiles are now loaded into cesium. The problem now is that the 3d view is zoomed all the way in so that you can't see the images at all. If I zoom out I start to see a tile magnified, but then the browser runs out of memory and crashes. There are also other tile requests from Cesium for tiles that are outwith the bounding box of my tileset. Is there a way to somehow constrain the zoom levels and extent of the 3d view in Cesium so that these problems don't occur?

gberaudo commented 8 years ago

There is a rectangle property on the imagery provider.

dilignt commented 8 years ago

Yes, I noticed the Rectangle, but I can't see a way to convert my pixel dimensions into radians or degrees when my tileset is flat and not a globe - Cesium.Rectangle is instantiated with NSEW lat/lon points in radians. Do you know if this is possible?

I have no way of generating a tileset on a global grid - it isn't a map it's a floorplan.