commit 9474e6e25e7da48259a26f7a94fe017b8bc5996a Author: aNNiMON Date: Tue Feb 13 23:58:29 2024 +0200 Initial commit diff --git a/.classpath b/.classpath new file mode 100644 index 0000000..4160c21 --- /dev/null +++ b/.classpath @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/.project b/.project new file mode 100644 index 0000000..a2c0547 --- /dev/null +++ b/.project @@ -0,0 +1,33 @@ + + + VisualME + + + + + + com.android.ide.eclipse.adt.ResourceManagerBuilder + + + + + com.android.ide.eclipse.adt.PreCompilerBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + com.android.ide.eclipse.adt.ApkBuilder + + + + + + com.android.ide.eclipse.adt.AndroidNature + org.eclipse.jdt.core.javanature + + diff --git a/AndroidManifest.xml b/AndroidManifest.xml new file mode 100644 index 0000000..f9e4d0e --- /dev/null +++ b/AndroidManifest.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/proguard-project.txt b/proguard-project.txt new file mode 100644 index 0000000..31ac955 --- /dev/null +++ b/proguard-project.txt @@ -0,0 +1,5 @@ +@E:\\SETUPS\\Disk\\Programming\\Java\\android.pro +-obfuscationdictionary E:\\SETUPS\\Disk\\Programming\\Java\\compact.txt +-optimizationpasses 9 +-allowaccessmodification +-overloadaggressively \ No newline at end of file diff --git a/project.properties b/project.properties new file mode 100644 index 0000000..e22da9e --- /dev/null +++ b/project.properties @@ -0,0 +1,14 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system edit +# "ant.properties", and override values to adapt the script to your +# project structure. +# +# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): +proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt + +# Project target. +target=android-16 diff --git a/res/drawable-hdpi/ic_launcher.png b/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 0000000..7a0af23 Binary files /dev/null and b/res/drawable-hdpi/ic_launcher.png differ diff --git a/res/drawable-ldpi/ic_launcher.png b/res/drawable-ldpi/ic_launcher.png new file mode 100644 index 0000000..15e9f95 Binary files /dev/null and b/res/drawable-ldpi/ic_launcher.png differ diff --git a/res/drawable-mdpi/ic_launcher.png b/res/drawable-mdpi/ic_launcher.png new file mode 100644 index 0000000..b643202 Binary files /dev/null and b/res/drawable-mdpi/ic_launcher.png differ diff --git a/res/drawable-xhdpi/ic_launcher.png b/res/drawable-xhdpi/ic_launcher.png new file mode 100644 index 0000000..34b5026 Binary files /dev/null and b/res/drawable-xhdpi/ic_launcher.png differ diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml new file mode 100644 index 0000000..55bc485 --- /dev/null +++ b/res/values-ru/strings.xml @@ -0,0 +1,30 @@ + + + + VisualME + + Запустить VisualME + Показывать fps + Количество ветвей + Гибкость + Количество звеньев в линии + Пропорции экрана + Скорость + Автосмена визуализаций? + Автоматически изменять режим визуализации? + Автосмена фигур? + Автоматически изменять тип рисуемых фигур? + Тип фигуры + + + Линия + Эллипс + Квадрат + + + 0 + 1 + 2 + + + \ No newline at end of file diff --git a/res/values/strings.xml b/res/values/strings.xml new file mode 100644 index 0000000..11a4e7c --- /dev/null +++ b/res/values/strings.xml @@ -0,0 +1,30 @@ + + + + VisualME + + Run VisualME + Show fps + Number of branches + Flexibility + Number of elements in line + Screen proportions + Speed + Change visualization? + Automatically change visualization mode? + Change figures? + Automatically change drawing figures? + Shape type + + + Line + Ellipse + Square + + + 0 + 1 + 2 + + + \ No newline at end of file diff --git a/res/xml/visualme.xml b/res/xml/visualme.xml new file mode 100644 index 0000000..eed7449 --- /dev/null +++ b/res/xml/visualme.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/com/annimon/visualme/FastMath.java b/src/com/annimon/visualme/FastMath.java new file mode 100644 index 0000000..b713135 --- /dev/null +++ b/src/com/annimon/visualme/FastMath.java @@ -0,0 +1,1046 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.annimon.visualme; + + +/** + * Faster, more accurate, portable alternative to {@link Math} and + * {@link StrictMath} for large scale computation. + *

+ * FastMath is a drop-in replacement for both Math and StrictMath. This + * means that for any method in Math (say {@code Math.sin(x)} or + * {@code Math.cbrt(y)}), user can directly change the class and use the + * methods as is (using {@code FastMath.sin(x)} or {@code FastMath.cbrt(y)} + * in the previous example). + *

+ *

+ * FastMath speed is achieved by relying heavily on optimizing compilers + * to native code present in many JVMs today and use of large tables. + * The larger tables are lazily initialised on first use, so that the setup + * time does not penalise methods that don't need them. + *

+ *

+ * Note that FastMath is + * extensively used inside Apache Commons Math, so by calling some algorithms, + * the overhead when the the tables need to be intialised will occur + * regardless of the end-user calling FastMath methods directly or not. + * Performance figures for a specific JVM and hardware can be evaluated by + * running the FastMathTestPerformance tests in the test directory of the source + * distribution. + *

+ *

+ * FastMath accuracy should be mostly independent of the JVM as it relies only + * on IEEE-754 basic operations and on embedded tables. Almost all operations + * are accurate to about 0.5 ulp throughout the domain range. This statement, + * of course is only a rough global observed behavior, it is not a + * guarantee for every double numbers input (see William Kahan's Table + * Maker's Dilemma). + *

+ *

+ * FastMath additionally implements the following methods not found in Math/StrictMath: + *

+ * The following methods are found in Math/StrictMath since 1.6 only, they are provided + * by FastMath even in 1.5 Java virtual machines + * + *

+ * @version $Id: FastMath.java 1422313 2012-12-15 18:53:41Z psteitz $ + * @since 2.2 + */ +public class FastMath { + /** Archimede's constant PI, ratio of circle circumference to diameter. */ + public static final double PI = 105414357.0 / 33554432.0 + 1.984187159361080883e-9; + + /** Napier's constant e, base of the natural logarithm. */ + public static final double E = 2850325.0 / 1048576.0 + 8.254840070411028747e-8; + + /** Index of exp(0) in the array of integer exponentials. */ + static final int EXP_INT_TABLE_MAX_INDEX = 750; + /** Length of the array of integer exponentials. */ + static final int EXP_INT_TABLE_LEN = EXP_INT_TABLE_MAX_INDEX * 2; + /** Logarithm table length. */ + static final int LN_MANT_LEN = 1024; + /** Exponential fractions table length. */ + static final int EXP_FRAC_TABLE_LEN = 1025; // 0, 1/1024, ... 1024/1024 + + + /** Sine table (high bits). */ + private static final double SINE_TABLE_A[] = + { + +0.0d, + +0.1246747374534607d, + +0.24740394949913025d, + +0.366272509098053d, + +0.4794255495071411d, + +0.5850973129272461d, + +0.6816387176513672d, + +0.7675435543060303d, + +0.8414709568023682d, + +0.902267575263977d, + +0.9489846229553223d, + +0.9808930158615112d, + +0.9974949359893799d, + +0.9985313415527344d, + }; + + /** Sine table (low bits). */ + private static final double SINE_TABLE_B[] = + { + +0.0d, + -4.068233003401932E-9d, + +9.755392680573412E-9d, + +1.9987994582857286E-8d, + -1.0902938113007961E-8d, + -3.9986783938944604E-8d, + +4.23719669792332E-8d, + -5.207000323380292E-8d, + +2.800552834259E-8d, + +1.883511811213715E-8d, + -3.5997360512765566E-9d, + +4.116164446561962E-8d, + +5.0614674548127384E-8d, + -1.0129027912496858E-9d, + }; + + /** Cosine table (high bits). */ + private static final double COSINE_TABLE_A[] = + { + +1.0d, + +0.9921976327896118d, + +0.9689123630523682d, + +0.9305076599121094d, + +0.8775825500488281d, + +0.8109631538391113d, + +0.7316888570785522d, + +0.6409968137741089d, + +0.5403022766113281d, + +0.4311765432357788d, + +0.3153223395347595d, + +0.19454771280288696d, + +0.07073719799518585d, + -0.05417713522911072d, + }; + + /** Cosine table (low bits). */ + private static final double COSINE_TABLE_B[] = + { + +0.0d, + +3.4439717236742845E-8d, + +5.865827662008209E-8d, + -3.7999795083850525E-8d, + +1.184154459111628E-8d, + -3.43338934259355E-8d, + +1.1795268640216787E-8d, + +4.438921624363781E-8d, + +2.925681159240093E-8d, + -2.6437112632041807E-8d, + +2.2860509143963117E-8d, + -4.813899778443457E-9d, + +3.6725170580355583E-9d, + +2.0217439756338078E-10d, + }; + + + /** Bits of 1/(2*pi), need for reducePayneHanek(). */ + private static final long RECIP_2PI[] = new long[] { + (0x28be60dbL << 32) | 0x9391054aL, + (0x7f09d5f4L << 32) | 0x7d4d3770L, + (0x36d8a566L << 32) | 0x4f10e410L, + (0x7f9458eaL << 32) | 0xf7aef158L, + (0x6dc91b8eL << 32) | 0x909374b8L, + (0x01924bbaL << 32) | 0x82746487L, + (0x3f877ac7L << 32) | 0x2c4a69cfL, + (0xba208d7dL << 32) | 0x4baed121L, + (0x3a671c09L << 32) | 0xad17df90L, + (0x4e64758eL << 32) | 0x60d4ce7dL, + (0x272117e2L << 32) | 0xef7e4a0eL, + (0xc7fe25ffL << 32) | 0xf7816603L, + (0xfbcbc462L << 32) | 0xd6829b47L, + (0xdb4d9fb3L << 32) | 0xc9f2c26dL, + (0xd3d18fd9L << 32) | 0xa797fa8bL, + (0x5d49eeb1L << 32) | 0xfaf97c5eL, + (0xcf41ce7dL << 32) | 0xe294a4baL, + 0x9afed7ecL << 32 }; + + /** Bits of pi/4, need for reducePayneHanek(). */ + private static final long PI_O_4_BITS[] = new long[] { + (0xc90fdaa2L << 32) | 0x2168c234L, + (0xc4c6628bL << 32) | 0x80dc1cd1L }; + + /** Eighth's. + * This is used by sinQ, because its faster to do a table lookup than + * a multiply in this time-critical routine + */ + private static final double EIGHTHS[] = {0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1.0, 1.125, 1.25, 1.375, 1.5, 1.625}; + + /* + * There are 52 bits in the mantissa of a double. + * For additional precision, the code splits double numbers into two parts, + * by clearing the low order 30 bits if possible, and then performs the arithmetic + * on each half separately. + */ + + /** + * 0x40000000 - used to split a double into two parts, both with the low order bits cleared. + * Equivalent to 2^30. + */ + private static final long HEX_40000000 = 0x40000000L; // 1073741824L + + /** 2^52 - double numbers this large must be integral (no fraction) or NaN or Infinite */ + private static final double TWO_POWER_52 = 4503599627370496.0; + + /** + * Private Constructor + */ + private FastMath() {} + + // Generic helper methods + + + /** + * Computes sin(x) - x, where |x| < 1/16. + * Use a Remez polynomial approximation. + * @param x a number smaller than 1/16 + * @return sin(x) - x + */ + private static double polySine(final double x) + { + double x2 = x*x; + + double p = 2.7553817452272217E-6; + p = p * x2 + -1.9841269659586505E-4; + p = p * x2 + 0.008333333333329196; + p = p * x2 + -0.16666666666666666; + //p *= x2; + //p *= x; + p = p * x2 * x; + + return p; + } + + /** + * Computes cos(x) - 1, where |x| < 1/16. + * Use a Remez polynomial approximation. + * @param x a number smaller than 1/16 + * @return cos(x) - 1 + */ + private static double polyCosine(double x) { + double x2 = x*x; + + double p = 2.479773539153719E-5; + p = p * x2 + -0.0013888888689039883; + p = p * x2 + 0.041666666666621166; + p = p * x2 + -0.49999999999999994; + p *= x2; + + return p; + } + + /** + * Compute sine over the first quadrant (0 < x < pi/2). + * Use combination of table lookup and rational polynomial expansion. + * @param xa number from which sine is requested + * @param xb extra bits for x (may be 0.0) + * @return sin(xa + xb) + */ + private static double sinQ(double xa, double xb) { + int idx = (int) ((xa * 8.0) + 0.5); + final double epsilon = xa - EIGHTHS[idx]; //idx*0.125; + + // Table lookups + final double sintA = SINE_TABLE_A[idx]; + final double sintB = SINE_TABLE_B[idx]; + final double costA = COSINE_TABLE_A[idx]; + final double costB = COSINE_TABLE_B[idx]; + + // Polynomial eval of sin(epsilon), cos(epsilon) + double sinEpsA = epsilon; + double sinEpsB = polySine(epsilon); + final double cosEpsA = 1.0; + final double cosEpsB = polyCosine(epsilon); + + // Split epsilon xa + xb = x + final double temp = sinEpsA * HEX_40000000; + double temp2 = (sinEpsA + temp) - temp; + sinEpsB += sinEpsA - temp2; + sinEpsA = temp2; + + /* Compute sin(x) by angle addition formula */ + double result; + + /* Compute the following sum: + * + * result = sintA + costA*sinEpsA + sintA*cosEpsB + costA*sinEpsB + + * sintB + costB*sinEpsA + sintB*cosEpsB + costB*sinEpsB; + * + * Ranges of elements + * + * xxxtA 0 PI/2 + * xxxtB -1.5e-9 1.5e-9 + * sinEpsA -0.0625 0.0625 + * sinEpsB -6e-11 6e-11 + * cosEpsA 1.0 + * cosEpsB 0 -0.0625 + * + */ + + //result = sintA + costA*sinEpsA + sintA*cosEpsB + costA*sinEpsB + + // sintB + costB*sinEpsA + sintB*cosEpsB + costB*sinEpsB; + + //result = sintA + sintA*cosEpsB + sintB + sintB * cosEpsB; + //result += costA*sinEpsA + costA*sinEpsB + costB*sinEpsA + costB * sinEpsB; + double a = 0; + double b = 0; + + double t = sintA; + double c = a + t; + double d = -(c - a - t); + a = c; + b = b + d; + + t = costA * sinEpsA; + c = a + t; + d = -(c - a - t); + a = c; + b = b + d; + + b = b + sintA * cosEpsB + costA * sinEpsB; + /* + t = sintA*cosEpsB; + c = a + t; + d = -(c - a - t); + a = c; + b = b + d; + + t = costA*sinEpsB; + c = a + t; + d = -(c - a - t); + a = c; + b = b + d; + */ + + b = b + sintB + costB * sinEpsA + sintB * cosEpsB + costB * sinEpsB; + /* + t = sintB; + c = a + t; + d = -(c - a - t); + a = c; + b = b + d; + + t = costB*sinEpsA; + c = a + t; + d = -(c - a - t); + a = c; + b = b + d; + + t = sintB*cosEpsB; + c = a + t; + d = -(c - a - t); + a = c; + b = b + d; + + t = costB*sinEpsB; + c = a + t; + d = -(c - a - t); + a = c; + b = b + d; + */ + + if (xb != 0.0) { + t = ((costA + costB) * (cosEpsA + cosEpsB) - + (sintA + sintB) * (sinEpsA + sinEpsB)) * xb; // approximate cosine*xb + c = a + t; + d = -(c - a - t); + a = c; + b = b + d; + } + + result = a + b; + + return result; + } + + /** + * Compute cosine in the first quadrant by subtracting input from PI/2 and + * then calling sinQ. This is more accurate as the input approaches PI/2. + * @param xa number from which cosine is requested + * @param xb extra bits for x (may be 0.0) + * @return cos(xa + xb) + */ + private static double cosQ(double xa, double xb) { + final double pi2a = 1.5707963267948966; + final double pi2b = 6.123233995736766E-17; + + final double a = pi2a - xa; + double b = -(a - pi2a + xa); + b += pi2b - xb; + + return sinQ(a, b); + } + + /** + * Compute tangent (or cotangent) over the first quadrant. 0 < x < pi/2 + * Use combination of table lookup and rational polynomial expansion. + * @param xa number from which sine is requested + * @param xb extra bits for x (may be 0.0) + * @param cotanFlag if true, compute the cotangent instead of the tangent + * @return tan(xa+xb) (or cotangent, depending on cotanFlag) + */ + private static double tanQ(double xa, double xb, boolean cotanFlag) { + + int idx = (int) ((xa * 8.0) + 0.5); + final double epsilon = xa - EIGHTHS[idx]; //idx*0.125; + + // Table lookups + final double sintA = SINE_TABLE_A[idx]; + final double sintB = SINE_TABLE_B[idx]; + final double costA = COSINE_TABLE_A[idx]; + final double costB = COSINE_TABLE_B[idx]; + + // Polynomial eval of sin(epsilon), cos(epsilon) + double sinEpsA = epsilon; + double sinEpsB = polySine(epsilon); + final double cosEpsA = 1.0; + final double cosEpsB = polyCosine(epsilon); + + // Split epsilon xa + xb = x + double temp = sinEpsA * HEX_40000000; + double temp2 = (sinEpsA + temp) - temp; + sinEpsB += sinEpsA - temp2; + sinEpsA = temp2; + + /* Compute sin(x) by angle addition formula */ + + /* Compute the following sum: + * + * result = sintA + costA*sinEpsA + sintA*cosEpsB + costA*sinEpsB + + * sintB + costB*sinEpsA + sintB*cosEpsB + costB*sinEpsB; + * + * Ranges of elements + * + * xxxtA 0 PI/2 + * xxxtB -1.5e-9 1.5e-9 + * sinEpsA -0.0625 0.0625 + * sinEpsB -6e-11 6e-11 + * cosEpsA 1.0 + * cosEpsB 0 -0.0625 + * + */ + + //result = sintA + costA*sinEpsA + sintA*cosEpsB + costA*sinEpsB + + // sintB + costB*sinEpsA + sintB*cosEpsB + costB*sinEpsB; + + //result = sintA + sintA*cosEpsB + sintB + sintB * cosEpsB; + //result += costA*sinEpsA + costA*sinEpsB + costB*sinEpsA + costB * sinEpsB; + double a = 0; + double b = 0; + + // Compute sine + double t = sintA; + double c = a + t; + double d = -(c - a - t); + a = c; + b = b + d; + + t = costA*sinEpsA; + c = a + t; + d = -(c - a - t); + a = c; + b = b + d; + + b = b + sintA*cosEpsB + costA*sinEpsB; + b = b + sintB + costB*sinEpsA + sintB*cosEpsB + costB*sinEpsB; + + double sina = a + b; + double sinb = -(sina - a - b); + + // Compute cosine + + a = b = c = d = 0.0; + + t = costA*cosEpsA; + c = a + t; + d = -(c - a - t); + a = c; + b = b + d; + + t = -sintA*sinEpsA; + c = a + t; + d = -(c - a - t); + a = c; + b = b + d; + + b = b + costB*cosEpsA + costA*cosEpsB + costB*cosEpsB; + b = b - (sintB*sinEpsA + sintA*sinEpsB + sintB*sinEpsB); + + double cosa = a + b; + double cosb = -(cosa - a - b); + + if (cotanFlag) { + double tmp; + tmp = cosa; cosa = sina; sina = tmp; + tmp = cosb; cosb = sinb; sinb = tmp; + } + + + /* estimate and correct, compute 1.0/(cosa+cosb) */ + /* + double est = (sina+sinb)/(cosa+cosb); + double err = (sina - cosa*est) + (sinb - cosb*est); + est += err/(cosa+cosb); + err = (sina - cosa*est) + (sinb - cosb*est); + */ + + // f(x) = 1/x, f'(x) = -1/x^2 + + double est = sina/cosa; + + /* Split the estimate to get more accurate read on division rounding */ + temp = est * HEX_40000000; + double esta = (est + temp) - temp; + double estb = est - esta; + + temp = cosa * HEX_40000000; + double cosaa = (cosa + temp) - temp; + double cosab = cosa - cosaa; + + //double err = (sina - est*cosa)/cosa; // Correction for division rounding + double err = (sina - esta*cosaa - esta*cosab - estb*cosaa - estb*cosab)/cosa; // Correction for division rounding + err += sinb/cosa; // Change in est due to sinb + err += -sina * cosb / cosa / cosa; // Change in est due to cosb + + if (xb != 0.0) { + // tan' = 1 + tan^2 cot' = -(1 + cot^2) + // Approximate impact of xb + double xbadj = xb + est*est*xb; + if (cotanFlag) { + xbadj = -xbadj; + } + + err += xbadj; + } + + return est+err; + } + + /** Reduce the input argument using the Payne and Hanek method. + * This is good for all inputs 0.0 < x < inf + * Output is remainder after dividing by PI/2 + * The result array should contain 3 numbers. + * result[0] is the integer portion, so mod 4 this gives the quadrant. + * result[1] is the upper bits of the remainder + * result[2] is the lower bits of the remainder + * + * @param x number to reduce + * @param result placeholder where to put the result + */ + private static void reducePayneHanek(double x, double result[]) + { + /* Convert input double to bits */ + long inbits = Double.doubleToLongBits(x); + int exponent = (int) ((inbits >> 52) & 0x7ff) - 1023; + + /* Convert to fixed point representation */ + inbits &= 0x000fffffffffffffL; + inbits |= 0x0010000000000000L; + + /* Normalize input to be between 0.5 and 1.0 */ + exponent++; + inbits <<= 11; + + /* Based on the exponent, get a shifted copy of recip2pi */ + long shpi0; + long shpiA; + long shpiB; + int idx = exponent >> 6; + int shift = exponent - (idx << 6); + + if (shift != 0) { + shpi0 = (idx == 0) ? 0 : (RECIP_2PI[idx-1] << shift); + shpi0 |= RECIP_2PI[idx] >>> (64-shift); + shpiA = (RECIP_2PI[idx] << shift) | (RECIP_2PI[idx+1] >>> (64-shift)); + shpiB = (RECIP_2PI[idx+1] << shift) | (RECIP_2PI[idx+2] >>> (64-shift)); + } else { + shpi0 = (idx == 0) ? 0 : RECIP_2PI[idx-1]; + shpiA = RECIP_2PI[idx]; + shpiB = RECIP_2PI[idx+1]; + } + + /* Multiply input by shpiA */ + long a = inbits >>> 32; + long b = inbits & 0xffffffffL; + + long c = shpiA >>> 32; + long d = shpiA & 0xffffffffL; + + long ac = a * c; + long bd = b * d; + long bc = b * c; + long ad = a * d; + + long prodB = bd + (ad << 32); + long prodA = ac + (ad >>> 32); + + boolean bita = (bd & 0x8000000000000000L) != 0; + boolean bitb = (ad & 0x80000000L ) != 0; + boolean bitsum = (prodB & 0x8000000000000000L) != 0; + + /* Carry */ + if ( (bita && bitb) || + ((bita || bitb) && !bitsum) ) { + prodA++; + } + + bita = (prodB & 0x8000000000000000L) != 0; + bitb = (bc & 0x80000000L ) != 0; + + prodB = prodB + (bc << 32); + prodA = prodA + (bc >>> 32); + + bitsum = (prodB & 0x8000000000000000L) != 0; + + /* Carry */ + if ( (bita && bitb) || + ((bita || bitb) && !bitsum) ) { + prodA++; + } + + /* Multiply input by shpiB */ + c = shpiB >>> 32; + d = shpiB & 0xffffffffL; + ac = a * c; + bc = b * c; + ad = a * d; + + /* Collect terms */ + ac = ac + ((bc + ad) >>> 32); + + bita = (prodB & 0x8000000000000000L) != 0; + bitb = (ac & 0x8000000000000000L ) != 0; + prodB += ac; + bitsum = (prodB & 0x8000000000000000L) != 0; + /* Carry */ + if ( (bita && bitb) || + ((bita || bitb) && !bitsum) ) { + prodA++; + } + + /* Multiply by shpi0 */ + c = shpi0 >>> 32; + d = shpi0 & 0xffffffffL; + + bd = b * d; + bc = b * c; + ad = a * d; + + prodA += bd + ((bc + ad) << 32); + + /* + * prodA, prodB now contain the remainder as a fraction of PI. We want this as a fraction of + * PI/2, so use the following steps: + * 1.) multiply by 4. + * 2.) do a fixed point muliply by PI/4. + * 3.) Convert to floating point. + * 4.) Multiply by 2 + */ + + /* This identifies the quadrant */ + int intPart = (int)(prodA >>> 62); + + /* Multiply by 4 */ + prodA <<= 2; + prodA |= prodB >>> 62; + prodB <<= 2; + + /* Multiply by PI/4 */ + a = prodA >>> 32; + b = prodA & 0xffffffffL; + + c = PI_O_4_BITS[0] >>> 32; + d = PI_O_4_BITS[0] & 0xffffffffL; + + ac = a * c; + bd = b * d; + bc = b * c; + ad = a * d; + + long prod2B = bd + (ad << 32); + long prod2A = ac + (ad >>> 32); + + bita = (bd & 0x8000000000000000L) != 0; + bitb = (ad & 0x80000000L ) != 0; + bitsum = (prod2B & 0x8000000000000000L) != 0; + + /* Carry */ + if ( (bita && bitb) || + ((bita || bitb) && !bitsum) ) { + prod2A++; + } + + bita = (prod2B & 0x8000000000000000L) != 0; + bitb = (bc & 0x80000000L ) != 0; + + prod2B = prod2B + (bc << 32); + prod2A = prod2A + (bc >>> 32); + + bitsum = (prod2B & 0x8000000000000000L) != 0; + + /* Carry */ + if ( (bita && bitb) || + ((bita || bitb) && !bitsum) ) { + prod2A++; + } + + /* Multiply input by pio4bits[1] */ + c = PI_O_4_BITS[1] >>> 32; + d = PI_O_4_BITS[1] & 0xffffffffL; + ac = a * c; + bc = b * c; + ad = a * d; + + /* Collect terms */ + ac = ac + ((bc + ad) >>> 32); + + bita = (prod2B & 0x8000000000000000L) != 0; + bitb = (ac & 0x8000000000000000L ) != 0; + prod2B += ac; + bitsum = (prod2B & 0x8000000000000000L) != 0; + /* Carry */ + if ( (bita && bitb) || + ((bita || bitb) && !bitsum) ) { + prod2A++; + } + + /* Multiply inputB by pio4bits[0] */ + a = prodB >>> 32; + b = prodB & 0xffffffffL; + c = PI_O_4_BITS[0] >>> 32; + d = PI_O_4_BITS[0] & 0xffffffffL; + ac = a * c; + bc = b * c; + ad = a * d; + + /* Collect terms */ + ac = ac + ((bc + ad) >>> 32); + + bita = (prod2B & 0x8000000000000000L) != 0; + bitb = (ac & 0x8000000000000000L ) != 0; + prod2B += ac; + bitsum = (prod2B & 0x8000000000000000L) != 0; + /* Carry */ + if ( (bita && bitb) || + ((bita || bitb) && !bitsum) ) { + prod2A++; + } + + /* Convert to double */ + double tmpA = (prod2A >>> 12) / TWO_POWER_52; // High order 52 bits + double tmpB = (((prod2A & 0xfffL) << 40) + (prod2B >>> 24)) / TWO_POWER_52 / TWO_POWER_52; // Low bits + + double sumA = tmpA + tmpB; + double sumB = -(sumA - tmpA - tmpB); + + /* Multiply by PI/2 and return */ + result[0] = intPart; + result[1] = sumA * 2.0; + result[2] = sumB * 2.0; + } + + /** + * Sine function. + * + * @param x Argument. + * @return sin(x) + */ + public static double sin(double x) { + boolean negative = false; + int quadrant = 0; + double xa; + double xb = 0.0; + + /* Take absolute value of the input */ + xa = x; + if (x < 0) { + negative = true; + xa = -xa; + } + + /* Check for zero and negative zero */ + if (xa == 0.0) { + long bits = Double.doubleToLongBits(x); + if (bits < 0) { + return -0.0; + } + return 0.0; + } + + if (xa != xa || xa == Double.POSITIVE_INFINITY) { + return Double.NaN; + } + + /* Perform any argument reduction */ + if (xa > 3294198.0) { + // PI * (2**20) + // Argument too big for CodyWaite reduction. Must use + // PayneHanek. + double reduceResults[] = new double[3]; + reducePayneHanek(xa, reduceResults); + quadrant = ((int) reduceResults[0]) & 3; + xa = reduceResults[1]; + xb = reduceResults[2]; + } else if (xa > 1.5707963267948966) { + final CodyWaite cw = new CodyWaite(xa); + quadrant = cw.getK() & 3; + xa = cw.getRemA(); + xb = cw.getRemB(); + } + + if (negative) { + quadrant ^= 2; // Flip bit 1 + } + + switch (quadrant) { + case 0: + return sinQ(xa, xb); + case 1: + return cosQ(xa, xb); + case 2: + return -sinQ(xa, xb); + case 3: + return -cosQ(xa, xb); + default: + return Double.NaN; + } + } + + /** + * Cosine function. + * + * @param x Argument. + * @return cos(x) + */ + public static double cos(double x) { + int quadrant = 0; + + /* Take absolute value of the input */ + double xa = x; + if (x < 0) { + xa = -xa; + } + + if (xa != xa || xa == Double.POSITIVE_INFINITY) { + return Double.NaN; + } + + /* Perform any argument reduction */ + double xb = 0; + if (xa > 3294198.0) { + // PI * (2**20) + // Argument too big for CodyWaite reduction. Must use + // PayneHanek. + double reduceResults[] = new double[3]; + reducePayneHanek(xa, reduceResults); + quadrant = ((int) reduceResults[0]) & 3; + xa = reduceResults[1]; + xb = reduceResults[2]; + } else if (xa > 1.5707963267948966) { + final CodyWaite cw = new CodyWaite(xa); + quadrant = cw.getK() & 3; + xa = cw.getRemA(); + xb = cw.getRemB(); + } + + //if (negative) + // quadrant = (quadrant + 2) % 4; + + switch (quadrant) { + case 0: + return cosQ(xa, xb); + case 1: + return -sinQ(xa, xb); + case 2: + return -cosQ(xa, xb); + case 3: + return sinQ(xa, xb); + default: + return Double.NaN; + } + } + + /** + * Tangent function. + * + * @param x Argument. + * @return tan(x) + */ + public static double tan(double x) { + boolean negative = false; + int quadrant = 0; + + /* Take absolute value of the input */ + double xa = x; + if (x < 0) { + negative = true; + xa = -xa; + } + + /* Check for zero and negative zero */ + if (xa == 0.0) { + long bits = Double.doubleToLongBits(x); + if (bits < 0) { + return -0.0; + } + return 0.0; + } + + if (xa != xa || xa == Double.POSITIVE_INFINITY) { + return Double.NaN; + } + + /* Perform any argument reduction */ + double xb = 0; + if (xa > 3294198.0) { + // PI * (2**20) + // Argument too big for CodyWaite reduction. Must use + // PayneHanek. + double reduceResults[] = new double[3]; + reducePayneHanek(xa, reduceResults); + quadrant = ((int) reduceResults[0]) & 3; + xa = reduceResults[1]; + xb = reduceResults[2]; + } else if (xa > 1.5707963267948966) { + final CodyWaite cw = new CodyWaite(xa); + quadrant = cw.getK() & 3; + xa = cw.getRemA(); + xb = cw.getRemB(); + } + + if (xa > 1.5) { + // Accuracy suffers between 1.5 and PI/2 + final double pi2a = 1.5707963267948966; + final double pi2b = 6.123233995736766E-17; + + final double a = pi2a - xa; + double b = -(a - pi2a + xa); + b += pi2b - xb; + + xa = a + b; + xb = -(xa - a - b); + quadrant ^= 1; + negative ^= true; + } + + double result; + if ((quadrant & 1) == 0) { + result = tanQ(xa, xb, false); + } else { + result = -tanQ(xa, xb, true); + } + + if (negative) { + result = -result; + } + + return result; + } + + + /** Enclose the Cody/Waite reduction (used in "sin", "cos" and "tan"). */ + private static class CodyWaite { + /** k */ + private final int finalK; + /** remA */ + private final double finalRemA; + /** remB */ + private final double finalRemB; + + /** + * @param xa Argument. + */ + CodyWaite(double xa) { + // Estimate k. + //k = (int)(xa / 1.5707963267948966); + int k = (int)(xa * 0.6366197723675814); + + // Compute remainder. + double remA; + double remB; + while (true) { + double a = -k * 1.570796251296997; + remA = xa + a; + remB = -(remA - xa - a); + + a = -k * 7.549789948768648E-8; + double b = remA; + remA = a + b; + remB += -(remA - b - a); + + a = -k * 6.123233995736766E-17; + b = remA; + remA = a + b; + remB += -(remA - b - a); + + if (remA > 0) { + break; + } + + // Remainder is negative, so decrement k and try again. + // This should only happen if the input is very close + // to an even multiple of pi/2. + --k; + } + + this.finalK = k; + this.finalRemA = remA; + this.finalRemB = remB; + } + + /** + * @return k + */ + int getK() { + return finalK; + } + /** + * @return remA + */ + double getRemA() { + return finalRemA; + } + /** + * @return remB + */ + double getRemB() { + return finalRemB; + } + } +} diff --git a/src/com/annimon/visualme/Fps.java b/src/com/annimon/visualme/Fps.java new file mode 100644 index 0000000..b386621 --- /dev/null +++ b/src/com/annimon/visualme/Fps.java @@ -0,0 +1,35 @@ +/* By aNNiMON from GipGameActivity */ + +package com.annimon.visualme; + +public class Fps { + + private static final int MAX_FPS = 30; + private static final int MAX_DELAY = 1000 / MAX_FPS; + + private static long currentFps; + private static long counter = 0, startTime = 0; + private static long startTimeForMeasureDelay = 0; + + public static String getFpsAsString() { + counter++; + if (startTime == 0) { + startTime = System.currentTimeMillis(); + } + if ((System.currentTimeMillis() - startTime) >= 1000) { + currentFps = counter; + counter = 0; + startTime = System.currentTimeMillis(); + } + return Long.toString(currentFps); + } + + public static void startMeasuringDelay() { + startTimeForMeasureDelay = System.currentTimeMillis(); + } + + public static long getDelay() { + long delay = System.currentTimeMillis() - startTimeForMeasureDelay; + return (delay > MAX_DELAY ? 0 : MAX_DELAY - delay); + } +} diff --git a/src/com/annimon/visualme/GameSurfaceView.java b/src/com/annimon/visualme/GameSurfaceView.java new file mode 100644 index 0000000..bf26bb9 --- /dev/null +++ b/src/com/annimon/visualme/GameSurfaceView.java @@ -0,0 +1,146 @@ +package com.annimon.visualme; + +import com.annimon.visualme.visuals.Visual; +import com.annimon.visualme.visuals.VisualME; + +import android.content.Context; +import android.content.SharedPreferences; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.preference.PreferenceManager; +import android.view.MotionEvent; +import android.view.SurfaceHolder; +import android.view.SurfaceView; + +public class GameSurfaceView extends SurfaceView implements SurfaceHolder.Callback { + + private static final int BACKGROUND_COLOR = 0xff000000; + + private boolean showFps; + private Paint paint; + private SurfaceHolder surfaceHolder; + private DrawingThread thread; + + private Visual visual; + + + public GameSurfaceView(Context context) { + super(context); + + surfaceHolder = getHolder(); + surfaceHolder.addCallback(this); + + visual = new VisualME(); + SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(context); + showFps = pref.getBoolean("show_fps", false); + if (visual instanceof VisualME) { + VisualME vis = (VisualME) visual; + vis.setNumberOfBranches( Integer.parseInt(pref.getString("branches", "15")) ); + vis.setFlexibility( Integer.parseInt(pref.getString("flexibility", "20")) ); + vis.setScreenProportions( Integer.parseInt(pref.getString("proportions", "4")) ); + vis.setSpeed( Integer.parseInt(pref.getString("speed", "1")) ); + + vis.setShapeType( Integer.parseInt(pref.getString("shape_type", "0")) ); + + vis.setVisualizationAutochange( pref.getBoolean("autochangevis", true) ); + vis.setShapeAutochange( pref.getBoolean("autochangefig", false) ); + } + } + + @Override + public void surfaceCreated(SurfaceHolder holder) { + paint = new Paint(Paint.ANTI_ALIAS_FLAG); + paint.setStyle(Paint.Style.FILL); + + + + thread = new DrawingThread(); + thread.keepRunning = true; + thread.start(); + } + + @Override + public void surfaceChanged(SurfaceHolder holder, int format, int newW, int newH) { + visual.sizeChanged(newW, newH); + } + + @Override + public void surfaceDestroyed(SurfaceHolder holder) { + thread.keepRunning = false; + boolean retry = true; + while (retry) { + try { + thread.join(); + retry = false; + + paint = null; + thread = null; + } catch (InterruptedException e) { + } + } + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + visual.onTouch((int) event.getX(), (int)event.getY()); + return true; + } + return super.onTouchEvent(event); + } + + @Override + protected void onDraw(Canvas canvas) { + // Fill background + paint.setColor(BACKGROUND_COLOR); + canvas.drawPaint(paint); + + visual.paint(canvas, paint); + + // Draw FPS + if (showFps) { + paint.setColor(Color.WHITE); + canvas.drawText(Fps.getFpsAsString(), 10, 10, paint); + } + } + + private void update() { + visual.update(); + } + + private class DrawingThread extends Thread { + public boolean keepRunning = true; + + @Override + public void run() { + Canvas c; + + while (keepRunning) { + Fps.startMeasuringDelay(); + update(); + c = null; + + try { + c = surfaceHolder.lockCanvas(); + if (c != null) { + synchronized (surfaceHolder) { + onDraw(c); + } + } + } finally { + if (c != null) { + surfaceHolder.unlockCanvasAndPost(c); + } + } + + try { + Thread.sleep(Fps.getDelay()); + } catch (InterruptedException ex) { + Thread.currentThread().interrupt(); + } + } + } + } +} \ No newline at end of file diff --git a/src/com/annimon/visualme/MainActivity.java b/src/com/annimon/visualme/MainActivity.java new file mode 100644 index 0000000..09765b7 --- /dev/null +++ b/src/com/annimon/visualme/MainActivity.java @@ -0,0 +1,23 @@ +package com.annimon.visualme; + +import android.app.Activity; +import android.os.Bundle; +import android.view.WindowManager; + +public class MainActivity extends Activity { + + private GameSurfaceView gameView; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + // Turn on the backlight + getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, + WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + + gameView = new GameSurfaceView(this); + gameView.setFocusable(true); + setContentView(gameView); + } +} \ No newline at end of file diff --git a/src/com/annimon/visualme/SettingsActivity.java b/src/com/annimon/visualme/SettingsActivity.java new file mode 100644 index 0000000..bcf9e26 --- /dev/null +++ b/src/com/annimon/visualme/SettingsActivity.java @@ -0,0 +1,14 @@ +package com.annimon.visualme; + +import android.os.Bundle; +import android.preference.PreferenceActivity; + +public class SettingsActivity extends PreferenceActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + addPreferencesFromResource(R.xml.visualme); + } + +} diff --git a/src/com/annimon/visualme/visuals/Visual.java b/src/com/annimon/visualme/visuals/Visual.java new file mode 100644 index 0000000..23b08d2 --- /dev/null +++ b/src/com/annimon/visualme/visuals/Visual.java @@ -0,0 +1,24 @@ +package com.annimon.visualme.visuals; + +import android.graphics.Canvas; +import android.graphics.Paint; + +public abstract class Visual { + + protected int width, height; + + public void sizeChanged(int width, int height) { + this.width = width; + this.height = height; + init(); + } + + public abstract void init(); + + public abstract void paint(Canvas canvas, Paint paint); + + public abstract void onTouch(int x, int y); + + public abstract void update(); + +} diff --git a/src/com/annimon/visualme/visuals/VisualME.java b/src/com/annimon/visualme/visuals/VisualME.java new file mode 100644 index 0000000..1d7d200 --- /dev/null +++ b/src/com/annimon/visualme/visuals/VisualME.java @@ -0,0 +1,403 @@ +package com.annimon.visualme.visuals; + +import java.util.Random; + +import com.annimon.visualme.FastMath; + +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.RectF; + +public class VisualME extends Visual { + + private static final int MAX_DELTA_COLOR = 20; + + protected static final Random random = new Random(); + + // + private int numberOfBranches; + private int flexibility; + private float screenProportions; + private int shapeType; + private int speed; + + // + private boolean shapeAutochange; + private boolean visualizationAutochange; + + // + private boolean redChange, greenChange, blueChange; + + private int rc, gc, bc; + private int rgbChangeMode, visualMode, colorMode; + private int startAngleInt; + private float angleDelta;// + private float len; // + private float[] angles; + + private Thread thr; + + public void init() { + // () + rc = 0; + gc = 0; + bc = 0; + // () + rgbChangeMode = 1; + // + visualMode = 1; + // + colorMode = 1; + + // + startAngleInt = random.nextInt(360); + + // + if (width > height) { + len = height / screenProportions / flexibility; + } else { + len = width / screenProportions / flexibility; + } + + thr = new Thread(new Runnable() { + + @Override + public void run() { + while (thr == Thread.currentThread()) { + threadUpdate(); + } + } + }); + thr.start(); + } + + /** + * . + * @param flexibility . + */ + public void setFlexibility(int flexibility) { + this.flexibility = flexibility; + angles = new float[flexibility]; + } + + /** + * . + * @param numberOfBranches + */ + public void setNumberOfBranches(int numberOfBranches) { + this.numberOfBranches = numberOfBranches; + // + angleDelta = (float) (2 * FastMath.PI / numberOfBranches); + } + + /** + * . + * @param screenProportions + */ + public void setScreenProportions(int screenProportions) { + this.screenProportions = 4f / screenProportions; + } + + /** + * (, , ..). + * @param shapeType + */ + public void setShapeType(int shapeType) { + this.shapeType = shapeType; + } + + /** + * . + * @param speed + */ + public void setSpeed(int speed) { + this.speed = 10 - speed; + } + + /** + * . + * @param shapeAutochange + */ + public void setShapeAutochange(boolean shapeAutochange) { + this.shapeAutochange = shapeAutochange; + } + + /** + * . + * @param visualizationAutochange + */ + public void setVisualizationAutochange(boolean visualizationAutochange) { + this.visualizationAutochange = visualizationAutochange; + } + + @Override + public void paint(Canvas canvas, Paint paint) { + if (random.nextInt(20) == 5) startAngleInt = random.nextInt(360); + + // + float startAngle = (float) (startAngleInt * FastMath.PI / 180); + + // + angles[0] = (float) (angles[0] + FastMath.sin(startAngle) / speed); + for (int i = 1; i < flexibility; i++) { + angles[i] = (float) (angles[i] + (angles[i - 1] - angles[i]) * 0.1); + } + + //String currentTime = ""; + //if (shapeType == 3) currentTime = time2fileName(); + for (int j = 0; j < numberOfBranches; j++) { + float x = 0.5f * width; + float y = 0.5f * height; + float tx = 0, ty = 0; + final float temp1 = j * angleDelta + angles[1]; + for (int i = 1; i < flexibility; i++) { + final float temp2 = j * angleDelta + angles[i]; + if (visualMode == 1) { + tx = (float) (x + FastMath.cos(temp1) * len); + ty = (float) (y + FastMath.sin(temp2) * len); + x = x + (float) (FastMath.cos(temp2) * len); + } + else if (visualMode == 2) { + tx = (float) (x + FastMath.sin(temp2) * len); + ty = (float) (y + FastMath.cos(temp2) * len); + } + else if (visualMode == 3) { + tx = (float) (x + FastMath.tan(temp1) * len); + ty = (float) (y + FastMath.cos(temp2) * len); + y = y - (float) (FastMath.sin(temp2) * len); + } + else if (visualMode == 4) { + tx = (float) (x + FastMath.tan(temp1) * len); + ty = (float) (y + FastMath.cos(temp2) * len); + x = y - (float) (FastMath.sin(temp2) * len); + } + else if (visualMode == 5) { + tx = (float) (x + FastMath.tan(temp1) * len); + ty = (float) (y + FastMath.cos(temp2) * len); + x = x * ty * angleDelta + angles[i] - (float) (FastMath.sin(temp2) * len); + } + else if (visualMode == 6) { + x = x + (float) (FastMath.sin(temp2) * len); + y = y + (float) (FastMath.cos(temp2) * len); + tx = (float) (x + FastMath.cos(temp1) * len); + ty = (float) (y + FastMath.sin(temp1) * len); + x = x + (float) (FastMath.sin(temp2) * len); + y = y + (float) (FastMath.cos(temp2) * len); + } + + if (colorMode == 1) setColor(paint, rc, gc, bc); + else { + final int deltaColor = 255 - 255 * i / flexibility; + if (colorMode == 2) setColor(paint, deltaColor, 0, 255); + else if (colorMode == 3) setColor(paint, deltaColor, 255, 0); + else if (colorMode == 4) setColor(paint, deltaColor, 255, 255); + + else if (colorMode == 5) setColor(paint, 0, deltaColor, 255); + else if (colorMode == 6) setColor(paint, 255, deltaColor, 0); + else if (colorMode == 7) setColor(paint, 255, deltaColor, 255); + + else if (colorMode == 8) setColor(paint, 0, 255, deltaColor); + else if (colorMode == 9) setColor(paint, 255, 0, deltaColor); + else if (colorMode == 10) setColor(paint, 255, 255, deltaColor); + + else if (colorMode == 11) setColor(paint, deltaColor, deltaColor, 0); + else if (colorMode == 12) setColor(paint, deltaColor, deltaColor, 255); + + else if (colorMode == 13) setColor(paint, deltaColor, 0, deltaColor); + else if (colorMode == 14) setColor(paint, deltaColor, 255, deltaColor); + + else if (colorMode == 15) setColor(paint, 0, deltaColor, deltaColor); + else if (colorMode == 16) setColor(paint, 255, deltaColor, deltaColor); + + else if (colorMode == 17) setColor(paint, rc, deltaColor, 255); + else if (colorMode == 18) setColor(paint, 255, gc, deltaColor); + else if (colorMode == 19) setColor(paint, 255, deltaColor, bc); + + else if (colorMode == 20) setColor(paint, bc, rc, deltaColor); + } + + if (shapeType == 0) canvas.drawLine(x, y, tx, ty, paint); + else if (shapeType == 1) { + RectF rf = new RectF(tx, ty, x, y); + canvas.drawArc(rf, 0, 360, false, paint); + } + else if (shapeType == 2) canvas.drawRect(tx, ty, x, y, paint); + // else if (shapeType == 3) grf.drawString(currentTime,(int) x, (int) y, 20); + + x = tx; + y = ty; + } + } + // Motion-Blur + //grf.drawRGB(backgroundPixels, 0, width, 0, 0, width, height/2, true); + //grf.drawRGB(backgroundPixels, 0, width, 0, height/2, width, height/2, true); + + } + + @Override + public void onTouch(int x, int y) { + if (y >= (height / 2)) { + colorMode++; + if (colorMode > MAX_DELTA_COLOR) { + colorMode = 1; + } + } else { + visualMode++; + if (visualMode > 6) { + visualMode = 1; + } + } + } + + @Override + public void update() { + rgb(); + } + + public void threadUpdate() { + int i = random.nextInt(40); + if (visualizationAutochange) { + if (i == 16) colorMode = random.nextInt(MAX_DELTA_COLOR) + 1; + else if (i == 19) visualMode = random.nextInt(6) + 1; + } + if (shapeAutochange) if (i == 36) shapeType = random.nextInt(4); + + try { + Thread.sleep(800); + } catch (InterruptedException ex) {} + } + + private void setColor(Paint paint, int red, int green, int blue) { + paint.setColor(Color.argb(255, red, green, blue)); + } + + private void rgb() { + if (rgbChangeMode == 1) { + rc++; + if (rc > 253) { + rc--; + redChange = true; + } + if (redChange == true) { + rc = rc - 2; + } + if (rc < 18 && redChange == true) { + rc = 0; + redChange = false; + rgbChangeMode++; + } + } + else if (rgbChangeMode == 2) { + gc++; + if (gc > 253) { + gc--; + greenChange = true; + } + if (greenChange == true) { + gc = gc - 2; + } + if (gc < 18 && greenChange == true) { + gc = 0; + greenChange = false; + rgbChangeMode++; + } + } + else if (rgbChangeMode == 3) { + bc++; + if (bc > 253) { + bc--; + blueChange = true; + } + if (blueChange == true) { + bc = bc - 2; + } + if (bc < 18 && blueChange == true) { + bc = 0; + blueChange = false; + rgbChangeMode++; + } + } + else if (rgbChangeMode == 4) { + rc++; + gc++; + if (rc > 253) { + rc--; + gc--; + redChange = true; + } + if (redChange == true) { + rc = rc - 2; + gc = gc - 2; + } + if (rc < 18 && redChange == true) { + rc = 0; + gc = 0; + redChange = false; + rgbChangeMode++; + } + } + else if (rgbChangeMode == 5) { + rc++; + bc++; + if (rc > 253) { + rc--; + bc--; + redChange = true; + } + if (redChange == true) { + rc = rc - 2; + bc = bc - 2; + } + if (rc < 18 && redChange == true) { + rc = 0; + bc = 0; + redChange = false; + rgbChangeMode++; + } + } + else if (rgbChangeMode == 6) { + gc++; + bc++; + if (gc > 253) { + gc--; + bc--; + greenChange = true; + } + if (greenChange == true) { + gc = gc - 2; + bc = bc - 2; + } + if (gc < 18 && greenChange == true) { + gc = 0; + bc = 0; + greenChange = false; + rgbChangeMode++; + } + } + else if (rgbChangeMode == 7) { + rc++; + gc++; + bc++; + if (gc > 253) { + rc--; + gc--; + bc--; + greenChange = true; + } + if (greenChange == true) { + rc = rc - 2; + gc = gc - 2; + bc = bc - 2; + } + if (gc < 18 && greenChange == true) { + rc = 0; + gc = 0; + bc = 0; + greenChange = false; + rgbChangeMode = 1; + } + } + } + +}