TDT4102-Ovinger/Oving1/include/Graph_lib/Graph.h

624 lines
9.5 KiB
C++

#ifndef GRAPH_GUARD
#define GRAPH_GUARD 1
#include "Point.h"
#include <vector>
//#include<string>
//#include<cmath>
#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 T> class Vector_ref
{
vector<T*> v;
vector<T*> 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<T*>::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<T*>::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<Point> lst); // add() the Points to this Shape
// Changed init_list constructor, i.e. implemented at all
Shape(initializer_list<Point> 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<Point> points; // not used by all shapes
Color lcolor{static_cast<int>(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<Point> lst) : Shape{lst}
// Not equal to book constructor.
{
if (lst.size() % 2)
error("odd number of points for Lines");
}
Lines(initializer_list<pair<Point, Point>> 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