# 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. – jgallant Jun 4 '16 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 Jun 4 '16 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 Jun 6 '16 at 8:20
• @ali just give Jon some sample data, what's so difficult about that? – Tyyppi_77 Jun 6 '16 at 11:32
• @Jon sorry guys I updated a link to sample data. – ali Jun 6 '16 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;

Colors  = new Color (230 / 255f, 29 / 255f, 0 / 255f, 1);
Colors  = new Color (230 / 255f, 74 / 255f, 0 / 255f, 1);
Colors  = new Color (230 / 255f, 119 / 255f, 0 / 255f, 1);
Colors  = new Color (230 / 255f, 164 / 255f, 0 / 255f, 1);
Colors  = new Color (230 / 255f, 207 / 255f, 0 / 255f, 1);
Colors  = new Color (185 / 255f, 207 / 255f, 0 / 255f, 1);
Colors  = new Color (140 / 255f, 207 / 255f, 0 / 255f, 1);
Colors  = new Color (94 / 255f, 207 / 255f, 0 / 255f, 1);
Colors  = new Color (49 / 255f, 207 / 255f, 23 / 255f, 1);
Colors  = new Color (3 / 255f, 207 / 255f, 73 / 255f, 1);
Colors  = new Color (0 / 255f, 207 / 255f, 173 / 255f, 1);
Colors  = new Color (0 / 255f, 198 / 255f, 223 / 255f, 1);
Colors  = new Color (0 / 255f, 153 / 255f,  230 / 255f, 1);
Colors  = new Color (0 / 255f, 108 / 255f, 230 / 255f, 1);
Colors  = new Color (0 / 255f, 63 / 255f, 230 / 255f, 1);
Colors  = new Color (37 / 255f, 18 / 255f, 230 / 255f, 1);
Colors  = new Color (82 / 255f, 0 / 255f, 230 / 255f, 1);
Colors  = new Color (128 / 255f, 0 / 255f, 230 / 255f, 1);
Colors  = new Color (173 / 255f, 0 / 255f, 230 / 255f, 1);
Colors  = 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 );
float y =  System.Convert.ToSingle(split );
float value =  System.Convert.ToSingle(split );

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 Jun 6 '16 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. – jgallant Jun 6 '16 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. – Kyranstar Jun 21 '16 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. – jgallant Jun 21 '16 at 16:56
• Oh sorry, I didn't look closely enough. – Kyranstar Jun 21 '16 at 16:57