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