#include "shape.h" shape::shape(const coordsys& sys):drawable(sys),center_angle(0), filled(false),fill_color(red) { } void shape::set_filled(bool b) { filled = b; } void shape::set_center_angle(double a) { center_angle = a; } void shape::set_fill_color(const color& c) { fill_color = c; } bool shape::inside(const coordinate& o, const canvas& C) { // true if o is in C if (round(o.x()) >= C.width() || o.x() < 0 || round(o.y()) >= C.height() || o.y() < 0) { return false; } return true; } bool shape::intersects(const coordinate& p1, const coordinate& p2, const canvas& C, coordinate& o) { // the equation of the line // // dy dy // ---- x + p1.y - ---- p1.x = y // dx dx // // where dy = p2.y - p1.y, dx = p2.y - p2.x // // special case when p2.x == p1.x, ie dx = 0 // if (p2.x() == p1.x()) { if (p2.x() >= 0 && p2.x() < C.width()) { o = coordinate(p2.x(),C.height()/2); return true; } else { return false; } } double dy = p2.y() - p1.y(), dx = p2.x() - p1.x(); double a = dy/dx, b = p1.y() - (p1.x()*dy)/dx; coordinate o1; bool o1_set=false; // does it intersect x = 0 if (b>=0 && b< (double)C.height()) { o1_set = true; o1 = coordinate(0,b); } // does it intersect x = C.width() - 1? double y = (double)(C.width()-1)*a + b; if (y>=0 && y < (double)C.height()) { if (!o1_set) { o1_set=true; o1 = coordinate(C.width()-1,y); } else { o = coordinate((o1.x()+C.width() - 1)/2,(o1.y()+y)/2); return true; } } // does it intersect y = C.height()-1 ? double x = ((double)C.height() - 1 - b)/a; if (x>=0 && x < (double)C.width()) { if (!o1_set) { o1_set=true; o1 = coordinate(x,C.height()-1); } else { o = coordinate((o1.x()+x)/2,(o1.y()+C.height()-1)/2); return true; } } // does it intersect y = 0 x = -b/a; if (!o1_set) return false; if (x>=0 && x < (double)C.width()) { o = coordinate((o1.x()+x)/2,o1.y()/2); return true; } return false; } coordinate shape::find_in(const coordinate& o1, const coordinate& o2, const canvas& C) { // assumptions o1 in, o2 in or out // // | o2 if o2 in // eval f(o1,o2) = | // | f(o1,(o1+o2)/2) // this procedure only takes a logarithmic number of steps, // and in practice is very fast if (inside(o2,C)) return o2; return find_in(o1, coordinate((o1.x()+o2.x())/2,(o1.y()+o2.y())/2),C); }