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

refactor: move Layer folder, extract geometric layers from views #815

Merged
merged 1 commit into from
Aug 9, 2018

Conversation

zarov
Copy link
Contributor

@zarov zarov commented Jul 23, 2018

This is a PR similar to #794 but more advanced. It is still missing documentation and test at the moment, but we can discuss the main goal of the PR while I add it.

Description

Several things have been done here:

  • move the content of src/Core/Layer to src/Layer
  • create several class for layers in this folder: GeometryLayer, TiledGeometryLayer, ColorLayer and ElevationLayer
  • from each type of view in src/Core/Prefab, remove the createXXXLayer in profit of a XXXLayer file

Motivation and Context

I feel that layers are one of the main aspect in itowns, and refactoring them like this can help us see clearer through it and help refactoring things around them (like #798 and #807).

@zarov zarov added wip 🚧 Still being worked on to validate labels Jul 23, 2018
@zarov zarov changed the title refactor: move geometric layers off views refactor: move Layer folder, extract geometric layers from views Jul 23, 2018
@peppsac
Copy link
Contributor

peppsac commented Jul 23, 2018

If we move away from layers being data-container + attached (external) functions to layers being classes, then we should also reconsider the existence of the process code.

For instance, all the code from GlobeTileProcessing is now only meant to be used from GlobeLayer so IMHO, it would make more sense to remove GlobeTileProcessing and move all of its code in GlobeLayer.

Other questions:

  • why GlobeLayer exists but not $3dtilesLayer or PointCloudLayer?
  • why not removing completely the view.addLayer({ type: 'color' }) API, and only allow the view.addLayer(new ColorLayer(...)) form?

@zarov
Copy link
Contributor Author

zarov commented Jul 23, 2018

For instance, all the code from GlobeTileProcessing is now only meant to be used from GlobeLayer so IMHO, it would make more sense to remove GlobeTileProcessing and move all of its code in GlobeLayer.

Completely agree, all layers should have their own update method. I didn't do it here to not clutter the PR.

why GlobeLayer exists but not $3dtilesLayer or PointCloudLayer?

It could, and it should, but those layers are for now more present in examples. But we could take the opportunity to create them here.

why not removing completely the view.addLayer({ type: 'color' }) API, and only allow the view.addLayer(new ColorLayer(...)) form?

I don't have an opinion here, I'm okay to leave it or remove it. It could be at least deprecated in this PR.

@peppsac
Copy link
Contributor

peppsac commented Jul 23, 2018

I don't have any opinion on the proposed changes, so I'll keep asking questions :)

Is there a point to keep PlanarView, GlobeView, PanoramaView? Can't you move all the view type specific code to each Layer class?

It could, and it should, but those layers are for now more present in examples. But we could take the opportunity to create them here.

I'm not sure that theses layers would make sense actually.
Can you show the code to display a 3dtiles point cloud using itowns using both this PR and a source concept (the one from #798 or similar)? what about a pointcloud from PotreeConverter?

@zarov
Copy link
Contributor Author

zarov commented Jul 24, 2018

Is there a point to keep PlanarView, GlobeView, PanoramaView? Can't you move all the view type specific code to each Layer class?

There is some code that we could move from views to layers, but I don't really see the point of dropping views. To me, views are the basis of any project using itowns. Or do you meant we could only keep View and only use that ?

I'm not sure that theses layers would make sense actually.

OK, so maybe a 3dtiles layer would be added as a GeometryLayer/TiledGeometryLayer, and then the provider(/source ?) would change the specific update stuff ?

Copy link
Contributor

@gchoqueux gchoqueux left a comment

Choose a reason for hiding this comment

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

the specific globe's part in GlobeTileProcessing is the horizonCulling, this part could be moved in globeLayer. We must strive to unify the other parts of the GlobeTileProcessing (if possible and justified)

Do you meant we could only keep View and only use that ?

Yes, it would be necessary to have only View, the different things are the controls / Camera and the fog / atmosphere (atmosphere should be a layer)

@@ -1,199 +0,0 @@
import { EventDispatcher } 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.

move Layer.js in other PR to see history change

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yep !

this.builder = new BuilderEllipsoidTile();
}

pickObjectsAt(view, mouse, radius = 5) {
Copy link
Contributor

Choose a reason for hiding this comment

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

why he doesn't inherit from geometryLayer or TiledGeometryLayer.js?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Because of the default radius value which isn't the same, and I don't know a way of specifying this differently.

this._latestUpdateStartingLevel = 0;
}

preGlobeUpdate(context, this);
Copy link
Contributor

Choose a reason for hiding this comment

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

Why globeLayer.preUpdate should be identical to planarLayer.preUpdate or panoramaLayer.preUpdate, exepted for preGlobeUpdate, prePlanarUpdate

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done


Object.assign(this, config);

Object.defineProperty(this, 'id', {
Copy link
Contributor

Choose a reason for hiding this comment

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

we could you use class's getter and setter?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Only using a getter would do the same job indeed, but does not emit an error: what is your take here ?

// * the minimum sequence will always be 0
// * the maximum sequence will always be layers.lenght - 1
// the ordering of all layers (Except that specified) doesn't change
moveLayerToIndex: function moveLayerToIndex(layer, newIndex, imageryLayers) {
Copy link
Contributor

Choose a reason for hiding this comment

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

maybe this should be in geometryLayer because the color and elevation layers are only attached to geometric layers : geometryLayer.moveColorLayerToIndex(layer, index)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This kind of makes sense, but this method is used in ColorLayersOrdering too; how do you see the integration with this one, very specific to color layers ?

@zarov zarov force-pushed the refactor_layers branch from 3f5469c to 2559684 Compare August 7, 2018 15:02
@zarov
Copy link
Contributor Author

zarov commented Aug 7, 2018

PR updated, I moved the pickObjectsAt and added documentation.

Note that it is getting quite unbrowseable in the jsdoc page, so it may be interesting to regroup classes by theme (here we could have Layers for example) and only display their name and not the method names. But this is the matter of another PR.

@zarov zarov force-pushed the refactor_layers branch from 1ca9f1d to ad56118 Compare August 8, 2018 08:31
@gchoqueux gchoqueux added validated 👌 validated by PSC and removed to validate labels Aug 8, 2018
this.options = config.options || {};

// Does this layer is attached to another one
this.isAttached = false;
Copy link
Contributor

Choose a reason for hiding this comment

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

it's necessary, because if (this.attachedLayers.length === 0) so this.isAttached === false

// Does this layer is attached to another one
this.isAttached = false;

if (!this.updateStrategy) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Note
It's necessary to think where to place the strategy of loading.
The layer is a good place because it must independent of the source.

});

// Default properties
this.options = config.options || {};
Copy link
Contributor

Choose a reason for hiding this comment

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

It would be necessary, to write _ before private property name.
Could you tell me the properties that make sense to be accessible?

by example this.isAttached is not supposed to be modifiable by the user

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So this line comes from View, so I kinda let it as it is. For private property name, I'm okay to write it with _, but I don't know a way to keep a property modifiable by us but not by the user.


function subdivision(context, layer, node) {
if (TiledGeometryLayer.hasEnoughTexturesToSubdivide(context, node)) {
return globeSubdivisionControl(2,
Copy link
Contributor

Choose a reason for hiding this comment

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

  • Could you standardize the signature of globeSubdivisionControl, panoramaSubdivisionControl and planarSubdivisionControl, because these functions are pretty much the same

  • Could you move subdivision and this.update declaration to TiledGeometryLayer

Copy link
Contributor Author

Choose a reason for hiding this comment

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

  • pretty much yes, but the panorama one is kinda annoying... I'll see what I can do here
  • I don't agree with this, I'd prefer to transfer the called methods (from GlobeTiledProcessing for example) in layers in the PR following this one.


this.update = processTiledGeometryNode(panoramaCulling, subdivision);
this.builder = new PanoramaTileBuilder(type, config.ratio || 1);
this.segments = 8;
Copy link
Contributor

Choose a reason for hiding this comment

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

move to this.options

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

defineLayerProperty(layer, 'visible', true, () => _syncGeometryLayerVisibility(layer, view));
defineLayerProperty(layer, 'frozen', false);
if (layer.type == 'geometry' || layer.type == 'debug') {
layer.defineLayerProperty('visible', true, () => _syncGeometryLayerVisibility(layer, view));
Copy link
Contributor

Choose a reason for hiding this comment

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

It's a shame that (layer.defineLayerProperty) this remains
It should use the notifyChange mechanism

Copy link
Contributor Author

Choose a reason for hiding this comment

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

How could I use it ?

* @return {Array} An array containing all targets picked under the
* specified coordinates.
*/
pickObjectsAt(view, coordinates, radius) {
Copy link
Contributor

Choose a reason for hiding this comment

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

why radius parameter don't use default value?
pickObjectsAt(view, coordinates, radius = this.config.defaultRadius)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks, didn't think of it this way !

* @return {Array} An array containing all targets picked under the
* specified coordinates.
*/
pickObjectsAt(view, coordinates, radius) {
Copy link
Contributor

Choose a reason for hiding this comment

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

you can declare in class geometryLayer

 pickObjectsAt(view, coordinates, radius = this.defaultPickingRadius) {
        return Picking.pickTilesAt(view, coordinates, radius, this);
 }

and remove pickObjectsAt in TiledGeometryLayer

Copy link
Contributor Author

Choose a reason for hiding this comment

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

But TiledGeometryLayer uses pickTilesAt and GeometryLayer uses pickObjectsAt.

@@ -42,15 +42,6 @@ export function preGlobeUpdate(context, layer) {

// pre-sse
context.camera.preSSE = _preSSE(context.view);

Copy link
Contributor

Choose a reason for hiding this comment

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

what is this deleted or moved part for?

@@ -24,17 +24,6 @@ function _isTileBigOnScreen(camera, node) {
return (dim.x >= 256 && dim.y >= 256);
}

export function prePlanarUpdate(context, layer) {
Copy link
Contributor

Choose a reason for hiding this comment

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

same part that here
There's the same preUpdate in globePreUpdate ?
It's used for elevation with color data , can use color data for elevation in the globeLayer?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is the same indeed, so I moved it to TiledGeometryLayer.

@zarov zarov force-pushed the refactor_layers branch from 244cf6f to 76d784e Compare August 9, 2018 15:37
Move all contents of `createXXXLayer` in XXXView to XXXLayer in
Prefab/XXX/. This declutters the XXXView files. This change applies for
Globe, Planar and Panorama.

In the same time, GeometryLayer has been extract from Layer and given
some new methods which were repeated through each View.
TiledGeometryLayer, ColorLayer and ElevationLayer has been created as
well, in the same spirit.

All code present in src/Core/Layer has been moved to src/Layer.
@gchoqueux
Copy link
Contributor

good job

@gchoqueux gchoqueux merged commit 10decfd into iTowns:master Aug 9, 2018
@zarov zarov deleted the refactor_layers branch August 29, 2018 08:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
validated 👌 validated by PSC wip 🚧 Still being worked on
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants