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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
mod file_header_utils;
use std::fs::File;
use std::io::{prelude::BufRead, BufReader};
use std::path::Path;
use std::str::FromStr;
pub use file_header_utils::{DataCoordinates, DataDimensionality};
#[derive(Debug)]
pub struct FileData {
pub file_name: String,
pub geo_points: Vec<[f64; 3]>,
pub fld_points: Vec<Vec<f64>>,
pub dimensionality: DataDimensionality,
pub coordinates: DataCoordinates,
pub num_points: usize,
}
impl FileData {
pub fn load_file(
file_path: String,
expected_field_data_size: usize,
) -> Result<Self, std::io::Error> {
// file
let os_file_path = Path::new(&file_path);
let file_name = retrieve_file_name(&os_file_path);
let file = File::open(os_file_path)?;
// file reader buffer
let file_reader = BufReader::new(file);
let mut geo_points = Vec::new();
let mut fld_points = Vec::new();
let mut dimensionality = DataDimensionality::new();
let mut coordinates = DataCoordinates::None;
assert!(
expected_field_data_size > 0,
"FileData cannot expect zero sized data!"
);
for (i, line) in file_reader.lines().enumerate() {
match line {
Ok(line_text) => {
match i {
0 => {
// first header line -> geometric meta-data
dimensionality = match DataDimensionality::from_file_header(&line_text)
{
Ok(data_dimensionality) => data_dimensionality,
Err(msg) => panic!(
"Problem Parsing Fld File: `{}` \n Err: {}",
file_name, msg
),
};
let num_points = dimensionality.total_num_points();
// reserve space for appropriate number of points
geo_points.reserve(num_points);
fld_points.reserve(num_points);
}
1 => {
// second header line -> field type and coordinate system
coordinates = match DataCoordinates::from_file_header(&line_text) {
Ok(data_coordinates) => data_coordinates,
Err(msg) => panic!(
"Problem Parsing Fld File: `{}` \n Err: {}",
file_name, msg
),
};
}
_ => {
// remaining lines => field data points
let mut line_geo_points = [0.0; 3];
let mut line_fld_points = Vec::with_capacity(expected_field_data_size);
// split on double space to get text sections for [geo \s\s field] data
let line_text_sections = line_text.split(" ");
for (s, section) in line_text_sections.enumerate() {
// split on singe space to get individual numerical tokens
let tokens = section.split(' ');
for (t, token) in tokens.enumerate() {
if token == "" {
continue;
}
// attempt to parse each token as an f64
match f64::from_str(token) {
// populate appropriate array with geometric or field data
Ok(value) => match s {
0 => line_geo_points[t] = value,
1 => {
assert!(
t < expected_field_data_size,
"Unexpected token on line {} of {}",
i,
file_name
);
line_fld_points.push(value);
}
_ => {
panic!(
"Unexpected token on line {} of {}",
i, file_name
);
}
},
Err(msg) => panic!(
"Unable to parse value on line {} of {} as f64! \n {}",
i, file_name, msg
),
}
}
}
// populate data vectors with geo and fld data from line i
geo_points.push(line_geo_points);
fld_points.push(line_fld_points);
}
}
}
Err(msg) => panic!("Unable to read line {} of {} \n {}", i, file_name, msg),
}
}
geo_points.shrink_to_fit();
fld_points.shrink_to_fit();
let num_points = geo_points.len();
assert_eq!(
num_points,
fld_points.len(),
"Problem Parsing Fld File: `{}` \n Inconsistent Number of geometric and data points!",
file_name
);
dark_yellow!("{} \t", num_points);
print!("Data Points successfully loaded from: ");
dark_grey_ln!("`{}`", file_name);
Ok(Self {
file_name,
geo_points,
fld_points,
dimensionality,
coordinates,
num_points,
})
}
}
fn retrieve_file_name(os_file_path: &Path) -> String {
let name = os_file_path.file_name();
match name {
Some(file_name) => file_name.to_string_lossy().into_owned(),
None => String::from("-UNNAMED FLD FILE-"),
}
}