将球体映射到立方体

2024-03-09

这里描述了一种将立方体映射到球体的特殊方法:http://mathproofs.blogspot.com/2005/07/mapping-cube-to-sphere.html http://mathproofs.blogspot.com/2005/07/mapping-cube-to-sphere.html

这不是您基本的“标准化点就完成了”的方法,并且提供了更均匀间隔的映射。

我尝试进行从球体坐标到立方体坐标的映射的逆操作,但无法得出工作方程。这是一个相当复杂的方程组,有很多平方根。

有数学天才想尝试一下吗?

这是 C++ 代码中的方程:

sx = x * sqrtf(1.0f - y * y * 0.5f - z * z * 0.5f + y * y * z * z / 3.0f);

sy = y * sqrtf(1.0f - z * z * 0.5f - x * x * 0.5f + z * z * x * x / 3.0f);

sz = z * sqrtf(1.0f - x * x * 0.5f - y * y * 0.5f + x * x * y * y / 3.0f);

sx,sy,sz 是球体坐标,x,y,z 是立方体坐标。


我想将此归功于 gmatt,因为他做了很多工作。我们的答案唯一的区别是 x 的方程。

要进行从球体到立方体的逆映射,首先确定球体点投影到的立方体面。这一步很简单 - 只需找到具有最大长度的球体向量的分量,如下所示:

// map the given unit sphere position to a unit cube position
void cubizePoint(Vector3& position) {
    double x,y,z;
    x = position.x;
    y = position.y;
    z = position.z;

    double fx, fy, fz;
    fx = fabsf(x);
    fy = fabsf(y);
    fz = fabsf(z);

    if (fy >= fx && fy >= fz) {
        if (y > 0) {
            // top face
            position.y = 1.0;
        }
        else {
            // bottom face
            position.y = -1.0;
        }
    }
    else if (fx >= fy && fx >= fz) {
        if (x > 0) {
            // right face
            position.x = 1.0;
        }
        else {
            // left face
            position.x = -1.0;
        }
    }
    else {
        if (z > 0) {
            // front face
            position.z = 1.0;
        }
        else {
            // back face
            position.z = -1.0;
        }
    }
}

对于每个面 - 获取表示为 s 和 t 的剩余立方体向量分量,并使用这些方程求解它们,这些方程基于表示为 a 和 b 的剩余球体向量分量:

s = sqrt(-sqrt((2 a^2-2 b^2-3)^2-24 a^2)+2 a^2-2 b^2+3)/sqrt(2)
t = sqrt(-sqrt((2 a^2-2 b^2-3)^2-24 a^2)-2 a^2+2 b^2+3)/sqrt(2)

您应该看到两个方程中都使用了内部平方根,因此该部分只需执行一次。

这是最终的函数,其中包含方程并检查 0.0 和 -0.0 以及正确设置立方体分量符号的代码 - 它应该等于球体分量的符号。

void cubizePoint2(Vector3& position)
{
    double x,y,z;
    x = position.x;
    y = position.y;
    z = position.z;

    double fx, fy, fz;
    fx = fabsf(x);
    fy = fabsf(y);
    fz = fabsf(z);

    const double inverseSqrt2 = 0.70710676908493042;

    if (fy >= fx && fy >= fz) {
        double a2 = x * x * 2.0;
        double b2 = z * z * 2.0;
        double inner = -a2 + b2 -3;
        double innersqrt = -sqrtf((inner * inner) - 12.0 * a2);

        if(x == 0.0 || x == -0.0) { 
            position.x = 0.0; 
        }
        else {
            position.x = sqrtf(innersqrt + a2 - b2 + 3.0) * inverseSqrt2;
        }

        if(z == 0.0 || z == -0.0) {
            position.z = 0.0;
        }
        else {
            position.z = sqrtf(innersqrt - a2 + b2 + 3.0) * inverseSqrt2;
        }

        if(position.x > 1.0) position.x = 1.0;
        if(position.z > 1.0) position.z = 1.0;

        if(x < 0) position.x = -position.x;
        if(z < 0) position.z = -position.z;

        if (y > 0) {
            // top face
            position.y = 1.0;
        }
        else {
            // bottom face
            position.y = -1.0;
        }
    }
    else if (fx >= fy && fx >= fz) {
        double a2 = y * y * 2.0;
        double b2 = z * z * 2.0;
        double inner = -a2 + b2 -3;
        double innersqrt = -sqrtf((inner * inner) - 12.0 * a2);

        if(y == 0.0 || y == -0.0) { 
            position.y = 0.0; 
        }
        else {
            position.y = sqrtf(innersqrt + a2 - b2 + 3.0) * inverseSqrt2;
        }

        if(z == 0.0 || z == -0.0) {
            position.z = 0.0;
        }
        else {
            position.z = sqrtf(innersqrt - a2 + b2 + 3.0) * inverseSqrt2;
        }

        if(position.y > 1.0) position.y = 1.0;
        if(position.z > 1.0) position.z = 1.0;

        if(y < 0) position.y = -position.y;
        if(z < 0) position.z = -position.z;

        if (x > 0) {
            // right face
            position.x = 1.0;
        }
        else {
            // left face
            position.x = -1.0;
        }
    }
    else {
        double a2 = x * x * 2.0;
        double b2 = y * y * 2.0;
        double inner = -a2 + b2 -3;
        double innersqrt = -sqrtf((inner * inner) - 12.0 * a2);

        if(x == 0.0 || x == -0.0) { 
            position.x = 0.0; 
        }
        else {
            position.x = sqrtf(innersqrt + a2 - b2 + 3.0) * inverseSqrt2;
        }

        if(y == 0.0 || y == -0.0) {
            position.y = 0.0;
        }
        else {
            position.y = sqrtf(innersqrt - a2 + b2 + 3.0) * inverseSqrt2;
        }

        if(position.x > 1.0) position.x = 1.0;
        if(position.y > 1.0) position.y = 1.0;

        if(x < 0) position.x = -position.x;
        if(y < 0) position.y = -position.y;

        if (z > 0) {
            // front face
            position.z = 1.0;
        }
        else {
            // back face
            position.z = -1.0;
        }
    }

因此,这个解决方案并不像立方体到球体的映射那么漂亮,但它完成了工作!

任何提高上述代码的效率或可读性的建议都将受到赞赏!

- - 编辑 - - 我应该提到,我已经对此进行了测试,到目前为止,在我的测试中,代码显示正确,结果至少精确到小数点后第七位。这是我使用浮点数时的情况,现在使用双精度数可能更准确。

- - 编辑 - - 这是 Daniel 优化的 glsl 片段着色器版本,以表明它不必是一个如此大的可怕函数。丹尼尔用它来过滤立方体贴图上的采样!好想法!

const float isqrt2 = 0.70710676908493042;

vec3 cubify(const in vec3 s)
{
float xx2 = s.x * s.x * 2.0;
float yy2 = s.y * s.y * 2.0;

vec2 v = vec2(xx2 – yy2, yy2 – xx2);

float ii = v.y – 3.0;
ii *= ii;

float isqrt = -sqrt(ii – 12.0 * xx2) + 3.0;

v = sqrt(v + isqrt);
v *= isqrt2;

return sign(s) * vec3(v, 1.0);
}

vec3 sphere2cube(const in vec3 sphere)
{
vec3 f = abs(sphere);

bool a = f.y >= f.x && f.y >= f.z;
bool b = f.x >= f.z;

return a ? cubify(sphere.xzy).xzy : b ? cubify(sphere.yzx).zxy : cubify(sphere);
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将球体映射到立方体 的相关文章

  • 与两点相交的圆心

    给定 2D 平面上的两个点 以及与这两个点相交的半径为 r 的圆 计算该圆中心的公式是什么 我意识到圆圈可以放置在两个地方 当从任意角度开始扫描围绕其中一个点连接两个点的线时 我希望首先沿顺时针方向遇到其中心的圆 我想这是我的问题的下一阶段
  • 从三点求圆心的算法是什么?

    我在圆的圆周上有三个点 pt A A x A y pt B B x B y pt C C x C y 如何计算圆心 在Processing Java 中实现它 我找到了答案并实施了一个可行的解决方案 pt circleCenter pt A
  • 这个按位运算如何检查 2 的幂?

    我正在看一些应该很简单的代码 但我的数学在这里严重失败 下面是一个使用以下条件检查数字是否为 2 的幂的条件 if num 1 num num 1 make num pow of 2 我的问题是 如何在 num 和 num 1 之间使用按位
  • 在网络上编写数学方程的最佳方法是什么?

    Locked 这个问题及其答案是locked help locked posts因为这个问题是题外话 但却具有历史意义 目前不接受新的答案或互动 我正在开发一个与数学相关的网页 并正在寻找一种将数学方程轻松写入网页的解决方案 目前我可以使用
  • 通过三点的贝塞尔曲线

    我已经阅读了类似的主题以找到解决方案 但没有成功 我想做的是使该工具与 CorelDraw 中的工具相同 名为 钢笔工具 我通过连接贝塞尔三次曲线来做到这一点 但仍然缺少一个功能 即拖动曲线 而不是控制点 以编辑其形状 我可以成功确定曲线上
  • C++ 中求幂的函数是什么?

    如何计算一个数的幂 2 1 2 2 2 3 etc cmath 库中的 pow 更多信息here http en cppreference com w cpp numeric math pow 别忘了放 include
  • 如果是 @ConstructorResult,@SqlResultSetMapping 应该放在哪里

    我正在尝试使用jpa的entityManager的createNativeQuery方法映射非实体pojo 通过使用这样的东西 SqlResultSetMapping name ResultMapping classes Construct
  • 比较批处理文件中的两个数字

    我在这个网站上搜索了我的问题 但没有找到解决我问题的方法 系统为玩家和计算机提供一个从 2 到 12 的随机数 这有 3 部分 X 大于 Y 如果 X 小于 Y 以及当 X 与 Y 相同 当我开始 bat 效果很好 我选择Play Game
  • 在球体边缘绘制点

    因此 来自 Flash 背景的我对一些简单的 2D 三角函数有很好的理解 在带有 I 圆的二维中 我知道使用给定角度和半径将项目放置在边缘上的数学 x cos a r y sin a r 现在 如果我在 3d 空间中有一个点 我知道球体的半
  • 为什么我的 NHibernate 包集合没有动态设置子项的“父 ID”?

    我有一个新对象 其中包含一些作为 IList 属性的新对象的集合 我通过sql探查器看到正在执行两个插入查询 一个用于父级 它具有新的guid id 另一个用于子级 但是 引用父级的子级上的外键是一个空guid 这是我在父级上的映射
  • 有 JavaScript 的微积分库吗? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 有人知道 JavaScript 的微积分库吗 我做了一些谷歌搜索 但没有想出任何东西 我申请了 Wolf
  • Fluent NHibernate 日期时间 UTC

    我想创建一个流畅的 nhibernate 映射来通过以下方式映射 DateTime 字段 保存时 保存 UTC 值 读取时 调整为本地时区值 实现此映射的最佳方法是什么 就我个人而言 我会将日期存储在 UTC 格式的对象中 然后在读 写时在
  • python:查找围绕某个 GPS 位置的圆的 GPS 坐标的优雅方法

    我有一组以十进制表示的 GPS 坐标 并且我正在寻找一种方法来查找每个位置周围半径可变的圆中的坐标 这是一个例子 http green and energy com downloads test circle html我需要什么 这是一个圆
  • 三角形纹理映射OpenGL

    我正在开发一个使用 Marching Cubes 算法并将数据更改为 3D 模型的项目 现在我想在 OpenGL 中为我的 3D 模型使用纹理映射 我首先尝试了一个简单的示例 它将图片映射到三角形上 这是我的代码 int DrawGLSce
  • 矩阵乘法 - 视图/投影、世界/投影等

    在 HLSL 中有很多矩阵乘法 虽然我了解如何以及在何处使用它们 但我不确定它们是如何导出的或它们的实际目标是什么 所以我想知道是否有在线资源可以解释这一点 我特别好奇将世界矩阵乘以视图矩阵以及世界 视图矩阵乘以投影矩阵背后的目的是什么 您
  • 选择一组数字以达到最小总数的算法

    给定 一组数字n 1 n 2 n 3 n x 还有一个数字M 我想找到最好的组合 n a n b n c n gt M 该组合应达到达到或超过 M 所需的最小值 没有其他组合可以提供更好的结果 将在 PHP 中执行此操作 因此可以使用 PH
  • 从 x,y 屏幕空间坐标查找 2D 等距网格上的列、行(将方程转换为函数)

    我试图在屏幕空间点 x y 的二维等距网格中找到行 列 现在我几乎知道我需要做什么 即找到上图中红色向量的长度 然后将其与表示网格边界的向量的长度 由黑色向量表示 进行比较 现在我在数学堆栈交换中寻求帮助 以获得用于计算点 x y 与黑色边
  • 如何将Excel中的每个条目转换为一行“矩阵”表

    我有类似的东西 1 2 3 a x o x b x x o c o o o 并想将其转换成像这样的线 1 a x 1 b x 1 c x 2 a o 2 b x 2 c o 3 a x 3 b o 3 c o 通过使用Excel文档中的公式
  • 为什么我的圈子值为零?

    这是我的 Circle 类代码 class Circle private double radius private double area public Circle double radius this radius radius pu
  • 计算移动的球与移动的线/多边形碰撞的时间(2D)

    我有一个多边形 里面有一个移动的球 如果球撞到边界 它应该反弹回来 My current solution I split the polygon in lines and calculate when the ball hits the

随机推荐

  • 反斜杠后是否允许有空格来继续一行(在 C/C++ 中)[重复]

    这个问题在这里已经有答案了 使用时 要续行 是否允许有空格after反斜杠 在同一行 换行符应紧接在反斜杠之后 C 标准 N4140 状态 2 2 翻译阶段 反斜杠字符的每个实例 紧随其后的换行符被删除 拼接物理源线以形成逻辑源线 任何物理
  • 将 django 应用程序移动到子文件夹和 url.py 错误

    我有一个关于将 django 应用程序放入 apps 子目录的问题 我在项目根目录中有一个名为 faktura 的应用程序 我不喜欢它放在那里 我想将所有应用程序存储在 apps 子目录下 所以 我发现我可以将python路径扩展到 app
  • MVC 5 ViewBag 安全性

    我正在编写一个 MVC 互联网应用程序 我有一个关于使用 ViewBag 的问题 在我的许多控制器中 我都有 SelectList 对象 用户可以在其中选择一个对象 所选对象是我的模型的外键值 我的问题是 我应该使用 ViewBag 吗 V
  • 使用 htaccess 将 HTTP GET 请求重写为 Apache 中的 POST

    我需要更改第三方 PHP 应用程序的行为 并在此后不久恢复更改 如果我可以重写 GET 请求并从中生成 POST 请求 我将节省大量时间 并且可以避免在应用程序中进行任何更改 是否可以改造GEThttp website action1 pa
  • 如何用C语言打印

    一个 C 初学者 事实上这是我的第一个测试程序 我实际上不知道如何将该数字打印到终端 include
  • 我可以同时使用 setupWithNavController 和 setOnNavigationItemSelectedListener

    我有一个带有 BottomNavigationView 的活动 其中包含 5 个项目和片段来显示页面 我将 NavController 设置如下 NavigationUI setupWithNavController mBottomNavi
  • PHP 获取前一个数组元素并知道当前数组键

    我有一个带有特定键的数组 array 420 gt array 430 gt array 555 gt array 在我的应用程序中 我知道当前的密钥 例如555 我想获取前一个数组元素 在此示例中 它是带有键的数组元素430 我怎样才能在
  • MQTT:如何知道 puback 是针对哪条消息的?

    我正在尝试设置一个 MQTT 服务器 它将客户端发送的消息保存到本地数据库中 每条消息都有一个 成功接收 标志 当接收客户端为收到的每条消息 QOS 1 返回 puback 时 我想翻转该标志 问题是 当我发布消息时 服务器正确接收从接收客
  • Symfony 2 多个应用程序?

    这似乎是与 Symfony2 相关的最可怕的话题 因为经过一周的搜索和测试 我仍然找不到答案 简而言之 我正在构建一个具有多个子域的应用程序 我希望为所有子域提供不同的配置 同时共享来自 src 的多个捆绑包 更重要的是 导入中央配置和路由
  • Spring Data JPA:删除乐观锁定语义

    有一个实体Foo with a Version柱子 如果我想删除它 我希望 Spring Data JPA 和 或 Hibernate 检查 Version列与数据库中的列匹配 如果不符合 则应拒绝删除 对于独立实体来说 这可以按预期工作
  • 为什么在 Javascript 的 array.forEach 回调中提供数组参数?

    Javascript 的数组迭代函数 forEach every some等 允许您传递三个参数 当前项 当前索引和正在操作的数组 我的问题是 与通过闭包访问数组相比 将数组作为参数进行操作有什么好处 我为什么要使用这个 myArray f
  • Github Desktop - 作者身份未知

    我正在使用 github 桌面上传一些基本网站的代码 然后使用 github 页面 但是 每次我尝试提交到 main 时 都会出现错误 提示 作者身份未知 我知道我必须将我的姓名和电子邮件放入文件中 但是其中有两个带有 JavaScript
  • 可变参数函数 - 如何确保参数正确传递

    有没有什么方法 内置或代码模式 来确保向可变参数函数传递正确数量的参数 显然 这将作为 API 的一部分包含在内 我可以检查我自己的内部代码 我正在考虑要求 UN32 Magic Number 作为最后一个传递的参数 并检查可变参数函数的有
  • “tensorboard”不被识别为内部或外部命令,

    刚刚开始使用 Tensorflow 但我无法在 cmd 上使用 tensorboard 命令 它给出了错误命令 C Users tushar PycharmProjects gt tensorboard logdir NewTF tenso
  • AngularJS 和 ReactJS 之间的主要区别是什么

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我需要创建一个将转换为移动应用程序的网站 我想要构建的内容更适合成为网站而不是应用程序 因此建筑物本身应该作为网站 由于我更熟悉桌面和
  • Camel Apache:从接收到的 XML 中提取一些值的 xpath

    在我的 Camel 路由期间 我查询服务器 HTTP GET 结果 我收到一个 200 OK 其 XML 正文看起来类似如下
  • PHP websocket 连接到 node.js 服务器

    我有简单的 node js websocket 服务器 var fs require fs var ws require var options secure false var Server ws createServer options
  • 从 Graph API 中删除照片标签

    我正在尝试创建一个应用程序来帮助用户删除不需要的标签 我听到很多人抱怨 FB 不再允许公众访问删除图片 标签也是如此吗 I get error type OAuthException message 3 Application does n
  • 无法从存储“C:\Users\....\.android\debug.keystore”读取密钥 AndroidDebugKey:密钥库格式无效

    我正在尝试在 android studio 中发布一个简单的项目 所以我转到菜单 gt 构建 gt 构建 apk 但是我收到此错误 Error Execution failed for task app packageDebug gt Fa
  • 将球体映射到立方体

    这里描述了一种将立方体映射到球体的特殊方法 http mathproofs blogspot com 2005 07 mapping cube to sphere html http mathproofs blogspot com 2005