public static void demoSquare() { TriMesh tm = new TriMesh(); TriMesh.Node n0 = new TriMesh.Node(0.0f,0.0f); TriMesh.Node n1 = new TriMesh.Node(1.0f,0.0f); TriMesh.Node n2 = new TriMesh.Node(0.0f,1.0f); TriMesh.Node n3 = new TriMesh.Node(1.0f,1.0f); tm.addNode(n0); tm.addNode(n1); tm.addNode(n2); tm.addNode(n3); plot(tm); }
/** * Finds the node nearest to the point with specified coordinates. * @param x the x coordinate. * @param y the y coordinate. * @return the nearest node. */ public synchronized Node findNodeNearest(float x, float y) { return findNodeNearest((double)x,(double)y); }
/** * Appends the node nabors of the specified node to the specified list. * @param node the node for which to get nabors. * @param nabors the list to which nabors are appended. */ public synchronized void getNodeNabors(Node node, NodeList nabors) { clearNodeMarks(); clearTriMarks(); getNodeNabors(node,node._tri,nabors); }
/** * Appends the tri nabors of the specified node to the specified list. * @param node the node for which to get nabors. * @param nabors the list to which nabors are appended. */ public synchronized void getTriNabors(Node node, TriList nabors) { clearTriMarks(); getTriNabors(node,node._tri,nabors); }
/** * Determines whether the specified node is an inner node. * @param node a node. * @return true, if inner; false, otherwise. */ public boolean isInner(Node node) { Tri tri = node.tri(); if (tri==null || isInner(tri)) return true; Tri[] tris = getTriNabors(node); int ntri = tris.length; for (int itri=0; itri<ntri; ++itri) { if (isInner(tris[itri])) return true; } return false; }
public void testAddFindRemove() { java.util.Random random = new java.util.Random(); TriMesh tm = new TriMesh(); //int nadd = 0; //int nremove = 0; for (int niter=0; niter<1000; ++niter) { float x = random.nextFloat(); float y = random.nextFloat(); if (tm.countNodes()<10 || random.nextFloat()>0.5f) { TriMesh.Node node = new TriMesh.Node(x,y); boolean ok = tm.addNode(node); assertTrue(ok); tm.validate(); //++nadd; } else if (tm.countNodes()>0) { TriMesh.Node node = tm.findNodeNearest(x,y); assertTrue(node!=null); TriMesh.Node nodeSlow = tm.findNodeNearestSlow(x,y); assertTrue(node==nodeSlow); tm.removeNode(node); tm.validate(); //++nremove; } } //System.out.println("Nodes added/removed = "+nadd+"/"+nremove); }
public void testNabors() { TriMesh tm = new TriMesh(); TriMesh.Node n0 = new TriMesh.Node(1.0f,0.0f); TriMesh.Node n1 = new TriMesh.Node(0.0f,1.0f); TriMesh.Node n2 = new TriMesh.Node(0.0f,0.0f); TriMesh.Node n3 = new TriMesh.Node(1.1f,1.1f); tm.addNode(n0); tm.addNode(n1); tm.addNode(n2); tm.addNode(n3); assertEquals(2,tm.getTriNabors(n0).length); assertEquals(2,tm.getTriNabors(n1).length); assertEquals(1,tm.getTriNabors(n2).length); assertEquals(1,tm.getTriNabors(n3).length); assertEquals(2,tm.getTriNabors(tm.findEdge(n0,n1)).length); assertEquals(1,tm.getTriNabors(tm.findEdge(n0,n2)).length); assertEquals(1,tm.getTriNabors(tm.findEdge(n1,n2)).length); assertEquals(1,tm.getTriNabors(tm.findEdge(n0,n3)).length); assertEquals(1,tm.getTriNabors(tm.findEdge(n1,n3)).length); assertEquals(3,tm.getEdgeNabors(n0).length); assertEquals(3,tm.getEdgeNabors(n1).length); assertEquals(2,tm.getEdgeNabors(n2).length); assertEquals(2,tm.getEdgeNabors(n3).length); assertEquals(3,tm.getNodeNabors(n0).length); assertEquals(3,tm.getNodeNabors(n1).length); assertEquals(2,tm.getNodeNabors(n2).length); assertEquals(2,tm.getNodeNabors(n3).length); }
public void testSquare() { TriMesh tm = new TriMesh(); TriMesh.Node n0 = new TriMesh.Node(0.0f,0.0f); TriMesh.Node n1 = new TriMesh.Node(1.0f,0.0f); TriMesh.Node n2 = new TriMesh.Node(0.0f,1.0f); TriMesh.Node n3 = new TriMesh.Node(1.0f,1.0f); tm.addNode(n0); tm.addNode(n1); tm.addNode(n2); tm.addNode(n3); tm.removeNode(n3); tm.removeNode(n2); tm.removeNode(n1); tm.removeNode(n0); tm.validate(); }
TriMesh.Node n10 = new TriMesh.Node(1.0f,0.0f); TriMesh.Node n11 = new TriMesh.Node(1.0f,1.0f); TriMesh tm = new TriMesh(); tm.addNode(n00); tm.addNode(n01); tm.addNode(n10); tm.addNode(n11); int nnode = tm.countNodes(); int ntri = tm.countTris(); assertEquals(4,nnode); TriMesh.NodePropertyMap map = tm.getNodePropertyMap("foo"); map.put(n00,0); map.put(n01,1); tm = (TriMesh)ois.readObject(); bais.close(); assertEquals(nnode,tm.countNodes()); assertEquals(ntri,tm.countTris()); String name = tm.getNodePropertyMapNames()[0]; assertEquals("foo",name); map = tm.getNodePropertyMap(name); n00 = tm.findNodeNearest(0.0f,0.0f); n01 = tm.findNodeNearest(0.0f,1.0f); n10 = tm.findNodeNearest(1.0f,0.0f); n11 = tm.findNodeNearest(1.0f,1.0f); assertEquals(0,((Integer)map.get(n00)).intValue()); assertEquals(1,((Integer)map.get(n01)).intValue());
public void benchAddNode() { java.util.Random random = new java.util.Random(); for (int itest=0; itest<3; ++itest) { for (int nnode=1000; nnode<=64000; nnode*=2) { Stopwatch sw = new Stopwatch(); sw.restart(); TriMesh tm = new TriMesh(); for (int inode=0; inode<nnode; ++inode) { float x = random.nextFloat(); float y = random.nextFloat(); TriMesh.Node node = new TriMesh.Node(x,y); tm.addNode(node); } sw.stop(); System.out.println( "Added "+nnode+" nodes to make "+tm.countTris() + " tris in "+sw.time()+" seconds."); tm.validate(); } try { System.out.println("Sleeping"); Thread.sleep(5000,0); } catch (InterruptedException e) { throw new RuntimeException(e); } } }
public void testTriListener() { TriMesh tm = new TriMesh(); tm.addNode(new TriMesh.Node(0.0f,0.0f)); tm.addNode(new TriMesh.Node(1.0f,0.0f)); tm.addNode(new TriMesh.Node(0.0f,1.0f)); TriListener tl = new TriListener(); tm.addTriListener(tl); TriMesh.Node node = new TriMesh.Node(0.1f,0.1f); tm.addNode(node); assertEquals(3,tl.countAdded()); assertEquals(1,tl.countRemoved()); tm.removeNode(node); assertEquals(4,tl.countAdded()); assertEquals(4,tl.countRemoved()); } private static class TriListener implements TriMesh.TriListener {
boolean haveEdgeColors = _triEdgeColors!=null; TriMesh.NodePropertyMap colorMap = null; if (_mesh.hasNodePropertyMap("Color")) colorMap = _mesh.getNodePropertyMap("Color"); g2d.setColor(_triLineColor); TriMesh.TriIterator ti = _mesh.getTris(); while (ti.hasNext()) { TriMesh.Tri tri = ti.next(); if (_mesh.isOuter(tri)) continue; TriMesh.Node na = tri.nodeA(); Color cca = null; if (_drawTris && haveEdgeColors) { cab = _triEdgeColors.get(_mesh.findEdge(na,nb)); cbc = _triEdgeColors.get(_mesh.findEdge(nb,nc)); cca = _triEdgeColors.get(_mesh.findEdge(nc,na)); if (cab==null) cab = _triLineColor; if (cbc==null) cbc = _triLineColor; if (_mesh.hasNodePropertyMap("Color")) colorMap = _mesh.getNodePropertyMap("Color"); g2d.setColor(_polyLineColor); float[] pa = new float[2]; float[] pn = new float[2]; float[] qc = new float[2]; TriMesh.TriIterator ti = _mesh.getTris(); while (ti.hasNext()) {
java.util.Random random = new java.util.Random(); Stopwatch sw = new Stopwatch(); TriMesh tm = new TriMesh(); for (int inode=0; inode<nnode; ++inode) { float x = random.nextFloat(); float y = random.nextFloat(); TriMesh.Node node = new TriMesh.Node(x,y); tm.addNode(node); sw.start(); for (int ifind=0; ifind<nfind; ++ifind) nfast[ifind] = tm.findNodeNearest(x[ifind],y[ifind]); sw.stop(); int sfast = (int)(nfind/sw.time()); sw.start(); for (int ifind=0; ifind<nfind; ++ifind) nslow[ifind] = tm.findNodeNearestSlow(x[ifind],y[ifind]); sw.stop(); int sslow = (int)(nfind/sw.time());
/** * Moves a node in the mesh to the specified (x,y) coordinates. * Roughly equivalent to (but potentially more efficient than) * first removing and then adding the node to the mesh at the * specified coordinates. However, if the node is not in the mesh, * then it will be moved, but not added to the mesh. Also, if the * specified coordinates are already occupied by another node in * the mesh, then the specified node is not moved. * @param node a node in the mesh. * @param x the x coordinate of the moved node. * @param y the y coordinate of the moved node. * @return true, if the node was moved; false, otherwise. */ public synchronized boolean moveNode(Node node, float x, float y) { // TODO: optimize for small movements that require no retriangulation. if (x!=node.x() || y!=node.y()) { Node nodeNearest = findNodeNearest(x,y); if (node==nodeNearest || x!=nodeNearest.x() || y!=nodeNearest.y()) { boolean nodeInMesh = removeNode(node); node.setPosition(x,y); if (nodeInMesh) { boolean addedNode = addNode(node); assert addedNode; } return true; } } return false; }
/** * Interpolates at specified sample points without using those samples. * This method implements a form of cross-validation. Differences * between the values of the specified samples and the returned * interpolated values are measures of errors for those samples. * <p> * If bounds have not been set explicitly, then this method will return * null values if the validated sample is on the convex hull of samples. * <p> * This method does not recompute gradients that may have been estimated * using the samples to be validated. Therefore, validation should be * performed without using gradients. * @param i array of indices of samples to validate. * @return array of values interpolated at validated sample points. */ public float[] validate(int[] i) { int nv = i.length; for (int iv=0; iv<nv; ++iv) _mesh.removeNode(_nodes[i[iv]]); float[] fv = new float[nv]; for (int iv=0; iv<nv; ++iv) { TriMesh.Node node = _nodes[i[iv]]; float xn = node.x(); float yn = node.y(); fv[iv] = interpolate(xn,yn); } for (int iv=0; iv<nv; ++iv) _mesh.addNode(_nodes[i[iv]]); return fv; }
float xg = x[ig]; float yg = y[ig]; TriMesh.PointLocation pl = _mesh.locatePoint(xg,yg); if (pl.isOutside()) { TriMesh.Node n = new TriMesh.Node(xg,yg); n.index = -1-ig; // ghost nodes have negative indices _mesh.addNode(n); NodeData data = new NodeData(); n.data = data; data.gy = (float)s.get(2,0); } else { // otherwise, just use value of nearest node TriMesh.Node m = _mesh.findNodeNearest(xg,yg); data.f = f(m); data.gx = 0.0f;
mark(tri); nabors.add(tri); Node n0 = tri._n0; Tri t2 = tri._t2; if (node==n0) { if (t1!=null && !isMarked(t1)) getTriNabors(node,t1,nabors); if (t2!=null && !isMarked(t2)) getTriNabors(node,t2,nabors); } else if (node==n1) { if (t2!=null && !isMarked(t2)) getTriNabors(node,t2,nabors); if (t0!=null && !isMarked(t0)) getTriNabors(node,t0,nabors); } else if (node==n2) { if (t0!=null && !isMarked(t0)) getTriNabors(node,t0,nabors); if (t1!=null && !isMarked(t1)) getTriNabors(node,t1,nabors); } else { assert false:"node is referenced by tri";
mark(tri); Node n0 = tri._n0; Node n1 = tri._n1; Tri t2 = tri._t2; if (node==n0) { if (!isMarked(n1)) { mark(n1); nabors.add(n1); if (!isMarked(n2)) { mark(n2); nabors.add(n2); if (t1!=null && !isMarked(t1)) getNodeNabors(node,t1,nabors); if (t2!=null && !isMarked(t2)) getNodeNabors(node,t2,nabors); } else if (node==n1) { if (!isMarked(n2)) { mark(n2); nabors.add(n2); if (!isMarked(n0)) { mark(n0); nabors.add(n0); if (t2!=null && !isMarked(t2)) getNodeNabors(node,t2,nabors);
/** * Validates the internal consistency of the mesh. * @exception RuntimeException if the mesh is invalid. */ public synchronized void validate() { // Check nodes. int nnode = 0; NodeIterator ni = getNodes(); while (ni.hasNext()) { ++nnode; Node node = ni.next(); validate(node); } assert nnode==_nnode; // Check tris. int ntri = 0; TriIterator ti = getTris(); while (ti.hasNext()) { ++ntri; Tri tri = ti.next(); validate(tri); } assert ntri==_ntri; }
private void addGhostNodes(float[] x, float[] y) { int ng = x.length; for (int ig=0; ig<ng; ++ig) { float xg = x[ig]; float yg = y[ig]; TriMesh.PointLocation pl = _mesh.locatePoint(xg,yg); if (pl.isOutside()) { TriMesh.Node n = new TriMesh.Node(xg,yg); n.data = new NodeData(); n.index = -1-ig; // ghost nodes have negative indices _mesh.addNode(n); } } }