1 /*
2  *  (C) 2001 by Argonne National Laboratory
3  *      See COPYRIGHT in top-level directory.
4  */
5 
6 /*
7  *  @author  Anthony Chan
8  */
9 
10 package base.drawable;
11 
12 import java.util.Comparator;
13 import java.io.DataOutput;
14 import java.io.DataInput;
15 
16 import base.io.DataIO;
17 
18 public class TimeBoundingBox implements DataIO
19 {
20     public  static final TimeBoundingBox  ALL_TIMES
21                          = new TimeBoundingBox( Double.NEGATIVE_INFINITY,
22                                                 Double.POSITIVE_INFINITY );
23 
24     public  static final Order            INCRE_STARTTIME_ORDER
25                          = new IncreasingStarttimeOrder();
26 
27     public  static final Order            DECRE_STARTTIME_ORDER
28                          = new DecreasingStarttimeOrder();
29 
30     public  static final Order            INCRE_FINALTIME_ORDER
31                          = new IncreasingFinaltimeOrder();
32 
33     public  static final Order            DECRE_FINALTIME_ORDER
34                          = new DecreasingFinaltimeOrder();
35 
36     public  static final int              BYTESIZE = 8  /* earliest_time */
37                                                    + 8  /* latest_time */  ;
38 
39     private              double           earliest_time;
40     private              double           latest_time;
41 
TimeBoundingBox()42     public TimeBoundingBox()
43     {
44         earliest_time = Double.POSITIVE_INFINITY;
45         latest_time   = Double.NEGATIVE_INFINITY;
46     }
47 
TimeBoundingBox( final TimeBoundingBox timebox )48     public TimeBoundingBox( final TimeBoundingBox timebox )
49     {
50         earliest_time = timebox.earliest_time;
51         latest_time   = timebox.latest_time;
52     }
53 
TimeBoundingBox( final Coord[] vtxs )54     public TimeBoundingBox( final Coord[] vtxs )
55     {
56         if ( vtxs != null ) {
57             earliest_time  = latest_time  = vtxs[ 0 ].time;
58             for ( int idx = 1; idx < vtxs.length; idx++ ) {
59                 this.affectEarliestTime( vtxs[ idx ].time );
60                 this.affectLatestTime( vtxs[ idx ].time );
61             }
62         }
63         else {
64             earliest_time = Double.POSITIVE_INFINITY;
65             latest_time   = Double.NEGATIVE_INFINITY;
66         }
67     }
68 
TimeBoundingBox( double starttime, double finaltime )69     public TimeBoundingBox( double starttime, double finaltime )
70     {
71         earliest_time = starttime;
72         latest_time   = finaltime;
73     }
74 
reinitialize()75     public void reinitialize()
76     {
77         earliest_time = Double.POSITIVE_INFINITY;
78         latest_time   = Double.NEGATIVE_INFINITY;
79     }
80 
affectTimeBounds( final TimeBoundingBox endtimes )81     public void affectTimeBounds( final TimeBoundingBox endtimes )
82     {
83         this.affectEarliestTime( endtimes.getEarliestTime() );
84         this.affectLatestTime( endtimes.getLatestTime() );
85     }
86 
affectTimeBounds( final Coord vtx )87     public void affectTimeBounds( final Coord vtx )
88     {
89         this.affectEarliestTime( vtx.time );
90         this.affectLatestTime( vtx.time );
91     }
92 
affectTimeBounds( final Coord[] vtxs )93     public void affectTimeBounds( final Coord[] vtxs )
94     {
95         for ( int idx = 0; idx < vtxs.length; idx++ ) {
96             this.affectEarliestTime( vtxs[ idx ].time );
97             this.affectLatestTime( vtxs[ idx ].time );
98         }
99     }
100 
101 
affectEarliestTime( double in_time )102     public void affectEarliestTime( double in_time )
103     {
104         if ( in_time < earliest_time )
105             earliest_time = in_time;
106     }
107 
setEarliestTime( double in_time )108     public void setEarliestTime( double in_time )
109     {
110         earliest_time = in_time;
111     }
112 
getEarliestTime()113     public double getEarliestTime()
114     {
115         return earliest_time;
116     }
117 
118 
affectLatestTime( double in_time )119     public void affectLatestTime( double in_time )
120     {
121         if ( in_time > latest_time )
122             latest_time = in_time;
123     }
124 
setLatestTime( double in_time )125     public void setLatestTime( double in_time )
126     {
127         latest_time = in_time;
128     }
129 
getLatestTime()130     public double getLatestTime()
131     {
132         return latest_time;
133     }
134 
135 
getBorderTime( boolean isStartTime )136     public double getBorderTime( boolean isStartTime )
137     {
138         if ( isStartTime )
139             return earliest_time;
140         else
141             return latest_time;
142     }
143 
144 
145     // Functions useful in ScrollableObject
146     // This is used after this.setEarliestTime() is invoked.
147     // time_extent is positive definite
setLatestFromEarliest( double time_extent )148     public void setLatestFromEarliest( double time_extent )
149     {
150         latest_time = earliest_time + time_extent;
151     }
152 
153     // This is used after this.setLatestTime() is invoked.
154     // time_extent is positive definite
setEarliestFromLatest( double time_extent )155     public void setEarliestFromLatest( double time_extent )
156     {
157         earliest_time = latest_time - time_extent;
158     }
159 
isTimeOrdered()160     public boolean isTimeOrdered()
161     {
162         return earliest_time <= latest_time;
163     }
164 
165     // Return true when endtimes covers the one end of this.TimeBoundingBox
remove( final TimeBoundingBox endtimes )166     public boolean remove( final TimeBoundingBox  endtimes )
167     {
168         if ( this.earliest_time == endtimes.earliest_time ) {
169             this.earliest_time = endtimes.latest_time;
170             return true;
171         }
172         if ( this.latest_time == endtimes.latest_time ) {
173             this.latest_time = endtimes.earliest_time;
174             return true;
175         }
176         return false;
177     }
178 
179     //  TimeBoundingBox Checking Routines for SLOG-2 Input API
180     /*
181        Logic concerning overlaps(), covers() and disjoints()
182        1) covers()      implies  overlaps().
183        2) !overlaps()   implies  disjoints().
184        3) !disjoints()  implies  overlaps().
185     */
covers( final TimeBoundingBox endtimes )186     public boolean covers( final TimeBoundingBox endtimes )
187     {
188         return    ( this.earliest_time <= endtimes.earliest_time )
189                && ( endtimes.latest_time <= this.latest_time );
190     }
191 
overlaps( final TimeBoundingBox endtimes )192     public boolean overlaps( final TimeBoundingBox endtimes )
193     {
194         return    ( this.earliest_time <= endtimes.latest_time )
195                && ( endtimes.earliest_time <= this.latest_time );
196     }
197 
198     // For consistence: Avoid using disjoints(), use !overlaps() instead
disjoints( final TimeBoundingBox endtimes )199     public boolean disjoints( final TimeBoundingBox endtimes )
200     {
201         return    ( this.latest_time < endtimes.earliest_time )
202                || ( endtimes.latest_time < this.earliest_time );
203     }
204 
contains( double timestamp )205     public boolean contains( double timestamp )
206     {
207         return    ( this.earliest_time <= timestamp )
208                && ( timestamp <= this.latest_time );
209     }
210 
equals( final TimeBoundingBox endtimes )211     public boolean equals( final TimeBoundingBox endtimes )
212     {
213         return    ( this.earliest_time == endtimes.earliest_time )
214                && ( this.latest_time == endtimes.latest_time );
215     }
216 
217     /*
218        containsWithinLeft()/containsWithinRight() are for logformat.slog2.Print
219        Or they are for logformat.slog2.input.InputLog.iterator()
220     */
containsWithinLeft( double timestamp )221     public boolean containsWithinLeft( double timestamp )
222     {
223         return    ( this.earliest_time <= timestamp )
224                && ( timestamp < this.latest_time );
225     }
226 
containsWithinRight( double timestamp )227     public boolean containsWithinRight( double timestamp )
228     {
229         return    ( this.earliest_time < timestamp )
230                && ( timestamp <= this.latest_time );
231     }
232 
getIntersection( final TimeBoundingBox endtimes )233     public TimeBoundingBox getIntersection( final TimeBoundingBox endtimes )
234     {
235         TimeBoundingBox  intersect_endtimes;
236         double           intersect_earliest_time, intersect_latest_time;
237 
238         if ( this.overlaps( endtimes ) ) {
239             if ( this.earliest_time < endtimes.earliest_time )
240                 intersect_earliest_time = endtimes.earliest_time;
241             else
242                 intersect_earliest_time = this.earliest_time;
243             if ( this.latest_time < endtimes.latest_time )
244                 intersect_latest_time   = this.latest_time;
245             else
246                 intersect_latest_time   = endtimes.latest_time;
247             intersect_endtimes = new TimeBoundingBox();
248             intersect_endtimes.earliest_time  = intersect_earliest_time;
249             intersect_endtimes.latest_time    = intersect_latest_time;
250             return intersect_endtimes;
251         }
252         else
253             return null;
254     }
255 
getIntersectionDuration( final TimeBoundingBox endtimes )256     public double getIntersectionDuration( final TimeBoundingBox endtimes )
257     {
258         double           intersect_earliest_time, intersect_latest_time;
259         double           intersect_duration;
260 
261         if ( this.overlaps( endtimes ) ) {
262             if ( this.earliest_time < endtimes.earliest_time )
263                 intersect_earliest_time = endtimes.earliest_time;
264             else
265                 intersect_earliest_time = this.earliest_time;
266             if ( this.latest_time < endtimes.latest_time )
267                 intersect_latest_time   = this.latest_time;
268             else
269                 intersect_latest_time   = endtimes.latest_time;
270             intersect_duration  = intersect_latest_time
271                                 - intersect_earliest_time;
272             if ( intersect_duration > 0.0d )
273                 return intersect_duration;
274             else
275                 return 0.0d;
276         }
277         else
278             return 0.0d;
279     }
280 
281     /* For SLOG-2 Input API & viewer */
getDuration()282     public double getDuration()
283     {
284         return latest_time - earliest_time;
285     }
286 
setZeroDuration( double time )287     public void setZeroDuration( double time )
288     {
289         earliest_time = time;
290         latest_time   = time;
291     }
292 
293 
writeObject( final TimeBoundingBox timebox, DataOutput outs )294     public static void writeObject( final TimeBoundingBox  timebox,
295                                           DataOutput       outs )
296     throws java.io.IOException
297     {
298         outs.writeDouble( timebox.earliest_time );
299         outs.writeDouble( timebox.latest_time );
300         // timebox.writeObject( outs ) invokes InfoBox.writeObject( outs )
301     }
302 
readObject( TimeBoundingBox timebox, DataInput ins )303     public static void readObject( TimeBoundingBox  timebox,
304                                    DataInput        ins )
305     throws java.io.IOException
306     {
307         timebox.earliest_time  = ins.readDouble();
308         timebox.latest_time    = ins.readDouble();
309     }
310 
writeObject( DataOutput outs )311     public void writeObject( DataOutput outs )
312     throws java.io.IOException
313     {
314         outs.writeDouble( earliest_time );
315         outs.writeDouble( latest_time );
316     }
317 
TimeBoundingBox( DataInput ins )318     public TimeBoundingBox( DataInput ins )
319     throws java.io.IOException
320     {
321         this.readObject( ins );
322     }
323 
readObject( DataInput ins )324     public void readObject( DataInput ins )
325     throws java.io.IOException
326     {
327         earliest_time  = ins.readDouble();
328         latest_time    = ins.readDouble();
329     }
330 
toString()331     public String toString()
332     {
333         /*
334         if ( latest_time - earliest_time >= 0 )
335             return ( "TimeBBox( + )" );
336         else
337             return ( "TimeBBox( - )" );
338         */
339         return ( "TimeBBox(" + earliest_time + "," + latest_time + ")" );
340     }
341 
toShortString()342     public String toShortString()
343     {
344         return ( "TimeBBox(" + (float) earliest_time
345                        + "," + (float) latest_time + ")" );
346     }
347 
348 
349 
350     /*
351         Define TimeBoundingBox.Order as an alias of java.util.Comparator
352     */
353     public interface Order extends Comparator
354     {
isIncreasingTimeOrdered()355         public boolean isIncreasingTimeOrdered();
isStartTimeOrdered()356         public boolean isStartTimeOrdered();
toString()357         public String  toString();
358     }
359 
360 /*
361     This comparator to Collections.sort() will arrange TimeBoundingBoxs
362     in increasing starttime order.  If starttimes are equals, TimeBoundingBox
363     will then be arranged in decreasing finaltime order.
364 */
365     private static class IncreasingStarttimeOrder implements Order
366     {
compare( Object o1, Object o2 )367         public int compare( Object o1, Object o2 )
368         {
369             TimeBoundingBox  timebox1, timebox2;
370             timebox1 = (TimeBoundingBox) o1;
371             timebox2 = (TimeBoundingBox) o2;
372             if ( timebox1.earliest_time != timebox2.earliest_time )
373                 // increasing starttime order ( 1st order )
374                 return ( timebox1.earliest_time < timebox2.earliest_time
375                        ? -1 : 1 );
376             else {
377                 if ( timebox1.latest_time != timebox2.latest_time )
378                     // decreasing finaltime order ( 2nd order )
379                     return ( timebox1.latest_time > timebox2.latest_time
380                            ? -1 : 1 );
381                 else {
382                     // if ( timebox1 == timebox2 )
383                         return 0;
384                 }   // FinalTime
385             }   // StartTime
386         }
387 
isIncreasingTimeOrdered()388         public boolean isIncreasingTimeOrdered() {return true;}
isStartTimeOrdered()389         public boolean isStartTimeOrdered() {return true;}
toString()390         public String toString() {return "INCRE_STARTTIME_ORDER";}
391     }
392 
393 /*
394     This comparator to Collections.sort() will arrange TimeBoundingBoxs
395     in decreasing starttime order.  If starttimes are equals, TimeBoundingBox
396     will then be arranged in increasing finaltime order.
397 */
398     private static class DecreasingStarttimeOrder implements Order
399     {
compare( Object o1, Object o2 )400         public int compare( Object o1, Object o2 )
401         {
402             TimeBoundingBox  timebox1, timebox2;
403             timebox1 = (TimeBoundingBox) o1;
404             timebox2 = (TimeBoundingBox) o2;
405             if ( timebox1.earliest_time != timebox2.earliest_time )
406                 // decreasing starttime order ( 1st order )
407                 return ( timebox1.earliest_time > timebox2.earliest_time
408                        ? -1 : 1 );
409             else {
410                 if ( timebox1.latest_time != timebox2.latest_time )
411                     // increasing finaltime order ( 2nd order )
412                     return ( timebox1.latest_time < timebox2.latest_time
413                            ? -1 : 1 );
414                 else {
415                     // if ( timebox1 == timebox2 )
416                         return 0;
417                 }   // FinalTime
418             }   // StartTime
419         }
420 
isIncreasingTimeOrdered()421         public boolean isIncreasingTimeOrdered() {return false;}
isStartTimeOrdered()422         public boolean isStartTimeOrdered() {return true;}
toString()423         public String toString() {return "DECRE_STARTTIME_ORDER";}
424     }
425 
426 /*
427     This comparator to Collections.sort() will arrange TimeBoundingBoxs
428     in increasing finaltime order.  If finaltimes are equals, TimeBoundingBox
429     will then be arranged in decreasing starttime order.
430 */
431     private static class IncreasingFinaltimeOrder implements Order
432     {
compare( Object o1, Object o2 )433         public int compare( Object o1, Object o2 )
434         {
435             TimeBoundingBox  timebox1, timebox2;
436             timebox1 = (TimeBoundingBox) o1;
437             timebox2 = (TimeBoundingBox) o2;
438             if ( timebox1.latest_time != timebox2.latest_time )
439                 // increasing finaltime order ( 1st order )
440                 return ( timebox1.latest_time < timebox2.latest_time
441                        ? -1 : 1 );
442             else {
443                 if ( timebox1.earliest_time != timebox2.earliest_time )
444                     // decreasing starttime order ( 2nd order )
445                     return ( timebox1.earliest_time > timebox2.earliest_time
446                            ? -1 : 1 );
447                 else {
448                     // if ( timebox1 == timebox2 )
449                         return 0;
450                 }   // StartTime
451             }   // FinalTime
452         }
453 
isIncreasingTimeOrdered()454         public boolean isIncreasingTimeOrdered() {return true;}
isStartTimeOrdered()455         public boolean isStartTimeOrdered() {return false;}
toString()456         public String toString() {return "INCRE_FINALTIME_ORDER";}
457     }
458 
459 /*
460     This comparator to Collections.sort() will arrange TimeBoundingBoxs
461     in decreasing finaltime order.  If finaltimes are equals, TimeBoundingBox
462     will then be arranged in increasing starttime order.
463 */
464     private static class DecreasingFinaltimeOrder implements Order
465     {
compare( Object o1, Object o2 )466         public int compare( Object o1, Object o2 )
467         {
468             TimeBoundingBox  timebox1, timebox2;
469             timebox1 = (TimeBoundingBox) o1;
470             timebox2 = (TimeBoundingBox) o2;
471             if ( timebox1.latest_time != timebox2.latest_time )
472                 // increasing finaltime order ( 1st order )
473                 return ( timebox1.latest_time > timebox2.latest_time
474                        ? -1 : 1 );
475             else {
476                 if ( timebox1.earliest_time != timebox2.earliest_time )
477                     // decreasing starttime order ( 2nd order )
478                     return ( timebox1.earliest_time < timebox2.earliest_time
479                            ? -1 : 1 );
480                 else {
481                     // if ( timebox1 == timebox2 )
482                         return 0;
483                 }   // StartTime
484             }   // FinalTime
485         }
486 
isIncreasingTimeOrdered()487         public boolean isIncreasingTimeOrdered() {return false;}
isStartTimeOrdered()488         public boolean isStartTimeOrdered() {return false;}
toString()489         public String toString() {return "DECRE_FINALTIME_ORDER";}
490     }
491 
main( String[] args )492     public static final void main( String[] args )
493     {
494         TimeBoundingBox timebox = new TimeBoundingBox();
495         System.out.println( timebox );
496 
497         if ( INCRE_STARTTIME_ORDER.equals( DECRE_STARTTIME_ORDER ) )
498             System.out.println( "INCRE_STARTTIME_ORDER=DECRE_STARTTIME_ORDER" );
499         else
500             System.out.println( "INCRE_STARTTIME_ORDER!DECRE_STARTTIME_ORDER" );
501 
502         if ( INCRE_STARTTIME_ORDER.equals( INCRE_FINALTIME_ORDER ) )
503             System.out.println( "INCRE_STARTTIME_ORDER=INCRE_FINALTIME_ORDER" );
504         else
505             System.out.println( "INCRE_STARTTIME_ORDER!INCRE_FINALTIME_ORDER" );
506 
507         if ( INCRE_STARTTIME_ORDER.equals( DECRE_FINALTIME_ORDER ) )
508             System.out.println( "INCRE_STARTTIME_ORDER=DECRE_FINALTIME_ORDER" );
509         else
510             System.out.println( "INCRE_STARTTIME_ORDER!DECRE_FINALTIME_ORDER" );
511 
512         if ( INCRE_STARTTIME_ORDER.equals( INCRE_STARTTIME_ORDER ) )
513             System.out.println( "INCRE_STARTTIME_ORDER=INCRE_STARTTIME_ORDER" );
514         else
515             System.out.println( "INCRE_STARTTIME_ORDER!INCRE_STARTTIME_ORDER" );
516 
517         TimeBoundingBox.Order tmp_order = new IncreasingStarttimeOrder();
518         if ( INCRE_STARTTIME_ORDER.equals( tmp_order ) )
519             System.out.println( "INCRE_STARTTIME_ORDER=tmp_order" );
520         else
521             System.out.println( "INCRE_STARTTIME_ORDER!tmp_order" );
522     }
523 
524 }
525