Merge remote-tracking branch 'origin/master'

This commit is contained in:
Arthur 2021-04-19 11:09:28 +02:00
commit c10ecfeb15
11 changed files with 170 additions and 118 deletions

View File

@ -18,13 +18,21 @@ Ce mot passera ensuite par un moteur graphique dans le but d'être modélisé.
\section{Notre L-Système} \section{Notre L-Système}
\subsection{Alphabet} \subsection{Alphabet}
Notre alphabet est composés de plusieurs constantes : Notre alphabet est composés de plusieurs règles et constantes:\\
\begin{itemize}[label=\textbullet] \begin{itemize}
\item Peut \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 Etre \item Il est possible de modifier l'angle d'une branche en utilisant par exemple les +, -, -35, +64y, qui donnera
\item Faire 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 Une liste \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} \end{itemize}
\subsection{Axiome, règles de réécritures et nombre d'itérations} \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. 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. 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}

View File

@ -79,21 +79,6 @@ linewidth=1pt]{infoenv}
\end{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 % Gestion d'abstracts multiples
\newenvironment{abstractpage} \newenvironment{abstractpage}

View File

@ -178,5 +178,12 @@ public class Parser {
return n; return n;
} }
public int getNbIterations() {
return nbIterations;
}
public String getAxiom() {
return axiom;
}
} }

View File

@ -41,7 +41,7 @@ public class Constants {
+ "\tX = X20yY-X\r\n" + "\tX = X20yY-X\r\n"
+ "\r\n" + "\r\n"
+ "On ajoute le principe de branches aux expressions, on utilise donc pour ce faire les crochets \"[ ]\".\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" + "les elements étant à l'intérieur des crochets"
+ "\r\n" + "\r\n"
+ "Ainsi, dans l'expression:\r\n" + "Ainsi, dans l'expression:\r\n"

View File

@ -33,7 +33,7 @@ public abstract class AbstractListener implements GLEventListener {
GL2 gl = glAutoDrawable.getGL().getGL2(); GL2 gl = glAutoDrawable.getGL().getGL2();
gl.glClearColor(0f, 0f, 0f, 1.0f); gl.glClearColor(0f, 0f, 0f, 1.0f);
gl.setSwapInterval(0);
new Thread(() -> { new Thread(() -> {
while (canvas.frame.isVisible()) { while (canvas.frame.isVisible()) {
try { try {

View File

@ -47,34 +47,6 @@ public class DrawHelper {
glut.glutBitmapCharacter(GLUT.BITMAP_HELVETICA_18, 'Z'); // draw the z axis 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") @SuppressWarnings("unused")
public static void drawDebugInformation(GL2 gl, GLUT glut, AbstractCanvas canvas) { public static void drawDebugInformation(GL2 gl, GLUT glut, AbstractCanvas canvas) {

View File

@ -3,6 +3,7 @@ package lsystem.screen.gl3d;
import com.jogamp.opengl.GL2; import com.jogamp.opengl.GL2;
import com.jogamp.opengl.GLAutoDrawable; import com.jogamp.opengl.GLAutoDrawable;
import lsystem.engine.Element; import lsystem.engine.Element;
import lsystem.engine.ElementProperties;
import lsystem.screen.Constants; 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 @Override
public void drawLSystem(GL2 gl, Element element) { 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();
} }

View File

@ -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":
}
}
}
}

View File

@ -1,9 +1,6 @@
package lsystem.screen.main; package lsystem.screen.main;
import lsystem.Main;
import lsystem.engine.Parser; import lsystem.engine.Parser;
import lsystem.screen.gl3d.AbstractCanvas;
import lsystem.utils.Pair;
import javax.swing.*; import javax.swing.*;
import java.awt.*; import java.awt.*;
@ -16,7 +13,6 @@ public class Listener implements ActionListener, KeyListener, MouseWheelListener
Integer index; Integer index;
String type; String type;
Integer nbAxioms= 0; Integer nbAxioms= 0;
Thread parserThread = null;
ImageIcon staticIcon = new ImageIcon(Toolkit.getDefaultToolkit().createImage(getClass().getClassLoader().getResource("./loading-gif.gif"))); 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": case "Tab":
frame.newTab(); frame.newTab();
break; break;
case "example":
frame.newExample();
break;
case "Clear": case "Clear":
tab.getTextArea((byte) 0).setText("Axiome : \n"); tab.getTextArea((byte) 0).setText("Axiome : \n");
tab.getTextArea((byte) 1).setText("Règles : \n"); tab.getTextArea((byte) 1).setText("Règles : \n");
@ -60,46 +58,13 @@ public class Listener implements ActionListener, KeyListener, MouseWheelListener
String axiom3D = tab.getAxiom(); String axiom3D = tab.getAxiom();
List<String> rules3D = tab.getRules(); List<String> rules3D = tab.getRules();
Parser parser3D = new Parser(axiom3D, rules3D, tab.getNbIterations()); Parser parser3D = new Parser(axiom3D, rules3D, tab.getNbIterations());
if(Main.joglFrame.frame.isVisible()) { frame.generateLSystem(this, parser3D, tab.submitButton);
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<Pair<String, String>> 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<String, String> 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();
}
break; break;
} }
} }
private void openDialog(String message) { void openDialog(String message) {
JOptionPane.showMessageDialog(null, message); JOptionPane.showMessageDialog(null, message);
new Listener(null, index, "Clear", tab); new Listener(null, index, "Clear", tab);
} }

View File

@ -1,20 +1,28 @@
package lsystem.screen.main; package lsystem.screen.main;
import lsystem.Main;
import lsystem.engine.Parser;
import lsystem.screen.Constants; import lsystem.screen.Constants;
import lsystem.screen.gl3d.AbstractCanvas;
import lsystem.utils.Pair;
import javax.swing.*; import javax.swing.*;
import java.awt.*; import java.awt.*;
import java.awt.event.WindowAdapter; import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent; import java.awt.event.WindowEvent;
import java.util.List;
public class MainFrame extends JFrame { public class MainFrame extends JFrame {
private int nbTabs;
Thread parserThread = null;
public int nbTabs;
boolean helpWindow = false; boolean helpWindow = false;
private final JPanel basePanel; private final JPanel basePanel;
public final JTabbedPane tabs; public final JTabbedPane tabs;
private final JButton newGen; private final JButton newGen;
private final JButton example;
private final JButton help; private final JButton help;
private final int nbRules; private final int nbRules;
@ -32,6 +40,9 @@ public class MainFrame extends JFrame {
newGen = new JButton("Nouvelle génération"); newGen = new JButton("Nouvelle génération");
newGen.addActionListener(new Listener(this,null,"Tab",null)); newGen.addActionListener(new Listener(this,null,"Tab",null));
toolBar.add(newGen); toolBar.add(newGen);
example = new JButton("Exemples");
example.addActionListener(new Listener(this, null, "example", null));
toolBar.add(example);
help = new JButton("Aide"); help = new JButton("Aide");
help.addActionListener(new Listener(this,null,"Help",null)); help.addActionListener(new Listener(this,null,"Help",null));
toolBar.add(help); toolBar.add(help);
@ -96,10 +107,10 @@ public class MainFrame extends JFrame {
*/ */
public void newTab() { public void newTab() {
if(nbTabs>2) if(nbTabs>2)
JOptionPane.showMessageDialog(null, "Nombre maximal de générations atteintes"); JOptionPane.showMessageDialog(null, "Nombre maximal d'onglets atteintes");
else { else {
nbTabs++; 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<Pair<String, String>> 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<String, String> 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();
}
}
} }

View File

@ -6,22 +6,16 @@ import java.util.Arrays;
public class Tab extends JPanel{ public class Tab extends JPanel{
public int nbTabs;
int nbRules;
public JSpinner itSpinner; public JSpinner itSpinner;
JTextField axiomeField,rulesField; JTextField axiomeField, rulesField;
JTextArea axiomList,rulesList; JTextArea axiomList, rulesList;
JButton submitButton3D; JButton submitButton;
/** /**
* A method which create a new instance of the class JPanel ready to be added to the MainFrame's tabs variable (JTabbedPane). * 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. * @param frame the MainFrame instance that is useful to access all the components.
*/ */
public Tab(int nbTabs,MainFrame frame) { public Tab(MainFrame frame) {
this.nbRules = nbRules;
this.nbTabs = nbTabs;
axiomList = textArea("Axiome :"); axiomList = textArea("Axiome :");
rulesList = textArea("Règles :"); rulesList = textArea("Règles :");
@ -35,22 +29,22 @@ public class Tab extends JPanel{
JLabel rules = new JLabel("Règles :"); JLabel rules = new JLabel("Règles :");
axiomeField = new JTextField(); 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)); axiomeField.setPreferredSize(new Dimension(120,20));
rulesField = new JTextField(); 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)); 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"); 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); clearButton.setBackground(Color.GREEN);
submitButton3D.addActionListener(new Listener(null,nbTabs,"Generate 3D",this)); submitButton.addActionListener(new Listener(frame, frame.nbTabs,"Generate 3D",this));
submitButton3D.setBackground(Color.CYAN); submitButton.setBackground(Color.CYAN);
JButton close = new JButton("Close"); JButton close = new JButton("Close");
close.addActionListener(new Listener(frame,null,"Close",null)); close.addActionListener(new Listener(frame,null,"Close",null));
close.setBackground(Color.RED); close.setBackground(Color.RED);
JPanel southComponents = subPanel(submitButton3D,close,null); JPanel southComponents = subPanel(submitButton,close,null);
southComponents = subPanel(clearButton, southComponents, null); southComponents = subPanel(clearButton, southComponents, null);
GridBagConstraints gc = new GridBagConstraints(); GridBagConstraints gc = new GridBagConstraints();
@ -59,11 +53,11 @@ public class Tab extends JPanel{
gc.weightx = 0; gc.weightx = 0;
gc.weighty = 0.5; gc.weighty = 0.5;
JPanel lists = subPanel(axiomList,rulesList,gc); JPanel lists = subPanel(axiomList, rulesList,gc);
JPanel fields = subPanel(axiomeField,rulesField,gc); JPanel fields = subPanel(axiomeField, rulesField,gc);
JPanel labels = subPanel(axiome,rules,gc); JPanel labels = subPanel(axiome, rules, gc);
JPanel Iterations = subPanel(itLabel,itSpinner,gc); JPanel Iterations = subPanel(itLabel, itSpinner, gc);
JPanel aboveComponents = new JPanel(); JPanel aboveComponents = new JPanel();
aboveComponents.add(labels); aboveComponents.add(labels);