OSDN Git Service

first
[psychlops/cpp.git] / psychlops / core / graphic / psychlops_g_shape.cpp
1 /*
2  *  psychlops_g_shape.cpp
3  *  Psychlops Standard Library (Universal)
4  *
5  *  Last Modified 2005/10/05 by Kenchi HOSOKAWA
6  *  (C) 2005 Kenchi HOSOKAWA, Kazushi MARUYA, Takao SATO
7  */
8
9 #include "psychlops_g_fundamental.h"
10 #include "psychlops_g_color.h"
11 #include "psychlops_g_shape.h"
12
13 #include "psychlops_g_canvas.h"
14 #include "psychlops_g_image.h"
15
16 #include <stdlib.h>
17 #include <Math.h>
18
19
20 namespace Psychlops {
21
22 //      Shape& Shape::draw() { draw(*Drawable::prime); return *this; };
23
24
25         Stroke::Stroke() {
26                 color = Color::white;
27                 width = 1;
28                 pattern = SOLID;
29         }
30         Stroke::Stroke(const Color col, const double wid, const Pattern pat) {
31                 color = col;
32                 width = wid;
33                 pattern = pat;
34         }
35
36         Stroke& Stroke::set(const Color col, const double wid, const Pattern pat) {
37                 color = col;
38                 width = wid;
39                 pattern = pat;
40                 return *this;
41         }
42
43         const Stroke Stroke::null_line(Color::null_color, 0, SOLID);
44         const Stroke Stroke::hair_line(Color(0.75), 1, SOLID);
45
46         Shape::Shape() : fill(Color::null_color), stroke(Stroke::null_line) {
47         }
48         Shape& Shape::draw_base(Drawable &target) {
49                 if(fill.getA()!=0) draw(fill, target);
50                 if(stroke.width!=0) draw(stroke, target);
51                 return *this;
52         }
53 #if !defined(_MSC_VER)
54         Shape& Shape::draw(Drawable &target) {
55                 return draw_base(target);
56         }
57 #endif
58
59
60
61
62
63 ////////        Rectangle ////////
64
65         template <typename X> inline void Rectangle::correctInversion(X &l, X &t, X &r, X &b) {
66                 X tmp;
67                 if(l>r) { tmp=l; l=r; r=tmp; }
68                 if(t>b) { tmp=t; t=b; b=tmp; }
69         }
70         inline void Rectangle::setbypix(double l, double t, double r, double b) {
71                 left = l;
72                 top = t;
73                 right = r;
74                 bottom = b;
75         }
76         inline void Rectangle::setbypix(double width, double height) {
77                 setbypix(0.0, 0.0, width-1, height-1);
78         }
79         inline void Rectangle::set(double size) {
80                 setbypix(0.0, 0.0, size-1, size-1);
81         }
82
83
84 //      Rectangle::Rectangle() : left(0.0), top(0.0), right(0.0), bottom(0.0), color(0.0, 0.0, 0.0) {
85         Rectangle::Rectangle() {}
86         Rectangle::Rectangle(double l, double t, double r, double b) {
87                 if(r-l<=0 || b-t<=0) throw Exception(typeid(*this), "SIZE ERROR", "Width and Height must be defined as positive value.");
88                 set(l, t, r, b);
89         }
90         Rectangle::Rectangle(double width, double height) {
91                 if(width<=0 || height<=0) throw Exception(typeid(*this), "SIZE ERROR", "Width and Height must be defined as positive value.");
92                 set(width, height);
93         }
94
95         Rectangle& Rectangle::set(const Rectangle &r) {
96                 set(r.left, r.top, r.right, r.bottom);
97                 return *this;
98         }
99         Rectangle& Rectangle::set(const Point &po1, const Point &po2) {
100                 double l=po1.x, t=po1.y, r=po2.x, b=po2.y;
101                 correctInversion(l,t,r,b);
102                 setbypix(l, t, r, b);
103                 return *this;
104         }
105         Rectangle& Rectangle::set(double l, double t, double r, double b) {
106                 correctInversion(l,t,r,b);
107                 setbypix(l, t, r, b);
108                 return *this;
109         }
110         Rectangle& Rectangle::set(double width, double height) {
111                 setbypix(width, height);
112                 return *this;
113         }
114         Rectangle Rectangle::dup() {
115                 return *this;
116         }
117         Rectangle& Rectangle::resize(double width, double height) {
118                 Point po = getCenter();
119                 setbypix(width, height);
120                 centering(po);
121                 return *this;
122         }
123         Rectangle& Rectangle::locate(const Point &p) {
124                 return locate(p.x, p.y);
125         }
126         Rectangle& Rectangle::locate(double x, double y) {
127                 double w = getWidth(), h = getHeight();
128                 set(x,y,x+w-1,y+h-1);
129                 return *this;
130         }\r
131         Rectangle& Rectangle::alignLeft(const double lef) {\r
132                 return move_to(lef, getTop(), getDatum().z);\r
133         }\r
134         Rectangle& Rectangle::alignTop(const double to_) {\r
135                 return move_to(getLeft(), to_, getDatum().z);\r
136         }\r
137         Rectangle& Rectangle::alignRight(const double rig) {\r
138                 return move_to(rig-getWidth(), getTop(), getDatum().z);\r
139         }\r
140         Rectangle& Rectangle::alignBottom(const double bot) {\r
141                 return move_to(getLeft(), bot-getHeight(), getDatum().z);\r
142         }\r
143
144
145         Rectangle& Rectangle::setDatum(const Point& p) {
146                 return move_to(p.x, p.y, p.z);
147         }
148         Rectangle& Rectangle::move_to(const double x, const double y, const double z) {
149                 //int Hoffset = x-getHcenter(), Voffset=getVcenter();
150                 //return shift(Hoffset, Voffset);
151                 double l = x,
152                         r = x + (getWidth()-1),
153                         t = y,
154                         b = y + (getHeight()-1);
155                 setbypix(l,t,r,b);
156                 return *this;
157         }
158         Rectangle& Rectangle::centering(const double x, const double y, const double z) {
159                 //int Hoffset = x-getHcenter(), Voffset=getVcenter();
160                 //return shift(Hoffset, Voffset);
161                 double l = x - (getWidth()-1)/2.0,
162                         r = x + (getWidth()-1)/2.0,
163                         t = y - (getHeight()-1)/2.0,
164                         b = y + (getHeight()-1)/2.0;
165                 setbypix(l,t,r,b);
166                 return *this;
167         }
168         Rectangle& Rectangle::centering(const Drawable& target) {
169                 return centering(target.getCenter());
170         }
171         Rectangle& Rectangle::centering(const Figure &fig) {
172                 return centering(fig.getDatum());
173         }
174         Rectangle& Rectangle::centering(const Point &po) {
175                 return centering(po.x, po.y);
176         }
177         Rectangle& Rectangle::shift(const double h, const double v, const double d) {
178                 set(    left + h,
179                                 top + v,
180                                 right + h,
181                                 bottom + v);
182                 return *this;
183         }
184
185         Rectangle& Rectangle::draw(Drawable &target) {
186                 Shape::draw_base(target);
187                 return *this;
188         }
189         Rectangle& Rectangle::draw(const Color &col, Drawable &target) {
190                 Drawable::prime->rect(*this, col);
191                 return *this;
192         }
193         Rectangle& Rectangle::draw(const Stroke &strk, Drawable &target) {
194                 Drawable::prime->rect(*this, strk);
195                 return *this;
196         }
197                 // obsolete
198                 Rectangle& Rectangle::display() {
199                         return draw();
200                 }
201                 Rectangle& Rectangle::display(const Color &col) {
202                         return draw(col);
203                 }
204
205
206         void Rectangle::clipped_by(const Rectangle &source) {
207                 double t=top, l=left, b=bottom, r=right;
208                 if(top < source.top) { t = source.top; }
209                 if(left < source.left) { l = source.left; }
210                 if(bottom > source.bottom) { b = source.bottom; }
211                 if(right > source.right) { r = source.right; }
212                 try {
213                         set(l, t, r, b);
214                 } catch(...) {
215                         throw Exception(typeid(*this), "SIZE ERROR", "Cripped rectangle is null.");
216                 }
217         }
218         void Rectangle::clip(Rectangle &target) {
219                 double t=top, l=left, b=bottom, r=right;
220                 if(top < target.top) { t = target.top; }
221                 if(left < target.left) { l = target.left; }
222                 if(bottom > target.bottom) { b = target.bottom; }
223                 if(right > target.right) { r = target.right; }
224                 try {
225                         set(l, t, r, b);
226                 } catch(...) {
227                         throw Exception(typeid(*this), "SIZE ERROR", "Cripped rectangle is null.");
228                 }
229         }
230                 // obsolete: misspelled
231                 void Rectangle::cripped(const Rectangle &source) { clipped_by(source); }
232                 void Rectangle::crip(Rectangle &target) { clip(target); }
233
234         bool Rectangle::include(double x, double y) const {
235                 return (top <= y) && (left <= x) && (bottom >= y) && (right >= x);
236         }
237         bool Rectangle::include(const Point &p) const {
238                 return (top <= p.y) && (left <= p.x) && (bottom >= p.y) && (right >= p.x);
239         }
240         bool Rectangle::include(const Rectangle &rect) const {
241                 return (top <= rect.top) && (left <= rect.left) && (bottom >= rect.bottom) && (right >= rect.right);
242         }
243
244
245         void Rectangle::setColor(Color col) {
246                 fill = col;
247         }
248
249         double Rectangle::getWidth() const { return right>left ? right-left+1 : left-right+1; }
250         double Rectangle::getHeight() const { return bottom>top ? bottom-top+1 : top-bottom+1; }
251         const Point Rectangle::getDatum() const {
252                 //Point po(getHcenter(), getVcenter());\r
253                 Point po(left, top);
254                 return po;
255         }
256         const Point Rectangle::getCenter() const {
257                 Point po(getHcenter(), getVcenter());
258                 return po;
259         }
260         double Rectangle::getHcenter() const { return (double)( (right + left) / 2.0 ); }
261         double Rectangle::getVcenter() const { return (double)( (bottom + top) / 2.0 ); }
262         double Rectangle::getTop() const { return top; }
263         double Rectangle::getLeft() const { return left; }
264         double Rectangle::getBottom() const { return bottom; }
265         double Rectangle::getRight() const { return right; }
266
267
268
269
270         ////////        Line ////////
271
272         Line::Line() {}
273         Line::Line(const double x1, const double y1, const double x2, const double y2) : end(Point(x2, y2)) {
274                 datum.x = x1;
275                 datum.y = y1;
276                 datum.z = 0;
277         }
278         Line::Line(const Point &dbegin, const Point &dend) : end(dend) {
279                 datum = dbegin;
280         }
281         Line& Line::set(const double x1, const double y1, const double x2, const double y2) {
282                 datum.x = x1;
283                 datum.y = y1;
284                 datum.z = 0;
285                 end.x = x2;
286                 end.y = y2;
287                 end.z = 0;
288                 return *this;
289         }
290         Line& Line::set(const Point &dbegin, const Point &dend) {
291                 datum = dbegin;
292                 end = dend;
293                 return *this;
294         }
295
296         Line& Line::setDatum(const Point &p) {
297                 Point vec = end-datum;
298                 datum = p;
299                 end = (Point)p + vec;
300                 return *this;
301         }
302         Line& Line::setStart(const Point &p) {
303                 datum = p;
304                 return *this;
305         }
306         Line& Line::centering(const Point &p) {
307                 Point v = end-datum;
308                 datum.set(p.x-v.x, p.y-v.y, p.z-v.y);
309                 end.set(p.x+v.x, p.y+v.y, p.z+v.y);
310                 return *this;
311         }\r
312         Line& Line::shift(const double x, const double y, const double z) {\r
313                 datum.x += x;\r
314                 datum.y += y;\r
315                 datum.z += z;\r
316                 end.x += x;\r
317                 end.y += y;\r
318                 end.z += z;\r
319                 return *this;\r
320         }
321         Line& Line::draw(Drawable &target) {
322                 target.line(*this, stroke);
323                 return *this;
324         }
325         Line& Line::draw(const Color &col, Drawable &target) {
326                 target.line(*this, col);
327                 return *this;
328         }
329         Line& Line::draw(const Stroke &strk, Drawable &target) {
330                 target.line(*this, strk);
331                 return *this;
332         }
333
334         Point Line::getEnd() const {
335                 return (Point)end;
336         }
337
338
339         ////////        Ellipse ////////
340
341         Ellipse::Ellipse() : radius(0), v_radius(0), sector_begin(0), sector_end(0) {}
342         Ellipse::Ellipse(const double d_radius, const double d_v_radius, const Point& d_datum) : sector_begin(0), sector_end(0) { set(d_radius, d_v_radius, d_datum); }
343         Ellipse::Ellipse(const Rectangle& rect) : radius(0), v_radius(0), sector_begin(0), sector_end(0) { set(rect); }
344         Ellipse::~Ellipse(){}
345         Ellipse& Ellipse::set(const double d_radius, const double d_v_radius, const Point& d_datum) {
346                 datum = d_datum;
347                 radius = d_radius;
348                 v_radius = (d_v_radius<0) ? d_radius : d_v_radius;
349                 return *this;
350         }
351         Ellipse& Ellipse::set(const Rectangle& rect) {
352                 datum = rect.getDatum();
353                 radius = rect.getWidth();
354                 v_radius = rect.getHeight();
355                 return *this;
356         }\r
357         Ellipse& Ellipse::resize(double width, double height)\r
358         {\r
359                 radius = width;\r
360                 v_radius = height;\r
361                 return *this;\r
362         }
363         Ellipse& Ellipse::centering(const Point &p) {
364                 datum = p;
365                 return *this;
366         }
367         Ellipse& Ellipse::draw(Drawable &target) {
368                 Shape::draw_base(target);
369                 return *this;
370         }
371         Ellipse& Ellipse::draw(const Color &col, Drawable &target){
372                 target.ellipse(*this, col);
373                 return *this;
374         }
375         Ellipse& Ellipse::draw(const Stroke &strk, Drawable &target) {
376                 target.ellipse(*this, strk);
377                 return *this;
378         }
379 \r
380         Ellipse& Ellipse::centering(const Figure& fig) { centering(fig.getDatum()); return *this; }
381         Ellipse& Ellipse::centering(const Drawable &target) { centering(target.getCenter()); return *this; }
382         Ellipse& Ellipse::centering(const double x, const double y, const double z) { centering(Point(x,y,z)); return *this; }
383         Ellipse& Ellipse::shift(const double x, const double y, const double z) { Point n=getDatum(); n=n+Point(x,y,z); setDatum(n); return *this; }
384
385         ////////        Polygon ////////
386
387         Polygon::Polygon() {}
388         bool Polygon::empty() const {
389                 return vertices.empty();
390         }
391         Polygon& Polygon::append(const Point& p) {
392                 vertices.push_back(p);
393                 return *this;
394         }
395         Polygon& Polygon::append(const double x, const double y, const double z) { return append(Point(x,y,z)); }
396         Polygon& Polygon::centering(const Point &p) {
397                 datum = p;
398                 return *this;
399         }
400         Polygon& Polygon::draw(Drawable& target) {
401                 Shape::draw_base(target);
402                 return *this;
403         }
404 /*
405         Polygon& Polygon::append(const Point& p, const Color& col) {
406                 Vertex v;
407                 v.point = p;
408                 v.color = col;
409                 vertices.push_back(v);
410                 return *this;
411         }
412 */
413 //      Polygon& Polygon::append(const double x, const double y, const double z, const Color& col) { return append(Point(x, y, z), col); }
414 //      Polygon& Polygon::append(const double x, const double y, const Color& col) { return add(x,y,0,col); }
415
416         Polygon& Polygon::draw(const Color& col, Drawable& target) {
417                 target.polygon(*this, col);
418                 return *this;
419         }
420         Polygon& Polygon::draw(const Stroke& strk, Drawable &target) {
421                 target.polygon(*this, strk);
422                 return *this;
423         }
424
425         Polygon& Polygon::centering(const Figure& fig) { centering(fig.getDatum()); return *this; }
426         Polygon& Polygon::centering(const Drawable &target) { centering(target.getCenter()); return *this; }
427         Polygon& Polygon::centering(const double x, const double y, const double z) { centering(Point(x,y,z)); return *this; }
428         Polygon& Polygon::shift(const double x, const double y, const double z) { Point n=getDatum(); n=n+Point(x,y,z); setDatum(n); return *this; }
429
430         ////////        PolyLine ////////
431
432         PolyLine::PolyLine() {}
433         bool PolyLine::empty() const {
434                 return vertices.empty();
435         }
436         PolyLine& PolyLine::append(const Point& p) {
437                 vertices.push_back(p);
438                 return *this;
439         }
440         PolyLine& PolyLine::append(const double x, const double y, const double z) { return append(Point(x,y,z)); }
441         PolyLine& PolyLine::centering(const Point &p) {
442                 datum = p;
443                 return *this;
444         }
445         PolyLine& PolyLine::draw(Drawable& target) {
446                 Shape::draw_base(target);
447                 return *this;
448         }
449         PolyLine& PolyLine::draw(const Color& col, Drawable& target) {
450                 target.polyline(*this, col);
451                 return *this;
452         }
453         PolyLine& PolyLine::draw(const Stroke& strk, Drawable &target) {
454                 target.polyline(*this, strk);
455                 return *this;
456         }
457
458         PolyLine& PolyLine::centering(const Figure& fig) { centering(fig.getDatum()); return *this; }
459         PolyLine& PolyLine::centering(const Drawable &target) { centering(target.getCenter()); return *this; }
460         PolyLine& PolyLine::centering(const double x, const double y, const double z) { centering(Point(x,y,z)); return *this; }
461         PolyLine& PolyLine::shift(const double x, const double y, const double z) { Point n=getDatum(); n=n+Point(x,y,z); setDatum(n); return *this; }
462
463 }       /*      <- namespace Psycholops         */