module fortplot_matplotlib_scatter_dispatch !! Internal dispatch layer for matplotlib-compatible scatter plots. !! !! Provides 2D and 3D dispatch procedures that prepare data arrays, !! resolve sizes/linewidths/edgecolors, and call the core scatter !! library (add_scatter_2d / add_scatter_3d). !! !! This module is internal to the scatter subsystem; consumers should !! use the public `scatter` and `add_scatter` interfaces instead. use, intrinsic :: iso_fortran_env, only: wp => real64 use fortplot_global, only: fig => global_figure use fortplot_logging, only: log_error use fortplot_matplotlib_color_utils, only: resolve_color_string_or_rgb use fortplot_matplotlib_scatter_utils, only: build_scatter_size_array, & effective_linewidth, & optional_logical, & uniform_edgecolor, & store_scatter_style_arrays, & edgecolors_are_none use fortplot_matplotlib_session, only: ensure_fig_init use fortplot_scatter_plots, only: add_scatter_2d, add_scatter_3d implicit none private public :: scatter_2d_dispatch public :: scatter_3d_dispatch public :: scatter_3d_string_dispatch contains subroutine scatter_3d_string_dispatch(x, y, z, color_rgb, has_color, s, & s_scalar, c, label, marker, & linewidths, linewidths_scalar, & edgecolors, alpha, cmap, vmin, vmax) real(wp), contiguous, intent(in) :: x(:), y(:), z(:) real(wp), intent(in) :: color_rgb(3) logical, intent(in) :: has_color real(wp), intent(in), optional :: s(:), s_scalar, c(:) character(len=*), intent(in), optional :: label, marker, cmap real(wp), intent(in), optional :: linewidths(..) real(wp), intent(in), optional :: linewidths_scalar class(*), intent(in), optional :: edgecolors(..) real(wp), intent(in), optional :: alpha real(wp), intent(in), optional :: vmin, vmax if (has_color) then call scatter_3d_dispatch(x, y, z, s=s, s_scalar=s_scalar, c=c, & label=label, marker=marker, & color=color_rgb, & linewidths=linewidths, & linewidths_scalar=linewidths_scalar, & edgecolors=edgecolors, alpha=alpha, & cmap=cmap, vmin=vmin, vmax=vmax) else call scatter_3d_dispatch(x, y, z, s=s, s_scalar=s_scalar, c=c, & label=label, marker=marker, & linewidths=linewidths, & linewidths_scalar=linewidths_scalar, & edgecolors=edgecolors, alpha=alpha, & cmap=cmap, vmin=vmin, vmax=vmax) end if end subroutine scatter_3d_string_dispatch subroutine scatter_2d_dispatch(x, y, s, s_scalar, c, label, marker, & color, linewidths, & linewidths_scalar, edgecolors, alpha, cmap, & vmin, vmax, edgecolors_none) real(wp), contiguous, intent(in) :: x(:), y(:) real(wp), intent(in), optional :: s(:), s_scalar, c(:) character(len=*), intent(in), optional :: label, marker, cmap real(wp), intent(in), optional :: color(3) real(wp), intent(in), optional :: linewidths(..) real(wp), intent(in), optional :: linewidths_scalar class(*), intent(in), optional :: edgecolors(..) real(wp), intent(in), optional :: alpha, vmin, vmax logical, intent(in), optional :: edgecolors_none real(wp), allocatable :: wx(:), wy(:), s_arr(:) real(wp) :: edge_rgb(3) real(wp) :: lw_effective logical :: has_uniform_edge, no_edges call ensure_fig_init() allocate (wx(size(x)), wy(size(y))) wx = x wy = y call build_scatter_size_array(size(x), s, s_scalar, s_arr) lw_effective = effective_linewidth(linewidths, linewidths_scalar) call uniform_edgecolor(size(x), edgecolors, edge_rgb, has_uniform_edge) no_edges = optional_logical(edgecolors_none) .or. & edgecolors_are_none(edgecolors) if (has_uniform_edge) then call add_scatter_2d(fig, wx, wy, s=s_arr, c=c, label=label, & marker=marker, color=color, colormap=cmap, & vmin=vmin, vmax=vmax, alpha=alpha, & edgecolor=edge_rgb, linewidth=lw_effective) else call add_scatter_2d(fig, wx, wy, s=s_arr, c=c, label=label, & marker=marker, color=color, colormap=cmap, & vmin=vmin, vmax=vmax, alpha=alpha, & linewidth=lw_effective) end if call store_scatter_style_arrays(size(x), edgecolors, linewidths, no_edges) end subroutine scatter_2d_dispatch subroutine scatter_3d_dispatch(x, y, z, s, s_scalar, c, label, marker, & color, linewidths, & linewidths_scalar, edgecolors, alpha, cmap, & vmin, vmax, edgecolors_none) real(wp), contiguous, intent(in) :: x(:), y(:), z(:) real(wp), intent(in), optional :: s(:), s_scalar, c(:) character(len=*), intent(in), optional :: label, marker, cmap real(wp), intent(in), optional :: color(3) real(wp), intent(in), optional :: linewidths(..) real(wp), intent(in), optional :: linewidths_scalar class(*), intent(in), optional :: edgecolors(..) real(wp), intent(in), optional :: alpha, vmin, vmax logical, intent(in), optional :: edgecolors_none real(wp), allocatable :: wx(:), wy(:), wz(:), s_arr(:) real(wp) :: edge_rgb(3) real(wp) :: lw_effective logical :: has_uniform_edge, no_edges call ensure_fig_init() allocate (wx(size(x)), wy(size(y)), wz(size(z))) wx = x wy = y wz = z call build_scatter_size_array(size(x), s, s_scalar, s_arr) lw_effective = effective_linewidth(linewidths, linewidths_scalar) call uniform_edgecolor(size(x), edgecolors, edge_rgb, has_uniform_edge) no_edges = optional_logical(edgecolors_none) .or. & edgecolors_are_none(edgecolors) if (has_uniform_edge) then call add_scatter_3d(fig, wx, wy, wz, s=s_arr, c=c, label=label, & marker=marker, color=color, colormap=cmap, & vmin=vmin, vmax=vmax, alpha=alpha, & edgecolor=edge_rgb, linewidth=lw_effective) else call add_scatter_3d(fig, wx, wy, wz, s=s_arr, c=c, label=label, & marker=marker, color=color, colormap=cmap, & vmin=vmin, vmax=vmax, alpha=alpha, & linewidth=lw_effective) end if call store_scatter_style_arrays(size(x), edgecolors, linewidths, no_edges) end subroutine scatter_3d_dispatch end module fortplot_matplotlib_scatter_dispatch