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

Refacto provider and add Sources #798

Merged
merged 5 commits into from
Aug 23, 2018
Merged

Refacto provider and add Sources #798

merged 5 commits into from
Aug 23, 2018

Conversation

gchoqueux
Copy link
Contributor

@gchoqueux gchoqueux commented Jun 29, 2018

Description

add Source in layer : all the parameters to get the data from a source
add convert in layer : fonction to convert data from source to layer's elements

The layer does

const layer = {
  id, 
  type,
  source,
  convert,
}

The provider does

function executeCommand() {
      const extent = command.extent; //  the datas's extent  to fetch
      const dataFetchedFromSource = await fetcher(source.urlFromExtent(extent));
      const dataParsed = await parse(dataFetchedFromSource);
      const layerElement = convert(dataParsed);
      return layerElement;
}

Motivation

  • Isolate sources and converters/parsers from providers and use them for other layers
  • simplify providers and merge certain providers (WMTS, WMS, Rasterizer), see delete them

@gchoqueux gchoqueux added wip 🚧 Still being worked on to validate labels Jun 29, 2018
@gchoqueux gchoqueux mentioned this pull request Jul 2, 2018
Copy link
Collaborator

@mbredif mbredif left a comment

Choose a reason for hiding this comment

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

It looks better than the current state IMHO.
Some remarks after a quick review :

  • layer.source || layer looks odd, is it temporary ? can't we get rid of it ?
  • converts and parsers are 2 different things (eg: WMTS source -> Geojson parser -> Mesh converter)

I however feel that tiledCRS version of extents should be an implementation detail of quadtree-based sources and that other parts of itowns should only handle extents as a (BBox3 + CRS).

Likewise instead of relative pitches / offsetscales, we could use absolute coordinates (BBox2 + CRS) for textures so that downscaling a texture would be a noop and uvs in the shader would be well defined coordinates with a proper crs instead of normalized coordinates.

@@ -205,8 +204,9 @@ TileMesh.prototype.changeSequenceLayers = function changeSequenceLayers(sequence

TileMesh.prototype.getCoordsForLayer = function getCoordsForLayer(layer) {
if (layer.protocol.indexOf('wmts') == 0) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

layer.source.protocol ?

src/Core/View.js Outdated
@@ -177,12 +184,15 @@ function _preprocessLayer(view, layer, provider, parentLayer) {

// probably not the best place to do this
if (layer.type == 'color') {
layer.fx = layer.fx || 0.0;
Copy link
Collaborator

Choose a reason for hiding this comment

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

why not a defineLayerProperty as for other properties?

Copy link
Contributor

Choose a reason for hiding this comment

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

defineLayerProperty is a bad practice imho, and achieves nothing besides reducing a little the duplicated code, executing a callback in really rare usecases and emitting events on properties change. But I wouldn't change it here, and in the meantime keep this property declaration as it is.

Copy link
Contributor

@zarov zarov left a comment

Choose a reason for hiding this comment

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

I think this is a good idea. The introduction of a Source object (kind of like OpenLayers ?) is a good step towards decluttering providers. Could you add a more accurate description (maybe documentation like the current Provider interface ?) to this object ?

However I don't really like a few things:

  • the fetching in geoFileSource: no operation like should happen in a Source
  • the convert method in layer: what about your initials thoughts with source, processing, style only ?

};

export default {
textureColorLayer(texture, extent, layer) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I wouldn't call this textureColorLayer. Why not have two methods, color and elevation, which gives textureConverter.color and textureConverter.elevation calls.

Also by introducing this you could drop the getColor/XBilTextureByUrl in OGCWebServiceHelper which have nothing to do with OGC.

@@ -1,14 +1,24 @@
import { TextureLoader } from 'three';
import { TextureLoader, DataTexture, AlphaFormat, FloatType, LinearFilter } from 'three';
Copy link
Contributor

Choose a reason for hiding this comment

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

My opinion: we should always import * as THREE, I don't get the appeal behind selecting what we are importing.

checkResponse(response);
return response.arrayBuffer();
arrayBuffer,
textureFloat(url, options = {}) {
Copy link
Contributor

Choose a reason for hiding this comment

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

This part should be in the elevationTexture part imho. Let's keep the Fetcher simple.

if (typeof (provider.preprocessDataLayer) !== 'function') {
throw new Error(`Can't add provider for ${protocol}: missing a preprocessDataLayer function.`);
}
// if (typeof (provider.preprocessDataLayer) !== 'function') {
Copy link
Contributor

Choose a reason for hiding this comment

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

👍

src/Core/View.js Outdated

// temp
// devrait etre supprime et placer dans source
if (provider && !layer.source) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Yep, a provider shouldn't be the one defining the limit.

@@ -166,6 +174,15 @@ function _preprocessLayer(view, layer, provider, parentLayer) {
if (!(providerPreprocessing && providerPreprocessing.then)) {
providerPreprocessing = Promise.resolve();
}
} else if (layer.source) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't like having this here, as much as I don't like having all other things below (conditions on type of layer). I know though that you hope to move it to the layer itself, so I'm ok with this here for now.

src/Core/View.js Outdated
@@ -177,12 +184,15 @@ function _preprocessLayer(view, layer, provider, parentLayer) {

// probably not the best place to do this
if (layer.type == 'color') {
layer.fx = layer.fx || 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.

defineLayerProperty is a bad practice imho, and achieves nothing besides reducing a little the duplicated code, executing a callback in really rare usecases and emitting events on properties change. But I wouldn't change it here, and in the meantime keep this property declaration as it is.

@peppsac
Copy link
Contributor

peppsac commented Jul 9, 2018

I'm all for refactoring this part, and the chosen solution looks similar to what was previously discussed.
(the only downside is that we already have almost 30 open PR and that updating/reviewing/merging others would be more relevant)

Random notes:

  • IMHO, processing can depend on the data type (points or textures) but should not depend on the source type
  • provider (or source) implements the protocol specific knowledge and don't necesarly need to do network accesses themselves
  • a big refactoring must like this one:
    • not lose features (obviously)
    • bring new features (not necessarly in the same PR) to show its usefulness.

The last point is important. For instance, if this PR doesn't help implement vector-tiles support easily, then something is wrong.

@nosy-b
Copy link
Contributor

nosy-b commented Jul 24, 2018

Sounds like the way to go!

@gchoqueux gchoqueux force-pushed the Source branch 4 times, most recently from 1a22624 to 24adf87 Compare August 21, 2018 17:48
@zarov
Copy link
Contributor

zarov commented Aug 22, 2018

I tested the examples, here's what I saw:

  • cubic_planar: there seems to have artifact on the sides, see those two comparisons screenshots (first actual version, second this PR)
    image
    image
  • globe_vector: picking is not working anymore
  • syncCameras: not working, I have a Cannot read property 'protocol' of undefined

@gchoqueux
Copy link
Contributor Author

@zarov all examples are fixed

New change:

  • root tile are build in constructor
  • Layer.projection are determined in addLayer

@gchoqueux gchoqueux force-pushed the Source branch 3 times, most recently from d6fcdb4 to dd1006a Compare August 22, 2018 14:26
*/
class Source {
/**
* @param {sourceParams} source object to set source
Copy link
Contributor

Choose a reason for hiding this comment

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

You should remove the @class declaration above, and write a @constructor here, to avoid duplication in the generated page of the documentation.

You should also write an example of declaring a random Source. Best would be to have it for all Sources files.

@gchoqueux gchoqueux force-pushed the Source branch 2 times, most recently from bcb8f07 to 15c1612 Compare August 22, 2018 16:37
Copy link
Contributor

@zarov zarov left a comment

Choose a reason for hiding this comment

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

Added some comments on the Sources files !

*/
constructor(source, crsOut) {
super(source);
if (!source.url) {
Copy link
Contributor

Choose a reason for hiding this comment

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

No need to repeat this as it is already been checked in Source.

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

throw new Error('source.url is required in FileSource');
}

if (!source.projection) {
Copy link
Contributor

Choose a reason for hiding this comment

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

You should specify in the documentation above that the projection is mandatory for this type of Source. This check can also be moved before calling super(source).

* @param {Extent} extent extent to convert in url
* @return {string} url from extent
*/
// eslint-disable-next-line
Copy link
Contributor

Choose a reason for hiding this comment

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

This is a problem I encountered as well, there is three solutions:

  • eslint-disable-next-line
  • declaring this method as static: static urlFromExtent(extent), that can still be called with this.urlFromExtent(extent) or source.urlFromExtent(extent)
  • removing the class-method-use-this eslint check from the configuration

Copy link
Contributor Author

@gchoqueux gchoqueux Aug 23, 2018

Choose a reason for hiding this comment

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

yes, there are errors lint too for jsdoc

constructor(source) {
super(source);

if (!source.extent) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same as above, you can move this check before calling the parent constructor and specify in the documentation that the extent is required here.

* @param {Object} [source.zoom]
* @param {number} [source.zoom.min] layer's zoom minimum
* @param {number} [source.zoom.max] layer's zoom maximum
* @param {string} [source.zoom.max] layer's zoom maximum
Copy link
Contributor

Choose a reason for hiding this comment

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

Did you mean something else ?

*/
constructor(source) {
super(source);
if (!source.typeName) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same, move the super below

}
}

let crsPropName = 'SRS';
Copy link
Contributor

Choose a reason for hiding this comment

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

Why not directly const crsPropName = (this.version === '1.3.0') ? 'CRS' : 'SRS'; ?


/**
* Options to wtms protocol
* @typedef {Object} OptionsWmts
Copy link
Contributor

Choose a reason for hiding this comment

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

Will it be detailed ?

@gchoqueux gchoqueux force-pushed the Source branch 2 times, most recently from c8cecb8 to 228116e Compare August 23, 2018 12:26
Add new object source:
 - Source have the properties to fetch the data to display
 - Remove all source abstractions from provider
@gchoqueux
Copy link
Contributor Author

@zarov PR updated

Copy link
Contributor

@zarov zarov left a comment

Choose a reason for hiding this comment

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

OK let's validate this, I think I didn't see any problem.

For fixing your failing test, either remove it, or install a polyfill for URL (like this one https://github.com/webcomponents/URL) as it is not a component supported in nodejs.

@zarov
Copy link
Contributor

zarov commented Aug 23, 2018

It is even occurring because the URL component has only been added in node 10.

@gchoqueux gchoqueux merged commit c7fd059 into iTowns:master Aug 23, 2018
@gchoqueux gchoqueux deleted the Source branch August 23, 2018 16:35
@gchoqueux gchoqueux mentioned this pull request Aug 28, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature 🍏 Adds a new feature validated 👌 validated by PSC
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants