2023-06-28 21:28:00 +08:00
|
|
|
|
#include<hgl/type/StringList.h>
|
2023-06-27 20:45:28 +08:00
|
|
|
|
#include<hgl/type/LoadStringList.h>
|
2023-06-28 18:40:06 +08:00
|
|
|
|
#include<hgl/type/Gradient.h>
|
2023-06-27 20:45:28 +08:00
|
|
|
|
#include<hgl/math/Vector.h>
|
|
|
|
|
#include<hgl/util/imgfmt/tga.h>
|
|
|
|
|
#include<hgl/io/FileOutputStream.h>
|
|
|
|
|
#include<iostream>
|
2023-06-28 18:40:06 +08:00
|
|
|
|
#include"BitmapFont.h"
|
2023-06-27 20:45:28 +08:00
|
|
|
|
|
|
|
|
|
using namespace hgl;
|
|
|
|
|
|
2023-06-28 18:40:06 +08:00
|
|
|
|
uint CHAR_BITMAP_WIDTH=0;
|
|
|
|
|
uint CHAR_BITMAP_HEIGHT=0;
|
2023-06-27 21:43:03 +08:00
|
|
|
|
|
2023-06-28 18:40:06 +08:00
|
|
|
|
bool InitBitmapFont()
|
2023-06-27 21:43:03 +08:00
|
|
|
|
{
|
2023-06-28 18:40:06 +08:00
|
|
|
|
if(!LoadBitmapFont())
|
|
|
|
|
return(false);
|
|
|
|
|
|
|
|
|
|
CHAR_BITMAP_WIDTH=GetCharWidth();
|
|
|
|
|
CHAR_BITMAP_HEIGHT=GetCharHeight();
|
|
|
|
|
|
|
|
|
|
return(true);
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-28 21:28:00 +08:00
|
|
|
|
constexpr const float LOW_GAP=0.2f;
|
2023-06-28 18:40:06 +08:00
|
|
|
|
constexpr const Vector3u8 white_color={255,255,255};
|
|
|
|
|
|
2023-06-28 21:28:00 +08:00
|
|
|
|
constexpr const Vector3u8 stop_color[]=
|
2023-06-28 18:40:06 +08:00
|
|
|
|
{
|
|
|
|
|
{255,0,0},
|
|
|
|
|
{255,255,0},
|
|
|
|
|
{0,255,0},
|
|
|
|
|
{0,255,255},
|
2023-06-28 21:28:00 +08:00
|
|
|
|
{0,0,255}
|
2023-06-27 21:43:03 +08:00
|
|
|
|
};
|
|
|
|
|
|
2023-06-28 21:28:00 +08:00
|
|
|
|
constexpr const uint STOP_COUNT=sizeof(stop_color)/sizeof(Vector3u8);
|
|
|
|
|
|
2023-06-28 18:40:06 +08:00
|
|
|
|
HGL_GRADIENT_DEFINE(GradientColor3u8,uint,Vector3u8)
|
|
|
|
|
{
|
|
|
|
|
result.r=start.r+float(end.r-start.r)*pos;
|
|
|
|
|
result.g=start.g+float(end.g-start.g)*pos;
|
|
|
|
|
result.b=start.b+float(end.b-start.b)*pos;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GradientColor3u8 ColorGradient;
|
|
|
|
|
|
|
|
|
|
void InitGradient(uint max_count)
|
|
|
|
|
{
|
|
|
|
|
for(uint i=0;i<STOP_COUNT;i++)
|
|
|
|
|
ColorGradient.Add(max_count*(1.0-float(i)/float(STOP_COUNT-1)),stop_color[i]);
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-27 20:45:28 +08:00
|
|
|
|
bool ParseLine(Vector2i *result,const UTF8String &str)
|
|
|
|
|
{
|
|
|
|
|
if(!result)return(false);
|
|
|
|
|
|
|
|
|
|
if(str.Length()<=0)return(false);
|
|
|
|
|
|
|
|
|
|
const char *sp=str.c_str();
|
|
|
|
|
const char *cp;
|
|
|
|
|
|
|
|
|
|
if(*sp!='X')return(false);
|
|
|
|
|
|
|
|
|
|
sp+=2;
|
|
|
|
|
cp=hgl::strchr(sp,'Y');
|
|
|
|
|
|
|
|
|
|
if(!cp)return(false);
|
|
|
|
|
|
|
|
|
|
if(!hgl::stoi(sp,result->x))
|
|
|
|
|
return(false);
|
|
|
|
|
|
|
|
|
|
sp=cp+2;
|
|
|
|
|
|
|
|
|
|
cp=hgl::strchr(sp,'Z');
|
|
|
|
|
|
|
|
|
|
if(!cp)return(false);
|
|
|
|
|
|
|
|
|
|
if(!hgl::stoi(sp,result->y))
|
|
|
|
|
return(false);
|
|
|
|
|
|
|
|
|
|
return(true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct PositionStat
|
|
|
|
|
{
|
|
|
|
|
uint count;
|
|
|
|
|
|
|
|
|
|
Vector2i minp,maxp;
|
|
|
|
|
Vector2i gap;
|
|
|
|
|
|
|
|
|
|
Vector2i *data;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
|
|
PositionStat(const uint c)
|
|
|
|
|
{
|
|
|
|
|
count=c;
|
|
|
|
|
|
|
|
|
|
hgl_zero(minp);
|
|
|
|
|
hgl_zero(maxp);
|
|
|
|
|
hgl_zero(gap);
|
|
|
|
|
|
|
|
|
|
data=new Vector2i[count];
|
|
|
|
|
|
|
|
|
|
hgl_zero(data,count);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
~PositionStat()
|
|
|
|
|
{
|
|
|
|
|
delete[] data;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
PositionStat *ToVector2i(const UTF8StringList &sl)
|
|
|
|
|
{
|
|
|
|
|
const uint count=sl.GetCount();
|
|
|
|
|
|
|
|
|
|
PositionStat *ps=new PositionStat(count);
|
|
|
|
|
|
|
|
|
|
Vector2i *p=ps->data;
|
|
|
|
|
|
|
|
|
|
UTF8String str;
|
|
|
|
|
uint result=0;
|
|
|
|
|
|
|
|
|
|
for(int i=0;i<count;i++)
|
|
|
|
|
{
|
|
|
|
|
str=sl[i];
|
|
|
|
|
|
|
|
|
|
if(str.Length()<=0)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if(!ParseLine(p,str))
|
|
|
|
|
continue;
|
|
|
|
|
|
2023-06-28 21:28:00 +08:00
|
|
|
|
(*p)/=100; //Unreal单位为cm,把单位缩到米
|
|
|
|
|
(*p)/=4;
|
2023-06-27 20:45:28 +08:00
|
|
|
|
|
2023-06-28 21:28:00 +08:00
|
|
|
|
if(p->x>=1024
|
|
|
|
|
||p->y>=1024)
|
2023-06-27 20:45:28 +08:00
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
//std::cout<<"X="<<p->x<<",Y="<<p->y<<std::endl;
|
|
|
|
|
|
|
|
|
|
// if(p->x<ps->minp.x)ps->minp.x=p->x;
|
2023-06-27 21:43:03 +08:00
|
|
|
|
// if(p->x>ps->maxp.x)ps->maxp.x=p->x;
|
2023-06-27 20:45:28 +08:00
|
|
|
|
// if(p->y<ps->minp.y)ps->minp.y=p->y;
|
2023-06-27 21:43:03 +08:00
|
|
|
|
// if(p->y>ps->maxp.y)ps->maxp.y=p->y;
|
2023-06-27 20:45:28 +08:00
|
|
|
|
|
|
|
|
|
++result;
|
|
|
|
|
++p;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//std::cout<<"minp: "<<ps->minp.x<<","<<ps->minp.y<<std::endl;
|
2023-06-27 21:43:03 +08:00
|
|
|
|
//std::cout<<"maxp: "<<ps->maxp.x<<","<<ps->maxp.y<<std::endl;
|
|
|
|
|
|
|
|
|
|
ps->maxp.x=1023;
|
|
|
|
|
ps->maxp.y=1023;
|
2023-06-27 20:45:28 +08:00
|
|
|
|
|
|
|
|
|
ps->count=result;
|
|
|
|
|
|
|
|
|
|
return ps;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct Chart
|
|
|
|
|
{
|
|
|
|
|
uint width,height;
|
|
|
|
|
|
|
|
|
|
uint max_count;
|
|
|
|
|
|
|
|
|
|
uint32 *count_data;
|
|
|
|
|
uint32 *circle_data;
|
|
|
|
|
uint8 *chart_data;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
|
|
Chart(const uint w,const uint h)
|
|
|
|
|
{
|
|
|
|
|
width=w;
|
|
|
|
|
height=h;
|
|
|
|
|
|
|
|
|
|
count_data=new uint32[width*height];
|
|
|
|
|
circle_data=new uint32[width*height];
|
|
|
|
|
chart_data=new uint8[width*height*4];
|
|
|
|
|
|
|
|
|
|
hgl_zero(count_data,width*height);
|
|
|
|
|
hgl_zero(circle_data,width*height);
|
|
|
|
|
hgl_zero(chart_data,width*height*4);
|
|
|
|
|
|
|
|
|
|
max_count=0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
~Chart()
|
|
|
|
|
{
|
|
|
|
|
delete[] count_data;
|
|
|
|
|
delete[] circle_data;
|
|
|
|
|
delete[] chart_data;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-28 18:40:06 +08:00
|
|
|
|
void DrawCircle(uint x,uint y,uint radius)
|
2023-06-27 20:45:28 +08:00
|
|
|
|
{
|
|
|
|
|
uint r2=radius*radius;
|
|
|
|
|
uint length;
|
|
|
|
|
|
|
|
|
|
for(int col=x-radius;col<=x+radius;col++)
|
|
|
|
|
{
|
|
|
|
|
if(col<0||col>=width)continue;
|
|
|
|
|
|
|
|
|
|
for(int row=y-radius;row<=y+radius;row++)
|
|
|
|
|
{
|
|
|
|
|
if(row<0||row>=height)continue;
|
|
|
|
|
|
|
|
|
|
length=(col-x)*(col-x)+(row-y)*(row-y);
|
|
|
|
|
|
|
|
|
|
if(length<=r2)
|
2023-06-28 18:40:06 +08:00
|
|
|
|
{
|
2023-06-27 20:45:28 +08:00
|
|
|
|
++circle_data[col+row*width];
|
2023-06-28 18:40:06 +08:00
|
|
|
|
}
|
2023-06-27 20:45:28 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-06-27 21:43:03 +08:00
|
|
|
|
|
2023-06-28 18:40:06 +08:00
|
|
|
|
void DrawBar(const uint x,const uint y,const uint size,const Vector3u8 &stop_color,const uint8 alpha)
|
2023-06-27 21:43:03 +08:00
|
|
|
|
{
|
|
|
|
|
uint8 *tp=chart_data+(x+y*width)*4;
|
|
|
|
|
uint line_bytes=(width-size)*4;
|
|
|
|
|
|
|
|
|
|
for(uint row=0;row<size;row++)
|
|
|
|
|
{
|
|
|
|
|
for(uint col=0;col<size;col++)
|
|
|
|
|
{
|
2023-06-28 18:40:06 +08:00
|
|
|
|
tp[0]=stop_color.b;
|
|
|
|
|
tp[1]=stop_color.g;
|
|
|
|
|
tp[2]=stop_color.r;
|
2023-06-27 21:43:03 +08:00
|
|
|
|
tp[3]=alpha;
|
|
|
|
|
|
|
|
|
|
tp+=4;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tp+=line_bytes;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-28 18:40:06 +08:00
|
|
|
|
void DrawChar(const char ch,const uint x,const uint y,const Vector3u8 &stop_color,const uint8 alpha)
|
2023-06-27 21:43:03 +08:00
|
|
|
|
{
|
2023-06-28 18:40:06 +08:00
|
|
|
|
const uint8 *sp=GetBitmapChar(ch);
|
|
|
|
|
uint8 bit;
|
2023-06-28 21:28:00 +08:00
|
|
|
|
uint8 *tp=chart_data+(x+y*width)*4;
|
|
|
|
|
|
|
|
|
|
uint line_wrap_bytes=(width-CHAR_BITMAP_WIDTH)*4;
|
2023-06-27 21:43:03 +08:00
|
|
|
|
|
|
|
|
|
for(uint row=0;row<CHAR_BITMAP_HEIGHT;row++)
|
|
|
|
|
{
|
2023-06-28 18:40:06 +08:00
|
|
|
|
bit=1<<7;
|
|
|
|
|
|
2023-06-27 21:43:03 +08:00
|
|
|
|
for(uint col=0;col<CHAR_BITMAP_WIDTH;col++)
|
|
|
|
|
{
|
2023-06-28 21:28:00 +08:00
|
|
|
|
if(*sp&bit)
|
|
|
|
|
{
|
|
|
|
|
tp[0]=stop_color.b;
|
|
|
|
|
tp[1]=stop_color.g;
|
|
|
|
|
tp[2]=stop_color.r;
|
|
|
|
|
tp[3]=alpha;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tp+=4;
|
2023-06-27 21:43:03 +08:00
|
|
|
|
|
2023-06-28 18:40:06 +08:00
|
|
|
|
bit>>=1;
|
2023-06-27 21:43:03 +08:00
|
|
|
|
}
|
2023-06-28 18:40:06 +08:00
|
|
|
|
|
2023-06-28 21:28:00 +08:00
|
|
|
|
tp+=line_wrap_bytes;
|
2023-06-28 18:40:06 +08:00
|
|
|
|
++sp;
|
2023-06-27 21:43:03 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-28 18:40:06 +08:00
|
|
|
|
void DrawString(const AnsiString &str,const uint x,const uint y,const Vector3u8 &stop_color,const uint8 alpha)
|
2023-06-27 21:43:03 +08:00
|
|
|
|
{
|
|
|
|
|
const char *sp=str.c_str();
|
|
|
|
|
const uint len=str.Length();
|
|
|
|
|
|
|
|
|
|
uint pos=x;
|
|
|
|
|
|
|
|
|
|
for(uint i=0;i<len;i++)
|
|
|
|
|
{
|
2023-06-28 18:40:06 +08:00
|
|
|
|
if(*sp!=' ')
|
|
|
|
|
DrawChar(*sp,pos,y,stop_color,alpha);
|
2023-06-27 21:43:03 +08:00
|
|
|
|
|
2023-06-28 21:28:00 +08:00
|
|
|
|
pos+=CHAR_BITMAP_WIDTH;
|
2023-06-27 21:43:03 +08:00
|
|
|
|
++sp;
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-06-28 18:40:06 +08:00
|
|
|
|
|
|
|
|
|
void DrawGradient(const uint left,const uint top,const uint w,const uint h)
|
|
|
|
|
{
|
|
|
|
|
uint8 *tp=chart_data+(left+top*width)*4;
|
|
|
|
|
Vector3u8 color;
|
|
|
|
|
|
|
|
|
|
uint low,high,gap;
|
|
|
|
|
|
|
|
|
|
ColorGradient.GetLowest(low);
|
|
|
|
|
ColorGradient.GetHighest(high);
|
|
|
|
|
|
|
|
|
|
gap=high-low;
|
|
|
|
|
|
|
|
|
|
for(uint i=0;i<h;i++)
|
|
|
|
|
{
|
2023-06-28 20:51:08 +08:00
|
|
|
|
ColorGradient.Get(color,(1.0f-float(i)/float(h))*float(gap)+float(low));
|
2023-06-28 18:40:06 +08:00
|
|
|
|
|
|
|
|
|
for(uint j=0;j<w;j++)
|
|
|
|
|
{
|
|
|
|
|
tp[0]=color.b;
|
|
|
|
|
tp[1]=color.g;
|
|
|
|
|
tp[2]=color.r;
|
|
|
|
|
tp[3]=255;
|
|
|
|
|
|
|
|
|
|
tp+=4;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tp+=(width-w)*4;
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-06-27 20:45:28 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Chart *ToChart32(const PositionStat *ps)
|
|
|
|
|
{
|
|
|
|
|
uint width=ps->maxp.x-ps->minp.x+1;
|
|
|
|
|
uint height=ps->maxp.y-ps->minp.y+1;
|
|
|
|
|
|
|
|
|
|
std::cout<<"width: "<<width<<",height: "<<height<<std::endl;
|
|
|
|
|
|
|
|
|
|
Chart *chart=new Chart(width,height);
|
2023-06-28 18:40:06 +08:00
|
|
|
|
uint max_count=0;
|
2023-06-28 21:28:00 +08:00
|
|
|
|
uint step_count[STOP_COUNT];
|
2023-06-27 20:45:28 +08:00
|
|
|
|
|
2023-06-28 21:28:00 +08:00
|
|
|
|
//统计每个格子数据数量
|
2023-06-27 20:45:28 +08:00
|
|
|
|
{
|
|
|
|
|
uint x,y;
|
|
|
|
|
uint32 *cp32=chart->count_data;
|
|
|
|
|
|
|
|
|
|
const Vector2i *p=ps->data;
|
|
|
|
|
|
|
|
|
|
for(uint i=0;i<ps->count;i++)
|
|
|
|
|
{
|
|
|
|
|
x=p->x-ps->minp.x;
|
|
|
|
|
y=p->y-ps->minp.y;
|
|
|
|
|
|
|
|
|
|
cp32=chart->count_data+(x+y*width);
|
|
|
|
|
|
2023-06-28 18:40:06 +08:00
|
|
|
|
++(*cp32);
|
|
|
|
|
|
|
|
|
|
if(*cp32>max_count)max_count=*cp32;
|
2023-06-27 20:45:28 +08:00
|
|
|
|
|
|
|
|
|
++p;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-28 21:28:00 +08:00
|
|
|
|
//统计占比
|
2023-06-28 18:40:06 +08:00
|
|
|
|
{
|
|
|
|
|
uint32 *cp32=chart->count_data;
|
|
|
|
|
|
|
|
|
|
hgl_zero(step_count);
|
|
|
|
|
|
|
|
|
|
for(uint y=0;y<height;y++)
|
|
|
|
|
{
|
|
|
|
|
for(uint x=0;x<width;x++)
|
|
|
|
|
{
|
|
|
|
|
if(*cp32>0)
|
|
|
|
|
for(uint i=0;i<STOP_COUNT;i++)
|
|
|
|
|
if(*cp32>max_count*(STOP_COUNT-1-i)/STOP_COUNT)
|
|
|
|
|
{
|
|
|
|
|
step_count[i]+=*cp32;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
++cp32;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-28 21:28:00 +08:00
|
|
|
|
//画圆
|
2023-06-27 20:45:28 +08:00
|
|
|
|
{
|
|
|
|
|
uint32 *cp32=chart->count_data;
|
|
|
|
|
|
|
|
|
|
for(uint y=0;y<height;y++)
|
|
|
|
|
{
|
|
|
|
|
for(uint x=0;x<width;x++)
|
|
|
|
|
{
|
|
|
|
|
if(*cp32>0)
|
2023-06-28 20:51:08 +08:00
|
|
|
|
chart->DrawCircle(x,y,(*cp32));
|
2023-06-27 20:45:28 +08:00
|
|
|
|
|
|
|
|
|
++cp32;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-28 21:28:00 +08:00
|
|
|
|
//统计最大值
|
2023-06-27 20:45:28 +08:00
|
|
|
|
{
|
|
|
|
|
uint32 *cp32=chart->circle_data;
|
|
|
|
|
|
|
|
|
|
for(uint i=0;i<width*height;i++)
|
|
|
|
|
{
|
|
|
|
|
if(*cp32>chart->max_count)chart->max_count=*cp32;
|
|
|
|
|
|
|
|
|
|
++cp32;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-27 21:43:03 +08:00
|
|
|
|
std::cout<<"max_count: "<<chart->max_count<<std::endl;
|
2023-06-27 20:45:28 +08:00
|
|
|
|
}
|
|
|
|
|
|
2023-06-28 18:40:06 +08:00
|
|
|
|
InitGradient(chart->max_count);
|
|
|
|
|
|
2023-06-28 21:28:00 +08:00
|
|
|
|
//生成权重图
|
2023-06-27 20:45:28 +08:00
|
|
|
|
{
|
|
|
|
|
uint32 *cp32=chart->circle_data;
|
|
|
|
|
uint8 *cp8=chart->chart_data;
|
|
|
|
|
|
2023-06-28 18:40:06 +08:00
|
|
|
|
float alpha;
|
|
|
|
|
Vector3u8 final_color;
|
2023-06-27 20:45:28 +08:00
|
|
|
|
|
|
|
|
|
for(uint i=0;i<width*height;i++)
|
|
|
|
|
{
|
2023-06-28 18:40:06 +08:00
|
|
|
|
alpha=float(*cp32)/float(chart->max_count);
|
2023-06-27 20:45:28 +08:00
|
|
|
|
|
2023-06-28 18:40:06 +08:00
|
|
|
|
ColorGradient.Get(final_color,*cp32);
|
|
|
|
|
|
2023-06-28 21:28:00 +08:00
|
|
|
|
if(*cp32>0) //为了避免最后什么都看不见,所以把没数据的挑出来,剩下的透明度全部加0.25
|
2023-06-27 20:45:28 +08:00
|
|
|
|
{
|
2023-06-28 21:28:00 +08:00
|
|
|
|
alpha+=LOW_GAP;
|
2023-06-28 18:40:06 +08:00
|
|
|
|
|
|
|
|
|
if(alpha>1)
|
|
|
|
|
alpha=1;
|
2023-06-27 20:45:28 +08:00
|
|
|
|
}
|
|
|
|
|
|
2023-06-28 18:40:06 +08:00
|
|
|
|
cp8[0]=final_color.b;
|
|
|
|
|
cp8[1]=final_color.g;
|
|
|
|
|
cp8[2]=final_color.r;
|
|
|
|
|
cp8[3]=alpha*255.0f;
|
2023-06-27 20:45:28 +08:00
|
|
|
|
|
|
|
|
|
++cp32;
|
|
|
|
|
cp8+=4;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-28 21:28:00 +08:00
|
|
|
|
if(CHAR_BITMAP_HEIGHT==0)
|
2023-06-28 18:40:06 +08:00
|
|
|
|
return chart;
|
|
|
|
|
|
2023-06-28 21:28:00 +08:00
|
|
|
|
//写入数值
|
2023-06-27 21:43:03 +08:00
|
|
|
|
{
|
2023-06-28 18:40:06 +08:00
|
|
|
|
uint col=10;
|
|
|
|
|
uint row=10;
|
2023-06-28 20:51:08 +08:00
|
|
|
|
uint stop_str_width=0;
|
2023-06-28 18:40:06 +08:00
|
|
|
|
|
|
|
|
|
AnsiString str;
|
|
|
|
|
AnsiString num_str;
|
|
|
|
|
const AnsiString str_total=AnsiString::numberOf(ps->count);
|
|
|
|
|
|
2023-06-28 21:28:00 +08:00
|
|
|
|
AnsiString step_str[STOP_COUNT];
|
|
|
|
|
const uint dradient_bar_height=CHAR_BITMAP_HEIGHT*STOP_COUNT;
|
2023-06-27 21:43:03 +08:00
|
|
|
|
|
2023-06-28 18:40:06 +08:00
|
|
|
|
char space[32];
|
2023-06-27 21:43:03 +08:00
|
|
|
|
|
2023-06-28 18:40:06 +08:00
|
|
|
|
memset(space,' ',32);
|
2023-06-28 20:51:08 +08:00
|
|
|
|
|
|
|
|
|
for(uint i=0;i<STOP_COUNT;i++)
|
2023-06-28 21:28:00 +08:00
|
|
|
|
{
|
|
|
|
|
step_str[i]=AnsiString::numberOf(uint(max_count*(1.0-float(i)/float(STOP_COUNT))));
|
|
|
|
|
|
2023-06-28 20:51:08 +08:00
|
|
|
|
if(stop_str_width<step_str[i].Length())
|
|
|
|
|
stop_str_width=step_str[i].Length();
|
2023-06-28 21:28:00 +08:00
|
|
|
|
}
|
2023-06-28 18:40:06 +08:00
|
|
|
|
|
|
|
|
|
str=AnsiString("TOTAL - ")+str_total;
|
|
|
|
|
|
|
|
|
|
chart->DrawString(str,col,row,white_color,255);
|
2023-06-28 21:28:00 +08:00
|
|
|
|
row+=CHAR_BITMAP_HEIGHT;
|
2023-06-28 18:40:06 +08:00
|
|
|
|
|
2023-06-28 21:28:00 +08:00
|
|
|
|
chart->DrawGradient(col,row,CHAR_BITMAP_WIDTH,dradient_bar_height);
|
2023-06-28 18:40:06 +08:00
|
|
|
|
|
2023-06-28 21:28:00 +08:00
|
|
|
|
col+=CHAR_BITMAP_WIDTH*2;
|
2023-06-28 18:40:06 +08:00
|
|
|
|
|
2023-06-28 21:28:00 +08:00
|
|
|
|
chart->DrawGradient(col+(stop_str_width+1)*CHAR_BITMAP_WIDTH,
|
|
|
|
|
row,CHAR_BITMAP_WIDTH,dradient_bar_height);
|
2023-06-28 20:51:08 +08:00
|
|
|
|
|
2023-06-28 21:28:00 +08:00
|
|
|
|
chart->DrawGradient(col+(str_total.Length()+stop_str_width+4)*CHAR_BITMAP_WIDTH,
|
|
|
|
|
row,CHAR_BITMAP_WIDTH,dradient_bar_height);
|
2023-06-28 20:51:08 +08:00
|
|
|
|
|
2023-06-28 18:40:06 +08:00
|
|
|
|
for(uint i=0;i<STOP_COUNT;i++)
|
|
|
|
|
{
|
2023-06-28 20:51:08 +08:00
|
|
|
|
str.Strcpy(space,stop_str_width-step_str[i].Length());
|
2023-06-28 18:40:06 +08:00
|
|
|
|
|
2023-06-28 20:51:08 +08:00
|
|
|
|
str+=step_str[i];
|
2023-06-28 18:40:06 +08:00
|
|
|
|
|
2023-06-28 20:51:08 +08:00
|
|
|
|
num_str=AnsiString::numberOf(step_count[i]);
|
2023-06-28 18:40:06 +08:00
|
|
|
|
|
2023-06-28 20:51:08 +08:00
|
|
|
|
str.Strcat(space,str_total.Length()-num_str.Length()+3);
|
2023-06-28 18:40:06 +08:00
|
|
|
|
|
2023-06-28 20:51:08 +08:00
|
|
|
|
str+=num_str;
|
|
|
|
|
|
|
|
|
|
if(step_count[i]>0)
|
|
|
|
|
{
|
|
|
|
|
str+=" ";
|
|
|
|
|
str+=AnsiString::numberOf(float(step_count[i])*100.0f/float(ps->count));
|
|
|
|
|
str+="%";
|
2023-06-28 18:40:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
chart->DrawString(str,col,row,stop_color[i],255);
|
2023-06-28 21:28:00 +08:00
|
|
|
|
row+=CHAR_BITMAP_HEIGHT;
|
2023-06-28 18:40:06 +08:00
|
|
|
|
}
|
2023-06-27 21:43:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
2023-06-27 20:45:28 +08:00
|
|
|
|
return chart;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int os_main(int argc,os_char **argv)
|
|
|
|
|
{
|
|
|
|
|
std::cout<<"Distribution Chart 2D"<<std::endl<<std::endl;
|
|
|
|
|
|
|
|
|
|
if(argc<2)
|
|
|
|
|
{
|
|
|
|
|
std::cout<<"example: DistributionChart2D data.csv"<<std::endl<<std::endl;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UTF8StringList sl;
|
|
|
|
|
|
|
|
|
|
int line_count=LoadStringListFromTextFile(sl,argv[1]);
|
|
|
|
|
|
|
|
|
|
if(line_count<=1)
|
|
|
|
|
{
|
|
|
|
|
std::cout<<"Load file "<<argv[1]<<" failed!"<<std::endl;
|
|
|
|
|
return(-1);
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-28 18:40:06 +08:00
|
|
|
|
bool font=InitBitmapFont();
|
|
|
|
|
|
2023-06-27 20:45:28 +08:00
|
|
|
|
std::cout<<"file total line: "<<line_count<<std::endl;
|
|
|
|
|
|
|
|
|
|
AutoDelete<PositionStat> ps=ToVector2i(sl);
|
|
|
|
|
|
|
|
|
|
AutoDelete<Chart> chart=ToChart32(ps);
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
util::TGAHeader tga_header;
|
|
|
|
|
|
|
|
|
|
util::FillTGAHeader(&tga_header,chart->width,chart->height,4);
|
|
|
|
|
|
|
|
|
|
io::OpenFileOutputStream fos(OS_TEXT("chart.tga"),io::FileOpenMode::CreateTrunc);
|
|
|
|
|
|
2023-06-28 18:40:06 +08:00
|
|
|
|
if(fos)
|
2023-06-27 20:45:28 +08:00
|
|
|
|
{
|
2023-06-28 18:40:06 +08:00
|
|
|
|
fos->Write(&tga_header,util::TGAHeaderSize);
|
|
|
|
|
fos->Write(chart->chart_data,chart->width*chart->height*4);
|
|
|
|
|
fos->Close();
|
2023-06-27 20:45:28 +08:00
|
|
|
|
}
|
2023-06-28 18:40:06 +08:00
|
|
|
|
else
|
|
|
|
|
std::cerr<<"Create chart.tga failed!"<<std::endl;
|
2023-06-27 20:45:28 +08:00
|
|
|
|
}
|
|
|
|
|
|
2023-06-28 18:40:06 +08:00
|
|
|
|
if(font)
|
|
|
|
|
ClearBitmapFont();
|
|
|
|
|
|
2023-06-27 20:45:28 +08:00
|
|
|
|
return 0;
|
2023-06-28 21:28:00 +08:00
|
|
|
|
}
|