package ecoparasite.svg; import ecoparasite.representation.ValeursXY; import ecoparasite.svg.elements.Element; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.UUID; public class SVGFactory { static final private String EXPORT_PATH = "export/"; static final private String EXTENSION = ".svg"; /** * Permet la création du fichier SVG * @param mesElements un array des elements à ajouter dans le svg * @return True si la création est un succès, False sinon */ public static boolean createSVG(ArrayList mesElements){ String code = createSVGCode(mesElements); try { createFile(code); } catch (Exception e) { return false; } return true; } /** * Permet la création du fichier SVG (Polymorphisme pour ajouter un nom de fichier) * @param mesElements un Array des elements à ajouter dans le SVG * @param filename une String représentant le nom du fichier choisi * @return True si la création est un succès, False sinon */ public static boolean createSVG(ArrayList mesElements, String filename) { String code = createSVGCode(mesElements); try { createFile(code,filename); } catch (Exception e) { return false; } return true; } /** * Fonction basique de transformation des éléments en code SVG * @param mesElements un array contenant les éléments à mettre dans le svg * @return une String contenant la totalité du code SVG de notre graphique */ public static String createSVGCode(ArrayList mesElements){ String code = ""; for (Element e : mesElements){ code += e.toSVG(); } code += ""; return code; } /** * fonction qui créer le fichier, ici avec une ID random comme nom de fichier * @param data une String contenant le contenue du fichier désiré (ici pour le SVG) * @throws IOException Déclenché par un échec de la création du fichier */ public static void createFile(String data) throws IOException { String id = UUID.randomUUID().toString(); createFile(data,id); } /** * Permet la création du fichier * @param data une String contenant le contenue du fichier désiré * @param filename une String contenant le nom du fichier voulu * @throws IOException Déclenché par un échec de la création du fichier */ public static void createFile(String data, String filename) throws IOException { // create a FileWriter object with the file name FileWriter writer = new FileWriter(EXPORT_PATH + filename + EXTENSION); // write the string to the file writer.write(data); // close the writer writer.close(); System.out.println("Successfully wrote text to file."); } /** * Permet de renvoyer des valeurs "clean" pour l'affichage des axes * @param h Contient les Coordonnées de chacun des points de nos données * @return une HashMap de String et de Hashset de Double. * Avec la String "AxeX", un Hashset de Double contenant les valeurs des gradations de l'axe X * Avec la String "AxeY", un Hashset de Double contenant les valeurs des gragations de l'axe Y * Avec la String "OffsetX", un Hashset de Double contenant uniquement la valeur de l'offset des points par rapport à l'axe X * Avec la String "OffsetY", un Hashset de Double contenant uniquement la valeur de l'offset des points par rapport à l'axe Y */ public static HashMap< String ,HashSet> PointAXES(HashSet h){ HashMap< String, HashSet > map = new HashMap<>(); //Définition des min et max double max_x = Double.MIN_VALUE; double min_x = Double.MAX_VALUE; double max_y = Double.MIN_VALUE; double min_y = Double.MAX_VALUE; //Trouvé les min et max for (ValeursXY var : h) { if (max_x < var.getX()){ max_x = var.getX(); } else if (min_x > var.getX()){ min_x = var.getX(); } if (max_y < var.getY()){ max_y = var.getY(); } else if (min_y > var.getY()){ min_y = var.getY(); } } double range_x = max_x-min_x; double range_y = max_y-min_y; int target = 10; // Ideal Number of Gradation double step_x = niceStep(range_x,target); double step_y = niceStep(range_y,target); double nicemin_x = roundMin(min_x,step_x); double nicemax_x = roundMax(max_x,step_x); double nicemin_y = roundMin(min_y,step_y); double nicemax_y = roundMax(max_y,step_y); // Compléter un Hashset de Double pour X et pour Y et Offset X et Y. TODO HashSet axeX = new HashSet<>(); HashSet axeY = new HashSet<>(); HashSet OffsetX = new HashSet<>(); HashSet OffsetY = new HashSet<>(); Double ix = nicemin_x; while ( ix <= nicemax_x ) { axeX.add(ix); ix+=step_x; }; map.put("AxeX", axeX); Double iy = nicemin_y; while ( iy <= nicemax_y ) { axeY.add(iy); iy+=step_y; } map.put("AxeY",axeY); double offsetX = min_x - nicemin_x; double offsetY = min_y - nicemin_y; HashSet offsetXHash = new HashSet<>(); offsetXHash.add(offsetX); HashSet offsetYHash = new HashSet<>(); offsetYHash.add(offsetY); map.put("OffsetX", offsetXHash); map.put("OffsetY", offsetYHash); return map; } /** * Fonction de calcul d'un step rond * Cette fonction est basé sur une idée demandée à ChatGPT * @param range écart entre la plus petite et la plus grande valeur * @param targetTicks nombre de gradation ideal * @return */ public static double niceStep(double range, int targetTicks) { double rawStep = range / targetTicks; double exponent = Math.floor(Math.log10(rawStep)); double fraction = rawStep / Math.pow(10, exponent); double niceFraction; if (fraction < 1.5) niceFraction = 1; else if (fraction < 3) niceFraction = 2; else if (fraction < 7) niceFraction = 5; else niceFraction = 10; return niceFraction * Math.pow(10, exponent); } /** * retourne une valeur arrondi "joli" adapter à un graphique * @param value * @param step * @return */ public static double roundMin(double value, double step) { return Math.floor(value / step) * step; } public static double roundMax(double value, double step) { return Math.ceil(value / step) * step; } }