Skip to content

Commit

Permalink
refactor(Feature): remove geometry.properties.style -> use style fct …
Browse files Browse the repository at this point in the history
…at Feature level
  • Loading branch information
ftoromanoff committed Dec 13, 2023
1 parent 4d44cd3 commit b736f72
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 68 deletions.
20 changes: 10 additions & 10 deletions examples/source_file_gpx_3d.html
Expand Up @@ -61,6 +61,15 @@

var waypointGeometry = new itowns.THREE.BoxGeometry(1, 1, 80);
var waypointMaterial = new itowns.THREE.MeshBasicMaterial({ color: 0xffffff });
const style = {
stroke: {
color: 'red',
width: 2,
},
point: {
color: 'white',
}
};
// Listen for globe full initialisation event
view.addEventListener(itowns.GLOBE_VIEW_EVENTS.GLOBE_INITIALIZED, function () {
console.info('Globe initialized');
Expand All @@ -72,18 +81,9 @@
out: {
crs: view.referenceCrs,
structure: '3d',
style: new itowns.Style({
stroke: {
color: 'red',
width: 2,
},
point: {
color: 'white',
}
}),
}
}))
.then(itowns.Feature2Mesh.convert())
.then(itowns.Feature2Mesh.convert({style}))
.then(function (mesh) {
if (mesh) {
mesh.updateMatrixWorld();
Expand Down
20 changes: 13 additions & 7 deletions src/Converter/Feature2Mesh.js
Expand Up @@ -525,12 +525,13 @@ function createInstancedMesh(mesh, count, ptsIn) {
* Convert a [Feature]{@link Feature} of type POINT to a Instanced meshes
*
* @param {Object} feature
* @param {Object} options - options controlling the conversion
* @returns {THREE.Mesh} mesh or GROUP of THREE.InstancedMesh
*/
function pointsToInstancedMeshes(feature) {
function pointsToInstancedMeshes(feature, options) {
const ptsIn = feature.vertices;
const count = feature.geometries.length;
const modelObject = feature.style.point.model.object;
const modelObject = options.layer.style.point.model.object;

if (modelObject instanceof THREE.Mesh) {
return createInstancedMesh(modelObject, count, ptsIn);
Expand All @@ -541,7 +542,7 @@ function pointsToInstancedMeshes(feature) {
meshes.forEach(mesh => group.add(createInstancedMesh(mesh, count, ptsIn)));
return group;
} else {
throw new Error('The format of the model object provided in the feature style (feature.style.point.model.object) is not supported. Only THREE.Mesh or THREE.Object3D are supported.');
throw new Error('The format of the model object provided in the style (layer.style.point.model.object) is not supported. Only THREE.Mesh or THREE.Object3D are supported.');
}
}

Expand All @@ -560,9 +561,9 @@ function featureToMesh(feature, options) {
let mesh;
switch (feature.type) {
case FEATURE_TYPES.POINT:
if (feature.style.point?.model?.object) {
if (options.layer?.style?.point?.model?.object) {
try {
mesh = pointsToInstancedMeshes(feature);
mesh = pointsToInstancedMeshes(feature, options);
mesh.isInstancedMesh = true;
} catch (e) {
mesh = featureToPoint(feature, options);
Expand All @@ -575,7 +576,7 @@ function featureToMesh(feature, options) {
mesh = featureToLine(feature, options);
break;
case FEATURE_TYPES.POLYGON:
if (feature.style.fill.extrusion_height) {
if (options.layer?.style?.fill.extrusion_height) {
mesh = featureToExtrudedPolygon(feature, options);
} else {
mesh = featureToPolygon(feature, options);
Expand Down Expand Up @@ -645,7 +646,12 @@ export default {
options.pointMaterial = ReferLayerProperties(new THREE.PointsMaterial(), this);
options.lineMaterial = ReferLayerProperties(new THREE.LineBasicMaterial(), this);
options.polygonMaterial = ReferLayerProperties(new THREE.MeshBasicMaterial(), this);
options.layer = this;
// options.layer.style will be used later on to define the final style.
// In the case we didn't instanciate the layer before the convert, we can directly
// pass a style using options.style.
// This is usually done in some tests and if you want to use Feature2Mesh.convert()
// as in examples/source_file_gpx_3d.html.
options.layer = this || { style: options.style };
}

context.setCollection(collection);
Expand Down
2 changes: 1 addition & 1 deletion src/Core/Feature.js
Expand Up @@ -251,7 +251,7 @@ class Feature {
}
this._pos = 0;
this._pushValues = (this.size === 3 ? push3DValues : push2DValues).bind(this);
this.style = new Style({}, collection.style);
this.style = Style.setFromProperties;
}
/**
* Instance a new {@link FeatureGeometry} and push in {@link Feature}.
Expand Down
5 changes: 3 additions & 2 deletions src/Core/Style.js
Expand Up @@ -674,11 +674,12 @@ class Style {
/**
* set Style from (geojson-like) properties.
* @param {Object} properties (geojson-like) properties.
* @param {Number} type
* @param {FeatureContext} featCtx the context of the feature
*
* @returns {StyleOptions} containing all properties for itowns.Style
*/
static setFromProperties(properties, type) {
static setFromProperties(properties, featCtx) {
const type = featCtx.type;
const style = {};
if (type === FEATURE_TYPES.POINT) {
const point = {
Expand Down
3 changes: 0 additions & 3 deletions src/Parser/GeoJsonParser.js
@@ -1,6 +1,5 @@
import Coordinates from 'Core/Geographic/Coordinates';
import { FeatureCollection, FEATURE_TYPES } from 'Core/Feature';
import Style from 'Core/Style';
import { deprecatedParsingOptionsToNewOne } from 'Core/Deprecated/Undeprecator';

function readCRS(json) {
Expand Down Expand Up @@ -73,7 +72,6 @@ const toFeature = {
}

const geometry = feature.bindNewGeometry();
properties.style = Style.setFromProperties(properties, feature.type);
geometry.properties = properties;

this.populateGeometry(crsIn, coordsIn, geometry, feature);
Expand All @@ -85,7 +83,6 @@ const toFeature = {
return;
}
const geometry = feature.bindNewGeometry();
properties.style = Style.setFromProperties(properties, feature.type);
geometry.properties = properties;

// Then read contour and holes
Expand Down
88 changes: 45 additions & 43 deletions test/unit/feature2mesh.js
Expand Up @@ -3,7 +3,6 @@ import proj4 from 'proj4';
import assert from 'assert';
import GeoJsonParser from 'Parser/GeoJsonParser';
import Feature2Mesh from 'Converter/Feature2Mesh';
import Style from 'Core/Style';

const geojson = require('../data/geojson/holes.geojson.json');
const geojson2 = require('../data/geojson/simple.geojson.json');
Expand Down Expand Up @@ -58,63 +57,66 @@ describe('Feature2Mesh', function () {
const parsed3 = GeoJsonParser.parse(geojson3, { in: { crs: 'EPSG:3946' }, out: { crs: 'EPSG:3946', buildExtent: true, mergeFeatures: false, structure: '3d' } });

it('rect mesh area should match geometry extent', function (done) {
parsed.then((collection) => {
const mesh = Feature2Mesh.convert()(collection).meshes;
const extentSize = collection.extent.planarDimensions();
parsed
.then((collection) => {
const mesh = Feature2Mesh.convert()(collection).meshes;
const extentSize = collection.extent.planarDimensions();

assert.equal(
extentSize.x * extentSize.y,
computeAreaOfMesh(mesh.children[0]));
done();
}).catch(done);
assert.equal(
extentSize.x * extentSize.y,
computeAreaOfMesh(mesh.children[0]));
done();
}).catch(done);
});

it('square mesh area should match geometry extent minus holes', function (done) {
parsed.then((collection) => {
const mesh = Feature2Mesh.convert()(collection).meshes;
parsed
.then((collection) => {
const mesh = Feature2Mesh.convert()(collection).meshes;

const noHoleArea = computeAreaOfMesh(mesh.children[0]);
const holeArea = computeAreaOfMesh(mesh.children[1]);
const meshWithHoleArea = computeAreaOfMesh(mesh.children[2]);
const noHoleArea = computeAreaOfMesh(mesh.children[0]);
const holeArea = computeAreaOfMesh(mesh.children[1]);
const meshWithHoleArea = computeAreaOfMesh(mesh.children[2]);

assert.equal(
noHoleArea - holeArea,
meshWithHoleArea);
done();
}).catch(done);
assert.equal(
noHoleArea - holeArea, meshWithHoleArea,
);
done();
}).catch(done);
});

it('convert points, lines and mesh', function (done) {
parsed2.then((collection) => {
const mesh = Feature2Mesh.convert()(collection).meshes;
assert.equal(mesh.children[0].type, 'Points');
assert.equal(mesh.children[1].type, 'LineSegments');
assert.equal(mesh.children[2].type, 'Mesh');
done();
}).catch(done);
parsed2
.then((collection) => {
const mesh = Feature2Mesh.convert()(collection).meshes;
assert.equal(mesh.children[0].type, 'Points');
assert.equal(mesh.children[1].type, 'LineSegments');
assert.equal(mesh.children[2].type, 'Mesh');
done();
}).catch(done);
});

it('convert to instanced meshes', function (done) {
const styleModel3D = new Style({
const styleModel3D = {
point: {
model: { object: makeTree() },
},
});
parsed3.then((collection) => {
for (const feat of collection.features) { feat.style = styleModel3D; }
const mesh = Feature2Mesh.convert()(collection).meshes;
};
parsed3
.then((collection) => {
const mesh = Feature2Mesh.convert({ style: styleModel3D })(collection).meshes;

let isInstancedMesh = false;
mesh.traverse((obj) => {
if (obj.isInstancedMesh) {
isInstancedMesh = true;
return null;
}
},
);
assert.ok(isInstancedMesh);
assert.equal(mesh.children.length, 3);
done();
}).catch(done);
let isInstancedMesh = false;
mesh.traverse((obj) => {
if (obj.isInstancedMesh) {
isInstancedMesh = true;
return null;
}
},
);
assert.ok(isInstancedMesh);
assert.equal(mesh.children.length, 3);
done();
}).catch(done);
});
});
4 changes: 2 additions & 2 deletions test/unit/style.js
Expand Up @@ -287,7 +287,7 @@ describe('Style', function () {
'label-color': '#eba55f',
'icon-color': '#eba55f',
};
const style = Style.setFromProperties(properties, FEATURE_TYPES.POINT);
const style = Style.setFromProperties(properties, { type: FEATURE_TYPES.POINT });
assert.equal(style.point.radius, 2);
assert.equal(style.text.color, '#eba55f');
assert.equal(style.icon.color, '#eba55f');
Expand All @@ -297,7 +297,7 @@ describe('Style', function () {
fill: '#eba55f',
stroke: '#eba55f',
};
const style = Style.setFromProperties(properties, FEATURE_TYPES.POLYGON);
const style = Style.setFromProperties(properties, { type: FEATURE_TYPES.POLYGON });
assert.equal(style.stroke.color, '#eba55f');
assert.equal(style.fill.color, '#eba55f');
});
Expand Down

0 comments on commit b736f72

Please sign in to comment.