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 SomeOp { 012 public static final int SUBOP = 0; 013 public static final int ADDOP = 1; 014 public static final int INTOP = 2; 015 public static final int XOROP = 3; 016 017 public SomeOp(int type) 018 { 019 _type=type; 020 } 021 private int _type=-1; 022 boolean inLeft; 023 boolean inRight; 024 boolean inResult; 025 026 public void newRow() { 027 inLeft = false; 028 inRight = false; 029 inResult = false; 030 } 031 032 public int classify(Edge e) { 033 if (e.getCurveTag() == AreaOp2.CTAG_LEFT) { 034 inLeft = !inLeft; 035 } else { 036 inRight = !inRight; 037 } 038 boolean newClass = newClassification(inLeft, inRight); 039 if (inResult == newClass) { 040 return AreaOp2.ETAG_IGNORE; 041 } 042 inResult = newClass; 043 return (newClass ? AreaOp2.ETAG_ENTER : AreaOp2.ETAG_EXIT); 044 } 045 046 public int getState() { 047 return (inResult ? AreaOp2.RSTAG_INSIDE : AreaOp2.RSTAG_OUTSIDE); 048 } 049 public boolean newClassification(boolean inLeft, boolean inRight) { 050 switch(_type) 051 { 052 case ADDOP: 053 return (inLeft || inRight); 054 case SUBOP: 055 return (inLeft && !inRight); 056 case INTOP: 057 return (inLeft && inRight); 058 case XOROP: 059 return (inLeft != inRight); 060 default: 061 return false; 062 063 } 064 } 065 066 067 //all the code from AreaOp that this class extends 068 public Vector calculate(Vector left, Vector right) { 069 Vector edges = new Vector(); 070 addEdges(edges, left, AreaOp2.CTAG_LEFT); 071 addEdges(edges, right, AreaOp2.CTAG_RIGHT); 072 edges = pruneEdges(edges); 073 if (false) { 074 System.out.println("result: "); 075 int numcurves = edges.size(); 076 //Curve[] curvelist = (Curve[]) edges.toArray(new Curve[numcurves]); 077 Curve[] curvelist = (Curve[]) edges.toArray2(); 078 for (int i = 0; i < numcurves; i++) { 079 System.out.println("curvelist["+i+"] = "+curvelist[i]); 080 } 081 } 082 return edges; 083 } 084 085 private static void addEdges(Vector edges, Vector curves, int curvetag) { 086 Enumeration enum_ = curves.elements(); 087 CurveObject c=null; 088 Object obj=null; 089 while (enum_.hasMoreElements()) { 090 //CurveObject c = (CurveObject) enum_.nextElement(); 091 obj=enum_.nextElement(); 092 if(obj instanceof CurveObject) 093 c=(CurveObject)obj; 094 else 095 c=new CurveObject(obj); 096 if (c.getOrder() > 0) { 097 edges.add(new Edge(c, curvetag)); 098 } 099 } 100 } 101 102 private Vector pruneEdges(Vector edges) { 103 int numedges = edges.size(); 104 if (numedges < 2) { 105 return edges; 106 } 107 //Edge[] edgelist = (Edge[]) edges.toArray(new Edge[numedges]); 108 //Edge[] edgelist = (Edge[]) edges.toArray(); 109 Edge[] edgelist = new Edge[numedges]; 110 Enumeration _enum=edges.elements(); 111 int k=0; 112 while(_enum.hasMoreElements()) 113 { 114 edgelist[k++]=(Edge)_enum.nextElement(); 115 } 116 //Arrays.sort(edgelist, YXTopComparator); 117 Arrays.sort(edgelist); 118 if (false) { 119 System.out.println("pruning: "); 120 for (int i = 0; i < numedges; i++) { 121 System.out.println("edgelist["+i+"] = "+edgelist[i]); 122 } 123 } 124 Edge e; 125 int left = 0; 126 int right = 0; 127 int cur = 0; 128 int next = 0; 129 double yrange[] = new double[2]; 130 Vector subcurves = new Vector(); 131 Vector chains = new Vector(); 132 Vector links = new Vector(); 133 // Active edges are between left (inclusive) and right (exclusive) 134 while (left < numedges) { 135 double y = yrange[0]; 136 // Prune active edges that fall off the top of the active y range 137 for (cur = next = right - 1; cur >= left; cur--) { 138 e = edgelist[cur]; 139 if (e.getCurve().getYBot() > y) { 140 if (next > cur) { 141 edgelist[next] = e; 142 } 143 next--; 144 } 145 } 146 left = next + 1; 147 // Grab a new "top of Y range" if the active edges are empty 148 if (left >= right) { 149 if (right >= numedges) { 150 break; 151 } 152 y = edgelist[right].getCurve().getYTop(); 153 if (y > yrange[0]) { 154 finalizeSubCurves(subcurves, chains); 155 } 156 yrange[0] = y; 157 } 158 // Incorporate new active edges that enter the active y range 159 while (right < numedges) { 160 e = edgelist[right]; 161 if (e.getCurve().getYTop() > y) { 162 break; 163 } 164 right++; 165 } 166 // Sort the current active edges by their X values and 167 // determine the maximum valid Y range where the X ordering 168 // is correct 169 yrange[1] = edgelist[left].getCurve().getYBot(); 170 if (right < numedges) { 171 y = edgelist[right].getCurve().getYTop(); 172 if (yrange[1] > y) { 173 yrange[1] = y; 174 } 175 } 176 if (false) { 177 System.out.println("current line: y = ["+ 178 yrange[0]+", "+yrange[1]+"]"); 179 for (cur = left; cur < right; cur++) { 180 System.out.println(" "+edgelist[cur]); 181 } 182 } 183 // Note: We could start at left+1, but we need to make 184 // sure that edgelist[left] has its equivalence set to 0. 185 int nexteq = 1; 186 for (cur = left; cur < right; cur++) { 187 e = edgelist[cur]; 188 e.setEquivalence(0); 189 for (next = cur; next > left; next--) { 190 Edge prevedge = edgelist[next-1]; 191 int ordering = e.compareTo(prevedge, yrange); 192 if (yrange[1] <= yrange[0]) { 193 throw new InternalError("backstepping to "+yrange[1]+ 194 " from "+yrange[0]); 195 } 196 if (ordering >= 0) { 197 if (ordering == 0) { 198 // If the curves are equal, mark them to be 199 // deleted later if they cancel each other 200 // out so that we avoid having extraneous 201 // curve segments. 202 int eq = prevedge.getEquivalence(); 203 if (eq == 0) { 204 eq = nexteq++; 205 prevedge.setEquivalence(eq); 206 } 207 e.setEquivalence(eq); 208 } 209 break; 210 } 211 edgelist[next] = prevedge; 212 } 213 edgelist[next] = e; 214 } 215 if (false) { 216 System.out.println("current sorted line: y = ["+ 217 yrange[0]+", "+yrange[1]+"]"); 218 for (cur = left; cur < right; cur++) { 219 System.out.println(" "+edgelist[cur]); 220 } 221 } 222 // Now prune the active edge list. 223 // For each edge in the list, determine its classification 224 // (entering shape, exiting shape, ignore - no change) and 225 // record the current Y range and its classification in the 226 // Edge object for use later in constructing the new outline. 227 newRow(); 228 double ystart = yrange[0]; 229 double yend = yrange[1]; 230 for (cur = left; cur < right; cur++) { 231 e = edgelist[cur]; 232 int etag; 233 int eq = e.getEquivalence(); 234 if (eq != 0) { 235 // Find one of the segments in the "equal" range 236 // with the right transition state and prefer an 237 // edge that was either active up until ystart 238 // or the edge that extends the furthest downward 239 // (i.e. has the most potential for continuation) 240 int origstate = getState(); 241 etag = (origstate == AreaOp2.RSTAG_INSIDE 242 ? AreaOp2.ETAG_EXIT 243 : AreaOp2.ETAG_ENTER); 244 Edge activematch = null; 245 Edge longestmatch = e; 246 double furthesty = yend; 247 do { 248 // Note: classify() must be called 249 // on every edge we consume here. 250 classify(e); 251 if (activematch == null && 252 e.isActiveFor(ystart, etag)) 253 { 254 activematch = e; 255 } 256 y = e.getCurve().getYBot(); 257 if (y > furthesty) { 258 longestmatch = e; 259 furthesty = y; 260 } 261 } while (++cur < right && 262 (e = edgelist[cur]).getEquivalence() == eq); 263 --cur; 264 if (getState() == origstate) { 265 etag = AreaOp2.ETAG_IGNORE; 266 } else { 267 e = (activematch != null ? activematch : longestmatch); 268 } 269 } else { 270 etag = classify(e); 271 } 272 if (etag != AreaOp2.ETAG_IGNORE) { 273 e.record(yend, etag); 274 links.add(new CurveLink(e.getCurve(), ystart, yend, etag)); 275 } 276 } 277 // assert(getState() == AreaOp.RSTAG_OUTSIDE); 278 if (getState() != AreaOp2.RSTAG_OUTSIDE) { 279 System.out.println("Still inside at end of active edge list!"); 280 System.out.println("num curves = "+(right-left)); 281 System.out.println("num links = "+links.size()); 282 System.out.println("y top = "+yrange[0]); 283 if (right < numedges) { 284 System.out.println("y top of next curve = "+ 285 edgelist[right].getCurve().getYTop()); 286 } else { 287 System.out.println("no more curves"); 288 } 289 for (cur = left; cur < right; cur++) { 290 e = edgelist[cur]; 291 System.out.println(e); 292 int eq = e.getEquivalence(); 293 if (eq != 0) { 294 System.out.println(" was equal to "+eq+"..."); 295 } 296 } 297 } 298 if (false) { 299 System.out.println("new links:"); 300 for (int i = 0; i < links.size(); i++) { 301 CurveLink link = (CurveLink) links.elementAt(i); 302 System.out.println(" "+link.getSubCurve()); 303 } 304 } 305 resolveLinks(subcurves, chains, links); 306 links.clear(); 307 // Finally capture the bottom of the valid Y range as the top 308 // of the next Y range. 309 yrange[0] = yend; 310 } 311 finalizeSubCurves(subcurves, chains); 312 Vector ret = new Vector(); 313 Enumeration enum_ = subcurves.elements(); 314 CurveObject c=null; 315 Object obj=null; 316 while (enum_.hasMoreElements()) { 317 CurveLink link = (CurveLink) enum_.nextElement(); 318 ret.add(link.getMoveto()); 319 CurveLink nextlink = link; 320 while ((nextlink = nextlink.getNext()) != null) { 321 if (!link.absorb(nextlink)) 322 { 323 //ret.add(link.getSubCurve()); 324 obj=link.getSubCurve(); 325// if(! (obj instanceof CurveObject) ) 326// { 327// CurveObject c=new CurveObject(obj); 328// ret.add(c); 329// } 330// else 331// ret.add(link.getSubCurve()); 332 if(obj instanceof Order0) 333 c=((Order0)obj).getParent(); 334 else if(obj instanceof Order1) 335 c=((Order1)obj).getParent(); 336 else if(obj instanceof Order2) 337 c=((Order2)obj).getParent(); 338 else if(obj instanceof Order3) 339 c=((Order3)obj).getParent(); 340 else if(obj instanceof CurveObject) 341 c=(CurveObject)obj; 342 if(c==null) 343 c=new CurveObject(obj); 344 345 346 ret.add(c); 347 link = nextlink; 348 } 349 } 350 obj=link.getSubCurve(); 351 //ret.add(link.getSubCurve()); 352 if(obj instanceof Order0) 353 c=((Order0)obj).getParent(); 354 else if(obj instanceof Order1) 355 c=((Order1)obj).getParent(); 356 else if(obj instanceof Order2) 357 c=((Order2)obj).getParent(); 358 else if(obj instanceof Order3) 359 c=((Order3)obj).getParent(); 360 else if(obj instanceof CurveObject) 361 c=(CurveObject)obj; 362 if(c==null) 363 c=new CurveObject(obj); 364 365 ret.add(c); 366 } 367 return ret; 368 } 369 370 public static void finalizeSubCurves(Vector subcurves, Vector chains) { 371 int numchains = chains.size(); 372 if (numchains == 0) { 373 return; 374 } 375 if ((numchains & 1) != 0) { 376 throw new InternalError("Odd number of chains!"); 377 } 378 ChainEnd[] endlist = new ChainEnd[numchains]; 379 chains.toArray(endlist); 380 for (int i = 1; i < numchains; i += 2) { 381 ChainEnd open = endlist[i - 1]; 382 ChainEnd close = endlist[i]; 383 CurveLink subcurve = open.linkTo(close); 384 if (subcurve != null) { 385 subcurves.add(subcurve); 386 } 387 } 388 chains.clear(); 389 } 390 391 private static CurveLink[] EmptyLinkList = new CurveLink[2]; 392 private static ChainEnd[] EmptyChainList = new ChainEnd[2]; 393 394 public static void resolveLinks(Vector subcurves, 395 Vector chains, 396 Vector links) 397 { 398 int numlinks = links.size(); 399 CurveLink[] linklist; 400 if (numlinks == 0) { 401 linklist = EmptyLinkList; 402 } else { 403 if ((numlinks & 1) != 0) { 404 throw new InternalError("Odd number of new curves!"); 405 } 406 linklist = new CurveLink[numlinks+2]; 407 links.toArray(linklist); 408 } 409 int numchains = chains.size(); 410 ChainEnd[] endlist; 411 if (numchains == 0) { 412 endlist = EmptyChainList; 413 } else { 414 if ((numchains & 1) != 0) { 415 throw new InternalError("Odd number of chains!"); 416 } 417 endlist = new ChainEnd[numchains+2]; 418 chains.toArray(endlist); 419 } 420 int curchain = 0; 421 int curlink = 0; 422 chains.clear(); 423 ChainEnd chain = endlist[0]; 424 ChainEnd nextchain = endlist[1]; 425 CurveLink link = linklist[0]; 426 CurveLink nextlink = linklist[1]; 427 while (chain != null || link != null) { 428 /* 429 * Strategy 1: 430 * Connect chains or links if they are the only things left... 431 */ 432 boolean connectchains = (link == null); 433 boolean connectlinks = (chain == null); 434 435 if (!connectchains && !connectlinks) { 436 // assert(link != null && chain != null); 437 /* 438 * Strategy 2: 439 * Connect chains or links if they close off an open area... 440 */ 441 connectchains = ((curchain & 1) == 0 && 442 chain.getX() == nextchain.getX()); 443 connectlinks = ((curlink & 1) == 0 && 444 link.getX() == nextlink.getX()); 445 446 if (!connectchains && !connectlinks) { 447 /* 448 * Strategy 3: 449 * Connect chains or links if their successor is 450 * between them and their potential connectee... 451 */ 452 double cx = chain.getX(); 453 double lx = link.getX(); 454 connectchains = 455 (nextchain != null && cx < lx && 456 obstructs(nextchain.getX(), lx, curchain)); 457 connectlinks = 458 (nextlink != null && lx < cx && 459 obstructs(nextlink.getX(), cx, curlink)); 460 } 461 } 462 if (connectchains) { 463 CurveLink subcurve = chain.linkTo(nextchain); 464 if (subcurve != null) { 465 subcurves.add(subcurve); 466 } 467 curchain += 2; 468 chain = endlist[curchain]; 469 nextchain = endlist[curchain+1]; 470 } 471 if (connectlinks) { 472 ChainEnd openend = new ChainEnd(link, null); 473 ChainEnd closeend = new ChainEnd(nextlink, openend); 474 openend.setOtherEnd(closeend); 475 chains.add(openend); 476 chains.add(closeend); 477 curlink += 2; 478 link = linklist[curlink]; 479 nextlink = linklist[curlink+1]; 480 } 481 if (!connectchains && !connectlinks) { 482 // assert(link != null); 483 // assert(chain != null); 484 // assert(chain.getEtag() == link.getEtag()); 485 chain.addLink(link); 486 chains.add(chain); 487 curchain++; 488 chain = nextchain; 489 nextchain = endlist[curchain+1]; 490 curlink++; 491 link = nextlink; 492 nextlink = linklist[curlink+1]; 493 } 494 } 495 if ((chains.size() & 1) != 0) { 496 System.out.println("Odd number of chains!"); 497 } 498 } 499 500 /* 501 * Does the position of the next edge at v1 "obstruct" the 502 * connectivity between current edge and the potential 503 * partner edge which is positioned at v2? 504 * 505 * Phase tells us whether we are testing for a transition 506 * into or out of the interior part of the resulting area. 507 * 508 * Require 4-connected continuity if this edge and the partner 509 * edge are both "entering into" type edges 510 * Allow 8-connected continuity for "exiting from" type edges 511 */ 512 public static boolean obstructs(double v1, double v2, int phase) { 513 return (((phase & 1) == 0) ? (v1 <= v2) : (v1 < v2)); 514 } 515 516}