Skip to content

Commit

Permalink
iNIT
Browse files Browse the repository at this point in the history
  • Loading branch information
Volko76 authored Apr 3, 2024
0 parents commit fa2440b
Show file tree
Hide file tree
Showing 31 changed files with 205,591 additions and 0 deletions.
100 changes: 100 additions & 0 deletions 10x10.poly
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
0 0 0
0 0 1
0 0 2
0 0 3
0 0 4
0 0 5
0 0 6
0 0 7
0 0 8
0 0 9
0 1 9
0 2 9
0 3 9
0 4 9
0 5 9
0 6 9
0 6 8
0 5 8
0 4 8
0 3 8
0 2 8
0 1 8
0 1 7
0 1 6
0 1 5
0 1 4
0 1 3
0 1 2
0 1 1
0 2 1
0 3 1
0 3 2
0 2 2
0 2 3
0 2 4
0 2 5
0 2 6
0 2 7
0 3 7
0 4 7
0 5 7
0 6 7
0 7 7
0 7 6
0 7 5
0 7 4
0 7 3
0 7 2
0 6 2
0 5 2
0 4 2
0 4 1
0 5 1
0 6 1
0 7 1
0 8 1
0 8 2
0 8 3
0 8 4
0 8 5
0 8 6
0 8 7
0 8 8
0 7 8
0 7 9
0 8 9
0 9 9
0 9 8
0 9 7
0 9 6
0 9 5
0 9 4
0 9 3
0 9 2
0 9 1
0 9 0
0 8 0
0 7 0
0 6 0
0 5 0
0 4 0
0 3 0
0 2 0
0 1 0
1 3 3
1 4 3
1 5 3
1 6 3
1 6 4
1 6 5
1 6 6
1 5 6
1 4 6
1 3 6
1 3 5
1 4 5
1 5 5
1 5 4
1 4 4
1 3 4
42 changes: 42 additions & 0 deletions GUI_figure.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import colorsys

# Parse les données
data = [line.split() for line in open("randomly_generated.poly").read().split("\n") if line]
polygons = {}
points = {}
colors = {}
for line in data:
poly_id, x, y = line
poly_id = int(poly_id)
x, y = float(x), float(y)
point_id = f"{poly_id}.{len(polygons.get(poly_id, []))}"
points[point_id] = (x, y)
polygons.setdefault(poly_id, []).append(point_id)
colors.setdefault(poly_id, None)

# Génère des couleurs uniques pour chaque polygone
for poly_id in colors:
hue = poly_id / len(colors)
color = colorsys.hsv_to_rgb(hue, 1, 1)
colors[poly_id] = color

# Crée la figure et l'axe
fig, ax = plt.subplots()

# Dessine les polygones et les points
for poly_id, point_ids in polygons.items():
color = colors[poly_id]
x, y = zip(*[points[point_id] for point_id in point_ids])
poly = patches.Polygon([(x[i], y[i]) for i in range(len(x))], closed=True, facecolor=color, edgecolor=color, alpha=0.5)
ax.add_patch(poly)
ax.text(x[0], y[0]+ 0.5, f"Polygone {poly_id}", ha="center", va="center", color=color)
for point_id in point_ids:
x, y = points[point_id]
ax.scatter(x, y, color=color)
ax.text(x, y + 0.05, point_id, ha="center", va="bottom", color=color) # Ajoute un décalage de 0.05 à la coordonnée y de l'étiquette

# Ajuste les limites et affiche la figure
plt.axis("scaled")
plt.show()
108 changes: 108 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
---
editor_options:
markdown:
wrap: 72
---

# Test 1

![Illustration](art.png)

On s'intéresse à l'inclusion de polygones.

Le sujet n'est pas compliqué :

- on prend en entrée un ensemble de polygones simples
- on affiche sur la sortie standard quel polygone est inclus dans quel
autre polygone

## Entrée

On récupère en entrée un ensemble de polygones à partir d'un fichier
*.poly*. Ce format de fichier texte est basé sur le principe suivant :

- chaque ligne est constituée de 3 éléments séparés par un ou
plusieurs espaces : un entier, un flottant, un flottant
- les deux flottants forment les coordonnées *x* et *y* d'un point
- l'entier en début de ligne indique à quel polygone ce point est
rajouté, en partant de 0
- l'ordre des lignes du fichier indique l'ordre des points des
polygones
- les indices des polygones sont consécutifs (tous les points du
polygone 0, puis tous les points du polygone 1, ...)

Au chargement, chaque fichier est converti en un vecteur de polygones.

À noter qu'il n'y a **jamais** d'intersection de segments entre deux
polygones différents. Au sein d'un même polygone seuls les segments
consécutifs s'intersectent et uniquement à leurs extrémités.

## Détection d'inclusion

Pour ce projet, on ne vous donne pas d'algorithme complet. Néanmoins, un
des algorithmes de base qu'il vous faudra implémenter consiste à
détecter si un point est à l'intérieur d'un polygone. On peut y arriver
en *partant* du point dans une direction arbitraire et en comptant le
nombre de segments du polygone traversés sur notre chemin. Si c'est
impair le point est à l'intérieur sinon à l'extérieur. Pour essayer
d'éviter les problèmes liés aux erreurs d'arrondi et simplifier les
calculs, le mieux est d'avancer verticalement ou horizontalement.

Pour plus d'info voir
[wikipedia](https://en.wikipedia.org/wiki/Point_in_polygon)

## Sortie

En sortie on vous demande d'afficher sur la sortie standard le vecteur
indiquant quel polygone est inclus (directement) dans quel autre
polygone. On identifie chaque polygone par son numéro. Comme tout
polygone ne peut être inclus (directement) que dans au plus un autre
polygone, il suffit pour stocker la solution d'associer à chaque
polygone l'indice de son père ou *-1* s'il n'en a aucun. Le plus simple
est alors de stocker cette information dans un vecteur tel que la ième
case contient le père du ième polygone.

Par exemple le fichier *10x10.poly* fourni contient les deux polygones
ci-dessous :

![polys](c10x10.png)

Le polygone 0 est affiché en rouge et le polygone 1 en vert. Comme le
vert est inclus dans le rouge et que le rouge n'est inclus dans personne
la solution est le vecteur [-1, 0].

Afficher la solution consiste simplement à faire un *print* de ce
vecteur ce qui est d'ailleurs déjà réalisé ligne 30 du fichier *main.py*
fourni.

Second exemple, le fichier *e2.poly* suivant (0 est rouge, 1 est vert, 2
est bleu, 3 est violet): ![polys](e2.png)

a pour solution : [1, -1, 0, 0]

## Code fourni

On vous fourni un petit module de géométrie : *geo*.

Celui-ci contient toutes les classes de base (points, segments,
polygones) ainsi qu'un module d'affichage à base de *tycat*. Tous les
objets de base sont affichables ainsi que les itérables et itérateurs
sur des objets de base. Vous pouvez voir comment ça fonctionne en
examinant les fichiers *hello.py* et *tycat.py*.

Le fichier *main.py* est important car il sera utilisé pour les tests
automatiques. Vous pouvez (devez) le modifier mais attention ! Il faut
respecter la sémantique : la sortie standard doit contenir exactement
une ligne par fichier donné en argument, dans l'ordre donné. Chaque
ligne est un *print* d'un vecteur d'entiers.

On vous demande d'interpréter ce que vous voyez et de faire le lien avec
la théorie. C'est la partie la plus importante du rapport. En plus de
ça, nous sommes intéressés par :

- plusieurs algos
- comparaisons expérimentale d'algos
- lien entre algo et entrée (sous quelle condition sur une entrée un
algo marche)
- les générateurs d'entrée (comment ils sont construits, pour quelle
raison)
Binary file added __pycache__/tycat.cpython-39.pyc
Binary file not shown.
Binary file added art.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added c10x10.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions complex_poly.poly
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
0 0 0
0 0 5
0 5 5
0 5 0
1 1 1
1 1 4
1 4 4
1 4 1
2 2 2
2 2 3
2 3 3
2 3 2
Binary file added e2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 14 additions & 0 deletions e2.poly
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
0 1 1
0 5 1
0 5 5
0 1 5
1 0 0
1 6 0
1 6 6
1 0 6
2 2 2
2 2 3
2 3 2
3 4 4
3 4 3
3 3 4
Empty file added empty_poly.poly
Empty file.
64 changes: 64 additions & 0 deletions generate_test_files.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import random

def generate_test_file(name, polygons):
"""
Generate a test file with polygons in .poly
"""
test_file = name + ".poly"
with open(test_file, 'w') as f:
to_write = ""
for i, polygon in enumerate(polygons):
for point in polygon:
to_write += f"{i} {point[0]} {point[1]} \n"
f.write(to_write)


def generate_random_polygons(n, m, min_coord, max_coord):
"""
Generate n random polygons, each with m random points within the specified coordinate range.
"""
polygons = []
for _ in range(n):
polygon = []
for _ in range(m):
x = random.randint(min_coord, max_coord)
y = random.randint(min_coord, max_coord)
point = [x, y]
polygon.append(point)
polygons.append(polygon)
return polygons


# Test Case 1: Single polygon
polygons_1 = [[[0, 0], [0, 5], [5, 5], [5, 0]]]
generate_test_file("single_poly",polygons_1)

# Test Case 2: Multiple polygons
polygons_2 = [[[0, 0], [0, 5], [5, 5], [5, 0]], [[1, 1], [1, 4], [4, 4], [4, 1]]]
generate_test_file("mutliple_poly", polygons_2)

# Test Case 3: Empty polygon
polygons_3 = [[]]
generate_test_file("empty_poly",polygons_3)

# Test Case 4: Complex polygons
polygons_4 = [
[[0, 0], [0, 5], [5, 5], [5, 0]],
[[1, 1], [1, 4], [4, 4], [4, 1]],
[[2, 2], [2, 3], [3, 3], [3, 2]]
]
generate_test_file("complex_poly",polygons_4)

# Test Case 5: Large number of polygons
polygons_5 = [[[i, i], [i, i + 1], [i + 1, i + 1], [i + 1, i]] for i in range(1000)]
generate_test_file("large_poly",polygons_5)


# Générer n polygones de m points de manière aléatoire
n = 4000
m = 50
min_coord = -100000000
max_coord = 100000000
polygons = generate_random_polygons(n, m, min_coord, max_coord)

generate_test_file("randomly_generated", polygons)
Binary file added geo/__pycache__/point.cpython-39.pyc
Binary file not shown.
Binary file added geo/__pycache__/polygon.cpython-39.pyc
Binary file not shown.
Binary file added geo/__pycache__/quadrant.cpython-39.pyc
Binary file not shown.
Binary file added geo/__pycache__/segment.cpython-39.pyc
Binary file not shown.
Binary file added geo/__pycache__/tycat.cpython-39.pyc
Binary file not shown.
Loading

0 comments on commit fa2440b

Please sign in to comment.