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