Repository navigation
Expand file tree
/
Copy pathdla.rs
More file actions
130 lines (110 loc) · 4.12 KB
/
Copy pathdla.rs
File metadata and controls
130 lines (110 loc) · 4.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
use std::fs::File;
use std::io::{BufWriter, Write};
use std::path::PathBuf;
use clap::{Parser, ValueEnum};
use generative::dla::{Model, format_tgf, format_wkt};
/// Specifies the plaintext output format.
/// In all cases, the seed points will be written first.
#[derive(Debug, Clone, ValueEnum)]
enum OutputFormat {
/// Use TGF graph output format, labelling each node with the WKT point.
/// Edges will be unlabeled with weight, as that can be done in a post-processing
/// step, which simplifies the datastructure here.
Tgf,
/// Prints each point in WKT on its own line.
Wkt,
}
/// Off-lattice diffusion limited aggregation
#[derive(Debug, Parser)]
#[clap(name = "dla")]
struct CmdlineOptions {
/// The log level
#[clap(short, long, default_value_t = tracing::Level::INFO)]
log_level: tracing::Level,
/// Output file to write result to. Defaults to stdout.
#[clap(short, long)]
output: Option<PathBuf>,
/// Output format. Either "tgf" graph format or "points" point cloud.
#[clap(short, long, default_value = "tgf")]
format: OutputFormat,
/// Spacing between joined together particles.
#[clap(long, default_value = "1")]
particle_spacing: f64,
/// Distance threshold for joining together two particles.
#[clap(short, long, default_value = "3")]
attraction_distance: f64,
/// Minimum move distance for random walk.
#[clap(short, long, default_value = "1")]
min_move_distance: f64,
/// Defines how many interactions are necessary for a particle to stick to another.
/// The number of join attempts is tracked per-particle.
#[clap(long, default_value = "0")]
stubbornness: usize,
/// Defines the probability that another particle will allow a particle to stick to another.
/// Applies after stubbornness.
#[clap(long, default_value = "1")]
stickiness: f64,
/// Number of seed particles.
/// If one seed particle is used, it will be placed at the origin.
/// Otherwise, the seed particles will be uniformly spread around the origin.
#[clap(long, default_value = "1")]
seeds: usize,
/// The random seed to use, for reproducibility. Zero for a random seed.
#[clap(long, default_value = "0")]
seed: u64,
// TODO: Need to define different methods of placing the seed points.
/// Dimensionality of the particles.
#[clap(short, long, default_value = "2")]
dimensions: u8,
/// Number of particles to add.
#[clap(short, long, default_value = "10000")]
particles: usize,
}
impl CmdlineOptions {
/// Get a BufWriter for stdout or the specified output file.
fn get_output_writer(&self) -> BufWriter<Box<dyn Write>> {
match &self.output {
Some(path) => match File::create(path) {
Err(why) => panic!("Couldn't create: {} because: {}", path.display(), why),
Ok(file) => {
tracing::trace!("Using file output: {}", path.display());
BufWriter::new(Box::new(file))
}
},
None => {
tracing::trace!("Using stdout output");
BufWriter::new(Box::new(std::io::stdout()))
}
}
}
}
fn main() -> eyre::Result<()> {
color_eyre::install()?;
let args = CmdlineOptions::parse();
let filter = tracing_subscriber::EnvFilter::builder()
.with_default_directive(args.log_level.into())
.from_env_lossy();
tracing_subscriber::fmt()
.with_env_filter(filter)
.with_ansi(true)
.with_writer(std::io::stderr)
.init();
let mut model = Model::new(
args.dimensions,
// TODO: Seed type.
args.seeds,
args.seed,
args.particle_spacing,
args.attraction_distance,
args.min_move_distance,
args.stubbornness,
args.stickiness,
);
model.run(args.particles);
tracing::trace!("Model {model:?}");
let mut writer = args.get_output_writer();
match args.format {
OutputFormat::Tgf => format_tgf(&mut writer, model.particle_graph),
OutputFormat::Wkt => format_wkt(&mut writer, model.particle_graph),
}
}