/* -*-ePiX-*- */ #include "epix.h" using namespace ePiX; // sortable class for drawing hyperboloid rulings class Sgmt { public: Sgmt(const P& tail, const P& head) : m_tail(tail), m_head(head) { } P midpt() const { return 0.5*(m_tail + m_head); } void draw() const { pen(White(), 3); line(m_tail, m_head); bold(Black()); line(m_tail, m_head); } private: P m_tail, m_head; }; // Must not be called until camera location is set class by_distance { public: by_distance() : m_viewpt(camera.viewpt()) { } // crude hack works for these special purposes bool operator() (const Sgmt& S1, const Sgmt& S2) { return norm(S1.midpt() - m_viewpt) > norm(S2.midpt() - m_viewpt); } private: P m_viewpt; }; int main() { picture(P(-1, -1), P(1, 1), "2 x 2in"); begin(); // number of segments const int N(20); double x0(4), y0(0.5), th(Atan(y0/x0)), dth(-M_PI_4), step(2*M_PI/N); camera.at(P(x0, y0, 1.25)).range(0); bold(); // back half of base ellipse(P(0,0,0), E_1, E_2, M_PI_2+th, 3*M_PI_2+th); // rulings std::list data; for (int i=0; i < N; ++i) data.push_back(Sgmt(cyl(1, i*step, 0), cyl(1, i*step + dth, 1))); data.sort(by_distance()); for (std::list::const_iterator ep=data.begin(); ep != data.end(); ++ep) (*ep).draw(); // top, and front half of base ellipse(P(0,0,1), E_1, E_2); ellipse(P(0,0,0), E_1, E_2, -M_PI_2+th, M_PI_2+th); tikz_format(); end(); }