diff --git a/src/backends/raster/fortplot_raster.f90 b/src/backends/raster/fortplot_raster.f90 index c145101e..620c1a3e 100644 --- a/src/backends/raster/fortplot_raster.f90 +++ b/src/backends/raster/fortplot_raster.f90 @@ -20,6 +20,7 @@ module fortplot_raster use fortplot_raster_core, only: raster_image_t, create_raster_image, destroy_raster_image use fortplot_raster_axes, only: raster_draw_axes_and_labels, raster_render_ylabel, & raster_draw_axes_lines_and_ticks, raster_draw_axis_labels_only + use fortplot_raster_labels, only: raster_draw_axis_labels use fortplot_raster_rendering, only: raster_fill_heatmap, raster_fill_quad, fill_triangle, & raster_render_legend_specialized, raster_calculate_legend_dimensions, & raster_set_legend_border_width, raster_calculate_legend_position, & @@ -456,7 +457,8 @@ subroutine raster_draw_axes_and_labels_context(this, xscale, yscale, symlog_thre character(len=:), allocatable, intent(in), optional :: title, xlabel, ylabel real(wp), intent(in), optional :: z_min, z_max logical, intent(in) :: has_3d_plots - + character(len=:), allocatable :: title_str, xlabel_str, ylabel_str + ! Set color to black for axes and text call this%color(0.0_wp, 0.0_wp, 0.0_wp) @@ -465,12 +467,24 @@ subroutine raster_draw_axes_and_labels_context(this, xscale, yscale, symlog_thre call draw_3d_axes(this, x_min, x_max, y_min, y_max, & merge(z_min, 0.0_wp, present(z_min)), & merge(z_max, 1.0_wp, present(z_max))) - ! Draw title/xlabel/ylabel using existing raster helpers for labels only + ! Draw title/xlabel/ylabel without re-drawing 2D tick labels if (present(title) .or. present(xlabel) .or. present(ylabel)) then - call raster_draw_axis_labels_only(this%raster, this%width, this%height, this%plot_area, & - xscale, yscale, symlog_threshold, & - x_min, x_max, y_min, y_max, & - title, xlabel, ylabel) + title_str = "" + xlabel_str = "" + ylabel_str = "" + + if (present(title)) then + if (allocated(title)) title_str = title + end if + if (present(xlabel)) then + if (allocated(xlabel)) xlabel_str = xlabel + end if + if (present(ylabel)) then + if (allocated(ylabel)) ylabel_str = ylabel + end if + + call raster_draw_axis_labels(this%raster, this%width, this%height, this%plot_area, & + title_str, xlabel_str, ylabel_str) end if else ! Delegate to standard 2D axes module diff --git a/src/plotting/fortplot_3d_axes.f90 b/src/plotting/fortplot_3d_axes.f90 index 6f01899e..68ddca1f 100644 --- a/src/plotting/fortplot_3d_axes.f90 +++ b/src/plotting/fortplot_3d_axes.f90 @@ -226,11 +226,14 @@ subroutine draw_3d_axis_ticks_and_labels(ctx, corners_2d, x_min, x_max, y_min, y real(wp) :: x_range, y_range real(wp) :: tick_len_y, tick_len_x real(wp) :: pad_x, pad_y + real(wp) :: tick_y_end, label_y_pos + real(wp) :: y_span integer :: decimals_x, decimals_y, decimals_z ! Use fractions of the current data ranges for tick lengths and padding - x_range = max(1.0e-12_wp, x_max - x_min) - y_range = max(1.0e-12_wp, y_max - y_min) + x_range = max(1.0e-12_wp, abs(x_max - x_min)) + y_span = y_max - y_min + y_range = max(1.0e-12_wp, abs(y_span)) tick_len_y = 0.02_wp * y_range ! vertical tick length (in data units) tick_len_x = 0.02_wp * x_range ! horizontal tick length (in data units) pad_x = 0.02_wp * x_range ! horizontal text padding (data units) @@ -252,13 +255,22 @@ subroutine draw_3d_axis_ticks_and_labels(ctx, corners_2d, x_min, x_max, y_min, y ! Interpolate position along edge x_pos = corners_2d(1,1) + (corners_2d(1,2) - corners_2d(1,1)) * real(i-1, wp) / real(n_ticks-1, wp) y_pos = corners_2d(2,1) + (corners_2d(2,2) - corners_2d(2,1)) * real(i-1, wp) / real(n_ticks-1, wp) - - ! Draw tick mark pointing down (in data units) - call ctx%line(x_pos, y_pos, x_pos, y_pos + tick_len_y) - + + ! Determine downward direction in device space based on Y span sign + if (y_span >= 0.0_wp) then + tick_y_end = y_pos - tick_len_y + label_y_pos = tick_y_end - pad_y + else + tick_y_end = y_pos + tick_len_y + label_y_pos = tick_y_end + pad_y + end if + + ! Draw tick mark pointing down in device space + call ctx%line(x_pos, y_pos, x_pos, tick_y_end) + ! Draw label using consistent decimal places across the axis label = format_tick_value_consistent(value, decimals_x) - call render_text_to_ctx(ctx, x_pos - 0.5_wp*pad_x, y_pos + tick_len_y + pad_y, trim(adjustl(label))) + call render_text_to_ctx(ctx, x_pos - 0.5_wp*pad_x, label_y_pos, trim(adjustl(label))) end do ! Y-axis ticks and labels (edge from corner 1 to corner 4)