Skip to content

Commit

Permalink
Merge pull request #22 from coilysiren/with-d3
Browse files Browse the repository at this point in the history
Adds D3 graphing !!!
  • Loading branch information
coilysiren authored Nov 25, 2023
2 parents db1784f + 7ae3b24 commit 9d37c97
Show file tree
Hide file tree
Showing 7 changed files with 269 additions and 306 deletions.
94 changes: 62 additions & 32 deletions src/js/lib/application.tsx
Original file line number Diff line number Diff line change
@@ -1,111 +1,141 @@
import React from 'react';
import "./styles.css"
import React from "react";
import "./styles.css";
import * as dataviz from "./dataviz";
import * as galaxy from "./galaxy";

const wasm = import("galaxy_gen_backend/galaxy_gen_backend");

export function Interface() {
export function Interface() {
const [galaxySize, setGalaxySize] = React.useState(100);
const [galaxySeedMass, setGalaxySeedMass] = React.useState(3);
const [galaxyGravityReach, setGalaxyGravityReach] = React.useState(10);
const [galaxySeedMass, setGalaxySeedMass] = React.useState(5);
const [minStarMass, setMinStarMass] = React.useState(1000);
let wasmModule: any = null;
let galaxyFrontend: galaxy.Frontend = null;

wasm.then((module) => {
console.log("wasm module loaded: ", module)
console.log("wasm module loaded: ", module);
wasmModule = module;
});

const handleGalaxySizeChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setGalaxySize(parseInt(event.target.value));
const handleGalaxySizeChange = (
event: React.ChangeEvent<HTMLInputElement>
) => {
const value = parseInt(event.target.value);
setGalaxySize(Number.isNaN(value) ? 0 : value);
};

const galaxySizeInput = (
<div className="input-group mb-3">
<span className="input-group-text" id="basic-addon1">Galaxy Size:</span>
<span className="input-group-text" id="basic-addon1">
Galaxy Size:
</span>
<input
type="text" className="form-control" placeholder="Username" name="galaxySize"
value={galaxySize.toString()} onChange={handleGalaxySizeChange}
type="text"
className="form-control"
name="galaxySize"
value={galaxySize.toString()}
onChange={handleGalaxySizeChange}
/>
</div>
)
);

const handleGalaxySeedMassChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setGalaxySeedMass(parseInt(event.target.value));
const handleGalaxySeedMassChange = (
event: React.ChangeEvent<HTMLInputElement>
) => {
const value = parseInt(event.target.value);
setGalaxySeedMass(Number.isNaN(value) ? 0 : value);
};

const galaxySeedMassInput = (
<div className="input-group mb-3">
<span className="input-group-text" id="basic-addon1">Seed Mass:</span>
<span className="input-group-text" id="basic-addon1">
Seed Mass:
</span>
<input
type="text" className="form-control" placeholder="Username" name="galaxySeedMass"
value={galaxySeedMass.toString()} onChange={handleGalaxySeedMassChange}
type="text"
className="form-control"
name="galaxySeedMass"
value={galaxySeedMass.toString()}
onChange={handleGalaxySeedMassChange}
/>
</div>
)
);

const handleGalaxyGravityReachChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setGalaxySeedMass(parseInt(event.target.value));
const handleMinStarMassChange = (
event: React.ChangeEvent<HTMLInputElement>
) => {
const value = parseInt(event.target.value);
setMinStarMass(Number.isNaN(value) ? 0 : value);
};

const galaxyGravityReachInput = (
const minStarMassInput = (
<div className="input-group mb-3">
<span className="input-group-text" id="basic-addon1">Gravity Reach:</span>
<span className="input-group-text" id="basic-addon1">
Min Star Mass:
</span>
<input
type="text" className="form-control" placeholder="Username" name="galaxyGravityReach"
value={galaxyGravityReach.toString()} onChange={handleGalaxyGravityReachChange}
type="text"
className="form-control"
name="minStarMass"
value={minStarMass.toString()}
onChange={handleMinStarMassChange}
/>
</div>
)
);

const handleInitClick = () => {
if (wasmModule === null) {
console.error("wasm not yet loaded");
} else {
console.log("initializing galaxy");
galaxyFrontend = new galaxy.Frontend(galaxySize);
galaxyFrontend = new galaxy.Frontend(galaxySize, minStarMass);
dataviz.initViz(galaxyFrontend);
}
};

const initButton = (
<button type="button" className="btn btn-primary" onClick={handleInitClick}>
init new galaxy
</button>
)
);

const handleSeedClick = () => {
if (galaxyFrontend === null) {
console.error("galaxy not yet initialized");
} else {
console.log("seeding galaxy");
galaxyFrontend.seed(galaxySeedMass);
dataviz.initData(galaxyFrontend);
}
};

const seedButton = (
<button type="button" className="btn btn-primary" onClick={handleSeedClick}>
seed the galaxy
</button>
)
);

const handleTickClick = () => {
galaxyFrontend.tick(galaxyGravityReach);
galaxyFrontend.tick(minStarMass);
};

const tickButton = (
<button type="button" className="btn btn-primary" onClick={handleTickClick}>
advance time
</button>
)
);

return (
<div className="container">
<h1>Galaxy Generator</h1>
<h2><small className="text-muted">( rust =&gt; wasm =&gt; js ) galaxy generation simulation</small></h2>
<h2>
<small className="text-muted">
( rust =&gt; wasm =&gt; js ) galaxy generation simulation
</small>
</h2>
{galaxySizeInput}
{galaxySeedMassInput}
{galaxyGravityReachInput}
{minStarMassInput}
<div className="d-flex justify-content-between">
{initButton}
{seedButton}
Expand Down
94 changes: 59 additions & 35 deletions src/js/lib/dataviz.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,47 +2,71 @@ import React from "react";
import * as d3 from "d3";
import * as galaxy from "./galaxy";

export function DataViz(data: galaxy.Frontend) {
// set the dimensions and margins of the graph
const margin = { top: 10, right: 30, bottom: 30, left: 60 },
width = 460 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;
const margin = { top: 40, right: 40, bottom: 40, left: 40 };

function getSizeModifier(galaxyFrontend: galaxy.Frontend) {
return Math.sqrt(galaxyFrontend.galaxySize);
}

export function initViz(galaxyFrontend: galaxy.Frontend) {
const sizeModifier = getSizeModifier(galaxyFrontend);
const width = galaxyFrontend.galaxySize + margin.left + margin.right;
const height = galaxyFrontend.galaxySize + margin.top + margin.bottom;

// remove old svg
d3.select("#dataviz svg").remove();

// append the svg object to the body of the page
const svg = d3
.select("#dataviz")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.attr("width", width * sizeModifier + margin.left + margin.right)
.attr("height", height * sizeModifier + margin.top + margin.bottom)
.append("g")
.attr("transform", `translate(${margin.left}, ${margin.top})`);

//Read the data
d3.csv("https://raw.githubusercontent.com/holtzy/data_to_viz/master/Example_dataset/2_TwoNum.csv").then( function(data) {

// Add X axis
const x = d3.scaleLinear()
.domain([0, 4000])
.range([ 0, width ]);
svg.append("g")
.attr("transform", `translate(0, ${height})`)
.call(d3.axisBottom(x));

// Add Y axis
const y = d3.scaleLinear()
.domain([0, 500000])
.range([ height, 0]);
svg.append("g")
.call(d3.axisLeft(y));

// Add dots
svg.append('g')
.selectAll("dot")
.data(data)
.join("circle")
.attr("cx", function (d) { return x(d.GrLivArea); } )
.attr("cy", function (d) { return y(d.SalePrice); } )
.attr("r", 1.5)
.style("fill", "#69b3a2")
});
// Add X axis
const x = d3
.scaleLinear()
.domain([0, galaxyFrontend.galaxySize])
.range([0, galaxyFrontend.galaxySize * sizeModifier]);
svg
.append("g")
.attr(
"transform",
`translate(0, ${galaxyFrontend.galaxySize * sizeModifier})`
)
.call(d3.axisBottom(x));

// Add Y axis
const y = d3
.scaleLinear()
.domain([0, galaxyFrontend.galaxySize])
.range([galaxyFrontend.galaxySize * sizeModifier, 0]);
svg.append("g").call(d3.axisLeft(y));
}

export function initData(galaxyFrontend: galaxy.Frontend) {
const sizeModifier = getSizeModifier(galaxyFrontend);

// remove old data
d3.select("#dataviz svg circle").remove();

// append the svg object to the body of the page
const svg = d3.select("#dataviz svg");
svg
.append("g")
.selectAll("dot")
.data(galaxyFrontend.cells())
.join("circle")
.attr("cx", function (c: galaxy.Cell) {
return c.x * sizeModifier + margin.left;
})
.attr("cy", function (c: galaxy.Cell) {
return c.y * sizeModifier + margin.top;
})
.attr("r", function (c: galaxy.Cell) {
return c.mass;
})
.style("fill", "#69b3a2");
}
29 changes: 15 additions & 14 deletions src/js/lib/galaxy.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as wasm from "galaxy_gen_backend/galaxy_gen_backend";

interface Cell {
export interface Cell {
mass: number;
x: number;
y: number;
Expand All @@ -12,32 +12,33 @@ interface Cell {
*/
export class Frontend {
private galaxy: wasm.Galaxy; // pointer to galaxy
private galaxySize: number;
public galaxySize: number;

constructor(galaxySize: number) {
this.galaxy = new wasm.Galaxy(galaxySize, 0);
constructor(galaxySize: number, minStarMass: number) {
this.galaxy = new wasm.Galaxy(galaxySize, 0, minStarMass);
this.galaxySize = galaxySize;
}

public seed(additionalMass: number): void {
this.galaxy.seed(additionalMass);
this.galaxy = this.galaxy.seed(additionalMass);
}

public tick(gravityReach: number): void {
this.galaxy.tick(gravityReach);
this.galaxy = this.galaxy.tick(gravityReach);
}

public cells(): Cell[] {
// Uint16Array to list of numbers
let cells: Cell[] = [];
const mass = Array.from(this.galaxy.mass());
mass.forEach((element, index) => {
const mass = this.galaxy.mass();
const x = this.galaxy.x();
const y = this.galaxy.y();
const cells: Cell[] = [];
for (let i = 0; i < this.galaxySize ** 2; i++) {
cells.push({
mass: element,
x: index % this.galaxySize,
y: Math.floor(index / this.galaxySize),
mass: mass[i],
x: x[i],
y: y[i],
});
});
}
return cells;
}
}
Loading

0 comments on commit 9d37c97

Please sign in to comment.