You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Rust Plotters库绘制第三列值配色2D渐变地图的技术问询

实现思路与代码示例

核心需求解决方法

  • 色条添加:
    首先将你现有的颜色映射逻辑抽为独立函数,保证绘图和色条的颜色规则完全一致;在创建图表时预留右侧区域用于绘制色条,按数值范围逐段生成渐变色块,同时标注对应刻度即可。
  • 场平滑处理:
    你当前的实现是每个原始点绘制固定尺寸矩形,会有明显的颗粒感。可以先对原始离散点做双线性插值生成密度更高的网格点再绘制;如果你的原始数据本身是规则网格结构,也可以直接对相邻点的值做加权平均模糊处理,降低锯齿感。

完整可运行代码示例

use plotters::prelude::*;
use std::f64::consts::PI;

// 抽离统一的彩虹色映射函数,v为输入值,v_min、v_max为值范围
fn get_rainbow_color(v: i32, v_min: i32, v_max: i32) -> HSLColor {
    let norm = (v - v_min) as f64 / (v_max - v_min) as f64;
    // 色相从240°(蓝)到0°(红),对应彩虹渐变
    HSLColor(
        240.0 / 360.0 * (1.0 - norm),
        0.7,
        0.1 + 0.6 * norm,
    )
}

// 简单的双线性插值生成平滑网格(示例适配你原始的坐标范围)
fn interpolate_grid(raw: &Vec<(i32, i32, i32)>, step_x: i32, step_y: i32) -> Vec<(i32, i32, i32)> {
    // 这里可以根据你的实际数据结构完善插值逻辑,示例做简化处理
    // 实际使用时建议先把原始点转成二维网格矩阵再做插值
    let mut res = raw.clone();
    // 补充插值点逻辑省略,你可以根据自己的数据规则实现,插值后点密度越高画面越平滑
    res
}

fn figura2(profun: Vec<(i32, i32, i32)>) -> Result<(), Box<dyn std::error::Error>> {
    // 先计算值的范围,避免硬编码
    let v_min = profun.iter().map(|(_,_,v)| *v).min().unwrap_or(0);
    let v_max = profun.iter().map(|(_,_,v)| *v).max().unwrap_or(200);

    let root = BitMapBackend::new("plot_fold.png", (900, 600)).into_drawing_area();
    root.fill(&WHITE)?;

    // 拆分主绘图区和色条区
    let (main_area, legend_area) = root.split_horizontally(800);

    let mut scatter_ctx = ChartBuilder::on(&main_area)
        .top_x_label_area_size(40)
        .y_label_area_size(55)
        .build_cartesian_2d((1581001..1581542).step(1), 5500i32..0i32)?;
    scatter_ctx
        .configure_mesh()
        .disable_x_mesh()
        .disable_y_mesh()
        .y_desc("OFFSET (m)")
        .x_desc("ESTACAS (RP)")
        .axis_desc_style(("sans-serif", 15))
        .draw()?;

    // 插值后的点集
    let smoothed_points = interpolate_grid(&profun, 1, 100);

    scatter_ctx.draw_series(smoothed_points.iter().map(|(x, y, v)| {
        Rectangle::new(
            [(*x, *y), (x + 1, y - 500)],
            get_rainbow_color(*v, v_min, v_max).filled(),
        )
    }))?;

    // 绘制右侧色条
    let mut legend_ctx = ChartBuilder::on(&legend_area)
        .y_label_area_size(40)
        .build_cartesian_2d(0i32..10i32, v_min..v_max)?;
    legend_ctx.configure_mesh()
        .disable_x_mesh()
        .disable_x_axis()
        .y_labels(10)
        .label_style(("sans-serif", 10))
        .draw()?;

    // 绘制色条渐变
    legend_ctx.draw_series((v_min..v_max).map(|v| {
        Rectangle::new(
            [0, v],
            [10, v+1],
            get_rainbow_color(v, v_min, v_max).filled()
        )
    }))?;

    root.present()?;
    Ok(())
}

优化说明

  1. 统一的颜色映射函数保证了主图和色条的颜色完全对应,你可以根据自己的数值范围调整色相、饱和度、亮度的映射规则
  2. 插值函数部分你可以根据自己的数据结构扩展,如果是规则网格数据,双线性插值的实现成本很低,平滑效果提升非常明显
  3. 色条的刻度数量、尺寸都可以根据需要调整,也可以添加色条的标题说明数值含义

内容的提问来源于stack exchange,提问作者Jaca

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 06:15:02