forked from MatterHackers/MatterSlice
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsliceDataStorage.cs
263 lines (225 loc) · 10 KB
/
sliceDataStorage.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
/*
This file is part of MatterSlice. A commandline utility for
generating 3D printing GCode.
Copyright (C) 2013 David Braam
Copyright (c) 2014, Lars Brubaker
MatterSlice is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.Diagnostics;
using MatterSlice.ClipperLib;
namespace MatterHackers.MatterSlice
{
using Polygon = List<IntPoint>;
using Polygons = List<List<IntPoint>>;
/*
SliceData
+ Layers[]
+ LayerParts[]
+ OutlinePolygons[]
+ Insets[]
+ Polygons[]
+ SkinPolygons[]
*/
public class SliceLayerPart
{
public AABB boundaryBox = new AABB();
public Polygons outline = new Polygons();
public Polygons combBoundery = new Polygons();
public List<Polygons> insets = new List<Polygons>();
public Polygons skinOutline = new Polygons();
public Polygons sparseOutline = new Polygons();
public int bridgeAngle;
};
public class SliceLayer
{
public long printZ;
public List<SliceLayerPart> parts = new List<SliceLayerPart>();
};
/******************/
public class SupportPoint
{
public int z;
public double angleFromHorizon;
public SupportPoint(int z, double angleFromHorizon)
{
this.z = z;
this.angleFromHorizon = angleFromHorizon;
}
}
public class SupportStorage
{
public bool generated;
public int endAngleDegrees;
public bool generateInternalSupport;
public int supportXYDistance_um;
public int supportLayerHeight_um;
public int supportZGapLayers;
public int supportInterfaceLayers;
public IntPoint gridOffset;
public int gridScale;
public int gridWidth, gridHeight;
public List<List<SupportPoint>> xYGridOfSupportPoints = new List<List<SupportPoint>>();
static void swap(ref int p0, ref int p1)
{
int tmp = p0;
p0 = p1;
p1 = tmp;
}
static void swap(ref long p0, ref long p1)
{
long tmp = p0;
p0 = p1;
p1 = tmp;
}
static void swap(ref Point3 p0, ref Point3 p1)
{
Point3 tmp = p0;
p0 = p1;
p1 = tmp;
}
private static int SortSupportsOnZ(SupportPoint one, SupportPoint two)
{
return one.z.CompareTo(two.z);
}
public void GenerateSupportGrid(OptimizedModel model, ConfigSettings config)
{
this.generated = false;
if (config.supportEndAngle < 0)
{
return;
}
this.generated = true;
this.gridOffset.X = model.minXYZ_um.x;
this.gridOffset.Y = model.minXYZ_um.y;
this.gridScale = 200;
this.gridWidth = (model.size_um.x / this.gridScale) + 1;
this.gridHeight = (model.size_um.y / this.gridScale) + 1;
int gridSize = this.gridWidth * this.gridHeight;
this.xYGridOfSupportPoints = new List<List<SupportPoint>>(gridSize);
for (int i = 0; i < gridSize; i++)
{
this.xYGridOfSupportPoints.Add(new List<SupportPoint>());
}
this.endAngleDegrees = config.supportEndAngle;
this.generateInternalSupport = config.generateInternalSupport;
this.supportXYDistance_um = config.supportXYDistance_um;
this.supportLayerHeight_um = config.layerThickness_um;
this.supportZGapLayers = config.supportNumberOfLayersToSkipInZ;
this.supportInterfaceLayers = config.supportInterfaceLayers;
// This should really be a ray intersection as later code is going to count on it being an even odd list of bottoms and tops.
// As it is we are finding the hit on the plane but not checking for good intersection with the triangle.
for (int volumeIndex = 0; volumeIndex < model.volumes.Count; volumeIndex++)
{
OptimizedVolume vol = model.volumes[volumeIndex];
for (int faceIndex = 0; faceIndex < vol.facesTriangle.Count; faceIndex++)
{
OptimizedFace faceTriangle = vol.facesTriangle[faceIndex];
Point3 v0 = vol.vertices[faceTriangle.vertexIndex[0]].position;
Point3 v1 = vol.vertices[faceTriangle.vertexIndex[1]].position;
Point3 v2 = vol.vertices[faceTriangle.vertexIndex[2]].position;
// get the angle of this polygon
double angleFromHorizon;
{
FPoint3 v0f = new FPoint3(v0);
FPoint3 v1f = new FPoint3(v1);
FPoint3 v2f = new FPoint3(v2);
FPoint3 normal = (v1f - v0f).Cross(v2f - v0f);
normal.z = Math.Abs(normal.z);
angleFromHorizon = (Math.PI / 2) - FPoint3.CalculateAngle(normal, FPoint3.Up);
}
v0.x = (int)((v0.x - this.gridOffset.X) / (double)this.gridScale + .5);
v0.y = (int)((v0.y - this.gridOffset.Y) / (double)this.gridScale + .5);
v1.x = (int)((v1.x - this.gridOffset.X) / (double)this.gridScale + .5);
v1.y = (int)((v1.y - this.gridOffset.Y) / (double)this.gridScale + .5);
v2.x = (int)((v2.x - this.gridOffset.X) / (double)this.gridScale + .5);
v2.y = (int)((v2.y - this.gridOffset.Y) / (double)this.gridScale + .5);
if (v0.x > v1.x) swap(ref v0, ref v1);
if (v1.x > v2.x) swap(ref v1, ref v2);
if (v0.x > v1.x) swap(ref v0, ref v1);
for (long x = v0.x; x < v1.x; x++)
{
long y0 = (long)(v0.y + (v1.y - v0.y) * (x - v0.x) / (double)(v1.x - v0.x) + .5);
long y1 = (long)(v0.y + (v2.y - v0.y) * (x - v0.x) / (double)(v2.x - v0.x) + .5);
long z0 = (long)(v0.z + (v1.z - v0.z) * (x - v0.x) / (double)(v1.x - v0.x) + .5);
long z1 = (long)(v0.z + (v2.z - v0.z) * (x - v0.x) / (double)(v2.x - v0.x) + .5);
if (y0 > y1)
{
swap(ref y0, ref y1);
swap(ref z0, ref z1);
}
for (long y = y0; y < y1; y++)
{
SupportPoint newSupportPoint = new SupportPoint((int)(z0 + (z1 - z0) * (y - y0) / (double)(y1 - y0) + .5), angleFromHorizon);
this.xYGridOfSupportPoints[(int)(x + y * this.gridWidth)].Add(newSupportPoint);
}
}
for (int x = v1.x; x < v2.x; x++)
{
long y0 = (long)(v1.y + (v2.y - v1.y) * (x - v1.x) / (double)(v2.x - v1.x) + .5);
long y1 = (long)(v0.y + (v2.y - v0.y) * (x - v0.x) / (double)(v2.x - v0.x) + .5);
long z0 = (long)(v1.z + (v2.z - v1.z) * (x - v1.x) / (double)(v2.x - v1.x) + .5);
long z1 = (long)(v0.z + (v2.z - v0.z) * (x - v0.x) / (double)(v2.x - v0.x) + .5);
if (y0 > y1)
{
swap(ref y0, ref y1);
swap(ref z0, ref z1);
}
for (int y = (int)y0; y < y1; y++)
{
this.xYGridOfSupportPoints[x + y * this.gridWidth].Add(new SupportPoint((int)(z0 + (z1 - z0) * (double)(y - y0) / (double)(y1 - y0) + .5), angleFromHorizon));
}
}
}
}
for (int x = 0; x < this.gridWidth; x++)
{
for (int y = 0; y < this.gridHeight; y++)
{
int gridIndex = x + y * this.gridWidth;
List<SupportPoint> currentList = this.xYGridOfSupportPoints[gridIndex];
currentList.Sort(SortSupportsOnZ);
if(currentList.Count > 1)
{
// now remove duplicates (try to make it a better bottom and top list)
for (int i = currentList.Count-1; i>=1; i--)
{
if (currentList[i].z == currentList[i - 1].z)
{
currentList.RemoveAt(i);
}
}
}
}
}
this.gridOffset.X += this.gridScale / 2;
this.gridOffset.Y += this.gridScale / 2;
}
}
/******************/
public class SliceVolumeStorage
{
public List<SliceLayer> layers = new List<SliceLayer>();
}
public class SliceDataStorage
{
public Point3 modelSize, modelMin, modelMax;
public Polygons skirt = new Polygons();
public Polygons raftOutline = new Polygons();
public List<Polygons> wipeShield = new List<Polygons>();
public List<SliceVolumeStorage> volumes = new List<SliceVolumeStorage>();
public SupportStorage support = new SupportStorage();
public Polygons wipeTower = new Polygons();
public IntPoint wipePoint;
}
}