#ifndef SURFACE_H #define SURFACE_H #include "fml.h" #include "manifold.h" namespace fml { /* All surfaces inherit this class */ /* The exact meaning of d is surface-dependent (see class * definitions below); the limit of the calculated integral must * approach its true value as d->0. d must be > 0. */ class Surface : public Manifold { public: const int dimension() const { return 2; } }; class Plane : public Surface { private: /* The surface is specified by all points p = p0 + s v1 + t v2, * such that 0 <= {s, t} < 1 * * v1 and v2 must NOT be parallel. * * v1 and v2 should (but do not have to be) be normal (this is * motivated primarily by usability; if the two vectors are indeed * normal, then m1 and m2 have the nice geometric meaning of side * length). * * d = ds = dt. * dA will be in the direction of v1 x v2. */ vec3 p0, v1, v2; public: Plane(vec3 p, vec3 _v1, vec3 _v2) : p0(p), v1(_v1), v2(_v2) {}; vec3 integrate(vec3 (*integrand)(vec3 s, vec3 dA), scalar d) const; const char *name() const { return "Plane"; } }; /* Flat, circular disk (of varying extent) */ class Disk : public Surface { private: /* This represents a (possibly incomplete) circular disk in space, * with a center, radius, and normal vector as specified. * * `angle' specifies the extent of the disk; angle=2pi for a full * circle. * * We use: * d = dr. * d_theta = d / r. * * This makes it so that differential area elements on the edge of * the disk are square. * * dA will be in the direction of normal. */ vec3 center, radius, normal; scalar angle; public: Disk(vec3 c, vec3 r, vec3 n, scalar a) : center(c), radius(r), normal(n), angle(a) {}; vec3 integrate(vec3 (*integrand)(vec3 s, vec3 dA), scalar d) const; const char *name() const { return "Disk"; } }; /* Hollow, spherical shell */ class Sphere : public Surface { private: /* d = dtheta = dphi */ vec3 center; scalar radius; public: Sphere(vec3 c, scalar r) : center(c), radius(r) {}; vec3 integrate(vec3 (*integrand)(vec3 s, vec3 dA), scalar d) const; const char *name() const { return "Sphere"; } }; /* Cylinder without end caps */ class OpenCylinder : public Surface { private: /* Like this: * * ___________________ * / \ \ * origin ---------------> axis * \_/_________________/ * */ vec3 origin, axis; scalar radius; public: OpenCylinder(vec3 o, vec3 a, scalar r) : origin(o), axis(a), radius(r) {} vec3 integrate(vec3 (*integrand)(vec3 s, vec3 dA), scalar d) const; const char *name() const { return "OpenCylinder"; } }; /* Capped cylinder */ class ClosedCylinder : public OpenCylinder { private: Disk cap1, cap2; public: ClosedCylinder(vec3 o, vec3 a, scalar r) : OpenCylinder(o, a, r), cap1(o, vec3::any_unit_normal(a), -a.normalize(), 2*M_PI), cap2(o + a, vec3::any_unit_normal(a), a.normalize(), 2*M_PI) {} vec3 integrate(vec3 (*integrand)(vec3 s, vec3 dA), scalar d) const; const char *name() const { return "ClosedCylinder"; } }; } #endif