float x = random.nextFloat(); float y = random.nextFloat(); TriMesh.Node node = new TriMesh.Node(x,y); tm.addNode(node); for (int ifind=0; ifind<nfind; ++ifind) { if (nfast[ifind]!=nslow[ifind]) { float xfast = nfast[ifind].x(); float yfast = nfast[ifind].y(); float xslow = nslow[ifind].x(); float yslow = nslow[ifind].y(); float dxfast = xfast-x[ifind]; float dyfast = yfast-y[ifind];
/** * Constructs a node with the specified coordinates. * (Does not add the node to the mesh.) * @param x the x coordinate. * @param y the y coordinate. */ public Node(float x, float y) { _prev = null; _next = null; _mark = 0; _tri = null; _hash = System.identityHashCode(this); setPosition(x,y); }
private void estimateGradient(TriMesh.Node n) { NodeData data = data(n); double fn = data.f; double xn = n.xp(); double yn = n.yp(); _mesh.removeNode(n); double asum = computeAreas((float)xn,(float)yn); double fm = f(m); double wm = area(m); double xm = m.xp(); double ym = m.yp(); double df = fn-fm; double dx = xn-xm;
Tri tri = node.tri(); Node ta = tri.nodeA(); Node tb = tri.nodeB();
public void testIO() throws IOException,ClassNotFoundException { TriMesh.Node n00 = new TriMesh.Node(0.0f,0.0f); TriMesh.Node n01 = new TriMesh.Node(0.0f,1.0f); 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);
TriMesh.Node node = new TriMesh.Node(x1i,x2i); boolean added = _mesh.addNode(node); Check.argument(added,"each sample has unique coordinates");
TriMesh.Node n = _nodes[in]; double fn = f(n); double xn = n.xp(); double yn = n.yp(); for (int ig=0; ig<ng; ++ig) { double xg = x[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);
/** * Locates a point. */ private PointLocation locatePoint(double x, double y) { // If no tris yet, search the node list for an exact match. // Here, we use unperturbed node coordinates. if (_troot==null) { if (_nroot!=null) { Node node = _nroot; do { if (x==node.x() && y==node.y()) return new PointLocation(node); node = node._next; } while (node!=_nroot); } return new PointLocation(null,false); } // Otherwise, find a good tri in which to begin the recursive search. Node nmin = _nroot; double dmin = distanceSquared(nmin,x,y); for (Node n:_sampledNodes) { double d = distanceSquared(n,x,y); if (d<dmin) { dmin = d; nmin = n; } } Tri tri = nmin._tri; return locatePoint(tri,x,y); }
public double accumulateAreas( double xp, double yp, TriMesh mesh, TriMesh.NodeList nodeList, TriMesh.TriList triList) { clear(); int ntri = triList.ntri(); TriMesh.Tri[] tris = triList.tris(); for (int itri=0; itri<ntri; ++itri) { TriMesh.Tri tri = tris[itri]; TriMesh.Node na = tri.nodeA(); TriMesh.Node nb = tri.nodeB(); TriMesh.Node nc = tri.nodeC(); double xa = na.xp(), ya = na.yp(); double xb = nb.xp(), yb = nb.yp(); double xc = nc.xp(), yc = nc.yp(); Geometry.centerCircle(xp,yp,xb,yb,xc,yc,_ca); Geometry.centerCircle(xp,yp,xc,yc,xa,ya,_cb); Geometry.centerCircle(xp,yp,xa,ya,xb,yb,_cc); Geometry.centerCircle(xa,ya,xb,yb,xc,yc,_ct); double aa = area(_cb,_cc,_ct); double ab = area(_cc,_ca,_ct); double ac = area(_ca,_cb,_ct); accumulate(na,aa); accumulate(nb,ab); accumulate(nc,ac); } return sum(); } private double[] _ca = new double[2]; // circumcenter of fake tri pbc
/** * 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; }
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 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); } } }
/** * Computes nearest neighbor distances and values. * @param s1 sampling for coordinate x1. * @param s2 sampling for coordinate x2. * @param d array of distances to nearest known samples. * @param g array of nearest known sample values. */ public void computeDistancesAndValues( Sampling s1, Sampling s2, float[][] d, float[][] g) { int n1 = s1.getCount(); int n2 = s2.getCount(); for (int i2=0; i2<n2; ++i2) { float x2 = (float)s2.getValue(i2); for (int i1=0; i1<n1; ++i1) { float x1 = (float)s1.getValue(i1); TriMesh.Node node = _mesh.findNodeNearest(x1,x2); float d1 = x1-node.x(); float d2 = x2-node.y(); if (g!=null) g[i2][i1] = _f[node.index]; if (d!=null) d[i2][i1] = sqrt(d1*d1+d2*d2); } } }
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); }
/** * 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; }
/** * Called when bounds on (x,y) coordinates in mesh may have changed. */ private void updateMinMax() { if (_mesh==null) return; _xmin = Float.MAX_VALUE; _ymin = Float.MAX_VALUE; _xmax = -Float.MAX_VALUE; _ymax = -Float.MAX_VALUE; TriMesh.NodeIterator ni = _mesh.getNodes(); while (ni.hasNext()) { TriMesh.Node node = ni.next(); float x = node.x(); float y = node.y(); if (x<_xmin) _xmin = x; if (y<_ymin) _ymin = y; if (x>_xmax) _xmax = x; if (y>_ymax) _ymax = y; } }
/** * 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; }