001/* 002 * $Id$ 003 */ 004 005package edu.jas.root; 006 007 008import java.io.Serializable; 009 010import edu.jas.arith.BigDecimal; 011import edu.jas.arith.BigRational; 012import edu.jas.arith.Rational; 013import edu.jas.poly.Complex; 014import edu.jas.poly.ComplexRing; 015import edu.jas.structure.ElemFactory; 016import edu.jas.structure.RingElem; 017import edu.jas.structure.RingFactory; 018 019 020/** 021 * Rectangle. For example isolating rectangle for complex roots. 022 * @param <C> coefficient type. 023 * @author Heinz Kredel 024 */ 025public class Rectangle<C extends RingElem<C> & Rational> implements Serializable { 026 027 028 /** 029 * rectangle corners. 030 */ 031 public final Complex<C>[] corners; 032 033 034 /** 035 * Constructor. 036 * @param c array of corners. 037 */ 038 @SuppressWarnings("unchecked") 039 /*package*/ Rectangle(Complex<C>[] c) { 040 if (c.length < 5) { 041 corners = (Complex<C>[]) new Complex[5]; 042 for (int i = 0; i < 4; i++) { 043 corners[i] = c[i]; 044 } 045 } else { 046 corners = c; 047 } 048 if (corners[4] == null) { 049 corners[4] = corners[0]; 050 } 051 } 052 053 054 /** 055 * Constructor. 056 * @param mid corner. 057 */ 058 @SuppressWarnings("unchecked") 059 public Rectangle(Complex<C> mid) { 060 this(mid, mid); 061 } 062 063 064 /** 065 * Constructor. 066 * @param sw corner. 067 * @param ne corner. 068 */ 069 @SuppressWarnings("unchecked") 070 public Rectangle(Complex<C> sw, Complex<C> ne) { 071 this(new Complex<C>(sw.ring, sw.getRe(), ne.getIm()), sw, 072 new Complex<C>(sw.ring, ne.getRe(), sw.getIm()), ne); 073 } 074 075 076 /** 077 * Constructor. 078 * 079 * <pre> 080 * nw|0 ne|3 081 * sw|1 se|2 082 * </pre> 083 * 084 * @param nw corner. 085 * @param sw corner. 086 * @param se corner. 087 * @param ne corner. 088 */ 089 @SuppressWarnings("unchecked") 090 public Rectangle(Complex<C> nw, Complex<C> sw, Complex<C> se, Complex<C> ne) { 091 this((Complex<C>[]) new Complex[] { nw, sw, se, ne }); 092 } 093 094 095 /** 096 * String representation of Rectangle. 097 * @see java.lang.Object#toString() 098 */ 099 @Override 100 public String toString() { 101 //return "[" + corners[0] + ", " + corners[1] + ", " + corners[2] + ", " + corners[3] + "]"; 102 return "[" + corners[1] + ", " + corners[3] + "]"; 103 //return centerApprox() + " = [" + corners[0] + ", " + corners[1] + ", " + corners[2] + ", " + corners[3] + "]"; 104 } 105 106 107 /** 108 * Get a scripting compatible string representation. 109 * @return script compatible representation for this Rectangle. 110 */ 111 public String toScript() { 112 // Python case 113 //return "(" + corners[0] + ", " + corners[1] + ", " + corners[2] + ", " + corners[3] + ")"; 114 return "(" + corners[1].toScript() + ", " + corners[3].toScript() + ")"; 115 } 116 117 118 /** 119 * Get north west corner. 120 * @return north west corner of this rectangle. 121 */ 122 public Complex<C> getNW() { 123 return corners[0]; 124 } 125 126 127 /** 128 * Get south west corner. 129 * @return south west corner of this rectangle. 130 */ 131 public Complex<C> getSW() { 132 return corners[1]; 133 } 134 135 136 /** 137 * Get south east corner. 138 * @return south east corner of this rectangle. 139 */ 140 public Complex<C> getSE() { 141 return corners[2]; 142 } 143 144 145 /** 146 * Get north east corner. 147 * @return north east corner of this rectangle. 148 */ 149 public Complex<C> getNE() { 150 return corners[3]; 151 } 152 153 154 /** 155 * Exchange NW corner. 156 * @param c new NW corner. 157 * @return rectangle with north west corner c of this rectangle. 158 */ 159 public Rectangle<C> exchangeNW(Complex<C> c) { 160 Complex<C> d = getSE(); 161 Complex<C> sw = new Complex<C>(c.factory(), c.getRe(), d.getIm()); 162 Complex<C> ne = new Complex<C>(c.factory(), d.getRe(), c.getIm()); 163 return new Rectangle<C>(c, sw, d, ne); 164 } 165 166 167 /** 168 * Exchange SW corner. 169 * @param c new SW corner. 170 * @return rectangle with south west corner c of this rectangle. 171 */ 172 public Rectangle<C> exchangeSW(Complex<C> c) { 173 Complex<C> d = getNE(); 174 Complex<C> nw = new Complex<C>(c.factory(), c.getRe(), d.getIm()); 175 Complex<C> se = new Complex<C>(c.factory(), d.getRe(), c.getIm()); 176 return new Rectangle<C>(nw, c, se, d); 177 } 178 179 180 /** 181 * Exchange SE corner. 182 * @param c new SE corner. 183 * @return rectangle with south east corner c of this rectangle. 184 */ 185 public Rectangle<C> exchangeSE(Complex<C> c) { 186 Complex<C> d = getNW(); 187 Complex<C> sw = new Complex<C>(c.factory(), d.getRe(), c.getIm()); 188 Complex<C> ne = new Complex<C>(c.factory(), c.getRe(), d.getIm()); 189 return new Rectangle<C>(d, sw, c, ne); 190 } 191 192 193 /** 194 * Exchange NE corner. 195 * @param c new NE corner. 196 * @return rectangle with north east corner c of this rectangle. 197 */ 198 public Rectangle<C> exchangeNE(Complex<C> c) { 199 Complex<C> d = getSW(); 200 Complex<C> nw = new Complex<C>(c.factory(), d.getRe(), c.getIm()); 201 Complex<C> se = new Complex<C>(c.factory(), c.getRe(), d.getIm()); 202 return new Rectangle<C>(nw, d, se, c); 203 } 204 205 206 /** 207 * Contains a point. 208 * @param c point. 209 * @return true if c is contained in this rectangle, else false. 210 */ 211 public boolean contains(Complex<C> c) { 212 Complex<C> ll = getSW(); 213 Complex<C> ur = getNE(); // ?? Fix ?? getSW(); 214 C cre = c.getRe(); 215 C cim = c.getIm(); 216 return cre.compareTo(ll.getRe()) >= 0 && cim.compareTo(ll.getIm()) >= 0 217 && cre.compareTo(ur.getRe()) <= 0 && cim.compareTo(ur.getIm()) <= 0; 218 } 219 220 221 /** 222 * Contains a rectangle. 223 * @param r rectangle. 224 * @return true if r is contained in this rectangle, else false. 225 */ 226 public boolean contains(Rectangle<C> r) { 227 return contains(r.getSW()) && contains(r.getNE()); // && contains(r.getSE()) && contains(r.getNW()) 228 } 229 230 231 /** 232 * Random point of recatangle. 233 * @return a random point contained in this rectangle. 234 */ 235 public Complex<C> randomPoint() { 236 Complex<C> sw = getSW(); 237 Complex<C> se = getSE(); 238 Complex<C> nw = getNW(); 239 Complex<C> r = sw.factory().random(13); 240 C dr = se.getRe().subtract(sw.getRe()); // >= 0 241 C di = nw.getIm().subtract(sw.getIm()); // >= 0 242 C rr = r.getRe().abs(); 243 C ri = r.getIm().abs(); 244 C one = ((RingFactory<C>) dr.factory()).getONE(); 245 if (!rr.isZERO()) { 246 if (rr.compareTo(one) > 0) { 247 rr = rr.inverse(); 248 } 249 } 250 if (!ri.isZERO()) { 251 if (ri.compareTo(one) > 0) { 252 ri = ri.inverse(); 253 } 254 } 255 // 0 <= rr, ri <= 1 256 rr = rr.multiply(dr); 257 ri = ri.multiply(di); 258 Complex<C> rp = new Complex<C>(sw.factory(), rr, ri); 259 //System.out.println("rp = " + rp); 260 rp = sw.sum(rp); 261 return rp; 262 } 263 264 265 /** 266 * Copy this. 267 * @return a copy of this. 268 */ 269 public Rectangle<C> copy() { 270 return new Rectangle<C>(corners); 271 } 272 273 274 /** 275 * Comparison with any other object. 276 * @see java.lang.Object#equals(java.lang.Object) 277 */ 278 @Override 279 @SuppressWarnings("unchecked") 280 public boolean equals(Object b) { 281 if (!(b instanceof Rectangle)) { 282 return false; 283 } 284 Rectangle<C> a = null; 285 try { 286 a = (Rectangle<C>) b; 287 } catch (ClassCastException e) { 288 return false; 289 } 290 for (int i = 0; i < 4; i++) { 291 if (!corners[i].equals(a.corners[i])) { 292 return false; 293 } 294 } 295 return true; 296 } 297 298 299 /** 300 * Hash code for this Rectangle. 301 * @see java.lang.Object#hashCode() 302 */ 303 @Override 304 public int hashCode() { 305 int hc = 0; 306 for (int i = 0; i < 3; i++) { 307 hc += 37 * corners[i].hashCode(); 308 } 309 return 37 * hc + corners[3].hashCode(); 310 } 311 312 313 /** 314 * Complex center. 315 * @return r + i m of the center. 316 */ 317 public Complex<C> getCenter() { 318 C r = corners[2].getRe().subtract(corners[1].getRe()); 319 C m = corners[0].getIm().subtract(corners[1].getIm()); 320 ElemFactory<C> rf = r.factory(); 321 C two = rf.fromInteger(2); 322 r = r.divide(two); 323 m = m.divide(two); 324 r = corners[1].getRe().sum(r); 325 m = corners[1].getIm().sum(m); 326 return new Complex<C>(corners[0].factory(), r, m); 327 } 328 329 330 /** 331 * Complex of BigRational approximation of center. 332 * @return r + i m as rational approximation of the center. 333 */ 334 public Complex<BigRational> getRationalCenter() { 335 Complex<C> cm = getCenter(); 336 BigRational rs = cm.getRe().getRational(); 337 BigRational ms = cm.getIm().getRational(); 338 ComplexRing<BigRational> cf = new ComplexRing<BigRational>(rs.factory()); 339 Complex<BigRational> c = new Complex<BigRational>(cf, rs, ms); 340 return c; 341 } 342 343 344 /** 345 * Complex of BigDecimal approximation of center. 346 * @return r + i m as decimal approximation of the center. 347 */ 348 public Complex<BigDecimal> getDecimalCenter() { 349 Complex<BigRational> rc = getRationalCenter(); 350 BigDecimal rd = new BigDecimal(rc.getRe()); 351 BigDecimal md = new BigDecimal(rc.getIm()); 352 ComplexRing<BigDecimal> cf = new ComplexRing<BigDecimal>(rd.factory()); 353 Complex<BigDecimal> c = new Complex<BigDecimal>(cf, rd, md); 354 return c; 355 } 356 357 358 /** 359 * Approximation of center. 360 * @return r + i m as string of decimal approximation of the center. 361 */ 362 public String centerApprox() { 363 Complex<BigDecimal> c = getDecimalCenter(); 364 StringBuffer s = new StringBuffer(); 365 s.append("[ "); 366 s.append(c.getRe().toString()); 367 s.append(" i "); 368 s.append(c.getIm().toString()); 369 s.append(" ]"); 370 return s.toString(); 371 } 372 373 374 /** 375 * Length. 376 * @return |ne-sw|**2; 377 */ 378 public C length() { 379 Complex<C> m = corners[3].subtract(corners[1]); 380 return m.norm().getRe(); 381 } 382 383 384 /** 385 * Rational Length. 386 * @return rational(|ne-sw|**2); 387 */ 388 public BigRational rationalLength() { 389 //BigRational r = new BigRational(length().toString()); 390 return length().getRational(); 391 } 392 393 394 /** 395 * Length real side. 396 * @return |re(ne)-re(sw)|; 397 */ 398 public C lengthReal() { 399 C m = corners[3].getRe().subtract(corners[1].getRe()); 400 return m.abs(); 401 } 402 403 404 /** 405 * Length imaginary side. 406 * @return |im(ne)-im(sw)|; 407 */ 408 public C lengthImag() { 409 C m = corners[3].getIm().subtract(corners[1].getIm()); 410 return m.abs(); 411 } 412 413}