绘图数据是一个一维的图形数组:
在Render中
onSurfaceCreated方法:
// 黑色背景
gl.glClearColor(0, 0, 0, 0);
// 设置深度缓存
gl.glClearDepthf(1.0f);
// 启用深度测试
gl.glEnable(GL10.GL_DEPTH_TEST);
// 所作深度测试的类型
gl.glDepthFunc(GL10.GL_LEQUAL);
// 设置点大小
gl.glPointSize(1.5f);
// 设置所画的点为圆点
gl.glEnable(GL10.GL_POINT_SMOOTH);
onSurfaceChanged方法:
//设置可显示区域
gl.glViewport(0, 0, width, height);
//设备正投影
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glMatrixMode(GL10.GL_MODELVIEW);
//初始化数据宽高与View的宽高
this.mWidth = 50 * 5;
this.mHeight = 60 * 5;
this.mViewWidth = width;
this.mViewHeight = height;
//重设投影模型
gl.glLoadIdentity();
// 校准显示内容区域
gl.glTranslatef(-0.15f, 0.15f, 0f);
gl.glRotatef(-90f, 0, 0, 1);
gl.glScalef(0.8f, 0.8f, 1f);
//初始化数据缓冲区
ByteBuffer colorTmp = ByteBuffer.allocateDirect(mHeight * mWidth * 4 * 4);
colorTmp.order(ByteOrder.nativeOrder());
colorBuff = colorTmp.asFloatBuffer();
ByteBuffer quateTmp = ByteBuffer.allocateDirect(mHeight * mWidth * 2 * 4);
quateTmp.order(ByteOrder.nativeOrder());
vertexBuff = quateTmp.asFloatBuffer();
double[][] intensity = new double[mWidth + 2 * mRadius][mHeight + 2 * mRadius];
int n; //数组索引位置
double value; //数据的值
mMaxIntensity = 0;
for (int i = 0; i < 50; i++) {
for (int j = 0; j < 60; j++) {
n = i * 60 + j;
value = data[n];
if (value > 0) {
//根据原有的数组,填充到一个更大的数组
int bucketX = (int) (clamp((float) i / 50 , 0.0f, mWidth));
int bucketY = (int) (clamp((float) j / 60, 0.0f, mHeight));
if (bucketX < mWidth && bucketX >= 0
&& bucketY < mHeight && bucketY >= 0) {
intensity[bucketX][bucketY] = value;
}
//获取数据中的最大值
if (value > mMaxIntensity) {
mMaxIntensity = value;
}
}
}
}
private double[] mKernel = generateKernel(mRadius, mRadius / 3.0);
static private double[] generateKernel(int radius, double sd) {
double[] kernel = new double[radius * 2 + 1];
for (int i = -radius; i <= radius; i++) {
kernel[i + radius] = (Math.exp(-i * i / (2 * sd * sd)));
}
return kernel;
}
double[][] convolved = convolve(intensity, mKernel);
static private double[][] convolve(double[][] grid, double[] kernel) {
int radius = mRadius;
int dimOldW = grid.length;
int dimOldH = grid[0].length;
int dimW = dimOldW - 2 * radius;
int dimH = dimOldH - 2 * radius;
int lowerLimit = radius;
int upperLimitW = radius + dimW - 1;
int upperLimitH = radius + dimH - 1;
double[][] intermediate = new double[dimOldW][dimOldH];
int x, y, x2, xUpperLimit, initial;
double val;
for (x = 0; x < dimOldW; x++) {
for (y = 0; y < dimOldH; y++) {
val = grid[x][y];
if (val != 0) {
xUpperLimit = ((upperLimitW < x + radius) ? upperLimitW : x + radius) + 1;
initial = (lowerLimit > x - radius) ? lowerLimit : x - radius;
for (x2 = initial; x2 < xUpperLimit; x2++) {
intermediate[x2][y] += val * kernel[x2 - (x - radius)];
}
}
}
}
double[][] outputGrid = new double[dimW][dimH];
int y2, yUpperLimit;
for (x = lowerLimit; x < upperLimitW + 1; x++) {
for (y = 0; y < dimOldH; y++) {
val = intermediate[x][y];
if (val != 0) {
yUpperLimit = ((upperLimitH < y + radius) ? upperLimitH : y + radius) + 1;
initial = (lowerLimit > y - radius) ? lowerLimit : y - radius;
for (y2 = initial; y2 < yUpperLimit; y2++) {
outputGrid[x - radius][y2 - radius] += val * kernel[y2 - (y - radius)];
}
}
}
}
return outputGrid;
}
convolved为处理好的数组
int dimw = d.length;
int dimh = d[0].length;
//根据OpenGL坐标系统,坐标由-1到+1,范围为2,实际坐标需影射到OpenGL坐标系(0:-1, Max:1)
//每个点坐标包含两个浮点数:X、Y
float[] ver = new float[dimw * dimh * 2];
//每个颜色数据包令4个浮点数:R、G、B
float[] colorDBuff = new float[dimw * dimh * 3];
//点颜色的RGB数组
float[] colorArr;
//每点的宽高
float z = (float) mViewWidth / (float) dimw;
float Ysplit = (2f / (float) mViewHeight) * z;
float Xsplit = (2f / (float) mViewWidth) * z;
int k = 0;//点坐标的序号
int c = 0;//点颜色的序号
int i, j;
double val;
indexNum = 0;
for (i = 0; i < dimw; i++) {
for (j = 0; j < dimh; j++) {
val = d[i][j];
if (val != 0) {
colorArr = getColor((float) (val / mMaxIntensity));
//point and color
ver[k++] = -1f + i * Ysplit;
ver[k++] = -1f + j * Xsplit;
colorDBuff[c++] = colorArr[0];
colorDBuff[c++] = colorArr[1];
colorDBuff[c++] = colorArr[2];
indexNum++;
}
}
}
colorBuff.put(colorDBuff);
colorBuff.position(0);
vertexBuff.put(ver);
vertexBuff.position(0); // 需重置数组位置,否则不能顶点数据访问为空,无图形输出
能量色条值获取方法
/**
* 能量色条值获取
* @param value 实际数据值
* @return 对应能量色条颜色数组[r, g, b]
*/
protected float[] getColor(float value) {
int sr1 = 0x00, sg1 = 0x00, sb1 = 0x00;
int sr2 = 0x46, sg2 = 0xb7, sb2 = 0xec;
int sr3 = 0x22, sg3 = 0xfe, sb3 = 0x2c;
int sr4 = 0xff, sg4 = 0xea, sb4 = 0x00;
int sr5 = 0xff, sg5 = 0x4e, sb5 = 0x00;
double r = 0, g = 0, b = 0;
if( value < 0.15 ) {
r = sr1 + (sr2 - sr1) * (value / 0.15);
g = sg1 + (sg2 - sg1) * (value / 0.15);
b = sb1 + (sb2 - sb1) * (value / 0.15);
} else if(value < 0.5){
r = sr2 + (sr3 - sr2) * ((value - 0.15) / 0.35);
g = sg2 + (sg3 - sg2) * ((value - 0.15) / 0.35);
b = sb2 + (sb3 - sb2) * ((value - 0.15) / 0.35);
} else if(value < 0.75){
r = sr3 + (sr4 - sr3) * ((value - 0.5) / 0.25);
g = sg3 + (sg4 - sg3) * ((value - 0.5) / 0.25);
b = sb3 + (sb4 - sb3) * ((value - 0.5) / 0.25);
} else {
r = sr4 + (sr5 - sr4) * ((value - 0.75) / 0.25);
g = sg4 + (sg5 - sg4) * ((value - 0.75) / 0.25);
b = sb4 + (sb5 - sb4) * ((value - 0.75) / 0.25);
}
return new float[]{(float) (r / 0xFF), (float) (g / 0xFF), (float) (b / 0xFF)};
}
onDrawFrame方法:
//启动相关管道
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); // 开启顶点数组画图模式,否则不能使用顶点数组画图
gl.glEnableClientState(GL10.GL_COLOR_ARRAY); // 打开着色数组,启用顶点着色功能
//绘图
gl.glVertexPointer(2, GL10.GL_FLOAT, 0, vertexBuff);
gl.glColorPointer(3, GL10.GL_FLOAT, 0, colorBuff);
gl.glDrawArrays(GL10.GL_POINTS, 0, indexNum);
//关闭相关管道
gl.glDisableClientState(GL10.GL_COLOR_ARRAY);
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);