Solution du TD d'informatique No. 2 :
Calcul d'enveloppe convexe

Patrick Gros -- Patrick.Gros@irisa.fr
Didier Le Botlan -- didier.le_botlan@inria.fr

Lundi 20 novembre 2000

import java.io.* ;
import java.lang.* ;
import java.util.* ;

class enveloppe_convexe {
    // Variables globales = disponibles dans toute la classe
    static int max ;    // max donne le nombre de points dont on cherche l'enveloppe convexe.
    static Point[] P ;  // P est le tableau des points.
    
    // Fonction d'initialisation aleatoire
    static void Initialise() {
 for (int i = 0 ; i < max ; ++i) {
     P[i] = new Point() ;
     P[i].h = (short)(Math.random() * 200) ;
     P[i].v = (short)(Math.random() * 200) ;
 }
    }
    
    // Fonction d'initialisation a la main
    static void Initialise_souris() {
 for (int i = 0 ; i < max ; ++i) {
     P[i] = new Point() ;
     MacLib.WaitClickDown() ;
     MacLib.GetMouse(P[i]) ;
     MacLib.PaintCircle(P[i].h, P[i].v, 2) ;
 }
    }
    
    // Echange de deux points dans le tableau
    static void Echange(int a, int b) {
 Point p = P[a] ;
 P[a] = P[b] ;
 P[b] = p ;
    }
    
    // Recherche du point d'ordonnee minimale
    static int TrouveOrdonneeMinimum() {
 int min = 0 ;
 for (int i = 0 ; i < max ; ++i)
     if (P[i].v < P[min].v)
  min = i ;
 return min ;
    }
    
    // Calcul de l'angle entre deux points et l'horizontale
    static double Angle(Point p, Point q) {
 double angle = Math.atan2(q.v - p.v, q.h - p.h) ;
 if (angle < 0)
     angle += 2.0 * Math.PI ;
 return 180.0 * angle / Math.PI ;
    }
    
    // Calcul de l'enveloppe convexe par l'algorithme du cordeau
    static int Wrap() {
 int min = TrouveOrdonneeMinimum() ;
 // place une sentinelle
 P[max]= P[min] ;
 double angle = 0.0 ;
 for (int j = 0 ; j < max ; ++j) {
     Echange(j, min) ;
     min = max ;
     double am = angle ;
     angle = 360.0 ;
     for (int k = j + 1 ; k <= (j == 0 ? max - 1 : max) ; ++k)
  if (Angle(P[j], P[k]) >= am)
      if (Angle(P[j], P[k]) < angle) {
   min = k ;
   angle = Angle(P[j], P[k]) ;
      }
     if (min == max)
  return j ;
 }
 return max ;
    }

    // Tri du tableau par selection en fonction des angles
    static void Tri_Tableau() {
 for (int i = 1 ; i < max - 1 ; ++i) {
     int m = i ;
     for (int j =  i + 1 ; j < max ; ++j) {
  if (Angle(P[0], P[m]) > Angle(P[0], P[j]))
      m = j ;
     }
     Echange(i, m) ;
 }
    }

    // Calcul de l'enveloppe convexe par le balayage de Graham
    static int[] Graham() {
 // Recherche du point d'ordonnee minimale et tri du tableau selon les angles
 int min = TrouveOrdonneeMinimum() ;
 Echange(min, 0) ;
 Tri_Tableau() ;

 // Parcours du tableau avec creation d'un tableau auxiliaire
 int [] tableau = new int[max + 1] ;
 for (int i = 0 ; i < max ; ++i) 
     tableau[i] = -1 ;
 tableau[0] = 0 ;
 tableau[1] = 1 ;
 int m = 2, n = 2 ;
 while (m < max) {
     tableau[n] = m ;
     while (Angle(P[tableau[n - 1]], P[tableau[n]]) < Angle(P[tableau[n - 2]], P[tableau[n - 1]])) {
  tableau[n - 1] = tableau[n] ;
  tableau[n] = -1 ;
  n-- ;
     }
     m++ ;
     n++ ;
 }
 System.out.println(m) ;
 tableau[n] = 0 ;
 return tableau ;
    }
    
    // Intialisation du graphique
    static void Init_graphique() {
 MacLib.InitQuickDraw() ;
 MacLib.ShowDrawing() ;
 Rect r = new Rect() ;
 r. top = 100 ;
 r.left = 100 ;
 r.bottom = 350 ;
 r.right = 350 ;
 MacLib.SetDrawingRect(r) ;
    }
    
    // Affichage des points et de l'enveloppe calculee par le cordeau
    static void Affichage(int nb) {
 for (int i = 0 ; i < max ; ++i)
     MacLib.PaintCircle(P[i].h, P[i].v, 2) ;
 MacLib.MoveTo(P[0].h, P[0].v) ;
 for (int j = 1 ; j <= nb ; ++j)
     MacLib.LineTo(P[j].h, P[j].v) ;
 MacLib.LineTo(P[0].h, P[0].v) ;
 MacLib.WaitClickDown();
 System.exit(0) ;
    }    
    
    // Affichage des points et de l'enveloppe calculee par balayage
    static void Afficher(int[] tableau) {
 for (int i = 0 ; i < max ; ++i)
     MacLib.PaintCircle(P[i].h, P[i].v, 2) ;
 MacLib.MoveTo(P[0].h, P[0].v) ;
 int j = 1 ;
 while (j < max && tableau[j] != -1) {
     MacLib.LineTo(P[tableau[j]].h, P[tableau[j]].v) ;
     ++j ;
 }
 MacLib.LineTo(P[0].h, P[0].v) ;
 MacLib.WaitClickDown();
 System.exit(0) ;
    }    
    
    // La fonction principale
    public static void main(String[] arg) {
 // Determination du nombre max de points
 if (arg.length == 0)
     max = 100 ;
 else if (arg.length == 1)
     max = Integer.valueOf(arg[0]).intValue() ;
 else {
     System.out.println("Utilisation : java enveloppe_convexe nb_points\n") ;
     System.exit(0) ;
 }
 P = new Point[max + 1] ;

 // Initialisation des points
 Init_graphique() ;
 Initialise_souris() ;
 Afficher(Graham()) ;
 
 // Calcul de l'enveloppe
 //Affichage(Wrap()) ;

 
    }
}


This document was translated from LATEX by HEVEA.