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