Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/markerFeature.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ var pointFeature = require('./pointFeature');
*
* @typedef {geo.feature.styleSpec} geo.markerFeature.styleSpec
* @extends geo.feature.styleSpec
* @property {number|Function} [radius=5] Radius of each marker in pixels.
* @property {number|Function} [radius=6.25] Radius of each marker in pixels.
* This includes the stroke width if `strokeOffset` is -1, excludes it if
* `strokeOffset` is 1, and includes half the stroke width if `strokeOffset`
* is 0. Note that is `radiusIncludesStroke` is `false`, this never
Expand Down
42 changes: 42 additions & 0 deletions src/polygonFeature.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,45 @@ var transform = require('./transform');
* style options.
*/

/**
* Style specification for a polygon pattern.
*
* @typedef {geo.polygonPattern} geo.polygonPattern
* @property {geo.geoColor} [fillColor] RGBA fill color. Default is polygon
* strokeColor and strokeOpacity.
* @property {geo.geoColor} [strokeColor] RGBA stroke color. Default is
* polygon fillColor and fillOpacity.
* @property {number} [strokeWidth=1.25] The weight of the pattern marker's
* stroke in pixels. Set this or A on strokeFill to zero to not have a
* stroke.
* @property {number} [strokeOffset=-1] The position of the stroke compared to
* the pattern radius. This can only be -1, 0, or 1 (the sign of the value
* is used).
* @property {boolean} [radiusIncludesStroke=true] If truthy or undefined, the
* `radius` includes the `strokeWidth` based on the `strokeOffset`. If
* defined and falsy, the radius does not include the `strokeWidth`.
* @property {number} [symbol=0] One of the predefined symbol numbers. This is
* one of `geo.markerFeature.symbols`.
* @property {number|number[]} [symbolValue=0] A value the affects the
* appearance of the symbol. Some symbols can take an array of numbers.
* @property {number} [rotation=0] The rotation of the symbol in clockwise
* radians.
* @property {geo.markerFeature.scaleMode} [scaleWithZoom='none'] This
* determines if the fill, stroke, or both scale with zoom. If set, the
* values for radius and strokeWidth are the values at zoom-level zero.
* @property {boolean} [rotateWithMap=false] If truthy, rotate symbols with the
* map. If falsy, symbol orientation is absolute.
* @property {number} [radius=6.25] Radius of each marker in pixels. This
* includes the stroke width if `strokeOffset` is -1, excludes it if
* `strokeOffset` is 1, and includes half the stroke width if `strokeOffset`
* is 0. Note that is `radiusIncludesStroke` is `false`, this never
* includes the stroke width.
* @property {number} [spacing=20] Spacing in pixels between pattern symbols;
* scaled if either radius or strokeWidth is scaled. If positive, patterns
* are on a square grid. If negative, patterns are on a triangular grid.
* @property {number[]} [origin=[0, 0]] Origin of the pattern.
*/

/**
* Style specification for a polygon feature.
*
Expand All @@ -35,6 +74,9 @@ var transform = require('./transform');
* function, this is passed an array of items, each of which has a vertices
* property that is a single continuous array in map gcs coordinates. It
* defaults to the first polygon's first vertex's position.
* @property {geo.polygonPattern|Function} [pattern] Pattern to apply to each
* polygon. Each polygon can be distinct, but the pattern is uniform across
* any one polygon.
*/

/**
Expand Down
21 changes: 21 additions & 0 deletions src/util/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -1506,6 +1506,27 @@ var util = {
return d;
},

/**
* Pack an array of three numbers and one boolean into a single float. Each
* numerical value is either undefined or on the scale of [0, 1] and is
* mapped to an integer range of [0, 250].
*
* @param {number|number[]} value A single value or an array of up to four
* values where the first three values are numbers and the last is a
* boolean.
* @returns {number} A packed number.
*/
packFloats: function (value) {
if (!value.length) {
return value === undefined ? 0 : Math.floor(Math.abs(value) * 250) + 1;
}
return (
(value[0] === undefined ? 0 : Math.floor(Math.abs(value[0]) * 250) + 1) +
(value[1] === undefined ? 0 : Math.floor(Math.abs(value[1]) * 250) + 1) * 252 +
(value[2] === undefined ? 0 : Math.floor(Math.abs(value[2]) * 250) + 1) * 252 * 252
) * (value[3] ? -1 : 1);
},

///////////////////////////////////////////////////////////////////////////
/*
* Utility member properties.
Expand Down
23 changes: 1 addition & 22 deletions src/webgl/markerFeature.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,27 +74,6 @@ var webgl_markerFeature = function (arg) {
return shader;
}

/**
* Pack an array of three numbers and one boolean into a single float. Each
* numerical value is either undefined or on the scale of [0, 1] and is
* mapped to an integer range of [0, 250].
*
* @param {number|number[]} value A single value or an array of up to four
* values where the first three values are numbers and the last is a
* boolean.
* @returns {number} A packed number.
*/
function packFloats(value) {
if (!value.length) {
return value === undefined ? 0 : Math.floor(Math.abs(value) * 250) + 1;
}
return (
(value[0] === undefined ? 0 : Math.floor(Math.abs(value[0]) * 250) + 1) +
(value[1] === undefined ? 0 : Math.floor(Math.abs(value[1]) * 250) + 1) * 252 +
(value[2] === undefined ? 0 : Math.floor(Math.abs(value[2]) * 250) + 1) * 252 * 252
) * (value[3] ? -1 : 1);
}

/**
* Create and style the data needed to render the markers.
*
Expand Down Expand Up @@ -195,7 +174,7 @@ var webgl_markerFeature = function (arg) {
((Math.sign(styleVal.radiusIncludesStroke !== undefined && styleVal.radiusIncludesStroke ? styleVal.strokeOffset : 1) + 1) * 16) +
styleVal.symbol * 64);
if (styleVal.symbolValue && styleVal.symbol >= markerFeature.symbols.arrow && styleVal.symbol < markerFeature.symbols.arrow + markerFeature.symbols.arrowMax) {
styleVal.symbolValue = packFloats(styleVal.symbolValue);
styleVal.symbolValue = util.packFloats(styleVal.symbolValue);
}
for (j = 0; j < vpf; j += 1, ivpf += 1, ivpf3 += 3) {
if (!onlyStyle) {
Expand Down
43 changes: 38 additions & 5 deletions src/webgl/markerFeatureFS.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -256,14 +256,42 @@ vec2 rotationalSymmetry(vec2 pos, int repetitions) {
return vec2(cos(ang), sin(ang)) * length(pos);
}

void markerFeatureFragment(vec2 pos) {
float markerFeatureFragment(vec3 posAndSpacing) {
vec2 pos = posAndSpacing.xy;
float spacing = posAndSpacing.z;
// square lattice
if (spacing > 0.0) {
pos.x = mod(pos.x + spacing * 0.5, spacing) - spacing * 0.5;
pos.y = mod(pos.y + spacing * 0.5, spacing) - spacing * 0.5;
}
// triangular lattice
if (spacing < 0.0) {
spacing = spacing * -1.0;
float cz = (2.0 * pos.y) / (sqrt(3.0) * spacing);
float cx = pos.x / spacing - 0.5 * cz;
float cy = -cx - cz;
float rx = floor(cx + 0.5);
float ry = floor(cy + 0.5);
float rz = floor(cz + 0.5);
float dx = abs(rx - cx);
float dy = abs(ry - cy);
float dz = abs(rz - cz);
if (dx > dy && dx > dz) {
rx = -ry - rz;
} else if (dy > dz) {
ry = -rx - rz;
} else {
rz = -rx - ry;
}
vec2 center = vec2(spacing * (rx + 0.5 * rz), (sqrt(3.0) * spacing * 0.5) * rz);
pos = pos - center;
}
// rad is a value in pixels from the edge of the symbol where negative is
// inside the shape
float rad = length(pos.xy) - radiusVar;
// never allow points outside of the main radius
if (rad > 0.0) {
discard;
return;
return 0.0;
}
// apply clockwise rotation
if (rotationVar != 0.0) {
Expand Down Expand Up @@ -309,8 +337,7 @@ void markerFeatureFragment(vec2 pos) {
}

if (rad >= 0.0) {
discard;
return;
return 0.0;
}
// If there is no stroke, the fill region should transition to nothing
if (strokeColorVar.a == 0.0 || strokeWidthVar <= 0.0) {
Expand All @@ -326,13 +353,19 @@ void markerFeatureFragment(vec2 pos) {
} else {
fillColor = fillColorVar;
}
float alpha = 1.0;
if (rad <= endStep) {
float step = smoothstep(endStep - antialiasDist, endStep, rad);
vec4 color = mix(fillColor, strokeColor, step);
float step2 = smoothstep(-antialiasDist, 0.0, rad);
gl_FragColor = mix(color, vec4(color.rgb, 0.0), step2);
if (color.a > 0.0)
alpha = gl_FragColor.a / color.a;
} else {
float step = smoothstep(-antialiasDist, 0.0, rad);
gl_FragColor = mix(strokeColor, vec4(strokeColor.rgb, 0.0), step);
if (strokeColor.a > 0.0)
alpha = gl_FragColor.a / strokeColor.a;
}
return alpha;
}
3 changes: 2 additions & 1 deletion src/webgl/markerFeaturePoly.frag
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ varying vec2 unitVar; // distinct for square/triangle
void main() {
if (fillColorVar.a == 0.0 && strokeColorVar.a == 0.0)
discard;
markerFeatureFragment(unitVar);
if (markerFeatureFragment(vec3(unitVar, 0.0)) == 0.0)
discard;
}
3 changes: 2 additions & 1 deletion src/webgl/markerFeatureSprite.frag
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ void main(void) {
discard;
// for sprites, convert the position to [-radius,radius],[-radius,radius]
vec2 pos = (gl_PointCoord.xy - 0.5) * 2.0 * radiusVar;
markerFeatureFragment(pos);
if (markerFeatureFragment(vec3(pos, 0.0)) == 0.0)
discard;
}
Loading