@genome-spy/core 0.36.1 → 0.37.1
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/README.md +1 -0
- package/dist/{index.es.js → bundle/index.es.js} +2253 -2115
- package/dist/{index.js → bundle/index.js} +180 -44
- package/dist/src/data/collector.d.ts +36 -0
- package/dist/src/data/collector.d.ts.map +1 -0
- package/dist/src/data/collector.js +184 -0
- package/dist/src/data/collector.test.js +84 -0
- package/dist/src/data/dataFlow.d.ts +65 -0
- package/dist/src/data/dataFlow.d.ts.map +1 -0
- package/dist/src/data/dataFlow.js +142 -0
- package/dist/src/data/dataFlow.test.js +5 -0
- package/dist/src/data/facetNode.d.ts +17 -0
- package/dist/src/data/facetNode.d.ts.map +1 -0
- package/dist/src/data/facetNode.js +17 -0
- package/dist/src/data/flow.test.js +72 -0
- package/dist/src/data/flowNode.d.ts +136 -0
- package/dist/src/data/flowNode.d.ts.map +1 -0
- package/dist/src/data/flowNode.js +286 -0
- package/dist/src/data/flowNode.test.js +50 -0
- package/dist/src/data/flowOptimizer.d.ts +27 -0
- package/dist/src/data/flowOptimizer.d.ts.map +1 -0
- package/dist/src/data/flowOptimizer.js +133 -0
- package/dist/src/data/flowOptimizer.test.js +193 -0
- package/dist/src/data/flowTestUtils.d.ts +30 -0
- package/dist/src/data/flowTestUtils.d.ts.map +1 -0
- package/dist/src/data/flowTestUtils.js +63 -0
- package/dist/src/data/formats/fasta.d.ts +20 -0
- package/dist/src/data/formats/fasta.d.ts.map +1 -0
- package/dist/src/data/formats/fasta.js +32 -0
- package/dist/src/data/formats/fasta.test.js +27 -0
- package/dist/src/data/sources/dataSource.d.ts +12 -0
- package/dist/src/data/sources/dataSource.d.ts.map +1 -0
- package/dist/src/data/sources/dataSource.js +25 -0
- package/dist/src/data/sources/dataSourceFactory.d.ts +16 -0
- package/dist/src/data/sources/dataSourceFactory.d.ts.map +1 -0
- package/dist/src/data/sources/dataSourceFactory.js +127 -0
- package/dist/src/data/sources/dataUtils.d.ts +50 -0
- package/dist/src/data/sources/dataUtils.d.ts.map +1 -0
- package/dist/src/data/sources/dataUtils.js +83 -0
- package/dist/src/data/sources/dynamic/README.md +3 -0
- package/dist/src/data/sources/dynamic/axisGenomeSource.d.ts +13 -0
- package/dist/src/data/sources/dynamic/axisGenomeSource.d.ts.map +1 -0
- package/dist/src/data/sources/dynamic/axisGenomeSource.js +19 -0
- package/dist/src/data/sources/dynamic/axisTickSource.d.ts +18 -0
- package/dist/src/data/sources/dynamic/axisTickSource.d.ts.map +1 -0
- package/dist/src/data/sources/dynamic/axisTickSource.js +73 -0
- package/dist/src/data/sources/dynamic/bamSource.d.ts +46 -0
- package/dist/src/data/sources/dynamic/bamSource.d.ts.map +1 -0
- package/dist/src/data/sources/dynamic/bamSource.js +115 -0
- package/dist/src/data/sources/dynamic/bigBedSource.d.ts +51 -0
- package/dist/src/data/sources/dynamic/bigBedSource.d.ts.map +1 -0
- package/dist/src/data/sources/dynamic/bigBedSource.js +128 -0
- package/dist/src/data/sources/dynamic/bigWigSource.d.ts +58 -0
- package/dist/src/data/sources/dynamic/bigWigSource.d.ts.map +1 -0
- package/dist/src/data/sources/dynamic/bigWigSource.js +166 -0
- package/dist/src/data/sources/dynamic/gff3Source.d.ts +8 -0
- package/dist/src/data/sources/dynamic/gff3Source.d.ts.map +1 -0
- package/dist/src/data/sources/dynamic/gff3Source.js +19 -0
- package/dist/src/data/sources/dynamic/indexedFastaSource.d.ts +30 -0
- package/dist/src/data/sources/dynamic/indexedFastaSource.d.ts.map +1 -0
- package/dist/src/data/sources/dynamic/indexedFastaSource.js +86 -0
- package/dist/src/data/sources/dynamic/singleAxisLazySource.d.ts +42 -0
- package/dist/src/data/sources/dynamic/singleAxisLazySource.d.ts.map +1 -0
- package/dist/src/data/sources/dynamic/singleAxisLazySource.js +129 -0
- package/dist/src/data/sources/dynamic/tabixSource.d.ts +54 -0
- package/dist/src/data/sources/dynamic/tabixSource.d.ts.map +1 -0
- package/dist/src/data/sources/dynamic/tabixSource.js +140 -0
- package/dist/src/data/sources/dynamic/windowedMixin.d.ts +32 -0
- package/dist/src/data/sources/dynamic/windowedMixin.d.ts.map +1 -0
- package/dist/src/data/sources/dynamic/windowedMixin.js +53 -0
- package/dist/src/data/sources/inlineSource.d.ts +16 -0
- package/dist/src/data/sources/inlineSource.d.ts.map +1 -0
- package/dist/src/data/sources/inlineSource.js +68 -0
- package/dist/src/data/sources/inlineSource.test.js +56 -0
- package/dist/src/data/sources/namedSource.d.ts +25 -0
- package/dist/src/data/sources/namedSource.d.ts.map +1 -0
- package/dist/src/data/sources/namedSource.js +80 -0
- package/dist/src/data/sources/sequenceSource.d.ts +17 -0
- package/dist/src/data/sources/sequenceSource.d.ts.map +1 -0
- package/dist/src/data/sources/sequenceSource.js +47 -0
- package/dist/src/data/sources/sequenceSource.test.js +46 -0
- package/dist/src/data/sources/urlSource.d.ts +16 -0
- package/dist/src/data/sources/urlSource.d.ts.map +1 -0
- package/dist/src/data/sources/urlSource.js +74 -0
- package/dist/src/data/transforms/aggregate.d.ts +18 -0
- package/dist/src/data/transforms/aggregate.d.ts.map +1 -0
- package/dist/src/data/transforms/aggregate.js +67 -0
- package/dist/src/data/transforms/clone.d.ts +15 -0
- package/dist/src/data/transforms/clone.d.ts.map +1 -0
- package/dist/src/data/transforms/clone.js +40 -0
- package/dist/src/data/transforms/clone.test.js +11 -0
- package/dist/src/data/transforms/coverage.d.ts +30 -0
- package/dist/src/data/transforms/coverage.d.ts.map +1 -0
- package/dist/src/data/transforms/coverage.js +183 -0
- package/dist/src/data/transforms/coverage.test.js +123 -0
- package/dist/src/data/transforms/filter.d.ts +12 -0
- package/dist/src/data/transforms/filter.d.ts.map +1 -0
- package/dist/src/data/transforms/filter.js +33 -0
- package/dist/src/data/transforms/filter.test.js +18 -0
- package/dist/src/data/transforms/filterScoredLabels.d.ts +29 -0
- package/dist/src/data/transforms/filterScoredLabels.d.ts.map +1 -0
- package/dist/src/data/transforms/filterScoredLabels.js +134 -0
- package/dist/src/data/transforms/flatten.d.ts +10 -0
- package/dist/src/data/transforms/flatten.d.ts.map +1 -0
- package/dist/src/data/transforms/flatten.js +68 -0
- package/dist/src/data/transforms/flatten.test.js +93 -0
- package/dist/src/data/transforms/flattenCompressedExons.d.ts +19 -0
- package/dist/src/data/transforms/flattenCompressedExons.d.ts.map +1 -0
- package/dist/src/data/transforms/flattenCompressedExons.js +53 -0
- package/dist/src/data/transforms/flattenDelimited.d.ts +10 -0
- package/dist/src/data/transforms/flattenDelimited.d.ts.map +1 -0
- package/dist/src/data/transforms/flattenDelimited.js +66 -0
- package/dist/src/data/transforms/flattenDelimited.test.js +87 -0
- package/dist/src/data/transforms/flattenSequence.d.ts +11 -0
- package/dist/src/data/transforms/flattenSequence.d.ts.map +1 -0
- package/dist/src/data/transforms/flattenSequence.js +35 -0
- package/dist/src/data/transforms/flattenSequence.test.js +34 -0
- package/dist/src/data/transforms/formula.d.ts +13 -0
- package/dist/src/data/transforms/formula.d.ts.map +1 -0
- package/dist/src/data/transforms/formula.js +35 -0
- package/dist/src/data/transforms/formula.test.js +19 -0
- package/dist/src/data/transforms/identifier.d.ts +40 -0
- package/dist/src/data/transforms/identifier.d.ts.map +1 -0
- package/dist/src/data/transforms/identifier.js +106 -0
- package/dist/src/data/transforms/identifier.test.js +83 -0
- package/dist/src/data/transforms/linearizeGenomicCoordinate.d.ts +10 -0
- package/dist/src/data/transforms/linearizeGenomicCoordinate.d.ts.map +1 -0
- package/dist/src/data/transforms/linearizeGenomicCoordinate.js +97 -0
- package/dist/src/data/transforms/measureText.d.ts +18 -0
- package/dist/src/data/transforms/measureText.d.ts.map +1 -0
- package/dist/src/data/transforms/measureText.js +42 -0
- package/dist/src/data/transforms/pileup.d.ts +10 -0
- package/dist/src/data/transforms/pileup.d.ts.map +1 -0
- package/dist/src/data/transforms/pileup.js +126 -0
- package/dist/src/data/transforms/pileup.test.js +70 -0
- package/dist/src/data/transforms/project.d.ts +13 -0
- package/dist/src/data/transforms/project.d.ts.map +1 -0
- package/dist/src/data/transforms/project.js +38 -0
- package/dist/src/data/transforms/project.test.js +32 -0
- package/dist/src/data/transforms/regexExtract.d.ts +13 -0
- package/dist/src/data/transforms/regexExtract.d.ts.map +1 -0
- package/dist/src/data/transforms/regexExtract.js +57 -0
- package/dist/src/data/transforms/regexExtract.test.js +67 -0
- package/dist/src/data/transforms/regexFold.d.ts +14 -0
- package/dist/src/data/transforms/regexFold.d.ts.map +1 -0
- package/dist/src/data/transforms/regexFold.js +139 -0
- package/dist/src/data/transforms/regexFold.test.js +160 -0
- package/dist/src/data/transforms/sample.d.ts +42 -0
- package/dist/src/data/transforms/sample.d.ts.map +1 -0
- package/dist/src/data/transforms/sample.js +99 -0
- package/dist/src/data/transforms/sample.test.js +38 -0
- package/dist/src/data/transforms/stack.d.ts +11 -0
- package/dist/src/data/transforms/stack.d.ts.map +1 -0
- package/dist/src/data/transforms/stack.js +134 -0
- package/dist/src/data/transforms/stack.test.js +91 -0
- package/dist/src/data/transforms/transformFactory.d.ts +12 -0
- package/dist/src/data/transforms/transformFactory.d.ts.map +1 -0
- package/dist/src/data/transforms/transformFactory.js +59 -0
- package/dist/src/encoder/accessor.d.ts +15 -0
- package/dist/src/encoder/accessor.d.ts.map +1 -0
- package/dist/src/encoder/accessor.js +76 -0
- package/dist/src/encoder/accessor.test.js +47 -0
- package/dist/src/encoder/encoder.d.ts +144 -0
- package/dist/src/encoder/encoder.d.ts.map +1 -0
- package/dist/src/encoder/encoder.js +400 -0
- package/dist/src/encoder/encoder.test.js +98 -0
- package/dist/src/fonts/Lato-Regular.json +1267 -0
- package/dist/src/fonts/Lato-Regular.png +0 -0
- package/dist/src/fonts/OFL.txt +93 -0
- package/dist/src/fonts/README.md +3 -0
- package/dist/src/fonts/bmFontManager.d.ts +182 -0
- package/dist/src/fonts/bmFontManager.d.ts.map +1 -0
- package/dist/src/fonts/bmFontManager.js +359 -0
- package/dist/src/fonts/bmFontMetrics.d.ts +45 -0
- package/dist/src/fonts/bmFontMetrics.d.ts.map +1 -0
- package/dist/src/fonts/bmFontMetrics.js +108 -0
- package/dist/src/genome/genome.d.ts +172 -0
- package/dist/src/genome/genome.d.ts.map +1 -0
- package/dist/src/genome/genome.js +379 -0
- package/dist/src/genome/genome.test.js +226 -0
- package/dist/src/genome/genomeStore.d.ts +20 -0
- package/dist/src/genome/genomeStore.d.ts.map +1 -0
- package/dist/src/genome/genomeStore.js +54 -0
- package/dist/src/genome/locusFormat.d.ts +14 -0
- package/dist/src/genome/locusFormat.d.ts.map +1 -0
- package/dist/src/genome/locusFormat.js +37 -0
- package/dist/src/genome/scaleIndex.d.ts +6 -0
- package/dist/src/genome/scaleIndex.d.ts.map +1 -0
- package/dist/src/genome/scaleIndex.js +165 -0
- package/dist/src/genome/scaleIndex.test.js +78 -0
- package/dist/src/genome/scaleLocus.d.ts +3 -0
- package/dist/src/genome/scaleLocus.d.ts.map +1 -0
- package/dist/src/genome/scaleLocus.js +101 -0
- package/dist/src/genome/scaleLocus.test.js +4 -0
- package/dist/src/genomeSpy.d.ts +141 -0
- package/dist/src/genomeSpy.d.ts.map +1 -0
- package/dist/src/genomeSpy.js +788 -0
- package/dist/src/gl/arrayBuilder.d.ts +71 -0
- package/dist/src/gl/arrayBuilder.d.ts.map +1 -0
- package/dist/src/gl/arrayBuilder.js +199 -0
- package/dist/src/gl/dataToVertices.d.ts +194 -0
- package/dist/src/gl/dataToVertices.d.ts.map +1 -0
- package/dist/src/gl/dataToVertices.js +639 -0
- package/dist/src/gl/includes/common.glsl.js +2 -0
- package/dist/src/gl/includes/picking.fragment.glsl.js +2 -0
- package/dist/src/gl/includes/picking.vertex.glsl.js +2 -0
- package/dist/src/gl/includes/sampleFacet.glsl.js +2 -0
- package/dist/src/gl/includes/scales.glsl.js +2 -0
- package/dist/src/gl/link.fragment.glsl.js +2 -0
- package/dist/src/gl/link.vertex.glsl.js +2 -0
- package/dist/src/gl/point.fragment.glsl.js +2 -0
- package/dist/src/gl/point.vertex.glsl.js +2 -0
- package/dist/src/gl/rect.fragment.glsl.js +2 -0
- package/dist/src/gl/rect.vertex.glsl.js +2 -0
- package/dist/src/gl/rule.fragment.glsl.js +2 -0
- package/dist/src/gl/rule.vertex.glsl.js +2 -0
- package/dist/src/gl/text.fragment.glsl.js +2 -0
- package/dist/src/gl/text.vertex.glsl.js +2 -0
- package/dist/src/gl/webGLHelper.d.ts +118 -0
- package/dist/src/gl/webGLHelper.d.ts.map +1 -0
- package/dist/src/gl/webGLHelper.js +513 -0
- package/dist/src/img/bowtie.svg +1 -0
- package/dist/src/img/genomespy-favicon.svg +34 -0
- package/dist/src/index.d.ts +15 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.html +11 -0
- package/dist/src/index.js +129 -0
- package/dist/src/marks/link.d.ts +11 -0
- package/dist/src/marks/link.d.ts.map +1 -0
- package/dist/src/marks/link.js +175 -0
- package/dist/src/marks/mark.d.ts +226 -0
- package/dist/src/marks/mark.d.ts.map +1 -0
- package/dist/src/marks/mark.js +1004 -0
- package/dist/src/marks/markUtils.d.ts +23 -0
- package/dist/src/marks/markUtils.d.ts.map +1 -0
- package/dist/src/marks/markUtils.js +125 -0
- package/dist/src/marks/pointMark.d.ts +11 -0
- package/dist/src/marks/pointMark.d.ts.map +1 -0
- package/dist/src/marks/pointMark.js +251 -0
- package/dist/src/marks/rectMark.d.ts +18 -0
- package/dist/src/marks/rectMark.d.ts.map +1 -0
- package/dist/src/marks/rectMark.js +255 -0
- package/dist/src/marks/rule.d.ts +6 -0
- package/dist/src/marks/rule.d.ts.map +1 -0
- package/dist/src/marks/rule.js +250 -0
- package/dist/src/marks/text.d.ts +13 -0
- package/dist/src/marks/text.d.ts.map +1 -0
- package/dist/src/marks/text.js +279 -0
- package/dist/src/scale/colorUtils.d.ts +34 -0
- package/dist/src/scale/colorUtils.d.ts.map +1 -0
- package/dist/src/scale/colorUtils.js +184 -0
- package/dist/src/scale/glslScaleGenerator.d.ts +45 -0
- package/dist/src/scale/glslScaleGenerator.d.ts.map +1 -0
- package/dist/src/scale/glslScaleGenerator.js +506 -0
- package/dist/src/scale/scale.d.ts +10 -0
- package/dist/src/scale/scale.d.ts.map +1 -0
- package/dist/src/scale/scale.js +456 -0
- package/dist/src/scale/scale.test.js +324 -0
- package/dist/src/scale/ticks.d.ts +47 -0
- package/dist/src/scale/ticks.d.ts.map +1 -0
- package/dist/src/scale/ticks.js +203 -0
- package/dist/src/scale/ticks.test.js +40 -0
- package/dist/src/singlePageApp.d.ts +2 -0
- package/dist/src/singlePageApp.d.ts.map +1 -0
- package/dist/src/singlePageApp.js +13 -0
- package/dist/src/spec/axis.d.ts +402 -0
- package/dist/src/spec/channel.d.ts +440 -0
- package/dist/src/spec/data.d.ts +370 -0
- package/dist/src/spec/font.d.ts +15 -0
- package/dist/src/spec/genome.d.ts +35 -0
- package/dist/src/spec/mark.d.ts +435 -0
- package/dist/src/spec/root.d.ts +22 -0
- package/dist/src/spec/sampleView.d.ts +185 -0
- package/dist/src/spec/scale.d.ts +273 -0
- package/dist/src/spec/title.d.ts +102 -0
- package/dist/src/spec/tooltip.d.ts +9 -0
- package/dist/src/spec/transform.d.ts +504 -0
- package/dist/src/spec/view.d.ts +214 -0
- package/dist/src/styles/genome-spy.css.d.ts +3 -0
- package/dist/src/styles/genome-spy.css.d.ts.map +1 -0
- package/dist/src/styles/genome-spy.css.js +114 -0
- package/dist/src/styles/genome-spy.scss +153 -0
- package/dist/src/tooltip/dataTooltipHandler.d.ts +2 -0
- package/dist/src/tooltip/dataTooltipHandler.d.ts.map +1 -0
- package/dist/src/tooltip/dataTooltipHandler.js +64 -0
- package/dist/src/tooltip/refseqGeneTooltipHandler.d.ts +2 -0
- package/dist/src/tooltip/refseqGeneTooltipHandler.d.ts.map +1 -0
- package/dist/src/tooltip/refseqGeneTooltipHandler.js +78 -0
- package/dist/src/tooltip/tooltipHandler.d.ts +9 -0
- package/dist/src/tooltip/tooltipHandler.d.ts.map +1 -0
- package/dist/src/tooltip/tooltipHandler.ts +12 -0
- package/dist/src/types/bmFont.d.ts +58 -0
- package/dist/src/types/embedApi.d.ts +67 -0
- package/dist/src/types/encoder.d.ts +84 -0
- package/dist/src/types/flowBatch.d.ts +40 -0
- package/dist/src/types/rendering.d.ts +65 -0
- package/dist/src/types/scaleResolutionApi.d.ts +40 -0
- package/dist/src/types/viewContext.d.ts +85 -0
- package/dist/src/utils/addBaseUrl.d.ts +6 -0
- package/dist/src/utils/addBaseUrl.d.ts.map +1 -0
- package/dist/src/utils/addBaseUrl.js +19 -0
- package/dist/src/utils/addBaseUrl.test.js +22 -0
- package/dist/src/utils/animator.d.ts +41 -0
- package/dist/src/utils/animator.d.ts.map +1 -0
- package/dist/src/utils/animator.js +83 -0
- package/dist/src/utils/arrayUtils.d.ts +34 -0
- package/dist/src/utils/arrayUtils.d.ts.map +1 -0
- package/dist/src/utils/arrayUtils.js +61 -0
- package/dist/src/utils/binnedIndex.d.ts +23 -0
- package/dist/src/utils/binnedIndex.d.ts.map +1 -0
- package/dist/src/utils/binnedIndex.js +167 -0
- package/dist/src/utils/binnedIndex.test.js +155 -0
- package/dist/src/utils/clamp.d.ts +7 -0
- package/dist/src/utils/clamp.d.ts.map +1 -0
- package/dist/src/utils/clamp.js +8 -0
- package/dist/src/utils/cloner.d.ts +16 -0
- package/dist/src/utils/cloner.d.ts.map +1 -0
- package/dist/src/utils/cloner.js +34 -0
- package/dist/src/utils/cloner.test.js +24 -0
- package/dist/src/utils/coalesce.d.ts +6 -0
- package/dist/src/utils/coalesce.d.ts.map +1 -0
- package/dist/src/utils/coalesce.js +11 -0
- package/dist/src/utils/coalesce.test.js +16 -0
- package/dist/src/utils/concatIterables.d.ts +8 -0
- package/dist/src/utils/concatIterables.d.ts.map +1 -0
- package/dist/src/utils/concatIterables.js +26 -0
- package/dist/src/utils/concatIterables.test.js +8 -0
- package/dist/src/utils/debounce.d.ts +8 -0
- package/dist/src/utils/debounce.d.ts.map +1 -0
- package/dist/src/utils/debounce.js +37 -0
- package/dist/src/utils/domainArray.d.ts +61 -0
- package/dist/src/utils/domainArray.d.ts.map +1 -0
- package/dist/src/utils/domainArray.js +216 -0
- package/dist/src/utils/domainArray.test.js +130 -0
- package/dist/src/utils/eerp.d.ts +12 -0
- package/dist/src/utils/eerp.d.ts.map +1 -0
- package/dist/src/utils/eerp.js +13 -0
- package/dist/src/utils/expression.d.ts +9 -0
- package/dist/src/utils/expression.d.ts.map +1 -0
- package/dist/src/utils/expression.js +32 -0
- package/dist/src/utils/field.d.ts +17 -0
- package/dist/src/utils/field.d.ts.map +1 -0
- package/dist/src/utils/field.js +28 -0
- package/dist/src/utils/formatObject.d.ts +7 -0
- package/dist/src/utils/formatObject.d.ts.map +1 -0
- package/dist/src/utils/formatObject.js +37 -0
- package/dist/src/utils/indexer.d.ts +16 -0
- package/dist/src/utils/indexer.d.ts.map +1 -0
- package/dist/src/utils/indexer.js +43 -0
- package/dist/src/utils/indexer.test.js +47 -0
- package/dist/src/utils/inertia.d.ts +42 -0
- package/dist/src/utils/inertia.d.ts.map +1 -0
- package/dist/src/utils/inertia.js +124 -0
- package/dist/src/utils/interactionEvent.d.ts +26 -0
- package/dist/src/utils/interactionEvent.d.ts.map +1 -0
- package/dist/src/utils/interactionEvent.js +33 -0
- package/dist/src/utils/iterateNestedMaps.d.ts +11 -0
- package/dist/src/utils/iterateNestedMaps.d.ts.map +1 -0
- package/dist/src/utils/iterateNestedMaps.js +21 -0
- package/dist/src/utils/iterateNestedMaps.test.js +33 -0
- package/dist/src/utils/kWayMerge.d.ts +9 -0
- package/dist/src/utils/kWayMerge.d.ts.map +1 -0
- package/dist/src/utils/kWayMerge.js +42 -0
- package/dist/src/utils/kWayMerge.test.js +26 -0
- package/dist/src/utils/layout/flexLayout.d.ts +182 -0
- package/dist/src/utils/layout/flexLayout.d.ts.map +1 -0
- package/dist/src/utils/layout/flexLayout.js +381 -0
- package/dist/src/utils/layout/flexLayout.test.js +323 -0
- package/dist/src/utils/layout/grid.d.ts +29 -0
- package/dist/src/utils/layout/grid.d.ts.map +1 -0
- package/dist/src/utils/layout/grid.js +95 -0
- package/dist/src/utils/layout/grid.test.js +71 -0
- package/dist/src/utils/layout/padding.d.ts +83 -0
- package/dist/src/utils/layout/padding.d.ts.map +1 -0
- package/dist/src/utils/layout/padding.js +155 -0
- package/dist/src/utils/layout/point.d.ts +16 -0
- package/dist/src/utils/layout/point.d.ts.map +1 -0
- package/dist/src/utils/layout/point.js +23 -0
- package/dist/src/utils/layout/rectangle.d.ts +142 -0
- package/dist/src/utils/layout/rectangle.d.ts.map +1 -0
- package/dist/src/utils/layout/rectangle.js +296 -0
- package/dist/src/utils/layout/rectangle.test.js +172 -0
- package/dist/src/utils/mergeObjects.d.ts +15 -0
- package/dist/src/utils/mergeObjects.d.ts.map +1 -0
- package/dist/src/utils/mergeObjects.js +99 -0
- package/dist/src/utils/mergeObjects.test.js +42 -0
- package/dist/src/utils/numberExtractor.d.ts +9 -0
- package/dist/src/utils/numberExtractor.d.ts.map +1 -0
- package/dist/src/utils/numberExtractor.js +24 -0
- package/dist/src/utils/numberExtractor.test.js +6 -0
- package/dist/src/utils/point.d.ts +9 -0
- package/dist/src/utils/point.d.ts.map +1 -0
- package/dist/src/utils/point.js +14 -0
- package/dist/src/utils/propertyCacher.d.ts +30 -0
- package/dist/src/utils/propertyCacher.d.ts.map +1 -0
- package/dist/src/utils/propertyCacher.js +70 -0
- package/dist/src/utils/propertyCacher.test.js +85 -0
- package/dist/src/utils/propertyCoalescer.d.ts +15 -0
- package/dist/src/utils/propertyCoalescer.d.ts.map +1 -0
- package/dist/src/utils/propertyCoalescer.js +42 -0
- package/dist/src/utils/propertyCoalescer.test.js +22 -0
- package/dist/src/utils/reservationMap.d.ts +42 -0
- package/dist/src/utils/reservationMap.d.ts.map +1 -0
- package/dist/src/utils/reservationMap.js +103 -0
- package/dist/src/utils/reservationMap.test.js +20 -0
- package/dist/src/utils/scaleNull.d.ts +13 -0
- package/dist/src/utils/scaleNull.d.ts.map +1 -0
- package/dist/src/utils/scaleNull.js +21 -0
- package/dist/src/utils/setOperations.d.ts +31 -0
- package/dist/src/utils/setOperations.d.ts.map +1 -0
- package/dist/src/utils/setOperations.js +75 -0
- package/dist/src/utils/smoothstep.d.ts +7 -0
- package/dist/src/utils/smoothstep.d.ts.map +1 -0
- package/dist/src/utils/smoothstep.js +10 -0
- package/dist/src/utils/throttle.d.ts +8 -0
- package/dist/src/utils/throttle.d.ts.map +1 -0
- package/dist/src/utils/throttle.js +34 -0
- package/dist/src/utils/topK.d.ts +22 -0
- package/dist/src/utils/topK.d.ts.map +1 -0
- package/dist/src/utils/topK.js +76 -0
- package/dist/src/utils/topK.test.js +64 -0
- package/dist/src/utils/transition.d.ts +44 -0
- package/dist/src/utils/transition.d.ts.map +1 -0
- package/dist/src/utils/transition.js +74 -0
- package/dist/src/utils/trees.d.ts +56 -0
- package/dist/src/utils/trees.d.ts.map +1 -0
- package/dist/src/utils/trees.js +92 -0
- package/dist/src/utils/trees.test.js +130 -0
- package/dist/src/utils/ui/tooltip.d.ts +50 -0
- package/dist/src/utils/ui/tooltip.d.ts.map +1 -0
- package/dist/src/utils/ui/tooltip.js +189 -0
- package/dist/src/utils/url.d.ts +9 -0
- package/dist/src/utils/url.d.ts.map +1 -0
- package/dist/src/utils/url.js +22 -0
- package/dist/src/utils/variableTools.d.ts +14 -0
- package/dist/src/utils/variableTools.d.ts.map +1 -0
- package/dist/src/utils/variableTools.js +24 -0
- package/dist/src/utils/variableTools.test.js +13 -0
- package/dist/src/view/axisGridView.d.ts +39 -0
- package/dist/src/view/axisGridView.d.ts.map +1 -0
- package/dist/src/view/axisGridView.js +246 -0
- package/dist/src/view/axisResolution.d.ts +24 -0
- package/dist/src/view/axisResolution.d.ts.map +1 -0
- package/dist/src/view/axisResolution.js +141 -0
- package/dist/src/view/axisResolution.test.js +201 -0
- package/dist/src/view/axisView.d.ts +49 -0
- package/dist/src/view/axisView.d.ts.map +1 -0
- package/dist/src/view/axisView.js +629 -0
- package/dist/src/view/concatView.d.ts +16 -0
- package/dist/src/view/concatView.d.ts.map +1 -0
- package/dist/src/view/concatView.js +84 -0
- package/dist/src/view/containerView.d.ts +43 -0
- package/dist/src/view/containerView.d.ts.map +1 -0
- package/dist/src/view/containerView.js +137 -0
- package/dist/src/view/facetView.d.ts +71 -0
- package/dist/src/view/facetView.d.ts.map +1 -0
- package/dist/src/view/facetView.js +492 -0
- package/dist/src/view/flowBuilder.d.ts +37 -0
- package/dist/src/view/flowBuilder.d.ts.map +1 -0
- package/dist/src/view/flowBuilder.js +383 -0
- package/dist/src/view/flowBuilder.test.js +125 -0
- package/dist/src/view/gridView.d.ts +111 -0
- package/dist/src/view/gridView.d.ts.map +1 -0
- package/dist/src/view/gridView.js +1086 -0
- package/dist/src/view/implicitRootView.d.ts +9 -0
- package/dist/src/view/implicitRootView.d.ts.map +1 -0
- package/dist/src/view/implicitRootView.js +23 -0
- package/dist/src/view/importView.d.ts +17 -0
- package/dist/src/view/importView.d.ts.map +1 -0
- package/dist/src/view/importView.js +22 -0
- package/dist/src/view/layerView.d.ts +25 -0
- package/dist/src/view/layerView.d.ts.map +1 -0
- package/dist/src/view/layerView.js +77 -0
- package/dist/src/view/renderingContext/bufferedViewRenderingContext.d.ts +30 -0
- package/dist/src/view/renderingContext/bufferedViewRenderingContext.d.ts.map +1 -0
- package/dist/src/view/renderingContext/bufferedViewRenderingContext.js +175 -0
- package/dist/src/view/renderingContext/compositeViewRenderingContext.d.ts +14 -0
- package/dist/src/view/renderingContext/compositeViewRenderingContext.d.ts.map +1 -0
- package/dist/src/view/renderingContext/compositeViewRenderingContext.js +51 -0
- package/dist/src/view/renderingContext/debuggingViewRenderingContext.d.ts +51 -0
- package/dist/src/view/renderingContext/debuggingViewRenderingContext.d.ts.map +1 -0
- package/dist/src/view/renderingContext/debuggingViewRenderingContext.js +94 -0
- package/dist/src/view/renderingContext/layoutRecorderViewRenderingContext.d.ts +60 -0
- package/dist/src/view/renderingContext/layoutRecorderViewRenderingContext.d.ts.map +1 -0
- package/dist/src/view/renderingContext/layoutRecorderViewRenderingContext.js +128 -0
- package/dist/src/view/renderingContext/simpleViewRenderingContext.d.ts +19 -0
- package/dist/src/view/renderingContext/simpleViewRenderingContext.d.ts.map +1 -0
- package/dist/src/view/renderingContext/simpleViewRenderingContext.js +64 -0
- package/dist/src/view/renderingContext/svgViewRenderingContext.d.ts +22 -0
- package/dist/src/view/renderingContext/svgViewRenderingContext.d.ts.map +1 -0
- package/dist/src/view/renderingContext/svgViewRenderingContext.js +125 -0
- package/dist/src/view/renderingContext/viewRenderingContext.d.ts +33 -0
- package/dist/src/view/renderingContext/viewRenderingContext.d.ts.map +1 -0
- package/dist/src/view/renderingContext/viewRenderingContext.js +41 -0
- package/dist/src/view/scaleResolution.d.ts +170 -0
- package/dist/src/view/scaleResolution.d.ts.map +1 -0
- package/dist/src/view/scaleResolution.js +874 -0
- package/dist/src/view/scaleResolution.test.js +658 -0
- package/dist/src/view/testUtils.d.ts +30 -0
- package/dist/src/view/testUtils.d.ts.map +1 -0
- package/dist/src/view/testUtils.js +101 -0
- package/dist/src/view/title.d.ts +6 -0
- package/dist/src/view/title.d.ts.map +1 -0
- package/dist/src/view/title.js +165 -0
- package/dist/src/view/unitView.d.ts +93 -0
- package/dist/src/view/unitView.d.ts.map +1 -0
- package/dist/src/view/unitView.js +345 -0
- package/dist/src/view/view.d.ts +291 -0
- package/dist/src/view/view.d.ts.map +1 -0
- package/dist/src/view/view.js +691 -0
- package/dist/src/view/view.test.js +214 -0
- package/dist/src/view/viewFactory.d.ts +76 -0
- package/dist/src/view/viewFactory.d.ts.map +1 -0
- package/dist/src/view/viewFactory.js +178 -0
- package/dist/src/view/viewFactory.test.js +17 -0
- package/dist/src/view/viewUtils.d.ts +90 -0
- package/dist/src/view/viewUtils.d.ts.map +1 -0
- package/dist/src/view/viewUtils.js +326 -0
- package/dist/src/view/zoom.d.ts +23 -0
- package/dist/src/view/zoom.d.ts.map +1 -0
- package/dist/src/view/zoom.js +89 -0
- package/package.json +17 -12
- package/dist/style.css +0 -1
|
@@ -0,0 +1,1004 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createBufferInfoFromArrays,
|
|
3
|
+
createProgramInfoFromProgram,
|
|
4
|
+
createUniformBlockInfo,
|
|
5
|
+
createVertexArrayInfo,
|
|
6
|
+
setAttribInfoBufferFromArray,
|
|
7
|
+
setBlockUniforms,
|
|
8
|
+
setUniformBlock,
|
|
9
|
+
setUniforms,
|
|
10
|
+
} from "twgl.js";
|
|
11
|
+
import { isContinuous, isDiscrete } from "vega-scale";
|
|
12
|
+
import createEncoders, {
|
|
13
|
+
isChannelDefWithScale,
|
|
14
|
+
isChannelWithScale,
|
|
15
|
+
isDatumDef,
|
|
16
|
+
isValueDef,
|
|
17
|
+
} from "../encoder/encoder";
|
|
18
|
+
import {
|
|
19
|
+
DOMAIN_PREFIX,
|
|
20
|
+
generateValueGlsl,
|
|
21
|
+
generateScaleGlsl,
|
|
22
|
+
RANGE_TEXTURE_PREFIX,
|
|
23
|
+
ATTRIBUTE_PREFIX,
|
|
24
|
+
isHighPrecisionScale,
|
|
25
|
+
toHighPrecisionDomainUniform,
|
|
26
|
+
splitHighPrecision,
|
|
27
|
+
} from "../scale/glslScaleGenerator";
|
|
28
|
+
import GLSL_COMMON from "../gl/includes/common.glsl.js";
|
|
29
|
+
import GLSL_SCALES from "../gl/includes/scales.glsl.js";
|
|
30
|
+
import GLSL_SAMPLE_FACET from "../gl/includes/sampleFacet.glsl.js";
|
|
31
|
+
import GLSL_PICKING_VERTEX from "../gl/includes/picking.vertex.glsl.js";
|
|
32
|
+
import GLSL_PICKING_FRAGMENT from "../gl/includes/picking.fragment.glsl.js";
|
|
33
|
+
import { getCachedOrCall } from "../utils/propertyCacher";
|
|
34
|
+
import { createProgram } from "../gl/webGLHelper";
|
|
35
|
+
import coalesceProperties from "../utils/propertyCoalescer";
|
|
36
|
+
import { isScalar } from "../utils/variableTools";
|
|
37
|
+
import { InternMap } from "internmap";
|
|
38
|
+
import scaleNull from "../utils/scaleNull";
|
|
39
|
+
|
|
40
|
+
export const SAMPLE_FACET_UNIFORM = "SAMPLE_FACET_UNIFORM";
|
|
41
|
+
export const SAMPLE_FACET_TEXTURE = "SAMPLE_FACET_TEXTURE";
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
*
|
|
45
|
+
* @typedef {import("../types/rendering").RenderingOptions} RenderingOptions
|
|
46
|
+
* @typedef {object} _MarkRenderingOptions
|
|
47
|
+
* @prop {boolean} [skipViewportSetup] Don't configure viewport. Allows for
|
|
48
|
+
* optimized faceted rendering
|
|
49
|
+
* @typedef {RenderingOptions & _MarkRenderingOptions} MarkRenderingOptions
|
|
50
|
+
*
|
|
51
|
+
* @callback DrawFunction
|
|
52
|
+
* @param {number} offset
|
|
53
|
+
* @param {number} count
|
|
54
|
+
*
|
|
55
|
+
*/
|
|
56
|
+
export default class Mark {
|
|
57
|
+
/**
|
|
58
|
+
* @typedef {import("../spec/mark").MarkConfig} MarkConfig
|
|
59
|
+
* @typedef {import("../spec/channel").Channel} Channel
|
|
60
|
+
* @typedef {import("../spec/channel").Encoding} Encoding
|
|
61
|
+
* @typedef {import("../spec/channel").ValueDef} ValueDef
|
|
62
|
+
*/
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* @param {import("../view/unitView").default} unitView
|
|
66
|
+
*/
|
|
67
|
+
constructor(unitView) {
|
|
68
|
+
this.unitView = unitView;
|
|
69
|
+
|
|
70
|
+
/** @type {Record<string, import("../types/encoder").Encoder>} */
|
|
71
|
+
this.encoders = undefined;
|
|
72
|
+
|
|
73
|
+
// TODO: Consolidate the following webgl stuff into a single object
|
|
74
|
+
|
|
75
|
+
/** @type {import("twgl.js").BufferInfo & { allocatedVertices?: number }} WebGL buffers */
|
|
76
|
+
this.bufferInfo = undefined;
|
|
77
|
+
|
|
78
|
+
/** @type {import("twgl.js").ProgramInfo} WebGL buffers */
|
|
79
|
+
this.programInfo = undefined;
|
|
80
|
+
|
|
81
|
+
/** @type {import("twgl.js").VertexArrayInfo} WebGL buffers */
|
|
82
|
+
this.vertexArrayInfo = undefined;
|
|
83
|
+
|
|
84
|
+
/** @type {import("twgl.js").UniformBlockInfo} WebGL buffers */
|
|
85
|
+
this.domainUniformInfo = undefined;
|
|
86
|
+
|
|
87
|
+
/** @type {import("twgl.js").UniformBlockInfo} WebGL buffers */
|
|
88
|
+
this.viewUniformInfo = undefined;
|
|
89
|
+
|
|
90
|
+
/** @type {RangeMap<any>} keep track of facet locations within the vertex array */
|
|
91
|
+
this.rangeMap = new RangeMap();
|
|
92
|
+
|
|
93
|
+
// TODO: Implement https://vega.github.io/vega-lite/docs/config.html
|
|
94
|
+
/** @type {MarkConfig} */
|
|
95
|
+
this.defaultProperties = {
|
|
96
|
+
get clip() {
|
|
97
|
+
// TODO: Cache once the scales have been resolved
|
|
98
|
+
// TODO: Only check channels that are used
|
|
99
|
+
// TODO: provide more fine-grained xClip and yClip props
|
|
100
|
+
return /** @type {import("../spec/channel").PositionalChannel[]} */ ([
|
|
101
|
+
"x",
|
|
102
|
+
"y",
|
|
103
|
+
])
|
|
104
|
+
.map((channel) => unitView.getScaleResolution(channel))
|
|
105
|
+
.some((resolution) => resolution?.isZoomable() ?? false);
|
|
106
|
+
},
|
|
107
|
+
xOffset: 0,
|
|
108
|
+
yOffset: 0,
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Minimum size for WebGL buffers (number of data items).
|
|
112
|
+
* Allows for using bufferSubData to update graphics.
|
|
113
|
+
* This property is intended for internal usage.
|
|
114
|
+
*/
|
|
115
|
+
minBufferSize: 0,
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* A properties object that contains the configured mark properties or
|
|
120
|
+
* default values as fallback.
|
|
121
|
+
*
|
|
122
|
+
* TODO: Proper and comprehensive typings for mark properties
|
|
123
|
+
*
|
|
124
|
+
* @type {Partial<MarkConfig>}
|
|
125
|
+
* @readonly
|
|
126
|
+
*/
|
|
127
|
+
this.properties = coalesceProperties(
|
|
128
|
+
typeof this.unitView.spec.mark == "object"
|
|
129
|
+
? () => /** @type {MarkConfig} */ (this.unitView.spec.mark)
|
|
130
|
+
: () => /** @type {MarkConfig} */ ({}),
|
|
131
|
+
() => this.defaultProperties
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
get opaque() {
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Returns attribute info for WebGL attributes that match visual channels.
|
|
141
|
+
*
|
|
142
|
+
* Note: attributes and channels do not necessarily match.
|
|
143
|
+
* For example, rectangles have x, y, x2, and y2 channels but only x and y as attributes.
|
|
144
|
+
*
|
|
145
|
+
* @returns {string[]}
|
|
146
|
+
*/
|
|
147
|
+
getAttributes() {
|
|
148
|
+
// override
|
|
149
|
+
throw new Error("Not implemented!");
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* @returns {Channel[]}
|
|
154
|
+
*/
|
|
155
|
+
getSupportedChannels() {
|
|
156
|
+
return [
|
|
157
|
+
"sample",
|
|
158
|
+
"facetIndex",
|
|
159
|
+
"x",
|
|
160
|
+
"y",
|
|
161
|
+
"color",
|
|
162
|
+
"opacity",
|
|
163
|
+
"search",
|
|
164
|
+
"uniqueId",
|
|
165
|
+
];
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* @returns {Encoding}
|
|
170
|
+
*/
|
|
171
|
+
getDefaultEncoding() {
|
|
172
|
+
/** @type {Encoding} */
|
|
173
|
+
const encoding = {
|
|
174
|
+
sample: undefined,
|
|
175
|
+
uniqueId: undefined,
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
if (this.isPickingParticipant()) {
|
|
179
|
+
encoding.uniqueId = {
|
|
180
|
+
field: "_uniqueId", // TODO: Use constant
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return encoding;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Adds intelligent defaults etc to the encoding.
|
|
189
|
+
*
|
|
190
|
+
* @param {Encoding} encoding
|
|
191
|
+
* @returns {Encoding}
|
|
192
|
+
*/
|
|
193
|
+
fixEncoding(encoding) {
|
|
194
|
+
return encoding;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Returns the encoding spec supplemented with mark's default encodings
|
|
199
|
+
*
|
|
200
|
+
* @returns {Encoding}
|
|
201
|
+
*/
|
|
202
|
+
get encoding() {
|
|
203
|
+
return getCachedOrCall(this, "encoding", () => {
|
|
204
|
+
const defaults = this.getDefaultEncoding();
|
|
205
|
+
const configured = this.unitView.getEncoding();
|
|
206
|
+
|
|
207
|
+
/** @type {(property: string) => ValueDef} */
|
|
208
|
+
const propToValueDef = (property) => {
|
|
209
|
+
const value =
|
|
210
|
+
this.properties[/** @type {keyof MarkConfig} */ (property)];
|
|
211
|
+
return isScalar(value) && { value };
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
const propertyValues = Object.fromEntries(
|
|
215
|
+
this.getSupportedChannels()
|
|
216
|
+
.map(
|
|
217
|
+
(channel) =>
|
|
218
|
+
/** @type {[Channel, ValueDef]} */ ([
|
|
219
|
+
channel,
|
|
220
|
+
propToValueDef(channel),
|
|
221
|
+
])
|
|
222
|
+
)
|
|
223
|
+
.filter((entry) => entry[1].value !== undefined)
|
|
224
|
+
);
|
|
225
|
+
|
|
226
|
+
const encoding = this.fixEncoding({
|
|
227
|
+
...defaults,
|
|
228
|
+
...propertyValues,
|
|
229
|
+
...configured,
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
for (const channel of Object.keys(encoding)) {
|
|
233
|
+
if (!this.getSupportedChannels().includes(channel)) {
|
|
234
|
+
// TODO: Only delete channels that were inherited
|
|
235
|
+
// Should complain about unsupported channels that were
|
|
236
|
+
// explicitly specified.
|
|
237
|
+
delete encoding[channel];
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return encoding;
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
getContext() {
|
|
246
|
+
return this.unitView.context;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
getType() {
|
|
250
|
+
return this.unitView.getMarkType();
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
initializeData() {
|
|
254
|
+
//
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Initialize encoders that encode fields of the data (or constants) to
|
|
259
|
+
* the ranges of the visual channels.
|
|
260
|
+
*/
|
|
261
|
+
initializeEncoders() {
|
|
262
|
+
this.encoders = createEncoders(this);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Initialize shaders etc.
|
|
267
|
+
*/
|
|
268
|
+
async initializeGraphics() {
|
|
269
|
+
//override
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* Update WebGL buffers from the data
|
|
274
|
+
*/
|
|
275
|
+
updateGraphicsData() {
|
|
276
|
+
// override
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
getSampleFacetMode() {
|
|
280
|
+
if (this.encoders.facetIndex) {
|
|
281
|
+
return SAMPLE_FACET_TEXTURE;
|
|
282
|
+
} else if (
|
|
283
|
+
// If the UnitView is inside app's SampleView.
|
|
284
|
+
// TODO: This may break if non-faceted stuff is added to SampleView,
|
|
285
|
+
// e.g., view background or an x axis.
|
|
286
|
+
// This could also be more generic and work with other faceting views
|
|
287
|
+
// that will be available in the future.
|
|
288
|
+
this.unitView
|
|
289
|
+
.getLayoutAncestors()
|
|
290
|
+
.find((view) => "samples" in view.spec)
|
|
291
|
+
) {
|
|
292
|
+
return SAMPLE_FACET_UNIFORM;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
*
|
|
298
|
+
* @param {string} vertexShader
|
|
299
|
+
* @param {string} fragmentShader
|
|
300
|
+
* @param {string[]} [extraHeaders]
|
|
301
|
+
*/
|
|
302
|
+
createAndLinkShaders(vertexShader, fragmentShader, extraHeaders = []) {
|
|
303
|
+
const attributes = this.getAttributes();
|
|
304
|
+
|
|
305
|
+
// For debugging
|
|
306
|
+
extraHeaders.push("// view: " + this.unitView.getPathString());
|
|
307
|
+
|
|
308
|
+
// TODO: This is a temporary variable, don't store it in the mark object
|
|
309
|
+
/** @type {string[]} */
|
|
310
|
+
this.domainUniforms = [];
|
|
311
|
+
|
|
312
|
+
/** @type {string[]} */
|
|
313
|
+
let scaleCode = [];
|
|
314
|
+
|
|
315
|
+
const sampleFacetMode = this.getSampleFacetMode();
|
|
316
|
+
if (sampleFacetMode) {
|
|
317
|
+
extraHeaders.push(`#define ${sampleFacetMode}`);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
for (const attribute of attributes) {
|
|
321
|
+
/** @type {Channel} */
|
|
322
|
+
let channel;
|
|
323
|
+
if (attribute in this.encoding) {
|
|
324
|
+
channel = /** @type {Channel} */ (attribute);
|
|
325
|
+
} else {
|
|
326
|
+
continue;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
const channelDef = this.encoding[channel];
|
|
330
|
+
|
|
331
|
+
if (!channelDef) {
|
|
332
|
+
continue;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
if (isValueDef(channelDef)) {
|
|
336
|
+
scaleCode.push(generateValueGlsl(channel, channelDef.value));
|
|
337
|
+
} else {
|
|
338
|
+
const resolutionChannel =
|
|
339
|
+
(isChannelDefWithScale(channelDef) &&
|
|
340
|
+
channelDef.resolutionChannel) ||
|
|
341
|
+
channel;
|
|
342
|
+
|
|
343
|
+
const scale = isChannelWithScale(resolutionChannel)
|
|
344
|
+
? this.unitView
|
|
345
|
+
.getScaleResolution(resolutionChannel)
|
|
346
|
+
.getScale()
|
|
347
|
+
: scaleNull();
|
|
348
|
+
|
|
349
|
+
const generated = generateScaleGlsl(channel, scale, channelDef);
|
|
350
|
+
|
|
351
|
+
scaleCode.push(generated.glsl);
|
|
352
|
+
if (generated.domainUniform) {
|
|
353
|
+
this.domainUniforms.push(generated.domainUniform);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
const domainUniformBlock = this.domainUniforms.length
|
|
359
|
+
? "layout(std140) uniform Domains {\n" +
|
|
360
|
+
this.domainUniforms.map((u) => ` ${u}\n`).join("") +
|
|
361
|
+
"};\n\n"
|
|
362
|
+
: "";
|
|
363
|
+
|
|
364
|
+
const vertexPrecision = "precision highp float;\n";
|
|
365
|
+
|
|
366
|
+
const vertexParts = [
|
|
367
|
+
vertexPrecision,
|
|
368
|
+
...extraHeaders,
|
|
369
|
+
GLSL_COMMON,
|
|
370
|
+
GLSL_SCALES,
|
|
371
|
+
domainUniformBlock,
|
|
372
|
+
...scaleCode,
|
|
373
|
+
GLSL_SAMPLE_FACET,
|
|
374
|
+
GLSL_PICKING_VERTEX,
|
|
375
|
+
vertexShader,
|
|
376
|
+
];
|
|
377
|
+
|
|
378
|
+
const fragmentParts = [
|
|
379
|
+
...extraHeaders,
|
|
380
|
+
GLSL_COMMON,
|
|
381
|
+
GLSL_PICKING_FRAGMENT,
|
|
382
|
+
fragmentShader,
|
|
383
|
+
];
|
|
384
|
+
|
|
385
|
+
const gl = this.gl;
|
|
386
|
+
|
|
387
|
+
// Postpone status checking to allow for background compilation
|
|
388
|
+
// See: https://toji.github.io/shader-perf/
|
|
389
|
+
// TODO: It might make sense to cache and share identical programs between mark instances.
|
|
390
|
+
this.programStatus = createProgram(
|
|
391
|
+
gl,
|
|
392
|
+
this.glHelper.compileShader(gl.VERTEX_SHADER, vertexParts),
|
|
393
|
+
this.glHelper.compileShader(gl.FRAGMENT_SHADER, fragmentParts)
|
|
394
|
+
);
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* Check WebGL shader/program compilation/linking status and finalize
|
|
399
|
+
* initialization.
|
|
400
|
+
*/
|
|
401
|
+
finalizeGraphicsInitialization() {
|
|
402
|
+
const error = this.programStatus.getProgramErrors();
|
|
403
|
+
if (error) {
|
|
404
|
+
if (error.detail) {
|
|
405
|
+
console.warn(error.detail);
|
|
406
|
+
}
|
|
407
|
+
/** @type {Error & { view?: import("../view/view").default}} */
|
|
408
|
+
const err = new Error(
|
|
409
|
+
"Cannot create shader program: " + error.message
|
|
410
|
+
);
|
|
411
|
+
err.view = this.unitView;
|
|
412
|
+
throw err;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
this.programInfo = createProgramInfoFromProgram(
|
|
416
|
+
this.gl,
|
|
417
|
+
this.programStatus.program
|
|
418
|
+
);
|
|
419
|
+
delete this.programStatus;
|
|
420
|
+
|
|
421
|
+
if (this.domainUniforms.length) {
|
|
422
|
+
this.domainUniformInfo = createUniformBlockInfo(
|
|
423
|
+
this.gl,
|
|
424
|
+
this.programInfo,
|
|
425
|
+
"Domains"
|
|
426
|
+
);
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
this.viewUniformInfo = createUniformBlockInfo(
|
|
430
|
+
this.gl,
|
|
431
|
+
this.programInfo,
|
|
432
|
+
"View"
|
|
433
|
+
);
|
|
434
|
+
|
|
435
|
+
this.gl.useProgram(this.programInfo.program);
|
|
436
|
+
|
|
437
|
+
this._setDatums();
|
|
438
|
+
|
|
439
|
+
setUniforms(this.programInfo, {
|
|
440
|
+
// left pos, left height, right pos, right height
|
|
441
|
+
uSampleFacet: [0, 1, 0, 1],
|
|
442
|
+
uTransitionOffset: 0.0,
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
_setDatums() {
|
|
447
|
+
for (const [channel, channelDef] of Object.entries(this.encoding)) {
|
|
448
|
+
if (isDatumDef(channelDef)) {
|
|
449
|
+
const encoder = this.encoders[channel];
|
|
450
|
+
|
|
451
|
+
const datum = encoder.indexer
|
|
452
|
+
? encoder.indexer(channelDef.datum)
|
|
453
|
+
: isHighPrecisionScale(encoder.scale.type)
|
|
454
|
+
? splitHighPrecision(+channelDef.datum)
|
|
455
|
+
: +channelDef.datum;
|
|
456
|
+
|
|
457
|
+
setUniforms(this.programInfo, {
|
|
458
|
+
[ATTRIBUTE_PREFIX + channel]: datum,
|
|
459
|
+
});
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
/**
|
|
465
|
+
* Delete WebGL buffers etc.
|
|
466
|
+
*/
|
|
467
|
+
deleteGraphicsData() {
|
|
468
|
+
if (this.bufferInfo) {
|
|
469
|
+
const gl = this.gl;
|
|
470
|
+
// A hack to prevent WebGL: INVALID_OPERATION: drawArrays: no buffer is bound to enabled attribute
|
|
471
|
+
// TODO: Consider using bufferSubData or DYNAMIC_DRAW etc...
|
|
472
|
+
for (let i = 0; i < 8; i++) {
|
|
473
|
+
gl.disableVertexAttribArray(i);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
Object.values(this.bufferInfo.attribs).forEach((attribInfo) =>
|
|
477
|
+
this.gl.deleteBuffer(attribInfo.buffer)
|
|
478
|
+
);
|
|
479
|
+
if (this.bufferInfo.indices) {
|
|
480
|
+
this.gl.deleteBuffer(this.bufferInfo.indices);
|
|
481
|
+
}
|
|
482
|
+
this.bufferInfo = undefined;
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
/**
|
|
487
|
+
*
|
|
488
|
+
* @param {any} vertexData TODO: Extract type from VertexBuilder
|
|
489
|
+
*/
|
|
490
|
+
updateBufferInfo(vertexData) {
|
|
491
|
+
// Ensure that no VAOs are inadvertently altered
|
|
492
|
+
this.gl.bindVertexArray(null);
|
|
493
|
+
|
|
494
|
+
if (
|
|
495
|
+
this.bufferInfo &&
|
|
496
|
+
vertexData.vertexCount <= this.bufferInfo.allocatedVertices
|
|
497
|
+
) {
|
|
498
|
+
for (const [attribute, attributeData] of Object.entries(
|
|
499
|
+
vertexData.arrays
|
|
500
|
+
)) {
|
|
501
|
+
// Skip constants
|
|
502
|
+
if (attributeData.data) {
|
|
503
|
+
// TODO: Check that all attributes and numComponents match
|
|
504
|
+
setAttribInfoBufferFromArray(
|
|
505
|
+
this.gl,
|
|
506
|
+
this.bufferInfo.attribs[attribute],
|
|
507
|
+
attributeData.data,
|
|
508
|
+
0
|
|
509
|
+
);
|
|
510
|
+
// TODO: Consider double buffering:
|
|
511
|
+
// https://community.khronos.org/t/texture-buffers-are-much-slower-than-uniform-buffers/77139
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
} else {
|
|
515
|
+
this.deleteGraphicsData();
|
|
516
|
+
this.bufferInfo = createBufferInfoFromArrays(
|
|
517
|
+
this.gl,
|
|
518
|
+
vertexData.arrays,
|
|
519
|
+
{ numElements: vertexData.vertexCount }
|
|
520
|
+
);
|
|
521
|
+
this.bufferInfo.allocatedVertices = vertexData.allocatedVertices;
|
|
522
|
+
this.vertexArrayInfo = undefined;
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
/** Convenience method */
|
|
527
|
+
get glHelper() {
|
|
528
|
+
return this.getContext().glHelper;
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
/** Convenience method */
|
|
532
|
+
get gl() {
|
|
533
|
+
return this.glHelper.gl;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
onBeforeSampleAnimation() {
|
|
537
|
+
// override
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
onAfterSampleAnimation() {
|
|
541
|
+
// override
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
isReady() {
|
|
545
|
+
return this.bufferInfo && this.programInfo;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
/**
|
|
549
|
+
* Returns true if this mark instance participates in picking.
|
|
550
|
+
*
|
|
551
|
+
* TODO: Check if tooltip is enabled,
|
|
552
|
+
* TODO: Check if selection (when it's implemented) is enabled
|
|
553
|
+
*/
|
|
554
|
+
isPickingParticipant() {
|
|
555
|
+
// TODO: Should check encoding instead
|
|
556
|
+
if (this.properties.tooltip === null) {
|
|
557
|
+
// Disabled
|
|
558
|
+
return false;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
for (const view of this.unitView.getLayoutAncestors()) {
|
|
562
|
+
if (!view.isPickingSupported()) {
|
|
563
|
+
return false;
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
return true;
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
/**
|
|
571
|
+
* Configures the WebGL state for rendering the mark instances.
|
|
572
|
+
* A separate preparation stage allows for efficient rendering of faceted
|
|
573
|
+
* views, i.e., multiple views share the uniforms (such as mark properties
|
|
574
|
+
* and scales) and buffers.
|
|
575
|
+
*
|
|
576
|
+
* @param {import("../types/rendering").GlobalRenderingOptions} options
|
|
577
|
+
* @returns {(() => void)[]}
|
|
578
|
+
*/
|
|
579
|
+
// eslint-disable-next-line complexity
|
|
580
|
+
prepareRender(options) {
|
|
581
|
+
const glHelper = this.glHelper;
|
|
582
|
+
const gl = this.gl;
|
|
583
|
+
|
|
584
|
+
/** @type {(() => void)[]} */
|
|
585
|
+
const ops = [];
|
|
586
|
+
|
|
587
|
+
ops.push(() => {
|
|
588
|
+
if (!this.vertexArrayInfo) {
|
|
589
|
+
this.vertexArrayInfo = createVertexArrayInfo(
|
|
590
|
+
this.gl,
|
|
591
|
+
this.programInfo,
|
|
592
|
+
this.bufferInfo
|
|
593
|
+
);
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
gl.useProgram(this.programInfo.program);
|
|
597
|
+
});
|
|
598
|
+
|
|
599
|
+
if (this.domainUniformInfo) {
|
|
600
|
+
// TODO: Only update the domains that have changed
|
|
601
|
+
|
|
602
|
+
for (const [uniform, setter] of Object.entries(
|
|
603
|
+
this.domainUniformInfo.setters
|
|
604
|
+
)) {
|
|
605
|
+
// TODO: isChannel()
|
|
606
|
+
const channel = /** @type {Channel} */ (
|
|
607
|
+
uniform.substring(DOMAIN_PREFIX.length)
|
|
608
|
+
);
|
|
609
|
+
|
|
610
|
+
const channelDef = this.encoding[channel];
|
|
611
|
+
const resolutionChannel =
|
|
612
|
+
(isChannelDefWithScale(channelDef) &&
|
|
613
|
+
channelDef.resolutionChannel) ||
|
|
614
|
+
channel;
|
|
615
|
+
|
|
616
|
+
if (isChannelWithScale(resolutionChannel)) {
|
|
617
|
+
const scale = this.unitView
|
|
618
|
+
.getScaleResolution(resolutionChannel)
|
|
619
|
+
.getScale();
|
|
620
|
+
|
|
621
|
+
ops.push(() => {
|
|
622
|
+
const domain = isDiscrete(scale.type)
|
|
623
|
+
? [0, scale.domain().length]
|
|
624
|
+
: scale.domain();
|
|
625
|
+
|
|
626
|
+
setter(
|
|
627
|
+
isHighPrecisionScale(scale.type)
|
|
628
|
+
? toHighPrecisionDomainUniform(domain)
|
|
629
|
+
: domain
|
|
630
|
+
);
|
|
631
|
+
});
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
ops.push(() =>
|
|
636
|
+
setUniformBlock(gl, this.programInfo, this.domainUniformInfo)
|
|
637
|
+
);
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
for (const [channel, channelDef] of Object.entries(this.encoding)) {
|
|
641
|
+
if (isChannelDefWithScale(channelDef)) {
|
|
642
|
+
const resolutionChannel =
|
|
643
|
+
(isChannelDefWithScale(channelDef) &&
|
|
644
|
+
channelDef.resolutionChannel) ||
|
|
645
|
+
channel;
|
|
646
|
+
|
|
647
|
+
if (isChannelWithScale(resolutionChannel)) {
|
|
648
|
+
const resolution =
|
|
649
|
+
this.unitView.getScaleResolution(resolutionChannel);
|
|
650
|
+
|
|
651
|
+
const texture = glHelper.rangeTextures.get(resolution);
|
|
652
|
+
if (texture) {
|
|
653
|
+
ops.push(() =>
|
|
654
|
+
setUniforms(this.programInfo, {
|
|
655
|
+
[RANGE_TEXTURE_PREFIX + channel]: texture,
|
|
656
|
+
})
|
|
657
|
+
);
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
if (this.getSampleFacetMode() == SAMPLE_FACET_TEXTURE) {
|
|
664
|
+
ops.push(() => {
|
|
665
|
+
/** @type {WebGLTexture} */
|
|
666
|
+
let facetTexture;
|
|
667
|
+
for (const view of this.unitView.getLayoutAncestors()) {
|
|
668
|
+
facetTexture = view.getSampleFacetTexture();
|
|
669
|
+
if (facetTexture) {
|
|
670
|
+
break;
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
if (!facetTexture) {
|
|
675
|
+
throw new Error("No facet texture available. This is bug.");
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
setUniforms(this.programInfo, {
|
|
679
|
+
uSampleFacetTexture: facetTexture,
|
|
680
|
+
});
|
|
681
|
+
});
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
// TODO: Rendering of the mark should be completely skipped if it doesn't
|
|
685
|
+
// participate picking
|
|
686
|
+
const picking =
|
|
687
|
+
(options.picking ?? false) && this.isPickingParticipant();
|
|
688
|
+
|
|
689
|
+
// Note: the block is sent to GPU in setViewport(), which is repeated for each facet
|
|
690
|
+
ops.push(() =>
|
|
691
|
+
setBlockUniforms(this.viewUniformInfo, {
|
|
692
|
+
uViewOpacity: this.unitView.getEffectiveOpacity(),
|
|
693
|
+
uPickingEnabled: picking,
|
|
694
|
+
})
|
|
695
|
+
);
|
|
696
|
+
|
|
697
|
+
if (this.opaque || options.picking) {
|
|
698
|
+
ops.push(() => gl.disable(gl.BLEND));
|
|
699
|
+
} else {
|
|
700
|
+
ops.push(() => gl.enable(gl.BLEND));
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
return ops;
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
/**
|
|
707
|
+
* Prepares rendering of a single sample facet.
|
|
708
|
+
*
|
|
709
|
+
* @param {MarkRenderingOptions} options
|
|
710
|
+
* @returns {boolean} true if rendering should proceed,
|
|
711
|
+
* false if it should be skipped
|
|
712
|
+
*/
|
|
713
|
+
prepareSampleFacetRendering(options) {
|
|
714
|
+
const opts = options.sampleFacetRenderingOptions;
|
|
715
|
+
const locationSetter = this.programInfo.uniformSetters.uSampleFacet;
|
|
716
|
+
|
|
717
|
+
if (opts && locationSetter) {
|
|
718
|
+
const pos = opts.locSize ? opts.locSize.location : 0.0;
|
|
719
|
+
const height = opts.locSize ? opts.locSize.size : 1.0;
|
|
720
|
+
|
|
721
|
+
if (pos > 1.0 || pos + height < 0.0) {
|
|
722
|
+
// Not visible
|
|
723
|
+
return false;
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
const targetPos = opts.targetLocSize
|
|
727
|
+
? opts.targetLocSize.location
|
|
728
|
+
: pos;
|
|
729
|
+
const targetHeight = opts.targetLocSize
|
|
730
|
+
? opts.targetLocSize.size
|
|
731
|
+
: height;
|
|
732
|
+
|
|
733
|
+
// Use WebGL directly, because twgl uses gl.uniform4fv, which has an
|
|
734
|
+
// inferior performance. Based on profiling, this optimization gives
|
|
735
|
+
// a significant performance boost.
|
|
736
|
+
this.gl.uniform4f(
|
|
737
|
+
// @ts-expect-error
|
|
738
|
+
locationSetter.location, // TODO: Make a twgl pull request to fix typing
|
|
739
|
+
pos,
|
|
740
|
+
height,
|
|
741
|
+
targetPos,
|
|
742
|
+
targetHeight
|
|
743
|
+
);
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
return true;
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
/**
|
|
750
|
+
* Returns a callback function that the ViewRenderingContext calls to
|
|
751
|
+
* perform the actual rendering either immediately or at a later time.
|
|
752
|
+
*
|
|
753
|
+
* @param {MarkRenderingOptions} options
|
|
754
|
+
* @returns {function():void} A function that renderingContext calls to
|
|
755
|
+
* trigger the actual rendering
|
|
756
|
+
*/
|
|
757
|
+
render(options) {
|
|
758
|
+
// Override
|
|
759
|
+
return undefined;
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
/**
|
|
763
|
+
* @param {DrawFunction} draw A function that draws a range of vertices
|
|
764
|
+
* @param {import("./mark").MarkRenderingOptions} options
|
|
765
|
+
*/
|
|
766
|
+
createRenderCallback(draw, options) {
|
|
767
|
+
if (!this.bufferInfo) {
|
|
768
|
+
const e = new Error(
|
|
769
|
+
`${this.getType()} mark has no data. This is bug.`
|
|
770
|
+
);
|
|
771
|
+
// @ts-ignore
|
|
772
|
+
e.view = this.unitView;
|
|
773
|
+
throw e;
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
// eslint-disable-next-line consistent-this
|
|
777
|
+
const self = this;
|
|
778
|
+
|
|
779
|
+
/** @type {function(import("../gl/dataToVertices").RangeEntry):void} rangeEntry */
|
|
780
|
+
let drawWithRangeEntry;
|
|
781
|
+
|
|
782
|
+
const scale = this.unitView.getScaleResolution("x")?.getScale();
|
|
783
|
+
const continuous = scale && isContinuous(scale.type);
|
|
784
|
+
const domainStartOffset = ["index", "locus"].includes(scale?.type)
|
|
785
|
+
? -1
|
|
786
|
+
: 0;
|
|
787
|
+
|
|
788
|
+
/** @type {[number, number]} Recycle to ease garbage collector's work */
|
|
789
|
+
const arr = [0, 0];
|
|
790
|
+
|
|
791
|
+
drawWithRangeEntry = (rangeEntry) => {
|
|
792
|
+
if (continuous && rangeEntry.xIndex) {
|
|
793
|
+
const domain = scale.domain();
|
|
794
|
+
const vertexIndices = rangeEntry.xIndex(
|
|
795
|
+
domain[0] + domainStartOffset,
|
|
796
|
+
domain[1],
|
|
797
|
+
arr
|
|
798
|
+
);
|
|
799
|
+
const offset = vertexIndices[0];
|
|
800
|
+
const count = vertexIndices[1] - offset;
|
|
801
|
+
if (count > 0) {
|
|
802
|
+
draw(offset, count);
|
|
803
|
+
}
|
|
804
|
+
} else {
|
|
805
|
+
draw(rangeEntry.offset, rangeEntry.count);
|
|
806
|
+
}
|
|
807
|
+
};
|
|
808
|
+
|
|
809
|
+
// If is either faceted or non-faceted, not both.
|
|
810
|
+
// An undefined key with vertices means that the mark is non-faceted.
|
|
811
|
+
// In such case, the same non-faceted data is repeated for each facet.
|
|
812
|
+
const facetId =
|
|
813
|
+
this.rangeMap.get(undefined).count == 0
|
|
814
|
+
? options.facetId
|
|
815
|
+
: undefined;
|
|
816
|
+
const rangeEntry = this.rangeMap.get(facetId);
|
|
817
|
+
|
|
818
|
+
return options.sampleFacetRenderingOptions
|
|
819
|
+
? function renderSampleFacetRange() {
|
|
820
|
+
if (rangeEntry.count) {
|
|
821
|
+
if (self.prepareSampleFacetRendering(options)) {
|
|
822
|
+
drawWithRangeEntry(rangeEntry);
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
: function renderRange() {
|
|
827
|
+
if (rangeEntry.count) {
|
|
828
|
+
drawWithRangeEntry(rangeEntry);
|
|
829
|
+
}
|
|
830
|
+
};
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
/**
|
|
834
|
+
* Sets viewport, clipping, and uniforms related to scaling and translation
|
|
835
|
+
*
|
|
836
|
+
* @param {import("../utils/layout/rectangle").default} coords
|
|
837
|
+
* @param {import("../utils/layout/rectangle").default} [clipRect]
|
|
838
|
+
* @returns {boolean} true if the viewport is renderable (size > 0)
|
|
839
|
+
*/
|
|
840
|
+
setViewport(coords, clipRect) {
|
|
841
|
+
coords = coords.flatten();
|
|
842
|
+
|
|
843
|
+
const dpr = this.unitView.context.devicePixelRatio;
|
|
844
|
+
const gl = this.gl;
|
|
845
|
+
const props = this.properties;
|
|
846
|
+
|
|
847
|
+
const logicalSize = this.glHelper.getLogicalCanvasSize();
|
|
848
|
+
|
|
849
|
+
// Translate by half a pixel to place vertical / horizontal
|
|
850
|
+
// rules inside pixels, not between pixels.
|
|
851
|
+
const pixelOffset = 0.5;
|
|
852
|
+
|
|
853
|
+
// Note: we also handle xOffset/yOffset mark properties here
|
|
854
|
+
const xOffset = (props.xOffset ?? 0) + pixelOffset;
|
|
855
|
+
const yOffset = (props.yOffset ?? 0) + pixelOffset;
|
|
856
|
+
|
|
857
|
+
/** @type {object} */
|
|
858
|
+
let uniforms;
|
|
859
|
+
|
|
860
|
+
let clippedCoords = coords;
|
|
861
|
+
|
|
862
|
+
if (props.clip !== "never" && (props.clip || clipRect)) {
|
|
863
|
+
let xClipOffset = 0;
|
|
864
|
+
let yClipOffset = 0;
|
|
865
|
+
|
|
866
|
+
/** @type {[number, number]} */
|
|
867
|
+
let uViewScale;
|
|
868
|
+
|
|
869
|
+
if (clipRect) {
|
|
870
|
+
clippedCoords = coords.intersect(clipRect).flatten();
|
|
871
|
+
if (!clippedCoords.isDefined()) {
|
|
872
|
+
return false;
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
uViewScale = [
|
|
876
|
+
coords.width / clippedCoords.width,
|
|
877
|
+
coords.height / clippedCoords.height,
|
|
878
|
+
];
|
|
879
|
+
|
|
880
|
+
yClipOffset = Math.max(0, coords.y2 - clipRect.y2);
|
|
881
|
+
xClipOffset = Math.max(0, coords.x2 - clipRect.x2);
|
|
882
|
+
} else {
|
|
883
|
+
uViewScale = [1, 1];
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
const physicalGlCoords = [
|
|
887
|
+
clippedCoords.x,
|
|
888
|
+
logicalSize.height - clippedCoords.y2,
|
|
889
|
+
clippedCoords.width,
|
|
890
|
+
clippedCoords.height,
|
|
891
|
+
].map((x) => x * dpr);
|
|
892
|
+
|
|
893
|
+
// Because glViewport accepts only integers, we subtract the rounding
|
|
894
|
+
// errors from xyOffsets to guarantee that graphics in clipped
|
|
895
|
+
// and non-clipped viewports align correctly
|
|
896
|
+
const roundedCoords = physicalGlCoords.map((x) => Math.round(x));
|
|
897
|
+
const [xError, yError] = physicalGlCoords.map(
|
|
898
|
+
(x, i) => x - roundedCoords[i]
|
|
899
|
+
);
|
|
900
|
+
|
|
901
|
+
// @ts-ignore
|
|
902
|
+
gl.viewport(...roundedCoords);
|
|
903
|
+
// @ts-ignore
|
|
904
|
+
gl.scissor(...roundedCoords);
|
|
905
|
+
gl.enable(gl.SCISSOR_TEST);
|
|
906
|
+
|
|
907
|
+
uniforms = {
|
|
908
|
+
uViewOffset: [
|
|
909
|
+
(xOffset + xClipOffset + xError / dpr) /
|
|
910
|
+
clippedCoords.width,
|
|
911
|
+
-(yOffset + yClipOffset - yError / dpr) /
|
|
912
|
+
clippedCoords.height,
|
|
913
|
+
],
|
|
914
|
+
uViewScale,
|
|
915
|
+
};
|
|
916
|
+
} else {
|
|
917
|
+
if (!coords.isDefined()) {
|
|
918
|
+
return false;
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
// Viewport comprises the full canvas
|
|
922
|
+
gl.viewport(
|
|
923
|
+
0,
|
|
924
|
+
0,
|
|
925
|
+
logicalSize.width * dpr,
|
|
926
|
+
logicalSize.height * dpr
|
|
927
|
+
);
|
|
928
|
+
gl.disable(gl.SCISSOR_TEST);
|
|
929
|
+
|
|
930
|
+
// Offset and scale all drawing to the view rectangle
|
|
931
|
+
uniforms = {
|
|
932
|
+
uViewOffset: [
|
|
933
|
+
(coords.x + xOffset) / logicalSize.width,
|
|
934
|
+
(logicalSize.height - coords.y - yOffset - coords.height) /
|
|
935
|
+
logicalSize.height,
|
|
936
|
+
],
|
|
937
|
+
uViewScale: [
|
|
938
|
+
coords.width / logicalSize.width,
|
|
939
|
+
coords.height / logicalSize.height,
|
|
940
|
+
],
|
|
941
|
+
};
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
setBlockUniforms(this.viewUniformInfo, {
|
|
945
|
+
...uniforms,
|
|
946
|
+
uViewportSize: [coords.width, coords.height],
|
|
947
|
+
uDevicePixelRatio: dpr,
|
|
948
|
+
});
|
|
949
|
+
|
|
950
|
+
setUniformBlock(this.gl, this.programInfo, this.viewUniformInfo);
|
|
951
|
+
|
|
952
|
+
return true;
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
/**
|
|
956
|
+
* Finds a datum that overlaps the given value on the x domain.
|
|
957
|
+
* The result is unspecified if multiple data are found.
|
|
958
|
+
*
|
|
959
|
+
* This is highly specific to SampleView and its sorting/filtering functionality.
|
|
960
|
+
*
|
|
961
|
+
* @param {string} facetId
|
|
962
|
+
* @param {import("../spec/channel").Scalar} x value on the x domain
|
|
963
|
+
* @returns {any}
|
|
964
|
+
*/
|
|
965
|
+
findDatumAt(facetId, x) {
|
|
966
|
+
// override
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
/**
|
|
971
|
+
* @augments {InternMap<K, import("../gl/dataToVertices").RangeEntry>}
|
|
972
|
+
* @template K
|
|
973
|
+
*/
|
|
974
|
+
class RangeMap extends InternMap {
|
|
975
|
+
constructor() {
|
|
976
|
+
super([], JSON.stringify);
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
/**
|
|
980
|
+
* @param {K} key
|
|
981
|
+
*/
|
|
982
|
+
get(key) {
|
|
983
|
+
let value = super.get(key);
|
|
984
|
+
if (value === undefined) {
|
|
985
|
+
value = {
|
|
986
|
+
offset: 0,
|
|
987
|
+
count: 0,
|
|
988
|
+
xIndex: undefined,
|
|
989
|
+
};
|
|
990
|
+
super.set(key, value);
|
|
991
|
+
}
|
|
992
|
+
return value;
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
/**
|
|
996
|
+
*
|
|
997
|
+
* @param {Map<K, import("../gl/dataToVertices").RangeEntry>} anotherMap
|
|
998
|
+
*/
|
|
999
|
+
migrateEntries(anotherMap) {
|
|
1000
|
+
for (const [key, value] of anotherMap.entries()) {
|
|
1001
|
+
Object.assign(this.get(key), value);
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
}
|