diff --git a/rapport/chapters/chapitre2.tex b/rapport/chapters/chapitre2.tex index 625d793..a08e534 100644 --- a/rapport/chapters/chapitre2.tex +++ b/rapport/chapters/chapitre2.tex @@ -18,13 +18,21 @@ Ce mot passera ensuite par un moteur graphique dans le but d'être modélisé. \section{Notre L-Système} \subsection{Alphabet} -Notre alphabet est composés de plusieurs constantes : -\begin{itemize}[label=\textbullet] - \item Peut - \item Etre - \item Faire - \item Une liste +Notre alphabet est composés de plusieurs règles et constantes:\\ +\begin{itemize} + \item X permet de dessiner une branche et Y de dessinera rien, il permet avec certaines règles de contrôler l'évolution de notre L-Système. + \item Il est possible de modifier l'angle d'une branche en utilisant par exemple les +, -, -35, +64y, qui donnera +respectivement une orientation de 25° et -25° sur l'axe de rotation x, une rotation de -35° sur l'axe X et une orientation de 64° sur l'axe de rotation y; il n'est pas possible de modifier l'orientation de l'axe de rotation Z. +\item Enfin il est possible d'utiliser les crochets [] pour contrôler l'évolution et obtenir des branches à votre arbres, ces crochets vont conserver l'état, c'est à dire qu'une rotation appliqué aux crochets s'appliquera a tout les éléments étant à l'intérieur des crochets, par exemple: +[XYX] appliquera une rotation de 25° à XYX. Il est possible d'imbriquer des crochets. \end{itemize} + \subsection{Axiome, règles de réécritures et nombre d'itérations} Pour l'axiome, les règles de réécritures et le nombre d'itérations, ils seront définis par l'utilisateur dans les zones de textes de l'interface prévus a cet effet. -Un bouton "Aide" est présent sur cette même interface aidant a comprendre et mettre en place le L-Système. \ No newline at end of file +Un bouton "Aide" est présent sur cette même interface aidant a comprendre et mettre en place le L-Système. + +\begin{figure}[h!] + \centering + \includegraphics[width=0.8\linewidth]{pics/aideGUI.png} + \caption{Fenêtre d'aide} + \label{fig:my_label} +\end{figure} \ No newline at end of file diff --git a/rapport/main.tex b/rapport/main.tex index cdfa9ef..628830b 100644 --- a/rapport/main.tex +++ b/rapport/main.tex @@ -79,21 +79,6 @@ linewidth=1pt]{infoenv} \end{infoenv} } -\newcommand{\img}[1]{ -\begin{figure}[H] - \centering - \includegraphics[width=0.8\textwidth]{#1} -\end{figure} -} - -\newcommand{\imgwlegend}[2]{ - \begin{figure}[H] - \centering - \includegraphics[width=0.8\textwidth]{#1} - \caption{#2} - \end{figure} -} - % Gestion d'abstracts multiples \newenvironment{abstractpage} diff --git a/src/lsystem/engine/Parser.java b/src/lsystem/engine/Parser.java index 2a92464..9ab4883 100644 --- a/src/lsystem/engine/Parser.java +++ b/src/lsystem/engine/Parser.java @@ -178,5 +178,12 @@ public class Parser { return n; } - + + public int getNbIterations() { + return nbIterations; + } + + public String getAxiom() { + return axiom; + } } diff --git a/src/lsystem/screen/Constants.java b/src/lsystem/screen/Constants.java index 0cd37db..90379eb 100644 --- a/src/lsystem/screen/Constants.java +++ b/src/lsystem/screen/Constants.java @@ -41,7 +41,7 @@ public class Constants { + "\tX = X20yY-X\r\n" + "\r\n" + "On ajoute le principe de branches aux expressions, on utilise donc pour ce faire les crochets \"[ ]\".\r\n" - + "Elles permettent de controler l'évolution de l'arbre en appliquant la rotation qu'il lui est appliqué à tout" + + "Elles permettent de controler l'évolution de l'arbre en appliquant la rotation qu'il lui est appliqué à tout\r\n" + "les elements étant à l'intérieur des crochets" + "\r\n" + "Ainsi, dans l'expression:\r\n" diff --git a/src/lsystem/screen/gl3d/AbstractListener.java b/src/lsystem/screen/gl3d/AbstractListener.java index ed2add2..dafa27b 100644 --- a/src/lsystem/screen/gl3d/AbstractListener.java +++ b/src/lsystem/screen/gl3d/AbstractListener.java @@ -33,7 +33,7 @@ public abstract class AbstractListener implements GLEventListener { GL2 gl = glAutoDrawable.getGL().getGL2(); gl.glClearColor(0f, 0f, 0f, 1.0f); - + gl.setSwapInterval(0); new Thread(() -> { while (canvas.frame.isVisible()) { try { diff --git a/src/lsystem/screen/gl3d/DrawHelper.java b/src/lsystem/screen/gl3d/DrawHelper.java index 9296a1d..965f3fe 100644 --- a/src/lsystem/screen/gl3d/DrawHelper.java +++ b/src/lsystem/screen/gl3d/DrawHelper.java @@ -47,34 +47,6 @@ public class DrawHelper { glut.glutBitmapCharacter(GLUT.BITMAP_HELVETICA_18, 'Z'); // draw the z axis } - /** - * draw the L-System, move the camera and then use recursive call to draw branches of {@code element} - * @param listener use to move the camera depending of the size if the L-System - * @param gl use to move cursor - * @param glut use to draw pre implemented function like {@link GLUT#glutSolidCylinder(double, double, int, int)} - * @param element working branch of the {@link Element LSystem} - */ - public static void drawLSystem(AbstractListener listener, GL2 gl, GLUT glut, Element element) { - gl.glPushMatrix(); - gl.glRotatef(element.rotation[0] * 360, 1f, 0f, 0f); - gl.glRotatef(element.rotation[1] * 360, 0f, 1f, 0f); - gl.glRotated(-Math.sin(element.rotation[0]) * 180 - Math.sin(element.rotation[1]) * 180, 0f, 0f, 1f); - gl.glTranslated(-Math.sin(element.rotation[0]), -Math.sin(element.rotation[1]), -Math.sin(element.rotation[0] + element.rotation[1])); - - if(element.property == ElementProperties.DRAW) { - if(listener.firstGen) { - listener.canvas.camera[1] += 0.10f; - listener.canvas.camera[2] += 0.10f; - } - glut.glutSolidCylinder(0.25f, 1f, 10, 10); - gl.glTranslatef(0f, 0f, 1f); - } - - for(Element child : element.children) { - drawLSystem(listener, gl, glut, child); - } - gl.glPopMatrix(); - } @SuppressWarnings("unused") public static void drawDebugInformation(GL2 gl, GLUT glut, AbstractCanvas canvas) { diff --git a/src/lsystem/screen/gl3d/GLEventListener.java b/src/lsystem/screen/gl3d/GLEventListener.java index 90a40be..b0cad84 100644 --- a/src/lsystem/screen/gl3d/GLEventListener.java +++ b/src/lsystem/screen/gl3d/GLEventListener.java @@ -3,6 +3,7 @@ package lsystem.screen.gl3d; import com.jogamp.opengl.GL2; import com.jogamp.opengl.GLAutoDrawable; import lsystem.engine.Element; +import lsystem.engine.ElementProperties; import lsystem.screen.Constants; /** @@ -76,9 +77,32 @@ public class GLEventListener extends AbstractListener { } + /** + * draw the L-System, move the camera and then use recursive call to draw branches of {@code element} + * @param gl use to move cursor + * @param element working branch of the {@link Element LSystem} + */ @Override public void drawLSystem(GL2 gl, Element element) { - DrawHelper.drawLSystem(this, gl, glut, element); + gl.glPushMatrix(); + gl.glRotatef(element.rotation[0] * 360, 1f, 0f, 0f); + gl.glRotatef(element.rotation[1] * 360, 0f, 1f, 0f); + gl.glRotated(-Math.sin(element.rotation[0]) * 180 - Math.sin(element.rotation[1]) * 180, 0f, 0f, 1f); + gl.glTranslated(-Math.sin(element.rotation[0]), -Math.sin(element.rotation[1]), -Math.sin(element.rotation[0] + element.rotation[1])); + + if(element.property == ElementProperties.DRAW) { + if(firstGen) { + canvas.camera[1] += 0.10f; + canvas.camera[2] += 0.10f; + } + glut.glutSolidCylinder(0.25f, 1f, 10, 10); + gl.glTranslatef(0f, 0f, 1f); + } + + for(Element child : element.children) { + drawLSystem(gl, child); + } + gl.glPopMatrix(); } diff --git a/src/lsystem/screen/main/Example.java b/src/lsystem/screen/main/Example.java new file mode 100644 index 0000000..b2951f2 --- /dev/null +++ b/src/lsystem/screen/main/Example.java @@ -0,0 +1,39 @@ +package lsystem.screen.main; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public class Example extends JPanel { + + private final MainFrame frame; + + public Example(MainFrame frame) { + this.frame = frame; + + JPanel list = new JPanel(); + list.setLayout(new GridBagLayout()); + JButton a = new JButton("{axiom=\"Y\",rules:[\"Y=X+[[Y]-Y]-X[-XY]+Y\", \"X=XX\"]}"); + a.addActionListener(new ExampleListener("a")); + JPanel aboveComponents = new JPanel(); + + } + + private class ExampleListener implements ActionListener { + + private final String type; + + public ExampleListener(String type) { + this.type = type; + } + + @Override + public void actionPerformed(ActionEvent e) { + switch(type) { + case "a": + + } + } + } +} diff --git a/src/lsystem/screen/main/Listener.java b/src/lsystem/screen/main/Listener.java index 79a559e..d42e718 100644 --- a/src/lsystem/screen/main/Listener.java +++ b/src/lsystem/screen/main/Listener.java @@ -1,9 +1,6 @@ package lsystem.screen.main; -import lsystem.Main; import lsystem.engine.Parser; -import lsystem.screen.gl3d.AbstractCanvas; -import lsystem.utils.Pair; import javax.swing.*; import java.awt.*; @@ -16,7 +13,6 @@ public class Listener implements ActionListener, KeyListener, MouseWheelListener Integer index; String type; Integer nbAxioms= 0; - Thread parserThread = null; ImageIcon staticIcon = new ImageIcon(Toolkit.getDefaultToolkit().createImage(getClass().getClassLoader().getResource("./loading-gif.gif"))); @@ -46,7 +42,9 @@ public class Listener implements ActionListener, KeyListener, MouseWheelListener case "Tab": frame.newTab(); break; - + case "example": + frame.newExample(); + break; case "Clear": tab.getTextArea((byte) 0).setText("Axiome : \n"); tab.getTextArea((byte) 1).setText("Règles : \n"); @@ -60,46 +58,13 @@ public class Listener implements ActionListener, KeyListener, MouseWheelListener String axiom3D = tab.getAxiom(); List rules3D = tab.getRules(); Parser parser3D = new Parser(axiom3D, rules3D, tab.getNbIterations()); - if(Main.joglFrame.frame.isVisible()) { - openDialog("Veuillez fermer la fenêtre 2D ou 3D avant de lancer une nouvelle génération"); - } else if(Main.joglFrame.parsedState == AbstractCanvas.State.LOAD) { - openDialog("Une génération est actuellement en cours, impossible d'en relancer un autre"); - openDialog("Une génération est actuellement en cours, impossible d'en relancer un autre"); - } else if (!parser3D.isCorrect()) { - openDialog("Vos règles ou votre axiome ne sont pas correctement écrites, veuillez recommencer"); - } else { - tab.submitButton3D.setIcon(staticIcon); - tab.submitButton3D.setText(""); - parserThread = new Thread(() -> { - try { - List> lSystemRules = parser3D.parseRules(); - Main.joglFrame.setLSystem(axiom3D, lSystemRules, tab.getNbIterations()); - - StringBuilder message = new StringBuilder("L-System 3D - {axiom:\"").append(axiom3D).append("\",rules:["); - for(int i = 0; i < lSystemRules.size(); ++i) { - Pair rule = lSystemRules.get(i); - message.append("\"").append(rule.getLeft()).append("=").append(rule.getRight()).append("\""); - if(i + 1 != lSystemRules.size()) - message.append(","); - } - Main.joglFrame.frame.setTitle(message.append("]} - Nombres d'itérations: ").append(tab.getNbIterations()).toString()); - - Main.joglFrame.setVisible(true); - } catch (NumberFormatException err) { - Main.joglFrame.parsedState = AbstractCanvas.State.FINISH_OR_NULL; - openDialog("Une erreur de type " + err.getClass().getSimpleName() + " est survenue lors de l'execution du parser: " + err.getMessage()); - } - tab.submitButton3D.setIcon(null); - tab.submitButton3D.setText("Générer en 3D"); - }); - parserThread.start(); - } + frame.generateLSystem(this, parser3D, tab.submitButton); break; } } - private void openDialog(String message) { + void openDialog(String message) { JOptionPane.showMessageDialog(null, message); new Listener(null, index, "Clear", tab); } diff --git a/src/lsystem/screen/main/MainFrame.java b/src/lsystem/screen/main/MainFrame.java index cc89fba..e79b38f 100644 --- a/src/lsystem/screen/main/MainFrame.java +++ b/src/lsystem/screen/main/MainFrame.java @@ -1,20 +1,28 @@ package lsystem.screen.main; +import lsystem.Main; +import lsystem.engine.Parser; import lsystem.screen.Constants; +import lsystem.screen.gl3d.AbstractCanvas; +import lsystem.utils.Pair; import javax.swing.*; import java.awt.*; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; +import java.util.List; public class MainFrame extends JFrame { - private int nbTabs; + + Thread parserThread = null; + public int nbTabs; boolean helpWindow = false; private final JPanel basePanel; public final JTabbedPane tabs; private final JButton newGen; + private final JButton example; private final JButton help; private final int nbRules; @@ -32,6 +40,9 @@ public class MainFrame extends JFrame { newGen = new JButton("Nouvelle génération"); newGen.addActionListener(new Listener(this,null,"Tab",null)); toolBar.add(newGen); + example = new JButton("Exemples"); + example.addActionListener(new Listener(this, null, "example", null)); + toolBar.add(example); help = new JButton("Aide"); help.addActionListener(new Listener(this,null,"Help",null)); toolBar.add(help); @@ -96,10 +107,10 @@ public class MainFrame extends JFrame { */ public void newTab() { if(nbTabs>2) - JOptionPane.showMessageDialog(null, "Nombre maximal de générations atteintes"); + JOptionPane.showMessageDialog(null, "Nombre maximal d'onglets atteintes"); else { nbTabs++; - tabs.addTab("Génération" + nbTabs,new Tab(nbTabs,this)); + tabs.addTab("Génération" + nbTabs,new Tab(this)); } } @@ -113,4 +124,51 @@ public class MainFrame extends JFrame { } } + public void newExample() { + if(nbTabs > 2) + JOptionPane.showMessageDialog(null, "Nombre maximal d'onglets atteintes"); + else { + nbTabs++; + tabs.addTab("Exemples", new Example(this)); + } + } + + public void generateLSystem(Listener listener, Parser parser, JButton submitButton) { + if(Main.joglFrame.frame.isVisible()) { + listener.openDialog("Veuillez fermer la fenêtre 2D ou 3D avant de lancer une nouvelle génération"); + } else if(Main.joglFrame.parsedState == AbstractCanvas.State.LOAD) { + listener.openDialog("Une génération est actuellement en cours, impossible d'en relancer un autre"); + } else if (!parser.isCorrect()) { + listener.openDialog("Vos règles ou votre axiome ne sont pas correctement écrites, veuillez recommencer"); + } else { + String initialText = submitButton.getText(); + parserThread = new Thread(() -> { + try { + submitButton.setIcon(listener.staticIcon); + submitButton.setText(""); + List> lSystemRules = parser.parseRules(); + Main.joglFrame.setLSystem(parser.getAxiom(), lSystemRules, parser.getNbIterations()); + + StringBuilder message = new StringBuilder("L-System 3D - {axiom:\"").append(parser.getAxiom()).append("\",rules:["); + for(int i = 0; i < lSystemRules.size(); ++i) { + Pair rule = lSystemRules.get(i); + message.append("\"").append(rule.getLeft()).append("=").append(rule.getRight()).append("\""); + if(i + 1 != lSystemRules.size()) + message.append(","); + } + Main.joglFrame.frame.setTitle(message.append("]} - Nombres d'itérations: ").append(parser.getNbIterations()).toString()); + + Main.joglFrame.setVisible(true); + } catch (NumberFormatException err) { + Main.joglFrame.parsedState = AbstractCanvas.State.FINISH_OR_NULL; + listener.openDialog("Une erreur de type " + err.getClass().getSimpleName() + " est survenue lors de l'execution du parser: " + err.getMessage()); + } + submitButton.setIcon(null); + submitButton.setText(initialText); + }); + + parserThread.start(); + } + } + } diff --git a/src/lsystem/screen/main/Tab.java b/src/lsystem/screen/main/Tab.java index b81e99a..e405ae0 100644 --- a/src/lsystem/screen/main/Tab.java +++ b/src/lsystem/screen/main/Tab.java @@ -6,22 +6,16 @@ import java.util.Arrays; public class Tab extends JPanel{ - public int nbTabs; - int nbRules; public JSpinner itSpinner; - JTextField axiomeField,rulesField; - JTextArea axiomList,rulesList; - JButton submitButton3D; + JTextField axiomeField, rulesField; + JTextArea axiomList, rulesList; + JButton submitButton; /** * A method which create a new instance of the class JPanel ready to be added to the MainFrame's tabs variable (JTabbedPane). - * @param nbTabs the number of this tab, useful for the listener. * @param frame the MainFrame instance that is useful to access all the components. */ - public Tab(int nbTabs,MainFrame frame) { - - this.nbRules = nbRules; - this.nbTabs = nbTabs; + public Tab(MainFrame frame) { axiomList = textArea("Axiome : \n"); rulesList = textArea("Règles : \n"); @@ -35,22 +29,22 @@ public class Tab extends JPanel{ JLabel rules = new JLabel("Règles :"); axiomeField = new JTextField(); - axiomeField.addKeyListener(new Listener(null,nbTabs,"Axiome",this)); + axiomeField.addKeyListener(new Listener(null,frame.nbTabs,"Axiome",this)); axiomeField.setPreferredSize(new Dimension(120,20)); rulesField = new JTextField(); - rulesField.addKeyListener(new Listener(null,nbTabs+10,"Règles",this)); + rulesField.addKeyListener(new Listener(null,frame.nbTabs + 10,"Règles",this)); rulesField.setPreferredSize(new Dimension(120,20)); - submitButton3D = new JButton("Générer en 3D"); + submitButton = new JButton("Générer en 3D"); JButton clearButton = new JButton("Clear"); - clearButton.addActionListener(new Listener(null,nbTabs,"Clear",this)); + clearButton.addActionListener(new Listener(null,frame.nbTabs,"Clear",this)); clearButton.setBackground(Color.GREEN); - submitButton3D.addActionListener(new Listener(null,nbTabs,"Generate 3D",this)); - submitButton3D.setBackground(Color.CYAN); + submitButton.addActionListener(new Listener(frame, frame.nbTabs,"Generate 3D",this)); + submitButton.setBackground(Color.CYAN); JButton close = new JButton("Close"); close.addActionListener(new Listener(frame,null,"Close",null)); close.setBackground(Color.RED); - JPanel southComponents = subPanel(submitButton3D,close,null); + JPanel southComponents = subPanel(submitButton,close,null); southComponents = subPanel(clearButton, southComponents, null); GridBagConstraints gc = new GridBagConstraints(); @@ -59,11 +53,11 @@ public class Tab extends JPanel{ gc.weightx = 0; gc.weighty = 0.5; - JPanel lists = subPanel(axiomList,rulesList,gc); - JPanel fields = subPanel(axiomeField,rulesField,gc); - JPanel labels = subPanel(axiome,rules,gc); + JPanel lists = subPanel(axiomList, rulesList,gc); + JPanel fields = subPanel(axiomeField, rulesField,gc); + JPanel labels = subPanel(axiome, rules, gc); - JPanel Iterations = subPanel(itLabel,itSpinner,gc); + JPanel Iterations = subPanel(itLabel, itSpinner, gc); JPanel aboveComponents = new JPanel(); aboveComponents.add(labels);