Squiz Matrix  4.12.2
 All Data Structures Namespaces Functions Variables Pages
PolygonFiller.java
1 package ij.process;
2 import ij.*;
3 import ij.gui.*;
4 import java.awt.Rectangle;
5 
6 
9 public class PolygonFiller {
10  int BLACK=0xff000000, WHITE=0xffffffff;
11  int edges; // number of edges
12  int activeEdges; // number of active edges
13 
14  // the polygon
15  int[] x; // x coordinates
16  int[] y; // y coordinates
17  int n; // number of coordinates
18 
19  // edge table
20  double[] ex; // x coordinates
21  int[] ey1; // upper y coordinates
22  int[] ey2; // lower y coordinates
23  double[] eslope; // inverse slopes (1/m)
24 
25  // sorted edge table (indexes into edge table) (currently not used)
26  int[] sedge;
27 
28  // active edge table (indexes into edge table)
29  int[] aedge;
30 
32  public PolygonFiller() {
33  }
34 
36  public PolygonFiller(int[] x, int[] y, int n) {
37  setPolygon(x, y, n);
38  }
39 
41  public void setPolygon(int[] x, int[] y, int n) {
42  this.x = x;
43  this.y = y;
44  this.n = n;
45  }
46 
47  void allocateArrays(int n) {
48  if (ex==null || n>ex.length) {
49  ex = new double[n];
50  ey1 = new int[n];
51  ey2 = new int[n];
52  sedge = new int[n];
53  aedge = new int[n];
54  eslope = new double[n];
55  }
56  }
57 
59  void buildEdgeTable(int[] x, int[] y, int n) {
60  int length, iplus1, x1, x2, y1, y2;
61  edges = 0;
62  for (int i=0; i<n; i++) {
63  iplus1 = i==n-1?0:i+1;
64  y1 = y[i]; y2 = y[iplus1];
65  x1 = x[i]; x2 = x[iplus1];
66  if (y1==y2)
67  continue; //ignore horizontal lines
68  if (y1>y2) { // swap ends
69  int tmp = y1;
70  y1=y2; y2=tmp;
71  tmp=x1;
72  x1=x2; x2=tmp;
73  }
74  double slope = (double)(x2-x1)/(y2-y1);
75  ex[edges] = x1 + slope/2.0;
76  ey1[edges] = y1;
77  ey2[edges] = y2;
78  eslope[edges] = slope;
79  edges++;
80  }
81  for (int i=0; i<edges; i++)
82  sedge[i] = i;
83  activeEdges = 0;
84  //quickSort(sedge);
85  }
86 
87 
90  void addToSortedTable(int edge) {
91  int index = 0;
92  while (index<edges && ey1[edges]>ey1[sedge[index]]) {
93  index++;
94  }
95  for (int i=edges-1; i>=index; i--) {
96  sedge[i+1] = sedge[i];
97  //IJ.log((i+1)+"="+i);
98  }
99  sedge[index] = edges;
100  }
101 
103  public void fill(ImageProcessor ip, Rectangle r) {
104  ip.fill(getMask(r.width, r.height));
105  }
106 
108  public ImageProcessor getMask(int width, int height) {
109  allocateArrays(n);
110  buildEdgeTable(x, y, n);
111  //printEdges();
112  int x1, x2, offset, index;
113  ImageProcessor mask = new ByteProcessor(width, height);
114  byte[] pixels = (byte[])mask.getPixels();
115  for (int y=0; y<height; y++) {
116  removeInactiveEdges(y);
117  activateEdges(y);
118  offset = y*width;
119  for (int i=0; i<activeEdges; i+=2) {
120  x1 = (int)(ex[aedge[i]]+0.5);
121  if (x1<0) x1=0;
122  if (x1>width) x1 = width;
123  x2 = (int)(ex[aedge[i+1]]+0.5);
124  if (x2<0) x2=0;
125  if (x2>width) x2 = width;
126  //IJ.log(y+" "+x1+" "+x2);
127  for (int x=x1; x<x2; x++)
128  pixels[offset+x] = -1; // 255 (white)
129  }
130  updateXCoordinates();
131  }
132  return mask;
133  }
134 
136  void updateXCoordinates() {
137  int index;
138  double x1=-Double.MAX_VALUE, x2;
139  boolean sorted = true;
140  for (int i=0; i<activeEdges; i++) {
141  index = aedge[i];
142  x2 = ex[index] + eslope[index];
143  ex[index] = x2;
144  if (x2<x1) sorted = false;
145  x1 = x2;
146  }
147  if (!sorted)
148  sortActiveEdges();
149  }
150 
152  void sortActiveEdges() {
153  int min, tmp;
154  for (int i=0; i<activeEdges; i++) {
155  min = i;
156  for (int j=i; j<activeEdges; j++)
157  if (ex[aedge[j]] <ex[aedge[min]]) min = j;
158  tmp=aedge[min];
159  aedge[min] = aedge[i];
160  aedge[i]=tmp;
161  }
162  }
163 
165  void removeInactiveEdges(int y) {
166  int i = 0;
167  while (i<activeEdges) {
168  int index = aedge[i];
169  if (y<ey1[index] || y>=ey2[index]) {
170  for (int j=i; j<activeEdges-1; j++)
171  aedge[j] = aedge[j+1];
172  activeEdges--;
173  } else
174  i++;
175  }
176  }
177 
179  void activateEdges(int y) {
180  for (int i=0; i<edges; i++) {
181  int edge =sedge[i];
182  if (y==ey1[edge]) {
183  int index = 0;
184  while (index<activeEdges && ex[edge]>ex[aedge[index]])
185  index++;
186  for (int j=activeEdges-1; j>=index; j--)
187  aedge[j+1] = aedge[j];
188  aedge[index] = edge;
189  activeEdges++;
190  }
191  }
192  }
193 
195  void printEdges() {
196  for (int i=0; i<edges; i++) {
197  int index = sedge[i];
198  IJ.log(i+" "+ex[index]+" "+ey1[index]+" "+ey2[index] + " " + IJ.d2s(eslope[index],2) );
199  }
200  }
201 
203  void printActiveEdges() {
204  for (int i=0; i<activeEdges; i++) {
205  int index =aedge[i];
206  IJ.log(i+" "+ex[index]+" "+ey1[index]+" "+ey2[index] );
207  }
208  }
209 
210  /*
211  void quickSort(int[] a) {
212  quickSort(a, 0, a.length-1);
213  }
214 
215  void quickSort(int[] a, int from, int to) {
216  int i=from, j=to;
217  int center = a[(from+to)/2];
218  do {
219  //while ( i < to && center.compareTo(a[i]) > 0 ) i++;
220  while (i<to && ey1[center]>ey1[a[i]]) j--;
221  //while ( j > from && center.compareTo(a[j]) < 0 ) j--;
222  while (j>from && ey1[center]<ey1[a[j]]) j--;
223  if (i < j) {int temp = a[i]; a[i] = a[j]; a[j] = temp;}
224  if (i <= j) { i++; j--; }
225  } while(i <= j);
226  if (from < j) quickSort(a, from, j);
227  if (i < to) quickSort(a, i, to);
228  }
229  */
230 
231 }