/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package sec.sun.awt.geom;
/**
*
* @author Michael Deutch
*/
public class NonZero {
public static final boolean debug = false;
int limit = 0;
double yranges[] = new double[10];
double xlo, ylo, xhi, yhi;
private int crosscounts[];
public NonZero(double xlo, double ylo, double xhi, double yhi) {
//super(xlo, ylo, xhi, yhi);
this.xlo = xlo;
this.ylo = ylo;
this.xhi = xhi;
this.yhi = yhi;
crosscounts = new int[yranges.length / 2];
}
public final boolean covers(double ystart, double yend) {
int i = 0;
while (i < limit) {
double ylo = yranges[i++];
double yhi = yranges[i++];
if (ystart >= yhi) {
continue;
}
if (ystart < ylo) {
return false;
}
if (yend <= yhi) {
return true;
}
ystart = yhi;
}
return (ystart >= yend);
}
public void remove(int cur) {
limit -= 2;
int rem = limit - cur;
if (rem > 0) {
System.arraycopy(yranges, cur + 2, yranges, cur, rem);
System.arraycopy(crosscounts, cur / 2 + 1,
crosscounts, cur / 2,
rem / 2);
}
}
public void insert(int cur, double lo, double hi, int dir) {
int rem = limit - cur;
double oldranges[] = yranges;
int oldcounts[] = crosscounts;
if (limit >= yranges.length) {
yranges = new double[limit + 10];
System.arraycopy(oldranges, 0, yranges, 0, cur);
crosscounts = new int[(limit + 10) / 2];
System.arraycopy(oldcounts, 0, crosscounts, 0, cur / 2);
}
if (rem > 0) {
System.arraycopy(oldranges, cur, yranges, cur + 2, rem);
System.arraycopy(oldcounts, cur / 2,
crosscounts, cur / 2 + 1,
rem / 2);
}
yranges[cur + 0] = lo;
yranges[cur + 1] = hi;
crosscounts[cur / 2] = dir;
limit += 2;
}
public void record(double ystart, double yend, int direction) {
if (ystart >= yend) {
return;
}
int cur = 0;
// Quickly jump over all pairs that are completely "above"
while (cur < limit && ystart > yranges[cur + 1]) {
cur += 2;
}
if (cur < limit) {
int rdir = crosscounts[cur / 2];
double yrlo = yranges[cur + 0];
double yrhi = yranges[cur + 1];
if (yrhi == ystart && rdir == direction) {
// Remove the range from the list and collapse it
// into the range being inserted. Note that the
// new combined range may overlap the following range
// so we must not simply combine the ranges in place
// unless we are at the last range.
if (cur + 2 == limit) {
yranges[cur + 1] = yend;
return;
}
remove(cur);
ystart = yrlo;
rdir = crosscounts[cur / 2];
yrlo = yranges[cur + 0];
yrhi = yranges[cur + 1];
}
if (yend < yrlo) {
// Just insert the new range at the current location
insert(cur, ystart, yend, direction);
return;
}
if (yend == yrlo && rdir == direction) {
// Just prepend the new range to the current one
yranges[cur] = ystart;
return;
}
// The ranges must overlap - (yend > yrlo && yrhi > ystart)
if (ystart < yrlo) {
insert(cur, ystart, yrlo, direction);
cur += 2;
ystart = yrlo;
} else if (yrlo < ystart) {
insert(cur, yrlo, ystart, rdir);
cur += 2;
yrlo = ystart;
}
// assert(yrlo == ystart);
int newdir = rdir + direction;
double newend = Math.min(yend, yrhi);
if (newdir == 0) {
remove(cur);
} else {
crosscounts[cur / 2] = newdir;
yranges[cur++] = ystart;
yranges[cur++] = newend;
}
ystart = yrlo = newend;
if (yrlo < yrhi) {
insert(cur, yrlo, yrhi, rdir);
}
}
if (ystart < yend) {
insert(cur, ystart, yend, direction);
}
}
public final double getXLo() {
return xlo;
}
public final double getYLo() {
return ylo;
}
public final double getXHi() {
return xhi;
}
public final double getYHi() {
return yhi;
}
public final boolean isEmpty() {
return (limit == 0);
}
public boolean accumulateLine(double x0, double y0,
double x1, double y1)
{
if (y0 <= y1) {
return accumulateLine2(x0, y0, x1, y1, 1);
} else {
return accumulateLine2(x1, y1, x0, y0, -1);
}
}
public boolean accumulateLine2(double x0, double y0,
double x1, double y1,
int direction)
{
if (yhi <= y0 || ylo >= y1) {
return false;
}
if (x0 >= xhi && x1 >= xhi) {
return false;
}
if (y0 == y1) {
return (x0 >= xlo || x1 >= xlo);
}
double xstart, ystart, xend, yend;
double dx = (x1 - x0);
double dy = (y1 - y0);
if (y0 < ylo) {
xstart = x0 + (ylo - y0) * dx / dy;
ystart = ylo;
} else {
xstart = x0;
ystart = y0;
}
if (yhi < y1) {
xend = x0 + (yhi - y0) * dx / dy;
yend = yhi;
} else {
xend = x1;
yend = y1;
}
if (xstart >= xhi && xend >= xhi) {
return false;
}
if (xstart > xlo || xend > xlo) {
return true;
}
record(ystart, yend, direction);
return false;
}
}