1use serde_json::{json, Value};
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 lines = vec![
38 json!([
40 v1_x - thick * 0.3,
41 v1_y - thick * 0.5,
42 v2_x + thick * 0.5,
43 v2_y - thick * 0.3,
44 ]),
45 json!([
46 v1_x + thick * 0.3,
47 v1_y - thick * 0.5,
48 v2_x - thick * 0.5,
49 v2_y + thick * 0.3,
50 ]),
51 json!([
53 v2_x + thick * 0.5,
54 v2_y - thick * 0.3,
55 v3_x - thick * 0.5,
56 v3_y - thick * 0.3,
57 ]),
58 json!([
59 v2_x + thick * 0.5,
60 v2_y + thick * 0.3,
61 v3_x - thick * 0.5,
62 v3_y + thick * 0.3,
63 ]),
64 json!([
66 v3_x + thick * 0.3,
67 v3_y - thick * 0.5,
68 v1_x + thick * 0.3,
69 v1_y + thick * 0.5,
70 ]),
71 json!([
72 v3_x - thick * 0.3,
73 v3_y + thick * 0.5,
74 v1_x - thick * 0.3,
75 v1_y + thick * 0.5,
76 ]),
77 json!([
80 v1_x - thick * 0.3,
81 v1_y - thick * 0.5,
82 v1_x - thick * 0.3,
83 v1_y + thick * 0.5,
84 ]),
85 json!([
86 v1_x + thick * 0.3,
87 v1_y - thick * 0.5,
88 v1_x + thick * 0.3,
89 v1_y + thick * 0.5,
90 ]),
91 json!([
93 v2_x - thick * 0.5,
94 v2_y - thick * 0.3,
95 v2_x - thick * 0.5,
96 v2_y + thick * 0.3,
97 ]),
98 json!([
99 v2_x + thick * 0.5,
100 v2_y - thick * 0.3,
101 v2_x + thick * 0.5,
102 v2_y + thick * 0.3,
103 ]),
104 json!([
106 v3_x - thick * 0.5,
107 v3_y - thick * 0.3,
108 v3_x - thick * 0.5,
109 v3_y + thick * 0.3,
110 ]),
111 json!([
112 v3_x + thick * 0.5,
113 v3_y - thick * 0.3,
114 v3_x + thick * 0.5,
115 v3_y + thick * 0.3,
116 ]),
117 ];
118
119 json!(lines)
120}
121
122pub fn impossible_cube(center_x: f64, center_y: f64, size: f64) -> Value {
132 let s = size * 0.5;
133
134 let f_bl_x = center_x - s; let f_bl_y = center_y + s;
137 let f_br_x = center_x + s; let f_br_y = center_y + s;
139 let f_tl_x = center_x - s; let f_tl_y = center_y - s;
141 let f_tr_x = center_x + s; let f_tr_y = center_y - s;
143
144 let offset = s * 0.6;
146 let b_bl_x = center_x - s + offset; let b_bl_y = center_y + s - offset;
148 let b_br_x = center_x + s + offset; let b_br_y = center_y + s - offset;
150 let b_tl_x = center_x - s + offset; let b_tl_y = center_y - s - offset;
152 let b_tr_x = center_x + s + offset; let b_tr_y = center_y - s - offset;
154
155 let lines = vec![
156 json!([f_bl_x, f_bl_y, f_br_x, f_br_y]), json!([f_br_x, f_br_y, f_tr_x, f_tr_y]), json!([f_tr_x, f_tr_y, f_tl_x, f_tl_y]), json!([f_tl_x, f_tl_y, f_bl_x, f_bl_y]), json!([b_bl_x, b_bl_y, b_br_x, b_br_y]), json!([b_br_x, b_br_y, b_tr_x, b_tr_y]), json!([b_tr_x, b_tr_y, b_tl_x, b_tl_y]), json!([b_tl_x, b_tl_y, b_bl_x, b_bl_y]), json!([f_bl_x, f_bl_y, b_bl_x, b_bl_y]),
168 json!([f_br_x, f_br_y, b_br_x, b_br_y]),
169 json!([f_tl_x, f_tl_y, b_tl_x, b_tl_y]),
170 json!([f_tr_x, f_tr_y, b_tr_x, b_tr_y]),
171 json!([f_bl_x + s * 0.3, f_bl_y, b_bl_x - s * 0.3, b_bl_y]),
173 json!([f_tr_x - s * 0.3, f_tr_y, b_tr_x + s * 0.3, b_tr_y]),
174 ];
175
176 json!(lines)
177}
178
179pub fn spiral(center_x: f64, center_y: f64, turns: i32, radius: f64, points: i32) -> Value {
191 let mut points_arr = Vec::new();
192 let total_points = turns * points;
193
194 for i in 0..total_points {
195 let t = (i as f64) / (total_points as f64); let angle = t * turns as f64 * 2.0 * std::f64::consts::PI;
197 let r = t * radius;
198
199 let x = center_x + r * angle.cos();
200 let y = center_y + r * angle.sin();
201
202 points_arr.push(json!([x, y]));
203 }
204
205 json!(points_arr)
206}
207
208pub fn muller_lyer(center_x: f64, center_y: f64, length: f64) -> Value {
218 let half = length / 2.0;
219 let arrow_size = length * 0.15;
220
221 let mut lines = Vec::new();
222
223 let y1 = center_y - length * 0.3;
225 lines.push(json!([center_x - half, y1, center_x + half, y1])); lines.push(json!([
229 center_x - half,
230 y1,
231 center_x - half + arrow_size,
232 y1 - arrow_size * 0.6
233 ]));
234 lines.push(json!([
235 center_x - half,
236 y1,
237 center_x - half + arrow_size,
238 y1 + arrow_size * 0.6
239 ]));
240
241 lines.push(json!([
243 center_x + half,
244 y1,
245 center_x + half - arrow_size,
246 y1 - arrow_size * 0.6
247 ]));
248 lines.push(json!([
249 center_x + half,
250 y1,
251 center_x + half - arrow_size,
252 y1 + arrow_size * 0.6
253 ]));
254
255 let y2 = center_y + length * 0.3;
257 lines.push(json!([center_x - half, y2, center_x + half, y2])); lines.push(json!([
261 center_x - half,
262 y2,
263 center_x - half - arrow_size,
264 y2 - arrow_size * 0.6
265 ]));
266 lines.push(json!([
267 center_x - half,
268 y2,
269 center_x - half - arrow_size,
270 y2 + arrow_size * 0.6
271 ]));
272
273 lines.push(json!([
275 center_x + half,
276 y2,
277 center_x + half + arrow_size,
278 y2 - arrow_size * 0.6
279 ]));
280 lines.push(json!([
281 center_x + half,
282 y2,
283 center_x + half + arrow_size,
284 y2 + arrow_size * 0.6
285 ]));
286
287 json!(lines)
288}
289
290pub fn ponzo(
302 center_x: f64,
303 center_y: f64,
304 height: f64,
305 width_top: f64,
306 width_bottom: f64,
307) -> Value {
308 let mut lines = Vec::new();
309
310 let top_y = center_y - height / 2.0;
312 let bottom_y = center_y + height / 2.0;
313
314 lines.push(json!([
315 center_x - width_top / 2.0,
316 top_y,
317 center_x - width_bottom / 2.0,
318 bottom_y
319 ]));
320 lines.push(json!([
321 center_x + width_top / 2.0,
322 top_y,
323 center_x + width_bottom / 2.0,
324 bottom_y
325 ]));
326
327 let top_line_width = width_top * 0.8;
329 let bottom_line_width = width_bottom * 0.8;
330
331 lines.push(json!([
333 center_x - top_line_width / 2.0,
334 top_y + height * 0.2,
335 center_x + top_line_width / 2.0,
336 top_y + height * 0.2
337 ]));
338
339 lines.push(json!([
341 center_x - bottom_line_width / 2.0,
342 bottom_y - height * 0.2,
343 center_x + bottom_line_width / 2.0,
344 bottom_y - height * 0.2
345 ]));
346
347 let mid_y = (top_y + bottom_y) / 2.0;
349 let mid_line_width = (width_top + width_bottom) * 0.4;
350 lines.push(json!([
351 center_x - mid_line_width / 2.0,
352 mid_y,
353 center_x + mid_line_width / 2.0,
354 mid_y
355 ]));
356 lines.push(json!([
357 center_x - mid_line_width / 2.0 * 0.5,
358 mid_y + height * 0.15,
359 center_x + mid_line_width / 2.0 * 0.5,
360 mid_y + height * 0.15
361 ]));
362
363 json!(lines)
364}
365
366#[cfg(test)]
367mod tests {
368 use super::*;
369
370 #[test]
371 fn test_penrose_returns_lines() {
372 let result = penrose(400.0, 300.0, 100.0);
373 let lines = result.as_array().unwrap();
374
375 assert!(!lines.is_empty());
376 assert!(lines.len() >= 10); let first_line = lines[0].as_array().unwrap();
380 assert_eq!(first_line.len(), 4);
381 }
382
383 #[test]
384 fn test_impossible_cube_returns_lines() {
385 let result = impossible_cube(400.0, 300.0, 100.0);
386 let lines = result.as_array().unwrap();
387
388 assert!(!lines.is_empty());
389 assert!(lines.len() >= 12); let first_line = lines[0].as_array().unwrap();
392 assert_eq!(first_line.len(), 4);
393 }
394
395 #[test]
396 fn test_spiral_returns_points() {
397 let result = spiral(400.0, 300.0, 3, 100.0, 20);
398 let points = result.as_array().unwrap();
399
400 assert_eq!(points.len(), 60); let first_point = points[0].as_array().unwrap();
403 assert_eq!(first_point.len(), 2); }
405
406 #[test]
407 fn test_muller_lyer_returns_lines() {
408 let result = muller_lyer(400.0, 300.0, 200.0);
409 let lines = result.as_array().unwrap();
410
411 assert_eq!(lines.len(), 10); let first_line = lines[0].as_array().unwrap();
414 assert_eq!(first_line.len(), 4);
415 }
416
417 #[test]
418 fn test_ponzo_returns_lines() {
419 let result = ponzo(400.0, 300.0, 300.0, 100.0, 300.0);
420 let lines = result.as_array().unwrap();
421
422 assert_eq!(lines.len(), 6); let first_line = lines[0].as_array().unwrap();
425 assert_eq!(first_line.len(), 4);
426 }
427
428 #[test]
429 fn test_spiral_center_point() {
430 let result = spiral(400.0, 300.0, 1, 100.0, 10);
432 let points = result.as_array().unwrap();
433 let first_point = points[0].as_array().unwrap();
434
435 let x = first_point[0].as_f64().unwrap();
436 let y = first_point[1].as_f64().unwrap();
437
438 assert!((x - 400.0).abs() < 1.0); assert!((y - 300.0).abs() < 1.0);
440 }
441
442 #[test]
443 fn test_spiral_outer_point() {
444 let result = spiral(400.0, 300.0, 1, 100.0, 10);
446 let points = result.as_array().unwrap();
447 let last_point = points[points.len() - 1].as_array().unwrap();
448
449 let x = last_point[0].as_f64().unwrap();
450 let y = last_point[1].as_f64().unwrap();
451
452 let dist = ((x - 400.0).powi(2) + (y - 300.0).powi(2)).sqrt();
455 assert!(dist > 80.0 && dist < 120.0); }
457}