WHY数学表达式的3D可视化
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可视化的更多相关文章
- 基于语法分析器GOLD Parser开发的数学表达式计算器
最近发现一款文法分析神器,看完官网(http://goldparser.org/)的介绍后感觉很犀利的样子,于是就拿来测试了一番,写了一个数学表达式分析的小程序,支持的数学运算符如下所示:常规运算:+ ...
- 基于 HTML5 WebGL 的挖掘机 3D 可视化应用
前言 在工业互联网以及物联网的影响下,人们对于机械的管理,机械的可视化,机械的操作可视化提出了更高的要求.如何在一个系统中完整的显示机械的运行情况,机械的运行轨迹,或者机械的机械动作显得尤为的重要,因 ...
- 基于 HTML5 + WebGL 的 3D 可视化挖掘机
前言 在工业互联网以及物联网的影响下,人们对于机械的管理,机械的可视化,机械的操作可视化提出了更高的要求.如何在一个系统中完整的显示机械的运行情况,机械的运行轨迹,或者机械的机械动作显得尤为的重要,因 ...
- 理解CSS中的数学表达式calc()
前面的话 数学表达式calc()是CSS中的函数,主要用于数学运算.使用calc()为页面元素布局提供了便利和新的思路.本文将介绍calc()的相关内容 定义 数学表达式calc()是calculat ...
- Qt计算器开发(二):信号槽实现数学表达式合法性检查
表达式的合法性 由于我们的计算器不是单步计算的,所以我们能够一次性输入一个长表达式.然而假设用户输入的长表达式不合法的话,那么就会引发灾难.所以有必要对于用户的输入做一个限制. 一些限制举例: 比方, ...
- 基于 HTML5 WebGL 的地铁站 3D 可视化系统
前言 工业互联网,物联网,可视化等名词在我们现在信息化的大背景下已经是耳熟能详,日常生活的交通,出行,吃穿等可能都可以用信息化的方式来为我们表达,在传统的可视化监控领域,一般都是基于 Web SCAD ...
- 分享数百个 HT 工业互联网 2D 3D 可视化应用案例
过去的 2018 年,我们认为是国内工业互联网可视化的元年,图扑软件作为在工业可视化领域的重度参与者,一线见证了众多 HTML5/Web 化.2D/3D 化的项目在工业界应用落地,我们觉得有必要在此分 ...
- 基于 WebGL 的 HTML5 楼宇自控 3D 可视化监控
前言 智慧楼宇和人们的生活息息相关,楼宇智能化程度的提高,会极大程度的改善人们的生活品质,在当前工业互联网大背景下受到很大关注.目前智慧楼宇可视化监控的主要优点包括: 智慧化 -- 智慧楼宇是一个生态 ...
- 基于 HTML5 的 WebGL 楼宇自控 3D 可视化监控
前言 智慧楼宇和人们的生活息息相关,楼宇智能化程度的提高,会极大程度的改善人们的生活品质,在当前工业互联网大背景下受到很大关注.目前智慧楼宇可视化监控的主要优点包括: 智慧化 -- 智慧楼宇是一个生态 ...
随机推荐
- 温故而知新--JavaScript书摘(三)
前言 毕业到入职腾讯已经差不多一年的时光了,接触了很多项目,也积累了很多实践经验,在处理问题的方式方法上有很大的提升.随着时间的增加,愈加发现基础知识的重要性,很多开发过程中遇到的问题都是由最基础的知 ...
- pytest十:用例 a 失败,跳过测试用例 b 和 c 并标记失败 xfail
当用例 a 失败的时候,如果用例 b 和用例 c 都是依赖于第一个用例的结果,那可以直接跳过用例 b 和 c 的测试,直接给他标记失败 xfail用到的场景,登录是第一个用例,登录之后的操作 b 是第 ...
- springMVC3学习--ModelAndView对象(转)
原文链接:springMVC3学习(二)--ModelAndView对象 当控制器处理完请求时,通常会将包含视图名称或视图对象以及一些模型属性的ModelAndView对象返回到DispatcherS ...
- ERP合同审核流程处理(二十九)
合同审批流程: 前端的代码: <%@ Page Language="C#" AutoEventWireup="true" CodeBehind=" ...
- Javascript中类的实现机制(四)
一: 理解类的实现机制 在JavaScript中可以使用function关键字来定义一个“类”,如何为类添加成员.在函数内通过this指针引用的变量或者方法都会成为类的成员,例如:function ...
- git的入门摸索和入门研究
git官网:https://git-scm.com/ git教程---菜鸟教程:http://www.runoob.com/git/git-tutorial.html git教程---廖雪峰:http ...
- 利用mysqldump 实现每天备份方案
1.创建单独的导出导入数据库帐号 grant SELECT, RELOAD, SHOW DATABASES, LOCK TABLES on game to jackluo@localhost iden ...
- android-getTextSize返回值是以像素(px)为单位的,setTextSize()以sp为单位
使用如下代码时,发现字号不会变大,反而会变小:size = (int) mText.getTextSize() + 1;mText.setTextSize(size);后来发现getTextSize返 ...
- python ThreadLocal
ThreadLocal: 主要是为了解决各个线程引用全局变量,并且各个线程之间互不影响而设置的. 实例: import threading threadlocal = threading.local( ...
- Codeforces 295C Greg and Friends BFS
Greg and Friends BFS的过程中维护一下方案数. 我个人感觉不是很好想, 但是写出来之后怎么感觉这题这么SB啊啊. #include<bits/stdc++.h> #def ...