ryan‘s blog 0x1

一、粗略步骤 

#notice:部分内容在gpt4的协助下创作

要在平面上绘制一个具有空间三维坐标的长方体,你可以采取以下几个步骤。这个过程涉及将三维坐标转换为二维平面上的点,并连接这些点以形成长方体的轮廓。这种转换通常涉及一些形式的投影,如正投影、透视投影等。下面是一个基本的指南:

1. 确定投影类型

首先,你需要决定使用哪种类型的投影。最常见的有:

  • 正投影(Orthographic Projection):在这种投影中,三维空间中的点直接映射到二维平面上,忽略深度。这意味着远近物体的大小不会因距离变化而变化。
  • 透视投影(Perspective Projection):在透视投影中,三维空间中的点会根据它们与观察点的距离进行变换,模拟人眼的视觉效果。远处的对象会看起来比近处的对象小。

2. 定义三维坐标

假设你已经有了长方体每个顶点的三维坐标(x, y, z),这些坐标定义了长方体在空间中的位置和形状。

3. 转换坐标(可选)

根据选择的投影类型,你可能需要转换这些三维坐标到二维平面上。对于简化的正投影,你可以直接忽略Z轴(深度),使用(x, y)作为平面坐标。对于透视投影,你需要根据透视规则调整每个点的x和y坐标,以模拟深度效果。

4. 绘制长方体

在二维平面上,使用转换后的二维坐标来连接各个顶点。长方体有12条边,你需要按正确的顺序连接这些点,以形成长方体的轮廓。

如果你想通过编程方式在计算机屏幕上完成这一过程,你可以使用各种图形库或API,如HTML5的Canvas API、SVG或Three.js(对于三维到二维的投影)。以下是一个使用Canvas API的简化示例,仅用于说明如何在二维平面上绘制长方体的轮廓:


// 假设我们已经计算好了长方体在二维平面上的投影坐标
const vertices2D = [
    {x: 100, y: 100}, // 顶点1
    {x: 200, y: 100}, // 顶点2
    {x: 200, y: 200}, // 顶点3
    {x: 100, y: 200}, // 顶点4
    {x: 150, y: 150}, // 顶点5(对应顶点1的透视或正投影)
    {x: 250, y: 150}, // 顶点6(对应顶点2的透视或正投影)
    {x: 250, y: 250}, // 顶点7(对应顶点3的透视或正投影)
    {x: 150, y: 250}, // 顶点8(对应顶点4的透视或正投影)
];

// 使用Canvas API绘制长方体
function drawCube(vertices, context) {
    context.beginPath();
    // 绘制前面的矩形
    for (let i = 0; i < 4; i++) {
        context.lineTo(vertices[i].x, vertices[i].y);
    }
    context.closePath();
    // 绘制后面的矩形
    context.moveTo(vertices[4].x, vertices[4].y);
    for (let i = 4; i < 8; i++) {
        context.lineTo(vertices[i].x, vertices[i].y);
    }
    context.closePath();
    // 连接前面和后面的顶点
    for (let i = 0; i < 4; i++) {
        context.moveTo(vertices[i].x, vertices[i].y);
        context.lineTo(vertices[i+4].x, vertices[i+4].y);
    }
    context.stroke(); // 绘制线条
}

// 获取Canvas元素和上下文
const canvas = document.getElementById('canvas');
const context = canvas.getContext('2d');

// 调用函数绘制长方体
drawCube(vertices2D, context);

这个代码示例展示了如何在HTML5 Canvas上绘制一个简化的“长方体”,其中包括了正面和背面的连接,以及它们之间的边缘。请根据实际情况调整坐标和逻辑。

5. 补充:关于正投影和透视投影

正投影和透视投影是两种用于将三维物体表示在二维平面上的方法,它们在视觉效果和应用场景上有显著的不同。下面详细说明这两种投影方式。

正投影(Orthographic Projection)
定义

正投影是一种将三维对象无视深度地直接投射到二维平面上的方法。在这种投影中,所有的投影线都是平行的,不会因为它们的相对深度而收敛或发散。

特点
  • 无透视缩小:物体的大小不会随着距离的增加而减小,即远处的物体与近处的物体在视觉上保持相同的尺寸。
  • 角度和比例保持不变:物体的角度和比例不受观察位置的影响,能够保持其真实的形状和比例,这使得正投影在工程、建筑和设计领域中非常有用,特别是在需要精确测量的情况下。
应用
  • 工程图纸
  • 建筑平面图
  • 技术绘图
  • 某些类型的游戏,如模拟建造或策略游戏

透视投影(Perspective Projection)

定义

透视投影是一种模拟人眼视觉感知的投影方法,通过这种方法投射的物体会因为距离的不同而在视觉上出现大小变化。在透视投影中,所有的投影线都会在一个或多个消失点上汇聚。

特点
  • 透视缩小:随着物体距离观察者越远,它们在画面上的表示就会越小,这反映了人眼观察远处物体时的真实视觉效果。
  • 视角和深度:透视投影能够很好地模拟深度和空间感,使得绘制的场景或物体看起来更加立体和真实。
  • 消失点:透视图中,平行线会向远处延伸并在画面上的一个或多个点上相交,这些点称为消失点。
应用
  • 艺术绘画
  • 电影和视频制作
  • 视频游戏设计
  • 任何需要模拟真实视觉感知的场景

比较

  • 视觉效果:正投影保持物体的准确比例和形状,而透视投影则提供深度感和更为真实的视觉体验。
  • 应用领域:正投影通常用于需要精确尺寸和比例的技术和工程领域,透视投影则广泛应用于艺术和娱乐领域,以及任何需要模拟人眼视觉效果的场合。
  • 实现复杂性:透视投影在计算上比正投影复杂,因为它需要考虑观察点、视线和消失点等因素。

总的来说,选择哪种投影方式取决于你想要表达的视觉效果和应用的具体需求。正投影适合展示技术细节和确保尺寸精确,而透视投影则更适合创建动人的视觉场景和增强深度感与现实感。

二、如何利用three.js画长方体的正投影

在Three.js中,虽然它主要用于创建和渲染三维场景,包括使用透视相机来模拟人眼视角的透视效果,但也可以通过配置来模拟正投影(Orthographic Projection)。Three.js提供了THREE.OrthographicCamera,用于创建没有透视效果的场景,这可以用来绘制物体的正投影。

步骤1: 创建场景

首先,创建一个THREE.Scene对象,作为你的3D世界的容器。

const scene = new THREE.Scene();

步骤2: 创建正投影相机

创建THREE.OrthographicCamera时,需要指定六个参数:左边界(left)、右边界(right)、上边界(top)、下边界(bottom)、近裁剪面(near)和远裁剪面(far)。这些参数共同定义了相机的视锥体,决定了哪些对象被渲染。

const aspectRatio = window.innerWidth / window.innerHeight;
const camera = new THREE.OrthographicCamera(-aspectRatio * 10, aspectRatio * 10, 10, -10, 1, 100);
camera.position.set(2, 2, 2); // 设置相机位置
camera.lookAt(scene.position); // 让相机指向场景的中心

步骤3: 设置渲染器

创建THREE.WebGLRenderer渲染器,并设置其大小。

const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

步骤4: 创建长方体(Box)

使用THREE.BoxGeometryTHREE.MeshBasicMaterial(或其他材质)创建一个长方体,然后添加到场景中。

const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshBasicMaterial({color: 0x00ff00});
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);

步骤5: 渲染循环

最后,创建一个渲染循环来不断渲染场景。

function animate() {
    requestAnimationFrame(animate);
    renderer.render(scene, camera);
}
animate();

使用THREE.OrthographicCamera,你可以创建长方体的正投影效果。不同于透视相机,正投影相机不会模拟远处物体看起来更小的透视效果,因此它特别适用于需要展示准确比例和角度的应用场景,如建筑设计、CAD工具和某些类型的游戏。

调整相机的位置和方向,你可以得到不同方向上的正投影视图,例如顶视图、正视图或侧视图。通过改变相机参数和相机位置,你可以模拟不同的正投影效果。

三、如何手动计算一个长方体在非平凡平面上的正投影

import numpy as np

# 平面法线向量和D值
A, B, C, D = 1, 2, 3, -4  # 示例平面方程 Ax + By + Cz + D = 0
N = np.array([A, B, C])
N_unit = N / np.linalg.norm(N)  # 单位法线向量

# 顶点坐标
V = np.array([1, 2, 3])  # 示例顶点

# 计算顶点到平面的距离
d = abs(A*V[0] + B*V[1] + C*V[2] + D) / np.linalg.norm(N)

# 计算投影坐标
P_prime = V - d * N_unit  # 如果法线指向顶点
# 或者 P_prime = V + d * N_unit  # 如果法线背离顶点

print("投影坐标:", P_prime)

四、透视投影的数学概念

透视投影是一种模拟人眼观察现实世界的投影方式,它考虑到了深度,使得物体随着距离的增加看起来越来越小。在透视投影中,物体上的平行线在远处会汇聚于一个或多个消失点。计算透视投影坐标相比正投影更为复杂,因为它涉及到视点(观察点)与投影面(通常是画布或屏幕)之间的相对位置。

## 1. 确定视点和投影面

首先,你需要确定视点(即观察者的位置)和投影面(你想要将三维场景投影到的平面)。视点通常由三维坐标表示(例如,`V(x_v, y_v, z_v)`),而投影面可以简化为一个二维平面,例如屏幕或画布,其位置可以由它与视点的相对距离定义。

## 2. 选择透视类型

透视投影通常分为两种类型:一点透视和两点(或多点)透视。选择哪一种取决于你想要呈现的视觉效果。

- **一点透视**:所有的投影线都汇聚于一个消失点,通常用于内部场景。
- **两点透视**:有两个消失点,通常用于外部或角度视图。
- **三点透视**:添加了第三个消失点来模拟高度的变化,通常用于高角度或低角度的视图。

## 3. 计算透视投影坐标

对于简单的一点透视,透视投影坐标可以通过以下步骤计算:

- **确定消失点**:在投影面上选择一个点作为消失点(DP)。对于一点透视,这个点通常位于画面的中心。
- **计算投影线**:对于长方体的每个顶点,从视点到该顶点画一条直线。这些线在投影面上的交点即为顶点的透视投影坐标。
- **计算交点**:使用透视投影的公式计算每个顶点在投影面上的坐标。

假设长方体的一个顶点为 `P(x, y, z)`,视点为 `V(x_v, y_v, z_v)`,投影面位于 `z = d` 的平面上(`d`是视点到投影面的距离),那么顶点 `P` 在投影面上的透视投影坐标 `P'(x', y')` 可以通过以下公式计算:

x' = d × (x - x_v) / (z - z_v) + x_v

y' = d × (y - y_v) / (z - z_v) + y_v


这里,`x'` 和 `y'` 是顶点在投影面上的二维坐标。

## 注意事项

- 实际应用中,可能还需要考虑相机的朝向、视角等因素,这会使得透视投影的计算更加复杂。
- 在计算过程中,所有坐标都应该相对于视点和投影面进行调整。
- 透视投影的计算涉及到较为复杂的数学概念,尤其是在处理两点或三点透视时。对于复杂场景的透视投影,通常借助计算机图形学软件或库(如OpenGL或Three.js)来自动处理这些计算。
 

五、如何利用three.js来绘制透视投影

在Three.js中,绘制一个长方体(Box)并自动实现其透视投影是相当直接的。Three.js库封装了大部分底层的WebGL调用,提供了简单的API来创建3D场景、相机和光源等,同时自动处理透视投影的计算。

以下是一个基本示例,展示了如何使用Three.js来创建一个场景、添加一个透视相机和一个长方体,然后渲染长方体的透视投影:

步骤 1: 创建场景

首先,你需要创建一个THREE.Scene对象,它将作为所有3D对象的容器。

const scene = new THREE.Scene();

步骤 2: 添加透视相机

然后,创建一个THREE.PerspectiveCamera,它模拟了人眼的透视视图。透视相机需要四个参数:视野角度(fov)、纵横比(aspect ratio)、近裁剪面(near)和远裁剪面(far)。

const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 5; // 设置相机位置,以便能看到长方体

步骤 3: 设置渲染器

接下来,创建一个THREE.WebGLRenderer渲染器,它会在浏览器的<canvas>元素中渲染场景。

const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement); // 将渲染器的DOM元素添加到文档中

步骤 4: 创建长方体

使用THREE.BoxGeometry来创建一个长方体几何体,并使用THREE.MeshBasicMaterial来创建一个材质。然后,将它们结合成一个THREE.Mesh对象,并添加到场景中。

const geometry = new THREE.BoxGeometry(1, 1, 1); // 创建几何体,参数为长宽高
const material = new THREE.MeshBasicMaterial({color: 0x00ff00}); // 创建材质,设置颜色
const cube = new THREE.Mesh(geometry, material); // 创建网格(Mesh)对象
scene.add(cube); // 将长方体添加到场景中

步骤 5: 渲染循环

最后,创建一个渲染循环来不断渲染场景。这允许长方体在屏幕上动态显示,并且可以响应用户输入或其他动态变化。

function animate() {
    requestAnimationFrame(animate); // 请求动画帧
    cube.rotation.x += 0.01; // 让长方体绕x轴旋转
    cube.rotation.y += 0.01; // 让长方体绕y轴旋转
    renderer.render(scene, camera); // 渲染场景
}

animate(); // 开始动画循环

这段代码将创建一个简单的Three.js应用,显示了一个旋转的绿色长方体。在这个示例中,THREE.PerspectiveCamera自动处理了透视投影的所有复杂性,你无需手动计算投影坐标。通过调整相机的参数和位置,你可以改变视觉效果,比如更改透视深度或观察角度。

  • 28
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值