1use serde_json::{Value, json};
9
10pub fn penrose(center_x: f64, center_y: f64, size: f64) -> Value {
20 let s = size;
21
22 let v1_x = center_x;
24 let v1_y = center_y - s * 0.577; let v2_x = center_x - s * 0.5;
27 let v2_y = center_y + s * 0.289;
28
29 let v3_x = center_x + s * 0.5;
30 let v3_y = center_y + s * 0.289;
31
32 let thick = s * 0.15;
34
35 let mut lines = Vec::new();
38
39 lines.push(json!([v1_x - thick * 0.3, v1_y - thick * 0.5, v2_x + thick * 0.5, v2_y - thick * 0.3]));
41 lines.push(json!([v1_x + thick * 0.3, v1_y - thick * 0.5, v2_x - thick * 0.5, v2_y + thick * 0.3]));
42
43 lines.push(json!([v2_x + thick * 0.5, v2_y - thick * 0.3, v3_x - thick * 0.5, v3_y - thick * 0.3]));
45 lines.push(json!([v2_x + thick * 0.5, v2_y + thick * 0.3, v3_x - thick * 0.5, v3_y + thick * 0.3]));
46
47 lines.push(json!([v3_x + thick * 0.3, v3_y - thick * 0.5, v1_x + thick * 0.3, v1_y + thick * 0.5]));
49 lines.push(json!([v3_x - thick * 0.3, v3_y + thick * 0.5, v1_x - thick * 0.3, v1_y + thick * 0.5]));
50
51 lines.push(json!([v1_x - thick * 0.3, v1_y - thick * 0.5, v1_x - thick * 0.3, v1_y + thick * 0.5]));
54 lines.push(json!([v1_x + thick * 0.3, v1_y - thick * 0.5, v1_x + thick * 0.3, v1_y + thick * 0.5]));
55
56 lines.push(json!([v2_x - thick * 0.5, v2_y - thick * 0.3, v2_x - thick * 0.5, v2_y + thick * 0.3]));
58 lines.push(json!([v2_x + thick * 0.5, v2_y - thick * 0.3, v2_x + thick * 0.5, v2_y + thick * 0.3]));
59
60 lines.push(json!([v3_x - thick * 0.5, v3_y - thick * 0.3, v3_x - thick * 0.5, v3_y + thick * 0.3]));
62 lines.push(json!([v3_x + thick * 0.5, v3_y - thick * 0.3, v3_x + thick * 0.5, v3_y + thick * 0.3]));
63
64 json!(lines)
65}
66
67pub fn impossible_cube(center_x: f64, center_y: f64, size: f64) -> Value {
77 let s = size * 0.5;
78
79 let f_bl_x = center_x - s; let f_bl_y = center_y + s;
82 let f_br_x = center_x + s; let f_br_y = center_y + s;
84 let f_tl_x = center_x - s; let f_tl_y = center_y - s;
86 let f_tr_x = center_x + s; let f_tr_y = center_y - s;
88
89 let offset = s * 0.6;
91 let b_bl_x = center_x - s + offset; let b_bl_y = center_y + s - offset;
93 let b_br_x = center_x + s + offset; let b_br_y = center_y + s - offset;
95 let b_tl_x = center_x - s + offset; let b_tl_y = center_y - s - offset;
97 let b_tr_x = center_x + s + offset; let b_tr_y = center_y - s - offset;
99
100 let mut lines = Vec::new();
101
102 lines.push(json!([f_bl_x, f_bl_y, f_br_x, f_br_y])); lines.push(json!([f_br_x, f_br_y, f_tr_x, f_tr_y])); lines.push(json!([f_tr_x, f_tr_y, f_tl_x, f_tl_y])); lines.push(json!([f_tl_x, f_tl_y, f_bl_x, f_bl_y])); lines.push(json!([b_bl_x, b_bl_y, b_br_x, b_br_y])); lines.push(json!([b_br_x, b_br_y, b_tr_x, b_tr_y])); lines.push(json!([b_tr_x, b_tr_y, b_tl_x, b_tl_y])); lines.push(json!([b_tl_x, b_tl_y, b_bl_x, b_bl_y])); lines.push(json!([f_bl_x, f_bl_y, b_bl_x, b_bl_y]));
116 lines.push(json!([f_br_x, f_br_y, b_br_x, b_br_y]));
117 lines.push(json!([f_tl_x, f_tl_y, b_tl_x, b_tl_y]));
118 lines.push(json!([f_tr_x, f_tr_y, b_tr_x, b_tr_y]));
119
120 lines.push(json!([f_bl_x + s * 0.3, f_bl_y, b_bl_x - s * 0.3, b_bl_y]));
123 lines.push(json!([f_tr_x - s * 0.3, f_tr_y, b_tr_x + s * 0.3, b_tr_y]));
124
125 json!(lines)
126}
127
128pub fn spiral(center_x: f64, center_y: f64, turns: i32, radius: f64, points: i32) -> Value {
140 let mut points_arr = Vec::new();
141 let total_points = turns * points;
142
143 for i in 0..total_points {
144 let t = (i as f64) / (total_points as f64); let angle = t * turns as f64 * 2.0 * std::f64::consts::PI;
146 let r = t * radius;
147
148 let x = center_x + r * angle.cos();
149 let y = center_y + r * angle.sin();
150
151 points_arr.push(json!([x, y]));
152 }
153
154 json!(points_arr)
155}
156
157pub fn muller_lyer(center_x: f64, center_y: f64, length: f64) -> Value {
167 let half = length / 2.0;
168 let arrow_size = length * 0.15;
169
170 let mut lines = Vec::new();
171
172 let y1 = center_y - length * 0.3;
174 lines.push(json!([center_x - half, y1, center_x + half, y1])); lines.push(json!([center_x - half, y1, center_x - half + arrow_size, y1 - arrow_size * 0.6]));
178 lines.push(json!([center_x - half, y1, center_x - half + arrow_size, y1 + arrow_size * 0.6]));
179
180 lines.push(json!([center_x + half, y1, center_x + half - arrow_size, y1 - arrow_size * 0.6]));
182 lines.push(json!([center_x + half, y1, center_x + half - arrow_size, y1 + arrow_size * 0.6]));
183
184 let y2 = center_y + length * 0.3;
186 lines.push(json!([center_x - half, y2, center_x + half, y2])); lines.push(json!([center_x - half, y2, center_x - half - arrow_size, y2 - arrow_size * 0.6]));
190 lines.push(json!([center_x - half, y2, center_x - half - arrow_size, y2 + arrow_size * 0.6]));
191
192 lines.push(json!([center_x + half, y2, center_x + half + arrow_size, y2 - arrow_size * 0.6]));
194 lines.push(json!([center_x + half, y2, center_x + half + arrow_size, y2 + arrow_size * 0.6]));
195
196 json!(lines)
197}
198
199pub fn ponzo(center_x: f64, center_y: f64, height: f64, width_top: f64, width_bottom: f64) -> Value {
211 let mut lines = Vec::new();
212
213 let top_y = center_y - height / 2.0;
215 let bottom_y = center_y + height / 2.0;
216
217 lines.push(json!([center_x - width_top / 2.0, top_y, center_x - width_bottom / 2.0, bottom_y]));
218 lines.push(json!([center_x + width_top / 2.0, top_y, center_x + width_bottom / 2.0, bottom_y]));
219
220 let top_line_width = width_top * 0.8;
222 let bottom_line_width = width_bottom * 0.8;
223
224 lines.push(json!([center_x - top_line_width / 2.0, top_y + height * 0.2, center_x + top_line_width / 2.0, top_y + height * 0.2]));
226
227 lines.push(json!([center_x - bottom_line_width / 2.0, bottom_y - height * 0.2, center_x + bottom_line_width / 2.0, bottom_y - height * 0.2]));
229
230 let mid_y = (top_y + bottom_y) / 2.0;
232 let mid_line_width = (width_top + width_bottom) * 0.4;
233 lines.push(json!([center_x - mid_line_width / 2.0, mid_y, center_x + mid_line_width / 2.0, mid_y]));
234 lines.push(json!([center_x - mid_line_width / 2.0 * 0.5, mid_y + height * 0.15, center_x + mid_line_width / 2.0 * 0.5, mid_y + height * 0.15]));
235
236 json!(lines)
237}
238
239#[cfg(test)]
240mod tests {
241 use super::*;
242
243 #[test]
244 fn test_penrose_returns_lines() {
245 let result = penrose(400.0, 300.0, 100.0);
246 let lines = result.as_array().unwrap();
247
248 assert!(!lines.is_empty());
249 assert!(lines.len() >= 10); let first_line = lines[0].as_array().unwrap();
253 assert_eq!(first_line.len(), 4);
254 }
255
256 #[test]
257 fn test_impossible_cube_returns_lines() {
258 let result = impossible_cube(400.0, 300.0, 100.0);
259 let lines = result.as_array().unwrap();
260
261 assert!(!lines.is_empty());
262 assert!(lines.len() >= 12); let first_line = lines[0].as_array().unwrap();
265 assert_eq!(first_line.len(), 4);
266 }
267
268 #[test]
269 fn test_spiral_returns_points() {
270 let result = spiral(400.0, 300.0, 3, 100.0, 20);
271 let points = result.as_array().unwrap();
272
273 assert_eq!(points.len(), 60); let first_point = points[0].as_array().unwrap();
276 assert_eq!(first_point.len(), 2); }
278
279 #[test]
280 fn test_muller_lyer_returns_lines() {
281 let result = muller_lyer(400.0, 300.0, 200.0);
282 let lines = result.as_array().unwrap();
283
284 assert_eq!(lines.len(), 10); let first_line = lines[0].as_array().unwrap();
287 assert_eq!(first_line.len(), 4);
288 }
289
290 #[test]
291 fn test_ponzo_returns_lines() {
292 let result = ponzo(400.0, 300.0, 300.0, 100.0, 300.0);
293 let lines = result.as_array().unwrap();
294
295 assert_eq!(lines.len(), 6); let first_line = lines[0].as_array().unwrap();
298 assert_eq!(first_line.len(), 4);
299 }
300
301 #[test]
302 fn test_spiral_center_point() {
303 let result = spiral(400.0, 300.0, 1, 100.0, 10);
305 let points = result.as_array().unwrap();
306 let first_point = points[0].as_array().unwrap();
307
308 let x = first_point[0].as_f64().unwrap();
309 let y = first_point[1].as_f64().unwrap();
310
311 assert!((x - 400.0).abs() < 1.0); assert!((y - 300.0).abs() < 1.0);
313 }
314
315 #[test]
316 fn test_spiral_outer_point() {
317 let result = spiral(400.0, 300.0, 1, 100.0, 10);
319 let points = result.as_array().unwrap();
320 let last_point = points[points.len() - 1].as_array().unwrap();
321
322 let x = last_point[0].as_f64().unwrap();
323 let y = last_point[1].as_f64().unwrap();
324
325 let dist = ((x - 400.0).powi(2) + (y - 300.0).powi(2)).sqrt();
328 assert!(dist > 80.0 && dist < 120.0); }
330}