用opengl实现轨迹圆|经典程序
来源:互联网 发布:淘宝扣12分有什么影响 编辑:程序博客网 时间:2024/05/24 01:36
在你的图形工程中添加轨迹球的功能,可以更好的对模型进行查看。
之前写过一个.ply模型的读取程序,加入了下面轨迹球的功能。
下面是一个比较经典的轨迹球实现程序。
ArcBall.h
#pragma once///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////ArcBall.h///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////#ifndef _ArcBall_h#define _ArcBall_h// 仅在Debug模式下,启用断言#ifdef _DEBUG# include "assert.h"#else# define assert(x) { }#endif//2维点typedef union Tuple2f_t{ struct { GLfloat X, Y; } s; GLfloat T[2];} Tuple2fT;//3维点typedef union Tuple3f_t{ struct { GLfloat X, Y, Z; } s; GLfloat T[3];} Tuple3fT;//4维点typedef union Tuple4f_t{ struct { GLfloat X, Y, Z, W; } s; GLfloat T[4];} Tuple4fT;//3x3矩阵typedef union Matrix3f_t{ struct { //column major union { GLfloat M00; GLfloat XX; GLfloat SX; }; union { GLfloat M10; GLfloat XY; }; union { GLfloat M20; GLfloat XZ; }; union { GLfloat M01; GLfloat YX; }; union { GLfloat M11; GLfloat YY; GLfloat SY; }; union { GLfloat M21; GLfloat YZ; }; union { GLfloat M02; GLfloat ZX; }; union { GLfloat M12; GLfloat ZY; }; union { GLfloat M22; GLfloat ZZ; GLfloat SZ; }; } s; GLfloat M[9];} Matrix3fT;//4x4矩阵typedef union Matrix4f_t{ struct { //column major union { GLfloat M00; GLfloat XX; GLfloat SX; }; union { GLfloat M10; GLfloat XY; }; union { GLfloat M20; GLfloat XZ; }; union { GLfloat M30; GLfloat XW; }; union { GLfloat M01; GLfloat YX; }; union { GLfloat M11; GLfloat YY; GLfloat SY; }; union { GLfloat M21; GLfloat YZ; }; union { GLfloat M31; GLfloat YW; }; union { GLfloat M02; GLfloat ZX; }; union { GLfloat M12; GLfloat ZY; }; union { GLfloat M22; GLfloat ZZ; GLfloat SZ; }; union { GLfloat M32; GLfloat ZW; }; union { GLfloat M03; GLfloat TX; }; union { GLfloat M13; GLfloat TY; }; union { GLfloat M23; GLfloat TZ; }; union { GLfloat M33; GLfloat TW; GLfloat SW; }; } s; GLfloat M[16];} Matrix4fT;//定义类型的别名#define Point2fT Tuple2fT #define Quat4fT Tuple4fT #define Vector2fT Tuple2fT #define Vector3fT Tuple3fT #define FuncSqrt sqrtf# define Epsilon 1.0e-5//2维点相加inlinestatic void Point2fAdd(Point2fT* NewObj, const Tuple2fT* t1){ assert(NewObj && t1); NewObj->s.X += t1->s.X; NewObj->s.Y += t1->s.Y;}//2维点相减inlinestatic void Point2fSub(Point2fT* NewObj, const Tuple2fT* t1){ assert(NewObj && t1); NewObj->s.X -= t1->s.X; NewObj->s.Y -= t1->s.Y;}//3维点矢积inlinestatic void Vector3fCross(Vector3fT* NewObj, const Vector3fT* v1, const Vector3fT* v2){ Vector3fT Result; assert(NewObj && v1 && v2); Result.s.X = (v1->s.Y * v2->s.Z) - (v1->s.Z * v2->s.Y); Result.s.Y = (v1->s.Z * v2->s.X) - (v1->s.X * v2->s.Z); Result.s.Z = (v1->s.X * v2->s.Y) - (v1->s.Y * v2->s.X); *NewObj = Result;}//3维点点积inlinestatic GLfloat Vector3fDot(const Vector3fT* NewObj, const Vector3fT* v1){ assert(NewObj && v1); return (NewObj->s.X * v1->s.X) + (NewObj->s.Y * v1->s.Y) + (NewObj->s.Z * v1->s.Z);}//3维点的长度的平方inlinestatic GLfloat Vector3fLengthSquared(const Vector3fT* NewObj){ assert(NewObj); return (NewObj->s.X * NewObj->s.X) + (NewObj->s.Y * NewObj->s.Y) + (NewObj->s.Z * NewObj->s.Z);}//3维点的长度inlinestatic GLfloat Vector3fLength(const Vector3fT* NewObj){ assert(NewObj); return FuncSqrt(Vector3fLengthSquared(NewObj));}//设置3x3矩阵为0矩阵inlinestatic void Matrix3fSetZero(Matrix3fT* NewObj){ NewObj->s.M00 = NewObj->s.M01 = NewObj->s.M02 = NewObj->s.M10 = NewObj->s.M11 = NewObj->s.M12 = NewObj->s.M20 = NewObj->s.M21 = NewObj->s.M22 = 0.0f;}//设置4x4矩阵为0矩阵inlinestatic void Matrix4fSetZero(Matrix4fT* NewObj){ NewObj->s.M00 = NewObj->s.M01 = NewObj->s.M02 = NewObj->s.M10 = NewObj->s.M11 = NewObj->s.M12 = NewObj->s.M20 = NewObj->s.M21 = NewObj->s.M22 = NewObj->s.M30 = NewObj->s.M31 = NewObj->s.M32 = 0.0f;}//设置3x3矩阵为单位矩阵inlinestatic void Matrix3fSetIdentity(Matrix3fT* NewObj){ Matrix3fSetZero(NewObj); NewObj->s.M00 = NewObj->s.M11 = NewObj->s.M22 = 1.0f;}//设置4x4矩阵为单位矩阵inlinestatic void Matrix4fSetIdentity(Matrix4fT* NewObj){ Matrix4fSetZero(NewObj); NewObj->s.M00 = 1.0f; NewObj->s.M11 = 1.0f; NewObj->s.M22 = 1.0f; NewObj->s.M33 = 1.0f;}//从四元数设置旋转矩阵inlinestatic void Matrix3fSetRotationFromQuat4f(Matrix3fT* NewObj, const Quat4fT* q1){ GLfloat n, s; GLfloat xs, ys, zs; GLfloat wx, wy, wz; GLfloat xx, xy, xz; GLfloat yy, yz, zz; assert(NewObj && q1); n = (q1->s.X * q1->s.X) + (q1->s.Y * q1->s.Y) + (q1->s.Z * q1->s.Z) + (q1->s.W * q1->s.W); s = (n > 0.0f) ? (2.0f / n) : 0.0f; xs = q1->s.X * s; ys = q1->s.Y * s; zs = q1->s.Z * s; wx = q1->s.W * xs; wy = q1->s.W * ys; wz = q1->s.W * zs; xx = q1->s.X * xs; xy = q1->s.X * ys; xz = q1->s.X * zs; yy = q1->s.Y * ys; yz = q1->s.Y * zs; zz = q1->s.Z * zs; NewObj->s.XX = 1.0f - (yy + zz); NewObj->s.YX = xy - wz; NewObj->s.ZX = xz + wy; NewObj->s.XY = xy + wz; NewObj->s.YY = 1.0f - (xx + zz); NewObj->s.ZY = yz - wx; NewObj->s.XZ = xz - wy; NewObj->s.YZ = yz + wx; NewObj->s.ZZ = 1.0f - (xx + yy);}//3x3矩阵相乘inlinestatic void Matrix3fMulMatrix3f(Matrix3fT* NewObj, const Matrix3fT* m1){ Matrix3fT Result; assert(NewObj && m1); Result.s.M00 = (NewObj->s.M00 * m1->s.M00) + (NewObj->s.M01 * m1->s.M10) + (NewObj->s.M02 * m1->s.M20); Result.s.M01 = (NewObj->s.M00 * m1->s.M01) + (NewObj->s.M01 * m1->s.M11) + (NewObj->s.M02 * m1->s.M21); Result.s.M02 = (NewObj->s.M00 * m1->s.M02) + (NewObj->s.M01 * m1->s.M12) + (NewObj->s.M02 * m1->s.M22); Result.s.M10 = (NewObj->s.M10 * m1->s.M00) + (NewObj->s.M11 * m1->s.M10) + (NewObj->s.M12 * m1->s.M20); Result.s.M11 = (NewObj->s.M10 * m1->s.M01) + (NewObj->s.M11 * m1->s.M11) + (NewObj->s.M12 * m1->s.M21); Result.s.M12 = (NewObj->s.M10 * m1->s.M02) + (NewObj->s.M11 * m1->s.M12) + (NewObj->s.M12 * m1->s.M22); Result.s.M20 = (NewObj->s.M20 * m1->s.M00) + (NewObj->s.M21 * m1->s.M10) + (NewObj->s.M22 * m1->s.M20); Result.s.M21 = (NewObj->s.M20 * m1->s.M01) + (NewObj->s.M21 * m1->s.M11) + (NewObj->s.M22 * m1->s.M21); Result.s.M22 = (NewObj->s.M20 * m1->s.M02) + (NewObj->s.M21 * m1->s.M12) + (NewObj->s.M22 * m1->s.M22); *NewObj = Result;}//4x4矩阵相乘inlinestatic void Matrix4fSetRotationScaleFromMatrix4f(Matrix4fT* NewObj, const Matrix4fT* m1){ assert(NewObj && m1); NewObj->s.XX = m1->s.XX; NewObj->s.YX = m1->s.YX; NewObj->s.ZX = m1->s.ZX; NewObj->s.XY = m1->s.XY; NewObj->s.YY = m1->s.YY; NewObj->s.ZY = m1->s.ZY; NewObj->s.XZ = m1->s.XZ; NewObj->s.YZ = m1->s.YZ; NewObj->s.ZZ = m1->s.ZZ;}//进行矩阵的奇异值分解,旋转矩阵被保存到rot3和rot4中,返回矩阵的缩放因子inlinestatic GLfloat Matrix4fSVD(const Matrix4fT* NewObj, Matrix3fT* rot3, Matrix4fT* rot4){ GLfloat s, n; assert(NewObj); s = FuncSqrt( ((NewObj->s.XX * NewObj->s.XX) + (NewObj->s.XY * NewObj->s.XY) + (NewObj->s.XZ * NewObj->s.XZ) + (NewObj->s.YX * NewObj->s.YX) + (NewObj->s.YY * NewObj->s.YY) + (NewObj->s.YZ * NewObj->s.YZ) + (NewObj->s.ZX * NewObj->s.ZX) + (NewObj->s.ZY * NewObj->s.ZY) + (NewObj->s.ZZ * NewObj->s.ZZ)) / 3.0f); if (rot3) { rot3->s.XX = NewObj->s.XX; rot3->s.XY = NewObj->s.XY; rot3->s.XZ = NewObj->s.XZ; rot3->s.YX = NewObj->s.YX; rot3->s.YY = NewObj->s.YY; rot3->s.YZ = NewObj->s.YZ; rot3->s.ZX = NewObj->s.ZX; rot3->s.ZY = NewObj->s.ZY; rot3->s.ZZ = NewObj->s.ZZ; n = 1.0f / FuncSqrt((NewObj->s.XX * NewObj->s.XX) + (NewObj->s.XY * NewObj->s.XY) + (NewObj->s.XZ * NewObj->s.XZ)); rot3->s.XX *= n; rot3->s.XY *= n; rot3->s.XZ *= n; n = 1.0f / FuncSqrt((NewObj->s.YX * NewObj->s.YX) + (NewObj->s.YY * NewObj->s.YY) + (NewObj->s.YZ * NewObj->s.YZ)); rot3->s.YX *= n; rot3->s.YY *= n; rot3->s.YZ *= n; n = 1.0f / FuncSqrt((NewObj->s.ZX * NewObj->s.ZX) + (NewObj->s.ZY * NewObj->s.ZY) + (NewObj->s.ZZ * NewObj->s.ZZ)); rot3->s.ZX *= n; rot3->s.ZY *= n; rot3->s.ZZ *= n; } if (rot4) { if (rot4 != NewObj) { Matrix4fSetRotationScaleFromMatrix4f(rot4, NewObj); } n = 1.0f / FuncSqrt((NewObj->s.XX * NewObj->s.XX) + (NewObj->s.XY * NewObj->s.XY) + (NewObj->s.XZ * NewObj->s.XZ)); rot4->s.XX *= n; rot4->s.XY *= n; rot4->s.XZ *= n; n = 1.0f / FuncSqrt((NewObj->s.YX * NewObj->s.YX) + (NewObj->s.YY * NewObj->s.YY) + (NewObj->s.YZ * NewObj->s.YZ)); rot4->s.YX *= n; rot4->s.YY *= n; rot4->s.YZ *= n; n = 1.0f / FuncSqrt((NewObj->s.ZX * NewObj->s.ZX) + (NewObj->s.ZY * NewObj->s.ZY) + (NewObj->s.ZZ * NewObj->s.ZZ)); rot4->s.ZX *= n; rot4->s.ZY *= n; rot4->s.ZZ *= n; } return s;}//从3x3矩阵变为4x4的旋转矩阵inlinestatic void Matrix4fSetRotationScaleFromMatrix3f(Matrix4fT* NewObj, const Matrix3fT* m1){ assert(NewObj && m1); NewObj->s.XX = m1->s.XX; NewObj->s.YX = m1->s.YX; NewObj->s.ZX = m1->s.ZX; NewObj->s.XY = m1->s.XY; NewObj->s.YY = m1->s.YY; NewObj->s.ZY = m1->s.ZY; NewObj->s.XZ = m1->s.XZ; NewObj->s.YZ = m1->s.YZ; NewObj->s.ZZ = m1->s.ZZ;}//4x4矩阵的与标量的乘积inlinestatic void Matrix4fMulRotationScale(Matrix4fT* NewObj, GLfloat scale){ assert(NewObj); NewObj->s.XX *= scale; NewObj->s.YX *= scale; NewObj->s.ZX *= scale; NewObj->s.XY *= scale; NewObj->s.YY *= scale; NewObj->s.ZY *= scale; NewObj->s.XZ *= scale; NewObj->s.YZ *= scale; NewObj->s.ZZ *= scale;}//设置旋转矩阵inlinestatic void Matrix4fSetRotationFromMatrix3f(Matrix4fT* NewObj, const Matrix3fT* m1){ GLfloat scale; assert(NewObj && m1); scale = Matrix4fSVD(NewObj, NULL, NULL); Matrix4fSetRotationScaleFromMatrix3f(NewObj, m1); Matrix4fMulRotationScale(NewObj, scale);}typedef class ArcBall_t{protected: //把二维点映射到三维点 inline void _mapToSphere(const Point2fT* NewPt, Vector3fT* NewVec) const;public: //构造/析构函数 ArcBall_t(GLfloat NewWidth, GLfloat NewHeight); ~ArcBall_t() { }; //设置边界 inline void setBounds(GLfloat NewWidth, GLfloat NewHeight) { assert((NewWidth > 1.0f) && (NewHeight > 1.0f)); //设置长宽的调整因子 this->AdjustWidth = 1.0f / ((NewWidth - 1.0f) * 0.5f); this->AdjustHeight = 1.0f / ((NewHeight - 1.0f) * 0.5f); } //鼠标点击 void click(const Point2fT* NewPt); //鼠标拖动计算旋转 void drag(const Point2fT* NewPt, Quat4fT* NewRot); //更新鼠标状态 void upstate(); //void mousemove(WPARAM wParam,LPARAM lParam);protected: Vector3fT StVec; //保存鼠标点击的坐标 Vector3fT EnVec; //保存鼠标拖动的坐标 GLfloat AdjustWidth; //宽度的调整因子 GLfloat AdjustHeight; //长度的调整因子public: Matrix4fT Transform; //计算变换 Matrix3fT LastRot; //上一次的旋转 Matrix3fT ThisRot; //这次的旋转 float zoomRate; float lastZoomRate; bool isDragging; // 是否拖动 bool isRClicked; // 是否右击鼠标 bool isClicked; // 是否点击鼠标 bool isZooming; //是否正在缩放 Point2fT LastPt; Matrix4fT origTransform; Point2fT MousePt; // 当前的鼠标位置} ArcBallT;#endif
ArcBall.cpp
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////ArcBall.cpp//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #include <glut.h> #include <math.h> #include "ArcBall.h" //轨迹球参数://直径 2.0f//半径 1.0f//半径平方 1.0fvoid ArcBall_t::_mapToSphere(const Point2fT* NewPt, Vector3fT* NewVec) const{ Point2fT TempPt; GLfloat length; //复制到临时变量 TempPt = *NewPt; //把长宽调整到[-1 ... 1]区间 TempPt.s.X = (TempPt.s.X * this->AdjustWidth) - 1.0f; TempPt.s.Y = 1.0f - (TempPt.s.Y * this->AdjustHeight); //计算长度的平方 length = (TempPt.s.X * TempPt.s.X) + (TempPt.s.Y * TempPt.s.Y); //如果点映射到球的外面 if (length > 1.0f) { GLfloat norm; //缩放到球上 norm = 1.0f / FuncSqrt(length); //设置z坐标为0 NewVec->s.X = TempPt.s.X * norm; NewVec->s.Y = TempPt.s.Y * norm; NewVec->s.Z = 0.0f; } //如果在球内 else { //利用半径的平方为1,求出z坐标 NewVec->s.X = TempPt.s.X; NewVec->s.Y = TempPt.s.Y; NewVec->s.Z = FuncSqrt(1.0f - length); }}ArcBall_t::ArcBall_t(GLfloat NewWidth, GLfloat NewHeight){ this->StVec.s.X = 0.0f; this->StVec.s.Y = 0.0f; this->StVec.s.Z = 0.0f; this->EnVec.s.X = 0.0f; this->EnVec.s.Y = 0.0f; this->EnVec.s.Z = 0.0f; Matrix4fSetIdentity(&Transform); Matrix3fSetIdentity(&LastRot); Matrix3fSetIdentity(&ThisRot); this->isDragging = false; this->isClicked = false; this->isRClicked = false; this->isZooming = false; this->zoomRate = 1; this->setBounds(NewWidth, NewHeight);}void ArcBall_t::upstate(){ if (!this->isZooming && this->isRClicked) { // 开始拖动 this->isZooming = true; // 设置拖动为变量为true this->LastPt = this->MousePt; this->lastZoomRate = this->zoomRate; } else if (this->isZooming) {//正在拖动 if (this->isRClicked) { //拖动 Point2fSub(&this->MousePt, &this->LastPt); this->zoomRate = this->lastZoomRate + this->MousePt.s.X * this->AdjustWidth * 2; } else { //停止拖动 this->isZooming = false; } } else if (!this->isDragging && this->isClicked) { // 如果没有拖动 this->isDragging = true; // 设置拖动为变量为true this->LastRot = this->ThisRot; this->click(&this->MousePt); } else if (this->isDragging) { if (this->isClicked) { //如果按住拖动 Quat4fT ThisQuat; this->drag(&this->MousePt, &ThisQuat); // 更新轨迹球的变量 Matrix3fSetRotationFromQuat4f(&this->ThisRot, &ThisQuat); // 计算旋转量 Matrix3fMulMatrix3f(&this->ThisRot, &this->LastRot); Matrix4fSetRotationFromMatrix3f(&this->Transform, &this->ThisRot); } else // 如果放开鼠标,设置拖动为false this->isDragging = false; }}//按下鼠标,记录当前对应的轨迹球的位置void ArcBall_t::click(const Point2fT* NewPt){ this->_mapToSphere(NewPt, &this->StVec);}//鼠标拖动,计算旋转四元数void ArcBall_t::drag(const Point2fT* NewPt, Quat4fT* NewRot){ //新的位置 this->_mapToSphere(NewPt, &this->EnVec); //计算旋转 if (NewRot) { Vector3fT Perp; //计算旋转轴 Vector3fCross(&Perp, &this->StVec, &this->EnVec); //如果不为0 if (Vector3fLength(&Perp) > Epsilon) { //记录旋转轴 NewRot->s.X = Perp.s.X; NewRot->s.Y = Perp.s.Y; NewRot->s.Z = Perp.s.Z; //在四元数中,w=cos(a/2),a为旋转的角度 NewRot->s.W = Vector3fDot(&this->StVec, &this->EnVec); } //是0,说明没有旋转 else { NewRot->s.X = NewRot->s.Y = NewRot->s.Z = NewRot->s.W = 0.0f; } }}
sample.cpp
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////sample.cpp////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////#include <glut.h>#include <math.h> #include "ArcBall.h" //初始化,必须用全局变量的方式,不能用newArcBallT arcBall(600.0f, 400.0f);ArcBallT* ArcBall = &arcBall;// new ArcBallT(600.0f,400.0f);//&arcBall;void reshape(int w, int h) { glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glFrustum(-1, 1, -1, 1, 1.5, 20); glMatrixMode(GL_MODELVIEW); ////ball ArcBall->setBounds((GLfloat)w, (GLfloat)h);//1. 设置窗口边界}void init() { glClearColor(0, 0, 0, 0); glShadeModel(GL_FLAT);}void display(void){ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glColor3f(1.0, 1.0, 1.0); glLoadIdentity(); gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); glScalef(1.0, 2.0, 1.0); //glPushMatrix(); glTranslatef(0, 0, -3); glScalef(ArcBall->zoomRate, ArcBall->zoomRate, ArcBall->zoomRate);//2. 缩放 glMultMatrixf(ArcBall->Transform.M); //3. 旋转 glutWireCube(1.0); //glPopMatrix(); glFlush();}//移动void move(int x, int y){ ArcBall->MousePt.s.X = x; ArcBall->MousePt.s.Y = y; ArcBall->upstate(); glutPostRedisplay();}//点击void mouse(int button, int state, int x, int y){ if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) { ArcBall->isClicked = true; move(x, y); } else if (button == GLUT_LEFT_BUTTON && state == GLUT_UP) ArcBall->isClicked = false; else if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) { ArcBall->isRClicked = true; move(x, y); } else if (button == GLUT_RIGHT_BUTTON && state == GLUT_UP) ArcBall->isRClicked = false; ArcBall->upstate(); glutPostRedisplay();}int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); glutInitWindowSize(640, 480); glutCreateWindow("HI"); init(); glutDisplayFunc(display); glutReshapeFunc(reshape); glutMouseFunc(mouse); //registered the mouse event. glutMotionFunc(move); //registered the move event glutMainLoop(); return 0;}
转载自 http://blog.sina.com.cn/s/blog_8d8425f30100ywap.html
1 0
- 用opengl实现轨迹圆|经典程序
- OpenGL MFC单文档 实现轨迹球
- OpenGL笔记——轨迹球实现资料
- Opengl 利用FBO实现物体移动轨迹变淡的效果
- 用GLUT库创建基本OpenGL窗口经典程序
- OpenGL轨迹球代码
- OpenGL鼠标轨迹球
- OpenGL交互式程序实现
- C实现简易运动轨迹检测的程序
- OpenGL中的轨迹球问题
- Flex3学习轨迹:实现按钮圆角
- 经典opengl
- OpenGL和Glut实现的选取程序
- 用c实现数据结构中的经典程序:josephus-向量
- 用c语言实现数据结构中经典程序:Josephus-链表
- 用C++实现《经典c程序100例》(未完待续)
- 用OpenGL实现 中点画圆法
- 用OpenGL实现 Breseham画圆算法
- Jenkins中使用过的Msbuild编译bat
- IO编程
- 编程之美2.7节求最大公约数问题
- 单例模式(一)
- 如何快速更新数据库中的百万条数据
- 用opengl实现轨迹圆|经典程序
- C/C++复习:向量的数量积
- 朴素贝叶斯的三个常用模型:高斯、多项式、伯努利
- Android SDK更新不了问题解决
- 设计模式之---中介者模式(Mediator Design Pattern)
- maven/gradle 打包后自动上传到nexus仓库---学习笔记
- Juju's lessons
- 算数题
- 使用NSMutableAttributedString添加下划线、删除线、阴影、填充、不同字体颜色等