# Creating colour spectrum by light flux values

I am using radiosity method to compute the inter-reflected light within a room. The room is gridded into small patches and the light flux in lumen is calculated for each. This part is done. Now I want to change the colour of each patch so that the room surfaces show a continuous colour banding contours like this image, but have no clue how to this.

Update:

Here is a sample data for a room surface. The data is in this format: (x, y): value

• You need to provide more information on your data. Commented Jun 4, 2016 at 15:43
• Thanks Jon. The data is(for each surface sub patch) the ratio of the total flux received by the patch to the total lamp flux.
– ali
Commented Jun 4, 2016 at 18:22
• Thanks. Room surfaces are divided into grid squares of 0.3mx0.3m and the value for the centre of each grid cell is computed. Patches values vary between 0-5. The closer the surface to the source of light(ex. the window) the higher the value. Towards the end of the room values linearly go down to zero.
– ali
Commented Jun 6, 2016 at 8:20
• @ali just give Jon some sample data, what's so difficult about that?
– user35344
Commented Jun 6, 2016 at 11:32
• @Jon sorry guys I updated a link to sample data.
– ali
Commented Jun 6, 2016 at 16:06

Here is a little help on getting you started with this rendering. This may not be the best way to accomplish this task however, it should work.

First I created a structure to hold your data for parsing from text file:

public struct Data {

public Data(float x, float y, float value){
X = x;
Y = y;
Value = value;
}

public float Value;
public float X;
public float Y;
}


I then initialized the color palette based on your above image (reversed because I messed up the ordering initially):

Color[] Colors;

private void InitColors()
{
Colors = new Color[20];

Colors [19] = new Color (230 / 255f, 29 / 255f, 0 / 255f, 1);
Colors [18] = new Color (230 / 255f, 74 / 255f, 0 / 255f, 1);
Colors [17] = new Color (230 / 255f, 119 / 255f, 0 / 255f, 1);
Colors [16] = new Color (230 / 255f, 164 / 255f, 0 / 255f, 1);
Colors [15] = new Color (230 / 255f, 207 / 255f, 0 / 255f, 1);
Colors [14] = new Color (185 / 255f, 207 / 255f, 0 / 255f, 1);
Colors [13] = new Color (140 / 255f, 207 / 255f, 0 / 255f, 1);
Colors [12] = new Color (94 / 255f, 207 / 255f, 0 / 255f, 1);
Colors [11] = new Color (49 / 255f, 207 / 255f, 23 / 255f, 1);
Colors [10] = new Color (3 / 255f, 207 / 255f, 73 / 255f, 1);
Colors [9] = new Color (0 / 255f, 207 / 255f, 173 / 255f, 1);
Colors [8] = new Color (0 / 255f, 198 / 255f, 223 / 255f, 1);
Colors [7] = new Color (0 / 255f, 153 / 255f,  230 / 255f, 1);
Colors [6] = new Color (0 / 255f, 108 / 255f, 230 / 255f, 1);
Colors [5] = new Color (0 / 255f, 63 / 255f, 230 / 255f, 1);
Colors [4] = new Color (37 / 255f, 18 / 255f, 230 / 255f, 1);
Colors [3] = new Color (82 / 255f, 0 / 255f, 230 / 255f, 1);
Colors [2] = new Color (128 / 255f, 0 / 255f, 230 / 255f, 1);
Colors [1] = new Color (173 / 255f, 0 / 255f, 230 / 255f, 1);
Colors [0] = new Color (219 / 255f, 1 / 255f, 230 / 255f, 1);
}


I then wrote a parsing function to get the data from your text file into memory, and analyze parts of the data for future use:

private HashSet<float> XValues;
private HashSet<float> YValues;

private List<Data> DataList;

private float Min, MinX, MinY;
private float Max, MaxX, MaxY;

private void ParseData()
{
Min = float.MaxValue;
Max = float.MinValue;
MinX = float.MaxValue;
MaxX = float.MinValue;
MinY = float.MaxValue;
MaxY = float.MinValue;

DataList = new List<Data> ();
XValues = new HashSet<float> ();
YValues = new HashSet<float> ();

if (File.Exists ("data.txt")) {

string line = "";

while ((line = file.ReadLine ()) != null) {

line = line.Replace("(", string.Empty);
line = line.Replace(")", string.Empty);
line = line.Replace(":", ",");
string[] split = line.Split (',');

float x = System.Convert.ToSingle(split [0]);
float y =  System.Convert.ToSingle(split [1]);
float value =  System.Convert.ToSingle(split [2]);

Data data = new Data (x, y, value);

Min = Mathf.Min (Min, value);
Max = Mathf.Max (Max, value);
MinX = Mathf.Min (MinX, x);
MaxX = Mathf.Max (MaxX, x);
MinY = Mathf.Min (MinY, y);
MaxY = Mathf.Max (MaxY, y);

}

file.Close ();
}
}


Now it is easy to convert the parsed data into a Dataset that we can use:

private Data[,] Data;

private void GenerateDataSet()
{
Data = new Data[XValues.Count, YValues.Count];

for (int x = 0; x < XValues.Count; x++) {
for (int y = 0; y < YValues.Count; y++) {
Data [x, y] = DataList [x + y * XValues.Count];
}
}
}


If we visualize this data now, we get the following:

In order to smooth this out, we are going to add values in between and interpolate based on the distance between known node values:

float[,] Interpolated;

private void Interpolate()
{
int steps = 25;

Interpolated = new float[Data.GetLength (0) * steps, Data.GetLength (1) * steps];

for (int y = 0; y < Interpolated.GetLength (1) - steps; y++) {

for (int x = 0; x < Interpolated.GetLength (0) - steps; x++) {

int x1 = x / steps;
int x2 = x1 + 1;
int y1 = y / steps;
int y2 = y1 + 1;

float distance1 = (new Vector2 (x, y) - new Vector2 (x1 * steps, y1 * steps)).magnitude;
float distance2 = (new Vector2 (x, y) - new Vector2 (x1 * steps, y2 * steps)).magnitude;
float distance3 = (new Vector2 (x, y) - new Vector2 (x2 * steps, y1 * steps)).magnitude;
float distance4 = (new Vector2 (x, y) - new Vector2 (x2 * steps, y2 * steps)).magnitude;

float value1 = Data [x1, y1].Value;
float value2 = Data [x1, y2].Value;
float value3 = Data [x2, y1].Value;
float value4 = Data [x2, y2].Value;

int totalCount = 0;

int count = steps - (int)distance1;
count = Mathf.Max (count, 0);
float total = value1 * count;
totalCount += count;

count = steps - (int)distance2;
count = Mathf.Max (count, 0);
total += value2 * count;
totalCount += count;

count = steps - (int)distance3;
count = Mathf.Max (count, 0);
total += value3 * count;
totalCount += count;

count = steps - (int)distance4;
count = Mathf.Max (count, 0);
total += value4 * count;
totalCount += count;

total = total / (float)totalCount;

Interpolated [x, y] = total;
}
}
}


Now if we draw this interpolated data, we get something that looks a lot more like what you are trying to output. Here is the Texture generation code that was used:

public Texture2D GetHeatMapTexture()
{
int width = Interpolated.GetLength (0);
int height = Interpolated.GetLength (1);

var texture = new Texture2D (width, height);
var pixels = new Color[width * height];

for (var x = 0; x < width; x++)
{
for (var y = 0; y < height; y++)
{
float value = Interpolated [x,y];

float normalized = (value - Min) / (Max - Min);
normalized *= Colors.Length;
int colorValue = (int)normalized;
colorValue = Mathf.Clamp (colorValue, 0, 19);

pixels [x + y * width] = Colors [colorValue];
}
}

texture.SetPixels(pixels);
texture.wrapMode = TextureWrapMode.Clamp;
texture.filterMode = FilterMode.Point;
texture.Apply();
return texture;
}


And here is what it looks like with your provided dataset:

There are probably better ways to accomplish this result, but at least this can provide you with a way to at least get started doing what it is you are trying to do.

• Thanks Jon this is amazing; and sorry I didn't appreciate your asking for sample data first.
– ali
Commented Jun 6, 2016 at 20:00
• No problem at all. The problem looked like fun to tackle, so that is why I was asking for it. Let me know if you have any questions about the above implementation. Commented Jun 6, 2016 at 20:07
• I believe in Java you can initialize a color with all integers out of 255, so you can get rid of the division. Commented Jun 21, 2016 at 16:55
• @Kyranstar The code above is not java, it is C#. More specifically it is utilizing the Unity Color class. You will of course have to port this code to whatever platform it is you are developing with. Commented Jun 21, 2016 at 16:56
• Oh sorry, I didn't look closely enough. Commented Jun 21, 2016 at 16:57