1 // Copyright 2016-2021 Doug Moen
2 // Licensed under the Apache License, version 2.0
3 // See accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0
4 
5 #ifndef LIBCURV_SHAPE_H
6 #define LIBCURV_SHAPE_H
7 
8 #include <libcurv/frame.h>
9 #include <libcurv/sc_compiler.h>
10 #include <libcurv/location.h>
11 #include <libcurv/vec.h>
12 #include <cmath>
13 
14 namespace curv {
15 
16 struct Function;
17 struct Context;
18 struct System;
19 struct Program;
20 struct Phrase;
21 struct Render_Opts;
22 
23 struct Viewed_Shape;
24 
25 // axis aligned bounding box
26 struct BBox
27 {
28     double xmin, ymin, zmin;
29     double xmax, ymax, zmax;
empty2BBox30     bool empty2() const {
31         return (xmin >= xmax || ymin >= ymax);
32     }
empty3BBox33     bool empty3() const {
34         return (xmin >= xmax || ymin >= ymax || zmin >= zmax);
35     }
infinite2BBox36     bool infinite2() const {
37         return (xmin == -INFINITY || ymin == -INFINITY ||
38                 xmax == +INFINITY || ymax == +INFINITY);
39     }
infinite3BBox40     bool infinite3() const {
41         return (xmin == -INFINITY || ymin == -INFINITY || zmin == -INFINITY ||
42                 xmax == +INFINITY || ymax == +INFINITY || zmax == +INFINITY);
43     }
size2BBox44     glm::dvec2 size2() const {
45         return glm::dvec2(xmax - xmin, ymax - ymin);
46     }
size3BBox47     glm::dvec3 size3() const {
48         return glm::dvec3(xmax - xmin, ymax - ymin, zmax - zmin);
49     }
50     static BBox from_value(Value, const Context&);
51 };
52 
53 struct Shape
54 {
55     bool is_2d_;
56     bool is_3d_;
57     BBox bbox_;
58     virtual double dist(double x, double y, double z, double t) = 0;
59     virtual Vec3 colour(double x, double y, double z, double t) = 0;
60 };
61 
62 struct Shape_Program final : public Shape
63 {
64     // is_shape is initially false, becomes true after recognize() succeeds.
is_shapefinal65     bool is_shape() const { return is_2d_ || is_3d_; }
66 
67     // implement PROGRAM api for use with At_Program
68     Source_State& sstate_;
69     Shared<const Phrase> nub_; // source code of shape expression
systemfinal70     System& system() const { return sstate_.system_; }
syntaxfinal71     const Phrase& syntax() const { return *nub_; }
72 
73     // shape fields, filled in by recognize()
74     Shared<Record> record_;
75     Shared<const Function> dist_fun_;
76     Shared<const Function> colour_fun_;
77     std::unique_ptr<Frame> dist_frame_;
78     std::unique_ptr<Frame> colour_frame_;
79 
80     Viewed_Shape* viewed_shape_ = nullptr;
81 
82     Shape_Program(Program&);
83 
Shape_Programfinal84     Shape_Program(Source_State& sstate, Shared<const Phrase> nub)
85     : sstate_(sstate), nub_(move(nub))
86     {}
87 
88     // If the value is a shape, fill in the shape fields and return true.
89     // The Render_Opts argument is modified using data from shape.render,
90     // if the recognized shape has a render field.
91     // Used with the first constructor.
92     bool recognize(Value, Render_Opts*);
93 
94     // This is called from the Viewed_Shape constructor, after a
95     // parametric shape has been recognized. We construct a Shape_Program
96     // that describes a parametric shape.
97     Shape_Program(const Shape_Program&, Shared<Record>, Viewed_Shape*);
98 
99     // Invoke the shape's `dist` function.
100     double dist(double x, double y, double z, double t);
101 
102     // Invoke the shape's `colour` function.
103     Vec3 colour(double x, double y, double z, double t);
104 };
105 
106 } // namespace
107 #endif // header guard
108