Loading src/main/java/Conflict.java 0 → 100644 +194 −0 Original line number Original line Diff line number Diff line /** ** ** Conflict - Represent a "conflit" between connected supertiles ** ** Copyright (C) 2017 Elphel, Inc. ** ** -----------------------------------------------------------------------------** ** ** Conflict.java is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 3 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program. If not, see <http://www.gnu.org/licenses/>. ** -----------------------------------------------------------------------------** ** */ public class Conflict{ int start_layer; int end_layer; boolean [] start_dirs = new boolean[24]; // 0 ... 7 - ortho-diagonal-ortho // 0 ... 3 from start_layer to end_layer: 0 - start_layer->N->SE->W->end_layer, 1 - start_layer->E->SW->N->end_layer, ... // 4 ... 7 from end_layer to start_layer: 4 - end_layer->N->SE->W->start_layer, 7 - end_layer->E->SW->N->start_layer, ... // 8 ... 15 - ortho-ortho-diagonal (turn right) // 8 ... 11 : 8 - start_layer->N->E->SW->end_layer, 9 - start_layer->E->S->NW->end_layer, ... // 12 ... 15 : 12 - end_layer->N->E->SW->start_layer, 13 - end_layer->E->S->NW->start_layer, ... // 16 ... 23 - ortho-ortho-diagonal (turn left) // 16 ... 19 : 16 - start_layer->N->W->SE->end_layer, 17 - start_layer->E->N->SW->end_layer, ... // 20 ... 23 : 20 - end_layer->N->W->SE->start_layer, 21 - end_layer->E->N->SW->start_layer, ... Conflict(int start_layer, int end_layer, int start_dir) // for ortho-diag-ortho { if (end_layer > start_layer) { this.start_layer = start_layer; this.end_layer = end_layer; this.start_dirs[start_dir] = true; } else { this.start_layer = end_layer; this.end_layer = start_layer; this.start_dirs[start_dir + 4] = true; } } Conflict(int start_layer, int end_layer, int start_dir, boolean right) // for ortho-ortho-diag { if (end_layer > start_layer) { this.start_layer = start_layer; this.end_layer = end_layer; this.start_dirs[(right? 8 : 12) + start_dir] = true; } else { this.start_layer = end_layer; this.end_layer = start_layer; this.start_dirs[(right? 16 : 20) + start_dir] = true; } } Conflict(int [] arr) { this.start_layer = arr[0]; this.end_layer = arr[1]; for (int i = 0; i < start_dirs.length; i++){ start_dirs[i] = (arr[2] & (1 << i)) != 0; } } Conflict(int bits) { this.start_layer = -1; this.end_layer = -1; for (int i = 0; i < start_dirs.length; i++){ start_dirs[i] = (bits & (1 << i)) != 0; } } boolean combine (Conflict other_conflict) { if ((other_conflict.start_layer == this.start_layer) && (other_conflict.end_layer == this.end_layer)) { for (int i = 0; i < start_dirs.length; i++) start_dirs[i] |= other_conflict.start_dirs[i]; return true; } return false; } int getStartLayer(){ return start_layer; } int getEndLayer(){ return end_layer; } int getDirBits(){ int dirs_bits = 0; for (int i = 0; i < start_dirs.length; i++){ if (start_dirs[i]) dirs_bits |= (1 << i); } return dirs_bits; } int getDirBitsOrthoDiagOrtho(){ int dirs_bits = 0; for (int i = 0; i < 8; i++){ if (start_dirs[i]) dirs_bits |= (1 << i); } return dirs_bits; } int getDirBitsOrthoOrthoDiag(boolean right){ int dirs_bits = 0; if (right) { for (int i = 0; i < 8; i++){ if (start_dirs[i]) dirs_bits |= (1 << (i + 8)); } } else { for (int i = 0; i < 8; i++){ if (start_dirs[i]) dirs_bits |= (1 << (i + 16)); } } return dirs_bits; } int [] toArray() { int dirs_bits = 0; for (int i = 0; i < start_dirs.length; i++){ if (start_dirs[i]) dirs_bits |= (1 << i); } int [] rslt = {start_layer, end_layer, dirs_bits}; return rslt; } int getNumConflicts(){ int numbits = 0; for (int i = 0; i < start_dirs.length; i++){ if (start_dirs[i]) numbits++; } return numbits; } int getNumOrthoDiagOrthoConflicts(){ int numbits = 0; for (int i = 0; i < 8; i++){ if (start_dirs[i]) numbits++; } return numbits; } int getNumOrthoOrthoDiagConflicts(){ int numbits = 0; for (int i = 8; i < 24; i++){ if (start_dirs[i]) numbits++; } return numbits; } int getIncompatibleOrthoDiagOrthoConflicts(){ int num_incompat = 0; for (int i = 0; i < 8; i++){ if (start_dirs[i]) { int [] incomp_bits= { i ^ 4, (i & 4) | ((i + 1) & 3), (i & 4) | ((i - 1) & 3)}; for (int j = 1; j < 3; j++){ // skip dual triangles int i1 = incomp_bits[j]; if (start_dirs[i1]){ num_incompat ++; } } } } return num_incompat / 2; } public int getDualTriOrthoDiagOrthoConflicts() { int num_dual = 0; for (int i = 0; i < 4; i++) if (start_dirs[i] && start_dirs[i + 4]) num_dual++; return num_dual; } } src/main/java/Conflicts.java 0 → 100644 +394 −0 Original line number Original line Diff line number Diff line /** ** ** Conflicts - Represent "conflicts" (instances of Conflict) between connected supertiles ** ** Copyright (C) 2017 Elphel, Inc. ** ** -----------------------------------------------------------------------------** ** ** Conflicts.java is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 3 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program. If not, see <http://www.gnu.org/licenses/>. ** -----------------------------------------------------------------------------** ** */ import java.util.ArrayList; import java.util.HashMap; import java.util.concurrent.atomic.AtomicInteger; public class Conflicts { private int [] num_ortho_diag_ortho = new int [8]; private int [] num_ortho_ortho_diag = new int [16]; private int [] num_all_conflicts = new int [24]; private int num_ortho_incompat = 0; private int num_ortho_dual = 0; private int num_conflicts; private SuperTiles st = null; public Conflicts( SuperTiles st){ this.st = st; } public Conflicts( int [][][] conflicts, SuperTiles st, int debugLevel) { this.st = st; addConflicts( conflicts, debugLevel); } public Conflicts( int [][][] conflicts, SuperTiles st) { this.st = st; addConflicts( conflicts, -1); } public Conflicts( Conflict [][] conflicts, SuperTiles st, int debugLevel) { this.st = st; addConflicts( conflicts, debugLevel); } public Conflicts( Conflict [][] conflicts, SuperTiles st) { this.st = st; addConflicts( conflicts, -1); } public void addConflicts(Conflicts conflicts){ addsubConflicts(conflicts, false); } public void subConflicts(Conflicts conflicts){ addsubConflicts(conflicts, true); } public void addsubConflicts(Conflicts conflicts, boolean sub) { int s = sub? -1: 1; for (int i = 0; i < num_ortho_diag_ortho.length; i++) num_ortho_diag_ortho[i] += s * conflicts.num_ortho_diag_ortho[i]; for (int i = 0; i < num_ortho_ortho_diag.length; i++) num_ortho_ortho_diag[i] += s * conflicts.num_ortho_ortho_diag[i]; for (int i = 0; i < num_all_conflicts.length; i++) num_all_conflicts[i] += s * conflicts.num_all_conflicts[i]; num_ortho_incompat += s * conflicts.num_ortho_incompat; num_ortho_dual += s * conflicts.num_ortho_dual; num_conflicts += s * conflicts.num_conflicts; } public int addConflicts( int [][][] conflicts, int debugLevel) { for (int nsTile = 0; nsTile < conflicts.length; nsTile++) if (conflicts[nsTile] != null){ for (int nc = 0; nc < conflicts[nsTile].length; nc++){ Conflict conf = new Conflict(conflicts[nsTile][nc]); if (conf.getNumOrthoDiagOrthoConflicts() > 0) num_ortho_diag_ortho[conf.getNumOrthoDiagOrthoConflicts() - 1]++; if (conf.getNumOrthoOrthoDiagConflicts() > 0) num_ortho_ortho_diag[conf.getNumOrthoOrthoDiagConflicts() - 1]++; if (conf.getNumConflicts() > 0) num_all_conflicts[conf.getNumConflicts() - 1]++; num_ortho_incompat += conf.getIncompatibleOrthoDiagOrthoConflicts(); num_ortho_dual += conf.getDualTriOrthoDiagOrthoConflicts(); num_conflicts += conf.getNumConflicts(); if (debugLevel > 0){ printConflict("addConflicts() nsTile = "+nsTile, conf); } } } return num_conflicts; } public int addConflicts( Conflict [][] conflicts, int debugLevel) { for (int nsTile = 0; nsTile < conflicts.length; nsTile++) if (conflicts[nsTile] != null){ for (int nc = 0; nc < conflicts[nsTile].length; nc++){ Conflict conf = conflicts[nsTile][nc]; if (conf.getNumOrthoDiagOrthoConflicts() > 0) num_ortho_diag_ortho[conf.getNumOrthoDiagOrthoConflicts() - 1]++; if (conf.getNumOrthoOrthoDiagConflicts() > 0) num_ortho_ortho_diag[conf.getNumOrthoOrthoDiagConflicts() - 1]++; if (conf.getNumConflicts() > 0) num_all_conflicts[conf.getNumConflicts() - 1]++; num_ortho_incompat += conf.getIncompatibleOrthoDiagOrthoConflicts(); num_ortho_dual += conf.getDualTriOrthoDiagOrthoConflicts(); num_conflicts += conf.getNumConflicts(); if (debugLevel > 0){ printConflict("addConflicts() nsTile = "+nsTile, conf); } } } return num_conflicts; } public int [] getNumOrthoDiagOrtho(){ return num_ortho_diag_ortho; } public int [] getNumOrthoOrthoDiag(){ return num_ortho_ortho_diag; } public int [] getNumAllConflicts(){ return num_all_conflicts; } public int getNumOrthoIncompat(){ return num_ortho_incompat; } public int getNumOrthoDual(){ return num_ortho_dual; } public int getNumConflicts(){ return num_conflicts; } public void printConflict(String prefix, Conflict conf) { System.out.println(prefix+ " nl1 = "+ conf.getStartLayer()+ " nl2 = "+ conf.getEndLayer()+ " all = "+ conf.getNumConflicts() + " ("+String.format("%06x", conf.getDirBits())+")" + " odo = "+ conf.getNumOrthoDiagOrthoConflicts() + " ood = "+ conf.getNumOrthoOrthoDiagConflicts() + " number of odo incompatible triangles = "+ conf.getIncompatibleOrthoDiagOrthoConflicts() + " number of odo dual triangles = "+conf.getDualTriOrthoDiagOrthoConflicts()); } public int numBetterWorse( boolean better, boolean use_all, boolean use_odo, boolean use_ood) { int num = 0; if (use_all) { for (int i = 0; i < num_all_conflicts.length; i++){ if (better?(num_all_conflicts[i] < 0):(num_all_conflicts[i] > 0)) num++; } } if (use_odo) { for (int i = 0; i < num_ortho_diag_ortho.length; i++){ if (better?(num_ortho_diag_ortho[i] < 0):(num_ortho_diag_ortho[i] > 0)) num++; } if (better? (num_ortho_incompat < 0) : (num_ortho_incompat > 0)) num++; if (better? (num_ortho_dual < 0) : (num_ortho_dual > 0)) num++; } return num; } public void printConflictSummary( String prefix, boolean use_all, boolean use_odo, boolean use_ood) { System.out.print(prefix); if (use_all) { for (int i = 0; i < num_all_conflicts.length; i++){ if (num_all_conflicts[i] != 0) System.out.print(" all_"+(i + 1)+": "+num_all_conflicts[i]); } } if (use_odo) { for (int i = 0; i < num_ortho_diag_ortho.length; i++){ if (num_ortho_diag_ortho[i] != 0) System.out.print(" odo_"+(i + 1)+": "+num_ortho_diag_ortho[i]); } if (num_ortho_incompat != 0) { System.out.print(" number of incompatible odo triangles = " + num_ortho_incompat); } if (num_ortho_dual != 0) { System.out.print(" number of dual odo triangles = " + num_ortho_dual); } } if (use_ood) { for (int i = 0; i < num_ortho_ortho_diag.length; i++){ if (num_ortho_ortho_diag[i] != 0) System.out.print(" ood_"+(i + 1)+": "+num_ortho_ortho_diag[i]); } } System.out.println(); } // TilePlanes.PlaneData [][] planes = null; /** * Find "triangular" conflicts after running selectNeighborPlanesMutual. * Such conflicts happen is when starting N (or other ortho direction) from some node, * then turning 135 degrees right, and then 135 right again it will get to the different * layer than started (and all 3 connections exist. * @param debugLevel * @return 3-d array, first index - tile number, 2-nd - tile conflict number. Each conflict * is stored as {start layer, end layer, bitmask of start directions} (+1 - N, +2 - E, +4 - S, +8 - W) */ public int [][][] detectTriangularConflicts( final int debugLevel) { final int tilesX = st.getTileProcessor().getTilesX(); final int tilesY = st.getTileProcessor().getTilesY(); final int superTileSize = st.getTileProcessor().getSuperTileSize(); final int stilesX = (tilesX + superTileSize -1)/superTileSize; final int stilesY = (tilesY + superTileSize -1)/superTileSize; final int nStiles = stilesX * stilesY; final int [][][] conflicts = new int [st.getPlanes().length][][]; final TileSurface.TileNeibs tnSurface = st.getTileSurface().new TileNeibs(stilesX, stilesY); final Thread[] threads = ImageDtt.newThreadArray(st.getTileProcessor().threadsMax); final AtomicInteger ai = new AtomicInteger(0); for (int ithread = 0; ithread < threads.length; ithread++) { threads[ithread] = new Thread() { public void run() { for (int nsTile0 = ai.getAndIncrement(); nsTile0 < nStiles; nsTile0 = ai.getAndIncrement()) { if ( st.getPlanes()[nsTile0] != null) { conflicts[nsTile0] = detectTriangularTileConflicts( nsTile0, null, // HashMap<Integer,Integer> replacement_tiles, // null, // int [][][] replacement_neibs, tnSurface); } } } }; } ImageDtt.startAndJoin(threads); if (debugLevel > -1){ addConflicts( conflicts, debugLevel); printConflictSummary("Detected conflicts:",true,false,false); printConflictSummary("Detected ortho-diagonal-ortho conflicts:",false, true, false); printConflictSummary("Detected ortho-ortho-diagonal conflicts:",false, false, true); } return conflicts; } public int [][] detectTriangularTileConflicts( int nsTile0, HashMap<Integer,Integer> replacement_tiles, // int [][][] replacement_neibs, TileSurface.TileNeibs tnSurface) { TilePlanes.PlaneData [][] planes = st.getPlanes(); ArrayList<Conflict> conflicts_list= new ArrayList<Conflict>(); if ( planes[nsTile0] != null) { Integer repl_indx = (replacement_tiles != null) ? replacement_tiles.get(new Integer(nsTile0)): null; for (int np0 = 0; np0 < planes[nsTile0].length; np0++){ if (planes[nsTile0][np0] != null) { int [] neibs0 = ((repl_indx == null) || (replacement_neibs[repl_indx][np0] == null)) ? planes[nsTile0][np0].getNeibBest() : replacement_neibs[repl_indx][np0]; for (int dir = 0; dir < 8; dir +=2){ int np1; np1= neibs0[dir]; // planes[nsTile0][np0].getNeibBest(dir); if (np1 >=0) { int nsTile1 = tnSurface.getNeibIndex(nsTile0, dir); if (nsTile1 >= 0){ Integer repl_indx1 = (replacement_tiles != null) ? replacement_tiles.get(new Integer(nsTile1)): null; int [] neibs1 = (((repl_indx1 == null) || (replacement_neibs[repl_indx1][np1] == null) )? planes[nsTile1][np1].getNeibBest() : replacement_neibs[repl_indx1][np1]); int dir1 = (dir + 3) % 8; int np2 = neibs1[dir1]; // planes[nsTile1][np1].getNeibBest(dir1); if (np2 >= 0){ int nsTile2 = tnSurface.getNeibIndex(nsTile1, dir1); if (nsTile2 >= 0){ Integer repl_indx2 = (replacement_tiles != null) ? replacement_tiles.get(new Integer(nsTile2)): null; int [] neibs2 = (((repl_indx2 == null) || (replacement_neibs[repl_indx2][np2] == null)) ? planes[nsTile2][np2].getNeibBest() : replacement_neibs[repl_indx2][np2]); int dir2 = (dir1 + 3) % 8; int np3 = neibs2[dir2]; // planes[nsTile2][np2].getNeibBest(dir2); if ((np3 >= 0) && (np3 != np0)){ Conflict conflict = new Conflict(np0, np3, dir/2); label_apply: { for (Conflict conf_old:conflicts_list){ if (conf_old.combine(conflict)){ break label_apply; } } conflicts_list.add(conflict); } } } } // ortho-ortho-diagonal, right hand from np0 dir1 = (dir + 2) % 8; np2 = neibs1[dir1]; // planes[nsTile1][np1].getNeibBest(dir1); if (np2 >= 0){ int nsTile2 = tnSurface.getNeibIndex(nsTile1, dir1); if (nsTile2 >= 0){ Integer repl_indx2 = (replacement_tiles != null) ? replacement_tiles.get(new Integer(nsTile2)): null; int [] neibs2 = (((repl_indx2 == null) || (replacement_neibs[repl_indx2][np2] == null)) ? planes[nsTile2][np2].getNeibBest() : replacement_neibs[repl_indx2][np2]); int dir2 = (dir1 + 3) % 8; int np3 = neibs2[dir2]; // planes[nsTile2][np2].getNeibBest(dir2); if ((np3 >= 0) && (np3 != np0)){ Conflict conflict = new Conflict(np0, np3, dir/2, true); // ood, right label_apply: { for (Conflict conf_old:conflicts_list){ if (conf_old.combine(conflict)){ break label_apply; } } conflicts_list.add(conflict); } } } } // ortho-ortho-diagonal, left hand from np0 dir1 = (dir + 6) % 8; np2 = neibs1[dir1]; // planes[nsTile1][np1].getNeibBest(dir1); if (np2 >= 0){ int nsTile2 = tnSurface.getNeibIndex(nsTile1, dir1); if (nsTile2 >= 0){ Integer repl_indx2 = (replacement_tiles != null) ? replacement_tiles.get(new Integer(nsTile2)): null; int [] neibs2 = (((repl_indx2 == null) || (replacement_neibs[repl_indx2][np2] == null)) ? planes[nsTile2][np2].getNeibBest() : replacement_neibs[repl_indx2][np2]); int dir2 = (dir1 + 5) % 8; int np3 = neibs2[dir2]; // planes[nsTile2][np2].getNeibBest(dir2); if ((np3 >= 0) && (np3 != np0)){ Conflict conflict = new Conflict(np0, np3, dir/2, true); // ood, right label_apply: { for (Conflict conf_old:conflicts_list){ if (conf_old.combine(conflict)){ break label_apply; } } conflicts_list.add(conflict); } } } } } } } } } } if(conflicts_list.isEmpty()){ return null; } int [][] conflicts = new int [conflicts_list.size()][]; int indx=0; for (Conflict conflict:conflicts_list){ conflicts[indx++] = conflict.toArray(); } return conflicts; } } Loading
src/main/java/Conflict.java 0 → 100644 +194 −0 Original line number Original line Diff line number Diff line /** ** ** Conflict - Represent a "conflit" between connected supertiles ** ** Copyright (C) 2017 Elphel, Inc. ** ** -----------------------------------------------------------------------------** ** ** Conflict.java is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 3 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program. If not, see <http://www.gnu.org/licenses/>. ** -----------------------------------------------------------------------------** ** */ public class Conflict{ int start_layer; int end_layer; boolean [] start_dirs = new boolean[24]; // 0 ... 7 - ortho-diagonal-ortho // 0 ... 3 from start_layer to end_layer: 0 - start_layer->N->SE->W->end_layer, 1 - start_layer->E->SW->N->end_layer, ... // 4 ... 7 from end_layer to start_layer: 4 - end_layer->N->SE->W->start_layer, 7 - end_layer->E->SW->N->start_layer, ... // 8 ... 15 - ortho-ortho-diagonal (turn right) // 8 ... 11 : 8 - start_layer->N->E->SW->end_layer, 9 - start_layer->E->S->NW->end_layer, ... // 12 ... 15 : 12 - end_layer->N->E->SW->start_layer, 13 - end_layer->E->S->NW->start_layer, ... // 16 ... 23 - ortho-ortho-diagonal (turn left) // 16 ... 19 : 16 - start_layer->N->W->SE->end_layer, 17 - start_layer->E->N->SW->end_layer, ... // 20 ... 23 : 20 - end_layer->N->W->SE->start_layer, 21 - end_layer->E->N->SW->start_layer, ... Conflict(int start_layer, int end_layer, int start_dir) // for ortho-diag-ortho { if (end_layer > start_layer) { this.start_layer = start_layer; this.end_layer = end_layer; this.start_dirs[start_dir] = true; } else { this.start_layer = end_layer; this.end_layer = start_layer; this.start_dirs[start_dir + 4] = true; } } Conflict(int start_layer, int end_layer, int start_dir, boolean right) // for ortho-ortho-diag { if (end_layer > start_layer) { this.start_layer = start_layer; this.end_layer = end_layer; this.start_dirs[(right? 8 : 12) + start_dir] = true; } else { this.start_layer = end_layer; this.end_layer = start_layer; this.start_dirs[(right? 16 : 20) + start_dir] = true; } } Conflict(int [] arr) { this.start_layer = arr[0]; this.end_layer = arr[1]; for (int i = 0; i < start_dirs.length; i++){ start_dirs[i] = (arr[2] & (1 << i)) != 0; } } Conflict(int bits) { this.start_layer = -1; this.end_layer = -1; for (int i = 0; i < start_dirs.length; i++){ start_dirs[i] = (bits & (1 << i)) != 0; } } boolean combine (Conflict other_conflict) { if ((other_conflict.start_layer == this.start_layer) && (other_conflict.end_layer == this.end_layer)) { for (int i = 0; i < start_dirs.length; i++) start_dirs[i] |= other_conflict.start_dirs[i]; return true; } return false; } int getStartLayer(){ return start_layer; } int getEndLayer(){ return end_layer; } int getDirBits(){ int dirs_bits = 0; for (int i = 0; i < start_dirs.length; i++){ if (start_dirs[i]) dirs_bits |= (1 << i); } return dirs_bits; } int getDirBitsOrthoDiagOrtho(){ int dirs_bits = 0; for (int i = 0; i < 8; i++){ if (start_dirs[i]) dirs_bits |= (1 << i); } return dirs_bits; } int getDirBitsOrthoOrthoDiag(boolean right){ int dirs_bits = 0; if (right) { for (int i = 0; i < 8; i++){ if (start_dirs[i]) dirs_bits |= (1 << (i + 8)); } } else { for (int i = 0; i < 8; i++){ if (start_dirs[i]) dirs_bits |= (1 << (i + 16)); } } return dirs_bits; } int [] toArray() { int dirs_bits = 0; for (int i = 0; i < start_dirs.length; i++){ if (start_dirs[i]) dirs_bits |= (1 << i); } int [] rslt = {start_layer, end_layer, dirs_bits}; return rslt; } int getNumConflicts(){ int numbits = 0; for (int i = 0; i < start_dirs.length; i++){ if (start_dirs[i]) numbits++; } return numbits; } int getNumOrthoDiagOrthoConflicts(){ int numbits = 0; for (int i = 0; i < 8; i++){ if (start_dirs[i]) numbits++; } return numbits; } int getNumOrthoOrthoDiagConflicts(){ int numbits = 0; for (int i = 8; i < 24; i++){ if (start_dirs[i]) numbits++; } return numbits; } int getIncompatibleOrthoDiagOrthoConflicts(){ int num_incompat = 0; for (int i = 0; i < 8; i++){ if (start_dirs[i]) { int [] incomp_bits= { i ^ 4, (i & 4) | ((i + 1) & 3), (i & 4) | ((i - 1) & 3)}; for (int j = 1; j < 3; j++){ // skip dual triangles int i1 = incomp_bits[j]; if (start_dirs[i1]){ num_incompat ++; } } } } return num_incompat / 2; } public int getDualTriOrthoDiagOrthoConflicts() { int num_dual = 0; for (int i = 0; i < 4; i++) if (start_dirs[i] && start_dirs[i + 4]) num_dual++; return num_dual; } }
src/main/java/Conflicts.java 0 → 100644 +394 −0 Original line number Original line Diff line number Diff line /** ** ** Conflicts - Represent "conflicts" (instances of Conflict) between connected supertiles ** ** Copyright (C) 2017 Elphel, Inc. ** ** -----------------------------------------------------------------------------** ** ** Conflicts.java is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 3 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program. If not, see <http://www.gnu.org/licenses/>. ** -----------------------------------------------------------------------------** ** */ import java.util.ArrayList; import java.util.HashMap; import java.util.concurrent.atomic.AtomicInteger; public class Conflicts { private int [] num_ortho_diag_ortho = new int [8]; private int [] num_ortho_ortho_diag = new int [16]; private int [] num_all_conflicts = new int [24]; private int num_ortho_incompat = 0; private int num_ortho_dual = 0; private int num_conflicts; private SuperTiles st = null; public Conflicts( SuperTiles st){ this.st = st; } public Conflicts( int [][][] conflicts, SuperTiles st, int debugLevel) { this.st = st; addConflicts( conflicts, debugLevel); } public Conflicts( int [][][] conflicts, SuperTiles st) { this.st = st; addConflicts( conflicts, -1); } public Conflicts( Conflict [][] conflicts, SuperTiles st, int debugLevel) { this.st = st; addConflicts( conflicts, debugLevel); } public Conflicts( Conflict [][] conflicts, SuperTiles st) { this.st = st; addConflicts( conflicts, -1); } public void addConflicts(Conflicts conflicts){ addsubConflicts(conflicts, false); } public void subConflicts(Conflicts conflicts){ addsubConflicts(conflicts, true); } public void addsubConflicts(Conflicts conflicts, boolean sub) { int s = sub? -1: 1; for (int i = 0; i < num_ortho_diag_ortho.length; i++) num_ortho_diag_ortho[i] += s * conflicts.num_ortho_diag_ortho[i]; for (int i = 0; i < num_ortho_ortho_diag.length; i++) num_ortho_ortho_diag[i] += s * conflicts.num_ortho_ortho_diag[i]; for (int i = 0; i < num_all_conflicts.length; i++) num_all_conflicts[i] += s * conflicts.num_all_conflicts[i]; num_ortho_incompat += s * conflicts.num_ortho_incompat; num_ortho_dual += s * conflicts.num_ortho_dual; num_conflicts += s * conflicts.num_conflicts; } public int addConflicts( int [][][] conflicts, int debugLevel) { for (int nsTile = 0; nsTile < conflicts.length; nsTile++) if (conflicts[nsTile] != null){ for (int nc = 0; nc < conflicts[nsTile].length; nc++){ Conflict conf = new Conflict(conflicts[nsTile][nc]); if (conf.getNumOrthoDiagOrthoConflicts() > 0) num_ortho_diag_ortho[conf.getNumOrthoDiagOrthoConflicts() - 1]++; if (conf.getNumOrthoOrthoDiagConflicts() > 0) num_ortho_ortho_diag[conf.getNumOrthoOrthoDiagConflicts() - 1]++; if (conf.getNumConflicts() > 0) num_all_conflicts[conf.getNumConflicts() - 1]++; num_ortho_incompat += conf.getIncompatibleOrthoDiagOrthoConflicts(); num_ortho_dual += conf.getDualTriOrthoDiagOrthoConflicts(); num_conflicts += conf.getNumConflicts(); if (debugLevel > 0){ printConflict("addConflicts() nsTile = "+nsTile, conf); } } } return num_conflicts; } public int addConflicts( Conflict [][] conflicts, int debugLevel) { for (int nsTile = 0; nsTile < conflicts.length; nsTile++) if (conflicts[nsTile] != null){ for (int nc = 0; nc < conflicts[nsTile].length; nc++){ Conflict conf = conflicts[nsTile][nc]; if (conf.getNumOrthoDiagOrthoConflicts() > 0) num_ortho_diag_ortho[conf.getNumOrthoDiagOrthoConflicts() - 1]++; if (conf.getNumOrthoOrthoDiagConflicts() > 0) num_ortho_ortho_diag[conf.getNumOrthoOrthoDiagConflicts() - 1]++; if (conf.getNumConflicts() > 0) num_all_conflicts[conf.getNumConflicts() - 1]++; num_ortho_incompat += conf.getIncompatibleOrthoDiagOrthoConflicts(); num_ortho_dual += conf.getDualTriOrthoDiagOrthoConflicts(); num_conflicts += conf.getNumConflicts(); if (debugLevel > 0){ printConflict("addConflicts() nsTile = "+nsTile, conf); } } } return num_conflicts; } public int [] getNumOrthoDiagOrtho(){ return num_ortho_diag_ortho; } public int [] getNumOrthoOrthoDiag(){ return num_ortho_ortho_diag; } public int [] getNumAllConflicts(){ return num_all_conflicts; } public int getNumOrthoIncompat(){ return num_ortho_incompat; } public int getNumOrthoDual(){ return num_ortho_dual; } public int getNumConflicts(){ return num_conflicts; } public void printConflict(String prefix, Conflict conf) { System.out.println(prefix+ " nl1 = "+ conf.getStartLayer()+ " nl2 = "+ conf.getEndLayer()+ " all = "+ conf.getNumConflicts() + " ("+String.format("%06x", conf.getDirBits())+")" + " odo = "+ conf.getNumOrthoDiagOrthoConflicts() + " ood = "+ conf.getNumOrthoOrthoDiagConflicts() + " number of odo incompatible triangles = "+ conf.getIncompatibleOrthoDiagOrthoConflicts() + " number of odo dual triangles = "+conf.getDualTriOrthoDiagOrthoConflicts()); } public int numBetterWorse( boolean better, boolean use_all, boolean use_odo, boolean use_ood) { int num = 0; if (use_all) { for (int i = 0; i < num_all_conflicts.length; i++){ if (better?(num_all_conflicts[i] < 0):(num_all_conflicts[i] > 0)) num++; } } if (use_odo) { for (int i = 0; i < num_ortho_diag_ortho.length; i++){ if (better?(num_ortho_diag_ortho[i] < 0):(num_ortho_diag_ortho[i] > 0)) num++; } if (better? (num_ortho_incompat < 0) : (num_ortho_incompat > 0)) num++; if (better? (num_ortho_dual < 0) : (num_ortho_dual > 0)) num++; } return num; } public void printConflictSummary( String prefix, boolean use_all, boolean use_odo, boolean use_ood) { System.out.print(prefix); if (use_all) { for (int i = 0; i < num_all_conflicts.length; i++){ if (num_all_conflicts[i] != 0) System.out.print(" all_"+(i + 1)+": "+num_all_conflicts[i]); } } if (use_odo) { for (int i = 0; i < num_ortho_diag_ortho.length; i++){ if (num_ortho_diag_ortho[i] != 0) System.out.print(" odo_"+(i + 1)+": "+num_ortho_diag_ortho[i]); } if (num_ortho_incompat != 0) { System.out.print(" number of incompatible odo triangles = " + num_ortho_incompat); } if (num_ortho_dual != 0) { System.out.print(" number of dual odo triangles = " + num_ortho_dual); } } if (use_ood) { for (int i = 0; i < num_ortho_ortho_diag.length; i++){ if (num_ortho_ortho_diag[i] != 0) System.out.print(" ood_"+(i + 1)+": "+num_ortho_ortho_diag[i]); } } System.out.println(); } // TilePlanes.PlaneData [][] planes = null; /** * Find "triangular" conflicts after running selectNeighborPlanesMutual. * Such conflicts happen is when starting N (or other ortho direction) from some node, * then turning 135 degrees right, and then 135 right again it will get to the different * layer than started (and all 3 connections exist. * @param debugLevel * @return 3-d array, first index - tile number, 2-nd - tile conflict number. Each conflict * is stored as {start layer, end layer, bitmask of start directions} (+1 - N, +2 - E, +4 - S, +8 - W) */ public int [][][] detectTriangularConflicts( final int debugLevel) { final int tilesX = st.getTileProcessor().getTilesX(); final int tilesY = st.getTileProcessor().getTilesY(); final int superTileSize = st.getTileProcessor().getSuperTileSize(); final int stilesX = (tilesX + superTileSize -1)/superTileSize; final int stilesY = (tilesY + superTileSize -1)/superTileSize; final int nStiles = stilesX * stilesY; final int [][][] conflicts = new int [st.getPlanes().length][][]; final TileSurface.TileNeibs tnSurface = st.getTileSurface().new TileNeibs(stilesX, stilesY); final Thread[] threads = ImageDtt.newThreadArray(st.getTileProcessor().threadsMax); final AtomicInteger ai = new AtomicInteger(0); for (int ithread = 0; ithread < threads.length; ithread++) { threads[ithread] = new Thread() { public void run() { for (int nsTile0 = ai.getAndIncrement(); nsTile0 < nStiles; nsTile0 = ai.getAndIncrement()) { if ( st.getPlanes()[nsTile0] != null) { conflicts[nsTile0] = detectTriangularTileConflicts( nsTile0, null, // HashMap<Integer,Integer> replacement_tiles, // null, // int [][][] replacement_neibs, tnSurface); } } } }; } ImageDtt.startAndJoin(threads); if (debugLevel > -1){ addConflicts( conflicts, debugLevel); printConflictSummary("Detected conflicts:",true,false,false); printConflictSummary("Detected ortho-diagonal-ortho conflicts:",false, true, false); printConflictSummary("Detected ortho-ortho-diagonal conflicts:",false, false, true); } return conflicts; } public int [][] detectTriangularTileConflicts( int nsTile0, HashMap<Integer,Integer> replacement_tiles, // int [][][] replacement_neibs, TileSurface.TileNeibs tnSurface) { TilePlanes.PlaneData [][] planes = st.getPlanes(); ArrayList<Conflict> conflicts_list= new ArrayList<Conflict>(); if ( planes[nsTile0] != null) { Integer repl_indx = (replacement_tiles != null) ? replacement_tiles.get(new Integer(nsTile0)): null; for (int np0 = 0; np0 < planes[nsTile0].length; np0++){ if (planes[nsTile0][np0] != null) { int [] neibs0 = ((repl_indx == null) || (replacement_neibs[repl_indx][np0] == null)) ? planes[nsTile0][np0].getNeibBest() : replacement_neibs[repl_indx][np0]; for (int dir = 0; dir < 8; dir +=2){ int np1; np1= neibs0[dir]; // planes[nsTile0][np0].getNeibBest(dir); if (np1 >=0) { int nsTile1 = tnSurface.getNeibIndex(nsTile0, dir); if (nsTile1 >= 0){ Integer repl_indx1 = (replacement_tiles != null) ? replacement_tiles.get(new Integer(nsTile1)): null; int [] neibs1 = (((repl_indx1 == null) || (replacement_neibs[repl_indx1][np1] == null) )? planes[nsTile1][np1].getNeibBest() : replacement_neibs[repl_indx1][np1]); int dir1 = (dir + 3) % 8; int np2 = neibs1[dir1]; // planes[nsTile1][np1].getNeibBest(dir1); if (np2 >= 0){ int nsTile2 = tnSurface.getNeibIndex(nsTile1, dir1); if (nsTile2 >= 0){ Integer repl_indx2 = (replacement_tiles != null) ? replacement_tiles.get(new Integer(nsTile2)): null; int [] neibs2 = (((repl_indx2 == null) || (replacement_neibs[repl_indx2][np2] == null)) ? planes[nsTile2][np2].getNeibBest() : replacement_neibs[repl_indx2][np2]); int dir2 = (dir1 + 3) % 8; int np3 = neibs2[dir2]; // planes[nsTile2][np2].getNeibBest(dir2); if ((np3 >= 0) && (np3 != np0)){ Conflict conflict = new Conflict(np0, np3, dir/2); label_apply: { for (Conflict conf_old:conflicts_list){ if (conf_old.combine(conflict)){ break label_apply; } } conflicts_list.add(conflict); } } } } // ortho-ortho-diagonal, right hand from np0 dir1 = (dir + 2) % 8; np2 = neibs1[dir1]; // planes[nsTile1][np1].getNeibBest(dir1); if (np2 >= 0){ int nsTile2 = tnSurface.getNeibIndex(nsTile1, dir1); if (nsTile2 >= 0){ Integer repl_indx2 = (replacement_tiles != null) ? replacement_tiles.get(new Integer(nsTile2)): null; int [] neibs2 = (((repl_indx2 == null) || (replacement_neibs[repl_indx2][np2] == null)) ? planes[nsTile2][np2].getNeibBest() : replacement_neibs[repl_indx2][np2]); int dir2 = (dir1 + 3) % 8; int np3 = neibs2[dir2]; // planes[nsTile2][np2].getNeibBest(dir2); if ((np3 >= 0) && (np3 != np0)){ Conflict conflict = new Conflict(np0, np3, dir/2, true); // ood, right label_apply: { for (Conflict conf_old:conflicts_list){ if (conf_old.combine(conflict)){ break label_apply; } } conflicts_list.add(conflict); } } } } // ortho-ortho-diagonal, left hand from np0 dir1 = (dir + 6) % 8; np2 = neibs1[dir1]; // planes[nsTile1][np1].getNeibBest(dir1); if (np2 >= 0){ int nsTile2 = tnSurface.getNeibIndex(nsTile1, dir1); if (nsTile2 >= 0){ Integer repl_indx2 = (replacement_tiles != null) ? replacement_tiles.get(new Integer(nsTile2)): null; int [] neibs2 = (((repl_indx2 == null) || (replacement_neibs[repl_indx2][np2] == null)) ? planes[nsTile2][np2].getNeibBest() : replacement_neibs[repl_indx2][np2]); int dir2 = (dir1 + 5) % 8; int np3 = neibs2[dir2]; // planes[nsTile2][np2].getNeibBest(dir2); if ((np3 >= 0) && (np3 != np0)){ Conflict conflict = new Conflict(np0, np3, dir/2, true); // ood, right label_apply: { for (Conflict conf_old:conflicts_list){ if (conf_old.combine(conflict)){ break label_apply; } } conflicts_list.add(conflict); } } } } } } } } } } if(conflicts_list.isEmpty()){ return null; } int [][] conflicts = new int [conflicts_list.size()][]; int indx=0; for (Conflict conflict:conflicts_list){ conflicts[indx++] = conflict.toArray(); } return conflicts; } }