diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..d744708 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,32 @@ +apply plugin: 'com.android.application' + +sourceCompatibility = source_compatibility +targetCompatibility = target_compatibility + +repositories { + google() + jcenter() +} + +android { + compileSdkVersion 28 + defaultConfig { + applicationId "org.kynosarges.tektosyne" + minSdkVersion 16 + targetSdkVersion 28 + versionCode 1 + versionName "1.0" + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation 'com.android.support:appcompat-v7:28.0.0' +} diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..0e159cd --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,11 @@ + + + + diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..a9844a8 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..49e2583 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,171 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..6d5e5d0 --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..6d5e5d0 --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..898f3ed Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000..dffca36 Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..64ba76f Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000..dae5e08 Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..e5ed465 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000..14ed0af Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..b0907ca Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..d8ae031 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..2c18de9 Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..beed3cd Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..b2b4267 --- /dev/null +++ b/app/src/main/res/values/colors.xml @@ -0,0 +1,6 @@ + + + #008577 + #00574B + #D81B60 + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..d7149f9 --- /dev/null +++ b/app/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + Tektosyne + diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..705be27 --- /dev/null +++ b/app/src/main/res/values/styles.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/build.gradle b/build.gradle index 4e190d7..c6ce7cd 100644 --- a/build.gradle +++ b/build.gradle @@ -8,14 +8,18 @@ buildscript { ext.project_license_tag = 'MIT' // the license tag name ext.project_license_url = 'https://raw.githubusercontent.com/kynosarges/tektosyne/master/LICENSE.txt' // link to the license - ext.your_github_name = 'PixelBumper' + ext.your_github_name = 'toteto' ext.source_compatibility = '1.8' ext.target_compatibility = '1.8' repositories{ + google() mavenCentral() jcenter() } + dependencies { + classpath 'com.android.tools.build:gradle:3.2.1' + } } diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..82618ce --- /dev/null +++ b/gradle.properties @@ -0,0 +1,15 @@ +# Project-wide Gradle settings. +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx1536m +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true + + diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e1205dc..e3fd96f 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Sun Mar 12 18:46:54 CET 2017 +#Thu Nov 29 21:00:46 CET 2018 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip diff --git a/settings.gradle b/settings.gradle index f852a0c..c8aa638 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,3 +1,4 @@ rootProject.name = 'tektosyne' include 'tektosyne' include 'tektosyne-demo' +include ':app' diff --git a/tektosyne/src/main/java/org/kynosarges/tektosyne/Fortran.java b/tektosyne/src/main/java/org/kynosarges/tektosyne/Fortran.java index 98d549a..8ac9388 100755 --- a/tektosyne/src/main/java/org/kynosarges/tektosyne/Fortran.java +++ b/tektosyne/src/main/java/org/kynosarges/tektosyne/Fortran.java @@ -334,7 +334,7 @@ public static float modulo(float a, float p) { * @throws ArithmeticException if {@code p} is zero */ public static int modulo(int a, int p) { - return Math.floorMod(a, p); + return MathCompat.floorMod(a, p); } /** @@ -348,7 +348,7 @@ public static int modulo(int a, int p) { * @throws ArithmeticException if {@code p} is zero */ public static long modulo(long a, long p) { - return Math.floorMod(a, p); + return MathCompat.floorMod(a, p); } /** @@ -429,7 +429,7 @@ public static float sum(float... args) { public static int sum(int... args) { int sum = 0; for (int n: args) - sum = Math.addExact(sum, n); + sum = MathCompat.addExact(sum, n); return sum; } @@ -446,7 +446,7 @@ public static int sum(int... args) { public static long sum(long... args) { long sum = 0; for (long n: args) - sum = Math.addExact(sum, n); + sum = MathCompat.addExact(sum, n); return sum; } diff --git a/tektosyne/src/main/java/org/kynosarges/tektosyne/MathCompat.java b/tektosyne/src/main/java/org/kynosarges/tektosyne/MathCompat.java new file mode 100644 index 0000000..4d6ac9f --- /dev/null +++ b/tektosyne/src/main/java/org/kynosarges/tektosyne/MathCompat.java @@ -0,0 +1,241 @@ +package org.kynosarges.tektosyne; + +/** + * Provide needed {@link Math} from Java 1.8 to standard Java 1.7 for backward compatibility. + */ +public final class MathCompat { + + private MathCompat() { + //no instance + } + + /** + * Returns the sum of its arguments, + * throwing an exception if the result overflows an {@code int}. + * + * @param x the first value + * @param y the second value + * @return the result + * @throws ArithmeticException if the result overflows an int + * @since 1.8 + */ + public static int addExact(int x, int y) { + int r = x + y; + // HD 2-12 Overflow iff both arguments have the opposite sign of the result + if (((x ^ r) & (y ^ r)) < 0) { + throw new ArithmeticException("integer overflow"); + } + return r; + } + + /** + * Returns the sum of its arguments, + * throwing an exception if the result overflows a {@code long}. + * + * @param x the first value + * @param y the second value + * @return the result + * @throws ArithmeticException if the result overflows a long + * @since 1.8 + */ + public static long addExact(long x, long y) { + long r = x + y; + // HD 2-12 Overflow iff both arguments have the opposite sign of the result + if (((x ^ r) & (y ^ r)) < 0) { + throw new ArithmeticException("long overflow"); + } + return r; + } + + /** + * Returns the difference of the arguments, + * throwing an exception if the result overflows an {@code int}. + * + * @param x the first value + * @param y the second value to subtract from the first + * @return the result + * @throws ArithmeticException if the result overflows an int + * @since 1.8 + */ + public static int subtractExact(int x, int y) { + int r = x - y; + // HD 2-12 Overflow iff the arguments have different signs and + // the sign of the result is different than the sign of x + if (((x ^ y) & (x ^ r)) < 0) { + throw new ArithmeticException("integer overflow"); + } + return r; + } + + /** + * Returns the difference of the arguments, + * throwing an exception if the result overflows a {@code long}. + * + * @param x the first value + * @param y the second value to subtract from the first + * @return the result + * @throws ArithmeticException if the result overflows a long + * @since 1.8 + */ + public static long subtractExact(long x, long y) { + long r = x - y; + // HD 2-12 Overflow iff the arguments have different signs and + // the sign of the result is different than the sign of x + if (((x ^ y) & (x ^ r)) < 0) { + throw new ArithmeticException("long overflow"); + } + return r; + } + + /** + * Returns the largest (closest to positive infinity) + * {@code int} value that is less than or equal to the algebraic quotient. + * There is one special case, if the dividend is the + * {@linkplain Integer#MIN_VALUE Integer.MIN_VALUE} and the divisor is {@code -1}, + * then integer overflow occurs and + * the result is equal to the {@code Integer.MIN_VALUE}. + *

+ * Normal integer division operates under the round to zero rounding mode + * (truncation). This operation instead acts under the round toward + * negative infinity (floor) rounding mode. + * The floor rounding mode gives different results than truncation + * when the exact result is negative. + *

+ *

+ * + * @param x the dividend + * @param y the divisor + * @return the largest (closest to positive infinity) + * {@code int} value that is less than or equal to the algebraic quotient. + * @throws ArithmeticException if the divisor {@code y} is zero + * @see #floorMod(int, int) + * @since 1.8 + */ + public static int floorDiv(int x, int y) { + int r = x / y; + // if the signs are different and modulo not zero, round down + if ((x ^ y) < 0 && (r * y != x)) { + r--; + } + return r; + } + + /** + * Returns the largest (closest to positive infinity) + * {@code long} value that is less than or equal to the algebraic quotient. + * There is one special case, if the dividend is the + * {@linkplain Long#MIN_VALUE Long.MIN_VALUE} and the divisor is {@code -1}, + * then integer overflow occurs and + * the result is equal to the {@code Long.MIN_VALUE}. + *

+ * Normal integer division operates under the round to zero rounding mode + * (truncation). This operation instead acts under the round toward + * negative infinity (floor) rounding mode. + * The floor rounding mode gives different results than truncation + * when the exact result is negative. + *

+ * For examples, see {@link #floorDiv(int, int)}. + * + * @param x the dividend + * @param y the divisor + * @return the largest (closest to positive infinity) + * {@code long} value that is less than or equal to the algebraic quotient. + * @throws ArithmeticException if the divisor {@code y} is zero + * @see #floorMod(long, long) + * @since 1.8 + */ + public static long floorDiv(long x, long y) { + long r = x / y; + // if the signs are different and modulo not zero, round down + if ((x ^ y) < 0 && (r * y != x)) { + r--; + } + return r; + } + + /** + * Returns the floor modulus of the {@code int} arguments. + *

+ * The floor modulus is {@code x - (floorDiv(x, y) * y)}, + * has the same sign as the divisor {@code y}, and + * is in the range of {@code -abs(y) < r < +abs(y)}. + * + *

+ * The relationship between {@code floorDiv} and {@code floorMod} is such that: + *

+ *

+ * The difference in values between {@code floorMod} and + * the {@code %} operator is due to the difference between + * {@code floorDiv} that returns the integer less than or equal to the quotient + * and the {@code /} operator that returns the integer closest to zero. + *

+ * Examples: + *

+ *

+ * If the signs of arguments are unknown and a positive modulus + * is needed it can be computed as {@code (floorMod(x, y) + abs(y)) % abs(y)}. + * + * @param x the dividend + * @param y the divisor + * @return the floor modulus {@code x - (floorDiv(x, y) * y)} + * @throws ArithmeticException if the divisor {@code y} is zero + * @see #floorDiv(int, int) + * @since 1.8 + */ + public static int floorMod(int x, int y) { + int r = x - floorDiv(x, y) * y; + return r; + } + + /** + * Returns the floor modulus of the {@code long} arguments. + *

+ * The floor modulus is {@code x - (floorDiv(x, y) * y)}, + * has the same sign as the divisor {@code y}, and + * is in the range of {@code -abs(y) < r < +abs(y)}. + * + *

+ * The relationship between {@code floorDiv} and {@code floorMod} is such that: + *

+ *

+ * For examples, see {@link #floorMod(int, int)}. + * + * @param x the dividend + * @param y the divisor + * @return the floor modulus {@code x - (floorDiv(x, y) * y)} + * @throws ArithmeticException if the divisor {@code y} is zero + * @see #floorDiv(long, long) + * @since 1.8 + */ + public static long floorMod(long x, long y) { + return x - floorDiv(x, y) * y; + } + +} diff --git a/tektosyne/src/main/java/org/kynosarges/tektosyne/MathUtils.java b/tektosyne/src/main/java/org/kynosarges/tektosyne/MathUtils.java index 20e4ce0..1ede4a1 100755 --- a/tektosyne/src/main/java/org/kynosarges/tektosyne/MathUtils.java +++ b/tektosyne/src/main/java/org/kynosarges/tektosyne/MathUtils.java @@ -14,7 +14,7 @@ */ public final class MathUtils { - private final static ThreadLocalRandom RANDOM = ThreadLocalRandom.current(); + private final static Random RANDOM = ThreadLocalRandomCompat.current(); /** * Creates a {@link MathUtils} instance. diff --git a/tektosyne/src/main/java/org/kynosarges/tektosyne/QuadTree.java b/tektosyne/src/main/java/org/kynosarges/tektosyne/QuadTree.java index 48e3948..326dd66 100755 --- a/tektosyne/src/main/java/org/kynosarges/tektosyne/QuadTree.java +++ b/tektosyne/src/main/java/org/kynosarges/tektosyne/QuadTree.java @@ -240,8 +240,8 @@ public boolean containsValue(V value, Node node) { * {@code arrayIndex} plus {@link #size} is greater than the length of {@code array} * @throws NullPointerException if {@code array} is {@code null} */ - public void copyTo(Map.Entry[] array, int arrayIndex) { - for (Map.Entry entry: entrySet()) + public void copyTo(Entry[] array, int arrayIndex) { + for (Entry entry: entrySet()) array[arrayIndex++] = entry; } @@ -701,7 +701,7 @@ public V put(PointD key, V value) { */ @Override public void putAll(Map map) { - for (Map.Entry entry: map.entrySet()) + for (Entry entry: map.entrySet()) put(entry.getKey(), entry.getValue()); } @@ -874,7 +874,7 @@ public boolean addAll(Collection> collection) { final int oldSize = _size; boolean changed = false; - for (Map.Entry entry: collection) { + for (Entry entry: collection) { final V value = entry.getValue(); if (!Objects.equals(value, put(entry.getKey(), value))) changed = true; @@ -912,7 +912,7 @@ public void clear() { * * @param obj the element to examine * @return {@code true} if {@code obj} was found, else {@code false} - * @throws ClassCastException if {@code obj} cannot be cast to {@link Map.Entry} + * @throws ClassCastException if {@code obj} cannot be cast to {@link Entry} * with a {@link PointD} key and a V value * @throws NullPointerException if {@code obj} or its key is {@code null} */ @@ -970,7 +970,7 @@ public Iterator> iterator() { * * @param obj the element to remove * @return {@code true} if {@code obj} was found and removed, else {@code false} - * @throws ClassCastException if {@code obj} cannot be cast to {@link Map.Entry} + * @throws ClassCastException if {@code obj} cannot be cast to {@link Entry} * with a {@link PointD} key and a V value * @throws NullPointerException if {@code obj} or its key is {@code null} */ @@ -1396,7 +1396,7 @@ private void findRange(RectD range, boolean useCircle, Map output) { final double x = range.min.x + radius; final double y = range.min.y + radius; - for (Map.Entry pair: _entries.entrySet()) { + for (Entry pair: _entries.entrySet()) { final PointD key = pair.getKey(); if (range.contains(key)) { final double dx = key.x - x, dy = key.y - y; @@ -1405,7 +1405,7 @@ private void findRange(RectD range, boolean useCircle, Map output) { } } } else { - for (Map.Entry pair: _entries.entrySet()) + for (Entry pair: _entries.entrySet()) if (range.contains(pair.getKey())) output.put(pair.getKey(), pair.getValue()); } @@ -1483,7 +1483,7 @@ else if (child == _maxXmaxY) { */ private void split() { - for (Map.Entry pair: _entries.entrySet()) { + for (Entry pair: _entries.entrySet()) { final PointD key = pair.getKey(); final Node child = findOrCreateChild(key); child._entries.put(key, pair.getValue()); diff --git a/tektosyne/src/main/java/org/kynosarges/tektosyne/ThreadLocalRandomCompat.java b/tektosyne/src/main/java/org/kynosarges/tektosyne/ThreadLocalRandomCompat.java new file mode 100644 index 0000000..bbb7600 --- /dev/null +++ b/tektosyne/src/main/java/org/kynosarges/tektosyne/ThreadLocalRandomCompat.java @@ -0,0 +1,26 @@ +package org.kynosarges.tektosyne; + +import java.security.SecureRandom; +import java.util.Random; +import java.util.concurrent.ThreadLocalRandom; + +/** + * Provide {@link java.util.concurrent.ThreadLocalRandom} compatibility for Java 1.7. + */ +public final class ThreadLocalRandomCompat { + + private static ThreadLocal RANDOM_INSTANCE = new ThreadLocal() { + @Override + public Random get() { + return new SecureRandom(); + } + }; + + /** + * Compatible replacement for {@link ThreadLocalRandom#current()}. + */ + public static Random current() { + return RANDOM_INSTANCE.get(); + } + +} diff --git a/tektosyne/src/main/java/org/kynosarges/tektosyne/geometry/GeoUtils.java b/tektosyne/src/main/java/org/kynosarges/tektosyne/geometry/GeoUtils.java index 759fa00..266b271 100755 --- a/tektosyne/src/main/java/org/kynosarges/tektosyne/geometry/GeoUtils.java +++ b/tektosyne/src/main/java/org/kynosarges/tektosyne/geometry/GeoUtils.java @@ -16,7 +16,7 @@ */ public final class GeoUtils { - private final static ThreadLocalRandom RANDOM = ThreadLocalRandom.current(); + private final static Random RANDOM = ThreadLocalRandomCompat.current(); /** * Creates a {@link GeoUtils} instance. @@ -475,10 +475,10 @@ public static LineD randomLine(double x, double y, double width, double height) throw new IllegalArgumentException("height <= 0"); return new LineD( - x + RANDOM.nextDouble(width), - y + RANDOM.nextDouble(height), - x + RANDOM.nextDouble(width), - y + RANDOM.nextDouble(height)); + x + RANDOM.nextDouble() * width, + y + RANDOM.nextDouble() * height, + x + RANDOM.nextDouble() * width, + y + RANDOM.nextDouble() * height); } /** @@ -498,8 +498,8 @@ public static PointD randomPoint(double x, double y, double width, double height throw new IllegalArgumentException("height <= 0"); return new PointD( - x + RANDOM.nextDouble(width), - y + RANDOM.nextDouble(height)); + x + RANDOM.nextDouble() * width, + y + RANDOM.nextDouble() * height); } /** @@ -520,8 +520,8 @@ public static PointD randomPoint(RectD bounds) { throw new IllegalArgumentException("bounds.height == 0"); return new PointD( - bounds.min.x + RANDOM.nextDouble(width), - bounds.min.y + RANDOM.nextDouble(height)); + bounds.min.x + RANDOM.nextDouble() * width, + bounds.min.y + RANDOM.nextDouble() * height); } /** @@ -549,8 +549,8 @@ public static PointD[] randomPoints(int count, RectD bounds) { for (int i = 0; i < points.length; i++) points[i] = new PointD( - bounds.min.x + RANDOM.nextDouble(width), - bounds.min.y + RANDOM.nextDouble(height)); + bounds.min.x + RANDOM.nextDouble() * width, + bounds.min.y + RANDOM.nextDouble() * height); return points; } @@ -596,8 +596,8 @@ public static PointD[] randomPoints(int count, for (int i = 0; i < count; i++) { do { point = new PointD( - bounds.min.x + RANDOM.nextDouble(width), - bounds.min.y + RANDOM.nextDouble(height)); + bounds.min.x + RANDOM.nextDouble() * width, + bounds.min.y + RANDOM.nextDouble() * height); if (points.isEmpty()) break; @@ -606,7 +606,7 @@ public static PointD[] randomPoints(int count, } while (length2 < distance); points.add(point); - points.sort(comparer); + Collections.sort(points, comparer); } return points.toArray(new PointD[count]); @@ -645,7 +645,7 @@ public static PointD[] randomPolygon(double x, double y, double width, double he for (double degrees = 0; degrees < 360; degrees += 6.0) { // random increment of angle for next vertex - degrees += RANDOM.nextDouble(110); + degrees += RANDOM.nextDouble() * 110; if (degrees >= 360) break; final double radians = degrees * Angle.DEGREES_TO_RADIANS; @@ -687,10 +687,10 @@ public static RectD randomRect(double x, double y, double width, double height) throw new IllegalArgumentException("height <= 0"); return new RectD( - x + RANDOM.nextDouble(width / 2), - y + RANDOM.nextDouble(height / 2), - x + width - RANDOM.nextDouble(width / 2), - y + height - RANDOM.nextDouble(height / 2)); + x + RANDOM.nextDouble() * width / 2, + y + RANDOM.nextDouble() * height / 2, + x + width - RANDOM.nextDouble() * width / 2, + y + height - RANDOM.nextDouble() * height /2); } /** diff --git a/tektosyne/src/main/java/org/kynosarges/tektosyne/geometry/LineI.java b/tektosyne/src/main/java/org/kynosarges/tektosyne/geometry/LineI.java index da4b314..48a70bb 100755 --- a/tektosyne/src/main/java/org/kynosarges/tektosyne/geometry/LineI.java +++ b/tektosyne/src/main/java/org/kynosarges/tektosyne/geometry/LineI.java @@ -1,5 +1,7 @@ package org.kynosarges.tektosyne.geometry; +import org.kynosarges.tektosyne.MathCompat; + /** * Represents a directed line segment in two-dimensional space, using {@link Integer} coordinates. * {@link LineI} contains two immutable {@link PointI} locations, indicating the {@link LineI#start} @@ -385,8 +387,8 @@ public LineD toLineD() { */ public PointI vector() { return new PointI( - Math.subtractExact(end.x, start.x), - Math.subtractExact(end.y, start.y)); + MathCompat.subtractExact(end.x, start.x), + MathCompat.subtractExact(end.y, start.y)); } /** diff --git a/tektosyne/src/main/java/org/kynosarges/tektosyne/geometry/PointI.java b/tektosyne/src/main/java/org/kynosarges/tektosyne/geometry/PointI.java index 566a86f..7505990 100755 --- a/tektosyne/src/main/java/org/kynosarges/tektosyne/geometry/PointI.java +++ b/tektosyne/src/main/java/org/kynosarges/tektosyne/geometry/PointI.java @@ -54,8 +54,8 @@ public PointI(int x, int y) { */ public PointI add(PointI point) { return new PointI( - Math.addExact(x, point.x), - Math.addExact(y, point.y)); + MathCompat.addExact(x, point.x), + MathCompat.addExact(y, point.y)); } /** @@ -273,8 +273,8 @@ public PointI restrict(int minX, int minY, int maxX, int maxY) { */ public PointI subtract(PointI point) { return new PointI( - Math.subtractExact(x, point.x), - Math.subtractExact(y, point.y)); + MathCompat.subtractExact(x, point.x), + MathCompat.subtractExact(y, point.y)); } /** diff --git a/tektosyne/src/main/java/org/kynosarges/tektosyne/geometry/RectI.java b/tektosyne/src/main/java/org/kynosarges/tektosyne/geometry/RectI.java index d3a311c..7c63d77 100755 --- a/tektosyne/src/main/java/org/kynosarges/tektosyne/geometry/RectI.java +++ b/tektosyne/src/main/java/org/kynosarges/tektosyne/geometry/RectI.java @@ -1,5 +1,7 @@ package org.kynosarges.tektosyne.geometry; +import org.kynosarges.tektosyne.MathCompat; + /** * Represents a rectangular region in two-dimensional space, using {@link Integer} coordinates. * {@link RectI} contains two immutable {@link PointI} locations, defining the opposite corners @@ -178,11 +180,11 @@ public boolean containsOpen(PointI point) { */ public PointI distanceVector(PointI q) { - final int x = (q.x < min.x ? Math.subtractExact(q.x, min.x) : - q.x > max.x ? Math.subtractExact(q.x, max.x) : 0); + final int x = (q.x < min.x ? MathCompat.subtractExact(q.x, min.x) : + q.x > max.x ? MathCompat.subtractExact(q.x, max.x) : 0); - final int y = (q.y < min.y ? Math.subtractExact(q.y, min.y) : - q.y > max.y ? Math.subtractExact(q.y, max.y) : 0); + final int y = (q.y < min.y ? MathCompat.subtractExact(q.y, min.y) : + q.y > max.y ? MathCompat.subtractExact(q.y, max.y) : 0); return new PointI(x, y); } @@ -290,8 +292,8 @@ public RectLocation locate(PointI q) { */ public RectI offset(int x, int y) { return new RectI( - Math.addExact(min.x, x), Math.addExact(min.y, y), - Math.addExact(max.x, x), Math.addExact(max.y, y)); + MathCompat.addExact(min.x, x), MathCompat.addExact(min.y, y), + MathCompat.addExact(max.x, x), MathCompat.addExact(max.y, y)); } /** diff --git a/tektosyne/src/main/java/org/kynosarges/tektosyne/geometry/SizeI.java b/tektosyne/src/main/java/org/kynosarges/tektosyne/geometry/SizeI.java index f2a3f16..a90f223 100755 --- a/tektosyne/src/main/java/org/kynosarges/tektosyne/geometry/SizeI.java +++ b/tektosyne/src/main/java/org/kynosarges/tektosyne/geometry/SizeI.java @@ -1,5 +1,7 @@ package org.kynosarges.tektosyne.geometry; +import org.kynosarges.tektosyne.MathCompat; + /** * Represents an extension in two-dimensional space, using {@link Integer} coordinates. * {@link SizeI} contains two immutable non-negative {@link Integer} dimensions. @@ -60,8 +62,8 @@ public SizeI(int width, int height) { */ public SizeI add(SizeI size) { return new SizeI( - Math.addExact(width, size.width), - Math.addExact(height, size.height)); + MathCompat.addExact(width, size.width), + MathCompat.addExact(height, size.height)); } /**