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/helicoid.flx |
Initial commit
Diffstat (limited to 'graphics/epix/samples/helicoid.flx')
-rw-r--r-- | graphics/epix/samples/helicoid.flx | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/graphics/epix/samples/helicoid.flx b/graphics/epix/samples/helicoid.flx new file mode 100644 index 0000000000..fdf68fc7ad --- /dev/null +++ b/graphics/epix/samples/helicoid.flx @@ -0,0 +1,133 @@ +/* -*-flix-*- */ +/* + * Animation depicting the local isometric deformation of a + * catenoid to a helicoid through minimal immersions + */ +#include "epix.h" +using namespace ePiX; + +// number of meridians and latitudes +int N1(72); +int N2(24); + +P VIEWPT(4, 3, 4); + +// locations of "lights"; see mesh::draw() below for implementation +P LIGHT_R(10,0,10); +P LIGHT_G(0,10,10); +P LIGHT_B(0,-10,10); + +// internal constants +double r_0(1.0); +double EPS(0.0); // fact shrink factor +double du(2.0/N1), dv(4.0/N2); + +// parametrized surfaces +P helicoid(double u, double v) +{ + return P(sinh(v)*Cos(M_PI*u), sinh(v)*Sin(M_PI*u), 2*M_PI*u); +} + +P catenoid(double u, double v) +{ + return P(cosh(v)*Sin(M_PI*u), -cosh(v)*Cos(M_PI*u), -v); +} + +P morph(double u, double v) +{ + return Cos(2*M_PI*tix())*helicoid(u,v) + Sin(2*M_PI*tix())*catenoid(u,v); +} + +// facet-like class with spot reflection +class element +{ +private: + P pt1; + P pt2; + P pt3; + P pt4; + + double distance; + +public: + element(P f(double u, double v), double u0, double v0) + : pt1(f(u0+EPS,v0+EPS)), pt2(f(u0+du-EPS,v0+EPS)), + pt3(f(u0+du-EPS,v0+dv-EPS)), pt4(f(u0+EPS,v0+dv-EPS)) + { + P center(0.25*(pt1 + (pt2 + (pt3 + pt4)))); + P temp(camera.viewpt()); + + distance = norm(center-temp); + } + + double how_far() const { return distance; } + + void draw() + { + P normal((pt2 - pt1)*(pt4 - pt1)); + normal *= 1/norm(normal); + + double dens_r(0.75*(pow(normal|LIGHT_R, 2)/(LIGHT_R|LIGHT_R))); + double dens_g(0.75*(pow(normal|LIGHT_G, 2)/(LIGHT_G|LIGHT_G))); + double dens_b(0.75*(pow(normal|LIGHT_B, 2)/(LIGHT_B|LIGHT_B))); + + fill(RGB(dens_r, dens_g, dens_b)); + ePiX::quad(pt1, pt2, pt3, pt4); + } + +}; + +class By_distance { +public: + bool operator() (const element& arg1, const element& arg2) + { + return arg1.how_far() > arg2.how_far(); + } +}; + + +int main(int argc, char* argv[]) +{ + if (argc == 3) + { + char* arg; + double temp1, temp2; + temp1=strtod(argv[1], &arg); + temp2=strtod(argv[2], &arg); + + tix()=temp1/temp2; + } + + double MAX(8); + picture(P(-MAX,-MAX),P(MAX,MAX), "5x5in"); + + begin(); + pen(Neutral(), 0); // no grid lines + + // draw bounding square for uniform frame size + backing(Black()); + viewpoint(VIEWPT); + + /* rotating lights + LIGHT_R=cis(2*M_PI*tix()); + LIGHT_G=cis(2*M_PI*(tix()+0.25)); + LIGHT_B=P(-2,-2,6); + */ + + camera.range(20); + + // build surface + std::vector<element> mesh; + + for (int i=0; i<N1; ++i) + for (int j=0; j<N2; ++j) + mesh.push_back(element(morph, -1+du*i, -2+dv*j)); + + sort(mesh.begin(), mesh.end(), By_distance()); + + for (unsigned int i=0; i<mesh.size(); ++i) + mesh.at(i).draw(); + + pst_format(); + end(); +} |