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 }