/* -*-ePiX-*- */ #include "epix.h" using namespace ePiX; // October 28, 2006 // // This file depicts two sheets of the Riemann surface of log, together // with the log function over the unit circle. Surface and path elements // must be drawn together. However, path-like mesh elements must be drawn // after surface elements that lie at the same location in the scene, // since otherwise surface elements' edges occlude the path. // // A mesh_elt class stores the necessary P data as well as a flag marking // the element as a segment or a surface patch. Elements are stored in a // std::vector (global to the scene) and sorted by distance. To ensure that // surface patches are printed first, their true distance is increased by a // "fudge" amount (0.25), making the By_distance class see them as farther // than they really are. // // Path elements are drawn in green; surface patches are shaded gray // according to the angle between the incoming light (from a point source) // and the surface normal. // // Surface patches are drawn as octagons to make the mesh appear smoother // than a quadrilateral mesh. The vertices of a patch are the images of the // corners and midpoints of a coordinate quadrilateral, "retracted" inward // by a small "gap" EPS (possibly zero). A positive gap simulates surface // transparency. // // (u,v+dv) (u+0.5*du,v+dv) (u+du,v+dv) // +----------------------+-----------------------+ // | *--------------------*---------------------* | // | | | | // | | | | // | | | | // + * (u+EPS,v+0.5*dv) * + (u+du,v+0.5*dv) // | | | | // | | | | // | | (u+EPS,v+EPS) | | // | *--------------------*---------------------* | // +----------------------+-----------------------+ // (u,v) (u+0.5*du,v) (u+du,v) const P LIGHT(2, 2, 0); // location of light, for shading const P VIEWPT(15,-10,6); // surface and path mesh fineness const int N1(18); const int N2(80); const int N3(120); const double du(4.5/N1); const double dv(6.0/N2); const double dt(4.0/N3); // "gap size" between surface mesh elements const double EPS(0); // (0.002); // visual styles void path_color() { green(0.8); } void label_color() { yellow(0.5); } void dot_color() { red(); } void path_width() { pen(1.5); } // class can represent either a surface element or a path element class mesh_elt { private: P pt1, pt2, pt3, pt4, pt5, pt6, pt7, pt8, center; double fudge; // artificial increment to distance static bool last_was_seg; bool is_segment; public: double how_far() const { return fudge + norm(center - camera.viewpt()); } mesh_elt(P f(double u, double v), double u0, double v0) : pt1(f(u0+EPS,v0+EPS)), pt2(f(u0+0.5*du,v0+EPS)), pt3(f(u0+du-EPS,v0+EPS)), pt4(f(u0+du-EPS,v0+0.5*dv)), pt5(f(u0+du-EPS,v0+dv-EPS)), pt6(f(u0+0.5*du,v0+dv-EPS)), pt7(f(u0+EPS,v0+dv-EPS)), pt8(f(u0+EPS,v0+0.5*dv)), center(0.25*(pt1 + (pt3 + (pt5 + pt7)))), fudge(0.25), is_segment(false) { } mesh_elt(P f(double), double t0) : pt1(f(t0)), pt2(f(t0+0.25*dt)), pt3(f(t0+0.5*dt)), pt4(f(t0+0.75*dt)), pt5(f(t0+dt)), pt6(), pt7(), pt8(), center(0.333*(pt1 + (pt3 + pt5))), fudge(0), is_segment(true) { } void draw() const { if (!is_segment) { P normal((pt2 - pt1)*(pt4 - pt1)); normal *= 1/norm(normal); double dens(0.5*(1-((normal|LIGHT)/norm(LIGHT)))); if (mesh_elt::last_was_seg) { mesh_elt::last_was_seg=false; plain(); // reset pen width } black(); gray(dens); std::vector

bd; bd.push_back(pt1); bd.push_back(pt2); bd.push_back(pt3); bd.push_back(pt4); bd.push_back(pt5); bd.push_back(pt6); bd.push_back(pt7); bd.push_back(pt8); path temp(bd, true, true); // closed and filled temp.draw(); } else { // segment if (!mesh_elt::last_was_seg) { mesh_elt::last_was_seg=true; path_width(); path_color(); } std::vector

bd; bd.push_back(pt1); bd.push_back(pt2); bd.push_back(pt3); bd.push_back(pt4); bd.push_back(pt5); path temp(bd, false, false); temp.draw(); } } // end of mesh_elt::draw() }; // end of class mesh_elt // initialize static data bool mesh_elt::last_was_seg = false; class By_distance { public: bool operator() (const mesh_elt arg1, const mesh_elt arg2) { return (arg1.how_far()) > (arg2.how_far()); } }; // the maps to be plotted P C_log(double u, double v) { return polar(exp(u), M_PI*v) + P(0, 0, u+M_PI*v); } P C_log1(double t) { return C_log(0,t); } int main() { bounding_box(P(-6, -12),P(6,12)); unitlength("1in"); picture(P(4,8)); begin(); fill(); degrees(); // label_angle(90); label(P(0, ymin()), P(0,4), "$z=\\mathrm{Re}\\,\\log(x+iy) + \\mathrm{Im}\\,\\log(x+iy)$", t); radians(); // label_angle(0); viewpoint(VIEWPT); camera.range(20); std::vector mesh_data; // surface elements for (int i=0; i