Skip to content

Commit befcd24

Browse files
committed
preliminary sphere implementation. Fixes #16.
Fixes "axis equal" for 3d plots.
1 parent a7ab913 commit befcd24

File tree

1 file changed

+105
-1
lines changed

1 file changed

+105
-1
lines changed

src/pyplot_module.f90

Lines changed: 105 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ module pyplot_module
5151

5252
procedure, public :: add_plot !! add a 2d plot to pyplot instance
5353
procedure, public :: add_3d_plot !! add a 3d plot to pyplot instance
54+
procedure, public :: add_sphere !! add a 3d sphere to pyplot instance
5455
procedure, public :: add_contour !! add a contour plot to pyplot instance
5556
procedure, public :: add_bar !! add a barplot to pyplot instance
5657
procedure, public :: add_imshow !! add an image plot (using `imshow`)
@@ -549,6 +550,58 @@ subroutine add_3d_plot(me, x, y, z, label, linestyle, markersize, linewidth, ist
549550
end subroutine add_3d_plot
550551
!*****************************************************************************************
551552

553+
!*****************************************************************************************
554+
!> author: Jacob Williams
555+
!
556+
! Add a sphere to a 3D x,y,z plot.
557+
!
558+
!@note Must initialize the class with `mplot3d=.true.` and `use_numpy=.true.`.
559+
560+
subroutine add_sphere(me, r, xc, yc, zc, istat)
561+
562+
implicit none
563+
564+
class(pyplot), intent (inout) :: me !! pyplot handler
565+
real(wp), intent (in) :: r !! radius of the sphere
566+
real(wp), intent (in) :: xc !! x value of sphere center
567+
real(wp), intent (in) :: yc !! y value of sphere center
568+
real(wp), intent (in) :: zc !! z value of sphere center
569+
integer, intent (out) :: istat !! status output (0 means no problems)
570+
571+
character(len=:), allocatable :: rstr !! r value stringified
572+
character(len=:), allocatable :: xcstr !! xc value stringified
573+
character(len=:), allocatable :: ycstr !! yc value stringified
574+
character(len=:), allocatable :: zcstr !! zc value stringified
575+
character(len=*), parameter :: xname = 'x' !! x variable name for script
576+
character(len=*), parameter :: yname = 'y' !! y variable name for script
577+
character(len=*), parameter :: zname = 'z' !! z variable name for script
578+
579+
if (allocated(me%str)) then
580+
581+
istat = 0
582+
583+
!convert the arrays to strings:
584+
call real_to_string(r , me%real_fmt, rstr)
585+
call real_to_string(xc, me%real_fmt, xcstr)
586+
call real_to_string(yc, me%real_fmt, ycstr)
587+
call real_to_string(zc, me%real_fmt, zcstr)
588+
589+
call me%add_str('u = np.linspace(0, 2 * np.pi, 100)')
590+
call me%add_str('v = np.linspace(0, np.pi, 100)')
591+
call me%add_str(xname//' = '//xcstr//' + '//rstr//' * np.outer(np.cos(u), np.sin(v))')
592+
call me%add_str(yname//' = '//ycstr//' + '//rstr//' * np.outer(np.sin(u), np.sin(v))')
593+
call me%add_str(zname//' = '//zcstr//' + '//rstr//' * np.outer(np.ones(np.size(u)), np.cos(v))')
594+
call me%add_str('ax.plot_surface('//xname//', '//yname//', '//zname//', color="Grey")')
595+
call me%add_str('')
596+
597+
else
598+
istat = -1
599+
write(error_unit,'(A)') 'Error in add_sphere: pyplot class not properly initialized.'
600+
end if
601+
602+
end subroutine add_sphere
603+
!*****************************************************************************************
604+
552605
!*****************************************************************************************
553606
!> author: Jacob Williams
554607
!
@@ -762,6 +815,35 @@ subroutine integer_to_string(i, s)
762815
end subroutine integer_to_string
763816
!*****************************************************************************************
764817

818+
!*****************************************************************************************
819+
!> author: Jacob Williams
820+
!
821+
! Real scalar to string.
822+
823+
subroutine real_to_string(v, fmt, str)
824+
825+
real(wp), intent(in) :: v !! real values
826+
character(len=*), intent(in) :: fmt !! real format string
827+
character(len=:), allocatable, intent(out) :: str !! real values stringified
828+
829+
integer :: istat !! IO status
830+
character(len=max_real_len) :: tmp !! dummy string
831+
832+
if (fmt=='*') then
833+
write(tmp, *, iostat=istat) v
834+
else
835+
write(tmp, fmt, iostat=istat) v
836+
end if
837+
if (istat/=0) then
838+
write(error_unit,'(A)') 'Error in real_to_string'
839+
str = '****'
840+
else
841+
str = trim(adjustl(tmp))
842+
end if
843+
844+
end subroutine real_to_string
845+
!*****************************************************************************************
846+
765847
!*****************************************************************************************
766848
!> author: Jacob Williams
767849
!
@@ -937,7 +1019,29 @@ subroutine finish_ops(me)
9371019
call me%add_str('')
9381020
end if
9391021
if (me%axis_equal) then
940-
call me%add_str('ax.axis("equal")')
1022+
if (me%mplot3d) then
1023+
call me%add_str('ax.set_aspect("equal")')
1024+
call me%add_str('')
1025+
1026+
call me%add_str('def set_axes_equal(ax):')
1027+
call me%add_str(' x_limits = ax.get_xlim3d()')
1028+
call me%add_str(' y_limits = ax.get_ylim3d()')
1029+
call me%add_str(' z_limits = ax.get_zlim3d()')
1030+
call me%add_str(' x_range = abs(x_limits[1] - x_limits[0])')
1031+
call me%add_str(' x_middle = np.mean(x_limits)')
1032+
call me%add_str(' y_range = abs(y_limits[1] - y_limits[0])')
1033+
call me%add_str(' y_middle = np.mean(y_limits)')
1034+
call me%add_str(' z_range = abs(z_limits[1] - z_limits[0])')
1035+
call me%add_str(' z_middle = np.mean(z_limits)')
1036+
call me%add_str(' plot_radius = 0.5*max([x_range, y_range, z_range])')
1037+
call me%add_str(' ax.set_xlim3d([x_middle - plot_radius, x_middle + plot_radius])')
1038+
call me%add_str(' ax.set_ylim3d([y_middle - plot_radius, y_middle + plot_radius])')
1039+
call me%add_str(' ax.set_zlim3d([z_middle - plot_radius, z_middle + plot_radius])')
1040+
call me%add_str('set_axes_equal(ax)')
1041+
1042+
else
1043+
call me%add_str('ax.axis("equal")')
1044+
end if
9411045
call me%add_str('')
9421046
end if
9431047

0 commit comments

Comments
 (0)