1 #include <2geom/d2.h>
2 #include <2geom/sbasis.h>
3 #include <2geom/sbasis-geometric.h>
4 #include <2geom/sbasis-2d.h>
5 #include <2geom/bezier-to-sbasis.h>
6 #include <2geom/transforms.h>
7 #include <2geom/sbasis-math.h>
8 
9 #include <toys/path-cairo.h>
10 #include <toys/toy-framework-2.h>
11 #include <2geom/path.h>
12 #include <2geom/svg-path-parser.h>
13 
14 #include <gsl/gsl_matrix.h>
15 
16 #include <vector>
17 using std::vector;
18 using namespace Geom;
19 using namespace std;
20 
21 class Box3d: public Toy {
22     double tmat[3][4];
23     PointHandle origin_handle;
24     PointSetHandle vanishing_points_handles;
25     PathVector paths_a;
26 
draw(cairo_t * cr,std::ostringstream * notify,int width,int height,bool save,std::ostringstream * timer_stream)27     void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
28 
29         Geom::Point orig = origin_handle.pos;
30 	cairo_set_source_rgba (cr, 0., 0.125, 0, 1);
31 
32         /* create the transformation matrix for the map  P^3 --> P^2 that has the following effect:
33               (1 : 0 : 0 : 0) --> vanishing point in x direction (= handle #0)
34               (0 : 1 : 0 : 0) --> vanishing point in y direction (= handle #1)
35               (0 : 0 : 1 : 0) --> vanishing point in z direction (= handle #2)
36               (0 : 0 : 0 : 1) --> origin (= handle #3)
37         */
38         for (int j = 0; j < 4; ++j) {
39             tmat[0][j] = vanishing_points_handles.pts[j][0];
40             tmat[1][j] = vanishing_points_handles.pts[j][1];
41             tmat[2][j] = 1;
42         }
43 
44         *notify << "Projection matrix:" << endl;
45         for (auto & i : tmat) {
46             for (double j : i) {
47                 *notify << j << " ";
48             }
49             *notify << endl;
50         }
51 
52         for(const auto & i : paths_a) {
53             Piecewise<D2<SBasis> >  path_a_pw = i.toPwSb();
54 
55             D2<Piecewise<SBasis> > B = make_cuts_independent(path_a_pw);
56             Piecewise<SBasis> preimage[4];
57 
58             preimage[0] =  (B[0] - orig[0]) / 100;
59             preimage[1] = -(B[1] - orig[1]) / 100;
60             Piecewise<SBasis> res[3];
61             for (int j = 0; j < 3; ++j) {
62                 res[j] = preimage[0] * tmat[j][0]
63                     + preimage[1] * tmat[j][1]
64                     + tmat[j][3];
65             }
66 
67             //if (fabs (res[2]) > 0.000001) {
68             D2<Piecewise<SBasis> > result(divide(res[0],res[2], 2),
69                                           divide(res[1],res[2], 2));
70 
71             cairo_d2_pw_sb(cr, result);
72             cairo_set_source_rgba (cr, 0., 0.125, 0, 1);
73             cairo_stroke(cr);
74         }
75 
76         Toy::draw(cr, notify, width, height, save,timer_stream);
77     }
first_time(int argc,char ** argv)78     void first_time(int argc, char** argv) override {
79         const char *path_a_name="ptitle.svgd";
80         if(argc > 1)
81             path_a_name = argv[1];
82         paths_a = read_svgd(path_a_name);
83         assert(paths_a.size() > 0);
84 
85         // Finite images of the three vanishing points and the origin
86         handles.push_back(&origin_handle);
87         handles.push_back(&vanishing_points_handles);
88         vanishing_points_handles.push_back(550,350);
89         vanishing_points_handles.push_back(150,300);
90         vanishing_points_handles.push_back(380,40);
91         vanishing_points_handles.push_back(340,450);
92         // plane origin
93         origin_handle.pos = Point(180,65);
94     }
95     //int should_draw_bounds() {return 1;}
96 
proj_image(cairo_t * cr,const double pt[4],const vector<Geom::Point> &)97     Geom::Point proj_image (cairo_t *cr, const double pt[4], const vector<Geom::Point> &/*handles*/)
98     {
99         double res[3];
100         for (int j = 0; j < 3; ++j) {
101             res[j] = 0;
102             for (int i = 0; i < 3; ++i)
103                 res[j] += tmat[j][i] * pt[i];
104         }
105         if (fabs (res[2]) > 0.000001) {
106             Geom::Point result = Geom::Point (res[0]/res[2], res[1]/res[2]);
107             draw_handle(cr, result);
108             return result;
109         }
110         assert(0); // unclipped point
111         return Geom::Point(0,0);
112     }
113 
114 };
115 
main(int argc,char ** argv)116 int main(int argc, char **argv) {
117     init(argc, argv, new Box3d);
118     return 0;
119 }
120 
121 /*
122   Local Variables:
123   mode:c++
124   c-file-style:"stroustrup"
125   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
126   indent-tabs-mode:nil
127   fill-column:99
128   End:
129 */
130 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
131