• Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by Onsterion · Oct 07, 2015 at 07:03 PM · c#unity 5drawtexture

Heat Map Effect

Hi all,

I intend to create an effect of heat map to detect the amount of people walking in an area like this:

alt text

But until now I only can draw pixels using vector2.

alt text

Anybody know any tutorial or information on how to do the effect?

Greetings.

heatmapintent.jpg (46.6 kB)
heatmap.jpg (69.7 kB)
Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

2 Replies

· Add your reply
  • Sort: 
avatar image
0

Answer by FortisVenaliter · Oct 07, 2015 at 08:36 PM

What you're probably going to want to do is render to a down-sampled screen buffer, then blur it and scale it up to screen space. Then you can do the drawing like you have in the screenshot, but it will look like the desired effect.

Look up RenderTargets to learn how to render to a separate buffer.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
2

Answer by Bunny83 · Oct 07, 2015 at 11:52 PM

A heatmap is usually drawn by taking all data in an area into account.

So lets say you have an array of Vector2/3 values which represents your recorded data. There are basically two ways to calculate the intensity for each pixel in your heatmap:

  • for each pixel you iterate through all of your data array and calculate the distance of the data point to the current pixel. The further away that data point is the less it's addition to that pixel would be. A quadratic fall off ise quite common (simply use sqrMagnitude instead of magnitude). This however can take quite a while if you have a lot data.

  • the second way is a bit more optimised. You simply iterate through all your data points and use a square area around that point. Here you also would use a falloff from the center to the points which are further away. So you basically start with a pixel grid where each value is 0 and for each point in the data you increate all the points around that pixel.

In the end you should have an actual map where the hot areas have the highest value. Now just scale the values to fit in a 0-1 range and use a Gradient to give each pixel a color.

edit
This question actually has been asked quite a few times now. Did you actually search? ^^

2. edit

Here's an example class i just written:

 public class Heatmap
 {
     private float[] samples;
     private float[] circle;
     private int width;
     private int height;
     private int radius;
 
     // returns the highest sample
     private float MaxValue
     {
         get
         {
             float v = 0f;
             for (int i = 0; i < samples.Length; i++)
                 if (samples[i] > v)
                     v = samples[i];
             return v;
         }
     }
 
     public Heatmap(int aWidth, int aHeight, int aRadius)
     {
         width = aWidth;
         height = aHeight;
         radius = aRadius;
         samples = new float[aWidth * aHeight];
         CreateCircleMap();
     }
     // creates our circle map that is "copied" into our map
     void CreateCircleMap()
     {
         circle = new float[radius * radius * 4];
         for(int x = -radius; x < radius; x++)
         {
             for(int y = -radius; y < radius; y++)
             {
                 float l = (x*x+y*y) / (float)(radius*radius);
                 float v = 0f;
                 if (l < 1f)
                     v = 1f - l;
                 circle[x + radius + radius * 2 * y] = v;
             }
         }
     }
     public void AddPoint(Vector2 aPos)
     {
         int px = Mathf.RoundToInt(aPos.x);
         int py = Mathf.RoundToInt(aPos.y);
         for (int x = -radius; x < radius; x++)
         {
             for (int y = -radius; y < radius; y++)
             {
                 int ix = px + x;
                 int iy = py + y;
                 if (ix < 0 || iy < 0 || ix >= width || iy >= height)
                     continue;
                 samples[ix + iy * width] += circle[x + radius + radius * 2 * y];
             }
         }
     }
 
     public Texture2D GetImage(Gradient aGradient)
     {
         Texture2D tex = new Texture2D(width, height,TextureFormat.ARGB32, false);
         float scale = 1f / MaxValue;
         Color[] colors = new Color[samples.Length];
         for (int i = 0; i < colors.Length; i++)
             colors[i] = aGradient.Evaluate(samples[i] * scale);
         tex.SetPixels(colors);
         tex.Apply();
         return tex;
     }
 }

I haven't tested the class but it mainly should show what i ment. So you create a new Heatmap with your desired width and height (which directly referes to the resulting image), and the size of the "circle" area that is added to the map for each point.

You can put your data into the heatmap with the "AddPoint" method where the point has to be already in pixel coordinates.

You can, at any time, create a texture out of the heatmap data by using "GetImage". GetImage takes a Gradient as parameter. That Gradient specifies which areas will be black / transparent and which are white. Keep in mind that "0" represents nothing/ transparent (first color in the gradient) while "1" means the last color in the gradient.

AddPoint shouldn't be too slow, however

Comment
Add comment · Show 7 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Onsterion · Oct 08, 2015 at 12:16 AM 0
Share

I use a UI canvas and a Raw Image for add the Texture and add pixels to texture.

I store pixels and draw circles in pixels:

 float pX = pixelPoint.x;
         float pY = pixelPoint.y;
 
         var r = 8;
         for (var y = -r; y <= r; y++)
         {
            for (var x = -r; x <= r; x++)
             {
                 if ((x * x) + (y * y) <= (r * r))
                 {
                     Color32 pixelColorA = DetectClosedPoint(new Vector2(pX + x, pY + y));
                     pointsList.Add(new Heat$$anonymous$$apPoint(new Vector2(pX + x, pY + y), pixelColorA));
                 }
                     
             }  
         }


But If i need a good circle i need r = 256 and the performance is really bad.

avatar image Bunny83 Onsterion · Oct 08, 2015 at 03:30 AM 0
Share

What's "Heat$$anonymous$$apPoint"? a class or a struct? I made a simple class that does what i've described in my second point. I'll edit my answer above.

avatar image Onsterion Bunny83 · Oct 08, 2015 at 12:42 PM 0
Share

It's a class.

Show more comments
Show more comments
avatar image Bunny83 · Oct 08, 2015 at 01:43 PM 1
Share

Never use SetPixel. It's horrible slow. Use a Color array and use SetPixels at the end.

avatar image Onsterion Bunny83 · Oct 08, 2015 at 08:52 PM 0
Share

Thanks i intend to use SetPixels :D

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Welcome to Unity Answers

The best place to ask and answer questions about development with Unity.

To help users navigate the site we have posted a site navigation guide.

If you are a new user to Unity Answers, check out our FAQ for more information.

Make sure to check out our Knowledge Base for commonly asked Unity questions.

If you are a moderator, see our Moderator Guidelines page.

We are making improvements to UA, see the list of changes.



Follow this Question

Answers Answers and Comments

4 People are following this question.

avatar image avatar image avatar image avatar image

Related Questions

Multiple Cars not working 1 Answer

Distribute terrain in zones 3 Answers

How do I make a 2D cars face the direction it is moving like drifting,How do I make a 2D object face the direction it is moving like drifting 0 Answers

Can't call derived class function from list of base class. Ideas? 1 Answer

Why am I receiving AnalyticsResult.TooManyRequests for any analytics custom event? 1 Answer

  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges