diff --git a/TP5/README.md b/TP5/README.md new file mode 100644 index 0000000000000000000000000000000000000000..868ad3e68094b8432d4ed9d6115c2694b27f5f7e --- /dev/null +++ b/TP5/README.md @@ -0,0 +1,18 @@ +# Visualisation processing + +## TP1 +**Enoncé du tp : http://malacria.com/teachings/RVA/visualisation/tpvisu1.html** + + +## TP2 +**Enoncé du tp : http://malacria.com/teachings/RVA/visualisation/tpvisu2.html** + +### Définir les marques + +Nous choisisons les attributs "population" et "altitude" pour encoder visuellement les villes. Voici comment nous pourrions associer une variable rétinienne à chaque attribut : + +- Population : la variable rétinienne associée à la population sera la taille du marqueur. Ainsi, une ville avec une population plus élevée aurait une marque plus grande qu'une ville avec une population plus faible. + +- Altitude : la variable rétinienne associée à l'altitude sera la couleur du marqueur. Par exemple, les villes ayant une altitude plus élevée seront représentées par des marqueurs jaunes à rouge, tandis que les villes ayant une altitude plus basse seront représentées par des marqueurs bleus. + +On met en place aussi un histogramme des valeurs de population, c'est-à -dire le nombre de valeurs appartenant à chaque intervalle de l'axe afin d'améliorer la visualisation des données. diff --git a/TP5/sketch_240321a/City.pde b/TP5/sketch_240321a/City.pde new file mode 100644 index 0000000000000000000000000000000000000000..eaa47676d6259ee12b8acd7981fafde2f0752ed7 --- /dev/null +++ b/TP5/sketch_240321a/City.pde @@ -0,0 +1,36 @@ +class City { + int postalcode; + String name; + float x; + float y; + float population; + float density; + float altitude; + + // put a drawing function in here and call from main drawing loop } + public City(String postalcode, String name, float x, float y, float population, float surface, float altitude) { + this.postalcode = Integer.parseInt(postalcode); + this.name = name; + this.x = x; + this.y = y; + this.population = population; + this.density = population/surface ; + this.altitude = altitude; + } + + void draw() { + //map the altitude to the color in porcentage + float porcentageAlt = map(this.altitude, minAltitude, maxAltitude, 0, 100); + float hue = getColorForAltitude(porcentageAlt); + + // Set marker size based on population + float size = map(this.population, minPopulation, maxPopulation, 3, 100); + + // Draw marker + fill(hue, 100, 100); + ellipse(x, y, size, size); +} + + +} + diff --git a/TP5/sketch_240321a/ColorPalette.pde b/TP5/sketch_240321a/ColorPalette.pde new file mode 100644 index 0000000000000000000000000000000000000000..0db55417eb72e87a99d1b65165a01eaa12cff413 --- /dev/null +++ b/TP5/sketch_240321a/ColorPalette.pde @@ -0,0 +1,3 @@ +float getColorForAltitude(float altitude) { + return map(altitude, 0, 100, 230, -50); +} diff --git a/TP5/sketch_240321a/Legends.pde b/TP5/sketch_240321a/Legends.pde new file mode 100644 index 0000000000000000000000000000000000000000..8c4b5fe07d8c2cd02ddebe14df41732e94431088 --- /dev/null +++ b/TP5/sketch_240321a/Legends.pde @@ -0,0 +1,78 @@ +/** +* Creates legend for altitude values using a color gradient +*/ +void drawAltitudeLegend(float minVal, float maxVal, float x, float y, float w, float h) { + int barCount = 50; + float barWidth = w / barCount; + float highestBarHeight = h * 0.9; + + // Draw title + fill(0); + textAlign(CENTER, CENTER); + text("Altitude distribution", x + w / 2, y - 10); + + // Draw axis + stroke(0); + line(x, y + h, x + w, y + h); // x axis + + // Draw labels + fill(0); + textAlign(CENTER, CENTER); + text(minVal, x, y + h + 10); + text(maxVal, x + w, y + h + 10); + + // Draw bars + for (int i = 0; i < barCount; i++) { + float porcentageAlt = map(i, 0, barCount, 0, 100); + float hue = getColorForAltitude(porcentageAlt); + fill(hue, 100, 100); + noStroke(); + rect(x + i * barWidth, y, barWidth, highestBarHeight); + } +} + +void drawDistributionPopulationLegend(int minPopulation, int maxPopulation, float x, float y, float width, float height, int numberOfDiv, float[] populationValues) { + // Calcul de l'histogramme + int[] histogram = new int[numberOfDiv]; + for (int i = 0; i < populationValues.length; i++) { + int val = (int) map(populationValues[i], minPopulation, maxPopulation, 0, numberOfDiv); + if (val >= 0 && val < numberOfDiv) { + histogram[val]++; + } + } + + // Recherche du maximum de l'histogramme + int maxHistogram = 0; + for (int i = 0; i < histogram.length; i++) { + if (histogram[i] > maxHistogram) { + maxHistogram = histogram[i]; + } + } + + // Dessin de l'axe et des barres de l'histogramme + float binWidth = width / numberOfDiv; + + fill(220, 100, 100); + + for (int i = 0; i < numberOfDiv; i++) { + float currentX = x + i * binWidth; + float barHeight = map(histogram[i], 0, maxHistogram, 0, height); + rect(currentX, y - barHeight, binWidth, barHeight); + } + + // Dessin de la légende + + // Draw title + fill(0); + textAlign(CENTER, CENTER); + text("Distribution de la Population", x + width / 2, y + height + 10); + text(minPopulation, x, y + 10); + text(maxPopulation, x + width, y + 10); + + for (int i = 0; i <= numberOfDiv; i++) { + float value = map(i, 0, numberOfDiv, minPopulation, maxPopulation); // Valeur du label + String label = nf(value, 0, 0); // Formatage du label + float xPos = map(i, 0, numberOfDiv, 0, width); // Position x du label + line(x + xPos , y , x + xPos, y + 4); + } +} diff --git a/TP5/sketch_240321a/sketch_240321a.pde b/TP5/sketch_240321a/sketch_240321a.pde index e7a0a80b920e7d6f9325b18567a5c25a292812ec..9918691014d9d948702e84a22b4108b434cb85e6 100644 --- a/TP5/sketch_240321a/sketch_240321a.pde +++ b/TP5/sketch_240321a/sketch_240321a.pde @@ -10,27 +10,34 @@ int minAltitude, maxAltitude; int x = 1; int y = 2; -// and the tables in which the city coordinates will be stored -float xList[]; -float yList[]; +City cities[]; + +int legendsHeight=100; void setup() { - size(800,800); + size(900,900); readData(); } void draw(){ background(255); - color black = color(0); - for (int i = 0 ; i < totalCount ; ++i) { + for (int i = 0 ; i < totalCount - 2 ; ++i) { // draw a point at the coordinates of the city - float x = mapX(xList[i]); - float y = mapY(yList[i]); - stroke(black); - point(x, y); + cities[i].draw(); } updatePixels(); + + // Draw the distribution of the altitude values + float[] altitudeValues = new float[cities.length]; + for (int i = 0; i < cities.length - 2; i++) { + altitudeValues[i] = cities[i].altitude; + } + + if (legendsHeight > 0) { + drawLegend(); + } + } @@ -47,14 +54,15 @@ void readData() { parseInfo(lines[0]); // read the header line - xList = new float[totalCount]; - yList = new float[totalCount]; + cities = new City[totalCount]; for (int i = 2 ; i < totalCount ; ++i) { String[] columns = split(lines[i], TAB); - xList[i-2] = float (columns[x]); - yList[i-2] = float (columns[y]); + float pointX = float (columns[x]); + float pointY = float (columns[y]); + cities[i-2] = new City(columns[0], columns[4], mapX(pointX), mapY(pointY), float (columns[5]), float (columns[6]), float (columns[7])); } + println("City list created: " + cities.length + " cities"); } @@ -81,3 +89,20 @@ float mapX(float x) { float mapY(float y) { return map(y, maxY, minY, 0, 800); } + +void drawLegend() { + float distributionX = 50; + float distributionY = height - legendsHeight; + float distributionWidth = width - 100; + float distributionHeight = 50; + drawAltitudeLegend(minAltitude, maxAltitude, distributionX, distributionY, distributionWidth, distributionHeight); + // get list of population values from the cities + float[] populationValues = new float[cities.length]; + for (int i = 0; i < cities.length - 2; i++) { + populationValues[i] = cities[i].population; + } + + int numberOfDiv = 30; + // draw the population distribution + drawDistributionPopulationLegend(minPopulation, maxPopulation, distributionX, distributionY, distributionWidth, distributionHeight, numberOfDiv, populationValues); +}