从零开始openGL—— 二、 基本图形绘制
前言
这是从零开始openGL系列文章的第二篇,在上篇文章中介绍了基本的环境配置,这篇文章将介绍如何绘制基本图形(圆、三角形、立方体、圆柱、圆锥)。
基本框架
下面这里我先给出opengl的3D绘图的基本框架
#include <windows.h>
#include <string.h>
#include <stdlib.h>
#include <gl\glui.h>
#include <math.h>
#include "common.h" int g_xform_mode = TRANSFORM_NONE;
int g_main_window;
double g_windows_width, g_windows_height; CObj g_obj;
//the lighting
static GLfloat g_light0_ambient[] = {0.0f, 0.0f, 0.0f, 1.0f};//环境光
static GLfloat g_light0_diffuse[] = {1.0f, 1.0f, 1.0f, 1.0f};//散射光
static GLfloat g_light0_specular[] = {1.0f,1.0f,1.0f,1.0f}; //镜面光
static GLfloat g_light0_position[] = {0.0f, 0.0f, 100.0f, 0.0f};//光源的位置。第4个参数为1,表示点光源;第4个参数量为0,表示平行光束{0.0f, 0.0f, 10.0f, 0.0f} static GLfloat g_material[] = {0.96f, 0.8f, 0.69f, 1.0f};//材质
static GLfloat g_rquad = ;
static GLfloat g_rquad_x = ;
static GLfloat g_rquad_y = ; static float g_x_offset = 0.0;
static float g_y_offset = 0.0;
static float g_z_offset = 0.0;
static float g_scale_size = ;
static int g_press_x; //鼠标按下时的x坐标
static int g_press_y; //鼠标按下时的y坐标 const int n = ;
const GLfloat R = 0.5f;
const GLfloat Pi = 3.1415926536f;
int g_view_type = VIEW_FLAT;
int g_draw_content = SHAPE_TRIANGLE; void DrawTriangle()
{//绘制三角形
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glBegin(GL_TRIANGLES);
glNormal3f(0.0f, 0.0f, 1.0f); //指定面法向
glVertex3f( 0.0f, 1.0f, 0.0f); // 上顶点
glVertex3f(-1.0f,-1.0f, 0.0f); // 左下
glVertex3f( 1.0f,-1.0f, 0.0f); // 右下
glEnd();
glFlush();
} void DrawCube()
{//绘制立方体
glBegin(GL_QUADS);
glNormal3f( 0.0f, 0.0f, 1.0f); //指定面法向
glVertex3f( 1.0f, 1.0f,1.0f); //列举面顶点数据,逆时针顺序
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
//前----------------------------
glNormal3f( 0.0f, 0.0f,-1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f(-1.0f, 1.0f,-1.0f);
glVertex3f( 1.0f, 1.0f,-1.0f);
glVertex3f( 1.0f,-1.0f,-1.0f);
//后----------------------------
glNormal3f( 0.0f, 1.0f, 0.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f, 1.0f,-1.0f);
glVertex3f(-1.0f, 1.0f,-1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
//上----------------------------
glNormal3f( 0.0f,-1.0f, 0.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f( 1.0f,-1.0f,-1.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
//下----------------------------
glNormal3f( 1.0f, 0.0f, 0.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glVertex3f( 1.0f,-1.0f,-1.0f);
glVertex3f( 1.0f, 1.0f,-1.0f);
//右----------------------------
glNormal3f(-1.0f, 0.0f, 0.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f,-1.0f);
//左----------------------------*/
glEnd();
glFlush();
} void DrawCircle()
{//绘制圆
glBegin(GL_POLYGON);
glNormal3f(0.0f, 0.0f, 1.0f);
for (int i = ; i < n; ++i) {
glVertex2f(R*cos( * Pi / n * i), R*sin( * Pi / n * i));
}
glEnd();
} void DrawCylinder()
{//绘制圆柱 } void DrawTorus()
{ }void myInit()
{
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);//用白色清屏 glLightfv(GL_LIGHT0, GL_AMBIENT, g_light0_ambient);//设置场景的环境光
glLightfv(GL_LIGHT0, GL_DIFFUSE, g_light0_diffuse);//设置场景的散射光
glLightfv(GL_LIGHT0, GL_POSITION, g_light0_position);//设置场景的位置 glMaterialfv(GL_FRONT, GL_DIFFUSE, g_material);//指定用于光照计算的当前材质属性
glEnable(GL_TEXTURE_2D);
glEnable(GL_LIGHTING);//开启灯光
glEnable(GL_LIGHT0);//开启光照0 glShadeModel(GL_SMOOTH); //设置着色模式为光滑着色
glEnable(GL_DEPTH_TEST);//启用深度测试 glMatrixMode(GL_MODELVIEW); //指定当前矩阵为模型视景矩阵
glLoadIdentity(); //将当前的用户坐标系的原点移到了屏幕中心:类似于一个复位操作
gluLookAt(0.0, 0.0, 8.0, , , , , 1.0, );//该函数定义一个视图矩阵,并与当前矩阵相乘.
//第一组eyex, eyey,eyez 相机在世界坐标的位置;第二组centerx,centery,centerz 相机镜头对准的物体在世界坐标的位置;第三组upx,upy,upz 相机向上的方向在世界坐标中的方向
}void myGlutDisplay() //绘图函数, 操作系统在必要时刻就会对窗体进行重新绘制操作
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); //清除颜色缓冲以及深度缓冲
glEnable(GL_NORMALIZE); //打开法线向量归一化,确保了法线的长度为1 glMatrixMode(GL_MODELVIEW);//模型视图矩阵
glPushMatrix(); //压入当前矩阵堆栈 if (g_draw_content == SHAPE_MODEL)
{//绘制模型 }
else if (g_draw_content == SHAPE_TRIANGLE) //画三角形
{
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -6.0f);
DrawTriangle();
}
else if(g_draw_content == SHAPE_CUBE) //画立方体
{
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -6.0f);
glRotatef(g_rquad, g_rquad, g_rquad, 1.0f); // 在XYZ轴上旋转立方体
DrawCube();
g_rquad+=0.2f;// 增加旋转变量
}
else if (g_draw_content == SHAPE_CIRCLE) // 画圆
{
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -6.0f);
DrawCircle();
}
else if (g_draw_content == SHAPE_CYLINDER)
{//TODO: 添加画圆柱的代码 }
else if (g_draw_content == SHAPE_TORUS)
{//TODO:添加画圆环的代码 }
glPopMatrix();
glutSwapBuffers(); //双缓冲
} void myGlutReshape(int x,int y) //当改变窗口大小时的回调函数
{
if (y == )
{
y = ;
} g_windows_width = x;
g_windows_height = y;
double xy_aspect = (float)x / (float)y;
GLUI_Master.auto_set_viewport(); //自动设置视口大小 glMatrixMode( GL_PROJECTION );//当前矩阵为投影矩阵
glLoadIdentity();
gluPerspective(60.0, xy_aspect, 0.01, 1000.0);//视景体 glutPostRedisplay(); //标记当前窗口需要重新绘制
} void myGlutKeyboard(unsigned char Key, int x, int y)
{//键盘时间回调函数 } void myGlutMouse(int button, int state, int x, int y)
{
if (state == GLUT_DOWN) //鼠标的状态为按下
{
g_press_x = x;
g_press_y = y;
if (button == GLUT_LEFT_BUTTON)
{//按下鼠标的左键表示对模型进行旋转操作
g_xform_mode = TRANSFORM_ROTATE;
}
else if (button == GLUT_RIGHT_BUTTON)
{//按下鼠标的右键表示对模型进行平移操作
g_xform_mode = TRANSFORM_TRANSLATE;
}
else if (button == GLUT_MIDDLE_BUTTON)
{//按下鼠标的滑轮表示按下鼠标的右键表示对模型进行缩放操作
g_xform_mode = TRANSFORM_SCALE;
}
}
else if (state == GLUT_UP)
{//如果没有按鼠标,则不对模型进行任何操作
g_xform_mode = TRANSFORM_NONE;
}
} void myGlutMotion(int x, int y) //处理当鼠标键摁下时,鼠标拖动的事件
{
if (g_xform_mode == TRANSFORM_ROTATE) //旋转
{//TODO:添加鼠标移动控制模型旋转参数的代码 }
else if(g_xform_mode == TRANSFORM_SCALE) //缩放
{//TODO:添加鼠标移动控制模型缩放参数的代码 }
else if(g_xform_mode == TRANSFORM_TRANSLATE) //平移
{//TODO:添加鼠标移动控制模型平移参数的代码 } // force the redraw function
glutPostRedisplay();
} void myGlutIdle(void) //空闲回调函数
{
if ( glutGetWindow() != g_main_window )
glutSetWindow(g_main_window); glutPostRedisplay();
} void glui_control(int control ) //处理控件的返回值
{
switch(control)
{
case CRTL_LOAD://选择“open”控件
loadObjFile();
g_draw_content = SHAPE_MODEL;
break;
case CRTL_CHANGE://选择Type面板
if (g_view_type == VIEW_POINT)
{
glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); // 设置两面均为顶点绘制方式
}
else if (g_view_type == VIEW_WIRE)
{
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // 设置两面均为线段绘制方式
}
else
{
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); // 设置两面为填充方式
}
break;
case CRTL_TRIANGLE:
g_draw_content = SHAPE_TRIANGLE;
break;
case CRTL_CUBE:
g_draw_content = SHAPE_CUBE;
break;
case CRTL_CIRCLE:
g_draw_content = SHAPE_CIRCLE;
break;
case CRTL_CYLINDER:
g_draw_content = SHAPE_CYLINDER;
break;
case CRTL_CONE:
g_draw_content = SHAPE_TORUS;
break;
case CRTL_MODEL:
g_draw_content = SHAPE_MODEL;
break;
default:
break;
}
} void myGlui()
{
GLUI_Master.set_glutDisplayFunc( myGlutDisplay ); //注册渲染事件回调函数, 系统在需要对窗体进行重新绘制操作时调用
GLUI_Master.set_glutReshapeFunc( myGlutReshape ); //注册窗口大小改变事件回调函数
GLUI_Master.set_glutKeyboardFunc( myGlutKeyboard );//注册键盘输入事件回调函数
glutMotionFunc( myGlutMotion);//注册鼠标移动事件回调函数
GLUI_Master.set_glutMouseFunc( myGlutMouse );//注册鼠标点击事件回调函数
GLUI_Master.set_glutIdleFunc(myGlutIdle); //为GLUI注册一个标准的GLUT空闲回调函数,当系统处于空闲时,就会调用该注册的函数 //GLUI
GLUI *glui = GLUI_Master.create_glui_subwindow( g_main_window, GLUI_SUBWINDOW_RIGHT); //新建子窗体,位于主窗体的右部
new GLUI_StaticText(glui, "GLUI" ); //在GLUI下新建一个静态文本框,输出内容为“GLUI”
new GLUI_Separator(glui); //新建分隔符
new GLUI_Button(glui,"Open", CRTL_LOAD, glui_control); //新建按钮控件,参数分别为:所属窗体、名字、ID、回调函数,当按钮被触发时,它会被调用.
new GLUI_Button(glui, "Quit", ,(GLUI_Update_CB)exit );//新建退出按钮,当按钮被触发时,退出程序 GLUI_Panel *type_panel = glui->add_panel("Type" ); //在子窗体glui中新建面板,名字为“Type”
GLUI_RadioGroup *radio = glui->add_radiogroup_to_panel(type_panel, &g_view_type, CRTL_CHANGE, glui_control); //在Type面板中添加一组单选按钮
glui->add_radiobutton_to_group(radio, "points");
glui->add_radiobutton_to_group(radio, "wire");
glui->add_radiobutton_to_group(radio, "flat"); GLUI_Panel *draw_panel = glui->add_panel("Draw" ); //在子窗体glui中新建面板,名字为“Draw”
new GLUI_Button(draw_panel,"Triangle",CRTL_TRIANGLE,glui_control);
new GLUI_Button(draw_panel,"Cube",CRTL_CUBE,glui_control);
new GLUI_Button(draw_panel,"Circle",CRTL_CIRCLE,glui_control);
new GLUI_Button(draw_panel,"Cylinder",CRTL_CYLINDER,glui_control);
new GLUI_Button(draw_panel,"Torus",CRTL_CONE,glui_control);
new GLUI_Button(draw_panel,"Model",CRTL_MODEL,glui_control); glui->set_main_gfx_window(g_main_window ); //将子窗体glui与主窗体main_window绑定,当窗体glui中的控件的值发生过改变,则该glui窗口被重绘
GLUI_Master.set_glutIdleFunc( myGlutIdle );
} int main(int argc, char* argv[]) //程序入口
{
/****************************************/
/* Initialize GLUT and create window */
/****************************************/ freopen("log.txt", "w", stdout);//重定位,将输出放入log.txt文件中
glutInit(&argc, argv);//初始化glut
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);//初始化渲染模式
glutInitWindowPosition(, ); //初始化窗口位置
glutInitWindowSize(, ); //初始化窗口大小 g_main_window = glutCreateWindow("Model Viewer"); //创建主窗体Model Viewer myGlui();
myInit(); glutMainLoop();//进入glut消息循环 return EXIT_SUCCESS;
}
#ifndef COMMON
#define COMMON #define VIEW_POINT 0x00
#define VIEW_WIRE 0x01
#define VIEW_FLAT 0x02 #define CRTL_LOAD 0x00
#define CRTL_CHANGE 0x01
#define CRTL_TRIANGLE 0x02
#define CRTL_CUBE 0x03
#define CRTL_CIRCLE 0x04
#define CRTL_CYLINDER 0x05
#define CRTL_CONE 0x06
#define CRTL_MODEL 0x07 #define SHAPE_TRIANGLE 0x00
#define SHAPE_CUBE 0x01
#define SHAPE_CIRCLE 0x02
#define SHAPE_CYLINDER 0x03
#define SHAPE_TORUS 0x04
#define SHAPE_MODEL 0x05 #define TRANSFORM_NONE 0x51
#define TRANSFORM_ROTATE 0x52
#define TRANSFORM_SCALE 0x53
#define TRANSFORM_TRANSLATE 0x54 #endif
common.h
运行这段代码可以得到如下所示的结果
图形绘制
在上面那段代码中,已经给出了三角形、圆、正方体的绘制代码,下面还将介绍圆柱与圆环的绘制
圆
在opengl中并不能直接绘制圆,那么,此时想到了极限的方法,如果把圆分割成很多个扇形,这个扇形的角度足够小的话,那么曲线自然可以看作直线。有了这个思路,代码就很好写了。
void DrawCircle()
{//绘制圆
glBegin(GL_POLYGON);
glNormal3f(0.0f, 0.0f, 1.0f);
for (int i = ; i < n; ++i) {
glVertex2f(R*cos( * Pi / n * i), R*sin( * Pi / n * i));
}
glEnd();
}
三角形
三角形的绘制就十分的简单了,确定三个顶点,然后连线
void DrawTriangle()
{//绘制三角形
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBegin(GL_TRIANGLES);
glNormal3f(0.0f, 0.0f, 1.0f); //指定面法向
glVertex3f( 0.0f, 1.0f, 0.0f); // 上顶点
glVertex3f(-1.0f,-1.0f, 0.0f); // 左下
glVertex3f( 1.0f,-1.0f, 0.0f); // 右下
glEnd();
glFlush();
}
立方体
原理同三角形,确定八个顶点坐标,然后连线,不过这里要注意的是立方体为3D图形,要展示光照效果的话需要在绘制的时候确定各个面的法向量。
void DrawCube()
{//绘制立方体
glBegin(GL_QUADS);
glNormal3f( 0.0f, 0.0f, 1.0f); //指定面法向
glVertex3f( 1.0f, 1.0f,1.0f); //列举面顶点数据,逆时针顺序
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
//前----------------------------
glNormal3f( 0.0f, 0.0f,-1.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f(-1.0f, 1.0f,-1.0f);
glVertex3f( 1.0f, 1.0f,-1.0f);
glVertex3f( 1.0f,-1.0f,-1.0f);
//后----------------------------
glNormal3f( 0.0f, 1.0f, 0.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f, 1.0f,-1.0f);
glVertex3f(-1.0f, 1.0f,-1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
//上----------------------------
glNormal3f( 0.0f,-1.0f, 0.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f( 1.0f,-1.0f,-1.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
//下----------------------------
glNormal3f( 1.0f, 0.0f, 0.0f);
glVertex3f( 1.0f, 1.0f, 1.0f);
glVertex3f( 1.0f,-1.0f, 1.0f);
glVertex3f( 1.0f,-1.0f,-1.0f);
glVertex3f( 1.0f, 1.0f,-1.0f);
//右----------------------------
glNormal3f(-1.0f, 0.0f, 0.0f);
glVertex3f(-1.0f,-1.0f,-1.0f);
glVertex3f(-1.0f,-1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f,-1.0f);
//左----------------------------*/
glEnd();
glFlush();
}
圆柱
对于圆柱的绘制,思想同圆十分相似,就是分割。不过需要注意的是上下两个圆面和一个侧面需要分开来绘制。这里需要思考的是这个侧面该如何绘制呢?想象以下,把圆柱侧面展开,我们得到的是一个矩形,那分割成小片段的话也就是矩形了,即绘制无数个矩形,然后拼接形成侧面。
注:绘制时注意法向量的选取
void DrawCylinder()
{//绘制圆柱
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glBegin(GL_POLYGON);
glNormal3f(0.0f, 1.0f, 0.0f);
for (int i = ; i < n; i++) {
glVertex3f(R*cos( * Pi / n * i), 1.0f, R*sin( * Pi / n * i));
}
glEnd();
glBegin(GL_POLYGON);
glNormal3f(0.0f, -1.0f, 0.0f);
for (int i = ; i < n; i++) {
glVertex3f(R*cos( * Pi / n * i), 0.0f, R*sin( * Pi / n * i));
}
glEnd();
glBegin(GL_QUADS);
for (int i = ; i <= n; i++)
{
glNormal3f(R*cos( * Pi / n * i), 0.0f, R*sin( * Pi / n * i));
glVertex3f(R*cos( * Pi / n * i), 1.0f, R*sin( * Pi / n * i));
glVertex3f(R*cos( * Pi / n * i), 0.0f, R*sin( * Pi / n * i));
glNormal3f(R*cos( * Pi / n * (i + )), 0.0f, R*sin( * Pi / n * (i + )));
glVertex3f(R*cos( * Pi / n * (i + )), 0.0f, R*sin( * Pi / n * (i + )));
glVertex3f(R*cos( * Pi / n * (i + )), 1.0f, R*sin( * Pi / n * (i + )));
}
glEnd();
}
圆环
圆环的绘制稍微有些麻烦,先来看看下面这个圆环的线图
这里的难点就是各点的坐标表示,首先我们需要做的是把圆环压缩成一个圆面
压缩之后的表示为 R+r*cos(θ),然后再把压缩完后的点映射到x y轴上
X轴:(R+r*cos(θ))*cosα
Y轴:(R+r*cos(θ))*sinα
Z轴:r*sin(θ)
这样,我们的圆环就可以实现了
void DrawTorus()
{
int num = n / ;
for (int i = ; i < num; i++)
{
glBegin(GL_QUAD_STRIP);
for (int j = ; j <= num; j++)
{
for (int k = ; k >= ; k--)
{
double s = (i + k) % num + 0.5;
double t = j % num;
glNormal3f(cos( * Pi / num * s) * cos( * Pi / num * t), cos( * Pi / num * s)*sin( * Pi / num * t), sin( * Pi / num * s));
glVertex3f(( + R*cos( * Pi / num * s))*cos( * Pi / num * t), ( + R*cos( * Pi / num * s))*sin( * Pi / num * t), R*sin( * Pi / num * s));
}
}
glEnd();
}
}
小节
以上介绍了如何使用opengl绘制基本图形,下篇文章中将介绍如何使用opengl加载绘制模型,以及鼠标交互的实现。
从零开始openGL—— 二、 基本图形绘制的更多相关文章
- VS2008集成QT的OpenGL开发(实现二维图形的旋转)
主要是利用Qt中的定时器实现了二维图形的旋转功能: #ifndef QGLTEST_H #define QGLTEST_H #include <QGLWidget> #include &l ...
- matlab绘制二维图形
常用的二维图形命令: plot:绘制二维图形 loglog:用全对数坐标绘图 semilogx:用半对数坐标(X)绘图 semilogy:用半对数坐标(Y)绘图 fill:绘制二维多边填充图形 pol ...
- [github项目]基于百度地图二次开发实现的车辆监管(包含车辆定位、车辆图片和方向控制,电子围栏,图形绘制等功能)前端实现(不包含后端实现)
前言:基于百度地图javascript版本开发,百度地图中所用的key已承诺仅用于测试,不用于商业用途 注:本文所有代码可以到github上进行下载,github地址:http://map.eguid ...
- SVG.js 基础图形绘制整理(二)
一.折线 var draw = SVG('svg1').size(300, 300); //画折线 //使用字符串点 // var polyline=draw.polyline('0,0 100,50 ...
- Android OpenGL ES 开发:绘制图形
OpenGL 绘制图形步骤 上一篇介绍了 OpenGL 的相关概念,今天来实际操作,使用 OpenGL 绘制出图形,对其过程有一个初步的了解. OpenGL 绘制图形主要概括成以下几个步骤: 创建程序 ...
- QT 二维图形 原理、发展及应用
转载自 网易博客:sun的博客 http://zhouyang340.blog.163.com/blog/static/3024095920126710504178/ 2D绘图 Qt4中的2D绘图部分 ...
- (转)GPU图形绘制管线
摘抄“GPU Programming And Cg Language Primer 1rd Edition” 中文名“GPU编程与CG语言之阳春白雪下里巴人”第二章. 图形绘制管线描述GPU渲染流程, ...
- 13个JavaScript图表(JS图表)图形绘制插件【转】
现在网络上又有越来越多的免费的(JS 图表)JavaScript图表图形绘制插件.我之前给一家网站做过复杂的图形,我们用的是 highchart.在那段时间,没有很多可供选择的插件.但现在不同了,很容 ...
- 13个JavaScript图表(JS图表)图形绘制插件
转自:http://blog.jobbole.com/13671/ 1. Flash 过去是最佳解决方案,但很多人多在从那迁移: 2. 现代浏览器及其更强大的计算能力,使其在转化绘制实时数据方面的能力 ...
随机推荐
- 线段树合并学习笔记(P4556)
直入主题: 学习线段树合并..... 从名字就能看出,这个东西要合并线段树..... 线段树怎么能合并呢...... 暴力合就行了啊...... 一次从上往下的遍历,把所有的节点信息暴力合并,然后就没 ...
- 奶牛邻居——treap+契比雪夫距离+并查集
题目描述 了解奶牛们的人都知道,奶牛喜欢成群结队.观察约翰的N(1≤N≤100000)只奶牛,你会发现她们已经结成了几个“群”. 每只奶牛在吃草的时候有一个独一无二的位置坐标Xi,Yi(l≤Xi,Yi ...
- Zabbix日志监控插件
#!/usr/bin/env python # coding:utf-8 import re import os import sys import logging logging.basicConf ...
- java基础阶段几个面试题
1.说出你对面向对象的理解 在我理解,面向对象是向现实世界模型的自然延伸,这是一种“万物皆对象”的编程思想.在现实生活中的任何物体都可以归为一类事物,而每一个个体都是一类事物的实例.面向对象的编程是以 ...
- 使用客户机和主机做DNS服务正向解析及小问题解决
1.下载yum包 命令:yum install bind-chroot 2.更改配置文件 在这里,要了解到主配置文件为: /etc/named.conf 但是,为了避免经常修改主配置文件named ...
- 别翻了,这篇文章绝对让你深刻理解java类的加载以及ClassLoader源码分析【JVM篇二】
目录 1.什么是类的加载(类初始化) 2.类的生命周期 3.接口的加载过程 4.解开开篇的面试题 5.理解首次主动使用 6.类加载器 7.关于命名空间 8.JVM类加载机制 9.双亲委派模型 10.C ...
- jquery 判断数组是否为空
jquery 判断数组是否为空 if (data.length === 0) { console.log("数组为空"); }
- thinkphp6.0 开启调试模式以及Driver [Think] not supported
thinkphp6.0 开启调试模式 首先确认自己是通过 composer 进行的下载,然后修改系统目录下的 .example.env 为 .env 文件 修改 config->app.php ...
- suseoj 1210: 会场安排问题 (贪心)
1210: 会场安排问题 时间限制: 1 Sec 内存限制: 128 MB提交: 1 解决: 1[提交][状态][讨论版][命题人:liyuansong] 题目描述 假设要在足够多的会场里安排一批 ...
- 0MQ是会阻塞的,不要字面上看到队列就等同非阻塞。
如果你是希望通过0MQ来做缓冲队列,非阻塞的效果,那你就必须清楚 0MQ Socket是会阻塞,你要搞清楚0MQ Socket与队列的关系. 官方协议文档规定了,一部分类型的 0MQ Socket为不 ...