Merge branch 'master' of https://forge.info.unicaen.fr/git/l-system
This commit is contained in:
commit
3ee0261350
12
.gitignore
vendored
12
.gitignore
vendored
@ -1 +1,13 @@
|
|||||||
.idea/
|
.idea/
|
||||||
|
out/
|
||||||
|
/bin/
|
||||||
|
.project
|
||||||
|
.classpath
|
||||||
|
.bin
|
||||||
|
.settings/
|
||||||
|
rapport/rapport.out
|
||||||
|
rapport/rapport.aux
|
||||||
|
rapport/rapport.pdf
|
||||||
|
rapport/rapport.log
|
||||||
|
rapport/rapport.toc
|
||||||
|
rapport/rapport.synctex.gz
|
75
rapport/rapport.tex
Normal file
75
rapport/rapport.tex
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
\documentclass[12pt]{article}
|
||||||
|
|
||||||
|
\usepackage[utf8]{inputenc}
|
||||||
|
\usepackage[T1]{fontenc}
|
||||||
|
\usepackage[french]{babel}
|
||||||
|
\usepackage{hyperref}
|
||||||
|
\usepackage{graphicx}
|
||||||
|
\title{Conception Logicielle - L-système}
|
||||||
|
\author{Antonin Boyon, Thomas Lalong, Quentin Legot, Arthur Page}
|
||||||
|
\date{\today}
|
||||||
|
|
||||||
|
\begin{document}
|
||||||
|
|
||||||
|
\maketitle
|
||||||
|
\thispagestyle{empty}
|
||||||
|
\setcounter{page}{0}
|
||||||
|
\newpage
|
||||||
|
|
||||||
|
\tableofcontents
|
||||||
|
\newpage
|
||||||
|
|
||||||
|
\section{Introduction}
|
||||||
|
\subsection{}
|
||||||
|
Le but de notre projet était de concevoir un générateur de flores vidéo-ludiques. Ce genre de logiciel à pour but de créer de manière procédurale des modèles végétaux qui pourront notamment être utilisés dans les jeux vidéos. Nous devions pour cela nous baser sur un L-système \ref{l-system}, un parser \ref{parser}, un moteur de réécriture\ref{rw-engine} et un moteur graphique\ref{g-engine}. Le rôle de ses différents éléments sera expliqué dans les sections suivantes.
|
||||||
|
|
||||||
|
|
||||||
|
\section{Le logiciel}
|
||||||
|
\subsection{Organigramme}
|
||||||
|
%inclure à la fin quand le logiciel sera terminé
|
||||||
|
|
||||||
|
\subsection{Le l-system}
|
||||||
|
\label{l-system}
|
||||||
|
\subsubsection{Qu'est-ce qu'un L-system}
|
||||||
|
Un L-system (ou L-système en français) est un langage de réécriture permettant de modéliser l'évolution de modèles végétaux ou bactériologiques. (Wikipédia : \url{https://fr.wikipedia.org/wiki/L-Syst%C3%A8me}).
|
||||||
|
\\
|
||||||
|
Un L-system se base sur plusieurs paramètres:
|
||||||
|
\begin{itemize}
|
||||||
|
\item L'alphabet.\ref{alpha}\\
|
||||||
|
C'est le "langage" du L-system, il est propre à chaque L-system et c'est à nous de le définir.
|
||||||
|
\item L'axiome.\ref{axiome}\\
|
||||||
|
C'est l'élément qui servira de base à la génération.
|
||||||
|
\item Les règles.\ref{rules}\\
|
||||||
|
Elles servent à définir comment le modèle va évoluer en partant de l'axiome.
|
||||||
|
\item Le nombre d'itérations.\ref{nbIt}\\
|
||||||
|
Ce nombre indique le nombre de fois que les règles peuvent être appliquées.
|
||||||
|
\end{itemize}
|
||||||
|
\subsubsection{Notre L-system}
|
||||||
|
Voici, expliqué en détail, les composants de notre L-système.
|
||||||
|
\paragraph{L'alphabet}\label{alpha} étant propre à chaque L-system, nous avons du créer le notre.
|
||||||
|
Il est constitué de 6 lettres , 10 chiffres et 6 caractères.
|
||||||
|
Les lettres comprennent 3 majuscules $(X,Y,Z)$ et 3 minuscules $(x,y,z)$.
|
||||||
|
Les trois majuscules servent à représenter un mouvement d'une unité dans le sens positif de leur axe.
|
||||||
|
Ainsi $X = $ mouvement d'une unité dans le sens positif sur l'axe $X$.
|
||||||
|
Les trois minuscules quant à elles, permettent d'effectuer une rotation de +25° sur leurs axes respectifs.
|
||||||
|
Ainsi, $x = $ rotation de 25° par rapport à l'axe des $X$.
|
||||||
|
Les chiffres permettent, avec les symboles $(.,+,-)$ de faire varier les valeurs de base des lettres de l'alphabet.
|
||||||
|
Ainsi, $-0.5X$ représentera un mouvement négatif de 0.5 unités sur l'axe $X$.
|
||||||
|
De même, $+2x$ représentera un mouvement positif de 50° sur l'axe des $X$.
|
||||||
|
Les symboles, $([,])$ permettent de différer l'exécution d'une règle, nous expliquerons leur utilité dans cette ce paragraphe \ref{rules}. Pour le dernier symbole, $=$, son utilité sera expliquée dans ce paragraphe \ref{axiome}.
|
||||||
|
\paragraph{L'axiome}\label{axiome}
|
||||||
|
\paragraph{Les règles}\label{rules}
|
||||||
|
\paragraph{Le nombre d'itérations}\label{nbIt}
|
||||||
|
\subsection{Le parser}
|
||||||
|
\label{parser}
|
||||||
|
\subsection{Le moteur de réécriture}
|
||||||
|
\label{rw-engine}
|
||||||
|
\subsection{Le moteur graphique}
|
||||||
|
\label{g-engine}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
\section{Conclusion}
|
||||||
|
\end{document}
|
@ -1,5 +1,8 @@
|
|||||||
package lsystem;
|
package lsystem;
|
||||||
|
|
||||||
|
import lsystem.engine.Parser;
|
||||||
|
import lsystem.engine.Rewrite;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Scanner;
|
import java.util.Scanner;
|
||||||
@ -7,14 +10,30 @@ import java.util.Scanner;
|
|||||||
public class Main {
|
public class Main {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
Scanner scanner = new Scanner(System.in);
|
final Scanner scanner = new Scanner(System.in);
|
||||||
System.out.println("Axiom: ");
|
String axiom = null;
|
||||||
String axiom = scanner.next();
|
Parser parser = null;
|
||||||
System.out.println("Règles (laissez vide quand vous avez fini): ");
|
final List<String> rules = new ArrayList<>();
|
||||||
List<String> rules = new ArrayList<>();
|
int nbIterations = 0;
|
||||||
while(rules.isEmpty() || !rules.get(rules.size() - 1).equals("")) {
|
while(parser == null || !parser.isCorrect()) {
|
||||||
rules.add(scanner.next());
|
if(parser != null)
|
||||||
|
System.out.println("Vos règles ou votre axiome ne sont pas correctement écrites, veuillez recommencer");
|
||||||
|
System.out.println("Axiome: ");
|
||||||
|
axiom = scanner.next();
|
||||||
|
System.out.println("Règles: (\"finish\" quand vous avez fini): ");
|
||||||
|
while(rules.isEmpty() || !rules.get(rules.size() - 1).equals("finish")) {
|
||||||
|
rules.add(scanner.next());
|
||||||
|
}
|
||||||
|
rules.remove(rules.size() - 1);
|
||||||
|
System.out.println("Nombre d'itérations: ");
|
||||||
|
nbIterations = scanner.nextInt();
|
||||||
|
parser = new Parser(axiom, rules,nbIterations);
|
||||||
}
|
}
|
||||||
|
System.out.println("Réécriture, veuillez patientez...");
|
||||||
|
Rewrite rewriter = new Rewrite(axiom, parser.parseRules(), nbIterations);
|
||||||
|
final String word = rewriter.rewrite();
|
||||||
|
System.out.println(word);
|
||||||
|
scanner.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
8
src/lsystem/Type.java
Normal file
8
src/lsystem/Type.java
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
package lsystem;
|
||||||
|
|
||||||
|
public enum Type {
|
||||||
|
|
||||||
|
AXIOM,
|
||||||
|
RULE
|
||||||
|
|
||||||
|
}
|
87
src/lsystem/engine/Parser.java
Normal file
87
src/lsystem/engine/Parser.java
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
package lsystem.engine;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import lsystem.Type;
|
||||||
|
import lsystem.utils.Pair;
|
||||||
|
|
||||||
|
public class Parser {
|
||||||
|
|
||||||
|
private final String axiom;
|
||||||
|
private final List<String> rules;
|
||||||
|
private final int nbIterations;
|
||||||
|
private char[] validChars = {'=',']','[','.','+','-','X','Y','Z','x','y','z','0','1','2','3','4','5','6','7','8','9',' '};
|
||||||
|
|
||||||
|
public Parser(String axiom, List<String> rules,int nbIterations) {
|
||||||
|
this.axiom = axiom;
|
||||||
|
this.rules = rules;
|
||||||
|
this.nbIterations = nbIterations;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if axiom and rules given by user respect the syntax
|
||||||
|
* @return true if the syntax is correct
|
||||||
|
*/
|
||||||
|
public boolean isCorrect(){
|
||||||
|
if (nbIterations < 1) {
|
||||||
|
System.out.println("Erreur, nombre d'itérations insuffisant (plus petit que 1)");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
boolean bl = isCorrect(axiom, Type.AXIOM);
|
||||||
|
for(String rule : this.rules){
|
||||||
|
bl = bl && isCorrect(rule, Type.RULE);
|
||||||
|
}
|
||||||
|
return bl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private boolean isCorrect(String stringToCheck, Type type) {
|
||||||
|
char old = ' ';
|
||||||
|
int bracket = 0;
|
||||||
|
boolean equalsSymbolFound = false;
|
||||||
|
for (int i = 0; i > stringToCheck.length(); i++){
|
||||||
|
char temp = stringToCheck.charAt(i);
|
||||||
|
if (temp == '[')
|
||||||
|
bracket++;
|
||||||
|
if(temp == ']')
|
||||||
|
bracket--;
|
||||||
|
if(temp == '=') {
|
||||||
|
if(!equalsSymbolFound)
|
||||||
|
equalsSymbolFound = true;
|
||||||
|
else
|
||||||
|
// only one '=' allowed
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(old == '.'){
|
||||||
|
for(int y = (type == Type.RULE ? 0 : 1); y < 12; y++){
|
||||||
|
if(temp == validChars[y])
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
old = temp;
|
||||||
|
for(char validChar : validChars){
|
||||||
|
if(temp == validChar)
|
||||||
|
break;
|
||||||
|
if(validChar == ' ')
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bracket == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used by {@link Rewrite}
|
||||||
|
* @return a list of rules with the left and right sides separated by a {@link lsystem.utils.Pair Pair}
|
||||||
|
*/
|
||||||
|
public List<Pair<String, String>> parseRules() {
|
||||||
|
List<Pair<String, String>> rules = new ArrayList<>();
|
||||||
|
this.rules.forEach(rule -> {
|
||||||
|
String[] str = rule.split("=");
|
||||||
|
rules.add(new Pair<String, String>(str[0], str[1]));
|
||||||
|
});
|
||||||
|
return rules;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
30
src/lsystem/engine/Rewrite.java
Normal file
30
src/lsystem/engine/Rewrite.java
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package lsystem.engine;
|
||||||
|
|
||||||
|
import lsystem.utils.Pair;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Rewrite {
|
||||||
|
|
||||||
|
private final String axiom;
|
||||||
|
private final List<Pair<String, String >> rules;
|
||||||
|
private final int recurrences;
|
||||||
|
|
||||||
|
public Rewrite(String axiom, List<Pair<String, String>> rules, int recurrences) {
|
||||||
|
this.axiom = axiom;
|
||||||
|
this.rules = rules;
|
||||||
|
this.recurrences = recurrences;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String rewrite() {
|
||||||
|
String rewritted = axiom;
|
||||||
|
for(int i = 0; i < recurrences; ++i) {
|
||||||
|
for(int j = 0; j < rules.size(); ++j){
|
||||||
|
Pair<String, String> pair = rules.get(j);
|
||||||
|
rewritted = rewritted.replace(pair.getLeft(), pair.getRight());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rewritted;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
51
src/lsystem/utils/Pair.java
Normal file
51
src/lsystem/utils/Pair.java
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
package lsystem.utils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tuple containing 2 unknown type elements
|
||||||
|
*
|
||||||
|
* @param <U> left
|
||||||
|
* @param <K> right
|
||||||
|
*/
|
||||||
|
public class Pair<U, K> {
|
||||||
|
|
||||||
|
private final U left;
|
||||||
|
private final K right;
|
||||||
|
|
||||||
|
public Pair(U left, K right) {
|
||||||
|
this.left = left;
|
||||||
|
this.right = right;
|
||||||
|
}
|
||||||
|
|
||||||
|
public U getLeft() {
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
public K getRight() {
|
||||||
|
return right;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (obj == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (getClass() != obj.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final Pair<?, ?> other = (Pair<?, ?>) obj;
|
||||||
|
return this.left.equals(other.getLeft()) && this.left.equals(other.getRight());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return 31 + left.hashCode() * right.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "(" + left + ", " + right + ")";
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user