001/**
002 * Copyright (c) 2011, The University of Southampton and the individual contributors.
003 * All rights reserved.
004 *
005 * Redistribution and use in source and binary forms, with or without modification,
006 * are permitted provided that the following conditions are met:
007 *
008 *   *  Redistributions of source code must retain the above copyright notice,
009 *      this list of conditions and the following disclaimer.
010 *
011 *   *  Redistributions in binary form must reproduce the above copyright notice,
012 *      this list of conditions and the following disclaimer in the documentation
013 *      and/or other materials provided with the distribution.
014 *
015 *   *  Neither the name of the University of Southampton nor the names of its
016 *      contributors may be used to endorse or promote products derived from this
017 *      software without specific prior written permission.
018 *
019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
020 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
021 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
022 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
023 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
026 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
028 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029 */
030/**
031 *
032 */
033package org.openimaj.vis.general;
034
035import java.awt.Dimension;
036
037import org.openimaj.image.MBFImage;
038import org.openimaj.vis.Visualisation;
039
040/**
041 *      A chronological bar chart, where each time you add a data point, the visualisation is
042 *      moved along and another set of data is added to the 3D visualisation. Data must therefore
043 *      be one dimensional.
044 *
045 *      @author David Dupplaw (dpd@ecs.soton.ac.uk)
046 *  @created 8 Jul 2013
047 */
048public class ChronologicalScrollingBarVisualisation3D implements Visualisation<double[]>
049{
050        /** The 3D bar visualisation used to display the time series */
051        private final BarVisualisation3D barVis;
052
053        /** The data */
054        private final double[][] data;
055
056        /** The expected length of each data line */
057        private final int expectedDataLength;
058
059        /**
060         *      Default constructor
061         *      @param width Width in pixels
062         *      @param height Height in pixels
063         *      @param timeLength The number of time points to show
064         *      @param dataWidth Length of each data line
065         */
066        public ChronologicalScrollingBarVisualisation3D( final int width, final int height, final int timeLength, final int dataWidth )
067        {
068                this.barVis = new BarVisualisation3D( width, height );
069                this.data = new double[timeLength][dataWidth];
070                this.expectedDataLength = dataWidth;
071        }
072
073        /**
074         *      {@inheritDoc}
075         *      @see org.openimaj.vis.VisualisationImageProvider#updateVis()
076         */
077        @Override
078        public void updateVis()
079        {
080                this.barVis.updateVis();
081        }
082
083        /**
084         *      {@inheritDoc}
085         *      @see org.openimaj.vis.VisualisationImageProvider#getVisualisationImage()
086         */
087        @Override
088        public MBFImage getVisualisationImage()
089        {
090                return this.barVis.getVisualisationImage();
091        }
092
093        /**
094         *      {@inheritDoc}
095         *      @see org.openimaj.vis.VisualisationImageProvider#setRequiredSize(java.awt.Dimension)
096         */
097        @Override
098        public void setRequiredSize( final Dimension d )
099        {
100                this.barVis.setRequiredSize( d );
101        }
102
103        /**
104         *      Set the maximum data value
105         *      @param max The maximum
106         */
107        public void setMaximum( final double max )
108        {
109                this.barVis.setMaximum( max );
110        }
111
112        /**
113         *      Set the x axis name
114         *      @param xAxis The x axis
115         */
116        public void setXAxisName( final String xAxis )
117        {
118                this.barVis.setxAxisName( xAxis );
119        }
120
121        /**
122         *      Set the y axis name
123         *      @param yAxis The y axis
124         */
125        public void setYAxisName( final String yAxis )
126        {
127                this.barVis.setyAxisName( yAxis );
128        }
129
130        /**
131         *      Set the z axis name
132         *      @param zAxis The z axis
133         */
134        public void setZAxisName( final String zAxis )
135        {
136                this.barVis.setzAxisName( zAxis );
137        }
138
139        /**
140         *      Data is copied into the visualisation, so the arrays passed in are untouched.
141         *
142         *      {@inheritDoc}
143         *      @see org.openimaj.vis.Visualisation#setData(java.lang.Object)
144         */
145        @Override
146        public void setData( final double[] newData )
147        {
148                if( newData.length != this.expectedDataLength )
149                        throw new IllegalArgumentException( "WARNING: Data was not the correct length. Expected "
150                                                +this.expectedDataLength+" got "+newData.length );
151
152                // Move all the old data up
153                for( int i = 1; i < this.data.length; i++ )
154                        System.arraycopy( this.data[i], 0, this.data[i-1], 0, this.expectedDataLength );
155                System.arraycopy( newData, 0, this.data[this.data.length-1], 0, this.expectedDataLength );
156
157                this.barVis.setData( this.data );
158        }
159
160        /**
161         *      Test
162         *      @param args
163         * @throws InterruptedException
164         */
165        public static void main( final String[] args ) throws InterruptedException
166        {
167                // Number of data points
168                final int N = 10;
169
170                // Number of data frames to draw
171                final int F = 2500;
172
173                // Number of time points to draw
174                final int T = 50;
175
176                // Sleep time
177                final int S = 25;
178
179                final ChronologicalScrollingBarVisualisation3D c =
180                                new ChronologicalScrollingBarVisualisation3D( 800, 800, T, N );
181                c.setMaximum( 2 );
182                c.setXAxisName( "Scrolling Bar Demo" );
183                c.setZAxisName( "Time" );
184                c.setYAxisName( "Value" );
185
186                for( int i = 0; i < F; i++ )
187                {
188                        final double[] d = new double[N];
189                        for( int j = 0; j < N; j++ )
190                                d[j] = Math.sin( (N+i+4*j)/20d ) + 1d;
191                        c.setData( d );
192                        Thread.sleep( S );
193                }
194        }
195}