Matlab三角剖分插值问题分析

目录

前言

一、问题引入

二、一个例子

1.生成散点图

2.对数据进行剖分

3.点法式分析

三、最后结果



前言

上一篇文章感觉对三角剖分问题没有说清楚,这次专门对三角剖分问题再仔细说说。


一、问题引入

实际上这个问题是用来解决二维曲面插值问题的。

二维插值问题,用matlab的一些函数就可以方便操作,比如 interp2 。但 interp2函数是用在规则点数据集的情况下,比如已知“密度较稀疏”的一些数据点,进行插值,找到“密度适中”的点。下面举个例子说明。

% 生成自定义的网格点
x = linspace(-3, 3, 10);
y = linspace(-3, 3, 15);
[X, Y] = meshgrid(x, y);

% 计算相应的高度值
Z = peaks(X, Y);

% 绘制原始网格图
figure;
subplot(1, 2, 1);
surf(X, Y, Z);
xlabel('X');
ylabel('Y');
zlabel('Z');
title('Original Peaks Surface');
axis tight;
grid on;

% 指定插值后的网格点
xi = linspace(-3, 3, 30);
yi = linspace(-3, 3, 45);
[XI, YI] = meshgrid(xi, yi);

% 使用插值方法计算插值后的高度值
ZI = interp2(X, Y, Z, XI, YI, 'spline');

% 绘制插值后的网格图
subplot(1, 2, 2);
surf(XI, YI, ZI);
xlabel('X');
ylabel('Y');
zlabel('Z');
title('Interpolated Peaks Surface');
axis tight;
grid on;

得到图如下:

但对于一些无序(或者说在空间排列没有规律)的散点进行插值,这时要使用 三角剖分插值

具体概念介绍可以参考下面的wiki链接

https://en.wikipedia.org/wiki/Delauna4_triangulation

二、一个例子

1.生成散点图

为了好说明,我们在1/4半球面上进行操作,随机选取球面上的一些点作为散点,同时画出它的xy面投影剖分(后面要用)

% 定义半径和绘制分辨率
radius = 1;  % 半径
resolution = 50;  % 分辨率

% 生成球面上的坐标点
theta = linspace(-pi/2, 0, resolution);
phi = linspace(0, pi/2, resolution);
[THETA, PHI] = meshgrid(theta, phi);
x = radius * sin(PHI) .* cos(THETA);
y = radius * sin(PHI) .* sin(THETA);
z = radius * cos(PHI);

% 随机选择50个点
numPoints = 50;
indices = randperm(resolution^2, numPoints);
selectedPoints = [x(indices(:)), y(indices(:)), z(indices(:))];

% 进行三角剖分
tri = delaunay(selectedPoints(:, 1), selectedPoints(:, 2));


% 绘制1/4半球面
figure;
surf(x, y, z);
hold on;

% 绘制随机选择的点
scatter3(selectedPoints(:, 1), selectedPoints(:, 2), selectedPoints(:, 3), 'filled', 'r');

 

2.对数据进行剖分

代码如下:


clear all
close all
clc
 rng(10)
% 定义半径和绘制分辨率
radius = 1;  % 半径
resolution = 50;  % 分辨率

% 生成球面上的坐标点
theta = linspace(-pi/2, 0, resolution);
phi = linspace(0, pi/2, resolution);
[THETA, PHI] = meshgrid(theta, phi);
x = radius * sin(PHI) .* cos(THETA);
y = radius * sin(PHI) .* sin(THETA);
z = radius * cos(PHI);

% 随机选择点
numPoints = 50;
indices = randperm(resolution^2, numPoints);
selectedPoints = [x(indices(:)), y(indices(:)), z(indices(:))];

save selectedPoints.mat selectedPoints

% 在xy平面上进行平面剖分
dt = delaunayTriangulation(selectedPoints(:, 1), selectedPoints(:, 2));
tri = dt.ConnectivityList;

% 根据剖分点的坐标和对应的z值生成三维空间中的三角网格
tri3D = [tri, tri(:, 1) + size(selectedPoints, 1), tri(:, 2) + size(selectedPoints, 1)];

x3D = [selectedPoints(:, 1); selectedPoints(:, 1); selectedPoints(:, 1)];
y3D = [selectedPoints(:, 2); selectedPoints(:, 2); selectedPoints(:, 2)];
z3D = [selectedPoints(:, 3); selectedPoints(:, 3); selectedPoints(:, 3)];

% 绘制1/4半球面
figure;
h = surf(x, y, z);
set(h, 'FaceAlpha', 0.5);  % 设置表面的透明度
% set(h, 'FaceColor', 'green');  % 设置表面颜色为空
hold on;

% 绘制随机选择的点
scatter3(selectedPoints(:, 1), selectedPoints(:, 2), selectedPoints(:, 3), 'filled', 'r');

triplot(dt);

% % 绘制三角网格
% trisurf(tri3D, x3D, y3D, z3D, 'FaceColor', 'none', 'EdgeColor', 'b', 'FaceAlpha', 0.5);

% 绘制三角网格
patch('Faces', tri3D, 'Vertices', [x3D, y3D, z3D], 'FaceColor', 'red', 'EdgeColor', 'b', 'FaceAlpha', 0.5);

% 设置坐标轴和标题
xlabel('X');
ylabel('Y');
zlabel('Z');
title('Quarter Sphere with Random Points and Triangulation');

% 设置坐标轴比例和网格
axis equal;
grid on;




这个显示的有点复杂了,它是几个数据图像的结合 包括 原始数据(网格图)、散点图(红色)、空间和平面三角剖分图(蓝色)

我们去掉原始网格图,只留平面剖分和对应曲面的映射,看看如下

待插值的点会在这些红色三角面上找到对应的z值,因为散点插值可不同于interp2插值,根本没有"可以依赖"现成附近的方形网格点用来估算,需要借助剖分的找到它附近的点。好了,思路有了,流程化的东西如下:

三角剖分的流程

1、对空间散点的xy平面投影进行三角剖分(注意:并不是直接在空间曲面上进行三角剖分,而是对平面进行,因为使用delaunayTriangulation会对xyz三维数据直接给出的四面体立体剖分!即它会认为是立体剖分)

2、对待插值点的xy平面投影点,找到它属于xy平面剖分的哪个三角形(注意,是在xy平面)

3、在空间对对应三角形建立平面方程,然后使用点法式方式对待插值点求出z的值

平面和立体对应关系如下图(共同的xy,z当然不同了)

3.点法式分析

参考代码,还是沿用上一次提到的线性三角剖分的matlab代码

https://www.mathworks.com/matlabcentral/fileexchange/38925-linearly-interpolate-triangulation

 这代码核心的部分在这里:

其中点法式大家估计印象不是很深刻了,需要复习下空间解析几何的一点知识 ,两页ppt帮大家回疑

 法向量怎么求呢,相当于在平面中两个矢量的叉乘!我们翻一下matlab cross的内容

比如两个矢量 V1 = [x2-x1,y2-y1,z2-z1],V2=[x3-x1,y3-y1,z3-z1],,记为 (a1,a2,a3)  (b1,b2,b3)

叉乘的结果是

A=a2*b3 - a3*b2=(y2-y1)*(z3-z1)-(z2-z1)*(y3-y1)

B = a3*b1-a1*b3=(z2-z1)*(x3-x1)-(x2-x1)*(z3-z1)

C = a1*b2-a2*b1 = (x2-x1)*(y3-y1)-(y2-y1)*(x3-x1) 

A*(xi-x1)+B*(yi-y1)+C*(zi-z1) = 0

zi =  (-((y3 - y1) * (z2 - z1) - (z3 - z1) * (y2 - y1)) * (x - x1) - ((z3 - z1) * (x2 - x1) - (x3 - x1) * (z2 - z1)) * (y - y1)) / ((x3 - x1) * (y2 - y1) - (y3 - y1) * (x2 - x1)) + z1

z1变到分子上去,然后分子变成 z1*XXX+z2*YYY+z3*CCC ,XXX,YYY,CCC就是代码中N1 N2 N3的分子

这样按照待插值的网格的点的顺序,依次计算即可得到全部的插值数据。


三、最后结果

简单对几个点进行插值,插值之后的空间点是黄色:


load selectedPoints.mat

%散点
x = selectedPoints(:,1);
y = selectedPoints(:,2);
z = selectedPoints(:,3);

% 定义插值点的网格
n_points = 5; % 插值点个数

xi = linspace(min(x), max(x), n_points); % x 坐标范围
yi = linspace(min(y), max(y), n_points); % y 坐标范围
[XI, YI] = meshgrid(xi, yi); % 插值点的网格

%x y z数据同前

% 构建三角剖分
DT = delaunayTriangulation(x, y);

% Get the connectivity table
tri = DT.ConnectivityList;
tri = tri(:, [1, 2, 3]);

ZI=interptri(tri,x,y,z,XI,YI);

%  绘制插值结果
figure(1)
hold on
% surf(XI, YI, ZI);

scatter3(XI(:), YI(:), ZI(:), 'filled', 'y');

xlabel('X');
ylabel('Y');
zlabel('Z');

很显然,原始插值点密集的话,插出来的曲面会更理想。

总结:空间曲面散点的三角剖分线性插值是一种常用的方法,用于从离散的散点数据中构建连续的曲面模型。该方法基于三角剖分技术,将散点分布的空间曲面划分为一系列三角形,然后利用线性插值来估计每个三角形内部的数据点。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/183697.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

python tkinter使用(五)

python tkinter使用(五) 本篇文章讲述tkinter 中treeview的使用 Treeview是一个多列列表框,可以显示层次数据。 #!/usr/bin/python3 # -*- coding: UTF-8 -*- """Author: zhTime 2023/11/23 下午8:28 .Email:Describe: treeview 使用 "&quo…

YB4051系列设备是高度集成的 Li-lon 和 Li-Pol 线性充电器,针对便携式应用的小容量电池。

YB4051H 300mA 单电池锂离子电池充电器0.1 mA 终端,45nA 电池漏电流 概述: YB4051系列设备是高度集成的 Li-lon 和 Li-Pol 线性充电器,针对便携式应用的小容量电池。它是一个完整的恒流/恒压线性充电器。不需要外部感应电阻,由于…

〖大前端 - 基础入门三大核心之JS篇㊷〗- DOM事件对象及它的属性

说明:该文属于 大前端全栈架构白宝书专栏,目前阶段免费,如需要项目实战或者是体系化资源,文末名片加V!作者:不渴望力量的哈士奇(哈哥),十余年工作经验, 从事过全栈研发、产品经理等工作&#xf…

vulnhub6

靶机地址:https://download.vulnhub.com/evilbox/EvilBox---One.ova 准备工作 可以先安装 kali 的字典: sudo apt install seclists ​ 或者直接输入 seclists​,系统会问你是否安装,输入 y 即可自动安装 733 x 3751414 x 723 ​ 默认路…

opencv 常用操作指南

1.通道交换 读取图像,然后将RGB通道替换成BGR通道,需要注意的是,opencv读取的图像默认是BGR。cv2.cvtColor函数可以参考Color Space Conversions img cv2.imread(imori.jpg) img cv2.cvtColor(img, cv2.COLOR_BGR2RGB) cv2.imwrite(answe…

HarmonyOS(五)—— 认识页面和自定义组件生命周期

前言 在前面我们通过如何创建自定义组件一文知道了如何如何自定义组件以及自定义组件的相关注意事项,接下来我们认识一下页面和自定义组件生命周期。 自定义组件和页面的关系 在开始之前,我们先明确自定义组件和页面的关系 自定义组件:Co…

聚观早报 |一加12正式开启预订;OPPO Reno11系列卖点

【聚观365】11月24日消息 一加12正式开启预订 OPPO Reno11系列卖点 小鹏第三季度营收财报 Claude 2.1 聊天机器人公布 现代汽车将与伦敦大学学院合作 一加12正式开启预订 全新的一加12系列公开亮相已有一段时间,不久前一加官方宣布,该机将于12月4日…

(1)(1.19) TeraRanger One/EVO测距仪

文章目录 前言 1 通过I2C与TeraRanger EVO连接 2 Mission Planner中的设置 3 测试传感器 4 参数说明 前言 TeraBee EVO 系列测距仪是基于红外飞行时间 (TOF) 技术的轻型距离测量传感器。与基于激光的激光雷达相比,它们的速度比超声波快得多,体积更…

Microsoft Office 2019下载工具

今天博主继续推出重磅福利——Microsoft Office合集的安装工具。 Microsoft Office是一套由微软公司开发的办公软件,它为 Microsoft Windows 和 Mac OS X而开发。与办公室应用程序一样,它包括联合的服务器和基于互联网的服务。最近版本的 Office 被称为 …

Linux实验三:shell程序设计: shell基础

实验目的: 进一步巩固shell程序设计语言基本语法,加深对所学知识理解。 实验要求 1. 四种变量的使用 2. 配置环境变量 3. 元字符和正则表达式 4. 引号 1. 本地变量 $ var1"hello Linux" //定义本地变量var1 $ read var2 //定义本地变量vae…

React基础入门

文章目录 创建项目组件和事件更新状态导出组件jsx react是目前最流行的前端框架,几乎也不同太介绍了。 创建项目 首先下载node.js,安装成功后,最好换成国内的源 npm config set registry https://registry.npm.taobao.org然后就可以使用脚…

Ubuntu20.04清理垃圾vscode缓存

使用VM虚拟机安装了Ubuntu系统,主目录空间越来越小,硬盘扩容之后很快又空间不足,甚至出现了开机卡黑屏的情况,这里记录一下解决过程。 1 重新开机进入系统 状态:卡到了开机黑屏状态,左上角有一条小横杠 原…

Charles 网络抓包工具详解与实战指南

文章目录 导读软件版本Charles基本原理核心功能下载及安装界面介绍网络包展示 常用场景介绍PC 端网络抓包移动端网络抓包PC 端配置手机端配置 开启 SSL 代理PC 端和移动端 CA 证书安装Charles 直接安装Charles 下载 CA 文件手动安装 常用操作请求重发请求改写、动态改写断点&am…

常用服务注册中心与发现(Eurake、zookeeper、Nacos)笔记(一)基础概念

基础概念 注册中心 在服务治理框架中,通常都会构建一个注册中心,每个服务单元向注册中心登记自己提供的服务,将主机与端口号、版本号、通信协议等一些附加信息告知注册中心,注册中心按照服务名分类组织服务清单,服务…

【100个Cocos实例】东皇太一的技能环绕效果

引言 Cocos中物体围绕物体做圆周运动。 不管是2D还是3D游戏,旋转是游戏中常见的操作之一,它可以用来改变游戏对象的方向、角度或者位置,从而创造出更加生动和有趣的游戏体验。 本文将介绍一下如何实现王者荣耀中东皇太一的技能环绕效果。 …

五分钟,Docker安装flink,并使用flinksql消费kafka数据

1、拉取flink镜像,创建网络 docker pull flink docker network create flink-network2、创建 jobmanager # 创建 JobManager docker run \-itd \--namejobmanager \--publish 8081:8081 \--network flink-network \--env FLINK_PROPERTIES"jobmanager.rpc.ad…

123. 股票买卖的最佳时机III(2次交易)

题目 题解 class Solution:def maxProfit(self, prices: List[int]) -> int:N len(prices)# 状态定义 dp[i][j][k]代表在第i天,被允许完成j次交易时,持有或者不持有的最大利润。k0代表不持有,k1代表持有dp [[[0 for k in range(2)] for…

朋友圈被折叠怎么解决?

最近有客户咨询发的朋友圈老被折叠怎么办,正常发都被折叠。一些朋友在微信做私域的,在朋友圈日常营销是必不可少的,如何避免这种问题和怎么解决呢? 为什么会被折叠? 1.据了解,朋友圈内容折叠功能是主要针对…

【JavaScript】3.1 项目实践:制作一个简单的网页应用

文章目录 项目需求HTML结构JavaScript逻辑添加待办事项标记待办事项删除待办事项保存待办事项 总结 在此章节中,我们将学习如何使用JavaScript创建一个简单的网页应用。这将是一个待办事项列表应用,用户可以添加新的待办事项,标记已完成的事项…

【MySQL】mysql中不推荐使用uuid或者雪花id作为主键的原因以及差异化对比

文章目录 前言什么是UUID?什么是雪花ID?什么是MySql自增ID?优缺点对比UUID:优点1.全球唯一性2.无需数据库支持 缺点1.存储空间大2.索引效率低3.查询效率低 雪花ID:优点1.分布式环境下唯一性 缺点1.依赖于机器时钟2.存储空间较大3.查询效率低 MYSQL自增:优点1.简单…