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