précédent | suivant | table des matières
Algorithme
On commence par ordonner les points de l'ensemble par ordre croissant des abcisses, et pour des abcisses égales par ordre croissant des ordonnées.
Soient E1 et E2 les deux enveloppes convexes qu'on veut fusionner. On commence par choisir le point le plus à droite de E1 et le point le plus à gauche de E2. Le segment qui relie ces deux points va être mis en place, de façon à relier les deux enveloppes convexes. Sur l'exemple ce sont les opérations 1, puis 2, 3, 4, 5 et enfin 6. On fait de la même façon pour relier les deux enveloppes convexes par le bas. |
void partition(ArrayList<Point> lp, ArrayList<Point> env){ env.clear(); // ordonner les points par ordre croissant des abcisses Collections.sort(lp, new CompAbcs()); if(lp.size()<=3) { env.addAll(lp); if( lp.size()==3 && surface(env.get(0), env.get(1), env.get(2))>0){ Point p = env.get(1); env.remove(p); env.add(p); } return; } //On divise en deux ArrayList<Point> e1 = new ArrayList<Point>(); ArrayList<Point> e2 = new ArrayList<Point>(); for(int i = 0; i<lp.size()/2; ++i) e1.add(lp.get(i)); for(int i = lp.size()/2; i<lp.size(); ++i) e2.add(lp.get(i)); // On calcule les enveloppes de chaque morceau ArrayList<Point> env1 = new ArrayList<Point>(); ArrayList<Point> env2 = new ArrayList<Point>(); partition(e1, env1); partition(e2, env2); // et on fusionne ! env.addAll( fusion(env1, env2) ); } ArrayList<Point> fusion(ArrayList<Point> e1, ArrayList<Point> e2){ // recherche du point d'abcisse le plus grand dans e1; int iMax = 0; for( int i = 1; i < e1.size(); ++i) if(e1.get(i).x > e1.get(iMax).x) iMax = i; // le point d'abcisse le plus petit dans e2 est en 0 int iMin = 0; // le segment du haut int ip1 = iMax; int ip2 = iMin; boolean b = true; while(b){ b = false; if(Algs.surface(e2.get(ip2), e1.get(ip1), e1.get((ip1+1)%e1.size()))>0){ ip1 = (ip1+1)%e1.size(); b = true; } if(Algs.surface(e1.get(ip1), e2.get(ip2), e2.get((ip2-1+e2.size())%e2.size()))<0){ ip2 = (ip2-1+e2.size())%e2.size(); b = true; } } // le segment du bas int im1 = iMax; int im2 = iMin; b = true; while(b){ b = false; if(Algs.surface(e2.get(im2), e1.get(im1), e1.get((im1-1+e1.size())%e1.size()))<0){ im1 = (im1-1+e1.size())%e1.size(); b = true; } if(Algs.surface(e1.get(im1), e2.get(im2), e2.get((im2+1)%e2.size()))>0){ im2 = (im2+1)%e2.size(); b = true; } } // fabrication de l'enveloppe ArrayList<Point> env = new ArrayList(); for( int i = 0; i<=im1; ++i) env.add(e1.get(i)); if(ip2==0){ for( int i = im2; i<e2.size(); ++i) env.add(e2.get(i)); env.add(e2.get(0)); } else for( int i = im2; i<=ip2; ++i) env.add(e2.get(i)); if(ip1!=0) for( int i = ip1; i<e1.size(); ++i) env.add(e1.get(i)); return env; }
Estimation
Le tri de l'ensemble est en n×log(n). La fusion est une opération de coût n. Le coût total est donc en n×log(n).