Closed dcooley closed 4 years ago
Your positions array should still be organized in loops for extrusion to work.
Your positions array should still be organized in loops for extrusion to work.
Can I ask how this is handled inside SolidpolygonLayer
? Specifically, here is where you call earcut()
to triangulate the polygon. But I can't see how you then organise the result into these 'loops'.
Positions must trace the bounds of each polygon, as called for by the getPolygon
API (which complies with the GeoJSON specification). The SolidPolygonLayer does check if a polygon is closed (i.e. the first vertex is the same as the last vertex) and automatically closes it if needed - the closing of loops is required for extrusion to work correctly. When you are using binary attributes, it is your responsibility to make sure that all polygons are defined in order and in closed loops.
I've made a simplified example, but I still can't quite see what I'm doing wrong to solve the extrusion issue.
The process I'm using
earcut()
to make trianglesFloat32Array()
of the coordinates which make the trianglesSolidpolygonLayer
Here's the relevant code from the linked jsfiddle - can you see what I'm doing wrong?
// polygon with a hole
// each ring is closed
const dimension = 2;
const polygon = [
0,0, 0,1, 0.5,1.5, 1,1, 1,0, 0,0,
0.2,0.2, 0.2,0.8, 0.6,0.8, 0.6,0.2, 0.2,0.2
];
const ec = earcut( polygon, [6], dimension ); // hole at idx 6, stride == 2
// earcut gives the index of triangle coordinates
// in groups of 3
//console.log( ec );
// [9,8,7, 4,3,2, 2,1,0, 4,2,5, 9,7,10]
const binaryLocation = new Float32Array( ec.length * dimension );
var counter = 0;
var idx;
for( var i = 0; i < ec.length; ++i ) {
let idx = ec[ i ] * dimension;
binaryLocation[ counter ] = polygon[ idx ];
binaryLocation[ counter + 1 ] = polygon[ idx + 1 ];
counter = counter + dimension;
}
const stride = 2;
const n_points = binaryLocation.length / stride;
const n_points_per_tri = 3;
const len = n_points / n_points_per_tri;
const binaryStartIndices = new Uint16Array([0]);
const binaryIndices = new Uint16Array( binaryLocation.length );
for( var i = 0; i < ( binaryLocation.length ); i++ ) {
binaryIndices[i] = i;
}
const polygonLayer = new deck.SolidPolygonLayer({
id: 'polygon',
wireframe: true,
extruded: true,
data: {
length: len,
startIndices: binaryStartIndices,
attributes: {
indices: binaryIndices,
getPolygon: {value: binaryLocation, size: stride}
}
},
_normalize: false, // skip normalization for ear-cut polygons
getFillColor: [255,0,0,100],
pickable: true,
autoHighlight: true
});
deckgl.setProps({layers: [polygonLayer] });
I am not fully up-to-date so I could be wrong, but I am not sure that the polygonlayer supports pre-tesselated geometries (i.e. the application calling earcut).
const polygonLayer = new deck.SolidPolygonLayer({
id: 'polygon',
wireframe: true,
extruded: true,
data: {
length: 2, // number of polygons
startIndices: [0, 6], // vertex count at the start of each polygon
attributes: {
indices: new Uint16Array(ec), // result from earcut
getPolygon: {value: new Float32Array(polygon), size: dimension} // positions tracing the bounds of each polygon
}
},
_normalize: false, // skip normalization for ear-cut polygons
getFillColor: [255,0,0,100],
getElevation: 3000,
pickable: true,
autoHighlight: true
});
Picking does not work quite as expected here because there is no mechanism to define "polygon with holes" in binary. You can work around this by providing the pickingColors
attribute yourself (it is calculated by stacking the results of layer.encodePickingColor(index)
).
Thanks - this is really helpful.
Example
I've got this polygon (using
Solidpolygon layer
) which has already been earcut into triangles and I'm plotting it using the 'binary' specifications.I've said
pickable: true
, but it only highlights the individual triangles, not the polygon has a whole.working jsfiddle
If I understand correctly the
startIndices
attribute defines each polygon. So if I set this to0
it means all the triangles are part of the same polygon. Which makes the highlight work, but it adds extra side-walls between adjoining coordinates.working jsfiddle
If I set
extruded: false
, this removes those wallsworking jsfiddle
Question
In my example, how should I specify the
startIndices
andindices
attributes so the picking selects the whole polygon for both extruded and non-extruded, and also avoids drawing the extra side-walls?