NDEVR
API Documentation
ModelTiler.h
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: ModelTiler
29Included in API: True
30Author(s): Tyler Parke
31 *-----------------------------------------------------------------------------------------**/
32#pragma once
33#include <NDEVR/Model.h>
34#if NDEVR_MODEL_TILE_CONTAINER
35#include <NDEVR/Geometry.h>
36#include <NDEVR/AngleDefinitions.h>
37#include <NDEVR/MatrixFunctions.h>
38#include <NDEVR/Scene.h>
39namespace NDEVR
40{
49 class ModelTiler
50 {
51 public:
55 enum TileMode
56 {
57 e_vertex_random
58 , e_vertex_even
59 };
63 struct TileOptions
64 {
65 Model parent;
66 Model model_to_tile;
67 Buffer<Model> old_model_pool;
68 Buffer<Model> new_models_added;
69 Matrix<fltp08> source_transform = Matrix<fltp08>(1.0);
70 Matrix<fltp08> model_to_tile_transform = Matrix<fltp08>(1.0);
71 LineSegment<3, fltp08> placement_segment;
72 bool use_heading = true;
73 bool use_inclination = true;
74 bool scale_to_fit = false;
75 bool per_vertex_placement = false;
76 };
87 static Model IndexChild(TileOptions& options)
88 {
89 Model child;
90 if (options.old_model_pool.size() > 0)
91 {
92 child = options.old_model_pool.last();
93 if(child.isDeleted())
94 options.new_models_added.add(child);
95 if (child.get<NDPO::library_id>() != options.model_to_tile.get<NDPO::library_id>())
96 child.copyFrom(options.model_to_tile, false);
97 options.model_to_tile = child;
98 options.old_model_pool.removeLast();
99 }
100 else
101 {
102 child = options.parent.createChild();
103 child.copyFrom(options.model_to_tile, false);
104 options.model_to_tile = child;
105 options.new_models_added.add(child);
106 }
107 return child;
108 }
118 static void TileAlongGeo(const Geometry& linework, TileOptions& options)
119 {
120 if (linework.getGeometryType() == GeometryType::e_linework)
121 {
122 //bool is_closed = linework.get<NDPG::has_closed_primitive>();
123 Buffer<Polyline<3, fltp08>> polylines = linework.polylines<3, fltp08>(PrimitiveProperty::Outline, VertexProperty::Position);
124 //Extrude Shape
125 for (uint04 i = 0; i < polylines.size(); i++)
126 {
127 polylines[i].simplify();
128 TileModelAlongLine(polylines[i], options);
129 }
130 }
131 /*
132
133
134 for (uint04 i = 0; i < broken_poly.vertexCount(); i++)
135 {
136 Model child = IndexChild(i, root_child, options);
137 Matrix<fltp08> mat = Matrix<fltp08>::OffsetMatrix(broken_poly.vertex(i));
138 uint04 segment_index = getMin(broken_poly.segmentCount() - 1, i);
139 if(options.use_heading)
140 mat = mat.rotate(AngleDefinitions::Heading<sint04>(broken_poly.segment(segment_index).ray()), Vector<3, fltp08>(0, 0, 1));
141 if(options.use_inclination)
142 mat = mat.rotate(-AngleDefinitions::Inclination<sint04>(broken_poly.segment(segment_index).ray()), Vector<3, fltp08>(0, 1, 0));
143 mat = parent_transform * mat * dest_transform;
144 child.setProperty<NDPO::transform>(mat);
145 }
146 */
147 else if (linework.getGeometryType() == GeometryType::e_points)
148 {
149 Buffer<Vertex<3, fltp08>> vertices = linework.vertices<Vertex<3, fltp08>>(VertexProperty::Position);
150 const Matrix<fltp08> dest_transform = options.model_to_tile_transform;
151 const Matrix<fltp08> parent_transform = options.parent.getCompleteTransform().invert();
152 for (uint04 i = 0; i < vertices.size(); i++)
153 {
154 if (IsInvalid(vertices[i]))
155 continue;
156 Model child = IndexChild(options);
157 Matrix<fltp08> mat = Matrix<fltp08>::OffsetMatrix(options.source_transform * vertices[i]);
158 mat = parent_transform * mat * dest_transform;
159 child.set<NDPO::transform>(mat);
160 }
161 }
162 }
174 static void TileModelAlongLine(const Polyline<3, fltp08>& extrude_path, TileOptions& options)
175 {
176 fltp08 distance = options.placement_segment.ray()[X];
177 Polyline<3, fltp08> broken_poly = options.source_transform * extrude_path;
178 if (!options.per_vertex_placement)
179 {
180 broken_poly = broken_poly.breakIntoSegmentsByDistance(distance);
181 if (options.scale_to_fit)
182 distance = 0.9999999 * broken_poly.length<fltp08>() / cast<fltp08>(cast<sint04>(broken_poly.length<fltp08>() / distance));
183 }
184 if (broken_poly.segmentCount() == 0)
185 return;
186 //Vertex<3, fltp08> model_offset = model_to_tile.getTransform() * seg.vertex(A);
187 //Angle heading_angle = AngleDefinitions::Heading<sint04>(seg.ray());
188 //Angle inclination_angle = AngleDefinitions::Inclination(seg.ray());
189 Matrix<fltp08> dest_transform = options.model_to_tile_transform;
190
191 const Matrix<fltp08> parent_transform = options.parent.getCompleteTransform().invert();
192 for (uint04 i = 0; i < broken_poly.vertexCount(); i++)
193 {
194 Model child = IndexChild(options);
195 Matrix<fltp08> mat = Matrix<fltp08>::OffsetMatrix(broken_poly.vertex(i));
196 uint04 segment_index = getMin(broken_poly.segmentCount() - 1, i);
197 if(options.use_heading)
198 mat = mat.rotate(AngleDefinitions::Heading<sint04>(broken_poly.segment(segment_index).ray()), Vector<3, fltp08>(0, 0, 1));
199 if(options.use_inclination)
200 mat = mat.rotate(-AngleDefinitions::Inclination<sint04>(broken_poly.segment(segment_index).ray()), Vector<3, fltp08>(0, 1, 0));
201 if (options.scale_to_fit)
202 {
203 auto bounds = dest_transform * child.getBounds();
204 mat = mat.scale({ distance / bounds.span(X), 1.0, 1.0 });
205 }
206 mat = parent_transform * mat * dest_transform;
207 child.update<NDPO::transform>(mat);
208 }
209 }
210
211 };
212}
213#endif
The primary namespace for the NDEVR SDK.
constexpr t_type getMin(const t_type &left, const t_type &right)
Finds the minimum of the given arguments based on the < operator Author: Tyler Parke Date: 2017-11-05...
uint32_t uint04
-Defines an alias representing a 4 byte, unsigned integer -Can represent exact integer values 0 throu...
double fltp08
Defines an alias representing an 8 byte floating-point number.
constexpr bool IsInvalid(const t_type &value)
Query if 'value' is valid or invalid.