WHY数学表达式的3D可视化

很早之前我就有这种想法,将数学表达式的图形显示出来.最近终于实现了这套较为完善的版本,将其代码公布,也为开源做点贡献.首先系统中定义一套脚本语言格式,用于描述数学表达式.使用时先要将数学表达式写成该脚本的形式,解析脚本代码以生成相应的图形.该系统能够生成三维曲线图形和曲面图形.

开发环境:VS2008,图形渲染用的是D3D9,用于解析数学表达式的核心代码MathExpression只使用了C的基本库函数,可以跨平台使用.

软件下载地址:

http://files.cnblogs.com/WhyEngine/MathGraph_2_0.zip

代码下载地址:

http://pan.baidu.com/s/1pJkD4Bh

早期版本地址:

http://www.cnblogs.com/WhyEngine/p/3535903.html

补丁下载地址:

http://files.cnblogs.com/WhyEngine/MathExpression.zip修改了几个表达式解析错误的BUG,支持科学计数格式.

[一]软件介绍

(1)主界面

将数学脚本文件拖入到主界面中,可以显示其图形.亦可以通过菜单项打开脚本文件.

(2)数学脚本面板

用于打开脚本文件,编辑脚本,保存文件,解析脚本,输出编译信息.

(3)可视化属性面板

用于对图形显示的设置,如果设置颜色,纹理等.有两种类型的图形,MESH和曲线.将纹理文件拖入软件界面中后,会自动将其设置为MESH纹理.

(4)包围盒面板

图形包围盒的显示.

(5)系统配置面板

设置场景相关的属性,并能够保存配置文件.

(6)快捷方式

F5:         数学脚本编辑界面

F6:         可视化属性面板

F7:         包围盒面板

F9:         系统配置面板

F11:        全屏切换

ESC:       退出全屏

‘X’:        恢复为默认视角

'L':          开关灯光

'B':          包围盒的可见属性切换

'G':          地平面网格的可见属性切换

'M':         坐标系轴的可见属性切换

'N':          地面的可见属性切换

'1':          MESH图形中,面片可见,线框不可见

'2':          MESH图形中,面片不可见,线框可见

'3':          MESH图形中,面片可见,线框可见

'4':          MESH图形中,使用纹理色

'5':          MESH图形中,使用顶点色

'6':          MESH图形中,使用默认色

'0':          重新编译脚本(如果脚本中使用了随机数函数,则重新编译后,生成的图形会不一样)

[二]脚本语法

(1)常量

系统中默认有两个常量值

PI    3.1415927

E     2.7182818

常量名通常为大写字母,如 (PI + E) 或 sin(PI*0.5)

(2)数值解析

对整数的解析支持2,8,10,16四种进制

0X开头为16进制, XABCDEF大小写都可以, 如0xffff

0Y开头为2进制, Y大小写都可以, 如0y10101010000

0开头为8进制, 如07523, 注意出现了"08"之类的会解析失败

默认为10进制

对浮点数的解析只支持形如”0.12”的格式,不能省略前面的0,目前尚不支持科学表达.

(3)顶点数目

所谓顶点数目是指表达式运算时所需要的输入数据.数据分为两类:一维数据用于生成曲线图形,其定义如下:

vertices = 3600 // 设置顶点数目

二维数据用于生成生成MESH图形数据,其定义如下:

vertices = dimension1:80 dimension2:160 或

vertices = D1:80 D2:160

表示第一个维度的输入为80,第二个维度的输入为160,整体输入的顶点数目为80*160.

(4)变量及其赋值

系统中使用a-z的26个英文小写字母表示变量,变量能够存储单个实数,或一个实数数组.如果为实数数据,则其大小为之前设置的顶点数目(见3).

设置为单个实数

a = 3.1415                   // 将a赋值为3.1415

一维数组的设置

a = from 0 to 100       // a为一个实数数组,数组大小为vertices的设置,数值为线性插值求得.

二维数据的设置

a = from 0 to (2*PI) dimension1

b = from (-PI*0.5) to (PI*0.5) dimension2

或者

a = from 0 to (2*PI) D1

b = from (-PI*0.5) to (PI*0.5) D2

变量中x,y,z将组成3D顶点位置坐标

r,g,b将组成顶点颜色.其值范围在0-1.0之间.如果没有设置r,g,b,将使用默认方式生成顶点色.

u,v为顶点的纹理坐标,如果没有设置u,v,将使用x,z生成顶点的纹理坐标.

(5)运算符

a.标准单目运算符

+,-

如:a = -b

b.标准双目运算符

+,-,*,/,%,^

如:c = a * b 如果a,b都为单个实数则运算结果c也是单个实数,否则c为实数数组

c.函数单目运算符 形如sin(a)

positive,negative,abs,floor,ceil,sign,sqrt,exp,log,log2,log10,sin,cos,tan,asin,acos,atan,rand 

d.函数双目运算符 形如pow(a, b)

add,sub,multiply,divide,max,min,mod,pow,atan2,rand2,  

e.函数三目运算符 形如lerp(a, b, r)

lerp,clamp,gray,add3,min3,max3,average3

f.函数四目运算符 形如average4(a, b, c, d)

add4,min4,max4,average4

g.函数数组运算符(输入实数数组,输出一个浮点数,如求最大值,最小值,数组加和等)

add_array,min_array,max_array,ave_array

h.函数数组运算符(输入实数数组,输出也是实数数组,如求数组左移,数组右移,前向累加等)

array_move_right,array_move_left,array_cumulate

(6)运算符嵌套

支持{}, [], ()这三类括号标志符,括号必需成对出现.支持最大32级括号的嵌套.如:

(2+(-2+(5.0*(9 + ((1+2)*3))/3) + 2))

-{exp[5*sqrt(1 -abs[sin{rand(100)}]) + 6]}

(7)示例

Sin曲线

vertices = 1200

x = from (-4*PI) to (4*PI)

y = sin(x)

vertices = 360

w = from 0 to (2*PI)

r = 10.0

x = r*sin(w)

y = r*cos(w)

曲线球

vertices = 3600

w = from 0 to 32

a = mod(w, 1) * 2 * PI

b = from 0 to PI

r = 10.0

x = r*sin(a)*sin(b)

y = r*cos(a)*sin(b)

z = r*cos(b)

线圈

vertices = 36000

a = rand2(8, 64)

b = rand2(4, 64)

c = a + b

s = c / b

o = rand2(4, b)

i = from 0 to (360*2*PI)

j = mod(i, 2*PI)

k = mod(s*i, 2*PI)

m = a*sin(j)

n = a*cos(j)

x = m + o*sin(k)

y = n + o*cos(k)

地形面

vertices = dimension1:320 dimension2:320

x = from (-4) to (4) dimension1

z = from (-4) to (4) dimension2

r = x^2 + z^2

y = sin(x^2 + z^2*3)/(0.05 + r) + (x^2 + z^2*5)*exp(1 -r)/2

抛物线曲面

vertices = dimension1:101 dimension2:101

x = from (-100) to (100) dimension1

z = from (-100) to (100) dimension2

y = (20000 - x^2 - z^2)*0.005

三维球体

vertices = dimension1:36 dimension2:72

a = from 0 to (2*PI) dimension1

b = from (-PI*0.5) to (PI*0.5) dimension2

r = 10.0

x = r*cos(b)*sin(a)

y = r*sin(b)

z = r*cos(b)*cos(a)

圆锥体

vertices = D1:72 D2:72

u = from 0 to (2) D2

v = from 0 to (2*PI) D1

a = 1.0

b = 0.5

c = sin(v);d = cos(v);

e = sin(b);f = cos(b);

g = sin(a);h = cos(a);

x = f*h*d - f*g*c + e*3

y = g*d + h*c

z = -e*h*d + e*g*c + f*3

x = x*u

y = y*u

z = z*u

心形

vertices = dimension1:80 dimension2:160

a = from 0 to (2*PI) dimension1

b = from (-PI*0.5) to (PI*0.5) dimension2

r = 10.0

c = sqrt(abs(a - PI))*1.5

x = r*cos(b)*sin(a)*c

y = -r*cos(b)*cos(a)*c

z = r*sin(b)*0.5

海螺

vertices = dimension1:160 dimension2:160

u = from 0 to (6*PI) dimension1

v = from 0 to (2*PI) dimension2

k = 1.2

a = 1.5

w = (k^u) * (1+cos(v))

x = w*cos(u)

y = w*sin(u)

z = (k^u)*sin(v) - (k^u)*a

vertices = D1:20 D2:500

u = from 0 to (2*PI) D1

v = from 0 to (2*PI) D2

a = sin(u)

b = cos(u)

c = sin(v)

d = cos(v)

r = (12 + c + b) *(1+d)

v = 10 * v

x = r*sin(v)

y = a + 32*d

z = r*cos(v)

[三]代码与用户自定义扩展

代码中MathExpression模块中为数学表达式及脚本解析的代码逻辑.

(1)主要接口

文件”math_expression_parser.h”提供了对表达式的解析函数

// 设置参数值

void SetParameterValue(char c, float value);

// 清空参数值

void ClearParameterValues();

// 表达式解析

bool ParseExpression(const char* szExpression, float& rst);

// 括号内的子表达式解析

bool ParseBracketExpression(const char* szExpression,

    unsigned int& pos, float& rst,

unsigned int bracketIndex, bool endComma);

 

可以针求独立表达式的结果,如:

bool sus = ParseExpression(“sin(PI*3) + 10*E*log(100)”, rst);

 

文件”math_script_parser.h”提供了一个对象MathScriptParser,用于对数学脚本的解析

class MathScriptParser

{

public:

    ...

    // 加载脚本文件

    bool LoadFile(const char* szFile);

    // 处理内存数据

    bool ProcessMemory(const char* bufPtr, unsigned int bufSize);

    ...

};

(2)添加或设置常量值

开发者可以通过”const_value.h”文件中的如下函数对常量进行添加或修改

// 添加或设置常量值

bool SetConstValue(const char* szName, float value);

(3)添加或设置函数运算符

程序中的运算符操作是以函数指针的方式使用,开发者可以将自己实现的函数设置到系统中.

有6种运算符函数类型:

// 单目运算函数

typedef float (*SINGLE_OPERATOR_FUNC)(float);

 

// 双目运算函数

typedef float (*TWIN_OPERATOR_FUNC)(float, float);

 

// 三目运算函数

typedef float (*THREE_OPERATOR_FUNC)(float, float, float);

 

// 四目运算函数

typedef float (*FOUR_OPERATOR_FUNC)(float, float, float, float);

 

// 对ValueNode的运算函数(输入ValueNode,输出一个浮点数)

typedef float (*VALUENODE_TO_FLOAT_OPERATOR_FUNC)(const ValueNode*);

 

// 对ValueNode的运算函数(输入ValueNode,输出ValueNode)

typedef void  (*VALUENODE_CONVERT_OPERATOR_FUNC)(const ValueNode*, ValueNode*);

开发者可自定义运算函数后,使用如下接口,将其添加到系统中.

// 添加或设置运算函数

bool SetSingleOperator(const char* szName, SINGLE_OPERATOR_FUNC func);

bool SetTwinOperator(const char* szName, TWIN_OPERATOR_FUNC func);

bool SetThreeOperator(const char* szName, THREE_OPERATOR_FUNC func);

bool SetFourOperator(const char* szName, FOUR_OPERATOR_FUNC func);

bool SetValueNodeToFloatOperator(const char* szName, VALUENODE_TO_FLOAT_OPERATOR_FUNC func);

bool SetValueNodeConvertOperator2(const char* szName, VALUENODE_CONVERT_OPERATOR_FUNC func);

需要注意这两个宏:

#define OPERATOR_NAME_LENGTH        24                // 操作符名的最大长度

#define MAX_FUNCTIONS_COUNT         256               // 运算函数的最大数目

如果不满足要求,请自己修改这两个宏值,不要出现内存越界.

 

 

WHY数学表达式的3D可视化的更多相关文章

  1. 基于语法分析器GOLD Parser开发的数学表达式计算器

    最近发现一款文法分析神器,看完官网(http://goldparser.org/)的介绍后感觉很犀利的样子,于是就拿来测试了一番,写了一个数学表达式分析的小程序,支持的数学运算符如下所示:常规运算:+ ...

  2. 基于 HTML5 WebGL 的挖掘机 3D 可视化应用

    前言 在工业互联网以及物联网的影响下,人们对于机械的管理,机械的可视化,机械的操作可视化提出了更高的要求.如何在一个系统中完整的显示机械的运行情况,机械的运行轨迹,或者机械的机械动作显得尤为的重要,因 ...

  3. 基于 HTML5 + WebGL 的 3D 可视化挖掘机

    前言 在工业互联网以及物联网的影响下,人们对于机械的管理,机械的可视化,机械的操作可视化提出了更高的要求.如何在一个系统中完整的显示机械的运行情况,机械的运行轨迹,或者机械的机械动作显得尤为的重要,因 ...

  4. 理解CSS中的数学表达式calc()

    前面的话 数学表达式calc()是CSS中的函数,主要用于数学运算.使用calc()为页面元素布局提供了便利和新的思路.本文将介绍calc()的相关内容 定义 数学表达式calc()是calculat ...

  5. Qt计算器开发(二):信号槽实现数学表达式合法性检查

    表达式的合法性 由于我们的计算器不是单步计算的,所以我们能够一次性输入一个长表达式.然而假设用户输入的长表达式不合法的话,那么就会引发灾难.所以有必要对于用户的输入做一个限制. 一些限制举例: 比方, ...

  6. 基于 HTML5 WebGL 的地铁站 3D 可视化系统

    前言 工业互联网,物联网,可视化等名词在我们现在信息化的大背景下已经是耳熟能详,日常生活的交通,出行,吃穿等可能都可以用信息化的方式来为我们表达,在传统的可视化监控领域,一般都是基于 Web SCAD ...

  7. 分享数百个 HT 工业互联网 2D 3D 可视化应用案例

    过去的 2018 年,我们认为是国内工业互联网可视化的元年,图扑软件作为在工业可视化领域的重度参与者,一线见证了众多 HTML5/Web 化.2D/3D 化的项目在工业界应用落地,我们觉得有必要在此分 ...

  8. 基于 WebGL 的 HTML5 楼宇自控 3D 可视化监控

    前言 智慧楼宇和人们的生活息息相关,楼宇智能化程度的提高,会极大程度的改善人们的生活品质,在当前工业互联网大背景下受到很大关注.目前智慧楼宇可视化监控的主要优点包括: 智慧化 -- 智慧楼宇是一个生态 ...

  9. 基于 HTML5 的 WebGL 楼宇自控 3D 可视化监控

    前言 智慧楼宇和人们的生活息息相关,楼宇智能化程度的提高,会极大程度的改善人们的生活品质,在当前工业互联网大背景下受到很大关注.目前智慧楼宇可视化监控的主要优点包括: 智慧化 -- 智慧楼宇是一个生态 ...

随机推荐

  1. Math对象应用详解

    JavaScript中的Math对象提供了大量的算术运算功能和数值操作方法. JavaScript中的Math对象的与众不同之处在于,它是一个全局对象.在使用Math对象之前,既不需要将一个变量声明为 ...

  2. sql基础笔记备忘

    MySQL中定义数据字段的类型对你数据库的优化是非常重要的. MySQL支持多种类型,大致可以分为三类:数值.日期/时间和字符串(字符)类型. 数值类型:tinyint smallint medium ...

  3. python 全栈开发,Day78(Django组件-forms组件)

    一.Django组件-forms组件 forms组件 django中的Form组件有以下几个功能: 生成HTML标签 验证用户数据(显示错误信息) HTML Form提交保留上次提交数据 初始化页面显 ...

  4. python 全栈开发,Day54(jQuery的属性操作,使用jQuery操作input的value值,jQuery的文档操作)

    昨日内容回顾 jQuery 宗旨:write less do more 就是js的库,它是javascript的基础上封装的一个框架 在前端中,一个js文件就是一个模块 一.用法: 1.引入包 2.入 ...

  5. python 全栈开发,Day52(关于DOM操作的相关案例,JS中的面向对象,定时器,BOM,client、offset、scroll系列)

    昨日作业讲解: 京东购物车 京东购物车效果: 实现原理: 用2个盒子,就可以完整效果. 先让上面的小盒子向下移动1px,此时就出现了压盖效果.小盒子设置z-index压盖大盒子,将小盒子的下边框去掉, ...

  6. JQuery中的事件(三)

    一:页面载入 ready(fn)当DOM载入就绪可以查询及操纵时绑定一个要执行的函数.这是事件模块中最重要的一个函数,因为它可以极大地提高web应用程序的响应速度.简单地说,这个方法纯粹是对向wind ...

  7. Could not get lock /var/lib/apt/lists/lock - open (11: Resource temporarily unavailable)

    今天在对 Ubuntu 进行更新源的时候,突然出现下列错误(为了省事,更新前直接切换了 root 用户) 上网查了一下,网上解释说应该是之前那个更新被强制取消的问题,进程仍然还在.用这个命令查看一下: ...

  8. 你需要知道的 .NET

    1. 简述private.protected.public.internal 修饰符的访问权限. 答. private : 私有成员, 在类的内部才可以访问. protected : 保护成员,该类内 ...

  9. #12【BZOJ3003】LED BFS+状压DP

    题解: 看到区间修改先想一下差分 这题用差分是为了分析问题 现在的问题就变成了 原序列全为0,要使得特定的k个点变为1,每个操作改变x,y+1 然后我们会发现 对于二元组a,b我们要修改它,实际上是在 ...

  10. day6作业--游戏人生完善

    本节作业: 熟练使用类和模块,写一个交互性强.有冲突的程序.     一.作业目的 1.规范程序写法,要按照模块来规范书写: 2.类的使用,文件之间的调用练习: 3.思路的开阔,自己编写冲突,实现调用 ...