source: branches/1.7/src/core2/RpMeshTri2D.cc @ 6226

Last change on this file since 6226 was 5679, checked in by ldelgass, 9 years ago

Full merge 1.3 branch to uq branch to sync. Fixed partial subdirectory merge
by removing mergeinfo from lang/python/Rappture directory.

  • Property svn:eol-style set to native
File size: 10.4 KB
Line 
1/*
2 * ----------------------------------------------------------------------
3 *  Rappture::MeshTri2D
4 *    This is a non-uniform, triangular mesh for 2-dimensional
5 *    structures.
6 *
7 * ======================================================================
8 *  AUTHOR:  Michael McLennan, Purdue University
9 *  Copyright (c) 2004-2012  HUBzero Foundation, LLC
10 *
11 *  See the file "license.terms" for information on usage and
12 *  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
13 * ======================================================================
14 */
15#include <math.h>
16#include <assert.h>
17#include <float.h>
18#include <iostream>
19
20#include "RpMeshTri2D.h"
21
22using namespace Rappture;
23
24CellTri2D::CellTri2D()
25{
26    _cellId = -1;
27    _nodes[0] = NULL;
28    _nodes[1] = NULL;
29    _nodes[2] = NULL;
30}
31
32CellTri2D::CellTri2D(int cellId, Node2D* n1Ptr, Node2D* n2Ptr, Node2D* n3Ptr)
33{
34    _cellId = cellId;
35    _nodes[0] = n1Ptr;
36    _nodes[1] = n2Ptr;
37    _nodes[2] = n3Ptr;
38}
39
40CellTri2D::CellTri2D(const CellTri2D& cell)
41{
42    _cellId = cell._cellId;
43    _nodes[0] = cell._nodes[0];
44    _nodes[1] = cell._nodes[1];
45    _nodes[2] = cell._nodes[2];
46}
47
48CellTri2D&
49CellTri2D::operator=(const CellTri2D& cell)
50{
51    _cellId = cell._cellId;
52    _nodes[0] = cell._nodes[0];
53    _nodes[1] = cell._nodes[1];
54    _nodes[2] = cell._nodes[2];
55    return *this;
56}
57
58int
59CellTri2D::isNull() const
60{
61    return (_nodes[0] == NULL || _nodes[1] == NULL || _nodes[2] == NULL);
62}
63
64int
65CellTri2D::isOutside() const
66{
67    return (_cellId < 0);
68}
69
70void
71CellTri2D::clear()
72{
73    _cellId = -1;
74    _nodes[0] = _nodes[1] = _nodes[2] = NULL;
75}
76
77int
78CellTri2D::cellId() const
79{
80    return _cellId;
81}
82
83int
84CellTri2D::nodeId(int n) const
85{
86    assert(n >= 0 && n <= 2);
87    return _nodes[n]->id();
88}
89
90double
91CellTri2D::x(int n) const
92{
93    assert(n >= 0 && n <= 2);
94    return _nodes[n]->x();
95}
96
97double
98CellTri2D::y(int n) const
99{
100    assert(n >= 0 && n <= 2);
101    return _nodes[n]->y();
102}
103
104void
105CellTri2D::barycentrics(const Node2D& node, double* phi) const
106{
107    assert( _nodes[0] != NULL && _nodes[1] != NULL && _nodes[2] != NULL);
108
109    double x2 = _nodes[1]->x() - _nodes[0]->x();
110    double y2 = _nodes[1]->y() - _nodes[0]->y();
111    double x3 = _nodes[2]->x() - _nodes[0]->x();
112    double y3 = _nodes[2]->y() - _nodes[0]->y();
113    double xr = node.x() - _nodes[0]->x();
114    double yr = node.y() - _nodes[0]->y();
115    double det = x2*y3-x3*y2;
116
117    phi[1] = (xr*y3 - x3*yr)/det;
118    phi[2] = (x2*yr - xr*y2)/det;
119    phi[0] = 1.0-phi[1]-phi[2];
120}
121
122
123Tri2D::Tri2D()
124{
125    nodes[0] = nodes[1] = nodes[2] = -1;
126    neighbors[0] = neighbors[1] = neighbors[2] = -1;
127}
128
129Tri2D::Tri2D(int n1, int n2, int n3)
130{
131    nodes[0] = n1;
132    nodes[1] = n2;
133    nodes[2] = n3;
134    neighbors[0] = neighbors[1] = neighbors[2] = -1;
135}
136
137
138MeshTri2D::MeshTri2D()
139  : _counter(0),
140    _id2nodeDirty(0),
141    _id2node(100,-1)
142{
143    _nodelist.reserve(1024);
144    _min[0] = _min[1] = NAN;
145    _max[0] = _max[1] = NAN;
146}
147
148MeshTri2D::MeshTri2D(const MeshTri2D& mesh)
149  : _nodelist(mesh._nodelist),
150    _counter(mesh._counter),
151    _celllist(mesh._celllist),
152    _id2nodeDirty(mesh._id2nodeDirty),
153    _id2node(mesh._id2node)
154{
155    for (int i=0; i < 2; i++) {
156        _min[i] = mesh._min[i];
157        _max[i] = mesh._max[i];
158    }
159}
160
161MeshTri2D&
162MeshTri2D::operator=(const MeshTri2D& mesh)
163{
164    _nodelist = mesh._nodelist;
165    _counter = mesh._counter;
166    for (int i=0; i < 2; i++) {
167        _min[i] = mesh._min[i];
168        _max[i] = mesh._max[i];
169    }
170    _celllist = mesh._celllist;
171    _id2nodeDirty = mesh._id2nodeDirty;
172    _id2node = mesh._id2node;
173    _lastLocate.clear();
174    return *this;
175}
176
177MeshTri2D::~MeshTri2D()
178{
179}
180
181Node2D&
182MeshTri2D::addNode(const Node2D& nd)
183{
184    Node2D node(nd);
185
186    if (node.id() < 0) {
187        node.id(_counter++);
188    } else {
189        // see if this node already exists
190        Node2D* nptr = _getNodeById(node.id());
191        if (nptr) {
192            return *nptr;
193        }
194    }
195
196    // add this new node
197    _nodelist.push_back(node);
198
199    if (isnan(_min[0])) {
200        _min[0] = _max[0] = node.x();
201        _min[1] = _max[1] = node.y();
202    } else {
203        if (node.x() < _min[0]) { _min[0] = node.x(); }
204        if (node.x() > _max[0]) { _max[0] = node.x(); }
205        if (node.y() < _min[1]) { _min[1] = node.y(); }
206        if (node.y() > _max[1]) { _max[1] = node.y(); }
207    }
208
209    // index of this new node
210    int n = _nodelist.size()-1;
211
212    if (!_id2nodeDirty) {
213        // id2node map up to date?  then keep it up to date
214        if ((unsigned int)node.id() >= _id2node.size()) {
215            int newsize = 2*_id2node.size();
216            for (int i=_id2node.size(); i < newsize; i++) {
217                _id2node.push_back(-1);
218            }
219        }
220        _id2node[node.id()] = n;
221    }
222    return _nodelist[n];
223}
224
225void
226MeshTri2D::addCell(const Node2D& n1, const Node2D& n2, const Node2D& n3)
227{
228    Node2D node1 = addNode(n1);
229    Node2D node2 = addNode(n2);
230    Node2D node3 = addNode(n3);
231    addCell(node1.id(), node2.id(), node3.id());
232}
233
234void
235MeshTri2D::addCell(int nId1, int nId2, int nId3)
236{
237    _celllist.push_back( Tri2D(nId1,nId2,nId3) );
238    int triId = _celllist.size()-1;
239
240    Edge2D edge;
241    int nodes[4];
242    nodes[0] = nId1;
243    nodes[1] = nId2;
244    nodes[2] = nId3;
245    nodes[3] = nId1;
246
247    // update the neighbors for this triangle
248    for (int i=0; i < 3; i++) {
249        int n = (i+2) % 3;    // this is node opposite i/i+1 edge
250
251        // build an edge with nodes in proper order
252        if (nodes[i] < nodes[i+1]) {
253            edge.fromNode = nodes[i];
254            edge.toNode = nodes[i+1];
255        } else {
256            edge.fromNode = nodes[i+1];
257            edge.toNode = nodes[i];
258        }
259
260        Neighbor2D& nbr = _edge2neighbor[edge];
261        if (nbr.triId < 0) {
262            // not found? then register this for later
263            nbr.triId = triId;
264            nbr.index = n;
265        } else {
266            // this triangle points to other one for the edge
267            _celllist[triId].neighbors[n] = nbr.triId;
268            // other triangle points to this one for the same edge
269            _celllist[nbr.triId].neighbors[nbr.index] = triId;
270            _edge2neighbor.erase(edge);
271        }
272    }
273}
274
275MeshTri2D&
276MeshTri2D::clear()
277{
278    _nodelist.clear();
279    _counter = 0;
280    _id2nodeDirty = 0;
281    _id2node.assign(100, -1);
282    _lastLocate.clear();
283    return *this;
284}
285
286int
287MeshTri2D::sizeNodes() const
288{
289    return _nodelist.size();
290}
291
292Node2D&
293MeshTri2D::atNode(int pos)
294{
295    assert(pos >= 0 && (unsigned int)(pos) < _nodelist.size());
296    return _nodelist.at(pos);
297}
298
299int
300MeshTri2D::sizeCells() const
301{
302    return _celllist.size();
303}
304
305CellTri2D
306MeshTri2D::atCell(int pos)
307{
308    assert(pos >= 0 && (unsigned int)(pos) < _celllist.size());
309
310    Tri2D& cell = _celllist[pos];
311    Node2D* n1Ptr = _getNodeById(cell.nodes[0]);
312    Node2D* n2Ptr = _getNodeById(cell.nodes[1]);
313    Node2D* n3Ptr = _getNodeById(cell.nodes[2]);
314    assert(n1Ptr && n2Ptr && n3Ptr);
315
316    CellTri2D rval(pos, n1Ptr, n2Ptr, n3Ptr);
317    return rval;
318}
319
320double
321MeshTri2D::rangeMin(Axis which) const
322{
323    assert(which != Rappture::zaxis);
324    return _min[which];
325}
326
327double
328MeshTri2D::rangeMax(Axis which) const
329{
330    assert(which != Rappture::zaxis);
331    return _max[which];
332}
333
334CellTri2D
335MeshTri2D::locate(const Node2D& node) const
336{
337    MeshTri2D* nonconst = (MeshTri2D*)this;
338    CellTri2D cell = _lastLocate;
339
340    if (cell.isNull() && _celllist.size() > 0) {
341        Tri2D& tri = nonconst->_celllist[0];
342        cell = CellTri2D(0, &nonconst->_nodelist[tri.nodes[0]],
343                            &nonconst->_nodelist[tri.nodes[1]],
344                            &nonconst->_nodelist[tri.nodes[2]]);
345    }
346
347    while (!cell.isNull()) {
348        double phi[3];
349
350        // compute barycentric coords
351        // if all are >= 0, then this tri contains node
352        // Check against -DBL_EPSILON to handle precision issues at boundaries
353        cell.barycentrics(node, phi);
354        if (phi[0] > -DBL_EPSILON &&
355            phi[1] > -DBL_EPSILON &&
356            phi[2] > -DBL_EPSILON) {
357            break;
358        }
359
360        // find the smallest (most negative) coord phi, and search that dir
361        int dir = 0;
362        for (int i=1; i <= 2; i++) {
363            if (phi[i] < phi[dir]) {
364                dir = i;
365            }
366        }
367
368        Tri2D& tri = nonconst->_celllist[ cell.cellId() ];
369        int neighborId = tri.neighbors[dir];
370        if (neighborId < 0) {
371            cell.clear();
372            return cell;
373        }
374
375        Tri2D& tri2 = nonconst->_celllist[neighborId];
376        Node2D *n1Ptr = &nonconst->_nodelist[tri2.nodes[0]];
377        Node2D *n2Ptr = &nonconst->_nodelist[tri2.nodes[1]];
378        Node2D *n3Ptr = &nonconst->_nodelist[tri2.nodes[2]];
379        cell = CellTri2D(neighborId, n1Ptr, n2Ptr, n3Ptr);
380    }
381
382    nonconst->_lastLocate = cell;
383    return cell;
384}
385
386Ptr<Serializable>
387MeshTri2D::create()
388{
389    return Ptr<Serializable>( (Serializable*) new MeshTri2D() );
390}
391
392void
393MeshTri2D::serialize_A(SerialBuffer& buffer) const
394{
395}
396
397Outcome
398deserialize_A(SerialBuffer& buffer)
399{
400    Outcome status;
401    return status;
402}
403
404Node2D*
405MeshTri2D::_getNodeById(int nodeId)
406{
407    MeshTri2D* nonconst = (MeshTri2D*)this;
408    Node2D *rptr = NULL;
409    nonconst->_rebuildNodeIdMap();
410
411    if ((unsigned int)nodeId < _id2node.size()) {
412        int n = _id2node[nodeId];
413        if (n >= 0) {
414            return &_nodelist[n];
415        }
416    }
417    return rptr;
418}
419
420void
421MeshTri2D::_rebuildNodeIdMap()
422{
423    if (_id2nodeDirty) {
424        _min[0] = _min[1] = NAN;
425        _max[0] = _max[1] = NAN;
426
427        // figure out how big the _id2node array should be
428        int maxId = -1;
429        std::vector<Node2D>::iterator n = _nodelist.begin();
430        while (n != _nodelist.end()) {
431            if (n->id() > maxId) {
432                maxId = n->id();
433            }
434            ++n;
435        }
436        if (maxId > 0) {
437            _id2node.assign(maxId+1, -1);
438        }
439
440        // scan through and map id -> node index
441        int i = 0;
442        n = _nodelist.begin();
443        while (n != _nodelist.end()) {
444            _id2node[n->id()] = i++;
445
446            if (isnan(_min[0])) {
447                _min[0] = _max[0] = n->x();
448                _min[1] = _max[1] = n->y();
449            } else {
450                if (n->x() < _min[0]) { _min[0] = n->x(); }
451                if (n->x() > _max[0]) { _max[0] = n->x(); }
452                if (n->y() < _min[1]) { _min[1] = n->y(); }
453                if (n->y() > _max[1]) { _max[1] = n->y(); }
454            }
455            ++n;
456        }
457        _id2nodeDirty = 0;
458    }
459}
Note: See TracBrowser for help on using the repository browser.