Vous êtes sur la page 1sur 28

Affectation 1

Géométrie de calcul 2020


Ομάδα 10
Σουλούνιας Νικόλαος (sdi1600156)
Ιγιάμου Περισανίδης Σίμων (sdi1600051)
Table des matières
Exercice 1
Dépendances
Utilisation
Contexte
Approche
Exemple 1
Exemple 2
Exemple 3
Exemple 4

Exercice 2 - Points du réseau


Mise en œuvre
Instructions d’exécution
Dépendances
Idée de base et concept
Épreuves mathématiques

Exercice 3 - Coque convexe incrémentale


Dépendances
Utilisation
Contexte
Approche

Exercice 4 - Enveloppe-cadeau à coque convexe


Mise en œuvre
Instructions d’exécution
Dépendances
Idée de base et concept
Détails de la mise en œuvre

Références
Exercice 1

Implémenter un algorithme qui prend comme entrée trois points dans le plan.
vérifie que
ils forment un triangle et si l’intérieur du triangle contient l’origine (0, 0) ou
non.

Dépendances
Python 3.7.6

Utilisation
$ python q1/main.py

Contexte
● Trois points forment un triangle si l’aire de la forme qu’ils forment est > 0.
● Que A, B, C soient les sommets d’un triangle, et P un point. Que
A0,A1,A2,A3 soit la zone des triangles ABC, PBC, PAC, PAB
respectivement. Ensuite, le point P se trouve à l’intérieur du triangle ABC
iff A0 = A1+A2+A3.

Les déclarations sont triviales, donc aucune preuve n’est fournie.

Approche
Les énoncés susmentionnés sont traduits en code.

Pour vérifier si trois points forment un triangle, on utilise la fonction area() qui
calcule l’aire du triangle formé par les trois points
donnés. Si la valeur retournée est supérieure à zéro, alors
la réponse est oui. C’est exactement ce que la fonction
isTriangle() vérifie.
Pour le second problème, nous avons implémenté la fonction
containsOrigin() qui prend trois points en entrée et retourne true si le triangle
formé contient l’origine de l’axe. La façon dont il est fait est basée sur la deuxième
instruction d’en haut, en utilisant l’origine (0,0) comme point P. Initialement, les
zones des quatre triangles sont calculés. Si l’aire du grand triangle est égale à la
somme des aires des trois petits triangles, alors l’origine de l’axe est contenue dans
le triangle ABC.

Dans le script python, il y a quatre exemples qui montrent la fonctionnalité


des algorithmes.

Exemple 1

Les sommets C et B sont identiques, de sorte que la sortie attendue est que
les points A, B et C ne forment pas un triangle.

Exemple 2

Les sommets C sont dans la ligne AB, de sorte que la sortie attendue est encore
que les points A, B et C ne forment pas un triangle.
Exemple 3

Les sommets forment un triangle et aussi l’origine de l’axe y est contenue.

Exemple 4

Les sommets forment un triangle mais l’origine de l’axe y est contenue.


Exercice 2

Avec un cercle de rayon r dans le plan avec (0, 0) comme centre, implémenter
un
algorithme qui trouve les points du réseau total sur la circonférence. Treillis
Les points sont des points avec des coordonnées entières.

Mise en œuvre
lattice_points.py

Instructions d’exécution
$ python3 lattice.py

Lorsqu’il est exécuté, le programme attend que l’utilisateur insère la valeur du


rayon r. (Assurez-vous d’appuyer sur ENTER après avoir saisi le numéro que
vous voulez). Le rayon r doit être un nombre positif (flottant ou entier). Sinon, un
message d’erreur s’affiche et l’application se termine sans succès.

Si un nombre positif est donné comme rayon r, le programme trouve les points
de réseau du cercle, les imprime et les trace également dans une figure qui est
également enregistrée comme « lattice_points.png ». Pour terminer l’application,
l’utilisateur doit fermer la fenêtre de figure qui apparaît.

Dépendances
matplotlib (pip3 install matplotlib)

La bibliothèque est utilisée pour créer un tracé du cercle avec le centre (0,0) et le
rayon r et ses points en treillis. Le cercle est de couleur bleue et ses points en
treillis sont de couleur rouge. Les coordonnées du centre et des points du réseau
sont également imprimées dans le graphique.
Idée de base et concept
L’équation d’un cercle avec le centre (0,0) et le rayon r est la suivante :

Soit xL, yL soit les coordonnées d’un point de réseau (aléatoire) P du cercle. Puisque L est un

point du cercle :


En outre, par la définition des points de réseau :

Donc, une première approche du problème serait la suivante :

Lattice Points : 1re édition


pour x := -r à r :
y := r2 x2
si isInteger(y ) :
(x,y) est un point de réseau
si y>0 :
(x,-y) est un point de réseau

Dans la 1ère édition de l’algorithme des points de réseau, nous calculons dans la même répétition
si un point (x,y) et son point symétrique sur l’axe des x (x,-y) sont des points de réseau.

Ainsi, la 1ère édition de l’algorithme est basée sur l’implication suivante (symétrie du
cercle à travers l’axe des x) :

(x , y) est un point en treillis (x , y) est un point en treillis


Comme les valeurs données à x tout au long de la boucle sont des valeurs
entières, pour qu’un point (x,y) soit un point de réseau du cercle, nous devons
simplement vérifier que y est aussi un nombre entier.

Pour éviter de compter chacun des points (-r,0) et (r,0) deux fois, on vérifie si
y>0.

Comment pourrait-on améliorer cet algorithme ? Nous devrions réduire le


nombre de répétitions, donc le nombre de valeurs que nous vérifions pour
x.

Comment on va faire ça ? Nous profiterons de la symétrie du cercle sur l’axe y.

Lattice Points : 2e édition


pour x := 0 à r :
y := r2 x2
si isInteger(y ) :
(x,y) est un point de réseau
si x>0 :
(-x,y) est un point de
réseau si y> 0 :
(x,-y) est un point de réseau
si x>0 et y>0 :
(-x,-y) est un point en treillis

La 2ème édition de l’algorithme est basée sur l’implication suivante (symétrie du cercle sur l’axe
y) :

(x , y) est un point en treillis ( x , y) est un point de réseau


Pour éviter de compter chacun des points (-r,0), (r,0), (0,r) et (0,-r) deux fois,
on vérifie si x>0 et y>0 .
C’est le mieux qu’on puisse faire ? Nope.
La prochaine édition de l’algorithme de points de réseau est la suivante :

e édition
Lattice Points : 3
pour x := 0 au sol (r/ 2) :
x
y := r2 2
si isInteger(y ) :
(x,y) est un point de réseau
(y,x) est un point de réseau
(x,-y) est un point de réseau
(-y,x) est un point en treillis
si x>0 :
(-x,y) est un point de réseau
(y,-x) est un point de réseau
(-x,-y) est un point en treillis
(-y,-x) est un point en treillis

La 3ème édition de l’algorithme est basée sur l’implication suivante (symétrie du cercle à travers
la ligne y=x) :

(x , y) est un point en treillis (y, x) est un point de réseau

Ainsi, alors que dans la 2ème édition nous vérifiions un quatuor, dans la 3ème édition nous
vérifions une octante.

Il n’est pas nécessaire de vérifier si y>0 comme nous l’avons fait dans la 2ème
édition, puisque nous travaillons dans la 2ème octante, ce qui signifie que r / 2 y
r.
NOTA : Tous les chiffres qui sont représentés dans un ordinateur ont le
formulaire.
± 2e * nombre . Donc r sera un nombre rationnel positif.

Donc, en prenant cette note en considération, il n’est pas nécessaire d’éliminer


les doublons si un point réseau a y = r / 2 , simplement parce qu’il ne peut pas.
C’est parce que 2 est un nombre irrationnel, donc r / 2 est un nombre irrationnel,
pas un nombre entier.
Je dois également noter que le calcul de r/ 2 ne sera pas précis à 100 % (car 2
ne peut pas être représenté avec précision). Cependant, l’erreur de précision
de la borne n’est pas un problème pratique.

C’est le concept de l’algorithme. Cependant, il y a encore une


amélioration que nous pourrions apporter.

e édition
Lattice Points : 4
si isNotInteger(r) :
Il n’y a pas de réseau.
mettre fin à
pour x := 0 au sol (r/ 2) :
y := r2 x2
si isInteger(y) :
(x,y) est un point de réseau
(y,x) est un point de réseau
(x,-y) est un point de réseau
(-y,x) est un point en treillis
si x>0 :
(-x,y) est un point de réseau
(y,-x) est un point de réseau
(-x,-y) est un point en treillis
(-y,-x) est un point en treillis

La 4ème édition de l’algorithme est basée sur l’implication suivante :

et r représenté par un nombre fini de chiffres et


Nous sommes encore une fois basés sur le fait que le rayon donné ne peut pas
être un nombre irrationnel.
Épreuves mathématiques
Que (x , y) soit un point en treillis :

et

(x , y) est un point en treillis (x , y) est un point en treillis

Pour le point (x,-y) nous avons :

, ce qui signifie que (x,-y) est un point du cercle.

et

, depuis

Donc, le point (x,-y) est un point en treillis.

(x , y) est un point en treillis ( x , y) est un point de réseau

Pour le point (-x,y) nous avons :

, ce qui signifie que (-x,y) est un point du cercle.

et

, depuis

Donc, le point (-x,y) est un point en treillis.


(x , y) est un point en treillis (y, x) est un point de réseau

Pour le point (y,x) nous avons :

, ce qui signifie que (y,x) est un point du cercle.

et

Donc le point (y,x) est un point en treillis.

● et r représenté par un nombre fini de chiffres et


d soit le dernier chiffre non nul de la partie décimale de r. Ensuite

d2mod 10 = 0 (S)
depuis d2mod 10 sera dans la partie décimale de r2 , que nous voulons être
0.

❖ d = 1 d2 = 1 d2mod 10 = 1 =/ 0
❖ d = 2 d2 = 4 d2mod 10 = 4 =/ 0
❖ d = 3 d2 = 9 d2mod 10 = 9 =/ 0
❖ d = 4 d2 = 16 d2mod 10 = 6 =/ 0
❖ d = 5 d2 = 25 d2mod 10 = 5 =/ 0
❖ d = 6 d2 = 36 d2mod 10 = 6 =/ 0
❖ d = 7 d2 = 49 d2mod 10 = 9 =/ 0
❖ d = 8 d2 = 64 d2mod 10 = 4 =/ 0
❖ d = 9 d2 = 81 d2mod 10 = 1 =/ 0

Donc, d2mod 10 =/ 0 .

d2mod 10 =/ 0 ⇒
Est vrai comme le contre-positif de la phrase S.

Par conséquent, .
Étant donné que la multiplication est fermée dans l’ensemble et
.

Maintenant, laissez .

Depuis ajout est fermé dans l’ensemble et et et


contradiction Donc,

Maintenant, laissons
Puisque la multiplication est fermée dans
l’ensemble et .
contradiction Donc,
Exercice 3

Implémenter l’algorithme 2D incrémental pour calculer la coque convexe d’un


ensemble fini de points dans le plan.

Dépendances
● Python 3.7.6
● matplotlib
● numpy

Utilisation
$ python q3/main.py

Contexte
● La coque convexe d’une forme est le plus petit ensemble convexe qui la
contient. Il peut être visualisé comme la forme enfermée par un élastique
étiré autour d’un sous-ensemble délimité d’une planète.
● Algorithme convexe incrémental de coque idée de base : Tout d’abord
prendre un sous-ensemble de l’entrée assez petite pour que le
problème est facilement résolu. Puis, un par un, ajouter les éléments
restants tout en maintenant la solution à chaque étape.
● Tangente au Polygone : une ligne qui la touche sans franchir sa limite.
● Pour un polygone convexe, il y a exactement deux tangentes uniques
à partir d’un point en dehors du polygone.

Approche
Nous définissons une classe nommée Point dans Point.py, afin de représenter
les points dans le plan 2D.
L’algorithme est implémenté dans main.py. Dans le but de former l’ensemble
d’entrée, 20 points d’échantillonnage aléatoires sont créés.
Au départ, les points sont triés en fonction de leur coordonnée x. Ensuite, les
trois premiers points sont choisis de manière à commencer par un problème
trivial comme celui d’un triangle. Évidemment, la coque convexe d’un triangle
est composée de tous ses bords.

Ensuite, nous ajoutons le reste des points un par un. Pour chaque point P,
nous travaillons comme suit :

Trouver le point tangent supérieur du


point P à la coque convexe.

Recherchez la tangente inférieure, qui


tourne dans le sens horaire autour du
polygone convexe de la coque, en
commençant par la tangente supérieure.

Étendre la coque convexe pour contenir


le point P et les nouveaux bords (P V i et P V

k)

Notez que, lors de la recherche de la Tangente inférieure, les points qui sont
visités mais ne sont pas des points de tangence, sont retirés de la coque.

Maintenant on pourrait se demander, comment vérifiez-vous si un point est un


point de tangence supérieur/inférieur ou non ? Eh bien, c’est simple. Prenons
par exemple le sommet Vi. Afin de déterminer s’il s’agit du point de tangence
supérieur, nous pouvons vérifier si le point P est à droite du bord ei 1 et à
gauche du bord ei . L’inverse s’applique au point de tangence inférieur Vk.

En général, si P est à l’intérieur de ces deux bords, ou à l’extérieur des deux


bords, alors ces deux bords sont sur des côtés différents de PVi, et donc PVi ne
peut pas être une tangente. D’autre part, si P est à l’intérieur d’un bord et à
l’extérieur de l’autre, alors PVi est localement tangente au polygone à Vi.
Cette idée est implémentée par les fonctions

isUpperTangent(), isLowerTangent(), isLeftOf(),

isRightOf() .
En fin de compte, les points et la coque convexe sont tracés pour
nous donner une représentation visuelle des résultats.

Un exemple de graphique de sortie est le suivant.


Exercice 4

Mettre en œuvre l’algorithme d’emballage cadeau pour calculer la coque


convexe d’un ensemble fini de points dans le plan

Mise en œuvre
gift_wrap.py

Instructions d’exécution
$ python3 gift_wrap.py

Lorsqu’il est exécuté, le programme attend que l’utilisateur insère le nombre de


points 2D qui seront générés aléatoirement. (Assurez-vous d’appuyer sur
ENTER après avoir saisi le nombre que vous voulez). Le nombre donné doit
être un nombre entier positif. Sinon, un message d’erreur s’affiche et
l’application se termine sans succès.

Si un nombre positif est donné comme nombre de points 2D, le programme


génère ce nombre de points 2D. Ensuite, le programme trouve la coque
convexe des points à l’aide de l’algorithme d’emballage cadeau. Le programme
imprime les points générés, ainsi que les points de la coque convexe. Le
programme trace les points et la coque convexe dans une figure enregistrée
sous « gift_wrap.png ». Pour terminer l’application, l’utilisateur doit fermer la
fenêtre de figure qui apparaît.

Dépendances
● Python 3.6.9
● matplotlib (pip3 install matplotlib - vérifiez les dépendances de l’exercice 2
pour plus de détails)
● numpy (bibliothèque pré-installée)
● Sys (bibliothèque préinstallée)
Idée de base et concept
L’algorithme commence par trouver le point le plus à gauche dans les points
convexes de la coque. Si plusieurs points de l’ensemble ont la même
coordonnée minimale sur l’axe des x, nous choisissons parmi eux le point
avec la coordonnée minimale sur l’axe des y. Pour tout ensemble donné de
points, ce point appartiendra à la coque convexe de l’ensemble.

Ensuite, dans chaque itération, l’algorithme choisit un point qui n’a pas déjà été
placé dans la liste convexe de la coque. Ensuite, l’algorithme vérifie si ce point
est le prochain point du polygone convexe de la coque. Pour que cela soit vrai,
le nouveau point doit maximiser l’angle formé lorsqu’il est relié au point
précédent du polygone convexe de la coque. Comment on va vérifier ça ?
Supposons que r est le dernier point inséré dans le polygone convexe de la
coque et u est notre candidat pour le prochain point du polygone convexe de la
coque et t est un point aléatoire différent de u qui n’a pas non plus été inséré
dans la liste convexe de la coque.

Nous formons les vecteurs et . Pour maximiser l’angle, lorsque nous tournons
le vecteur vers la rotation doit être dans le sens inverse des aiguilles d’une
montre (CCW). Autrement,
l’angle formé lorsque t est choisi comme point suivant de la coque convexe est
plus grand. Donc, dans ce cas, nous définissons u = t. Si nous avons vérifié que
l’angle formé quand un point s est choisi est inférieur à l’angle formé quand u
est choisi, alors l’angle pour t sera plus grand que l’angle pour s. Donc, il n’est
pas nécessaire de vérifier deux points dans une seule itération de l’algorithme.

Now, a detail that we have to address is what happens when r,u,t are collinear.
Well, we just check if u is in the middle of them. If that’s the case we set u = t.
Otherwise we continue our search for the best candidate.

The algorithm terminates when u = r0 and the convex hull polygon is complete.
Check out the pseudocode for more details.
Convex Hull Gift Wrap Algorithm

Input: 2d_points (a list containing the 2d points of the


plane)
Output: convex_hull_list (a list of 2d points that form

the convex hull of all the points in the 2d_list)

if 2d_points contains 1 or 2 points:

convex_hull_list = 2d_points

return convex_hull_list

Find the left-most points in the 2d_list. If there are


multiple points with the same minimum x-coordinate,
choose the point with the minimum y-coordinate. Let r0
be the point we found.
convex_hull_list = [ r0 ]

unused_points_list = 2d_points (Notice we keep r0 in the

list)

u = None

while u != r0:

r = last element inserted in the convex_hull_list

u = unused_points_list[0]

counter = 1

si r == r0 et u == r0 :

u = unused_points_list[1]
counter = 2

while counter < #elements in unused_points_list:

t = unused_points_list [ counter ]

si r==r0 et t == r0 :

counter ++

Go to next repetition

if CW( r, u, t ) or (r,u,t are collinear and u

is between r and t):

u = t

counter ++

Remove point u from the unused_points_list.

si u != r0 :

Append u at the end of the convex_hull_list

return convex_hull_list

Implementation Details
There are 3 things I’d like to point out in my implementation:

● In the function ordered(point0, point1, point2) the 3 points passed


as arguments are supposed to be collinear. However, due to
arithmetical precision issues:

λA = (point2.y − point0.y)/(point1.y − point0.y)


and

λB = (point2.x − point0.x)/(point1.x − point0.x)

may not be equal as they should be.

So to assert that the points passed as arguments are, in fact,


collinear, I check whether:
15
|λΑ λΒ| < 10

−15
where 10 is the upper bound of the acceptable precision error.

● Instead of using a list for the unused_points_list of the pseudocode,


a set is used instead. That is because a deletion in a set has time
complexity O(1) compared to O(n) for a deletion in a list.

● An improvement compared to the pseudocode is that in one iteration more


points than one may be removed. That’s the case when the new point of
the convex hull has one or more collinear points.
References
● Lecture slides
● http://geomalgorithms.com/a15-_tangents.html

Vous aimerez peut-être aussi