/*
* @(#)SquareRainTransition2D.java
*
* $Date: 2014-06-06 20:04:49 +0200 (P, 06 jún. 2014) $
*
* Copyright (c) 2011 by Jeremy Wood.
* All rights reserved.
*
* The copyright of this software is owned by Jeremy Wood.
* You may not use, copy or modify this software, except in
* accordance with the license agreement you entered into with
* Jeremy Wood. For details see accompanying license terms.
*
* This software is probably, but not necessarily, discussed here:
* https://javagraphics.java.net/
*
* That site should also contain the most recent official version
* of this software. (See the SVN repository for more details.)
*/
package com.bric.image.transition;
import java.awt.Dimension;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
import java.util.Random;
import java.util.Vector;
import com.bric.geom.TransformUtils;
/** In this transition geometric shapes (squares and circles)
* trickle downwards revealing the next frame. Here are playback samples:
* <p><table summary="Sample Animations of SquareRainTransition2D" cellspacing="50" border="0"><tr>
* <td align="center">
* <img src="https://javagraphics.java.net/resources/transition/SquareRainTransition2D/SquareRain(6).gif" alt="Square Rain (6)">
* <p>Square Rain (6)
* </td>
* <td align="center">
* <img src="https://javagraphics.java.net/resources/transition/SquareRainTransition2D/SquareRain(12).gif" alt="Square Rain (12)">
* <p>Square Rain (12)
* </td>
* <td align="center">
* <img src="https://javagraphics.java.net/resources/transition/SquareRainTransition2D/SquareRain(24).gif" alt="Square Rain (24)">
* <p>Square Rain (24)
* </td>
* </tr></table>
*
*/
public class SquareRainTransition2D extends AbstractClippedTransition2D {
/** This public static method is used by the
* {@link com.bric.image.transition.Transition2DDemoHelper}
* class to create sample animations of this transition.
* @return the transitions that should be used to demonstrate this
* transition.
*/
public static Transition[] getDemoTransitions() {
return new Transition[] {
new SquareRainTransition2D(6, false),
new SquareRainTransition2D(12, false),
new SquareRainTransition2D(24, false)
};
}
float[] offset;
float[] accel;
/** Creates a new square rain transition with 12 columns that is not randomized.
*
*/
public SquareRainTransition2D() {
this(12,false);
}
/** Creates a new square rain transition.
*
* @param columns how many columns to use
* @param randomize whether the transition should be randomly generated or not.
* If not, a constant random seed is used.
*/
public SquareRainTransition2D(int columns,boolean randomize) {
Random r = new Random();
offset = new float[columns];
accel = new float[columns];
boolean ok = false;
long seed = 1196622174915L;
if(randomize) {
seed = System.currentTimeMillis();
}
while(!ok) {
seed++;
r.setSeed(seed);
ok = true;
for(int a = 0; a<columns && ok; a++) {
float m = (a)/(columns-1f);
if(m<.5f) {
m = m/.5f;
} else {
m = (1-m)/.5f;
}
offset[a] = -m;
accel[a] = 10*r.nextFloat();
if(accel[a]+1+offset[a]<1.2)
ok = false;
}
if(ok) {
//make sure at least one strand takes up the whole time t=[0,1]
boolean atLeastOneSlowOne = false;
for(int a = 0; a<columns && atLeastOneSlowOne==false; a++) {
atLeastOneSlowOne = accel[a]+1+offset[a]<1.3;
}
ok = atLeastOneSlowOne;
}
}
}
@SuppressWarnings("unused")
@Override
public Shape[] getShapes(float progress, Dimension size) {
Vector<Shape> v = new Vector<Shape>();
Rectangle2D rect;
float columnWidth = ((float)size.width)/((float)offset.length);
int rows = (int)(size.height/columnWidth+.5);
float rowHeight = ((float)size.height)/rows;
for(int a = 0; a<offset.length; a++) {
float x = a*columnWidth;
float centerX = x+columnWidth/2;
float w = size.width/offset.length;
float y = size.height*(offset[a]+progress+progress*progress*accel[a]);
int row = (int)((y-2*rowHeight)/rowHeight);
rect = new Rectangle2D.Float(x-1,0,w+2,row*rowHeight);
v.add(rect);
float centerY = row*rowHeight+rowHeight/2;
float k = ((y-rowHeight*row))/((rowHeight));
float k1 = k/3f;
float k2 = (k-1f)/3f;
float k3 = (k-2f)/3f;
if(k1<0) k1 = 0;
if(k2<0) k2 = 0;
if(k3<0) k3 = 0;
if(k1>1) k1 = 1;
if(k2>1) k2 = 1;
if(k3>1) k3 = 1;
if(true) {
if(k1>0) {
Shape shape = new RoundRectangle2D.Float(centerX-k1*columnWidth/2,centerY-k1*rowHeight/2,k1*columnWidth,k1*rowHeight,columnWidth/4*(1-k1),rowHeight/4*(1-k1));
v.add(shape);
}
if(k2>0) {
Shape shape = new RoundRectangle2D.Float(centerX-k2*columnWidth/2,centerY-k2*rowHeight/2+rowHeight,k2*columnWidth,k2*rowHeight,columnWidth*(1-k2),rowHeight*(1-k2));
v.add(shape);
}
if(k3>0) {
Shape shape = new RoundRectangle2D.Float(centerX-k3*columnWidth/2,centerY-k3*rowHeight/2+2*rowHeight,k3*columnWidth,k3*rowHeight,columnWidth*(1-k3),rowHeight*(1-k3));
v.add(shape);
}
} else {
if(k1>0) {
Shape shape = new Rectangle2D.Float(centerX-k1*columnWidth/2,centerY-k1*rowHeight/2,k1*columnWidth,k1*rowHeight);
v.add(shape);
}
if(k2>0) {
Shape shape = new Rectangle2D.Float(centerX-k2*columnWidth/2,centerY-k2*rowHeight/2+rowHeight,k2*columnWidth,k2*rowHeight);
v.add(shape);
}
if(k3>0) {
Shape shape = new Rectangle2D.Float(centerX-k3*columnWidth/2,centerY-k3*rowHeight/2+2*rowHeight,k3*columnWidth,k3*rowHeight);
v.add(shape);
}
}
}
if(false) {
AffineTransform transform = TransformUtils.createAffineTransform(
0,0,
size.width,0,
0,size.height,
0,size.height,
size.width,size.height,
0,0 );
for(int a = 0; a<v.size(); a++) {
Shape shape = v.get(a);
shape = transform.createTransformedShape(shape);
v.set(a, shape);
}
}
Shape[] shapes = v.toArray(new Shape[v.size()]);
//make sure the stroke doesn't show:
float k = getStrokeWidth(progress, size)+1;
AffineTransform fit = TransformUtils.createAffineTransform(
0,0,
size.width,0,
0,size.height,
-k,-k,
size.width+k,-k,
-k,size.height+k
);
for(int a = 0; a<shapes.length; a++) {
if(shapes[a] instanceof GeneralPath) {
((GeneralPath)shapes[a]).transform(fit);
} else {
shapes[a] = fit.createTransformedShape(shapes[a]);
}
}
return shapes;
}
@Override
public float getStrokeWidth(float progress,Dimension size) {
return 5;
}
@Override
public String toString() {
return "Square Rain ("+offset.length+")";
}
}