Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "Graph.h"
- #include<map>
- #include <iostream>
- #include <string>
- #include "std_lib_facilities.h"
- namespace Graph_lib {
- void Shape::draw_lines() const
- {
- if (color().visibility() && 1<points.size()) // draw sole pixel?
- for (unsigned int i = 1; i<points.size(); ++i)
- fl_line(points[i - 1].x, points[i - 1].y, points[i].x, points[i].y);
- }
- void Shape::draw() const
- {
- Fl_Color oldc = fl_color();
- // there is no good portable way of retrieving the current style
- fl_color(lcolor.as_int());
- fl_line_style(ls.style(), ls.width());
- draw_lines();
- fl_color(oldc); // reset color (to pevious) and style (to default)
- fl_line_style(0);
- }
- // does two lines (p1,p2) and (p3,p4) intersect?
- // if se return the distance of the intersect point as distances from p1
- inline std::pair<double, double> line_intersect(Point p1, Point p2, Point p3, Point p4, bool& parallel)
- {
- double x1 = p1.x;
- double x2 = p2.x;
- double x3 = p3.x;
- double x4 = p4.x;
- double y1 = p1.y;
- double y2 = p2.y;
- double y3 = p3.y;
- double y4 = p4.y;
- double denom = ((y4 - y3)*(x2 - x1) - (x4 - x3)*(y2 - y1));
- if (denom == 0) {
- parallel = true;
- return std::pair<double, double>(0, 0);
- }
- parallel = false;
- return std::pair<double, double>(((x4 - x3)*(y1 - y3) - (y4 - y3)*(x1 - x3)) / denom,
- ((x2 - x1)*(y1 - y3) - (y2 - y1)*(x1 - x3)) / denom);
- }
- //intersection between two line segments
- //Returns true if the two segments intersect,
- //in which case intersection is set to the point of intersection
- bool line_segment_intersect(Point p1, Point p2, Point p3, Point p4, Point& intersection) {
- bool parallel;
- std::pair<double, double> u = line_intersect(p1, p2, p3, p4, parallel);
- if (parallel || u.first < 0 || u.first > 1 || u.second < 0 || u.second > 1) return false;
- intersection.x = p1.x + u.first*(p2.x - p1.x);
- intersection.y = p1.y + u.first*(p2.y - p1.y);
- return true;
- }
- void Polygon::add(Point p)
- {
- int np = number_of_points();
- if (1<np) { // check that thenew line isn't parallel to the previous one
- if (p == point(np - 1)) error("polygon point equal to previous point");
- bool parallel;
- line_intersect(point(np - 1), p, point(np - 2), point(np - 1), parallel);
- if (parallel)
- error("two polygon points lie in a straight line");
- }
- for (int i = 1; i<np - 1; ++i) { // check that new segment doesn't interset and old point
- Point ignore(0, 0);
- if (line_segment_intersect(point(np - 1), p, point(i - 1), point(i), ignore))
- error("intersect in polygon");
- }
- Closed_polyline::add(p);
- }
- void Polygon::draw_lines() const
- {
- if (number_of_points() < 3) error("less than 3 points in a Polygon");
- Closed_polyline::draw_lines();
- }
- void Open_polyline::draw_lines() const
- {
- if (fill_color().visibility()) {
- fl_color(fill_color().as_int());
- fl_begin_complex_polygon();
- for (int i = 0; i<number_of_points(); ++i) {
- fl_vertex(point(i).x, point(i).y);
- }
- fl_end_complex_polygon();
- fl_color(color().as_int()); // reset color
- }
- if (color().visibility())
- Shape::draw_lines();
- }
- void Closed_polyline::draw_lines() const
- {
- Open_polyline::draw_lines();
- if (color().visibility()) // draw closing line:
- fl_line(point(number_of_points() - 1).x, point(number_of_points() - 1).y, point(0).x, point(0).y);
- }
- void Shape::move(int dx, int dy)
- {
- for (unsigned int i = 0; i<points.size(); ++i) {
- points[i].x += dx;
- points[i].y += dy;
- }
- }
- void Lines::draw_lines() const
- {
- // if (number_of_points()%2==1) error("odd number of points in set of lines");
- if (color().visibility())
- for (int i = 1; i<number_of_points(); i += 2)
- fl_line(point(i - 1).x, point(i - 1).y, point(i).x, point(i).y);
- }
- void Text::draw_lines() const
- {
- int ofnt = fl_font();
- int osz = fl_size();
- fl_font(fnt.as_int(), fnt_sz);
- fl_draw(lab.c_str(), point(0).x, point(0).y);
- fl_font(ofnt, osz);
- }
- Function::Function(Fct f, double r1, double r2, Point xy, int count, double xscale, double yscale)
- // graph f(x) for x in [r1:r2) using count line segments with (0,0) displayed at xy
- // x coordinates are scaled by xscale and y coordinates scaled by yscale
- {
- if (r2 - r1 <= 0) error("bad graphing range");
- if (count <= 0) error("non-positive graphing count");
- double dist = (r2 - r1) / count;
- double r = r1;
- for (int i = 0; i<count; ++i) {
- add(Point(xy.x + int(r*xscale), xy.y - int(f(r)*yscale)));
- r += dist;
- }
- }
- void Rectangle::draw_lines() const
- {
- if (fill_color().visibility()) { // fill
- fl_color(fill_color().as_int());
- fl_rectf(point(0).x, point(0).y, w, h);
- fl_color(color().as_int()); // reset color
- }
- if (color().visibility()) { // edge on top of fill
- fl_color(color().as_int());
- fl_rect(point(0).x, point(0).y, w, h);
- }
- }
- Axis::Axis(Orientation d, Point xy, int length, int n, std::string lab)
- :label(Point(0, 0), lab)
- {
- if (length<0) error("bad axis length");
- switch (d) {
- case Axis::x:
- { Shape::add(xy); // axis line
- Shape::add(Point(xy.x + length, xy.y)); // axis line
- if (1<n) {
- int dist = length / n;
- int x = xy.x + dist;
- for (int i = 0; i<n; ++i) {
- notches.add(Point(x, xy.y), Point(x, xy.y - 5));
- x += dist;
- }
- }
- // label under the line
- label.move(length / 3, xy.y + 20);
- break;
- }
- case Axis::y:
- { Shape::add(xy); // a y-axis goes up
- Shape::add(Point(xy.x, xy.y - length));
- if (1<n) {
- int dist = length / n;
- int y = xy.y - dist;
- for (int i = 0; i<n; ++i) {
- notches.add(Point(xy.x, y), Point(xy.x + 5, y));
- y -= dist;
- }
- }
- // label at top
- label.move(xy.x - 10, xy.y - length - 10);
- break;
- }
- case Axis::z:
- error("z axis not implemented");
- }
- }
- void Axis::draw_lines() const
- {
- Shape::draw_lines(); // the line
- notches.draw(); // the notches may have a different color from the line
- label.draw(); // the label may have a different color from the line
- }
- void Axis::set_color(Color c)
- {
- Shape::set_color(c);
- notches.set_color(c);
- label.set_color(c);
- }
- void Axis::move(int dx, int dy)
- {
- Shape::move(dx, dy);
- notches.move(dx, dy);
- label.move(dx, dy);
- }
- void Circle::draw_lines() const
- {
- if (fill_color().visibility()) { // fill
- fl_color(fill_color().as_int());
- fl_pie(point(0).x, point(0).y, r + r - 1, r + r - 1, 0, 360);
- fl_color(color().as_int()); // reset color
- }
- if (color().visibility()) {
- fl_color(color().as_int());
- fl_arc(point(0).x, point(0).y, r + r, r + r, 0, 360);
- }
- }
- void Ellipse::draw_lines() const
- {
- if (fill_color().visibility()) { // fill
- fl_color(fill_color().as_int());
- fl_pie(point(0).x, point(0).y, w + w - 1, h + h - 1, 0, 360);
- fl_color(color().as_int()); // reset color
- }
- if (color().visibility()) {
- fl_color(color().as_int());
- fl_arc(point(0).x, point(0).y, w + w, h + h, 0, 360);
- }
- }
- void draw_mark(Point xy, char c)
- {
- static const int dx = 4;
- static const int dy = 4;
- string m(1, c);
- fl_draw(m.c_str(), xy.x - dx, xy.y + dy);
- }
- void Marked_polyline::draw_lines() const
- {
- Open_polyline::draw_lines();
- for (int i = 0; i<number_of_points(); ++i)
- draw_mark(point(i), mark[i%mark.size()]);
- }
- /*
- void Marks::draw_lines() const
- {
- for (int i=0; i<number_of_points(); ++i)
- fl_draw(mark.c_str(),point(i).x-4,point(i).y+4);
- }
- */
- std::map<string, Suffix::Encoding> suffix_map;
- int init_suffix_map()
- {
- suffix_map["jpg"] = Suffix::jpg;
- suffix_map["JPG"] = Suffix::jpg;
- suffix_map["jpeg"] = Suffix::jpg;
- suffix_map["JPEG"] = Suffix::jpg;
- suffix_map["gif"] = Suffix::gif;
- suffix_map["GIF"] = Suffix::gif;
- suffix_map["bmp"] = Suffix::bmp;
- suffix_map["BMP"] = Suffix::bmp;
- return 0;
- }
- Suffix::Encoding get_encoding(const std::string& s)
- // try to deduce type from file name using a lookup table
- {
- static int x = init_suffix_map();
- string::const_iterator p = find(s.begin(), s.end(), '.');
- if (p == s.end()) return Suffix::none; // no suffix
- string suf(p + 1, s.end());
- return suffix_map[suf];
- }
- bool can_open(const std::string& s)
- // check if a file named s exists and can be opened for reading
- {
- ifstream ff(s.c_str());
- return ff ? true : false;
- }
- // somewhat overelaborate constructor
- // because errors related to image files can be such a pain to debug
- Image::Image(Point xy, string s, Suffix::Encoding e)
- :w(0), h(0), fn(xy, "")
- {
- add(xy);
- if (!can_open(s)) {
- fn.set_label("cannot open \"" + s + '\"');
- p = new Bad_image(30, 20); // the "error image"
- return;
- }
- if (e == Suffix::none) e = get_encoding(s);
- switch (e) {
- case Suffix::jpg:
- p = new Fl_JPEG_Image(s.c_str());
- break;
- case Suffix::gif:
- p = new Fl_GIF_Image(s.c_str());
- break;
- // case Suffix::bmp:
- // p = new Fl_BMP_Image(s.c_str());
- // break;
- default: // Unsupported image encoding
- fn.set_label("unsupported file type \"" + s + '\"');
- p = new Bad_image(30, 20); // the "error image"
- }
- }
- void Image::draw_lines() const
- {
- if (fn.label() != "") fn.draw_lines();
- if (w&&h)
- p->draw(point(0).x, point(0).y, w, h, cx, cy);
- else
- p->draw(point(0).x, point(0).y);
- }
- } // Graph
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement