Skip to content

Commit

Permalink
1.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
grantshandy committed Feb 6, 2024
1 parent e7591c3 commit 50755f1
Show file tree
Hide file tree
Showing 23 changed files with 285 additions and 2,051 deletions.
8 changes: 0 additions & 8 deletions .direnv/bin/nix-direnv-reload

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

1,945 changes: 0 additions & 1,945 deletions .direnv/flake-profile-a5d5b61aa8a61b7d9d765e1daf971a9a578f1cfa.rc

This file was deleted.

Binary file added .github/screenshot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions .github/workflows/build_nix.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
name: "Build nix flake on Ubuntu"

on:
push:

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: cachix/install-nix-action@v12
- name: Building package
run: nix --extra-experimental-features nix-command --extra-experimental-features flakes build
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@
/*.dot
/.idea/
/public/
/.direnv/
/.direnv
/result
27 changes: 25 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 11 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
[package]
name = "fdg-sim"
version = "0.1.0"
name = "fdg"
version = "1.0.0"
edition = "2021"
authors = [ "Grant Handy <[email protected]>" ]
license = "MIT"
description = "A flexible force-directed graph drawing library"
repository = "https://github.com/grantshandy/fdg/"
documentation = "https://docs.rs/fdg/"
keywords = [ "graph", "force", "directed", "viz" ]
categories = [ "visualization" ]
readme = "README.md"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

Expand All @@ -23,4 +31,5 @@ petgraph-gen = "0.1.3"

[features]
rayon = ["dep:rayon"]
serde = ["petgraph/serde", "nalgebra/serde-serialize"]
default = ["rayon"]
19 changes: 19 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
Copyright (c) 2024 Grant Handy

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
42 changes: 36 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,40 @@
# fdg
A Force-Directed Graph Library for Rust.
A [(force-directed)](https://en.wikipedia.org/wiki/Force-directed_graph_drawing) [graph drawing](https://en.wikipedia.org/wiki/Graph_drawing) library for Rust. *Convert any [`petgraph::Graph`](https://docs.rs/petgraph/latest/petgraph/graph/struct.Graph.html) into a pretty picture!*

![screenshot](./.github/screenshot.png)

## Dev Branch
This is the dev branch, here I'm working towards a much more polished v1.0. It'll be much more cut back and only one crate (fdg-sim).
- fdg-macroquad and fdg-img will be 1-file examples.
- The DOT, GML & jsongraph parsers will be removed and delegated to the user/other's libraries.
The goal of this library is to create some idiomatic building blocks for writing fast graph drawing algorithms in Rust. I hope to implement more algorithms such as [ForceAtlas2 (2014)](https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0098679) and [Kamada-Kawai (1989)](https://citeseerx.ist.psu.edu/document?repid=rep1&type=pdf&doi=b8d3bca50ccc573c5cb99f7d201e8acce6618f04). I also want to experiment with [generating the layouts with SIMD, parallelization, and GPU compute](https://github.com/grantshandy/fdg/issues/15).

This new version will focus more on idiomatic & generic API design, and performance.
The library is currently undergoing a complete rewrite with more performant algorithms and a more generic API (now supports computing in N dimensions 😉). The pre 1.0 version is now located in the `old` branch.

Contributions always welcome!

## Usage
```rust
use fdg::{fruchterman_reingold::FruchtermanReingold, Force, ForceGraph};

// your dataset: Into<StableGraph<(), ()>>

// Initialize a ForceGraph in 2 dimentions with random node positions from -10.0..=10.0.
let mut graph: ForceGraph<f32, 2, (), ()> = fdg::init_force_graph_uniform(dataset, 10.0);

// Apply the Fruchterman-Reingold (1991) force-directed drawing algorithm 100 times.
FruchtermanReingold::default().apply_many(&mut graph, 100);
// Center the graph's average around (0,0).
Center::default().apply(&mut graph);

// Render nodes:
println!("nodes:");
for (_, pos) in graph.node_weights() {
println!("{pos:?}");
}

// Render edges:
println!("edges:");
for edge_idx in graph.edge_indices() {
let (source_idx, target_idx) = graph.edge_endpoints(edge_idx).unwrap();

println!("{edge_idx:?}: {:?} to {:?}", &graph[source_idx].1, &graph[target_idx].1);
}
```
**See [basic.rs](./examples/basic.rs)...**
23 changes: 15 additions & 8 deletions examples/basic.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
use fdg_sim::{Force, ForceGraph, distributions::Uniform};
use fdg::{fruchterman_reingold::FruchtermanReingold, Force, ForceGraph, simple::Center};

fn main() {
let mut rng = rand::thread_rng();
let dataset = petgraph_gen::barabasi_albert_graph(&mut rng, 10, 3, None);

let mut force_graph: ForceGraph<f32, 2, (), ()> = fdg_sim::init_force_graph(
petgraph_gen::barabasi_albert_graph(&mut rng, 100, 3, None),
Uniform::new(-10.0, 10.0),
);
let mut graph: ForceGraph<f32, 2, (), ()> = fdg::init_force_graph_uniform(dataset, 10.0);

let mut force = fdg_sim::FruchtermanReingoldParallel::default();
FruchtermanReingold::default().apply_many(&mut graph, 100);
Center::default().apply(&mut graph);

for _ in 1..100 {
force.apply(&mut force_graph);
println!("nodes:");
for (_, pos) in graph.node_weights() {
println!("{pos:?}");
}

println!("edges:");
for edge_idx in graph.edge_indices() {
let (source_idx, target_idx) = graph.edge_endpoints(edge_idx).unwrap();

println!("{edge_idx:?}: {:?} to {:?}", &graph[source_idx].1, &graph[target_idx].1);
}
}
36 changes: 18 additions & 18 deletions examples/demo.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use ::rand::distributions::Uniform;
use fdg_sim::{
petgraph::Graph, Center, Force, ForceGraph, FruchtermanReingold,
FruchtermanReingoldConfiguration, Node, Translate,
use fdg::{
fruchterman_reingold::{FruchtermanReingold, FruchtermanReingoldConfiguration},
nalgebra::Rotation2,
petgraph::Graph,
simple::Center,
Force, ForceGraph,
};
use nalgebra::vector;

use macroquad::prelude::*;

Expand All @@ -18,10 +19,14 @@ async fn main() {
graph.extend_with_edges(&[(pg, fb), (pg, qc), (qc, rand), (rand, libc), (qc, libc)]);

let mut force_graph: ForceGraph<f32, 2, &str, ()> =
fdg_sim::init_force_graph(graph, Uniform::new(-200.0, 200.0));
fdg::init_force_graph_uniform(graph, 200.0);

let mut center = Center::default();
let mut translate = Translate::new(vector![0.0, -100.0]);
// custom closure force which rotates each node
let mut rotate = |graph: &mut ForceGraph<f32, 2, &str, ()>| {
graph
.node_weights_mut()
.for_each(|(_, p)| *p = Rotation2::new(0.005).transform_point(p))
};
let mut force = FruchtermanReingold {
conf: FruchtermanReingoldConfiguration {
scale: 400.0,
Expand All @@ -32,20 +37,15 @@ async fn main() {

loop {
// apply the fruchterman-reingold force 4 times
for _ in 0..4 {
force.apply(&mut force_graph);
}

// move the graph mean position to 0,0
center.apply(&mut force_graph);
force.apply_many(&mut force_graph, 4);

// translate the whole graph up 100 units
translate.apply(&mut force_graph);
Center::default().apply(&mut force_graph);
rotate.apply(&mut force_graph);

clear_background(WHITE);

for idx in force_graph.edge_indices() {
let (Node(_, source), Node(_, target)) = force_graph
let ((_, source), (_, target)) = force_graph
.edge_endpoints(idx)
.map(|(a, b)| {
(
Expand All @@ -65,7 +65,7 @@ async fn main() {
);
}

for Node(name, pos) in force_graph.node_weights() {
for (name, pos) in force_graph.node_weights() {
let x = translate_x(pos.coords.column(0)[0]);
let y = translate_y(pos.coords.column(0)[1]);

Expand Down
35 changes: 34 additions & 1 deletion flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 9 additions & 3 deletions flake.nix
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
{
description = "A basic rust devshell";

inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
flake-utils.url = "github:numtide/flake-utils";
Expand All @@ -11,9 +9,10 @@
flake-utils.follows = "flake-utils";
};
};
naersk.url = "github:nix-community/naersk";
};

outputs = { nixpkgs, rust-overlay, flake-utils, ... }:
outputs = { nixpkgs, rust-overlay, flake-utils, naersk, ... }:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = import nixpkgs {
Expand Down Expand Up @@ -41,9 +40,16 @@
cargo-watch
pkg-config
xorg.libxcb
hyperfine
];

naersk-lib = pkgs.callPackage naersk { };
in {
# nothing in this package, just for CI.
defaultPackage = naersk-lib.buildPackage {
inherit nativeBuildInputs;
root = ./.;
};

devShells.default = pkgs.mkShell {
RUST_SRC_PATH = "${rustToolchain}/lib/rustlib/src/rust/library";
Expand Down
5 changes: 0 additions & 5 deletions src/forces.rs

This file was deleted.

Loading

0 comments on commit 50755f1

Please sign in to comment.