MATLAB将xyz数据转换成STL文件

您所在的位置:网站首页 matlab读取stl模型导出切片 MATLAB将xyz数据转换成STL文件

MATLAB将xyz数据转换成STL文件

2024-07-18 09:10:29| 来源: 网络整理| 查看: 265

我在之前的一个专栏发过一个将地理坐标的数据转成3D的STL模型。我下面介绍一下如何将长方体转成STL文件。我提供两个方法。

第一个是matlab程序。与地理坐标不一样,长方体存在特殊的情况,比如需要把其分成上下、左右、前后6部分进行拼接。关于这部分的知识,可以参考这个up的专栏。我在此基础上,得到了一个方案。具体的代码如下:

bi = load('b01.txt'); scatter3(bi(1,:),bi(2,:),bi(3,:)) x = bi(1,:); y = bi(2,:); z = bi(3,:); [Anum,index] = sort(x); %% labeling x1 = [Anum(1),Anum(3);Anum(5),Anum(7)]; y1 = [y(index(1)),y(index(3));y(index(5)),y(index(7))]; z1 = [z(index(1)),z(index(3));z(index(5)),z(index(7))]; xyz2stl('rectangular.stl',x1,y1,z1)

其中的 b01.txt为x,y,z三列数据。

18.6613959728922 3.14143675683556 3.02457703598341 20.3888047311257 -7.71573813292703 3.02457703598341 30.4000436850529 -6.12292029353781 3.02457703598341 28.6726349268193 4.73425459622477 3.02457703598341 28.6726349268193 4.73425459622477 -3.02457703598341 30.4000436850529 -6.12292029353781 -3.02457703598341 20.3888047311257 -7.71573813292703 -3.02457703598341 18.6613959728922 3.14143675683556 -3.02457703598341

而xyz2stl函数为

function f=xyz2stl(FileName,X,Y,Z) Nx=size(Z,2); Ny=size(Z,1); fid=fopen(FileName,'w'); fprintf(fid,'solid\n'); %top surface Surf_write(fid,X,Y,Z,0); %other surface assumed to be plane % %X=X(1,1) plane Xs=repmat(X(1,:),2,1); Ys=repmat(Y(1,:),2,1); Zs=[zeros(1,Ny);Z(:,1)']; Surf_write(fid,Xs,Ys,Zs,0); %X=X(1,Nx) plane Xs=repmat(X(2,:),2,1); Ys=repmat(Y(2,:),2,1); Zs=[zeros(1,Ny);Z(:,1)']; Surf_write(fid,Xs,Ys,Zs,0); % %Y=Y(1,1) plane Xs=repmat(X(:,1)',2,1); Ys=repmat(Y(:,1)',2,1); Zs=[zeros(1,Ny);Z(:,1)']; Surf_write(fid,Xs,Ys,Zs,0); % %Y=Y(Ny,1) plane Xs=repmat(X(:,2)',2,1); Ys=repmat(Y(:,2)',2,1); Zs=[zeros(1,Ny);Z(:,1)']; Surf_write(fid,Xs,Ys,Zs,0); % % %the bottom plane Surf_write(fid,X,Y,0*Z,0); fprintf(fid,'endsolid'); fclose(fid); disp('xyz2stl finish!') end

其中包含的函数为:

function f=Surf_write(fid,X,Y,Z,opt) for i=1:size(Z,1)-1 for j=1:size(Z,2)-1 %splitting each small rectangular to 2 small triangular p1=[X(i,j),Y(i,j),Z(i,j)]; p2=[X(i+1,j),Y(i+1,j),Z(i+1,j)]; p3=[X(i+1,j+1),Y(i+1,j+1),Z(i+1,j+1)]; local_write_facet(fid,p1,p2,p3,opt); p1=[X(i,j),Y(i,j),Z(i,j)]; p3=[X(i,j+1),Y(i,j+1),Z(i,j+1)]; p2=[X(i+1,j+1),Y(i+1,j+1),Z(i+1,j+1)]; local_write_facet(fid,p1,p2,p3,opt); end end f=1; end %to write a single small triangular to the file function num = local_write_facet(fid,p1,p2,p3,opt) num = 1; n = local_find_normal(p1,p2,p3,opt); fprintf(fid,'facet normal %.7E %.7E %.7E\r\n', n(1),n(2),n(3) ); fprintf(fid,'outer loop\r\n'); fprintf(fid,'vertex %.7E %.7E %.7E\r\n', p1); fprintf(fid,'vertex %.7E %.7E %.7E\r\n', p2); fprintf(fid,'vertex %.7E %.7E %.7E\r\n', p3); fprintf(fid,'endloop\r\n'); fprintf(fid,'endfacet\r\n'); end %to generate the normal direction vector n, from the vertex of triangular function n = local_find_normal(p1,p2,p3,opt) if ~opt v2 = p2-p1; v1 = p3-p1; v3 = cross(v1,v2); n = v3 ./ sqrt(sum(v3.*v3)); else n=opt; end end

第二个是一个matlab小程序包。具体的下载链接为:https://github.com/NWRichmond/xyz2stl.

经过本文的测试,运行该程序包,需要在这个文件目录下增加一个函数:stlWrite函数,如下:

function stlWrite(filename, varargin) %STLWRITE Write STL file from patch or surface data. % % STLWRITE(FILE,fv) writes a stereolithography (STL) file to FILE for a triangulated % patch defined by FV (a structure with fields 'vertices' and 'faces'). % % STLWRITE(FILE,FACES,VERTICES) takes faces and vertices separately, rather than in an FV struct % % STLWRITE(FILE,X,Y,Z) creates an STL file from surface data in X, Y, and Z. STLWRITE triangulates % this gridded data into a triangulated surface using triangulations options specified below. X, Y % and Z can be two-dimensional arrays with the same size. If X and Y are vectors with length equal % to SIZE(Z,2) and SIZE(Z,1), respectively, they are passed through MESHGRID to create gridded % data. If X or Y are scalar values, they are used to specify the X and Y spacing between grid % points. % % STLWRITE(...,'PropertyName',VALUE,'PropertyName',VALUE,...) writes an STL file using the % following property values: % % MODE - File is written using 'binary' (default) or 'ascii'. % % TITLE - Header text (max 80 characters) written to the STL file. % % TRIANGULATION - When used with gridded data, TRIANGULATION is either: % 'delaunay' - (default) Delaunay triangulation of X, Y % 'f' - Forward slash division of grid quadrilaterals % 'b' - Back slash division of quadrilaterals % 'x' - Cross division of quadrilaterals % Note that 'f', 'b', or 't' triangulations require FEX entry 28327, "mesh2tri". % % FACECOLOR - (not currently implemented) When used with face/vertex input, specifies the % colour of each triangle face. If users request this feature, I will attempt to % implement it. % % Example 1: % % Write binary STL from face/vertex data % tmpvol = zeros(20,20,20); % Empty voxel volume % tmpvol(8:12,8:12,5:15) = 1; % Turn some voxels on % fv = isosurface(tmpvol, 0.99); % Create the patch object % stlwrite('test.stl',fv) % Save to binary .stl % % Example 2: % % Write ascii STL from gridded data % [X,Y] = deal(1:40); % Create grid reference % Z = peaks(40); % Create grid height % stlwrite('test.stl',X,Y,Z,'mode','ascii') % Original idea adapted from surf2stl by Bill McDonald. Huge speed % improvements implemented by Oliver Woodford. Non-Delaunay triangulation % of quadrilateral surface input requires mesh2tri by Kevin Moerman. % % Author: Sven Holcombe, 11-24-11 % Check valid filename path narginchk(2, inf) path = fileparts(filename); if ~isempty(path) && ~exist(path,'dir') error('Directory "%s" does not exist.',path); end % Get faces, vertices, and user-defined options for writing [faces, vertices, options] = parseInputs(varargin{:}); asciiMode = strcmp( options.mode ,'ascii'); % Create the facets facets = single(vertices'); facets = reshape(facets(:,faces'), 3, 3, []); % Compute their normals V1 = squeeze(facets(:,2,:) - facets(:,1,:)); V2 = squeeze(facets(:,3,:) - facets(:,1,:)); normals = V1([2 3 1],:) .* V2([3 1 2],:) - V2([2 3 1],:) .* V1([3 1 2],:); clear V1 V2 normals = bsxfun(@times, normals, 1 ./ sqrt(sum(normals .* normals, 1))); facets = cat(2, reshape(normals, 3, 1, []), facets); clear normals % Open the file for writing permissions = {'w','wb+'}; fid = fopen(filename, permissions{asciiMode+1}); if (fid == -1) error('stlwrite:cannotWriteFile', 'Unable to write to %s', filename); end % Write the file contents if asciiMode % Write HEADER fprintf(fid,'solid %s\r\n',options.title); % Write DATA fprintf(fid,[... 'facet normal %.7E %.7E %.7E\r\n' ... 'outer loop\r\n' ... 'vertex %.7E %.7E %.7E\r\n' ... 'vertex %.7E %.7E %.7E\r\n' ... 'vertex %.7E %.7E %.7E\r\n' ... 'endloop\r\n' ... 'endfacet\r\n'], facets); % Write FOOTER fprintf(fid,'endsolid %s\r\n',options.title); else % BINARY % Write HEADER fprintf(fid, '%-80s', options.title); % Title fwrite(fid, size(facets, 3), 'uint32'); % Number of facets % Write DATA % Add one uint16(0) to the end of each facet using a typecasting trick facets = reshape(typecast(facets(:), 'uint16'), 12*2, []); facets(end+1,:) = 0; fwrite(fid, facets, 'uint16'); end % Close the file fclose(fid); fprintf('Wrote %d facets\n',size(facets, 3)); %% Input handling subfunctions function [faces, vertices, options] = parseInputs(varargin) % Determine input type if isstruct(varargin{1}) % stlwrite('file', FVstruct, ...) if ~all(isfield(varargin{1},{'vertices','faces'})) error( 'Variable p must be a faces/vertices structure' ); end faces = varargin{1}.faces; vertices = varargin{1}.vertices; options = parseOptions(varargin{2:end}); elseif isnumeric(varargin{1}) firstNumInput = cellfun(@isnumeric,varargin); firstNumInput(find(~firstNumInput,1):end) = 0; % Only consider numerical input PRIOR to the first non-numeric numericInputCnt = nnz(firstNumInput); options = parseOptions(varargin{numericInputCnt+1:end}); switch numericInputCnt case 3 % stlwrite('file', X, Y, Z, ...) % Extract the matrix Z Z = varargin{3}; % Convert scalar XY to vectors ZsizeXY = fliplr(size(Z)); for i = 1:2 if isscalar(varargin{i}) varargin{i} = (0:ZsizeXY(i)-1) * varargin{i}; end end % Extract X and Y if isequal(size(Z), size(varargin{1}), size(varargin{2})) % X,Y,Z were all provided as matrices [X,Y] = varargin{1:2}; elseif numel(varargin{1})==ZsizeXY(1) && numel(varargin{2})==ZsizeXY(2) % Convert vector XY to meshgrid [X,Y] = meshgrid(varargin{1}, varargin{2}); else error('stlwrite:badinput', 'Unable to resolve X and Y variables'); end % Convert to faces/vertices if strcmp(options.triangulation,'delaunay') faces = delaunay(X,Y); vertices = [X(:) Y(:) Z(:)]; else if ~exist('mesh2tri','file') error('stlwrite:missing', '"mesh2tri" is required to convert X,Y,Z matrices to STL. It can be downloaded from:\n%s\n',... 'http://www.mathworks.com/matlabcentral/fileexchange/28327') end [faces, vertices] = mesh2tri(X, Y, Z, options.triangulation); end case 2 % stlwrite('file', FACES, VERTICES, ...) faces = varargin{1}; vertices = varargin{2}; otherwise error('stlwrite:badinput', 'Unable to resolve input types.'); end end function options = parseOptions(varargin) IP = inputParser; IP.addParamValue('mode', 'binary', @ischar) IP.addParamValue('title', sprintf('Created by stlwrite.m %s',datestr(now)), @ischar); IP.addParamValue('triangulation', 'delaunay', @ischar); IP.addParamValue('facecolor',[], @isnumeric) IP.parse(varargin{:}); options = IP.Results;

运行该程序包中的xyz2stl.mlapp,得到以下的界面:

(1)我读取的文件是csv格式,因此选择文件后,Field Delimiter选择Comma,文件头没有则为0,下面选择的参数默认即可。

(2)下一步选择输出的路径和文件名,其余参数默认,点击运行即可。

下面即为得到的stl文件。

致谢:感谢B站粉丝提供的问题。



【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭