FiberVISH 0.2
Fish - The Fiber Bundle API for the Vish Visualization Shell
Isosurface.hpp
1#ifndef __BASEOP_ISOSURFACE_HPP
2#define __BASEOP_ISOSURFACE_HPP
3
4#include "gridopDllApi.h"
5
6#include <eagle/PhysicalSpace.hpp>
7
8#include <vector/MultiIndex.hpp>
9
10#include <field/Cell.hpp>
11
12#include <grid/Grid.hpp>
13#include <grid/CartesianChart.hpp>
14#include <grid/RegularTopology.hpp>
15
16#include <bundle/Slice.hpp>
17
18namespace Fiber
19{
20
21template <class ArrayType>
23
24template <Dims_t Dims, class ValueType>
26{
28 const ValueType Isolevel;
29
32 , Isolevel(Threshold)
33 {}
34
35 bool isBelowThreshold(const MultiIndex<Dims>&I) const
36 {
37 return Field[ I ] < Isolevel;
38 }
39
40 template <class ResultType>
42 const ResultType&precision) const
43 {
44 const ValueType &P1 = Field[ FirstVertex ],
45 &P2 = Field[ SecondVertex ];
46
47/* if ( fabs(Isolevel - P1) < precision)
48 return 0.0;
49
50 if ( fabs(Isolevel - P2) < precision)
51 return 1.0;
52*/
53
54 ValueType dP = P2-P1;
55// if ( fabs(dP) < precision)
56 if ( dP == 0.0)
57 return 0.5;
58
59 ResultType r = (Isolevel - P1) / dP;
60 if (r<0.0) return 0.0;
61 if (r>1.0) return 1.0;
62
63 return r;
64 }
65
66};
67
72template <class ValueType, Dims_t Dims, class ResultType>
74 int &EdgeOrientation,
78 const ResultType&precision)
79{
80//MultiIndex<Dims> EdgeDir = SecondVertex - FirstVertex;
81//MultiIndex<Dims> IndexDifference = distance(SecondVertex, FirstVertex);
82
83 EdgeOrientation = FirstVertex.getSignedOrientation(SecondVertex);
84 assert( EdgeOrientation != 0 );
85
86 if (EdgeOrientation<0)
87 {
90 assert( EdgeID < NumberOfEdges( FE.Field.Size() ));
91 Weight = 1.0 - FE.InterpolationWeight(FirstVertex, SecondVertex, precision);
92 }
93 else
94 {
96 assert( EdgeID < NumberOfEdges( FE.Field.Size() ));
97 Weight = FE.InterpolationWeight(FirstVertex, SecondVertex, precision);
98 }
99}
100
101extern gridop_API const int edgeTable[256];
102extern gridop_API const int triTable[256][16];
103
109template <class ArrayType>
110inline int Polygonize(// data given per iso vertex
111 std::vector<index_t> &IsoVertexEdge,
112 std::vector<double> &IsoVertexWeight,
113
114 // data given per iso triangle
115 std::vector<TriangleCell> &IsoSurfaceTriangles,
116
117 // internal collector
118 map<index_t, index_t> &IsosurfaceVerticesAsEdges,
119
122
123 const MultiIndex<3>&CellIndex,
124 double precision,
125 index_t EdgeOffset = 0)
126{
128
129 /*
130 Determine the index into the edge table which
131 tells us which vertices are inside of the surface
132 */
133int cubeindex = 0;
134
136
137static const int VertexConvention[] =
138{
1390, // 0,0,0
1401, // 1,0,0
1413, // 0,1,0
1422, // 1,1,0
1434, // 0,0,1
1445, // 1,0,1
1457, // 1,1,0
1466, // 1,1,1
147};
148
149//
150// Build up mapping from vertex number (counted) to vertex index (computed)
151//
152 for(int i=0; i< (1<<3); i++)
153 {
154 MultiIndex<3> I = CellIndex + MultiIndex<3>::BitIndex(i);
156 }
157
158//
159// Compute edge bitmap
160//
161 for(int i=0; i< (1<<3); i++)
162 {
164
165// if ( ScalarField[ I ] < Isolevel )
166 if ( FE.isBelowThreshold( I ) )
167 {
168 cubeindex |= 1<<i;
169 }
170 }
171 /* Cube is entirely in/out of the surface */
172 if (edgeTable[cubeindex] == 0)
173 return 0;
174
175index_t Edges[12] = { -1u, -1u, -1u, -1u,
176 -1u, -1u, -1u, -1u,
177 -1u, -1u, -1u, -1u };
178
179int EdgeOrientations[12];
180double Weights[12];
181
182static int EdgeVertices[12][2] = {
183{0,1},
184{1,2},
185{2,3},
186{3,0},
187
188{4,5},
189{5,6},
190{6,7},
191{7,4},
192
193{0,4},
194{1,5},
195{2,6},
196{3,7}
197};
198
199int Nints = 0;
200
201 // Compute Edges array
202
203 //
204 // Find the edges where the surface intersects the cube
205 //
206 for(int E=0; E<12; E++)
207 {
208 if (edgeTable[cubeindex] & (1<<E) )
209 {
210 int edge = E;
211
213 V1 = VertexIndices[ EdgeVertices[edge][1] ];
214
215 Nints++;
216
218 FE,
219 V0, V1,
220 precision);
221 }
222 }
223
224 //
225 // Create and the triangles
226 //
227int ntriang = 0;
228 for (int i=0;triTable[cubeindex][i]!=-1; i+=3)
229 {
230 // Indices in locale Edge/Weights table
231 int I[3] = { triTable[cubeindex][i ],
232 triTable[cubeindex][i+1],
233 triTable[cubeindex][i+2] };
234
235 TriangleCell Triangle;
236 for(int k=0; k<3; k++)
237 {
238 int LocalEdge = I[k];
239 assert( LocalEdge <12 );
240 index_t edge = Edges[ LocalEdge ] + EdgeOffset;
241
243
244 IsosurfaceVerticesAsEdges_t::const_iterator it =
245 IsosurfaceVerticesAsEdges.find( edge );
246 if (it == IsosurfaceVerticesAsEdges.end() )
247 {
248 SurfaceVertexIndex = IsoVertexEdge.size();
249 IsosurfaceVerticesAsEdges[ edge ] = SurfaceVertexIndex;
250
251 IsoVertexEdge .push_back( edge );
252
254 IsoVertexWeight .push_back( Weights[ LocalEdge ] );
255 }
256 else
257 {
258 SurfaceVertexIndex = it->second;
259 }
260 Triangle[ k ] = SurfaceVertexIndex;
261 }
262 IsoSurfaceTriangles.push_back( Triangle );
263
264 ntriang++;
265 }
266 return ntriang;
267}
268
274template <class VertexFieldType>
276 // data given per vertex
279
280 // original vertex field
284
286 index_t EdgeOffset = 0)
287{
288 enum Dims_t { Dims = VertexFieldType::Dims };
289 typedef typename VertexFieldType::value_type value_type;
290
291 EvaluatedField.resize( Edges.size() );
292
293 for(index_t i = StartEvaluationAtVertex; i<Edges.size(); i++)
294 {
295 index_t EdgeIndex = Edges[i] - EdgeOffset;
296
299
300 const value_type&P0 = RegularField[ Edge.first + FragmentOffset ],
302
303 double w = Weights[ i ];
304
305 EvaluatedField[ i ] = P0 + w*(P1-P0);
306 }
307}
308
309
310
311typedef std::pair<RefPtr<MemArray<1, ::Eagle::PhysicalSpace::point> >, RefPtr<MemArray<1, TriangleCell> > > TriangleSurface_t;
312
313template <class VertexField_t, class ArrayType>
314inline gridop_API TriangleSurface_t
315 ComputeIsosurfaceT(const FieldExplorer<ArrayType>&FE,
316 const VertexField_t&VertexField,
317 double precision)
318{
319 // data given per iso vertex
320MemCore::MemVector<index_t> IsoVertexEdge(0);
321MemCore::MemVector<double> IsoVertexWeight(0);
322
323 // data given per iso triangle
324MemCore::MemVector<TriangleCell> IsoSurfaceTriangles(0);
325
326 // internal collector
327map<index_t, index_t> IsosurfaceVerticesAsEdges;
328
329MultiIndex<3> NumberOfCells = FE.Field.Size() - MIndex(1,1,1);
330
331 try
332 {
333 for(MultiIndex<3> CellIndex : NumberOfCells )
334 {
335 Polygonize(IsoVertexEdge,
336 IsoVertexWeight,
337 IsoSurfaceTriangles,
338
339 IsosurfaceVerticesAsEdges,
340
341 FE,
342 CellIndex,
343 precision);
344 }
345 }
346 catch(...)
347 {
348 printf("ComputeIsosurfaceT(): INTERNAL ERROR\n"); fflush(stdout);
349 throw;
350 }
351
352RefPtr<MemBase>
353 IsoVertexEdgeM = makeMemArray1D( IsoVertexEdge ),
354 IsoVertexEdgeW = makeMemArray1D( IsoVertexWeight ),
355
356 IsoTriangleM = makeMemArray1D( IsoSurfaceTriangles );
357
359
361 IsoVertices( IsoVertexEdge.size() );
362
363// ComputeVertices
364
365 EvalVertexFieldOnEdges(IsoVertices.std_vector(),
366 // data given per iso vertex
367 IsoVertexEdge.std_vector(),
368 IsoVertexWeight.std_vector(),
369
370 // original vertex field
371 VertexField,
372 VertexField.Size(),
373 MIndex(0,0,0) );
374
375 return TriangleSurface_t( makeMemArray1D( IsoVertices ),
376 IsoTriangleM);
377}
378
379
380
381extern gridop_API
382TriangleSurface_t ComputeIsosurface(double Isolevel,
383 const MultiArray<3,double>&ScalarField,
384 const MultiArray<3,::Eagle::PhysicalSpace::point>&VertexField,
385 double precision);
386
387
388} // namespace Fiber
389
390#endif
constexpr void push_back(const value_type &__x)
constexpr size_type size() const noexcept
An iterator with an optional DataCreator, which is just a class to intercept creation of data along a...
Definition CreativeIterator.hpp:34
Identify the edges on a skeleton within a Grid.
Definition Edges.hpp:35
A Field is a collection of CreativeArrayBase reference pointers which are accessed via FragmentID obj...
Definition Field.hpp:245
Definition MultiArray.hpp:371
index_t BitIndex() const
From this given multiindex which is supposed to have index values of either 0 or 1 in each direction,...
Definition MultiIndex.hpp:489
double P0(double x)
double P1(double x)
std::pair< MultiIndex< Dims >, MultiIndex< Dims > > ComputeEdgeVertices(index_t EdgeIndex, const MultiIndex< Dims > &NumberOfVertices)
Compute the both vertices that correspond to a certain edge, where the edge is linearly numbered over...
Definition RegularTopology.hpp:122
index_t ComputeEdgeIDfromVertexAndOrientation(const MultiIndex< Dims > &Vertex, int Orientation, const MultiIndex< Dims > &NumberOfVertices)
Given a vertex and an orientation (i.e.
Definition RegularTopology.hpp:152
index_t NumberOfEdges(const MultiIndex< Dims > &NumberOfVertices)
Compute the number of edges on a regular grid that consists of the given number of vertices.
Definition RegularTopology.hpp:24
int EdgeOrientation(index_t EdgeIndex, const MultiIndex< Dims > &NumberOfVertices)
Compute the orientation of a given edge index in a regular grid, given the number of vertices in the ...
Definition RegularTopology.hpp:46
Given a fragmented field of curvilinear coordinates, (3D array of coordinates), build a uniform Grid ...
Definition FAQ.dox:2
int Polygonize(std::vector< index_t > &IsoVertexEdge, std::vector< double > &IsoVertexWeight, std::vector< TriangleCell > &IsoSurfaceTriangles, map< index_t, index_t > &IsosurfaceVerticesAsEdges, const FieldExplorer< ArrayType > &FE, const MultiIndex< 3 > &CellIndex, double precision, index_t EdgeOffset=0)
Create polygons out of a given field to be explored, based on the algorithm described by http://local...
Definition Isosurface.hpp:110
void EvalVertexFieldOnEdges(std::vector< typename VertexFieldType::value_type > &EvaluatedField, const std::vector< index_t > &Edges, const std::vector< double > &Weights, const VertexFieldType &RegularField, const MultiIndex< 3 > &FragmentSize, const MultiIndex< 3 > &FragmentOffset, index_t StartEvaluationAtVertex=0, index_t EdgeOffset=0)
Given a set of edge indices and weights on them, plus a field defined on the vertices of a regular gr...
Definition Isosurface.hpp:275
void ComputeInterpolationEdgeAndWeight(index_t &EdgeID, int &EdgeOrientation, ResultType &Weight, const FieldExplorer< MultiArray< Dims, ValueType > > &FE, const MultiIndex< Dims > &FirstVertex, const MultiIndex< Dims > &SecondVertex, const ResultType &precision)
Given an value, and field with two vertices to evaluate at, compute the weight that each of the verti...
Definition Isosurface.hpp:73
RefPtr< MemArray< 1, T > > makeMemArray1D(const RefPtr< MemCore::TypedChunk< T > > &DataChunk, const MemBase::Creator_t &C=MemCore::NullPtr())
Create one-dimensional MemArray from provided data chunk.
Definition MemArray.hpp:357
Grid & ComputeIsosurface(double Isolevel, const Ageable &Trigger, const Grid &RegularGrid, const string &fieldname, Slice &timeStep, const string &isosurfacename, double precision)
Compute an isosurface as a new Grid object from a scalar field given on a regular grid.
Definition GridIsosurface.cpp:262
IndexTypeConfig< sizeof(void *)>::index_t index_t
Define the index type as according to the size of a pointer, i.e.
Definition Index.hpp:22
Definition Isosurface.hpp:22
A type describing an n-dimensional simplex cell.
Definition Cell.hpp:70