Announcement

Collapse
No announcement yet.

How to implement a public non WMS tile set ?

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • How to implement a public non WMS tile set ?

    Hello

    I'm looking for a way to render a public map tile service such as mapbox or stamen onto a publicly available instance of Nasa Web World Wind.

    Mapbox and Stamen serve their tiles like this:
    http://api.mapbox.com/v4/mapbox.terrain/3/2/3.jpg
    http://tile.stamen.com/watercolor/3/2/3.jpg

    But NWWW appears to require WMS.

    Is there a clear example of how to implement this ?

    Thanks
    Last edited by timoto; 07-27-2018, 04:58 AM. Reason: NOT RESOLVED

  • #2
    Depending on the source imagery projection, this can be accomplished by using either the RestImageLayer or a customized UrlFactory with the MercatorTiledImageLayer.
    Zach
    World Wind Team
    https://github.com/NASAWorldWind

    Comment


    • #3
      Thanks Zach, I will see how far we get with those possibilities.

      When you write "RestImageLayer" do you mean "RestTiledImageLayer" https://nasaworldwind.github.io/WebW...mageLayer.html ?

      When you write "UrlFactory" do you mean "UrlBuilder" https://nasaworldwind.github.io/WebW...rlBuilder.html ?

      I guess mapbox and stamen are all mercator projections so perhaps MercatorTiledImageLayer makes sense. Are there any working examples of either method that I could take a look at ?

      Thanks

      Comment


      • #4
        A working example of MercatorTiledImageLayer with UrlBuilder would help me a lot.

        Comment


        • #5
          You're right on the naming, whoops!

          All of the Bing imagery layers are concrete implementations of MercatorTiledImageLayer with custom UrlBuilders. So take a look at BingAerialWithLabelsLayer and BingImageryUrlBuilder.
          Zach
          World Wind Team
          https://github.com/NASAWorldWind

          Comment


          • #6
            Hi Glueck, thank you for pointing me in the right direction.

            I must say I am having to hunt around a bit.

            Although BingAerialWithLabelsLayer does call MercatorTiledImageLayer it actually does this from: https://nasaworldwind.github.io/WebW...eLayer.js.html where we actually see the function in use.

            UrlBuilder use in BingImageUrlBuilder https://nasaworldwind.github.io/WebW...uilder.js.html looks like enough information to go on, but I may come back with some more questions.

            Thanks

            Comment


            • #7
              Originally posted by glueck View Post
              You're right on the naming, whoops!

              All of the Bing imagery layers are concrete implementations of MercatorTiledImageLayer with custom UrlBuilders. So take a look at BingAerialWithLabelsLayer and BingImageryUrlBuilder.
              Hello glueck

              My developer says he is struggling with this setup. He says:

              The classes BingTiledImageLayer and BingImageryUrlBuilder use RequireJS but we do not host NWWW locally - we include the js library directly from their server. Now, I copy the classes and modify them but my question is how do I include the modules that are usually included with RequireJS. For example BingTiledImageLayer needs:

              define([
              '../geom/Angle',
              '../util/Color',
              '../geom/Location',
              '../util/Offset',
              '../shapes/ScreenImage',
              '../geom/Sector',
              '../layer/MercatorTiledImageLayer'
              ],

              For example I cannot get LayerManager();

              How do I invoke "MercatorTiledImageLayer"?

              Can you help ?

              Thanks

              Tim

              Comment


              • #8
                To add to this I wondered if we could host the library locally, but my developer says

                "It is possible but why should we do that when we can use the latest library directly from their [nasa] server."

                So far he has got this much figured out:
                Code:
                var wwd = new WorldWind.WorldWindow("canvasOne"); WorldWind.StamenUrlBuilder = function ( imagerySet, ) { var StamenUrlBuilder = function ( imagerySet ) { this.imagerySet = imagerySet; }; StamenUrlBuilder.urlForTile = function ( tile, imageFormat ) { console.log( tile ); if ( !tile ) { console.log( "Missing tile!" ); } var url = "http://tile.stamen.com/watercolor/" + tile.level.levelNumber + "/" + tile.row + "/" + tile.column + ".jpg"; console.log( url ); return url; }; return StamenUrlBuilder; }; WorldWind.StamenWatercolor = function ( displayName ) { this.imageSize = 256; var StamenWatercolor = new WorldWind.MercatorTiledImageLayer( new WorldWind.Sector( -90, 90, -180, 180 ), new WorldWind.Location( 85.05, 180 ), 23, "image/jpeg", displayName, this.imageSize, this.imageSize ); StamenWatercolor.pickEnabled = false; StamenWatercolor.detectBlankImages = true; StamenWatercolor.mapSizeForLevel = function (levelNumber) { return 256 << (levelNumber + 1); }; StamenWatercolor.urlBuilder = new WorldWind.StamenUrlBuilder( "StamenWatercolor" ); return StamenWatercolor; }; wwd.addLayer( new WorldWind.BMNGOneImageLayer() ); var stamen = new WorldWind.StamenWatercolor( "StamenWatercolor" ); wwd.addLayer( stamen );

                He says it still doesn't work but at least it doesn't throw errors.

                Please can you shed some more light on this issue.

                The test link is here:
                http://dev.globaltimoto.com/

                Thanks

                Tim
                Last edited by timoto; 07-28-2018, 02:26 PM. Reason: code block

                Comment


                • #9
                  Can anyone with experience of this issue please chime in.

                  Thanks

                  Comment


                  • #10
                    OK my developer got a bit further down the line. Tiles from Stamen, a Web Mercator projection, are now being rendered on the globe.

                    However the tiles are not rendering as expected.

                    Click image for larger version

Name:	nwww-stamen.jpg
Views:	1
Size:	290.5 KB
ID:	158519


                    From your experience what could be the issue here ?

                    Comment


                    • #11
                      Yep, it's a problem of level/row/column...Here is the java code I use. The key is the URLBuilder. Don't forget to implement a Stamen ScreenCredit/Copyright somewhere in your app. Enjoy.
                      Code:
                      public class StamenWaterColorLayer extends BasicMercatorTiledImageLayer {
                          private static final String LAYER_NAME = "Stamen Watercolor";
                      
                          public StamenWaterColorLayer() {
                              super(LAYER_NAME, makeLevels());
                          }
                      
                          private static LevelSet makeLevels() {
                              AVList params = new AVListImpl();
                      
                              params.setValue(AVKey.TILE_WIDTH, 256);
                              params.setValue(AVKey.TILE_HEIGHT, 256);
                              params.setValue(AVKey.DATA_CACHE_NAME, "Earth/Stamen/Watercolor");
                              params.setValue(AVKey.SERVICE, "http://tile.stamen.com/watercolor/");
                              params.setValue(AVKey.DATASET_NAME, "*");
                              params.setValue(AVKey.FORMAT_SUFFIX, ".jpg");
                              params.setValue(AVKey.NUM_LEVELS, 16);
                              params.setValue(AVKey.NUM_EMPTY_LEVELS, 0);
                              params.setValue(AVKey.LEVEL_ZERO_TILE_DELTA, new LatLon(Angle.fromDegrees(22.5d), Angle.fromDegrees(45d)));
                              params.setValue(AVKey.SECTOR, new MercatorSector(-1.0, 1.0, Angle.NEG180, Angle.POS180));
                              params.setValue(AVKey.TILE_URL_BUILDER, new URLBuilder());
                              params.setValue(AVKey.SCREEN_CREDIT, LayerPanelUtil.buildScreenCredit(LayerPanelUtil.STAMEN));
                      
                              return new LevelSet(params);
                          }
                      
                          private static class URLBuilder implements TileUrlBuilder {
                              public URL getURL(Tile tile, String imageFormat) throws MalformedURLException {
                                  return new URL(tile.getLevel().getService() + (tile.getLevelNumber() + 3) + "/" + tile.getColumn() + "/" + ((1 << (tile.getLevelNumber()) + 3) - 1 - tile.getRow()) + ".png");
                              }
                          }
                      
                          @Override
                          public String toString() {
                              return LAYER_NAME;
                          }
                      }

                      Comment


                      • #12
                        Hi frenchy

                        Thanks for the input. I will pass it on.

                        Yes credits will follow once prototyping is complete.

                        Tim

                        Comment


                        • #13
                          Hi @frenchy

                          The developer resolved that issue by incrementing the level for the tile, here is the code for reference:

                          Code:
                          define( 'layer/StamenWatercolor',
                          [
                          '../geom/Location',
                          '../geom/Sector',
                          '../layer/StamenTiledImageLayer',
                          '../util/StamenImageryUrlBuilder'
                          ],
                          function (Location,
                          Sector,
                          StamenTiledImageLayer,
                          StamenImageryUrlBuilder) {
                          "use strict";
                          
                          var StamenWatercolor = function () {
                          StamenTiledImageLayer.call(this, "Stamen Watercolor");
                          this.urlBuilder = new StamenImageryUrlBuilder("StamenWatercolor");
                          };
                          StamenWatercolor.prototype = Object.create(StamenTiledImageLayer.prototype);
                          
                          return StamenWatercolor;
                          });
                          
                          define( 'layer/StamenTiledImageLayer',
                          [
                          '../geom/Angle',
                          '../util/Color',
                          '../geom/Location',
                          '../util/Offset',
                          '../shapes/ScreenImage',
                          '../geom/Sector',
                          '../layer/MercatorTiledImageLayer'
                          ],
                          function (Angle,
                          Color,
                          Location,
                          Offset,
                          ScreenImage,
                          Sector,
                          MercatorTiledImageLayer) {
                          "use strict";
                          
                          var StamenTiledImageLayer = function (displayName) {
                          this.imageSize = 256;
                          MercatorTiledImageLayer.call(this,
                          new Sector(-90, 90, -180, 180), new Location(90, 90), 22, "image/jpeg", displayName,
                          this.imageSize, this.imageSize);
                          this.displayName = displayName;
                          // TODO: Picking is enabled as a temporary measure for screen credit hyperlinks to work (see Layer.render)
                          this.pickEnabled = true;
                          };
                          StamenTiledImageLayer.prototype = Object.create(MercatorTiledImageLayer.prototype);
                          StamenTiledImageLayer.prototype.doRender = function (dc) {
                          MercatorTiledImageLayer.prototype.doRender.call(this, dc);
                          };
                          
                          // Determines the Stamen map size for a specified level number.
                          StamenTiledImageLayer.prototype.mapSizeForLevel = function (levelNumber) {
                          return 256 << (levelNumber + 1);
                          };
                          return StamenTiledImageLayer;
                          });
                          
                          define( 'util/StamenImageryUrlBuilder',
                          [
                          '../error/ArgumentError',
                          '../util/Logger',
                          '../util/WWUtil'
                          ],
                          function (ArgumentError,
                          Logger,
                          WWUtil) {
                          "use strict";
                          
                          var StamenImageryUrlBuilder = function (imagerySet) {
                          
                          this.imagerySet = imagerySet;
                          };
                          
                          StamenImageryUrlBuilder.prototype.urlForTile = function ( tile, imageFormat ) {
                          
                          if ( !tile ) {
                          
                          console.log( "Missing tile!" );
                          }
                          
                          var url = "https://stamen-tiles.a.ssl.fastly.net/watercolor/" + ( tile.level.levelNumber + 1 ) + "/" + tile.column + "/" + tile.row + ".jpg";
                          
                          return url;
                          };
                          
                          return StamenImageryUrlBuilder;
                          });
                          At this stage we have 2 further issues with the setup:

                          1. Why are the North and South poles missing ?

                          Click image for larger version

Name:	nwww-stamen-2.jpg
Views:	1
Size:	383.9 KB
ID:	158526


                          This is also seen on NWWW examples:

                          Click image for larger version

Name:	nwww-poles-missing.png
Views:	2
Size:	101.9 KB
ID:	158528

                          2. Why don't tiles load/render higher resolution of the tiles when expected?

                          The levels need to switch earlier.

                          Perhaps this is due to levelZeroDelta but we don't know what values should be used.

                          36,36 seem to render a really low quality map, where 180,180 renders high quality but only the Northern hemisphere is displayed. Anything more than 90,90 doesn't render the full sphere.

                          Current example is here: https://dev.globaltimoto.com

                          Thanks
                          Attached Files

                          Comment


                          • #14
                            0/ Nice! But i advice you to put a logo somewhere, or you'll be in trouble soon, even with opensource stuff.
                            1/ That's the way it is. Historically WMS servers don't display at these latitudes (even after 85N, or below 85S) because projection maths go crazy with tangential problems... That's no big deal, because these is not much at these places!
                            2/ This artistic layer is perhaps not the best one to see details, maybe there is also more levels (you may try 18 instead of 16) - I created the java file by copying another one...
                            3/ Good to see javascript implementation is very close to the java one, I'm not a big fan of javascript... no indentation?
                            Congrats anyway.

                            Comment


                            • #15
                              Hi frenchy

                              Thanks for your continued input.

                              0. Yes credits will follow, if we can get our test case working.

                              1. I now understand that this Web Mercator projection does not provide tiles for the poles.

                              2. Whilst we can try to use different levels for the rendering quality, I do notice that other examples provided also suffer from this issue. Both the labels and the map tiles are pixelated:
                              https://files.worldwind.arc.nasa.gov...icExample.html

                              Click image for larger version

Name:	nwww-render-quality.png
Views:	1
Size:	577.9 KB
ID:	158531


                              3. Yes, we use javascript because this is a web application, java is not an option.

                              Thanks

                              Comment

                              Working...
                              X