begin process at 2010 02 10 05:00:22
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Maths & Algorithmes

 > CALCUL DE L'ENVELOPPE CONVEXE D'UN NUAGE DE POINTS DANS UN PLAN

CALCUL DE L'ENVELOPPE CONVEXE D'UN NUAGE DE POINTS DANS UN PLAN


 Information sur la source

Note :
9 / 10 - par 1 personne
9,00 / 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10
Catégorie :Maths & Algorithmes Classé sous :nuage, convexe, stl, cpp, algorithme Niveau :Initié Date de création :14/12/2008 Date de mise à jour :15/12/2008 19:38:21 Vu :2 996

Auteur : Lucky92

Ecrire un message privé
Commentaire sur cette source (9)
Ajouter un commentaire et/ou une note

 Description

Cliquez pour voir la capture en taille normale
Cette source fournit la mise en oeuvre d'un algorithme pour le calcul de l'enveloppe convexe d'un nuage de points dans le plan.
L'algorithme utilisé est celui decrit dans le cours d'algorithmie de Gerard Berry du College de France, dont la video est disponible à l'adresse suivante :

http://www.college-de-france.fr/default/EN/all/ inn_tec2007/cours_n1_les_algorithmes.htm

Ce lien a été fourni par coucou747 lors d'une discussion sur le forum à l'endroit suivant :

http://www.cppfrance.com/forum/sujet-CALCULER-E NVELOPPE-CONVEXE-NUAGE-POINT-CPLUSPLUS_1241680.asp x

Source

  • /*_________________________________________________________________________________________
  • */
  • #include <iostream>
  • #include <fstream>
  • #include <list>
  • #include <vector>
  • #include <ctime>
  • #include <cmath>
  • /*_________________________________________________________________________________________
  • *//*!
  • * structure de base
  • */
  • struct point
  • {
  • double _x ;
  • double _y ;
  • };
  • /*_________________________________________________________________________________________
  • *//*!
  • * predicat qui de deux points renvoie le plus bas
  • */
  • bool le_plus_bas( const point & a , const point & b )
  • {
  • return a._y < b._y ;
  • }
  • /*_________________________________________________________________________________________
  • *//*!
  • * foncteur qui permet de classer deux points suivant l'angle entre l'axe des x et le vecteur
  • * forme par chacun des points et un p donne.
  • */
  • class sens_trigo
  • {
  • private:
  • point _p ;
  • public:
  • sens_trigo( const point & p )
  • :_p( p )
  • {}
  • bool operator()( const point & a , const point & b )
  • {
  • double tta_a = atan2( a._y - _p._y , a._x - _p._x ) ;
  • double tta_b = atan2( b._y - _p._y , b._x - _p._x ) ;
  • return tta_a > tta_b ;
  • }
  • };
  • /*_________________________________________________________________________________________
  • *//*!
  • * droite construite a partir de deux points
  • * dont l'equation est de la forme ax + by + c = 0
  • */
  • class droite
  • {
  • private:
  • double _a ;
  • double _b ;
  • double _c ;
  • public:
  • droite( const point & p1 , const point & p2 )
  • :_a( p2._y - p1._y )
  • ,_b( -p2._x + p1._x )
  • ,_c( p1._y * p2._x - p1._x * p2._y )
  • {}
  • /*!
  • * Renvoie true si p1 et p2 sont du meme cote de la droite,
  • * c'est-a-dire si le signe de ax + by + c pour chacun des points est le meme
  • */
  • bool meme_cote( const point & p1 , const point & p2 )
  • {
  • return ( _a * p1._x + _b * p1._y + _c ) * ( _a * p2._x + _b * p2._y + _c ) > 0 ;
  • }
  • };
  • /*_________________________________________________________________________________________
  • *//*!
  • * algorithme de calcul de l'enveloppe
  • */
  • std::vector< point > enveloppe( std::list< point > nuage )
  • {
  • //Recherche du point le plus bas
  • nuage.sort( le_plus_bas ) ;
  • point bas = nuage.front() ;
  • nuage.pop_front();
  • //Tri du reste du nuage en fonction des angles par rapport au point le plus bas
  • nuage.sort( sens_trigo( bas ) ) ;
  • //On place le point le plus bas dans l'enveloppe
  • std::vector< point > env ;
  • env.push_back( bas ) ;
  • //On replace egalement le point le plus bas a la fin du nuage
  • nuage.push_back( bas ) ;
  • //Tant qu'il y a des points dans le nuage...
  • while ( !nuage.empty() )
  • {
  • //On retire le premier point du nuage et on le place dans l'enveloppe
  • env.push_back( nuage.front() ) ;
  • nuage.pop_front() ;
  • //Tant qu'il y a au moins 4 points dans l'enveloppe...
  • while ( env.size() >= 4 )
  • {
  • size_t n = env.size() - 1 ;
  • const point & b = env[ n ] ;
  • const point & p2 = env[ n - 1 ] ;
  • const point & p1 = env[ n - 2 ] ;
  • const point & a = env[ n - 3 ] ;
  • //Si les points a et b sont du meme cote que la droite passant par p1 et p2
  • if ( ! droite( p1 , p2 ).meme_cote( a , b ) )
  • {
  • env.erase( env.begin() + n - 1 ) ;
  • }
  • else
  • {
  • //sinon on quitte la boucle
  • break ;
  • }
  • }
  • }
  • return env ;
  • }
  • /*_________________________________________________________________________________________
  • *//*!
  • * programme illustrant l'utilisation de l'algorithme
  • */
  • int main()
  • {
  • //generation d'un nuage de points
  • srand( (unsigned int) time( 0 ) ) ;
  • std::list< point > nuage( 100 ) ;
  • {
  • std::list< point >::iterator it ;
  • for ( it = nuage.begin() ; it != nuage.end() ; ++it )
  • {
  • it->_x = rand() % 1000 ;
  • it->_y = rand() % 1000 ;
  • }
  • }
  • //enregistrement du nuage dans un fichier csv
  • {
  • std::ofstream ofs( "nuage.csv" ) ;
  • std::list< point >::iterator it ;
  • for ( it = nuage.begin() ; it != nuage.end() ; ++it )
  • {
  • ofs << it->_x << ";" << it->_y << std::endl ;
  • }
  • ofs.close() ;
  • }
  • //execution de l'algorithme
  • std::vector< point > env = enveloppe( nuage ) ;
  • //enregistrement de l'enveloppe dans un fichier csv
  • {
  • std::ofstream ofs( "enveloppe.csv" ) ;
  • std::vector< point >::iterator it ;
  • for ( it = env.begin() ; it != env.end() ; ++it )
  • {
  • ofs << it->_x << ";" << it->_y << std::endl ;
  • }
  • ofs.close() ;
  • }
  • }
  • /*_________________________________________________________________________________________
  • */
/*_________________________________________________________________________________________
*/
#include <iostream>
#include <fstream>
#include <list>
#include <vector>
#include <ctime>
#include <cmath>
/*_________________________________________________________________________________________
*//*!
* structure de base
*/
struct point
{
	double _x ;
	double _y ;
};
/*_________________________________________________________________________________________
*//*!
* predicat qui de deux points renvoie le plus bas
*/
bool le_plus_bas( const point & a , const point & b )
{
	return a._y < b._y ;
}
/*_________________________________________________________________________________________
*//*!
* foncteur qui permet de classer deux points suivant l'angle entre l'axe des x et le vecteur
* forme par chacun des points et un p donne.
*/
class sens_trigo
{
private:
	point _p ;

public:
	sens_trigo( const point & p )
		:_p( p )
	{}
	bool operator()( const point & a , const point & b )
	{
		double tta_a = atan2( a._y - _p._y , a._x - _p._x ) ;
		double tta_b = atan2( b._y - _p._y , b._x - _p._x ) ;
		return  tta_a > tta_b ;
	}
};
/*_________________________________________________________________________________________
*//*!
* droite construite a partir de deux points
* dont l'equation est de la forme ax + by + c = 0
*/
class droite
{
private:
	double _a ;
	double _b ;
	double _c ;

public:
	droite( const point & p1 , const point & p2 )
		:_a( p2._y - p1._y )
		,_b( -p2._x + p1._x )
		,_c( p1._y * p2._x - p1._x * p2._y )
	{}
	/*!
	* Renvoie true si p1 et p2 sont du meme cote de la droite,
	* c'est-a-dire si le signe de ax + by + c pour chacun des points est le meme
	*/
	bool meme_cote( const point & p1 , const point & p2 )
	{
		return ( _a * p1._x + _b * p1._y + _c ) * ( _a * p2._x + _b * p2._y + _c ) > 0 ;
	}
};
/*_________________________________________________________________________________________
*//*!
* algorithme de calcul de l'enveloppe
*/
std::vector< point > enveloppe( std::list< point > nuage )
{
	//Recherche du point le plus bas
	nuage.sort( le_plus_bas ) ;
	point bas = nuage.front() ;
	nuage.pop_front();

	//Tri du reste du nuage en fonction des angles par rapport au point le plus bas
	nuage.sort( sens_trigo( bas ) ) ;

	//On place le point le plus bas dans l'enveloppe
	std::vector< point > env ;
	env.push_back( bas ) ;

	//On replace egalement le point le plus bas a la fin du nuage
	nuage.push_back( bas ) ;

	//Tant qu'il y a des points dans le nuage...
	while ( !nuage.empty() )
	{
		//On retire le premier point du nuage et on le place dans l'enveloppe
		env.push_back( nuage.front() ) ;
		nuage.pop_front() ;

		//Tant qu'il y a au moins 4 points dans l'enveloppe...
		while ( env.size() >= 4 )
		{
			size_t n = env.size() - 1 ;
			const point & b = env[ n ] ;
			const point & p2 = env[ n - 1 ] ;
			const point & p1 = env[ n - 2 ] ;
			const point & a = env[ n - 3 ] ;

			//Si les points a et b sont du meme cote que la droite passant par p1 et p2
			if ( ! droite( p1 , p2 ).meme_cote( a , b ) )
			{
				env.erase( env.begin() + n - 1 ) ;
			}
			else
			{
				//sinon on quitte la boucle
				break ;
			}
		}
	}
	return env ;
}
/*_________________________________________________________________________________________
*//*!
* programme illustrant l'utilisation de l'algorithme
*/
int main()
{
	//generation d'un nuage de points
	srand( (unsigned int) time( 0 ) ) ;

	std::list< point > nuage( 100 ) ;
	{
		std::list< point >::iterator it ;
		for ( it = nuage.begin() ; it != nuage.end() ; ++it )
		{
			it->_x = rand() % 1000 ;
			it->_y = rand() % 1000 ;
		}
	}

	//enregistrement du nuage dans un fichier csv
	{
		std::ofstream ofs( "nuage.csv" ) ;
		std::list< point >::iterator it ;
		for ( it = nuage.begin() ; it != nuage.end() ; ++it )
		{
			ofs << it->_x << ";" << it->_y << std::endl ;
		}
		ofs.close() ;
	}

	//execution de l'algorithme
	std::vector< point > env = enveloppe( nuage ) ;

	//enregistrement de l'enveloppe dans un fichier csv
	{
		std::ofstream ofs( "enveloppe.csv" ) ;
		std::vector< point >::iterator it ;
		for ( it = env.begin() ; it != env.end() ; ++it )
		{
			ofs << it->_x << ";" << it->_y << std::endl ;
		}
		ofs.close() ;
	}
}
/*_________________________________________________________________________________________
*/

 Conclusion

Vos suggestions, remarques, et questions sont les bienvenues !


 Historique

14 décembre 2008 21:34:01 :
ajout snapshot
15 décembre 2008 19:38:21 :
mise à jour du lien de la video

 Sources de la même categorie

Source avec Zip OPERATION SUR LES MATRICES CARREES AVEC CLASSE GENERIQUE par chouhad
Source avec une capture OPÉRATIONS SUR MATRICES C++ par Minilogus
[DEV-C++] CALCUL DE LA RACINE CARRÉE D'UN RÉEL par Jhep
PROGRAMME QUI CALCUL LE PPCM ET LE PGCD par AnoSantino
EVALUER UNE EXPRESSION MATHÉMATIQUE par begueradj

 Sources en rapport avec celle ci

Source avec Zip CALLOCATOR par troctsch
Source avec Zip Source avec une capture RESOLUTION DE SYSTEME LINEAIRE PAR LA METHODE DU GRADIENT CO... par zangul
Source avec Zip Source avec une capture JEU DU CONTRE LA MONTRE par verbatron
Source avec Zip ALGO : RESOLUTION "LE COMPTE EST BON" AVEC DES ARBRES BINAIR... par panini21
Source avec une capture MAP STL ET ARBRES ROUGES ET NOIRS par guill76

Commentaires et avis

Commentaire de pgl10 le 15/12/2008 18:01:22

L'adresse Internet de la conférence de Gérard Berry au Collège de France vient de changer. On peut la retrouver parmi l'ensemble des conférences référencées à : http://www.college-de-france.fr/default/EN/all/inn_tec2007/index.htm
  

Commentaire de Pistol_Pete le 15/12/2008 18:17:05

Salut

J'ai pas encore regardé ni le lien ni le code mais quelle est la complexité de cet algorithme?

A+

Commentaire de Lucky92 le 15/12/2008 19:54:16

Bonjour et merci pour l'intérêt que vous portez à cette source.

- J'ai mis à jour le lien de la vidéo, merci PLG10.

- l'algorithme a une complexité en O(N) ; ce qui est une bonne nouvelle !


Commentaire de Pistol_Pete le 15/12/2008 22:17:50

Houla o(N)!!!  Quoi qu'il arrive tu utilises un algo de tri donc c'est déjà o(nlogn). Pour moi il est impossible de faire ce problème en o(n).
Cependant, cela semble bien être un algo en o(nlogn), à confirmer.

Quel est le nom de la méthode utilisé?

A+

Commentaire de pgl10 le 15/12/2008 23:03:33

Le cours de Gérard Berry identifie une partie en o(nlogn) et deux autres en o(n). Globalement cet algorithme est donc bien en o(nlogn) comme signalé. Mais c'est déjà bien !

Commentaire de pgl10 le 15/12/2008 23:11:42

Le support du cours est à : http://www.college-de-france.fr/media/inn_tec2007/UPL15767_GBerryAlgorithmescours250108.pdf et fait 537 Ko

Commentaire de Lucky92 le 15/12/2008 23:26:50

Damned ! J'avais oublié le tri !
Merci pour le lien PGL10.

Commentaire de Pistol_Pete le 16/12/2008 11:45:56 9/10

Effectivement, j'ai testé l'algo et il est bien en n log(n). Il s'agit en fait de l'algo de Graham.

C'est un très bon algorithme mais c'est peu être pas le meilleur. Matlab implémente le Quick Hull par exemple. Le principe est très attractif et je pense que tu peux amélioré la vitesse de ton algo avec cette méthode.

Le principe: tu calcules les 4 points extrémaux de ton nuage de point (le point le plus à gauche, le plus à droite ,le plus en haut, et le plus en bas). Il forment donc un quadrilatère. Et tu supprimes tous les points qui sont dans ce quadrilatère par ce que tu es sure qu'ils ne font pas partie de l'enveloppe convexe.

Là tu as déjà supprimé une bonne partie des points...
Il doit y avoir beaucoup de doc sur cet algo.

Très bonne source 9/10. Je pense que tu aurais pu faire une petite interface graphique. Cela aurait été plus ludique.
A+

Commentaire de Lucky92 le 16/12/2008 19:02:50

Pistol_Pete , merci pour ta note. Je vais essayer de dégager un peu de temps pour prendre en compte tes deux excellentes suggestions.

 Ajouter un commentaire


Discussions en rapport avec ce code source dans le forum

Erreur: invalid use of `this' in non-member function & `int' is not an aggregate type [ par GrosTony ] Bonjour,J'ai un probl&#232;me avec une Classe C++, voici le trac&#233; des erreurs :$ makeg++ -c -O4 -W -g -Wall -o Nuage.o Nuage.cppNuage.cpp:4: ISO enveloppe convexe sous matlab [ par leo2bordo ] Bonjour, J'ai fait un programme qui crée un nuage de points, ensuite trace la triangulation de Delaunay a ce nuage de points, dessine l'enveloppe conv calculer une enveloppe convexe d'un nuage de point en c++ [ par fantome2040 ] Bonjour Comme il est ecrit dans le sujet je cherche un programme en C++ qui me permetrai de calculer une enveloppe convexe d'un nuage de point. Je GROS PROPLEMES POUR FAIRE RECONNAITRE UNE CLASSE DANS VISUALC++ 2008 Express [ par marius72 ] Bonsoir,ce message remplace celui que j'ai écrit précédemment,je vais écrire ma demande de façon plus concise et précise :je suis développeur de longu Aide pour un algorithme [ par ashlee14 ] Bonjour, etant débutante en C je voudrais savoir si quelqu'un peut me dire les étapes que je dois faire pour réaliser l'algorithme suivant. Le but de Probleme d'inclusion de fichier (.hpp Vs .cpp)? [ par ano2345 ] Bonjour a tous,Je suis en train de developper sous Dev-C++ 4.9.9.2 une classe template MyVector basee sur la classe vector de telle maniere que je pui l'algorithme de trémaux [ par tchesa17 ] salut,je cherche un programme de l'algorithme de trémaux en c++, et merci de votre aide d'avance. Compilation + teste [ par nidhaletec ] je cherche a compiler cette bibliotheque: '' http://trac.openstreetmap.org/browser/applications/lib/libosm " et puis tester les programmes test1.cpp, Dev-Cpp [ par marcotte ] Bonjour à tous(tes)Comme débutant, j'avais laissé tombé la programmation C/C++ depuis 2000 (je crois ?) et je voulais m'y remettre avec Dev-Cpp mais l ALGORITHME DE CLARKE AND WRIGHT [ par maynot09 ] bonjour, Je suis à la recherche du code ou l'algorithme de Clarke and wright  proposé pour le problème du tournées de véhicules avec flotte hétérogéne


Nos sponsors


Sondage...

Comparez les prix

CalendriCode

Février 2010
LMMJVSD
1234567
891011121314
15161718192021
22232425262728

Consulter la suite du CalendriCode

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,702 sec (4)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales