1 ///
2 module plot2d.types;
3 
4 import plot2d.util;
5 
6 ///
7 struct DimSeg
8 {
9     ///
10     double min = 0, max = 0;
11 
12     /// set this.min as min(a,b), this.max as max(a,b)
13     this(double a, double b)
14     {
15         min = .min(a,b);
16         max = .max(a,b);
17     }
18 
19 @safe nothrow @nogc:
20 
21     /// quantize!round max and min by step and add and sub step
22     void stepExpand(double step)
23     {
24         max = max.quantize!round(step) + step;
25         min = min.quantize!round(step) - step;
26     }
27 
28     /// max - min
29     double diff() const @property { return max - min; }
30 }
31 
32 ///
33 struct Viewport
34 {
35     ///
36     DimSeg w, h;
37 
38     static Viewport initial()(auto ref const Point v)
39     { return Viewport(DimSeg(v.x, v.x), DimSeg(v.y, v.y)); }
40 
41     ///
42     void expand()(auto ref const Point p)
43     {
44         set!max(w.max, p.x);
45         set!max(h.max, p.y);
46         set!min(w.min, p.x);
47         set!min(h.min, p.y);
48     }
49 
50     ///
51     void expand()(auto ref const Viewport o)
52     {
53         set!max(w.max, o.w.max);
54         set!max(h.max, o.h.max);
55         set!min(w.min, o.w.min);
56         set!min(h.min, o.h.min);
57     }
58 
59     ///
60     void expandRel()(auto ref const Point p)
61     {
62         if (p.x > 0) w.max += p.x;
63         else w.min += p.x; // p.x is negative
64 
65         if (p.y > 0) h.max += p.y;
66         else h.min += p.y; // p.y is negative
67     }
68 
69     ///
70     bool onBinaryRight(string op)(auto ref const Point p)
71         if (op == "in")
72     {
73         return p.x <= w.max &&
74                p.x >= w.min &&
75                p.y <= h.max &&
76                p.y >= h.min;
77     }
78 
79 pure @safe nothrow @nogc const @property:
80 
81     /// left top
82     Point lt() { return Point(w.min, h.min); }
83     /// left bottom
84     Point lb() { return Point(w.min, h.max); }
85     /// right top
86     Point rt() { return Point(w.max, h.min); }
87     /// right bottom
88     Point rb() { return Point(w.max, h.max); }
89 }
90 
91 ///
92 struct Border
93 {
94     ///
95     double left, top, right, bottom;
96 
97     ///
98     this(double o) { this(o,o,o,o); }
99     ///
100     this(double x, double y) { this(x,y,x,y); }
101     ///
102     this(double l, double t, double r, double b)
103     { left = l; top = t; right = r; bottom = b; }
104 
105     const pure nothrow @safe @property @nogc
106     {
107         ///
108         double sx() { return left + right; }
109         ///
110         double sy() { return top + bottom; }
111     }
112 }
113 
114 ///
115 struct Point
116 {
117     ///
118     double x, y;
119 
120     const pure nothrow
121     {
122         ///
123         Point opBinary(string op)(auto ref const Point b)
124         { mixin(q{return Point(x %1$s b.x, y %1$s b.y);}.format(op)); }
125 
126         ///
127         Point opBinary(string op)(double b)
128         { mixin(q{return Point(x %1$s b, y %1$s b);}.format(op)); }
129 
130         ///
131         Point opUnary(string op)() if (op == "-")
132         { return Point(-x, -y); }
133 
134         @property
135         {
136             ///
137             double len2() { return x*x + y*y; }
138             ///
139             double len() { return hypot(x, y); }
140         }
141     }
142 }
143 
144 ///
145 struct Color
146 {
147     ///
148     double r=0, g=0, b=0, a=1;
149 
150     ///
151     auto opBinary(string op)(auto ref const Color c) const pure nothrow
152     {
153         mixin(q{return Color(r %1$s c.r,
154                              g %1$s c.g,
155                              b %1$s c.b,
156                              a %1$s c.a
157                              );}.format(op));
158     }
159 
160     ///
161     auto opBinary(string op)(double c) const pure nothrow
162     {
163         mixin(q{return Color(r %1$s c,
164                              g %1$s c,
165                              b %1$s c,
166                              a %1$s c
167                              );}.format(op));
168     }
169 
170     static pure nothrow
171     {
172         ///
173         Color red(double v=1, double b=0) { return Color(v, b, b, 1); }
174         ///
175         Color green(double v=1, double b=0) { return Color(b, v, b, 1); }
176         ///
177         Color blue(double v=1, double b=0) { return Color(b, b, v, 1); }
178         ///
179         Color mono(double v=1, double a=1) { return Color(v, v, v, a); }
180         ///
181         Color none() @property { return Color.mono(0, 0); }
182     }
183 }