@genome-spy/core 0.38.0 → 0.40.0

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/schema.json CHANGED
@@ -2457,6 +2457,27 @@
2457
2457
  "description": "The rotation angle in degrees.\n\n**Default value:** `0`",
2458
2458
  "type": "number"
2459
2459
  },
2460
+ "arcFadingDistance": {
2461
+ "anyOf": [
2462
+ {
2463
+ "items": {
2464
+ "type": "number"
2465
+ },
2466
+ "maxItems": 2,
2467
+ "minItems": 2,
2468
+ "type": "array"
2469
+ },
2470
+ {
2471
+ "const": false,
2472
+ "type": "boolean"
2473
+ }
2474
+ ],
2475
+ "description": "The range of the `\"arc\"` shape's fading distance in pixels. This property allows for making the arc's opacity fade out as it extends away from the chord. The fading distance is interpolated from one to zero between the interval defined by this property. Both `false` and `[0, 0]` disable fading.\n\n**Default value:** `false`"
2476
+ },
2477
+ "arcHeightFactor": {
2478
+ "description": "Scaling factor for the `\"arc`\" shape's height. The default value `1.0` produces roughly circular arcs.\n\n**Default value:** `1.0`",
2479
+ "type": "number"
2480
+ },
2460
2481
  "baseline": {
2461
2482
  "$ref": "#/definitions/Baseline",
2462
2483
  "description": "The vertical alignment of the text. One of `\"top\"`, `\"middle\"`, `\"bottom\"`.\n\n**Default value:** `\"bottom\"`"
@@ -2465,6 +2486,10 @@
2465
2486
  "description": "Builds and index for efficient rendering of subsets of the data. The data must be sorted by the x coordinate.\n\nTODO: This should be enabled automatically if the data are sorted.",
2466
2487
  "type": "boolean"
2467
2488
  },
2489
+ "clampApex": {
2490
+ "description": "Whether the apex of the `\"dome\"` shape is clamped to the viewport edge. When over a half of the dome is located outside the viewport, clamping allows for more accurate reading of the value encoded by the apex' position.\n\n**Default value:** `false`",
2491
+ "type": "boolean"
2492
+ },
2468
2493
  "clip": {
2469
2494
  "anyOf": [
2470
2495
  {
@@ -2480,10 +2505,6 @@
2480
2505
  "color": {
2481
2506
  "type": "string"
2482
2507
  },
2483
- "color2": {
2484
- "description": "TODO",
2485
- "type": "string"
2486
- },
2487
2508
  "cornerRadius": {
2488
2509
  "description": "Radius of the rounded corners.\n\n**Default value:** `0`",
2489
2510
  "type": "number"
@@ -2560,10 +2581,28 @@
2560
2581
  "description": "Should the stroke only grow inwards, e.g, the diameter/outline is not affected by the stroke width. Thus, a point that has a zero size has no visible stroke. This allows strokes to be used with geometric zoom, etc.\n\n**Default value:** `false`",
2561
2582
  "type": "boolean"
2562
2583
  },
2584
+ "linkShape": {
2585
+ "description": "The shape of the link path. Either `\"arc\"`, `\"diagonal\"`, `\"line\"`, or `\"dome\"`.\n\n**Default value:** `\"arc\"`",
2586
+ "enum": [
2587
+ "arc",
2588
+ "diagonal",
2589
+ "line",
2590
+ "dome"
2591
+ ],
2592
+ "type": "string"
2593
+ },
2563
2594
  "logoLetters": {
2564
2595
  "description": "Stretch letters so that they can be used with [sequence logos](https://en.wikipedia.org/wiki/Sequence_logo), etc...",
2565
2596
  "type": "boolean"
2566
2597
  },
2598
+ "maxChordLength": {
2599
+ "description": "The maximum length of `\"arc\"` shape's chord in pixels. The chord is the line segment between the two points that define the arc. Limiting the chord length serves two purposes when zooming in close enough: 1) it prevents the arc from becoming a straight line and 2) it mitigates the limited precision of floating point numbers in arc rendering.\n\n**Default value:** `50000`",
2600
+ "type": "number"
2601
+ },
2602
+ "minArcHeight": {
2603
+ "description": "The minimum height of an `\"arc\"` shape. Makes very short links more clearly visible.\n\n**Default value:** `1.5`",
2604
+ "type": "number"
2605
+ },
2567
2606
  "minBufferSize": {
2568
2607
  "description": "Minimum size for WebGL buffers (number of data items). Allows for using `bufferSubData()` to update graphics.\n\nThis property is intended for internal use.",
2569
2608
  "type": "number"
@@ -2580,8 +2619,8 @@
2580
2619
  "description": "Clamps the minimum size-dependent opacity. The property does not affect the `opacity` channel. Valid values are between `0` and `1`.\n\nWhen a rectangle would be smaller than what is specified in `minHeight` and `minWidth`, it is faded out proportionally. Example: a rectangle would be rendered as one pixel wide, but `minWidth` clamps it to five pixels. The rectangle is actually rendered as five pixels wide, but its opacity is multiplied by 0.2. With this setting, you can limit the factor to, for example, 0.5 to keep the rectangles more clearly visible.\n\n**Default value:** `0`",
2581
2620
  "type": "number"
2582
2621
  },
2583
- "minSagittaLength": {
2584
- "description": "Minimum length of the arc's sagitta. Makes very short links more clearly visible.\n\n**Default value:** `1.5`",
2622
+ "minPickingSize": {
2623
+ "description": "The minimum stroke width of the links when pointing with the mouse cursor. Allows making very thin links easier to point at.\n\n**Default value:** `3.0`",
2585
2624
  "type": "number"
2586
2625
  },
2587
2626
  "minWidth": {
@@ -2591,6 +2630,14 @@
2591
2630
  "opacity": {
2592
2631
  "type": "number"
2593
2632
  },
2633
+ "orient": {
2634
+ "description": "The orientation of the link path. Either `\"vertical\"` or `\"horizontal\"`. Only applies to diagonal links.\n\n**Default value:** `\"vertical\"`",
2635
+ "enum": [
2636
+ "vertical",
2637
+ "horizontal"
2638
+ ],
2639
+ "type": "string"
2640
+ },
2594
2641
  "paddingX": {
2595
2642
  "description": "The horizontal padding, in pixels, when the `x2` channel is used for ranged text.\n\n**Default value:** `0`",
2596
2643
  "type": "number"
@@ -2599,10 +2646,6 @@
2599
2646
  "description": "The vertical padding, in pixels, when the `y2` channel is used for ranged text.\n\n**Default value:** `0`",
2600
2647
  "type": "number"
2601
2648
  },
2602
- "sagittaScaleFactor": {
2603
- "description": "Scaling factor of the arc's sagitta. The default value `1.0` produces roughly circular arcs.\n\n**Default value:** `1.0`",
2604
- "type": "number"
2605
- },
2606
2649
  "sampleFacetPadding": {
2607
2650
  "description": "Padding between sample facet's upper/lower edge and the maximum point size. This property controls how tightly points are squeezed when facet's height is smaller than the maximum point size. The unit is a proportion of facet's height. The value must be between `0` and `0.5`. This property has no effect when sample faceting is not used.\n\n**Default value:** `0.1`",
2608
2651
  "type": "number"
@@ -2623,10 +2666,6 @@
2623
2666
  "description": "The font size in pixels.\n\n**Default value:** `11`",
2624
2667
  "type": "number"
2625
2668
  },
2626
- "size2": {
2627
- "description": "TODO",
2628
- "type": "number"
2629
- },
2630
2669
  "squeeze": {
2631
2670
  "description": "If the `squeeze` property is true and secondary positional channels (`x2` and/or `y2`) are used, the text is scaled to fit mark's width and/or height.\n\n**Default value:** `true`",
2632
2671
  "type": "boolean"
@@ -1 +1 @@
1
- {"version":3,"file":"encoder.d.ts","sourceRoot":"","sources":["../../../src/encoder/encoder.js"],"names":[],"mappings":"AAIA;;;;;;;;;;GAUG;AACH,6CAJW,OAAO,kBAAkB,EAAE,OAAO,aAClC,OAAO,oBAAoB,EAAE,QAAQ,gGAsC/C;AAED;;;;;;;GAOG;AACH,0CANW,OAAO,oBAAoB,EAAE,UAAU,SACvC,GAAG,0IAyFb;AAED;;;;;GAKG;AACH,uCAHW,OAAO,oBAAoB,EAAE,UAAU,4FAKjD;AAED;;;GAGG;AACH,uCAHW,OAAO,oBAAoB,EAAE,UAAU,mEAKjD;AAED;;;GAGG;AACH,uCAHW,OAAO,oBAAoB,EAAE,UAAU,uDAKjD;AAED;;;GAGG;AACH,kDAHW,OAAO,oBAAoB,EAAE,UAAU,kEAWjD;AAED;;;GAGG;AACH,6CAHW,OAAO,qBAAqB,EAAE,OAAO,WACrC,OAAO,oBAAoB,EAAE,OAAO,klBAS9C;AAED;;;GAGG;AACH,0CAHW,OAAO,oBAAoB,EAAE,UAAU,0DAKjD;AAED;;;GAGG;AACH,sCAHW,OAAO,oBAAoB,EAAE,UAAU,sDAKjD;AAoBD;;;GAGG;AACH,oDAHW,OAAO,oBAAoB,EAAE,OAAO,oEAM9C;AAED;;;GAGG;AACH,6CAHW,OAAO,oBAAoB,EAAE,OAAO,6DAM9C;AAqBD;;;GAGG;AACH,4CAFW,MAAM,WAIhB;AAED;;;;GAIG;AACH,oDAFW,OAAO,oBAAoB,EAAE,OAAO,2DAS9C;AAED;;;;;GAKG;AACH,2CAFW,OAAO,oBAAoB,EAAE,OAAO,wCAI9C;AAED;;;;GAIG;AACH,kDAFW,OAAO,oBAAoB,EAAE,OAAO,0CAM9C;AAED;;GAEG;AACH,wCAFW,OAAO,oBAAoB,EAAE,OAAO,WAI9C;AAED;;;;GAIG;AACH,2CAFW,OAAO,oBAAoB,EAAE,OAAO,WAI9C;AAED;;;GAGG;AACH,4CAHW,OAAO,oBAAoB,EAAE,OAAO,4DAuB9C;AAED;;;;;GAKG;AACH,0CAHW,OAAO,oBAAoB,EAAE,OAAO,GAClC,GAAG,EAAE,CAkBjB;AAED;;;GAGG;AACH,gDAHW,OAAO,oBAAoB,EAAE,OAAO,UACzB,GAAG,KAAE,MAAM,CAkBhC;AAxLD;;GAEG;AACH,wCAFU,OAAO,oBAAoB,EAAE,wBAAwB,EAAE,CAEb;AAEpD;;GAEG;AACH,0CAFU,OAAO,oBAAoB,EAAE,0BAA0B,EAAE,CAEX;AAExD;;GAEG;AACH,iCAFU,OAAO,oBAAoB,EAAE,iBAAiB,EAAE,CAKxD;AAoBF;;;;GAIG;AACH,gCAFU,QAAQ,OAAO,OAAO,oBAAoB,EAAE,OAAO,EAAE,OAAO,oBAAoB,EAAE,0BAA0B,CAAC,CAAC,CAKtH;AAEF;;;;GAIG;AACH,8BAFU,QAAQ,OAAO,OAAO,oBAAoB,EAAE,OAAO,EAAE,OAAO,oBAAoB,EAAE,OAAO,CAAC,CAAC,CAInG"}
1
+ {"version":3,"file":"encoder.d.ts","sourceRoot":"","sources":["../../../src/encoder/encoder.js"],"names":[],"mappings":"AAIA;;;;;;;;;;GAUG;AACH,6CAJW,OAAO,kBAAkB,EAAE,OAAO,aAClC,OAAO,oBAAoB,EAAE,QAAQ,gGAsC/C;AAED;;;;;;;GAOG;AACH,0CANW,OAAO,oBAAoB,EAAE,UAAU,SACvC,GAAG,0IAyFb;AAED;;;;;GAKG;AACH,uCAHW,OAAO,oBAAoB,EAAE,UAAU,4FAKjD;AAED;;;GAGG;AACH,uCAHW,OAAO,oBAAoB,EAAE,UAAU,mEAKjD;AAED;;;GAGG;AACH,uCAHW,OAAO,oBAAoB,EAAE,UAAU,uDAKjD;AAED;;;GAGG;AACH,kDAHW,OAAO,oBAAoB,EAAE,UAAU,kEAWjD;AAED;;;GAGG;AACH,6CAHW,OAAO,qBAAqB,EAAE,OAAO,WACrC,OAAO,oBAAoB,EAAE,OAAO,klBAS9C;AAED;;;GAGG;AACH,0CAHW,OAAO,oBAAoB,EAAE,UAAU,0DAKjD;AAED;;;GAGG;AACH,sCAHW,OAAO,oBAAoB,EAAE,UAAU,sDAKjD;AAoBD;;;GAGG;AACH,oDAHW,OAAO,oBAAoB,EAAE,OAAO,oEAM9C;AAED;;;GAGG;AACH,6CAHW,OAAO,oBAAoB,EAAE,OAAO,6DAM9C;AAqBD;;;GAGG;AACH,4CAFW,MAAM,WAIhB;AAED;;;;GAIG;AACH,oDAFW,OAAO,oBAAoB,EAAE,OAAO,2DAS9C;AAED;;;;;GAKG;AACH,2CAFW,OAAO,oBAAoB,EAAE,OAAO,wCAI9C;AAED;;;;GAIG;AACH,kDAFW,OAAO,oBAAoB,EAAE,OAAO,0CAM9C;AAED;;GAEG;AACH,wCAFW,OAAO,oBAAoB,EAAE,OAAO,WAI9C;AAED;;;;GAIG;AACH,2CAFW,OAAO,oBAAoB,EAAE,OAAO,WAI9C;AAED;;;GAGG;AACH,4CAHW,OAAO,oBAAoB,EAAE,OAAO,4DAuB9C;AAED;;;;;GAKG;AACH,0CAHW,OAAO,oBAAoB,EAAE,OAAO,GAClC,GAAG,EAAE,CAsBjB;AAED;;;GAGG;AACH,gDAHW,OAAO,oBAAoB,EAAE,OAAO,UACzB,GAAG,KAAE,MAAM,CAmBhC;AA7LD;;GAEG;AACH,wCAFU,OAAO,oBAAoB,EAAE,wBAAwB,EAAE,CAEb;AAEpD;;GAEG;AACH,0CAFU,OAAO,oBAAoB,EAAE,0BAA0B,EAAE,CAEX;AAExD;;GAEG;AACH,iCAFU,OAAO,oBAAoB,EAAE,iBAAiB,EAAE,CAKxD;AAoBF;;;;GAIG;AACH,gCAFU,QAAQ,OAAO,OAAO,oBAAoB,EAAE,OAAO,EAAE,OAAO,oBAAoB,EAAE,0BAA0B,CAAC,CAAC,CAKtH;AAEF;;;;GAIG;AACH,8BAFU,QAAQ,OAAO,OAAO,oBAAoB,EAAE,OAAO,EAAE,OAAO,oBAAoB,EAAE,OAAO,CAAC,CAAC,CAInG"}
@@ -366,12 +366,16 @@ export function getDiscreteRange(channel) {
366
366
  return [
367
367
  "circle",
368
368
  "square",
369
- "triangle-up",
370
369
  "cross",
371
370
  "diamond",
372
- "triangle-down",
371
+ "triangle-up",
373
372
  "triangle-right",
373
+ "triangle-down",
374
374
  "triangle-left",
375
+ "tick-up",
376
+ "tick-right",
377
+ "tick-down",
378
+ "tick-left",
375
379
  ];
376
380
  default:
377
381
  }
@@ -391,6 +395,7 @@ export function getDiscreteRangeMapper(channel) {
391
395
  );
392
396
 
393
397
  return (value) => {
398
+ // TODO: Memoize previous
394
399
  const mapped = valueMap.get(value);
395
400
  if (mapped !== undefined) {
396
401
  return mapped;
@@ -135,7 +135,7 @@ export class PointVertexBuilder extends GeometryBuilder {
135
135
  numItems?: number;
136
136
  });
137
137
  }
138
- export class ConnectionVertexBuilder extends GeometryBuilder {
138
+ export class LinkVertexBuilder extends GeometryBuilder {
139
139
  /**
140
140
  * @param {object} object
141
141
  * @param {Record<string, Encoder>} object.encoders
@@ -415,7 +415,7 @@ export class PointVertexBuilder extends GeometryBuilder {
415
415
  }
416
416
  }
417
417
 
418
- export class ConnectionVertexBuilder extends GeometryBuilder {
418
+ export class LinkVertexBuilder extends GeometryBuilder {
419
419
  /**
420
420
  * @param {object} object
421
421
  * @param {Record<string, Encoder>} object.encoders
@@ -1,2 +1,2 @@
1
- const shader = "const float inf=1.0/0.0;vec3 getDiscreteColor(sampler2D s,int index){return texelFetch(s,ivec2(index % textureSize(s,0).x,0),0).rgb;}vec3 getInterpolatedColor(sampler2D s,float unitValue){return texture(s,vec2(unitValue,0.0)).rgb;}float clampToRange(float value,vec2 range){return clamp(value,min(range[0],range[1]),max(range[0],range[1]));}float scaleIdentity(float value){return value;}float scaleLinear(float value,vec2 domain,vec2 range){float domainSpan=domain[1]-domain[0];float rangeSpan=range[1]-range[0];return(value-domain[0])/domainSpan*rangeSpan+range[0];}float scaleLog(float value,vec2 domain,vec2 range,float base){return scaleLinear(log(value)/log(base),log(domain)/log(base),range);}float symlog(float value,float constant){return sign(value)*log(abs(value/constant)+1.0);}float scaleSymlog(float value,vec2 domain,vec2 range,float constant){return scaleLinear(symlog(value,constant),vec2(symlog(domain[0],constant),symlog(domain[1],constant)),range);}float scalePow(float value,vec2 domain,vec2 range,float exponent){return scaleLinear(pow(abs(value),exponent)*sign(value),pow(abs(domain),vec2(exponent))*sign(domain),range);}float scaleBand(float value,vec2 domainExtent,vec2 range,float paddingInner,float paddingOuter,float align,float band){float start=range[0];float stop=range[1];float rangeSpan=stop-start;float n=domainExtent[1]-domainExtent[0];paddingInner=int(n)>1 ? paddingInner : 0.0;float step=rangeSpan/max(1.0,n-paddingInner+paddingOuter*2.0);start+=(rangeSpan-step*(n-paddingInner))*align;float bandwidth=step*(1.0-paddingInner);return start+(value-domainExtent[0])*step+bandwidth*band;}float scaleBandHp(vec2 value,vec3 domainExtent,vec2 range,float paddingInner,float paddingOuter,float align,float band){float start=range[0];float stop=range[1];float rangeSpan=stop-start;vec2 domainStart=domainExtent.xy;float n=domainExtent[2];float step=rangeSpan/max(1.0,n-paddingInner+paddingOuter*2.0);start+=(rangeSpan-step*(n-paddingInner))*align;float bandwidth=step*(1.0-paddingInner);float hi=max(value[0]-domainStart[0],-inf);float lo=max(value[1]-domainStart[1],-inf);return dot(vec4(start,hi,lo,bandwidth),vec4(1.0,step,step,band));}";
1
+ const shader = "uniform highp float uZero;vec3 getDiscreteColor(sampler2D s,int index){return texelFetch(s,ivec2(index % textureSize(s,0).x,0),0).rgb;}vec3 getInterpolatedColor(sampler2D s,float unitValue){return texture(s,vec2(unitValue,0.0)).rgb;}float clampToRange(float value,vec2 range){return clamp(value,min(range[0],range[1]),max(range[0],range[1]));}float scaleIdentity(float value){return value;}float scaleLinear(float value,vec2 domain,vec2 range){float domainSpan=domain[1]-domain[0];float rangeSpan=range[1]-range[0];return(value-domain[0])/domainSpan*rangeSpan+range[0];}float scaleLog(float value,vec2 domain,vec2 range,float base){return scaleLinear(log(value)/log(base),log(domain)/log(base),range);}float symlog(float value,float constant){return sign(value)*log(abs(value/constant)+1.0);}float scaleSymlog(float value,vec2 domain,vec2 range,float constant){return scaleLinear(symlog(value,constant),vec2(symlog(domain[0],constant),symlog(domain[1],constant)),range);}float scalePow(float value,vec2 domain,vec2 range,float exponent){return scaleLinear(pow(abs(value),exponent)*sign(value),pow(abs(domain),vec2(exponent))*sign(domain),range);}float scaleBand(float value,vec2 domainExtent,vec2 range,float paddingInner,float paddingOuter,float align,float band){float start=range[0];float stop=range[1];float rangeSpan=stop-start;float n=domainExtent[1]-domainExtent[0];paddingInner=int(n)>1 ? paddingInner : 0.0;float step=rangeSpan/max(1.0,n-paddingInner+paddingOuter*2.0);start+=(rangeSpan-step*(n-paddingInner))*align;float bandwidth=step*(1.0-paddingInner);return start+(value-domainExtent[0])*step+bandwidth*band;}float scaleBandHp(vec2 value,vec3 domainExtent,vec2 range,float paddingInner,float paddingOuter,float align,float band){float start=range[0];float stop=range[1];float rangeSpan=stop-start;vec2 domainStart=domainExtent.xy;float n=domainExtent[2];float step=rangeSpan/max(1.0,n-paddingInner+paddingOuter*2.0);start+=(rangeSpan-step*(n-paddingInner))*align;float bandwidth=step*(1.0-paddingInner);float inf=1.0/uZero;float hi=max(value[0]-domainStart[0],-inf);float lo=max(value[1]-domainStart[1],-inf);return dot(vec4(start,hi,lo,bandwidth),vec4(1.0,step,step,band));}";
2
2
  export default shader;
@@ -1,2 +1,2 @@
1
- const shader = "in lowp vec4 vColor;in float vSize;in float vNormalLengthInPixels;out lowp vec4 fragColor;void main(void){float dpr=uDevicePixelRatio;float distance=abs(vNormalLengthInPixels);float opacity=clamp(((vSize/2.0-distance)*dpr),0.0,1.0);fragColor=vColor*opacity;if(uPickingEnabled){fragColor=vPickingColor;}}";
1
+ const shader = "in vec4 vColor;in float vSize;in float vNormalLengthInPixels;out lowp vec4 fragColor;void main(void){float dpr=uDevicePixelRatio;float distance=abs(vNormalLengthInPixels);float opacity=clamp(((vSize/2.0-distance)*dpr),0.0,1.0);fragColor=vColor*opacity;if(uPickingEnabled){fragColor=vPickingColor;}}";
2
2
  export default shader;
@@ -1,2 +1,2 @@
1
- const shader = "uniform float uSagittaScaleFactor;uniform float uMinSagittaLength;in vec2 strip;out vec4 vColor;out float vSize;out float vNormalLengthInPixels;void main(void){float pixelSize=1.0/uDevicePixelRatio;float opacity=getScaled_opacity()*uViewOpacity;vec2 a=vec2(getScaled_x(),getScaled_y())*uViewportSize;vec2 b=vec2(getScaled_x2(),getScaled_y2())*uViewportSize;vec2 chordVector=b-a;vec2 unitChordVector=normalize(chordVector);vec2 chordNormal=vec2(-unitChordVector.y,unitChordVector.x);float sagitta=max(length(chordVector)/2.0*uSagittaScaleFactor,uMinSagittaLength);bool compress=false;if(compress){float maxSagittaLen=length(chordNormal*uViewportSize);float maxChordLen=length(unitChordVector*uViewportSize);float threshold=maxSagittaLen*0.5;if(sagitta>threshold){float m=(maxSagittaLen-threshold)/(maxChordLen-threshold);sagitta=(sagitta-threshold)*m+threshold;}}vec2 controlOffset=chordNormal*sagitta/0.75;vec2 p1=a;vec2 p2=a+controlOffset;vec2 p3=b+controlOffset;vec2 p4=b;float t=smoothstep(0.0,1.0,strip.x);vec2 C1=p4-3.0*p3+3.0*p2-p1;vec2 C2=3.0*p3-6.0*p2+3.0*p1;vec2 C3=3.0*p2-3.0*p1;vec2 C4=p1;vec2 p;if(t==0.0){p=p1;}else if(t==1.0){p=p4;}else{p=C1*t*t*t+C2*t*t+C3*t+C4;}vec2 tangent=normalize(3.0*C1*t*t+2.0*C2*t+C3);vec2 normal=vec2(-tangent.y,tangent.x);\n#ifdef size2_DEFINED\nfloat mixedSize=mix(getScaled_size(),getScaled_size2(),t);\n#else\nfloat mixedSize=getScaled_size();\n#endif\nif(mixedSize<pixelSize){opacity*=mixedSize/pixelSize;mixedSize=pixelSize;}float paddedSize=mixedSize+pixelSize;vNormalLengthInPixels=strip.y*paddedSize;p+=normal*vNormalLengthInPixels;gl_Position=pixelsToNdc(p);\n#ifdef color2_DEFINED\nvec3 color=mix(getScaled_color(),getScaled_color2(),t);\n#else\nvec3 color=getScaled_color();\n#endif\nvColor=vec4(color*opacity,opacity);vSize=paddedSize;setupPicking();}";
1
+ const shader = "uniform float uArcHeightFactor;uniform float uMinArcHeight;uniform float uMinPickingSize;uniform int uShape;uniform int uOrient;uniform bool uClampApex;uniform float uMaxChordLength;uniform vec2 uArcFadingDistance;in vec2 strip;out vec4 vColor;out float vSize;out float vNormalLengthInPixels;const int SHAPE_ARC=0;const int SHAPE_DOME=1;const int SHAPE_DIAGONAL=2;const int SHAPE_LINE=3;const int ORIENT_VERTICAL=0;const int ORIENT_HORIZONTAL=1;float distanceFromLine(vec2 pointOnLine1,vec2 pointOnLine2,vec2 point){vec2 a=point-pointOnLine1;vec2 b=pointOnLine2-pointOnLine1;vec2 proj=dot(a,b)/dot(b,b)*b;return length(a-proj);}bool isInsideViewport(vec2 point,float marginFactor){vec2 margin=uViewportSize*vec2(marginFactor);return point.x>=-margin.x&&point.x<=uViewportSize.x+margin.x&&point.y>=-margin.y&&point.y<=uViewportSize.y+margin.y;}void main(void){float pixelSize=1.0/uDevicePixelRatio;float opacity=getScaled_opacity()*uViewOpacity;vec2 p1,p2,p3,p4;vec2 a=applySampleFacet(vec2(getScaled_x(),getScaled_y()))*uViewportSize;vec2 b=applySampleFacet(vec2(getScaled_x2(),getScaled_y2()))*uViewportSize;if(uShape<=SHAPE_DOME){if(uShape==SHAPE_DOME){vec2 height=vec2(0.0);if(uOrient==ORIENT_VERTICAL){p1=vec2(min(a.x,b.x),b.y);p4=vec2(max(a.x,b.x),b.y);height=vec2(0.0,a.y-b.y);if(uClampApex){if(p4.x>0.0){p1.x=max(p1.x,-p4.x);}if(p1.x<uViewportSize.x){p4.x=min(p4.x,2.0*uViewportSize.x-p1.x);}}}else{p1=vec2(b.x,min(a.y,b.y));p4=vec2(b.x,max(a.y,b.y));height=vec2(a.x-b.x,0.0);if(uClampApex){if(p4.y>0.0){p1.y=max(p1.y,-p4.y);}if(p1.y<uViewportSize.y){p4.y=min(p4.y,2.0*uViewportSize.y-p1.y);}}}vec2 controlOffset=height/0.75;p2=p1+controlOffset;p3=p4+controlOffset;}if(uShape==SHAPE_ARC){p1=a;p4=b;vec2 chordVector=p4-p1;vec2 unitChordVector=normalize(chordVector);vec2 chordNormal=vec2(-unitChordVector.y,unitChordVector.x);float chordLength=length(chordVector);if(chordLength>uMaxChordLength){if(isInsideViewport(p1,2.0)){chordLength=uMaxChordLength;p4=p1+unitChordVector*uMaxChordLength;}else if(isInsideViewport(p4,2.0)){chordLength=uMaxChordLength;p1=p4-unitChordVector*uMaxChordLength;}}float height=max(chordLength/2.0*uArcHeightFactor,uMinArcHeight);vec2 controlOffset=chordNormal*height/0.75;p2=p1+controlOffset;p3=p4+controlOffset;}}else if(uShape==SHAPE_DIAGONAL){if(uOrient==ORIENT_VERTICAL){p1=a;p2=vec2(a.x,(a.y+b.y)/2.0);p3=vec2(b.x,(a.y+b.y)/2.0);p4=b;}else{p1=a;p2=vec2((a.x+b.x)/2.0,a.y);p3=vec2((a.x+b.x)/2.0,b.y);p4=b;}}else if(uShape==SHAPE_LINE){p1=a;p2=(a+b)/2.0;p3=p2;p4=b;}float t=smoothstep(0.0,1.0,strip.x);vec2 C1=p4-3.0*p3+3.0*p2-p1;vec2 C2=3.0*p3-6.0*p2+3.0*p1;vec2 C3=3.0*p2-3.0*p1;vec2 C4=p1;vec2 p;if(t==0.0){p=p1;}else if(t==1.0){p=p4;}else{p=C1*t*t*t+C2*t*t+C3*t+C4;}vec2 tangent=normalize(3.0*C1*t*t+2.0*C2*t+C3);vec2 normal=vec2(-tangent.y,tangent.x);float size=getScaled_size();if(size<pixelSize){opacity*=size/pixelSize;size=pixelSize;}float paddedSize=uPickingEnabled? max(size,uMinPickingSize): size+pixelSize;vNormalLengthInPixels=strip.y*paddedSize;if(uShape==SHAPE_ARC&&uArcFadingDistance[0]>0.0&&uArcFadingDistance[1]>0.0){float d=distanceFromLine(p1,p4,p);float distanceOpacity=smoothstep(uArcFadingDistance[1],uArcFadingDistance[0],d);opacity*=distanceOpacity;if(distanceOpacity<=0.0){vNormalLengthInPixels=0.0;}}p+=normal*vNormalLengthInPixels;gl_Position=pixelsToNdc(p);vec3 color=getScaled_color();vColor=vec4(color*opacity,opacity);vSize=paddedSize;setupPicking();}";
2
2
  export default shader;
@@ -1,2 +1,2 @@
1
- const shader = "const lowp vec4 white=vec4(1.0);const lowp vec4 black=vec4(0.0,0.0,0.0,1.0);uniform bool uInwardStroke;uniform float uGradientStrength;in float vRadius;in float vRadiusWithPadding;in lowp vec4 vFillColor;in lowp vec4 vStrokeColor;in lowp float vShape;in lowp float vHalfStrokeWidth;in mat2 vRotationMatrix;out lowp vec4 fragColor;const float CIRCLE=0.0;const float SQUARE=1.0;const float TRIANGLE_UP=2.0;const float CROSS=3.0;const float DIAMOND=4.0;const float TRIANGLE_DOWN=5.0;const float TRIANGLE_RIGHT=6.0;const float TRIANGLE_LEFT=7.0;float circle(vec2 p,float r){return length(p)-r;}float square(vec2 p,float r){p=abs(p);return max(p.x,p.y)-r;}float equilateralTriangle(vec2 p,float r,bool flip,bool swap){if(swap){p.xy=p.yx;}if(flip){p.y=-p.y;}float k=sqrt(3.0);float kr=k*r;p.y-=kr/2.0;return max((abs(p.x)*k+p.y)/2.0,-p.y-kr);}float crossShape(vec2 p,float r){p=abs(p);vec2 b=vec2(0.4,1.0)*r;vec2 v=abs(p)-b.xy;vec2 h=abs(p)-b.yx;return min(max(v.x,v.y),max(h.x,h.y));}float diamond(vec2 p,float r){p=abs(p);return(max(abs(p.x-p.y),abs(p.x+p.y))-r)/sqrt(2.0);}void main(){float d;vec2 p=vRotationMatrix*(2.0*gl_PointCoord-1.0)*vRadiusWithPadding;float r=vRadius;if(vShape==CIRCLE){d=circle(p,r);}else if(vShape==SQUARE){d=square(p,r);}else if(vShape==TRIANGLE_UP){d=equilateralTriangle(p,r,true,false);}else if(vShape==CROSS){d=crossShape(p,r);}else if(vShape==DIAMOND){d=diamond(p,r);}else if(vShape==TRIANGLE_DOWN){d=equilateralTriangle(p,r,false,false);}else if(vShape==TRIANGLE_RIGHT){d=equilateralTriangle(p,r,false,true);}else if(vShape==TRIANGLE_LEFT){d=equilateralTriangle(p,r,true,true);}else{d=0.0;}if(!uPickingEnabled){lowp vec4 fillColor=mix(vFillColor,white,-d*uGradientStrength/vRadius);fragColor=distanceToColor(d+(uInwardStroke ? vHalfStrokeWidth : 0.0),fillColor,vStrokeColor,vHalfStrokeWidth);}else if(d-vHalfStrokeWidth<=0.0){fragColor=vPickingColor;}else{discard;}}";
1
+ const shader = "const lowp vec4 white=vec4(1.0);const lowp vec4 black=vec4(0.0,0.0,0.0,1.0);uniform bool uInwardStroke;uniform float uGradientStrength;in float vRadius;in float vRadiusWithPadding;in lowp vec4 vFillColor;in lowp vec4 vStrokeColor;in lowp float vShape;in lowp float vHalfStrokeWidth;in mat2 vRotationMatrix;out lowp vec4 fragColor;const float CIRCLE=0.0;const float SQUARE=1.0;const float CROSS=2.0;const float DIAMOND=3.0;const float TRIANGLE_UP=4.0;const float TICK_UP=8.0;float circle(vec2 p,float r){return length(p)-r;}float square(vec2 p,float r){p=abs(p);return max(p.x,p.y)-r;}float tickUp(vec2 p,float r){float halfR=r*0.5;p.y+=halfR;p=abs(p);return max(p.x-r*0.15,p.y-halfR);}float equilateralTriangle(vec2 p,float r){p.y=-p.y;float k=sqrt(3.0);float kr=k*r;p.y-=kr/2.0;return max((abs(p.x)*k+p.y)/2.0,-p.y-kr);}float crossShape(vec2 p,float r){p=abs(p);vec2 b=vec2(0.4,1.0)*r;vec2 v=abs(p)-b.xy;vec2 h=abs(p)-b.yx;return min(max(v.x,v.y),max(h.x,h.y));}float diamond(vec2 p,float r){p=abs(p);return(max(abs(p.x-p.y),abs(p.x+p.y))-r)/sqrt(2.0);}void main(){float d;vec2 p=vRotationMatrix*(2.0*gl_PointCoord-1.0)*vRadiusWithPadding;float r=vRadius;if(vShape==CIRCLE){d=circle(p,r);}else if(vShape==SQUARE){d=square(p,r);}else if(vShape==CROSS){d=crossShape(p,r);}else if(vShape==DIAMOND){d=diamond(p,r);}else if(vShape==TRIANGLE_UP){d=equilateralTriangle(p,r);}else if(vShape==TICK_UP){d=tickUp(p,r);}else{d=0.0;}if(!uPickingEnabled){lowp vec4 fillColor=mix(vFillColor,white,-d*uGradientStrength/vRadius);fragColor=distanceToColor(d+(uInwardStroke ? vHalfStrokeWidth : 0.0),fillColor,vStrokeColor,vHalfStrokeWidth);}else if(d-vHalfStrokeWidth<=0.0){fragColor=vPickingColor;}else{discard;}}";
2
2
  export default shader;
@@ -1,2 +1,2 @@
1
- const shader = "/***The stroke should only grow inwards,e.g,the diameter/outline is not affected by the stroke width.*Thus,a point that has a zero size has no visible stroke. This allows strokes to be used with*geometric zoom,etc.*/uniform bool uInwardStroke;uniform lowp float uMaxRelativePointDiameter;uniform float uScaleFactor;uniform float uMaxPointSize;uniform float uZoomLevel;uniform float uSemanticThreshold;out float vRadius;out float vRadiusWithPadding;out lowp vec4 vFillColor;out lowp vec4 vStrokeColor;out lowp float vShape;out lowp float vHalfStrokeWidth;out mat2 vRotationMatrix;float computeSemanticThresholdFactor(){return getScaled_semanticScore()>=uSemanticThreshold ? 1.0 : 0.0;}/***Computes a scaling factor for the points in a sample-faceted view.*/float getDownscaleFactor(vec2 pos){if(!isFacetedSamples()){return 1.0;}float sampleFacetHeight=getSampleFacetHeight(pos);float maxPointDiameter=sqrt(uMaxPointSize);float factor=sampleFacetHeight*uViewportSize.y*uMaxRelativePointDiameter;return clamp(0.0,maxPointDiameter,factor)/maxPointDiameter;}vec2 getDxDy(){\n#if defined(dx_DEFINED) || defined(dy_DEFINED)\nreturn vec2(getScaled_dx(),getScaled_dy())/uViewportSize;\n#else\nreturn vec2(0.0,0.0);\n#endif\n}void main(void){float semanticThresholdFactor=computeSemanticThresholdFactor();if(semanticThresholdFactor<=0.0){gl_PointSize=0.0;gl_Position=vec4(100.0,0.0,0.0,0.0);return;}float size=getScaled_size();vec2 pos=vec2(getScaled_x(),getScaled_y())+getDxDy();gl_Position=unitToNdc(applySampleFacet(pos));float strokeWidth=getScaled_strokeWidth();float diameter=sqrt(size)*uScaleFactor*semanticThresholdFactor*getDownscaleFactor(pos);float opacity=uViewOpacity;if(strokeWidth<=0.0||uInwardStroke){float minDiameter=1.0/uDevicePixelRatio;if(diameter<minDiameter){opacity*=pow(diameter/minDiameter,2.5);diameter=minDiameter;}}float fillOpa=getScaled_fillOpacity()*opacity;float strokeOpa=getScaled_strokeOpacity()*opacity;vShape=getScaled_shape();bool circle=vShape==0.0;float angleInDegrees=getScaled_angle();float angle=-angleInDegrees*PI/180.0;float sinTheta=sin(angle);float cosTheta=cos(angle);vRotationMatrix=mat2(cosTheta,sinTheta,-sinTheta,cosTheta);float roomForRotation=circle ? 1.0 : sin(mod(angle,PI/2.0)+PI/4.0)/sin(PI/4.0);float aaPadding=1.0/uDevicePixelRatio;float rotationPadding=(diameter*roomForRotation)-diameter;float strokePadding=uInwardStroke ? 0.0 : strokeWidth*(circle ? 1.0 : sqrt(3.0));float padding=rotationPadding+strokePadding+aaPadding;gl_PointSize=(diameter+padding)*uDevicePixelRatio;vRadius=diameter/2.0;vRadiusWithPadding=vRadius+padding/2.0;vHalfStrokeWidth=strokeWidth/2.0;vFillColor=vec4(getScaled_fill()*fillOpa,fillOpa);vStrokeColor=vec4(getScaled_stroke()*strokeOpa,strokeOpa);setupPicking();}";
1
+ const shader = "/***The stroke should only grow inwards,e.g,the diameter/outline is not affected by the stroke width.*Thus,a point that has a zero size has no visible stroke. This allows strokes to be used with*geometric zoom,etc.*/uniform bool uInwardStroke;uniform lowp float uMaxRelativePointDiameter;uniform float uScaleFactor;uniform float uMaxPointSize;uniform float uZoomLevel;uniform float uSemanticThreshold;out float vRadius;out float vRadiusWithPadding;out lowp vec4 vFillColor;out lowp vec4 vStrokeColor;out lowp float vShape;out lowp float vHalfStrokeWidth;out mat2 vRotationMatrix;const float CIRCLE=0.0;const float SQUARE=1.0;const float CROSS=2.0;const float DIAMOND=3.0;const float TRIANGLE_UP=4.0;const float TRIANGLE_RIGHT=5.0;const float TRIANGLE_DOWN=6.0;const float TRIANGLE_LEFT=7.0;const float TICK_UP=8.0;const float TICK_RIGHT=9.0;const float TICK_DOWN=10.0;const float TICK_LEFT=11.0;float computeSemanticThresholdFactor(){return getScaled_semanticScore()>=uSemanticThreshold ? 1.0 : 0.0;}/***Computes a scaling factor for the points in a sample-faceted view.*/float getDownscaleFactor(vec2 pos){if(!isFacetedSamples()){return 1.0;}float sampleFacetHeight=getSampleFacetHeight(pos);float maxPointDiameter=sqrt(uMaxPointSize);float factor=sampleFacetHeight*uViewportSize.y*uMaxRelativePointDiameter;return clamp(0.0,maxPointDiameter,factor)/maxPointDiameter;}vec2 getDxDy(){\n#if defined(dx_DEFINED) || defined(dy_DEFINED)\nreturn vec2(getScaled_dx(),getScaled_dy())/uViewportSize;\n#else\nreturn vec2(0.0,0.0);\n#endif\n}void main(void){float shapeAngle=0.0;float semanticThresholdFactor=computeSemanticThresholdFactor();if(semanticThresholdFactor<=0.0){gl_PointSize=0.0;gl_Position=vec4(100.0,0.0,0.0,0.0);return;}float size=getScaled_size();vec2 pos=vec2(getScaled_x(),getScaled_y())+getDxDy();gl_Position=unitToNdc(applySampleFacet(pos));float strokeWidth=getScaled_strokeWidth();float diameter=sqrt(size)*uScaleFactor*semanticThresholdFactor*getDownscaleFactor(pos);float opacity=uViewOpacity;if(strokeWidth<=0.0||uInwardStroke){float minDiameter=1.0/uDevicePixelRatio;if(diameter<minDiameter){opacity*=pow(diameter/minDiameter,2.5);diameter=minDiameter;}}float fillOpa=getScaled_fillOpacity()*opacity;float strokeOpa=getScaled_strokeOpacity()*opacity;vShape=getScaled_shape();bool circle=vShape==0.0;if(vShape>TICK_UP&&vShape<=TICK_LEFT){shapeAngle=(vShape-TICK_UP)*90.0;vShape=TICK_UP;}else if(vShape>TRIANGLE_UP&&vShape<=TRIANGLE_LEFT){shapeAngle=(vShape-TRIANGLE_UP)*90.0;vShape=TRIANGLE_UP;}float angleInDegrees=getScaled_angle();float angle=-(shapeAngle+angleInDegrees)*PI/180.0;float sinTheta=sin(angle);float cosTheta=cos(angle);vRotationMatrix=mat2(cosTheta,sinTheta,-sinTheta,cosTheta);float roomForRotation=circle ? 1.0 : sin(mod(angle,PI/2.0)+PI/4.0)/sin(PI/4.0);float aaPadding=1.0/uDevicePixelRatio;float rotationPadding=(diameter*roomForRotation)-diameter;float strokePadding=uInwardStroke ? 0.0 : strokeWidth*(circle ? 1.0 : sqrt(3.0));float padding=rotationPadding+strokePadding+aaPadding;gl_PointSize=(diameter+padding)*uDevicePixelRatio;vRadius=diameter/2.0;vRadiusWithPadding=vRadius+padding/2.0;vHalfStrokeWidth=strokeWidth/2.0;vFillColor=vec4(getScaled_fill()*fillOpa,fillOpa);vStrokeColor=vec4(getScaled_stroke()*strokeOpa,strokeOpa);setupPicking();}";
2
2
  export default shader;
@@ -1 +1 @@
1
- {"version":3,"file":"link.d.ts","sourceRoot":"","sources":["../../../src/marks/link.js"],"names":[],"mappings":"AAOA;IAqGQ;;;;;;MAKC;CAkDR;iBA9JgB,WAAW"}
1
+ {"version":3,"file":"link.d.ts","sourceRoot":"","sources":["../../../src/marks/link.js"],"names":[],"mappings":"AAWA;IA0HQ;;;;;;MAKC;CAkDR;iBAvLgB,WAAW"}
@@ -1,9 +1,13 @@
1
1
  import { drawBufferInfo, setBuffersAndAttributes, setUniforms } from "twgl.js";
2
2
  import VERTEX_SHADER from "../gl/link.vertex.glsl.js";
3
3
  import FRAGMENT_SHADER from "../gl/link.fragment.glsl.js";
4
- import { ConnectionVertexBuilder } from "../gl/dataToVertices.js";
4
+ import { LinkVertexBuilder } from "../gl/dataToVertices.js";
5
5
 
6
6
  import Mark from "./mark.js";
7
+ import { isChannelDefWithScale } from "../encoder/encoder.js";
8
+
9
+ const LINK_SHAPES = ["arc", "dome", "diagonal", "line"];
10
+ const ORIENTS = ["vertical", "horizontal"];
7
11
 
8
12
  export default class LinkMark extends Mark {
9
13
  /**
@@ -24,8 +28,15 @@ export default class LinkMark extends Mark {
24
28
  opacity: 1.0,
25
29
 
26
30
  segments: 101, // Performance is affected more by the fill rate, i.e. number of pixels
27
- sagittaScaleFactor: 1.0,
28
- minSagittaLength: 1.5,
31
+ arcHeightFactor: 1.0,
32
+ minArcHeight: 1.5,
33
+ minPickingSize: 3.0,
34
+ clampApex: false,
35
+ maxChordLength: 50000,
36
+ arcFadingDistance: false,
37
+
38
+ linkShape: "arc",
39
+ orient: "vertical",
29
40
  })
30
41
  );
31
42
  }
@@ -55,12 +66,20 @@ export default class LinkMark extends Mark {
55
66
  * @returns {import("../spec/channel.js").Encoding}
56
67
  */
57
68
  fixEncoding(encoding) {
58
- if (!encoding.x) {
59
- encoding.x2 = encoding.x;
69
+ if (!encoding.x2) {
70
+ if (isChannelDefWithScale(encoding.x)) {
71
+ encoding.x2 = { datum: 0.0 };
72
+ } else {
73
+ encoding.x2 = encoding.x;
74
+ }
60
75
  }
61
76
 
62
77
  if (!encoding.y2) {
63
- encoding.y2 = encoding.y;
78
+ if (isChannelDefWithScale(encoding.y)) {
79
+ encoding.y2 = { datum: 0.0 };
80
+ } else {
81
+ encoding.y2 = encoding.y;
82
+ }
64
83
  }
65
84
 
66
85
  return encoding;
@@ -80,8 +99,14 @@ export default class LinkMark extends Mark {
80
99
 
81
100
  // TODO: Use uniform block.
82
101
  setUniforms(this.programInfo, {
83
- uSagittaScaleFactor: props.sagittaScaleFactor,
84
- uMinSagittaLength: props.minSagittaLength,
102
+ uArcHeightFactor: props.arcHeightFactor,
103
+ uMinArcHeight: props.minArcHeight,
104
+ uMinPickingSize: props.minPickingSize,
105
+ uShape: LINK_SHAPES.indexOf(props.linkShape),
106
+ uOrient: ORIENTS.indexOf(props.orient),
107
+ uClampApex: !!props.clampApex,
108
+ uMaxChordLength: props.maxChordLength,
109
+ uArcFadingDistance: props.arcFadingDistance || [0, 0],
85
110
  });
86
111
  }
87
112
 
@@ -89,7 +114,7 @@ export default class LinkMark extends Mark {
89
114
  const collector = this.unitView.getCollector();
90
115
  const itemCount = collector.getItemCount();
91
116
 
92
- const builder = new ConnectionVertexBuilder({
117
+ const builder = new LinkVertexBuilder({
93
118
  encoders: this.encoders,
94
119
  attributes: this.getAttributes(),
95
120
  numItems: itemCount,
@@ -115,10 +115,7 @@ export default class Mark {
115
115
  program: WebGLProgram;
116
116
  getProgramErrors: () => {
117
117
  message: string;
118
- detail: string; /**
119
- *
120
- * @param {any} vertexData TODO: Extract type from VertexBuilder
121
- */
118
+ detail: string;
122
119
  };
123
120
  };
124
121
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"mark.d.ts","sourceRoot":"","sources":["../../../src/marks/mark.js"],"names":[],"mappings":";AAwCA,0DAA2D;AAC3D,0DAA2D;AAE3D;;;;;;;;;;;;GAYG;AACH;IACI;;;;;OAKG;IAEH;;OAEG;IACH,sBAFW,OAAO,qBAAqB,EAAE,OAAO,EAoE/C;IAjEG,gDAAwB;IAExB,oEAAoE;IACpE,UADW,OAAO,MAAM,EAAE,OAAO,qBAAqB,EAAE,OAAO,CAAC,CACvC;IAIzB,0FAA0F;IAC1F,YADW,OAAO,SAAS,EAAE,UAAU,GAAG;QAAE,iBAAiB,CAAC,EAAE,MAAM,CAAA;KAAE,CAC7C;IAE3B,0DAA0D;IAC1D,aADW,OAAO,SAAS,EAAE,WAAW,CACZ;IAE5B,8DAA8D;IAC9D,iBADW,OAAO,SAAS,EAAE,eAAe,CACZ;IAEhC,+DAA+D;IAC/D,mBADW,OAAO,SAAS,EAAE,gBAAgB,CACX;IAElC,+DAA+D;IAC/D,iBADW,OAAO,SAAS,EAAE,gBAAgB,CACb;IAEhC,kFAAkF;IAClF,UADW,SAAS,GAAG,CAAC,CACM;IAG9B,yBAAyB;IACzB,wDAqBC;IAED;;;;;;;;OAQG;IACH,mEAKC;IAGL,sBAEC;IAED;;;;;;;OAOG;IACH,iBAFa,MAAM,EAAE,CAKpB;IAED;;OAEG;IACH,+DAWC;IAED;;OAEG;IACH,oEAcC;IAED;;;;;OAKG;IACH,oHAEC;IAED;;;;OAIG;IACH,8DAyCC;IAED,wDAEC;IAED,8CAEC;IAED,uBAEC;IAED;;;OAGG;IACH,2BAEC;IAED;;OAEG;IACH,oCAEC;IAED;;OAEG;IACH,2BAEC;IAED,sEAeC;IAED;;;;;OAKG;IACH,mCAJW,MAAM,kBACN,MAAM,iBACN,MAAM,EAAE,QA+FlB;IAtFG,uBAAuB;IACvB,gBADW,MAAM,EAAE,CACK;IAgFxB;;;;4BAgGJ;;;eAGG;;MA/FE;IAGL;;;OAGG;IACH,uCA2CC;IAED,mBAgBC;IAED;;OAEG;IACH,2BAiBC;IAED;;;OAGG;IACH,6BAFW,GAAG,QAoCb;IAED,yBAAyB;IACzB,uDAEC;IAED,yBAAyB;IACzB,iCAEC;IAED,gCAEC;IAED,+BAEC;IAED,yCAEC;IAED;;;;;OAKG;IACH,gCAcC;IAED;;;;;;;;OAQG;IAEH,uBAJW,OAAO,uBAAuB,EAAE,sBAAsB,GACpD,CAAC,MAAM,IAAI,CAAC,EAAE,CA+H1B;IAED;;;;;;OAMG;IACH,qCAJW,oBAAoB,GAClB,OAAO,CAqCnB;IAED;;;;;;;OAOG;IACH,gBAJW,oBAAoB,SACP,IAAI,CAM3B;IAED;;;OAGG;IACH,2BAHW,YAAY,WACZ,OAAO,WAAW,EAAE,oBAAoB,cAiElD;IAED;;;;;;OAMG;IACH,oBAJW,OAAO,6BAA6B,EAAE,OAAO,aAC7C,OAAO,6BAA6B,EAAE,OAAO,GAC3C,OAAO,CAuHnB;IAED;;;;;;;;;OASG;IACH,qBAJW,MAAM,KACN,OAAO,oBAAoB,EAAE,MAAM,GACjC,GAAG,CAIf;CACJ;+BA75BY,OAAO,uBAAuB,EAAE,gBAAgB;;;;;;wBAEnD,OAAO;;mCAEJ,gBAAgB,GAAG,qBAAqB;oCAG1C,MAAM,SACN,MAAM;AAu5BjB;;;GAGG;AACH;IACI,cAEC;IAkBD;;;OAGG;IACH,2BAFW,IAAI,CAAC,EAAE,OAAO,yBAAyB,EAAE,UAAU,CAAC,QAM9D;CACJ;0BA18ByB,WAAW"}
1
+ {"version":3,"file":"mark.d.ts","sourceRoot":"","sources":["../../../src/marks/mark.js"],"names":[],"mappings":";AAwCA,0DAA2D;AAC3D,0DAA2D;AAE3D;;;;;;;;;;;;GAYG;AACH;IACI;;;;;OAKG;IAEH;;OAEG;IACH,sBAFW,OAAO,qBAAqB,EAAE,OAAO,EAoE/C;IAjEG,gDAAwB;IAExB,oEAAoE;IACpE,UADW,OAAO,MAAM,EAAE,OAAO,qBAAqB,EAAE,OAAO,CAAC,CACvC;IAIzB,0FAA0F;IAC1F,YADW,OAAO,SAAS,EAAE,UAAU,GAAG;QAAE,iBAAiB,CAAC,EAAE,MAAM,CAAA;KAAE,CAC7C;IAE3B,0DAA0D;IAC1D,aADW,OAAO,SAAS,EAAE,WAAW,CACZ;IAE5B,8DAA8D;IAC9D,iBADW,OAAO,SAAS,EAAE,eAAe,CACZ;IAEhC,+DAA+D;IAC/D,mBADW,OAAO,SAAS,EAAE,gBAAgB,CACX;IAElC,+DAA+D;IAC/D,iBADW,OAAO,SAAS,EAAE,gBAAgB,CACb;IAEhC,kFAAkF;IAClF,UADW,SAAS,GAAG,CAAC,CACM;IAG9B,yBAAyB;IACzB,wDAqBC;IAED;;;;;;;;OAQG;IACH,mEAKC;IAGL,sBAEC;IAED;;;;;;;OAOG;IACH,iBAFa,MAAM,EAAE,CAKpB;IAED;;OAEG;IACH,+DAWC;IAED;;OAEG;IACH,oEAcC;IAED;;;;;OAKG;IACH,oHAEC;IAED;;;;OAIG;IACH,8DAyCC;IAED,wDAEC;IAED,8CAEC;IAED,uBAEC;IAED;;;OAGG;IACH,2BAEC;IAED;;OAEG;IACH,oCAEC;IAED;;OAEG;IACH,2BAEC;IAED,sEAeC;IAED;;;;;OAKG;IACH,mCAJW,MAAM,kBACN,MAAM,iBACN,MAAM,EAAE,QA+FlB;IAtFG,uBAAuB;IACvB,gBADW,MAAM,EAAE,CACK;IAgFxB;;;;;;MAIC;IAGL;;;OAGG;IACH,uCA4CC;IAED,mBAgBC;IAED;;OAEG;IACH,2BAiBC;IAED;;;OAGG;IACH,6BAFW,GAAG,QAoCb;IAED,yBAAyB;IACzB,uDAEC;IAED,yBAAyB;IACzB,iCAEC;IAED,gCAEC;IAED,+BAEC;IAED,yCAEC;IAED;;;;;OAKG;IACH,gCAcC;IAED;;;;;;;;OAQG;IAEH,uBAJW,OAAO,uBAAuB,EAAE,sBAAsB,GACpD,CAAC,MAAM,IAAI,CAAC,EAAE,CA+H1B;IAED;;;;;;OAMG;IACH,qCAJW,oBAAoB,GAClB,OAAO,CAqCnB;IAED;;;;;;;OAOG;IACH,gBAJW,oBAAoB,SACP,IAAI,CAM3B;IAED;;;OAGG;IACH,2BAHW,YAAY,WACZ,OAAO,WAAW,EAAE,oBAAoB,cAiElD;IAED;;;;;;OAMG;IACH,oBAJW,OAAO,6BAA6B,EAAE,OAAO,aAC7C,OAAO,6BAA6B,EAAE,OAAO,GAC3C,OAAO,CAuHnB;IAED;;;;;;;;;OASG;IACH,qBAJW,MAAM,KACN,OAAO,oBAAoB,EAAE,MAAM,GACjC,GAAG,CAIf;CACJ;+BA95BY,OAAO,uBAAuB,EAAE,gBAAgB;;;;;;wBAEnD,OAAO;;mCAEJ,gBAAgB,GAAG,qBAAqB;oCAG1C,MAAM,SACN,MAAM;AAw5BjB;;;GAGG;AACH;IACI,cAEC;IAkBD;;;OAGG;IACH,2BAFW,IAAI,CAAC,EAAE,OAAO,yBAAyB,EAAE,UAAU,CAAC,QAM9D;CACJ;0BA38ByB,WAAW"}
@@ -441,6 +441,7 @@ export default class Mark {
441
441
  // left pos, left height, right pos, right height
442
442
  uSampleFacet: [0, 1, 0, 1],
443
443
  uTransitionOffset: 0.0,
444
+ uZero: 0.0,
444
445
  });
445
446
  }
446
447
 
@@ -328,6 +328,30 @@ export interface PointProps extends AngleProps {
328
328
  }
329
329
 
330
330
  export interface LinkProps extends SecondaryPositionProps {
331
+ /**
332
+ * The shape of the link path. Either `"arc"`, `"diagonal"`, `"line"`, or `"dome"`.
333
+ *
334
+ * **Default value:** `"arc"`
335
+ */
336
+ linkShape?: "arc" | "diagonal" | "line" | "dome";
337
+
338
+ /**
339
+ * The orientation of the link path. Either `"vertical"` or `"horizontal"`.
340
+ * Only applies to diagonal links.
341
+ *
342
+ * **Default value:** `"vertical"`
343
+ */
344
+ orient?: "vertical" | "horizontal";
345
+
346
+ /**
347
+ * Whether the apex of the `"dome"` shape is clamped to the viewport edge. When over a
348
+ * half of the dome is located outside the viewport, clamping allows for more accurate
349
+ * reading of the value encoded by the apex' position.
350
+ *
351
+ * **Default value:** `false`
352
+ */
353
+ clampApex?: boolean;
354
+
331
355
  /**
332
356
  * The number of segments in the bézier curve. Affects the rendering quality and performance.
333
357
  * Use a higher value for a smoother curve.
@@ -337,28 +361,47 @@ export interface LinkProps extends SecondaryPositionProps {
337
361
  segments?: number;
338
362
 
339
363
  /**
340
- * Scaling factor of the arc's sagitta. The default value `1.0` produces roughly circular arcs.
364
+ * Scaling factor for the `"arc`" shape's height. The default value `1.0` produces roughly circular arcs.
341
365
  *
342
366
  * **Default value:** `1.0`
343
367
  */
344
- sagittaScaleFactor?: number;
368
+ arcHeightFactor?: number;
345
369
 
346
370
  /**
347
- * Minimum length of the arc's sagitta. Makes very short links more clearly visible.
371
+ * The minimum height of an `"arc"` shape. Makes very short links more clearly visible.
348
372
  *
349
373
  * **Default value:** `1.5`
350
374
  */
351
- minSagittaLength?: number;
375
+ minArcHeight?: number;
352
376
 
353
377
  /**
354
- * TODO
378
+ * The maximum length of `"arc"` shape's chord in pixels. The chord is the line segment
379
+ * between the two points that define the arc. Limiting the chord length serves two purposes
380
+ * when zooming in close enough:
381
+ * 1) it prevents the arc from becoming a straight line and
382
+ * 2) it mitigates the limited precision of floating point numbers in arc rendering.
383
+ *
384
+ * **Default value:** `50000`
355
385
  */
356
- color2?: string;
386
+ maxChordLength?: number;
357
387
 
358
388
  /**
359
- * TODO
389
+ * The range of the `"arc"` shape's fading distance in pixels. This property allows for
390
+ * making the arc's opacity fade out as it extends away from the chord. The fading distance
391
+ * is interpolated from one to zero between the interval defined by this property.
392
+ * Both `false` and `[0, 0]` disable fading.
393
+ *
394
+ * **Default value:** `false`
395
+ */
396
+ arcFadingDistance?: [number, number] | false;
397
+
398
+ /**
399
+ * The minimum stroke width of the links when pointing with the mouse cursor.
400
+ * Allows making very thin links easier to point at.
401
+ *
402
+ * **Default value:** `3.0`
360
403
  */
361
- size2?: number;
404
+ minPickingSize?: number;
362
405
  }
363
406
 
364
407
  // TODO: Mark-specific configs
@@ -93,7 +93,7 @@ export class GridChild {
93
93
  /** @type {Partial<Record<import("../spec/axis.js").AxisOrient, AxisGridView>>} gridLines */
94
94
  gridLines: Partial<Record<import("../spec/axis.js").AxisOrient, AxisGridView>>;
95
95
  /** @type {Partial<Record<ScrollDirection, Scrollbar>>} */
96
- scrollbars: Partial<Record<"horizontal" | "vertical", Scrollbar>>;
96
+ scrollbars: Partial<Record<"vertical" | "horizontal", Scrollbar>>;
97
97
  /** @type {UnitView} */
98
98
  title: UnitView;
99
99
  /** @type {Rectangle} */
@@ -116,12 +116,12 @@ declare class Scrollbar extends UnitView {
116
116
  * @param {GridChild} gridChild
117
117
  * @param {ScrollDirection} scrollDirection
118
118
  */
119
- constructor(gridChild: GridChild, scrollDirection: "horizontal" | "vertical");
119
+ constructor(gridChild: GridChild, scrollDirection: "vertical" | "horizontal");
120
120
  config: {
121
121
  scrollbarSize: number;
122
122
  scrollbarPadding: number;
123
123
  };
124
- scrollDirection: "horizontal" | "vertical";
124
+ scrollDirection: "vertical" | "horizontal";
125
125
  viewportOffset: number;
126
126
  maxScrollOffset: number;
127
127
  scrollbarCoords: Rectangle;
@@ -1 +1 @@
1
- {"version":3,"file":"scaleResolution.d.ts","sourceRoot":"","sources":["../../../src/view/scaleResolution.js"],"names":[],"mappings":"AAy0BA;;;;;;;;;;GAUG;AACH,6CAFW,OAAO,WAAW,EAAE,OAAO,GAAG,OAAO,WAAW,EAAE,OAAO,EAAE,QA4BrE;AA/zBD,0CAA2C;AAC3C,gCAAiC;AACjC,gCAAiC;AACjC,4BAA6B;AAC7B,4BAA6B;AAE7B;;;;GAIG;AACH;;;;;;;GAOG;AACH;IAyBI;;OAEG;IACH,2DASC;IARG,8CAAsB;IACtB,oDAAoD;IACpD,SADW,gBAAgB,EAAE,CACZ;IACjB,+DAA+D;IAC/D,MADW,MAAM,CACD;IAEhB,iEAAiE;IACjE,MADW,MAAM,CACI;IAGzB;;;;;;;OAOG;IACH,uBAHW,QAAQ,oFAQlB;IAED;;;OAGG;IACH,0BAHW,QAAQ,oFAQlB;IAWD;;;;;;OAMG;IACH,kHA0BC;IAED;;OAEG;IACH,4BAEC;IAED,+BAiBC;IAuBD;;;;;OAKG;IACH,iBAFa,OAAO,kBAAkB,EAAE,KAAK,CA+D5C;IAYD;;;;OAIG;IACH,qEAMC;IAED;;;;OAIG;IACH,+DAQC;IAED;;OAEG;IACH,oBAkCC;IAED;;OAEG;IACH,oDAmBC;IAED,mBAEC;IAED;;OAEG;IACH,oBAFa,mFAA6B,CAOzC;IAED;;;;OAIG;IACH,oBAKC;IAED;;OAEG;IACH,sBAGC;IAUD;;;;;;;OAOG;IACH,kBALW,MAAM,eACN,MAAM,OACN,MAAM,GACJ,OAAO,CAwEnB;IAED;;;;;;OAMG;IACH,eAJW,mFAA6B,aAC7B,OAAO,GAAG,MAAM,iBAgD1B;IAED;;;;OAIG;IACH,qBAcC;IAED;;;;;OAKG;IACH,uBAOC;IA2DD;;;OAGG;IACH,aAFa,OAAO,qBAAqB,EAAE,OAAO,CAajD;IAID;;;;;OAKG;IACH,uBAFW,MAAM,yDAUhB;IAED;;OAEG;IACH,iBAFW,MAAM,yDAKhB;IAED;;;OAGG;IACH,6EAFa,MAAM,CAQlB;IAED;;;OAGG;IACH,mHAFa,MAAM,EAAE,CAOpB;;CA6BJ;wIA3rBY;IAAC,IAAI,EAAE,OAAO,eAAe,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,CAAC,CAAA;CAAC"}
1
+ {"version":3,"file":"scaleResolution.d.ts","sourceRoot":"","sources":["../../../src/view/scaleResolution.js"],"names":[],"mappings":"AA20BA;;;;;;;;;;GAUG;AACH,6CAFW,OAAO,WAAW,EAAE,OAAO,GAAG,OAAO,WAAW,EAAE,OAAO,EAAE,QA4BrE;AAl0BD,0CAA2C;AAC3C,gCAAiC;AACjC,gCAAiC;AACjC,4BAA6B;AAC7B,4BAA6B;AAE7B;;;;GAIG;AACH;;;;;;;GAOG;AACH;IAyBI;;OAEG;IACH,2DASC;IARG,8CAAsB;IACtB,oDAAoD;IACpD,SADW,gBAAgB,EAAE,CACZ;IACjB,+DAA+D;IAC/D,MADW,MAAM,CACD;IAEhB,iEAAiE;IACjE,MADW,MAAM,CACI;IAGzB;;;;;;;OAOG;IACH,uBAHW,QAAQ,oFAQlB;IAED;;;OAGG;IACH,0BAHW,QAAQ,oFAQlB;IAWD;;;;;;OAMG;IACH,kHA0BC;IAED;;OAEG;IACH,4BAEC;IAED,+BAiBC;IAuBD;;;;;OAKG;IACH,iBAFa,OAAO,kBAAkB,EAAE,KAAK,CA+D5C;IAYD;;;;OAIG;IACH,qEAMC;IAED;;;;OAIG;IACH,+DAQC;IAED;;OAEG;IACH,oBAkCC;IAED;;OAEG;IACH,oDAmBC;IAED,mBAEC;IAED;;OAEG;IACH,oBAFa,mFAA6B,CAOzC;IAED;;;;OAIG;IACH,oBAKC;IAED;;OAEG;IACH,sBAGC;IAUD;;;;;;;OAOG;IACH,kBALW,MAAM,eACN,MAAM,OACN,MAAM,GACJ,OAAO,CAwEnB;IAED;;;;;;OAMG;IACH,eAJW,mFAA6B,aAC7B,OAAO,GAAG,MAAM,iBAgD1B;IAED;;;;OAIG;IACH,qBAcC;IAED;;;;;OAKG;IACH,uBAOC;IA8DD;;;OAGG;IACH,aAFa,OAAO,qBAAqB,EAAE,OAAO,CAajD;IAID;;;;;OAKG;IACH,uBAFW,MAAM,yDAUhB;IAED;;OAEG;IACH,iBAFW,MAAM,yDAKhB;IAED;;;OAGG;IACH,6EAFa,MAAM,CAQlB;IAED;;;OAGG;IACH,mHAFa,MAAM,EAAE,CAOpB;;CA6BJ;wIA9rBY;IAAC,IAAI,EAAE,OAAO,eAAe,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,CAAC,CAAA;CAAC"}
@@ -23,7 +23,6 @@ import createScale, { configureScale } from "../scale/scale.js";
23
23
  import { invalidate, getCachedOrCall } from "../utils/propertyCacher.js";
24
24
  import {
25
25
  getChannelDefWithScale,
26
- getDiscreteRange,
27
26
  isColorChannel,
28
27
  isDiscreteChannel,
29
28
  isPositionalChannel,
@@ -649,7 +648,10 @@ export default class ScaleResolution {
649
648
  : "viridis";
650
649
  } else if (isDiscreteChannel(channel)) {
651
650
  // Shapes of point mark, for example
652
- props.range = getDiscreteRange(channel);
651
+ props.range =
652
+ channel == "shape"
653
+ ? ["circle", "square", "triangle-up", "cross", "diamond"]
654
+ : [];
653
655
  } else if (channel == "size") {
654
656
  props.range = [0, 400]; // TODO: Configurable default. This is currently optimized for points.
655
657
  } else if (channel == "angle") {
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  },
8
8
  "contributors": [],
9
9
  "license": "MIT",
10
- "version": "0.38.0",
10
+ "version": "0.40.0",
11
11
  "jsdelivr": "dist/bundle/index.js",
12
12
  "unpkg": "dist/bundle/index.js",
13
13
  "browser": "dist/bundle/index.js",
@@ -65,5 +65,5 @@
65
65
  "vega-scale": "^7.1.1",
66
66
  "vega-util": "^1.16.0"
67
67
  },
68
- "gitHead": "cd0ae7c4bc32d3a8937b04baa14af742b0fab889"
68
+ "gitHead": "74d4f6721b31c1916051f868e95be7d83d8d6369"
69
69
  }