当前位置: 首页 > news >正文

用纯C语言实现3D空间中的点坐标转化为屏幕二维点坐标,包含主视图、侧视图、俯视图、正等轴投影

要实现3D空间中的点坐标转换为屏幕二维点坐标,需要进行透视变换和投影变换。以下是一些基本的思路和示例代码,可以用于实现主视图、侧视图、俯视图、正等轴投影。

1. 主视图投影

主视图投影是指以一个点作为视点,从一个方向观察物体,投影到一个平面上。通常情况下,主视图的观察方向是从正面,也就是Z轴负方向。投影平面一般是平行于X-Y平面。

具体实现可以通过以下步骤完成:

  • 定义观察点坐标和投影平面距离
  • 对3D坐标进行透视变换
  • 对透视变换后的坐标进行投影变换
  • 将投影后的坐标映射到屏幕上

示例代码:

int x_2d = (int) (x_3d / (z_3d - view_point_z) * distance_to_projection_plane);
int y_2d = (int) (y_3d / (z_3d - view_point_z) * distance_to_projection_plane);

2. 侧视图投影

侧视图投影是指以一个点作为视点,从一个方向观察物体,投影到一个平面上。通常情况下,侧视图的观察方向是从侧面,也就是X轴正方向。投影平面一般是平行于Y-Z平面。

具体实现可以通过以下步骤完成:

  • 定义观察点坐标和投影平面距离
  • 对3D坐标进行透视变换
  • 对透视变换后的坐标进行投影变换
  • 将投影后的坐标映射到屏幕上

示例代码:

int x_2d = (int) (y_3d / (x_3d - view_point_x) * distance_to_projection_plane);
int y_2d = (int) (z_3d / (x_3d - view_point_x) * distance_to_projection_plane);

3. 俯视图投影

俯视图投影是指以一个点作为视点,从一个方向观察物体,投影到一个平面上。通常情况下,俯视图的观察方向是从上方,也就是Y轴正方向。投影平面一般是平行于X-Z平面。

具体实现可以通过以下步骤完成:

  • 定义观察点坐标和投影平面距离
  • 对3D坐标进行透视变换
  • 对透视变换后的坐标进行投影变换
  • 将投影后的坐标映射到屏幕上

以下是一个简单的示例代码,用于将3D空间中的点坐标转化为屏幕二维点坐标。这里包括了主视图、侧视图、俯视图、正等轴投影的实现。

#include <stdio.h>
#include <stdlib.h>
#include <math.h>#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480typedef struct {double x, y, z;
} Point3D;typedef struct {int x, y;
} Point2D;void project_ortho(Point3D point_3d, Point2D *point_2d, double distance_to_projection_plane) {point_2d->x = (int) point_3d.x;point_2d->y = (int) point_3d.y;
}void project_isometric(Point3D point_3d, Point2D *point_2d, double distance_to_projection_plane) {point_2d->x = (int) ((point_3d.x - point_3d.z) * cos(30 * M_PI / 180));point_2d->y = (int) ((point_3d.y - (point_3d.x + point_3d.z) * sin(30 * M_PI / 180)) * cos(30 * M_PI / 180));
}void project_main(Point3D point_3d, Point2D *point_2d, Point3D view_point, double distance_to_projection_plane) {double z_3d = point_3d.z - view_point.z;point_2d->x = (int) (point_3d.x - view_point.x) * distance_to_projection_plane / z_3d + SCREEN_WIDTH / 2;point_2d->y = (int) (point_3d.y - view_point.y) * distance_to_projection_plane / z_3d + SCREEN_HEIGHT / 2;
}void project_side(Point3D point_3d, Point2D *point_2d, Point3D view_point, double distance_to_projection_plane) {double x_3d = point_3d.x - view_point.x;point_2d->x = (int) (point_3d.y - view_point.y) * distance_to_projection_plane / x_3d + SCREEN_WIDTH / 2;point_2d->y = (int) (point_3d.z - view_point.z) * distance_to_projection_plane / x_3d + SCREEN_HEIGHT / 2;
}void project_top(Point3D point_3d, Point2D *point_2d, Point3D view_point, double distance_to_projection_plane) {double y_3d = point_3d.y - view_point.y;point_2d->x = (int) (point_3d.x - view_point.x) * distance_to_projection_plane / y_3d + SCREEN_WIDTH / 2;point_2d->y = (int) (point_3d.z - view_point.z) * distance_to_projection_plane / y_3d + SCREEN_HEIGHT / 2;
}int main() {// Define the 3D points of a cubePoint3D cube[8] = {{-50, -50, -50},{50, -50, -50},{50, 50, -50},{-50, 50, -50},{50, -50, 50},{50, 50, 50},{-50, 50, 50},{-50, -50, 50},};// Define the view point for the main, side, and top projectionsPoint3D main_view_point = {0, 0, 200};Point3D side_view_point = {-200, 0, 0};Point3D top_view_point = {0, 200, 0};// Define the distance from the projection plane for the orthogonal and isometric projectionsdouble distance_to_ortho_projection_plane = 200;double distance_to_isometric_projection_plane = 200 / cos(30 * M_PI / 180);// Project the 3D points to 2D points for each projectionPoint2D main_projection[8];Point2D side_projection[8];Point2D top_projection[8];Point2D ortho_projection[8];Point2D iso_projection[8];int i;for (i = 0; i < 8; i++) {project_main(cube[i], &main_projection[i], main_view_point, distance_to_ortho_projection_plane);project_side(cube[i], &side_projection[i], side_view_point, distance_to_ortho_projection_plane);project_top(cube[i], &top_projection[i], top_view_point, distance_to_ortho_projection_plane);project_ortho(cube[i], &ortho_projection[i], distance_to_ortho_projection_plane);project_isometric(cube[i], &iso_projection[i], distance_to_isometric_projection_plane);}// Draw the 2D projections// ...// Your code to draw the projections goes here// ...return 0;
}

相关文章:

用纯C语言实现3D空间中的点坐标转化为屏幕二维点坐标,包含主视图、侧视图、俯视图、正等轴投影

要实现3D空间中的点坐标转换为屏幕二维点坐标&#xff0c;需要进行透视变换和投影变换。以下是一些基本的思路和示例代码&#xff0c;可以用于实现主视图、侧视图、俯视图、正等轴投影。 1. 主视图投影 主视图投影是指以一个点作为视点&#xff0c;从一个方向观察物体&#x…...

.sh脚本文件的执行方式

方法1&#xff1a; ./xxx.sh方法2&#xff1a; source xxx.sh方法3&#xff1a; bash xxx.sh方法4: sh xxx.sh初识shell&#xff0c;学习并记录...

Android 基础知识4-2.5View与VIewGroup的概念、关系与区别

1.概念&#xff1a; Android里的图形界面都是由View和ViewGroup以及他们的子类构成的&#xff1a; View&#xff1a;所有可视化控件的父类,提供组件描绘和时间处理方法 ViewGroup&#xff1a; View类的子类&#xff0c;可以拥有子控件,可以看作是容器 Android UI中的控件都是…...

【ESP 保姆级教程】玩转巴法云篇① ——初识巴法云

忘记过去,超越自己 ❤️ 博客主页 单片机菜鸟哥,一个野生非专业硬件IOT爱好者 ❤️❤️ 本篇创建记录 2023-02-19 ❤️❤️ 本篇更新记录 2023-02-19 ❤️🎉 欢迎关注 🔎点赞 👍收藏 ⭐️留言📝🙏 此博客均由博主单独编写,不存在任何商业团队运营,如发现错误,请…...

Python学习-----模块3.0(正则表达式-->re模块)

目录 前言&#xff1a; 导入模块 1.re.match() 函数 &#xff08;1&#xff09;匹配单个字符 &#xff08;2&#xff09;匹配多个字符 (3) 匹配开头和结尾 2.re.search() 函数 3.re.findall() 函数 4.re.finditer() 函数 5.re.split() 函数 6.re.sub() 函数 7.re.sub…...

JSP中http与内置对象学习笔记

本博文讲述jsp客户端与服务器端的http、jsp内置对象与控制流和数据流实现 1.HTTP请求响应机制 HTTP协议是TCP/IP协议中的一个应用层协议&#xff0c;用于定义客户端与服务器之间交换数据的过程 1.1 HTTP请求 HTTP请求由请求行、消息报头、空行和请求数据4部分组成。 请求行…...

Windows Server 2016远程桌面配置全过程

镜像下载 系统镜像网址 本次下载的是 Windows Server 2016 (Updated Feb 2018) (x64) - DVD (Chinese-Simplified) 远程桌面配置 Step 1 在开始菜单搜索服务&#xff0c;打开服务器管理器&#xff0c;点击右上角的管理按钮 Step 2 添加角色控制&#xff0c;点击下一步 S…...

SPI通讯简介

一、基本概念 SPI是串行外设接口(Serial Peripheral Interface)的缩写&#xff0c;是一种高速的&#xff0c;全双工&#xff0c;同步的通信总线&#xff0c;主要应用在EEPROM,FLASH,实时时钟&#xff0c;AD转换器&#xff0c;多MCU间通讯等等&#xff0c;SPI端口可以在多主器件…...

Python 迭代器

迭代器协议 对象必须提供一个 next() 方法&#xff0c;执行该方法要么迭代下一项&#xff0c;要么就引起一个 StopIteration异常以终止迭代&#xff08;只能往后不能往前&#xff09;—— 迭代器协议 协议是一种约定&#xff0c;可迭代对象实现了迭代器协议&#xff08;for、…...

Python语言零基础入门教程(二十七)

Python OS 文件/目录方法 Python语言零基础入门教程&#xff08;二十六&#xff09; 61、Python os.utime() 方法 概述 os.utime() 方法用于设置指定路径文件最后的修改和访问时间。 在Unix&#xff0c;Windows中有效。 语法 utime()方法语法格式如下&#xff1a; os.uti…...

Redis基础操作以及数据类型

目录 Redis基础操作 java中的i是不是原子操作&#xff1f;不是 数据类型 1. list 2. set 3. Hash哈希 4. Zset有序集合 Redis基础操作 set [key] [value] 设置值 &#xff08;设置相同的会将原先的覆盖&#xff09; get [key] 获取值 不能覆盖和替换 ttl [key] 以秒为单…...

自抗扰控制ADRC之反馈控制律(NLSEF)

目录 前言 1.非线性状态误差反馈控制律(NLSEF) 1.1 控制律形式 1.2 控制量的生成(或者说扰动的补偿) 1.2.1补偿形式① 1.2.1补偿形式② 2.仿真分析 2.1仿真模型 2.2仿真结果 前言 前面的两篇博客依次介绍了TD微分跟踪器安排过渡过程、扩张观测器&#xff1a; 自抗扰…...

“生成音乐“ 【循环神经网络】

前言 本文介绍循环神经网络的进阶案例&#xff0c;通过搭建和训练一个模型&#xff0c;来对钢琴的音符进行预测&#xff0c;通过重复调用模型来进而生成一段音乐&#xff1b; 使用到Maestro的钢琴MIDI文件 &#xff0c;每个文件由不同音符组成&#xff0c;音符用三个量来表示…...

能否手写vue3响应式原理-面试进阶

&#xff08;二&#xff09;响应式原理 利用ES6中Proxy作为拦截器&#xff0c;在get时收集依赖&#xff0c;在set时触发依赖&#xff0c;来实现响应式。 &#xff08;三&#xff09;手写实现 1、实现Reactive 基于原理&#xff0c;我们可以先写一下测试用例 //reactive.spe…...

前端工程师leetcode算法面试必备-简单的二叉树

一、前言 本难度的题目主要考察二叉树的基本概念和操作。 1、基本概念 树是计算机科学中经常用到的一种非线性数据结构&#xff0c;以分层的形式存储数据。二叉树是一种特殊的树结构&#xff0c;每个节点最多有两个子树&#xff0c;通常子树被称作“左子树”和“右子树”。 …...

【什么程度叫熟悉linux系统】

一、编译内核 1、Linux系统背景&#xff1a;Ubuntu 2、内核源码kernel.org进行下载 3、解压内核源文件linux-6.1.12.tar.xz、命令&#xff1a;tar -xvf linux-6.1.12.tar.xz 4、进入解压好的文件inux-6.1.12 5、配置内核命令&#xff1a;make menuconfig&#xff08;需要进…...

编译安装MySQL

MySQL 5.7主要特性 随机root 密码&#xff1a;MySQL 5.7 数据库初始化完成后&#xff0c;会自动生成一个 rootlocalhost 用户&#xff0c;root 用户的密码不为空&#xff0c;而是随机产生一个密码。原生支持&#xff1a;Systemd 更好的性能&#xff1a;对于多核CPU、固态硬盘、…...

Kubernetes一 Kubernetes之入门

二 Kubernetes介绍 1.1 应用部署方式演变 在部署应用程序的方式上&#xff0c;主要经历了三个时代&#xff1a; 传统部署&#xff1a;互联网早期&#xff0c;会直接将应用程序部署在物理机上 优点&#xff1a;简单&#xff0c;不需要其它技术的参与 缺点&#xff1a;不能为应…...

SQLServer2000 断电后数据库suspect“置疑”处理

SQLServer2000 断电后数据库suspect“置疑”处理 背景介绍&#xff1a; 前些天加班时候&#xff0c;接到小舅子微信&#xff0c;说一个客户的winXP 机器上sql2000的数据库在断电重启后&#xff0c;数据库执行命令时提示suspect“置疑”错误。小舅子电子工程师&#xff0c;对数…...

多模态机器学习入门Tutorial on MultiModal Machine Learning——第一堂课个人学习内容

文章目录课程记录核心技术Core Technical Challengesrepresentation表示alignment对齐转换translationFusion融合co-learning共同学习总结Course Syllabus教学大纲个人总结第一周的安排相关连接课程记录 这部分是自己看视频&#xff0c;然后截屏&#xff0c;记录下来的这部分的…...

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql

智慧工地管理云平台系统&#xff0c;智慧工地全套源码&#xff0c;java版智慧工地源码&#xff0c;支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求&#xff0c;提供“平台网络终端”的整体解决方案&#xff0c;提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

【Linux】C语言执行shell指令

在C语言中执行Shell指令 在C语言中&#xff0c;有几种方法可以执行Shell指令&#xff1a; 1. 使用system()函数 这是最简单的方法&#xff0c;包含在stdlib.h头文件中&#xff1a; #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端

&#x1f31f; 什么是 MCP&#xff1f; 模型控制协议 (MCP) 是一种创新的协议&#xff0c;旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议&#xff0c;它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

dedecms 织梦自定义表单留言增加ajax验证码功能

增加ajax功能模块&#xff0c;用户不点击提交按钮&#xff0c;只要输入框失去焦点&#xff0c;就会提前提示验证码是否正确。 一&#xff0c;模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...

1.3 VSCode安装与环境配置

进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件&#xff0c;然后打开终端&#xff0c;进入下载文件夹&#xff0c;键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...

linux 错误码总结

1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

汇编常见指令

汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX&#xff08;不访问内存&#xff09;XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

自然语言处理——循环神经网络

自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元&#xff08;GRU&#xff09;长短期记忆神经网络&#xff08;LSTM&#xff09…...

Device Mapper 机制

Device Mapper 机制详解 Device Mapper&#xff08;简称 DM&#xff09;是 Linux 内核中的一套通用块设备映射框架&#xff0c;为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程&#xff0c;并配以详细的…...