算法完善,并更新ReadMe

This commit is contained in:
yunfei li 2024-08-14 16:48:59 +08:00
parent 3f21a6b44d
commit 674988a23a
8 changed files with 128 additions and 314 deletions

View File

@ -1,5 +1,7 @@
/**
* 天空盒子相关计算函数
*/
const CatalogSkybox = {
};
/**
@ -9,42 +11,37 @@ const CatalogSkybox = {
* @param {number} y 立方盒子的y坐标,[-1,1]
* @param {number} z 立方盒子的z坐标,[-1,1]
* @returns {i,j,faceId} i为图片的x坐标(向右),[0,1],j为图片的y坐标(向下),[0,0]为图片的左上角
*
* faceId为图片的面id,[0,5]
*
* 0: mx, 1: my, 2: px, 3: py, 4: pz, 5: mz
*/
CatalogSkybox.cubeXyzToImgUV = function(x, y, z) {
let faceId, i, j;
if (x === -1) { // back,mx
//j = (1.0 - y) / 2.0;
//i = (1.0 + z) / 2.0;
j = (1.0 + y) / 2.0;
i = (1.0 + z) / 2.0;
faceId = 0;
} else if (y === -1) { // left,my
//i = (1.0 + x) / 2.0;
//j = (1.0 - z) / 2.0;
i = (1.0 + x) / 2.0;
j = (1.0 + z) / 2.0;
faceId = 1;
} else if (x === 1) { // front,px
//j = (1.0 - y) / 2.0;
//i = (1.0 - z) / 2.0;
i = (1.0 + y) / 2.0;
j = (1.0 - z) / 2.0;
j = (1.0 + y) / 2.0;
i = (1.0 - z) / 2.0;
faceId = 2;
} else if (y === 1) { // right,py
//i = (1.0 + x) / 2.0;
//j = (1.0 + z) / 2.0;
i = (1.0 + x) / 2.0;
j = (1.0 - z) / 2.0;
faceId = 3;
} else if (z === 1) { // top
} else if (z === 1) { // top,pz
i = (1.0 + x) / 2.0;
j = (1.0 - y) / 2.0;
j = (1.0 + y) / 2.0;
faceId = 4;
} else if (z === -1) { // bottom
} else if (z === -1) { // bottom,mz
i = (1.0 - x) / 2.0;
j = (1.0 - y) / 2.0;
j = (1.0 + y) / 2.0;
faceId = 5;
}
else {
@ -165,86 +162,4 @@ CatalogSkybox.sphere2CubeXyz = function (theta, phi) {
return { x, y, z };
}
/**
* 由立方体盒子某个面的图片坐标转换为对应立方盒子面的坐标
*
* @param {number} i 图片的x坐标(向右),[0,1]
* @param {number} j 图片的y坐标(向下),[0,0]为图片的左上角
* @param {number} faceId 立方盒子的面id,[0,5]
* @returns {x,y,z} 立方盒子的坐标,[-1,1]
*/
CatalogSkybox.imgUvToCubeXyz = function(i, j, faceId) {
/*
* 此函数被修改以适应cesium skybox的贴图
*/
let a = 2.0 * i ;
let b = 2.0 * j;
let x, y, z;
if (faceId === 0) { // back
// (x,y,z) = (-1.0, 1.0 - a, 1.0 - b);
x = -1.0;
y = 1.0 - b;
z = a - 1.0;
} else if (faceId === 1) { // left
x = a - 1.0;
y = -1.0;
z = 1.0 - b;
} else if (faceId === 2) { // front
// (x,y,z) = (1.0, a - 1.0, 1.0 - b);
x = 1.0;
y = 1.0 - b;
z = 1.0 - a;
} else if (faceId === 3) { // right
// (x,y,z) = (1.0 - a, 1.0, 1.0 - b);
x = a - 1.0;
y = 1.0;
z = b - 1.0;
} else if (faceId === 4) { // top
// (x,y,z) = (b - 1.0, a - 1.0, 1.0);
x = a - 1.0;
y = 1.0 - b;
z = 1.0;
} else if (faceId === 5) { // bottom
// (x,y,z) = (1.0 - b, a - 1.0, -1.0);
x = 1.0 - a;
y = 1.0 - b;
z = -1.0;
}
return { x, y, z };
}
/**
* 由立方体盒子上的坐标(单位长度为2)转换为赤经赤纬坐标
*
* @param {number} x 立方盒子的x坐标,[-1,1]
* @param {number} y 立方盒子的y坐标,[-1,1]
* @param {number} z 立方盒子的z坐标,[-1,1]
* @returns {theta, phi} theta为赤经,弧度,[-PI,PI],phi为赤纬,弧度,[-PI/2,PI/2]
*/
CatalogSkybox.cubeXyz2Sphere = function (x, y, z) {
let theta = Math.atan2(y, x);
let r = Math.sqrt(x * x + y * y);
let phi = Math.atan2(z, r);
return { theta, phi };
}
export default CatalogSkybox;

View File

@ -1,29 +0,0 @@
import CatalogSkybox from "./CatalogSkybox.js";
// 测试CatalogSkybox相关函数的正向和反向转换
// 这个文件单独运行使用node方式运行
// 20240812 blitheli
// theta从-Pi到Piphi从-Pi/2到Pi/2
// theta取100个点phi取50个点
for (let ii = 0; ii < 100; ii++) {
let theta = -Math.PI + ii * Math.PI / 50.0;
for (let jj = 0; jj < 50; jj++) {
let phi = -Math.PI / 2.0 + jj * Math.PI / 50.0;
let { x, y, z } = CatalogSkybox.sphere2CubeXyz(theta, phi);
let { i, j, faceId } = CatalogSkybox.cubeXyzToImgUV(x, y, z);
// 反向转换
let { x1, y1, z1 } = CatalogSkybox.imgUvToCubeXyz(i, j, faceId);
let { thetap, phip } = CatalogSkybox.cubeXyz2Sphere(x1, y1, z1);
if (Math.abs(theta - thetap) > 0.0001 || Math.abs(phi - phip) > 0.0001) {
console.log("error", theta, phi, thetap, phip);
}
}
}
console.log("如果没有输出其它信息,那么表明测试成功了!!");

View File

@ -1,36 +0,0 @@
# testSkybox
#### Description
{**When you're done, you can delete the content in this README and update the file with details for others getting started with your repository**}
#### Software Architecture
Software architecture description
#### Installation
1. xxxx
2. xxxx
3. xxxx
#### Instructions
1. xxxx
2. xxxx
3. xxxx
#### Contribution
1. Fork the repository
2. Create Feat_xxx branch
3. Commit your code
4. Create Pull Request
#### Gitee Feature
1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md
2. Gitee blog [blog.gitee.com](https://blog.gitee.com)
3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore)
4. The most valuable open source project [GVP](https://gitee.com/gvp)
5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help)
6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)

View File

@ -1,39 +1,35 @@
# testSkybox
# Cesium天空盒子(Skybox)制作和显示
#### 介绍
{**以下是 Gitee 平台说明,您可以替换此简介**
Gitee 是 OSCHINA 推出的基于 Git 的代码托管平台(同时支持 SVN。专为开发者提供稳定、高效、安全的云端软件开发协作平台
无论是个人、团队、或是企业,都能够用 Gitee 实现代码托管、项目管理、协作开发。企业项目请看 [https://gitee.com/enterprises](https://gitee.com/enterprises)}
在Cesium中星空背景是通过天空盒子方式6张图片来显示的原生的图片分辨率太低本项目用于生成天空盒子的6张图片。
#### 原理
星空背景本质上就是将所有的恒星投影到天空盒子对应的6个方位的图片上。
本项目利用Canvas的2D作图功能创建一个纯黑色的背景。然后根据每个恒星的位置转换为对应图片下的像素坐标然后再利用恒星
对应的星等画一个白色的点,点的像素大小和透明度由星等决定(恒星越亮,则点的像素越大,越不透明)。
目前基本设置为详见createSkyboxImage.js
- 最亮: -1等对应为5像素透明度为1.0(不透明)
- 中等: 7等对应为1像素透明度为0.75
本项目中最暗为7等星因为超过8等星人眼就看不到了
#### 软件架构
软件架构说明
#### 安装教程
1. xxxx
2. xxxx
3. xxxx
- CesiumUnminified文件夹为Cesium下载安装包里面的内容Build目录下本项目用于引用Cesium.js文件
- Skybox文件夹里存放了其它方式生成的天空盒子可供测试使用
- CatalogSkybox.js为天球坐标系ICRF到立方体盒子的投影转换相关函数
- createSkyboxImage.js用于生成立方体盒子的一副图片
- hipparcos_7_concise.js包含了依巴谷星表hipparcos的7等星以上的所有数据经过处理的来源: https://github.com/gmiller123456/hip2000
#### 使用说明
1. xxxx
2. xxxx
3. xxxx
#### 参与贡献
1. Fork 本仓库
2. 新建 Feat_xxx 分支
3. 提交代码
4. 新建 Pull Request
1. 使用Live Server打开index.html即可加载Cesium默认的启动界面同时加载了内置生成的天空盒子
2. 网页启动后会自动将创建的6张天空盒子照片存放在浏览器的下载目录下
#### 特技
#### 其它
1. 用户可自行修改createSkyboxImage.js函数使用不同的星等创建不同像素大小的星星
1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com)
3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目
4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目
5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
20240814 liyunfei

View File

@ -1,36 +0,0 @@
function createImage(width) {
// 创建width*width的jpg格式的图片背景为黑色随机生成1000个像素点颜色为白色大小从1到5像素不等
var canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = width;
var context = canvas.getContext('2d');
context.fillStyle = 'black';
context.fillRect(0, 0, width, width);
for (var i = 0; i < 10000; i++) {
var x = Math.random() * width;
var y = Math.random() * width;
var size = Math.random() * 3;
context.fillStyle = 'white';
context.fillRect(x, y, size, size);
}
var dataUrl = canvas.toDataURL('image/jpeg');
// 将这个图片插入到id为img1的img元素中
var img1 = document.getElementById('img1');
img1.src = dataUrl;
return dataUrl;
var image = new Image();
image.src = dataUrl;
return image;
// 将这个图片插入到id为img1的img元素中
//var img1 = document.getElementById('img1');
//img1.src = dataUrl;
}
export default createImage;

View File

@ -1,6 +1,22 @@
import hipparcos_catalog from "./hipparcos_7_concise.js";
import CatalogSkybox from "./CatalogSkybox.js";
// 20240814 blitheli
/**
* 由hipparcos星表数据生成天空盒子的一个面的图片
*
* 通过Canvas绘制纯黑色背景行星为白色大小和亮度与星等相关
*
* 用户可以通过这个函数生成天空盒子的6个面的图片然后通过Cesium的SkyBox类创建自定义的天空盒
*
* 目前数据为hipparcos星表数据仅考虑星等7以上亮度./hipparcos_7_concise.js
* 来源: https://github.com/gmiller123456/hip2000
* 可根据需要自行下载和替换数据
*
* @param {number} faceId0 立方体盒子的面id,0: mx, 1: my, 2: px, 3: py, 4: pz, 5: mz
* @param {number} width 图片的宽度高度也是这个值单位像素
* @returns base64格式的图片(png)
*/
function createSkyboxImage(faceId0, width) {
// 恒星亮度(等级),亮度等级越小,亮度越大
const magBright = -1;
@ -12,7 +28,7 @@ function createSkyboxImage(faceId0, width) {
const sizeDim = 0.1;
// 恒星透明度(1为不透明0为透明)
const translucentBright = 1.0;
const translucentMedium = 0.5;
const translucentMedium = 0.75;
const translucentDim = 0.2;
const d2r = Math.PI / 180;
@ -33,10 +49,11 @@ function createSkyboxImage(faceId0, width) {
var ra = star[2];
var dec = star[3];
// 赤经、赤纬转换为弧度
// 赤经原始为0-360°需要转换为[-180,180]°
if (ra > 180) {
ra = ra - 360;
}
// 赤经赤纬转换为弧度
ra = ra * d2r;
dec = dec * d2r;
@ -46,12 +63,13 @@ function createSkyboxImage(faceId0, width) {
// 转换为图片坐标i,为横坐标,向右,[0,1]), (j为纵坐标,向下,[0,1])
let { i, j, faceId } = CatalogSkybox.cubeXyzToImgUV(x, y, z);
// 不是当前盒子面的点,不绘制,直接跳过
if (faceId !== faceId0) {
continue;
}
// 像素大小
let size = sizeBright;
// 像素大小、透明度(根据星等,按照最大值和最小值线性插值)
let size = sizeBright; // 默认最大值
let translucent = translucentBright;
if (mag > magBright && mag <= magMedium) {
size =
@ -63,17 +81,13 @@ function createSkyboxImage(faceId0, width) {
((translucentBright - translucentMedium) * (mag - magMedium)) /
(magBright - magMedium);
}
// 亮度太暗,最小值
// 亮度太暗,最小值
else if (mag > magMedium) {
size = sizeDim;
translucent = translucentDim;
}
if (mag < 1) {
console.log(mag, size, translucent);
}
// 图像坐标系下的坐标
// 图像坐标系下的坐标(考虑到图片的大小,精确到实际的像素坐标)
let u = i * width - size / 2;
let v = j * width - size / 2;
if (u < 0) {
@ -88,20 +102,10 @@ function createSkyboxImage(faceId0, width) {
context.fillRect(u, v, size, size);
}
// 生成base64格式的图片
var dataUrl = canvas.toDataURL("image/jpeg");
// 将这个图片插入到id为img1的img元素中
//var img1 = document.getElementById('img1');
//img1.src = dataUrl;
return dataUrl;
var image = new Image();
image.src = dataUrl;
return image;
// 将这个图片插入到id为img1的img元素中
//var img1 = document.getElementById('img1');
//img1.src = dataUrl;
}
export default createSkyboxImage;

View File

@ -31,16 +31,73 @@
</head>
<body>
<div id="cesiumContainer"></div>
<div >
<img
id="img1"
src="./Skybox/SkyCube2k/skyCube2k_my.jpg"
alt="skyCube2k_px.jpg"
width="1024"
height="1024"
/>
</div>
<script type="module" src = './main.js' >
<script type="module">
import createSkyboxImage from "./createSkyboxImage.js";
// 请使用你自己的Cesium ion access token!!
// Cesium ion access token.
Cesium.Ion.defaultAccessToken =
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI4M2ZhYzM4My1lN2NhLTRjNTktODY1OC1jZDdmOTU3Y2ZjMGEiLCJpZCI6MTMwNTAsInNjb3BlcyI6WyJhc3IiLCJnYyJdLCJpYXQiOjE1NjI0NzA5NzB9.rRTs6chsWJdo9KNYe5VjJj2fUzMHeniIJvFQOd0aLJU";
// 初始化Cesium Viewer
const viewer = new Cesium.Viewer("cesiumContainer");
// 创建天空盒子的6个面的图片
const width = 8192; // 单个图片的宽度和高度(像素)
const mx = createSkyboxImage(0, width);
const my = createSkyboxImage(1, width);
const px = createSkyboxImage(2, width);
const py = createSkyboxImage(3, width);
const pz = createSkyboxImage(4, width);
const mz = createSkyboxImage(5, width);
// 更改天空盒(可通过注释切换不同的天空盒)
viewer.scene.skyBox = new Cesium.SkyBox({
sources: {
/*
positiveX: "./Skybox/starmap_2020_16k/starmap_2020_16k_px.jpg",
negativeX: "./Skybox/starmap_2020_16k/starmap_2020_16k_mx.jpg",
positiveY: "./Skybox/starmap_2020_16k/starmap_2020_16k_py.jpg",
negativeY: "./Skybox/starmap_2020_16k/starmap_2020_16k_my.jpg",
positiveZ: "./Skybox/starmap_2020_16k/starmap_2020_16k_pz.jpg",
negativeZ: "./Skybox/starmap_2020_16k/starmap_2020_16k_mz.jpg",
*/
/*
positiveX: "./Skybox/SkyCube2k/skyCube2k_px.jpg",
negativeX: "./Skybox/SkyCube2k/skyCube2k_mx.jpg",
positiveY: "./Skybox/SkyCube2k/skyCube2k_py.jpg",
negativeY: "./Skybox/SkyCube2k/skyCube2k_my.jpg",
positiveZ: "./Skybox/SkyCube2k/skyCube2k_pz.jpg",
negativeZ: "./Skybox/SkyCube2k/skyCube2k_mz.jpg",
*/
positiveX: px,
negativeX: mx,
positiveY: py,
negativeY: my,
positiveZ: pz,
negativeZ: mz,
},
});
// 下载天空盒图片(6张)(通过网页下载,下载的图片在浏览器的下载目录里)
const names = ["mx", "my", "px", "py", "pz", "mz"];
const hrefs = [mx, my, px, py, pz, mz];
for (let i = 0; i < 6; i++) {
// 创建下载链接
const link = document.createElement("a");
link.download = "hippa2_" + width + "_" + names[i] + `.png`;
link.href = hrefs[i];
// 模拟点击下载链接
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
// 显示帧率
viewer.scene.debugShowFramesPerSecond = true;
</script>
</body>
</html>

57
main.js
View File

@ -1,57 +0,0 @@
import createSkyboxImage from "./createSkyboxImage.js";
// Cesium ion access token.
Cesium.Ion.defaultAccessToken =
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI4M2ZhYzM4My1lN2NhLTRjNTktODY1OC1jZDdmOTU3Y2ZjMGEiLCJpZCI6MTMwNTAsInNjb3BlcyI6WyJhc3IiLCJnYyJdLCJpYXQiOjE1NjI0NzA5NzB9.rRTs6chsWJdo9KNYe5VjJj2fUzMHeniIJvFQOd0aLJU";
console.log("Cesium 启动");
const viewer = new Cesium.Viewer("cesiumContainer");
const width = 3522;
const py = createSkyboxImage(2, width);
/*
const py = createImage( width);
const pz = createImage( width);
const nx = createImage( width);
const ny = createImage( width);
const nz = createImage( width);
*/
// 自定义的天空盒
viewer.scene.skyBox = new Cesium.SkyBox({
sources: {
positiveX: "./Skybox/SkyCube2k/skyCube2k_px.jpg",
negativeX: "./Skybox/SkyCube2k/skyCube2k_mx.jpg",
positiveY: "./Skybox/SkyCube2k/skyCube2k_py.jpg",
negativeY: "./Skybox/SkyCube2k/skyCube2k_my.jpg",
positiveZ: "./Skybox/SkyCube2k/skyCube2k_pz.jpg",
negativeZ: "./Skybox/SkyCube2k/skyCube2k_mz.jpg",
/*
positiveX: px,
negativeX: nx,
positiveY: py,
negativeY: ny,
positiveZ: pz,
negativeZ: nz,
*/
},
});
// 创建下载链接
const link = document.createElement('a');
link.download = 'px.jpg';
link.href = py;
// 模拟点击下载链接
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
// 显示帧率
viewer.scene.debugShowFramesPerSecond = true;