Skip to content
Snippets Groups Projects
Commit d200eb5d authored by Guillaume Huard's avatar Guillaume Huard
Browse files

Machine à tracer récupérée de diverses UEs

parents
No related branches found
No related tags found
No related merge requests found
/* MachineTrace - Encore une nouvelle version (à but pédagogique) de la célèbre tortue LOGO
* Copyright (C) 2018 Guillaume Huard
*
* Ce programme est libre, vous pouvez le redistribuer et/ou le
* modifier selon les termes de la Licence Publique Générale GNU publiée par la
* Free Software Foundation (version 2 ou bien toute autre version ultérieure
* choisie par vous).
*
* Ce programme est distribué car potentiellement utile, mais SANS
* AUCUNE GARANTIE, ni explicite ni implicite, y compris les garanties de
* commercialisation ou d'adaptation dans un but spécifique. Reportez-vous à la
* Licence Publique Générale GNU pour plus de détails.
*
* Vous devez avoir reçu une copie de la Licence Publique Générale
* GNU en même temps que ce programme ; si ce n'est pas le cas, écrivez à la Free
* Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
* États-Unis.
*
* Contact:
* Guillaume.Huard@imag.fr
* Laboratoire LIG
* 700 avenue centrale
* Domaine universitaire
* 38401 Saint Martin d'Hères
*/
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.util.Iterator;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
/**
* Classe permettant d'ouvrir une fenêtre graphique et de dessiner dans cette
* fenêtre de manière simple. Le dessin se fait à l'aide d'une plume orientée
* qu'il est possible de lever/baisser et de déplacer. La fenêtre représente une
* portion du plan dans laquelle :
* <ul>
* <li>(0,0) est au centre</li>
* <li>l'orientation de la plume est un angle en degrés avec 0° à droite, 90° en
* haut et 180° à gauche</li>
* </ul>
* La plume démarre :
* <ul>
* <li>en position (0,0), c'est à dire au centre de la fenêtre</li>
* <li>avec l'angle 90, c'est à dire orientée vers le haut</li>
* </ul>
* Tout déplacement avec la plume baissée dessine dans la fenêtre.
*
* @author Guillaume Huard
* @version 29/06/2018
*/
public class MachineTrace {
final static int NOIR = 0;
final static int BLANC = 1;
final static int JAUNE = 2;
final static int ROUGE = 3;
final static int VERT = 4;
final static int BLEU = 5;
RefreshHandler refresh;
Etat etat;
boolean autoRefresh;
int autoWait;
/**
* Permet d'attendre.
*
* @param ms
* Le nombre de millisecondes à attendre
*/
public void attendre(int ms) {
if (ms > 0) {
try {
Thread.sleep(ms);
} catch (Exception e) {
}
;
}
}
/**
* Ajoute une attente automatique après chaque commande.
*
* @param ms
* Le nombre de millisecondes à attendre
*/
public void attenteAutomatique(int ms) {
autoWait = ms;
}
private void commit() {
if (autoRefresh) {
rafraichir();
}
attendre(autoWait);
}
/**
* Lève la plume.
*/
public void lever() {
etat.enBas = false;
commit();
}
/**
* Baisse la plume.
*/
public void baisser() {
etat.enBas = true;
commit();
}
/**
* Fait avancer la plume.
*
* @param L
* Distance à parcourir (en pixels)
*/
public void avancer(double L) {
etat.avancer(L);
commit();
}
/**
* Tourne la plume vers la gauche.
*
* @param a
* L'angle de rotation en degrés.
*/
public void tournerGauche(double a) {
etat.tourner(a);
commit();
}
/**
* Tourne la plume vers la droite.
*
* @param a
* L'angle de rotation en degrés.
*/
public void tournerDroite(double a) {
etat.tourner(-a);
commit();
}
/**
* Oriente la plume de manière absolue.
*
* @param a
* Nouvel angle de la plume
*/
public void orienter(double a) {
etat.orienter(a);
commit();
}
/**
* Place la plume au point donné. Attention, ceci est un déplacement : si la
* plume est baissée elle dessinera jusqu'au point destination.
*
* @param x
* Abscisse du point destination
* @param y
* Ordonnée du point destination
*/
public void placer(double x, double y) {
etat.placer(x, y);
commit();
}
/**
* Si la plume est baissée, trace un cercle autour de la position courante de la plume.
*
* @param r
* Rayon du cercle
*/
public void tracerCercle(double r) {
etat.tracerOvale(r, r);
commit();
}
/**
* Si la plume est baissée, trace un ovale autour de la position courante de la plume.
*
* @param rX
* Rayon en abscisse de l'ovale
* @param rY
* Rayon en ordonnée de l'ovale
*/
public void tracerOvale(double rX, double rY) {
etat.tracerOvale(rX, rY);
commit();
}
/**
* Change la couleur de la plume. La couleur est un entier entre 0 et 5 ou peut
* être choisie parmi :
* <ul>
* <li>MachineTrace.NOIR</li>
* <li>MachineTrace.BLANC</li>
* <li>MachineTrace.JAUNE</li>
* <li>MachineTrace.ROUGE</li>
* <li>MachineTrace.VERT</li>
* <li>MachineTrace.BLEU</li>
* </ul>
*
* @param couleur
* La nouvelle couleur
*/
public void changeCouleur(int couleur) {
etat.changeCouleur(couleur);
commit();
}
/**
* Renvoie la couleur courante de la plume.
*
* @return couleur courante de la plume.
*/
public int couleurCourante() {
return etat.colorIndex;
}
/**
* Masque le pointeur qui représente la plume.
*/
public void masquerPointeur() {
etat.pointeur = false;
commit();
}
/**
* Montre le pointeur qui représente la plume.
*/
public void montrerPointeur() {
etat.pointeur = true;
commit();
}
/**
* Efface le contenu de la fenêtre.
*/
public void effacerTout() {
etat.effacerTout();
commit();
}
/**
* Met à jour l'affichage (inutile sauf si le rafraîchissement automatique est
* desactivé).
*/
public void rafraichir() {
refresh.run();
}
/**
* Crée une nouvelle fenêtre de dessin.
*
* @param l
* Largeur de la fenêtre
* @param h
* Hauteur de la fenêtre
*/
public MachineTrace(int l, int h) {
autoRefresh = true;
autoWait = 0;
etat = new Etat(l, h);
JComponent sc = new SwingComponent(etat);
refresh = new RefreshHandler(sc);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame("Machine trace");
sc.setPreferredSize(new Dimension(l, h));
frame.add(sc);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// frame.setSize(d.width, d.height);
frame.pack();
frame.setVisible(true);
}
});
}
/**
* Crée une nouvelle fenêtre de dessin.
*
* @param l
* Largeur de la fenêtre
* @param h
* Hauteur de la fenêtre
* @param r
* Rafraichissement automatique
*/
public MachineTrace(int l, int h, boolean r) {
this(l, h);
autoRefresh = r;
}
}
class Etat {
static Color[] colors = { Color.BLACK, Color.WHITE, Color.YELLOW, Color.RED, Color.GREEN, Color.BLUE };
java.util.List<Command> commands;
double angle;
Point2D position;
Dimension d;
volatile boolean enBas;
Color color;
volatile int colorIndex;
volatile boolean pointeur;
Etat(int l, int h) {
commands = new java.util.ArrayList<>();
angle = 0;
position = new Point2D.Double();
d = new Dimension(l, h);
enBas = false;
colorIndex = MachineTrace.NOIR;
color = colors[colorIndex];
pointeur = true;
}
synchronized Etat recuperer() {
Etat resultat = new Etat(d.width, d.height);
java.util.List<Command> tmp = resultat.commands;
resultat.commands = commands;
commands = tmp;
resultat.angle = angle;
resultat.position.setLocation(position.getX(), position.getY());
resultat.enBas = enBas;
resultat.colorIndex = colorIndex;
resultat.color = color;
resultat.pointeur = pointeur;
return resultat;
}
synchronized void avancer(double L) {
double x = position.getX();
double y = position.getY();
x += L * Math.cos(angle);
y += L * Math.sin(angle);
placer(x, y);
}
synchronized void tourner(double a) {
angle += a * 2 * Math.PI / 360.0;
}
synchronized void orienter(double a) {
angle = a * 2 * Math.PI / 360.0;
}
private static int convert(double d) {
return (int) Math.round(d);
}
private int convertX(double x) {
return convert(x) + d.width / 2;
}
private int convertY(double y) {
return -convert(y) + d.height / 2;
}
synchronized void placer(double x, double y) {
if (enBas) {
int x1 = convertX(position.getX());
int y1 = convertY(position.getY());
int x2 = convertX(x);
int y2 = convertY(y);
Line l = new Line(x1, y1, x2, y2, color);
commands.add(l);
}
position.setLocation(x, y);
}
synchronized void tracerOvale(double rX, double rY) {
if (enBas) {
int x = convertX(position.getX()-rX);
int y = convertY(position.getY()+rY);
int dX = convert(2*rX);
int dY = convert(2*rY);
Oval c = new Oval(x, y, dX, dY, color);
commands.add(c);
}
}
synchronized void changeCouleur(int couleur) {
color = colors[couleur];
colorIndex = couleur;
}
synchronized void effacerTout() {
commands.add(new Erase());
}
void dessinePointeur(int[] pointeurX, int[] pointeurY) {
double taille = 5;
double x = position.getX();
double y = position.getY();
pointeurX[0] = convertX(x);
pointeurY[0] = convertY(y);
pointeurX[1] = convertX(x + taille * Math.cos(angle + Math.PI * 3 / 4));
pointeurY[1] = convertY(y + taille * Math.sin(angle + Math.PI * 3 / 4));
pointeurX[2] = convertX(x + 2 * taille * Math.cos(angle));
pointeurY[2] = convertY(y + 2 * taille * Math.sin(angle));
pointeurX[3] = convertX(x + taille * Math.cos(angle - Math.PI * 3 / 4));
pointeurY[3] = convertY(y + taille * Math.sin(angle - Math.PI * 3 / 4));
}
}
class SwingComponent extends JComponent {
private static final long serialVersionUID = 5663965186068436350L;
Etat etatGlobal;
int width, height;
BufferedImage image;
Graphics2D dessin;
int[] pointeurX, pointeurY;
SwingComponent(Etat e) {
etatGlobal = e;
image = null;
pointeurX = new int[4];
pointeurY = new int[4];
}
public void paintComponent(Graphics g) {
Graphics2D drawable = (Graphics2D) g;
width = getSize().width;
height = getSize().height;
if (image == null) {
image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
dessin = image.createGraphics();
dessin.setBackground(Color.WHITE);
dessin.clearRect(0, 0, width, height);
}
Etat etat = etatGlobal.recuperer();
// Image en cours
Iterator<Command> it = etat.commands.iterator();
while (it.hasNext()) {
Command c = it.next();
if (c != null) {
c.draw(dessin, width, height);
}
}
drawable.drawImage(image, 0, 0, null);
// Pointeur
if (etat.pointeur) {
etat.dessinePointeur(pointeurX, pointeurY);
if (etat.enBas) {
drawable.setPaint(etat.color);
} else {
drawable.setPaint(Color.WHITE);
}
drawable.fillPolygon(pointeurX, pointeurY, 4);
drawable.setPaint(Color.BLACK);
drawable.drawPolygon(pointeurX, pointeurY, 4);
}
}
}
class RefreshHandler implements Runnable {
JComponent c;
RefreshHandler(JComponent component) {
c = component;
}
public void run() {
c.repaint();
}
}
abstract class Command {
abstract void draw(Graphics2D drawable, int width, int height);
}
class Line extends Command {
int x1, y1, x2, y2;
Color col;
Line(int a, int b, int c, int d, Color co) {
x1 = a;
y1 = b;
x2 = c;
y2 = d;
col = co;
}
@Override
void draw(Graphics2D drawable, int width, int height) {
drawable.setPaint(col);
drawable.drawLine(x1, y1, x2, y2);
}
}
class Erase extends Command {
@Override
void draw(Graphics2D drawable, int width, int height) {
drawable.setBackground(Color.WHITE);
drawable.clearRect(0, 0, width, height);
}
}
class Oval extends Command {
int x, y, dX, dY;
Color col;
Oval(int a, int b, int c, int d, Color co) {
x = a;
y = b;
dX = c;
dY = d;
col = co;
}
@Override
void draw(Graphics2D drawable, int width, int height) {
drawable.setPaint(col);
drawable.drawOval(x, y, dX, dY);
}
}
\ No newline at end of file
* MachineTrace - Encore une nouvelle version (à but pédagogique) de la célèbre tortue LOGO
Copyright (C) 2018 Guillaume Huard
Ce programme est libre, vous pouvez le redistribuer et/ou le
modifier selon les termes de la Licence Publique Générale GNU publiée par la
Free Software Foundation (version 2 ou bien toute autre version ultérieure
choisie par vous).
Ce programme est distribué car potentiellement utile, mais SANS
AUCUNE GARANTIE, ni explicite ni implicite, y compris les garanties de
commercialisation ou d'adaptation dans un but spécifique. Reportez-vous à la
Licence Publique Générale GNU pour plus de détails.
Vous devez avoir reçu une copie de la Licence Publique Générale
GNU en même temps que ce programme ; si ce n'est pas le cas, écrivez à la Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
États-Unis.
Contact:
Guillaume.Huard@imag.fr
Laboratoire LIG
700 avenue centrale
Domaine universitaire
38401 Saint Martin d'Hères
class SegmentsAlignes
{
public static void tracerSegmentProgressivement(MachineTrace m, double x, double y,
double angle, double l) {
m.lever();
m.placer(x, y);
m.orienter(angle);
m.baisser();
for (double i=0; i<l; i+=10) {
m.avancer(10);
}
}
public static int choisirCouleur(int i) {
if (i == 0)
return MachineTrace.NOIR;
else if (i == 1)
return MachineTrace.BLANC;
else if (i == 2)
return MachineTrace.JAUNE;
else if (i == 3)
return MachineTrace.ROUGE;
else if (i == 4)
return MachineTrace.VERT;
else if (i == 5)
return MachineTrace.BLEU;
else
return MachineTrace.NOIR;
}
public static void main(String [] args) {
MachineTrace m = new MachineTrace(400,400);
int n=20, d=10;
double x, y;
// Attend automatiquement après chaque commande
// Permet de voir le dessin se construire
m.attenteAutomatique(10);
// Première série de tracés sans le pointeur
m.masquerPointeur();
for (int i=0; i<=n; i++) {
x = -50;
y = i*d-100;
m.changeCouleur(choisirCouleur(i%6));
tracerSegmentProgressivement(m, x, y, 45, 100);
}
// Seconde série de tracés avec le pointeur
m.effacerTout();
m.montrerPointeur();
for (int i=0; i<=n; i++) {
x = 50;
y = i*d-100;
m.changeCouleur(choisirCouleur(i%6));
m.lever();
m.placer(x, y);
m.baisser();
m.tracerCercle(3);
tracerSegmentProgressivement(m, x, y, 135, 100);
m.tracerCercle(3);
}
}
}
class Un_Segment
{
public static void main(String [] args) {
MachineTrace m = new MachineTrace(400,400);
m.placer(0, 0);
m.baisser();
m.placer(100,100);
m.lever();
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment