Skip to content

Commit

Permalink
scaling fix
Browse files Browse the repository at this point in the history
  • Loading branch information
bmschmidt committed Jun 4, 2024
1 parent ded9c8a commit fe4f9a0
Show file tree
Hide file tree
Showing 9 changed files with 130 additions and 71 deletions.
3 changes: 2 additions & 1 deletion dev/FourClasses.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import SwitchPositions from './svelte/SwitchPositions.svelte';
import ColorChange from './svelte/ColorChange.svelte';
import SizeSlider from './svelte/SizeSlider.svelte';
import PositionScales from './svelte/PositionScales.svelte';
const startSize = 2;
const prefs = {
source_url: '/tiles',
Expand Down Expand Up @@ -41,6 +41,7 @@
<SwitchPositions {scatterplot}></SwitchPositions>
<ColorChange {scatterplot}></ColorChange>
<SizeSlider size={startSize} {scatterplot}></SizeSlider>
<PositionScales {scatterplot} />
</div>

<div id="deepscatter"></div>
Expand Down
22 changes: 8 additions & 14 deletions dev/svelte/ColorChange.svelte
Original file line number Diff line number Diff line change
@@ -1,30 +1,24 @@
<script lang="ts">
export let scatterplot;
let value = 'category10';
const schemes = [
'okabe',
'category10',
'dark2',
'pastel2'
]
const schemes = ['okabe', 'category10', 'dark2', 'pastel2'];
function changeColor() {
scatterplot.plotAPI({
encoding: {
color: {
field: scatterplot.prefs.encoding.color.field,
range: value,
// range: ["red", "yellow", "pink", "purple"],
// domain: ["Apple", "Banana", "Strawberry", "Mulberry"]
}
}
})
// range: ["red", "yellow", "pink", "purple"],
// domain: ["Apple", "Banana", "Strawberry", "Mulberry"]
},
},
});
}
</script>

<select bind:value={value} on:change={changeColor}>
<select bind:value on:change={changeColor}>
{#each schemes as scheme}
<option value={scheme}>{scheme}</option>
{/each}
</select>
</select>
70 changes: 70 additions & 0 deletions dev/svelte/PositionScales.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<script lang="ts">
export let scatterplot;
function plotBigX() {
scatterplot.plotAPI({
encoding: {
x: {
field: 'x',
domain: [-1, 1],
range: [-2, 2],
transform: 'linear',
},
y: {
field: 'y',
domain: [-1, 1],
range: [-3, 3],
transform: 'linear',
},
},
});
// for (let d of ['x', 'y']) {
// scatterplot.deeptable.transformations[`big_${d}`] = async function (
// tile,
// ) {
// const trueVals = (await tile.get_column(d)).toArray();
// const out = new Float32Array(trueVals.length);
// for (let i = 0; i < out.length; i++) {
// out[i] = trueVals[i] * 2;
// }
// return out;
// };
// }
// scatterplot.plotAPI({
// encoding: {
// x: {
// field: 'big_x',
// transform: 'linear',
// domain: scatterplot.deeptable.extent.x.map((d) => d * 2),
// range: scatterplot.deeptable.extent.x,
// },
// y: {
// field: 'big_y',
// transform: 'linear',
// domain: scatterplot.deeptable.extent.y.map((d) => d * 2),
// range: scatterplot.deeptable.extent.y,
// },
// },
// });
}
function plotNormal() {
scatterplot.plotAPI({
encoding: {
x: {
field: 'x',
domain: [-1, 1],
range: [-1, 1],
},
y: {
field: 'y',
domain: [-1, 1],
range: [-2, 2],
},
},
});
}
</script>

<button on:click={plotBigX}>big x</button>
<button on:click={plotNormal}>normal x</button>
2 changes: 1 addition & 1 deletion src/aesthetics/ScaledAesthetic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ export abstract class ScaledAesthetic<
TODO: integer and bool support.
}*/ else {
throw new Error(
'Only dictionary columns can create categorical values for now scales.',
'Only dictionary columns can create categorical values for new scales.',
);
}
return values as Input['domainType'][];
Expand Down
29 changes: 20 additions & 9 deletions src/glsl/general.vert
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,10 @@ float linstep(in vec2 range, in float x) {
return clamp(from_left / scale_size, 0.0, 1.0);
}


/**
Given a range and a value, return the value scaled to between 0 and 1.
*/
float linscale(in vec2 range, in float x) {
float scale_size = range.y - range.x;
float from_left = x - range.x;
Expand All @@ -501,9 +505,19 @@ vec2 box_muller(in float ix, in float seed) {
/*************** END COLOR SCALES *******************************/


/**
* Clamp an attribute into a domain, with an optional log or sqrt transform.
* @param domain The domain to clamp into.
* @param transform The type of transform to apply.
* @param attr The value to place in the scale to transform.
* @param overflow_behavior
0 : extrapolate
1 : clamp
2 : wrap
* @return The transformed attribute on a range between zero and one.
*/
float domainify(in vec2 domain, in float transform, in float attr, in float overflow_behavior) {


// Clamp an attribute into a domain, with an optional log or sqrt transform.
if (transform == 2.) {
domain = sqrt(domain);
Expand Down Expand Up @@ -627,19 +641,16 @@ vec2 calculate_position(in vec2 position, in float x_scale_type,
float y;

if (x_scale_type < 4.0) {
float x_ = linscale(u_color_domain, a_color);
x = texture_float_lookup(x_domain, x_range,
x_scale_type,
position.x, 0. // ymap position 0 means never use a texture lookup.
);
// scaled between zero and one.
float scaled = domainify(x_domain, x_scale_type, position.x, 0.0);
x = mix(x_range.x, x_range.y, scaled);
} else {
x = position.x;
}

if (y_scale_type < 4.0) {
y = texture_float_lookup(y_domain, y_range, y_scale_type,
position.y, 0. // ymap position 0 means never use a texture lookup.
);
float scaled = domainify(y_domain, y_scale_type, position.y, 0.0);
y = mix(y_range.x, y_range.y, scaled);
} else {
y = position.y;
}
Expand Down
37 changes: 28 additions & 9 deletions src/interaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,18 @@ type Annotation = {
data: StructRowProxy;
};

// A collection of zoomed and unzoomed scales returned by the interaction component.
export type ScaleSet = {
// The x scale to the screen coordinates at no zoom.
x: ScaleLinear<number, number>;
// The y scale to the screen coordinates at no zoom.
y: ScaleLinear<number, number>;
// The x scale in the translated space of the current zoom.
x_: ScaleLinear<number, number>;
// The y scale in the translated space of the current zoom.
y_: ScaleLinear<number, number>;
};

export class Zoom {
public prefs: DS.APICall;
public svg_element_selection: d3.Selection<
Expand All @@ -36,7 +48,7 @@ export class Zoom {
public renderers: Map<string, Renderer>;
public deeptable?: Deeptable;
public _timer?: d3.Timer;
public _scales?: Record<string, d3.ScaleLinear<number, number>>;
public _scales?: ScaleSet;
public zoomer?: d3.ZoomBehavior<Element, unknown>;
public transform?: d3.ZoomTransform;
public _start?: number;
Expand Down Expand Up @@ -169,7 +181,7 @@ export class Zoom {
}

set_highlit_points(data: StructRowProxy[]) {
const { x_, y_ } = this.scales();
const { x_, y_, x, y } = this.scales();
const xdim = this.scatterplot.dim('x') as PositionalAesthetic;
const ydim = this.scatterplot.dim('y') as PositionalAesthetic;
this.scatterplot.highlit_point_change(data, this.scatterplot);
Expand Down Expand Up @@ -200,6 +212,7 @@ export class Zoom {
.attr('fill', (dd) => this.scatterplot.dim('color').apply(dd))
.attr('cx', (datum) => x_(xdim.apply(datum)))
.attr('cy', (datum) => y_(ydim.apply(datum))),

(update) =>
update.attr('fill', (dd) => this.scatterplot.dim('color').apply(dd)),
(exit) =>
Expand Down Expand Up @@ -289,7 +302,11 @@ export class Zoom {
return this as Zoom;
}

scales(): Record<string, ScaleLinear<number, number>> {
/**
*
* @returns
*/
scales(): ScaleSet {
// General x and y scales that map from data space
// to pixel coordinates, and also
// rescaled ones that describe the current zoom.
Expand All @@ -309,7 +326,6 @@ export class Zoom {
throw new Error('Error--scales created before tileSet present.');
}
const { extent } = this.deeptable;
const scales: Record<string, ScaleLinear<number, number>> = {};
if (extent === undefined) {
throw new Error('Error--scales created before extent present.');
}
Expand Down Expand Up @@ -350,17 +366,20 @@ export class Zoom {
y_buffer_size = (height - y_target_size) / 2;
}

scales.x = scaleLinear()
const x = scaleLinear()
.domain(scale_dat.x.limits)
.range([x_buffer_size, width - x_buffer_size]);

scales.y = scaleLinear()
const y = scaleLinear()
.domain(scale_dat.y.limits)
.range([y_buffer_size, height - y_buffer_size]);

scales.x_ = this.transform.rescaleX(scales.x);
scales.y_ = this.transform.rescaleY(scales.y);

const scales: ScaleSet = {
x,
y,
x_: this.transform.rescaleX(x),
y_: this.transform.rescaleY(y),
};
this._scales = scales;
return scales;
}
Expand Down
12 changes: 0 additions & 12 deletions src/scatterplot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -878,18 +878,6 @@ export class Scatterplot {
}
return this._zoom;
}

sample_points(n = 10): Record<string, number | string>[] {
const vals: Record<string, number | string>[] = [];
for (const p of this.deeptable.points(this.zoom.current_corners())) {
vals.push({ ...p });
if (vals.length >= n * 3) {
break;
}
}
vals.sort((a, b) => Number(a.ix) - Number(b.ix));
return vals.slice(0, n);
}
}

/**
Expand Down
1 change: 1 addition & 0 deletions src/shared.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { ZoomTransform } from 'd3-zoom';
import { TileBufferManager } from './regl_rendering';
import type { Tile } from './tile';
import type { Rectangle } from './tile';
import { ScaleLinear } from 'd3-scale';
export type { Renderer, Deeptable, ConcreteAesthetic };

export type BufferLocation = {
Expand Down
25 changes: 0 additions & 25 deletions src/tile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -244,31 +244,6 @@ export class Tile {
}
} else {
throw new Error('Sorted iteration not supported');
/*
let children = this.children.map((tile) => {
const f = {
t: tile,
iterator: tile.points(bounding, sorted),
next: undefined,
};
f.next = f.iterator.next();
return f;
});
children = children.filter((d) => d?.next?.value);
while (children.length > 0) {
let mindex = 0;
for (let i = 1; i < children.length; i++) {
if (children[i].next.value.ix < children[mindex].next.value.ix) {
mindex = i;
}
}
yield children[mindex].next.value;
children[mindex].next = children[mindex].iterator.next();
if (children[mindex].next.done) {
children = children.splice(mindex, 1);
}
}
*/
}
}

Expand Down

0 comments on commit fe4f9a0

Please sign in to comment.