Commit 18261553 authored by Andrey Filippov's avatar Andrey Filippov

trying another way to resolve conflicts/ improve supertile connections

parent 1ca1c6d0
import java.awt.Point;
import java.util.HashMap;
import java.util.HashSet;
/** /**
** **
** ConnectionCosts - calculate and incrementally update cost of supertile connections ** ConnectionCosts - calculate and incrementally update cost of supertile connections
...@@ -25,6 +21,9 @@ import java.util.HashSet; ...@@ -25,6 +21,9 @@ import java.util.HashSet;
** -----------------------------------------------------------------------------** ** -----------------------------------------------------------------------------**
** **
*/ */
import java.awt.Point;
import java.util.HashMap;
import java.util.HashSet;
public class ConnectionCosts { public class ConnectionCosts {
TilePlanes.PlaneData [][] planes = null; TilePlanes.PlaneData [][] planes = null;
......
...@@ -2175,7 +2175,12 @@ public class EyesisCorrectionParameters { ...@@ -2175,7 +2175,12 @@ public class EyesisCorrectionParameters {
public double plMaxWorldSin2 = 0.1; // Maximal sine squared of the world angle between planes to merge. Set to >= 1.0 to disable public double plMaxWorldSin2 = 0.1; // Maximal sine squared of the world angle between planes to merge. Set to >= 1.0 to disable
public double plWeakWorsening = 1.0; // Relax merge requirements for weaker planes public double plWeakWorsening = 1.0; // Relax merge requirements for weaker planes
public int plStarSteps = 1; // How far to look around when calculationg connection cost public boolean plConflDualTri = false; // Resolve dual triangles conflict (odoodo)
public boolean plConflMulti = false; // Resolve multiple odo triangles conflicts
public boolean plConflDiag = false; // Resolve diagonal (ood) conflicts
public boolean plConflStar = true; // Resolve all conflicts around a supertile
public int plStarSteps = 2; // How far to look around when calculationg connection cost
public double plStarOrtho = 0.5; // When calculating cost for the connections scale 4 ortho neighbors public double plStarOrtho = 0.5; // When calculating cost for the connections scale 4 ortho neighbors
public double plStarDiag = 0.25; // When calculating cost for the connections scale 4 diagonal neighbors public double plStarDiag = 0.25; // When calculating cost for the connections scale 4 diagonal neighbors
public double plStarPwr = 0.5; // Divide cost by number of connections to this power public double plStarPwr = 0.5; // Divide cost by number of connections to this power
...@@ -2529,6 +2534,10 @@ public class EyesisCorrectionParameters { ...@@ -2529,6 +2534,10 @@ public class EyesisCorrectionParameters {
properties.setProperty(prefix+"plMaxWorldSin2", this.plMaxWorldSin2 +""); properties.setProperty(prefix+"plMaxWorldSin2", this.plMaxWorldSin2 +"");
properties.setProperty(prefix+"plWeakWorsening", this.plWeakWorsening +""); properties.setProperty(prefix+"plWeakWorsening", this.plWeakWorsening +"");
properties.setProperty(prefix+"plConflDualTri", this.plConflDualTri+"");
properties.setProperty(prefix+"plConflMulti", this.plConflMulti+"");
properties.setProperty(prefix+"plConflDiag", this.plConflDiag+"");
properties.setProperty(prefix+"plConflStar", this.plConflStar+"");
properties.setProperty(prefix+"plStarSteps", this.plStarSteps+""); properties.setProperty(prefix+"plStarSteps", this.plStarSteps+"");
properties.setProperty(prefix+"plStarOrtho", this.plStarOrtho +""); properties.setProperty(prefix+"plStarOrtho", this.plStarOrtho +"");
properties.setProperty(prefix+"plStarDiag", this.plStarDiag +""); properties.setProperty(prefix+"plStarDiag", this.plStarDiag +"");
...@@ -2863,6 +2872,10 @@ public class EyesisCorrectionParameters { ...@@ -2863,6 +2872,10 @@ public class EyesisCorrectionParameters {
if (properties.getProperty(prefix+"plMaxWorldSin2")!=null) this.plMaxWorldSin2=Double.parseDouble(properties.getProperty(prefix+"plMaxWorldSin2")); if (properties.getProperty(prefix+"plMaxWorldSin2")!=null) this.plMaxWorldSin2=Double.parseDouble(properties.getProperty(prefix+"plMaxWorldSin2"));
if (properties.getProperty(prefix+"plWeakWorsening")!=null) this.plWeakWorsening=Double.parseDouble(properties.getProperty(prefix+"plWeakWorsening")); if (properties.getProperty(prefix+"plWeakWorsening")!=null) this.plWeakWorsening=Double.parseDouble(properties.getProperty(prefix+"plWeakWorsening"));
if (properties.getProperty(prefix+"plConflDualTri")!=null) this.plConflDualTri=Boolean.parseBoolean(properties.getProperty(prefix+"plConflDualTri"));
if (properties.getProperty(prefix+"plConflMulti")!=null) this.plConflMulti=Boolean.parseBoolean(properties.getProperty(prefix+"plConflMulti"));
if (properties.getProperty(prefix+"plConflDiag")!=null) this.plConflDiag=Boolean.parseBoolean(properties.getProperty(prefix+"plConflDiag"));
if (properties.getProperty(prefix+"plConflStar")!=null) this.plConflStar=Boolean.parseBoolean(properties.getProperty(prefix+"plConflStar"));
if (properties.getProperty(prefix+"plStarSteps")!=null) this.plStarSteps=Integer.parseInt(properties.getProperty(prefix+"plStarSteps")); if (properties.getProperty(prefix+"plStarSteps")!=null) this.plStarSteps=Integer.parseInt(properties.getProperty(prefix+"plStarSteps"));
if (properties.getProperty(prefix+"plStarOrtho")!=null) this.plStarOrtho=Double.parseDouble(properties.getProperty(prefix+"plStarOrtho")); if (properties.getProperty(prefix+"plStarOrtho")!=null) this.plStarOrtho=Double.parseDouble(properties.getProperty(prefix+"plStarOrtho"));
if (properties.getProperty(prefix+"plStarDiag")!=null) this.plStarDiag=Double.parseDouble(properties.getProperty(prefix+"plStarDiag")); if (properties.getProperty(prefix+"plStarDiag")!=null) this.plStarDiag=Double.parseDouble(properties.getProperty(prefix+"plStarDiag"));
...@@ -3225,6 +3238,10 @@ public class EyesisCorrectionParameters { ...@@ -3225,6 +3238,10 @@ public class EyesisCorrectionParameters {
gd.addNumericField("Maximal sine squared of the world angle between planes to merge. Set to >= 1.0 to disable", this.plMaxWorldSin2, 6); gd.addNumericField("Maximal sine squared of the world angle between planes to merge. Set to >= 1.0 to disable", this.plMaxWorldSin2, 6);
gd.addNumericField("Relax merge requirements for weaker planes", this.plWeakWorsening, 6); gd.addNumericField("Relax merge requirements for weaker planes", this.plWeakWorsening, 6);
gd.addCheckbox ("Resolve dual triangles conflict (odoodo)", this.plConflDualTri);
gd.addCheckbox ("Resolve multiple odo triangles conflicts", this.plConflMulti);
gd.addCheckbox ("Resolve diagonal (ood) conflicts", this.plConflDiag);
gd.addCheckbox ("Resolve all conflicts around a supertile", this.plConflStar);
gd.addNumericField("How far to look around when calculationg connection cost", this.plStarSteps, 0); gd.addNumericField("How far to look around when calculationg connection cost", this.plStarSteps, 0);
gd.addNumericField("When calculating cost for the connections scale 4 ortho neighbors", this.plStarOrtho, 6); gd.addNumericField("When calculating cost for the connections scale 4 ortho neighbors", this.plStarOrtho, 6);
gd.addNumericField("When calculating cost for the connections scale 4 diagonal neighbors", this.plStarDiag, 6); gd.addNumericField("When calculating cost for the connections scale 4 diagonal neighbors", this.plStarDiag, 6);
...@@ -3572,6 +3589,10 @@ public class EyesisCorrectionParameters { ...@@ -3572,6 +3589,10 @@ public class EyesisCorrectionParameters {
this.plMaxWorldSin2= gd.getNextNumber(); this.plMaxWorldSin2= gd.getNextNumber();
this.plWeakWorsening= gd.getNextNumber(); this.plWeakWorsening= gd.getNextNumber();
this.plConflDualTri= gd.getNextBoolean();
this.plConflMulti= gd.getNextBoolean();
this.plConflDiag= gd.getNextBoolean();
this.plConflStar= gd.getNextBoolean();
this.plStarSteps= (int) gd.getNextNumber(); this.plStarSteps= (int) gd.getNextNumber();
this.plStarOrtho= gd.getNextNumber(); this.plStarOrtho= gd.getNextNumber();
this.plStarDiag= gd.getNextNumber(); this.plStarDiag= gd.getNextNumber();
......
...@@ -4061,58 +4061,6 @@ public class SuperTiles{ ...@@ -4061,58 +4061,6 @@ public class SuperTiles{
} }
public int [] resolveMultiTriangularConflicts(
int [][][] conflicts,
Conflicts conflict_stats, // to be updated after applying resolution
int starSteps, // How far to look around when calculationg connection cost
double orthoWeight,
double diagonalWeight,
double starPwr, // Divide cost by number of connections to this power
double dblTriLoss, // When resolving double triangles allow minor degradation (0.0 - strict)
boolean preferDisparity,
int debugLevel,
int dbg_X,
int dbg_Y)
{
final int tilesX = tileProcessor.getTilesX();
final int tilesY = tileProcessor.getTilesY();
final int superTileSize = tileProcessor.getSuperTileSize();
// final int tileSize = tileProcessor.getTileSize();
final int stilesX = (tilesX + superTileSize -1)/superTileSize;
final int stilesY = (tilesY + superTileSize -1)/superTileSize;
final int dbgTile = dbg_Y * stilesX + dbg_X;
final TileSurface.TileNeibs tnSurface = tileSurface.new TileNeibs(stilesX, stilesY);
int [] rslt = {0,0};
for (int nsTile = 0; nsTile < conflicts.length; nsTile++) if (conflicts[nsTile] != null) {
// conflicts may disappear after being fixed, recheck for null
for (int nConfl = 0; (conflicts[nsTile] != null) && (nConfl < conflicts[nsTile].length); nConfl++){
int dl = ((debugLevel > 0) && (nsTile == dbgTile)) ? 3 : 0;
boolean OK = resolveMultiTriangularConflict(
nsTile,
conflicts[nsTile][nConfl][0], // int nl1,
conflicts[nsTile][nConfl][1], // int nl2,
conflicts[nsTile][nConfl][2], // int dir_mask,
tnSurface,
conflicts,
conflict_stats, // to be updated after applying resolution
// maxEigen, // maximal eigenvalue of planes to consider
starSteps, // How far to look around when calculationg connection cost
orthoWeight,
diagonalWeight,
starPwr, // double starPwr, // Divide cost by number of connections to this power
dblTriLoss, // When resolving double triangles allow minor degradation (0.0 - strict)
preferDisparity,
dl); // debugLevel,
if (OK) rslt[0]++;
else rslt[1]++;
}
}
return rslt;
}
public boolean resolveMultiTriangularConflict( public boolean resolveMultiTriangularConflict(
int nsTile, int nsTile,
int nl1, int nl1,
...@@ -4238,6 +4186,13 @@ public class SuperTiles{ ...@@ -4238,6 +4186,13 @@ public class SuperTiles{
double [] variant_costs_diff = new double [neibs_vars.length]; double [] variant_costs_diff = new double [neibs_vars.length];
for (int variant = 0; variant < neibs_vars.length; variant ++){ for (int variant = 0; variant < neibs_vars.length; variant ++){
if (debugLevel > 0) {
System.out.println("resolveMultiTriangularConflict(): resolving conflict for tile "+nsTile+
", nl1 = "+nl1+
", nl2 = "+nl2 +
", dir_mask = "+dir_mask+" variant = "+variant);
}
variant_costs_diff[variant] = connectionCosts.getConnectionsCostDiff( variant_costs_diff[variant] = connectionCosts.getConnectionsCostDiff(
neibs_vars[variant], neibs_vars[variant],
debugLevel); debugLevel);
...@@ -4289,7 +4244,7 @@ public class SuperTiles{ ...@@ -4289,7 +4244,7 @@ public class SuperTiles{
System.out.println("resolveMultiTriangularConflict() OLD: resolving conflict for tile "+nsTile+ System.out.println("resolveMultiTriangularConflict() OLD: resolving conflict for tile "+nsTile+
", nl1 = "+nl1+ ", nl1 = "+nl1+
", nl2 = "+nl2 + ", nl2 = "+nl2 +
", dir_mask = "+dir_mask+" variant = "+variant+" improvement (negative diff) = "+variant_costs_diff[variant]); ", dir_mask = "+dir_mask+" variant = "+variant+" improvement (negative diff) = "+variant_costs_diff_old[variant]);
} }
if (debugLevel > -1) { if (debugLevel > -1) {
...@@ -4375,6 +4330,336 @@ public class SuperTiles{ ...@@ -4375,6 +4330,336 @@ public class SuperTiles{
return true; return true;
} }
public int [] resolveMultiTriangularConflicts(
int [][][] conflicts,
Conflicts conflict_stats, // to be updated after applying resolution
int starSteps, // How far to look around when calculationg connection cost
double orthoWeight,
double diagonalWeight,
double starPwr, // Divide cost by number of connections to this power
double dblTriLoss, // When resolving double triangles allow minor degradation (0.0 - strict)
boolean preferDisparity,
int debugLevel,
int dbg_X,
int dbg_Y)
{
final int tilesX = tileProcessor.getTilesX();
final int tilesY = tileProcessor.getTilesY();
final int superTileSize = tileProcessor.getSuperTileSize();
// final int tileSize = tileProcessor.getTileSize();
final int stilesX = (tilesX + superTileSize -1)/superTileSize;
final int stilesY = (tilesY + superTileSize -1)/superTileSize;
final int dbgTile = dbg_Y * stilesX + dbg_X;
final TileSurface.TileNeibs tnSurface = tileSurface.new TileNeibs(stilesX, stilesY);
int [] rslt = {0,0};
for (int nsTile = 0; nsTile < conflicts.length; nsTile++) if (conflicts[nsTile] != null) {
// conflicts may disappear after being fixed, recheck for null
for (int nConfl = 0; (conflicts[nsTile] != null) && (nConfl < conflicts[nsTile].length); nConfl++){
int dl = ((debugLevel > 0) && (nsTile == dbgTile)) ? 3 : 0;
boolean OK = resolveMultiTriangularConflict(
nsTile,
conflicts[nsTile][nConfl][0], // int nl1,
conflicts[nsTile][nConfl][1], // int nl2,
conflicts[nsTile][nConfl][2], // int dir_mask,
tnSurface,
conflicts,
conflict_stats, // to be updated after applying resolution
// maxEigen, // maximal eigenvalue of planes to consider
starSteps, // How far to look around when calculationg connection cost
orthoWeight,
diagonalWeight,
starPwr, // double starPwr, // Divide cost by number of connections to this power
dblTriLoss, // When resolving double triangles allow minor degradation (0.0 - strict)
preferDisparity,
dl); // debugLevel,
if (OK) rslt[0]++;
else rslt[1]++;
}
}
return rslt;
}
public int [] resolveStarConflicts(
int [][][] conflicts,
Conflicts conflict_stats, // to be updated after applying resolution
int starSteps, // How far to look around when calculationg connection cost
double orthoWeight,
double diagonalWeight,
double starPwr, // Divide cost by number of connections to this power
double dblTriLoss, // When resolving double triangles allow minor degradation (0.0 - strict)
boolean preferDisparity,
int debugLevel,
int dbg_X,
int dbg_Y)
{
final int tilesX = tileProcessor.getTilesX();
final int tilesY = tileProcessor.getTilesY();
final int superTileSize = tileProcessor.getSuperTileSize();
// final int tileSize = tileProcessor.getTileSize();
final int stilesX = (tilesX + superTileSize -1)/superTileSize;
final int stilesY = (tilesY + superTileSize -1)/superTileSize;
final int dbgTile = dbg_Y * stilesX + dbg_X;
final TileSurface.TileNeibs tnSurface = tileSurface.new TileNeibs(stilesX, stilesY);
int [] rslt = {0,0};
for (int nsTile = 0; nsTile < conflicts.length; nsTile++) if (conflicts[nsTile] != null) {
// conflicts may disappear after being fixed, recheck for null
for (int nConfl = 0; (conflicts[nsTile] != null) && (nConfl < conflicts[nsTile].length); nConfl++){
int dl = ((debugLevel > 0) && (nsTile == dbgTile)) ? 3 : 0;
boolean OK = resolveStarConflict(
nsTile,
conflicts[nsTile][nConfl][0], // int nl1,
conflicts[nsTile][nConfl][1], // int nl2,
// conflicts[nsTile][nConfl][2], // int dir_mask,
tnSurface,
conflicts,
conflict_stats, // to be updated after applying resolution
// maxEigen, // maximal eigenvalue of planes to consider
starSteps, // How far to look around when calculationg connection cost
orthoWeight,
diagonalWeight,
starPwr, // double starPwr, // Divide cost by number of connections to this power
dblTriLoss, // When resolving double triangles allow minor degradation (0.0 - strict)
preferDisparity,
dl); // debugLevel,
if (OK) rslt[0]++;
else rslt[1]++;
}
}
return rslt;
}
public boolean resolveStarConflict(
int nsTile,
int nl1,
int nl2,
// int dir_mask,
TileSurface.TileNeibs tnSurface,
int [][][] conflicts,
Conflicts conflict_stats, // to be updated after applying resolution
int starSteps, // How far to look around when calculationg connection cost
double orthoWeight,
double diagonalWeight,
double starPwr, // Divide cost by number of connections to this power
double dblTriLoss, // When resolving double triangles allow minor degradation (0.0 - strict)
boolean preferDisparity,
int debugLevel)
{
Conflicts iconflicts = new Conflicts(this);
TwoLayerNeighbors twoLayerNeighbors = new TwoLayerNeighbors();
for (int dir = -1; dir < 8; dir++){
int nt = tnSurface.getNeibIndex(nsTile, dir);
if ((nt >= 0) && (planes[nt] != null)) {
int [][] neibs = new int [planes[nt].length][];
for (int nl = 0; nl < planes[nt].length; nl++) if ( planes[nt][nl] != null){
neibs[nl] = planes[nt][nl].getNeibBest();
}
twoLayerNeighbors.setNeighbors(neibs,dir);
}
}
twoLayerNeighbors.setLayers(nl1, nl2);
int [][][][] neibs_vars_dir = twoLayerNeighbors.getNeighborVariants();
int [] mod_supertiles = {nsTile};
mod_supertiles = getInvolvedSupertiles( // first mod_supertiles.length entries will be mod_supertiles[]
mod_supertiles,
tnSurface);
HashMap<Integer,Integer> replacement_tiles = new HashMap<Integer,Integer>();
for (int i = 0; i < mod_supertiles.length; i++){
replacement_tiles.put(mod_supertiles[i], new Integer(i));
}
// up to 9 tiles
int [] indexToDir = new int[mod_supertiles.length];
for (int i = 0; i < indexToDir.length; i++) indexToDir[i] = -1;
for (int dir = -1; dir < 8; dir++){
int nindx = (dir < 0) ? 8 : dir;
int nt = tnSurface.getNeibIndex(nsTile, dir);
int indx = replacement_tiles.get(nt);
if (indx >= 0) {
indexToDir[indx] = nindx;
}
}
int [][][][] neibs_vars = new int [neibs_vars_dir.length][][][];
for (int variant = 0; variant < neibs_vars_dir.length; variant ++){
neibs_vars[variant] = new int [indexToDir.length][][];
for (int i = 0; i <indexToDir.length; i++){
if (indexToDir[i] >=0){
neibs_vars[variant][i] = neibs_vars_dir[variant][indexToDir[i]];
} else {
System.out.println("resolveStarConflict(): a BUG: indexToDir["+i+"] = "+indexToDir[i]);
}
}
}
// See how this application will influence number of conflicts
// All supertiles that may have different conflicts
int [] nsTiles = getInvolvedSupertiles( // first mod_supertiles.length entries will be mod_supertiles[]
mod_supertiles,
tnSurface);
ConnectionCosts connectionCosts = new ConnectionCosts(
orthoWeight,
diagonalWeight,
starPwr, // Divide cost by number of connections to this power
starSteps,
this.planes,
tnSurface,
preferDisparity);
int [][][] neibs_prev = connectionCosts.initConnectionCosts(mod_supertiles);
int [][][] conflicts_old = new int [nsTiles.length][][];
for (int isTile = 0; isTile < nsTiles.length; isTile++){
conflicts_old[isTile] = iconflicts.detectTriangularTileConflicts(
nsTiles[isTile], // int nsTile0,
replacement_tiles, //HashMap<Integer,Integer> replacement_tiles, //
neibs_prev, // int [][][] replacement_neibs,
tnSurface); // TileSurface.TileNeibs tnSurface)
}
if (debugLevel > 1) {
System.out.println("Involved supertiles:");
for (int i = 0; i < nsTiles.length; i++){
System.out.println(i+":"+nsTiles[i]);
}
}
if (debugLevel > 1) {
System.out.println("Calculating original conflicts");
}
iconflicts.addConflicts(conflicts_old,
debugLevel - 1); // debugLevel);
// After getting old (referfence data) iterate through all variants, for each calculate cost and number of conflicts.
// First - just collect data - cost and full statistics of the conflicts, print them
// Then select the best one (not incrementing number of conflicts? and reducing cost)
int [][][][] variant_conflicts = new int [neibs_vars.length][nsTiles.length][][];
Conflicts [] variant_conflicts_stats = new Conflicts [neibs_vars.length];
double [] variant_costs_diff = new double [neibs_vars.length];
for (int variant = 0; variant < neibs_vars.length; variant ++){
if (debugLevel > 0) {
System.out.println("resolveStarConflict(): resolving conflict for tile "+nsTile+
", nl1 = "+nl1+
", nl2 = "+nl2 +
", variant = "+variant);
}
variant_costs_diff[variant] = connectionCosts.getConnectionsCostDiff(
neibs_vars[variant],
debugLevel);
if (debugLevel > -1) {
System.out.println("resolveStarConflict(): resolving conflict for tile "+nsTile+
", nl1 = "+nl1+
", nl2 = "+nl2 +
", variant = "+variant+" improvement (negative diff) = "+variant_costs_diff[variant]);
}
for (int isTile = 0; isTile < nsTiles.length; isTile++){
variant_conflicts[variant][isTile] = iconflicts.detectTriangularTileConflicts(
nsTiles[isTile], // int nsTile0,
replacement_tiles, //HashMap<Integer,Integer> replacement_tiles, //
neibs_vars[variant], // neibs, // int [][][] replacement_neibs,
tnSurface); // TileSurface.TileNeibs tnSurface)
}
variant_conflicts_stats[variant] = new Conflicts(
variant_conflicts[variant],
this,
debugLevel - 1); // debugLevel);
variant_conflicts_stats[variant].subConflicts(iconflicts); // subtract old number of different types of conflicts
if (debugLevel > -1) {
variant_conflicts_stats[variant].printConflictSummary(
"Conflicts difference after resolution:", true, true, false);
}
}
// How to compare? 1 attempt: none of the conflicts get worse, some get better or cost goes down
int best_variant = -1;
int [][] num_better_worse = new int [neibs_vars.length][2];
for (int variant = 0; variant < neibs_vars.length; variant ++){
int num_worse = variant_conflicts_stats[variant].numBetterWorse(
false, // boolean better,
false, // boolean use_all,
true, // boolean use_odo,
false); // ); // boolean use_ood)
int num_better = variant_conflicts_stats[variant].numBetterWorse(
true, // boolean better,
false, // boolean use_all,
true, // boolean use_odo,
false); // ); // boolean use_ood)
num_better_worse[variant][0] = num_better;
num_better_worse[variant][1] = num_worse;
if ((num_worse == 0) &&
(variant_costs_diff[variant] <= dblTriLoss) && // not too worse
((variant_costs_diff[variant] < 0) || (num_better > 0)) && // either
((best_variant < 0) ||
( num_better_worse[variant][0] > num_better_worse[best_variant][0]) ||
(( num_better_worse[variant][0] == num_better_worse[best_variant][0]) &&
(variant_costs_diff[variant] < variant_costs_diff[best_variant])))){
best_variant = variant;
}
}
if (debugLevel > 1){
System.out.println("resolveStarConflict(): for tile "+nsTile);
}
if ((best_variant < 0) || (variant_costs_diff[best_variant] > dblTriLoss)){
if (debugLevel > -1) {
System.out.println("resolveMultiTriangularConflict(): FAILED find a sutable solution for tile "+nsTile+
", nl1 = "+nl1+
", nl2 = "+nl2 +" of "+ neibs_vars.length+" variants");
return false;
}
} else {
if (debugLevel > -1) {
System.out.println("resolveStarConflict(): SUCCESS to find a sutable solution for tile "+nsTile+
", nl1 = "+nl1+
", nl2 = "+nl2 +". Of "+ neibs_vars.length+" variants - use variant # " + best_variant+
" cost difference (negative) = "+variant_costs_diff[best_variant]+" num conflict reductions = "+num_better_worse[best_variant][0]);
variant_conflicts_stats[best_variant].printConflictSummary(
"Conflicts number change per type: ",
true, // use_all,
true, //use_odo,
true); // use_ood);
iconflicts.printConflictSummary(
"Conflicts before resolution: ",
true, // use_all,
true, //use_odo,
true); // use_ood);
// update statistics
conflict_stats.addConflicts(variant_conflicts_stats[best_variant]);
// update conflict
for (int i = 0; i < nsTiles.length; i++){
conflicts[nsTiles[i]]= variant_conflicts[best_variant][i];
}
// apply resolution
for (int i = 0; i < mod_supertiles.length; i++){
for (int nl = 0; nl < neibs_vars[best_variant][i].length; nl ++) if (neibs_vars[best_variant][i][nl] != null){
planes[mod_supertiles[i]][nl].setNeibBest(neibs_vars[best_variant][i][nl]);
}
}
}
}
return true;
}
// //
/** /**
* Generate variants for changing connections while preserving number of connections between each pair of tiles * Generate variants for changing connections while preserving number of connections between each pair of tiles
...@@ -4625,6 +4910,10 @@ public class SuperTiles{ ...@@ -4625,6 +4910,10 @@ public class SuperTiles{
public void resolveConflicts( public void resolveConflicts(
double maxEigen, // maximal eigenvalue of planes to consider double maxEigen, // maximal eigenvalue of planes to consider
boolean conflDualTri, // Resolve dual triangles conflict (odoodo)
boolean conflMulti, // Resolve multiple odo triangles conflicts
boolean conflDiag, // Resolve diagonal (ood) conflicts
boolean conflStar, // Resolve all conflicts around a supertile
int starSteps, // How far to look around when calculationg connection cost int starSteps, // How far to look around when calculationg connection cost
double orthoWeight, double orthoWeight,
double diagonalWeight, double diagonalWeight,
...@@ -4646,7 +4935,12 @@ public class SuperTiles{ ...@@ -4646,7 +4935,12 @@ public class SuperTiles{
-1); // debugLevel); -1); // debugLevel);
for (int pass = 0; pass < 10; pass ++) { for (int pass = 0; pass < 10; pass ++) {
int [] dual_tri_results = resolveDualTriangularConflicts( int [] dual_tri_results = {0,0};
int [] multi_resoultion_results = {0,0};
int [] diagonal_resoultion_results = {0,0};
int [] conflict_star_results = {0,0};
if (conflDualTri) {
dual_tri_results = resolveDualTriangularConflicts(
conflicts0, // int [][][] conflicts, conflicts0, // int [][][] conflicts,
conflicts0_stats, conflicts0_stats,
maxEigen, maxEigen,
...@@ -4660,9 +4954,9 @@ public class SuperTiles{ ...@@ -4660,9 +4954,9 @@ public class SuperTiles{
dbg_X, dbg_X,
dbg_Y); dbg_Y);
System.out.println("Pass "+(pass+1)+": dual_tri_results (success/failures) = "+dual_tri_results[0]+" / "+dual_tri_results[1]); System.out.println("Pass "+(pass+1)+": dual_tri_results (success/failures) = "+dual_tri_results[0]+" / "+dual_tri_results[1]);
}
if (conflMulti) {
int [] conflict_resoultion_results = resolveMultiTriangularConflicts( multi_resoultion_results = resolveMultiTriangularConflicts(
conflicts0, // int [][][] conflicts, conflicts0, // int [][][] conflicts,
conflicts0_stats, conflicts0_stats,
starSteps, // How far to look around when calculationg connection cost starSteps, // How far to look around when calculationg connection cost
...@@ -4674,9 +4968,10 @@ public class SuperTiles{ ...@@ -4674,9 +4968,10 @@ public class SuperTiles{
debugLevel, // 1, // final int debugLevel) debugLevel, // 1, // final int debugLevel)
dbg_X, dbg_X,
dbg_Y); dbg_Y);
System.out.println("Pass "+(pass+1)+": multi_tri_results (success/failures) = "+conflict_resoultion_results[0]+" / "+conflict_resoultion_results[1]); System.out.println("Pass "+(pass+1)+": multi_tri_results (success/failures) = "+multi_resoultion_results[0]+" / "+multi_resoultion_results[1]);
}
int [] diagonal_resoultion_results = resolveDiagonalTriangularConflicts( if (conflDiag) {
diagonal_resoultion_results = resolveDiagonalTriangularConflicts(
conflicts0, // int [][][] conflicts, conflicts0, // int [][][] conflicts,
conflicts0_stats, conflicts0_stats,
starSteps, // How far to look around when calculationg connection cost starSteps, // How far to look around when calculationg connection cost
...@@ -4689,9 +4984,27 @@ public class SuperTiles{ ...@@ -4689,9 +4984,27 @@ public class SuperTiles{
dbg_X, dbg_X,
dbg_Y); dbg_Y);
System.out.println("Pass "+(pass+1)+": resolveDiagonalTriangularConflicts (success/failures) = "+diagonal_resoultion_results[0]+" / "+diagonal_resoultion_results[1]); System.out.println("Pass "+(pass+1)+": resolveDiagonalTriangularConflicts (success/failures) = "+diagonal_resoultion_results[0]+" / "+diagonal_resoultion_results[1]);
}
if (conflStar) {
conflict_star_results = resolveStarConflicts(
conflicts0, // int [][][] conflicts,
conflicts0_stats,
starSteps, // How far to look around when calculationg connection cost
orthoWeight, // double orthoWeight,
diagonalWeight, // double diagonalWeight,
starPwr, // double starPwr, // Divide cost by number of connections to this power
dblTriLoss, // double diagonalWeight,
preferDisparity,
debugLevel, // 1, // final int debugLevel)
dbg_X,
dbg_Y);
System.out.println("Pass "+(pass+1)+": resolveStarConflicts (success/failures) = "+conflict_star_results[0]+" / "+conflict_star_results[1]);
}
if ( (dual_tri_results[0] == 0) && if ( (dual_tri_results[0] == 0) &&
(conflict_resoultion_results[0] == 0) && (multi_resoultion_results[0] == 0) &&
(diagonal_resoultion_results[0] == 0)) { (diagonal_resoultion_results[0] == 0) &&
(conflict_star_results[0] == 0)) {
System.out.println("No more improvements"); System.out.println("No more improvements");
break; break;
} }
...@@ -4771,7 +5084,7 @@ public class SuperTiles{ ...@@ -4771,7 +5084,7 @@ public class SuperTiles{
for (int dir4 = 0; dir4 < 4; dir4 ++ ){ for (int dir4 = 0; dir4 < 4; dir4 ++ ){
// conflicts may disappear after being fixed, recheck for null // conflicts may disappear after being fixed, recheck for null
if ((conflicts[nsTile] != null) && (conflicts[nsTile][nConfl] != null) && ((conflicts[nsTile][nConfl][2] & (1 << dir4)) > 0) && ((conflicts[nsTile][nConfl][2] & (16 << dir4)) > 0)) { if ((conflicts[nsTile] != null) && (conflicts[nsTile][nConfl] != null) && ((conflicts[nsTile][nConfl][2] & (1 << dir4)) > 0) && ((conflicts[nsTile][nConfl][2] & (16 << dir4)) > 0)) {
if (debugLevel > 1){ if (debugLevel > 0) { //1){
System.out.println("resolveDualTriangularConflicts(): resolving dual triangular conflict for tile "+nsTile+ System.out.println("resolveDualTriangularConflicts(): resolving dual triangular conflict for tile "+nsTile+
", nl1 = "+conflicts[nsTile][nConfl][0]+ ", nl1 = "+conflicts[nsTile][nConfl][0]+
", nl2 = "+conflicts[nsTile][nConfl][1]+ ", nl2 = "+conflicts[nsTile][nConfl][1]+
......
...@@ -3431,6 +3431,10 @@ public class TileProcessor { ...@@ -3431,6 +3431,10 @@ public class TileProcessor {
st.resolveConflicts( st.resolveConflicts(
clt_parameters.plMaxEigen, clt_parameters.plMaxEigen,
clt_parameters.plConflDualTri, // boolean conflDualTri, // Resolve dual triangles conflict (odoodo)
clt_parameters.plConflMulti, // boolean conflMulti, // Resolve multiple odo triangles conflicts
clt_parameters.plConflDiag, // boolean conflDiag, // Resolve diagonal (ood) conflicts
clt_parameters.plConflStar, // boolean conflStar, // Resolve all conflicts around a supertile
clt_parameters.plStarSteps, // int starSteps, // How far to look around when calculationg connection cost clt_parameters.plStarSteps, // int starSteps, // How far to look around when calculationg connection cost
clt_parameters.plStarOrtho, // double orthoWeight, clt_parameters.plStarOrtho, // double orthoWeight,
clt_parameters.plStarDiag, // double diagonalWeight, clt_parameters.plStarDiag, // double diagonalWeight,
...@@ -3533,6 +3537,10 @@ public class TileProcessor { ...@@ -3533,6 +3537,10 @@ public class TileProcessor {
st.resolveConflicts( st.resolveConflicts(
clt_parameters.plMaxEigen, clt_parameters.plMaxEigen,
clt_parameters.plConflDualTri, // boolean conflDualTri, // Resolve dual triangles conflict (odoodo)
clt_parameters.plConflMulti, // boolean conflMulti, // Resolve multiple odo triangles conflicts
clt_parameters.plConflDiag, // boolean conflDiag, // Resolve diagonal (ood) conflicts
clt_parameters.plConflStar, // boolean conflStar, // Resolve all conflicts around a supertile
clt_parameters.plStarSteps, // int starSteps, // How far to look around when calculationg connection cost clt_parameters.plStarSteps, // int starSteps, // How far to look around when calculationg connection cost
clt_parameters.plStarOrtho, // double orthoWeight, clt_parameters.plStarOrtho, // double orthoWeight,
clt_parameters.plStarDiag, // double diagonalWeight, clt_parameters.plStarDiag, // double diagonalWeight,
......
import java.awt.Point;
import java.util.ArrayList;
/**
**
** TwoLayerNeighbors - Handle connection swapping for resolving conflicts
** between two layer connections
**
** Copyright (C) 2017 Elphel, Inc.
**
** -----------------------------------------------------------------------------**
**
** TwoLayerNeighbors.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 TwoLayerNeighbors {
/**
* connection variants (excluding from the center) as
* {start_dir, end_dir, relative_dir}
*/
static int [][] PAIRS = {
{0, 1, 2},
{1, 2, 4},
{2, 3, 4},
{3, 4, 6},
{4, 5, 6},
{5, 6, 0},
{6, 7, 0},
{7, 0, 2},
{0, 2, 3},
{2, 4, 5},
{4, 6, 7},
{6, 0, 1}};
/**
* Direction from dir1 (from center) to dir2 (from center)
* -1 - same (dir1 == dir2)
* -2 - impossible (no direct connection
*/
static int [][] rel_dirs = {
//0 1 2 3 4 5 6 7 // dir2 values
{-1, 2, 3, -2, -2, -2, 5, 6}, // dir1 = 0;
{ 6, -1, 4, -2, -2, -2, -2, -2}, // dir1 = 1;
{ 7, 0, -1, 4, 5, -2, -2, -2}, // dir1 = 2;
{-2, -2, 0, -1, 6, -2, -2, -2}, // dir1 = 3;
{-2, -2, 1, 2, -1, 6, 7, -2}, // dir1 = 4;
{-2, -2, -2, -2, 2, -1, 0, -2}, // dir1 = 5;
{ 1, -2, -2, -2, 3, 4, -1, 0}, // dir1 = 6;
{ 2, -2, -2, -2, -2, -2, 4, -1}};// dir1 = 7
int nl1;
int nl2;
NeibVariant neibs_init = new NeibVariant();
int [][] layers_around = new int [8][];
int [] options_around = new int [8];
int [][] num_se = new int [PAIRS.length][];
int [][][] conns = new int [PAIRS.length][][];
int [] selection_star = null;
int [] selection_conns = null;
class NeibVariant {
int [][][] neighbors = new int[9][][];
public int [][][] toArray()
{
return neighbors;
}
public void setNeighbors (int [][] neibs, int dir)
{
if (dir < 0) neighbors[8] = neibs;
else neighbors[dir] = neibs;
}
public int [][] getNeighbors (int dir)
{
if (dir < 0) return neighbors[8];
else return neighbors[dir];
}
public NeibVariant clone(){
NeibVariant variant = new NeibVariant();
variant.neighbors = neighbors.clone();
for (int dir = 0; dir < neighbors.length; dir++){
if (neighbors[dir] != null) {
variant.neighbors[dir] = neighbors[dir].clone();
for (int i = 0; i < neighbors[dir].length; i++){
if (neighbors[dir][i] != null){
variant.neighbors[dir][i] = neighbors[dir][i].clone();
}
}
}
}
return variant;
}
public int getDir2From1 (
int dir1,
int dir2)
{
if (dir1 < 0) return dir2;
if (dir2 < 0) return ((dir1 + 4) % 8);
return rel_dirs[dir1][dir2];
}
/**
* Connect tile at dir1 (-1 - center), layer nl1 to dir2, layer nl2
* Create connect in both directions, reconnect other ends of the broken links or plug with -1
* if there was none
* @param dir1 direction from the center to the start of the connection (-1 - center)
* @param nl1 start layer to connect (-1 - just disconnect the end)
* @param dir2 direction from the center to the end of the connection (-1 - center)
* @param nl2 end layer to connect (-1 - just disconnect the start)
*/
public void connect(
int dir1,
int nl1,
int dir2,
int nl2){
int dir12 = getDir2From1(dir1, dir2);
if (dir12 <0){
throw new IllegalArgumentException ("Invalid connection from "+dir1+" to "+dir2+": resulted in direction 1->2 = "+dir12);
}
int dir21 = (dir12 + 4) % 8;
int [][] neibs_start = getNeighbors(dir1);
int [][] neibs_end = getNeighbors(dir2);
int old_nl2 = -1, old_nl1 = -1;
if (nl1 >= 0){
old_nl2 = neibs_start[nl1][dir12]; // where it was connected before, may be -1
if (old_nl2 != nl2) {
neibs_start[nl1][dir12] = nl2;
}
}
if (nl2 >= 0){
old_nl1 = neibs_end[nl2][dir21];
neibs_end[nl2][dir21] = nl1;
}
// reconnect or plug broken links
if (old_nl2 >= 0){
neibs_end[old_nl2][dir21] = old_nl1; // (old_nl1 may be -1 here)
}
if (old_nl1 >= 0){
neibs_start[old_nl1][dir12] = old_nl2; // (old_nl2 may be -1 here)
}
}
}
/**
* Initialize or advance variand selection. Return false if nothing left
* @return new selection available
*/
public boolean nextSelection(){
if (selection_star == null){
selection_star = new int [options_around.length]; // 8
selection_conns = new int [PAIRS.length]; // 12
return true;
} else {
// increment connection variant if possible
for (int np = 0; np < PAIRS.length; np++){
// if (
// (num_se[np] == null) ||
// (conns[np] == null)) {
// System.out.println("nextSelection BUG");
// return false;
// }
if ((num_se[np] != null) && (num_se[np][0] == 2) && (num_se[np][1] == 2) && (conns[np] != null) && (conns[np].length == 1)){
if (selection_conns[np] == 0){
selection_conns[np] = 1;
for (int i = 0; i < np; i ++){
selection_conns[i] = 0;
}
return true;
}
}
}
// increment neighbor option, reset connection options;
for (int i = 0; i < PAIRS.length; i ++){
selection_conns[i] = 0;
}
for (int dir = 0; dir < options_around.length; dir++){
if ((options_around[dir]>1) && (selection_star[dir] == 0)){
selection_star[dir] = 1;
for (int dir1 = 0; dir1 < dir; dir1++){
selection_star[dir1] = 0;
}
return true;
}
}
return false;
}
}
/**
* Generate variant for the current selection (if consistent)
* @return neibVariant instance fro the current selection or null if the
* selection leads to conflicts
*/
public NeibVariant generateVariant()
{
// verify all connetions are possible
for (int np = 0; np < PAIRS.length; np++) if (conns[np] != null){
// single connection for a single variant for start and end - either match or not
if ((num_se[np] != null) && (conns[np].length == 1) && (num_se[np][0] == 1) && (num_se[np][1] == 1)){
// Start and end of the connection belong to different groups - they can not be connected
if (selection_star[PAIRS[np][0]] != selection_star[PAIRS[np][1]]){
return null;
}
}
}
// current selection is consistent, generate it
NeibVariant variant = neibs_init.clone();
// set connections for the center
for (int dir = 0; dir < 8; dir++) if (options_around[dir] > 0){
// make a first connection, if there are two - other will be created simultaneously
variant.connect(
-1, // int dir1,
((selection_star[dir] > 0) ? nl2 : nl1), // int nl1,
dir, // int dir2,
layers_around[dir][0]); // int nl2);
}
// set all other connections
for (int np = 0; np < PAIRS.length; np++) if (conns[np] != null){
int start_dir = PAIRS[np][0];
int end_dir = PAIRS[np][1];
boolean swap = (selection_star[start_dir] != selection_star[end_dir]) ^ (selection_conns[np] > 0);
int [] opts = {0,0};
if (swap){
if (num_se[np][0] > 1){
opts[0] = 1;
} else {
opts[1] = 1; // assuming there are two variants for the connection end as it should be
}
}
variant.connect(
start_dir, // int dir1,
layers_around[start_dir][opts[0]], // int nl1,
end_dir, // int dir2,
layers_around[end_dir][opts[1]]); // int nl2);
return variant;
}
return null;
}
public int [][][][] getNeighborVariants()
{
ArrayList<NeibVariant> variant_list = new ArrayList<NeibVariant>();
while (nextSelection()){
NeibVariant variant = generateVariant();
if (variant != null){
variant_list.add(variant);
}
}
int [][][][] variants = new int [variant_list.size()][][][];
int indx = 0;
for(NeibVariant variant : variant_list){
variants[indx++] = variant.toArray();
}
return variants;
}
public void setNeighbors (int [][] neibs, int dir)
{
neibs_init.setNeighbors(neibs, dir);
}
public int [][] getInitNeighbors (int dir)
{
return neibs_init.getNeighbors(dir);
}
public int [] getLayers()
{
int [] layers = {nl1,nl2};
return layers;
}
/**
* Return array pairs of start/end options or null if there are no connections for this pair
* @param np
* @return
*/
int [][] getConnections(int np)
{
int start_dir = PAIRS[np][0];
int end_dir = PAIRS[np][1];
int dir = PAIRS[np][2];
if ((options_around[start_dir] > 0) && (options_around[end_dir] > 0)){
ArrayList<Point> conn_list = new ArrayList<Point>();
for (int opt1 = 0; opt1 < options_around[start_dir]; opt1++){
int start_layer = layers_around[start_dir][opt1];
for (int opt2 = 0; opt2 < options_around[end_dir]; opt2++){
int end_layer = layers_around[end_dir][opt2];
if (neibs_init.neighbors[start_dir][start_layer][dir] == end_layer){
conn_list.add(new Point(opt1,opt2));
}
}
}
if (!conn_list.isEmpty()){
int [][] pconns = new int [conn_list.size()][2];
int indx = 0;
for (Point p :conn_list){
pconns[indx] [0] = p.x;
pconns[indx++][1] = p.y;
}
return pconns;
}
}
return null;
}
public void setLayers(int nl1, int nl2)
{
this.nl1 = nl1;
this.nl2 = nl1;
layers_around = new int [8][];
options_around = new int [8];
int [][] neighbors_center = neibs_init.getNeighbors(-1);
for (int dir = 0; dir < 8; dir++){
if ((neighbors_center[nl1][dir] >= 0) || (neighbors_center[nl2][dir] >= 0)){
options_around[dir] = 1;
layers_around[dir] = new int [2];
if (neighbors_center[nl1][dir] >= 0){
layers_around[dir][0] = neighbors_center[nl1][dir];
if (neighbors_center[nl2][dir] >= 0){
layers_around[dir][1] = neighbors_center[nl2][dir];
options_around[dir] ++;
} else {
layers_around[dir][1] = neighbors_center[nl1][dir];
}
} else {
layers_around[dir][0] = neighbors_center[nl2][dir];
layers_around[dir][1] = neighbors_center[nl2][dir];
}
}
}
for (int np = 0; np < PAIRS.length; np++){
if ((options_around[PAIRS[np][0]] > 0) && (options_around[PAIRS[np][1]] > 0)){
num_se[np] = new int [2]; // {options_around[PAIRS[np][0]],options_around[PAIRS[np][0]]};
num_se[np][0] = options_around[PAIRS[np][0]];
num_se[np][1] = options_around[PAIRS[np][1]];
conns[np] = getConnections(np);
}
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment