本文介绍了在图形中生成明显不同的 RGB 颜色的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在生成图表并显示不同的数据集时,最好按颜色区分数据集.所以一条线是红色的,下一条线是绿色的,依此类推.问题是,当数据集的数量未知时,需要随机生成这些颜色,而且通常它们最终彼此非常接近(例如绿色、浅绿色).

When generating graphs and showing different sets of data it usually a good idea to difference the sets by color. So one line is red and the next is green and so on. The problem is then that when the number of datasets is unknown one needs to randomly generate these colors and often they end up very close to each other (green, light green for example).

关于如何解决这个问题以及如何产生明显不同的颜色的任何想法?

Any ideas on how this could be solved and how it would be possibler to generate distinctly different colors?

如果有任何示例(如果您觉得更简单,请随意讨论问题和解决方案而不提供示例)是基于 C# 和 RGB 的颜色,我会很棒.

I'd be great if any examples (feel free to just discuss the problem and solution without examples if you find that easier) were in C# and RGB based colors.

推荐答案

您有 0 到 255 R、G 和 B 三个颜色通道.

You have three colour channels 0 to 255 R, G and B.

先通过

0, 0, 255
0, 255, 0
255, 0, 0

然后通过

0, 255, 255
255, 0, 255
255, 255, 0

然后除以 2 => 128 并重新开始:

Then divide by 2 => 128 and start again:

0, 0, 128
0, 128, 0
128, 0, 0
0, 128, 128
128, 0, 128
128, 128, 0

除以 2 => 64

下次将 64 添加到 128 => 192

Next time add 64 to 128 => 192

遵循模式.

直接编程并为您提供相当不同的颜色.

Straightforward to program and gives you fairly distinct colours.

代码示例请求

此外 - 如果灰色是可接受的颜色,则添加如下附加图案:

Also - adding in the additional pattern as below if gray is an acceptable colour:

255, 255, 255
128, 128, 128

您可以通过多种方式在代码中生成这些.

There are a number of ways you can handle generating these in code.

如果您可以保证永远不会需要超过固定数量的颜色,只需按照此模式生成一组颜色并使用它们:

If you can guarantee that you will never need more than a fixed number of colours, just generate an array of colours following this pattern and use those:

    static string[] ColourValues = new string[] {
        "FF0000", "00FF00", "0000FF", "FFFF00", "FF00FF", "00FFFF", "000000",
        "800000", "008000", "000080", "808000", "800080", "008080", "808080",
        "C00000", "00C000", "0000C0", "C0C000", "C000C0", "00C0C0", "C0C0C0",
        "400000", "004000", "000040", "404000", "400040", "004040", "404040",
        "200000", "002000", "000020", "202000", "200020", "002020", "202020",
        "600000", "006000", "000060", "606000", "600060", "006060", "606060",
        "A00000", "00A000", "0000A0", "A0A000", "A000A0", "00A0A0", "A0A0A0",
        "E00000", "00E000", "0000E0", "E0E000", "E000E0", "00E0E0", "E0E0E0",
    };

艰难的道路

如果您不知道需要多少种颜色,下面的代码将使用此图案生成多达 896 种颜色.(896 = 256 * 7/2) 256 是每个通道的颜色空间,我们有 7 个图案,我们在得到仅由 1 个颜色值分隔的颜色之前停止.

The Hard Way

If you don't know how many colours you are going to need, the code below will generate up to 896 colours using this pattern. (896 = 256 * 7 / 2) 256 is the colour space per channel, we have 7 patterns and we stop before we get to colours separated by only 1 colour value.

我可能比我需要的更努力地处理这段代码.首先,有一个从 255 开始的强度生成器,然后按照上述模式生成值.图案生成器只是循环遍历七种颜色图案.

I've probably made harder work of this code than I needed to. First, there is an intensity generator which starts at 255, then generates the values as per the pattern described above. The pattern generator just loops through the seven colour patterns.

using System;

class Program {
    static void Main(string[] args) {
        ColourGenerator generator = new ColourGenerator();
        for (int i = 0; i < 896; i++) {
            Console.WriteLine(string.Format("{0}: {1}", i, generator.NextColour()));
        }
    }
}

public class ColourGenerator {

    private int index = 0;
    private IntensityGenerator intensityGenerator = new IntensityGenerator();

    public string NextColour() {
        string colour = string.Format(PatternGenerator.NextPattern(index),
            intensityGenerator.NextIntensity(index));
        index++;
        return colour;
    }
}

public class PatternGenerator {
    public static string NextPattern(int index) {
        switch (index % 7) {
        case 0: return "{0}0000";
        case 1: return "00{0}00";
        case 2: return "0000{0}";
        case 3: return "{0}{0}00";
        case 4: return "{0}00{0}";
        case 5: return "00{0}{0}";
        case 6: return "{0}{0}{0}";
        default: throw new Exception("Math error");
        }
    }
}

public class IntensityGenerator {
    private IntensityValueWalker walker;
    private int current;

    public string NextIntensity(int index) {
        if (index == 0) {
            current = 255;
        }
        else if (index % 7 == 0) {
            if (walker == null) {
                walker = new IntensityValueWalker();
            }
            else {
                walker.MoveNext();
            }
            current = walker.Current.Value;
        }
        string currentText = current.ToString("X");
        if (currentText.Length == 1) currentText = "0" + currentText;
        return currentText;
    }
}

public class IntensityValue {

    private IntensityValue mChildA;
    private IntensityValue mChildB;

    public IntensityValue(IntensityValue parent, int value, int level) {
        if (level > 7) throw new Exception("There are no more colours left");
        Value = value;
        Parent = parent;
        Level = level;
    }

    public int Level { get; set; }
    public int Value { get; set; }
    public IntensityValue Parent { get; set; }

    public IntensityValue ChildA {
        get {
            return mChildA ?? (mChildA = new IntensityValue(this, this.Value - (1<<(7-Level)), Level+1));
        }
    }

    public IntensityValue ChildB {
        get {
            return mChildB ?? (mChildB = new IntensityValue(this, Value + (1<<(7-Level)), Level+1));
        }
    }
}

public class IntensityValueWalker {

    public IntensityValueWalker() {
        Current = new IntensityValue(null, 1<<7, 1);
    }

    public IntensityValue Current { get; set; }

    public void MoveNext() {
        if (Current.Parent == null) {
            Current = Current.ChildA;
        }
        else if (Current.Parent.ChildA == Current) {
            Current = Current.Parent.ChildB;
        }
        else {
            int levelsUp = 1;
            Current = Current.Parent;
            while (Current.Parent != null && Current == Current.Parent.ChildB) {
                Current = Current.Parent;
                levelsUp++;
            }
            if (Current.Parent != null) {
                Current = Current.Parent.ChildB;
            }
            else {
                levelsUp++;
            }
            for (int i = 0; i < levelsUp; i++) {
                Current = Current.ChildA;
            }

        }
    }
}

这篇关于在图形中生成明显不同的 RGB 颜色的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-20 09:04
查看更多