API Documentation
Loading...
Searching...
No Matches
Extruder.h
Go to the documentation of this file.
1/**--------------------------------------------------------------------------------------------
2Copyright (c) 2019, NDEVR LLC
3tyler.parke@ndevr.org
4 __ __ ____ _____ __ __ _______
5 | \ | | | __ \ | ___|\ \ / / | __ \
6 | \ | | | | \ \ | |___ \ \ / / | |__) |
7 | . \| | | |__/ / | |___ \ V / | _ /
8 | |\ |_|_____/__|_____|___\_/____| | \ \
9 |__| \__________________________________| \__\
10
11Subject to the terms of the Enterprise+ Agreement, NDEVR hereby grants
12Licensee a limited, non-exclusive, non-transferable, royalty-free license
13(without the right to sublicense) to use the API solely for the purpose of
14Licensee's internal development efforts to develop applications for which
15the API was provided.
16
17The above copyright notice and this permission notice shall be included in all
18copies or substantial portions of the Software.
19
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
21INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
22PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
23FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25DEALINGS IN THE SOFTWARE.
26
27Library: Design
28File: Extruder
29Included in API: True
30Author(s): Tyler Parke
31 *-----------------------------------------------------------------------------------------**/
32#pragma once
33#include <NDEVR/Geometry.h>
34#include <NDEVR/Plane.h>
35namespace NDEVR
36{
37 /**--------------------------------------------------------------------------------------------------
38 Class: Extruder
39
40 Class containing static functions that define logic to extrude shapes along some given polyline
41
42 Author: Tyler Parke
43
44 Date: 2019-01-14
45 *-----------------------------------------------------------------------------------------------**/
47 {
48 public:
49
50 /**--------------------------------------------------------------------------------------------------
51 Fn: void Extruder::ExtrudeRealThickness(Geometry& geo) const
52
53 Given a linework geometry, extrudes a flat line alog the path in order to create a "ribbon" with a
54 flat apperence and a thickness defined by geometryproperty Geometry::e_thickness
55
56 Author: Tyler Parke
57
58 Date: 2019-01-14
59
60 Parameters:
61 linework - The linework whos geometrytype must be of type linework, and must have some valid > 0.0 real
62 thickness. Upon completion of this function, the Solid index channel of this object will be filled with
63 vertices and indices relating to the object's real thickness.
64 *-----------------------------------------------------------------------------------------------**/
65 static void ExtrudeRealThickness(Geometry& linework, const Matrix<fltp08>& transform = Matrix<fltp08>(1.0))
66 {
67 lib_assert(linework.getGeometryType() == GeometryType::e_linework, "Can only extrude thickness along geometry of type linework");
69 lib_assert(!isNaN(thickness) && thickness > 0.0, "Thickness must be > 0.0");
70 Polyline<3, fltp08> geo_line;//Stores the line we want to extrude along the path
71 switch (linework.thicknessMode())
72 {
75 linework.setSolidVertexCountValue(0);
78 return;
81 geo_line.add({ -thickness / 2.0, 0, 0 });
82 geo_line.add({ thickness / 2.0, 0, 0 });
83 break;
86 {
87 uint04 width_segments = 128;
88 for (uint04 x = 0; x <= width_segments; x++)
89 {
90 fltp08 u = cast<fltp08>(x) / cast<fltp08>(width_segments);
91 const Angle angle = u * Angle<fltp08>(DEGREES, 360.0f);
92 Vertex<3, fltp08> position(-thickness * cos(angle), thickness * sin(angle), 0.0);
93 geo_line.add(position);
94
95 }
96 } break;
97 }
98
99
100 ExtrudePolylineAlongGeo(linework, geo_line, transform);
101 }
102
103 /**--------------------------------------------------------------------------------------------------
104 Fn: void Extruder::ExtrudeRealThickness(Geometry& mesh) const
105
106 Given a linework geometry, extrudes the given polyline along that linework
107
108 Author: Tyler Parke
109
110 Date: 2019-01-14
111
112 Parameters:
113 linework - The linework whos geometrytype must be of type linework and will store the extrusion.
114 Upon completion of this function, the Solid index channel of this object will be filled with
115 vertices and indices of the polyline extruded across the linework
116 *-----------------------------------------------------------------------------------------------**/
117 static void ExtrudePolylineAlongGeo(Geometry& linework, const Polyline<3, fltp08>& geo_line, const Matrix<fltp08>& transform = Matrix<fltp08>(1.0))
118 {
119 lib_assert(linework.getGeometryType() == GeometryType::e_linework, "Can only extrude thickness along geometry of type linework");
120
122
123
124
125 bool is_closed = linework.getGeometryProperty<bool>(Geometry::e_has_closed_primitive);
127
129 Buffer<Vertex<3, fltp08>> vertices;
130 Matrix<fltp08> poly_transform = (transform * linework.getTransform()).invert();
131 //Extrude Shape
132 for (uint04 i = 0; i < polylines.size(); i++)
133 {
134 polylines[i].simplify();
135 Vector<3, fltp08> poly_normal = plane_normal;
136 if (isNaN(poly_normal))
137 {
138 Vector<3, fltp08> bounds = polylines[i].bounds().span();
139 if (bounds[X] * bounds[X] + bounds[Y] * bounds[Y] > bounds[Z] * bounds[Z])
140 poly_normal = { 0.0, 0.0, 1.0 };
141 else if (bounds[X] * bounds[X] > bounds[Y] * bounds[Y])
142 poly_normal = { 0.0, 1.0, 0.0 };
143 else
144 poly_normal = { 1.0, 0.0, 0.0 };
145 }
146 Extrude(indices, vertices, geo_line, polylines[i], poly_normal, is_closed, poly_transform);
147 }
148
149 //Add shape to Geometry
150 uint04 solid_vertex_offset = linework.solidVertexOffset();
151 if (isNaN(solid_vertex_offset))
152 {
153 solid_vertex_offset = linework.vertexCount();
154 linework.setSolidVertexOffsetValue(solid_vertex_offset);
155 }
156 uint04 solid_vertex_size = linework.solidVertexReservedCount();
157 if (solid_vertex_size < vertices.size())
158 {
159 linework.addVertices(solid_vertex_offset, vertices.size() - solid_vertex_size);
160 linework.setSolidVertexReservedValue(vertices.size());
161 }
162 linework.setSolidVertexCountValue(vertices.size());
163 for (uint04 i = 0; i < vertices.size(); i++)
164 {
165 linework.setVertex(VertexProperty::Position, solid_vertex_offset + i, vertices[i]);
166 }
169 linework.setPrimitiveRange(PrimitiveProperty::Solid, index_offset, indices.size());
170 for (uint04 i = 0; i < indices.size(); i++)
171 {
172 linework.setPrimitive(PrimitiveProperty::Solid, i, solid_vertex_offset + indices[i]);
173 }
174 linework.updateVertexColumns();
175 linework.updateSolidVertexColumns();
176 linework.updatePrimitiveColumns();
177 linework.updateModifiedTime();
178 }
179
180 /**--------------------------------------------------------------------------------------------------
181 Fn: void Extruder::Extrude(Geometry& mesh, const Buffer<std::pair<Polyline<3, t_type>, bool>>& shape_to_extrude
182 , const Polyline<3, t_type>& extrude_path, const Vector<3, t_type>& plane_normal, bool is_path_closed) const
183
184 Given a linework geometry, extrudes a shape along the provided path to create a triangulated solid.
185 Note that the winding of the final shape will be the same as the given shape to extrude. Reversing
186 the vertices of this shape will reverse the winding order of the final solid. Note that passing a path
187 which fully lies in plane whos normal is perpendicular to the given plane normal will result in undefined
188 behavior
189
190 Author: Tyler Parke
191
192 Date: 2019-01-14
193
194 Parameters:
195 mesh - The geometry which will store, in its solid index, the extruded shape.
196 shape_to_extrude - The shape (Be it closed or not) to extrude.
197 extrude_path - The path the shape will be extruded along. It is expected this path is
198 simplified (no 2 neighbor vertices are the same)
199 plane_normal - The 'up' dirrection used to relate the path with the given shape to extrude. Generally
200 this vector is (0,0,1)
201 is_path_closed - If the extrude path is closed (ie the last vertex in path should be connected to the
202 first vertex in path)
203 *-----------------------------------------------------------------------------------------------**/
204 template<class t_type>
205 static void Extrude(Buffer<Vector<3, uint04>>& indices
206 , Buffer<Vertex<3, t_type>>& vertices
207 , const Polyline<3, t_type>& shape_to_extrude
208 , const Polyline<3, t_type>& extrude_path
209 , const Vector<3, t_type>& plane_normal
210 , bool is_path_closed
211 , const Matrix<fltp08>& transform = Matrix<fltp08>(1.0))
212 {
213 if (extrude_path.vertexCount() <= 1)
214 return;
215 Buffer<Vector<3, t_type>> last(shape_to_extrude.vertexCount());//Stores the last vertices of the shape_to_extrude along the path
216 Buffer<Vector<3, t_type>> current(shape_to_extrude.vertexCount());//Stores most recently calculated vertices of the shape_to_extrude along the path
217 //Loop over each segment in the extrusion path, projecting the shape at each vertex and connecting the neighboring projections
219
220 for (uint04 i = 0; i < extrude_path.vertexCount(); i++)
221 {
222 current.clear();
223 Vertex<3, t_type> offset = extrude_path.vertex(i);//This is the vertex we will draw our extrusion about
224 bool greater_than_90_turn = false;
225 if (!isNaN(offset))
226 {
227 Ray<3, t_type> dir;//The direction vector of our proected shape
228 Ray<3, t_type> original_dir;//The original direction of the shape (Used to determine how curved something is)
229 if (is_path_closed && (i == 0 || i == extrude_path.segmentCount()))
230 {
231 //Since our path is closed, we will use the last segment as our -1 index segment in order to have
232 // a properly curved solid
233 original_dir = extrude_path.segment(extrude_path.segmentCount() - 1).ray().template normalized<t_type>();
234 Vector<3, t_type> dir_2 = extrude_path.segment(0).ray().template normalized<t_type>();
235 dir = (dir_2 + original_dir).template normalized<t_type>();
236 greater_than_90_turn = dot(dir_2, original_dir) < 0;
237 }
238 else if (last.size() == 0)
239 {
240 //We have no last reference, meaning our path should be totally based on this line segment
241 original_dir = extrude_path.segment(i).ray().template normalized<t_type>();
242 dir = original_dir;
243
244 }
245 else if (i == extrude_path.segmentCount())
246 {
247 //We have no future reference, meaning our path should be totally based on the last line segment
248 original_dir = extrude_path.segment(i - 1).ray().template normalized<t_type>();
249 dir = original_dir;
250 }
251 else
252 {
253 //Normal case: We are at some center section, our path will be influenced by 3 vertices
254 original_dir = extrude_path.segment(i - 1).ray().template normalized<t_type>();
255 Vector<3, t_type> dir_2 = extrude_path.segment(i).ray().template normalized<t_type>();
256 dir = (dir_2 + original_dir).template normalized<t_type>();
257 greater_than_90_turn = dot(dir_2, original_dir) < 0;
258
259 }
260 //If the segment has 0 length, then we will either be undefined or have a 0 magnitude.
261
262 if (dir.template magnitude<fltp08>() == 0.0 || isNaN(dir))
263 {
264 //lib_assert(false, "Encountered a zero length polyline. Please call simplify on the extrusion path prior to pass it to this function");
265 continue;
266 }
267 //This vector points to the right of the extrusion path segment
268 Ray<3, t_type> right = cross(dir, plane_normal).template normalized<t_type>();
269
270 if (isNaN(right))//Handle Vertical segments
271 {
272 if (isNaN(last_right))
273 {
274 right = Ray<3, fltp08>(plane_normal[Y], plane_normal[Z], plane_normal[X]);
275 }
276 else
277 {
278 right = last_right;
279 }
280 //TODO: right may be undefined if dir is along the plane normal, in which case we need to do
281 //a look ahead, and look behind to determine a suitable interpolated right vector.
282 }
283 last_right = right;
284
285 //This vector points 'up' from the extrusion path segment
286 //const Vertex<3, t_type> up = cross(dir, right).normalized<t_type>();
287 const Ray<3, fltp08> up = cross(dir, right).template normalized<fltp08>();
288
289 //Depending on how much our line curves, we need to project outward further. For example, a 90 degree turn requires
290 // our projected point to go out sqrt(orginal_distance^2+orginal_distance^2) in distance in addition to the original distance
291 const t_type p_off_original = cast<t_type>(1.0) - dot(dir, original_dir) * dot(dir, original_dir);
292
293 t_type extra_distance = sqrt(4 * p_off_original * p_off_original + 1.0);
294 if (greater_than_90_turn)
295 extra_distance = 2.0 / extra_distance;
296
297 //loop over our shape to extrude, marking the points
298 for (const auto& vertex : shape_to_extrude)
299 {
300 Ray<3, t_type> projection;//This is the vertex on the shape to extrude, projected out via line direction
301 projection += vertex[X] * right;
302 projection += vertex[Y] * up;
303 projection += vertex[Z] * dir;
304 projection = projection.template normalized<fltp08>();
305 projection = (transform * projection) * vertex.template magnitude<fltp08>();
306 current.add((extra_distance * projection) + offset);
307 }
308 //Ensure that we have added vertices to this path before
309 if (last.size() > 0)
310 {
311 for (uint04 n = 0; n < shape_to_extrude.vertexCount() - 1; n++)
312 {
313 //Create a quad in the shape that connects the corrosponding segments. Note that this
314 //function also handles degenerate quads which may occur given sharp corners in the extrusion path.
315 indices.add(vertices.size() + Vector<3, uint04>(0, 1, 2));
316 indices.add(vertices.size() + Vector<3, uint04>(0, 2, 3));
317 vertices.add(last[n]);
318 vertices.add(current[n]);
319 vertices.add(current[n + 1]);
320 vertices.add(last[n + 1]);
321 }
322 }
323 }
324 last = current;
325 }
326 }
327 };
328}
329
330
331
#define lib_assert(expression, message)
Asserts some logic in the code. Disabled in non debug mode by default. Can be re-enabled in release u...
Definition LibAssert.h:70
Stores an angle in an optimized format.
Definition StringStream.h:352
The equivelent of std::vector but with a bit more control. The basic array unit of the library.
Definition Buffer.hpp:64
void add(t_type &&object)
Definition Buffer.hpp:199
constexpr t_index_type size() const
Definition Buffer.hpp:1461
void clear()
Definition Buffer.hpp:572
Matrix< fltp08 > getTransform() const
Definition DesignObject.cpp:593
Definition Extruder.h:47
static void ExtrudeRealThickness(Geometry &linework, const Matrix< fltp08 > &transform=Matrix< fltp08 >(1.0))
Definition Extruder.h:65
static void ExtrudePolylineAlongGeo(Geometry &linework, const Polyline< 3, fltp08 > &geo_line, const Matrix< fltp08 > &transform=Matrix< fltp08 >(1.0))
Definition Extruder.h:117
static void Extrude(Buffer< Vector< 3, uint04 > > &indices, Buffer< Vertex< 3, t_type > > &vertices, const Polyline< 3, t_type > &shape_to_extrude, const Polyline< 3, t_type > &extrude_path, const Vector< 3, t_type > &plane_normal, bool is_path_closed, const Matrix< fltp08 > &transform=Matrix< fltp08 >(1.0))
Definition Extruder.h:205
Definition Geometry.h:64
void setSolidVertexOffsetValue(uint04 count)
Definition Geometry.h:1335
void updateSolidVertexColumns(bool invalidate_bounds=true, bool erase_kd_tree=true)
Definition Geometry.cpp:2219
void updateModifiedTime(Time time=Time::SystemTime())
Definition Geometry.cpp:2008
void updateVertexColumns(bool invalidate_bounds=true, bool erase_kd_tree=true)
Definition Geometry.cpp:2206
void setPrimitive(PrimitiveProperty property, uint04 index, t_type index_value)
Definition Geometry.h:335
uint04 addVertices(uint04 size)
Definition Geometry.h:686
uint04 solidVertexOffset() const
Definition Geometry.h:717
uint04 vertexCount() const
Definition Geometry.h:713
GeometryType getGeometryType() const
Definition Geometry.cpp:1054
void setPrimitiveRange(PrimitiveProperty mode, uint04 start, uint04 primitive_count)
Definition Geometry.cpp:753
uint04 primitiveCount(PrimitiveProperty property) const
Definition Geometry.h:669
void setSolidVertexCountValue(uint04 count)
Definition Geometry.h:1327
void updatePrimitiveColumns(bool remove_tree=true)
Definition Geometry.cpp:1999
void setVertex(VertexProperty property, uint04 index, const t_type &vector)
Definition Geometry.h:871
@ e_flat_per_vertex
Definition Geometry.h:134
@ e_circle
Definition Geometry.h:135
@ e_none
Definition Geometry.h:131
@ e_flat_single
Definition Geometry.h:133
@ e_circle_per_vertex
Definition Geometry.h:136
@ e_pixel
Definition Geometry.h:132
ThicknessMode thicknessMode() const
Definition Geometry.cpp:498
t_type getGeometryProperty(GeometryProperty property) const
Definition Geometry.h:174
@ e_plane_normal
Definition Geometry.h:107
@ e_has_closed_primitive
Definition Geometry.h:106
@ e_thickness
Definition Geometry.h:101
Buffer< Polyline< t_dims, t_type > > polylines(PrimitiveProperty primitive_property, VertexProperty vertex_property) const
Definition Geometry.h:1170
void setPrimitiveMode(PrimitiveProperty property, PrimitiveMode mode)
Definition Geometry.cpp:1981
PrimitiveMode mode(PrimitiveProperty property) const
Definition Geometry.h:309
uint04 indexOffset() const
Definition Geometry.h:628
void setSolidVertexReservedValue(uint04 count)
Definition Geometry.h:1331
uint04 primitiveIndexCount() const
Definition Geometry.h:665
uint04 solidVertexReservedCount() const
Definition Geometry.h:721
Definition Matrix.hpp:173
Matrix< t_type, t_cols, t_rows > invert() const
Definition Matrix.hpp:649
A polyline which stores vertex information for many points along a given path.
Definition CoordinateProjectionManager.h:44
uint04 vertexCount() const
Definition PolyLine.hpp:209
uint04 segmentCount() const
Definition PolyLine.hpp:226
LineSegment< t_dims, t_type, t_vertex > segment(uint04 index) const
Definition PolyLine.hpp:175
void add(const t_vertex &vertex)
Definition PolyLine.hpp:265
const t_vertex & vertex(uint04 index) const
Definition PolyLine.hpp:155
Definition Vertex.hpp:341
An element of a vector space. An element of the real coordinate space Rn Basis vector,...
Definition Vector.hpp:62
A vertex.
Definition Vertex.hpp:54
Definition ACIColor.h:37
t_type dot(const Vector< t_dims, t_type > &v1, const Vector< t_dims, t_type > &v2)
Definition VectorFunctions.hpp:1096
@ DEGREES
Definition Angle.h:66
std::enable_if<!ObjectInfo< t_type >::Float, fltp08 >::type cos(const Angle< t_type > &angle)
Definition AngleFunctions.h:154
constexpr Vector< 1, t_type > cross(const Vector< 1, t_type > &, const Vector< 1, t_type > &)
Definition VectorFunctions.hpp:954
uint32_t uint04
-Defines an alias representing a 4 byte, unsigned integer -Can represent exact integer values 0 throu...
Definition BaseValues.hpp:120
t_type sqrt(const t_type &value)
Definition VectorFunctions.hpp:1309
constexpr t_to cast(const Angle< t_from > &value)
Definition Angle.h:514
std::enable_if<!ObjectInfo< t_type >::Float, fltp08 >::type sin(const Angle< t_type > &angle)
Definition AngleFunctions.h:113
constexpr bool isNaN(const t_type &value)
Query if 'value' is valid or invalid.
Definition BaseFunctions.hpp:200
@ Y
Definition BaseValues.hpp:202
@ X
Definition BaseValues.hpp:200
@ Z
Definition BaseValues.hpp:204
double fltp08
Defines an alias representing an 8 byte floating-point number.
Definition BaseValues.hpp:181
Definition BaseValues.hpp:272