{"id":13689614,"url":"https://github.com/thomasp85/particles","last_synced_at":"2025-04-04T13:13:54.487Z","repository":{"id":48308906,"uuid":"92283359","full_name":"thomasp85/particles","owner":"thomasp85","description":"A particle simulation engine based on a port of d3-force","archived":false,"fork":false,"pushed_at":"2024-12-03T09:13:52.000Z","size":21697,"stargazers_count":118,"open_issues_count":3,"forks_count":9,"subscribers_count":8,"default_branch":"main","last_synced_at":"2025-03-28T12:07:28.709Z","etag":null,"topics":["d3js","graph-layout","network","network-visualization","particles","rstats","simulation"],"latest_commit_sha":null,"homepage":null,"language":"R","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/thomasp85.png","metadata":{"files":{"readme":"README.Rmd","changelog":"NEWS.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-05-24T11:07:43.000Z","updated_at":"2025-03-22T11:16:31.000Z","dependencies_parsed_at":"2025-01-03T14:17:08.288Z","dependency_job_id":"6128f957-b2e0-434a-8f0c-c9a05e5bd2ee","html_url":"https://github.com/thomasp85/particles","commit_stats":{"total_commits":114,"total_committers":2,"mean_commits":57.0,"dds":0.01754385964912286,"last_synced_commit":"b194ad3c5c4017320ae0c51103401c274397cbf3"},"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thomasp85%2Fparticles","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thomasp85%2Fparticles/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thomasp85%2Fparticles/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thomasp85%2Fparticles/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/thomasp85","download_url":"https://codeload.github.com/thomasp85/particles/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247182350,"owners_count":20897380,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["d3js","graph-layout","network","network-visualization","particles","rstats","simulation"],"created_at":"2024-08-02T15:01:55.602Z","updated_at":"2025-04-04T13:13:54.470Z","avatar_url":"https://github.com/thomasp85.png","language":"R","funding_links":[],"categories":["R"],"sub_categories":[],"readme":"---\noutput: github_document\n---\n\n\u003c!-- README.md is generated from README.Rmd. Please edit that file --\u003e\n\n```{r, include=FALSE}\nknitr::opts_chunk$set(\n  collapse = TRUE,\n  comment = \"#\u003e\",\n  fig.path = \"man/figures/README-\",\n  ffmpeg.format='gif',\n  interval = 1/15\n)\n```\n\n# particles \u003cimg src=\"man/figures/logo.png\" align=\"right\" /\u003e\n\n\u003c!-- badges: start --\u003e\n[![R-CMD-check](https://github.com/thomasp85/particles/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/thomasp85/particles/actions/workflows/R-CMD-check.yaml)\n[![Codecov test coverage](https://codecov.io/gh/thomasp85/particles/branch/main/graph/badge.svg)](https://app.codecov.io/gh/thomasp85/particles?branch=main)\n[![CRAN_Release_Badge](http://www.r-pkg.org/badges/version-ago/particles)](https://CRAN.R-project.org/package=particles)\n[![CRAN_Download_Badge](http://cranlogs.r-pkg.org/badges/particles)](https://CRAN.R-project.org/package=particles)\n[![Codecov test coverage](https://codecov.io/gh/thomasp85/particles/graph/badge.svg)](https://app.codecov.io/gh/thomasp85/particles)\n\u003c!-- badges: end --\u003e\n\nThis package implements the [d3-force](https://github.com/d3/d3-force) algorithm \ndeveloped by Mike Bostock in R, thus providing a way to run many types of \nparticle simulations using its versatile interface.\n\nWhile the first goal is to provide feature parity with its JavaScript origin, \nthe intentions is to add more forces, constraints, etc. down the line. While\nd3-force is most well-known as a layout engine for visualising networks, it is\ncapable of much more. Therefore, `particles` is provided as a very open \nframework to play with. Eventually [`ggraph`](https://github.com/thomasp85/ggraph)\nwill provide some shortcut layouts based on `particles` with the aim of \nfacilitating network visualisation.\n\n## Usage\n`particles` builds upon the framework provided by [`tidygraph`](https://github.com/thomasp85/tidygraph)\nand adds a set of verbs that defines the simulation:\n\n* `simulate()` : Creates a simulation based on the input graph, global \n  parameters, and a genesis function that sets up the initial conditions of the\n  simulation.\n* `wield()` : Adds a force to the simulation. All forces implemented in d3-force\n  are available as well as some additionals.\n* `impose()` : Adds a constraint to the simulation. This function is a departure\n  from d3-force, as d3-force only allowed for simple fixing of x and/or y \n  coordinates through the use of the fx and fy accessors. `particles` formalises\n  the use of simulation constraints and adds new functionalities.\n* `evolve()` : Progresses the simulation, either a predefined number of steps, \n  or until the simulated annealing has cooled down.\n\n### Example\nA recreation of the Les Miserable network in \u003chttps://bl.ocks.org/mbostock/4062045\u003e\n\n```{r, message=FALSE, warning=FALSE}\nlibrary(tidyverse)\nlibrary(ggraph)\nlibrary(tidygraph)\nlibrary(particles)\n```\n\n```{r}\n# Data preparation\nd3_col \u003c- c(\n  '0' = \"#98df8a\",\n  '1' = \"#1f77b4\",\n  '2' = \"#aec7e8\",\n  '3' = \"#ff7f0e\",\n  '4' = \"#ffbb78\",\n  '5' = \"#2ca02c\",\n  '6' = \"#d62728\",\n  '7' = \"#ff9896\",\n  '8' = \"#9467bd\",\n  '9' = \"#c5b0d5\",\n  '10' =  \"#8c564b\"\n)\n\nraw_data \u003c- 'https://gist.githubusercontent.com/mbostock/4062045/raw/5916d145c8c048a6e3086915a6be464467391c62/miserables.json'\nmiserable_data \u003c- jsonlite::read_json(raw_data, simplifyVector = TRUE)\nmiserable_data$nodes$group \u003c- as.factor(miserable_data$nodes$group)\nmiserable_data$links \u003c- miserable_data$links |\u003e  \n  mutate(from = match(source, miserable_data$nodes$id),\n         to = match(target, miserable_data$nodes$id))\n\n# Actual particles part\nmis_graph \u003c- miserable_data |\u003e \n  simulate() |\u003e \n  wield(link_force) |\u003e \n  wield(manybody_force) |\u003e \n  wield(center_force) |\u003e \n  evolve() |\u003e \n  as_tbl_graph()\n\n# Plotting with ggraph\nggraph(mis_graph, 'nicely') + \n  geom_edge_link(aes(width = sqrt(value)), colour = '#999999', alpha = 0.6) + \n  geom_node_point(aes(fill = group), shape = 21, colour = 'white', size = 4, \n                  stroke = 1.5) + \n  scale_fill_manual('Group', values = d3_col) + \n  scale_edge_width('Value', range = c(0.5, 3)) + \n  coord_fixed() +\n  theme_graph()\n```\n\nIf you intend to follow the steps of the simulation it is possible to attach an\nevent handler that gets called ofter each generation of the simulation. If the\nhandler produces a plot the result will be an animation of the simulation:\n\n```{r, eval=FALSE}\n# Random overlapping circles\ngraph \u003c- as_tbl_graph(igraph::erdos.renyi.game(100, 0)) |\u003e \n  mutate(x = runif(100) - 0.5, \n         y = runif(100) - 0.5, \n         radius = runif(100, min = 0.1, 0.2))\n\n# Plotting function\ngraph_plot \u003c- function(sim) {\n  gr \u003c- as_tbl_graph(sim)\n  p \u003c- ggraph(gr, layout = as_tibble(gr)) +\n    geom_node_circle(aes(r = radius), fill = 'forestgreen', alpha = 0.5) + \n    coord_fixed(xlim = c(-2.5, 2.5), ylim = c(-2.5, 2.5)) + \n    theme_graph()\n  plot(p)\n}\n\n# Simulation\ngraph %\u003e% simulate(velocity_decay = 0.7, setup = predefined_genesis(x, y)) |\u003e \n  wield(collision_force, radius = radius, n_iter = 2) |\u003e \n  wield(x_force, x = 0, strength = 0.002) |\u003e \n  wield(y_force, y = 0, strength = 0.002) |\u003e \n  evolve(on_generation = graph_plot)\n```\n\n[Click here for resulting animation](https://www.dropbox.com/s/c5fta49hk53ku0g/bubbles.gif?raw=1)\n(GitHub don't allow big gifs in readme)\n\n## Installation\n\nYou can install particles from CRAN using `install.packages(\"particles\")` or \nalternatively install the development version from github with:\n\n```{r gh-installation, eval = FALSE}\n# install.packages(\"devtools\")\ndevtools::install_github(\"thomasp85/particles\")\n```\n\n## Immense Thanks\n* A huge \"Thank You\" to Mike Bostock is in place. Without d3-force, `particles`\n  wouldn't exist and without d3 in general the world would be a sadder place.\n* The C++ quad tree implementation that powers `manbody_force` and \n  `collision_force` is a modification of the [implementation made by Andrei Kashcha](https://github.com/anvaka/quadtree.cc) \n  and made available under MIT license. Big thanks to Andrei as well.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthomasp85%2Fparticles","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthomasp85%2Fparticles","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthomasp85%2Fparticles/lists"}