module fortplot_figure_grid !! Figure grid functionality module !! !! Single Responsibility: Handle grid configuration and rendering !! Extracted from fortplot_figure_core to improve modularity use, intrinsic :: iso_fortran_env, only: wp => real64 use fortplot_context use fortplot_axes, only: compute_scale_ticks use fortplot_scales, only: apply_scale_transform implicit none private public :: configure_grid, render_grid_lines contains subroutine configure_grid(grid_enabled, grid_which, grid_axis, grid_alpha, & grid_linestyle, enabled, which, axis, alpha, linestyle) !! Configure grid settings logical, intent(inout) :: grid_enabled character(len=10), intent(inout) :: grid_which character(len=1), intent(inout) :: grid_axis real(wp), intent(inout) :: grid_alpha character(len=10), intent(inout) :: grid_linestyle logical, intent(in), optional :: enabled character(len=*), intent(in), optional :: which, axis, linestyle real(wp), intent(in), optional :: alpha ! Handle boolean toggle syntax if (present(enabled)) then grid_enabled = enabled end if ! Handle string-based which parameter if (present(which)) then grid_which = which grid_enabled = .true. ! Implicitly enable grid end if ! Handle axis parameter with flexible input if (present(axis)) then select case(trim(axis)) case('x') grid_axis = 'x' case('y') grid_axis = 'y' case('both', 'b') grid_axis = 'b' case default grid_axis = 'b' end select grid_enabled = .true. ! Implicitly enable grid end if ! Handle alpha parameter if (present(alpha)) then grid_alpha = max(0.0_wp, min(1.0_wp, alpha)) grid_enabled = .true. ! Implicitly enable grid end if ! Handle linestyle parameter if (present(linestyle)) then grid_linestyle = linestyle grid_enabled = .true. ! Implicitly enable grid end if end subroutine configure_grid subroutine render_grid_lines(backend, grid_enabled, grid_which, grid_axis, & grid_alpha, width, height, margin_left, margin_right, & margin_bottom, margin_top, xscale, yscale, & symlog_threshold, x_min, x_max, y_min, y_max, & x_min_transformed, x_max_transformed, & y_min_transformed, y_max_transformed) !! Render grid lines on the figure class(plot_context), intent(inout) :: backend logical, intent(in) :: grid_enabled character(len=10), intent(in) :: grid_which character(len=1), intent(in) :: grid_axis real(wp), intent(in) :: grid_alpha integer, intent(in) :: width, height real(wp), intent(in) :: margin_left, margin_right, margin_bottom, margin_top character(len=*), intent(in) :: xscale, yscale real(wp), intent(in) :: symlog_threshold real(wp), intent(in) :: x_min, x_max, y_min, y_max real(wp), intent(in) :: x_min_transformed, x_max_transformed real(wp), intent(in) :: y_min_transformed, y_max_transformed real(wp) :: major_ticks(50) ! Fixed size array real(wp) :: tick_val, x1, y1, x2, y2, alpha_val integer :: i, plot_width, plot_height, num_ticks integer :: plot_x, plot_y real(wp) :: grid_color(3) if (.not. grid_enabled) return ! Calculate plot area in pixels plot_x = nint(margin_left * width) plot_y = nint(margin_bottom * height) plot_width = nint((1.0_wp - margin_left - margin_right) * width) plot_height = nint((1.0_wp - margin_bottom - margin_top) * height) ! Set grid color (gray) and alpha grid_color = [0.7_wp, 0.7_wp, 0.7_wp] alpha_val = grid_alpha ! Draw X-axis grid lines (vertical lines) if (grid_axis == 'x' .or. grid_axis == 'b') then ! Get major ticks for x-axis call compute_scale_ticks(xscale, x_min, x_max, & symlog_threshold, major_ticks, num_ticks) ! Draw major tick grid lines if (grid_which == 'major' .or. grid_which == 'both') then do i = 1, num_ticks tick_val = major_ticks(i) if (tick_val >= x_min .and. tick_val <= x_max) then ! Transform tick value to plot coordinates tick_val = apply_scale_transform(tick_val, xscale, symlog_threshold) ! Convert to pixel coordinates x1 = plot_x + (tick_val - x_min_transformed) / & (x_max_transformed - x_min_transformed) * plot_width y1 = real(plot_y, wp) x2 = x1 y2 = real(plot_y + plot_height, wp) ! Draw grid line call backend%color(grid_color(1), grid_color(2), grid_color(3)) call backend%line(x1, y1, x2, y2) end if end do end if end if ! Draw Y-axis grid lines (horizontal lines) if (grid_axis == 'y' .or. grid_axis == 'b') then ! Get major ticks for y-axis call compute_scale_ticks(yscale, y_min, y_max, & symlog_threshold, major_ticks, num_ticks) ! Draw major tick grid lines if (grid_which == 'major' .or. grid_which == 'both') then do i = 1, num_ticks tick_val = major_ticks(i) if (tick_val >= y_min .and. tick_val <= y_max) then ! Transform tick value to plot coordinates tick_val = apply_scale_transform(tick_val, yscale, symlog_threshold) ! Convert to pixel coordinates x1 = real(plot_x, wp) y1 = plot_y + (tick_val - y_min_transformed) / & (y_max_transformed - y_min_transformed) * plot_height x2 = real(plot_x + plot_width, wp) y2 = y1 ! Draw grid line call backend%color(grid_color(1), grid_color(2), grid_color(3)) call backend%line(x1, y1, x2, y2) end if end do end if end if end subroutine render_grid_lines end module fortplot_figure_grid