Skip to content

Commit a81d1e7

Browse files
authored
update the missing files
1 parent 297bbbf commit a81d1e7

File tree

3 files changed

+407
-0
lines changed

3 files changed

+407
-0
lines changed

generate_gcode.m

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
function [] = generate_gcode( Crossing_Point_of_All_Slices,z_slices,Extrude_Speed,Move_Speed_G0,Move_Speed_G1,slice_height,save_direction)
2+
% Crossing_Point_of_All_Slices 所有分层的交点坐标
3+
% z_slices 所有切片分层的Z坐标值,一维行向量
4+
% Extrude_Speed 挤出速度控制,*mm/两个连续输出的交点
5+
% slice_height 切片分层厚度
6+
% Move_Speed (滑块)挤出头的移动速度,不是挤出速度
7+
% 所有切片层的Z坐标值 z_slices = min_z: slice_height :max_z;
8+
%% 输出模型的起始代码
9+
fileID = fopen(save_direction,'w'); % 打开并写入文件femur_O.gcode
10+
fprintf(fileID,'Layer height:%.2f\r\n',slice_height); %显示层高
11+
fprintf(fileID,'M104 S200\r\n'); % 在文件中写入Gcode
12+
fprintf(fileID,'M109 S200\r\n'); % 设置喷头的目标温度,然后在加热过程中等待
13+
% 以下的起始代码,每个模型均相同(参考cura软件 Machine_Setting)
14+
fprintf(fileID,'G28;Home\r\n'); %该命令将使挤出机回到坐标原点
15+
fprintf(fileID,'G1 Z15.0 F6000;Move the platform down 15mm\r\n');
16+
fprintf(fileID,';Prime the extruder\r\n');
17+
fprintf(fileID,'G92 E0\r\n'); % G92指定当前各轴的坐标值指定当前各轴的坐标值
18+
fprintf(fileID,'G1 F200 E3\r\n');
19+
fprintf(fileID,'G92 E0\r\n');
20+
21+
%% 输出模型的代码Gcode
22+
fprintf(fileID,';Layer_Count:%d\r\n',size(z_slices,2)); %统计切片和打印的层数
23+
%% 输出第一层G代码
24+
fprintf(fileID,';Layer:%d\r\n',0); %定义初始层0
25+
%关闭风扇 M106 S0也可以达到相同的效果
26+
fprintf(fileID,'M107\r\n');
27+
% 提取第一层(第一个元胞)数据
28+
Crossing_Point_of_first_Slice = Crossing_Point_of_All_Slices{1};
29+
if ~isempty(Crossing_Point_of_first_Slice)
30+
% 快速定位到待打印区域附近,距离打印的第一个点XY方向分别为1mm
31+
% 如果第一个元胞(第一层)数据非空,则输出当前(第一个)元胞(层)的G代码
32+
% 快速定位时挤出机不挤出
33+
fprintf(fileID,'G0 F%d X%.2f Y%.2f Z%.2f\r\n',...
34+
Move_Speed_G0,...
35+
Crossing_Point_of_first_Slice(1,1)-1,...
36+
Crossing_Point_of_first_Slice(1,2)-1,...
37+
z_slices(1));
38+
Extrude_Length_of_Each_Step = 0;
39+
% 快速定位后输出同一层其他点的G代码
40+
% 第一顶点显示G1速度
41+
fprintf(fileID,'G1 F%.2f X%.2f Y%.2f\r\n',...
42+
Move_Speed_G1,... % 挤出机移动速度
43+
Crossing_Point_of_first_Slice(1,1),...
44+
Crossing_Point_of_first_Slice(1,2));
45+
46+
% 其他点不再显示G1速度
47+
for l = 2:size(Crossing_Point_of_first_Slice,1)
48+
% 每个指令都要比上一个指令的挤出长度多一个Extrude_Speed
49+
% 通过调整Extrude_Speed的大小,同一层打印也可实现变速
50+
Extrude_Length_of_Each_Step = Extrude_Length_of_Each_Step + Extrude_Speed;
51+
% 快速定位后输出其他点G代码
52+
fprintf(fileID,'G1 X%.2f Y%.2f E%.5f\r\n',...
53+
Crossing_Point_of_first_Slice(l,1),...
54+
Crossing_Point_of_first_Slice(l,2),...
55+
Extrude_Length_of_Each_Step);
56+
end
57+
%% 输出第二层及以上层G代码
58+
% 由于第一层已经输出,所以这里从第二层输出
59+
for i = 2: size(Crossing_Point_of_All_Slices,2)
60+
% 通过for循环 逐个提取每个切片层的元胞子矩阵 到矩阵Crossing_Poin_of_each_Slice中
61+
Crossing_Point_of_each_Slice = Crossing_Point_of_All_Slices{i};
62+
% 每一层输出G代码之前都要定义该层的编号
63+
fprintf(fileID,';Layer:%d\r\n',i-1);
64+
fprintf(fileID,'M106 S255\r\n');
65+
% 定义打印类型
66+
fprintf(fileID,';TYPE:WALL-OUTER\r\n');
67+
68+
% 快速定位到当前层的第一个顶点附近
69+
fprintf(fileID,'G0 F%d X%.2f Y%.2f Z%.2f\r\n',...
70+
Move_Speed_G0,... %快速移动时的挤出机移动速度
71+
Crossing_Point_of_each_Slice(1,1)-1,... % X坐标
72+
Crossing_Point_of_each_Slice(1,2)-1,... % Y坐标
73+
z_slices(i));
74+
75+
% 第一个顶点(j=1)显示挤出机移动速度,同一层的其他点不再显示挤出机速度
76+
fprintf(fileID,'G1 F%d X%.2f Y%.2f E%.5f\r\n',...
77+
Move_Speed_G1,... % 挤出机移动速度
78+
Crossing_Point_of_each_Slice(1,1),... % X坐标
79+
Crossing_Point_of_each_Slice(1,2),... % Y坐标
80+
Extrude_Length_of_Each_Step); % 挤出机的挤出速度
81+
% 同一层,第一个命令G1输出挤出机移动速度,之后的点(j>=2)(之后的指令)不再显示挤出机移动速度
82+
for j = 2:size(Crossing_Point_of_each_Slice,1)
83+
% 每个指令都要比上一个指令的挤出长度多一个Extrude_Speed
84+
% 通过调整Extrude_Speed的大小,同一层打印也可实现变速
85+
Extrude_Length_of_Each_Step = Extrude_Length_of_Each_Step + Extrude_Speed;
86+
fprintf(fileID,'G1 X%.2f Y%.2f E%.5f\r\n',...
87+
Crossing_Point_of_each_Slice(j,1),...
88+
Crossing_Point_of_each_Slice(j,2),...
89+
Extrude_Length_of_Each_Step);
90+
end
91+
92+
end
93+
94+
%% 读取第一元胞子矩阵时的第二种情况
95+
else
96+
Extrude_Length_of_Each_Step = 0;
97+
% 如果第一个元胞(第一层)数据空,则输出第2个元胞(层)的G代码
98+
% 输出第一层G代码
99+
Crossing_Point_of_first_Slice = Crossing_Point_of_All_Slices{2};
100+
% 快速定位
101+
fprintf(fileID,'G0 F%d X%.2f Y%.2f Z%.2f\r\n',...
102+
Move_Speed_G0,...
103+
Crossing_Point_of_first_Slice(1,1)-1,...
104+
Crossing_Point_of_first_Slice(1,2)-1,...
105+
z_slices(2));
106+
% 快速定位后输出同一层其他点的G代码
107+
% 第一顶点显示G1速度,其他点不再显示G1速度
108+
fprintf(fileID,'G1 F%d X%.2f Y%.2f\r\n',...
109+
Move_Speed_G1,...
110+
Crossing_Point_of_first_Slice(1,1),...
111+
Crossing_Point_of_first_Slice(1,2));
112+
113+
for k = 2:size(Crossing_Point_of_first_Slice,1)
114+
% 每个指令都要比上一个指令的挤出长度多一个Extrude_Speed
115+
% 通过调整Extrude_Speed的大小,同一层打印也可实现变速
116+
Extrude_Length_of_Each_Step = Extrude_Length_of_Each_Step + Extrude_Speed;
117+
% 快速定位后输出同一层其他点的G代码
118+
fprintf(fileID,'G1 X%.2f Y%.2f E%.5f\r\n',...
119+
Crossing_Point_of_first_Slice(k,1),...
120+
Crossing_Point_of_first_Slice(k,2),...
121+
Extrude_Length_of_Each_Step);
122+
end
123+
% 如果第一层元胞为空,第二层已经输出,所以这里从第三层输出
124+
for i = 3 : size(Crossing_Point_of_All_Slices,2)
125+
% 通过for循环 逐个提取每个切片层的元胞子矩阵 到矩阵Crossing_Poin_of_each_Slice中
126+
Crossing_Point_of_each_Slice = Crossing_Point_of_All_Slices{i};
127+
% 每一层输出G代码之前都要定义该层的编号
128+
fprintf(fileID,';Layer:%d\r\n',i-2);
129+
fprintf(fileID,'M106 S255\r\n');
130+
% 定义打印类型
131+
fprintf(fileID,';TYPE:WALL-OUTER\r\n');
132+
% 每一层都要进行快速定位
133+
% 快速定位到当前层的第一个顶点附近,距离第一点(X,Y)各1mm
134+
% 同层快速定位时输出Z轴坐标,其他指令不再输出Z坐标
135+
fprintf(fileID,'G0 F%d X%.2f Y%.2f Z%.2f\r\n',...
136+
Move_Speed_G0,... %快速移动时的挤出机移动速度
137+
Crossing_Point_of_each_Slice(1,1)-1,... % X坐标
138+
Crossing_Point_of_each_Slice(1,2)-1,... % Y坐标
139+
z_slices(i));
140+
141+
% 同一层的第一个顶点(j=1)显示挤出机移动速度,
142+
% 同一层的其他点不再显示挤出机移动速度
143+
fprintf(fileID,'G1 F%d X%.2f Y%.2f E%.5f\r\n',...
144+
Move_Speed_G1,... % G1运动时的挤出机移动速度
145+
Crossing_Point_of_each_Slice(1,1),...% X坐标
146+
Crossing_Point_of_each_Slice(1,2),...% Y坐标
147+
Extrude_Length_of_Each_Step);
148+
149+
% 同一层,第一个指令G1输出挤出机移动速度,
150+
% 之后的点(j>=2)(之后的指令)不再显示挤出机移动速度
151+
for j = 2:size(Crossing_Point_of_each_Slice,1)
152+
% 每个指令都要比上一个指令的挤出长度多一个Extrude_Speed
153+
% 通过调整Extrude_Speed的大小,同一层打印也可实现变速
154+
Extrude_Length_of_Each_Step = Extrude_Length_of_Each_Step + Extrude_Speed;
155+
fprintf(fileID,'G1 X%.2f Y%.2f E%.5f\r\n',...
156+
Crossing_Point_of_each_Slice(j,1),...
157+
Crossing_Point_of_each_Slice(j,2),...
158+
Extrude_Length_of_Each_Step);
159+
end
160+
161+
end
162+
end
163+
164+
%% 输出模型的终止代码
165+
fprintf(fileID,'M107\r\n');
166+
fprintf(fileID,'M104 S0\r\n');
167+
fprintf(fileID,'M140 S0\r\n');
168+
fprintf(fileID,'; Retract the filament\r\n');
169+
fprintf(fileID,'G92 E1\r\n');
170+
fprintf(fileID,'G1 E-1 F300\r\n');
171+
fprintf(fileID,'G28 X0 Y0\r\n');
172+
fprintf(fileID,'M84\r\n');
173+
fprintf(fileID,'M104 S0\r\n');
174+
fprintf(fileID,';End of Gcode\r\n');
175+
176+
end
177+

slice_stl_create_path.m

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
function [Crossing_Point_of_All_Slices,z_slices,model_height,triangles_new] = slice_stl_create_path(triangles,slice_height)
2+
% 该函数将读取的stl文件中的三角面片按照设定的切片高度分层。
3+
% 这会产生一系列坐标,3D打印机需要移动不同的高度对stl文件创建不同的轮廓。
4+
% 函数首先寻找并计算三角面片与切片平面的交线
5+
% 该函数创建连续的路径
6+
% uniquetol函数是在Matlab 2015b 及更高版本中集成
7+
%% 模型Z轴向高度
8+
% 根据三角面片来计算模型的Z轴方向的高度,最大和最小位置
9+
% 12列中的3,6,9列恰恰是三角面片的Z坐标值
10+
min_z = min([triangles(:,3); triangles(:,6);triangles(:,9)])-1e-5;
11+
max_z = max([triangles(:,3); triangles(:,6);triangles(:,9)])+1e-5;
12+
model_height = max_z - min_z;
13+
%% 等厚度分层
14+
% Z轴方向实现等厚度 slice_height 切片。其中 z_slices 是 1X413 维度的一维行向量,
15+
% z_slices 代表所有切平面的Z轴方向坐标值
16+
% 切平面的两个极端值,最高最低位置均穿过三角面片的顶点
17+
z_slices = min_z: slice_height :max_z;
18+
% 初始化元胞数组 movelist_all
19+
Crossing_Point_of_All_Slices = {};
20+
% min(A,[],2)是一个列向量,由A中每一行的最小值组成
21+
% 因此 min(triangles(:,[3 6 9]),[],2)表示triangles(:,[3 6 9])每一行三个顶点Z坐标的最小值(每个三角面片的最低的那个顶点)
22+
% max(triangles(:,[ 3 6 9]),[],2)表示triangles(:,[3 6 9])每一行三个顶点Z坐标的最大值(每个三角面片的最高的那个顶点)
23+
% 最终triangles_new是一个14列矩阵,后两列包含三角面片的最低顶点(第13列)和最高顶点(第14列)
24+
triangles_new = [triangles(:,1:12),min(triangles(:,[3 6 9]),[],2), max(triangles(:,[ 3 6 9]),[],2)];
25+
%% 寻找相交的三角形面片
26+
slices = z_slices;
27+
% slices所有切平面的Z坐标值,z_slices是一维行矩阵
28+
29+
% 开辟预处理空间 ,size(A,2)表示二维矩阵A的第二个维度大小,即列数
30+
z_triangles = zeros(size(z_slices,2),4000);
31+
z_triangles_size = zeros(size(z_slices,2),1);
32+
% size(triangles_new,1)表示所有三角面片的总个数
33+
for i = 1:size(triangles_new,1)
34+
node_lowest = triangles_new(i,13); % triangles_new(i,13)表示三角面片的最低顶点node_lowest,第13列
35+
high= size(slices,2); % high表示切平面的总个数,即最高位置的切平面编号
36+
low = 1; % low表示最低位置的切平面编号
37+
% start_point = floor((max+min)/2);
38+
not_match = true;
39+
% include1 = true;
40+
% include2 = true;
41+
while not_match % not_match值为真开始循环
42+
mid = low + floor((high - low)/2); %二分法求 参考切平面位置索引编号mid
43+
%check = comparator_floating2(match_node,nodes(mid,:),tol);
44+
% mid
45+
% slices(mid)
46+
% node
47+
%triangles(i,:)
48+
%% 判断参考平面与三角面片的相对位置关系
49+
if mid == 1 && slices(mid) >= node_lowest % 参考切平面高度高于三角面片的最低顶点,并且参考切平面已经到达最低处的切平面
50+
check = 2; % 这是一个错误的情况
51+
elseif slices(mid) <= node_lowest && mid == size(slices,2) % 参考切平面高度低于三角面片的最低顶点,并且参考切平面已经到达最高处的切平面
52+
check = 2; % 这是一个错误的情况
53+
elseif slices(mid)>node_lowest && slices(mid-1)<node_lowest % 参考切平面高度高于三角面片的最低顶点,并且(紧贴的)下方的切平面低于最低顶点
54+
check = 0;
55+
elseif slices(mid)>node_lowest % 参考切平面高度高于三角面片的最低顶点
56+
check = -1;
57+
elseif slices(mid) < node_lowest % 参考切平面高度低于三角面片的最低顶点
58+
check = 1;
59+
end
60+
61+
if check == -1 %当参考切平面高度高于三角面片的最低顶点
62+
high = mid - 1; %将参考平面降低一个位置
63+
elseif check == 1 %当参考切平面高度低于三角面片的最低顶点
64+
low = mid + 1; %将参考平面增加一个位置
65+
elseif check == 0 %当参考切平面高度高于三角面片的最低顶点,并且(紧贴的)下方的切平面低于最低顶点
66+
node_lowest = mid; %此时的参考平面刚好位于最低
67+
not_match = false;%匹配成功
68+
elseif high > low || check == 2
69+
include1 = false;
70+
not_match = false;
71+
end
72+
end
73+
% z_low_index 表示最低切平面的索引指数
74+
z_low_index = mid;
75+
%binary check high
76+
node_highest = triangles_new(i,14); % triangles_new(i,14)第14列,表示三角面片的最高顶点
77+
high= size(slices,2); % high表示切平面的总个数,即最高位置的切平面编号
78+
low = 1; % low表示最低位置的切平面编号
79+
%start_point = floor((max+min)/2);
80+
not_match = true; % 没有匹配成功 not match
81+
while not_match
82+
mid = low + floor((high - low)/2); %二分法求 参考切平面位置索引编号mid
83+
%check = comparator_floating2(match_node,nodes(mid,:),tol);
84+
if mid == 1 && slices(1) <= node_highest % 参考切平面编号等于最低处的切平面编号,并且最低切平面高度值小于等于三角面片的最高顶点高度值
85+
check = 2; % check = 2 表示参考切平面位置无效
86+
elseif mid == size(slices,2) && slices(mid) <=node_highest % 参考切平面编号等于最高处的切平面编号,并且参考切平面高度值小于等于三角面片的最高顶点高度值
87+
check = 2;
88+
elseif slices(mid)>node_highest && slices(mid-1)<node_highest % 参考切平面高度值大于三角面片的最高顶点高度值,并且参考切平面下方紧挨的平面高度值小于等于三角面片的最高顶点高度值
89+
check = 0; % check == 0表示参考平面已经移动到了模型的最高位置处
90+
elseif slices(mid)>node_highest % 参考切平面高度值大于三角面片的最高顶点高度值
91+
check = -1; % check = -1表示参考平面位置过高
92+
elseif slices(mid) < node_highest % 参考切平面高度值小于三角面片的最高顶点高度值
93+
check = 1; % check = 1表示参考平面位置过低
94+
end
95+
96+
if check == -1 % 参考切平面高度值大于三角面片的最高顶点高度值
97+
high = mid - 1; % check = -1表示参考平面位置过高,将参考平面下移一个位置
98+
elseif check == 1 % 参考切平面高度值小于三角面片的最高顶点高度值
99+
low = mid + 1; % check = -1表示参考平面位置过低,将参考平面上移一个位置
100+
elseif check == 0 % 参考切平面高度值大于三角面片的最高顶点高度值,并且参考切平面下方紧挨的平面高度值小于等于三角面片的最高顶点高度值
101+
node_highest = mid; % check == 0表示参考平面已经移动到了模型的最高位置处
102+
not_match = false;
103+
elseif high > low || check == 2 % 参考切平面编号等于最高处的切平面编号,并且参考切平面高度值小于等于三角面片的最高顶点高度值
104+
include2 = false; % 参考切平面编号等于最低处的切平面编号,并且最低切平面高度值小于等于三角面片的最高顶点高度值
105+
not_match = false; % check = 2 表示参考切平面位置无效
106+
end
107+
108+
end
109+
z_high_index = mid; % z_high_index 表示最高切平面的索引指数
110+
if z_high_index > z_low_index % 当最高处的切平面索引指数高于最低处的切平面索引指数
111+
for j = z_low_index:z_high_index-1
112+
z_triangles_size(j) = z_triangles_size(j) + 1;
113+
z_triangles(j,z_triangles_size(j)) = i;
114+
end
115+
end
116+
end
117+
% size(z_slices,2) 计算z_slices的第二个维度的大小,即列数
118+
% 此处的 k 值表示切片的编号
119+
for k = 1:size(z_slices,2)
120+
triangle_checklist = z_triangles(k,1:z_triangles_size(k));
121+
% 调用三角面片的交线求取函数 triangle_plane_intersection
122+
% linesize表示与某一切平面相交的三角面片数量,也可以表述为同一层相交线的个数,
123+
% size_pts_out也对应于该函数输出参数linesize(交线的数量)
124+
% lines表示与某一切平面相交的三角面片的顶点,
125+
% pts_out也对应于该函数的输出参数lines(交线的两个顶点)
126+
[lines,linesize] = triangle_plane_intersection(triangles_new(triangle_checklist,:), z_slices(k));
127+
% lines的数据结构,lines的每一行表示指定某一切片层的某个相交线的两端点坐标值,
128+
% lines的1-2列表示某个直线段的起点坐标值(X,Y)
129+
% lines的4-5列表示某个直线段的终点坐标值(X,Y)
130+
% linesize表示指定某一切片层中的相交线的总数
131+
if linesize ~= 0
132+
%查找所有分配的节点,并将重复项删除
133+
start_nodes = lines(1:linesize,1:2); %交线的开始节点二维坐标
134+
end_nodes = lines(1:linesize,4:5); %交线的终止节点坐标
135+
nodes = [start_nodes; end_nodes]; %汇总交线的所有节点坐标
136+
% connectivity = [];
137+
tol_uniquetol = 1e-8; %设定容差
138+
tol = 1e-8;
139+
%uniquetol函数是在Matlab 2015b 及更高版本中集成
140+
nodes = uniquetol(nodes,tol_uniquetol,'ByRows',true);
141+
nodes = sortrows(nodes,[1 2]);
142+
[~, n1] = ismembertol(start_nodes, nodes, tol, 'ByRows',true);
143+
[~, n2] = ismembertol(end_nodes, nodes,tol, 'ByRows',true);
144+
conn1 = [n1 n2];
145+
%检查损坏的stl文件,重复的边,太薄的表面,不封闭的图形
146+
%当发现stl模型是损坏的,则进行以下步骤进行修复
147+
conn2 = [n2 n1];
148+
check = ismember(conn2,conn1,'rows');
149+
conn1(check == 1,:)=[];
150+
%end check
151+
G = graph(conn1(:,1),conn1(:,2));
152+
%conncomp 函数用于创建连接几何的图形
153+
%bins 返回连接节点的数量
154+
% BINS = CONNCOMP(G) 计算图形G中相互连接的几何
155+
% BINS(i) 给出了包含节点i的几何的数量
156+
% 如果有路径连接他们,节点属于相同的几何
157+
bins = conncomp(G);
158+
Crossing_Point_of_Slice =[];
159+
for i = 1: max(bins)
160+
startNode = find(bins==i, 1, 'first');
161+
%path =[];%开辟预处理空间
162+
path = dfsearch(G, startNode);
163+
path = [path; path(1)];
164+
%list of x and y axes
165+
Crossing_Point_of_Slice1 = [nodes(path,1) nodes(path,2)];
166+
%Crossing_Point_of_Slice包含同一层的所有交点数据
167+
Crossing_Point_of_Slice = [Crossing_Point_of_Slice;Crossing_Point_of_Slice1];
168+
Size_Crossing_Point_of_Slice = size(Crossing_Point_of_Slice,1);
169+
end
170+
% 创建元胞数组,每一层的数据是一个子元胞
171+
Crossing_Point_of_All_Slices(k) = {Crossing_Point_of_Slice};
172+
end
173+
end
174+
175+
176+
177+

0 commit comments

Comments
 (0)