package ProGAL.geom3d.tessellation.BowyerWatson; import java.util.Collection; import java.util.LinkedList; import java.util.List; import java.util.Queue; import ProGAL.geom3d.PointWeighted; import ProGAL.math.Randomization; import java.util.ArrayList; public class RegularTessellation { private final Tetr bigTetr; private final LinkedList tetras = new LinkedList(); private final LinkedList points = new LinkedList(); private int lastSize = 1; private final Queue lastQueue = new LinkedList(); public static void main(String[] args){ Tetr t = new Tetr( new PointWeighted(9.80,9.19,-4.53, 0), new PointWeighted(8.73,9.54,-0.53, 0), new PointWeighted(9.44,9.78, 5.35, 0), new PointWeighted(9.97,8.47, 2.45, 0)); Randomization.seed(0); int insertedPoints = 1000000; LinkedList points= new LinkedList(); for(int i=0;i points){ this(); int c=0; for(PointWeighted pw: points) { insertPoint(pw); if(++c%10000==0){ System.out.println(c); } } } public void insertPoint(PointWeighted p){ Tetr tet = walk(p); LinkedList star = new LinkedList();//TODO: Replace with HashSet for faster contains method collectStar(p, tet, star); if ( star.size()==0 ) { throw new IllegalArgumentException("point fails because it is not within the circumsphere of tet"); } LinkedList newStar = new LinkedList(); //Create new tets for(Tetr t: star){ for(int i=0;i<4;i++){ if(t.neighbors[i]==null || !star.contains(t.neighbors[i])) { Tetr newTet = new Tetr(p, t.corners[(i+1)&3], t.corners[(i+2)&3], t.corners[(i+3)&3]); newTet.neighbors[0] = t.neighbors[i]; if(t.neighbors[i]!=null) { oneConnect(t.neighbors[i],newTet); } newStar.add(newTet); } } } //Connect tets for(Tetr t1: newStar){ for(Tetr t2: newStar){ if(t1==t2) break; connect(t1,t2); } } points.add(p); lastQueue.add(newStar.get(0)); lastSize = Math.max(1,(int)Math.pow(points.size(), 0.25)); while(lastQueue.size()>lastSize) lastQueue.poll(); } private final static int[] shared1 = new int[3]; private final static int[] shared2 = new int[3]; /** Assumes that t1.corner[0]==t2.corner[0] */ private static void connect(Tetr t1, Tetr t2){ int s = 1; shared1[0] = 0; shared2[0] = 0; for(int i=1;i<4;i++){ int partner = -1; for(int c=1;c<4;c++) if(t2.corners[c]==t1.corners[i]) {partner=c; break;} if(partner>0) { shared1[s]=i; shared2[s]=partner; s++; if(s==3 || (i>s+1)) break; } } if(s==3) { t1.neighbors[excluded(shared1)] = t2; t2.neighbors[excluded(shared2)] = t1; } } /** arr is assumed to hold three distinct values between 0 and 3. This method returns * the value not present in the array. */ private static int excluded(int[] arr){ search: for(int i=1;i<4;i++){ for(int v: arr) if(v==i) continue search; return i; } return -1; } /** Only connects t1 to t2 and assumes that t2.corners[0] is not on the shared face. */ private static void oneConnect(Tetr t1, Tetr t2){ for(int i=0;i<4;i++){ int idx = t2.cornerIdx(t1.corners[i]); if(idx<0) { t1.neighbors[i] = t2; return; } } } private void collectStar(PointWeighted p, Tetr t, Collection star){ // System.out.printf("collectStar(%s, %s ...)\n",p,t); if(regular(t.corners[0], t.corners[1], t.corners[2], t.corners[3], p)>0) { star.add(t); if(t.neighbors[0]!=null && !star.contains(t.neighbors[0])) collectStar(p, t.neighbors[0], star); if(t.neighbors[1]!=null && !star.contains(t.neighbors[1])) collectStar(p, t.neighbors[1], star); if(t.neighbors[2]!=null && !star.contains(t.neighbors[2])) collectStar(p, t.neighbors[2], star); if(t.neighbors[3]!=null && !star.contains(t.neighbors[3])) collectStar(p, t.neighbors[3], star); } } public Tetr walk(PointWeighted p){ Tetr t = bigTetr; double minDistSq = Double.POSITIVE_INFINITY; for(Tetr last: lastQueue){ double dSq = last.corners[1].distanceSquared(p); if(dSq1000 ) { // for ( int i=0; i