1use std::{
7 io::{self, Seek, Write},
8 marker::PhantomData,
9 ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, RemAssign, Sub, SubAssign},
10 rc::Rc,
11};
12
13use num_traits::{Bounded, Num, One, Zero};
14use raw::{
15 Construction, ConstructionItem, Coords, Element, ElementType, LabelMode, ObjColorType, Show,
16};
17use zip::{write::FileOptions, ZipWriter};
18
19pub mod raw;
20pub use raw::{LineStyle, LineType};
21
22pub mod prelude {
23 pub use super::{
24 Conic, ConicAccess, Expr as _, Geogebra, Line, LineAccess, List, ListAccess, Numeric,
25 NumericAccess, Point, PointAccess, Ray, Segment,
26 };
27}
28
29#[derive(Debug)]
31pub struct Geogebra {
32 data: raw::Geogebra,
33 next_id: usize,
35}
36
37impl Geogebra {
38 #[must_use]
40 pub fn new() -> Self {
41 Self {
42 data: raw::Geogebra {
43 format: String::from("5.0"),
44 construction: Construction::default(),
45 app: String::from("suite"),
46 sub_app: String::from("geometry"),
47 },
48 next_id: 0,
49 }
50 }
51
52 pub fn write(&self, stream: impl Write + Seek) -> io::Result<()> {
54 let geogebra = quick_xml::se::to_string(&self.data).unwrap();
55
56 let mut file = ZipWriter::new(stream);
57
58 file.start_file("geogebra.xml", FileOptions::<()>::default())?;
59 file.write_all(b"<?xml version=\"1.0\" encoding=\"utf-8\" ?>")?;
60 file.write_all(geogebra.as_bytes())?;
61 file.finish()?;
62
63 Ok(())
64 }
65
66 fn next_label(&mut self) -> String {
67 let mut next_label = format!("elem{}", self.next_id);
68 self.next_id += 1;
69
70 while self.data.construction.items.iter().any(|item| match item {
71 ConstructionItem::Element(element) => element.label == next_label,
72 ConstructionItem::Command(_) => false,
73 ConstructionItem::Expression(expression) => expression.label == next_label,
74 }) {
75 next_label = format!("elem{}", self.next_id);
76 self.next_id += 1;
77 }
78
79 next_label
80 }
81}
82
83#[derive(Clone, Copy)]
84struct Style {
85 pub display_label: bool,
87 pub line_style: Option<LineStyle>,
89 pub color: Option<ObjColorType>,
91}
92
93impl Default for Style {
94 fn default() -> Self {
95 Self {
96 display_label: true,
97 line_style: None,
98 color: None,
99 }
100 }
101}
102
103impl Style {
104 #[must_use]
105 fn to_element(self) -> Element {
106 Element {
107 type_: ElementType::Point,
108 label: String::new(),
109 caption: None,
110 label_mode: LabelMode::Caption.into(),
111 show: Show {
112 object: true,
113 label: self.display_label,
114 },
115 coords: None,
116 line_style: self.line_style,
117 obj_color: self.color,
118 }
119 }
120}
121
122pub trait Object: Into<Expression> {}
123
124pub struct Var<T>(Rc<String>, PhantomData<T>);
126
127impl<T> Var<T> {
128 #[must_use]
129 fn new(expr: String) -> Self {
130 Self(Rc::new(expr), PhantomData)
131 }
132}
133
134impl<T: Object> Object for Var<T> {}
135
136impl<T: Object> Object for &Var<T> {}
137
138impl<T: Expr> Expr for Var<T> {
139 type Target = T::Target;
140
141 fn get_type() -> ElementType {
142 T::get_type()
143 }
144
145 fn var(expr: String) -> Var<Self::Target> {
146 T::var(expr)
147 }
148}
149
150impl<T: Expr> Expr for &Var<T> {
151 type Target = T::Target;
152
153 fn get_type() -> ElementType {
154 T::get_type()
155 }
156
157 fn var(expr: String) -> Var<Self::Target> {
158 T::var(expr)
159 }
160}
161
162#[derive(Clone)]
164pub struct Expression {
165 expr: Rc<String>,
166 style: Style,
167}
168
169impl Expression {
170 pub fn expr(expr: impl ToString) -> Self {
172 Self {
173 expr: Rc::new(expr.to_string()),
174 style: Style::default(),
175 }
176 }
177}
178
179pub trait Expr: Into<Expression> {
180 type Target;
182
183 fn get_type() -> ElementType;
185
186 #[must_use]
188 fn var(expr: String) -> Var<Self::Target>;
189}
190
191impl<X: Into<Numeric>, Y: Into<Numeric>> From<(X, Y)> for Expression {
192 fn from((x, y): (X, Y)) -> Self {
193 Self {
194 expr: Rc::new(format!(
195 "(real({}), real({}))",
196 x.into().0.expr,
197 y.into().0.expr
198 )),
199 style: Style::default(),
200 }
201 }
202}
203
204impl From<f64> for Expression {
205 fn from(value: f64) -> Self {
206 Self {
207 expr: Rc::new(format!("{value} + 0i")),
208 style: Style::default(),
209 }
210 }
211}
212
213impl<T> From<Var<T>> for Expression {
214 fn from(value: Var<T>) -> Self {
215 Self::from(&value)
216 }
217}
218
219impl<T> From<&Var<T>> for Expression {
220 fn from(value: &Var<T>) -> Self {
221 Self {
222 expr: Rc::clone(&value.0),
223 style: Style::default(),
224 }
225 }
226}
227
228impl From<Point> for Expression {
229 fn from(value: Point) -> Self {
230 value.0
231 }
232}
233
234#[derive(Clone)]
236pub struct Point(Expression);
237
238impl Point {
239 pub fn set_color(&mut self, r: u8, g: u8, b: u8) {
241 self.0.style.color = Some(ObjColorType { r, g, b });
242 }
243
244 pub fn set_display_label(&mut self, v: bool) {
246 self.0.style.display_label = v;
247 }
248
249 #[must_use]
251 fn bound() -> Style {
252 Style {
253 display_label: true,
254 line_style: None,
255 color: Some(ObjColorType {
256 r: 97,
257 g: 97,
258 b: 97,
259 }),
260 }
261 }
262
263 #[must_use]
265 fn free() -> Style {
266 Style {
267 display_label: true,
268 line_style: None,
269 color: Some(ObjColorType {
270 r: 21,
271 g: 101,
272 b: 192,
273 }),
274 }
275 }
276
277 #[must_use]
279 pub fn intersect(k: impl Into<Line>, l: impl Into<Line>) -> Self {
280 Self(Expression {
281 expr: Rc::new(format!(
282 "Intersect({}, {})",
283 k.into().0.expr,
284 l.into().0.expr
285 )),
286 style: Self::bound(),
287 })
288 }
289
290 #[must_use]
292 pub fn on(v: impl Object) -> Self {
293 Self(Expression {
294 expr: Rc::new(format!("Point({})", v.into().expr)),
295 style: Self::free(),
296 })
297 }
298
299 #[must_use]
301 pub fn x(self) -> Numeric {
302 Numeric(Expression {
303 expr: Rc::new(format!("x({})", self.0.expr)),
304 style: Style::default(),
305 })
306 }
307
308 #[must_use]
310 pub fn y(self) -> Numeric {
311 Numeric(Expression {
312 expr: Rc::new(format!("y({})", self.0.expr)),
313 style: Style::default(),
314 })
315 }
316
317 #[must_use]
319 pub fn complex(self) -> Numeric {
320 Numeric(Expression::expr(format!("ToComplex({})", self.0.expr)))
321 }
322}
323
324impl<X: Into<Numeric>, Y: Into<Numeric>> From<(X, Y)> for Point {
325 fn from(value: (X, Y)) -> Self {
326 Self(Expression::from(value))
327 }
328}
329
330impl From<Var<Point>> for Point {
331 fn from(value: Var<Point>) -> Self {
332 Self(Expression::from(value))
333 }
334}
335
336impl From<&Var<Point>> for Point {
337 fn from(value: &Var<Point>) -> Self {
338 Self(Expression::from(value))
339 }
340}
341
342impl Expr for Point {
343 type Target = Self;
344
345 fn get_type() -> ElementType {
346 ElementType::Point
347 }
348
349 fn var(expr: String) -> Var<Self::Target> {
350 Var::new(expr)
351 }
352}
353
354impl Object for Point {}
355
356impl<X: Into<Numeric>, Y: Into<Numeric>> Expr for (X, Y) {
357 type Target = Point;
358
359 fn get_type() -> ElementType {
360 ElementType::Point
361 }
362
363 fn var(expr: String) -> Var<Self::Target> {
364 Var::new(expr)
365 }
366}
367
368pub trait PointAccess: Sized
370where
371 Point: From<Self>,
372{
373 #[must_use]
375 fn x(self) -> Numeric {
376 Point::from(self).x()
377 }
378
379 #[must_use]
381 fn y(self) -> Numeric {
382 Point::from(self).x()
383 }
384
385 #[must_use]
387 fn complex(self) -> Numeric {
388 Point::from(self).complex()
389 }
390}
391
392impl<T> PointAccess for T where Point: From<T> {}
393
394impl Expr for f64 {
395 type Target = Numeric;
396
397 fn get_type() -> ElementType {
398 ElementType::Numeric
399 }
400
401 fn var(expr: String) -> Var<Self::Target> {
402 Var::new(expr)
403 }
404}
405
406#[derive(Clone)]
408pub struct Line(Expression);
409
410impl Line {
411 pub fn set_color(&mut self, r: u8, g: u8, b: u8) {
413 self.0.style.color = Some(ObjColorType { r, g, b });
414 }
415
416 pub fn set_style(&mut self, style: LineStyle) {
418 self.0.style.line_style = Some(style);
419 }
420
421 pub fn set_display_label(&mut self, v: bool) {
423 self.0.style.display_label = v;
424 }
425
426 #[must_use]
428 fn style() -> Style {
429 Style {
430 display_label: false,
431 line_style: Some(LineStyle::default()),
432 color: None,
433 }
434 }
435
436 #[must_use]
438 pub fn new(a: impl Into<Point>, b: impl Into<Point>) -> Self {
439 Self(Expression {
440 expr: Rc::new(format!("Line({}, {})", a.into().0.expr, b.into().0.expr)),
441 style: Self::style(),
442 })
443 }
444
445 #[must_use]
447 pub fn point_vector(point: impl Into<Point>, vector: impl Into<Numeric>) -> Self {
448 Self(Expression {
449 expr: Rc::new(format!(
450 "Line({}, {})",
451 point.into().0.expr,
452 vector.into().0.expr
453 )),
454 style: Self::style(),
455 })
456 }
457
458 #[must_use]
460 pub fn angle_bisector(a: impl Into<Point>, b: impl Into<Point>, c: impl Into<Point>) -> Self {
461 Self(Expression::expr(format!(
462 "AngleBisector({}, {}, {})",
463 a.into().0.expr,
464 b.into().0.expr,
465 c.into().0.expr
466 )))
467 }
468
469 #[must_use]
471 pub fn perpendicular(to: impl Into<Line>, through: impl Into<Point>) -> Self {
472 Self(Expression::expr(format!(
473 "PerpendicularLine({}, {})",
474 through.into().0.expr,
475 to.into().0.expr
476 )))
477 }
478
479 #[must_use]
481 pub fn parallel(to: impl Into<Line>, through: impl Into<Point>) -> Self {
482 Self(Expression::expr(format!(
483 "Line({}, {})",
484 through.into().0.expr,
485 to.into().0.expr
486 )))
487 }
488
489 #[must_use]
491 pub fn direction(self) -> Numeric {
492 Numeric(Expression::expr(format!("Direction({})", self.0.expr)))
493 }
494}
495
496impl From<Var<Line>> for Line {
497 fn from(value: Var<Line>) -> Self {
498 Self(Expression::from(value))
499 }
500}
501
502impl From<&Var<Line>> for Line {
503 fn from(value: &Var<Line>) -> Self {
504 Self(Expression::from(value))
505 }
506}
507
508impl From<Line> for Expression {
509 fn from(value: Line) -> Self {
510 value.0
511 }
512}
513
514impl Expr for Line {
515 type Target = Self;
516
517 fn get_type() -> ElementType {
518 ElementType::Line
519 }
520
521 fn var(expr: String) -> Var<Self::Target> {
522 Var::new(expr)
523 }
524}
525
526impl Object for Line {}
527
528pub trait LineAccess: Sized
530where
531 Line: From<Self>,
532{
533 #[must_use]
535 fn direction(self) -> Numeric {
536 Line::from(self).direction()
537 }
538}
539
540impl<T> LineAccess for T where Line: From<T> {}
541
542#[derive(Clone)]
544pub struct List<T>(Expression, PhantomData<T>);
545
546impl<T: Expr, It: IntoIterator<Item = T>> From<It> for List<T::Target>
547where
548 Expression: From<T>,
549{
550 fn from(value: It) -> Self {
551 let mut args = String::new();
552
553 for arg in value {
554 args += Expression::from(arg).expr.as_ref();
555 args += ", "
556 }
557
558 args.pop();
559 args.pop();
560
561 Self(
562 Expression {
563 expr: Rc::new(format!("{{{args}}}")),
564 style: Style::default(),
565 },
566 PhantomData,
567 )
568 }
569}
570
571impl<T> From<List<T>> for Expression {
572 fn from(value: List<T>) -> Self {
573 value.0
574 }
575}
576
577impl<T> Expr for List<T> {
578 type Target = List<T>;
579
580 fn get_type() -> ElementType {
581 ElementType::List
582 }
583
584 fn var(expr: String) -> Var<Self::Target> {
585 Var::new(expr)
586 }
587}
588
589impl<T> From<&Var<List<T>>> for List<T> {
590 fn from(value: &Var<List<T>>) -> Self {
591 Self(value.into(), PhantomData)
592 }
593}
594
595impl List<Point> {
596 #[must_use]
598 pub fn mean_x(self) -> Numeric {
599 Numeric(Expression {
600 expr: Rc::new(format!("MeanX({})", self.0.expr)),
601 style: Style::default(),
602 })
603 }
604
605 #[must_use]
607 pub fn mean_y(self) -> Numeric {
608 Numeric(Expression {
609 expr: Rc::new(format!("MeanX({})", self.0.expr)),
610 style: Style::default(),
611 })
612 }
613}
614
615impl List<Numeric> {
616 #[must_use]
618 pub fn sum(self) -> Numeric {
619 Numeric(Expression {
620 expr: Rc::new(format!("Sum(Append({}, 0 + 0i))", self.0.expr)),
621 style: Style::default(),
622 })
623 }
624
625 #[must_use]
627 pub fn product(self) -> Numeric {
628 Numeric(Expression {
629 expr: Rc::new(format!("Product(Append({}, 1 + 0i))", self.0.expr)),
630 style: Style::default(),
631 })
632 }
633}
634
635pub trait ListAccess<T>: Sized
637where
638 List<T>: From<Self>,
639{
640 fn mean_x(self) -> Numeric
642 where
643 List<Point>: From<Self>,
644 {
645 List::from(self).mean_x()
646 }
647
648 fn mean_y(self) -> Numeric
650 where
651 List<Point>: From<Self>,
652 {
653 List::from(self).mean_y()
654 }
655
656 fn sum(self) -> Numeric
658 where
659 List<Numeric>: From<Self>,
660 {
661 List::from(self).sum()
662 }
663
664 fn product(self) -> Numeric
666 where
667 List<Numeric>: From<Self>,
668 {
669 List::from(self).product()
670 }
671}
672
673impl<T, V> ListAccess<T> for V where List<T>: From<V> {}
674
675#[derive(Clone)]
677pub struct Numeric(Expression);
678
679impl Numeric {
680 #[must_use]
682 pub fn is_const(&self) -> bool {
683 self.0.expr.parse::<f64>().is_ok()
684 }
685
686 #[must_use]
688 pub fn distance<T: Object>(point: impl Into<Point>, object: T) -> Self {
689 Self(Expression {
690 expr: Rc::new(format!(
691 "Distance({}, {})",
692 point.into().0.expr,
693 object.into().expr
694 )),
695 style: Style::default(),
696 })
697 }
698
699 #[must_use]
701 pub fn complex(real: impl Into<Numeric>, imaginary: impl Into<Numeric>) -> Self {
702 Self(Expression {
703 expr: Rc::new(format!(
704 "({}) + ({})i",
705 real.into().0.expr,
706 imaginary.into().0.expr
707 )),
708 style: Style::default(),
709 })
710 }
711
712 #[must_use]
714 pub fn angle(a: impl Into<Point>, b: impl Into<Point>, c: impl Into<Point>) -> Self {
715 Self(Expression::expr(format!(
716 "Angle({}, {}, {})",
717 a.into().0.expr,
718 b.into().0.expr,
719 c.into().0.expr
720 )))
721 }
722
723 #[must_use]
725 pub fn angle_lines(k: impl Into<Line>, l: impl Into<Line>) -> Self {
726 Self(Expression::expr(format!(
727 "Angle({}, {})",
728 k.into().0.expr,
729 l.into().0.expr
730 )))
731 }
732
733 #[must_use]
735 pub fn atan2(y: impl Into<Numeric>, x: impl Into<Numeric>) -> Self {
736 Self(Expression::expr(format!(
737 "atan2({}, {})",
738 y.into().0.expr,
739 x.into().0.expr
740 )))
741 }
742
743 #[must_use]
745 pub fn pow(self, exponent: impl Into<Numeric>) -> Self {
746 Self(Expression::expr(format!(
747 "({})^({})",
748 self.0.expr,
749 exponent.into().0.expr
750 )))
751 }
752
753 #[must_use]
755 pub fn real(self) -> Self {
756 Self(Expression::expr(format!("real({})", self.0.expr)))
757 }
758
759 #[must_use]
761 pub fn imaginary(self) -> Self {
762 Self(Expression::expr(format!("imaginary({})", self.0.expr)))
763 }
764
765 #[must_use]
767 pub fn ln(self) -> Self {
768 Self(Expression::expr(format!("ln({})", self.0.expr)))
769 }
770
771 #[must_use]
773 pub fn exp(self) -> Self {
774 Self(Expression::expr(format!("exp({})", self.0.expr)))
775 }
776
777 #[must_use]
779 pub fn arg(self) -> Self {
780 Self(Expression::expr(format!("arg({})", self.0.expr)))
781 }
782
783 #[must_use]
785 pub fn point(self) -> Point {
786 Point(Expression::expr(format!("ToPoint({})", self.0.expr)))
787 }
788
789 #[must_use]
791 pub fn sin(self) -> Numeric {
792 Numeric(Expression::expr(format!("sin({})", self.0.expr)))
793 }
794
795 #[must_use]
797 pub fn cos(self) -> Numeric {
798 Numeric(Expression::expr(format!("cos({})", self.0.expr)))
799 }
800
801 #[must_use]
803 pub fn asin(self) -> Numeric {
804 Numeric(Expression::expr(format!("asin({})", self.0.expr)))
805 }
806
807 #[must_use]
809 pub fn acos(self) -> Numeric {
810 Numeric(Expression::expr(format!("acos({})", self.0.expr)))
811 }
812
813 #[must_use]
815 pub fn atan(self) -> Numeric {
816 Numeric(Expression::expr(format!("atan({})", self.0.expr)))
817 }
818
819 #[must_use]
821 pub fn normalize(self) -> Numeric {
822 Numeric(Expression::expr(format!("UnitVector({})", self.0.expr)))
823 }
824}
825
826impl From<f64> for Numeric {
827 fn from(value: f64) -> Self {
828 Self(Expression::from(value))
829 }
830}
831
832impl From<&Var<Numeric>> for Numeric {
833 fn from(value: &Var<Numeric>) -> Self {
834 Self(Expression::from(value))
835 }
836}
837
838impl From<Numeric> for Expression {
839 fn from(value: Numeric) -> Self {
840 value.0
841 }
842}
843
844impl Expr for Numeric {
845 type Target = Self;
846
847 fn get_type() -> ElementType {
848 ElementType::Numeric
849 }
850
851 fn var(expr: String) -> Var<Self::Target> {
852 Var::new(expr)
853 }
854}
855
856impl<T: Into<Numeric>> Add<T> for Numeric {
857 type Output = Self;
858
859 fn add(mut self, rhs: T) -> Self::Output {
860 self += rhs;
861 self
862 }
863}
864
865impl<T: Into<Numeric>> AddAssign<T> for Numeric {
866 fn add_assign(&mut self, rhs: T) {
867 let expr = Expression {
868 expr: Rc::new(format!("({}) + ({})", self.0.expr, rhs.into().0.expr)),
869 style: Style::default(),
870 };
871 self.0 = expr;
872 }
873}
874
875impl<T: Into<Numeric>> Sub<T> for Numeric {
876 type Output = Self;
877
878 fn sub(mut self, rhs: T) -> Self::Output {
879 self -= rhs;
880 self
881 }
882}
883
884impl<T: Into<Numeric>> SubAssign<T> for Numeric {
885 fn sub_assign(&mut self, rhs: T) {
886 let expr = Expression {
887 expr: Rc::new(format!("({}) - ({})", self.0.expr, rhs.into().0.expr)),
888 style: Style::default(),
889 };
890 self.0 = expr;
891 }
892}
893
894impl<T: Into<Numeric>> Mul<T> for Numeric {
895 type Output = Self;
896
897 fn mul(mut self, rhs: T) -> Self::Output {
898 self *= rhs;
899 self
900 }
901}
902
903impl<T: Into<Numeric>> MulAssign<T> for Numeric {
904 fn mul_assign(&mut self, rhs: T) {
905 let expr = Expression {
906 expr: Rc::new(format!("({}) * ({})", self.0.expr, rhs.into().0.expr)),
907 style: Style::default(),
908 };
909 self.0 = expr;
910 }
911}
912
913impl<T: Into<Numeric>> Div<T> for Numeric {
914 type Output = Self;
915
916 fn div(mut self, rhs: T) -> Self::Output {
917 self /= rhs;
918 self
919 }
920}
921
922impl<T: Into<Numeric>> DivAssign<T> for Numeric {
923 fn div_assign(&mut self, rhs: T) {
924 let expr = Expression {
925 expr: Rc::new(format!("({}) / ({})", self.0.expr, rhs.into().0.expr)),
926 style: Style::default(),
927 };
928 self.0 = expr;
929 }
930}
931
932impl Neg for Numeric {
933 type Output = Self;
934
935 fn neg(self) -> Self::Output {
936 Self(Expression {
937 expr: Rc::new(format!("-({})", self.0.expr)),
938 style: Style::default(),
939 })
940 }
941}
942
943impl<T: Into<Numeric>> Rem<T> for Numeric {
944 type Output = Numeric;
945
946 fn rem(mut self, rhs: T) -> Self::Output {
947 self %= rhs;
948 self
949 }
950}
951
952impl<T: Into<Numeric>> RemAssign<T> for Numeric {
953 fn rem_assign(&mut self, rhs: T) {
954 let expr = Expression::expr(format!("Mod({}, {})", self.0.expr, rhs.into().0.expr));
955 self.0 = expr;
956 }
957}
958
959impl From<&Self> for Numeric {
960 fn from(value: &Self) -> Self {
961 Self(value.0.clone())
962 }
963}
964
965impl<T: Copy + Into<Numeric>> From<&T> for Numeric {
966 fn from(value: &T) -> Self {
967 (*value).into()
968 }
969}
970
971impl<T> PartialEq<T> for Numeric
972where
973 Numeric: for<'a> From<&'a T>,
974{
975 fn eq(&self, other: &T) -> bool {
976 let other = Self::from(other);
977 if self.0.expr == other.0.expr {
978 return true;
979 }
980
981 if let Ok(v) = self.0.expr.parse::<f64>() {
982 if let Ok(u) = other.0.expr.parse::<f64>() {
983 return v.partial_cmp(&u).is_some_and(|v| v.is_eq());
984 }
985 }
986
987 false
988 }
989}
990
991impl Zero for Numeric {
992 fn zero() -> Self {
993 Self(Expression::expr("0"))
994 }
995
996 fn is_zero(&self) -> bool {
998 self.0.expr.as_str() == "0" || self.0.expr.as_str() == "0.0"
999 }
1000}
1001
1002impl One for Numeric {
1003 fn one() -> Self {
1004 Self(Expression::expr("1"))
1005 }
1006
1007 fn is_one(&self) -> bool {
1009 self.0.expr.as_str() == "1" || self.0.expr.as_str() == "1.0"
1010 }
1011}
1012
1013impl Bounded for Numeric {
1014 fn min_value() -> Self {
1015 Self::zero()
1016 }
1017
1018 fn max_value() -> Self {
1019 Self(Expression::expr(format!("{} + {}i", f64::MAX, f64::MAX)))
1020 }
1021}
1022
1023impl Num for Numeric {
1024 type FromStrRadixErr = &'static str;
1025
1026 fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
1027 if radix != 10 {
1028 return Err("Only radix of 10 is supported.");
1029 }
1030
1031 Ok(Self(Expression::expr(str)))
1032 }
1033}
1034
1035pub trait NumericAccess: Sized
1037where
1038 Numeric: From<Self>,
1039{
1040 #[must_use]
1042 fn pow(self, exponent: impl Into<Numeric>) -> Numeric {
1043 Numeric::from(self).pow(exponent)
1044 }
1045
1046 #[must_use]
1048 fn real(self) -> Numeric {
1049 Numeric::from(self).real()
1050 }
1051
1052 #[must_use]
1054 fn imaginary(self) -> Numeric {
1055 Numeric::from(self).imaginary()
1056 }
1057
1058 #[must_use]
1060 fn arg(self) -> Numeric {
1061 Numeric::from(self).arg()
1062 }
1063
1064 #[must_use]
1066 fn point(self) -> Point {
1067 Numeric::from(self).point()
1068 }
1069
1070 #[must_use]
1072 fn ln(self) -> Numeric {
1073 Numeric::from(self).ln()
1074 }
1075
1076 #[must_use]
1078 fn exp(self) -> Numeric {
1079 Numeric::from(self).exp()
1080 }
1081
1082 #[must_use]
1084 fn sin(self) -> Numeric {
1085 Numeric::from(self).sin()
1086 }
1087
1088 #[must_use]
1090 fn cos(self) -> Numeric {
1091 Numeric::from(self).cos()
1092 }
1093
1094 #[must_use]
1096 fn asin(self) -> Numeric {
1097 Numeric::from(self).asin()
1098 }
1099
1100 #[must_use]
1102 fn acos(self) -> Numeric {
1103 Numeric::from(self).acos()
1104 }
1105
1106 #[must_use]
1108 fn atan(self) -> Numeric {
1109 Numeric::from(self).atan()
1110 }
1111
1112 #[must_use]
1114 fn normalize(self) -> Numeric {
1115 Numeric::from(self).normalize()
1116 }
1117}
1118
1119impl<T> NumericAccess for T where Numeric: From<Self> {}
1120
1121#[derive(Clone)]
1123pub struct Conic(Expression);
1124
1125impl Conic {
1126 pub fn set_color(&mut self, r: u8, g: u8, b: u8) {
1128 self.0.style.color = Some(ObjColorType { r, g, b });
1129 }
1130
1131 pub fn set_style(&mut self, style: LineStyle) {
1133 self.0.style.line_style = Some(style);
1134 }
1135
1136 pub fn set_display_label(&mut self, v: bool) {
1138 self.0.style.display_label = v;
1139 }
1140
1141 #[must_use]
1143 fn style() -> Style {
1144 Style {
1145 display_label: false,
1146 line_style: None,
1147 color: None,
1148 }
1149 }
1150
1151 #[must_use]
1153 pub fn circle(center: impl Into<Point>, radius: impl Into<Numeric>) -> Self {
1154 Self(Expression {
1155 expr: Rc::new(format!(
1156 "Circle({}, abs({}))",
1157 center.into().0.expr,
1158 radius.into().0.expr
1159 )),
1160 style: Self::style(),
1161 })
1162 }
1163
1164 #[must_use]
1166 pub fn center(self) -> Point {
1167 Point(Expression {
1168 expr: Rc::new(format!("Center({})", self.0.expr)),
1169 style: Point::bound(),
1170 })
1171 }
1172}
1173
1174impl Object for Conic {}
1175
1176impl From<Var<Conic>> for Conic {
1177 fn from(value: Var<Conic>) -> Self {
1178 Self(value.into())
1179 }
1180}
1181
1182impl From<&Var<Conic>> for Conic {
1183 fn from(value: &Var<Conic>) -> Self {
1184 Self(value.into())
1185 }
1186}
1187
1188impl From<Conic> for Expression {
1189 fn from(value: Conic) -> Self {
1190 value.0
1191 }
1192}
1193
1194impl Expr for Conic {
1195 type Target = Self;
1196
1197 fn get_type() -> ElementType {
1198 ElementType::Conic
1199 }
1200
1201 fn var(expr: String) -> Var<Self::Target> {
1202 Var::new(expr)
1203 }
1204}
1205
1206pub trait ConicAccess: Sized
1208where
1209 Conic: From<Self>,
1210{
1211 #[must_use]
1213 fn center(self) -> Point {
1214 Conic::from(self).center()
1215 }
1216}
1217
1218impl<T> ConicAccess for T where Conic: From<T> {}
1219
1220#[derive(Clone)]
1222pub struct Ray(Expression);
1223
1224impl Ray {
1225 pub fn set_color(&mut self, r: u8, g: u8, b: u8) {
1227 self.0.style.color = Some(ObjColorType { r, g, b });
1228 }
1229
1230 pub fn set_style(&mut self, style: LineStyle) {
1232 self.0.style.line_style = Some(style);
1233 }
1234
1235 pub fn set_display_label(&mut self, v: bool) {
1237 self.0.style.display_label = v;
1238 }
1239
1240 #[must_use]
1242 pub fn new(origin: impl Into<Point>, through: impl Into<Point>) -> Self {
1243 Self(Expression::expr(format!(
1244 "Ray({}, {})",
1245 origin.into().0.expr,
1246 through.into().0.expr
1247 )))
1248 }
1249}
1250
1251impl Object for Ray {}
1252
1253impl From<Var<Ray>> for Ray {
1254 fn from(value: Var<Ray>) -> Self {
1255 Self(value.into())
1256 }
1257}
1258
1259impl From<&Var<Ray>> for Ray {
1260 fn from(value: &Var<Ray>) -> Self {
1261 Self(value.into())
1262 }
1263}
1264
1265impl From<Ray> for Expression {
1266 fn from(value: Ray) -> Self {
1267 value.0
1268 }
1269}
1270
1271impl Expr for Ray {
1272 type Target = Self;
1273
1274 fn get_type() -> ElementType {
1275 ElementType::Ray
1276 }
1277
1278 fn var(expr: String) -> Var<Self::Target> {
1279 Var::new(expr)
1280 }
1281}
1282
1283impl Addable for Ray {}
1284
1285#[derive(Clone)]
1287pub struct Segment(Expression);
1288
1289impl Segment {
1290 pub fn set_color(&mut self, r: u8, g: u8, b: u8) {
1292 self.0.style.color = Some(ObjColorType { r, g, b });
1293 }
1294
1295 pub fn set_style(&mut self, style: LineStyle) {
1297 self.0.style.line_style = Some(style);
1298 }
1299
1300 pub fn set_display_label(&mut self, v: bool) {
1302 self.0.style.display_label = v;
1303 }
1304
1305 #[must_use]
1307 pub fn new(a: impl Into<Point>, b: impl Into<Point>) -> Self {
1308 Self(Expression::expr(format!(
1309 "Segment({}, {})",
1310 a.into().0.expr,
1311 b.into().0.expr
1312 )))
1313 }
1314}
1315
1316impl Object for Segment {}
1317
1318impl From<Var<Segment>> for Segment {
1319 fn from(value: Var<Segment>) -> Self {
1320 Self(value.into())
1321 }
1322}
1323
1324impl From<&Var<Segment>> for Segment {
1325 fn from(value: &Var<Segment>) -> Self {
1326 Self(value.into())
1327 }
1328}
1329
1330impl From<Segment> for Expression {
1331 fn from(value: Segment) -> Self {
1332 value.0
1333 }
1334}
1335
1336impl Expr for Segment {
1337 type Target = Self;
1338
1339 fn get_type() -> ElementType {
1340 ElementType::Segment
1341 }
1342
1343 fn var(expr: String) -> Var<Self::Target> {
1344 Var::new(expr)
1345 }
1346}
1347
1348pub trait Addable {}
1350
1351impl Addable for Point {}
1352
1353impl Addable for Line {}
1354
1355impl Addable for Conic {}
1356
1357impl Addable for Segment {}
1358
1359impl Geogebra {
1360 pub fn add<T: Expr>(&mut self, expr: T, caption: impl ToString) -> Var<T::Target>
1362 where
1363 T::Target: Addable,
1364 {
1365 let label = self.next_label();
1366 let expr = expr.into();
1367
1368 self.data
1369 .construction
1370 .items
1371 .push(ConstructionItem::Expression(raw::Expression {
1372 type_: T::get_type(),
1373 label: label.clone(),
1374 exp: expr.expr.as_ref().clone(),
1375 }));
1376
1377 self.data
1378 .construction
1379 .items
1380 .push(ConstructionItem::Element(Element {
1381 type_: T::get_type(),
1382 label: label.clone(),
1383 caption: Some(caption.to_string().into()),
1384 ..expr.style.to_element()
1385 }));
1386
1387 T::var(label)
1388 }
1389
1390 pub fn add_point(
1392 &mut self,
1393 point: impl Into<Point>,
1394 caption: impl ToString,
1395 (x, y): (f64, f64),
1396 ) -> Var<Point> {
1397 let label = self.next_label();
1398 let point = point.into();
1399
1400 self.data
1401 .construction
1402 .items
1403 .push(ConstructionItem::Expression(raw::Expression {
1404 type_: ElementType::Point,
1405 label: label.clone(),
1406 exp: point.0.expr.as_ref().clone(),
1407 }));
1408
1409 self.data
1410 .construction
1411 .items
1412 .push(ConstructionItem::Element(Element {
1413 type_: ElementType::Point,
1414 label: label.clone(),
1415 caption: Some(caption.to_string().into()),
1416 coords: Some(Coords::xy(x, y)),
1417 ..point.0.style.to_element()
1418 }));
1419
1420 Point::var(label)
1421 }
1422
1423 pub fn var<T: Expr>(&mut self, expr: T) -> Var<T::Target> {
1425 let label = self.next_label();
1426 let expr = expr.into();
1427
1428 self.data
1429 .construction
1430 .items
1431 .push(ConstructionItem::Expression(raw::Expression {
1432 type_: T::get_type(),
1433 label: label.clone(),
1434 exp: expr.expr.as_ref().clone(),
1435 }));
1436
1437 self.data
1438 .construction
1439 .items
1440 .push(ConstructionItem::Element(Element {
1441 type_: T::get_type(),
1442 label: label.clone(),
1443 caption: None,
1444 show: Show::none(),
1445 ..expr.style.to_element()
1446 }));
1447
1448 T::var(label)
1449 }
1450}
1451
1452impl Default for Geogebra {
1453 fn default() -> Self {
1454 Self::new()
1455 }
1456}