Skip to content

Commit

Permalink
feat(layers): add polygon3d , pointimagelayer
Browse files Browse the repository at this point in the history
  • Loading branch information
lzxue committed Oct 30, 2019
1 parent 30597d9 commit bda6b6c
Show file tree
Hide file tree
Showing 21 changed files with 886 additions and 136 deletions.
1 change: 0 additions & 1 deletion packages/core/src/services/layer/StyleAttributeService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,6 @@ export default class StyleAttributeService implements IStyleAttributeService {
const attributes: {
[attributeName: string]: IAttribute;
} = {};

descriptors.forEach((descriptor, attributeIdx) => {
if (descriptor) {
// IAttribute 参数透传
Expand Down
1 change: 1 addition & 0 deletions packages/layers/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"@l7/utils": "^0.0.1",
"@turf/meta": "^6.0.2",
"@types/d3-color": "^1.2.2",
"inversify": "^5.0.1",
"d3-array": "^2.3.1",
"d3-color": "^1.4.0",
"d3-scale": "^3.1.0",
Expand Down
6 changes: 3 additions & 3 deletions packages/layers/src/core/BaseLayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> implements ILayer {

protected layerSource: Source;

@lazyInject(TYPES.IRendererService)
protected readonly rendererService: IRendererService;

private encodedData: IEncodeFeature[];

private configSchema: object;
Expand All @@ -117,9 +120,6 @@ export default class BaseLayer<ChildLayerStyleOptions = {}> implements ILayer {
@lazyInject(TYPES.IShaderModuleService)
private readonly shaderModuleService: IShaderModuleService;

@lazyInject(TYPES.IRendererService)
private readonly rendererService: IRendererService;

@lazyInject(TYPES.IMapService)
private readonly map: IMapService;

Expand Down
65 changes: 65 additions & 0 deletions packages/layers/src/core/shape/Path.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
export type IPosition = [number, number, number] | [number, number];
export type IPath = IPosition[];
export enum ShapeType3D {
CYLINDER = 'cylinder',
SQUARECOLUMN = 'squareColumn',
TRIANGLECOLUMN = 'triangleColumn',
HEXAGONCOLUMN = 'hexagonColumn',
PENTAGONCOLUMN = 'pentagonColumn',
}
export enum ShapeType2D {
CIRCLE = 'circle',
SQUARE = 'square',
TRIANGLE = 'triangle',
HEXAGON = 'hexagon',
PENTAGON = 'pentagon',
}

/**
* 生成规则多边形顶点个数
* @param pointCount 顶点个数 3 => 三角形
* @param start 顶点起始角度 调整图形的方向
*/
export function polygonPath(pointCount: number, start: number = 0): IPath {
const step = (Math.PI * 2) / pointCount;
const line = [];
for (let i = 0; i < pointCount; i++) {
line.push(step * i + (start * Math.PI) / 12);
}
const path: IPath = line.map((t) => {
const x = Math.sin(t + Math.PI / 4);
const y = Math.cos(t + Math.PI / 4);
return [x, y, 0];
});
// path.push(path[0]);
return path;
}

export function circle(): IPath {
return polygonPath(30);
}
export function square(): IPath {
return polygonPath(4);
}
export function triangle(): IPath {
return polygonPath(3);
}
export function hexagon(): IPath {
return polygonPath(6);
}
export function pentagon(): IPath {
return polygonPath(5);
}

export const geometryShape = {
[ShapeType2D.CIRCLE]: circle,
[ShapeType2D.HEXAGON]: hexagon,
[ShapeType2D.TRIANGLE]: triangle,
[ShapeType2D.SQUARE]: square,
[ShapeType2D.PENTAGON]: pentagon,
[ShapeType3D.CYLINDER]: circle,
[ShapeType3D.HEXAGONCOLUMN]: hexagon,
[ShapeType3D.TRIANGLECOLUMN]: triangle,
[ShapeType3D.SQUARECOLUMN]: square,
[ShapeType3D.PENTAGONCOLUMN]: pentagon,
};
83 changes: 83 additions & 0 deletions packages/layers/src/core/shape/extrude.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import earcut from 'earcut';
import { IPath } from './Path';
export interface IExtrudeGeomety {
positions: number[];
index: number[];
}
/**
* 拉伸多边形顶点,返回拉伸后的顶点信息
* @param paths 路径数据组
* @param extrude 是否拉伸
*/
export default function extrudePolygon(path: IPath[]): IExtrudeGeomety {
const p1 = path[0][0];
const p2 = path[0][path[0].length - 1];
if (p1[0] === p2[0] && p1[1] === p2[1]) {
path[0] = path[0].slice(0, path[0].length - 1);
}

const n = path[0].length;
const flattengeo = earcut.flatten(path);
const { vertices, dimensions } = flattengeo;
const positions = [];
const indexArray = [];
// 设置顶部z值
for (let j = 0; j < vertices.length / dimensions; j++) {
if (dimensions === 2) {
positions.push(vertices[j * 2], vertices[j * 2 + 1], 1);
} else {
positions.push(vertices[j * 3], vertices[j * 3 + 1], 1);
}
}
const triangles = earcut(
flattengeo.vertices,
flattengeo.holes,
flattengeo.dimensions,
);
indexArray.push(...triangles);
for (let i = 0; i < n; i++) {
const prePoint = flattengeo.vertices.slice(
i * dimensions,
(i + 1) * dimensions,
);
let nextPoint = flattengeo.vertices.slice(
(i + 2) * dimensions,
(i + 3) * dimensions,
);
if (nextPoint.length === 0) {
nextPoint = flattengeo.vertices.slice(0, dimensions);
}
const indexOffset = positions.length / 3;
positions.push(
prePoint[0],
prePoint[1],
1,
nextPoint[0],
nextPoint[1],
1,
prePoint[0],
prePoint[1],
0,
nextPoint[0],
nextPoint[1],
0,
);
indexArray.push(...[1, 2, 0, 3, 2, 1].map((v) => v + indexOffset));
}
return {
positions,
index: indexArray,
};
}
export function fillPolygon(points: IPath[]) {
const flattengeo = earcut.flatten(points);
const triangles = earcut(
flattengeo.vertices,
flattengeo.holes,
flattengeo.dimensions,
);
return {
positions: flattengeo.vertices,
index: triangles,
};
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,21 @@
import { IEncodeFeature } from '@l7/core';
import { vec3 } from 'gl-matrix';
import getNormals from '../utils/polylineNormal';
import extrudePolygon, { IExtrudeGeomety } from './shape/extrude';
import { geometryShape, ShapeType2D, ShapeType3D } from './shape/Path';
import {
geometryShape,
IPosition,
ShapeType2D,
ShapeType3D,
} from './shape/Path';
interface IGeometryCache {
[key: string]: IExtrudeGeomety;
}
const GeometryCache: IGeometryCache = {};
/**
* 计算2D 填充点图顶点
* @param feature 映射feature
*/
export function PointFillTriangulation(feature: IEncodeFeature) {
const coordinates = feature.coordinates as number[];
return {
Expand All @@ -15,6 +25,10 @@ export function PointFillTriangulation(feature: IEncodeFeature) {
};
}

/**
* 计算3D 拉伸点图
* @param feature 映射feature
*/
export function PointExtrudeTriangulation(feature: IEncodeFeature) {
const { shape } = feature;
const { positions, index } = getGeometry(shape as ShapeType3D);
Expand All @@ -26,6 +40,46 @@ export function PointExtrudeTriangulation(feature: IEncodeFeature) {
};
}

/**
* 计算图片标注
* @param feature 映射feature
*/
export function PointImageTriangulation(feature: IEncodeFeature) {
const coordinates = feature.coordinates as number[];
return {
vertices: [...coordinates],
indices: [0],
size: coordinates.length,
};
}

/**
* 线三角化
* @param feature 映射feature
*/
export function LineTriangulation(feature: IEncodeFeature) {
const { coordinates } = feature;
const line = getNormals(coordinates as number[][], false, 0);
return {
vertices: line.attrPos, // [ x,y,z, distance, miter ]
indices: line.attrIndex,
normals: line.normals,
size: 5,
};
}

export function PolygonExtrudeTriangulation(feature: IEncodeFeature) {
const coordinates = feature.coordinates as IPosition[][];
const { positions, index } = extrudePolygon(coordinates);

return {
vertices: positions, // [ x, y, z ]
indices: index,
normals: Array.from(computeVertexNormals(positions, index)),
size: 3,
};
}

function getGeometry(shape: ShapeType3D): IExtrudeGeomety {
if (GeometryCache && GeometryCache[shape]) {
return GeometryCache[shape];
Expand All @@ -37,6 +91,7 @@ function getGeometry(shape: ShapeType3D): IExtrudeGeomety {
GeometryCache[shape] = geometry;
return geometry;
}

function computeVertexNormals(
positions: number[],
indexArray: number[],
Expand Down Expand Up @@ -75,6 +130,7 @@ function computeVertexNormals(
normalizeNormals(normals);
return normals;
}

function normalizeNormals(normals: Float32Array) {
for (let i = 0, li = normals.length; i < li; i += 3) {
const normal = vec3.fromValues(normals[i], normals[i + 1], normals[i + 2]);
Expand All @@ -83,3 +139,9 @@ function normalizeNormals(normals: Float32Array) {
normals.set(newNormal, i);
}
}

function checkIsClosed(points: number[][][]) {
const p1 = points[0][0];
const p2 = points[0][points[0].length - 1];
return p1[0] === p2[0] && p1[1] === p2[1];
}
10 changes: 7 additions & 3 deletions packages/layers/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { container, ILayerPlugin, TYPES } from '@l7/core';
import BaseLayer from './core/BaseLayer';
import Point3dLayer from './point/extrude';
// import HeatMapLayer from './heatmap';
// import Line from './line';
import LineLayer from './line/index';
import Point3dLayer from './point/extrude';
import PointImageLayer from './point/image';
import PointLayer from './point/index';
// import Point from './point/point';
import PolygonLayer from './polygon';
import Polygon3DLayer from './polygon/polygon3D';
// import ImageLayer from './raster';

import ConfigSchemaValidationPlugin from './plugins/ConfigSchemaValidationPlugin';
Expand Down Expand Up @@ -65,7 +67,9 @@ export {
PointLayer,
PolygonLayer,
Point3dLayer,
// Point,
PointImageLayer,
LineLayer,
Polygon3DLayer,
// Line,
// ImageLayer,
// HeatMapLayer,
Expand Down
Loading

0 comments on commit bda6b6c

Please sign in to comment.