Rev 616 |
Blame |
Compare with Previous |
Last modification |
View Log
| RSS feed
/*
* Copyright (C) 2014, Gerd Petermann
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 or
* version 2 as published by the Free Software Foundation.
*
* 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.
*/
package uk.me.parabola.splitter.solver;
import java.util.Arrays;
/**
* A helper class to store all kind of
* information which cannot be easily calculated
* @author GerdP
*/
class TileMetaInfo
{
private long minNodes
;
private final long[] rowSums
;
private final long[] colSums
;
private final Tile
[] parts =
new Tile
[2];
private int validStartX = -
1;
private int validStartY = -
1;
private int firstNonZeroX = -
1;
private int firstNonZeroY = -
1;
private int lastNonZeroX = -
1;
private int lastNonZeroY = -
1;
private long vertMidSum = -
1;
private long horMidSum = -
1;
private int vertMidPos = -
1;
private int horMidPos = -
1;
private int validEndX = -
1;
private int validEndY = -
1;
private int numOutside = -
1;
/**
* Copy information from parent tile to child. Reusing these values
* saves a lot of time.
* @param tile
* @param parent
* @param smiParent
*/
public TileMetaInfo
(Tile tile, Tile parent, TileMetaInfo smiParent
) {
rowSums =
new long[tile.
height];
colSums =
new long[tile.
width];
if (parent
!=
null && parent.
width == tile.
width){
int srcPos = tile.
y - parent.
y;
System.
arraycopy(smiParent.
rowSums, srcPos, rowSums,
0, rowSums.
length);
if (srcPos ==
0)
firstNonZeroY = smiParent.
firstNonZeroY;
} else
Arrays.
fill(rowSums, -
1);
if (parent
!=
null && parent.
height == tile.
height){
int srcPos = tile.
x - parent.
x;
System.
arraycopy(smiParent.
colSums, srcPos, colSums,
0, colSums.
length);
if (srcPos ==
0)
firstNonZeroX = smiParent.
firstNonZeroX;
} else
Arrays.
fill(colSums, -
1);
if (smiParent
!=
null) {
this.
minNodes = smiParent.
minNodes;
if (smiParent.
getNumOutside() ==
0)
numOutside =
0;
}
if (numOutside
< 0) {
numOutside = tile.
countElemsOutside();
}
}
/**
* Set new minNodes value. This invalidates cached values if the value is
* different to the previously used one.
* @param minNodes
*/
public void setMinNodes
(long minNodes
){
if (this.
minNodes == minNodes
)
return;
this.
minNodes = minNodes
;
this.
validStartX = -
1;
this.
validStartY = -
1;
this.
validEndX = -
1;
this.
validEndY = -
1;
}
public int getValidStartX
() {
return validStartX
;
}
public void setValidStartX
(int validStartX
) {
this.
validStartX = validStartX
;
}
public int getValidStartY
() {
return validStartY
;
}
public void setValidStartY
(int validStartY
) {
this.
validStartY = validStartY
;
}
public int getFirstNonZeroX
() {
return firstNonZeroX
;
}
public void setFirstNonZeroX
(int firstNonZeroX
) {
this.
firstNonZeroX = firstNonZeroX
;
}
public int getFirstNonZeroY
() {
return firstNonZeroY
;
}
public void setFirstNonZeroY
(int firstNonZeroY
) {
this.
firstNonZeroY = firstNonZeroY
;
}
public int getLastNonZeroX
() {
return lastNonZeroX
;
}
public void setLastNonZeroX
(int lastNonZeroX
) {
this.
lastNonZeroX = lastNonZeroX
;
}
public int getLastNonZeroY
() {
return lastNonZeroY
;
}
public void setLastNonZeroY
(int lastNonZeroY
) {
this.
lastNonZeroY = lastNonZeroY
;
}
public long getVertMidSum
() {
return vertMidSum
;
}
public void setVertMidSum
(long vertMidSum
) {
this.
vertMidSum = vertMidSum
;
}
public long getHorMidSum
() {
return horMidSum
;
}
public void setHorMidSum
(long horMidSum
) {
this.
horMidSum = horMidSum
;
}
public int getVertMidPos
() {
return vertMidPos
;
}
public void setVertMidPos
(int vertMidPos
) {
this.
vertMidPos = vertMidPos
;
}
public int getHorMidPos
() {
return horMidPos
;
}
public void setHorMidPos
(int horMidPos
) {
this.
horMidPos = horMidPos
;
}
public long getMinNodes
() {
return minNodes
;
}
public long[] getRowSums
() {
return rowSums
;
}
public long[] getColSums
() {
return colSums
;
}
public Tile
[] getParts
() {
return parts
;
}
public int getValidEndX
() {
return validEndX
;
}
public void setValidEndX
(int pos
) {
this.
validEndX = pos
;
}
public int getValidEndY
() {
return validEndY
;
}
public void setValidEndY
(int pos
) {
this.
validEndY = pos
;
}
public int getNumOutside
() {
return numOutside
;
}
public void setNumOutside
(int numOutside
) {
this.
numOutside = numOutside
;
}
/**
* Copy the information back from child to parent so that next child has more info.
* @param smiParent
* @param tile
* @param parent
*/
void propagateToParent
(TileMetaInfo smiParent, Tile tile, Tile parent
){
if (parent.
width == tile.
width){
int destPos = tile.
y - parent.
y;
System.
arraycopy(this.
rowSums,
0, smiParent.
rowSums, destPos,
this.
rowSums.
length);
if (destPos ==
0) {
if (smiParent.
firstNonZeroY < 0 && this.
firstNonZeroY >=
0)
smiParent.
firstNonZeroY =
this.
firstNonZeroY;
if (smiParent.
validStartY < 0 && this.
validStartY >=
0)
smiParent.
validStartY =
this.
validStartY;
} else {
if (smiParent.
lastNonZeroY < 0 && this.
lastNonZeroY >=
0){
smiParent.
lastNonZeroY = destPos +
this.
lastNonZeroY;
assert smiParent.
lastNonZeroY <= parent.
height;
}
if (smiParent.
validEndY < 0 && this.
validEndY >=
0){
smiParent.
validEndY = destPos +
this.
validEndY;
assert smiParent.
validEndY <= parent.
height;
}
}
}
if (parent.
height == tile.
height){
int destPos = tile.
x - parent.
x;
System.
arraycopy(this.
colSums,
0, smiParent.
colSums, destPos,
this.
colSums.
length);
if (destPos ==
0) {
if (smiParent.
firstNonZeroX < 0 && this.
firstNonZeroX >=
0)
smiParent.
firstNonZeroX =
this.
firstNonZeroX;
if (smiParent.
validStartX < 0 && this.
validStartX >=
0)
smiParent.
validStartX =
this.
validStartX;
} else {
if (smiParent.
lastNonZeroX < 0 && this.
lastNonZeroX >=
0){
smiParent.
lastNonZeroX = destPos +
this.
lastNonZeroX;
assert parent.
getColSum(smiParent.
lastNonZeroX) > 0;
}
if (smiParent.
validEndX < 0 && this.
validEndX >=
0){
smiParent.
validEndX = destPos +
this.
validEndX;
assert smiParent.
validEndX <= parent.
width;
}
}
}
// verify(tile);
// smiParent.verify(parent);
}
boolean verify
(Tile tile
){
if (firstNonZeroX
>=
0){
assert tile.
getColSum(firstNonZeroX
) > 0;
for (int i =
0; i
< firstNonZeroX
; i++
)
assert tile.
getColSum(i
) ==
0;
}
if (lastNonZeroX
>=
0){
assert tile.
getColSum(lastNonZeroX
) > 0;
for (int i = lastNonZeroX+
1; i
< tile.
width; i++
)
assert tile.
getColSum(i
) ==
0;
}
if (validEndX
>=
0){
long sum =
0;
for (int i = validEndX
; i
< tile.
width; i++
){
sum += tile.
getColSum(i
);
}
assert sum
>= minNodes
;
assert sum - tile.
getColSum(validEndX
) < minNodes
;
}
if (validStartX
>=
0){
long sum =
0;
for (int i =
0; i
< validStartX
; i++
){
sum += tile.
getColSum(i
);
}
assert sum
< minNodes
;
assert sum + tile.
getColSum(validStartX
) >= minNodes
;
}
if (firstNonZeroY
>=
0){
assert tile.
getRowSum(firstNonZeroY
) > 0;
for (int i =
0; i
< firstNonZeroY
; i++
)
assert tile.
getRowSum(i
) ==
0;
}
if (lastNonZeroY
>=
0){
assert tile.
getRowSum(lastNonZeroY
) > 0;
for (int i = lastNonZeroY+
1; i
< tile.
height; i++
)
assert tile.
getRowSum(i
) ==
0;
}
if (validStartY
>=
0){
long sum =
0;
for (int i =
0; i
< validStartY
; i++
){
sum += tile.
getRowSum(i
);
}
assert sum
< minNodes
;
assert sum + tile.
getRowSum(validStartY
) >= minNodes
;
}
if (validEndY
>=
0){
long sum =
0;
for (int i = validEndY
; i
< tile.
height; i++
){
sum += tile.
getRowSum(i
);
}
assert sum
>= minNodes
;
assert sum - tile.
getRowSum(validEndY
) < minNodes
;
}
return false;
}
}