Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
cylinder3d.cpp
Go to the documentation of this file.
1#include <2geom/d2.h>
2#include <2geom/sbasis.h>
4#include <2geom/sbasis-2d.h>
6#include <2geom/transforms.h>
7#include <2geom/sbasis-math.h>
8
9#include <toys/path-cairo.h>
11#include <2geom/path.h>
13
14#include <gsl/gsl_matrix.h>
15
16#include <vector>
17using std::vector;
18using namespace Geom;
19using namespace std;
20
23
25 for(unsigned i = 0; i < p.size(); i++) {
26 D2<SBasis> B;
27 B[0] = Linear(p.cuts[i], p.cuts[i+1]);
28 B[1] = p[i];
29 cairo_d2_sb(cr, B);
30 }
31}
32
34
35static void draw_box (cairo_t *cr, Geom::Point corners[8]);
36static void draw_slider_lines (cairo_t *cr);
37static Geom::Point proj_image (cairo_t *cr, const double pt[4], const vector<Geom::Point> &handles);
38
39double tmat[3][4];
40double c[8][4];
42
43class Box3d: public Toy {
44 std::vector<Toggle> togs;
45 Path path_a;
46 Piecewise<D2<SBasis> > path_a_pw;
47 PointSetHandle hand;
48
49 void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) override {
50 orig = hand.pts[7];
51
52 cairo_set_source_rgba (cr, 0., 0.125, 0, 1);
53
54 // draw vertical lines for the VP sliders and keep the sliders at their horizontal positions
56 hand.pts[4][0] = 30;
57 hand.pts[5][0] = 45;
58 hand.pts[6][0] = 60;
59
60 // draw the curve that is supposed to be projected on the box's front face
61 vector<Geom::Point>::iterator it = hand.pts.begin();
62 for (int j = 0; j < 7; ++j) ++it;
63
64 /* create the transformation matrix for the map P^3 --> P^2 that has the following effect:
65 (1 : 0 : 0 : 0) --> vanishing point in x direction (= handle #0)
66 (0 : 1 : 0 : 0) --> vanishing point in y direction (= handle #1)
67 (0 : 0 : 1 : 0) --> vanishing point in z direction (= handle #2)
68 (0 : 0 : 0 : 1) --> origin (= handle #3)
69 */
70 for (int j = 0; j < 4; ++j) {
71 tmat[0][j] = hand.pts[j][0];
72 tmat[1][j] = hand.pts[j][1];
73 tmat[2][j] = 1;
74 }
75
76 *notify << "Projection matrix:" << endl;
77 for (auto & i : tmat) {
78 for (double j : i) {
79 *notify << j << " ";
80 }
81 *notify << endl;
82 }
83
84 // draw the projective images of the box's corners
85 for (int i = 0; i < 8; ++i) {
86 corners[i] = proj_image (cr, c[i], hand.pts);
87 }
88 draw_box(cr, corners);
89 cairo_set_line_width (cr, 2);
90 cairo_stroke(cr);
91
92 {
94 Piecewise<SBasis> preimage[4];
95
96 if(togs[0].on) {
97 preimage[0] = sin((B[0] - orig[0]) / 100);
98 preimage[1] = -(B[1] - orig[1]) / 100;
99 preimage[2] = cos((B[0] - orig[0]) / 100);
100 } else { //if(togs[1].state) {
101 Piecewise<SBasis> sphi = sin((B[0] - orig[0]) / 200);
102 Piecewise<SBasis> cphi = cos((B[0] - orig[0]) / 200);
103
104 preimage[0] = -sphi*sin((B[1] - orig[1]) / 200);
105 preimage[1] = -sphi*cos((B[1] - orig[1]) / 200);
106 preimage[2] = -cphi;
107 }
108 Piecewise<SBasis> res[3];
109 for (int j = 0; j < 3; ++j) {
110 res[j] =
111 (preimage[0]) * tmat[j][0]
112 + (preimage[1] - ((hand.pts[5][1]-300)/100)) * tmat[j][1]
113 + (preimage[2] - ((hand.pts[6][1]-00)/100)) * tmat[j][2]
114 +( - (hand.pts[4][1]-300)/100) * tmat[j][0] + tmat[j][3];
115 }
116 //if (fabs (res[2]) > 0.000001) {
117 D2<Piecewise<SBasis> > result(divide(res[0],res[2], 4),
118 divide(res[1],res[2], 4));
119
121 cairo_set_source_rgba (cr, 0., 0.125, 0, 1);
122 cairo_stroke(cr);
123 }
124 draw_toggles(cr, togs);
125
126 Toy::draw(cr, notify, width, height, save,timer_stream);
127 }
128 void first_time(int argc, char** argv) override {
129 const char *path_a_name="star.svgd";
130 if(argc > 1)
131 path_a_name = argv[1];
132 PathVector paths_a = read_svgd(path_a_name);
133 assert(!paths_a.empty());
134 path_a = paths_a[0];
135
136 path_a.close(true);
137 path_a_pw = path_a.toPwSb();
138
139 // Finite images of the three vanishing points and the origin
140 hand.pts.emplace_back(150,300);
141 hand.pts.emplace_back(380,40);
142 hand.pts.emplace_back(550,350);
143 hand.pts.emplace_back(340,450);
144
145 // Hand.Pts for moving in axes directions
146 hand.pts.emplace_back(30,300);
147 hand.pts.emplace_back(45,300);
148 hand.pts.emplace_back(60,300);
149
150 // Box corners
151 for (int i = 0; i < 8; ++i) {
152 c[i][0] = ((i & 1) ? 1 : 0);
153 c[i][1] = ((i & 2) ? 1 : 0);
154 c[i][2] = ((i & 4) ? 1 : 0);
155 c[i][3] = 1;
156 }
157
158 // Origin handle
159 hand.pts.emplace_back(180,70);
160 togs.emplace_back("S", true);
161 handles.push_back(&hand);
162 }
163 void key_hit(unsigned keyval, unsigned modifiers) override {
164 if (keyval == 'c') {
165 togs[0].set(1);
166 } else if (keyval == 's') {
167 togs[0].set(0);
168 }
169 redraw();
170 }
171 void mouse_pressed(Geom::Point const &pos, unsigned button, unsigned modifiers) override {
172 toggle_events(togs, pos, button);
173 Toy::mouse_pressed(pos, button, modifiers);
174 }
175};
176
177int main(int argc, char **argv) {
178 init(argc, argv, new Box3d);
179 return 0;
180}
181
183 cairo_move_to(cr,corners[0]);
184 cairo_line_to(cr,corners[1]);
185 cairo_line_to(cr,corners[3]);
186 cairo_line_to(cr,corners[2]);
187 cairo_close_path(cr);
188
189 cairo_move_to(cr,corners[4]);
190 cairo_line_to(cr,corners[5]);
191 cairo_line_to(cr,corners[7]);
192 cairo_line_to(cr,corners[6]);
193 cairo_close_path(cr);
194
195 cairo_move_to(cr,corners[0]);
196 cairo_line_to(cr,corners[4]);
197
198 cairo_move_to(cr,corners[1]);
199 cairo_line_to(cr,corners[5]);
200
201 cairo_move_to(cr,corners[2]);
202 cairo_line_to(cr,corners[6]);
203
204 cairo_move_to(cr,corners[3]);
205 cairo_line_to(cr,corners[7]);
206}
207
209 cairo_move_to(cr, Geom::Point(20,300));
210 cairo_line_to(cr, Geom::Point(70,300));
211
212 cairo_move_to(cr, Geom::Point(30,00));
213 cairo_line_to(cr, Geom::Point(30,450));
214
215 cairo_move_to(cr, Geom::Point(45,00));
216 cairo_line_to(cr, Geom::Point(45,450));
217
218 cairo_move_to(cr, Geom::Point(60,00));
219 cairo_line_to(cr, Geom::Point(60,450));
220
221 cairo_set_line_width (cr, 1);
222 cairo_set_source_rgba (cr, 0.2, 0.2, 0.2, 1);
223 cairo_stroke(cr);
224}
225
226static Geom::Point proj_image (cairo_t *cr, const double pt[4], const vector<Geom::Point> &handles)
227{
228 double res[3];
229 for (int j = 0; j < 3; ++j) {
230 res[j] =
231 tmat[j][0] * (pt[0] - (handles[4][1]-300)/100)
232 + tmat[j][1] * (pt[1] - (handles[5][1]-300)/100)
233 + tmat[j][2] * (pt[2] - (handles[6][1]-300)/100)
234 + tmat[j][3] * pt[3];
235 }
236 if (fabs (res[2]) > 0.000001) {
237 Geom::Point result = Geom::Point (res[0]/res[2], res[1]/res[2]);
238 draw_handle(cr, result);
239 return result;
240 }
241 assert(0); // unclipped point
242 return Geom::Point(0,0);
243}
244
245/*
246 Local Variables:
247 mode:c++
248 c-file-style:"stroustrup"
249 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
250 indent-tabs-mode:nil
251 fill-column:99
252 End:
253*/
254// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
Path - a sequence of contiguous curves.
int main()
Conversion between Bezier control points and SBasis curves.
Adaptor that creates 2D functions from 1D ones.
Definition d2.h:55
Function that interpolates linearly between two values.
Definition linear.h:55
Sequence of subpaths.
Definition pathvector.h:122
bool empty() const
Check whether the vector contains any paths.
Definition pathvector.h:145
Sequence of contiguous curves, aka spline.
Definition path.h:353
void close(bool closed=true)
Set whether the path is closed.
Definition path.cpp:322
Piecewise< D2< SBasis > > toPwSb() const
Definition path.cpp:388
Function defined as discrete pieces.
Definition piecewise.h:71
unsigned size() const
Definition piecewise.h:131
std::vector< double > cuts
Definition piecewise.h:75
Two-dimensional point that doubles as a vector.
Definition point.h:66
std::vector< Geom::Point > pts
virtual void first_time(int, char **)
virtual void mouse_pressed(Geom::Point const &pos, unsigned button, unsigned modifiers)
vector< Handle * > handles
virtual void save(FILE *f)
virtual void key_hit(unsigned keyval, unsigned modifiers)
virtual void draw(cairo_t *cr, std::ostringstream *notify, int w, int h, bool save, std::ostringstream *timing_stream)
Css & result
static void draw_box(cairo_t *cr, Geom::Point corners[8])
void cairo_pw(cairo_t *cr, Piecewise< SBasis > p)
unsigned total_pieces_inc
Geom::Point corners[8]
unsigned total_pieces_sub
double c[8][4]
double tmat[3][4]
static Geom::Point proj_image(cairo_t *cr, const double pt[4], const vector< Geom::Point > &handles)
Geom::Point orig
static void draw_slider_lines(cairo_t *cr)
Lifts one dimensional objects into 2D.
PathVector read_svgd(char const *filename)
Create path vector from SVG path data stored in a file.
Various utility functions.
Definition affine.h:22
SBasisN< n > cos(LinearN< n > bo, int k)
D2< Piecewise< SBasis > > make_cuts_independent(Piecewise< D2< SBasis > > const &a)
Definition d2-sbasis.cpp:75
SBasisN< n > divide(SBasisN< n > const &a, SBasisN< n > const &b, int k)
SBasisN< n > sin(LinearN< n > bo, int k)
STL namespace.
void cairo_line_to(cairo_t *cr, Geom::Point p1)
struct _cairo cairo_t
Definition path-cairo.h:16
void cairo_d2_pw_sb(cairo_t *cr, Geom::D2< Geom::Piecewise< Geom::SBasis > > const &p)
void draw_handle(cairo_t *cr, Geom::Point h)
void cairo_move_to(cairo_t *cr, Geom::Point p1)
void cairo_d2_sb(cairo_t *cr, Geom::D2< Geom::SBasis > const &p)
Obsolete 2D SBasis function class.
two-dimensional geometric operators.
some std functions to work with (pw)s-basis
Polynomial in symmetric power basis (S-basis)
parse SVG path specifications
double height
double width
void toggle_events(std::vector< Toggle > &ts, Geom::Point const &pos, unsigned button)
void cairo_set_source_rgba(cairo_t *cr, colour c)
void draw_toggles(cairo_t *cr, std::vector< Toggle > &ts)
void redraw()
void init(int argc, char **argv, Toy *t, int width=600, int height=600)
Affine transformation classes.