Branch data Line data Source code
1 : : #include "meshkit/ExtrudeMesh.hpp"
2 : : #include "meshkit/CopyMesh.hpp"
3 : : #include "meshkit/MKCore.hpp"
4 : : #include "meshkit/ModelEnt.hpp"
5 : : #include "meshkit/SizingFunction.hpp"
6 : : #include "meshkit/RegisterMeshOp.hpp"
7 : : #include "meshkit/LocalSet.hpp"
8 : :
9 : : #include "iMesh_extensions.h"
10 : :
11 : : #define CHKERR(err) do { \
12 : : if ((err) != iBase_SUCCESS) \
13 : : return iBase_ErrorType(err); \
14 : : } while(false)
15 : :
16 : : namespace MeshKit
17 : : {
18 : :
19 : : // static registration of this mesh scheme
20 : : moab::EntityType ExtrudeMesh_tps[] = { moab::MBVERTEX,
21 : : moab::MBEDGE,
22 : : moab::MBTRI,
23 : : moab::MBHEX,
24 : : moab::MBMAXTYPE};
25 : :
26 : 40 : const moab::EntityType* ExtrudeMesh::output_types()
27 : 40 : { return ExtrudeMesh_tps; }
28 : :
29 : 3 : ExtrudeMesh::ExtrudeMesh(MKCore *mkcore, const MEntVector &me_vec)
30 : : : MeshScheme(mkcore, me_vec),
31 [ + - ]: 3 : mesh(mkcore->imesh_instance()),
32 : : extrudeTag(mkcore, "__ExtrudeMeshTag"),
33 : : copyTag(mkcore, "__CopyMeshTag"),
34 : : transform(0),
35 : : copyFaces(false),
36 : : extrudeSets(mkcore),
37 : : copySets(mkcore),
38 [ + - ][ + - ]: 6 : expandSets(mkcore)
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ]
39 : 3 : {}
40 : :
41 : 9 : ExtrudeMesh::~ExtrudeMesh()
42 [ - + ]: 6 : {}
43 : :
44 : :
45 : 0 : bool ExtrudeMesh::add_modelent(ModelEnt *model_ent)
46 : : {
47 : 0 : return MeshOp::add_modelent(model_ent);
48 : : }
49 : :
50 : 3 : void ExtrudeMesh::setup_this()
51 : 3 : {}
52 : :
53 : 3 : void ExtrudeMesh::execute_this()
54 : : {
55 [ + - ]: 3 : std::vector<iMesh::EntityHandle> orig_ents(mentSelection.size());
56 : :
57 : 3 : int i = 0;
58 [ + - + - ]: 14 : for (MEntSelection::iterator mit = mentSelection.begin();
[ + + ]
59 : 7 : mit != mentSelection.end(); mit++) {
60 [ + - ]: 4 : ModelEnt *me = mit->first;
61 [ + - ][ + - ]: 4 : orig_ents[i++] = reinterpret_cast<iBase_EntityHandle> (me->mesh_handle());
62 : : }
63 : :
64 [ + - ][ + - ]: 6 : LocalSet set(this->mk_core());
65 : :
66 [ + - ][ + - ]: 3 : IBERRCHK(mesh->addEntArrToSet(&orig_ents[0], orig_ents.size(), set), *mesh);
[ + - ][ + - ]
67 [ + - ][ + - ]: 6 : do_extrude(set);
68 : 3 : }
69 : :
70 : 3 : int ExtrudeMesh::getStructure(iMesh_Instance instance,
71 : : iBase_EntitySetHandle set,
72 : : std::vector<iBase_EntityHandle> &ents,
73 : : std::vector<iBase_EntityHandle> &unique_adj,
74 : : std::vector<int> &indices,
75 : : std::vector<int> &offsets)
76 : : {
77 : : // 1) Get source entities, making sure verts are first
78 : : int num;
79 : : int err;
80 [ + - ]: 3 : iMesh_getNumOfTypeRec(instance, set, iBase_ALL_TYPES, true, &num, &err);
81 [ - + ]: 3 : CHKERR(err);
82 : :
83 [ + - ]: 3 : ents.resize(num);
84 [ + - ]: 3 : offsets.resize(num+1);
85 : :
86 [ + - ]: 3 : iBase_EntityHandle *block = &ents[0];
87 : 3 : int block_alloc = ents.size(), block_size, num_verts = 0;
88 [ + - ][ + + ]: 17 : for (int t = iMesh_POINT; t < iMesh_ALL_TOPOLOGIES && block_alloc; ++t) {
89 : : iMesh_getEntitiesRec(instance, set, iBase_ALL_TYPES, t, true,
90 [ + - ]: 14 : &block, &block_alloc, &block_size, &err);
91 [ - + ]: 14 : CHKERR(err);
92 : :
93 : 14 : block_alloc -= block_size;
94 : 14 : block += block_size;
95 [ + + ]: 14 : if (t == iMesh_POINT)
96 : 3 : num_verts = block_size;
97 : : }
98 : :
99 : : // 2) Get verts adjacent to all source entitites (verts are adj to themselves)
100 [ + - ][ + - ]: 3 : std::vector<iBase_EntityHandle> all_adj(ents.begin(), ents.begin()+num_verts);
101 : :
102 : : // first, fill the vertex-vertex adjacencies
103 [ - + ]: 3 : for (int i = 0; i < num_verts; ++i)
104 [ # # ]: 0 : offsets[i] = i;
105 : :
106 : 3 : iBase_EntityHandle *tmp_adj = NULL;
107 : 3 : int tmp_adj_alloc = 0, tmp_adj_size;
108 [ + - ]: 3 : int *tmp_off = &offsets[num_verts];
109 : 3 : int tmp_off_alloc = offsets.size() - num_verts, tmp_off_size;
110 [ + - ]: 3 : iMesh_getEntArrAdj(instance, &ents[num_verts], ents.size()-num_verts,
111 : : iBase_VERTEX, &tmp_adj, &tmp_adj_alloc, &tmp_adj_size,
112 [ + - ]: 3 : &tmp_off, &tmp_off_alloc, &tmp_off_size, &err);
113 [ - + ]: 3 : CHKERR(err);
114 : :
115 : : // shift all the offsets to account for vertices
116 [ + + ]: 10 : for(unsigned int i = num_verts; i < offsets.size(); ++i)
117 [ + - ]: 7 : offsets[i] += num_verts;
118 : :
119 [ + - ]: 3 : all_adj.reserve(all_adj.size() + tmp_adj_size);
120 [ + - ]: 3 : all_adj.insert(all_adj.end(), tmp_adj, tmp_adj+tmp_adj_size);
121 : 3 : free(tmp_adj);
122 : :
123 : : // 3) Get unique adjacent vertices and offsets
124 [ + - ]: 3 : unique_adj.resize(all_adj.size());
125 [ + - ]: 3 : indices.resize(all_adj.size());
126 [ + - ]: 3 : std::copy(all_adj.begin(), all_adj.end(), unique_adj.begin());
127 [ + - ]: 3 : std::sort(unique_adj.begin(), unique_adj.end());
128 : :
129 : : size_t unique_size;
130 [ + - ][ + - ]: 3 : unique_size = std::unique(unique_adj.begin(), unique_adj.end()) -
131 : 3 : unique_adj.begin();
132 [ + - ]: 3 : unique_adj.resize(unique_size);
133 : :
134 [ + + ]: 18 : for (size_t i = 0; i < all_adj.size(); ++i) {
135 [ + - ]: 15 : indices[i] = std::lower_bound(unique_adj.begin(), unique_adj.end(),
136 [ + - ][ + - ]: 15 : all_adj[i]) - unique_adj.begin();
[ + - ]
137 : : }
138 : :
139 : 3 : return 0;
140 : : }
141 : :
142 : 3 : void ExtrudeMesh::update_sets()
143 : : {
144 : 3 : copySets.update_tagged_sets();
145 : 3 : expandSets.update_tagged_sets();
146 : 3 : }
147 : :
148 : 3 : void ExtrudeMesh::do_extrude(iBase_EntitySetHandle src)
149 : : {
150 [ + - ][ + - ]: 3 : assert(transform && transform->steps() > 0);
[ - + ]
151 : :
152 [ + - ]: 3 : update_sets();
153 : :
154 [ + - ]: 3 : std::vector<iBase_EntityHandle> ents;
155 [ + - ][ + - ]: 6 : std::vector<iBase_EntityHandle> verts;
156 [ + - ][ + - ]: 6 : std::vector<int> indices;
157 [ + - ][ + - ]: 6 : std::vector<int> offsets;
158 : :
159 : : // IBERRCHK(iMesh_getStructure(mesh->instance(), src, ents, verts,
160 : : // indices, offsets), *mesh);
161 : : getStructure(mesh->instance(), src, ents, verts,
162 [ + - ][ + - ]: 3 : indices, offsets);
163 : :
164 [ - + ]: 6 : if (ents.size() == 0) return;
165 : :
166 [ + - ][ + - ]: 6 : std::vector<iBase_EntityHandle> curr;
167 [ + - ]: 6 : std::vector<iBase_EntityHandle> next;
168 [ + - ]: 6 : std::vector<int> normals;
169 : :
170 [ + - ][ + - ]: 6 : LocalTag local_extrude_tag(this->mk_core());
171 [ + - ][ + - ]: 6 : LocalTag local_copy_tag(this->mk_core());
172 : :
173 [ + - ]: 3 : curr.resize(verts.size());
174 [ + - ]: 3 : next.resize(verts.size());
175 [ + - ]: 3 : transform->transform(1, mesh, verts, next);
176 : :
177 : : // Get the offset between vertices between steps
178 [ + - ][ + - ]: 3 : Vector<3> xa, xb, dx;
[ + - ]
179 [ + - ][ + - ]: 3 : IBERRCHK(mesh->getVtxCoord(next[0], xa[0], xa[1], xa[2]), *mesh);
[ + - ][ + - ]
[ + - ][ + - ]
180 [ + - ][ + - ]: 3 : IBERRCHK(mesh->getVtxCoord(verts[0], xb[0], xb[1], xb[2]), *mesh);
[ + - ][ + - ]
[ + - ][ + - ]
181 [ + - ][ + - ]: 3 : dx = xa-xb;
182 : :
183 [ + - ]: 3 : get_normals(verts, indices, offsets, dx, normals);
184 : :
185 : : // Make the first set of volumes
186 [ + - ][ + - ]: 6 : connect_up_dots(&ents[0], ents.size(), local_extrude_tag, &normals[0],
187 [ + - ][ + - ]: 9 : &indices[0], &offsets[0], &verts[0], &next[0]);
[ + - ][ + - ]
[ + - ][ + - ]
188 : :
189 : : // Now do the rest
190 [ + - ][ + + ]: 21 : for (int i=2; i<=transform->steps(); i++) {
191 [ + - ]: 18 : std::swap(curr, next);
192 [ + - ]: 18 : transform->transform(i, mesh, verts, next);
193 [ + - ][ + - ]: 36 : connect_up_dots(&ents[0], ents.size(), local_extrude_tag, &normals[0],
194 [ + - ][ + - ]: 54 : &indices[0], &offsets[0], &curr[0], &next[0]);
[ + - ][ + - ]
[ + - ][ + - ]
195 : : }
196 : :
197 [ + - ][ + - ]: 3 : tag_copy_sets(extrudeSets, local_extrude_tag, extrudeTag);
[ + - ]
198 : :
199 [ + - ]: 3 : if (copyFaces) {
200 : : // set the local copy tags on vertices
201 : : // XXX: Should this really happen? Doing so adds more entities to copysets
202 : : // than explicitly passed into this function. This may be a domain-
203 : : // specific question.
204 [ + - ][ + - ]: 3 : IBERRCHK(mesh->setEHArrData(&verts[0], verts.size(), local_copy_tag,
[ + - ][ + - ]
205 [ + - ]: 3 : &next[0]), *mesh);
206 : :
207 [ + - ][ + - ]: 3 : connect_the_dots(mesh, local_copy_tag, ents, indices, offsets, next);
208 : :
209 [ + - ][ + - ]: 3 : link_expand_sets(expandSets, local_copy_tag);
210 : :
211 [ + - ][ + - ]: 3 : process_ce_sets(mesh, copySets.sets(), local_copy_tag);
[ + - ]
212 [ + - ][ + - ]: 3 : process_ce_sets(mesh, expandSets.sets(), local_copy_tag);
[ + - ]
213 : :
214 [ + - ][ + - ]: 3 : tag_copy_sets(copySets, local_copy_tag, copyTag);
[ + - ]
215 : 3 : }
216 : : }
217 : :
218 : : // calculate the normals for each face (1 = towards v, -1 = away from v)
219 : : // TODO: this can fail with non-convex faces
220 : 3 : void ExtrudeMesh::get_normals(const std::vector<iBase_EntityHandle> &verts,
221 : : const std::vector<int> &indices,
222 : : const std::vector<int> &offsets,
223 : : const Vector<3> &dv, std::vector<int> &normals)
224 : : {
225 : 3 : size_t size = offsets.size() - 1;
226 : 3 : normals.resize(size);
227 : :
228 [ + + ]: 7 : for(size_t i=0; i<size; i++) {
229 [ + - ][ + - ]: 4 : Vector<3> a, b;
230 : : iBase_EntityHandle curr_verts[3];
231 : :
232 [ + - ][ + - ]: 4 : if(offsets[i+1] - offsets[i] > 2) { // face
[ + - ]
233 [ + + ]: 16 : for(int j=0; j<3; j++)
234 [ + - ][ + - ]: 12 : curr_verts[j] = verts[indices[ offsets[i]+j ]];
[ + - ]
235 : :
236 [ + - ]: 4 : std::vector< Vector<3> > coords(3);
237 [ + - ][ + - ]: 4 : IBERRCHK(mesh->getVtxArrCoords(curr_verts, 3, iBase_INTERLEAVED,
238 [ + - ]: 4 : vec2ptr(coords)), *mesh);
239 : :
240 [ + - ][ + - ]: 4 : a = coords[1] - coords[0];
[ + - ][ + - ]
241 [ + - ][ + - ]: 4 : b = coords[2] - coords[1];
[ + - ][ + - ]
242 [ + - ][ + - ]: 4 : normals[i] = (vector_product(a, b) % dv) > 0 ? 1:-1;
[ + - ][ + - ]
243 : : }
244 [ # # ][ # # ]: 0 : else if(offsets[i+1] - offsets[i] == 2) { // line
[ # # ]
245 [ # # ]: 0 : normals[i] = 1; // TODO: figure out a way of distinguishing swapped
246 : : // lines
247 : : }
248 : : else // vertex
249 [ # # ]: 0 : normals[i] = 1;
250 : : }
251 : 3 : }
252 : :
253 : 21 : void ExtrudeMesh::connect_up_dots(
254 : : iBase_EntityHandle *src, int size, iBase_TagHandle local_tag,
255 : : int *pre_norms, int *pre_inds, int *pre_offs, iBase_EntityHandle *pre,
256 : : int *post_norms, int *post_inds, int *post_offs, iBase_EntityHandle *post)
257 : : {
258 [ + + ]: 43 : for(int i=0; i<size; i++) {
259 : 22 : int count = pre_offs[i+1] - pre_offs[i];
260 : :
261 : : // If the normal is facing in the wrong direction (away from the
262 : : // translation) we add the vertices in reverse order. Otherwise, we go
263 : : // in the usual order. If count is 2, then we are creating quads and so
264 : : // need to swap the order of the post set of verts.
265 : :
266 : 22 : int dx = pre_norms [i];
267 [ - + ]: 22 : int dy = post_norms[i] * (count == 2 ? -1:1);
268 [ + - ]: 22 : int x = (dx == 1) ? pre_offs [i] : pre_offs [i+1]-1;
269 [ + - ]: 22 : int y = (dy == 1) ? post_offs[i] : post_offs[i+1]-1;
270 : :
271 [ + - ][ + - ]: 22 : iBase_EntityHandle *nodes = new iBase_EntityHandle[count*2];
272 [ + + ]: 100 : for(int j=0; j<count; j++) {
273 : 78 : nodes[j] = pre [ pre_inds [x + dx*j] ];
274 : 78 : nodes[j+count] = post[ post_inds[y + dy*j] ];
275 : : }
276 : :
277 : : iBase_EntityHandle out;
278 : :
279 : : iMesh::Error err;
280 [ + + ]: 22 : if(count == 4) // quad
281 [ + - ]: 12 : err = mesh->createEnt(iMesh_HEXAHEDRON, nodes, 8, out);
282 [ + - ]: 10 : else if(count == 3) // tri
283 [ + - ]: 10 : err = mesh->createEnt(iMesh_PRISM, nodes, 6, out);
284 [ # # ]: 0 : else if(count == 2) // line
285 [ # # ]: 0 : err = mesh->createEnt(iMesh_QUADRILATERAL, nodes, 4, out);
286 [ # # ]: 0 : else if(count == 1) // vertex
287 [ # # ]: 0 : err = mesh->createEnt(iMesh_LINE_SEGMENT, nodes, 2, out);
288 : : else
289 [ # # ]: 0 : throw Error(iBase_FAILURE, "Couldn't extrude face; unusual shape.");
290 : :
291 [ + - ]: 22 : IBERRCHK(err, *mesh);
292 [ + - ]: 22 : delete[] nodes;
293 : :
294 [ + - ][ + - ]: 22 : IBERRCHK(mesh->setEHData(src[i], local_tag, out), *mesh);
295 : : }
296 : :
297 : 21 : process_ce_sets(mesh, extrudeSets.sets(), local_tag);
298 : 21 : }
299 [ + - ][ + - ]: 156 : } // namespace MeshKit
|