-
Notifications
You must be signed in to change notification settings - Fork 633
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
266 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
import { AttributeType, gl, IEncodeFeature, ILayer } from '@l7/core'; | ||
import BaseLayer from '../core/BaseLayer'; | ||
import { LineArcTriangulation } from '../core/triangulation'; | ||
import line_arc2d_vert from './shaders/line_arc2d_vert.glsl'; | ||
import line_arc_frag from './shaders/line_arc_frag.glsl'; | ||
interface IArcLayerStyleOptions { | ||
opacity: number; | ||
segmentNumber: number; | ||
} | ||
export default class Arc2DLineLayer extends BaseLayer<IArcLayerStyleOptions> { | ||
public name: string = 'LineLayer'; | ||
|
||
protected getConfigSchema() { | ||
return { | ||
properties: { | ||
opacity: { | ||
type: 'number', | ||
minimum: 0, | ||
maximum: 1, | ||
}, | ||
}, | ||
}; | ||
} | ||
|
||
protected renderModels() { | ||
const { opacity } = this.getStyleOptions(); | ||
this.models.forEach((model) => | ||
model.draw({ | ||
uniforms: { | ||
u_Opacity: opacity || 1, | ||
segmentNumber: 30, | ||
}, | ||
}), | ||
); | ||
return this; | ||
} | ||
|
||
protected buildModels() { | ||
this.registerBuiltinAttributes(this); | ||
this.models = [ | ||
this.buildLayerModel({ | ||
moduleName: 'arc2dline', | ||
vertexShader: line_arc2d_vert, | ||
fragmentShader: line_arc_frag, | ||
triangulation: LineArcTriangulation, | ||
depth: { enable: false }, | ||
blend: { | ||
enable: true, | ||
func: { | ||
srcRGB: gl.ONE, | ||
srcAlpha: 1, | ||
dstRGB: gl.ONE, | ||
dstAlpha: 1, | ||
}, | ||
}, | ||
}), | ||
]; | ||
} | ||
|
||
private registerBuiltinAttributes(layer: ILayer) { | ||
// point layer size; | ||
layer.styleAttributeService.registerStyleAttribute({ | ||
name: 'size', | ||
type: AttributeType.Attribute, | ||
descriptor: { | ||
name: 'a_Size', | ||
buffer: { | ||
// give the WebGL driver a hint that this buffer may change | ||
usage: gl.DYNAMIC_DRAW, | ||
data: [], | ||
type: gl.FLOAT, | ||
}, | ||
size: 1, | ||
update: ( | ||
feature: IEncodeFeature, | ||
featureIdx: number, | ||
vertex: number[], | ||
attributeIdx: number, | ||
) => { | ||
const { size } = feature; | ||
return Array.isArray(size) ? [size[0]] : [size as number]; | ||
}, | ||
}, | ||
}); | ||
|
||
layer.styleAttributeService.registerStyleAttribute({ | ||
name: 'instance', // 弧线起始点信息 | ||
type: AttributeType.Attribute, | ||
descriptor: { | ||
name: 'a_Instance', | ||
buffer: { | ||
usage: gl.STATIC_DRAW, | ||
data: [], | ||
type: gl.FLOAT, | ||
}, | ||
size: 4, | ||
update: ( | ||
feature: IEncodeFeature, | ||
featureIdx: number, | ||
vertex: number[], | ||
attributeIdx: number, | ||
) => { | ||
return [vertex[3], vertex[4], vertex[5], vertex[6]]; | ||
}, | ||
}, | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
precision mediump float; | ||
attribute vec4 a_Color; | ||
attribute vec3 a_Position; | ||
attribute vec4 a_Instance; | ||
attribute float a_Size; | ||
uniform mat4 u_ModelMatrix; | ||
uniform float segmentNumber; | ||
varying vec4 v_color; | ||
|
||
#pragma include "projection" | ||
|
||
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.)); | ||
} | ||
|
||
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 / 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() { | ||
v_color = a_Color; | ||
vec2 source = radians(a_Instance.rg); | ||
vec2 target = radians(a_Instance.ba); | ||
float angularDist = getAngularDist(source, target); | ||
float segmentIndex = a_Position.x; | ||
float segmentRatio = getSegmentRatio(segmentIndex); | ||
float indexDir = mix(-1.0, 1.0, step(segmentIndex, 0.0)); | ||
float nextSegmentRatio = getSegmentRatio(segmentIndex + indexDir); | ||
|
||
vec4 curr = project_position(vec4(degrees(interpolate(source, target, angularDist, segmentRatio)), 0.0, 1.0)); | ||
vec4 next = project_position(vec4(degrees(interpolate(source, target, angularDist, nextSegmentRatio)), 0.0, 1.0)); | ||
|
||
vec2 offset = getExtrusionOffset((next.xy - curr.xy) * indexDir, a_Position.y); | ||
|
||
// vec4 project_pos = project_position(vec4(curr.xy, 0, 1.0)); | ||
gl_Position = project_common_position_to_clipspace(vec4(curr.xy + offset, 0, 1.0)); | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import { Arc2DLineLayer } from '@l7/layers'; | ||
import { Scene } from '@l7/scene'; | ||
import * as React from 'react'; | ||
|
||
export default class Arc2DLineDemo extends React.Component { | ||
private scene: Scene; | ||
|
||
public componentWillUnmount() { | ||
this.scene.destroy(); | ||
} | ||
|
||
public async componentDidMount() { | ||
const response = await fetch( | ||
'https://gw.alipayobjects.com/os/rmsportal/UEXQMifxtkQlYfChpPwT.txt', | ||
); | ||
const scene = new Scene({ | ||
center: [116.2825, 39.9], | ||
id: 'map', | ||
pitch: 0, | ||
type: 'mapbox', | ||
style: 'mapbox://styles/mapbox/dark-v9', | ||
zoom: 2, | ||
}); | ||
const lineLayer = new Arc2DLineLayer({}) | ||
.source(await response.text(), { | ||
parser: { | ||
type: 'csv', | ||
x: 'lng1', | ||
y: 'lat1', | ||
x1: 'lng2', | ||
y1: 'lat2', | ||
}, | ||
}) | ||
.size(0.5) | ||
.shape('arc') | ||
.color('rgb(13,64,140)'); | ||
scene.addLayer(lineLayer); | ||
scene.render(); | ||
this.scene = scene; | ||
} | ||
|
||
public render() { | ||
return ( | ||
<div | ||
id="map" | ||
style={{ | ||
position: 'absolute', | ||
top: 0, | ||
left: 0, | ||
right: 0, | ||
bottom: 0, | ||
}} | ||
/> | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters