package com.manager.heatmap;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Point;
import android.support.annotation.NonNull;
import android.util.Log;
import com.manager.db.PersonBean;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class HeatMapX {
private int im_width = 0;
private int im_heigth = 0;
private int radius= 30;
private Bitmap hotspot=null;
// private Dictionary<Integer,Integer> circledat= null;
// private int [][] circletemplate=null;
private Map<Integer, Integer> circletemplate = new HashMap<Integer, Integer>();
private List<WeightedLatLng> heatdata = null;
private int [] htdat = null;
private int [] htdat2 = null;
private int colorsteps = 240;
private float [][] colors = null;
private int [][] mdata = null;
public void build(int im_width, int im_heigth){
this.im_heigth = im_heigth;
this.im_width = im_width;
this.hotspot = Bitmap.createBitmap(this.im_width,this.im_heigth, Bitmap.Config.ARGB_8888);
this.htdat = new int[im_width*im_heigth];
this.htdat2 = new int[im_width*im_heigth];
this.make_colors(240);
this.make_circle(this.radius, this.im_width);
}
public Bitmap getHeatmap(){
return this.hotspot;
}
public void genheatdata(List<PersonBean> mDetailData){
// this.mdata = new int[mDetailData.size()][3];
// 统计密度
Map<String, Integer> locstr = new HashMap<String, Integer>();
for(PersonBean pb : mDetailData) {
float[] bx = pb.getBbox();
int cx = (int) ((bx[0] + bx[2]) / 2f);
int cy = (int) ((bx[1] + bx[3]) / 2f);
String tmp_loc = String.format("%d,%d", cx, cy);
Integer count = locstr.get(tmp_loc);
count = (count == null) ? 1 : count + 1;
locstr.put(tmp_loc, count);
}
// 生成数据
this.mdata = new int[locstr.size()][3];
int i=0;
for(Map.Entry<String,Integer> m: locstr.entrySet()) {
String tmp_loc = m.getKey();
String[] xy = tmp_loc.split(",");
int cx = Integer.valueOf(xy[0]);
int cy = Integer.valueOf(xy[1]);
int count = m.getValue();
mdata[i][0] = cx;
mdata[i][1] = cy;
mdata[i][2] = count;
i++;
}
}
public void heatmap(){
// this.make_circle(this.radius, this.im_width);
for(int i=0;i<this.mdata.length;i++){
int x = this.mdata[i][0];
int y = this.mdata[i][1];
int count = this.mdata[i][2];
if(x<0 || x>= this.im_width || y<=0 || y>=this.im_heigth){
continue;
}
this.doheat(this.htdat2,x,y,count,this.circletemplate);
}
rescaleheatdata(htdat2);
this.paint_heat();
}
public void doheat(int [] hdata, int x, int y, int n, Map<Integer,Integer> template){
int dlen = hdata.length;
int p = this.im_width*y+x;
for (Map.Entry<Integer , Integer> et: template.entrySet() )
{
Integer ip = et.getKey();
Integer iv = et.getValue();
int p2 = p+ ip;
if(p2<dlen && p2>=0){
hdata[p2] += iv*n;
}
}
}
public int getmaxv(int[] heatdata){
int maxv= 0;
for(int i=0;i<heatdata.length;i++){
if(heatdata[i]>maxv){
maxv = heatdata[i];
}
}
return maxv;
}
public void rescaleheatdata(int [] heatdata){
float max_v = getmaxv(heatdata);
for(int i=0;i<heatdata.length;i++){
float r = this.colorsteps/max_v;
htdat[i] = (int)(heatdata[i]*r)-1;
}
}
public void paint_heat(){
int msize = this.im_heigth*im_width;
for(int i=0;i<msize;i++){
int v = htdat[i];
if(v>0){
float [] color = this.colors[v];
int row = i/this.im_width;
int col = i%this.im_width;
float alpha = color[2];
if(alpha>50){
alpha = 255-255f*(alpha-50)/50f;
this.hotspot.setPixel(col, row, Color.argb((int)alpha,0,0,255));
}else{
int [] rgb = HSL2RGBNew(color[0],color[1]/100f,color[2]/100f);
// this.hotspot.setPixel(col, row, Color.argb((int)alpha, rgb[0],rgb[1],rgb[2]));
this.hotspot.setPixel(col, row, Color.rgb( rgb[0],rgb[1],rgb[2]));
}
}
}
Log.i("heatmap", "paint done.");
}
int [] HSL2RGBNew(float H, float S, float L){
int R=0,G=0,B=0 ;
float [] rgb = new float[3];
float q = 0f;
float p=0f;
float hk = 0f;
float tr=0f;
float tg=0f;
float tb = 0f;
if(S>0){
float v_1_3 = 1f/3;
float v_1_6 = 1f/6;
float v_2_3 = 2f/3;
if(L < 0.5 ){
q=L*(1f+S);
}else{
q=L+S-(L*S);
}
p=L*2f-q;
hk = H/360f;
tr = hk+v_1_3;
tg = hk;
tb = hk-v_1_3;
rgb[0] = tr;
rgb[1] = tg;
rgb[2] = tb;
for(int i=0;i<3;i++){
rgb[i] = onec(rgb[i]);
}
for(int i=0;i<3;i++) {
float tc = rgb[i];
if(tc<v_1_6){
rgb[i] = p+(q-p)*6f*tc;
}else if(tc<0.5 && tc>=v_1_6){
rgb[i] = q;
}else if(tc>=0.5 && tc<v_2_3){
rgb[i] = p+((q-p)*6f*(v_2_3-tc));
}else{
rgb[i] = p;
}
}
R = (int)(rgb[0]*255);
G = (int)(rgb[1]*255);
B = (int)(rgb[2]*255);
}else{
R=G=B = (int)(L*255);
}
int[] rgbint = {R,G,B};
return rgbint;
}
float onec(float tc){
float out = 0f;
if(tc<0){
out = tc+1f;
}else if(tc>1){
out = tc-1f;
}else{
out = tc;
}
return out;
}
float [] HSL2RGB(float H,float S,float L)
{
float R,G,B;
float var_1, var_2;
if (S == 0) //HSL values = 0 ÷ 1
{
R = L * 255.0f; //RGB results = 0 ÷ 255
G = L * 255.0f;
B = L * 255.0f;
}
else
{
if (L < 0.5) var_2 = L * (1 + S);
else var_2 = (L + S) - (S * L);
var_1 = 2.0f * L - var_2;
R = 255.0f * Hue2RGB(var_1, var_2, H + (1.0f / 3.0f));
G = 255.0f * Hue2RGB(var_1, var_2, H);
B = 255.0f * Hue2RGB(var_1, var_2, H - (1.0f / 3.0f));
}
float [] color_rgb = {R,G,B};
return color_rgb;
}
//---------------------------------------------------------------------------
float Hue2RGB(float v1, float v2, float vH)
{
if (vH < 0) vH += 1f;
if (vH > 1) vH -= 1f;
if (6.0 * vH < 1) return (float)(v1 + (v2 - v1) * 6.0 * vH);
if (2.0 * vH < 1) return v2;
if (3.0 * vH < 2) return (float)(v1 + (v2 - v1) * ((2.0 / 3.0) - vH) * 6.0f);
return (v1);
}
public void make_colors(int n){
colors = new float [n][3];
int n1 = (int)(n*0.4f);
int n2 = n-n1;
for(int i =0; i<n1;i++){
colors[i][0] = 240;
colors[i][1] = 100;
colors[i][2] = 100*(n1-i/2f)/n1;
}
for(int i =0; i<n2;i++){
colors[n1+i][0] = n*(1-i*1f/n2);
colors[n1+i][1] = 100;
colors[n1+i][2] = 50;
}
}
public void circle8(int ix, int iy,int v, int w){
List<Point> points = new ArrayList<>();
points.add(new Point(ix,iy));
points.add(new Point(-ix,iy));
points.add(new Point(ix,-iy));
points.add(new Point(-ix,-iy));
points.add(new Point(iy,ix));
points.add(new Point(-iy,ix));
points.add(new Point(iy,-ix));
points.add(new Point(-iy,-ix));
for(Point pt : points){
int p = pt.y*w + pt.x;
// circledat.put(p, v);
circletemplate.put(p,v);
}
}
public void make_circle(int radius , int w){
int x = 0;
int y = radius;
int d = 3 - (radius<<1);
while(x<=y){
for(int _y=x;_y<y+1;_y++){
circle8(x,_y, y+1-_y, w);
}
if(d<0){
d += (x<<2)+6;
}else{
d+=((x-y)<<2)+10;
y -= 1;
}
x += 1;
}
}
}
参考: 1.HeatMapForAndroid 2.pyheatmap