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 */ 030package org.openimaj.workinprogress; 031 032import java.io.File; 033import java.io.IOException; 034 035import org.openimaj.image.DisplayUtilities; 036import org.openimaj.image.FImage; 037import org.openimaj.image.ImageUtilities; 038import org.openimaj.image.pixel.Pixel; 039import org.openimaj.image.processing.transform.FProjectionProcessor; 040import org.openimaj.math.geometry.point.Point2dImpl; 041import org.openimaj.math.geometry.shape.Circle; 042import org.openimaj.math.geometry.shape.Rectangle; 043import org.openimaj.math.geometry.shape.RotatedRectangle; 044import org.openimaj.math.geometry.shape.Triangle; 045import org.openimaj.math.geometry.transforms.TransformUtilities; 046 047import Jama.Matrix; 048 049public class PendulumNonTextured { 050 public static void main(String[] args) throws IOException { 051 052 // background image 053 final FImage background = new FImage(800, 600); 054 055 final Triangle triangle = new Triangle(new Point2dImpl(400, 100), 056 new Point2dImpl(395, 500), 057 new Point2dImpl(405, 500)); 058 059 final FImage pendulumImage = new FImage(800, 600); 060 final FImage pendulumMask = new FImage(800, 600); 061 for (int y = 0; y < pendulumImage.height; y++) { 062 for (int x = 0; x < pendulumImage.width; x++) { 063 if (triangle.isInside(new Pixel(x, y))) { 064 pendulumImage.pixels[y][x] = 1f; 065 pendulumMask.pixels[y][x] = 1; 066 } 067 } 068 } 069 070 final Triangle triangle2 = new Triangle(new Point2dImpl(650, 150), 071 new Point2dImpl(645, 250), 072 new Point2dImpl(655, 250)); 073 074 final FImage clockImage = new FImage(800, 600); 075 final FImage clockMask = new FImage(800, 600); 076 for (int y = 0; y < clockImage.height; y++) { 077 for (int x = 0; x < clockImage.width; x++) { 078 if (triangle2.isInside(new Pixel(x, y))) { 079 clockImage.pixels[y][x] = 1f; 080 clockMask.pixels[y][x] = 1; 081 } 082 } 083 } 084 085 final Circle circle = new Circle(50, 50, 25); 086 final FImage linBallImage = new FImage(800, 600); 087 final FImage linBallMask = new FImage(800, 600); 088 for (int y = 0; y < linBallImage.height; y++) { 089 for (int x = 0; x < linBallImage.width; x++) { 090 if (circle.isInside(new Pixel(x, y))) { 091 linBallImage.pixels[y][x] = 1f; 092 linBallMask.pixels[y][x] = 1; 093 } 094 } 095 } 096 097 final Circle circle2 = new Circle(50, 550, 25); 098 final FImage accBallImage = new FImage(800, 600); 099 final FImage accBallMask = new FImage(800, 600); 100 for (int y = 0; y < accBallImage.height; y++) { 101 for (int x = 0; x < accBallImage.width; x++) { 102 if (circle2.isInside(new Pixel(x, y))) { 103 accBallImage.pixels[y][x] = 1f; 104 accBallMask.pixels[y][x] = 1; 105 } 106 } 107 } 108 109 final File dir = new File("/Users/jon/pendulum+circle+notexture"); 110 dir.mkdirs(); 111 int i = 0; 112 final double theta0 = 0.75; 113 final double T = 0.1; 114 double theta; 115 116 final double triMaxSpeed = theta0 * 400; 117 final double clockMaxSpeed = 50 * 100; 118 final double linBallMaxSpeed = 3000; 119 final double accBallMaxSpeed = 30000; 120 121 final double triMaxAcc = theta0 * 400; 122 final double accBallMaxAcc = 500000; 123 124 for (double t = 0; t < 1; t += 0.001, i++) { 125 theta = theta0 * Math.cos(2 * Math.PI * t / T); 126 127 final FImage rotPendulumMask = rotate(pendulumMask, theta, 400, 100); 128 final FImage rotPendulumImage = rotate(pendulumImage, theta, 400, 100); 129 130 // clock - constant angular motion 131 final FImage rotClockMask = rotate(clockMask, t * 50, 650, 150); 132 final FImage rotClockImage = rotate(clockImage, t * 50, 650, 150); 133 DisplayUtilities.displayName(rotClockMask, "foo"); 134 135 // upper circle - linear motion 136 final FImage transLinBallMask = translate(linBallMask, (float) t * 3000, 0f); 137 final FImage transLinBallImage = translate(linBallImage, (float) t * 3000, 0f); 138 139 // lower circle - accel motion 140 final FImage transAccBallMask = translate(accBallMask, (float) (t * t * 500 * 500), 0f); 141 final FImage transAccBallImage = translate(accBallImage, (float) (t * t * 500 * 500), 0f); 142 143 final FImage frame = new FImage(800, 600); 144 final FImage frameVelX = new FImage(800, 600); 145 final FImage frameVelY = new FImage(800, 600); 146 final FImage frameVelMag = new FImage(800, 600); 147 final FImage frameAccX = new FImage(800, 600); 148 final FImage frameAccY = new FImage(800, 600); 149 final FImage frameAccMag = new FImage(800, 600); 150 frameVelX.fill(0.5f); 151 frameVelY.fill(0.5f); 152 frameAccX.fill(0.5f); 153 frameAccY.fill(0.5f); 154 155 for (int y = 0; y < frame.height; y++) { 156 for (int x = 0; x < frame.width; x++) { 157 if (rotPendulumMask.pixels[y][x] > 0.5) { 158 frame.pixels[y][x] = rotPendulumImage.pixels[y][x]; 159 160 // Velocity of the pendulum triangle 161 final double dx = x - 400, dy = y - 100, r = Math.sqrt(dx * dx + dy * dy); 162 final double vt = -r * theta0 * Math.sin(2 * Math.PI * t / T); 163 final double vx = Math.cos(theta) * vt; 164 final double vy = Math.sin(theta) * vt; 165 frameVelX.pixels[y][x] = (float) ((vx + triMaxSpeed) / (2 * triMaxSpeed)); 166 frameVelY.pixels[y][x] = (float) ((vy + triMaxSpeed) / (2 * triMaxSpeed)); 167 frameVelMag.pixels[y][x] = (float) (Math.abs(vt) / (triMaxSpeed)); 168 169 // Acceleration of the pendulum triangle 170 final double at = -r * theta0 * Math.cos(2 * Math.PI * t / T); 171 final double ax = Math.cos(theta) * at; 172 final double ay = Math.sin(theta) * at; 173 frameAccX.pixels[y][x] = (float) ((ax + triMaxAcc) / (2 * triMaxAcc)); 174 frameAccY.pixels[y][x] = (float) ((ay + triMaxAcc) / (2 * triMaxAcc)); 175 frameAccMag.pixels[y][x] = (float) (Math.abs(at) / (triMaxAcc)); 176 } else if (rotClockMask.pixels[y][x] > 0.5) { 177 frame.pixels[y][x] = rotClockImage.pixels[y][x]; 178 179 // velocity of the clock triangle 180 final double dx = x - 650, dy = y - 150, r = Math.sqrt(dx * dx + dy * dy); 181 final double vt = r * 50; 182 final double vx = Math.cos(50 * t) * vt; 183 final double vy = Math.sin(50 * t) * vt; 184 185 frameVelX.pixels[y][x] = (float) ((vx + clockMaxSpeed) / (2 * clockMaxSpeed)); 186 frameVelY.pixels[y][x] = (float) ((vy + clockMaxSpeed) / (2 * clockMaxSpeed)); 187 frameVelMag.pixels[y][x] = (float) (Math.abs(vt) / (clockMaxSpeed)); 188 189 // acceleration of the clock triangle 190 // !!!clock doesn't accelerate!!! 191 } else if (transLinBallMask.pixels[y][x] > 0.5) { 192 frame.pixels[y][x] = transLinBallImage.pixels[y][x]; 193 194 // velocity of the linear ball 195 frameVelX.pixels[y][x] = (float) (3000f / (2 * linBallMaxSpeed)); 196 frameVelMag.pixels[y][x] = (float) (3000f / linBallMaxSpeed); 197 198 // acceleration of the linear ball 199 // !!!ball doesn't accelerate!!! 200 } else if (transAccBallMask.pixels[y][x] > 0.5) { 201 frame.pixels[y][x] = transAccBallImage.pixels[y][x]; 202 203 // velocity of the accelerating ball 204 frameVelX.pixels[y][x] = (float) (500000 * t / (2 * accBallMaxSpeed)); 205 frameVelMag.pixels[y][x] = (float) (500000 * t / accBallMaxSpeed); 206 207 // acceleration of the accelerating ball 208 frameAccX.pixels[y][x] = (float) (500000 / (2 * accBallMaxAcc)); 209 frameAccMag.pixels[y][x] = (float) (500000 / accBallMaxAcc); 210 } else { 211 frame.pixels[y][x] = background.pixels[y][x]; 212 } 213 } 214 } 215 216 frame.drawShapeFilled(new Rectangle(50, 275, 50, 50), 1f); 217 frame.drawShapeFilled(new RotatedRectangle(75, 300, 50, 50, Math.PI / 4), 1f); 218 219 DisplayUtilities.displayName(frame, ""); 220 // DisplayUtilities.displayName(frameVelX, "Vx"); 221 // DisplayUtilities.displayName(frameVelY, "Vy"); 222 // DisplayUtilities.displayName(frameVelMag, "Velocity Magnitude"); 223 // DisplayUtilities.displayName(frameAccX, "Ax"); 224 // DisplayUtilities.displayName(frameAccY, "Ay"); 225 // DisplayUtilities.displayName(frameAccMag, 226 // "Acceleration Magnitude"); 227 228 ImageUtilities.write(frame, new File(dir, "frame_" + i + ".png")); 229 // ImageUtilities.write(frameVelX, new File(dir, "frame_vx_" + i + 230 // ".png")); 231 // ImageUtilities.write(frameVelY, new File(dir, "frame_vy_" + i + 232 // ".png")); 233 // ImageUtilities.write(frameVelMag, new File(dir, "frame_vm+" + i + 234 // ".png")); 235 // ImageUtilities.write(frameAccX, new File(dir, "frame_ax_" + i + 236 // ".png")); 237 // ImageUtilities.write(frameAccY, new File(dir, "frame_ay_" + i + 238 // ".png")); 239 // ImageUtilities.write(frameAccMag, new File(dir, "frame_am_" + i + 240 // ".png")); 241 } 242 } 243 244 private static FImage rotate(final FImage image, double angle, float px, float py) { 245 final Matrix transform = TransformUtilities.rotationMatrixAboutPoint(angle, px, py); 246 final FProjectionProcessor pp = new FProjectionProcessor(); 247 pp.setMatrix(transform); 248 pp.accumulate(image); 249 return pp.performProjection(true, 0f); 250 } 251 252 private static FImage translate(final FImage image, float x, float y) { 253 final Matrix transform = TransformUtilities.translateMatrix(x, y); 254 final FProjectionProcessor pp = new FProjectionProcessor(); 255 pp.setMatrix(transform); 256 pp.accumulate(image); 257 return pp.performProjection(true, 0f); 258 } 259}