java - 绘制平滑色标并为其分配特定值

标签 java javafx javafx-2 javafx-8

我正在考虑一种新的实现简单 2D 图形矩阵的方法,其中其项目的颜色取决于分配给这些项目的各个值。到目前为止,我为此目的使用了以下架构:

1) 提供一个基于区间的色标引用(例如由 20 个色 block 构成),我可以为其分配特定范围的值,例如100-1000。

2) 将矩阵项的各个值与上述比例的颜色联系起来,因此值为 100 的项将为 BLUE,而值为 1000 的项将为 RED .

这种解决方案的问题是,我必须从“ block ”构建我的色标,所以它看起来像这样:

enter image description here

这个解决方案还不错,但我想更进一步,在色标的帮助下实现更准确的 value-color 匹配,如下所示:

enter image description here

接下来,与上述演习没有什么不同。我会将这个比例“放在”给定范围(例如 100-1000)的值之间,并根据矩阵项的各个值,我将从比例中选择合适的颜色并将其分配给给定项。

但是我如何绘制这样的比例并将其置于特定值的范围内,以避免旧解决方案中的 ItemValue-To-SpecificColorBlock 匹配问题?

最佳答案

在统计(可视化)中,这称为热图。

要计算给定值的颜色,MIN <= value < MAX,我会将其插值到 Color.BLUE.getHue() - Color.RED.getHue() 范围内。

double hue = Color.BLUE.getHue() + (Color.RED.getHue() - Color.BLUE.getHue()) * (value - MIN) / (MAX - MIN) ;

然后使用色调创建具有完全饱和度和亮度的颜色:

Color color = Color.hsb(hue, 1.0, 1.0);

要创建色标图像,请创建一个 WritableImage,抓取像素写入器,遍历所有像素,并使用上面的公式设置每个像素的颜色,值沿 x 轴从 0 插值到图像。 (如果你想要垂直色标,类似地沿 y 轴插值。)

这是一个绘制色标的示例。您可以使用 getColorForValue(...) 方法计算给定值的颜色,以显示矩阵。

import javafx.application.Application;
import javafx.geometry.Orientation;
import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.image.PixelWriter;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class HeatMap extends Application {

    private final static double MIN = 100 ;
    private final static double MAX = 1000 ;
    private final static double BLUE_HUE = Color.BLUE.getHue() ;
    private final static double RED_HUE = Color.RED.getHue() ;

    @Override
    public void start(Stage primaryStage) {
        Image colorScale = createColorScaleImage(600, 120, Orientation.HORIZONTAL);
        ImageView imageView = new ImageView(colorScale);
        StackPane root = new StackPane(imageView);
        Scene scene = new Scene(root, 800, 400);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    private Color getColorForValue(double value) {
        if (value < MIN || value > MAX) {
            return Color.BLACK ;
        }
        double hue = BLUE_HUE + (RED_HUE - BLUE_HUE) * (value - MIN) / (MAX - MIN) ;
        return Color.hsb(hue, 1.0, 1.0);
    }

    private Image createColorScaleImage(int width, int height, Orientation orientation) {
        WritableImage image = new WritableImage(width, height);
        PixelWriter pixelWriter = image.getPixelWriter();
        if (orientation == Orientation.HORIZONTAL) {
            for (int x=0; x<width; x++) {
                double value = MIN + (MAX - MIN) * x / width;
                Color color = getColorForValue(value);
                for (int y=0; y<height; y++) {
                    pixelWriter.setColor(x, y, color);
                }
            }
        } else {
            for (int y=0; y<height; y++) {
                double value = MAX - (MAX - MIN) * y / height ;
                Color color = getColorForValue(value);
                for (int x=0; x<width; x++) {
                    pixelWriter.setColor(x, y, color);
                }
            }
        }
        return image ;
    }

    public static void main(String[] args) {
        launch(args);
    }
}

关于java - 绘制平滑色标并为其分配特定值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25214538/

相关文章:

Java - 如何将 Files.lines() 的 URL 转换为 PATH

intellij-idea - JavaFX 源代码未显示

java - 如何知道窗口大小的调整是从左侧还是从右侧完成?

java - 我们如何使用 Scene builder 2 来定位 java 7?

Java,获取核心转储

java - RecyclerView 显示来自 2 种不同布局的数据

java - 是否可以在同一框架中打开新的 fxml 文件

javafx - 文本区域滚动 Pane 保留在文本附加中

java - 如何在 Java 中确定 Internet 网络接口(interface)

JAVAFX:从数据库加载图像