_nodeMarkRed = 0; _nodeMarkBlue = 0; _faceSet = new FaceSet(256,0.25); _edgeSet = new EdgeSet(256,0.25); _nodeList = new NodeList();
_faceSet.clear(); _nodeList.clear(); clearTetMarks(); for (boolean more=_faceSet.remove(); more; more=_faceSet.remove()) { if (!_faceSet.add(nabc,a)) linkTets(_faceSet.abcd,_faceSet.d,nabc,a); if (!_faceSet.add(nabc,b)) linkTets(_faceSet.abcd,_faceSet.d,nabc,b); if (!_faceSet.add(nabc,c)) linkTets(_faceSet.abcd,_faceSet.d,nabc,c);
Tet t3 = tet._t3; if (t0==null && leftOfPlane(n1,n2,n3,node)) { _faceSet.add(tet,n0); getDelaunayFacesOutside(node,getNextTetOnHull(tet,n1,n0)); getDelaunayFacesOutside(node,getNextTetOnHull(tet,n2,n0)); _faceSet.add(tet,n1); getDelaunayFacesOutside(node,getNextTetOnHull(tet,n3,n1)); getDelaunayFacesOutside(node,getNextTetOnHull(tet,n2,n1)); _faceSet.add(tet,n2); getDelaunayFacesOutside(node,getNextTetOnHull(tet,n3,n2)); getDelaunayFacesOutside(node,getNextTetOnHull(tet,n0,n2)); _faceSet.add(tet,n3); getDelaunayFacesOutside(node,getNextTetOnHull(tet,n1,n3)); getDelaunayFacesOutside(node,getNextTetOnHull(tet,n0,n3)); _faceSet.addMate(tet,n0); _faceSet.addMate(tet,n1); _faceSet.addMate(tet,n2); _faceSet.addMate(tet,n3); getDelaunayFacesOutside(node,t0); getDelaunayFacesOutside(node,t1);
Tet t3 = tet._t3; if (node==n0) { _faceSet.addMate(tet,n0); getDelaunayFacesOpposite(node,n1,n2,n3,t1,t2,t3); } else if (node==n1) { _faceSet.addMate(tet,n1); getDelaunayFacesOpposite(node,n3,n2,n0,t3,t2,t0); } else if (node==n2) { _faceSet.addMate(tet,n2); getDelaunayFacesOpposite(node,n3,n0,n1,t3,t0,t1); } else if (node==n3) { _faceSet.addMate(tet,n3); getDelaunayFacesOpposite(node,n1,n0,n2,t1,t0,t2); } else {
/** * Beginning with a tet that contains a node located inside the * mesh, recursively adds Delaunay faces to the face set. * The tet marks must be cleared before calling this method. */ private void getDelaunayFacesInside(Node node, Tet tet) { if (tet!=null && !isMarked(tet)) { mark(tet); Node n0 = tet._n0; Node n1 = tet._n1; Node n2 = tet._n2; Node n3 = tet._n3; if (inSphere(n0,n1,n2,n3,node)) { killTet(tet); Tet t0 = tet._t0; Tet t1 = tet._t1; Tet t2 = tet._t2; Tet t3 = tet._t3; _faceSet.addMate(tet,n0); _faceSet.addMate(tet,n1); _faceSet.addMate(tet,n2); _faceSet.addMate(tet,n3); getDelaunayFacesInside(node,t0); getDelaunayFacesInside(node,t1); getDelaunayFacesInside(node,t2); getDelaunayFacesInside(node,t3); } } }
/** * If the set is not empty, removes a face from the set. * Sets the current face to the face removed. * @return true, if the set was not empty; false, otherwise. */ boolean remove() { if (_n>0) { int start = _index; for (; _index<_nmax; ++_index) { if (_filled[_index]) { setCurrent(); remove(_index); return true; } } for (_index=0; _index<start; ++_index) { if (_filled[_index]) { setCurrent(); remove(_index); return true; } } } return false; }
/** * If the set does not contain the mate of the specified face, adds * the face to the set, remembers the face added, and returns true. * Otherwise, if the set already contains the mate, removes the mate * from the set, remembers the mate removed, and returns false. */ private boolean add(Node a, Node b, Node c, Node d, Tet abcd) { _index = indexOfMate(a,b,c); if (_filled[_index]) { setCurrent(); remove(_index); return false; } else { _a[_index] = a; _b[_index] = b; _c[_index] = c; _d[_index] = d; _abcd[_index] = abcd; _filled[_index] = true; ++_n; if (_n>_nmax*_factor && _nmax<MAX_CAPACITY) doubleCapacity(); setCurrent(); return true; } }
/** * Doubles the capacity of the set. */ private void doubleCapacity() { //trace("FaceSet.doubleCapacity"); FaceSet set = new FaceSet(2*_nmax,_factor); if (_n>0) { for (int i=0; i<_nmax; ++i) { if (_filled[i]) set.add(_a[i],_b[i],_c[i],_d[i],_abcd[i]); } } _a = set._a; _b = set._b; _c = set._c; _d = set._d; _abcd = set._abcd; _filled = set._filled; _nmax = set._nmax; _n = set._n; _factor = set._factor; _shift = set._shift; _mask = set._mask; _index = set._index; } }
/** * Adds the mate of the face of the specified tet that is opposite * the specified node, unless the face is in the set, in which case * that face is removed. Sets the current face to the mate added or * the face removed. * @param tet the tet that references the nodes in the face. * @param node the other node in the tet that is not in the face. * @return true, if the mate was added; false, if the face was removed. */ boolean addMate(Tet tet, Node node) { Tet tetNabor = tet.tetNabor(node); Node nodeNabor = (tetNabor!=null)?tet.nodeNabor(tetNabor):null; if (node==tet._n0) { return add(tet._n1,tet._n2,tet._n3,nodeNabor,tetNabor); } else if (node==tet._n1) { return add(tet._n3,tet._n2,tet._n0,nodeNabor,tetNabor); } else if (node==tet._n2) { return add(tet._n3,tet._n0,tet._n1,nodeNabor,tetNabor); } else if (node==tet._n3) { return add(tet._n1,tet._n0,tet._n2,nodeNabor,tetNabor); } else { assert false:"node is referenced by tet"; return false; } }
/** * Removes the face with specified index. */ private void remove(int i) { // Knuth, v. 3, 527, Algorithm R. --_n; for (;;) { _filled[i] = false; int j = i; int r; do { i = (i-1)&_mask; if (!_filled[i]) return; r = hash(_a[i],_b[i],_c[i]); } while ((i<=r && r<j) || (r<j && j<i) || (j<i && i<=r)); _a[j] = _a[i]; _b[j] = _b[i]; _c[j] = _c[i]; _d[j] = _d[i]; _abcd[j] = _abcd[i]; _filled[j] = _filled[i]; } }
/** * Adds the face of the specified tet that is opposite the specified node, * unless its mate is in the set, in which case that mate is removed. * Sets the current face to the face added or the mate removed. * @param tet the tet that references nodes in the face. * @param node the other node in the tet that is not in the face. * @return true, if the face was added; false, if the mate was removed. */ boolean add(Tet tet, Node node) { if (node==tet._n0) { return add(tet._n1,tet._n3,tet._n2,node,tet); } else if (node==tet._n1) { return add(tet._n2,tet._n3,tet._n0,node,tet); } else if (node==tet._n2) { return add(tet._n3,tet._n1,tet._n0,node,tet); } else if (node==tet._n3) { return add(tet._n0,tet._n1,tet._n2,node,tet); } else { assert false:"node is referenced by tet"; return false; } }
/** * Returns the index corresponding to the mate of the specified face, * or, if the mate is not found, the index of an empty slot in the set. */ private int indexOfMate(Node a, Node b, Node c) { int i = hash(a,b,c); while (_filled[i]) { Node ai = _a[i]; Node bi = _b[i]; Node ci = _c[i]; if ((a==ai && b==ci && c==bi) || (a==bi && b==ai && c==ci) || (a==ci && b==bi && c==ai)) return i; i = (i-1)&_mask; } return i; }
/** * Sets the current face to the first face in the set. * <em>While iterating over faces, the set should not be modified.</em> * @return true, if the set is not empty; false, otherwise. */ boolean first() { _index = -1; return next(); }