package ij.process;
import ij.*;
import ij.gui.*;
import java.awt.Rectangle;
public class PolygonFiller {
int BLACK=0xff000000, WHITE=0xffffffff;
int edges; int activeEdges;
int[] x; int[] y; int n;
double[] ex; int[] ey1; int[] ey2; double[] eslope;
int[] sedge;
int[] aedge;
public PolygonFiller() {
}
public PolygonFiller(int[] x, int[] y, int n) {
setPolygon(x, y, n);
}
public void setPolygon(int[] x, int[] y, int n) {
this.x = x;
this.y = y;
this.n = n;
}
void allocateArrays(int n) {
if (ex==null || n>ex.length) {
ex = new double[n];
ey1 = new int[n];
ey2 = new int[n];
sedge = new int[n];
aedge = new int[n];
eslope = new double[n];
}
}
void buildEdgeTable(int[] x, int[] y, int n) {
int length, iplus1, x1, x2, y1, y2;
edges = 0;
for (int i=0; i<n; i++) {
iplus1 = i==n-1?0:i+1;
y1 = y[i]; y2 = y[iplus1];
x1 = x[i]; x2 = x[iplus1];
if (y1==y2)
continue; if (y1>y2) { int tmp = y1;
y1=y2; y2=tmp;
tmp=x1;
x1=x2; x2=tmp;
}
double slope = (double)(x2-x1)/(y2-y1);
ex[edges] = x1 + slope/2.0;
ey1[edges] = y1;
ey2[edges] = y2;
eslope[edges] = slope;
edges++;
}
for (int i=0; i<edges; i++)
sedge[i] = i;
activeEdges = 0;
}
public void fill(ImageProcessor ip, Rectangle r) {
ip.fill(getMask(r.width, r.height));
}
public ImageProcessor getMask(int width, int height) {
allocateArrays(n);
buildEdgeTable(x, y, n);
int x1, x2, offset, index;
ImageProcessor mask = new ByteProcessor(width, height);
byte[] pixels = (byte[])mask.getPixels();
for (int y=0; y<height; y++) {
removeInactiveEdges(y);
activateEdges(y);
offset = y*width;
for (int i=0; i<activeEdges; i+=2) {
x1 = (int)(ex[aedge[i]]+0.5);
if (x1<0) x1=0;
if (x1>width) x1 = width;
x2 = (int)(ex[aedge[i+1]]+0.5);
if (x2<0) x2=0;
if (x2>width) x2 = width;
for (int x=x1; x<x2; x++)
pixels[offset+x] = -1; }
updateXCoordinates();
}
return mask;
}
void updateXCoordinates() {
int index;
double x1=-Double.MAX_VALUE, x2;
boolean sorted = true;
for (int i=0; i<activeEdges; i++) {
index = aedge[i];
x2 = ex[index] + eslope[index];
ex[index] = x2;
if (x2<x1) sorted = false;
x1 = x2;
}
if (!sorted)
sortActiveEdges();
}
void sortActiveEdges() {
int min, tmp;
for (int i=0; i<activeEdges; i++) {
min = i;
for (int j=i; j<activeEdges; j++)
if (ex[aedge[j]] <ex[aedge[min]]) min = j;
tmp=aedge[min];
aedge[min] = aedge[i];
aedge[i]=tmp;
}
}
void removeInactiveEdges(int y) {
int i = 0;
while (i<activeEdges) {
int index = aedge[i];
if (y<ey1[index] || y>=ey2[index]) {
for (int j=i; j<activeEdges-1; j++)
aedge[j] = aedge[j+1];
activeEdges--;
} else
i++;
}
}
void activateEdges(int y) {
for (int i=0; i<edges; i++) {
int edge =sedge[i];
if (y==ey1[edge]) {
int index = 0;
while (index<activeEdges && ex[edge]>ex[aedge[index]])
index++;
for (int j=activeEdges-1; j>=index; j--)
aedge[j+1] = aedge[j];
aedge[index] = edge;
activeEdges++;
}
}
}
void printEdges() {
for (int i=0; i<edges; i++) {
int index = sedge[i];
IJ.log(i+" "+ex[index]+" "+ey1[index]+" "+ey2[index] + " " + IJ.d2s(eslope[index],2) );
}
}
void printActiveEdges() {
for (int i=0; i<activeEdges; i++) {
int index =aedge[i];
IJ.log(i+" "+ex[index]+" "+ey1[index]+" "+ey2[index] );
}
}
}