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