3#include <thrust/sort.h>
7 template<typename TDataType>
8 SimplexSet<TDataType>::SimplexSet()
9 : PointSet<TDataType>()
13 template<typename TDataType>
14 SimplexSet<TDataType>::~SimplexSet()
17 mTriangleIndex.clear();
18 mTetrahedronIndex.clear();
21 template<typename TDataType>
22 void SimplexSet<TDataType>::copyFrom(SimplexSet<TDataType>& simplex)
24 PointSet<TDataType>::copyFrom(simplex);
26 mEdgeIndex.assign(simplex.mEdgeIndex);
27 mTriangleIndex.assign(simplex.mTriangleIndex);
28 mTetrahedronIndex.assign(simplex.mTetrahedronIndex);
31 template<typename TDataType>
32 bool SimplexSet<TDataType>::isEmpty()
35 empty |= mEdgeIndex.size() == 0;
36 empty |= mTriangleIndex.size() == 0;
37 empty |= mTetrahedronIndex.size() == 0;
42 template<typename TDataType>
43 void SimplexSet<TDataType>::updateTopology()
48 template<typename Edge>
49 __global__ void Simplex_SetEdgeIndexIds(
53 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
54 if (tId >= edges.size()) return;
56 Edge edge = edges[tId];
58 ids[2 * tId] = edge[0];
59 ids[2 * tId + 1] = edge[1];
62 __global__ void Simplex_CountVertexNumber(
66 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
67 if (tId >= vIds.size()) return;
69 if (tId == 0 || vIds[tId] != vIds[tId - 1])
75 template<typename Coord>
76 __global__ void Simplex_SetupEdgeVertices(
77 DArray<Coord> vertices,
78 DArray<Coord> originVertices,
79 DArray<uint> vertexIdMapper,
83 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
84 if (tId >= radix.size()) return;
86 int shift = radix[tId];
87 if (tId == 0 || radix[tId] != radix[tId - 1]) {
89 vertices[shift] = originVertices[vId];
90 vertexIdMapper[vId] = shift;
94 template<typename Edge>
95 __global__ void Simplex_UpdateEdgeIndex(
96 DArray<Edge> newEdgeIndices,
97 DArray<Edge> oldEdgeIndices,
98 DArray<uint> vertexIdMapper)
100 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
101 if (tId >= oldEdgeIndices.size()) return;
103 Edge edge = oldEdgeIndices[tId];
105 uint v0 = vertexIdMapper[edge[0]];
106 uint v1 = vertexIdMapper[edge[1]];
108 newEdgeIndices[tId] = Edge(v0, v1);
111 template<typename TDataType>
112 void SimplexSet<TDataType>::extractSimplex1D(EdgeSet<TDataType>& es)
116 uint eNum = mEdgeIndex.size();
118 DArray<uint> vIds(eNum * 2);
121 Simplex_SetEdgeIndexIds,
125 thrust::sort(thrust::device, vIds.begin(), vIds.begin() + vIds.size());
127 DArray<int> radix(eNum * 2);
129 cuExecute(vIds.size(),
130 Simplex_CountVertexNumber,
134 int vNum = thrust::reduce(thrust::device, radix.begin(), radix.begin() + radix.size());
135 thrust::exclusive_scan(thrust::device, radix.begin(), radix.begin() + radix.size(), radix.begin());
137 DArray<Coord> vertices(vNum);
138 DArray<Edge> edgeIndices(mEdgeIndex.size());
139 DArray<uint> vertexIdMapper(PointSet<TDataType>::mCoords.size());
141 cuExecute(radix.size(),
142 Simplex_SetupEdgeVertices,
144 PointSet<TDataType>::mCoords,
150 Simplex_UpdateEdgeIndex,
155 es.setPoints(vertices);
156 es.setEdges(edgeIndices);
162 vertexIdMapper.clear();
166 template<typename Triangle>
167 __global__ void Simplex_SetTriangleIndexIds(
169 DArray<Triangle> triangles)
171 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
172 if (tId >= triangles.size()) return;
174 Triangle tri = triangles[tId];
176 ids[3 * tId] = tri[0];
177 ids[3 * tId + 1] = tri[1];
178 ids[3 * tId + 2] = tri[2];
181 template<typename Triangle>
182 __global__ void Simplex_UpdateTriangleIndex(
183 DArray<Triangle> newTriangleIndices,
184 DArray<Triangle> oldTriangleIndices,
185 DArray<uint> vertexIdMapper)
187 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
188 if (tId >= oldTriangleIndices.size()) return;
190 Triangle tri = oldTriangleIndices[tId];
192 uint v0 = vertexIdMapper[tri[0]];
193 uint v1 = vertexIdMapper[tri[1]];
194 uint v2 = vertexIdMapper[tri[2]];
196 newTriangleIndices[tId] = Triangle(v0, v1, v2);
199 template<typename TDataType>
200 void SimplexSet<TDataType>::extractSimplex2D(TriangleSet<TDataType>& ts)
204 uint tNum = mTriangleIndex.size();
206 DArray<uint> vIds(tNum * 3);
209 Simplex_SetTriangleIndexIds,
213 thrust::sort(thrust::device, vIds.begin(), vIds.begin() + vIds.size());
215 DArray<int> radix(tNum * 3);
217 cuExecute(vIds.size(),
218 Simplex_CountVertexNumber,
222 int vNum = thrust::reduce(thrust::device, radix.begin(), radix.begin() + radix.size());
223 thrust::exclusive_scan(thrust::device, radix.begin(), radix.begin() + radix.size(), radix.begin());
225 DArray<Coord> vertices(vNum);
226 DArray<Triangle> triangleIndex(mTriangleIndex.size());
227 DArray<uint> vertexIdMapper(PointSet<TDataType>::mCoords.size());
229 cuExecute(radix.size(),
230 Simplex_SetupEdgeVertices,
232 PointSet<TDataType>::mCoords,
238 Simplex_UpdateTriangleIndex,
243 ts.setPoints(vertices);
244 ts.setTriangles(triangleIndex);
250 vertexIdMapper.clear();
251 triangleIndex.clear();
254 template<typename Tetrahedron>
255 __global__ void Simplex_SetTetrahedronIndexIds(
257 DArray<Tetrahedron> tetrahedrons)
259 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
260 if (tId >= tetrahedrons.size()) return;
262 Tetrahedron tet = tetrahedrons[tId];
264 ids[4 * tId] = tet[0];
265 ids[4 * tId + 1] = tet[1];
266 ids[4 * tId + 2] = tet[2];
267 ids[4 * tId + 3] = tet[3];
270 template<typename Tetrahedron>
271 __global__ void Simplex_UpdateTetrahedronIndex(
272 DArray<Tetrahedron> newTetIndices,
273 DArray<Tetrahedron> oldTetIndices,
274 DArray<uint> vertexIdMapper)
276 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
277 if (tId >= oldTetIndices.size()) return;
279 Tetrahedron tet = oldTetIndices[tId];
281 uint v0 = vertexIdMapper[tet[0]];
282 uint v1 = vertexIdMapper[tet[1]];
283 uint v2 = vertexIdMapper[tet[2]];
284 uint v3 = vertexIdMapper[tet[3]];
286 newTetIndices[tId] = Tetrahedron(v0, v1, v2, v3);
289 template<typename TDataType>
290 void SimplexSet<TDataType>::extractSimplex3D(TetrahedronSet<TDataType>& ts)
294 uint tNum = mTetrahedronIndex.size();
296 DArray<uint> vIds(tNum * 4);
299 Simplex_SetTetrahedronIndexIds,
303 thrust::sort(thrust::device, vIds.begin(), vIds.begin() + vIds.size());
305 DArray<int> radix(tNum * 4);
307 cuExecute(vIds.size(),
308 Simplex_CountVertexNumber,
312 int vNum = thrust::reduce(thrust::device, radix.begin(), radix.begin() + radix.size());
313 thrust::exclusive_scan(thrust::device, radix.begin(), radix.begin() + radix.size(), radix.begin());
315 DArray<Coord> vertices(vNum);
316 DArray<Tetrahedron> tetrahedronIndex(mTetrahedronIndex.size());
317 DArray<uint> vertexIdMapper(PointSet<TDataType>::mCoords.size());
319 cuExecute(radix.size(),
320 Simplex_SetupEdgeVertices,
322 PointSet<TDataType>::mCoords,
328 Simplex_UpdateTetrahedronIndex,
333 ts.setPoints(vertices);
334 ts.setTetrahedrons(tetrahedronIndex);
340 vertexIdMapper.clear();
341 tetrahedronIndex.clear();
344 template<typename TDataType>
345 void SimplexSet<TDataType>::extractPointSet(PointSet<TDataType>& ps)
349 ps.setPoints(PointSet<TDataType>::mCoords);
353 template<typename Edge, typename Triangle, typename Tetrahedron>
354 __global__ void Simplex_SetupEdgeKeyAndValue(
357 DArray<Edge> edgeIndices,
358 DArray<Triangle> triIndices,
359 DArray<Tetrahedron> tetIndices)
361 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
363 uint total_num = edgeIndices.size() + triIndices.size() + tetIndices.size();
365 if (tId >= total_num) return;
367 if (tId < edgeIndices.size())
369 Edge eIdx = edgeIndices[tId];
379 else if (tId < edgeIndices.size() + triIndices.size())
381 uint i = tId - edgeIndices.size();
383 Triangle tIdx = triIndices[i];
389 uint offset = edgeIndices.size() + 3 * i;
391 keys[offset] = EKey(v0, v1);
392 values[offset] = Edge(v0, v1);
394 keys[offset + 1] = EKey(v1, v2);
395 values[offset + 1] = Edge(v1, v2);
397 keys[offset + 2] = EKey(v2, v0);
398 values[offset + 2] = Edge(v2, v0);
402 uint i = tId - edgeIndices.size() - triIndices.size();
404 Tetrahedron tIdx = tetIndices[i];
411 uint offset = edgeIndices.size() + 3 * triIndices.size() + 6 * i;
413 keys[offset] = EKey(v0, v1);
414 values[offset] = Edge(v0, v1);
416 keys[offset + 1] = EKey(v1, v2);
417 values[offset + 1] = Edge(v1, v2);
419 keys[offset + 2] = EKey(v2, v0);
420 values[offset + 2] = Edge(v2, v0);
422 keys[offset + 3] = EKey(v0, v3);
423 values[offset + 3] = Edge(v0, v3);
425 keys[offset + 4] = EKey(v1, v3);
426 values[offset + 4] = Edge(v1, v3);
428 keys[offset + 5] = EKey(v2, v3);
429 values[offset + 5] = Edge(v2, v3);
433 __global__ void Simplex_CountEdgeNumber(
437 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
438 if (tId >= vIds.size()) return;
440 if (tId == 0 || vIds[tId] != vIds[tId - 1])
446 template<typename Edge>
447 __global__ void Simplex_SetupEdges(
448 DArray<Edge> newEdges,
449 DArray<Edge> oldEdges,
453 int tId = threadIdx.x + (blockIdx.x * blockDim.x);
454 if (tId >= radix.size()) return;
456 int shift = radix[tId];
457 if (tId == 0 || radix[tId] != radix[tId - 1]) {
458 newEdges[shift] = oldEdges[tId];
462 template<typename TDataType>
463 void SimplexSet<TDataType>::extractEdgeSet(EdgeSet<TDataType>& es)
467 uint priNum = mEdgeIndex.size() + mTriangleIndex.size() + mTetrahedronIndex.size();
468 uint eNum = mEdgeIndex.size() + 3 * mTriangleIndex.size() + 6 * mTetrahedronIndex.size();
470 DArray<EKey> keys(eNum);
471 DArray<Edge> edges(eNum);
474 Simplex_SetupEdgeKeyAndValue,
481 thrust::sort_by_key(thrust::device, keys.begin(), keys.begin() + keys.size(), edges.begin());
483 DArray<int> radix(eNum);
486 Simplex_CountEdgeNumber,
490 int N = thrust::reduce(thrust::device, radix.begin(), radix.begin() + radix.size());
491 thrust::exclusive_scan(thrust::device, radix.begin(), radix.begin() + radix.size(), radix.begin());
493 DArray<Edge> distinctEdges(N);
502 es.setPoints(PointSet<TDataType>::mCoords);
503 es.setEdges(distinctEdges);
509 distinctEdges.clear();
512 template<typename TDataType>
513 void SimplexSet<TDataType>::extractTriangleSet(TriangleSet<TDataType>& ts)
518 DEFINE_CLASS(SimplexSet);