mirror of https://gitee.com/antv-l7/antv-l7
feat(line): greatCircle
This commit is contained in:
parent
7d11de3748
commit
ca3df19c20
|
@ -0,0 +1,53 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="stylesheet" href="https://gw.alipayobjects.com/os/rmsportal/PqLCOJpqoOUfuPRacUzE.css" />
|
||||
<title>弧线图</title>
|
||||
<style> ::-webkit-scrollbar{display:none;}html,body{overflow:hidden;margin:0;}
|
||||
#map { position:absolute; top:0; bottom:0; width:100%; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="map"></div>
|
||||
<script>/*Fixing iframe window.innerHeight 0 issue in Safari*/ document.body.clientHeight; </script>
|
||||
<script src="https://webapi.amap.com/maps?v=1.4.8&key=15cd8a57710d40c9b7c0e3cc120f1200&plugin=Map3D"></script>
|
||||
<script src="https://gw.alipayobjects.com/os/antv/assets/lib/jquery-3.2.1.min.js"></script>
|
||||
<script src="../build/L7.js"></script>
|
||||
<script src="https://npmcdn.com/@turf/turf/turf.min.js"></script>
|
||||
<style>
|
||||
#map { position:absolute; top:0; bottom:0; width:100%; }
|
||||
</style>
|
||||
<script>
|
||||
var scene = new L7.Scene({
|
||||
id: 'map',
|
||||
mapStyle: 'dark', // 样式URL
|
||||
center: [116.2825, 39.9],
|
||||
pitch: 0,
|
||||
zoom: 4
|
||||
});
|
||||
scene.on('loaded', function() {
|
||||
$.get('https://gw.alipayobjects.com/os/rmsportal/UEXQMifxtkQlYfChpPwT.txt', function(data) {
|
||||
|
||||
scene.LineLayer({
|
||||
zIndex: 2
|
||||
}).source(data, {
|
||||
parser:{
|
||||
type:'csv',
|
||||
x: 'lng1',
|
||||
y: 'lat1',
|
||||
x1: 'lng2',
|
||||
y1: 'lat2'
|
||||
}
|
||||
}
|
||||
).color('rgb(13,64,140)').style({
|
||||
opacity: 0.6
|
||||
})
|
||||
.shape('greatCircle')
|
||||
.size(1)
|
||||
.render();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -136,12 +136,6 @@ export default class Layer extends Base {
|
|||
cfg.mapType = this.scene.mapType;
|
||||
cfg.zoom = this.scene.getZoom();
|
||||
this.layerSource = new source(cfg);
|
||||
// this.scene.workerPool.runTask({
|
||||
// command: 'geojson',
|
||||
// data: cfg
|
||||
// }).then(data => {
|
||||
// console.log(data);
|
||||
// });
|
||||
return this;
|
||||
}
|
||||
color(field, values) {
|
||||
|
|
|
@ -25,8 +25,8 @@ export default class Scene extends Base {
|
|||
|
||||
_initEngine(mapContainer) {
|
||||
this._engine = new Engine(mapContainer, this);
|
||||
this.registerMapEvent();
|
||||
// this._engine.run();
|
||||
// this.registerMapEvent();
|
||||
this._engine.run();
|
||||
// this.workerPool = new WorkerPool();
|
||||
compileBuiltinModules();
|
||||
}
|
||||
|
|
|
@ -3,11 +3,7 @@ import { lineShape } from '../shape';
|
|||
|
||||
export default class LineBuffer extends BufferBase {
|
||||
geometryBuffer() {
|
||||
const layerData = this.get('layerData');
|
||||
const shapeType = this.shapeType = this.get('shapeType');
|
||||
const positions = [];
|
||||
const positionsIndex = [];
|
||||
const instances = [];
|
||||
if (shapeType === 'line') {
|
||||
this.attributes = this._getMeshLineAttributes();
|
||||
return;
|
||||
|
@ -15,22 +11,6 @@ export default class LineBuffer extends BufferBase {
|
|||
this.attributes = this._getArcLineAttributes();
|
||||
return;
|
||||
}
|
||||
layerData.forEach((item, index) => {
|
||||
const props = item;
|
||||
const attrData = this._getShape(item.coordinates, props, index);
|
||||
positions.push(...attrData.positions);
|
||||
positionsIndex.push(...attrData.indexes);
|
||||
if (attrData.hasOwnProperty('instances')) {
|
||||
instances.push(...attrData.instances);
|
||||
}
|
||||
});
|
||||
this.bufferStruct.style = layerData;
|
||||
this.bufferStruct.verts = positions;
|
||||
this.bufferStruct.indexs = positionsIndex;
|
||||
if (instances.length > 0) {
|
||||
this.bufferStruct.instances = instances;
|
||||
}
|
||||
this.attributes = this._toAttributes(this.bufferStruct);
|
||||
}
|
||||
|
||||
_getShape(geo, props, index) {
|
||||
|
@ -55,6 +35,7 @@ export default class LineBuffer extends BufferBase {
|
|||
const indexArray = [];
|
||||
const sizes = [];
|
||||
const instances = [];
|
||||
const pickingIds = [];
|
||||
layerData.forEach(item => {
|
||||
const props = item;
|
||||
const positionCount = positions.length / 3;
|
||||
|
@ -64,8 +45,10 @@ export default class LineBuffer extends BufferBase {
|
|||
indexArray.push(...attrData.indexArray);
|
||||
instances.push(...attrData.instances);
|
||||
sizes.push(...attrData.sizes);
|
||||
pickingIds.push(...attrData.pickingIds);
|
||||
});
|
||||
return {
|
||||
pickingIds,
|
||||
positions,
|
||||
colors,
|
||||
indexArray,
|
||||
|
@ -111,38 +94,4 @@ export default class LineBuffer extends BufferBase {
|
|||
attrDashArray
|
||||
};
|
||||
}
|
||||
|
||||
_toAttributes(bufferStruct) {
|
||||
const vertCount = bufferStruct.verts.length;
|
||||
const vertices = new Float32Array(vertCount * 3);
|
||||
const pickingIds = new Float32Array(vertCount);
|
||||
const inposs = new Float32Array(vertCount * 4);
|
||||
const colors = new Float32Array(vertCount * 4);
|
||||
for (let i = 0; i < vertCount; i++) {
|
||||
const index = bufferStruct.indexs[i];
|
||||
const color = bufferStruct.style[index].color;
|
||||
const id = bufferStruct.style[index].id;
|
||||
vertices[i * 3] = bufferStruct.verts[i][0];
|
||||
vertices[i * 3 + 1] = bufferStruct.verts[i][1];
|
||||
vertices[i * 3 + 2] = bufferStruct.verts[i][2];
|
||||
colors[i * 4] = color[0];
|
||||
pickingIds[i] = id;
|
||||
colors[i * 4 + 1] = color[1];
|
||||
colors[i * 4 + 2] = color[2];
|
||||
colors[i * 4 + 3] = color[3];
|
||||
if (bufferStruct.instances) { // 弧线
|
||||
inposs[i * 4] = bufferStruct.instances[i][0];
|
||||
inposs[i * 4 + 1] = bufferStruct.instances[i][1];
|
||||
inposs[i * 4 + 2] = bufferStruct.instances[i][2];
|
||||
inposs[i * 4 + 3] = bufferStruct.instances[i][3];
|
||||
}
|
||||
|
||||
}
|
||||
return {
|
||||
pickingIds,
|
||||
vertices,
|
||||
colors,
|
||||
inposs
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
import * as THREE from '../../core/three';
|
||||
import Material from './material';
|
||||
import { getModule, wrapUniforms } from '../../util/shaderModule';
|
||||
import arcline_frag from '../shader/arcline_frag.glsl';
|
||||
import arcline_vert from '../shader/arcline_vert.glsl';
|
||||
import merge from '@antv/util/lib/deep-mix';
|
||||
|
||||
export function LineMaterial(options) {
|
||||
|
@ -23,17 +21,22 @@ export function LineMaterial(options) {
|
|||
return material;
|
||||
}
|
||||
export function ArcLineMaterial(options) {
|
||||
let moduleName = 'arcline';
|
||||
if (options.shapeType === 'greatCircle') {
|
||||
moduleName = 'greatcircle';
|
||||
}
|
||||
const { vs, fs } = getModule(moduleName);
|
||||
const material = new Material({
|
||||
uniforms: {
|
||||
u_opacity: { value: options.u_opacity || 1.0 },
|
||||
segmentNumber: { value: 49 },
|
||||
segmentNumber: { value: 29 },
|
||||
u_time: { value: 0 },
|
||||
u_zoom: { value: options.u_zoom || 10 },
|
||||
u_activeId: { value: options.activeId || 0 },
|
||||
u_activeColor: { value: options.activeColor || [ 1.0, 0, 0, 1.0 ] }
|
||||
},
|
||||
vertexShader: arcline_vert,
|
||||
fragmentShader: arcline_frag,
|
||||
vertexShader: vs,
|
||||
fragmentShader: fs,
|
||||
transparent: true,
|
||||
blending: THREE.AdditiveBlending
|
||||
});
|
||||
|
|
|
@ -4,6 +4,8 @@ attribute vec4 a_instance;
|
|||
attribute float a_size;
|
||||
uniform float u_zoom;
|
||||
uniform float u_time;
|
||||
uniform float u_activeId : 0;
|
||||
uniform vec4 u_activeColor : [ 1.0, 0, 0, 1.0 ];
|
||||
uniform mat4 matModelViewProjection;
|
||||
uniform float segmentNumber;
|
||||
varying vec4 v_color;
|
||||
|
@ -42,7 +44,6 @@ vec2 getExtrusionOffset(vec2 line_clipspace, float offset_direction) {
|
|||
|
||||
|
||||
void main() {
|
||||
float visindex =mod(u_time *10.,segmentNumber);
|
||||
mat4 matModelViewProjection = projectionMatrix * modelViewMatrix;
|
||||
vec2 source = a_instance.rg;
|
||||
vec2 target = a_instance.ba;
|
||||
|
@ -55,13 +56,11 @@ void main() {
|
|||
vec3 next = getPos(source, target, nextSegmentRatio);
|
||||
vec2 offset = getExtrusionOffset((next.xy - curr.xy) * indexDir, position.y);
|
||||
gl_Position =matModelViewProjection * vec4(vec3(curr + vec3(offset, 0.0)),1.0);
|
||||
// float apha = 0.;
|
||||
// if( position.x> 0. && position.x <visindex)
|
||||
// apha =1.0;
|
||||
// vec3 c1 = vec3(0.929,0.972,0.917);
|
||||
// vec3 c2 = vec3(0.062,0.325,0.603);
|
||||
// v_color = mix(c1, c2, segmentRatio);
|
||||
v_color = a_color;
|
||||
|
||||
// picking
|
||||
if(pickingId == u_activeId) {
|
||||
v_color = u_activeColor;
|
||||
}
|
||||
worldId = id_toPickColor(pickingId);
|
||||
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
#define PI 3.1415926535
|
||||
precision mediump float;
|
||||
attribute vec4 a_color;
|
||||
attribute vec4 a_instance;
|
||||
attribute float a_size;
|
||||
uniform float u_zoom;
|
||||
uniform float u_time;
|
||||
uniform float u_activeId : 0;
|
||||
uniform vec4 u_activeColor : [ 1.0, 0, 0, 1.0 ];
|
||||
uniform mat4 matModelViewProjection;
|
||||
uniform float segmentNumber;
|
||||
varying vec4 v_color;
|
||||
#pragma include "project"
|
||||
float maps (float value, float start1, float stop1, float start2, float stop2) {
|
||||
return start2 + (stop2 - start2) * ((value - start1) / (stop1 - start1));
|
||||
}
|
||||
|
||||
float getSegmentRatio(float index) {
|
||||
return smoothstep(0.0, 1.0, index / (segmentNumber - 1.0));
|
||||
}
|
||||
|
||||
float paraboloid(vec2 source, vec2 target, float ratio) {
|
||||
vec2 x = mix(source, target, ratio);
|
||||
vec2 center = mix(source, target, 0.5);
|
||||
float dSourceCenter = distance(source, center);
|
||||
float dXCenter = distance(x, center);
|
||||
return (dSourceCenter + dXCenter) * (dSourceCenter - dXCenter);
|
||||
}
|
||||
|
||||
vec3 getPos(vec2 source, vec2 target, float segmentRatio) {
|
||||
float vertex_height = paraboloid(source, target, segmentRatio);
|
||||
|
||||
return vec3(
|
||||
mix(source, target, segmentRatio),
|
||||
sqrt(max(0.0, vertex_height))
|
||||
);
|
||||
}
|
||||
vec2 getExtrusionOffset(vec2 line_clipspace, float offset_direction) {
|
||||
// normalized direction of the line
|
||||
vec2 dir_screenspace = normalize(line_clipspace);
|
||||
// rotate by 90 degrees
|
||||
dir_screenspace = vec2(-dir_screenspace.y, dir_screenspace.x);
|
||||
vec2 offset = dir_screenspace * offset_direction * a_size * pow(2.0,20.0-u_zoom) / 2.0;
|
||||
return offset;
|
||||
}
|
||||
float getAngularDist (vec2 source, vec2 target) {
|
||||
vec2 delta = source - target;
|
||||
vec2 sin_half_delta = sin(delta / 2.0);
|
||||
float a =
|
||||
sin_half_delta.y * sin_half_delta.y +
|
||||
cos(source.y) * cos(target.y) *
|
||||
sin_half_delta.x * sin_half_delta.x;
|
||||
return 2.0 * atan(sqrt(a), sqrt(1.0 - a));
|
||||
}
|
||||
vec2 interpolate (vec2 source, vec2 target, float angularDist, float t) {
|
||||
// if the angularDist is PI, linear interpolation is applied. otherwise, use spherical interpolation
|
||||
if(abs(angularDist - PI) < 0.001) {
|
||||
return (1.0 - t) * source + t * target;
|
||||
}
|
||||
float a = sin((1.0 - t) * angularDist) / sin(angularDist);
|
||||
float b = sin(t * angularDist) / sin(angularDist);
|
||||
vec2 sin_source = sin(source);
|
||||
vec2 cos_source = cos(source);
|
||||
vec2 sin_target = sin(target);
|
||||
vec2 cos_target = cos(target);
|
||||
float x = a * cos_source.y * cos_source.x + b * cos_target.y * cos_target.x;
|
||||
float y = a * cos_source.y * sin_source.x + b * cos_target.y * sin_target.x;
|
||||
float z = a * sin_source.y + b * sin_target.y;
|
||||
return vec2(atan(y, x), atan(z, sqrt(x * x + y * y)));
|
||||
}
|
||||
|
||||
void main() {
|
||||
mat4 matModelViewProjection = projectionMatrix * modelViewMatrix;
|
||||
vec2 source = radians(unProjectFlat(a_instance.rg));
|
||||
vec2 target = radians(unProjectFlat(a_instance.ba));
|
||||
float angularDist = getAngularDist(source, target);
|
||||
float segmentIndex = position.x;
|
||||
float segmentRatio = getSegmentRatio(segmentIndex);
|
||||
float indexDir = mix(-1.0, 1.0, step(segmentIndex, 0.0));
|
||||
float nextSegmentRatio = getSegmentRatio(segmentIndex + indexDir);
|
||||
|
||||
|
||||
|
||||
vec3 curr = vec3(degrees(interpolate(source, target, angularDist, segmentRatio)), 0.0);
|
||||
vec3 next = vec3(degrees(interpolate(source, target, angularDist, nextSegmentRatio)), 0.0);
|
||||
vec2 offset = getExtrusionOffset((ProjectFlat(next.xy) - ProjectFlat(curr.xy)) * indexDir, position.y);
|
||||
gl_Position =matModelViewProjection * vec4(vec3(vec3(ProjectFlat(curr.xy),2.) + vec3(offset, 0.0)),1.0);
|
||||
v_color = a_color;
|
||||
// picking
|
||||
if(pickingId == u_activeId) {
|
||||
v_color = u_activeColor;
|
||||
}
|
||||
worldId = id_toPickColor(pickingId);
|
||||
|
||||
}
|
|
@ -17,6 +17,12 @@ import point_line_vert from '../shader/point_meshLine_vert.glsl';
|
|||
import mesh_line_frag from '../shader/meshline_frag.glsl';
|
||||
import mesh_line_vert from '../shader/meshline_vert.glsl';
|
||||
|
||||
// arc line
|
||||
import arc_line_frag from '../shader/arcline_frag.glsl';
|
||||
import arc_line_vert from '../shader/arcline_vert.glsl';
|
||||
import great_circle_line_vert from '../shader/great_circle_line_vert.glsl';
|
||||
|
||||
|
||||
// 原生线
|
||||
import line_frag from '../shader/line_frag.glsl';
|
||||
import line_vert from '../shader/line_vert.glsl';
|
||||
|
@ -54,6 +60,7 @@ import pick_color from './shaderChunks/pick_color.glsl';
|
|||
import decode from './shaderChunks/decode.glsl';
|
||||
import lighting from './shaderChunks/lighting.glsl';
|
||||
import sdf_2d from './shaderChunks/sdf_2d.glsl';
|
||||
import project from './shaderChunks/project.glsl';
|
||||
|
||||
export function compileBuiltinModules() {
|
||||
registerModule('point', { vs: point_vert, fs: point_frag });
|
||||
|
@ -61,6 +68,7 @@ export function compileBuiltinModules() {
|
|||
registerModule('decode', { vs: decode, fs: '' });
|
||||
registerModule('lighting', { vs: lighting, fs: '' });
|
||||
registerModule('sdf_2d', { vs: '', fs: sdf_2d });
|
||||
registerModule('project', { vs: project, fs: '' });
|
||||
registerModule('pick_color', { vs: pick_color, fs: pick_color });
|
||||
registerModule('circle', { vs: circle_vert, fs: circle_frag });
|
||||
registerModule('polygon', { vs: polygon_vert, fs: polygon_frag });
|
||||
|
@ -68,6 +76,8 @@ export function compileBuiltinModules() {
|
|||
registerModule('hexagon', { vs: hexagon_vert, fs: hexagon_frag });
|
||||
registerModule('pointline', { vs: point_line_vert, fs: point_line_frag });
|
||||
registerModule('meshline', { vs: mesh_line_vert, fs: mesh_line_frag });
|
||||
registerModule('arcline', { vs: arc_line_vert, fs: arc_line_frag });
|
||||
registerModule('greatcircle', { vs: great_circle_line_vert, fs: arc_line_frag });
|
||||
registerModule('line', { vs: line_vert, fs: line_frag });
|
||||
registerModule('heatmap_color', { vs: heatmap_color_vert, fs: heatmap_color_frag });
|
||||
registerModule('heatmap_intensity', { vs: heatmap_intensity_vert, fs: heatmap_intensity_frag });
|
||||
|
|
|
@ -20,7 +20,6 @@ uniform float u_duration : 2.0;
|
|||
uniform float u_interval : 1.0;
|
||||
uniform float u_trailLength : 0.2;
|
||||
#endif
|
||||
|
||||
void main() {
|
||||
v_color = a_color;
|
||||
v_distance = a_distance;
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
|
||||
#define PI 3.1415926535
|
||||
#define E 2.718281828459045
|
||||
vec2 ProjectFlat(vec2 lnglat){
|
||||
float maxs=85.0511287798;
|
||||
float lat=max(min(maxs,lnglat.y),-maxs);
|
||||
float scale= 268435456.;
|
||||
float d=PI/180.;
|
||||
float x=lnglat.x*d;
|
||||
float y=lat*d;
|
||||
y=log(tan((PI/4.)+(y/2.)));
|
||||
|
||||
float a=.5/PI,
|
||||
b=.5,
|
||||
c=-.5/PI;
|
||||
d=.5;
|
||||
x=scale*(a*x+b)-215440491.;
|
||||
y=scale*(c*y+d)-106744817.;
|
||||
return vec2(x,y);
|
||||
}
|
||||
|
||||
vec2 unProjectFlat(vec2 px){
|
||||
float a=.5/PI;
|
||||
float b=.5;
|
||||
float c=-.5/PI;
|
||||
float d=.5;
|
||||
float scale = 268435456.;
|
||||
float x=((px.x+215440491.)/scale-b)/a;
|
||||
float y=((px.y+106744817.)/scale-d)/c;
|
||||
y=(atan(pow(E,y))-(PI/4.))*2.;
|
||||
d=PI/180.;
|
||||
float lat=y/d;
|
||||
float lng=x/d;
|
||||
return vec2(lng,lat);
|
||||
}
|
|
@ -9,12 +9,13 @@ import flatten from '@antv/util/lib/flatten';
|
|||
*/
|
||||
|
||||
export function arc(geo, props, positionsIndex) {
|
||||
const segNum = 50;
|
||||
const segNum = 30;
|
||||
const posArray = [];
|
||||
const instanceArray = [];
|
||||
const sizes = [];
|
||||
const colors = [];
|
||||
const { size, color } = props;
|
||||
const pickingIds = [];
|
||||
const { size, color, id } = props;
|
||||
const defaultInstance = [ geo[0][0], geo[0][1], geo[1][0], geo[1][1] ];
|
||||
const indexArray = [];
|
||||
let c = 0;
|
||||
|
@ -27,6 +28,8 @@ export function arc(geo, props, positionsIndex) {
|
|||
sizes.push(size, size);
|
||||
colors.push(...color);
|
||||
colors.push(...color);
|
||||
pickingIds.push(id);
|
||||
pickingIds.push(id);
|
||||
if (i !== segNum - 1) {
|
||||
indexArray[c++] = index + 0;
|
||||
indexArray[c++] = index + 1;
|
||||
|
@ -39,6 +42,7 @@ export function arc(geo, props, positionsIndex) {
|
|||
|
||||
}
|
||||
return {
|
||||
pickingIds,
|
||||
positions: posArray,
|
||||
indexArray,
|
||||
instances: instanceArray,
|
||||
|
|
|
@ -15,6 +15,7 @@ import DrawArcLine from './line/drawArc';
|
|||
|
||||
registerRender('line', 'line', DrawMeshLine);
|
||||
registerRender('line', 'arc', DrawArcLine);
|
||||
registerRender('line', 'greatCircle', DrawArcLine);
|
||||
|
||||
// point
|
||||
import DrawPointFill from './point/drawFill';
|
||||
|
|
|
@ -2,23 +2,26 @@ import * as THREE from '../../../core/three';
|
|||
import { LineBuffer } from '../../../geom/buffer/index';
|
||||
import { ArcLineMaterial } from '../../../geom/material/lineMaterial';
|
||||
export default function DrawArcLine(layerdata, layer) {
|
||||
const style = this.get('styleOptions');
|
||||
const style = layer.get('styleOptions');
|
||||
const activeOption = layer.get('activedOptions');
|
||||
const { attributes } = new LineBuffer({
|
||||
layerdata,
|
||||
layerData: layerdata,
|
||||
shapeType: 'arc',
|
||||
style
|
||||
});
|
||||
const geometry = new THREE.BufferGeometry();
|
||||
geometry.setIndex(attributes.indexArray);
|
||||
geometry.addAttribute('pickingId', new THREE.Float32BufferAttribute(attributes.pickingIds, 1));
|
||||
geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.positions, 3));
|
||||
geometry.addAttribute('a_color', new THREE.Float32BufferAttribute(attributes.colors, 4));
|
||||
geometry.addAttribute('a_instance', new THREE.Float32BufferAttribute(attributes.instances, 4));
|
||||
geometry.addAttribute('a_size', new THREE.Float32BufferAttribute(attributes.sizes, 1));
|
||||
|
||||
const lineMaterial = new ArcLineMaterial({
|
||||
u_opacity: style.opacity,
|
||||
u_zoom: layer.scene.getZoom(),
|
||||
activeColor: activeOption.fill
|
||||
activeColor: activeOption.fill,
|
||||
shapeType: layer.shapeType
|
||||
}, {
|
||||
SHAPE: false
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue