rskynet 是用 Rust 语言编写的小程序,虽然它的名字叫天网(Skynet),但它的确是一个小程序,代码不足千行,以后也不会有更多的代码。之所以写这个程序,一是为了熟悉 Rust 语言,二是为了便于可视化我的一些三维数据。rskynet 的前身是一份用 Python 3 写的脚本,名字叫 hamal [1]。二者功能基本相同,但 rskynet 在选择三维场景的观察方位更为容易,因为它实现了当初我的一个构想 [2],即在场景的包围球上,以经纬度的方式构造观察方位。
源码的获取和编译
$ git clone https://gitee.com/garfileo/rskynet.git
$ cd rskynet
$ rustc -O rskynet.rs
用法
在 rskynet/data 目录,我提供了 5 份三维数据文件作为示例,其类型分别是点集(points.asc)、矢量集(vectors.asc)、线段集(paths.asc)、轴向盒集(boxes.asc),曲面网格(mesh.off),要实现它们的可视化,只需
# 渲染点集
$ rskynet --points points.asc
$ povray +A +P points.pov
# 渲染矢量集
$ rskynet --vectors vectors.asc
$ povray +A +P vectors.pov
# 渲染路径集
$ rskynet --paths paths.asc
$ povray +A +P paths.pov
# 渲染轴向盒集
$ rskynet --boxes boxes.asc
$ povray +A +P boxes.pov
# 曲面网格
$ rskynet --mesh mesh.asc
$ povray +A +P mesh.pov
rskynet 输出了什么?
以点集为例,将点集文件 foo.asc 输入 rskynet,亦即
$ rskynet --points foo.asc
rskynet 可在当前目录输出以下文件:
.
├── foo.inc
├── foo.ini
├── foo_object.inc
├── foo.pov
└── foo_view.inc
其中,foo.pov 用于汇总其他文件内容,形成完整的三维场景。
上述示例生成的 foo.pov 内容如下:
#version 3.7;
#include "colors.inc"
global_settings {assumed_gamma 1.0}
// 相机参数(可根据需要,自行修改)
#declare sky_u = 0;
#declare sky_v = 0;
#declare theta = 0;
#declare odc = 3; // Object distance coefficient.
// 系统参数(不建议自行修改)
#declare bs_center = <-0.278, 4.010, -2.365>; // 包围球中心
#declare bs_r = 156.802; // 包围球半径
#declare sky_r = odc * bs_r; // 天球半径
// 点、矢量、线段的尺寸参数
#declare point_size = 0.0025 * sky_r;
#declare line_width = 0.75 * point_size;
#declare arrow_size = point_size;
#include "foo_view.inc"
#include "foo_object.inc"
即使对 POV Ray 场景语言不熟悉也无妨,只需知道以下参数决定着三维场景的观察方位:
// 相机参数(可根据需要,自行修改)
#declare sky_u = 0;
#declare sky_v = 0;
#declare theta = 0;
#declare odc = 3; // Object distance coefficient.
其中,sky_u
和 sky_v
表示场景包围球的经度和纬度,其值若为正数分别表示东经和北纬,负数表示西经和南纬。theta
表示相机倾角,正数向右倾斜,负数表示向左倾斜。odc
是决定了场景包围球的大小,其值为 1 时,场景包围球近似为场景中所有三维数据的包围球,可以通过 odc
控制场景的放大和缩小。
三维观察
下图是基于默认的相机参数的渲染结果:
倘若将相机的经度参数修改为
#declare sky_u = 90;
则渲染结果变为:
将相机倾斜角度参数修改为
#declare theta = -90;
渲染结果变为
倘若将 sky_u
和 theta
固定下来,不断修改 sky_v
的值,相当于在东经 90 度的经线上的各个维度查看图形。
倘若将 odc
的值缩小,可以观察到三维数据的局部,为了近距离看到点数据,也可以将 point_size
的值增大,例如:
#declare odc = 0.3;
... ... ...
#declare point_size = 0.01 * sky_r;
可得以下结果:
在通过经纬度和相机倾角构造观察方位时,务必记住,默认的初始方位是经纬皆为 0,且相机倾斜角度为零,此时相当于相机在赤道的经纬度为 0 的位置,头朝正北,向下俯瞰。倘若将相机移动到其他经纬坐标时,其顶端朝向与经线相切且指向北方,此时需要设身处地思考相机的倾角如何调整以获得符合需要的观察方位。
结语
若觉得 rskynet 有些用处,最好学一些 POV Ray 的基本知识,相信我,没那么难,浅尝辙止亦可。
Rust 不好用,特别是泛型,束手束脚,似乎是希望大家写代码时最好别用泛型……相形之下,我还是喜欢 C,感觉自己没救了。
[1] https://segmentfault.com/a/11...
[2] https://segmentfault.com/a/11...