001/* 002 * To change this template, choose Tools | Templates 003 * and open the template in the editor. 004 */ 005package sec.sun.awt.geom; 006 007/** 008 * 009 * @author Michael Deutch 010 */ 011public class NonZero { 012 013 public static final boolean debug = false; 014 int limit = 0; 015 double yranges[] = new double[10]; 016 double xlo, ylo, xhi, yhi; 017 private int crosscounts[]; 018 019 public NonZero(double xlo, double ylo, double xhi, double yhi) { 020 //super(xlo, ylo, xhi, yhi); 021 this.xlo = xlo; 022 this.ylo = ylo; 023 this.xhi = xhi; 024 this.yhi = yhi; 025 crosscounts = new int[yranges.length / 2]; 026 } 027 028 public final boolean covers(double ystart, double yend) { 029 int i = 0; 030 while (i < limit) { 031 double ylo = yranges[i++]; 032 double yhi = yranges[i++]; 033 if (ystart >= yhi) { 034 continue; 035 } 036 if (ystart < ylo) { 037 return false; 038 } 039 if (yend <= yhi) { 040 return true; 041 } 042 ystart = yhi; 043 } 044 return (ystart >= yend); 045 } 046 047 public void remove(int cur) { 048 limit -= 2; 049 int rem = limit - cur; 050 if (rem > 0) { 051 System.arraycopy(yranges, cur + 2, yranges, cur, rem); 052 System.arraycopy(crosscounts, cur / 2 + 1, 053 crosscounts, cur / 2, 054 rem / 2); 055 } 056 } 057 058 public void insert(int cur, double lo, double hi, int dir) { 059 int rem = limit - cur; 060 double oldranges[] = yranges; 061 int oldcounts[] = crosscounts; 062 if (limit >= yranges.length) { 063 yranges = new double[limit + 10]; 064 System.arraycopy(oldranges, 0, yranges, 0, cur); 065 crosscounts = new int[(limit + 10) / 2]; 066 System.arraycopy(oldcounts, 0, crosscounts, 0, cur / 2); 067 } 068 if (rem > 0) { 069 System.arraycopy(oldranges, cur, yranges, cur + 2, rem); 070 System.arraycopy(oldcounts, cur / 2, 071 crosscounts, cur / 2 + 1, 072 rem / 2); 073 } 074 yranges[cur + 0] = lo; 075 yranges[cur + 1] = hi; 076 crosscounts[cur / 2] = dir; 077 limit += 2; 078 } 079 080 public void record(double ystart, double yend, int direction) { 081 if (ystart >= yend) { 082 return; 083 } 084 int cur = 0; 085 // Quickly jump over all pairs that are completely "above" 086 while (cur < limit && ystart > yranges[cur + 1]) { 087 cur += 2; 088 } 089 if (cur < limit) { 090 int rdir = crosscounts[cur / 2]; 091 double yrlo = yranges[cur + 0]; 092 double yrhi = yranges[cur + 1]; 093 if (yrhi == ystart && rdir == direction) { 094 // Remove the range from the list and collapse it 095 // into the range being inserted. Note that the 096 // new combined range may overlap the following range 097 // so we must not simply combine the ranges in place 098 // unless we are at the last range. 099 if (cur + 2 == limit) { 100 yranges[cur + 1] = yend; 101 return; 102 } 103 remove(cur); 104 ystart = yrlo; 105 rdir = crosscounts[cur / 2]; 106 yrlo = yranges[cur + 0]; 107 yrhi = yranges[cur + 1]; 108 } 109 if (yend < yrlo) { 110 // Just insert the new range at the current location 111 insert(cur, ystart, yend, direction); 112 return; 113 } 114 if (yend == yrlo && rdir == direction) { 115 // Just prepend the new range to the current one 116 yranges[cur] = ystart; 117 return; 118 } 119 // The ranges must overlap - (yend > yrlo && yrhi > ystart) 120 if (ystart < yrlo) { 121 insert(cur, ystart, yrlo, direction); 122 cur += 2; 123 ystart = yrlo; 124 } else if (yrlo < ystart) { 125 insert(cur, yrlo, ystart, rdir); 126 cur += 2; 127 yrlo = ystart; 128 } 129 // assert(yrlo == ystart); 130 int newdir = rdir + direction; 131 double newend = Math.min(yend, yrhi); 132 if (newdir == 0) { 133 remove(cur); 134 } else { 135 crosscounts[cur / 2] = newdir; 136 yranges[cur++] = ystart; 137 yranges[cur++] = newend; 138 } 139 ystart = yrlo = newend; 140 if (yrlo < yrhi) { 141 insert(cur, yrlo, yrhi, rdir); 142 } 143 } 144 if (ystart < yend) { 145 insert(cur, ystart, yend, direction); 146 } 147 } 148 149 public final double getXLo() { 150 return xlo; 151 } 152 153 public final double getYLo() { 154 return ylo; 155 } 156 157 public final double getXHi() { 158 return xhi; 159 } 160 161 public final double getYHi() { 162 return yhi; 163 } 164 public final boolean isEmpty() { 165 return (limit == 0); 166 } 167 public boolean accumulateLine(double x0, double y0, 168 double x1, double y1) 169 { 170 if (y0 <= y1) { 171 return accumulateLine2(x0, y0, x1, y1, 1); 172 } else { 173 return accumulateLine2(x1, y1, x0, y0, -1); 174 } 175 } 176 177 public boolean accumulateLine2(double x0, double y0, 178 double x1, double y1, 179 int direction) 180 { 181 if (yhi <= y0 || ylo >= y1) { 182 return false; 183 } 184 if (x0 >= xhi && x1 >= xhi) { 185 return false; 186 } 187 if (y0 == y1) { 188 return (x0 >= xlo || x1 >= xlo); 189 } 190 double xstart, ystart, xend, yend; 191 double dx = (x1 - x0); 192 double dy = (y1 - y0); 193 if (y0 < ylo) { 194 xstart = x0 + (ylo - y0) * dx / dy; 195 ystart = ylo; 196 } else { 197 xstart = x0; 198 ystart = y0; 199 } 200 if (yhi < y1) { 201 xend = x0 + (yhi - y0) * dx / dy; 202 yend = yhi; 203 } else { 204 xend = x1; 205 yend = y1; 206 } 207 if (xstart >= xhi && xend >= xhi) { 208 return false; 209 } 210 if (xstart > xlo || xend > xlo) { 211 return true; 212 } 213 record(ystart, yend, direction); 214 return false; 215 } 216}