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 \brief 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 Given a linework geometry, extrudes a flat line alog the path in order to create a "ribbon" with a
52 flat apperence and a thickness defined by geometryproperty Geometry::e_thickness
53
54 Author: Tyler Parke
55
56 Date: 2019-01-14
57
58 Parameters:
59 linework - The linework whos geometrytype must be of type linework, and must have some valid > 0.0 real
60 thickness. Upon completion of this function, the Solid index channel of this object will be filled with
61 vertices and indices relating to the object's real thickness.
62 **/
63 static void ExtrudeRealThickness(Geometry& linework, const Matrix<fltp08>& transform = Matrix<fltp08>(1.0))
64 {
65 lib_assert(linework.getGeometryType() == GeometryType::e_linework, "Can only extrude thickness along geometry of type linework");
67 lib_assert(!IsInvalid(thickness) && thickness > 0.0, "Thickness must be > 0.0");
68 Polyline<3, fltp08> geo_line;//Stores the line we want to extrude along the path
69 switch (linework.thicknessMode())
70 {
73 linework.setSolidVertexCountValue(0);
76 return;
79 geo_line.add({ -thickness / 2.0, 0, 0 });
80 geo_line.add({ thickness / 2.0, 0, 0 });
81 break;
84 {
85 uint04 width_segments = 128;
86 for (uint04 x = 0; x <= width_segments; x++)
87 {
88 fltp08 u = cast<fltp08>(x) / cast<fltp08>(width_segments);
89 const Angle angle = u * Angle<fltp08>(DEGREES, 360.0f);
90 Vertex<3, fltp08> position(-thickness * cos(angle), thickness * sin(angle), 0.0);
91 geo_line.add(position);
92
93 }
94 } break;
95 }
96
97
98 ExtrudePolylineAlongGeo(linework, geo_line, transform);
99 }
100
101 /**--------------------------------------------------------------------------------------------------
102 Given a linework geometry, extrudes the given polyline along that linework
103
104 Author: Tyler Parke
105
106 Date: 2019-01-14
107
108 Parameters:
109 linework - The linework whos geometrytype must be of type linework and will store the extrusion.
110 Upon completion of this function, the Solid index channel of this object will be filled with
111 vertices and indices of the polyline extruded across the linework
112 **/
113 static void ExtrudePolylineAlongGeo(Geometry& linework, const Polyline<3, fltp08>& geo_line, const Matrix<fltp08>& transform = Matrix<fltp08>(1.0))
114 {
115 lib_assert(linework.getGeometryType() == GeometryType::e_linework, "Can only extrude thickness along geometry of type linework");
116
118
119
120
121 bool is_closed = linework.getGeometryProperty<bool>(Geometry::e_has_closed_primitive);
123
125 Buffer<Vertex<3, fltp08>> vertices;
126 Matrix<fltp08> poly_transform = (transform * linework.getTransform()).invert();
127 //Extrude Shape
128 for (uint04 i = 0; i < polylines.size(); i++)
129 {
130 polylines[i].simplify();
131 Vector<3, fltp08> poly_normal = plane_normal;
132 if (IsInvalid(poly_normal))
133 {
134 Vector<3, fltp08> bounds = polylines[i].bounds().span();
135 if (bounds[X] * bounds[X] + bounds[Y] * bounds[Y] > bounds[Z] * bounds[Z])
136 poly_normal = { 0.0, 0.0, 1.0 };
137 else if (bounds[X] * bounds[X] > bounds[Y] * bounds[Y])
138 poly_normal = { 0.0, 1.0, 0.0 };
139 else
140 poly_normal = { 1.0, 0.0, 0.0 };
141 }
142 Extrude(indices, vertices, geo_line, polylines[i], poly_normal, is_closed, poly_transform);
143 }
144
145 //Add shape to Geometry
146 uint04 solid_vertex_offset = linework.solidVertexOffset();
147 if (IsInvalid(solid_vertex_offset))
148 {
149 solid_vertex_offset = linework.vertexCount();
150 linework.setSolidVertexOffsetValue(solid_vertex_offset);
151 }
152 uint04 solid_vertex_size = linework.solidVertexReservedCount();
153 if (solid_vertex_size < vertices.size())
154 {
155 linework.addVertices(solid_vertex_offset, vertices.size() - solid_vertex_size);
156 linework.setSolidVertexReservedValue(vertices.size());
157 }
158 linework.setSolidVertexCountValue(vertices.size());
159 for (uint04 i = 0; i < vertices.size(); i++)
160 {
161 linework.setVertex(VertexProperty::Position, solid_vertex_offset + i, vertices[i]);
162 }
165 linework.setPrimitiveRange(PrimitiveProperty::Solid, index_offset, indices.size());
166 for (uint04 i = 0; i < indices.size(); i++)
167 {
168 linework.setPrimitive(PrimitiveProperty::Solid, i, solid_vertex_offset + indices[i]);
169 }
170 linework.updateVertexColumns();
171 linework.updateSolidVertexColumns();
172 linework.updatePrimitiveColumns();
173 linework.updateModifiedTime();
174 }
175
176 /**--------------------------------------------------------------------------------------------------
177
178 Given a linework geometry, extrudes a shape along the provided path to create a triangulated solid.
179 Note that the winding of the final shape will be the same as the given shape to extrude. Reversing
180 the vertices of this shape will reverse the winding order of the final solid. Note that passing a path
181 which fully lies in plane whos normal is perpendicular to the given plane normal will result in undefined
182 behavior
183
184 Author: Tyler Parke
185
186 Date: 2019-01-14
187
188 Parameters:
189 mesh - The geometry which will store, in its solid index, the extruded shape.
190 shape_to_extrude - The shape (Be it closed or not) to extrude.
191 extrude_path - The path the shape will be extruded along. It is expected this path is
192 simplified (no 2 neighbor vertices are the same)
193 plane_normal - The 'up' dirrection used to relate the path with the given shape to extrude. Generally
194 this vector is (0,0,1)
195 is_path_closed - If the extrude path is closed (ie the last vertex in path should be connected to the
196 first vertex in path)
197 **/
198 template<class t_type>
199 static void Extrude(Buffer<Vector<3, uint04>>& indices
200 , Buffer<Vertex<3, t_type>>& vertices
201 , const Polyline<3, t_type>& shape_to_extrude
202 , const Polyline<3, t_type>& extrude_path
203 , const Vector<3, t_type>& plane_normal
204 , bool is_path_closed
205 , const Matrix<fltp08>& transform = Matrix<fltp08>(1.0))
206 {
207 if (extrude_path.vertexCount() <= 1)
208 return;
209 Buffer<Vector<3, t_type>> last(shape_to_extrude.vertexCount());//Stores the last vertices of the shape_to_extrude along the path
210 Buffer<Vector<3, t_type>> current(shape_to_extrude.vertexCount());//Stores most recently calculated vertices of the shape_to_extrude along the path
211 //Loop over each segment in the extrusion path, projecting the shape at each vertex and connecting the neighboring projections
213
214 for (uint04 i = 0; i < extrude_path.vertexCount(); i++)
215 {
216 current.clear();
217 Vertex<3, t_type> offset = extrude_path.vertex(i);//This is the vertex we will draw our extrusion about
218 bool greater_than_90_turn = false;
219 if (!IsInvalid(offset))
220 {
221 Ray<3, t_type> dir;//The direction vector of our proected shape
222 Ray<3, t_type> original_dir;//The original direction of the shape (Used to determine how curved something is)
223 if (is_path_closed && (i == 0 || i == extrude_path.segmentCount()))
224 {
225 //Since our path is closed, we will use the last segment as our -1 index segment in order to have
226 // a properly curved solid
227 original_dir = extrude_path.segment(extrude_path.segmentCount() - 1).ray().template normalized<t_type>();
228 Vector<3, t_type> dir_2 = extrude_path.segment(0).ray().template normalized<t_type>();
229 dir = (dir_2 + original_dir).template normalized<t_type>();
230 greater_than_90_turn = dot(dir_2, original_dir) < 0;
231 }
232 else if (last.size() == 0)
233 {
234 //We have no last reference, meaning our path should be totally based on this line segment
235 original_dir = extrude_path.segment(i).ray().template normalized<t_type>();
236 dir = original_dir;
237
238 }
239 else if (i == extrude_path.segmentCount())
240 {
241 //We have no future reference, meaning our path should be totally based on the last line segment
242 original_dir = extrude_path.segment(i - 1).ray().template normalized<t_type>();
243 dir = original_dir;
244 }
245 else
246 {
247 //Normal case: We are at some center section, our path will be influenced by 3 vertices
248 original_dir = extrude_path.segment(i - 1).ray().template normalized<t_type>();
249 Vector<3, t_type> dir_2 = extrude_path.segment(i).ray().template normalized<t_type>();
250 dir = (dir_2 + original_dir).template normalized<t_type>();
251 greater_than_90_turn = dot(dir_2, original_dir) < 0;
252
253 }
254 //If the segment has 0 length, then we will either be undefined or have a 0 magnitude.
255
256 if (dir.template magnitude<fltp08>() == 0.0 || IsInvalid(dir))
257 {
258 //lib_assert(false, "Encountered a zero length polyline. Please call simplify on the extrusion path prior to pass it to this function");
259 continue;
260 }
261 //This vector points to the right of the extrusion path segment
262 Ray<3, t_type> right = cross(dir, plane_normal).template normalized<t_type>();
263
264 if (IsInvalid(right))//Handle Vertical segments
265 {
266 if (IsInvalid(last_right))
267 {
268 right = Ray<3, fltp08>(plane_normal[Y], plane_normal[Z], plane_normal[X]);
269 }
270 else
271 {
272 right = last_right;
273 }
274 //TODO: right may be undefined if dir is along the plane normal, in which case we need to do
275 //a look ahead, and look behind to determine a suitable interpolated right vector.
276 }
277 last_right = right;
278
279 //This vector points 'up' from the extrusion path segment
280 //const Vertex<3, t_type> up = cross(dir, right).normalized<t_type>();
281 const Ray<3, fltp08> up = cross(dir, right).template normalized<fltp08>();
282
283 //Depending on how much our line curves, we need to project outward further. For example, a 90 degree turn requires
284 // our projected point to go out sqrt(orginal_distance^2+orginal_distance^2) in distance in addition to the original distance
285 const t_type p_off_original = cast<t_type>(1.0) - dot(dir, original_dir) * dot(dir, original_dir);
286
287 t_type extra_distance = sqrt(4 * p_off_original * p_off_original + 1.0);
288 if (greater_than_90_turn)
289 extra_distance = 2.0 / extra_distance;
290
291 //loop over our shape to extrude, marking the points
292 for (const auto& vertex : shape_to_extrude)
293 {
294 Ray<3, t_type> projection;//This is the vertex on the shape to extrude, projected out via line direction
295 projection += vertex[X] * right;
296 projection += vertex[Y] * up;
297 projection += vertex[Z] * dir;
298 projection = projection.template normalized<fltp08>();
299 projection = (transform * projection) * vertex.template magnitude<fltp08>();
300 current.add((extra_distance * projection) + offset);
301 }
302 //Ensure that we have added vertices to this path before
303 if (last.size() > 0)
304 {
305 for (uint04 n = 0; n < shape_to_extrude.vertexCount() - 1; n++)
306 {
307 //Create a quad in the shape that connects the corrosponding segments. Note that this
308 //function also handles degenerate quads which may occur given sharp corners in the extrusion path.
309 indices.add(vertices.size() + Vector<3, uint04>(0, 1, 2));
310 indices.add(vertices.size() + Vector<3, uint04>(0, 2, 3));
311 vertices.add(last[n]);
312 vertices.add(current[n]);
313 vertices.add(current[n + 1]);
314 vertices.add(last[n + 1]);
315 }
316 }
317 }
318 last = current;
319 }
320 }
321 };
322}
323
324
325
#define lib_assert(expression, message)
Definition LibAssert.h:61
The primary angle storage class for this API. Stores an angle in an optimized format.
Definition StringStream.h:540
The equivelent of std::vector but with a bit more control. The basic array unit of the library.
Definition Buffer.hpp:56
void add(t_type &&object)
Adds object to the end of the buffer.
Definition Buffer.hpp:186
constexpr t_index_type size() const
Definition Buffer.hpp:823
void clear()
Definition Buffer.hpp:422
Matrix< fltp08 > getTransform() const
Class containing static functions that define logic to extrude shapes along some given polyline.
Definition Extruder.h:47
static void ExtrudeRealThickness(Geometry &linework, const Matrix< fltp08 > &transform=Matrix< fltp08 >(1.0))
Definition Extruder.h:63
static void ExtrudePolylineAlongGeo(Geometry &linework, const Polyline< 3, fltp08 > &geo_line, const Matrix< fltp08 > &transform=Matrix< fltp08 >(1.0))
Definition Extruder.h:113
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:199
A core class within the model heirarchy containing vertex-based data (Usually 3D data) within a set c...
Definition Geometry.h:64
void setSolidVertexOffsetValue(uint04 count)
Definition Geometry.h:1335
void updateSolidVertexColumns(bool invalidate_bounds=true, bool erase_kd_tree=true)
void updateModifiedTime(Time time=Time::SystemTime())
void updateVertexColumns(bool invalidate_bounds=true, bool erase_kd_tree=true)
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
void setPrimitiveRange(PrimitiveProperty mode, uint04 start, uint04 primitive_count)
uint04 primitiveCount(PrimitiveProperty property) const
Definition Geometry.h:669
void setSolidVertexCountValue(uint04 count)
Definition Geometry.h:1327
void updatePrimitiveColumns(bool remove_tree=true)
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
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
ThicknessMode thicknessMode() const
void setPrimitiveMode(PrimitiveProperty property, PrimitiveMode mode)
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:176
Matrix< t_type, t_cols, t_rows > invert() const
Definition Matrix.hpp:652
A polyline which stores vertex information for many points along a given path.
Definition CoordinateProjectionManager.h:44
uint04 vertexCount() const
Definition PolyLine.hpp:191
uint04 segmentCount() const
Definition PolyLine.hpp:206
LineSegment< t_dims, t_type, t_vertex > segment(uint04 index) const
Definition PolyLine.hpp:161
void add(const t_vertex &vertex)
Definition PolyLine.hpp:241
const t_vertex & vertex(uint04 index) const
Definition PolyLine.hpp:143
Definition Vertex.hpp:317
A fixed-size array with better performance compared to dynamic containers.
Definition Vector.hpp:60
A vertex or point. A specific type of Vector used primarily for spacial location information.
Definition Vertex.hpp:48
Definition ACIColor.h:37
constexpr bool IsInvalid(const t_type &value)
Query if 'value' is valid or invalid. Invalid values should return invalid if used for calculations o...
Definition BaseFunctions.hpp:170
t_type dot(const Vector< t_dims, t_type > &v1, const Vector< t_dims, t_type > &v2)
Definition VectorFunctions.hpp:1030
@ DEGREES
Definition Angle.h:58
std::enable_if<!ObjectInfo< t_type >::Float, fltp08 >::type cos(const Angle< t_type > &angle)
Performs optimized cosine operation on the given angle using pre-computed lookup table for optimal sp...
Definition AngleFunctions.h:124
constexpr Vector< 1, t_type > cross(const Vector< 1, t_type > &, const Vector< 1, t_type > &)
Definition VectorFunctions.hpp:898
uint32_t uint04
-Defines an alias representing a 4 byte, unsigned integer -Can represent exact integer values 0 throu...
Definition BaseValues.hpp:96
t_type sqrt(const t_type &value)
Definition VectorFunctions.hpp:1225
constexpr t_to cast(const Angle< t_from > &value)
Definition Angle.h:375
std::enable_if<!ObjectInfo< t_type >::Float, fltp08 >::type sin(const Angle< t_type > &angle)
Performs optimized sine operation on the given angle using pre-computed lookup table for optimal spee...
Definition AngleFunctions.h:79
@ Y
Definition BaseValues.hpp:169
@ X
Definition BaseValues.hpp:167
@ Z
Definition BaseValues.hpp:171
double fltp08
Defines an alias representing an 8 byte floating-point number.
Definition BaseValues.hpp:149
Defines for a given type (such as sint04, fltp08, UUID, etc) a maximum, minimum, and reserved 'invali...
Definition BaseValues.hpp:233