diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /graphics/epix/samples/log.xp |
Initial commit
Diffstat (limited to 'graphics/epix/samples/log.xp')
-rw-r--r-- | graphics/epix/samples/log.xp | 217 |
1 files changed, 217 insertions, 0 deletions
diff --git a/graphics/epix/samples/log.xp b/graphics/epix/samples/log.xp new file mode 100644 index 0000000000..4f16921cdf --- /dev/null +++ b/graphics/epix/samples/log.xp @@ -0,0 +1,217 @@ +/* -*-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<P> 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<P> 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_elt> mesh_data; + + // surface elements + for (int i=0; i<N1; ++i) + for (int j=0; j<N2; ++j) + mesh_data.push_back(mesh_elt(C_log, -3+du*i, -3+dv*j)); + + // path elements + for (int i=0; i<N3; ++i) + mesh_data.push_back(mesh_elt(C_log1, -2+i*dt)); + + stable_sort(mesh_data.begin(), mesh_data.end(), By_distance()); + + for (int i=0; i<mesh_data.size(); ++i) + mesh_data.at(i).draw(); + + dot_color(); + marker(C_log(0,-2), BOX); + marker(C_log(0, 0), BOX); + marker(C_log(0, 2), BOX); + + label_color(); + label(C_log(0,-2), P(6, 0), "$-2\\pi i$", r); + label(C_log(0, 0), P(6, 0), "$0$", r); + label(C_log(0, 2), P(-6, 0), "$2\\pi i$", l); + + end(); +} |