#ifndef GRAPH_GUARD #define GRAPH_GUARD 1 #include "Point.h" #include //#include //#include #include "fltk.h" #include "std_lib_facilities.h" namespace Graph_lib { // defense against ill-behaved Linux macros: #undef major #undef minor struct Color { enum Color_type { red = FL_RED, blue = FL_BLUE, green = FL_GREEN, yellow = FL_YELLOW, white = FL_WHITE, black = FL_BLACK, magenta = FL_MAGENTA, cyan = FL_CYAN, dark_red = FL_DARK_RED, dark_green = FL_DARK_GREEN, dark_yellow = FL_DARK_YELLOW, dark_blue = FL_DARK_BLUE, dark_magenta = FL_DARK_MAGENTA, dark_cyan = FL_DARK_CYAN, gray = FL_GRAY, mid_gray = 48, dark_gray = 38, light_gray = 50 }; enum Transparency { invisible = 0, visible = 255 }; Color(Color_type cc) : v(visible), c(Fl_Color(cc)) {} Color(Color_type cc, Transparency vv) : v(vv), c(Fl_Color(cc)) {} Color(int cc) : v(visible), c(Fl_Color(cc)) {} Color(Transparency vv) : v(vv), c(Fl_Color()) {} int as_int() const { return c; } char visibility() const { return v; } void set_visibility(Transparency vv) { v = vv; } private: unsigned char v; // 0 or 1 for now Fl_Color c; }; struct Line_style { enum Line_style_type { solid = FL_SOLID, // ------- dash = FL_DASH, // - - - - dot = FL_DOT, // ....... dashdot = FL_DASHDOT, // - . - . dashdotdot = FL_DASHDOTDOT // -..-.. }; Line_style(Line_style_type ss) : s(ss), w(0) {} Line_style(Line_style_type lst, int ww) : s(lst), w(ww) {} Line_style(int ss) : s(ss), w(0) {} int width() const { return w; } int style() const { return s; } private: int s; int w; }; class Font { public: enum Font_type { helvetica = FL_HELVETICA, helvetica_bold = FL_HELVETICA_BOLD, helvetica_italic = FL_HELVETICA_ITALIC, helvetica_bold_italic = FL_HELVETICA_BOLD_ITALIC, courier = FL_COURIER, courier_bold = FL_COURIER_BOLD, courier_italic = FL_COURIER_ITALIC, courier_bold_italic = FL_COURIER_BOLD_ITALIC, times = FL_TIMES, times_bold = FL_TIMES_BOLD, times_italic = FL_TIMES_ITALIC, times_bold_italic = FL_TIMES_BOLD_ITALIC, symbol = FL_SYMBOL, screen = FL_SCREEN, screen_bold = FL_SCREEN_BOLD, zapf_dingbats = FL_ZAPF_DINGBATS }; Font(Font_type ff) : f(ff) {} Font(int ff) : f(ff) {} int as_int() const { return f; } private: int f; }; template class Vector_ref { vector v; vector owned; public: Vector_ref() {} Vector_ref(T* a, T* b = 0, T* c = 0, T* d = 0) { if (a) push_back(a); if (b) push_back(b); if (c) push_back(c); if (d) push_back(d); } ~Vector_ref() { for (typename vector::size_type i = 0; i < owned.size(); ++i) delete owned[i]; } void push_back(T& s) { v.push_back(&s); } void push_back(T* p) { v.push_back(p); owned.push_back(p); } T& operator[](int i) { return *v[i]; } const T& operator[](int i) const { return *v[i]; } int size() const { return v.size(); } T& back() { return *v[v.size() - 1]; } const T& back() const { return *v[v.size() - 1]; } using iterator = typename vector::iterator; iterator begin() { return v.begin(); } auto end() { return v.end(); } auto begin() const { return v.begin(); } auto end() const { return v.end(); } }; typedef double Fct(double); class Shape { // deals with color and style, and holds sequence of lines protected: Shape() {} // Not by the book: // Shape(initializer_list lst); // add() the Points to this Shape // Changed init_list constructor, i.e. implemented at all Shape(initializer_list lst) { for (Point p : lst) add(p); } // add() the Points to this Shape void add(Point p) { points.push_back(p); } void set_point(int i, Point p) { points[i] = p; } public: void draw() const; // deal with color and draw_lines protected: virtual void draw_lines() const; // simply draw the appropriate lines public: virtual void move(int dx, int dy); // move the shape +=dx and +=dy void set_color(Color col) { lcolor = col; } Color color() const { return lcolor; } void set_style(Line_style sty) { ls = sty; } Line_style style() const { return ls; } void set_fill_color(Color col) { fcolor = col; } Color fill_color() const { return fcolor; } Point point(int i) const { return points[i]; } int number_of_points() const { return int(points.size()); } virtual ~Shape() {} Shape(const Shape&) = delete; Shape& operator=(const Shape&) = delete; private: vector points; // not used by all shapes Color lcolor{static_cast(fl_color())}; Line_style ls{0}; Color fcolor{Color::invisible}; }; struct Function : Shape { // the function parameters are not stored Function(Fct f, double r1, double r2, Point orig, int count = 100, double xscale = 25, double yscale = 25); }; struct Fill { Fill() : no_fill(true), fcolor(0) {} Fill(Color c) : no_fill(false), fcolor(c) {} void set_fill_color(Color col) { fcolor = col; } Color fill_color() { return fcolor; } protected: bool no_fill; Color fcolor; }; struct Line : Shape { Line(Point p1, Point p2) { add(p1); add(p2); } }; struct Rectangle : Shape { Rectangle(Point xy, int ww, int hh) : h{hh}, w{ww} { if (h <= 0 || w <= 0) error("Bad rectangle: non-positive side"); add(xy); } Rectangle(Point x, Point y) : h{y.y - x.y}, w{y.x - x.x} { if (h <= 0 || w <= 0) error("Bad rectangle: first point is not top left"); add(x); } void draw_lines() const; int height() const { return h; } int width() const { return w; } private: int h; // height int w; // width }; bool intersect(Point p1, Point p2, Point p3, Point p4); struct Open_polyline : Shape { // open sequence of lines using Shape::Shape; void add(Point p) { Shape::add(p); } void draw_lines() const; }; struct Closed_polyline : Open_polyline { // closed sequence of lines using Open_polyline::Open_polyline; void draw_lines() const; // void add(Point p) { Shape::add(p); } }; struct Polygon : Closed_polyline { // closed sequence of non-intersecting lines using Closed_polyline::Closed_polyline; void add(Point p); void draw_lines() const; }; struct Lines : Shape { // indepentdent lines Lines() {} Lines(initializer_list lst) : Shape{lst} // Not equal to book constructor. { if (lst.size() % 2) error("odd number of points for Lines"); } Lines(initializer_list> lst) { // This is the constructor from the book, p.450 1st print. for (auto p : lst) add(p.first, p.second); } void draw_lines() const; void add(Point p1, Point p2) { Shape::add(p1); Shape::add(p2); } }; struct Text : Shape { // the point is the bottom left of the first letter Text(Point x, const string& s) : lab{s} { add(x); } void draw_lines() const; void set_label(const string& s) { lab = s; } string label() const { return lab; } void set_font(Font f) { fnt = f; } Font font() const { return Font(fnt); } void set_font_size(int s) { fnt_sz = s; } int font_size() const { return fnt_sz; } private: string lab; // label Font fnt{fl_font()}; int fnt_sz{(14 < fl_size()) ? fl_size() : 14}; // at least 14 point }; struct Axis : Shape { // representation left public enum Orientation { x, y, z }; Axis(Orientation d, Point xy, int length, int nummber_of_notches = 0, string label = ""); void draw_lines() const; void move(int dx, int dy); void set_color(Color c); Text label; Lines notches; // Orientation orin; // int notches; }; struct Circle : Shape { Circle(Point p, int rr) // center and radius : r{rr} { add(Point{p.x - r, p.y - r}); } void draw_lines() const; Point center() const { return {point(0).x + r, point(0).y + r}; } void set_radius(int rr) { r = rr; } int radius() const { return r; } private: int r; }; struct Ellipse : Shape { Ellipse(Point p, int ww, int hh) // center, min, and max distance from center : w{ww}, h{hh} { add(Point{p.x - ww, p.y - hh}); } void draw_lines() const; Point center() const { return {point(0).x + w, point(0).y + h}; } Point focus1() const { return {center().x + int(sqrt(double(w * w - h * h))), center().y}; } Point focus2() const { return {center().x - int(sqrt(double(w * w - h * h))), center().y}; } void set_major(int ww) { w = ww; } int major() const { return w; } void set_minor(int hh) { h = hh; } int minor() const { return h; } private: int w; int h; }; struct Marked_polyline : Open_polyline { Marked_polyline(const string& m) : mark(m) {} void draw_lines() const; private: string mark; }; struct Marks : Marked_polyline { Marks(const string& m) : Marked_polyline(m) { set_color(Color(Color::invisible)); } }; struct Mark : Marks { Mark(Point xy, char c) : Marks(string(1, c)) { add(xy); } }; struct Bad_image : Fl_Image { Bad_image(int h, int w) : Fl_Image(h, w, 0) {} void draw(int x, int y, int, int, int, int) { draw_empty(x, y); } }; struct Suffix { enum Encoding { none, jpg, gif, bmp }; }; Suffix::Encoding get_encoding(const string& s); struct Image : Shape { Image(Point xy, string s, Suffix::Encoding e = Suffix::none); ~Image() { delete p; } void draw_lines() const; void set_mask(Point xy, int ww, int hh) { w = ww; h = hh; cx = xy.x; cy = xy.y; } void move(int dx, int dy) { Shape::move(dx, dy); p->draw(point(0).x, point(0).y); } private: int w, h, cx, cy; // define "masking box" within image relative to // position (cx,cy) Fl_Image* p; Text fn; }; } // namespace Graph_lib #endif