1 // plmtex3, plptex3 demo.
2 //
3 // Copyright (C) 2009 Werner Smekal
4 // Copyright (C) 2009 Alan W. Irwin
5 //
6 // This file is part of PLplot.
7 //
8 // PLplot is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU Library General Public License as published
10 // by the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
12 //
13 // PLplot is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU Library General Public License for more details.
17 //
18 // You should have received a copy of the GNU Library General Public License
19 // along with PLplot; if not, write to the Free Software
20 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 //
22 //
23
24 import std.string;
25 import std.math;
26
27 import plplot;
28
29 //--------------------------------------------------------------------------
30 // main
31 //
32 // Demonstrates plotting text in 3D.
33 //--------------------------------------------------------------------------
main(char[][]args)34 int main( char[][] args )
35 {
36 // Choose these values to correspond to tick marks.
37 const int XPTS = 2;
38 const int YPTS = 2;
39 const int NREVOLUTION = 16;
40 const int NROTATION = 8;
41 const int NSHEAR = 8;
42
43 PLFLT
44 xmin = 0.0, xmax = 1.0, xmid = 0.5 * ( xmax + xmin ), xrange = xmax - xmin,
45 ymin = 0.0, ymax = 1.0, ymid = 0.5 * ( ymax + ymin ), yrange = ymax - ymin,
46 zmin = 0.0, zmax = 1.0, zmid = 0.5 * ( zmax + zmin ), zrange = zmax - zmin,
47 ysmin = ymin + 0.1 * yrange,
48 ysmax = ymax - 0.1 * yrange,
49 ysrange = ysmax - ysmin,
50 dysrot = ysrange / cast(PLFLT) ( NROTATION - 1 ),
51 dysshear = ysrange / cast(PLFLT) ( NSHEAR - 1 ),
52 zsmin = zmin + 0.1 * zrange,
53 zsmax = zmax - 0.1 * zrange,
54 zsrange = zsmax - zsmin,
55 dzsrot = zsrange / cast(PLFLT) ( NROTATION - 1 ),
56 dzsshear = zsrange / cast(PLFLT) ( NSHEAR - 1 ),
57 ys, zs;
58
59 // p1string must be exactly one character + the null termination
60 // character.
61 string pstring = "The future of our civilization depends on software freedom.";
62
63 // Allocate and define the minimal x, y, and z to insure 3D box
64 PLFLT[XPTS] x;
65 PLFLT[YPTS] y;
66
67 PLFLT[][] z = new PLFLT[][XPTS];
68 for ( int i = 0; i < XPTS; i++ )
69 z[i] = new PLFLT[YPTS];
70
71 for ( int i = 0; i < XPTS; i++ )
72 x[i] = xmin + i * xrange / ( XPTS - 1 );
73
74 for ( int j = 0; j < YPTS; j++ )
75 y[j] = ymin + j * yrange / ( YPTS - 1 );
76
77 for ( int i = 0; i < XPTS; i++ )
78 for ( int j = 0; j < YPTS; j++ )
79 z[i][j] = 0.0;
80
81 // Parse and process command line arguments
82 plparseopts( args, PL_PARSE_FULL );
83
84 plinit();
85
86 // Page 1: Demonstrate inclination and shear capability pattern.
87 pladv( 0 );
88 plvpor( -0.15, 1.15, -0.05, 1.05 );
89 plwind( -1.2, 1.2, -0.8, 1.5 );
90 plw3d( 1.0, 1.0, 1.0, xmin, xmax, ymin, ymax, zmin, zmax, 20., 45. );
91
92 plcol0( 2 );
93 plbox3( "b", "", xrange, 0,
94 "b", "", yrange, 0,
95 "bcd", "", zrange, 0 );
96
97 PLFLT x_inclination, y_inclination, z_inclination;
98 PLFLT x_shear, y_shear, z_shear;
99 PLFLT omega, sin_omega, cos_omega;
100
101 // z = zmin.
102 plschr( 0., 1.0 );
103 for ( int i = 0; i < NREVOLUTION; i++ )
104 {
105 omega = ( 2. * PI * i ) / NREVOLUTION;
106 sin_omega = sin( omega );
107 cos_omega = cos( omega );
108 x_inclination = 0.5 * xrange * cos_omega;
109 y_inclination = 0.5 * yrange * sin_omega;
110 z_inclination = 0.0;
111 x_shear = -0.5 * xrange * sin_omega;
112 y_shear = 0.5 * yrange * cos_omega;
113 z_shear = 0.;
114 plptex3( xmid, ymid, zmin,
115 x_inclination, y_inclination, z_inclination,
116 x_shear, y_shear, z_shear,
117 0.0, " revolution" );
118 }
119
120 // x = xmax.
121 plschr( 0., 1.0 );
122 for ( int i = 0; i < NREVOLUTION; i++ )
123 {
124 omega = ( 2. * PI * i ) / NREVOLUTION;
125 sin_omega = sin( omega );
126 cos_omega = cos( omega );
127 x_inclination = 0.;
128 y_inclination = -0.5 * yrange * cos_omega;
129 z_inclination = 0.5 * zrange * sin_omega;
130 x_shear = 0.;
131 y_shear = 0.5 * yrange * sin_omega;
132 z_shear = 0.5 * zrange * cos_omega;
133 plptex3( xmax, ymid, zmid,
134 x_inclination, y_inclination, z_inclination,
135 x_shear, y_shear, z_shear,
136 0.0, " revolution" );
137 }
138
139 // y = ymax.
140 plschr( 0., 1.0 );
141 for ( int i = 0; i < NREVOLUTION; i++ )
142 {
143 omega = ( 2. * PI * i ) / NREVOLUTION;
144 sin_omega = sin( omega );
145 cos_omega = cos( omega );
146 x_inclination = 0.5 * xrange * cos_omega;
147 y_inclination = 0.;
148 z_inclination = 0.5 * zrange * sin_omega;
149 x_shear = -0.5 * xrange * sin_omega;
150 y_shear = 0.;
151 z_shear = 0.5 * zrange * cos_omega;
152 plptex3( xmid, ymax, zmid,
153 x_inclination, y_inclination, z_inclination,
154 x_shear, y_shear, z_shear,
155 0.0, " revolution" );
156 }
157
158 // Draw minimal 3D grid to finish defining the 3D box.
159 plmesh( x, y, z, DRAW_LINEXY );
160
161 // Page 2: Demonstrate rotation of string around its axis.
162 pladv( 0 );
163 plvpor( -0.15, 1.15, -0.05, 1.05 );
164 plwind( -1.2, 1.2, -0.8, 1.5 );
165 plw3d( 1.0, 1.0, 1.0, xmin, xmax, ymin, ymax, zmin, zmax, 20., 45. );
166
167 plcol0( 2 );
168 plbox3( "b", "", xrange, 0,
169 "b", "", yrange, 0,
170 "bcd", "", zrange, 0 );
171
172 // y = ymax.
173 plschr( 0., 1.0 );
174 x_inclination = 1.;
175 y_inclination = 0.;
176 z_inclination = 0.;
177 x_shear = 0.;
178 for ( int i = 0; i < NROTATION; i++ )
179 {
180 omega = ( 2. * PI * i ) / NROTATION;
181 sin_omega = sin( omega );
182 cos_omega = cos( omega );
183 y_shear = 0.5 * yrange * sin_omega;
184 z_shear = 0.5 * zrange * cos_omega;
185 zs = zsmax - dzsrot * cast(PLFLT) i;
186 plptex3( xmid, ymax, zs,
187 x_inclination, y_inclination, z_inclination,
188 x_shear, y_shear, z_shear,
189 0.5, "rotation for y = y#dmax#u" );
190 }
191
192 // x = xmax.
193 plschr( 0., 1.0 );
194 x_inclination = 0.;
195 y_inclination = -1.;
196 z_inclination = 0.;
197 y_shear = 0.;
198 for ( int i = 0; i < NROTATION; i++ )
199 {
200 omega = ( 2. * PI * i ) / NROTATION;
201 sin_omega = sin( omega );
202 cos_omega = cos( omega );
203 x_shear = 0.5 * xrange * sin_omega;
204 z_shear = 0.5 * zrange * cos_omega;
205 zs = zsmax - dzsrot * cast(PLFLT) i;
206 plptex3( xmax, ymid, zs,
207 x_inclination, y_inclination, z_inclination,
208 x_shear, y_shear, z_shear,
209 0.5, "rotation for x = x#dmax#u" );
210 }
211
212 // z = zmin.
213 plschr( 0., 1.0 );
214 x_inclination = 1.;
215 y_inclination = 0.;
216 z_inclination = 0.;
217 x_shear = 0.;
218 for ( int i = 0; i < NROTATION; i++ )
219 {
220 omega = ( 2. * PI * i ) / NROTATION;
221 sin_omega = sin( omega );
222 cos_omega = cos( omega );
223 y_shear = 0.5 * yrange * cos_omega;
224 z_shear = 0.5 * zrange * sin_omega;
225 ys = ysmax - dysrot * cast(PLFLT) i;
226 plptex3( xmid, ys, zmin,
227 x_inclination, y_inclination, z_inclination,
228 x_shear, y_shear, z_shear,
229 0.5, "rotation for z = z#dmin#u" );
230 }
231 // Draw minimal 3D grid to finish defining the 3D box.
232 plmesh( x, y, z, DRAW_LINEXY );
233
234 // Page 3: Demonstrate shear of string along its axis.
235 // Work around xcairo and pngcairo (but not pscairo) problems for
236 // shear vector too close to axis of string. (N.B. no workaround
237 // would be domega = 0.)
238 PLFLT domega = 0.05;
239 pladv( 0 );
240 plvpor( -0.15, 1.15, -0.05, 1.05 );
241 plwind( -1.2, 1.2, -0.8, 1.5 );
242 plw3d( 1.0, 1.0, 1.0, xmin, xmax, ymin, ymax, zmin, zmax, 20., 45. );
243
244 plcol0( 2 );
245 plbox3( "b", "", xrange, 0,
246 "b", "", yrange, 0,
247 "bcd", "", zrange, 0 );
248
249 // y = ymax.
250 plschr( 0., 1.0 );
251 x_inclination = 1.;
252 y_inclination = 0.;
253 z_inclination = 0.;
254 y_shear = 0.;
255 for ( int i = 0; i < NSHEAR; i++ )
256 {
257 omega = domega + ( 2. * PI * i ) / NSHEAR;
258 sin_omega = sin( omega );
259 cos_omega = cos( omega );
260 x_shear = 0.5 * xrange * sin_omega;
261 z_shear = 0.5 * zrange * cos_omega;
262 zs = zsmax - dzsshear * cast(PLFLT) i;
263 plptex3( xmid, ymax, zs,
264 x_inclination, y_inclination, z_inclination,
265 x_shear, y_shear, z_shear,
266 0.5, "shear for y = y#dmax#u" );
267 }
268
269 // x = xmax.
270 plschr( 0., 1.0 );
271 x_inclination = 0.;
272 y_inclination = -1.;
273 z_inclination = 0.;
274 x_shear = 0.;
275 for ( int i = 0; i < NSHEAR; i++ )
276 {
277 omega = domega + ( 2. * PI * i ) / NSHEAR;
278 sin_omega = sin( omega );
279 cos_omega = cos( omega );
280 y_shear = -0.5 * yrange * sin_omega;
281 z_shear = 0.5 * zrange * cos_omega;
282 zs = zsmax - dzsshear * cast(PLFLT) i;
283 plptex3( xmax, ymid, zs,
284 x_inclination, y_inclination, z_inclination,
285 x_shear, y_shear, z_shear,
286 0.5, "shear for x = x#dmax#u" );
287 }
288
289 // z = zmin.
290 plschr( 0., 1.0 );
291 x_inclination = 1.;
292 y_inclination = 0.;
293 z_inclination = 0.;
294 z_shear = 0.;
295 for ( int i = 0; i < NSHEAR; i++ )
296 {
297 omega = domega + ( 2. * PI * i ) / NSHEAR;
298 sin_omega = sin( omega );
299 cos_omega = cos( omega );
300 y_shear = 0.5 * yrange * cos_omega;
301 x_shear = 0.5 * xrange * sin_omega;
302 ys = ysmax - dysshear * cast(PLFLT) i;
303 plptex3( xmid, ys, zmin,
304 x_inclination, y_inclination, z_inclination,
305 x_shear, y_shear, z_shear,
306 0.5, "shear for z = z#dmin#u" );
307 }
308 // Draw minimal 3D grid to finish defining the 3D box.
309 plmesh( x, y, z, DRAW_LINEXY );
310
311 // Page 4: Demonstrate drawing a string on a 3D path.
312 pladv( 0 );
313 plvpor( -0.15, 1.15, -0.05, 1.05 );
314 plwind( -1.2, 1.2, -0.8, 1.5 );
315 plw3d( 1.0, 1.0, 1.0, xmin, xmax, ymin, ymax, zmin, zmax, 40., -30. );
316
317 plcol0( 2 );
318 plbox3( "b", "", xrange, 0,
319 "b", "", yrange, 0,
320 "bcd", "", zrange, 0 );
321
322 plschr( 0., 1.2 );
323 // domega controls the spacing between the various characters of the
324 // string and also the maximum value of omega for the given number
325 // of characters in *pstring.
326 domega = 2. * PI / pstring.length;
327 omega = 0.;
328 // 3D function is a helix of the given radius and pitch
329 PLFLT radius = 0.5;
330 PLFLT pitch = 1. / ( 2. * PI );
331 PLFLT xpos, ypos, zpos;
332 for ( int i = 0; i < pstring.length; i++ )
333 {
334 sin_omega = sin( omega );
335 cos_omega = cos( omega );
336 xpos = xmid + radius * sin_omega;
337 ypos = ymid - radius * cos_omega;
338 zpos = zmin + pitch * omega;
339
340 // In general, the inclination is proportional to the derivative of
341 // the position wrt theta.
342 x_inclination = radius * cos_omega;;
343 y_inclination = radius * sin_omega;
344 z_inclination = pitch;
345
346 // The shear vector should be perpendicular to the 3D line with Z
347 // component maximized, but for low pitch a good approximation is
348 // a constant vector that is parallel to the Z axis.
349 x_shear = 0.;
350 y_shear = 0.;
351 z_shear = 1.;
352 plptex3( xpos, ypos, zpos,
353 x_inclination, y_inclination, z_inclination,
354 x_shear, y_shear, z_shear,
355 0.5, pstring[i..i + 1] );
356 omega += domega;
357 }
358 // Draw minimal 3D grid to finish defining the 3D box.
359 plmesh( x, y, z, DRAW_LINEXY );
360
361 // Page 5: Demonstrate plmtex3 axis labelling capability
362 pladv( 0 );
363 plvpor( -0.15, 1.15, -0.05, 1.05 );
364 plwind( -1.2, 1.2, -0.8, 1.5 );
365 plw3d( 1.0, 1.0, 1.0, xmin, xmax, ymin, ymax, zmin, zmax, 20., 45. );
366
367 plcol0( 2 );
368 plbox3( "b", "", xrange, 0,
369 "b", "", yrange, 0,
370 "bcd", "", zrange, 0 );
371
372 plschr( 0., 1.0 );
373 plmtex3( "xp", 3.0, 0.5, 0.5, "Arbitrarily displaced" );
374 plmtex3( "xp", 4.5, 0.5, 0.5, "primary X-axis label" );
375 plmtex3( "xs", -2.5, 0.5, 0.5, "Arbitrarily displaced" );
376 plmtex3( "xs", -1.0, 0.5, 0.5, "secondary X-axis label" );
377 plmtex3( "yp", 3.0, 0.5, 0.5, "Arbitrarily displaced" );
378 plmtex3( "yp", 4.5, 0.5, 0.5, "primary Y-axis label" );
379 plmtex3( "ys", -2.5, 0.5, 0.5, "Arbitrarily displaced" );
380 plmtex3( "ys", -1.0, 0.5, 0.5, "secondary Y-axis label" );
381 plmtex3( "zp", 4.5, 0.5, 0.5, "Arbitrarily displaced" );
382 plmtex3( "zp", 3.0, 0.5, 0.5, "primary Z-axis label" );
383 plmtex3( "zs", -2.5, 0.5, 0.5, "Arbitrarily displaced" );
384 plmtex3( "zs", -1.0, 0.5, 0.5, "secondary Z-axis label" );
385
386 // Draw minimal 3D grid to finish defining the 3D box.
387 plmesh( x, y, z, DRAW_LINEXY );
388
389 plend();
390 return 0;
391 }
392