Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Autodetect the max zoom level based on the highest resolution coverage #79

Merged
merged 4 commits into from
Jul 29, 2017

Conversation

emxsys
Copy link
Contributor

@emxsys emxsys commented Jul 27, 2017

Overriding findMaxZoomAuto to return the zoom level closest to the highest resolution coverage in the request.

…ghest resolution coverage in the request.

- Re: issue #75
@emxsys emxsys added this to the WWSK v0.3.1 milestone Jul 27, 2017
@emxsys emxsys requested a review from pdavidc July 27, 2017 15:13
@ghost ghost assigned emxsys Jul 27, 2017
@ghost ghost added the needs review label Jul 27, 2017
@emxsys
Copy link
Contributor Author

emxsys commented Jul 27, 2017

@pdavidc You're review is welcome, but not required to move forward.

double e = Math.abs(g.getScaleDenominator() - reqScaleDenominator);
if (e > error) {
break;
} else {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this conditional necessary? I think readability could be improved:

if (e > error) {
    break;
}
error = e;
i++; 

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I concur. Thanks.

@emxsys
Copy link
Contributor Author

emxsys commented Jul 28, 2017

Problem

When a GeoPackage-based layer is exported as a GeoPackage, the max zoom level is determined to be the max zoom level in the gridset (level 21), not the max level in the tileset.

This is problematic: it creates a request for a GeoPackage at the highest possible resolution, many levels greater than required, causing a seemingly never-end job that consumes large amounts of memory and disk resources.

The coverage object that provides the gridset is unaware of the actual number of levels in the tileset.

Options/Ideas

  • Possibly trim the gridset. This would have to be performed at the time the data store is created as the grid range is stored in the data store's XML.
  • Possibly interrogate the data store. Metadata? Metadata would have to be added to the coverage/data store instances.
  • Create a UI for exporting to a GeoPackage that doesn't depend on the ability to autodetect the max zoom level in this case, but instead relies on the user to select a max zoom level (with constraint).

emxsys added 2 commits July 28, 2017 14:07
…t) of the tiles in the GeoPackage.

- Was returning the grid range of the entire grid level.
- Added supporting code to compute the grid range. 
- Refactoring is needed. See TODO statements.
…ided by the GridCoverage2DReader.

- Provides access to getOriginalGridRange for obtaining the width/height of a GeoPackage.
@emxsys
Copy link
Contributor Author

emxsys commented Jul 28, 2017

@pdavidc I would appreciate a sanity check on the changes while I move into functional testing.

Copy link
Contributor

@pdavidc pdavidc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a few questions about the handling of GeoPackage tile matrices that I'm hoping have easy answers, or highlight a potential problem.

@@ -90,21 +90,44 @@
protected File sourceFile;

protected Map<String, TileEntry> tiles = new HashMap<String, TileEntry>();

// TODO: store these gridRanges in the TileEntry class
protected Map<String, GridEnvelope2D> gridRanges = new HashMap<String, GridEnvelope2D>();

public GeoPackageReader(Object source, Hints hints) throws IOException {
coverageFactory = CoverageFactoryFinder.getGridCoverageFactory(this.hints);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It appears that the hints argument is unused. Could it be that the object property hints is unnecessary, or that it hints needs to be assigned before the call to getGridCoverageFactory?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good eyes! It appears the GeoPackageReader is intentionally using the "defaultHints" provided in the base class. The rationale for this is unknown.

// TODO: compute the gridRange in the GeoPackage class
List<TileMatrix> matricies = tileset.getTileMatricies();
TileMatrix matrix = matricies.get(matricies.size() - 1);
int maxZoomLevel = matrix.getZoomLevel();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are two aspects of the GeoPackage spec that could be problematic here:

  1. GeoPackage does not stipulate that tile matrices are ordered, which could invalidate the assumption that the last TileMatrix represents the maximum zoom level. Does the method TileEntry.getTileMatrices provide this guarantee?

  2. GeoPackage allows the definition of tile matrices that have no corresponding tile data in the file. For example, a GeoPackage could define 17 logical levels of tile matrices, yet provide tile data for only levels 5-10. We have test files that do this. In WorldWind Android, I queried the GeoPackage to identify the TileMatrix with the largest zoom level that also had at least one corresponding tile in the tile table.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re: 1. The GeoPackage class retrieves and assembles its tile matrices in ascending zoom level order.
Re: 2. The query behind the getTileBound method is on "coverage tiles" table, not the tile_matrix table.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To clarify, "coverage tiles table" refers to GeoPackage tile pyramid user data tables?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that is correct.

GridEnvelope2D gridRange = new GridEnvelope2D(new Rectangle(
numCols * matrix.getTileWidth(),
numRows * matrix.getTileHeight()));

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The conversion to GridEnvelope2D appears to lose information. This retains the tile count in each dimension, but drops which row and column the envelope begins at. Have I missed something here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The conversion is storing the height and width in pixels of the highest resolution level.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems odd that the Rectangle's upper left corner would be set to 0, 0. Are you certain that getOriginalGridRange, and any other use of this GridEnvelope2D, will only inspect its dimensions?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm been looking into it since your original comment. So far nearly all instances have been on the span, but its a large domain to inspect. I cannot identify an alternative approach to manifesting this data, nor can I propose candidate values for a top/left in this context other than 0,0.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It appears that the domain is logical tile matrix pixels. Given that, would minCol * matrix.getTileWidth() and minRow * matrix.getTileHeight() represent the upper left x and y, respectively?

Copy link
Contributor Author

@emxsys emxsys Jul 28, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On second thought, the low/high could be the pixels in the grid. 2^21 * 256 fits in an integer.

Copy link
Contributor

@zglueck zglueck left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@emxsys many of the details of the context of this pull request are out of the scope of my Geoserver knowledge :) I focused on the zoom level determination and found no issues in your approach. My spreadsheet backed testing indicated the closest level + 1 would be returned for a given scale denominator.

@emxsys emxsys merged commit 35a0cc0 into hotfix/v0.3.1 Jul 29, 2017
@ghost ghost removed the needs review label Jul 29, 2017
@emxsys emxsys deleted the fix/#75-geopackage_export_fidelity branch July 29, 2017 03:01
@emxsys emxsys restored the fix/#75-geopackage_export_fidelity branch July 29, 2017 03:15
@emxsys emxsys mentioned this pull request Jul 29, 2017
11 tasks
@emxsys emxsys deleted the fix/#75-geopackage_export_fidelity branch July 29, 2017 04:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

3 participants