Skip to content

Commit

Permalink
fix: 3d extrude polygon layer
Browse files Browse the repository at this point in the history
  • Loading branch information
lvisei committed May 14, 2024
1 parent 570fcc9 commit dd29d01
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 19 deletions.
2 changes: 2 additions & 0 deletions examples/demos/bugfix/muti-polygon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ export function MapRender(options: RenderDemoOptions) {
})
.color('rgb(22,199,255)')
.shape('fill')
// .shape('extrude')
// .size(1200 * 100)
.active(true)
.style({
opacity: 0.5,
Expand Down
12 changes: 9 additions & 3 deletions packages/layers/src/core/shape/extrude.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { lngLatToMeters } from '@antv/l7-utils';
import earcut from 'earcut';
import { vec3 } from 'gl-matrix';
import { getPolygonSurfaceIndices } from '../utils';
import type { IPath } from './Path';

export interface IExtrudeGeomety {
positions: number[];
index: number[];
Expand Down Expand Up @@ -62,6 +64,7 @@ export default function extrudePolygon(path: IPath[]): IExtrudeGeomety {
index: indexArray,
};
}

export function fillPolygon(points: IPath[]) {
const flattengeo = earcut.flatten(points);
const triangles = earcut(flattengeo.vertices, flattengeo.holes, flattengeo.dimensions);
Expand All @@ -82,7 +85,7 @@ export function extrude_PolygonNormal(
}
const n = path[0].length;
const flattengeo = earcut.flatten(path);
const { vertices, dimensions } = flattengeo;
const { vertices, dimensions, holes } = flattengeo;
const positions = [];
const indexArray = [];
const normals = [];
Expand All @@ -97,8 +100,10 @@ export function extrude_PolygonNormal(
);
normals.push(0, 0, 1);
}
const triangles = earcut(flattengeo.vertices, flattengeo.holes, flattengeo.dimensions);
indexArray.push(...triangles);

const indices = getPolygonSurfaceIndices(vertices, holes, dimensions, needFlat);
indexArray.push(...indices);

// 设置侧面
for (let i = 0; i < n; i++) {
const prePoint = flattengeo.vertices.slice(i * dimensions, (i + 1) * dimensions);
Expand Down Expand Up @@ -145,6 +150,7 @@ export function extrude_PolygonNormal(
normals,
};
}

function computeVertexNormals(
p1: [number, number, number],
p2: [number, number, number],
Expand Down
20 changes: 4 additions & 16 deletions packages/layers/src/core/triangulation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@ import {
} from '../earth/utils';
import ExtrudePolyline from '../utils/extrude_polyline';
import type { IPosition, ShapeType2D, ShapeType3D } from './shape/Path';
import { geometryShape } from './shape/Path';
import type { IExtrudeGeomety } from './shape/extrude';
import extrudePolygon, { extrude_PolygonNormal, fillPolygon } from './shape/extrude';
import { getPolygonSurfaceIndices } from './utils';

import { geometryShape } from './shape/Path';
type IShape = ShapeType2D & ShapeType3D;
interface IGeometryCache {
[key: string]: IExtrudeGeomety;
Expand Down Expand Up @@ -335,23 +336,10 @@ export function polygonTriangulation(feature: IEncodeFeature) {
const flattengeo = earcut.flatten(coordinates as number[][][]);
const { vertices, dimensions, holes } = flattengeo;

const positions = vertices.slice();
const p: number[] = [];
for (let i = 0; i < vertices.length; i += 2) {
p[0] = vertices[i];
p[1] = vertices[i + 1];

// earcut is a 2D triangulation algorithm, and handles 3D data as if it was projected onto the XY plane
const xy = lngLatToMeters(p, true, { enable: false, decimal: 1 });

positions[i] = xy[0];
positions[i + 1] = xy[1];
}

const triangles = earcut(positions, holes, dimensions);
const indices = getPolygonSurfaceIndices(vertices, holes, dimensions);

return {
indices: triangles,
indices,
vertices,
size: dimensions,
};
Expand Down
42 changes: 42 additions & 0 deletions packages/layers/src/core/utils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,45 @@
import { lngLatToMeters } from '@antv/l7-utils';
import earcut from 'earcut';

export function MultipleOfFourNumber(num: number) {
return Math.max(Math.ceil(num / 4) * 4, 4);
}

/**
* Get vertex indices for drawing polygon mesh (triangulation)
*/
export function getPolygonSurfaceIndices(
positions: number[],
holeIndices: number[],
positionSize: number,
preproject = true,
) {
const is3d = positionSize === 3;

if (preproject) {
positions = positions.slice();
const p: number[] = [];
for (let i = 0; i < positions.length; i += positionSize) {
p[0] = positions[i];
p[1] = positions[i + 1];

if (is3d) {
p[2] = positions[i + 2];
}

// earcut is a 2D triangulation algorithm, and handles 3D data as if it was projected onto the XY plane
const xy = lngLatToMeters(p, true, { enable: false, decimal: 1 });

positions[i] = xy[0];
positions[i + 1] = xy[1];

if (is3d) {
positions[i + 2] = xy[2];
}
}
}

const indices = earcut(positions, holeIndices, positionSize);

return indices;
}

0 comments on commit dd29d01

Please sign in to comment.