@genome-spy/core 0.30.0 → 0.30.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.es.js +16379 -0
- package/dist/index.js +43 -43
- package/package.json +10 -7
- package/src/data/collector.js +0 -183
- package/src/data/collector.test.js +0 -84
- package/src/data/dataFlow.js +0 -148
- package/src/data/dataFlow.test.js +0 -5
- package/src/data/facetNode.js +0 -17
- package/src/data/flow.test.js +0 -72
- package/src/data/flowBatch.d.ts +0 -40
- package/src/data/flowNode.js +0 -283
- package/src/data/flowNode.test.js +0 -50
- package/src/data/flowOptimizer.js +0 -123
- package/src/data/flowOptimizer.test.js +0 -193
- package/src/data/flowTestUtils.js +0 -63
- package/src/data/formats/fasta.js +0 -32
- package/src/data/formats/fasta.test.js +0 -27
- package/src/data/sources/dataSource.js +0 -22
- package/src/data/sources/dataSourceFactory.js +0 -24
- package/src/data/sources/dataUtils.js +0 -78
- package/src/data/sources/dynamicCallbackSource.js +0 -57
- package/src/data/sources/dynamicSource.js +0 -37
- package/src/data/sources/inlineSource.js +0 -67
- package/src/data/sources/inlineSource.test.js +0 -56
- package/src/data/sources/namedSource.js +0 -79
- package/src/data/sources/sequenceSource.js +0 -46
- package/src/data/sources/sequenceSource.test.js +0 -46
- package/src/data/sources/urlSource.js +0 -74
- package/src/data/transforms/aggregate.js +0 -70
- package/src/data/transforms/clone.js +0 -40
- package/src/data/transforms/clone.test.js +0 -11
- package/src/data/transforms/coverage.js +0 -187
- package/src/data/transforms/coverage.test.js +0 -123
- package/src/data/transforms/filter.js +0 -37
- package/src/data/transforms/filter.test.js +0 -18
- package/src/data/transforms/filterScoredLabels.js +0 -134
- package/src/data/transforms/flattenCompressedExons.js +0 -57
- package/src/data/transforms/flattenDelimited.js +0 -74
- package/src/data/transforms/flattenDelimited.test.js +0 -87
- package/src/data/transforms/flattenSequence.js +0 -39
- package/src/data/transforms/flattenSequence.test.js +0 -34
- package/src/data/transforms/formula.js +0 -39
- package/src/data/transforms/formula.test.js +0 -19
- package/src/data/transforms/identifier.js +0 -108
- package/src/data/transforms/identifier.test.js +0 -83
- package/src/data/transforms/linearizeGenomicCoordinate.js +0 -101
- package/src/data/transforms/measureText.js +0 -44
- package/src/data/transforms/pileup.js +0 -128
- package/src/data/transforms/pileup.test.js +0 -70
- package/src/data/transforms/project.js +0 -41
- package/src/data/transforms/project.test.js +0 -32
- package/src/data/transforms/regexExtract.js +0 -61
- package/src/data/transforms/regexExtract.test.js +0 -67
- package/src/data/transforms/regexFold.js +0 -141
- package/src/data/transforms/regexFold.test.js +0 -160
- package/src/data/transforms/sample.js +0 -101
- package/src/data/transforms/sample.test.js +0 -38
- package/src/data/transforms/stack.js +0 -137
- package/src/data/transforms/stack.test.js +0 -91
- package/src/data/transforms/transformFactory.js +0 -60
- package/src/embedApi.d.ts +0 -67
- package/src/encoder/accessor.js +0 -82
- package/src/encoder/accessor.test.js +0 -47
- package/src/encoder/encoder.js +0 -394
- package/src/encoder/encoder.test.js +0 -98
- package/src/fonts/Lato-Regular.json +0 -1267
- package/src/fonts/Lato-Regular.png +0 -0
- package/src/fonts/OFL.txt +0 -93
- package/src/fonts/README.md +0 -3
- package/src/fonts/bmFont.d.ts +0 -58
- package/src/fonts/bmFontManager.js +0 -357
- package/src/fonts/bmFontMetrics.js +0 -108
- package/src/genome/genome.js +0 -317
- package/src/genome/genome.test.js +0 -188
- package/src/genome/genomeStore.js +0 -54
- package/src/genome/locusFormat.js +0 -31
- package/src/genome/scaleIndex.d.ts +0 -38
- package/src/genome/scaleIndex.js +0 -166
- package/src/genome/scaleIndex.test.js +0 -78
- package/src/genome/scaleLocus.d.ts +0 -11
- package/src/genome/scaleLocus.js +0 -108
- package/src/genome/scaleLocus.test.js +0 -4
- package/src/genomeSpy.js +0 -785
- package/src/gl/arrayBuilder.js +0 -199
- package/src/gl/dataToVertices.js +0 -636
- package/src/gl/includes/common.glsl +0 -63
- package/src/gl/includes/picking.fragment.glsl +0 -1
- package/src/gl/includes/picking.vertex.glsl +0 -27
- package/src/gl/includes/sampleFacet.glsl +0 -107
- package/src/gl/includes/scales.glsl +0 -112
- package/src/gl/link.fragment.glsl +0 -18
- package/src/gl/link.vertex.glsl +0 -111
- package/src/gl/point.fragment.glsl +0 -123
- package/src/gl/point.vertex.glsl +0 -129
- package/src/gl/rect.fragment.glsl +0 -51
- package/src/gl/rect.vertex.glsl +0 -114
- package/src/gl/rule.fragment.glsl +0 -52
- package/src/gl/rule.vertex.glsl +0 -89
- package/src/gl/text.fragment.glsl +0 -31
- package/src/gl/text.vertex.glsl +0 -246
- package/src/gl/webGLHelper.js +0 -504
- package/src/img/bowtie.svg +0 -1
- package/src/img/genomespy-favicon.svg +0 -34
- package/src/index.html +0 -11
- package/src/index.js +0 -128
- package/src/marks/link.js +0 -175
- package/src/marks/mark.js +0 -975
- package/src/marks/markUtils.js +0 -125
- package/src/marks/pointMark.js +0 -251
- package/src/marks/rectMark.js +0 -241
- package/src/marks/rule.js +0 -250
- package/src/marks/text.js +0 -278
- package/src/node_modules/.vitest/results.json +0 -1
- package/src/scale/colorUtils.js +0 -184
- package/src/scale/glslScaleGenerator.js +0 -502
- package/src/scale/scale.js +0 -451
- package/src/scale/scale.test.js +0 -324
- package/src/scale/ticks.js +0 -203
- package/src/scale/ticks.test.js +0 -40
- package/src/singlePageApp.js +0 -13
- package/src/spec/axis.d.ts +0 -296
- package/src/spec/channel.d.ts +0 -430
- package/src/spec/data.d.ts +0 -196
- package/src/spec/font.d.ts +0 -15
- package/src/spec/genome.d.ts +0 -35
- package/src/spec/mark.d.ts +0 -429
- package/src/spec/root.d.ts +0 -17
- package/src/spec/sampleView.d.ts +0 -180
- package/src/spec/scale.d.ts +0 -273
- package/src/spec/title.d.ts +0 -102
- package/src/spec/tooltip.d.ts +0 -9
- package/src/spec/transform.d.ts +0 -479
- package/src/spec/view.d.ts +0 -201
- package/src/styles/genome-spy.scss +0 -153
- package/src/tooltip/dataTooltipHandler.js +0 -64
- package/src/tooltip/refseqGeneTooltipHandler.js +0 -78
- package/src/tooltip/tooltipHandler.ts +0 -12
- package/src/types/filetypes.d.ts +0 -14
- package/src/types/flatqueue.d.ts +0 -53
- package/src/types/glsl.d.ts +0 -4
- package/src/types/internmap.d.ts +0 -22
- package/src/types/object.d.ts +0 -21
- package/src/types/vega-loader.d.ts +0 -1
- package/src/types/vega-scale.d.ts +0 -60
- package/src/utils/addBaseUrl.js +0 -19
- package/src/utils/addBaseUrl.test.js +0 -22
- package/src/utils/animator.js +0 -83
- package/src/utils/arrayUtils.js +0 -61
- package/src/utils/binnedIndex.js +0 -167
- package/src/utils/binnedIndex.test.js +0 -155
- package/src/utils/clamp.js +0 -8
- package/src/utils/cloner.js +0 -34
- package/src/utils/cloner.test.js +0 -24
- package/src/utils/coalesce.js +0 -11
- package/src/utils/coalesce.test.js +0 -16
- package/src/utils/concatIterables.js +0 -26
- package/src/utils/concatIterables.test.js +0 -8
- package/src/utils/debounce.js +0 -37
- package/src/utils/domainArray.js +0 -216
- package/src/utils/domainArray.test.js +0 -130
- package/src/utils/eerp.js +0 -13
- package/src/utils/expression.js +0 -32
- package/src/utils/field.js +0 -28
- package/src/utils/formatObject.js +0 -31
- package/src/utils/indexer.js +0 -43
- package/src/utils/indexer.test.js +0 -47
- package/src/utils/inertia.js +0 -124
- package/src/utils/interactionEvent.js +0 -33
- package/src/utils/iterateNestedMaps.js +0 -21
- package/src/utils/iterateNestedMaps.test.js +0 -33
- package/src/utils/kWayMerge.js +0 -42
- package/src/utils/kWayMerge.test.js +0 -26
- package/src/utils/layout/flexLayout.js +0 -368
- package/src/utils/layout/flexLayout.test.js +0 -311
- package/src/utils/layout/grid.js +0 -95
- package/src/utils/layout/grid.test.js +0 -71
- package/src/utils/layout/padding.js +0 -120
- package/src/utils/layout/point.js +0 -23
- package/src/utils/layout/rectangle.js +0 -288
- package/src/utils/layout/rectangle.test.js +0 -172
- package/src/utils/mergeObjects.js +0 -99
- package/src/utils/mergeObjects.test.js +0 -42
- package/src/utils/numberExtractor.js +0 -24
- package/src/utils/numberExtractor.test.js +0 -6
- package/src/utils/point.js +0 -14
- package/src/utils/propertyCacher.js +0 -70
- package/src/utils/propertyCacher.test.js +0 -85
- package/src/utils/propertyCoalescer.js +0 -42
- package/src/utils/propertyCoalescer.test.js +0 -22
- package/src/utils/reservationMap.js +0 -103
- package/src/utils/reservationMap.test.js +0 -20
- package/src/utils/scaleNull.js +0 -19
- package/src/utils/setOperations.js +0 -75
- package/src/utils/smoothstep.js +0 -10
- package/src/utils/throttle.js +0 -34
- package/src/utils/topK.js +0 -76
- package/src/utils/topK.test.js +0 -64
- package/src/utils/transition.js +0 -74
- package/src/utils/ui/tooltip.js +0 -189
- package/src/utils/url.js +0 -22
- package/src/utils/variableTools.js +0 -24
- package/src/utils/variableTools.test.js +0 -13
- package/src/view/axisResolution.js +0 -140
- package/src/view/axisResolution.test.js +0 -201
- package/src/view/axisView.js +0 -747
- package/src/view/concatView.js +0 -45
- package/src/view/containerView.js +0 -159
- package/src/view/facetView.js +0 -491
- package/src/view/flowBuilder.js +0 -367
- package/src/view/flowBuilder.test.js +0 -125
- package/src/view/gridView.js +0 -786
- package/src/view/implicitRootView.js +0 -14
- package/src/view/importView.js +0 -19
- package/src/view/layerView.js +0 -74
- package/src/view/rendering.d.ts +0 -44
- package/src/view/renderingContext/compositeViewRenderingContext.js +0 -51
- package/src/view/renderingContext/deferredViewRenderingContext.js +0 -176
- package/src/view/renderingContext/layoutRecorderViewRenderingContext.js +0 -128
- package/src/view/renderingContext/simpleViewRenderingContext.js +0 -64
- package/src/view/renderingContext/svgViewRenderingContext.js +0 -125
- package/src/view/renderingContext/viewRenderingContext.js +0 -41
- package/src/view/scaleResolution.js +0 -797
- package/src/view/scaleResolution.test.js +0 -572
- package/src/view/scaleResolutionApi.d.ts +0 -40
- package/src/view/testUtils.js +0 -51
- package/src/view/title.js +0 -165
- package/src/view/unitView.js +0 -382
- package/src/view/view.js +0 -612
- package/src/view/view.test.js +0 -214
- package/src/view/viewContext.d.ts +0 -62
- package/src/view/viewFactory.js +0 -181
- package/src/view/viewFactory.test.js +0 -17
- package/src/view/viewUtils.js +0 -327
- package/src/view/zoom.js +0 -89
package/src/gl/dataToVertices.js
DELETED
|
@@ -1,636 +0,0 @@
|
|
|
1
|
-
import { InternMap } from "internmap";
|
|
2
|
-
import { format } from "d3-format";
|
|
3
|
-
import { isString } from "vega-util";
|
|
4
|
-
import ArrayBuilder from "./arrayBuilder";
|
|
5
|
-
import { SDF_PADDING } from "../fonts/bmFontMetrics";
|
|
6
|
-
import { createBinningRangeIndexer } from "../utils/binnedIndex";
|
|
7
|
-
import { isValueDef } from "../encoder/encoder";
|
|
8
|
-
import {
|
|
9
|
-
isHighPrecisionScale,
|
|
10
|
-
splitHighPrecision,
|
|
11
|
-
} from "../scale/glslScaleGenerator";
|
|
12
|
-
import { isContinuous } from "vega-scale";
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* @typedef {object} RangeEntry Represents a location of a vertex subset
|
|
16
|
-
* @prop {number} offset in vertices
|
|
17
|
-
* @prop {number} count in vertices
|
|
18
|
-
* @prop {import("../utils/binnedIndex").Lookup} xIndex
|
|
19
|
-
*
|
|
20
|
-
* @typedef {import("./arraybuilder").ConverterMetadata} Converter
|
|
21
|
-
* @typedef {import("../encoder/encoder").Encoder} Encoder
|
|
22
|
-
*/
|
|
23
|
-
export class GeometryBuilder {
|
|
24
|
-
/**
|
|
25
|
-
*
|
|
26
|
-
* @param {object} object
|
|
27
|
-
* @param {Record<string, Encoder>} object.encoders
|
|
28
|
-
* @param {string[]} [object.attributes]
|
|
29
|
-
* @param {number} [object.numVertices] If the number of data items is known, a
|
|
30
|
-
* preallocated TypedArray is used
|
|
31
|
-
*/
|
|
32
|
-
constructor({ encoders, numVertices = undefined, attributes = [] }) {
|
|
33
|
-
this.encoders = encoders;
|
|
34
|
-
|
|
35
|
-
// Encoders for variable channels
|
|
36
|
-
this.variableEncoders = Object.fromEntries(
|
|
37
|
-
Object.entries(encoders).filter(
|
|
38
|
-
([channel, e]) =>
|
|
39
|
-
attributes.includes(channel) && e && e.scale && !e.constant
|
|
40
|
-
)
|
|
41
|
-
);
|
|
42
|
-
|
|
43
|
-
this.allocatedVertices = numVertices;
|
|
44
|
-
|
|
45
|
-
this.variableBuilder = new ArrayBuilder(numVertices);
|
|
46
|
-
|
|
47
|
-
// Create converters and updaters for all variable channels.
|
|
48
|
-
// TODO: If more than one channels use the same field with the same data type, convert the field only once.
|
|
49
|
-
|
|
50
|
-
for (const [channel, ce] of Object.entries(this.variableEncoders)) {
|
|
51
|
-
const accessor = ce.accessor;
|
|
52
|
-
|
|
53
|
-
const doubleArray = [0, 0];
|
|
54
|
-
const hp = isHighPrecisionScale(ce.scale.type);
|
|
55
|
-
|
|
56
|
-
const indexer = ce.indexer;
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Discrete variables both numeric and strings must be "indexed",
|
|
60
|
-
* 64 bit floats must be converted to vec2.
|
|
61
|
-
* 32 bit continuous variables go to GPU as is.
|
|
62
|
-
*
|
|
63
|
-
* @type {function(any):(number | number[])}
|
|
64
|
-
*/
|
|
65
|
-
const f = indexer
|
|
66
|
-
? (d) => indexer(accessor(d))
|
|
67
|
-
: hp
|
|
68
|
-
? (d) => splitHighPrecision(accessor(d), doubleArray)
|
|
69
|
-
: accessor;
|
|
70
|
-
|
|
71
|
-
this.variableBuilder.addConverter(channel, {
|
|
72
|
-
f,
|
|
73
|
-
numComponents: hp ? 2 : 1,
|
|
74
|
-
arrayReference: hp ? doubleArray : undefined,
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
this.lastOffset = 0;
|
|
79
|
-
|
|
80
|
-
/** @type {Map<any, RangeEntry>} keep track of facet locations within the vertex array */
|
|
81
|
-
this.rangeMap = new InternMap([], JSON.stringify);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Must be called at the end of `addBatch`
|
|
86
|
-
*
|
|
87
|
-
* @param {any} key
|
|
88
|
-
*/
|
|
89
|
-
registerBatch(key) {
|
|
90
|
-
const offset = this.lastOffset;
|
|
91
|
-
const index = this.variableBuilder.vertexCount;
|
|
92
|
-
const size = index - offset;
|
|
93
|
-
if (size) {
|
|
94
|
-
this.rangeMap.set(key, {
|
|
95
|
-
offset,
|
|
96
|
-
count: size,
|
|
97
|
-
xIndex: this.xIndexer?.getIndex(),
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
this.lastOffset = index;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* @param {Map<any, object[]>} batches
|
|
105
|
-
*/
|
|
106
|
-
addBatches(batches) {
|
|
107
|
-
for (const [key, data] of batches) {
|
|
108
|
-
this.addBatch(key, data);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* @param {any} key The facet id, for example
|
|
114
|
-
* @param {object[]} data
|
|
115
|
-
*/
|
|
116
|
-
addBatch(key, data, lo = 0, hi = data.length) {
|
|
117
|
-
this.prepareXIndexer(data, lo, hi);
|
|
118
|
-
|
|
119
|
-
for (let i = lo; i < hi; i++) {
|
|
120
|
-
const d = data[i];
|
|
121
|
-
this.variableBuilder.pushFromDatum(d);
|
|
122
|
-
this.addToXIndex(d);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
this.registerBatch(key);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* @param {import("../data/flowNode").Data} data Domain, but specified using datums
|
|
130
|
-
* @param {number} [lo]
|
|
131
|
-
* @param {number} [hi]
|
|
132
|
-
*/
|
|
133
|
-
prepareXIndexer(data, lo = 0, hi = lo + data.length) {
|
|
134
|
-
const disable = () => {
|
|
135
|
-
/**
|
|
136
|
-
* @param {import("../data/flowNode").Datum} datum
|
|
137
|
-
*/
|
|
138
|
-
this.addToXIndex = (datum) => {
|
|
139
|
-
// nop
|
|
140
|
-
};
|
|
141
|
-
this.xIndexer = undefined;
|
|
142
|
-
};
|
|
143
|
-
|
|
144
|
-
if (!data.length || hi - lo < 0) {
|
|
145
|
-
disable();
|
|
146
|
-
return;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/** @param {Encoder} encoder */
|
|
150
|
-
const getContinuousEncoder = (encoder) =>
|
|
151
|
-
encoder && isContinuous(encoder.scale?.type) && encoder;
|
|
152
|
-
|
|
153
|
-
const xe = getContinuousEncoder(this.variableEncoders.x);
|
|
154
|
-
const x2e = getContinuousEncoder(this.variableEncoders.x2);
|
|
155
|
-
|
|
156
|
-
if (xe) {
|
|
157
|
-
const xa = xe.accessor;
|
|
158
|
-
const x2a = x2e ? x2e.accessor : xa;
|
|
159
|
-
|
|
160
|
-
/** @type {[number, number]} */
|
|
161
|
-
const dataDomain = [xa(data[lo]), x2a(data[hi - 1])];
|
|
162
|
-
|
|
163
|
-
// No indexer for point domains that have zero extent
|
|
164
|
-
if (dataDomain[1] > dataDomain[0]) {
|
|
165
|
-
this.xIndexer = createBinningRangeIndexer(
|
|
166
|
-
50,
|
|
167
|
-
dataDomain,
|
|
168
|
-
xa,
|
|
169
|
-
x2a
|
|
170
|
-
);
|
|
171
|
-
|
|
172
|
-
let lastVertexCount = this.variableBuilder.vertexCount;
|
|
173
|
-
|
|
174
|
-
/**
|
|
175
|
-
* @param {any} datum
|
|
176
|
-
*/
|
|
177
|
-
this.addToXIndex = (datum) => {
|
|
178
|
-
let currentVertexCount = this.variableBuilder.vertexCount;
|
|
179
|
-
this.xIndexer(datum, lastVertexCount, currentVertexCount);
|
|
180
|
-
lastVertexCount = currentVertexCount;
|
|
181
|
-
};
|
|
182
|
-
} else {
|
|
183
|
-
disable();
|
|
184
|
-
}
|
|
185
|
-
} else {
|
|
186
|
-
disable();
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
/**
|
|
191
|
-
* Add the datum to an index, which allows for efficient rendering of ranges
|
|
192
|
-
* on the x axis. Must be called after a datum has been pushed to the ArrayBuilder.
|
|
193
|
-
*
|
|
194
|
-
* @param {import("../data/flowNode").Datum} datum
|
|
195
|
-
*/
|
|
196
|
-
addToXIndex(datum) {
|
|
197
|
-
//
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
toArrays() {
|
|
201
|
-
return {
|
|
202
|
-
/** @type {Record<string, {data: number[] | Float32Array, numComponents: number, divisor?: number}>} */
|
|
203
|
-
arrays: this.variableBuilder.arrays,
|
|
204
|
-
/** Number of vertices used */
|
|
205
|
-
vertexCount: this.variableBuilder.vertexCount,
|
|
206
|
-
/** Number of vertices allocated in buffers */
|
|
207
|
-
allocatedVertices: this.allocatedVertices,
|
|
208
|
-
rangeMap: this.rangeMap,
|
|
209
|
-
};
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
export class RectVertexBuilder extends GeometryBuilder {
|
|
214
|
-
/**
|
|
215
|
-
*
|
|
216
|
-
* @param {Object} object
|
|
217
|
-
* @param {Record<string, Encoder>} object.encoders
|
|
218
|
-
* @param {string[]} object.attributes
|
|
219
|
-
* @param {number} [object.tessellationThreshold]
|
|
220
|
-
* If the rect is wider than the threshold, tessellate it into pieces
|
|
221
|
-
* @param {number[]} [object.visibleRange]
|
|
222
|
-
* @param {number} [object.numItems] Number of data items
|
|
223
|
-
*/
|
|
224
|
-
constructor({
|
|
225
|
-
encoders,
|
|
226
|
-
attributes,
|
|
227
|
-
tessellationThreshold = Infinity,
|
|
228
|
-
visibleRange = [-Infinity, Infinity],
|
|
229
|
-
numItems,
|
|
230
|
-
}) {
|
|
231
|
-
super({
|
|
232
|
-
encoders,
|
|
233
|
-
attributes,
|
|
234
|
-
numVertices:
|
|
235
|
-
tessellationThreshold == Infinity ? numItems * 6 : undefined,
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
this.visibleRange = visibleRange;
|
|
239
|
-
|
|
240
|
-
this.tessellationThreshold = tessellationThreshold || Infinity;
|
|
241
|
-
|
|
242
|
-
this.updateFrac = this.variableBuilder.createUpdater("frac", 2);
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
/**
|
|
246
|
-
*
|
|
247
|
-
* @param {any} key
|
|
248
|
-
* @param {object[]} data
|
|
249
|
-
*/
|
|
250
|
-
addBatch(key, data, lo = 0, hi = data.length) {
|
|
251
|
-
if (hi <= lo) {
|
|
252
|
-
return;
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
const e =
|
|
256
|
-
/** @type {Object.<string, import("../encoder/encoder").NumberEncoder>} */ (
|
|
257
|
-
this.encoders
|
|
258
|
-
);
|
|
259
|
-
const [lower, upper] = this.visibleRange;
|
|
260
|
-
|
|
261
|
-
/**
|
|
262
|
-
* @param {import("../encoder/encoder").Encoder} encoder
|
|
263
|
-
*/
|
|
264
|
-
const a = (encoder) => encoder.accessor || ((x) => 0);
|
|
265
|
-
|
|
266
|
-
const xAccessor = a(e.x);
|
|
267
|
-
const x2Accessor = a(e.x2);
|
|
268
|
-
|
|
269
|
-
this.prepareXIndexer(data, lo, hi);
|
|
270
|
-
|
|
271
|
-
const frac = [0, 0];
|
|
272
|
-
this.updateFrac(frac);
|
|
273
|
-
|
|
274
|
-
for (let i = lo; i < hi; i++) {
|
|
275
|
-
const d = data[i];
|
|
276
|
-
|
|
277
|
-
let x = xAccessor(d),
|
|
278
|
-
x2 = x2Accessor(d);
|
|
279
|
-
|
|
280
|
-
if (x > x2) {
|
|
281
|
-
[x, x2] = [x2, x];
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
// Skip rects that fall outside the visible range. TODO: Optimize by using binary search / interval tree
|
|
285
|
-
if (x2 < lower || x > upper) {
|
|
286
|
-
continue;
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
// Truncate to prevent tessellation of parts that are outside the viewport
|
|
290
|
-
if (x < lower) x = lower;
|
|
291
|
-
if (x2 > upper) x2 = upper;
|
|
292
|
-
|
|
293
|
-
// Start a new segment.
|
|
294
|
-
this.variableBuilder.updateFromDatum(d);
|
|
295
|
-
|
|
296
|
-
frac[0] = 0;
|
|
297
|
-
frac[1] = 0;
|
|
298
|
-
|
|
299
|
-
// Tessellate segments
|
|
300
|
-
const tileCount = 1;
|
|
301
|
-
// width < Infinity
|
|
302
|
-
// ? Math.ceil(width / this.tessellationThreshold)
|
|
303
|
-
// : 1;
|
|
304
|
-
|
|
305
|
-
// Duplicate the first vertex to produce degenerate triangles
|
|
306
|
-
this.variableBuilder.pushAll();
|
|
307
|
-
|
|
308
|
-
for (let i = 0; i <= tileCount; i++) {
|
|
309
|
-
frac[0] = i / tileCount;
|
|
310
|
-
frac[1] = 0;
|
|
311
|
-
this.variableBuilder.pushAll();
|
|
312
|
-
frac[1] = 1;
|
|
313
|
-
this.variableBuilder.pushAll();
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
// Duplicate the last vertex to produce a degenerate triangle between the segments
|
|
317
|
-
this.variableBuilder.pushAll();
|
|
318
|
-
this.addToXIndex(d);
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
this.registerBatch(key);
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
export class RuleVertexBuilder extends GeometryBuilder {
|
|
326
|
-
/**
|
|
327
|
-
*
|
|
328
|
-
* @param {Object} object
|
|
329
|
-
* @param {Record<string, Encoder>} object.encoders
|
|
330
|
-
* @param {string[]} object.attributes
|
|
331
|
-
* @param {number} [object.tessellationThreshold]
|
|
332
|
-
* If the rule is wider than the threshold, tessellate it into pieces
|
|
333
|
-
* @param {number[]} [object.visibleRange]
|
|
334
|
-
* @param {number} [object.numItems] Number of data items
|
|
335
|
-
*/
|
|
336
|
-
constructor({
|
|
337
|
-
encoders,
|
|
338
|
-
attributes,
|
|
339
|
-
tessellationThreshold = Infinity,
|
|
340
|
-
visibleRange = [-Infinity, Infinity],
|
|
341
|
-
numItems,
|
|
342
|
-
}) {
|
|
343
|
-
super({
|
|
344
|
-
encoders,
|
|
345
|
-
attributes,
|
|
346
|
-
numVertices:
|
|
347
|
-
tessellationThreshold == Infinity ? numItems * 6 : undefined,
|
|
348
|
-
});
|
|
349
|
-
|
|
350
|
-
this.visibleRange = visibleRange;
|
|
351
|
-
|
|
352
|
-
this.tessellationThreshold = tessellationThreshold || Infinity;
|
|
353
|
-
|
|
354
|
-
this.updateSide = this.variableBuilder.createUpdater("side", 1);
|
|
355
|
-
this.updatePos = this.variableBuilder.createUpdater("pos", 1);
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
/* eslint-disable complexity */
|
|
359
|
-
/**
|
|
360
|
-
*
|
|
361
|
-
* @param {any} key
|
|
362
|
-
* @param {object[]} data
|
|
363
|
-
*/
|
|
364
|
-
addBatch(key, data, lo = 0, hi = data.length) {
|
|
365
|
-
//const [lower, upper] = this.visibleRange; // TODO
|
|
366
|
-
|
|
367
|
-
this.prepareXIndexer(data, lo, hi);
|
|
368
|
-
|
|
369
|
-
for (let i = lo; i < hi; i++) {
|
|
370
|
-
const d = data[i];
|
|
371
|
-
|
|
372
|
-
// Start a new rule. Duplicate the first vertex to produce degenerate triangles
|
|
373
|
-
this.variableBuilder.updateFromDatum(d);
|
|
374
|
-
this.updateSide(-0.5);
|
|
375
|
-
this.updatePos(0);
|
|
376
|
-
this.variableBuilder.pushAll();
|
|
377
|
-
|
|
378
|
-
// Tesselate segments
|
|
379
|
-
const tileCount = 1;
|
|
380
|
-
// width < Infinity
|
|
381
|
-
// ? Math.ceil(width / this.tessellationThreshold)
|
|
382
|
-
// : 1;
|
|
383
|
-
for (let i = 0; i <= tileCount; i++) {
|
|
384
|
-
this.updatePos(i / tileCount);
|
|
385
|
-
this.updateSide(-0.5);
|
|
386
|
-
this.variableBuilder.pushAll();
|
|
387
|
-
this.updateSide(0.5);
|
|
388
|
-
this.variableBuilder.pushAll();
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
// Duplicate the last vertex to produce a degenerate triangle between the rules
|
|
392
|
-
this.variableBuilder.pushAll();
|
|
393
|
-
this.addToXIndex(d);
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
this.registerBatch(key);
|
|
397
|
-
}
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
export class PointVertexBuilder extends GeometryBuilder {
|
|
401
|
-
/**
|
|
402
|
-
*
|
|
403
|
-
* @param {object} object
|
|
404
|
-
* @param {Record<string, Encoder>} object.encoders
|
|
405
|
-
* @param {string[]} object.attributes
|
|
406
|
-
* @param {number} [object.numItems] Number of points if known, uses TypedArray
|
|
407
|
-
*/
|
|
408
|
-
constructor({ encoders, attributes, numItems = undefined }) {
|
|
409
|
-
super({
|
|
410
|
-
encoders,
|
|
411
|
-
attributes,
|
|
412
|
-
numVertices: numItems,
|
|
413
|
-
});
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
export class ConnectionVertexBuilder extends GeometryBuilder {
|
|
418
|
-
/**
|
|
419
|
-
* @param {object} object
|
|
420
|
-
* @param {Record<string, Encoder>} object.encoders
|
|
421
|
-
* @param {string[]} object.attributes
|
|
422
|
-
* @param {number} [object.numItems ] Number of points if known, uses TypedArray
|
|
423
|
-
*/
|
|
424
|
-
constructor({ encoders, attributes, numItems = undefined }) {
|
|
425
|
-
super({
|
|
426
|
-
encoders,
|
|
427
|
-
attributes,
|
|
428
|
-
numVertices: numItems,
|
|
429
|
-
});
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
toArrays() {
|
|
433
|
-
const arrays = this.variableBuilder.arrays;
|
|
434
|
-
|
|
435
|
-
// Prepare for instanced rendering
|
|
436
|
-
for (let a of Object.values(arrays)) {
|
|
437
|
-
a.divisor = 1;
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
return super.toArrays();
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
export class TextVertexBuilder extends GeometryBuilder {
|
|
445
|
-
/**
|
|
446
|
-
*
|
|
447
|
-
* @param {object} object
|
|
448
|
-
* @param {Record<string, Encoder>} object.encoders
|
|
449
|
-
* @param {string[]} object.attributes
|
|
450
|
-
* @param {import("../fonts/bmFontMetrics").BMFontMetrics} object.fontMetrics
|
|
451
|
-
* @param {Record<string, any>} object.properties
|
|
452
|
-
* @param {number} [object.numCharacters] number of characters
|
|
453
|
-
* @param {boolean} [object.logoLetters]
|
|
454
|
-
*/
|
|
455
|
-
constructor({
|
|
456
|
-
encoders,
|
|
457
|
-
attributes,
|
|
458
|
-
fontMetrics,
|
|
459
|
-
properties,
|
|
460
|
-
numCharacters = undefined,
|
|
461
|
-
}) {
|
|
462
|
-
super({
|
|
463
|
-
encoders,
|
|
464
|
-
attributes,
|
|
465
|
-
numVertices: numCharacters * 6, // six vertices per quad (character)
|
|
466
|
-
});
|
|
467
|
-
|
|
468
|
-
this.metadata = fontMetrics;
|
|
469
|
-
this.metrics = fontMetrics;
|
|
470
|
-
|
|
471
|
-
this.properties = properties;
|
|
472
|
-
|
|
473
|
-
const e = encoders;
|
|
474
|
-
|
|
475
|
-
const channelDef =
|
|
476
|
-
/** @type {import("../spec/channel").TextDef<string>} */ (
|
|
477
|
-
e.text.channelDef
|
|
478
|
-
);
|
|
479
|
-
/** @type {(value: any) => string} */
|
|
480
|
-
this.numberFormat =
|
|
481
|
-
!isValueDef(channelDef) && channelDef.format
|
|
482
|
-
? format(channelDef.format)
|
|
483
|
-
: (d) => d;
|
|
484
|
-
|
|
485
|
-
this.updateVertexCoord = this.variableBuilder.createUpdater(
|
|
486
|
-
"vertexCoord",
|
|
487
|
-
2
|
|
488
|
-
);
|
|
489
|
-
this.updateTextureCoord = this.variableBuilder.createUpdater(
|
|
490
|
-
"textureCoord",
|
|
491
|
-
2
|
|
492
|
-
);
|
|
493
|
-
|
|
494
|
-
this.updateWidth = this.variableBuilder.createUpdater("width", 1);
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
/**
|
|
498
|
-
*
|
|
499
|
-
* @param {any} key
|
|
500
|
-
* @param {object[]} data
|
|
501
|
-
*/
|
|
502
|
-
addBatch(key, data, lo = 0, hi = data.length) {
|
|
503
|
-
const align = this.properties.align || "left";
|
|
504
|
-
const logoLetters = this.properties.logoLetters ?? false;
|
|
505
|
-
|
|
506
|
-
const base = this.metadata.common.base;
|
|
507
|
-
const scale = this.metadata.common.scaleH; // Assume square textures
|
|
508
|
-
|
|
509
|
-
let baseline = -SDF_PADDING;
|
|
510
|
-
switch (this.properties.baseline) {
|
|
511
|
-
case "top":
|
|
512
|
-
baseline += this.metrics.capHeight;
|
|
513
|
-
break;
|
|
514
|
-
case "middle":
|
|
515
|
-
baseline += this.metrics.capHeight / 2;
|
|
516
|
-
break;
|
|
517
|
-
case "bottom":
|
|
518
|
-
baseline -= this.metrics.descent;
|
|
519
|
-
break;
|
|
520
|
-
default:
|
|
521
|
-
// alphabetic
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
const accessor = this.encoders.text.accessor || this.encoders.text; // accessor or constant value
|
|
525
|
-
|
|
526
|
-
const vertexCoord = [0, 0];
|
|
527
|
-
this.updateVertexCoord(vertexCoord);
|
|
528
|
-
const textureCoord = [0, 0];
|
|
529
|
-
this.updateTextureCoord(textureCoord);
|
|
530
|
-
|
|
531
|
-
this.prepareXIndexer(data, lo, hi);
|
|
532
|
-
|
|
533
|
-
for (let i = lo; i < hi; i++) {
|
|
534
|
-
const d = data[i];
|
|
535
|
-
|
|
536
|
-
const value = this.numberFormat(accessor(d));
|
|
537
|
-
const str = isString(value)
|
|
538
|
-
? value
|
|
539
|
-
: value === null
|
|
540
|
-
? ""
|
|
541
|
-
: "" + value;
|
|
542
|
-
if (str.length == 0) continue;
|
|
543
|
-
|
|
544
|
-
this.variableBuilder.updateFromDatum(d);
|
|
545
|
-
|
|
546
|
-
const textWidth = logoLetters
|
|
547
|
-
? str.length
|
|
548
|
-
: this.metrics.measureWidth(str);
|
|
549
|
-
|
|
550
|
-
this.updateWidth(textWidth); // TODO: Check if one letter space should be reduced
|
|
551
|
-
|
|
552
|
-
let x =
|
|
553
|
-
align == "right"
|
|
554
|
-
? -textWidth
|
|
555
|
-
: align == "center"
|
|
556
|
-
? -textWidth / 2
|
|
557
|
-
: 0;
|
|
558
|
-
|
|
559
|
-
if (!logoLetters) {
|
|
560
|
-
const firstChar = this.metrics.getCharByCode(str.charCodeAt(0));
|
|
561
|
-
x -= (firstChar.width - firstChar.xadvance) / base / 2; // TODO: Fix, this is a bit off..
|
|
562
|
-
}
|
|
563
|
-
|
|
564
|
-
let bottom = -0.5,
|
|
565
|
-
height = 1,
|
|
566
|
-
normalWidth = 1;
|
|
567
|
-
|
|
568
|
-
for (let i = 0; i < str.length; i++) {
|
|
569
|
-
const c = this.metrics.getCharByCode(str.charCodeAt(i));
|
|
570
|
-
|
|
571
|
-
const advance = logoLetters ? 1 : c.xadvance / base;
|
|
572
|
-
|
|
573
|
-
if (c.id == 32) {
|
|
574
|
-
x += advance;
|
|
575
|
-
continue;
|
|
576
|
-
}
|
|
577
|
-
|
|
578
|
-
if (!logoLetters) {
|
|
579
|
-
height = c.height / base;
|
|
580
|
-
bottom = -(c.height + c.yoffset + baseline) / base;
|
|
581
|
-
normalWidth = c.width / base;
|
|
582
|
-
} else {
|
|
583
|
-
normalWidth = (c.width + SDF_PADDING * 2) / c.width;
|
|
584
|
-
x = -normalWidth / 2;
|
|
585
|
-
height = (c.height + SDF_PADDING * 2) / c.height;
|
|
586
|
-
bottom = -0.5 - SDF_PADDING / c.height;
|
|
587
|
-
}
|
|
588
|
-
|
|
589
|
-
const tx = c.x;
|
|
590
|
-
const ty = c.y;
|
|
591
|
-
|
|
592
|
-
vertexCoord[0] = x;
|
|
593
|
-
vertexCoord[1] = bottom + height;
|
|
594
|
-
textureCoord[0] = tx / scale;
|
|
595
|
-
textureCoord[1] = ty / scale;
|
|
596
|
-
this.variableBuilder.pushAll();
|
|
597
|
-
|
|
598
|
-
vertexCoord[0] = x + normalWidth;
|
|
599
|
-
vertexCoord[1] = bottom + height;
|
|
600
|
-
textureCoord[0] = (tx + c.width) / scale;
|
|
601
|
-
textureCoord[1] = ty / scale;
|
|
602
|
-
this.variableBuilder.pushAll();
|
|
603
|
-
|
|
604
|
-
vertexCoord[0] = x;
|
|
605
|
-
vertexCoord[1] = bottom;
|
|
606
|
-
textureCoord[0] = tx / scale;
|
|
607
|
-
textureCoord[1] = (ty + c.height) / scale;
|
|
608
|
-
this.variableBuilder.pushAll();
|
|
609
|
-
|
|
610
|
-
vertexCoord[0] = x + normalWidth;
|
|
611
|
-
vertexCoord[1] = bottom + height;
|
|
612
|
-
textureCoord[0] = (tx + c.width) / scale;
|
|
613
|
-
textureCoord[1] = ty / scale;
|
|
614
|
-
this.variableBuilder.pushAll();
|
|
615
|
-
|
|
616
|
-
vertexCoord[0] = x;
|
|
617
|
-
vertexCoord[1] = bottom;
|
|
618
|
-
textureCoord[0] = tx / scale;
|
|
619
|
-
textureCoord[1] = (ty + c.height) / scale;
|
|
620
|
-
this.variableBuilder.pushAll();
|
|
621
|
-
|
|
622
|
-
vertexCoord[0] = x + normalWidth;
|
|
623
|
-
vertexCoord[1] = bottom;
|
|
624
|
-
textureCoord[0] = (tx + c.width) / scale;
|
|
625
|
-
textureCoord[1] = (ty + c.height) / scale;
|
|
626
|
-
this.variableBuilder.pushAll();
|
|
627
|
-
|
|
628
|
-
x += advance;
|
|
629
|
-
}
|
|
630
|
-
|
|
631
|
-
this.addToXIndex(d);
|
|
632
|
-
}
|
|
633
|
-
|
|
634
|
-
this.registerBatch(key);
|
|
635
|
-
}
|
|
636
|
-
}
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
#define PI 3.141593
|
|
2
|
-
|
|
3
|
-
uniform View {
|
|
4
|
-
/** Offset in "unit" units */
|
|
5
|
-
mediump vec2 uViewOffset;
|
|
6
|
-
mediump vec2 uViewScale;
|
|
7
|
-
/** Size of the logical viewport in pixels, i.e., the view */
|
|
8
|
-
mediump vec2 uViewportSize;
|
|
9
|
-
lowp float uDevicePixelRatio;
|
|
10
|
-
// TODO: Views with opacity less than 1.0 should be rendered into a texture
|
|
11
|
-
// that is rendered with the specified opacity.
|
|
12
|
-
lowp float uViewOpacity;
|
|
13
|
-
bool uPickingEnabled;
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Maps a coordinate on the unit scale to a normalized device coordinate.
|
|
19
|
-
* (0, 0) is at the bottom left corner.
|
|
20
|
-
*/
|
|
21
|
-
vec4 unitToNdc(vec2 coord) {
|
|
22
|
-
return vec4((coord * uViewScale + uViewOffset) * 2.0 - 1.0, 0.0, 1.0);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
vec4 unitToNdc(float x, float y) {
|
|
26
|
-
return unitToNdc(vec2(x, y));
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
vec4 pixelsToNdc(vec2 coord) {
|
|
30
|
-
return unitToNdc(coord / uViewportSize);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
vec4 pixelsToNdc(float x, float y) {
|
|
34
|
-
return pixelsToNdc(vec2(x, y));
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
float linearstep(float edge0, float edge1, float x) {
|
|
38
|
-
return clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// Fragment shader stuff ////////////////////////////////////////////////////////
|
|
42
|
-
|
|
43
|
-
// TODO: include the following only in fragment shaders
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Specialized linearstep for doing antialiasing
|
|
47
|
-
*/
|
|
48
|
-
float distanceToRatio(float d) {
|
|
49
|
-
return clamp(d * uDevicePixelRatio + 0.5, 0.0, 1.0);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
vec4 distanceToColor(float d, vec4 fill, vec4 stroke, float halfStrokeWidth) {
|
|
53
|
-
if (halfStrokeWidth > 0.0) {
|
|
54
|
-
// Distance to stroke's edge. Negative inside the stroke.
|
|
55
|
-
float sd = abs(d) - halfStrokeWidth;
|
|
56
|
-
return mix(
|
|
57
|
-
stroke,
|
|
58
|
-
d <= 0.0 ? fill : vec4(0.0),
|
|
59
|
-
distanceToRatio(sd));
|
|
60
|
-
} else {
|
|
61
|
-
return fill * distanceToRatio(-d);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
in highp vec4 vPickingColor;
|