当前位置: 首页 > 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;记录下来的这部分的…...

Docker 离线安装指南

参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性&#xff0c;不同版本的Docker对内核版本有不同要求。例如&#xff0c;Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本&#xff0c;Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...

【kafka】Golang实现分布式Masscan任务调度系统

要求&#xff1a; 输出两个程序&#xff0c;一个命令行程序&#xff08;命令行参数用flag&#xff09;和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽&#xff0c;然后将消息推送到kafka里面。 服务端程序&#xff1a; 从kafka消费者接收…...

java_网络服务相关_gateway_nacos_feign区别联系

1. spring-cloud-starter-gateway 作用&#xff1a;作为微服务架构的网关&#xff0c;统一入口&#xff0c;处理所有外部请求。 核心能力&#xff1a; 路由转发&#xff08;基于路径、服务名等&#xff09;过滤器&#xff08;鉴权、限流、日志、Header 处理&#xff09;支持负…...

Cesium1.95中高性能加载1500个点

一、基本方式&#xff1a; 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...

STM32+rt-thread判断是否联网

一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...

Golang dig框架与GraphQL的完美结合

将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用&#xff0c;可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器&#xff0c;能够帮助开发者更好地管理复杂的依赖关系&#xff0c;而 GraphQL 则是一种用于 API 的查询语言&#xff0c;能够提…...

ETLCloud可能遇到的问题有哪些?常见坑位解析

数据集成平台ETLCloud&#xff0c;主要用于支持数据的抽取&#xff08;Extract&#xff09;、转换&#xff08;Transform&#xff09;和加载&#xff08;Load&#xff09;过程。提供了一个简洁直观的界面&#xff0c;以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明

AI 领域的快速发展正在催生一个新时代&#xff0c;智能代理&#xff08;agents&#xff09;不再是孤立的个体&#xff0c;而是能够像一个数字团队一样协作。然而&#xff0c;当前 AI 生态系统的碎片化阻碍了这一愿景的实现&#xff0c;导致了“AI 巴别塔问题”——不同代理之间…...

【git】把本地更改提交远程新分支feature_g

创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...

OpenLayers 分屏对比(地图联动)

注&#xff1a;当前使用的是 ol 5.3.0 版本&#xff0c;天地图使用的key请到天地图官网申请&#xff0c;并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能&#xff0c;和卷帘图层不一样的是&#xff0c;分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...