source: trunk/src2/core/RpMeshTri2D.cc @ 657

Last change on this file since 657 was 657, checked in by dkearney, 17 years ago

cleaned up all the compile time warnings in core rappture2 objects

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