From b23e221988e1332214ed0fb0ff059054752430eb Mon Sep 17 00:00:00 2001 From: Edouard DUPIN Date: Tue, 16 Mar 2021 00:25:37 +0100 Subject: [PATCH] [DEV] continue integration --- src/module-info.java | 2 + src/org/atriasoft/etk/Color.java | 437 +++++++++++- src/org/atriasoft/etk/Uri.java | 192 +++++- src/org/atriasoft/etk/internal/Log.java | 84 +-- src/org/atriasoft/etk/math/Constant.java | 2 + src/org/atriasoft/etk/math/FMath.java | 8 +- src/org/atriasoft/etk/math/Matrix3f.java | 25 +- src/org/atriasoft/etk/math/Matrix4f.java | 33 +- src/org/atriasoft/etk/math/Quaternion.java | 20 +- src/org/atriasoft/etk/math/Vector2b.java | 174 +++++ src/org/atriasoft/etk/math/Vector2f.java | 67 +- src/org/atriasoft/etk/math/Vector2i.java | 633 ++++++++++-------- src/org/atriasoft/etk/math/Vector3f.java | 62 +- src/org/atriasoft/etk/math/Vector3i.java | 732 +++++++++++---------- src/org/atriasoft/etk/theme/Theme.java | 86 +++ src/org/atriasoft/etk/util/Pair.java | 75 +++ 16 files changed, 1929 insertions(+), 703 deletions(-) create mode 100644 src/org/atriasoft/etk/math/Vector2b.java create mode 100644 src/org/atriasoft/etk/theme/Theme.java create mode 100644 src/org/atriasoft/etk/util/Pair.java diff --git a/src/module-info.java b/src/module-info.java index fd1ce90..7146eb0 100644 --- a/src/module-info.java +++ b/src/module-info.java @@ -5,5 +5,7 @@ open module org.atriasoft.etk { exports org.atriasoft.etk; exports org.atriasoft.etk.math; + exports org.atriasoft.etk.util; + requires transitive io.scenarium.logger; } diff --git a/src/org/atriasoft/etk/Color.java b/src/org/atriasoft/etk/Color.java index 7f51443..e144fbd 100644 --- a/src/org/atriasoft/etk/Color.java +++ b/src/org/atriasoft/etk/Color.java @@ -1,25 +1,442 @@ package org.atriasoft.etk; +import java.util.Map; + +import org.atriasoft.etk.math.FMath; + +// TODO transform in record ... public class Color { - @Override - public String toString() { - return "Color [r=" + r + ", g=" + g + ", b=" + b + ", a=" + a + "]"; + public static final Color NONE = new Color(0x00, 0x00, 0x00, 0x00); + public static final Color ALICE_BLUE = new Color(0xF0, 0xF8, 0xFF, 0xFF); + public static final Color ANTIQUE_WHITE = new Color(0xFA, 0xEB, 0xD7, 0xFF); + public static final Color AQUA = new Color(0x00, 0xFF, 0xFF, 0xFF); + public static final Color AQUA_MARINE = new Color(0x7F, 0xFF, 0xD4, 0xFF); + public static final Color AZURE = new Color(0xF0, 0xFF, 0xFF, 0xFF); + public static final Color BEIGE = new Color(0xF5, 0xF5, 0xDC, 0xFF); + public static final Color BISQUE = new Color(0xFF, 0xE4, 0xC4, 0xFF); + public static final Color BLACK = new Color(0x00, 0x00, 0x00, 0xFF); + public static final Color BLANCHED_ALMOND = new Color(0xFF, 0xEB, 0xCD, 0xFF); + public static final Color BLUE = new Color(0x00, 0x00, 0xFF, 0xFF); + public static final Color BLUE_VIOLET = new Color(0x8A, 0x2B, 0xE2, 0xFF); + public static final Color BROWN = new Color(0xA5, 0x2A, 0x2A, 0xFF); + public static final Color BURLY_WOOD = new Color(0xDE, 0xB8, 0x87, 0xFF); + public static final Color CADET_BLUE = new Color(0x5F, 0x9E, 0xA0, 0xFF); + public static final Color CHARTREUSE = new Color(0x7F, 0xFF, 0x00, 0xFF); + public static final Color CHOCOLATE = new Color(0xD2, 0x69, 0x1E, 0xFF); + public static final Color CORAL = new Color(0xFF, 0x7F, 0x50, 0xFF); + public static final Color CORNFLOWER_BLUE = new Color(0x64, 0x95, 0xED, 0xFF); + public static final Color CORNSILK = new Color(0xFF, 0xF8, 0xDC, 0xFF); + public static final Color CRIMSON = new Color(0xDC, 0x14, 0x3C, 0xFF); + public static final Color CYAN = new Color(0x00, 0xFF, 0xFF, 0xFF); + public static final Color DARK_BLUE = new Color(0x00, 0x00, 0x8B, 0xFF); + public static final Color DARK_CYAN = new Color(0x00, 0x8B, 0x8B, 0xFF); + public static final Color DARK_GOLDENROD = new Color(0xB8, 0x86, 0x0B, 0xFF); + public static final Color DARK_GRAY = new Color(0xA9, 0xA9, 0xA9, 0xFF); + public static final Color DARK_GREY = new Color(0xA9, 0xA9, 0xA9, 0xFF); + public static final Color DARK_GREEN = new Color(0x00, 0x64, 0x00, 0xFF); + public static final Color DARK_KHAKI = new Color(0xBD, 0xB7, 0x6B, 0xFF); + public static final Color DARK_MAGENTA = new Color(0x8B, 0x00, 0x8B, 0xFF); + public static final Color DARK_OLIVEGREEN = new Color(0x55, 0x6B, 0x2F, 0xFF); + public static final Color DARK_ORANGE = new Color(0xFF, 0x8C, 0x00, 0xFF); + public static final Color DARK_ORCHID = new Color(0x99, 0x32, 0xCC, 0xFF); + public static final Color DARK_RED = new Color(0x8B, 0x00, 0x00, 0xFF); + public static final Color DARK_SALMON = new Color(0xE9, 0x96, 0x7A, 0xFF); + public static final Color DARK_SEAGREEN = new Color(0x8F, 0xBC, 0x8F, 0xFF); + public static final Color DARK_SLATE_BLUE = new Color(0x48, 0x3D, 0x8B, 0xFF); + public static final Color DARK_SLATE_GRAY = new Color(0x2F, 0x4F, 0x4F, 0xFF); + public static final Color DARK_SLATE_GREY = new Color(0x2F, 0x4F, 0x4F, 0xFF); + public static final Color DARK_TURQUOISE = new Color(0x00, 0xCE, 0xD1, 0xFF); + public static final Color DARK_VIOLET = new Color(0x94, 0x00, 0xD3, 0xFF); + public static final Color DEEP_PINK = new Color(0xFF, 0x14, 0x93, 0xFF); + public static final Color DEEP_SKY_BLUE = new Color(0x00, 0xBF, 0xFF, 0xFF); + public static final Color DIM_GRAY = new Color(0x69, 0x69, 0x69, 0xFF); + public static final Color DIM_GREY = new Color(0x69, 0x69, 0x69, 0xFF); + public static final Color DODGER_BLUE = new Color(0x1E, 0x90, 0xFF, 0xFF); + public static final Color FIRE_BRICK = new Color(0xB2, 0x22, 0x22, 0xFF); + public static final Color FLORAL_WHITE = new Color(0xFF, 0xFA, 0xF0, 0xFF); + public static final Color FOREST_GREEN = new Color(0x22, 0x8B, 0x22, 0xFF); + public static final Color FUCHSIA = new Color(0xFF, 0x00, 0xFF, 0xFF); + public static final Color GAINSBORO = new Color(0xDC, 0xDC, 0xDC, 0xFF); + public static final Color GHOST_WHITE = new Color(0xF8, 0xF8, 0xFF, 0xFF); + public static final Color GOLD = new Color(0xFF, 0xD7, 0x00, 0xFF); + public static final Color GOLDEN_ROD = new Color(0xDA, 0xA5, 0x20, 0xFF); + public static final Color GRAY = new Color(0x80, 0x80, 0x80, 0xFF); + public static final Color GREY = new Color(0x80, 0x80, 0x80, 0xFF); + public static final Color GREEN = new Color(0x00, 0x80, 0x00, 0xFF); + public static final Color GREEN_YELLOW = new Color(0xAD, 0xFF, 0x2F, 0xFF); + public static final Color HONEY_DEW = new Color(0xF0, 0xFF, 0xF0, 0xFF); + public static final Color HOT_PINK = new Color(0xFF, 0x69, 0xB4, 0xFF); + public static final Color INDIAN_RED = new Color(0xCD, 0x5C, 0x5C, 0xFF); + public static final Color INDIGO = new Color(0x4B, 0x00, 0x82, 0xFF); + public static final Color IVORY = new Color(0xFF, 0xFF, 0xF0, 0xFF); + public static final Color KHAKI = new Color(0xF0, 0xE6, 0x8C, 0xFF); + public static final Color LAVENDER = new Color(0xE6, 0xE6, 0xFA, 0xFF); + public static final Color LAVENDER_BLUSH = new Color(0xFF, 0xF0, 0xF5, 0xFF); + public static final Color LAWN_GREEN = new Color(0x7C, 0xFC, 0x00, 0xFF); + public static final Color LEMON_CHIFFON = new Color(0xFF, 0xFA, 0xCD, 0xFF); + public static final Color LIGHT_BLUE = new Color(0xAD, 0xD8, 0xE6, 0xFF); + public static final Color LIGHT_CORAL = new Color(0xF0, 0x80, 0x80, 0xFF); + public static final Color LIGHT_CYAN = new Color(0xE0, 0xFF, 0xFF, 0xFF); + public static final Color LIGHT_GOLDEN_ROD_YELLOW = new Color(0xFA, 0xFA, 0xD2, 0xFF); + public static final Color LIGHT_GRAY = new Color(0xD3, 0xD3, 0xD3, 0xFF); + public static final Color LIGHT_GREY = new Color(0xD3, 0xD3, 0xD3, 0xFF); + public static final Color LIGHT_GREEN = new Color(0x90, 0xEE, 0x90, 0xFF); + public static final Color LIGHT_PINK = new Color(0xFF, 0xB6, 0xC1, 0xFF); + public static final Color LIGHT_SALMON = new Color(0xFF, 0xA0, 0x7A, 0xFF); + public static final Color LIGHT_SEA_GREEN = new Color(0x20, 0xB2, 0xAA, 0xFF); + public static final Color LIGHT_SKY_BLUE = new Color(0x87, 0xCE, 0xFA, 0xFF); + public static final Color LIGHT_SLATE_GRAY = new Color(0x77, 0x88, 0x99, 0xFF); + public static final Color LIGHT_SLATE_GREY = new Color(0x77, 0x88, 0x99, 0xFF); + public static final Color LIGHT_STEEL_BLUE = new Color(0xB0, 0xC4, 0xDE, 0xFF); + public static final Color LIGHT_YELLOW = new Color(0xFF, 0xFF, 0xE0, 0xFF); + public static final Color LIME = new Color(0x00, 0xFF, 0x00, 0xFF); + public static final Color LIME_GREEN = new Color(0x32, 0xCD, 0x32, 0xFF); + public static final Color LINEN = new Color(0xFA, 0xF0, 0xE6, 0xFF); + public static final Color MAGENTA = new Color(0xFF, 0x00, 0xFF, 0xFF); + public static final Color MAROON = new Color(0x80, 0x00, 0x00, 0xFF); + public static final Color MEDIUM_AQUA_MARINE = new Color(0x66, 0xCD, 0xAA, 0xFF); + public static final Color MEDIUM_BLUE = new Color(0x00, 0x00, 0xCD, 0xFF); + public static final Color MEDIUM_ORCHID = new Color(0xBA, 0x55, 0xD3, 0xFF); + public static final Color MEDIUM_PURPLE = new Color(0x93, 0x70, 0xD8, 0xFF); + public static final Color MEDIUM_SEA_GREEN = new Color(0x3C, 0xB3, 0x71, 0xFF); + public static final Color MEDIUM_SLATE_BLUE = new Color(0x7B, 0x68, 0xEE, 0xFF); + public static final Color MEDIUM_SPRING_GREEN = new Color(0x00, 0xFA, 0x9A, 0xFF); + public static final Color MEDIUM_TURQUOISE = new Color(0x48, 0xD1, 0xCC, 0xFF); + public static final Color MEDIUM_VIOLET_RED = new Color(0xC7, 0x15, 0x85, 0xFF); + public static final Color MIDNIGHT_BLUE = new Color(0x19, 0x19, 0x70, 0xFF); + public static final Color MINT_CREAM = new Color(0xF5, 0xFF, 0xFA, 0xFF); + public static final Color MISTY_ROSE = new Color(0xFF, 0xE4, 0xE1, 0xFF); + public static final Color MOCCASIN = new Color(0xFF, 0xE4, 0xB5, 0xFF); + public static final Color NAVAJO_WHITE = new Color(0xFF, 0xDE, 0xAD, 0xFF); + public static final Color NAVY = new Color(0x00, 0x00, 0x80, 0xFF); + public static final Color OLDLACE = new Color(0xFD, 0xF5, 0xE6, 0xFF); + public static final Color OLIVE = new Color(0x80, 0x80, 0x00, 0xFF); + public static final Color OLIVE_DRAB = new Color(0x6B, 0x8E, 0x23, 0xFF); + public static final Color ORANGE = new Color(0xFF, 0xA5, 0x00, 0xFF); + public static final Color ORANGE_RED = new Color(0xFF, 0x45, 0x00, 0xFF); + public static final Color ORCHID = new Color(0xDA, 0x70, 0xD6, 0xFF); + public static final Color PALE_GOLDEN_ROD = new Color(0xEE, 0xE8, 0xAA, 0xFF); + public static final Color PALE_GREEN = new Color(0x98, 0xFB, 0x98, 0xFF); + public static final Color PALE_TURQUOISE = new Color(0xAF, 0xEE, 0xEE, 0xFF); + public static final Color PALE_VIOLET_RED = new Color(0xD8, 0x70, 0x93, 0xFF); + public static final Color PAPAYA_WHIP = new Color(0xFF, 0xEF, 0xD5, 0xFF); + public static final Color PEACH_PUFF = new Color(0xFF, 0xDA, 0xB9, 0xFF); + public static final Color PERU = new Color(0xCD, 0x85, 0x3F, 0xFF); + public static final Color PINK = new Color(0xFF, 0xC0, 0xCB, 0xFF); + public static final Color PLUM = new Color(0xDD, 0xA0, 0xDD, 0xFF); + public static final Color POWDER_BLUE = new Color(0xB0, 0xE0, 0xE6, 0xFF); + public static final Color PURPLE = new Color(0x80, 0x00, 0x80, 0xFF); + public static final Color RED = new Color(0xFF, 0x00, 0x00, 0xFF); + public static final Color ROSY_BROWN = new Color(0xBC, 0x8F, 0x8F, 0xFF); + public static final Color ROYAL_BLUE = new Color(0x41, 0x69, 0xE1, 0xFF); + public static final Color SADDLE_BROWN = new Color(0x8B, 0x45, 0x13, 0xFF); + public static final Color SALMON = new Color(0xFA, 0x80, 0x72, 0xFF); + public static final Color SANDY_BROWN = new Color(0xF4, 0xA4, 0x60, 0xFF); + public static final Color SEA_GREEN = new Color(0x2E, 0x8B, 0x57, 0xFF); + public static final Color SEA_SHELL = new Color(0xFF, 0xF5, 0xEE, 0xFF); + public static final Color SIENNA = new Color(0xA0, 0x52, 0x2D, 0xFF); + public static final Color SILVER = new Color(0xC0, 0xC0, 0xC0, 0xFF); + public static final Color SKY_BLUE = new Color(0x87, 0xCE, 0xEB, 0xFF); + public static final Color SLATE_BLUE = new Color(0x6A, 0x5A, 0xCD, 0xFF); + public static final Color SLATE_GRAY = new Color(0x70, 0x80, 0x90, 0xFF); + public static final Color SLATE_GREY = new Color(0x70, 0x80, 0x90, 0xFF); + public static final Color SNOW = new Color(0xFF, 0xFA, 0xFA, 0xFF); + public static final Color SPRING_GREEN = new Color(0x00, 0xFF, 0x7F, 0xFF); + public static final Color STEEL_BLUE = new Color(0x46, 0x82, 0xB4, 0xFF); + public static final Color TAN = new Color(0xD2, 0xB4, 0x8C, 0xFF); + public static final Color TEAL = new Color(0x00, 0x80, 0x80, 0xFF); + public static final Color THISTLE = new Color(0xD8, 0xBF, 0xD8, 0xFF); + public static final Color TOMATO = new Color(0xFF, 0x63, 0x47, 0xFF); + public static final Color TURQUOISE = new Color(0x40, 0xE0, 0xD0, 0xFF); + public static final Color VIOLET = new Color(0xEE, 0x82, 0xEE, 0xFF); + public static final Color WHEAT = new Color(0xF5, 0xDE, 0xB3, 0xFF); + public static final Color WHITE = new Color(0xFF, 0xFF, 0xFF, 0xFF); + public static final Color WHITE_SMOKE = new Color(0xF5, 0xF5, 0xF5, 0xFF); + 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 + Map.entry("none", NONE), + Map.entry("aliceblue", ALICE_BLUE), + Map.entry("antiquewhite", ANTIQUE_WHITE), + Map.entry("aqua", AQUA), + Map.entry("aquamarine", AQUA_MARINE), + Map.entry("azure", AZURE), + Map.entry("beige", BEIGE), + Map.entry("bisque", BISQUE), + Map.entry("black", BLACK), + Map.entry("blanchedalmond", BLANCHED_ALMOND), + Map.entry("blue", BLUE), + Map.entry("blueviolet", BLUE_VIOLET), + Map.entry("brown", BROWN), + Map.entry("burlywood", BURLY_WOOD), + Map.entry("cadetblue", CADET_BLUE), + Map.entry("chartreuse", CHARTREUSE), + Map.entry("chocolate", CHOCOLATE), + Map.entry("coral", CORAL), + Map.entry("cornflowerblue", CORNFLOWER_BLUE), + Map.entry("cornsilk", CORNSILK), + Map.entry("crimson", CRIMSON), + Map.entry("cyan", CYAN), + Map.entry("darkblue", DARK_BLUE), + Map.entry("darkcyan", DARK_CYAN), + Map.entry("darkgoldenrod", DARK_GOLDENROD), + Map.entry("darkgray", DARK_GRAY), + Map.entry("darkgrey", DARK_GREY), + Map.entry("darkgreen", DARK_GREEN), + Map.entry("darkkhaki", DARK_KHAKI), + Map.entry("darkmagenta", DARK_MAGENTA), + Map.entry("darkolivegreen", DARK_OLIVEGREEN), + Map.entry("darkorange", DARK_ORANGE), + Map.entry("darkorchid", DARK_ORCHID), + Map.entry("darkred", DARK_RED), + Map.entry("darksalmon", DARK_SALMON), + Map.entry("darkseagreen", DARK_SEAGREEN), + Map.entry("darkslateblue", DARK_SLATE_BLUE), + Map.entry("darkslategray", DARK_SLATE_GRAY), + Map.entry("darkslategrey", DARK_SLATE_GREY), + Map.entry("darkturquoise", DARK_TURQUOISE), + Map.entry("darkviolet", DARK_VIOLET), + Map.entry("deeppink", DEEP_PINK), + Map.entry("deepskyblue", DEEP_SKY_BLUE), + Map.entry("dimgray", DIM_GRAY), + Map.entry("dimgrey", DIM_GREY), + Map.entry("dodgerblue", DODGER_BLUE), + Map.entry("firebrick", FIRE_BRICK), + Map.entry("floralwhite", FLORAL_WHITE), + Map.entry("forestgreen", FOREST_GREEN), + Map.entry("fuchsia", FUCHSIA), + Map.entry("gainsboro", GAINSBORO), + Map.entry("ghostwhite", GHOST_WHITE), + Map.entry("gold", GOLD), + Map.entry("goldenrod", GOLDEN_ROD), + Map.entry("gray", GRAY), + Map.entry("grey", GREY), + Map.entry("green", GREEN), + Map.entry("greenyellow", GREEN_YELLOW), + Map.entry("honeydew", HONEY_DEW), + Map.entry("hotpink", HOT_PINK), + Map.entry("indianred", INDIAN_RED), + Map.entry("indigo", INDIGO), + Map.entry("ivory", IVORY), + Map.entry("khaki", KHAKI), + Map.entry("lavender", LAVENDER), + Map.entry("lavenderblush", LAVENDER_BLUSH), + Map.entry("lawngreen", LAWN_GREEN), + Map.entry("lemonchiffon", LEMON_CHIFFON), + Map.entry("lightblue", LIGHT_BLUE), + Map.entry("lightcoral", LIGHT_CORAL), + Map.entry("lightcyan", LIGHT_CYAN), + Map.entry("lightgoldenrodyellow", LIGHT_GOLDEN_ROD_YELLOW), + Map.entry("lightgray", LIGHT_GRAY), + Map.entry("lightgrey", LIGHT_GREY), + Map.entry("lightgreen", LIGHT_GREEN), + Map.entry("lightpink", LIGHT_PINK), + Map.entry("lightsalmon", LIGHT_SALMON), + Map.entry("lightseagreen", LIGHT_SEA_GREEN), + Map.entry("lightskyblue", LIGHT_SKY_BLUE), + Map.entry("lightslategray", LIGHT_SLATE_GRAY), + Map.entry("lightslategrey", LIGHT_SLATE_GREY), + Map.entry("lightsteelblue", LIGHT_STEEL_BLUE), + Map.entry("lightyellow", LIGHT_YELLOW), + Map.entry("lime", LIME), + Map.entry("limegreen", LIME_GREEN), + Map.entry("linen", LINEN), + Map.entry("magenta", MAGENTA), + Map.entry("maroon", MAROON), + Map.entry("mediumaquamarine", MEDIUM_AQUA_MARINE), + Map.entry("mediumblue", MEDIUM_BLUE), + Map.entry("mediumorchid", MEDIUM_ORCHID), + Map.entry("mediumpurple", MEDIUM_PURPLE), + Map.entry("mediumseagreen", MEDIUM_SEA_GREEN), + Map.entry("mediumslateblue", MEDIUM_SLATE_BLUE), + Map.entry("mediumspringgreen", MEDIUM_SPRING_GREEN), + Map.entry("mediumturquoise", MEDIUM_TURQUOISE), + Map.entry("mediumvioletred", MEDIUM_VIOLET_RED), + Map.entry("midnightblue", MIDNIGHT_BLUE), + Map.entry("mintcream", MINT_CREAM), + Map.entry("mistyrose", MISTY_ROSE), + Map.entry("moccasin", MOCCASIN), + Map.entry("navajowhite", NAVAJO_WHITE), + Map.entry("navy", NAVY), + Map.entry("oldlace", OLDLACE), + Map.entry("olive", OLIVE), + Map.entry("olivedrab", OLIVE_DRAB), + Map.entry("orange", ORANGE), + Map.entry("orangered", ORANGE_RED), + Map.entry("orchid", ORCHID), + Map.entry("palegoldenrod", PALE_GOLDEN_ROD), + Map.entry("palegreen", PALE_GREEN), + Map.entry("paleturquoise", PALE_TURQUOISE), + Map.entry("palevioletred", PALE_VIOLET_RED), + Map.entry("papayawhip", PAPAYA_WHIP), + Map.entry("peachpuff", PEACH_PUFF), + Map.entry("peru", PERU), + Map.entry("pink", PINK), + Map.entry("plum", PLUM), + Map.entry("powderblue", POWDER_BLUE), + Map.entry("purple", PURPLE), + Map.entry("red", RED), + Map.entry("rosybrown", ROSY_BROWN), + Map.entry("royalblue", ROYAL_BLUE), + Map.entry("saddlebrown", SADDLE_BROWN), + Map.entry("salmon", SALMON), + Map.entry("sandybrown", SANDY_BROWN), + Map.entry("seagreen", SEA_GREEN), + Map.entry("seashell", SEA_SHELL), + Map.entry("sienna", SIENNA), + Map.entry("silver", SILVER), + Map.entry("skyblue", SKY_BLUE), + Map.entry("slateblue", SLATE_BLUE), + Map.entry("slategray", SLATE_GRAY), + Map.entry("slategrey", SLATE_GREY), + Map.entry("snow", SNOW), + Map.entry("springgreen", SPRING_GREEN), + Map.entry("steelblue", STEEL_BLUE), + Map.entry("tan", TAN), + Map.entry("teal", TEAL), + Map.entry("thistle", THISTLE), + Map.entry("tomato", TOMATO), + Map.entry("turquoise", TURQUOISE), + Map.entry("violet", VIOLET), + Map.entry("wheat", WHEAT), + Map.entry("white", WHITE), + Map.entry("whitesmoke", WHITE_SMOKE), + Map.entry("yellow", YELLOW), + Map.entry("yellowgreen", YELLOW_GREEN) + //@formatter:on + ); + + public static Color get(final String name) { + return NAMED_COLORS.get(name.toLowerCase()); } + + public static Color valueOf(final String colorBase) throws Exception { + // remove all white space... + String color = colorBase.replace(" \r\n\t\\(\\)", ""); + if (color.isEmpty() == true) { + return new Color(0, 0, 0, 1.0f); + } + final Color named = get(colorBase); + if (named != null) { + return named.clone(); + } else if (color.charAt(0) == '#') { + // MODEL: #RGB + // #RGBA + // #RRGGBB + // #RRGGBBAA + switch (color.length()) { + case 4: { + final float r = Integer.parseInt(color.substring(1, 2), 16) * 255.0f * 16.0f; + final float g = Integer.parseInt(color.substring(2, 3), 16) * 255.0f * 16.0f; + final float b = Integer.parseInt(color.substring(3, 4), 16) * 255.0f * 16.0f; + return new Color(r, g, b); + } + case 5: { + final float r = Integer.parseInt(color.substring(1, 2), 16) * 255.0f * 16.0f; + final float g = Integer.parseInt(color.substring(2, 3), 16) * 255.0f * 16.0f; + final float b = Integer.parseInt(color.substring(3, 4), 16) * 255.0f * 16.0f; + final float a = Integer.parseInt(color.substring(4, 5), 16) * 255.0f * 16.0f; + return new Color(r, g, b, a); + } + case 7: { + final float r = Integer.parseInt(color.substring(1, 3), 16) * 255.0f; + final float g = Integer.parseInt(color.substring(3, 5), 16) * 255.0f; + final float b = Integer.parseInt(color.substring(5, 7), 16) * 255.0f; + return new Color(r, g, b); + } + case 9: { + final float r = Integer.parseInt(color.substring(1, 3), 16) * 255.0f; + final float g = Integer.parseInt(color.substring(3, 5), 16) * 255.0f; + final float b = Integer.parseInt(color.substring(5, 7), 16) * 255.0f; + final float a = Integer.parseInt(color.substring(7, 9), 16) * 255.0f; + return new Color(r, g, b, a); + } + default: + throw new Exception("Can not parse color ... '" + colorBase + "'"); + } + } else { + // Model: r.r,g.g,b.b + // r.r,g.g,b.b,a.a + // (r.r,g.g,b.b) + // (r.r,g.g,b.b,a.a) + // rgb(r.r,g.g,b.b) + // rgba(r.r,g.g,b.b,a.a) + // argb(a.a,r.r,g.g,b.b) + if (color.startsWith("argb") == true) { + color = color.replace("argb", ""); + final String[] vals = color.split(","); + if (vals.length == 4) { + final float a = FMath.avg(0.0f, Float.parseFloat(vals[0]), 1.0f); + final float r = FMath.avg(0.0f, Float.parseFloat(vals[1]), 1.0f); + final float g = FMath.avg(0.0f, Float.parseFloat(vals[2]), 1.0f); + final float b = FMath.avg(0.0f, Float.parseFloat(vals[3]), 1.0f); + return new Color(r, g, b, a); + } else { + throw new Exception("Can not parse color ... '" + colorBase + "'"); + } + } + color = color.replace("rgb", ""); + color = color.replace("rgba", ""); + final String[] vals = color.split(","); + if (vals.length == 3) { + final float r = FMath.avg(0.0f, Float.parseFloat(vals[0]), 1.0f); + final float g = FMath.avg(0.0f, Float.parseFloat(vals[1]), 1.0f); + final float b = FMath.avg(0.0f, Float.parseFloat(vals[2]), 1.0f); + return new Color(r, g, b); + } else if (vals.length == 4) { + final float r = FMath.avg(0.0f, Float.parseFloat(vals[0]), 1.0f); + final float g = FMath.avg(0.0f, Float.parseFloat(vals[1]), 1.0f); + final float b = FMath.avg(0.0f, Float.parseFloat(vals[2]), 1.0f); + final float a = FMath.avg(0.0f, Float.parseFloat(vals[3]), 1.0f); + return new Color(r, g, b, a); + } else { + throw new Exception("Can not parse color ... '" + colorBase + "'"); + } + } + } + public float r; public float g; public float b; public float a; - public Color(float r, float g, float b, float a) { - this.r = r; - this.g = g; - this.b = b; - this.a = a; - } - public Color(float r, float g, float b) { + + public Color(final float r, final float g, final float b) { super(); this.r = r; this.g = g; this.b = b; this.a = 1.0f; } + + public Color(final float r, final float g, final float b, final float a) { + this.r = r; + this.g = g; + this.b = b; + this.a = a; + } + + @Override + public Color clone() { + return new Color(this.r, this.g, this.b, this.a); + } + + @Override + public boolean equals(final Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof Color)) { + return false; + } + final Color other = (Color) obj; + return other.r == this.r && other.g == this.g && other.b == this.b && other.a == this.a; + } + + @Override + public String toString() { + return "rgba(" + this.r + ", " + this.g + ", " + this.b + ", " + this.a + ")"; + } + } diff --git a/src/org/atriasoft/etk/Uri.java b/src/org/atriasoft/etk/Uri.java index 4f6a12e..b5cd497 100644 --- a/src/org/atriasoft/etk/Uri.java +++ b/src/org/atriasoft/etk/Uri.java @@ -1,39 +1,197 @@ package org.atriasoft.etk; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; +import org.atriasoft.etk.internal.Log; + public class Uri { - private static Map genericMap = new HashMap(); + private static Map genericMap = new HashMap<>(); + private static Map> libraries = new HashMap<>(); + private static Class applicationClass = null; - public static void setGroup(String groupName, String basePath) { + static { + genericMap.put("DATA", ""); + genericMap.put("THEME_GUI", "theme/"); + } + + public static void addLibrary(final String libName, final Class classHandle) { + libraries.put(libName.toLowerCase(), classHandle); + } + + public static byte[] getAllData(final Uri resourceName) { + final InputStream out = getStream(resourceName); + if (out == null) { + return null; + } + byte[] data = null; + try { + data = out.readAllBytes(); + } catch (final IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return data; + } + + /* + public static Stream getResources(final URL element) { + try { + final URI uri = element.toURI(); + FileSystem fs; + Path path; + if (uri.getScheme().contentEquals("jar")) { + try { + fs = FileSystems.getFileSystem(uri); + } catch (final FileSystemNotFoundException e) { + fs = FileSystems.newFileSystem(uri, Collections. emptyMap()); + } + String pathInJar = "/"; + final String tmpPath = element.getPath(); + final int idSeparate = tmpPath.indexOf('!'); + if (idSeparate != -1) { + pathInJar = tmpPath.substring(idSeparate + 1); + while (pathInJar.startsWith("/")) { + pathInJar = pathInJar.substring(1); + } + } + path = fs.getPath(pathInJar); + } else { + fs = FileSystems.getDefault(); + path = Paths.get(uri); + } + return Files.walk(path, 1); + } catch (URISyntaxException | IOException e) { + e.printStackTrace(); + return Stream.of(); + } + } + */ + public static InputStream getStream(final Uri resourceName) { + Log.verbose("Load resource: " + resourceName); + String offset = ""; + if (resourceName.group != null) { + final String ret = genericMap.get(resourceName.group); + if (ret != null) { + offset = ret; + } + } + InputStream out = null; + if (applicationClass == null) { + Log.warning("Application data class is not defined ..."); + } else { + out = applicationClass.getResourceAsStream("/data/" + offset + resourceName.path); + } + if (out != null) { + // search in the libraries ... + if (resourceName.lib == null) { + return null; + } else { + final Class libClass = libraries.get(resourceName.lib); + if (libClass == null) { + return null; + } + out = libClass.getResourceAsStream("/data/" + offset + resourceName.path); + } + } + if (out == null) { + Log.error("Can not load resource: '" + resourceName + "'"); + } + return out; + } + + public static List listRecursive(final Uri uri) { + final List out = new ArrayList<>(); + return out; + } + + public static void setApplication(final Class classHandle) { + applicationClass = classHandle; + } + + public static void setGroup(final String groupName, final String basePath) { genericMap.put(groupName.toUpperCase(), basePath); } - private final String value; + private final String group; + + private final String path; + + private final String lib; + + // Format : DATA:jlfqkjsdflkjqs/sqldkhjflqksdjf/lll.png?lib=ewol public Uri(String value) { - this.value = value; + if (value.contains(":") == true) { + final String[] ret = value.split(":", 2); + this.group = ret[0].toUpperCase(); + ; + value = ret[1]; + } else { + this.group = "DATA"; + } + if (value.contains("?lib=") == true) { + final String[] ret = value.split("?lib=", 2); + this.path = ret[0]; + this.lib = ret[1].toLowerCase(); + } else { + this.path = value; + this.lib = null; + } } - public Uri(String group, String path) { - this.value = group.toUpperCase() + ":" + path; - } - - public String getValue() { - return value; + public Uri(final String group, final String path) { + this(group, path, null); } - public String getPath() { - String[] ret = value.split(":",2); - return genericMap.get(ret[0]) + "/" + ret[1]; + public Uri(final String group, final String path, final String lib) { + if (group == null) { + this.group = null; + } else { + this.group = group.toUpperCase(); + } + this.path = path; + if (lib == null) { + this.lib = null; + } else { + this.lib = lib.toLowerCase(); + } } + public String get() { return getPath(); } - - @Override - public String toString() { - return "Uri [value=" + value + "]"; + + public String getExtention() { + final String[] ret = this.path.split("."); + return ret[ret.length - 1]; } + public String getPath() { + return this.path; + } + + public String getValue() { + return toString(); + } + + public boolean isEmpty() { + return this.path == null || this.path.isEmpty(); + } + + @Override + public String toString() { + String out = ""; + if (this.group != null) { + out += this.group + ":"; + } + out += this.path; + if (this.lib != null) { + out += "?lib=" + this.lib; + } + return out; + } } diff --git a/src/org/atriasoft/etk/internal/Log.java b/src/org/atriasoft/etk/internal/Log.java index 65d29ef..747d8e8 100644 --- a/src/org/atriasoft/etk/internal/Log.java +++ b/src/org/atriasoft/etk/internal/Log.java @@ -3,7 +3,7 @@ package org.atriasoft.etk.internal; import io.scenarium.logger.LogLevel; import io.scenarium.logger.Logger; -class Log { +public class Log { private static final String LIB_NAME = "etk"; private static final String LIB_NAME_DRAW = Logger.getDrawableName(LIB_NAME); private static final boolean PRINT_CRITICAL = Logger.getNeedPrint(LIB_NAME, LogLevel.CRITICAL); @@ -14,47 +14,55 @@ class Log { private static final boolean PRINT_VERBOSE = Logger.getNeedPrint(LIB_NAME, LogLevel.VERBOSE); private static final boolean PRINT_TODO = Logger.getNeedPrint(LIB_NAME, LogLevel.TODO); private static final boolean PRINT_PRINT = Logger.getNeedPrint(LIB_NAME, LogLevel.PRINT); - - private Log() {} - - public static void print(String data) { - if (PRINT_PRINT) - Logger.print(LIB_NAME_DRAW, data); - } - - public static void todo(String data) { - if (PRINT_TODO) - Logger.todo(LIB_NAME_DRAW, data); - } - - public static void critical(String data) { - if (PRINT_CRITICAL) + + public static void critical(final String data) { + if (PRINT_CRITICAL) { Logger.critical(LIB_NAME_DRAW, data); + } } - - public static void error(String data) { - if (PRINT_ERROR) - Logger.error(LIB_NAME_DRAW, data); - } - - public static void warning(String data) { - if (PRINT_WARNING) - Logger.warning(LIB_NAME_DRAW, data); - } - - public static void info(String data) { - if (PRINT_INFO) - Logger.info(LIB_NAME_DRAW, data); - } - - public static void debug(String data) { - if (PRINT_DEBUG) + + public static void debug(final String data) { + if (PRINT_DEBUG) { Logger.debug(LIB_NAME_DRAW, data); + } } - - public static void verbose(String data) { - if (PRINT_VERBOSE) + + public static void error(final String data) { + 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); + } + } + + public static void print(final String data) { + if (PRINT_PRINT) { + Logger.print(LIB_NAME_DRAW, data); + } + } + + public static void todo(final String data) { + if (PRINT_TODO) { + Logger.todo(LIB_NAME_DRAW, data); + } + } + + public static void verbose(final String data) { + if (PRINT_VERBOSE) { Logger.verbose(LIB_NAME_DRAW, data); + } } - + + public static void warning(final String data) { + if (PRINT_WARNING) { + Logger.warning(LIB_NAME_DRAW, data); + } + } + + private Log() {} + } diff --git a/src/org/atriasoft/etk/math/Constant.java b/src/org/atriasoft/etk/math/Constant.java index 839ca8c..6f4a1f4 100644 --- a/src/org/atriasoft/etk/math/Constant.java +++ b/src/org/atriasoft/etk/math/Constant.java @@ -5,6 +5,8 @@ public class Constant { private Constant() { } + // Machine epsilon + public static final float FLOAT_EPSILON = 0.0000001192f; // Machine epsilon public static final float MACHINE_EPSILON = 0.000001f; // Pi constant diff --git a/src/org/atriasoft/etk/math/FMath.java b/src/org/atriasoft/etk/math/FMath.java index 325ff01..580a1a3 100644 --- a/src/org/atriasoft/etk/math/FMath.java +++ b/src/org/atriasoft/etk/math/FMath.java @@ -1,5 +1,7 @@ package org.atriasoft.etk.math; +import java.text.DecimalFormat; + public class FMath { public static float abs(final float a) { if (a < 0.0f) { @@ -15,7 +17,7 @@ public class FMath { * @return true if it is in the range */ public static boolean approxEqual(final float a, final float b) { - return approxEqual(a, b, Constant.MACHINE_EPSILON); + return approxEqual(a, b, Constant.FLOAT_EPSILON); } /** @@ -57,6 +59,10 @@ public class FMath { return FMath.min(FMath.max(value, lowerLimit), upperLimit); } + public static String floatToString(final float value) { + return new DecimalFormat("#0.0000000000").format(value); + } + // TODO check this basic function ... public static int floor(final float f) { return (int) Math.floor(f); diff --git a/src/org/atriasoft/etk/math/Matrix3f.java b/src/org/atriasoft/etk/math/Matrix3f.java index 71c3834..b207830 100644 --- a/src/org/atriasoft/etk/math/Matrix3f.java +++ b/src/org/atriasoft/etk/math/Matrix3f.java @@ -192,6 +192,23 @@ public class Matrix3f { + this.mat[2] * (this.mat[3] * this.mat[7] - this.mat[6] * this.mat[4]); } + /** + * @brief devide a value + * @param value value to devide all the matrix + */ + public Matrix3f devide(final float value) { + this.mat[0] /= value; + this.mat[1] /= value; + this.mat[2] /= value; + this.mat[3] /= value; + this.mat[4] /= value; + this.mat[5] /= value; + this.mat[6] /= value; + this.mat[7] /= value; + this.mat[8] /= value; + return this; + } + @Override public boolean equals(final Object obj) { if (obj == null) { @@ -280,11 +297,10 @@ public class Matrix3f { public Matrix3f inverse() { final float det = determinant(); //assert(Math.abs(det) > MACHINEEPSILON); - final float invDet = 1.0f / det; this.set((this.mat[4] * this.mat[8] - this.mat[7] * this.mat[5]), -(this.mat[1] * this.mat[8] - this.mat[7] * this.mat[2]), (this.mat[1] * this.mat[5] - this.mat[2] * this.mat[4]), -(this.mat[3] * this.mat[8] - this.mat[6] * this.mat[5]), (this.mat[0] * this.mat[8] - this.mat[6] * this.mat[2]), -(this.mat[0] * this.mat[5] - this.mat[3] * this.mat[2]), (this.mat[3] * this.mat[7] - this.mat[6] * this.mat[4]), -(this.mat[0] * this.mat[7] - this.mat[6] * this.mat[1]), (this.mat[0] * this.mat[4] - this.mat[1] * this.mat[3])); - this.multiply(invDet); + devide(det); return this; } @@ -538,8 +554,9 @@ public class Matrix3f { @Override public String toString() { - return "Matrix3f(" + this.mat[0] + "," + this.mat[1] + "," + this.mat[2] + "," + this.mat[3] + "," + this.mat[4] + "," + this.mat[5] + "," + this.mat[6] + "," + this.mat[7] + "," + this.mat[8] - + ")"; + return "Matrix3f(" + FMath.floatToString(this.mat[0]) + "," + FMath.floatToString(this.mat[1]) + "," + FMath.floatToString(this.mat[2]) + "," + FMath.floatToString(this.mat[3]) + "," + + FMath.floatToString(this.mat[4]) + "," + FMath.floatToString(this.mat[5]) + "," + FMath.floatToString(this.mat[6]) + "," + FMath.floatToString(this.mat[7]) + "," + + FMath.floatToString(this.mat[8]) + ")"; } /** diff --git a/src/org/atriasoft/etk/math/Matrix4f.java b/src/org/atriasoft/etk/math/Matrix4f.java index 9974e7f..ffa08db 100644 --- a/src/org/atriasoft/etk/math/Matrix4f.java +++ b/src/org/atriasoft/etk/math/Matrix4f.java @@ -349,23 +349,22 @@ public class Matrix4f { return clone(); } final Matrix4f temp = new Matrix4f(); - final float iDet = 1.0f / det; - temp.mat[0] = coFactor(0, 0) * iDet; - temp.mat[1] = coFactor(0, 1) * iDet; - temp.mat[2] = coFactor(0, 2) * iDet; - temp.mat[3] = coFactor(0, 3) * iDet; - temp.mat[4] = coFactor(1, 0) * iDet; - temp.mat[5] = coFactor(1, 1) * iDet; - temp.mat[6] = coFactor(1, 2) * iDet; - temp.mat[7] = coFactor(1, 3) * iDet; - temp.mat[8] = coFactor(2, 0) * iDet; - temp.mat[9] = coFactor(2, 1) * iDet; - temp.mat[10] = coFactor(2, 2) * iDet; - temp.mat[11] = coFactor(2, 3) * iDet; - temp.mat[12] = coFactor(3, 0) * iDet; - temp.mat[13] = coFactor(3, 1) * iDet; - temp.mat[14] = coFactor(3, 2) * iDet; - temp.mat[15] = coFactor(3, 3) * iDet; + temp.mat[0] = coFactor(0, 0) / det; + temp.mat[1] = coFactor(0, 1) / det; + temp.mat[2] = coFactor(0, 2) / det; + temp.mat[3] = coFactor(0, 3) / det; + temp.mat[4] = coFactor(1, 0) / det; + temp.mat[5] = coFactor(1, 1) / det; + temp.mat[6] = coFactor(1, 2) / det; + temp.mat[7] = coFactor(1, 3) / det; + temp.mat[8] = coFactor(2, 0) / det; + temp.mat[9] = coFactor(2, 1) / det; + temp.mat[10] = coFactor(2, 2) / det; + temp.mat[11] = coFactor(2, 3) / det; + temp.mat[12] = coFactor(3, 0) / det; + temp.mat[13] = coFactor(3, 1) / det; + temp.mat[14] = coFactor(3, 2) / det; + temp.mat[15] = coFactor(3, 3) / det; return temp; } diff --git a/src/org/atriasoft/etk/math/Quaternion.java b/src/org/atriasoft/etk/math/Quaternion.java index cad38c9..c5c80e8 100644 --- a/src/org/atriasoft/etk/math/Quaternion.java +++ b/src/org/atriasoft/etk/math/Quaternion.java @@ -515,11 +515,19 @@ public class Quaternion { this.w = 1.0f; return this; } - final float invLength = 1.0f / lengthTmp; - this.x *= invLength; - this.y *= invLength; - this.z *= invLength; - this.w *= invLength; + + final double invLength = 1.0 / lengthTmp; + this.x = (float) (this.x * invLength); + this.y = (float) (this.y * invLength); + this.z = (float) (this.z * invLength); + this.w = (float) (this.w * invLength); + + /* + this.x /= lengthTmp; + this.y /= lengthTmp; + this.z /= lengthTmp; + this.w /= lengthTmp; + */ return this; } @@ -705,6 +713,6 @@ public class Quaternion { @Override public String toString() { - return "Quaternion(" + this.x + "," + this.y + "," + this.z + "," + this.w + ")"; + return "Quaternion(" + FMath.floatToString(this.x) + "," + FMath.floatToString(this.y) + "," + FMath.floatToString(this.z) + "," + FMath.floatToString(this.w) + ")"; } } diff --git a/src/org/atriasoft/etk/math/Vector2b.java b/src/org/atriasoft/etk/math/Vector2b.java new file mode 100644 index 0000000..36a7515 --- /dev/null +++ b/src/org/atriasoft/etk/math/Vector2b.java @@ -0,0 +1,174 @@ +package org.atriasoft.etk.math; + +import org.atriasoft.etk.internal.Log; + +public class Vector2b { + public static Vector2b valueOf(String value) { + boolean val1 = false; + boolean val2 = false; + // copy to permit to modify it : + while (value.length() > 0 && value.charAt(0) == '(') { + value = value.substring(1); + } + while (value.length() > 0 && value.charAt(0) == ')') { + value = value.substring(0, value.length() - 1); + } + final String[] values = value.split(","); + if (values.length > 2) { + Log.error("Can not parse Vector2f with more than 2 values: '" + value + "'"); + } + if (values.length == 1) { + // no coma ... + // in every case, we parse the first element : + val1 = Boolean.valueOf(values[0]); + val2 = val1; + } else { + val1 = Boolean.valueOf(values[0]); + val2 = Boolean.valueOf(values[1]); + } + return new Vector2b(val1, val2); + } + + public boolean x = false; + public boolean y = false; + + /* **************************************************** + * Constructor + *****************************************************/ + public Vector2b() { + this.x = false; + this.y = false; + } + + /** + * @brief Constructor from scalars + * @param xxx X value + * @param yyy Y value + */ + public Vector2b(final boolean xxx, final boolean yyy) { + this.x = xxx; + this.y = yyy; + } + + /** + * @brief Constructor with external vector + * @param obj The vector to add to this one + */ + public Vector2b(final Vector2b obj) { + this.x = obj.x; + this.y = obj.y; + } + + @Override + public Vector2b clone() { + return new Vector2b(this.x, this.y); + } + + /** + * @brief Get X value + * @return the x value + */ + public boolean getX() { + return this.x; + } + + /** + * @brief Get Y value + * @return the y value + */ + public boolean getY() { + return this.y; + } + + /** + * @brief In-Equality compare operator with an other object. + * @param obj Reference on the comparing object + * @return true The Objects are NOT identical + * @return false The Objects are identical + */ + public boolean isDifferent(final Vector2b obj) { + return (obj.x != this.x || obj.y != this.y); + } + + /** + * @brief Equality compare operator with an other object. + * @param obj Reference on the comparing object + * @return true The Objects are identical + * @return false The Objects are NOT identical + */ + public boolean isEqual(final Vector2b obj) { + return (obj.x == this.x && obj.y == this.y); + } + + /** + * @brief Operator= Asign the current object with a value + * @param val Value to assign on the object + */ + public void set(final boolean val) { + this.x = val; + this.y = val; + }; + + /** + * @brief Operator= Asign the current object with a value + * @param xxx X value + * @param yyy Y value + */ + public void set(final boolean xxx, final boolean yyy) { + this.x = xxx; + this.y = yyy; + } + + /** + * @brief Operator= Asign the current object with an other object + * @param obj Reference on the external object + */ + public void set(final Vector2b obj) { + this.x = obj.x; + this.y = obj.y; + } + + public void setFalse() { + this.x = false; + this.y = false; + } + + /** + * @brief Set 0 value on all the vector + */ + public void setTrue() { + this.x = true; + this.y = true; + } + + /** + * @brief Set Value on the vector + * @param xxx X value. + * @param yyy Y value. + */ + public void setValue(final boolean xxx, final boolean yyy) { + this.x = xxx; + this.y = yyy; + } + + /** + * @brief Set the x value + * @param xxx New value + */ + public void setX(final boolean xxx) { + this.x = xxx; + } + + /** + * @brief Set the y value + * @param yyy New value + */ + public void setY(final boolean yyy) { + this.y = yyy; + } + + @Override + public String toString() { + return "(" + this.x + "," + this.y + ")"; + } +} diff --git a/src/org/atriasoft/etk/math/Vector2f.java b/src/org/atriasoft/etk/math/Vector2f.java index 59b2fb3..aab6d66 100644 --- a/src/org/atriasoft/etk/math/Vector2f.java +++ b/src/org/atriasoft/etk/math/Vector2f.java @@ -1,11 +1,40 @@ package org.atriasoft.etk.math; +import org.atriasoft.etk.internal.Log; + public class Vector2f { + public static Vector2f valueOf(String value) { + float val1 = 0; + float val2 = 0; + // copy to permit to modify it : + while (value.length() > 0 && value.charAt(0) == '(') { + value = value.substring(1); + } + while (value.length() > 0 && value.charAt(0) == ')') { + value = value.substring(0, value.length() - 1); + } + final String[] values = value.split(","); + if (values.length > 2) { + Log.error("Can not parse Vector2f with more than 2 values: '" + value + "'"); + } + if (values.length == 1) { + // no coma ... + // in every case, we parse the first element : + val1 = Float.valueOf(values[0]); + val2 = val1; + } else { + val1 = Float.valueOf(values[0]); + val2 = Float.valueOf(values[1]); + } + return new Vector2f(val1, val2); + } + public static Vector2f zero() { return new Vector2f(0, 0); } public float x = 0; + public float y = 0; /* **************************************************** @@ -69,6 +98,14 @@ public class Vector2f { return this; } + public Vector2f addNew(final float val) { + return new Vector2f(this.x + val, this.y + val); + } + + public Vector2f addNew(final Vector2f obj) { + return new Vector2f(this.x + obj.x, this.y + obj.y); + } + @Override public Vector2f clone() { return new Vector2f(this); @@ -120,6 +157,14 @@ public class Vector2f { return this; } + public Vector2f devideNew(final float val) { + return new Vector2f(this.x / val, this.y / val); + } + + public Vector2f devideNew(final Vector2f obj) { + return new Vector2f(this.x / obj.x, this.y / obj.y); + } + /** * @brief Return the distance between the ends of this and another vector * This is semantically treating the vector like a point @@ -163,10 +208,10 @@ public class Vector2f { // cast object final Vector2f other = (Vector2f) obj; // checks values - if (Float.floatToIntBits(this.x) != Float.floatToIntBits(other.x)) { + if (this.x != other.x) { return false; } - return Float.floatToIntBits(this.y) == Float.floatToIntBits(other.y); + return this.y == other.y; } /** @@ -320,6 +365,14 @@ public class Vector2f { return this; } + public Vector2f lessNew(final float val) { + return new Vector2f(this.x - val, this.y - val); + } + + public Vector2f lessNew(final Vector2f obj) { + return new Vector2f(this.x - obj.x, this.y - obj.y); + } + /** * @brief Return the axis with the largest value * @return values are 0,1 for x or y @@ -354,19 +407,23 @@ public class Vector2f { this.x *= obj.x; this.y *= obj.y; return this; - } + }; public Vector2f multiplyNew(final float val) { return new Vector2f(this.x * val, this.y * val); }; + public Vector2f multiplyNew(final Vector2f obj) { + return new Vector2f(this.x * obj.x, this.y * obj.y); + }; + /** * @brief Normalize this vector x^2 + y^2 = 1 */ public Vector2f normalize() { this.devide(length()); return this; - }; + } /** * @brief Return a normalized version of this vector @@ -489,7 +546,7 @@ public class Vector2f { @Override public String toString() { - return "Vector2f(" + this.x + "," + this.y + ")"; + return "(" + this.x + "," + this.y + ")"; } } diff --git a/src/org/atriasoft/etk/math/Vector2i.java b/src/org/atriasoft/etk/math/Vector2i.java index 35e8a10..5ef3d01 100644 --- a/src/org/atriasoft/etk/math/Vector2i.java +++ b/src/org/atriasoft/etk/math/Vector2i.java @@ -1,8 +1,37 @@ package org.atriasoft.etk.math; +import org.atriasoft.etk.internal.Log; + public class Vector2i { + public static Vector2i valueOf(String value) { + int val1 = 0; + int val2 = 0; + // copy to permit to modify it : + while (value.length() > 0 && value.charAt(0) == '(') { + value = value.substring(1); + } + while (value.length() > 0 && value.charAt(0) == ')') { + value = value.substring(0, value.length() - 1); + } + final String[] values = value.split(","); + if (values.length > 2) { + Log.error("Can not parse Vector2f with more than 2 values: '" + value + "'"); + } + if (values.length == 1) { + // no coma ... + // in every case, we parse the first element : + val1 = Integer.valueOf(values[0]); + val2 = val1; + } else { + val1 = Integer.valueOf(values[0]); + val2 = Integer.valueOf(values[1]); + } + return new Vector2i(val1, val2); + } + public int x = 0; public int y = 0; + /* **************************************************** * Constructor *****************************************************/ @@ -10,271 +39,67 @@ public class Vector2i { this.x = 0; this.y = 0; } + /** * @brief Constructor from scalars * @param xxx X value * @param yyy Y value */ - public Vector2i(int xxx, int yyy) { + public Vector2i(final int xxx, final int yyy) { this.x = xxx; this.y = yyy; } + /** * @brief Constructor with external vector * @param obj The vector to add to this one */ - public Vector2i(Vector2i obj) { + public Vector2i(final Vector2i obj) { this.x = obj.x; this.y = obj.y; } - /** - * @brief Operator= Asign the current object with an other object - * @param obj Reference on the external object - */ - public void set(Vector2i obj) { - this.x = obj.x; - this.y = obj.y; - } - /** - * @brief Operator= Asign the current object with a value - * @param val Value to assign on the object - */ - public void set(int val) { - this.x = val; - this.y = val; - } - /** - * @brief Operator= Asign the current object with a value - * @param xxx X value - * @param yyy Y value - */ - public void set(int xxx, int yyy) { - this.x = xxx; - this.y = yyy; - } - /** - * @brief Equality compare operator with an other object. - * @param obj Reference on the comparing object - * @return true The Objects are identical - * @return false The Objects are NOT identical - */ - public boolean isEqual(Vector2i obj) { - return ( obj.x == this.x - && obj.y == this.y); - } - /** - * @brief In-Equality compare operator with an other object. - * @param obj Reference on the comparing object - * @return true The Objects are NOT identical - * @return false The Objects are identical - */ - public boolean isDifferent(Vector2i obj) { - return ( obj.x != this.x - || obj.y != this.y); - } - public boolean isLowerOrEqual(Vector2i obj) { - return ( this.x <= obj.x - && this.y <= obj.y); - } - public boolean isLower(Vector2i obj) { - return ( this.x < obj.x - && this.y < obj.y); - } - public boolean isGreaterOrEqual(Vector2i obj) { - return ( this.x >= obj.x - && this.y >= obj.y); - } - public boolean isGreater(Vector2i obj) { - return ( this.x > obj.x - && this.y > obj.y); - } - /** - * @brief Operator+= Addition an other vertor with this one - * @param obj Reference on the external object - */ - void add(Vector2i obj) { - this.x += obj.x; - this.y += obj.y; - } - /** - * @brief Operator+= Addition an other vertor with this one - * @param val Value to addition at x/y - */ - public void add(int val) { - this.x += val; - this.y += val; - } - /** - * @brief Operator-= Decrement an other vertor with this one - * @param obj Reference on the external object - */ - public void less(Vector2i obj) { - this.x -= obj.x; - this.y -= obj.y; - } - /** - * @brief Operator-= Decrement an other vertor with this one - * @param val Value to addition at x/y - */ - public void less(int val) { - this.x -= val; - this.y -= val; - } - /** - * @brief Operator*= Multiplication an other vertor with this one - * @param obj Reference on the external object - */ - public void multiply(Vector2i obj) { - this.x *= obj.x; - this.y *= obj.y; - } - /** - * @brief Operator*= Multiplication an other vertor with this one - * @param val Value to addition at x/y - */ - public void multiply(int val) { - this.x *= val; - this.y *= val; - } - /** - * @brief Operator/ Dividing an other vertor with this one - * @param obj Reference on the external object - */ - public void devide(Vector2i obj) { - this.x /= obj.x; - this.y /= obj.y; - } - /** - * @brief Operator/ Dividing an other vertor with this one - * @param val Value to addition at x/y - */ - public void devide(int val) { - this.x /= val; - this.y /= val; - } - /** - * @brief Incrementation of this vector (+1 of 2 elements) - */ - public void increment() { - this.x++; - this.y++; - } - /** - * @brief Decrementation of this vector (-1 of 2 elements) - */ - public void decrement() { - this.x--; - this.y--; - } - /** - * @brief Return the cross product / determinant - * @param obj The other vector in the cross product - * @return cross product value - */ - public int cross(Vector2i obj) { - return this.x * obj.y - - this.y * obj.x; - } - /** - * @brief Return the dot product - * @param obj The other vector in the dot product - * @return Dot product value - */ - public int dot(Vector2i obj) { - return this.x * obj.x - + this.y * obj.y; - } - /** - * @brief Get the length of the vector squared - * @return Squared length value. - */ - public int length2() { - return dot(this); - } - /** - * @brief Get the length of the vector - * @return Length value - */ - public int length() { - return (int) Math.sqrt(length2()); - } - /** - * @brief Return the distance squared between the ends of this and another vector - * This is symantically treating the vector like a point - * @param obj The other vector to compare distance - * @return the square distance of the 2 points - */ - public int distance2(Vector2i obj) { - int deltaX = obj.x - this.x; - int deltaY = obj.y - this.y; - return deltaX*deltaX + deltaY*deltaY; - } - /** - * @brief Return the distance between the ends of this and another vector - * This is symantically treating the vector like a point - * @param obj The other vector to compare distance - * @return the distance of the 2 points - */ - public int distance(Vector2i obj) { - return (int)Math.sqrt(this.distance2(obj)); - } - /** - * @brief Normalize this vector x^2 + y^2 = 1 - */ - public void normalize() { - this.devide(length()); - } - /** - * @brief Normalize this vector x^2 + y^2 = 1 (check if not deviding by 0, if it is the case ==> return (1,0)) - * @return Local reference of the vector normalized - */ - public void safeNormalize() { - int tmp = length(); - if (tmp != 0) { - this.devide(length()); - return; - } - setValue(1,0); - return; - } - /** - * @brief Return a normalized version of this vector - * @return New vector containing the value - */ - public Vector2i normalized() { - Vector2i tmp = this.clone(); - tmp.normalize(); - return tmp; - } + /** * @brief Return a vector will the absolute values of each element * @return New vector containing the value */ public Vector2i absolute() { - return new Vector2i( Math.abs(this.x), - Math.abs(this.y)); + return new Vector2i(Math.abs(this.x), Math.abs(this.y)); } + /** - * @brief Return the axis with the smallest value - * @return values are 0,1 for x or y + * @brief Operator+= Addition an other vertor with this one + * @param val Value to addition at x/y */ - public int minAxis() { - return this.x < this.y ? 0 : 1; + public Vector2i add(final int val) { + this.x += val; + this.y += val; + return this; } + /** - * @brief Return the axis with the largest value - * @return values are 0,1 for x or y + * @brief Operator+= Addition an other vertor with this one + * @param obj Reference on the external object */ - public int maxAxis() { - return this.x < this.y ? 1 : 0; + public Vector2i add(final Vector2i obj) { + this.x += obj.x; + this.y += obj.y; + return this; } - /** - * @brief Return the axis with the smallest ABSOLUTE value - * @return values 0,1 for x, or z - */ - public int furthestAxis() { - return absolute().minAxis(); + + public Vector2i addNew(final int val) { + return new Vector2i(this.x + val, this.y + val); } + + public Vector2i addNew(final Vector2i obj) { + return new Vector2i(this.x + obj.x, this.y + obj.y); + } + + @Override + public Vector2i clone() { + return new Vector2i(this); + } + /** * @brief Return the axis with the largest ABSOLUTE value * @return values 0,1 for x or y @@ -282,20 +107,89 @@ public class Vector2i { public int closestAxis() { return absolute().maxAxis(); } + /** - * @brief Set the x value - * @param xxx New value + * @brief Return the cross product / determinant + * @param obj The other vector in the cross product + * @return cross product value */ - public void setX(int xxx) { - this.x = xxx; - }; + public int cross(final Vector2i obj) { + return this.x * obj.y - this.y * obj.x; + } + /** - * @brief Set the y value - * @param yyy New value + * @brief Decrementation of this vector (-1 of 2 elements) */ - public void setY(int yyy) { - this.y = yyy; - }; + public void decrement() { + this.x--; + this.y--; + } + + /** + * @brief Operator/ Dividing an other vertor with this one + * @param val Value to addition at x/y + */ + public void devide(final int val) { + this.x /= val; + this.y /= val; + } + + /** + * @brief Operator/ Dividing an other vertor with this one + * @param obj Reference on the external object + */ + public void devide(final Vector2i obj) { + this.x /= obj.x; + this.y /= obj.y; + } + + public Vector2i devideNew(final int val) { + return new Vector2i(this.x / val, this.y / val); + } + + public Vector2i devideNew(final Vector2i obj) { + return new Vector2i(this.x / obj.x, this.y / obj.y); + } + + /** + * @brief Return the distance between the ends of this and another vector + * This is symantically treating the vector like a point + * @param obj The other vector to compare distance + * @return the distance of the 2 points + */ + public int distance(final Vector2i obj) { + return (int) Math.sqrt(distance2(obj)); + } + + /** + * @brief Return the distance squared between the ends of this and another vector + * This is symantically treating the vector like a point + * @param obj The other vector to compare distance + * @return the square distance of the 2 points + */ + public int distance2(final Vector2i obj) { + final int deltaX = obj.x - this.x; + final int deltaY = obj.y - this.y; + return deltaX * deltaX + deltaY * deltaY; + } + + /** + * @brief Return the dot product + * @param obj The other vector in the dot product + * @return Dot product value + */ + public int dot(final Vector2i obj) { + return this.x * obj.x + this.y * obj.y; + } + + /** + * @brief Return the axis with the smallest ABSOLUTE value + * @return values 0,1 for x, or z + */ + public int furthestAxis() { + return absolute().minAxis(); + } + /** * @brief Get X value * @return the x value @@ -303,6 +197,7 @@ public class Vector2i { public int getX() { return this.x; } + /** * @brief Get Y value * @return the y value @@ -310,31 +205,257 @@ public class Vector2i { public int getY() { return this.y; } + + /** + * @brief Incrementation of this vector (+1 of 2 elements) + */ + public void increment() { + this.x++; + this.y++; + } + + /** + * @brief In-Equality compare operator with an other object. + * @param obj Reference on the comparing object + * @return true The Objects are NOT identical + * @return false The Objects are identical + */ + public boolean isDifferent(final Vector2i obj) { + return (obj.x != this.x || obj.y != this.y); + } + + /** + * @brief Equality compare operator with an other object. + * @param obj Reference on the comparing object + * @return true The Objects are identical + * @return false The Objects are NOT identical + */ + public boolean isEqual(final Vector2i obj) { + return (obj.x == this.x && obj.y == this.y); + } + + public boolean isGreater(final Vector2i obj) { + return (this.x > obj.x && this.y > obj.y); + } + + public boolean isGreaterOrEqual(final Vector2i obj) { + return (this.x >= obj.x && this.y >= obj.y); + } + + public boolean isLower(final Vector2i obj) { + return (this.x < obj.x && this.y < obj.y); + } + + public boolean isLowerOrEqual(final Vector2i obj) { + return (this.x <= obj.x && this.y <= obj.y); + } + + /** + * @brief Check if the vector is equal to (0,0) + * @return true The value is equal to (0,0) + * @return false The value is NOT equal to (0,0) + */ + public boolean isZero() { + return this.x == 0 && this.y == 0; + } + + /** + * @brief Get the length of the vector + * @return Length value + */ + public int length() { + return (int) Math.sqrt(length2()); + } + + /** + * @brief Get the length of the vector squared + * @return Squared length value. + */ + public int length2() { + return dot(this); + } + + /** + * @brief Operator-= Decrement an other vertor with this one + * @param val Value to addition at x/y + */ + public void less(final int val) { + this.x -= val; + this.y -= val; + } + + /** + * @brief Operator-= Decrement an other vertor with this one + * @param obj Reference on the external object + */ + public void less(final Vector2i obj) { + this.x -= obj.x; + this.y -= obj.y; + } + + public Vector2i lessNew(final int val) { + return new Vector2i(this.x - val, this.y - val); + } + + public Vector2i lessNew(final Vector2i obj) { + return new Vector2i(this.x - obj.x, this.y - obj.y); + } + + /** + * @brief Return the axis with the largest value + * @return values are 0,1 for x or y + */ + public int maxAxis() { + return this.x < this.y ? 1 : 0; + } + + /** + * @brief Return the axis with the smallest value + * @return values are 0,1 for x or y + */ + public int minAxis() { + return this.x < this.y ? 0 : 1; + } + + /** + * @brief Operator*= Multiplication an other vertor with this one + * @param val Value to addition at x/y + */ + public void multiply(final int val) { + this.x *= val; + this.y *= val; + } + + /** + * @brief Operator*= Multiplication an other vertor with this one + * @param obj Reference on the external object + */ + public void multiply(final Vector2i obj) { + this.x *= obj.x; + this.y *= obj.y; + } + + public Vector2i multiplyNew(final int val) { + return new Vector2i(this.x * val, this.y * val); + } + + public Vector2i multiplyNew(final Vector2i obj) { + return new Vector2i(this.x * obj.x, this.y * obj.y); + } + + /** + * @brief Normalize this vector x^2 + y^2 = 1 + */ + public void normalize() { + this.devide(length()); + } + + /** + * @brief Return a normalized version of this vector + * @return New vector containing the value + */ + public Vector2i normalized() { + final Vector2i tmp = clone(); + tmp.normalize(); + return tmp; + } + + /** + * @brief Normalize this vector x^2 + y^2 = 1 (check if not deviding by 0, if it is the case ==> return (1,0)) + * @return Local reference of the vector normalized + */ + public void safeNormalize() { + final int tmp = length(); + if (tmp != 0) { + this.devide(length()); + return; + } + setValue(1, 0); + return; + }; + + /** + * @brief Operator= Asign the current object with a value + * @param val Value to assign on the object + */ + public void set(final int val) { + this.x = val; + this.y = val; + }; + + /** + * @brief Operator= Asign the current object with a value + * @param xxx X value + * @param yyy Y value + */ + public void set(final int xxx, final int yyy) { + this.x = xxx; + this.y = yyy; + } + + /** + * @brief Operator= Asign the current object with an other object + * @param obj Reference on the external object + */ + public void set(final Vector2i obj) { + this.x = obj.x; + this.y = obj.y; + } + + public void setMax(final int xxx, final int yyy) { + this.x = Math.max(this.x, xxx); + this.y = Math.max(this.y, yyy); + } + /** * @brief Set each element to the max of the current values and the values of another vector * @param other The other vector to compare with */ - public void setMax(Vector2i other) { + public void setMax(final Vector2i other) { this.x = Math.max(this.x, other.x); this.y = Math.max(this.y, other.y); } + + public void setMin(final int xxx, final int yyy) { + this.x = Math.min(this.x, xxx); + this.y = Math.min(this.y, yyy); + } + /** * @brief Set each element to the min of the current values and the values of another vector * @param other The other vector to compare with */ - public void setMin(Vector2i other) { + public void setMin(final Vector2i other) { this.x = Math.min(this.x, other.x); this.y = Math.min(this.y, other.y); } + /** * @brief Set Value on the vector * @param xxx X value. * @param yyy Y value. */ - public void setValue(int xxx, int yyy) { + public void setValue(final int xxx, final int yyy) { this.x = xxx; this.y = yyy; } + + /** + * @brief Set the x value + * @param xxx New value + */ + public void setX(final int xxx) { + this.x = xxx; + } + + /** + * @brief Set the y value + * @param yyy New value + */ + public void setY(final int yyy) { + this.y = yyy; + } + /** * @brief Set 0 value on all the vector */ @@ -342,19 +463,7 @@ public class Vector2i { this.x = 0; this.y = 0; } - /** - * @brief Check if the vector is equal to (0,0) - * @return true The value is equal to (0,0) - * @return false The value is NOT equal to (0,0) - */ - public boolean isZero() { - return this.x == 0 - && this.y == 0; - } - public Vector2i clone() { - return new Vector2i(this); - } @Override public String toString() { return "Vector2i(" + this.x + "," + this.y + ")"; diff --git a/src/org/atriasoft/etk/math/Vector3f.java b/src/org/atriasoft/etk/math/Vector3f.java index a9973b8..b8af618 100644 --- a/src/org/atriasoft/etk/math/Vector3f.java +++ b/src/org/atriasoft/etk/math/Vector3f.java @@ -1,5 +1,7 @@ package org.atriasoft.etk.math; +import org.atriasoft.etk.internal.Log; + public class Vector3f { /** * @brief Get the length square between the 2 vectors @@ -14,12 +16,48 @@ public class Vector3f { return x * x + y * y + z * z; } + public static Vector3f valueOf(String value) { + float val1 = 0; + float val2 = 0; + float val3 = 0; + // copy to permit to modify it : + while (value.length() > 0 && value.charAt(0) == '(') { + value = value.substring(1); + } + while (value.length() > 0 && value.charAt(0) == ')') { + value = value.substring(0, value.length() - 1); + } + final String[] values = value.split(","); + if (values.length > 3) { + Log.error("Can not parse Vector3f with more than 3 values: '" + value + "'"); + } + if (values.length == 1) { + // no coma ... + // in every case, we parse the first element : + val1 = Float.valueOf(values[0]); + val2 = val1; + val3 = val1; + } else if (values.length == 1) { + // no coma ... + // in every case, we parse the first element : + val1 = Float.valueOf(values[0]); + val2 = Float.valueOf(values[1]); + val3 = val2; + } else { + val1 = Float.valueOf(values[0]); + val2 = Float.valueOf(values[1]); + val3 = Float.valueOf(values[2]); + } + return new Vector3f(val1, val2, val3); + } + public static Vector3f zero() { return new Vector3f(0, 0, 0); } public float x; public float y; + public float z; /** @@ -195,10 +233,9 @@ public class Vector3f { */ public Vector3f divide(final float val) { if (val != 0.0f) { - final float tmpVal = 1.0f / val; - this.x *= tmpVal; - this.y *= tmpVal; - this.z *= tmpVal; + this.x /= val; + this.y /= val; + this.z /= val; return this; } throw new IllegalArgumentException("divice by 0 (vector3f)"); @@ -221,8 +258,7 @@ public class Vector3f { */ public Vector3f divideNew(final float val) { if (val != 0.0f) { - final float tmpVal = 1.0f / val; - return new Vector3f(this.x * tmpVal, this.y * tmpVal, this.z * tmpVal); + return new Vector3f(this.x / val, this.y / val, this.z / val); } throw new IllegalArgumentException("divice by 0 (vector3f)"); } @@ -326,14 +362,14 @@ public class Vector3f { final Vector3f vectorAbs = new Vector3f(Math.abs(this.x), Math.abs(this.y), Math.abs(this.z)); final int minElement = vectorAbs.getMinAxis(); if (minElement == 0) { - final float devider = 1.0f / (float) Math.sqrt(this.y * this.y + this.z * this.z); - return new Vector3f(0.0f, -this.z * devider, this.y * devider); + final float devider = (float) Math.sqrt(this.y * this.y + this.z * this.z); + return new Vector3f(0.0f, -this.z / devider, this.y / devider); } else if (minElement == 1) { - final float devider = 1.0f / (float) Math.sqrt(this.x * this.x + this.z * this.z); - return new Vector3f(-this.z * devider, 0.0f, this.x * devider); + final float devider = (float) Math.sqrt(this.x * this.x + this.z * this.z); + return new Vector3f(-this.z / devider, 0.0f, this.x / devider); } - final float devider = 1.0f / (float) Math.sqrt(this.x * this.x + this.y * this.y); - return new Vector3f(-this.y * devider, this.x * devider, 0.0f); + 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); } /** @@ -726,7 +762,7 @@ public class Vector3f { @Override public String toString() { - return "Vector3f(" + this.x + "," + this.y + "," + this.z + ")"; + return "Vector3f(" + FMath.floatToString(this.x) + "," + FMath.floatToString(this.y) + "," + FMath.floatToString(this.z) + ")"; } /** diff --git a/src/org/atriasoft/etk/math/Vector3i.java b/src/org/atriasoft/etk/math/Vector3i.java index bfb9b00..f86c824 100644 --- a/src/org/atriasoft/etk/math/Vector3i.java +++ b/src/org/atriasoft/etk/math/Vector3i.java @@ -1,210 +1,88 @@ package org.atriasoft.etk.math; +import org.atriasoft.etk.internal.Log; + public class Vector3i { + public static Vector3i valueOf(String value) { + int val1 = 0; + int val2 = 0; + int val3 = 0; + // copy to permit to modify it : + while (value.length() > 0 && value.charAt(0) == '(') { + value = value.substring(1); + } + while (value.length() > 0 && value.charAt(0) == ')') { + value = value.substring(0, value.length() - 1); + } + final String[] values = value.split(","); + if (values.length > 3) { + Log.error("Can not parse Vector3f with more than 3 values: '" + value + "'"); + } + if (values.length == 1) { + // no coma ... + // in every case, we parse the first element : + val1 = Integer.valueOf(values[0]); + val2 = val1; + val3 = val1; + } else if (values.length == 1) { + // no coma ... + // in every case, we parse the first element : + val1 = Integer.valueOf(values[0]); + val2 = Integer.valueOf(values[1]); + val3 = val2; + } else { + val1 = Integer.valueOf(values[0]); + val2 = Integer.valueOf(values[1]); + val3 = Integer.valueOf(values[2]); + } + return new Vector3i(val1, val2, val3); + } + + public static Vector3i zero() { + return new Vector3i(0, 0, 0); + } + public int x = 0; public int y = 0; public int z = 0; + /** - * @brief Default contructor + * @brief Default constructor */ - public Vector3i() { + public Vector3i() {} + + /** + * @brief Constructor from scalars + * @param value unique value for X,Y and Z value + */ + public Vector3i(final int value) { + this.x = value; + this.y = value; + this.z = value; } + /** * @brief Constructor from scalars * @param xxx X value * @param yyy Y value * @param zzz Z value */ - public Vector3i(int xxx, int yyy, int zzz) { + public Vector3i(final int xxx, final int yyy, final int zzz) { this.x = xxx; this.y = yyy; this.z = zzz; } - /** - * @brief Constructor from scalars - * @param value unique value for X,Y and Z value - */ - public Vector3i(int value) { - this.x = value; - this.y = value; - this.z = value; - } + /** * @brief Constructor from other vector (copy) * @param obj The vector to add to this one */ - public Vector3i(Vector3i obj) { + public Vector3i(final Vector3i obj) { this.x += obj.x; this.y += obj.y; this.z += obj.z; } - /** - * @brief Add a vector to this one - * @param obj The vector to add to this one - */ - public Vector3i add(Vector3i obj) { - this.x += obj.x; - this.y += obj.y; - this.z += obj.z; - return this; - } - /** - * @brief Add a vector to this one - * @param obj The vector to add to this one - */ - public Vector3i addNew(Vector3i obj) { - return new Vector3i(this.x + obj.x, - this.y + obj.y, - this.z + obj.z); - } - /** - * @brief Subtract a vector from this one - * @param obj The vector to subtract - */ - public Vector3i less(Vector3i obj) { - this.x -= obj.x; - this.y -= obj.y; - this.z -= obj.z; - return this; - } - /** - * @brief Scale the vector - * @param val Scale factor - */ - public Vector3i multiply(int val) { - this.x *= val; - this.y *= val; - this.z *= val; - return this; - } - /** - * @brief Scale the vector - * @param val Scale factor - */ - public Vector3i multiplyNew(int val) { - return new Vector3i(this.x * val, this.y * val, this.z * val); - } - /** - * @brief Inversely scale the vector - * @param val Scale factor to divide by - */ - public void devide(int val) { - if (val != 0.0f) { - this.x /= val; - this.y /= val; - this.z /= val; - } - // TODO maybe throw ... - } - /** - * @brief Return the dot product - * @param obj The other vector in the dot product - * @return Dot product value - */ - public int dot(Vector3i obj) { - return this.x * obj.x - + this.y * obj.y - + this.z * obj.z; - } - /** - * @brief Get the length of the vector squared - * @return Squared length value. - */ - public int length2() { - return dot(this); - } - /** - * @brief Get the length of the vector - * @return Length value - */ - public int length() { - return (int) Math.sqrt(length2()); - } - /** - * @brief Return the distance squared between the ends of this and another vector - * This is symantically treating the vector like a point - * @param obj The other vector to compare distance - * @return the square distance of the 2 points - */ - public int distance2(Vector3i obj) { - int deltaX = obj.x - this.x; - int deltaY = obj.y - this.y; - int deltaZ = obj.z - this.z; - return deltaX*deltaX + deltaY*deltaY + deltaZ*deltaZ; - } - /** - * @brief Return the distance between the ends of this and another vector - * This is symantically treating the vector like a point - * @param obj The other vector to compare distance - * @return the distance of the 2 points - */ - public int distance(Vector3i obj) { - return (int)Math.sqrt(this.distance2(obj)); - } - /** - * @brief 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)) - */ - public void safeNormalize() { - int length = length(); - if (length != 0.0f) { - this.devide(length); - } - this.setValue(1,0,0); - } - /** - * @brief Normalize this vector x^2 + y^2 + z^2 = 1 - */ - public void normalize() { - this.devide(this.length()); - } - /** - * @brief Return a normalized version of this vector - * @return New vector containing the value - */ - public Vector3i normalizeNew() { - Vector3i out = new Vector3i(this); - out.normalize(); - return out; - } - /** - * @brief Return a normalized version of this vector (check if not deviding by 0, if it is the case ==> return (1,0,0)) - * @return New vector containing the value - */ - public Vector3i safeNormalizeNew() { - Vector3i out = new Vector3i(this); - out.safeNormalize(); - return out; - } - /** - * @brief Return a rotated version of this vector - * @param wAxis The axis to rotate about - * @param angle The angle to rotate by - * @return New vector containing the value - */ - public Vector3i rotateNew( Vector3i wAxis, int angle ) { - Vector3i out = wAxis.clone(); - out.multiply( wAxis.dot( this ) ); - Vector3i x = this.clone(); - x.less(out); - Vector3i y = wAxis.cross( this ); - x.multiply((int)Math.cos(angle)); - y.multiply((int)Math.sin(angle)); - out.add(x); - out.add(y); - return out; - } - /** - * @brief Calculate the angle between this and another vector - * @param obj The other vector - * @return Angle in radian - */ - public int angle(Vector3i obj) { - int s = (int) Math.sqrt(length2() * obj.length2()); - if (0!=s) { - return (int) Math.acos(this.dot(obj) / s); - } - return 0; - } + /** * @brief Return a vector will the absolute values of each element * @return the curent reference @@ -215,46 +93,260 @@ public class Vector3i { this.z = Math.abs(this.z); return this; } + /** * @brief Return a vector will the absolute values of each element * @return New vector containing the value */ public Vector3i absoluteNew() { - return new Vector3i( Math.abs(this.x), - Math.abs(this.y), - Math.abs(this.z)); + return new Vector3i(Math.abs(this.x), Math.abs(this.y), Math.abs(this.z)); } + + /** + * @brief Add a vector to this one + * @param obj The vector to add to this one + */ + public Vector3i add(final Vector3i obj) { + this.x += obj.x; + this.y += obj.y; + this.z += obj.z; + return this; + } + + /** + * @brief Add a vector to this one + * @param obj The vector to add to this one + */ + public Vector3i addNew(final Vector3i obj) { + return new Vector3i(this.x + obj.x, this.y + obj.y, this.z + obj.z); + } + + /** + * @brief Calculate the angle between this and another vector + * @param obj The other vector + * @return Angle in radian + */ + public int angle(final Vector3i obj) { + final int s = (int) Math.sqrt(length2() * obj.length2()); + if (0 != s) { + return (int) Math.acos(dot(obj) / s); + } + return 0; + } + + /** + * @brief Clone the current vector. + * @return New vector containing the value + */ + @Override + public Vector3i clone() { + return new Vector3i(this); + } + + /** + * @brief Return the axis with the largest ABSOLUTE value + * @return values 0,1,2 for x, y, or z + */ + public int closestAxis() { + return absoluteNew().maxAxis(); + } + /** * @brief Return the cross product between this and another vector * @param obj The other vector * @return Vector with the result of the cross product */ - public Vector3i cross(Vector3i obj) { - return new Vector3i(this.y * obj.z - this.z * obj.y, - this.z * obj.x - this.x * obj.z, - this.x * obj.y - this.y * obj.x); + public Vector3i cross(final Vector3i obj) { + return new Vector3i(this.y * obj.z - this.z * obj.y, this.z * obj.x - this.x * obj.z, this.x * obj.y - this.y * obj.x); } + /** - * @brief Return the triple product between this and another vector and another - * @param obj1 The other vector 1 - * @param obj2 The other vector 2 - * @return Value with the result of the triple product + * @brief Inversely scale the vector + * @param val Scale factor to divide by */ - public int triple(Vector3i obj1, Vector3i 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); + public void devide(final int val) { + if (val != 0.0f) { + this.x /= val; + this.y /= val; + this.z /= val; + } + // TODO maybe throw ... } + /** - * @brief Return the axis with the smallest value + * @brief Return the distance between the ends of this and another vector + * This is symantically treating the vector like a point + * @param obj The other vector to compare distance + * @return the distance of the 2 points + */ + public int distance(final Vector3i obj) { + return (int) Math.sqrt(distance2(obj)); + } + + /** + * @brief Return the distance squared between the ends of this and another vector + * This is symantically treating the vector like a point + * @param obj The other vector to compare distance + * @return the square distance of the 2 points + */ + public int distance2(final Vector3i obj) { + final int deltaX = obj.x - this.x; + final int deltaY = obj.y - this.y; + final int deltaZ = obj.z - this.z; + return deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ; + } + + /** + * @brief Return the dot product + * @param obj The other vector in the dot product + * @return Dot product value + */ + public int dot(final Vector3i obj) { + return this.x * obj.x + this.y * obj.y + this.z * obj.z; + } + + /** + * @brief Return the axis with the smallest ABSOLUTE value * @return values 0,1,2 for x, y, or z */ - public int minAxis() { - if (this.x < this.y) { - return this.x < this.z ? 0 : 2; - } - return this.y < this.z ? 1 : 2; + public int furthestAxis() { + return absoluteNew().minAxis(); } + + /** + * @brief Get the maximum value of the vector (x, y, z) + * @return The max value + */ + public int getMax() { + return Math.max(Math.max(this.x, this.y), this.z); + } + + /** + * @brief Get the Axis id with the maximum value + * @return Axis ID 0,1,2 + */ + public int getMaxAxis() { + return (this.x < this.y ? (this.y < this.z ? 2 : 1) : (this.x < this.z ? 2 : 0)); + } + + /** + * @brief Get the minimum value of the vector (x, y, z) + * @return The min value + */ + public int getMin() { + return Math.min(Math.min(this.x, this.y), this.z); + } + + /** + * @brief Get the Axis id with the minimum value + * @return Axis ID 0,1,2 + */ + public int getMinAxis() { + return (this.x < this.y ? (this.x < this.z ? 0 : 2) : (this.y < this.z ? 1 : 2)); + } + + /** + * @brief Create a skew matrix of the object + * @param obj0 Vector matric first line + * @param obj1 Vector matric second line + * @param obj2 Vector matric third line + */ + public void getSkewSymmetricMatrix(final Vector3i obj0, final Vector3i obj1, final Vector3i obj2) { + obj0.setValue(0, -this.z, this.y); + obj1.setValue(this.z, 0, -this.x); + obj2.setValue(-this.y, this.x, 0); + } + + /** + * @brief Get X value + * @return the x value + */ + public int getX() { + return this.x; + } + + /** + * @brief Get Y value + * @return the y value + */ + public int getY() { + return this.y; + } + + /** + * @brief Get Z value + * @return the z value + */ + public int getZ() { + return this.z; + } + + /** + * @brief In-Equality compare operator with an other object. + * @param obj Reference on the comparing object + * @return true The Objects are NOT identical + * @return false The Objects are identical + */ + public boolean isDifferent(final Vector3i obj) { + return ((this.z != obj.z) || (this.y != obj.y) || (this.x != obj.x)); + } + + /** + * @brief Equality compare operator with an other object. + * @param obj Reference on the comparing object + * @return true The Objects are identical + * @return false The Objects are NOT identical + */ + public boolean isEqual(final Vector3i obj) { + return ((this.z == obj.z) && (this.y == obj.y) && (this.x == obj.x)); + } + + /** + * @brief Check if the vector is equal to (0,0,0) + * @return true The value is equal to (0,0,0) + * @return false The value is NOT equal to (0,0,0) + */ + public boolean isZero() { + return this.x == 0 && this.y == 0 && this.z == 0; + } + + /** + * @brief Get the length of the vector + * @return Length value + */ + public int length() { + return (int) Math.sqrt(length2()); + } + + /** + * @brief Get the length of the vector squared + * @return Squared length value. + */ + public int length2() { + return dot(this); + } + + /** + * @brief Return the linear interpolation between this and another vector + * @param obj The other vector + * @param ratio The ratio of this to obj (ratio = 0 => return copy of this, ratio=1 => return other) + * @return New vector containing the value + */ + public Vector3i lerp(final Vector3i obj, final int ratio) { + return new Vector3i(this.x + (obj.x - this.x) * ratio, this.y + (obj.y - this.y) * ratio, this.z + (obj.z - this.z) * ratio); + } + + /** + * @brief Subtract a vector from this one + * @param obj The vector to subtract + */ + public Vector3i less(final Vector3i obj) { + this.x -= obj.x; + this.y -= obj.y; + this.z -= obj.z; + return this; + } + /** * @brief Return the axis with the largest value * @return values 0,1,2 for x, y, or z @@ -265,212 +357,192 @@ public class Vector3i { } return this.x < this.z ? 2 : 0; } + /** - * @brief Return the axis with the smallest ABSOLUTE value + * @brief Return the axis with the smallest value * @return values 0,1,2 for x, y, or z */ - public int furthestAxis() { - return absoluteNew().minAxis(); + public int minAxis() { + if (this.x < this.y) { + return this.x < this.z ? 0 : 2; + } + return this.y < this.z ? 1 : 2; } + /** - * @brief Return the axis with the largest ABSOLUTE value - * @return values 0,1,2 for x, y, or z + * @brief Scale the vector + * @param val Scale factor */ - public int closestAxis() { - return absoluteNew().maxAxis(); - } - /** - * @brief Return the linear interpolation between this and another vector - * @param obj The other vector - * @param ratio The ratio of this to obj (ratio = 0 => return copy of this, ratio=1 => return other) - * @return New vector containing the value - */ - public Vector3i lerp(Vector3i obj, int ratio) { - return new Vector3i(this.x + (obj.x - this.x) * ratio, - this.y + (obj.y - this.y) * ratio, - this.z + (obj.z - this.z) * ratio); + public Vector3i multiply(final int val) { + this.x *= val; + this.y *= val; + this.z *= val; + return this; } + /** * @brief Elementwise multiply this vector by the other * @param obj The other vector * @return the current reference */ - public Vector3i multiply(Vector3i obj) { + public Vector3i multiply(final Vector3i obj) { this.x *= obj.x; this.y *= obj.y; this.z *= obj.z; return this; } + + /** + * @brief Scale the vector + * @param val Scale factor + */ + public Vector3i multiplyNew(final int val) { + return new Vector3i(this.x * val, this.y * val, this.z * val); + } + /** * @brief Elementwise multiply this vector by the other * @param obj The other vector */ - public Vector3i multiplyNew(Vector3i obj) { + public Vector3i multiplyNew(final Vector3i obj) { this.x *= obj.x; this.y *= obj.y; this.z *= obj.z; return this; } + /** - * @brief Set the x value - * @param x New value + * @brief Normalize this vector x^2 + y^2 + z^2 = 1 */ - public void setX(int x) { - this.x = x; + public void normalize() { + devide(length()); } + /** - * @brief Set the y value - * @param y New value + * @brief Return a normalized version of this vector + * @return New vector containing the value */ - public void setY(int y) { - this.y = y; + public Vector3i normalizeNew() { + final Vector3i out = new Vector3i(this); + out.normalize(); + return out; } + /** - * @brief Set the z value - * @param z New value + * @brief Return a rotated version of this vector + * @param wAxis The axis to rotate about + * @param angle The angle to rotate by + * @return New vector containing the value */ - public void setZ(int z) { - this.z = z; + public Vector3i rotateNew(final Vector3i wAxis, final int angle) { + final Vector3i out = wAxis.clone(); + out.multiply(wAxis.dot(this)); + final Vector3i x = clone(); + x.less(out); + final Vector3i y = wAxis.cross(this); + x.multiply((int) Math.cos(angle)); + y.multiply((int) Math.sin(angle)); + out.add(x); + out.add(y); + return out; } + /** - * @brief Get X value - * @return the x value + * @brief 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)) */ - public int getX() { - return this.x; + public void safeNormalize() { + final int length = length(); + if (length != 0.0f) { + devide(length); + } + setValue(1, 0, 0); } + /** - * @brief Get Y value - * @return the y value + * @brief Return a normalized version of this vector (check if not deviding by 0, if it is the case ==> return (1,0,0)) + * @return New vector containing the value */ - public int getY() { - return this.y; - } - /** - * @brief Get Z value - * @return the z value - */ - public int getZ() { - return this.z; - } - /** - * @brief Equality compare operator with an other object. - * @param obj Reference on the comparing object - * @return true The Objects are identical - * @return false The Objects are NOT identical - */ - public boolean isEqual(Vector3i obj) { - return ( (this.z == obj.z) - && (this.y == obj.y) - && (this.x == obj.x)); - } - /** - * @brief In-Equality compare operator with an other object. - * @param obj Reference on the comparing object - * @return true The Objects are NOT identical - * @return false The Objects are identical - */ - public boolean isDifferent(Vector3i obj) { - return ( (this.z != obj.z) - || (this.y != obj.y) - || (this.x != obj.x)); + public Vector3i safeNormalizeNew() { + final Vector3i out = new Vector3i(this); + out.safeNormalize(); + return out; } + /** * @brief Set each element to the max of the current values and the values of another Vector3f * @param obj The other Vector3f to compare with */ - public void setMax(Vector3i obj) { + public void setMax(final Vector3i obj) { this.x = Math.max(this.x, obj.x); this.y = Math.max(this.y, obj.y); this.z = Math.max(this.z, obj.z); } + /** * @brief Set each element to the min of the current values and the values of another Vector3f * @param obj The other Vector3f to compare with */ - public void setMin(Vector3i obj) { + public void setMin(final Vector3i obj) { this.x = Math.min(this.x, obj.x); this.y = Math.min(this.y, obj.y); this.z = Math.min(this.z, obj.z); } - /** - * @brief Get the minimum value of the vector (x, y, z) - * @return The min value - */ - public int getMin() { - return Math.min(Math.min(this.x, this.y), this.z); - } - /** - * @brief Get the maximum value of the vector (x, y, z) - * @return The max value - */ - public int getMax() { - return Math.max(Math.max(this.x, this.y), this.z); - } + /** * @brief Set Value on the vector * @param xxx X value. * @param yyy Y value. * @param zzz Z value. */ - public void setValue(int xxx, int yyy, int zzz) { + public void setValue(final int xxx, final int yyy, final int zzz) { this.x = xxx; this.y = yyy; this.z = zzz; } + /** - * @brief Create a skew matrix of the object - * @param obj0 Vector matric first line - * @param obj1 Vector matric second line - * @param obj2 Vector matric third line + * @brief Set the x value + * @param x New value */ - public void getSkewSymmetricMatrix(Vector3i obj0,Vector3i obj1,Vector3i obj2) { - obj0.setValue(0 ,-z ,y); - obj1.setValue(z ,0 ,-x); - obj2.setValue(-y ,x ,0); + public void setX(final int x) { + this.x = x; } + + /** + * @brief Set the y value + * @param y New value + */ + public void setY(final int y) { + this.y = y; + } + + /** + * @brief Set the z value + * @param z New value + */ + public void setZ(final int z) { + this.z = z; + } + /** * @brief Set 0 value on all the vector */ public void setZero() { - setValue(0,0,0); - } - /** - * @brief Check if the vector is equal to (0,0,0) - * @return true The value is equal to (0,0,0) - * @return false The value is NOT equal to (0,0,0) - */ - public boolean isZero() { - return this.x == 0 - && this.y == 0 - && this.z == 0; - } - /** - * @brief Get the Axis id with the minimum value - * @return Axis ID 0,1,2 - */ - public int getMinAxis() { - return (this.x < this.y ? (this.x < this.z ? 0 : 2) : (this.y < this.z ? 1 : 2)); - } - /** - * @brief Get the Axis id with the maximum value - * @return Axis ID 0,1,2 - */ - public int getMaxAxis() { - return (this.x < this.y ? (this.y < this.z ? 2 : 1) : (this.x < this.z ? 2 : 0)); - } - /** - * @brief Clone the current vector. - * @return New vector containing the value - */ - public Vector3i clone() { - return new Vector3i(this); - } - public static Vector3i zero() { - return new Vector3i(0,0,0); + setValue(0, 0, 0); } + @Override public String toString() { return "Vector3i(" + this.x + "," + this.y + "," + this.z + ")"; } + + /** + * @brief Return the triple product between this and another vector and another + * @param obj1 The other vector 1 + * @param obj2 The other vector 2 + * @return Value with the result of the triple product + */ + public int triple(final Vector3i obj1, final Vector3i 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); + } } diff --git a/src/org/atriasoft/etk/theme/Theme.java b/src/org/atriasoft/etk/theme/Theme.java new file mode 100644 index 0000000..eb0497e --- /dev/null +++ b/src/org/atriasoft/etk/theme/Theme.java @@ -0,0 +1,86 @@ +package org.atriasoft.etk.theme; + +import java.nio.file.Path; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import org.atriasoft.etk.internal.Log; + +public class Theme { + private static Map g_listTheme = new HashMap<>(); + private static Map g_listThemeDefault = new HashMap<>(); + + /** + * @brief get the folder from a Reference theme + * @param[in] _refName Theme cathegorie ex : "GUI" "SHADER" "DEFAULT" + * @return the path of the theme + */ + public static Path getName(final String _refName) { + return g_listTheme.get(_refName); + } + + /** + * @brief get the default folder from a Reference theme + * @param[in] _refName Theme cathegorie ex : "GUI" "SHADER" "DEFAULT" + * @return the path of the theme + */ + public static Path getNameDefault(final String _refName) { + return g_listThemeDefault.get(_refName); + }; + + /** + * @brief initialize the theme system + */ + public static void init() { + + }; + + /** + * @brief Get the list of all the theme folder availlable in the user Home/appl + * @return The list of elements + */ + public static Set list() { + return g_listTheme.keySet(); + } + + /** + * @brief Set the Folder of a subset of a theme ... + * @param[in] _refName Theme cathegorie ex : "GUI" "SHADER" "DEFAULT" + * @param[in] _folderName The associated folder of the Theme (like "myTheme/folder/folder2/") + */ + public static void setName(final String _refName, final Path _folderName) { + Log.warning("Change theme : '" + _refName + "' : '" + _folderName + "'"); + g_listTheme.put(_refName, _folderName); + updateProvider(_refName); + } + + /** + * @brief Set the default folder of a subset of a theme ... + * @param[in] _refName Theme cathegorie ex : "GUI" "SHADER" "DEFAULT" + * @param[in] _folderName The associated default folder of the Theme (like "myTheme/color/default/") + */ + public static void setNameDefault(final String _refName, final Path _folderName) { + g_listThemeDefault.put(_refName, _folderName); + updateProvider(_refName); + } + + /** + * @brief un-initialize the theme system + */ + public static void unInit() { + g_listTheme.clear(); + g_listThemeDefault.clear(); + } + + public static void updateProvider(final String _refName) { + final Path base = getName(_refName); + final Path baseDefault = getNameDefault(_refName); + if (base == null) { + //etk::uri::provider::add("THEME_" + _refName, new ProviderTheme(new Path("theme") / baseDefault, Path("theme") / base)); + } else { + //etk::uri::provider::add("THEME_" + _refName, new ProviderTheme(Path("theme") / base, Path("theme") / baseDefault)); + } + }; + +} diff --git a/src/org/atriasoft/etk/util/Pair.java b/src/org/atriasoft/etk/util/Pair.java new file mode 100644 index 0000000..2a8c0a1 --- /dev/null +++ b/src/org/atriasoft/etk/util/Pair.java @@ -0,0 +1,75 @@ +package org.atriasoft.etk.util; + +// Pair class +public class Pair { + // Factory method for creating a Typed Pair immutable instance + public static Pair of(final U a, final V b) { + // calls private constructor + return new Pair<>(a, b); + } + + public final U first; // first field of a Pair + + public final V second; // second field of a Pair + + // Constructs a new Pair with specified values + public Pair(final U first, final V second) { + this.first = first; + this.second = second; + } + + @Override + // Checks specified object is "equal to" current object or not + public boolean equals(final Object o) { + if (this == o) { + return true; + } + + if (o == null || getClass() != o.getClass()) { + return false; + } + + final Pair pair = (Pair) o; + + // call equals() method of the underlying objects + if (!this.first.equals(pair.first)) { + return false; + } + return this.second.equals(pair.second); + } + + @Override + // Computes hash code for an object to support hash tables + public int hashCode() { + // use hash codes of the underlying objects + return 31 * this.first.hashCode() + this.second.hashCode(); + } + + @Override + public String toString() { + return "(" + this.first + ", " + this.second + ")"; + } +} + +// Program to implement Pair Class in Java +/* +class Main +{ + public static void main(String[] args) + { + Pair p1 = Pair.of("John", 26); + Pair p2 = Pair.of("Tom", 30); + Pair p3 = Pair.of("John", 26); + + List> pairs = new ArrayList<>(); + pairs.add(p1); + pairs.add(p2); + pairs.add(p3); + + System.out.println(pairs); + + Set> distinctPairs = new HashSet<>(pairs); + System.out.println(distinctPairs); + } +} +*/ \ No newline at end of file