Нарисуйте плавную цветовую шкалу и присвойте ей определенные значения

Я рассматриваю новый способ реализации простой двухмерной графической матрицы, в которой цвета элементов зависят от индивидуальных значений, присвоенных этим элементам. До сих пор я использовал для этого следующую схему:

1) Предоставьте ссылку на цветовую шкалу на основе интервалов (состоящую, скажем, из 20 блоков), которой я мог бы назначить определенный диапазон значений, например 100-1000.

2) Свяжите отдельные значения элементов матрицы с цветами из шкалы, упомянутой выше, таким образом, элемент со значением 100 будет, например, BLUE, а элемент со значением 1000 будет RED.

Проблема с таким решением в том, что мне пришлось строить свою цветовую шкалу из «блоков», и это выглядит так:

введите описание изображения здесь

Это решение не так уж и плохо, но я хочу пойти дальше и реализовать очень точное соответствие value-color с помощью цветовой шкалы, как показано ниже:

введите описание изображения здесь

Далее не будет ничего более отличного от дрели, описанной выше. Я «поставлю» эту шкалу между значениями заданного диапазона (например, 100-1000), и в зависимости от индивидуального значения элемента матрицы я выберу правильный цвет из шкалы и назначу его данному элементу.

Но как я мог нарисовать такую ​​шкалу и поместить ее в диапазон определенных значений, пытаясь избежать ItemValue-To-SpecificColorBlock проблемы соответствия из моего старого решения?


person bluevoxel    schedule 09.08.2014    source источник


Ответы (1)


В статистике (визуализации) это называется тепловой картой.

Чтобы вычислить цвет для заданного значения, с MIN ‹= value‹ MAX, я бы интерполировал его в диапазон Color.BLUE.getHue () - Color.RED.getHue ().

i.e.

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);
    }
}
person James_D    schedule 09.08.2014
comment
Отличное решение. Большое тебе спасибо. - person bluevoxel; 09.08.2014