summaryrefslogtreecommitdiff
path: root/graphics/epix/samples/log.xp
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /graphics/epix/samples/log.xp
Initial commit
Diffstat (limited to 'graphics/epix/samples/log.xp')
-rw-r--r--graphics/epix/samples/log.xp217
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();
+}