From ab18170a8cff054ac4ea92458888d790f1b69950 Mon Sep 17 00:00:00 2001 From: Edouard DUPIN Date: Sun, 4 Apr 2021 15:26:54 +0200 Subject: [PATCH] [DEV] add some feature --- .classpath | 10 +- src/org/atriasoft/etk/Color.java | 24 +- src/org/atriasoft/etk/Dimension.java | 313 +++++++++++++++++++++ src/org/atriasoft/etk/Dimension1D.java | 164 +++++++++++ src/org/atriasoft/etk/Distance.java | 16 ++ src/org/atriasoft/etk/Uri.java | 35 ++- src/org/atriasoft/etk/internal/Log.java | 7 + src/org/atriasoft/etk/math/FMath.java | 54 ++++ src/org/atriasoft/etk/math/Matrix2x3f.java | 230 +++++++++++++++ src/org/atriasoft/etk/math/Vector2f.java | 114 +++++--- src/org/atriasoft/etk/math/Vector2i.java | 12 +- src/org/atriasoft/etk/math/Vector3f.java | 126 +++++---- src/org/atriasoft/etk/math/Vector3i.java | 26 +- src/org/atriasoft/etk/util/Dynamic.java | 9 + src/org/atriasoft/etk/util/Pair.java | 9 + 15 files changed, 1042 insertions(+), 107 deletions(-) create mode 100644 src/org/atriasoft/etk/Dimension.java create mode 100644 src/org/atriasoft/etk/Dimension1D.java create mode 100644 src/org/atriasoft/etk/Distance.java create mode 100644 src/org/atriasoft/etk/math/Matrix2x3f.java create mode 100644 src/org/atriasoft/etk/util/Dynamic.java diff --git a/.classpath b/.classpath index 451e195..0e495fd 100644 --- a/.classpath +++ b/.classpath @@ -11,11 +11,6 @@ - - - - - @@ -31,5 +26,10 @@ + + + + + diff --git a/src/org/atriasoft/etk/Color.java b/src/org/atriasoft/etk/Color.java index 141785b..3c784eb 100644 --- a/src/org/atriasoft/etk/Color.java +++ b/src/org/atriasoft/etk/Color.java @@ -162,8 +162,8 @@ public record Color( public static final Color YELLOW = new Color(0xFF, 0xFF, 0x00, 0xFF); public static final Color YELLOW_GREEN = new Color(0x9A, 0xCD, 0x32, 0xFF); - private static final Map NAMED_COLORS = Map.ofEntries( - //@formatter:off + private static final Map NAMED_COLORS = Map. ofEntries( + //@formatter:off Map.entry("none", NONE), Map.entry("aliceblue", ALICE_BLUE), Map.entry("antiquewhite", ANTIQUE_WHITE), @@ -414,9 +414,29 @@ public record Color( this.a = a; } + public Color(final double r, final double g, final double b, final double a) { + this((float) r, (float) g, (float) b, (float) a); + } + @Override public String toString() { return "rgba(" + this.r + ", " + this.g + ", " + this.b + ", " + this.a + ")"; } + public Color withR(final float value) { + return new Color(value, this.g, this.b, this.a); + } + + public Color withG(final float value) { + return new Color(this.r, value, this.b, this.a); + } + + public Color withB(final float value) { + return new Color(this.r, this.g, value, this.a); + } + + public Color withA(final float value) { + return new Color(this.r, this.g, this.b, value); + } + } diff --git a/src/org/atriasoft/etk/Dimension.java b/src/org/atriasoft/etk/Dimension.java new file mode 100644 index 0000000..a4ac8e1 --- /dev/null +++ b/src/org/atriasoft/etk/Dimension.java @@ -0,0 +1,313 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2011, Edouard DUPIN, all right reserved + * @license MPL v2.0 (see license file) + */ +package org.atriasoft.etk; + +import org.atriasoft.etk.internal.Log; +import org.atriasoft.etk.math.Vector2f; +import org.atriasoft.etk.math.Vector2i; + +/** + * in the dimension class we store the data as the more usefull unit (pixel) + * but one case need to be dynamic the %, then when requested in % the register the % value + */ +@SuppressWarnings("preview") +public record Dimension( + Vector2f size, + Distance type) { + public static final Dimension ZERO = new Dimension(Vector2f.ZERO, Distance.PIXEL); + private static Vector2f ratio = new Vector2f(9999999, 888888); + private static Vector2f invRatio = new Vector2f(1, 1); + private static Dimension windowsSize = new Dimension(Vector2f.MAX_VALUE, Distance.PIXEL); + + public static final float INCH_TO_MILLIMETER = 1.0f / 25.4f; + public static final float FOOT_TO_MILLIMETER = 1.0f / 304.8f; + public static final float METER_TO_MILLIMETER = 1.0f / 1000.0f; + public static final float CENTIMETER_TO_MILLIMETER = 1.0f / 10.0f; + public static final float KILOMETER_TO_MILLIMETER = 1.0f / 1000000.0f; + public static final float MILLIMETER_TO_INCH = 25.4f; + public static final float MILLIMETER_TO_FOOT = 304.8f; + public static final float MILLIMETER_TO_METER = 1000.0f; + public static final float MILLIMETER_TO_CENTIMETER = 10.0f; + public static final float MILLIMETER_TO_KILOMETER = 1000000.0f; + /** + * basic init + */ + static { + final Dimension conversion = new Dimension(new Vector2f(72, 72), Distance.INCH); + ratio = conversion.getMillimeter(); + invRatio = new Vector2f(1.0f / ratio.x(), 1.0f / ratio.y()); + windowsSize = new Dimension(new Vector2f(200, 200), Distance.PIXEL); + } + + /** + * get the Windows diagonal size in the request unit + * @param type Unit type requested. + * @return the requested size + */ + public static float getWindowsDiag(final Distance type) { + final Vector2f size = getWindowsSize(type); + return size.length(); + } + + /** + * get the Windows size in the request unit + * @param type Unit type requested. + * @return the requested size + */ + public static Vector2f getWindowsSize(final Distance type) { + return windowsSize.get(type); + } + + /** + * set the Milimeter ratio for calculation + * @param ratio Milimeter ration for the screen calculation interpolation + * @param type Unit type requested. + * @note: same as @ref setPixelPerInch (internal manage convertion) + */ + public static void setPixelRatio(final Vector2f ratio, final Distance type) { + Log.info("Set a new screen ratio for the screen : ratio=" + ratio + " type=" + type); + final Dimension conversion = new Dimension(ratio, type); + Log.info(" == > " + conversion); + Dimension.ratio = conversion.getMillimeter(); + invRatio = new Vector2f(1.0f / Dimension.ratio.x(), 1.0f / Dimension.ratio.y()); + Log.info("Set a new screen ratio for the screen : ratioMm=" + Dimension.ratio); + } + + /** + * set the current Windows size + * @param size size of the current windows in pixel. + */ + public static void setPixelWindowsSize(final Vector2f size) { + windowsSize = new Dimension(size); + Log.verbose("Set a new Windows property size " + windowsSize + "px"); + } + + /** + * Constructor (default :0,0 mode pixel) + */ + public Dimension() { + this(Vector2f.ZERO, Distance.PIXEL); + } + + /** + * Constructor + * @param size Requested dimension + */ + public Dimension(final Vector2f size) { + this(size, Distance.PIXEL); + } + + public Dimension(final Vector2f size, final Distance type) { + this.size = size; + this.type = type; + } + + /** + * get the current dimension in requested type + * @param type Type of unit requested. + * @return dimension requested. + */ + public Vector2f get(final Distance type) { + return switch (type) { + case POURCENT -> getPourcent(); + case PIXEL -> getPixel(); + case METER -> getMeter(); + case CENTIMETER -> getCentimeter(); + case MILLIMETER -> getMillimeter(); + case KILOMETER -> getKilometer(); + case INCH -> getInch(); + case FOOT -> getFoot(); + case ELEMENT -> throw new UnsupportedOperationException("Unimplemented case: " + type); + case EX -> throw new UnsupportedOperationException("Unimplemented case: " + type); + case PC -> { + Log.error("Does not support other than Px and % type of dimention : " + type + " automaticly convert with {72,72} pixel/inch"); + yield null; + } + case POINT -> throw new UnsupportedOperationException("Unimplemented case: " + type); + default -> throw new IllegalArgumentException("Unexpected value: " + type); + }; + } + + /** + * get the current dimension in Centimeter + * @return dimension in Centimeter + */ + public Vector2f getCentimeter() { + return getMillimeter().multiply(MILLIMETER_TO_CENTIMETER); + } + + /** + * get the current dimension in Foot + * @return dimension in Foot + */ + public Vector2f getFoot() { + return getMillimeter().multiply(MILLIMETER_TO_FOOT); + } + + /** + * get the current dimension in Inch + * @return dimension in Inch + */ + public Vector2f getInch() { + return getMillimeter().multiply(MILLIMETER_TO_INCH); + } + + /** + * get the current dimension in Kilometer + * @return dimension in Kilometer + */ + public Vector2f getKilometer() { + return getMillimeter().multiply(MILLIMETER_TO_KILOMETER); + } + + /** + * get the current dimension in Meter + * @return dimension in Meter + */ + public Vector2f getMeter() { + return getMillimeter().multiply(MILLIMETER_TO_METER); + } + + /** + * get the current dimension in Millimeter + * @return dimension in Millimeter + */ + public Vector2f getMillimeter() { + return new Vector2f(getPixel().x() * invRatio.x(), getPixel().y() * invRatio.y()); + } + + /** + * get the current dimension in pixel + * @return dimension in Pixel + */ + public Vector2f getPixel() { + return getPixel(windowsSize.getPixel()); + } + + public Vector2f getPixel(final Vector2f uppersize) { + if (this.type != Distance.POURCENT) { + return this.size; + } + final Vector2f res = new Vector2f(uppersize.x() * this.size.x(), uppersize.y() * this.size.y()); + //GALE_DEBUG("Get % : " + m_data + " / " + windDim + " == > " + res); + return res; + } + + public Vector2i getPixeli() { + Vector2f tmpSize = windowsSize.getPixel(); + return getPixeli(new Vector2i((int) tmpSize.x(), (int) tmpSize.y())); + } + + public Vector2i getPixeli(final Vector2i uppersize) { + if (this.type != Distance.POURCENT) { + return new Vector2i((int) this.size.x(), (int) this.size.y()); + } + final Vector2i res = new Vector2i((int) (uppersize.x() * this.size.x()), (int) (uppersize.y() * this.size.y())); + //GALE_DEBUG("Get % : " + m_data + " / " + windDim + " == > " + res); + return res; + } + + /** + * get the current dimension in Pourcent + * @return dimension in Pourcent + */ + public Vector2f getPourcent() { + if (this.type != Distance.POURCENT) { + final Vector2f windDim = windowsSize.getPixel(); + //GALE_DEBUG(" windows dimension : " /*+ windowsSize*/ + " == > " + windDim + "px"); // ==> infinite loop ... + //printf(" windows dimension : %f,%f", windDim.x(),windDim.y()); + //printf(" data : %f,%f", m_data.x(),m_data.y()); + return new Vector2f((this.size.x() / windDim.x()) * 100.0f, (this.size.y() / windDim.y()) * 100.0f); + } + return new Vector2f(this.size.x() * 100.0f, this.size.y() * 100.0f); + }; + + /** + * get the dimension type + * @return the type + */ + public Distance getType() { + return this.type; + } + + /** + * set the current dimension in requested type + * @param config dimension configuration. + */ + public static Dimension valueOf(String config) { + final Vector2f size = Vector2f.ZERO; + Distance type = Distance.PIXEL; + if (config.endsWith("%")) { + type = Distance.POURCENT; + config = config.substring(0, config.length() - 1); + } else if (config.endsWith("px")) { + type = Distance.PIXEL; + config = config.substring(0, config.length() - 2); + } else if (config.endsWith("ft")) { + type = Distance.FOOT; + config = config.substring(0, config.length() - 2); + } else if (config.endsWith("in")) { + type = Distance.INCH; + config = config.substring(0, config.length() - 2); + } else if (config.endsWith("km")) { + type = Distance.KILOMETER; + config = config.substring(0, config.length() - 2); + } else if (config.endsWith("mm")) { + type = Distance.MILLIMETER; + config = config.substring(0, config.length() - 2); + } else if (config.endsWith("cm")) { + type = Distance.CENTIMETER; + config = config.substring(0, config.length() - 2); + } else if (config.endsWith("m")) { + type = Distance.METER; + config = config.substring(0, config.length() - 1); + } else if (config.endsWith("em")) { + type = Distance.ELEMENT; + config = config.substring(0, config.length() - 2); + } else if (config.endsWith("ex")) { + type = Distance.EX; + config = config.substring(0, config.length() - 2); + } else if (config.endsWith("pt")) { + type = Distance.POINT; + config = config.substring(0, config.length() - 2); + } else if (config.endsWith("pc")) { + type = Distance.PC; + config = config.substring(0, config.length() - 2); + } else { + Log.critical("Can not parse dimension : '" + config + "'"); + return null; + } + final Vector2f tmp = Vector2f.valueOf(config); + final Dimension ret = new Dimension(tmp, type); + Log.verbose(" config dimension : '" + config + "' == > " + ret.toString()); + return ret; + } + + /** + * string cast : + */ + @Override + public String toString() { + String str = get(getType()).toString(); + switch (getType()) { + case POURCENT -> str += "%"; + case PIXEL -> str += "px"; + case METER -> str += "m"; + case CENTIMETER -> str += "cm"; + case MILLIMETER -> str += "mm"; + case KILOMETER -> str += "km"; + case INCH -> str += "in"; + case FOOT -> str += "ft"; + case ELEMENT -> str += "em"; + case EX -> str += "ex"; + case POINT -> str += "pt"; + case PC -> str += "pc"; + default -> str += ""; + } + return str; + } + +} diff --git a/src/org/atriasoft/etk/Dimension1D.java b/src/org/atriasoft/etk/Dimension1D.java new file mode 100644 index 0000000..ad93af7 --- /dev/null +++ b/src/org/atriasoft/etk/Dimension1D.java @@ -0,0 +1,164 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2011, Edouard DUPIN, all right reserved + * @license MPL v2.0 (see license file) + */ +package org.atriasoft.etk; + +import org.atriasoft.etk.internal.Log; +import org.atriasoft.etk.math.Vector2f; + +/** + * in the dimension class we store the data as the more usefull unit (pixel) + * but one case need to be dynamic the %, then when requested in % the register the % value + */ +@SuppressWarnings("preview") +public record Dimension1D( + float size, + Distance type) { + private static final float BASIC_RATIO = 72.0f / 25.4f; + public static final Dimension1D ZERO = new Dimension1D(0); + public static final float INCH_TO_MILLIMETER = 1.0f / 25.4f; + public static final float FOOT_TO_MILLIMETER = 1.0f / 304.8f; + public static final float METER_TO_MILLIMETER = 1.0f / 1000.0f; + public static final float CENTIMETER_TO_MILLIMETER = 1.0f / 10.0f; + public static final float KILOMETER_TO_MILLIMETER = 1.0f / 1000000.0f; + public static final float MILLIMETER_TO_INCH = 25.4f; + public static final float MILLIMETER_TO_FOOT = 304.8f; + public static final float MILLIMETER_TO_METER = 1000.0f; + public static final float MILLIMETER_TO_CENTIMETER = 10.0f; + public static final float MILLIMETER_TO_KILOMETER = 1000000.0f; + + /** + * Constructor (default :0,0 mode pixel) + */ + public Dimension1D() { + this(0, Distance.PIXEL); + } + + /** + * Constructor + * @param size Requested dimension + */ + public Dimension1D(final float size) { + this(size, Distance.PIXEL); + } + + public Dimension1D(final float size, final Distance type) { + this.size = size; + this.type = type; + } + + /** + * get the current dimension in pixel + * @return dimension in Pixel + */ + public float getPixel(final float upperSize) { + switch (this.type) { + case POURCENT: + return upperSize * this.size * 0.01f; + case PIXEL: + return this.size; + case METER: + return this.size * METER_TO_MILLIMETER * BASIC_RATIO; + case CENTIMETER: + return this.size * CENTIMETER_TO_MILLIMETER * BASIC_RATIO; + case MILLIMETER: + return this.size * BASIC_RATIO; + case KILOMETER: + return this.size * KILOMETER_TO_MILLIMETER * BASIC_RATIO; + case INCH: + return this.size * INCH_TO_MILLIMETER * BASIC_RATIO; + case FOOT: + return this.size * FOOT_TO_MILLIMETER * BASIC_RATIO; + default: + return 128.0f; + } + } + + /** + * get the dimension type + * @return the type + */ + public Distance getType() { + return this.type; + } + + /** + * set the current dimension in requested type + * @param config dimension configuration. + */ + public static Dimension1D valueOf(String config) { + final Vector2f size = Vector2f.ZERO; + Distance type = Distance.PIXEL; + if (config.endsWith("%")) { + type = Distance.POURCENT; + config = config.substring(0, config.length() - 1); + } else if (config.endsWith("px")) { + type = Distance.PIXEL; + config = config.substring(0, config.length() - 2); + } else if (config.endsWith("ft")) { + type = Distance.FOOT; + config = config.substring(0, config.length() - 2); + } else if (config.endsWith("in")) { + type = Distance.INCH; + config = config.substring(0, config.length() - 2); + } else if (config.endsWith("km")) { + type = Distance.KILOMETER; + config = config.substring(0, config.length() - 2); + } else if (config.endsWith("mm")) { + type = Distance.MILLIMETER; + config = config.substring(0, config.length() - 2); + } else if (config.endsWith("cm")) { + type = Distance.CENTIMETER; + config = config.substring(0, config.length() - 2); + } else if (config.endsWith("m")) { + type = Distance.METER; + config = config.substring(0, config.length() - 1); + } else if (config.endsWith("em")) { + type = Distance.ELEMENT; + config = config.substring(0, config.length() - 2); + } else if (config.endsWith("ex")) { + type = Distance.EX; + config = config.substring(0, config.length() - 2); + } else if (config.endsWith("pt")) { + type = Distance.POINT; + config = config.substring(0, config.length() - 2); + } else if (config.endsWith("pc")) { + type = Distance.PC; + config = config.substring(0, config.length() - 2); + } else { + Log.critical("Can not parse dimension : '" + config + "'"); + return null; + } + final float tmp = Float.valueOf(config); + final Dimension1D ret = new Dimension1D(tmp, type); + Log.verbose(" config dimension : '" + config + "' == > " + ret.toString()); + return ret; + } + + /** + * string cast : + */ + @Override + public String toString() { + String str = Float.toString(this.size); + switch (getType()) { + case POURCENT -> str += "%"; + case PIXEL -> str += "px"; + case METER -> str += "m"; + case CENTIMETER -> str += "cm"; + case MILLIMETER -> str += "mm"; + case KILOMETER -> str += "km"; + case INCH -> str += "in"; + case FOOT -> str += "ft"; + case ELEMENT -> str += "em"; + case EX -> str += "ex"; + case POINT -> str += "pt"; + case PC -> str += "pc"; + default -> str += ""; + } + return str; + } + +} diff --git a/src/org/atriasoft/etk/Distance.java b/src/org/atriasoft/etk/Distance.java new file mode 100644 index 0000000..6e31533 --- /dev/null +++ b/src/org/atriasoft/etk/Distance.java @@ -0,0 +1,16 @@ +package org.atriasoft.etk; + +public enum Distance { + POURCENT, //!< "%" + PIXEL, //!< "px" + METER, //!< "m" + CENTIMETER, //!< "cm" + MILLIMETER, //!< "mm" + KILOMETER, //!< "km" + INCH, //!< "in" + FOOT, //!< "ft" + ELEMENT, //!< "em" + EX, //!< "ex" + POINT, //!< "pt" + PC; //!< "pc" +} diff --git a/src/org/atriasoft/etk/Uri.java b/src/org/atriasoft/etk/Uri.java index fdaae88..0967df2 100644 --- a/src/org/atriasoft/etk/Uri.java +++ b/src/org/atriasoft/etk/Uri.java @@ -1,5 +1,7 @@ package org.atriasoft.etk; +import java.io.BufferedWriter; +import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.net.URL; @@ -22,7 +24,8 @@ public class Uri { static { genericMap.put("DATA", "data/"); - genericMap.put("THEME_GUI", "theme/"); + genericMap.put("THEME", "theme/"); + genericMap.put("TRANSLATE", "translate/"); } public static void addLibrary(final String libName, final Class classHandle, String basePath) { @@ -84,6 +87,7 @@ public class Uri { Log.warning(" !! Application data class is not defined ..."); } else { String tmpPath = applicationBasePath + offsetGroup + uri.path; + tmpPath = tmpPath.replace("//", "/"); Log.info("(appl) Try to load '" + tmpPath + "' in " + applicationClass.getCanonicalName()); URL realFileName = applicationClass.getClassLoader().getResource(tmpPath); if (realFileName != null) { @@ -107,6 +111,7 @@ public class Uri { return null; } String tmpPath = libraryElement.basePath + offsetGroup + uri.path; + tmpPath = tmpPath.replace("//", "/"); Log.info("(lib) Try to load '" + tmpPath + "' in " + libraryElement.klass.getCanonicalName()); URL realFileName = libraryElement.klass.getClassLoader().getResource(tmpPath); if (realFileName != null) { @@ -131,6 +136,10 @@ public class Uri { return out; } + public static void setApplication(final Class classHandle) { + setApplication(classHandle, ""); + } + public static void setApplication(final Class classHandle, String basePath) { Log.info("Set application reference : " + classHandle.getCanonicalName() + " base path=" + basePath); applicationClass = classHandle; @@ -178,12 +187,36 @@ public class Uri { return new Uri(group, path, lib); } + public static void writeAll(final Uri uri, final String data) { + BufferedWriter out = null; + try { + FileWriter fstream = new FileWriter(uri.getPath(), true); //true tells to append data. + out = new BufferedWriter(fstream); + out.write(data); + } catch (IOException e) { + Log.error("Error: " + e.getMessage()); + } finally { + if (out != null) { + try { + out.close(); + } catch (IOException e) { + // TODO Auto-generated catch block + Log.error("Error: ", e); + } + } + } + } + private final String group; private final String path; private final String lib; + public Uri(final String path) { + this(null, path, null); + } + public Uri(final String group, final String path) { this(group, path, null); } diff --git a/src/org/atriasoft/etk/internal/Log.java b/src/org/atriasoft/etk/internal/Log.java index 747d8e8..a70bd22 100644 --- a/src/org/atriasoft/etk/internal/Log.java +++ b/src/org/atriasoft/etk/internal/Log.java @@ -33,6 +33,13 @@ public class Log { } } + public static void error(final String data, final Exception e) { + e.printStackTrace(); + if (PRINT_ERROR) { + Logger.error(LIB_NAME_DRAW, data); + } + } + public static void info(final String data) { if (PRINT_INFO) { Logger.info(LIB_NAME_DRAW, data); diff --git a/src/org/atriasoft/etk/math/FMath.java b/src/org/atriasoft/etk/math/FMath.java index 30c0faf..0aeec73 100644 --- a/src/org/atriasoft/etk/math/FMath.java +++ b/src/org/atriasoft/etk/math/FMath.java @@ -12,6 +12,10 @@ public class FMath { return a; } + public static float acos(final float value) { + return (float) Math.acos(value); + } + /** * Test if the value id in the correct range * @@ -36,6 +40,10 @@ public class FMath { return (abs(difference) < epsilon); } + public static float asin(final float value) { + return (float) Math.asin(value); + } + public static float atan(final float value) { return (float) Math.atan(value); } @@ -48,6 +56,10 @@ public class FMath { return Math.max(min, Math.min(value, max)); } + public static int avg(final int min, final int value, final int max) { + return Math.max(min, Math.min(value, max)); + } + /// Function that returns the result of the "value" clamped by /// two others values "lowerLimit" and "upperLimit" public static float clamp(final float value, final float lowerLimit, final float upperLimit) { @@ -80,6 +92,48 @@ public class FMath { return (int) Math.floor(f); } + public static double[] getTableDouble(final String data, final String separator, final int nbElement) { + double[] out = new double[nbElement]; + String[] values = data.split(separator); + if (values.length != nbElement) { + return null; + } + for (int iii = 0; iii < nbElement; iii++) { + out[iii] = Double.parseDouble(values[iii]); + } + return out; + } + + public static float[] getTableFloat(final String data, final String separator, final int nbElement) { + float[] out = new float[nbElement]; + String[] values = data.split(separator); + if (values.length != nbElement) { + return null; + } + for (int iii = 0; iii < nbElement; iii++) { + out[iii] = Float.parseFloat(values[iii]); + } + return out; + } + + // return list of read and the number of char read. + /* + public static Pair getTableFloatMax(final String data, final String separator, final int nbElement) { + data = data.replace(",", " "); + + List out = new ArrayList<>(); + String[] values = data.split(separator); + for (int iii = 0; iii < values.length; iii++) { + try { + float val = Float.parseFloat(values[iii]); + } catch (NumberFormatException e) { + break; + } + } + return out; + } + */ + public static float max(final float a, final float b) { return Math.max(a, b); } diff --git a/src/org/atriasoft/etk/math/Matrix2x3f.java b/src/org/atriasoft/etk/math/Matrix2x3f.java new file mode 100644 index 0000000..a973b12 --- /dev/null +++ b/src/org/atriasoft/etk/math/Matrix2x3f.java @@ -0,0 +1,230 @@ +package org.atriasoft.etk.math; + +/** + *Internal data + * sx shx tx + * sy shy ty + */ +@SuppressWarnings("preview") +public record Matrix2x3f( + float sx, + float shy, + float shx, + float sy, + float tx, + float ty) { + + /** + *Configuration ructor. + * @param sx Scale threw X axis + * @param shy Rotate in radian threw Y axis + * @param shx Rotate in radian threw X axis + * @param sy Scale threw Y axis + * @param tx Translate threw X axis + * @param ty translate threw Y axis + */ + public Matrix2x3f(final float sx, final float shy, final float shx, final float sy, final float tx, final float ty) { + this.sx = sx; + this.shy = shy; + this.shx = shx; + this.sy = sy; + this.tx = tx; + this.ty = ty; + } + + /** + *Configuration ructor. + * @param values vector of values in float + */ + public Matrix2x3f(final float[] values) { + this(values[0], values[1], values[2], values[3], values[4], values[5]); + } + + /** + *Configuration ructor. + * @param values vector of values in double + */ + public Matrix2x3f(final double[] values) { + this((float) values[0], (float) values[1], (float) values[2], (float) values[3], (float) values[4], (float) values[5]); + } + + /** + *Load Identity matrix + */ + public static final Matrix2x3f IDENTITY = new Matrix2x3f(1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f); + + /** + *Operator+= Addition an other matrix with this one + * @param obj Reference on the external object + * @return Local reference of the vector additionned + */ + public Matrix2x3f add(final Matrix2x3f obj) { + return new Matrix2x3f(this.sx + obj.sx, this.shy + obj.shy, this.shx + obj.shx, this.sy + obj.sy, this.tx + obj.tx, this.ty + obj.ty); + } + + /** + *Operator-= Decrement an other matrix with this one + * @param obj Reference on the external object + * @return Local reference of the vector decremented + */ + public Matrix2x3f less(final Matrix2x3f obj) { + return new Matrix2x3f(this.sx - obj.sx, this.shy - obj.shy, this.shx - obj.shx, this.sy - obj.sy, this.tx - obj.tx, this.ty - obj.ty); + } + + /** + *Operator*= Multiplication an other matrix with this one + * @param obj Reference on the external object + * @return Local reference of the vector multiplicated + */ + public Matrix2x3f multiply(final Matrix2x3f obj) { + float sx = this.sx * obj.sx + this.shy * obj.shx; + float shx = this.shx * obj.sx + this.sy * obj.shx; + float tx = this.tx * obj.sx + this.ty * obj.shx + obj.tx; + float shy = this.sx * obj.shy + this.shy * obj.sy; + float sy = this.shx * obj.shy + this.sy * obj.sy; + float ty = this.tx * obj.shy + this.ty * obj.sy + obj.ty; + return new Matrix2x3f(sx, shy, shx, sy, tx, ty); + } + + /** + *Operator* apply matrix on a vector + * @param point Point value to apply the matrix + * @return New vector containing the value + */ + public Vector2f multiply(final Vector2f point) { + return new Vector2f(point.x() * this.sx + point.y() * this.shx + this.tx, point.x() * this.shy + point.y() * this.sy + this.ty); + } + + /** + *Apply matrix on a vector Scale Rotate, but NOT the translation + * @param point Point value to apply the matrix + * @return New vector containing the value + */ + public Vector2f applyScaleRotation(final Vector2f point) { + return new Vector2f(point.x() * this.sx + point.y() * this.shx, point.x() * this.shy + point.y() * this.sy); + } + + /** + *Flip the mathix threw the X axis + */ + public Matrix2x3f flipX() { + return new Matrix2x3f(-this.sx, this.shy, -this.shx, this.sy, -this.tx, this.ty); + } + + /** + *Flip the mathix threw the Y axis + */ + public Matrix2x3f flipY() { + return new Matrix2x3f(this.sx, -this.shy, this.shx, -this.sy, this.tx, -this.ty); + } + + /** + *Scale the current Matrix. + * @param vect Vector to scale matrix. + */ + public Matrix2x3f scale(final Vector2f vect) { + return new Matrix2x3f(this.sx * vect.x(), this.shy * vect.y(), this.shx * vect.x(), this.sy * vect.y(), this.tx * vect.x(), this.ty * vect.y()); + } + + /** + *Scale the current Matrix. + * @param value Single value to scale in X andf Y. + */ + public Matrix2x3f scale(final float value) { + return new Matrix2x3f(this.sx * value, this.shy * value, this.shx * value, this.sy * value, this.tx * value, this.ty * value); + } + + /** + *Makes a rotation matrix. + * @param angleRad angle to apply. + */ + public Matrix2x3f rotate(final float angleRad) { + float ca = FMath.cos(angleRad); + float sa = FMath.sin(angleRad); + float sx = this.sx * ca - this.shy * sa; + float shx = this.shx * ca - this.sy * sa; + float tx = this.tx * ca - this.ty * sa; + float shy = this.sx * sa + this.shy * ca; + float sy = this.shx * sa + this.sy * ca; + float ty = this.tx * sa + this.ty * ca; + return new Matrix2x3f(sx, shy, shx, sy, tx, ty); + } + + /** + *Makes a translation of the matrix + * @param vect Translation to apply. + */ + public Matrix2x3f translate(final Vector2f vect) { + return new Matrix2x3f(this.sx, this.shy, this.shx, this.sy, this.tx + vect.x(), this.ty + vect.y()); + } + + /** + *Computes the determinant of the matrix. + * @return The determinent Value. + */ + public float determinant() { + return this.sx * this.sy - this.shy * this.shx; + } + + /** + *Inverts the matrix. + * @note The determinant must be != 0, otherwithe the matrix can't be inverted. + * @return The inverted matrix. + */ + public Matrix2x3f invert() { + double det = 1.0 / determinant(); + float sx = (float) (this.sy * det); + float sy = (float) (this.sx * det); + float shy = (float) (-this.shy * det); + float shx = (float) (-this.shx * det); + float tx = -this.tx * sx - this.ty * this.shx; + float ty = -this.tx * this.shy - this.ty * this.sy; + return new Matrix2x3f(sx, shy, shx, sy, tx, ty); + } + + /** + * Create a matrix 2D with a simple rotation + * @param angleRad Radian angle to set at the matrix + * @return New matrix of the transformation requested + */ + public static Matrix2x3f createRotate(final float angleRad) { + return new Matrix2x3f(FMath.cos(angleRad), FMath.sin(angleRad), -FMath.sin(angleRad), FMath.cos(angleRad), 0.0f, 0.0f); + }; + + /** + * Create a matrix 2D with a simple scale + * @param scale 2 dimention scale + * @return New matrix of the transformation requested + */ + public static Matrix2x3f createScale(final Vector2f scale) { + return new Matrix2x3f(scale.x(), 0.0f, 0.0f, scale.y(), 0.0f, 0.0f); + }; + + /** + *Create a matrix 2D with a simple scale + * @param scale same scale in 2 and Y + * @return New matrix of the transformation requested + */ + public static Matrix2x3f createScale(final float scale) { + return new Matrix2x3f(scale, 0.0f, 0.0f, scale, 0.0f, 0.0f); + }; + + /** + *Create a matrix 2D with a simple translation + * @param translate 2 dimention translation + * @return New matrix of the transformation requested + */ + public static Matrix2x3f createTranslate(final Vector2f translate) { + return new Matrix2x3f(1.0f, 0.0f, 0.0f, 1.0f, translate.x(), translate.y()); + }; + + /** + *Create a matrix 2D with a simple skew + * @param skew 2 dimention skew + * @return New matrix of the transformation requested + */ + public static Matrix2x3f createSkew(final Vector2f skew) { + return new Matrix2x3f(1.0f, FMath.tan(skew.y()), FMath.tan(skew.x()), 1.0f, 0.0f, 0.0f); + }; + +} diff --git a/src/org/atriasoft/etk/math/Vector2f.java b/src/org/atriasoft/etk/math/Vector2f.java index 56124c6..3fb68b7 100644 --- a/src/org/atriasoft/etk/math/Vector2f.java +++ b/src/org/atriasoft/etk/math/Vector2f.java @@ -1,10 +1,13 @@ package org.atriasoft.etk.math; -import edu.umd.cs.findbugs.annotations.CheckReturnValue; import org.atriasoft.etk.internal.Log; +import edu.umd.cs.findbugs.annotations.CheckReturnValue; + @SuppressWarnings("preview") -public record Vector2f(float x, float y) { +public record Vector2f( + float x, + float y) { public static Vector2f valueOf(String value) { float val1 = 0; float val2 = 0; @@ -30,32 +33,37 @@ public record Vector2f(float x, float y) { } return new Vector2f(val1, val2); } - + /* * **************************************************** Constructor *****************************************************/ - + public Vector2f(final float x, final float y) { this.x = x; this.y = y; } - - @CheckReturnValue public static Vector2f clipInt(final Vector2f obj1) { - return new Vector2f((int)obj1.x, (int)obj1.y); + return new Vector2f((int) obj1.x, (int) obj1.y); } - - + public static Vector2f max(final Vector2f obj1, final Vector2f obj2) { return new Vector2f(Math.max(obj1.x, obj2.x), Math.max(obj1.y, obj2.y)); } - + + public static Vector2f max(final Vector2f obj1, final Vector2f obj2, final Vector2f obj3) { + return new Vector2f(FMath.max(obj1.x, obj2.x, obj3.x), FMath.max(obj1.y, obj2.y, obj3.y)); + } + public static Vector2f min(final Vector2f obj1, final Vector2f obj2) { return new Vector2f(Math.min(obj1.x, obj2.x), Math.min(obj1.y, obj2.y)); } - + + public static Vector2f min(final Vector2f obj1, final Vector2f obj2, final Vector2f obj3) { + return new Vector2f(FMath.min(obj1.x, obj2.x, obj3.x), FMath.min(obj1.y, obj2.y, obj3.y)); + } + /** * Return a vector will the absolute values of each element * @return New vector containing the value @@ -70,19 +78,31 @@ public record Vector2f(float x, float y) { return new Vector2f(this.x + val, this.y + val); } + @CheckReturnValue + public Vector2f addX(final float val) { + return new Vector2f(this.x + val, this.y); + } + + @CheckReturnValue + public Vector2f addY(final float val) { + return new Vector2f(this.x, this.y + val); + } + @CheckReturnValue public Vector2f add(final Vector2f obj) { return new Vector2f(this.x + obj.x, this.y + obj.y); } + @CheckReturnValue public Vector2f add(final Vector2i obj) { return new Vector2f(this.x + obj.x(), this.y + obj.y()); } + @CheckReturnValue public Vector2f add(final float xxx, final float yyy) { return new Vector2f(this.x + xxx, this.y + yyy); } - + /** * Return the axis with the largest ABSOLUTE value * @return values 0,1 for x or y @@ -91,7 +111,7 @@ public record Vector2f(float x, float y) { public int closestAxis() { return abs().maxAxis(); } - + /** * Return the cross product / determinant * @param obj The other vector in the cross product @@ -101,7 +121,7 @@ public record Vector2f(float x, float y) { public float cross(final Vector2f obj) { return this.x * obj.y - this.y * obj.x; } - + /** * Decrementation of this vector (-1 of 2 elements) */ @@ -119,7 +139,7 @@ public record Vector2f(float x, float y) { public Vector2f devide(final Vector2f obj) { return new Vector2f(this.x / obj.x, this.y / obj.y); } - + /** * Return the distance between the ends of this and another vector This * is semantically treating the vector like a point @@ -130,7 +150,7 @@ public record Vector2f(float x, float y) { public float distance(final Vector2f obj) { return (float) Math.sqrt(distance2(obj)); } - + /** * Return the distance squared between the ends of this and another * vector This is semantically treating the vector like a point @@ -143,7 +163,7 @@ public record Vector2f(float x, float y) { final float deltaY = obj.y - this.y; return deltaX * deltaX + deltaY * deltaY; } - + /** * Return the dot product * @param obj The other vector in the dot product @@ -153,7 +173,7 @@ public record Vector2f(float x, float y) { public float dot(final Vector2f obj) { return this.x * obj.x + this.y * obj.y; } - + /** * Return the axis with the smallest ABSOLUTE value * @return values 0,1 for x, or z @@ -162,7 +182,7 @@ public record Vector2f(float x, float y) { public int furthestAxis() { return abs().minAxis(); } - + /** * get the value with his index * @param index Index of the value (0: x, 1: y) @@ -177,7 +197,7 @@ public record Vector2f(float x, float y) { } throw new IllegalArgumentException("Unknown index: " + index); } - + /** * Incrementation of this vector (+1 of 2 elements) */ @@ -185,13 +205,13 @@ public record Vector2f(float x, float y) { public Vector2f increment() { return new Vector2f(this.x + 1, this.y + 1); } - + // Overloaded operator for the negative of a vector @CheckReturnValue public Vector2f invert() { return new Vector2f(-this.x, -this.y); } - + /** * In-Equality compare operator with an other object. * @param obj Reference on the comparing object @@ -202,7 +222,7 @@ public record Vector2f(float x, float y) { public boolean isDifferent(final Vector2f obj) { return (obj.x != this.x || obj.y != this.y); } - + /** * Equality compare operator with an other object. * @param obj Reference on the comparing object @@ -233,7 +253,7 @@ public record Vector2f(float x, float y) { public boolean isLowerOrEqual(final Vector2f obj) { return (this.x <= obj.x && this.y <= obj.y); } - + /** * Check if the vector is unitary (langth = 10f=) * @return true if unit , false otherwise @@ -242,7 +262,7 @@ public record Vector2f(float x, float y) { public boolean isUnit() { return FMath.approxEqual(length2(), 1.0f, Constant.MACHINE_EPSILON); } - + /** * Check if the vector is equal to (0,0) * @return true The value is equal to (0,0) @@ -252,7 +272,7 @@ public record Vector2f(float x, float y) { public boolean isZero() { return FMath.approxEqual(length2(), 0.0f, Constant.MACHINE_EPSILON); } - + /** * Get the length of the vector * @return Length value @@ -261,7 +281,7 @@ public record Vector2f(float x, float y) { public float length() { return (float) Math.sqrt(length2()); } - + /** * Get the length of the vector squared * @return Squared length value. @@ -275,6 +295,17 @@ public record Vector2f(float x, float y) { public Vector2f less(final float val) { return new Vector2f(this.x - val, this.y - val); } + + @CheckReturnValue + public Vector2f lessX(final float val) { + return new Vector2f(this.x - val, this.y); + } + + @CheckReturnValue + public Vector2f lessY(final float val) { + return new Vector2f(this.x, this.y - val); + } + @CheckReturnValue public Vector2f less(final float xxx, final float yyy) { return new Vector2f(this.x - xxx, this.y - yyy); @@ -284,11 +315,12 @@ public record Vector2f(float x, float y) { public Vector2f less(final Vector2f obj) { return new Vector2f(this.x - obj.x, this.y - obj.y); } + @CheckReturnValue public Vector2f less(final Vector2i obj) { return new Vector2f(this.x - obj.x(), this.y - obj.y()); } - + /** * Return the axis with the largest value * @return values are 0,1 for x or y @@ -297,7 +329,7 @@ public record Vector2f(float x, float y) { public int maxAxis() { return this.x < this.y ? 1 : 0; } - + /** * Return the axis with the smallest value * @return values are 0,1 for x or y @@ -316,7 +348,7 @@ public record Vector2f(float x, float y) { public Vector2f multiply(final Vector2f obj) { return new Vector2f(this.x * obj.x, this.y * obj.y); }; - + /** * Normalize this vector x^2 + y^2 = 1 */ @@ -324,7 +356,7 @@ public record Vector2f(float x, float y) { public Vector2f normalize() { return this.devide(length()); } - + /** * Normalize this vector x^2 + y^2 = 1 (check if not deviding by 0, if it * is the case ==> return (1,0)) @@ -338,7 +370,7 @@ public record Vector2f(float x, float y) { } return new Vector2f(1, 0); } - + /** * Set each element to the max of the current values and the values of * another vector @@ -348,7 +380,7 @@ public record Vector2f(float x, float y) { public Vector2f max(final Vector2f other) { return new Vector2f(Math.max(this.x, other.x), Math.max(this.y, other.y)); } - + /** * Set each element to the min of the current values and the values of * another vector @@ -358,13 +390,13 @@ public record Vector2f(float x, float y) { public Vector2f min(final Vector2f other) { return new Vector2f(Math.min(this.x, other.x), Math.min(this.y, other.y)); } - + // Return one unit orthogonal vector of the current vector @CheckReturnValue public Vector2f unitOrthogonal() { return (new Vector2f(this.x, -this.y)).safeNormalize(); } - + /** * Set 0 value on all the vector */ @@ -372,7 +404,17 @@ public record Vector2f(float x, float y) { public static final Vector2f MIN_VALUE = new Vector2f(Float.MIN_VALUE, Float.MIN_VALUE); public static final Vector2f ZERO = new Vector2f(0, 0); public static final Vector2f ONE = new Vector2f(1, 1); - + public static final Vector2f VALUE_2 = new Vector2f(2, 2); + public static final Vector2f VALUE_4 = new Vector2f(4, 4); + public static final Vector2f VALUE_8 = new Vector2f(8, 8); + public static final Vector2f VALUE_16 = new Vector2f(16, 16); + public static final Vector2f VALUE_32 = new Vector2f(32, 32); + public static final Vector2f VALUE_64 = new Vector2f(64, 64); + public static final Vector2f VALUE_128 = new Vector2f(128, 128); + public static final Vector2f VALUE_256 = new Vector2f(256, 256); + public static final Vector2f VALUE_512 = new Vector2f(512, 512); + public static final Vector2f VALUE_1024 = new Vector2f(1024, 1024); + @Override public String toString() { return "(" + this.x + "," + this.y + ")"; diff --git a/src/org/atriasoft/etk/math/Vector2i.java b/src/org/atriasoft/etk/math/Vector2i.java index bbfd6a3..3623d73 100644 --- a/src/org/atriasoft/etk/math/Vector2i.java +++ b/src/org/atriasoft/etk/math/Vector2i.java @@ -21,7 +21,7 @@ public record Vector2i( } final String[] values = value.split(","); if (values.length > 2) { - Log.error("Can not parse Vector2f with more than 2 values: '" + value + "'"); + Log.error("Can not parse Vector2i with more than 2 values: '" + value + "'"); } if (values.length == 1) { // no coma ... @@ -318,6 +318,16 @@ public record Vector2i( */ public static final Vector2i ZERO = new Vector2i(0, 0); public static final Vector2i ONE = new Vector2i(1, 1); + public static final Vector2i VALUE_2 = new Vector2i(2, 2); + public static final Vector2i VALUE_4 = new Vector2i(4, 4); + public static final Vector2i VALUE_8 = new Vector2i(8, 8); + public static final Vector2i VALUE_16 = new Vector2i(16, 16); + public static final Vector2i VALUE_32 = new Vector2i(32, 32); + public static final Vector2i VALUE_64 = new Vector2i(64, 64); + public static final Vector2i VALUE_128 = new Vector2i(128, 128); + public static final Vector2i VALUE_256 = new Vector2i(256, 256); + public static final Vector2i VALUE_512 = new Vector2i(512, 512); + public static final Vector2i VALUE_1024 = new Vector2i(1024, 1024); @Override public String toString() { diff --git a/src/org/atriasoft/etk/math/Vector3f.java b/src/org/atriasoft/etk/math/Vector3f.java index a6a4c8a..7458b3b 100644 --- a/src/org/atriasoft/etk/math/Vector3f.java +++ b/src/org/atriasoft/etk/math/Vector3f.java @@ -1,9 +1,13 @@ package org.atriasoft.etk.math; -import edu.umd.cs.findbugs.annotations.CheckReturnValue; import org.atriasoft.etk.internal.Log; -public record Vector3f(float x, float y, float z) { +import edu.umd.cs.findbugs.annotations.CheckReturnValue; + +public record Vector3f( + float x, + float y, + float z) { /** * Get the length square between the 2 vectors * @param start First vector @@ -16,7 +20,7 @@ public record Vector3f(float x, float y, float z) { final float z = stop.z - start.z; return x * x + y * y + z * z; } - + public static Vector3f valueOf(String value) { float val1 = 0; float val2 = 0; @@ -51,7 +55,7 @@ public record Vector3f(float x, float y, float z) { } return new Vector3f(val1, val2, val3); } - + /** * Constructor from scalars * @param value unique value for X,Y and Z value @@ -59,13 +63,13 @@ public record Vector3f(float x, float y, float z) { public Vector3f(final float value) { this(value, value, value); } - + public Vector3f(final float x, final float y, final float z) { this.x = x; this.y = y; this.z = z; } - + /** * Return a vector will the absolute values of each element * @return the curent reference @@ -79,15 +83,17 @@ public record Vector3f(float x, float y, float z) { public Vector3f add(final float value) { return new Vector3f(this.x + value, this.y + value, this.z + value); } + @CheckReturnValue public Vector3f add(final float xxx, final float yyy, final float zzz) { return new Vector3f(this.x + xxx, this.y + yyy, this.z + zzz); } + @CheckReturnValue public Vector3f clipInteger() { - return new Vector3f((int)x, (int)y, (int)z); + return new Vector3f((int) this.x, (int) this.y, (int) this.z); } - + /** * Add a vector to this one * @param obj The vector to add to this one @@ -96,7 +102,7 @@ public record Vector3f(float x, float y, float z) { public Vector3f add(final Vector3f obj) { return new Vector3f(this.x + obj.x, this.y + obj.y, this.z + obj.z); } - + /** * Calculate the angle between this and another vector * @param obj The other vector @@ -118,7 +124,7 @@ public record Vector3f(float x, float y, float z) { } return this; } - + /** * Return the axis with the largest ABSOLUTE value * @return values 0,1,2 for x, y, or z @@ -127,7 +133,7 @@ public record Vector3f(float x, float y, float z) { public int closestAxis() { return abs().maxAxis(); } - + /** * Return the cross product between this and another vector * @param obj The other vector @@ -135,10 +141,9 @@ public record Vector3f(float x, float y, float z) { */ @CheckReturnValue public Vector3f cross(final Vector3f obj) { - return new Vector3f(this.y * obj.z - this.z * obj.y, this.z * obj.x - this.x * obj.z, - this.x * obj.y - this.y * obj.x); + return new Vector3f(this.y * obj.z - this.z * obj.y, this.z * obj.x - this.x * obj.z, this.x * obj.y - this.y * obj.x); } - + /** * Return the distance between the ends of this and another vector This * is symantically treating the vector like a point @@ -149,7 +154,7 @@ public record Vector3f(float x, float y, float z) { public float distance(final Vector3f obj) { return (float) Math.sqrt(distance2(obj)); } - + /** * Return the distance squared between the ends of this and another * vector This is symantically treating the vector like a point @@ -163,7 +168,7 @@ public record Vector3f(float x, float y, float z) { final float deltaZ = obj.z - this.z; return deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ; } - + /** * Inversely scale the vector * @param val Scale factor to divide by @@ -175,7 +180,7 @@ public record Vector3f(float x, float y, float z) { } throw new IllegalArgumentException("divice by 0 (vector3f)"); } - + /** * Inversely scale the vector * @param val Scale factor to divide by @@ -184,7 +189,7 @@ public record Vector3f(float x, float y, float z) { public Vector3f divide(final Vector3f val) { return new Vector3f(this.x / val.x, this.y / val.y, this.z / val.z); } - + /** * Return the dot product * @param obj The other vector in the dot product @@ -194,7 +199,7 @@ public record Vector3f(float x, float y, float z) { public float dot(final Vector3f obj) { return this.x * obj.x + this.y * obj.y + this.z * obj.z; } - + /** * Return the axis with the smallest ABSOLUTE value * @return values 0,1,2 for x, y, or z @@ -203,7 +208,7 @@ public record Vector3f(float x, float y, float z) { public int furthestAxis() { return abs().minAxis(); } - + /** * get the value with his index * @param index Index of the value (0: x, 1: y, 2: z) @@ -220,7 +225,7 @@ public record Vector3f(float x, float y, float z) { } throw new IllegalArgumentException("Unknown index: " + index); } - + /** * Get the maximum value of the vector (x, y, z) * @return The max value @@ -229,7 +234,7 @@ public record Vector3f(float x, float y, float z) { public float getMax() { return Math.max(Math.max(this.x, this.y), this.z); } - + /** * Get the Axis id with the maximum value * @return Axis ID 0,1,2 @@ -238,7 +243,7 @@ public record Vector3f(float x, float y, float z) { public int getMaxAxis() { return (this.x < this.y ? (this.y < this.z ? 2 : 1) : (this.x < this.z ? 2 : 0)); } - + /** * Get the minimum value of the vector (x, y, z) * @return The min value @@ -247,7 +252,7 @@ public record Vector3f(float x, float y, float z) { public float getMin() { return Math.min(Math.min(this.x, this.y), this.z); } - + /** * Get the Axis id with the minimum value * @return Axis ID 0,1,2 @@ -256,7 +261,7 @@ public record Vector3f(float x, float y, float z) { public int getMinAxis() { return (this.x < this.y ? (this.x < this.z ? 0 : 2) : (this.y < this.z ? 1 : 2)); } - + /** * @breif Get the orthogonal vector of the current vector * @return The ortho vector @@ -275,7 +280,7 @@ public record Vector3f(float x, float y, float z) { final float devider = (float) Math.sqrt(this.x * this.x + this.y * this.y); return new Vector3f(-this.y / devider, this.x / devider, 0.0f); } - + /* * public void getSkewSymmetricMatrix(final Vector3f obj0, final Vector3f obj1, * final Vector3f obj2) { obj0.setValue(0, -this.z, this.y); @@ -295,13 +300,13 @@ public record Vector3f(float x, float y, float z) { public Vector3f getSkewSymmetricMatrix2() { return new Vector3f(-this.y, this.x, 0); } - + // Overloaded operator for the negative of a vector @CheckReturnValue public Vector3f invert() { return new Vector3f(-this.x, -this.y, -this.z); } - + /** * In-Equality compare operator with an other object. * @param obj Reference on the comparing object @@ -312,7 +317,7 @@ public record Vector3f(float x, float y, float z) { public boolean isDifferent(final Vector3f obj) { return ((this.z != obj.z) || (this.y != obj.y) || (this.x != obj.x)); } - + /** * Equality compare operator with an other object. * @param obj Reference on the comparing object @@ -323,7 +328,7 @@ public record Vector3f(float x, float y, float z) { public boolean isEqual(final Vector3f obj) { return ((this.z == obj.z) && (this.y == obj.y) && (this.x == obj.x)); } - + /** * Check if the vector is unitary (langth = 10f=) * @return true if unit , false otherwise @@ -332,7 +337,7 @@ public record Vector3f(float x, float y, float z) { public boolean isUnit() { return FMath.approxEqual(length2(), 1.0f, Constant.MACHINE_EPSILON); } - + /** * Check if the vector is equal to (0,0,0) * @return true The value is equal to (0,0,0) @@ -342,7 +347,7 @@ public record Vector3f(float x, float y, float z) { public boolean isZero() { return FMath.approxEqual(length2(), 0.0f, Constant.MACHINE_EPSILON); } - + /** * Get the length of the vector * @return Length value @@ -351,7 +356,7 @@ public record Vector3f(float x, float y, float z) { public float length() { return (float) Math.sqrt(length2()); } - + /** * Get the length between the 2 vectors * @param start First vector @@ -362,7 +367,7 @@ public record Vector3f(float x, float y, float z) { public float length(final Vector3f start, final Vector3f stop) { return (float) Math.sqrt(length2(start, stop)); } - + /** * Get the length of the vector squared * @return Squared length value. @@ -371,7 +376,7 @@ public record Vector3f(float x, float y, float z) { public float length2() { return dot(this); } - + /** * Return the linear interpolation between this and another vector * @param obj The other vector @@ -381,19 +386,19 @@ public record Vector3f(float x, float y, float z) { */ @CheckReturnValue public Vector3f lerp(final Vector3f obj, final float ratio) { - return new Vector3f(this.x + (obj.x - this.x) * ratio, this.y + (obj.y - this.y) * ratio, - this.z + (obj.z - this.z) * ratio); + return new Vector3f(this.x + (obj.x - this.x) * ratio, this.y + (obj.y - this.y) * ratio, this.z + (obj.z - this.z) * ratio); } @CheckReturnValue public Vector3f less(final float value) { return new Vector3f(this.x - value, this.y - value, this.z - value); } + @CheckReturnValue public Vector3f less(final float xxx, final float yyy, final float zzz) { return new Vector3f(this.x - xxx, this.y - yyy, this.z - zzz); } - + /** * Subtract a vector from this one * @param obj The vector to subtract @@ -403,7 +408,7 @@ public record Vector3f(float x, float y, float z) { public Vector3f less(final Vector3f obj) { return new Vector3f(this.x - obj.x, this.y - obj.y, this.z - obj.z); } - + /** * Return the axis with the largest value * @return values 0,1,2 for x, y, or z @@ -415,7 +420,7 @@ public record Vector3f(float x, float y, float z) { } return this.x < this.z ? 2 : 0; } - + /** * Return the axis with the smallest value * @return values 0,1,2 for x, y, or z @@ -427,7 +432,7 @@ public record Vector3f(float x, float y, float z) { } return this.y < this.z ? 1 : 2; } - + /** * Scale the vector * @param val Scale factor @@ -437,7 +442,7 @@ public record Vector3f(float x, float y, float z) { public Vector3f multiply(final float val) { return new Vector3f(this.x * val, this.y * val, this.z * val); } - + /** * Elementwise multiply this vector by the other * @param obj The other vector @@ -446,7 +451,7 @@ public record Vector3f(float x, float y, float z) { public Vector3f multiply(final Vector3f obj) { return new Vector3f(this.x * obj.x, this.y * obj.y, this.z * obj.z); } - + /** * Normalize this vector x^2 + y^2 + z^2 = 1 * @return the current vector @@ -455,7 +460,7 @@ public record Vector3f(float x, float y, float z) { public Vector3f normalize() { return this.divide(this.length()); } - + /** * Return a rotated version of this vector * @param wAxis The axis to rotate about @@ -473,7 +478,7 @@ public record Vector3f(float x, float y, float z) { out = out.add(y); return out; } - + /** * Normalize this vector x^2 + y^2 + z^2 = 1 (check if not deviding by 0, * if it is the case ==> return (1,0,0)) @@ -487,7 +492,7 @@ public record Vector3f(float x, float y, float z) { } return new Vector3f(1, 0, 0); } - + /** * Interpolate the vector with a ration between 2 others * @param obj0 First vector @@ -497,11 +502,10 @@ public record Vector3f(float x, float y, float z) { @CheckReturnValue public Vector3f setInterpolate3(final Vector3f obj0, final Vector3f obj1, final float ratio) { final float inverse = 1.0f - ratio; - return new Vector3f(inverse * obj0.x + ratio * obj1.x, inverse * obj0.y + ratio * obj1.y, - inverse * obj0.z + ratio * obj1.z); + return new Vector3f(inverse * obj0.x + ratio * obj1.x, inverse * obj0.y + ratio * obj1.y, inverse * obj0.z + ratio * obj1.z); // this.co[3] = s * v0[3] + rt * v1[3]; } - + /** * Set each element to the max of the current values and the values of * another Vector3f @@ -521,7 +525,7 @@ public record Vector3f(float x, float y, float z) { public static Vector3f min(final Vector3f obj1, final Vector3f obj2) { return new Vector3f(Math.min(obj1.x, obj2.x), Math.min(obj1.y, obj2.y), Math.min(obj1.z, obj2.z)); } - + /** * Set each element to the min of the current values and the values of * another Vector3f @@ -546,19 +550,28 @@ public record Vector3f(float x, float y, float z) { public Vector3f withZ(final float zzz) { return new Vector3f(this.x, this.y, zzz); } - + /** * Set 0 value on all the vector */ public static final Vector3f ZERO = new Vector3f(0, 0, 0); public static final Vector3f ONE = new Vector3f(1, 1, 1); - + public static final Vector3f VALUE_2 = new Vector3f(2, 2, 2); + public static final Vector3f VALUE_4 = new Vector3f(4, 4, 4); + public static final Vector3f VALUE_8 = new Vector3f(8, 8, 8); + public static final Vector3f VALUE_16 = new Vector3f(16, 16, 16); + public static final Vector3f VALUE_32 = new Vector3f(32, 32, 32); + public static final Vector3f VALUE_64 = new Vector3f(64, 64, 64); + public static final Vector3f VALUE_128 = new Vector3f(128, 128, 128); + public static final Vector3f VALUE_256 = new Vector3f(256, 256, 256); + public static final Vector3f VALUE_512 = new Vector3f(512, 512, 512); + public static final Vector3f VALUE_1024 = new Vector3f(1024, 1024, 1024); + @Override public String toString() { - return "Vector3f(" + FMath.floatToString(this.x) + "," + FMath.floatToString(this.y) + "," - + FMath.floatToString(this.z) + ")"; + return "Vector3f(" + FMath.floatToString(this.x) + "," + FMath.floatToString(this.y) + "," + FMath.floatToString(this.z) + ")"; } - + /** * Return the triple product between this and another vector and another * @param obj1 The other vector 1 @@ -567,7 +580,6 @@ public record Vector3f(float x, float y, float z) { */ @CheckReturnValue public float triple(final Vector3f obj1, final Vector3f obj2) { - return this.x * (obj1.y * obj2.z - obj1.z * obj2.y) + this.y * (obj1.z * obj2.x - obj1.x * obj2.z) - + this.z * (obj1.x * obj2.y - obj1.y * obj2.x); + return this.x * (obj1.y * obj2.z - obj1.z * obj2.y) + this.y * (obj1.z * obj2.x - obj1.x * obj2.z) + this.z * (obj1.x * obj2.y - obj1.y * obj2.x); } } diff --git a/src/org/atriasoft/etk/math/Vector3i.java b/src/org/atriasoft/etk/math/Vector3i.java index b39d678..7470bee 100644 --- a/src/org/atriasoft/etk/math/Vector3i.java +++ b/src/org/atriasoft/etk/math/Vector3i.java @@ -1,8 +1,9 @@ package org.atriasoft.etk.math; -import edu.umd.cs.findbugs.annotations.CheckReturnValue; import org.atriasoft.etk.internal.Log; +import edu.umd.cs.findbugs.annotations.CheckReturnValue; + public record Vector3i( int x, int y, @@ -20,7 +21,7 @@ public record Vector3i( } final String[] values = value.split(","); if (values.length > 3) { - Log.error("Can not parse Vector3f with more than 3 values: '" + value + "'"); + Log.error("Can not parse Vector3i with more than 3 values: '" + value + "'"); } if (values.length == 1) { // no coma ... @@ -58,15 +59,15 @@ public record Vector3i( this.y = y; this.z = z; } - + public static Vector3i max(final Vector3i obj1, final Vector3i obj2) { return new Vector3i(Math.max(obj1.x, obj2.x), Math.max(obj1.y, obj2.y), Math.max(obj1.z, obj2.z)); } - + public static Vector3i min(final Vector3i obj1, final Vector3i obj2) { return new Vector3i(Math.min(obj1.x, obj2.x), Math.min(obj1.y, obj2.y), Math.min(obj1.z, obj2.z)); } - + /** * Constructor from scalars * @param value unique value for X,Y and Z value @@ -92,10 +93,12 @@ public record Vector3i( public Vector3i add(final Vector3i obj) { return new Vector3i(this.x + obj.x, this.y + obj.y, this.z + obj.z); } + @CheckReturnValue public Vector3i add(final int value) { return new Vector3i(this.x + value, this.y + value, this.z + value); } + @CheckReturnValue public Vector3i add(final int xxx, final int yyy, final int zzz) { return new Vector3i(this.x + xxx, this.y + yyy, this.z + zzz); @@ -225,6 +228,7 @@ public record Vector3i( public int getMinAxis() { return (this.x < this.y ? (this.x < this.z ? 0 : 2) : (this.y < this.z ? 1 : 2)); } + @CheckReturnValue public Vector3i getSkewSymmetricMatrix0() { return new Vector3i(0, -this.z, this.y); @@ -309,10 +313,12 @@ public record Vector3i( public Vector3i less(final Vector3i obj) { return new Vector3i(this.x - obj.x, this.y - obj.y, this.z - obj.z); } + @CheckReturnValue public Vector3i less(final int value) { return new Vector3i(this.x - value, this.y - value, this.z - value); } + @CheckReturnValue public Vector3i less(final int xxx, final int yyy, final int zzz) { return new Vector3i(this.x - xxx, this.y - yyy, this.z - zzz); @@ -414,6 +420,16 @@ public record Vector3i( */ public static final Vector3i ZERO = new Vector3i(0, 0, 0); public static final Vector3i ONE = new Vector3i(1, 1, 1); + public static final Vector3i VALUE_2 = new Vector3i(2, 2, 2); + public static final Vector3i VALUE_4 = new Vector3i(4, 4, 4); + public static final Vector3i VALUE_8 = new Vector3i(8, 8, 8); + public static final Vector3i VALUE_16 = new Vector3i(16, 16, 16); + public static final Vector3i VALUE_32 = new Vector3i(32, 32, 32); + public static final Vector3i VALUE_64 = new Vector3i(64, 64, 64); + public static final Vector3i VALUE_128 = new Vector3i(128, 128, 128); + public static final Vector3i VALUE_256 = new Vector3i(256, 256, 256); + public static final Vector3i VALUE_512 = new Vector3i(512, 512, 512); + public static final Vector3i VALUE_1024 = new Vector3i(1024, 1024, 1024); @Override public String toString() { diff --git a/src/org/atriasoft/etk/util/Dynamic.java b/src/org/atriasoft/etk/util/Dynamic.java new file mode 100644 index 0000000..d86ff0e --- /dev/null +++ b/src/org/atriasoft/etk/util/Dynamic.java @@ -0,0 +1,9 @@ +package org.atriasoft.etk.util; + +public class Dynamic { + public T value; + + public Dynamic(final T value) { + this.value = value; + } +} diff --git a/src/org/atriasoft/etk/util/Pair.java b/src/org/atriasoft/etk/util/Pair.java index 2a8c0a1..e2952c6 100644 --- a/src/org/atriasoft/etk/util/Pair.java +++ b/src/org/atriasoft/etk/util/Pair.java @@ -49,6 +49,15 @@ public class Pair { public String toString() { return "(" + this.first + ", " + this.second + ")"; } + + public Pair withFirst(final U value) { + return new Pair<>(value, this.second); + } + + public Pair withSecond(final V value) { + return new Pair<>(this.first, value); + } + } // Program to implement Pair Class in Java