Suite

ST_INTERSECT de chaque élément de deux tableaux (polygones, lignes)


Je suis nouveau sur postgis et j'essaie de résoudre le problème suivant :

J'ai deux tableaux : 1. contenant des polygones 2. contenant des lignes

J'ai besoin de trouver l'identifiant de tous les polygones sur chaque ligne et de les remplir dans de nouvelles colonnes. Ainsi, pour chaque intersection, il devrait y avoir une nouvelle colonne dans le tableau des lignes avec l'ID du polygone d'intersection. il n'y aura pas plus de trois polygones sur les lignes.

C'est le code que j'ai déjà, mais il ne donne que le premier polygone qui coupe la ligne.

SELECT a.osm_id, b.osm_id FROM lignes a LEFT JOIN polygons b ON ST_Intersects(b.way,a.way);


En partant du principe que les polygones ne seront jamais qu'à la fin des lignes, votre requête doit renvoyer chaque polygone de votre diagramme, mais pas dans le format que vous avez indiqué. Cela me fait penser que vous avez un petit écart entre votre polygone et la fin de la ligne. Je pense que la tolérance est de 0,00001 pour ST_Intersects.
Plutôt que d'utiliser ST_Intersects pour déterminer la relation, vous pouvez utiliser ST_Distance. Une autre option serait de tamponner légèrement la ligne (ou les extrémités) à l'aide de ST_Buffer. Le tampon est probablement la meilleure option en termes de performances.

Voici un exemple de requête pour récupérer les résultats comme vous l'avez indiqué

SELECT l.id Line_ID, p1.id Intersected_Polygons_id_1, p2.id Intersected_Polygons_id_2 FROM Lines l LEFT OUTER JOIN Polygons p1 ON ST_Intersects(p1.Geom, ST_Buffer(ST_StartPoint(l.Geom),0.05)) -- ST_Distance,(p1.Geom ST_StartPoint(l.Geom)) <= 0.05 LEFT OUTER JOIN Polygones p2 ON ST_Intersects(p2.Geom, ST_Buffer(ST_EndPoint(l.Geom),0.05)) -- ST_Distance(p2.Geom,ST_EndPoint(l.Geom)) < = 0,05 ;

J'ai également mis la clause de jointure ST_Distance en commentaire.

Éditer Selon vos commentaires, des polygones peuvent exister le long de la ligne. Il existe un certain nombre de façons de faire cette requête, mais à moins que vous ne connaissiez le nombre maximal d'intersections qui se produiront avec les lignes de sortie dans le format que vous avez spécifié, il sera difficile. Voici quelques options

-- Une ligne par intersection SELECT l.id line_id, p.id polygon_id FROM Lines l LEFT OUTER JOIN Polygons p ON ST_Intersects(p.Geom, ST_Buffer(l.Geom,0.05)); -- Une ligne par ligne avec un tableau d'identifiants d'intersections SELECT l.id line_id, array_agg(p.id) polygon_id FROM Lines l LEFT OUTER JOIN Polygons p ON ST_Intersects(p.Geom, ST_Buffer(l.Geom,0.05)) GROUP PAR l.id ; -- Requête croisée SELECT line_id, MAX(CASE WHEN r = 1 THEN polygon_id END) polygon_id_1, MAX(CASE WHEN r = 2 THEN polygon_id END) polygon_id_2, MAX(CASE WHEN r = 3 THEN polygon_id END) polygon_id_3, MAX(CASE WHEN r = 4 THEN polygon_id END) polygon_id_4, MAX(CASE WHEN r = 5 THEN polygon_id END) polygon_id_5 --… FROM ( SELECT l.id line_id, p.id polygon_id, ROW_NUMBER() OVER (PARTITION BY l.id ORDER BY p .id) r FROM Lines l LEFT OUTER JOIN Polygones p ON ST_Intersects(p.Geom, ST_Buffer(l.Geom,0.05)) ) a GROUP BY line_id;

La théorie des graphes a développé une représentation topologique et mathématique de la nature et de la structure des réseaux de transport. Cependant, la théorie des graphes peut être étendue à l'analyse de réseaux de transport réels et complexes en les codant dans un système d'information. Dans le processus, une représentation numérique du réseau est créée, qui peut ensuite être utilisée à diverses fins, telles que la gestion des livraisons ou la planification de la construction d'infrastructures de transport. Cette représentation numérique est très complexe car les données de transport sont souvent multimodales, peuvent couvrir plusieurs juridictions locales, nationales et internationales et ont des vues logiques différentes selon l'utilisateur particulier. Par ailleurs, alors que les infrastructures de transport sont des composants relativement stables, les véhicules sont des éléments très dynamiques.

Il devient ainsi de plus en plus pertinent d'utiliser un modèle de données où un réseau de transport peut être encodé, stocké, récupéré, modifié, analysé et affiché. De toute évidence, les systèmes d'information géographique (SIG) sont parmi les meilleurs outils pour créer, stocker et utiliser des modèles de données de réseau, qui font implicitement partie de nombreux SIG. Il existe quatre domaines d'application de base des modèles de données de réseau :

    . L'objectif principal d'un modèle de données de réseau est de fournir une représentation précise d'un réseau sous la forme d'un ensemble de liens et de nœuds. La topologie est la disposition des nœuds et des liens dans un réseau et leurs relations. Les représentations de l'emplacement, de la direction et de la connectivité sont particulièrement pertinentes, car différentes entités peuvent partager un point tel qu'une intersection de rue connectée à plusieurs lignes. Même si la théorie des graphes vise l'abstraction des réseaux de transport, la topologie d'un modèle de données de réseau doit être aussi proche que possible de la structure du monde réel qu'il représente. Cela est particulièrement vrai pour l'utilisation de modèles de données de réseau dans un SIG. (annotations). Permet la visualisation d'un réseau de transport à des fins de calcul et de navigation simple et sert à indiquer l'existence d'un réseau. Différents éléments du réseau peuvent avoir une symbolique définie par certains de leurs attributs. Par exemple, un tronçon d'autoroute peut être symbolisé par une ligne épaisse avec une étiquette telle que son numéro, tandis qu'une rue peut être symbolisée par une ligne simple sans étiquette. Le réseau symbolisé peut également être combiné avec d'autres fonctionnalités telles que des points de repère pour fournir un meilleur niveau d'orientation à l'utilisateur. C'est couramment le cas des cartes routières utilisées par le grand public. . Les modèles de réseaux de transport peuvent être utilisés pour dériver une localisation précise, notamment grâce à un système de référencement linéaire. Par exemple, la grande majorité des adresses sont définies selon un numéro et une rue. Si les informations d'adresse sont intégrées dans les attributs d'un modèle de données de réseau, il devient possible d'utiliser ce réseau pour le géocodage et de localiser l'emplacement d'une adresse, ou de tout emplacement le long du réseau, avec une précision raisonnable. et affectation. Les modèles de données de réseau peuvent être utilisés pour trouver des chemins optimaux et attribuer des flux avec des contraintes de capacité dans un réseau. Alors que le routage est concerné par le comportement spécifique d'un nombre limité de véhicules, l'affectation du trafic est principalement concernée par le comportement à l'échelle du système du trafic dans un réseau de transport. Cela nécessite une topologie dans laquelle la relation de chaque lien avec d'autres segments d'intersection est explicitement spécifiée. Des mesures d'impédance (par exemple la distance) sont également attribuées à chaque lien et auront un impact sur le chemin choisi ou sur l'affectation des flux dans le réseau. L'acheminement et l'affectation du trafic au niveau continental sont généralement simples car les petites variations d'impédance ont des conséquences limitées. L'affectation des itinéraires et du trafic dans une zone urbaine est beaucoup plus complexe car elle doit tenir compte des panneaux d'arrêt, des feux de circulation et des embouteillages pour déterminer l'impédance d'un itinéraire.

De B. Davis, SIG : Une approche visuelle, ©1996. Reproduit avec la permission de Onword Press, Santa Fe, NM.

De nombreuses organisations ont développé des progiciels pour l'analyse SIG. Les plus utilisés sont ARC/INFO (plateformes Unix et Windows NT) et ArcView (une version PC de bureau plus petite) commercialisés par l'Environmental Systems Research Institute (ESRI) de Redlands, Californie, une société fondée en 1969 par Jack et Laura Dangermond. Shane Murnion de l'Université Queens à Belfast, a créé un tutoriel pour l'utilisation d'ARC/INFO (http://boris.qub.ac.uk/shane/arc/ARChome.html). Un autre programme, appelé GRASS, a été développé par l'Army Corps of Engineers et, bien qu'ils ne le prennent plus en charge, vous pouvez en apprendre davantage sur cet outil sur GRASSLINKS de l'Université Baylor.

L'organigramme suivant décrit une conception générale du système pour les procédures et les étapes d'une routine de traitement de données SIG typique :

L'objectif de cette opération est d'assembler une base de données qui contient tous les ingrédients à manipuler, à travers des modèles et d'autres procédures de prise de décision, en une série de sorties pour l'effort de résolution de problèmes.

` <>`__15-12 : Dans le diagramme ci-dessus, l'une des entrées à la fin de la saisie des données est l'imagerie satellite. Faites une liste de certaines observations satellitaires qui conduisent à des informations pertinentes pour l'analyse SIG. `RÉPONSE <Sect15_answers.html#15-12>`__

Derrière cette table, sur laquelle nous montons une carte, se trouvent des fils électriques rapprochés disposés selon une grille que nous pouvons référencer en coordonnées x-y. L'opérateur (ici, Bill Campbell, chef, NASA GSFC Code 935, qui a rédigé le chapitre sur les SIG dans le manuel du didacticiel Landsat) place une rondelle mobile avec un réticule centré sur chaque point de la carte et clique sur un bouton pour entrer sa position, le long de avec un code numérique qui enregistre ses attributs dans une base de données informatique. Il passe ensuite au point suivant, répète le processus et entre une commande de lien.

Toute carte se compose de points, de lignes et de polygones qui localisent des points ou renferment des motifs (champs d'information) qui décrivent des attributs particuliers ou des catégories thématiques. Considérez cette situation qui fait référence à plusieurs champs (par exemple, différents types de couverture végétale) séparés par des limites linéaires :

` <>`__15-13 : Dans le diagramme ci-dessus, par inspection visuelle, décidez laquelle des deux méthodes de géocodage semble être la plus précise. `RÉPONSE <Sect15_answers.html#15-13>`__

De B.Davis, SIG : Une approche visuelle, ©1996. Reproduit avec la permission de Onword Press, Santa Fe, NM.

Chaque point a une valeur de coordonnée unique. Deux extrémités ou points de nœud définissent une ligne. Nous spécifions un polygone par une série de nœuds de connexion (deux lignes adjacentes partagent un nœud), qui doit se fermer (dans l'expérience de cet écrivain avec la numérisation, le principal écueil est que certains polygones ne se ferment pas, et nous devons répéter ou réparer le processus). Nous identifions ensuite chaque polygone par une étiquette de code appropriée (numérique ou alphabétique). Une table de correspondance associe les caractères du code aux attributs qu'ils représentent. De cette façon, nous pouvons saisir tous les champs cartographiques suffisamment grands pour être facilement circonscrits, ainsi que leurs valeurs de catégorie, dans une base de données numérique.

Dans l'approche raster, nous superposons ou scannons manuellement sur la carte une grille de cellules, ayant une taille spécifique. Comme indiqué dans le panneau de droite (format grille, ci-dessus), un polygone irrégulier comprend alors un certain nombre de cellules, entièrement contenues dans celui-ci. Le système enregistre les emplacements de ces cellules dans la grille et un numéro de code pertinent pour chaque élément de données qui leur est attribué. Mais certaines cellules chevauchent les limites du champ. Une règle prédéfinie attribue la cellule à l'un ou l'autre des champs adjacents, généralement liés à une proportion pertinente de l'un ou l'autre champ. Le tableau de cellules qui comprend un champ n'est qu'approximatif de la forme du champ, mais dans la plupart des cas, l'imprécision est tolérable pour effectuer des calculs.

En règle générale, les cellules de la grille sont plus grandes que les pixels inclus dans les affichages cartographiques illustrés, mais le groupe de pixels dans un polygone se rapproche de la forme du champ. La relation des cellules aux pixels rend ce format raster bien adapté à la manipulation numérique. La taille d'une cellule dépend en partie de la variabilité interne de la caractéristique ou de la propriété représentée. Les cellules plus petites augmentent la précision mais nécessitent également plus de stockage de données. Notez que plusieurs couches de données référencées à la même cellule de grille partagent cette dimensionnalité spatiale mais ont des valeurs codées différentes pour les divers attributs associés à une cellule donnée.

` <>`__15-14 : Du point de vue de la gestion des données, notamment des manipulations informatiques, quelle méthode de géocodage, vectorielle ou raster, devrait être la plus simple à traiter ? `RÉPONSE <Sect15_answers.html#15-14>`__

La gestion des données est sensible aux méthodes de récupération de stockage et aux structures de fichiers. Un bon progiciel de gestion doit être capable de :

Mettez à l'échelle et faites pivoter les valeurs de coordonnées pour les superpositions et les modifications de projection « optimales ».

Convertir (échanger) entre les formats de polygone et de grille.

Permet une mise à jour rapide, permettant des modifications de données avec une relative facilité.

Permettre plusieurs utilisateurs et plusieurs interactions entre bases de données compatibles.

Récupérez, transformez et combinez efficacement les éléments de données.

Recherchez, identifiez et acheminez une variété d'éléments de données différents et notez ces valeurs avec des valeurs pondérées attribuées, pour faciliter l'analyse de proximité et de routage.

Effectuer des analyses statistiques, telles que la régression multivariée, les corrélations, etc.

Superposer une variable de fichier sur une autre, c'est-à-dire superposition de carte.

Mesurez la zone, la distance et l'association entre les points et les champs.

Modéliser et simuler, et formuler des scénarios prédictifs, d'une manière qui permet des interactions directes entre le groupe d'utilisateurs et le programme informatique.

Développer un SIG peut être une expérience coûteuse, complexe et quelque peu frustrante pour le noviciat. Nous soulignons que la conception et l'encodage de la base de données sont des tâches majeures qui exigent du temps, du personnel qualifié et des fonds adéquats. Cependant, une fois développées, les possibilités d'information sont passionnantes et la valeur intrinsèque de la sortie compense largement les coûts marginaux de traitement des divers types de données. En langage clair, le SIG est un moyen systématique, polyvalent et complet de présenter, d'interpréter et de reformuler des données spatiales (géographiques) en sortie intelligible.


Vues dans ArcMap

ArcMap affiche le contenu de la carte dans l'une des deux vues :

Chaque vue vous permet de regarder et d'interagir avec la carte d'une manière spécifique.

Dans la vue de données ArcMap, la carte est le bloc de données. Le bloc de données actif est présenté comme une fenêtre géographique dans laquelle les couches cartographiques sont affichées et utilisées. Dans un bloc de données, vous travaillez avec des informations SIG présentées via des couches cartographiques à l'aide de coordonnées géographiques (du monde réel). Il s'agira généralement de mesures au sol en unités telles que les pieds, les mètres ou les mesures de latitude-longitude (telles que les degrés décimaux). La vue des données masque tous les éléments de la carte sur la mise en page, tels que les titres, les flèches nord et les barres d'échelle, et vous permet de vous concentrer sur les données dans un seul bloc de données, par exemple, l'édition ou l'analyse.

Lorsque vous préparez la mise en page de votre carte, vous souhaiterez travailler avec votre carte en mode mise en page. Une mise en page est un ensemble d'éléments cartographiques (tels qu'un bloc de données, un titre de carte, une barre d'échelle, une flèche nord et une légende de symboles) disposés sur une page. Les mises en page sont utilisées pour composer des cartes pour l'impression ou l'exportation vers des formats tels que Adobe PDF.

La vue Mise en page est utilisée pour concevoir et créer une carte pour l'impression, l'exportation ou la publication. Vous pouvez gérer les éléments cartographiques dans l'espace de la page (généralement en pouces ou en centimètres), ajouter de nouveaux éléments cartographiques et prévisualiser à quoi ressemblera votre carte avant de l'exporter ou de l'imprimer. Les éléments cartographiques courants comprennent des blocs de données avec des couches de carte, des barres d'échelle, des flèches nord, des légendes de symboles, des titres de carte, du texte et d'autres éléments graphiques.


Développement du module de généralisation SIG

Il est nécessaire de développer de nouveaux algorithmes puissants intégrés à des progiciels SIG largement utilisés, tels qu'ArcGIS, pour effectuer des processus de généralisation dans la base de données spatiale et attributaire intégrée. Ceci est très important pour de nombreuses raisons, telles que la réduction de la taille de la base de données à des fins de stockage et de traitement, la réalisation de certains types d'analyses sur des cartes numériques à petite échelle et des bases de données SIG, l'intégration de plusieurs sources de données avec différentes échelles et formats, le besoin de semi- module de généralisation automatique prenant l'échelle d'entrée et l'échelle de sortie pour faire le modèle de généralisation automatiquement sans aucune erreur humaine, et la nécessité de prendre en considération les normes des cartes égyptiennes.

Dans la section suivante, une nouvelle technique est développée pour effectuer certaines tâches de généralisation à l'aide du langage de programmation Visual Basic pour Application (VBA), associé au progiciel ArcGIS. Ces tâches sont l'élimination, la symbolisation, le regroupement et la simplification. La technique proposée est capable d'effectuer une abstraction de données et une généralisation de base de données SIG. De nombreuses expériences sont réalisées pour évaluer la technique proposée à l'aide de différents ensembles de données SIG qui sont développés séparément dans différents projets à partir de diverses sources avec différentes échelles et types.

Procédure de généralisation pour les entités polygonales (GPPF) :

La procédure de généralisation pour les entités surfaciques est exécutée comme suit :

1. Les polygones sont conservés avec la même définition d'entité

2. Les polygones dont l'aire est inférieure à (Précision en mm* Inverse de l'échelle de sortie) seront éliminés à moins qu'ils ne soient importants. Dans ce cas, ils seront symbolisés (transformés en entité ponctuelle) puis éliminés

3. Les polygones avec des distances intermédiaires inférieures à (Précision en mm* Inverse de l'échelle de sortie) seront groupés (Agrégés). Si l'une de ces caractéristiques est importante, elle sera également symbolisée

4. Les polygones qui ont des segments avec une longueur inférieure à (Précision en mm* Inverse de l'échelle de sortie) seront simplifiés. La figure (1) montre l'organigramme de la procédure adoptée.

Procédure de généralisation pour la fonction linéaire (GPLF) :

La procédure de généralisation pour la fonction linéaire est effectuée comme suit :

1. Les lignes sont conservées avec la même définition de caractéristique

2. Les lignes dont la longueur est inférieure à (Précision en mm* Inverse de l'échelle de sortie) seront éliminées

3. Les lignes dont la longueur des segments est supérieure à (Précision en mm* Inverse de l'échelle de sortie) seront simplifiées et lissées

La figure (2) montre l'organigramme de la procédure adoptée.

Développement du module de généralisation SIG :

Le module SIG complet (Figure (3)) est développé à l'aide du langage de programmation Visual Basic for Application (VBA) sur le dessus du logiciel ArcGIS ArcInfo.


ST_INTERSECT de chaque élément de deux tableaux (polygones, lignes) - Systèmes d'Information Géographique

Après avoir lu ce chapitre, vous serez en mesure d'effectuer les opérations suivantes :

  • Effacer la fenêtre à une couleur arbitraire
  • Forcer tout dessin en attente à se terminer
  • Dessinez avec n'importe quelle primitive géométrique - points, lignes et polygones - en deux ou trois dimensions
  • Activer et désactiver les états et interroger les variables d'état
  • Contrôlez l'affichage de ces primitives - par exemple, dessinez des lignes pointillées ou des polygones délimités
  • Spécifiez les vecteurs normaux aux points appropriés sur la surface des objets solides
  • Utilisez des tableaux de sommets pour stocker et accéder à de nombreuses données géométriques avec seulement quelques appels de fonction
  • Enregistrer et restaurer plusieurs variables d'état à la fois

Bien que vous puissiez dessiner des images complexes et intéressantes en utilisant OpenGL, elles sont toutes construites à partir d'un petit nombre d'éléments graphiques primitifs. Cela ne devrait pas être trop surprenant - regardez ce que Léonard de Vinci a accompli avec juste des crayons et des pinceaux.

Au niveau d'abstraction le plus élevé, il existe trois opérations de dessin de base : effacer la fenêtre, dessiner un objet géométrique et dessiner un objet raster. Les objets raster, qui incluent des éléments tels que des images bidimensionnelles, des bitmaps et des polices de caractères, sont traités au chapitre 8. Dans ce chapitre, vous apprendrez à effacer l'écran et à dessiner des objets géométriques, y compris des points, des lignes droites et des polygones.

Vous pourriez vous dire : "Attendez une minute.J'ai vu beaucoup d'infographies dans les films et à la télévision, et il y a beaucoup de lignes et de surfaces courbes magnifiquement ombragées. Comment sont-elles dessinées, si tout OpenGL peut dessiner sont des lignes droites et des polygones plats ?" Même l'image sur la couverture de ce livre comprend une table ronde et des objets sur la table qui ont des surfaces courbes. Il s'avère que toutes les lignes courbes et les surfaces que vous avez vues sont approximées par un grand nombre de petits polygones plats ou de lignes droites, de la même manière que le globe sur la couverture est construit à partir d'un grand ensemble de blocs rectangulaires. Le globe ne semble pas avoir une surface lisse parce que les blocs sont relativement gros par rapport au globe. Plus loin dans ce chapitre, nous vous montrerons comment construire des lignes courbes et des surfaces à partir de nombreuses petites primitives géométriques.

Ce chapitre comprend les sections principales suivantes :

  • "A Drawing Survival Kit" explique comment effacer la fenêtre et forcer le dessin à être terminé. Il vous donne également des informations de base sur le contrôle de la couleur des objets géométriques et la description d'un système de coordonnées.
  • "Décrire les points, les lignes et les polygones" vous montre ce qu'est l'ensemble d'objets géométriques primitifs et comment les dessiner.
  • "Basic State Management" décrit comment activer et désactiver certains états (modes) et interroger des variables d'état.
  • "Afficher les points, les lignes et les polygones" explique quel contrôle vous avez sur les détails de la façon dont les primitives sont dessinées - par exemple, le diamètre des points, si les lignes sont pleines ou en pointillés et si les polygones sont délimités ou remplis.
  • « Vecteurs normaux » explique comment spécifier des vecteurs normaux pour les objets géométriques et (brièvement) à quoi servent ces vecteurs.
  • "Vertex Arrays" vous montre comment mettre beaucoup de données géométriques dans quelques tableaux et comment, avec seulement quelques appels de fonction, rendre la géométrie qu'elle décrit. La réduction des appels de fonction peut augmenter l'efficacité et les performances du rendu.
  • "Groupes d'attributs" révèle comment interroger la valeur actuelle des variables d'état et comment enregistrer et restaurer plusieurs valeurs d'état associées à la fois.
  • "Quelques conseils pour la construction de modèles polygonaux de surfaces" explore les problèmes et les techniques impliqués dans la construction d'approximations polygonales de surfaces.

Une chose à garder à l'esprit pendant que vous lisez le reste de ce chapitre est qu'avec OpenGL, sauf indication contraire, chaque fois que vous exécutez une commande de dessin, l'objet spécifié est dessiné. Cela peut sembler évident, mais dans certains systèmes, vous faites d'abord une liste de choses à dessiner. Lorsque votre liste est complète, vous dites au matériel graphique de dessiner les éléments de la liste. Le premier style est appelé graphiques en mode immédiat et est le style OpenGL par défaut. En plus d'utiliser le mode immédiat, vous pouvez choisir d'enregistrer certaines commandes dans une liste (appelée liste d'affichage ) pour un dessin ultérieur. Les graphiques en mode immédiat sont généralement plus faciles à programmer, mais les listes d'affichage sont souvent plus efficaces. Le chapitre 7 vous explique comment utiliser les listes d'affichage et pourquoi vous pourriez vouloir les utiliser.

Un kit de survie de dessin

Cette section explique comment effacer la fenêtre en vue du dessin, définir la couleur des objets à dessiner et forcer l'achèvement du dessin. Aucun de ces sujets n'a rien à voir avec les objets géométriques de manière directe, mais tout programme qui dessine des objets géométriques doit faire face à ces problèmes.

Vider la fenêtre

Dessiner sur un écran d'ordinateur est différent du dessin sur papier en ce sens que le papier commence en blanc, et tout ce que vous avez à faire est de dessiner l'image. Sur un ordinateur, la mémoire contenant l'image est généralement remplie de la dernière image que vous avez dessinée, vous devez donc généralement l'effacer avec une couleur d'arrière-plan avant de commencer à dessiner la nouvelle scène. La couleur que vous utilisez pour l'arrière-plan dépend de l'application. Pour un traitement de texte, vous pouvez passer au blanc (la couleur du papier) avant de commencer à dessiner le texte. Si vous dessinez une vue depuis un vaisseau spatial, vous passez au noir de l'espace avant de commencer à dessiner les étoiles, les planètes et les vaisseaux spatiaux extraterrestres. Parfois, vous n'aurez peut-être pas du tout besoin d'effacer l'écran, par exemple, si l'image se trouve à l'intérieur d'une pièce, toute la fenêtre graphique est recouverte lorsque vous dessinez tous les murs.

À ce stade, vous vous demandez peut-être pourquoi nous continuons à parler de nettoyer la fenêtre - pourquoi ne pas simplement dessiner un rectangle de la couleur appropriée suffisamment grand pour couvrir toute la fenêtre ? Premièrement, une commande spéciale pour effacer une fenêtre peut être beaucoup plus efficace qu'une commande de dessin à usage général. De plus, comme vous le verrez au chapitre 3, OpenGL vous permet de définir le système de coordonnées, la position de visualisation et la direction de visualisation de manière arbitraire, il peut donc être difficile de déterminer une taille et un emplacement appropriés pour un rectangle d'effacement de fenêtre. Enfin, sur de nombreuses machines, le matériel graphique se compose de plusieurs tampons en plus du tampon contenant les couleurs des pixels qui sont affichés. Ces autres tampons doivent être effacés de temps en temps, et il est pratique d'avoir une seule commande qui peut effacer n'importe quelle combinaison d'entre eux. (Voir le chapitre 10 pour une discussion de tous les tampons possibles.)

Vous devez également savoir comment les couleurs des pixels sont stockées dans le matériel graphique appelé bitplanes. Il existe deux méthodes de stockage. Soit les valeurs rouge, verte, bleue et alpha (RVBA) d'un pixel peuvent être directement stockées dans les plans binaires, soit une seule valeur d'index qui fait référence à une table de recherche de couleurs est stockée. Le mode d'affichage couleur RVBA est plus couramment utilisé, c'est pourquoi la plupart des exemples de ce livre l'utilisent. (Voir le chapitre 4 pour plus d'informations sur les deux modes d'affichage.) Vous pouvez ignorer en toute sécurité toutes les références aux valeurs alpha jusqu'au chapitre 6.

À titre d'exemple, ces lignes de code effacent une fenêtre de mode RGBA en noir :

La première ligne définit la couleur d'effacement sur le noir et la commande suivante efface toute la fenêtre avec la couleur d'effacement actuelle. Le seul paramètre de glClear() indique quels tampons doivent être effacés. Dans ce cas, le programme n'efface que le tampon de couleur, où l'image affichée à l'écran est conservée. En règle générale, vous définissez la couleur d'effacement une fois, au début de votre application, puis vous effacez les tampons aussi souvent que nécessaire. OpenGL garde une trace de la couleur d'effacement actuelle en tant que variable d'état plutôt que de vous obliger à la spécifier à chaque fois qu'un tampon est effacé.

Les chapitres 4 et 10 expliquent comment les autres tampons sont utilisés. Pour l'instant, tout ce que vous devez savoir, c'est que les effacer est simple. Par exemple, pour effacer à la fois le tampon de couleur et le tampon de profondeur, vous utiliserez la séquence de commandes suivante :

Dans ce cas, l'appel à glClearColor() est le même qu'auparavant, la commande glClearDepth() spécifie la valeur à laquelle chaque pixel du tampon de profondeur doit être défini, et le paramètre de la commande glClear() se compose désormais du OU au niveau du bit de tous les tampons à effacer. Le résumé suivant de glClear() comprend un tableau qui répertorie les tampons qui peuvent être effacés, leurs noms et le chapitre où chaque type de tampon est abordé.

void glClearColor (GLclampf rouge , GLclampf vert , GLclampf bleu ,
GLclampf alpha ) Définit la couleur d'effacement actuelle à utiliser pour effacer les tampons de couleur en mode RGBA. (Voir le chapitre 4 pour plus d'informations sur le mode RGBA.) Les valeurs rouge , verte , bleue et alpha sont limitées si nécessaire à la plage [0,1]. La couleur d'effacement par défaut est (0, 0, 0, 0), qui est le noir. void glClear (GLbitfield mask ) Efface les tampons spécifiés à leurs valeurs d'effacement actuelles. L'argument mask est une combinaison OU binaire des valeurs répertoriées dans le Tableau 2-1 . Tableau 2-1 : Effacer les tampons

Avant d'émettre une commande pour effacer plusieurs tampons, vous devez définir les valeurs auxquelles chaque tampon doit être effacé si vous voulez quelque chose d'autre que la couleur RVBA par défaut, la valeur de profondeur, la couleur d'accumulation et l'indice de pochoir. En plus des commandes glClearColor() et glClearDepth() qui définissent les valeurs actuelles pour effacer les tampons de couleur et de profondeur, glClearIndex() , glClearAccum() et glClearStencil() spécifient l'index de couleur , la couleur d'accumulation et l'index de gabarit utilisés pour effacer les tampons correspondants. (Voir les chapitres 4 et 10 pour des descriptions de ces tampons et de leurs utilisations.)

OpenGL vous permet de spécifier plusieurs tampons car l'effacement est généralement une opération lente, car chaque pixel de la fenêtre (éventuellement des millions) est touché, et certains matériels graphiques permettent d'effacer simultanément des ensembles de tampons. Le matériel qui ne prend pas en charge les effacements simultanés les exécute de manière séquentielle. La différence entre

est que bien que les deux aient le même effet final, le premier exemple peut s'exécuter plus rapidement sur de nombreuses machines. Il ne fonctionnera certainement pas plus lentement.

Spécification d'une couleur

Avec OpenGL, la description de la forme d'un objet en cours de dessin est indépendante de la description de sa couleur. Chaque fois qu'un objet géométrique particulier est dessiné, il est dessiné en utilisant le schéma de coloration actuellement spécifié. Le schéma de coloration peut être aussi simple que « dessiner tout en rouge pompier » ou peut être aussi compliqué que « supposez que l'objet est fait de plastique bleu, qu'il y a un projecteur jaune pointé dans telle ou telle direction, et que il y a une lumière générale brun rougeâtre de faible intensité partout ailleurs." En général, un programmeur OpenGL définit d'abord la couleur ou le schéma de coloration, puis dessine les objets. Jusqu'à ce que la couleur ou le schéma de coloration soit modifié, tous les objets sont dessinés dans cette couleur ou en utilisant ce schéma de coloration. Cette méthode aide OpenGL à obtenir des performances de dessin plus élevées que s'il ne gardait pas trace de la couleur actuelle.

Par exemple, le pseudo-code

dessine les objets A et B en rouge et l'objet C en bleu. La commande sur la quatrième ligne qui définit la couleur actuelle sur le vert est gaspillée.

La coloration, l'éclairage et l'ombrage sont tous de grands sujets avec des chapitres entiers ou de grandes sections qui leur sont consacrés. Cependant, pour dessiner des primitives géométriques visibles, vous avez besoin de connaissances de base sur la façon de définir la couleur actuelle. Cette information est fournie dans les paragraphes suivants. (Voir les chapitres 4 et 5 pour plus de détails sur ces sujets.)

Pour définir une couleur, utilisez la commande glColor3f() . Il prend trois paramètres, qui sont tous des nombres à virgule flottante compris entre 0,0 et 1,0. Les paramètres sont, dans l'ordre, les composantes rouge, verte et bleue de la couleur. Vous pouvez considérer ces trois valeurs comme spécifiant un « mélange » de couleurs : 0,0 signifie n'utiliser aucun de ce composant et 1,0 signifie utiliser tout ce que vous pouvez de ce composant. Ainsi, le code

rend le rouge le plus brillant que le système puisse dessiner, sans composants verts ou bleus. Tous les zéros font du noir en contraste, tous les uns font du blanc. Le réglage des trois composants à 0,5 donne du gris (à mi-chemin entre le noir et le blanc). Voici huit commandes et les couleurs qu'elles définiraient.

Vous avez peut-être remarqué plus tôt que la routine pour définir la couleur d'effacement, glClearColor() , prend quatre paramètres, dont les trois premiers correspondent aux paramètres de glColor3f() . Le quatrième paramètre est la valeur alpha, il est couvert en détail dans "Blending" au chapitre 6. Pour l'instant, définissez le quatrième paramètre de glClearColor() à 0.0, qui est sa valeur par défaut.

Forcer l'achèvement du dessin

Comme vous l'avez vu dans "OpenGL Rendering Pipeline" au chapitre 1, la plupart des systèmes graphiques modernes peuvent être considérés comme une chaîne de montage. L'unité centrale principale (CPU) émet une commande de dessin. Peut-être que d'autres matériels effectuent des transformations géométriques. Un écrêtage est effectué, suivi d'un ombrage et/ou d'une texturation. Enfin, les valeurs sont écrites dans les plans de bits pour affichage. Dans les architectures haut de gamme, chacune de ces opérations est effectuée par un élément matériel différent qui a été conçu pour effectuer rapidement sa tâche particulière. Dans une telle architecture, le CPU n'a pas besoin d'attendre la fin de chaque commande de dessin avant d'émettre la suivante. Pendant que le CPU envoie un sommet dans le pipeline, le matériel de transformation travaille à transformer le dernier envoyé, celui d'avant qui est écrêté, et ainsi de suite. Dans un tel système, si le processeur attendait que chaque commande se termine avant d'émettre la suivante, il pourrait y avoir une énorme pénalité de performance.

De plus, l'application peut s'exécuter sur plusieurs machines. Par exemple, supposons que le programme principal s'exécute ailleurs (sur une machine appelée le client) et que vous visualisez les résultats du dessin sur votre poste de travail ou terminal (le serveur), qui est connecté par un réseau au client. Dans ce cas, il pourrait être horriblement inefficace d'envoyer chaque commande sur le réseau une par une, car une surcharge considérable est souvent associée à chaque transmission réseau. Habituellement, le client rassemble une collection de commandes dans un seul paquet réseau avant de l'envoyer. Malheureusement, le code réseau sur le client n'a généralement aucun moyen de savoir que le programme graphique a fini de dessiner une image ou une scène. Dans le pire des cas, il attend indéfiniment suffisamment de commandes de dessin supplémentaires pour remplir un paquet, et vous ne voyez jamais le dessin terminé.

Pour cette raison, OpenGL fournit la commande glFlush() , qui force le client à envoyer le paquet réseau même s'il n'est pas plein. Lorsqu'il n'y a pas de réseau et que toutes les commandes sont réellement exécutées immédiatement sur le serveur, glFlush() peut n'avoir aucun effet. Cependant, si vous écrivez un programme que vous voulez fonctionner correctement avec et sans réseau, incluez un appel à glFlush() à la fin de chaque image ou scène. Notez que glFlush() n'attend pas la fin du dessin - il force simplement le dessin à commencer l'exécution, garantissant ainsi que toutes les commandes précédentes s'exécutent dans un temps fini même si aucune autre commande de rendu n'est exécutée.

Il existe d'autres situations où glFlush() est utile.

  • Moteurs de rendu logiciels qui créent une image dans la mémoire système et ne veulent pas constamment mettre à jour l'écran.
  • Implémentations qui rassemblent des ensembles de commandes de rendu pour amortir les coûts de démarrage. L'exemple de transmission de réseau susmentionné en est un exemple.

Quelques commandes - par exemple, les commandes qui échangent des tampons en mode double tampon - vident automatiquement les commandes en attente sur le réseau avant qu'elles ne puissent se produire.

Si glFlush() ne vous suffit pas, essayez glFinish() . Cette commande vide le réseau comme le fait glFlush(), puis attend une notification du matériel graphique ou du réseau indiquant que le dessin est terminé dans le framebuffer. Vous devrez peut-être utiliser glFinish() si vous souhaitez synchroniser des tâches - par exemple, pour vous assurer que votre rendu tridimensionnel est à l'écran avant d'utiliser Display PostScript pour dessiner des étiquettes sur le rendu. Un autre exemple serait de s'assurer que le dessin est terminé avant qu'il ne commence à accepter l'entrée de l'utilisateur. Après avoir émis une commande glFinish(), votre processus graphique est bloqué jusqu'à ce qu'il reçoive une notification du matériel graphique indiquant que le dessin est terminé. Gardez à l'esprit qu'une utilisation excessive de glFinish() peut réduire les performances de votre application, surtout si vous l'exécutez sur un réseau, car elle nécessite une communication aller-retour. Si glFlush() est suffisant pour vos besoins, utilisez-le à la place de glFinish() .

void glFinish (void) Force toutes les commandes OpenGL précédemment émises à se terminer. Cette commande ne revient pas tant que tous les effets des commandes précédentes ne sont pas pleinement réalisés.

Kit de survie du système de coordonnées

Chaque fois que vous ouvrez une fenêtre pour la première fois ou que vous déplacez ou redimensionnez ultérieurement cette fenêtre, le système de fenêtres enverra un événement pour vous en informer. Si vous utilisez GLUT, la notification est automatisée, quelle que soit la routine enregistrée dans glutReshapeFunc() qui sera appelée. Vous devez enregistrer une fonction de rappel qui

  • Rétablir la région rectangulaire qui sera le nouveau canevas de rendu
  • Définir le système de coordonnées auquel les objets seront dessinés

Dans le chapitre 3, vous verrez comment définir des systèmes de coordonnées tridimensionnels, mais pour le moment, créez simplement un système de coordonnées bidimensionnel simple et basique dans lequel vous pouvez dessiner quelques objets. Appelez glutReshapeFunc ( reshape ), où reshape() est la fonction suivante illustrée dans l'exemple 2-1.

Exemple 2-1 : Remodeler la fonction de rappel

Les internes de GLUT passeront à cette fonction deux arguments : la largeur et la hauteur, en pixels, de la nouvelle fenêtre, déplacée ou redimensionnée. glViewport() ajuste le rectangle de pixels pour que le dessin soit la nouvelle fenêtre entière. Les trois routines suivantes ajustent le système de coordonnées pour le dessin de sorte que le coin inférieur gauche soit (0, 0) et le coin supérieur droit ( w , h ) (Voir Figure 2-1).

Pour l'expliquer autrement, pensez à un morceau de papier graphique. Les valeurs w et h dans reshape() représentent le nombre de colonnes et de rangées de carrés sur votre papier millimétré. Ensuite, vous devez mettre des axes sur le papier millimétré. La routine gluOrtho2D() place l'origine, (0, 0), complètement dans le carré le plus bas, le plus à gauche, et fait que chaque carré représente une unité. Maintenant, lorsque vous rendrez les points, les lignes et les polygones dans le reste de ce chapitre, ils apparaîtront sur ce papier dans des carrés facilement prévisibles. (Pour l'instant, gardez tous vos objets en deux dimensions.)

Figure 2-1 : Système de coordonnées défini par w = 50, h = 50

Description des points, des lignes et des polygones

Cette section explique comment décrire les primitives géométriques OpenGL. Toutes les primitives géométriques sont finalement décrites en fonction de leurs sommets - des coordonnées qui définissent les points eux-mêmes, les extrémités des segments de ligne ou les coins des polygones. La section suivante explique comment ces primitives sont affichées et quel contrôle vous avez sur leur affichage.

Que sont les points, les lignes et les polygones ?

Vous avez probablement une assez bonne idée de ce qu'un mathématicien entend par les termes point , ligne et polygone. Les significations OpenGL sont similaires, mais pas tout à fait les mêmes.

Une différence vient des limites des calculs informatisés. Dans toute implémentation OpenGL, les calculs à virgule flottante sont de précision finie et comportent des erreurs d'arrondi. Par conséquent, les coordonnées des points, lignes et polygones OpenGL souffrent des mêmes problèmes.

Une autre différence plus importante provient des limitations d'un affichage graphique raster. Sur un tel écran, la plus petite unité affichable est un pixel, et bien que les pixels puissent mesurer moins de 1/100 de pouce de large, ils sont toujours beaucoup plus grands que les concepts du mathématicien d'infiniment petit (pour les points) ou d'infiniment mince (pour les lignes ). Lorsque OpenGL effectue des calculs, il suppose que les points sont représentés comme des vecteurs de nombres à virgule flottante. Cependant, un point est généralement (mais pas toujours) dessiné comme un seul pixel, et de nombreux points différents avec des coordonnées légèrement différentes pourraient être dessinés par OpenGL sur le même pixel.

Points

Un point est représenté par un ensemble de nombres à virgule flottante appelé sommet. Tous les calculs internes sont effectués comme si les sommets étaient en trois dimensions. Les sommets spécifiés par l'utilisateur comme bidimensionnels (c'est-à-dire avec uniquement les coordonnées x et y) se voient attribuer une coordonnée z égale à zéro par OpenGL.

OpenGL fonctionne dans les coordonnées homogènes de la géométrie projective tridimensionnelle, donc pour les calculs internes, tous les sommets sont représentés avec quatre coordonnées à virgule flottante ( x , y , z , w ).Si w est différent de zéro, ces coordonnées correspondent au point tridimensionnel euclidien ( x/w , y/w , z/w ). Vous pouvez spécifier la coordonnée w dans les commandes OpenGL, mais c'est rarement fait. Si la coordonnée w n'est pas spécifiée, elle est comprise comme étant 1.0. (Voir l'annexe F pour plus d'informations sur les systèmes de coordonnées homogènes.)

Lignes

En OpenGL, le terme ligne fait référence à un segment de ligne, pas à la version du mathématicien qui s'étend à l'infini dans les deux sens. Il existe des moyens simples de spécifier une série connectée de segments de ligne, ou même une série fermée et connectée de segments (voir Figure 2-2). Dans tous les cas, cependant, les lignes constituant la série connectée sont spécifiées en termes de sommets à leurs extrémités.

Figure 2-2 : Deux séries de segments de ligne connectés

Polygones

Les polygones sont les zones délimitées par des boucles fermées simples de segments de ligne, où les segments de ligne sont spécifiés par les sommets à leurs extrémités. Les polygones sont généralement dessinés avec les pixels à l'intérieur remplis, mais vous pouvez également les dessiner sous forme de contours ou d'un ensemble de points. (Voir "Détails du polygone".)

En général, les polygones peuvent être compliqués, donc OpenGL impose de fortes restrictions sur ce qui constitue un polygone primitif. Premièrement, les bords des polygones OpenGL ne peuvent pas se croiser (un mathématicien appellerait un polygone satisfaisant cette condition un simple polygone ). Deuxièmement, les polygones OpenGL doivent être convexes , ce qui signifie qu'ils ne peuvent pas avoir d'indentations. En d'autres termes, une région est convexe si, étant donné deux points quelconques à l'intérieur, le segment de droite les joignant est également à l'intérieur. Voir la Figure 2-3 pour quelques exemples de polygones valides et non valides. OpenGL, cependant, ne limite pas le nombre de segments de ligne constituant la limite d'un polygone convexe. Notez que les polygones avec des trous ne peuvent pas être décrits. Ils ne sont pas convexes et ne peuvent pas être tracés avec une frontière constituée d'une seule boucle fermée. Sachez que si vous présentez OpenGL avec un polygone rempli non convexe, il se peut qu'il ne le dessine pas comme prévu. Par exemple, sur la plupart des systèmes, pas plus que l'enveloppe convexe du polygone ne serait remplie. Sur certains systèmes, moins que l'enveloppe convexe peut être rempli.

Figure 2-3 : Polygones valides et non valides

La raison des restrictions OpenGL sur les types de polygones valides est qu'il est plus simple de fournir du matériel de rendu de polygones rapide pour cette classe restreinte de polygones. Les polygones simples peuvent être rendus rapidement. Les cas difficiles sont difficiles à détecter rapidement. Donc, pour des performances maximales, OpenGL croise les doigts et suppose que les polygones sont simples.

De nombreuses surfaces du monde réel sont constituées de polygones non simples, de polygones non convexes ou de polygones avec des trous. Étant donné que tous ces polygones peuvent être formés à partir d'unions de polygones convexes simples, certaines routines pour construire des objets plus complexes sont fournies dans la bibliothèque GLU. Ces routines prennent des descriptions complexes et les tesselent, ou les divisent en groupes de polygones OpenGL plus simples qui peuvent ensuite être rendus. (Voir « Polygone tessellation » au chapitre 11 pour plus d'informations sur les routines de tessellation.)

Étant donné que les sommets OpenGL sont toujours en trois dimensions, les points formant la limite d'un polygone particulier ne se trouvent pas nécessairement sur le même plan dans l'espace. (Bien sûr, ils le font dans de nombreux cas - si toutes les coordonnées z sont nulles, par exemple, ou si le polygone est un triangle.) Si les sommets d'un polygone ne se trouvent pas dans le même plan, alors après diverses rotations dans l'espace, changements de point de vue et projection sur l'écran d'affichage, les points pourraient ne plus former un simple polygone convexe. Par exemple, imaginez un quadrilatère à quatre points où les points sont légèrement hors du plan et regardez-le presque de côté. Vous pouvez obtenir un polygone non simple qui ressemble à un nœud papillon, comme le montre la figure 2-4, dont le rendu n'est pas garanti correctement. Cette situation n'est pas si inhabituelle si vous approximez des surfaces courbes par des quadrilatères constitués de points situés sur la vraie surface. Vous pouvez toujours éviter le problème en utilisant des triangles, car trois points se trouvent toujours sur un plan.

Figure 2-4 : Polygone non plan transformé en polygone non simple

Rectangles

Comme les rectangles sont si courants dans les applications graphiques, OpenGL fournit une primitive de dessin de rectangles pleins, glRect*() . Vous pouvez dessiner un rectangle sous forme de polygone, comme décrit dans "OpenGL Geometric Drawing Primitives", mais votre implémentation particulière d'OpenGL peut avoir optimisé glRect*() pour les rectangles.

void glRect ( TYPEx1 , TYPEy1 , TYPEx2 , TYPEy2 )
void glRect v ( TYPE*v1 , TYPE*v2 ) Dessine le rectangle défini par les points d'angle ( x1, y1 ) et ( x2, y2 ). Le rectangle se trouve dans le plan z = 0 et a des côtés parallèles aux axes x et y. Si la forme vectorielle de la fonction est utilisée, les coins sont donnés par deux pointeurs vers des tableaux, dont chacun contient une paire ( x, y ).

Notez que bien que le rectangle commence par une orientation particulière dans l'espace tridimensionnel (dans le plan x-y et parallèle aux axes), vous pouvez changer cela en appliquant des rotations ou d'autres transformations. (Voir le chapitre 3 pour plus d'informations sur la façon de procéder.)

Courbes et surfaces courbes

Toute ligne ou surface légèrement incurvée peut être approchée - à n'importe quel degré de précision arbitraire - par des segments de ligne courts ou de petites régions polygonales. Ainsi, en subdivisant suffisamment les lignes et les surfaces courbes, puis en les rapprochant avec des segments de ligne droite ou des polygones plats, les fait apparaître courbes (voir Figure 2-5). Si vous doutez que cela fonctionne vraiment, imaginez une subdivision jusqu'à ce que chaque segment de ligne ou polygone soit si petit qu'il soit plus petit qu'un pixel à l'écran.

Figure 2-5 : Approximation des courbes

Même si les courbes ne sont pas des primitives géométriques, OpenGL fournit un support direct pour les subdiviser et les dessiner. (Voir le chapitre 12 pour plus d'informations sur la façon de dessiner des courbes et des surfaces courbes.)

Spécification des sommets

Avec OpenGL, tous les objets géométriques sont finalement décrits comme un ensemble ordonné de sommets. Vous utilisez la commande glVertex*() pour spécifier un sommet.

vide glVertex <234>[v]( TYPEcoords ) Spécifie un sommet à utiliser pour décrire un objet géométrique. Vous pouvez fournir jusqu'à quatre coordonnées (x, y, z, w) pour un sommet particulier ou aussi peu que deux (x, y) en sélectionnant la version appropriée de la commande. Si vous utilisez une version qui ne spécifie pas explicitement z ou w, z est compris comme étant 0 et w est compris comme étant 1. Les appels à glVertex*() ne sont efficaces qu'entre une paire glBegin() et glEnd().

L'exemple 2-2 fournit quelques exemples d'utilisation de glVertex*() .

Exemple 2-2 : Utilisations légales de glVertex*()

Le premier exemple représente un sommet avec des coordonnées tridimensionnelles (2, 3, 0). (Rappelez-vous que si elle n'est pas spécifiée, la coordonnée z est comprise comme étant 0.) Les coordonnées du deuxième exemple sont (0,0, 0,0, 3,1415926535898) (nombres à virgule flottante double précision). Le troisième exemple représente le sommet avec des coordonnées tridimensionnelles (1.15, 0.5, -1.1). (Rappelez-vous que les coordonnées x, y et z sont finalement divisées par la coordonnée w.) Dans le dernier exemple, dvect est un pointeur vers un tableau de trois nombres à virgule flottante double précision.

Sur certaines machines, la forme vectorielle de glVertex*() est plus efficace, puisqu'un seul paramètre doit être passé au sous-système graphique. Un matériel spécial peut être capable d'envoyer toute une série de coordonnées en un seul lot. Si votre machine est comme ça, c'est à votre avantage d'organiser vos données de manière à ce que les coordonnées des sommets soient empaquetées séquentiellement en mémoire. Dans ce cas, il peut y avoir un gain de performances en utilisant les opérations de tableau de sommets d'OpenGL. (Voir « Tableaux de sommets ».)

Primitives de dessin géométrique OpenGL

Maintenant que vous avez vu comment spécifier des sommets, vous devez encore savoir comment dire à OpenGL de créer un ensemble de points, une ligne ou un polygone à partir de ces sommets. Pour ce faire, vous encadrez chaque ensemble de sommets entre un appel à glBegin() et un appel à glEnd() . L'argument passé à glBegin() détermine quelle sorte de primitive géométrique est construite à partir des sommets. Par exemple, l'exemple 2-3> spécifie les sommets du polygone illustré à la figure 2-6.

Exemple 2-3 : Polygone rempli

Figure 2-6 : Dessiner un polygone ou un ensemble de points

Si vous aviez utilisé GL_POINTS au lieu de GL_POLYGON, la primitive aurait simplement été les cinq points illustrés à la figure 2-6. Le tableau 2-2 du résumé des fonctions suivant pour glBegin() répertorie les dix arguments possibles et le type de primitive correspondant.

void glBegin (GLenum mode ) Marque le début d'une liste de données de sommets qui décrit une primitive géométrique. Le type de primitive est indiqué par mode , qui peut être n'importe laquelle des valeurs indiquées dans le Tableau 2-2 . Tableau 2-2 : Noms et significations des primitifs géométriques

paires de sommets interprétées comme des segments de ligne individuels

série de segments de ligne connectés

comme ci-dessus, avec un segment ajouté entre le dernier et le premier sommet

triples de sommets interprétés comme des triangles

bande de triangles liés

quadruples de sommets interprétés comme des polygones à quatre côtés

bande de quadrilatères liés

limite d'un polygone simple et convexe

Marque la fin d'une liste de données de sommet.

La Figure 2-7 montre des exemples de toutes les primitives géométriques répertoriées dans le Tableau 2-2. Les paragraphes qui suivent la figure décrivent les pixels qui sont dessinés pour chacun des objets. Notez qu'en plus des points, plusieurs types de lignes et de polygones sont définis. Évidemment, vous pouvez trouver de nombreuses façons de dessiner la même primitive. La méthode que vous choisissez dépend de vos données de sommet.

Figure 2-7 : Types primitifs géométriques

En lisant les descriptions suivantes, supposons que n sommets (v0, v1, v2, . , vn-1) sont décrits entre une paire glBegin() et glEnd().

Dessine un point à chacun des n sommets.

Dessine une série de segments de ligne non connectés. Les segments sont dessinés entre v0 et v1, entre v2 et v3, et ainsi de suite. Si n est impair, le dernier segment est tracé entre vn-3 et vn-2, et vn-1 est ignoré.

Dessine un segment de ligne de v0 à v1, puis de v1 à v2, et ainsi de suite, pour finalement tracer le segment de vn-2 à vn-1. Ainsi, un total de n - 1 segments de ligne sont tracés. Rien n'est dessiné à moins que n soit supérieur à 1. Il n'y a aucune restriction sur les sommets décrivant une bande de ligne (ou une boucle de ligne) que les lignes peuvent se croiser arbitrairement.

Identique à GL_LINE_STRIP, sauf qu'un segment de ligne final est tracé de vn-1 à v0, complétant une boucle.

Dessine une série de triangles (polygones à trois côtés) en utilisant les sommets v0, v1, v2, puis v3, v4, v5, etc. Si n n'est pas un multiple exact de 3, le ou les deux sommets finaux sont ignorés.

Dessine une série de triangles (polygones à trois côtés) en utilisant les sommets v0, v1, v2, puis v2, v1, v3 (notez l'ordre), puis v2, v3, v4, et ainsi de suite. L'ordre est de s'assurer que les triangles sont tous dessinés avec la même orientation afin que la bande puisse correctement faire partie d'une surface. La préservation de l'orientation est importante pour certaines opérations, comme l'abattage. (Voir "Inverser et éliminer les faces de polygone") n doit être au moins égal à 3 pour que quoi que ce soit soit dessiné.

Identique à GL_TRIANGLE_STRIP, sauf que les sommets sont v0, v1, v2, puis v0, v2, v3, puis v0, v3, v4, et ainsi de suite (voir Figure 2-7).

Dessine une série de quadrilatères (polygones à quatre côtés) en utilisant les sommets v0, v1, v2, v3, puis v4, v5, v6, v7, etc. Si n n'est pas un multiple de 4, le dernier, deux ou trois sommets sont ignorés.

Dessine une série de quadrilatères (polygones à quatre côtés) commençant par v0, v1, v3, v2, puis v2, v3, v5, v4, puis v4, v5, v7, v6, etc. (voir Figure 2-7). n doit être au moins égal à 4 avant que quoi que ce soit soit dessiné. Si n est impair, le sommet final est ignoré.

Dessine un polygone en utilisant les points v0, . , vn-1 comme sommets. n doit être au moins égal à 3, sinon rien n'est dessiné. De plus, le polygone spécifié ne doit pas se couper et doit être convexe. Si les sommets ne satisfont pas à ces conditions, les résultats sont imprévisibles.

Restrictions sur l'utilisation de glBegin() et glEnd()

Les informations les plus importantes sur les sommets sont leurs coordonnées, qui sont spécifiées par la commande glVertex*(). Vous pouvez également fournir des données supplémentaires spécifiques aux sommets pour chaque sommet - une couleur, un vecteur normal, des coordonnées de texture ou toute combinaison de ceux-ci - à l'aide de commandes spéciales. De plus, quelques autres commandes sont valides entre une paire glBegin() et glEnd(). Le tableau 2-3 contient une liste complète de ces commandes valides.

Tableau 2-3 : Commandes valides entre glBegin() et glEnd()

définir les coordonnées vectorielles normales

extraire les données du tableau de sommets

Aucune autre commande OpenGL n'est valide entre une paire glBegin() et glEnd(), et faire la plupart des autres appels OpenGL génère une erreur. Certaines commandes de tableau de sommets, telles que glEnableClientState() et glVertexPointer() , lorsqu'elles sont appelées entre glBegin() et glEnd() , ont un comportement indéfini mais ne génèrent pas nécessairement d'erreur. (De plus, les routines liées à OpenGL, telles que les routines glX*() ont un comportement indéfini entre glBegin() et glEnd() .) Ces cas doivent être évités et leur débogage peut être plus difficile.

Notez, cependant, que seules les commandes OpenGL sont restreintes, vous pouvez certainement inclure d'autres constructions de langage de programmation (à l'exception des appels, tels que les routines glX*() susmentionnées). Par exemple, l'exemple 2-4 dessine un cercle encadré.

Exemple 2-4 : Autres constructions entre glBegin() et glEnd()

Remarque : cet exemple n'est pas le moyen le plus efficace de dessiner un cercle, surtout si vous avez l'intention de le faire à plusieurs reprises. Les commandes graphiques utilisées sont généralement très rapides, mais ce code calcule un angle et appelle les routines sin() et cos() pour chaque sommet en plus, il y a le surcoût de la boucle. (Une autre façon de calculer les sommets d'un cercle est d'utiliser une routine GLU voir "Quadriques : Rendu des sphères, des cylindres et des disques" au chapitre 11.) Si vous devez dessiner beaucoup de cercles, calculez les coordonnées des sommets une fois et enregistrez-les dans un tableau et créez une liste d'affichage (voir chapitre 7), ou utilisez des tableaux de sommets pour les afficher.

À moins qu'elles ne soient compilées dans une liste d'affichage, toutes les commandes glVertex*() devraient apparaître entre une combinaison glBegin() et glEnd(). (S'ils apparaissent ailleurs, ils n'accomplissent rien.) S'ils apparaissent dans une liste d'affichage, ils ne sont exécutés que s'ils apparaissent entre un glBegin() et un glEnd() . (Voir le chapitre 7 pour plus d'informations sur les listes d'affichage.)

Bien que de nombreuses commandes soient autorisées entre glBegin() et glEnd() , les sommets ne sont générés que lorsqu'une commande glVertex*() est émise. Au moment où glVertex*() est appelé, OpenGL attribue au sommet résultant la couleur actuelle, les coordonnées de texture, les informations vectorielles normales, etc. Pour voir cela, regardez la séquence de code suivante. Le premier point est dessiné en rouge et les deuxième et troisième en bleu, malgré les commandes de couleurs supplémentaires.

Vous pouvez utiliser n'importe quelle combinaison des 24 versions de la commande glVertex*() entre glBegin() et glEnd() , bien que dans les applications réelles, tous les appels dans une instance particulière aient tendance à être de la même forme. Si votre spécification de données de sommet est cohérente et répétitive (par exemple, glColor* , glVertex* , glColor* , glVertex* . ), vous pouvez améliorer les performances de votre programme en utilisant des tableaux de sommets. (Voir « Tableaux de sommets ».)

Gestion de l'état de base

Dans la section précédente, vous avez vu un exemple de variable d'état, la couleur RGBA actuelle et comment elle peut être associée à une primitive. OpenGL gère de nombreux états et variables d'état. Un objet peut être rendu avec un éclairage, une texture, une suppression de surface cachée, un brouillard ou d'autres états affectant son apparence.

Par défaut, la plupart de ces états sont initialement inactifs. Ces états peuvent être coûteux à activer, par exemple, l'activation du mappage de texture ralentira presque certainement la vitesse de rendu d'une primitive. Cependant, la qualité de l'image s'améliorera et semblera plus réaliste, en raison des capacités graphiques améliorées.

Pour activer et désactiver plusieurs de ces états, utilisez ces deux commandes simples :

void glEnable (GLenum cap )
void glDisable (GLenum cap ) glEnable() active une capacité et glDisable() la désactive. Il existe plus de 40 valeurs énumérées qui peuvent être transmises en tant que paramètre à glEnable() ou glDisable() . Quelques exemples de ceux-ci sont GL_BLEND (qui contrôle le mélange des valeurs RGBA), GL_DEPTH_TEST (qui contrôle les comparaisons de profondeur et les mises à jour du tampon de profondeur), GL_FOG (qui contrôle le brouillard), GL_LINE_STIPPLE (lignes à motifs), GL_LIGHTING (vous voyez l'idée), et ainsi de suite.

Vous pouvez également vérifier si un état est actuellement activé ou désactivé.

GLboolean glIsEnabled (capacité GLenum ) R etrend GL_TRUE ou GL_FALSE, selon que la capacité interrogée est actuellement activée.

Les états que vous venez de voir ont deux paramètres : activé et désactivé. Cependant, la plupart des routines OpenGL définissent des valeurs pour des variables d'état plus complexes. Par exemple, la routine glColor3f() définit trois valeurs, qui font partie de l'état GL_CURRENT_COLOR. Il existe cinq routines d'interrogation utilisées pour savoir quelles valeurs sont définies pour de nombreux états :

void glGetBooleanv (GLenum pname , GLboolean * params )
void glGetIntegerv (GLenum pname , GLint * params )
void glGetFloatv (GLenum pname , GLfloat * params )
void glGetDoublev (GLenum pname , GLdouble * params )
void glGetPointerv (GLenum pname , GLvoid ** params ) Obtient des variables d'état booléennes, entières, à virgule flottante, double précision ou pointeur. L'argument pname est une constante symbolique indiquant la variable d'état à renvoyer, et params est un pointeur vers un tableau du type indiqué dans lequel placer les données renvoyées. Voir les tableaux de l'annexe B pour les valeurs possibles pour pname . Par exemple, pour obtenir la couleur RGBA actuelle, un tableau de l'annexe B vous suggère d'utiliser glGetIntegerv (GL_CURRENT_COLOR, params ) ou glGetFloatv (GL_CURRENT_COLOR, params ). Une conversion de type est effectuée si nécessaire pour renvoyer la variable souhaitée en tant que type de données demandé.

Ces routines d'interrogation traitent la plupart, mais pas toutes, les demandes d'obtention d'informations d'état. (Voir "Les commandes de requête" dans l'annexe B pour 16 routines de requête supplémentaires.)

Affichage des points, des lignes et des polygones

Par défaut, un point est dessiné sous la forme d'un seul pixel sur l'écran, une ligne est dessinée en continu et large d'un pixel, et les polygones sont dessinés en continu. Les paragraphes suivants expliquent en détail comment modifier ces modes d'affichage par défaut.

Détails des points

Pour contrôler la taille d'un point rendu, utilisez glPointSize() et fournissez la taille souhaitée en pixels comme argument.

void glPointSize (GLfloat size ) Définit la largeur en pixels pour les points rendus. La taille des points doit être supérieure à 0.0 et par défaut est 1.0.

La collection réelle de pixels sur l'écran qui sont dessinés pour différentes largeurs de points dépend de l'activation ou non de l'anticrénelage. (L'anticrénelage est une technique de lissage des points et des lignes lorsqu'ils sont rendus, voir "Anticrénelage" au chapitre 6 pour plus de détails.) Si l'anticrénelage est désactivé (par défaut), les largeurs fractionnaires sont arrondies à des largeurs entières et un carré aligné sur l'écran région de pixels est dessinée. Ainsi, si la largeur est de 1,0, le carré fait 1 pixel sur 1 pixel si la largeur est de 2,0, le carré fait 2 pixels sur 2 pixels, et ainsi de suite.

Lorsque l'anticrénelage est activé, un groupe circulaire de pixels est dessiné et les pixels sur les limites sont généralement dessinés à une intensité inférieure à la pleine intensité pour donner au bord un aspect plus lisse. Dans ce mode, les largeurs non entières ne sont pas arrondies.

La plupart des implémentations OpenGL prennent en charge de très grandes tailles de points. La taille maximale des points anticrénelés est interrogeable, mais les mêmes informations ne sont pas disponibles pour les points crénelés standard. Une mise en œuvre particulière, cependant, pourrait limiter la taille des points aliasés standard à au moins sa taille de point anticrénelée maximale, arrondie à la valeur entière la plus proche. Vous pouvez obtenir cette valeur à virgule flottante en utilisant GL_POINT_SIZE_RANGE avec glGetFloatv() .

Détails de la ligne

Avec OpenGL, vous pouvez spécifier des lignes de différentes largeurs et des lignes pointillées de différentes manières - en pointillés, en pointillés, dessinées avec une alternance de points et de tirets, etc.

Lignes larges

Le rendu réel des lignes est affecté par le mode d'anticrénelage, de la même manière que pour les points. (Voir "Anticrénelage" au chapitre 6.) Sans anticrénelage, des largeurs de 1, 2 et 3 dessinent des lignes de 1, 2 et 3 pixels de large. Lorsque l'anticrénelage est activé, des largeurs de ligne non entières sont possibles et les pixels sur les limites sont généralement dessinés à une intensité inférieure à la pleine intensité. Comme pour les tailles de points, une implémentation OpenGL particulière peut limiter la largeur des lignes non anticrénelées à sa largeur de ligne anticrénelée maximale, arrondie à la valeur entière la plus proche. Vous pouvez obtenir cette valeur à virgule flottante en utilisant GL_LINE_WIDTH_RANGE avec glGetFloatv() .

Remarque : gardez à l'esprit que par défaut, les lignes ont une largeur de 1 pixel, elles apparaissent donc plus larges sur les écrans à faible résolution. Pour les écrans d'ordinateur, ce n'est généralement pas un problème, mais si vous utilisez OpenGL pour effectuer un rendu sur un traceur haute résolution, les lignes de 1 pixel peuvent être presque invisibles. Pour obtenir des largeurs de ligne indépendantes de la résolution, vous devez prendre en compte les dimensions physiques des pixels.

Avec des lignes larges non anticrénelées, la largeur de ligne n'est pas mesurée perpendiculairement à la ligne. Au lieu de cela, il est mesuré dans la direction y si la valeur absolue de la pente est inférieure à 1,0, sinon, il est mesuré dans la direction x. Le rendu d'une ligne anticrénelée est exactement équivalent au rendu d'un rectangle rempli de largeur donnée, centré sur la ligne exacte.

Lignes pointillées

Pour créer des lignes pointillées (pointillées ou pointillées), vous utilisez la commande glLineStipple() pour définir le motif de pointillé, puis vous activez la ligne pointillée avec glEnable() .

void glLineStipple (facteur GLint , motif GLushort ) Définit le motif de pointillé actuel pour les lignes. L'argument pattern est une série de 16 bits de 0 et de 1, et il est répété autant de fois que nécessaire pour pointer une ligne donnée. Un 1 indique que le dessin se produit, et 0 qu'il n'y en a pas, pixel par pixel, en commençant par le bit de poids faible du motif. Le motif peut être étendu en utilisant factor , qui multiplie chaque sous-série de 1 et de 0 consécutifs. Ainsi, si trois 1 consécutifs apparaissent dans le motif, ils sont étirés à six si le facteur est 2. le facteur est limité pour se situer entre 1 et 255. Le pointillé de ligne doit être activé en passant GL_LINE_STIPPLE à glEnable() il est désactivé en passant le même argument à glDisable() .

Avec l'exemple précédent et le motif 0x3F07 (qui se traduit par 0011111100000111 en binaire), une ligne serait dessinée avec 3 pixels activés, puis 5 désactivés, 6 activés et 2 désactivés. (Si cela semble en arrière, rappelez-vous que le bit de poids faible est utilisé en premier.) Si le facteur avait été de 2, le motif aurait été allongé : 6 pixels activés, 10 désactivés, 12 activés et 4 désactivés. La figure 2-8 montre des lignes tracées avec différents motifs et facteurs de répétition. Si vous n'activez pas le pointillé de ligne, le dessin se déroule comme si le motif était 0xFFFF et facteur 1. (Utilisez glDisable() avec GL_LINE_STIPPLE pour désactiver le pointillé.) Notez que le pointillé peut être utilisé en combinaison avec des lignes larges pour produire des lignes pointillées larges.

Figure 2-8 : Lignes pointillées

Une façon de penser au pointillé est que lorsque la ligne est dessinée, le motif est décalé d'un bit à chaque fois qu'un pixel est dessiné (ou que des pixels de facteur sont dessinés, si le facteur n'est pas 1). Lorsqu'une série de segments de ligne connectés est dessinée entre un seul glBegin() et glEnd() , le motif continue de se déplacer à mesure qu'un segment se transforme en un autre. De cette façon, un motif de pointillé se poursuit sur une série de segments de ligne connectés. Lorsque glEnd() est exécuté, le motif est réinitialisé et - si plus de lignes sont dessinées avant que le pointillé ne soit désactivé - le pointillé redémarre au début du motif. Si vous dessinez des lignes avec GL_LINES, le motif se réinitialise pour chaque ligne indépendante.

L'exemple 2-5 illustre les résultats du dessin avec quelques motifs de pointillés et largeurs de ligne différents. Il illustre également ce qui se passe si les lignes sont dessinées comme une série de segments individuels au lieu d'une seule bande de ligne connectée. Les résultats de l'exécution du programme apparaissent dans la Figure 2-9.

Figure 2-9 : Lignes pointillées larges

Exemple 2-5 : Motifs de pointillés : lines.c

Détails du polygone

Les polygones sont généralement dessinés en remplissant tous les pixels inclus dans la limite, mais vous pouvez également les dessiner comme des polygones délimités ou simplement comme des points aux sommets. Un polygone rempli peut être solidement rempli ou pointillé avec un certain motif. Bien que les détails exacts soient omis ici, les polygones remplis sont dessinés de telle sorte que si des polygones adjacents partagent un bord ou un sommet, les pixels constituant le bord ou le sommet sont dessinés exactement une fois - ils sont inclus dans un seul des polygones. Ceci est fait pour que les polygones partiellement transparents n'aient pas leurs bords dessinés deux fois, ce qui rendrait ces bords plus sombres (ou plus clairs, selon la couleur avec laquelle vous dessinez). Notez qu'il peut en résulter des polygones étroits n'ayant pas de pixels remplis dans une ou plusieurs lignes ou colonnes de pixels. L'anticrénelage des polygones est plus compliqué que pour les points et les lignes. (Voir "Anticrénelage" au chapitre 6 pour plus de détails.)

Polygones sous forme de points, de contours ou de solides

Un polygone a deux côtés - avant et arrière - et peut être rendu différemment selon le côté qui fait face au spectateur. Cela vous permet d'avoir des vues en coupe d'objets solides dans lesquels il existe une distinction évidente entre les pièces qui sont à l'intérieur et celles qui sont à l'extérieur. Par défaut, les faces avant et arrière sont dessinées de la même manière. Pour changer cela, ou pour ne dessiner que des contours ou des sommets, utilisez glPolygonMode() .

void glPolygonMode (GLenum face , GLenum mode ) Contrôle le mode de dessin des faces avant et arrière d'un polygone. Le paramètre face peut être GL_FRONT_AND_BACK, GL_FRONT, ou le mode GL_BACK peut être GL_POINT, GL_LINE ou GL_FILL pour indiquer si le polygone doit être dessiné sous forme de points, délimité ou rempli. Par défaut, les faces avant et arrière sont dessinées remplies.

Par exemple, vous pouvez avoir les faces avant remplies et les faces arrière décrites avec deux appels à cette routine :

Inversion et suppression des faces de polygone

Par convention, les polygones dont les sommets apparaissent dans le sens inverse des aiguilles d'une montre à l'écran sont dits de face. Vous pouvez construire la surface de n'importe quel solide "raisonnable" - un mathématicien appellerait une telle surface une variété orientable (les sphères, les beignets et les théières sont des bouteilles de Klein orientables et les bandes de Mobius ne le sont pas) - à partir de polygones d'orientation cohérente. En d'autres termes, vous pouvez utiliser tous les polygones dans le sens horaire ou tous les polygones dans le sens antihoraire. (C'est essentiellement la définition mathématique de orientable.)

Supposons que vous ayez systématiquement décrit un modèle de surface orientable mais que vous ayez l'orientation dans le sens des aiguilles d'une montre à l'extérieur. Vous pouvez échanger ce qu'OpenGL considère comme la face arrière en utilisant la fonction glFrontFace() , fournissant l'orientation souhaitée pour les polygones orientés vers l'avant.

void glFrontFace (mode GLenum) Contrôle la façon dont les polygones orientés vers l'avant sont déterminés. Par défaut, le mode est GL_CCW, ce qui correspond à une orientation dans le sens inverse des aiguilles d'une montre des sommets ordonnés d'un polygone projeté en coordonnées de fenêtre. Si le mode est GL_CW, les faces orientées dans le sens des aiguilles d'une montre sont considérées comme orientées vers l'avant.

Dans une surface complètement fermée construite à partir de polygones opaques avec une orientation cohérente, aucun des polygones orientés vers l'arrière n'est jamais visible - ils sont toujours masqués par les polygones orientés vers l'avant. Si vous êtes en dehors de cette surface, vous pouvez activer l'élimination pour éliminer les polygones qu'OpenGL détermine sont orientés vers l'arrière. De même, si vous êtes à l'intérieur de l'objet, seuls les polygones orientés vers l'arrière sont visibles. Pour indiquer à OpenGL de supprimer les polygones orientés vers l'avant ou l'arrière, utilisez la commande glCullFace() et activez l'élimination avec glEnable() .

void glCullFace (mode GLenum ) Indique quels polygones doivent être supprimés (éliminés) avant qu'ils ne soient convertis en coordonnées d'écran. Le mode est soit GL_FRONT, GL_BACK ou GL_FRONT_AND_BACK pour indiquer face à face, face à dos ou tous les polygones. Pour prendre effet, l'abattage doit être activé à l'aide de glEnable() avec GL_CULL_FACE, il peut être désactivé avec glDisable() et le même argument.

En termes plus techniques, la décision de savoir si une face d'un polygone est orientée vers l'avant ou vers l'arrière dépend du signe de l'aire du polygone calculé en coordonnées de fenêtre. Une façon de calculer cette zone est

où x i et y i sont les coordonnées de fenêtre x et y du i ème sommet du polygone à n sommets et

En supposant que GL_CCW a été spécifié, si un >0, le polygone correspondant à ce sommet est considéré comme étant orienté vers l'avant, sinon, il est orienté vers l'arrière. Si GL_CW est spécifié et si un <0, alors le polygone correspondant est orienté vers l'avant sinon, il est orienté vers l'arrière.

Modifiez l'exemple 2-5 en ajoutant des polygones remplis. Expérimentez avec différentes couleurs. Essayez différents modes de polygone. Activez également l'abattage pour voir son effet.

Pointillé de polygones

Par défaut, les polygones remplis sont dessinés avec un motif plein. Ils peuvent également être remplis avec un motif de pointillés alignés sur la fenêtre 32 bits par 32 bits, que vous spécifiez avec glPolygonStipple() .

void glPolygonStipple (const GLubyte * mask ) Définit le motif de pointillé actuel pour les polygones remplis. L'argument mask est un pointeur vers un bitmap 32 ´ 32 qui est interprété comme un masque de 0 et de 1. Lorsqu'un 1 apparaît, le pixel correspondant dans le polygone est dessiné, et où un 0 apparaît, rien n'est dessiné. La figure 2-10 montre comment un motif de pointillés est construit à partir des caractères du masque. Le pointillé de polygone est activé et désactivé en utilisant glEnable() et glDisable() avec GL_POLYGON_STIPPLE comme argument. L'interprétation des données de masque est affectée par les modes glPixelStore*() GL_UNPACK*. (Voir « Contrôle des modes de stockage des pixels » au chapitre 8.)

En plus de définir le motif de pointillé du polygone actuel, vous devez activer le pointillé :

Utilisez glDisable() avec le même argument pour désactiver le pointillé de polygone.

La figure 2-11 montre les résultats des polygones dessinés sans pointillés, puis avec deux motifs de pointillés différents. Le programme est illustré dans l'exemple 2-6. L'inversion du blanc au noir (de la figure 2-10 à la figure 2-11) se produit parce que le programme dessine en blanc sur un fond noir, en utilisant le motif de la figure 2-10 comme gabarit.

Figure 2-10 : Construction d'un motif de pointillé de polygone

Figure 2-11 : Polygones pointillés

Exemple 2-6 : Motifs de pointillés polygonaux : polys.c

Vous souhaiterez peut-être utiliser des listes d'affichage pour stocker des motifs de pointillés polygonaux afin d'optimiser l'efficacité. (Voir "Philosophie de conception des listes d'affichage" au chapitre 7.)

Marquage des bords des limites de polygone

OpenGL ne peut rendre que des polygones convexes, mais de nombreux polygones non convexes apparaissent dans la pratique. Pour dessiner ces polygones non convexes, vous les subdivisez généralement en polygones convexes - généralement des triangles, comme illustré à la figure 2-12 - puis dessinez les triangles. Malheureusement, si vous décomposez un polygone général en triangles et dessinez les triangles, vous ne pouvez pas vraiment utiliser glPolygonMode() pour dessiner le contour du polygone, car vous obtenez tous les contours des triangles à l'intérieur. Pour résoudre ce problème, vous pouvez indiquer à OpenGL si un sommet particulier précède une arête frontière. OpenGL garde une trace de cette information en transmettant avec chaque sommet un bit indiquant si ce sommet est suivi d'une arête frontière. Ensuite, lorsqu'un polygone est dessiné en mode GL_LINE, les arêtes non frontières ne sont pas dessinées. Dans la Figure 2-12, les lignes pointillées représentent les arêtes ajoutées.

Figure 2-12 : Subdivision d'un polygone non convexe

Par défaut, tous les sommets sont marqués comme précédant un bord limite, mais vous pouvez contrôler manuellement le réglage du drapeau de bord avec la commande glEdgeFlag*() . Cette commande est utilisée entre les paires glBegin() et glEnd(), et elle affecte tous les sommets spécifiés après elle jusqu'au prochain appel glEdgeFlag(). Elle s'applique uniquement aux sommets spécifiés pour les polygones, les triangles et les quads, pas à ceux spécifiés pour les bandes de triangles ou de quads.

void glEdgeFlag (indicateur GLbooléen )
void glEdgeFlagv (const GLboolean * flag ) Indique si un sommet doit être considéré comme initialisant un bord limite d'un polygone. Si flag est GL_TRUE, l'indicateur d'arête est défini sur TRUE (valeur par défaut) et tous les sommets créés sont considérés comme précédant les arêtes de frontière jusqu'à ce que cette fonction soit à nouveau appelée avec l'indicateur GL_FALSE.

À titre d'exemple, l'exemple 2-7 dessine le contour illustré à la figure 2-13.

Figure 2-13 : Polygone tracé dessiné à l'aide de drapeaux de bord

Exemple 2-7 : Marquage des bords des limites d'un polygone

Vecteurs normaux

Un vecteur normal (ou normal, pour faire court) est un vecteur qui pointe dans une direction perpendiculaire à une surface. Pour une surface plane, une direction perpendiculaire est la même pour chaque point de la surface, mais pour une surface incurvée générale, la direction normale peut être différente à chaque point de la surface. Avec OpenGL, vous pouvez spécifier une normale pour chaque polygone ou pour chaque sommet. Les sommets du même polygone peuvent partager la même normale (pour une surface plane) ou avoir des normales différentes (pour une surface courbe). Mais vous ne pouvez pas affecter de normales ailleurs qu'aux sommets.

Les vecteurs normaux d'un objet définissent l'orientation de sa surface dans l'espace, en particulier son orientation par rapport aux sources lumineuses. Ces vecteurs sont utilisés par OpenGL pour déterminer la quantité de lumière que l'objet reçoit à ses sommets. L'éclairage - un vaste sujet en soi - est le sujet du chapitre 5, et vous voudrez peut-être revoir les informations suivantes après avoir lu ce chapitre. Les vecteurs normaux sont discutés brièvement ici parce que vous définissez des vecteurs normaux pour un objet en même temps que vous définissez la géométrie de l'objet.

Vous utilisez glNormal*() pour définir la normale actuelle sur la valeur de l'argument transmis. Les appels ultérieurs à glVertex*() entraînent l'affectation de la normale actuelle aux sommets spécifiés. Souvent, chaque sommet a une normale différente, ce qui nécessite une série d'appels alternés, comme dans l'exemple 2-8.

Exemple 2-8 : normales de surface aux sommets

void glNormal3 (TYPEnx, TYPEny, TYPEnz)
void glNormal3 v (const TYPE *v) Définit le vecteur normal actuel tel que spécifié par les arguments. La version non vectorielle (sans le v ) prend trois arguments, qui spécifient un vecteur ( nx, ny, nz ) considéré comme normal. Alternativement, vous pouvez utiliser la version vectorielle de cette fonction (avec le v ) et fournir un seul tableau de trois éléments pour spécifier la normale souhaitée. Les versions b , s et i mettent à l'échelle leurs valeurs de paramètre de manière linéaire jusqu'à la plage [-1.0,1.0].

Il n'y a pas de magie pour trouver les normales d'un objet - très probablement, vous devez effectuer des calculs qui peuvent inclure la prise de dérivées - mais il existe plusieurs techniques et astuces que vous pouvez utiliser pour obtenir certains effets. L'annexe E explique comment trouver des vecteurs normaux pour des surfaces. Si vous savez déjà comment faire cela, si vous pouvez compter sur le fait d'être toujours fourni avec des vecteurs normaux, ou si vous ne voulez pas utiliser la fonction d'éclairage fournie par OpenGL Lighting Facility, vous n'avez pas besoin de lire cette annexe.

Notez qu'à un point donné sur une surface, deux vecteurs sont perpendiculaires à la surface, et ils pointent dans des directions opposées. Par convention, la normale est celle qui pointe vers l'extérieur de la surface à modéliser. (Si l'intérieur et l'extérieur de votre modèle sont inversés, changez simplement chaque vecteur normal de ( x, y, z ) à (- &xgr , - y, - z )).

De plus, gardez à l'esprit que puisque les vecteurs normaux n'indiquent que la direction, leur longueur n'a pratiquement aucune importance. Vous pouvez spécifier des normales de n'importe quelle longueur, mais elles doivent éventuellement être converties pour avoir une longueur de 1 avant que les calculs d'éclairage ne soient effectués. (Un vecteur qui a une longueur de 1 est dit de longueur unitaire, ou normalisé.) En général, vous devez fournir des vecteurs normaux normalisés. Pour créer un vecteur normal de longueur unitaire, divisez chacune de ses composantes x , y , z par la longueur de la normale :

Les vecteurs normaux restent normalisés tant que vos transformations de modèle n'incluent que des rotations et des translations. (Voir le chapitre 3 pour une discussion sur les transformations.) Si vous effectuez des transformations irrégulières (telles que la mise à l'échelle ou la multiplication par une matrice de cisaillement), ou si vous spécifiez des normales de longueur non unitaire, OpenGL devrait alors normaliser automatiquement vos vecteurs normaux après les transformations. . Pour ce faire, appelez glEnable() avec GL_NORMALIZE comme argument. Par défaut, la normalisation automatique est désactivée. Notez que la normalisation automatique nécessite généralement des calculs supplémentaires qui peuvent réduire les performances de votre application.

Tableaux de sommets

Vous avez peut-être remarqué qu'OpenGL nécessite de nombreux appels de fonction pour rendre les primitives géométriques. Dessiner un polygone à 20 côtés nécessite 22 appels de fonction : un appel à glBegin() , un appel pour chacun des sommets et un dernier appel à glEnd() . Dans les deux exemples de code précédents, des informations supplémentaires (indicateurs de bord de limite de polygone ou normales de surface) ont ajouté des appels de fonction pour chaque sommet. Cela peut rapidement doubler ou tripler le nombre d'appels de fonction requis pour un objet géométrique. Pour certains systèmes, les appels de fonction ont une surcharge importante et peuvent nuire aux performances.

Un problème supplémentaire est le traitement redondant des sommets qui sont partagés entre des polygones adjacents. Par exemple, le cube de la figure 2-14 a six faces et huit sommets partagés. Malheureusement, en utilisant la méthode standard de description de cet objet, chaque sommet devrait être spécifié trois fois : une fois pour chaque face qui l'utilise. Ainsi, 24 sommets seraient traités, même si huit suffiraient.

Figure 2-14 : Six côtés huit sommets partagés

OpenGL a des routines de tableau de sommets qui vous permettent de spécifier un grand nombre de données liées aux sommets avec seulement quelques tableaux et d'accéder à ces données avec également peu d'appels de fonction. En utilisant des routines de tableau de sommets, les 20 sommets d'un polygone à 20 côtés peuvent être placés dans un tableau et appelés avec une seule fonction. Si chaque sommet avait également une normale de surface, les 20 normales de surface pourraient être placées dans un autre tableau et également appelées avec une fonction.

L'organisation des données dans des tableaux de sommets peut augmenter les performances de votre application. L'utilisation de tableaux de sommets réduit le nombre d'appels de fonction, ce qui améliore les performances. De plus, l'utilisation de tableaux de sommets peut permettre un traitement non redondant des sommets partagés. (Le partage de sommets n'est pas pris en charge sur toutes les implémentations d'OpenGL.)

Remarque : les tableaux Vertex sont standard dans la version 1.1 d'OpenGL mais ne faisaient pas partie de la spécification OpenGL 1.0.Avec OpenGL 1.0, certains fournisseurs ont implémenté des tableaux de sommets en tant qu'extension.

L'utilisation de tableaux de sommets pour le rendu de la géométrie comporte trois étapes.

Activez (activez) jusqu'à six tableaux, chacun pour stocker un type de données différent : coordonnées de sommet, couleurs RGBA, indices de couleur, normales de surface, coordonnées de texture ou drapeaux de bord de polygone.

Mettez les données dans le ou les tableaux. Les tableaux sont accessibles par les adresses de (c'est-à-dire des pointeurs vers) leurs emplacements mémoire. Dans le modèle client-serveur, ces données sont stockées dans l'espace d'adressage du client.

Dessinez la géométrie avec les données. OpenGL obtient les données de tous les tableaux activés en déréférenciant les pointeurs. Dans le modèle client-serveur, les données sont transférées vers l'espace d'adressage du serveur. Il y a trois façons de le faire :

Accéder aux éléments individuels du tableau (sauter au hasard)

Création d'une liste d'éléments de tableau individuels (en sautant méthodiquement)

Traitement des éléments de tableau séquentiels

La méthode de déréférencement que vous choisissez peut dépendre du type de problème que vous rencontrez.

Les données de tableau de sommets entrelacées sont une autre méthode courante d'organisation. Au lieu d'avoir jusqu'à six tableaux différents, chacun conservant un type de données différent (couleur, normale de surface, coordonnée, etc.), vous pourriez avoir les différents types de données mélangés dans un seul tableau. (Voir " Tableaux entrelacés " pour deux méthodes pour résoudre ce problème.)

Étape 1 : Activation des baies

La première étape consiste à appeler glEnableClientState() avec un paramètre énuméré, ce qui active le tableau choisi. En théorie, vous devrez peut-être l'appeler jusqu'à six fois pour activer les six tableaux disponibles. En pratique, vous n'activerez probablement qu'entre un et quatre tableaux. Par exemple, il est peu probable que vous activiez à la fois GL_COLOR_ARRAY et GL_INDEX_ARRAY, car le mode d'affichage de votre programme prend en charge le mode RGBA ou le mode d'index de couleur, mais probablement pas les deux simultanément.

void glEnableClientState (GLenum array ) Spécifie le tableau à activer. Les constantes symboliques GL_VERTEX_ARRAY, GL_COLOR_ARRAY, GL_INDEX_ARRAY, GL_NORMAL_ARRAY, GL_TEXTURE_COORD_ARRAY et GL_EDGE_FLAG_ARRAY sont des paramètres acceptables.

Si vous utilisez un éclairage, vous souhaiterez peut-être définir une surface normale pour chaque sommet. (Voir « Vecteurs normaux. ») Pour utiliser des tableaux de sommets dans ce cas, vous activez à la fois les tableaux de normales de surface et de coordonnées de sommet :

Supposons que vous souhaitiez éteindre l'éclairage à un moment donné et dessiner simplement la géométrie en utilisant une seule couleur. Vous voulez appeler glDisable() pour désactiver les états d'éclairage (voir chapitre 5). Maintenant que l'éclairage a été désactivé, vous souhaitez également arrêter de modifier les valeurs de l'état normal de la surface, ce qui est un effort inutile. Pour ce faire, vous appelez

void glDisableClientState (GLenum array ) Spécifie le tableau à désactiver. Accepte les mêmes constantes symboliques que glEnableClientState() .

Vous vous demandez peut-être pourquoi les architectes d'OpenGL ont créé ces nouveaux (et longs !) noms de commandes, gl*ClientState() . Pourquoi ne pouvez-vous pas simplement appeler glEnable() et glDisable() ? L'une des raisons est que glEnable() et glDisable() peuvent être stockés dans une liste d'affichage, mais pas la spécification des tableaux de sommets, car les données restent du côté du client.

Étape 2 : Spécification des données pour les baies

Il existe un moyen simple par lequel une seule commande spécifie un seul tableau dans l'espace client. Il existe six routines différentes pour spécifier les tableaux - une routine pour chaque type de tableau. Il existe également une commande qui peut spécifier plusieurs tableaux d'espace client à la fois, tous provenant d'un seul tableau entrelacé.

void glVertexPointer (taille GLint , type GLenum , foulée GLsizei ,
const GLvoid *pointer ) Spécifie où les données de coordonnées spatiales sont accessibles. pointeur est l'adresse mémoire de la première coordonnée du premier sommet du tableau. type spécifie le type de données (GL_SHORT, GL_INT, GL_FLOAT ou GL_DOUBLE) de chaque coordonnée du tableau. size est le nombre de coordonnées par sommet, qui doit être 2, 3 ou 4. stride est le décalage d'octets entre les sommets consécutifs. Si la foulée est de 0, les sommets sont considérés comme étroitement emballés dans le tableau.

Pour accéder aux cinq autres tableaux, il existe cinq routines similaires :

void glColorPointer (taille GLint , type GLenum , foulée GLsizei ,
const GLvoid * pointeur )
void glIndexPointer (type GLenum , foulée GLsizei , const GLvoid * pointeur )
void glNormalPointer (type GLenum , foulée GLsizei ,
const GLvoid * pointeur )
void glTexCoordPointer (taille GLint , type GLenum , foulée GLsizei ,
const GLvoid * pointeur )
void glEdgeFlagPointer (GLsizei foulée , const GLvoid * pointeur )

Les principales différences entre les routines sont de savoir si la taille et le type sont uniques ou doivent être spécifiés. Par exemple, une normale de surface a toujours trois composants, il est donc redondant de spécifier sa taille. Un indicateur de bord est toujours un booléen unique, donc ni la taille ni le type n'ont besoin d'être mentionnés. Le tableau 2-4 affiche les valeurs légales pour la taille et les types de données.

Tableau 2-4 : Tailles des tableaux de sommets (valeurs par sommet) et types de données (suite)

GL_SHORT, GL_INT, GL_FLOAT, GL_DOUBLE

GL_BYTE, GL_SHORT, GL_INT, GL_FLOAT, GL_DOUBLE

GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_INT, GL_UNSIGNED_INT, GL_FLOAT, GL_DOUBLE

GL_UNSIGNED_BYTE, GL_SHORT, GL_INT, GL_FLOAT, GL_DOUBLE

GL_SHORT, GL_INT, GL_FLOAT, GL_DOUBLE

aucun argument de type (le type de données doit être GLboolean)

L'exemple 2-9 utilise des tableaux de sommets pour les couleurs RGBA et les coordonnées de sommet. Les valeurs à virgule flottante RVB et leurs coordonnées entières (x, y) correspondantes sont chargées dans GL_COLOR_ARRAY et GL_VERTEX_ARRAY.

Exemple 2-9 : Activation et chargement des tableaux de sommets : varray.c

Foulée

Avec une foulée de zéro, chaque type de tableau de sommets (couleur RVB, indice de couleur, coordonnée de sommet, etc.) doit être compacté. Les données du tableau doivent être homogènes, c'est-à-dire que les données doivent être toutes les valeurs de couleur RVB, toutes les coordonnées de sommet ou toutes les autres données similaires d'une manière ou d'une autre.

L'utilisation d'une foulée autre que zéro peut être utile, en particulier lorsqu'il s'agit de tableaux entrelacés. Dans le tableau suivant de GLfloats, il y a six sommets. Pour chaque sommet, il existe trois valeurs de couleur RVB, qui alternent avec les coordonnées du sommet (x, y, z).

Stride permet à un tableau de sommets d'accéder aux données souhaitées à intervalles réguliers dans le tableau. Par exemple, pour référencer uniquement les valeurs de couleur dans le tableau entrelacé, l'appel suivant commence au début du tableau (qui peut également être passé comme &intertwined[0] ) et avance de 6 * sizeof (GLfloat) octets, qui est le taille des valeurs de coordonnées de couleur et de sommet. Ce saut est suffisant pour accéder au début des données pour le prochain sommet.

Pour le pointeur de coordonnées de sommet, vous devez commencer plus loin dans le tableau, au quatrième élément entrelacé (rappelez-vous que les programmeurs C commencent à compter à zéro).

Étape 3 : Déréférencement et rendu

Tant que le contenu des tableaux de sommets n'est pas déréférencé, les tableaux restent côté client et leur contenu est facilement modifiable. À l'étape 3, le contenu des tableaux est obtenu, envoyé au serveur, puis envoyé au pipeline de traitement graphique pour le rendu.

Il existe trois façons d'obtenir des données : à partir d'un seul élément de tableau (emplacement indexé), à partir d'une séquence d'éléments de tableau et à partir d'une liste ordonnée d'éléments de tableau.

Déréférencer un élément de tableau unique

glArrayElement() est généralement appelé entre glBegin() et glEnd() . (S'il est appelé à l'extérieur, glArrayElement() définit l'état actuel de tous les tableaux activés, à l'exception du sommet, qui n'a pas d'état actuel.) Dans l'exemple 2-10, un triangle est dessiné en utilisant les troisième, quatrième et sixième sommets du sommet activé tableaux (encore une fois, rappelez-vous que les programmeurs C commencent à compter les emplacements des tableaux avec zéro).

Exemple 2-10 : Utilisation de glArrayElement() pour définir les couleurs et les sommets

Lorsqu'elles sont exécutées, les cinq dernières lignes de code ont le même effet que

Étant donné que glArrayElement() n'est qu'un seul appel de fonction par sommet, il peut réduire le nombre d'appels de fonction, ce qui augmente les performances globales.

Soyez averti que si le contenu du tableau est modifié entre glBegin() et glEnd() , il n'y a aucune garantie que vous recevrez les données d'origine ou les données modifiées pour l'élément demandé. Pour plus de sécurité, ne modifiez pas le contenu d'un élément de tableau auquel on pourrait accéder tant que la primitive n'est pas terminée.

Déréférencer une liste d'éléments de tableau

glArrayElement() est bon pour "sauter" au hasard vos tableaux de données. Une routine similaire, glDrawElements() , est utile pour parcourir vos tableaux de données de manière plus ordonnée.

void glDrawElements (mode GLenum , nombre GLsizei , type GLenum ,
void * indices ) Définit une séquence de primitives géométriques utilisant le nombre d'éléments, dont les indices sont stockés dans le tableau indices . type doit être l'un des GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT ou GL_UNSIGNED_INT, indiquant le type de données du tableau d'indices. mode spécifie quel type de primitives sont construits et est l'une des mêmes valeurs qui sont acceptées par glBegin() par exemple, GL_POLYGON, GL_LINE_LOOP, GL_LINES, GL_POINTS, et ainsi de suite.

L'effet de glDrawElements() est presque le même que cette séquence de commandes :

glDrawElements() vérifie en outre que mode , count et type sont valides. De plus, contrairement à la séquence précédente, l'exécution de glDrawElements() laisse plusieurs états indéterminés. Après l'exécution de glDrawElements() , la couleur RVB actuelle, l'indice de couleur, les coordonnées normales, les coordonnées de texture et le drapeau de bord sont indéterminés si le tableau correspondant a été activé.

Avec glDrawElements() , les sommets de chaque face du cube peuvent être placés dans un tableau d'indices. L'exemple 2-11 montre deux manières d'utiliser glDrawElements() pour rendre le cube. La figure 2-15 montre la numérotation des sommets utilisée dans l'exemple 2-11.

Figure 2-15 : Cube à sommets numérotés

Exemple 2-11 : Deux manières d'utiliser glDrawElements()

Ou mieux encore, rassemblez tous les indices :

Remarque : C'est une erreur d'encapsuler glDrawElements() entre une paire glBegin() / glEnd().

Avec à la fois glArrayElement() et glDrawElements() , il est également possible que votre implémentation OpenGL mette en cache les sommets récemment traités, permettant à votre application de "partager" ou de "réutiliser" les sommets. Prenez le cube susmentionné, par exemple, qui a six faces (polygones) mais seulement huit sommets. Chaque sommet est utilisé par exactement trois faces. Sans glArrayElement() ou glDrawElements() , le rendu des six faces nécessiterait le traitement de vingt-quatre sommets, même si seize sommets seraient redondants. Votre implémentation d'OpenGL peut être en mesure de minimiser la redondance et de traiter aussi peu que huit sommets. (La réutilisation des sommets peut être limitée à tous les sommets dans un seul appel glDrawElements() ou, pour glArrayElement() , dans une paire glBegin() / glEnd().)

Déréférencer une séquence d'éléments de tableau

Alors que glArrayElement() et glDrawElements() "sautent" vos tableaux de données, glDrawArrays() les parcourt directement.

void glDrawArrays (GLenum mode , GLint first , GLsizei count ) Construit une séquence de primitives géométriques en utilisant des éléments de tableau commençant en premier et se terminant en premier + count -1 de chaque tableau activé. mode spécifie quels types de primitives sont construits et est l'une des mêmes valeurs acceptées par glBegin() par exemple, GL_POLYGON, GL_LINE_LOOP, GL_LINES, GL_POINTS, et ainsi de suite.

L'effet de glDrawArrays() est presque le même que cette séquence de commandes :

Comme c'est le cas avec glDrawElements() , glDrawArrays() effectue également une vérification d'erreur sur les valeurs de ses paramètres et laisse la couleur RVB actuelle, l'indice de couleur, les coordonnées normales, les coordonnées de texture et le drapeau de bord avec des valeurs indéterminées si le tableau correspondant a été activé.

Tableaux entrelacés

Plus tôt dans ce chapitre (dans "Stride"), le cas particulier des tableaux entrelacés a été examiné. Dans cette section, le tableau entrelacé , qui entrelace la couleur RVB et les coordonnées de sommet 3D, était accessible par des appels à glColorPointer() et glVertexPointer() . Une utilisation prudente de la foulée a permis de spécifier correctement les tableaux.

Il existe également une routine géante, glInterleavedArrays() , qui peut spécifier plusieurs tableaux de sommets à la fois. glInterleavedArrays() active et désactive également les tableaux appropriés (il combine donc les étapes 1 et 2). Le tableau entrelacé correspond exactement à l'une des quatorze configurations d'entrelacement de données prises en charge par glInterleavedArrays() . Donc, pour spécifier le contenu du tableau entrelacé dans les tableaux de couleurs RVB et de sommets et activer les deux tableaux, appelez

Cet appel à glInterleavedArrays() active les tableaux GL_COLOR_ARRAY et GL_VERTEX_ARRAY. Il désactive GL_INDEX_ARRAY, GL_TEXTURE_COORD_ARRAY, GL_NORMAL_ARRAY et GL_EDGE_FLAG_ARRAY.

Cet appel a également le même effet que d'appeler glColorPointer() et glVertexPointer() pour spécifier les valeurs de six sommets dans chaque tableau. Vous êtes maintenant prêt pour l'étape 3 : Appeler glArrayElement() , glDrawElements() ou glDrawArrays() pour déréférencer les éléments du tableau.

void glInterleavedArrays (GLenum format , GLsizei stride , void * pointer ) Initialise les six tableaux, désactivant les tableaux qui ne sont pas spécifiés dans format , et activant les tableaux qui sont spécifiés. format est l'une des 14 constantes symboliques, qui représentent 14 configurations de données. Le tableau 2-5 affiche les valeurs de format. stride spécifie le décalage d'octet entre les sommets consécutifs. Si la foulée est de 0, les sommets sont considérés comme étant étroitement emballés dans le tableau. pointeur est l'adresse mémoire de la première coordonnée du premier sommet du tableau.

Notez que glInterleavedArrays() ne prend pas en charge les indicateurs de bord.

Les mécanismes de glInterleavedArrays() sont complexes et nécessitent une référence à l'exemple 2-12 et au tableau 2-5. Dans cet exemple et ce tableau, vous verrez et, ec et en, qui sont les valeurs booléennes pour les tableaux de coordonnées de texture, de couleur et de normal activés ou désactivés, et vous verrez st, sc et sv, qui sont les tailles (nombre de composants) pour les tableaux de coordonnées de texture, de couleurs et de sommets. tc est le type de données pour la couleur RGBA, qui est le seul tableau qui peut avoir des valeurs entrelacées non flottantes. pc, pn et pv sont les foulées calculées pour sauter par-dessus les valeurs de couleur, de normale et de sommet individuelles, et s est la foulée (si l'utilisateur n'en spécifie pas une) pour passer d'un élément du tableau au suivant.

L'effet de glInterleavedArrays() est le même que l'appel de la séquence de commandes de l'exemple 2-12 avec de nombreuses valeurs définies dans le tableau 2-5. Toute l'arithmétique de pointeur est effectuée en unités de taille (GL_UNSIGNED_BYTE).

Exemple 2-12 : Effet de glInterleavedArrays(format, foulée, pointeur)

Dans le Tableau 2-5, T et F sont Vrai et Faux. f est la taille de (GL_FLOAT). c est 4 fois la taille de (GL_UNSIGNED_BYTE), arrondie au multiple supérieur de f.


ST_INTERSECT de chaque élément de deux tableaux (polygones, lignes) - Systèmes d'Information Géographique

Qu'est-ce que le SIG ?

Définition d'un système d'information géographique : un système de matériel, de logiciels et de procédures conçu pour prendre en charge la capture, la gestion, la manipulation, l'analyse, la modélisation et l'affichage de données référencées spatialement pour résoudre des problèmes complexes de planification et de gestion impliquant des données référencées spatialement. à la terre.

Un système d'information géographique (SIG) est un outil informatique permettant de cartographier et d'analyser les choses qui existent et les événements qui se produisent sur terre. La technologie SIG intègre des opérations de base de données courantes telles que les requêtes et l'analyse statistique avec les avantages uniques de visualisation et d'analyse géographique offerts par les cartes. Ces capacités distinguent le SIG des autres systèmes d'information et le rendent précieux pour un large éventail d'entreprises publiques et privées pour expliquer les événements, prédire les résultats et planifier les stratégies. Les défis majeurs auxquels nous sommes confrontés dans le monde aujourd'hui - surpopulation, pollution, déforestation, catastrophes naturelles - ont une dimension géographique critique.

Composants d'un SIG :

Un SIG fonctionnel intègre cinq composants clés : le matériel, les logiciels, les données, les personnes et les méthodes.

Matériel : Le matériel est l'ordinateur sur lequel fonctionne un SIG. Aujourd'hui, les logiciels SIG fonctionnent sur un large éventail de types de matériel, des serveurs informatiques centralisés aux ordinateurs de bureau utilisés dans des configurations autonomes ou en réseau.

Logiciel : le logiciel SIG fournit les fonctions et les outils nécessaires pour stocker, analyser et afficher des informations géographiques. Les principaux composants logiciels sont

    • Outils de saisie et de manipulation d'informations géographiques
    • Un système de gestion de base de données (SGBD)
    • Outils prenant en charge les requêtes géographiques, l'analyse et la visualisation
    • Une interface utilisateur graphique (GUI) pour un accès facile aux outils

    Données : Les données sont probablement la composante la plus importante d'un SIG. Les données géographiques et les données tabulaires associées peuvent être collectées en interne ou achetées auprès d'un fournisseur de données commercial. Un SIG intégrera les données spatiales avec d'autres ressources de données et peut même utiliser un SGBD, utilisé par la plupart des organisations pour organiser et maintenir leurs données, afin de gérer les données spatiales.

    Personnes : la technologie SIG a une valeur limitée sans les personnes qui gèrent le système et élaborent des plans pour l'appliquer aux problèmes du monde réel. Les utilisateurs de SIG vont des spécialistes techniques qui conçoivent et entretiennent le système à ceux qui l'utilisent pour les aider à effectuer leur travail quotidien.

    Méthodes : Un SIG réussi fonctionne selon un plan bien conçu et des règles commerciales, qui sont les modèles et les pratiques d'exploitation propres à chaque organisation.

    Comment fonctionne le SIG :

    Un SIG stocke des informations sur le monde sous la forme d'un ensemble de couches thématiques pouvant être reliées entre elles par la géographie. Ce concept simple mais extrêmement puissant et polyvalent s'est avéré inestimable pour résoudre de nombreux problèmes du monde réel, du suivi des véhicules de livraison à l'enregistrement des détails des applications de planification, en passant par la modélisation de la circulation atmosphérique mondiale.

    Références géographiques : Les informations géographiques contiennent soit une référence géographique explicite, telle qu'une latitude et une longitude ou une coordonnée de grille nationale, soit une référence implicite telle qu'une adresse, un code postal, un nom de secteur de recensement, un identifiant de peuplement forestier ou un nom de route. Un processus automatisé appelé géocodage est utilisé pour créer des références géographiques explicites (emplacements multiples) à partir de références implicites (descriptions telles que des adresses). Ces références géographiques vous permettent de localiser des entités, telles qu'une entreprise ou un peuplement forestier, et des événements, tels qu'un tremblement de terre, à la surface de la terre pour analyse.

    Modèles vectoriels et raster : Les systèmes d'information géographique fonctionnent avec deux types de modèles géographiques fondamentalement différents : le modèle "vecteur" et le modèle "quotraster". Dans le modèle vectoriel, les informations sur les points, les lignes et les polygones sont codées et stockées sous la forme d'une collection de coordonnées x,y. L'emplacement d'une entité ponctuelle, telle qu'un trou de forage, peut être décrit par une seule coordonnée x,y. Les entités linéaires, telles que les routes et les rivières, peuvent être stockées sous la forme d'un ensemble de coordonnées de points. Les entités polygonales, telles que les territoires de vente et les bassins versants, peuvent être stockées sous forme de boucle fermée de coordonnées.

    Le modèle vectoriel est extrêmement utile pour décrire des caractéristiques discrètes, mais moins utile pour décrire des caractéristiques qui varient continuellement, telles que le type de sol ou les coûts d'accessibilité pour les hôpitaux. Le modèle raster a évolué pour modéliser de telles entités continues. Une image raster comprend une collection de cellules de grille un peu comme une carte ou une image numérisée. Les modèles vectoriels et raster pour le stockage des données géographiques présentent des avantages et des inconvénients uniques. Les SIG modernes sont capables de gérer les deux modèles.

    Le processus SIG :

    • Saisir
    • Manipulation
    • Gestion
    • Requête et analyse
    • Visualisation

    Saisir

    Avant que les données géographiques puissent être utilisées dans un SIG, les données doivent être converties dans un format numérique approprié. Le processus de conversion des données de cartes papier en fichiers informatiques s'appelle la numérisation.

    La technologie SIG moderne peut automatiser entièrement ce processus pour les grands projets à l'aide de la technologie de numérisation. Les petits travaux peuvent nécessiter une numérisation manuelle (à l'aide d'une table de numérisation). Aujourd'hui, de nombreux types de données géographiques existent déjà dans des formats compatibles avec les SIG. Ces données peuvent être obtenues auprès de fournisseurs de données et chargées directement dans un SIG.

    Manipulation : il est probable que les types de données requis pour un projet SIG particulier devront être transformés ou manipulés d'une manière ou d'une autre pour les rendre compatibles avec votre système. Par exemple, l'information géographique est disponible à différentes échelles (fichiers détaillés des lignes médianes des rues moins les limites détaillées du recensement et les codes postaux au niveau régional). Avant que ces informations puissent être intégrées, elles doivent être transformées à la même échelle (degré de détail ou de précision). Il peut s'agir d'une transformation temporaire à des fins d'affichage ou d'une transformation permanente requise pour l'analyse. La technologie SIG offre de nombreux outils pour manipuler les données spatiales et pour éliminer les données inutiles.

    Gestion : Pour les petits projets SIG, il peut être suffisant de stocker les informations géographiques sous forme de fichiers simples. Cependant, lorsque les volumes de données deviennent importants et que le nombre d'utilisateurs de données devient plus que quelques-uns, il est souvent préférable d'utiliser un système de gestion de base de données (SGBD) pour aider à stocker, organiser et gérer les données. Un SGBD n'est rien de plus qu'un logiciel informatique pour gérer une base de données.

    Il existe de nombreuses conceptions différentes de SGBD, mais dans les SIG, la conception relationnelle a été la plus utile. Dans la conception relationnelle, les données sont stockées de manière conceptuelle sous la forme d'un ensemble de tables. Des champs communs dans différentes tables sont utilisés pour les lier ensemble. Cette conception étonnamment simple a été si largement utilisée principalement en raison de sa flexibilité et de son très large déploiement dans les applications à la fois dans et sans SIG.

    • A qui appartient la parcelle de terrain au coin de la rue ?
    • Quelle distance y a-t-il entre deux endroits ?
    • Où le terrain est-il zoné à usage industriel?
    • Où sont tous les sites propices à la construction de nouvelles maisons ?
    • Quel est le type de sol dominant pour la forêt de chênes?
    • Si je construis une nouvelle autoroute ici, comment le trafic sera-t-il affecté ?

    Le SIG offre à la fois des fonctionnalités de requête pointer-cliquer simples et des outils d'analyse sophistiqués pour fournir des informations opportunes aux gestionnaires et aux analystes. La technologie SIG prend tout son sens lorsqu'elle est utilisée pour analyser des données géographiques afin de rechercher des modèles et des tendances et d'entreprendre des scénarios "et si". Les SIG modernes disposent de nombreux outils analytiques puissants, mais deux sont particulièrement importants.

    • Combien de maisons se trouvent à moins de 100 m de cette conduite d'eau ?
    • Quel est le nombre total de clients à moins de 10 km de ce magasin ?
    • Quelle proportion de la culture de luzerne se trouve à moins de 500 m du puits?

    Pour répondre à ces questions, la technologie SIG utilise un processus appelé mise en mémoire tampon pour déterminer la relation de proximité entre les entités.

    Analyse de superposition :

    L'intégration de différentes couches de données implique un processus appelé superposition. Dans sa forme la plus simple, il peut s'agir d'une opération visuelle, mais les opérations analytiques nécessitent la jonction physique d'une ou plusieurs couches de données. Cette superposition, ou jointure spatiale, peut intégrer des données sur les sols, la pente et la végétation, ou la propriété foncière avec évaluation fiscale.

    Visualisation:


    Pour de nombreux types d'opérations géographiques, le résultat final est mieux visualisé sous forme de carte ou de graphique. Les cartes sont très efficaces pour stocker et communiquer des informations géographiques. Alors que les cartographes créent des cartes depuis des millénaires, les SIG fournissent des outils nouveaux et passionnants pour étendre l'art et la science de la cartographie. Les affichages cartographiques peuvent être intégrés à des rapports, des vues en trois dimensions, des images photographiques et d'autres sorties telles que le multimédia.

    Technologie associée : Les SIG sont étroitement liés à plusieurs autres types de systèmes d'information, mais c'est la capacité de manipuler et d'analyser des données géographiques qui distingue la technologie SIG. Bien qu'il n'y ait pas de règles strictes sur la façon de classer les systèmes d'information, la discussion suivante devrait aider à différencier les SIG des technologies de cartographie de bureau, de conception assistée par ordinateur (CAO), de télédétection, de SGBD et de systèmes de positionnement global (GPS).

    Cartographie du bureau :

    Un système de cartographie de bureau utilise la métaphore de la carte pour organiser les données et l'interaction de l'utilisateur. L'objectif de ces systèmes est la création de cartes : la carte est la base de données. La plupart des systèmes de cartographie de bureau ont des capacités de gestion des données, d'analyse spatiale et de personnalisation plus limitées. Les systèmes de cartographie de bureau fonctionnent sur des ordinateurs de bureau tels que des PC, des Macintosh et des stations de travail UNIX plus petites.

    Les systèmes de CAO ont évolué pour créer des conceptions et des plans de bâtiments et d'infrastructures. Cette activité nécessitait que des composants de caractéristiques fixes soient assemblés pour créer l'ensemble de la structure. Ces systèmes nécessitent peu de règles pour spécifier comment les composants peuvent être assemblés et des capacités analytiques très limitées. Les systèmes de CAO ont été étendus pour prendre en charge les cartes mais ont généralement une utilité limitée pour la gestion et l'analyse de grandes bases de données géographiques.

    Télédétection et GPS :


    La télédétection est l'art et la science de faire des mesures de la terre à l'aide de capteurs tels que des caméras embarquées dans des avions, des récepteurs GPS ou d'autres appareils. Ces capteurs collectent des données sous forme d'images et fournissent des capacités spécialisées pour manipuler, analyser et visualiser ces images. Faute d'une solide gestion des données géographiques et d'opérations analytiques, ils ne peuvent pas être appelés de véritables SIG.

    Les systèmes de gestion de bases de données sont spécialisés dans le stockage et la gestion de tous types de données, y compris les données géographiques. Les SGBD sont optimisés pour stocker et récupérer des données et de nombreux SIG s'appuient sur eux à cette fin. Ils ne disposent pas des outils d'analyse et de visualisation communs aux SIG.

    Pourquoi la géographie est importante pour les gouvernements locaux :

    Les gouvernements étatiques et locaux sont de plus en plus tenus de rationaliser leurs pratiques commerciales tout en respectant des exigences réglementaires complexes. Pour ce faire, ils doivent digérer une immense quantité d'informations pour accomplir leurs tâches de manière juste et saine. Presque toutes ces informations sont d'une manière ou d'une autre liées à un élément géographique tel qu'une adresse, un colis, un code postal, un bloc de recensement ou un autre élément.

    La technologie SIG fournit un ensemble flexible d'outils pour exécuter les diverses fonctions du gouvernement en fournissant les outils de gestion des données pour aider à accomplir la tâche gargantuesque de gérer toutes ces informations géographiques. Plus important encore, la technologie SIG facilite le partage de données entre les ministères et autres organismes afin que le gouvernement puisse travailler comme une seule entreprise.


    Affichez la grille hexagonale pour visualiser la fourmi de Langton

    Je cherche à recréer l'image suivante à partir de cette référence comme

    en utilisant la documentation Polygon de Mathematica sous "Applications" comme point de départ. Je veux éventuellement utiliser Mathematica pour visualiser l'évolution de la fourmi de Langton multicolore sur une grille hexagonale (pas trop important). En travaillant pour créer la ligne z = 0 (indiquée dans l'image ci-dessus comme des 0 bleus) en utilisant Polygon et Graphics . Je génère un hexagone en utilisant l'exemple de Mathematica avec une rotation Pi/6 comme suit :

    pour créer un polygone au centre de avec la longueur de côté 1 tournée de manière appropriée. Je cherche ensuite à créer une rangée de ces polygones régulièrement espacés de sorte que leurs côtés se touchent comme dans l'image ci-dessus 2. Pour cela, je pense que chaque centre sera à 2r des centres adjacents où r est défini comme la longueur de le point central au centre du côté et est Sqrt[3]/2 * t où t est la longueur du côté telle que définie à partir de Wikipedia. Par conséquent, j'essaie de créer des hexagones où e hexagone est Sqrt[3] * i loin de <0,0>. Pour ce faire j'ai le code suivant

    qui produit la sortie suivante

    Je pense que mes mathématiques sont "solides" ici dans la façon dont je veux disposer les polygones, mais je n'arrive pas à les obtenir dans la bonne configuration. Comment puis-je faire en sorte que mes hexagones se touchent sur les bords d'une rangée en tant que tels où je crée un polygone en fonction de l'endroit où le point central devrait être (que je calculerais en fonction de la longueur des côtés de chaque hexagone) ?

    Merci d'avance! Je ne maîtrise pas Mathematica, donc je pense que mon erreur est la façon dont je programme, mais il se peut que j'aie raté quelque chose d'évident dans le problème et que mon code est correct :)


    Risque d'approvisionnement

    Capacité calorifique spécifique (J kg −1 K −1 )

    La capacité calorifique spécifique est la quantité d'énergie nécessaire pour modifier la température d'un kilogramme d'une substance de 1 K.

    Une mesure de la rigidité d'une substance. Il fournit une mesure de la difficulté d'étendre un matériau, avec une valeur donnée par le rapport de la résistance à la traction à la déformation à la traction.

    Une mesure de la difficulté à déformer un matériau. Elle est donnée par le rapport entre la contrainte de cisaillement et la déformation de cisaillement.

    Une mesure de la difficulté de comprimer une substance. Elle est donnée par le rapport de la pression sur un corps à la diminution fractionnaire de volume.

    Mesure de la propension d'une substance à s'évaporer. Elle est définie comme la pression d'équilibre exercée par le gaz produit au-dessus d'une substance dans un système fermé.


    ST_INTERSECT de chaque élément de deux tableaux (polygones, lignes) - Systèmes d'Information Géographique

    Plus grande satisfaction personnelle :

    Enquêtes et documents d'exposition

      Une introduction à la méthode du gradient conjugué sans la douleur atroce, août 1994. Abstrait, PostScript (1 716k, 58 pages), PDF (516k, 58 pages), PostScript de figures de classe (1 409k, 37 pages). PDF des figures de classe (394k, 37 pages). Ce rapport est un exercice visant à rendre un sujet difficile aussi transparent et facile à comprendre qu'il est humainement possible. Il comprend soixante-six illustrations et autant d'intuition que je peux fournir. Comment quinze lignes de pseudocode pourraient-elles prendre cinquante pages à expliquer ?

    Génération de maillage Delaunay

    Notre livre est un guide complet des algorithmes de raffinement de Delaunay qui sont mathématiquement garantis pour générer des maillages de haute qualité, y compris des maillages triangulaires dans le plan, des maillages de volume tétraédriques et des maillages de surface triangulaires intégrés en trois dimensions. C'est aussi le guide le plus complet disponible sur les triangulations de Delaunay et les algorithmes pour les construire. Ce livre a sa propre page web, cliquez ici pour plus de détails.

    • 1. Introduction.
    • 2. Triangulations de Delaunay à deux dimensions.
    • 3. Algorithmes de construction des triangulations de Delaunay.
    • 4. Triangulations de Delaunay en trois dimensions.
    • 5. Algorithmes de construction des triangulations de Delaunay dans R 3 .
    • 6. Le raffinement de Delaunay dans l'avion.
    • 7. Diagrammes de Voronoï et complexes pondérés.
    • 8. Maillage tétraédrique des automates.
    • 9. Raffinement de Delaunay pondéré pour les automates à petits angles.
    • 10. Exsudation de ruban.
    • 11. Raffinement pour l'exsudation du ruban.
    • 12. Surfaces lisses et échantillons ponctuels.
    • 13. Triangulations de Delaunay restreintes d'échantillons de surface.
    • 14. Maillage des surfaces et des volumes lisses.
    • 15. Maillage des complexes lisses par morceaux.

    Génération de maillage non Delaunay, maillage dynamique et animation par ordinateur physique

      François Labelle et Jonathan Richard Shewchuk, Bourrage isosurface : maillages tétraédriques rapides avec de bons angles dièdres, Transactions ACM sur les graphiques 26(3) : 57.1&ndash57.10, août 2007. Numéro spécial sur les Actes de SIGGRAPH 2007. PDF (couleur, 3 530 ko, 10 pages). Le farce isosurface L'algorithme remplit une isosurface avec un maillage dont les angles dièdres sont compris entre 10,7 o et 164,8 o . Nous en sommes assez fiers, car pratiquement personne n'a été en mesure de prouver des limites d'angle dièdre proches de cela, à l'exception de géométries très simples. Bien que les tétraèdres à l'isosurface doivent être de taille uniforme, les tétraèdres à l'intérieur peuvent être classés. L'algorithme est rapide, numériquement robuste et facile à mettre en œuvre car, comme les Marching Cubes, il génère des tétraèdres à partir d'un petit ensemble de gabarits précalculés. Les bornes des angles sont garanties par une preuve assistée par ordinateur. Si l'isosurface est une 2-variété lisse avec une courbure limitée et que les tétraèdres sont suffisamment petits, alors la limite du maillage est garantie d'être une approximation géométriquement et topologiquement précise de l'isosurface. Malheureusement, l'algorithme arrondit les angles et les arêtes vives. (Je pense qu'il sera extrêmement difficile pour quiconque de concevoir un algorithme qui obtient de manière prouvée des limites d'angle dièdre de cet ordre et épouse parfaitement les plis.)

    Calcul géométrique en continu

      Martin Isenburg, Yuanxin Liu, Jonathan Shewchuk et Jack Snoeyink, Calcul en continu des triangulations de Delaunay, Transactions ACM sur les graphiques 25(3):1049&ndash1056, juillet 2006. Numéro spécial sur les Actes de SIGGRAPH 2006. PDF (couleur, 9 175 Ko, 8 pages). Nous calculons une représentation de terrain d'un milliard de triangles pour le système de la Neuse River à partir de 11,2 Go de données LIDAR en 48 minutes en utilisant seulement 70 Mo de mémoire sur un ordinateur portable avec deux disques durs. C'est un facteur douze fois plus rapide que le précédent logiciel de triangulation Delaunay out-of-core le plus rapide. Nous construisons également une triangulation de neuf milliards de dollars, 152 Go en moins de sept heures en utilisant 166 Mo de mémoire principale. La principale nouveauté de nos triangulateurs de streaming Delaunay est finalisation spatiale. Nous partitionnons l'espace en régions et incluons balises de finalisation dans le flux qui indiquent quand plus aucun point du flux ne tombera dans les régions spécifiées. Nos triangulaires certifient les triangles ou tétraèdres comme Delaunay lorsque les balises de finalisation montrent qu'il est sûr de le faire. Cela permet de les écrire plus tôt, libérant ainsi de la mémoire pour lire davantage à partir du flux d'entrée. Étant donné que seules les parties non finalisées d'une triangulation résident en mémoire, l'empreinte mémoire reste faible.

    Qualité des éléments finis

      Qu'est-ce qu'un bon élément fini linéaire ? Interpolation, conditionnement, anisotropie et mesures de qualité, prépublication non publiée, 2002. COMMENTAIRES REQUIS ! Aidez-moi à améliorer ce manuscrit. Si vous lisez ceci, veuillez envoyer vos commentaires. PostScript (5 336 Ko, 66 pages), PDF (1 190 Ko, 66 pages). Pourquoi les éléments avec des angles minuscules sont-ils inoffensifs pour l'interpolation, mais mortels pour le conditionnement de la matrice de rigidité ? Pourquoi les éléments longs et minces avec des angles proches de 180 o sont-ils terribles dans les cas isotropes mais parfaitement acceptables, s'ils sont correctement alignés, pour les EDP anisotropes dont les solutions ont une courbure anisotrope ? Pourquoi des éléments trop longs et fins offrent-ils parfois des solutions PDE d'une précision inattendue ? Pourquoi l'erreur d'interpolation, l'erreur de discrétisation et le conditionnement matriciel de rigidité peuvent-ils parfois avoir un désaccord à trois sur le rapport hauteur/largeur et l'alignement de l'élément idéal ? Pourquoi les mesures de la qualité des éléments invariants à l'échelle conduisent-elles souvent à des conclusions incorrectes sur la manière d'améliorer un maillage d'éléments finis ? Pourquoi le rapport inradius/circumradius est-il une mesure de qualité si inefficace pour le lissage de maillage basé sur l'optimisation ? Tout est révélé ici.

    Triangulations de Delaunay contraintes

    Avant mon travail ci-dessous, le CDT n'avait pas été généralisé à des dimensions supérieures, et il ne peut jamais être entièrement généralisé car tous les polyèdres n'ont pas une tétraédralisation contrainte (ne permettant aucun sommet supplémentaire). Ici, cependant, je prouve qu'il existe une condition facile à tester qui garantit qu'un polyèdre (ou domaine linéaire par morceaux) en trois dimensions ou plus a une triangulation de Delaunay contrainte. (Un domaine qui satisfait la condition est dit bord protégé en trois dimensions, ou protégé contre les crêtes en dimensions générales.)

    Supposons que vous vouliez tétraédraliser un domaine tridimensionnel. Le résultat implique que si vous insérez suffisamment de sommets supplémentaires sur la limite d'un polygone pour récupérer ses bords dans une tétraédralisation de Delaunay (en d'autres termes, si vous le faites protéger par les bords), vous pouvez récupérer l'intérieur du polygone gratuitement&mdash, c'est-à-dire que vous peut forcer les faces triangulaires de la tétraédralisation à se conformer au polygone sans insérer encore plus de sommets. Cette méthode de récupération de polygones est immédiatement utile pour la génération de maillage ou l'interpolation de fonctions discontinues. (Le résultat comble également un vide théorique dans ma thèse en montrant qu'il est sûr de supprimer un sommet d'une tétraédralisation de Delaunay contrainte dans les circonstances où mon algorithme de &ldquodiametral lens&rdquo le fait.)

      Jonathan Richard Shewchuk et Brielin C. Brown, Insertion rapide de segments et construction incrémentale de triangulations de Delaunay contraintes, Géométrie computationnelle : théorie et applications 48(8):554&ndash574, septembre 2015. PostScript (536k, 29 pages), PDF (310k, 29 pages). Version conférence : Actes du vingt-neuvième symposium annuel sur la géométrie computationnelle (Rio de Janeiro, Brésil), pages 299&ndash308, Association for Computing Machinery, juin 2013. PostScript (320k, 10 pages), PDF (213k, 10 pages). La manière la plus courante de construire une triangulation de Delaunay contrainte (CDT) dans le plan est de construire d'abord la triangulation de Delaunay des sommets d'entrée, puis d'insérer progressivement les segments d'entrée un par un. Nous donnons un algorithme aléatoire pour insérer un segment dans un CDT en temps attendu linéaire en nombre d'arêtes traversées par le segment. Nous l'avons implémenté et nous montrons qu'il est plus rapide que l'emballage cadeau pour les segments qui traversent de nombreux bords. Nous montrons également qu'un algorithme simple pour emplacement des segments, qui précède l'insertion du segment, est suffisamment rapide pour ne jamais être un goulot d'étranglement dans la construction CDT. Un résultat d'Agarwal, Arge et Yi implique que la construction incrémentielle aléatoire des CDT par notre algorithme d'insertion de segment prend O(m Journal m + m journal 2 k) temps. Nous montrons que cette borne est serrée en dérivant une borne inférieure correspondante. Bien qu'il existe des algorithmes de construction CDT garantis pour s'exécuter en O(m Journal m) temps, la construction incrémentale de CDT est plus facile à programmer et compétitive dans la pratique. Notez que l'article du symposium n'étudie que les CDT bidimensionnels, alors que l'article de revue étend en partie l'analyse (mais pas l'algorithme d'insertion en temps linéaire) à trois dimensions.

    En commençant par une triangulation de Delaunay (ou régulière) et en insérant de manière incrémentielle les polygones un par un, vous pouvez construire la triangulation de Delaunay (ou régulière contrainte) contrainte d'une entrée protégée par une crête en O(mv + 1 journal mv) le temps, où mv est le nombre de sommets en entrée et est la dimensionnalité.Dans les dimensions impaires (y compris les trois dimensions, ce qui m'importe le plus), c'est dans un facteur de log mv du pire des cas optimal. L'algorithme est susceptible de ne prendre que O(mv Journal mv) temps dans de nombreux cas pratiques. Destiné à la fois aux programmeurs et aux géomètres computationnels. Discute le cas général-dimensionnel, mais le plus utile en trois dimensions.

    Reconstruction de surface

      Ravikrishna Kolluri, Jonathan Richard Shewchuk et James F. O'Brien, Reconstruction spectrale de la surface à partir de nuages ​​de points bruyants, Symposium on Geometry Processing 2004 (Nice, France), pages 11&ndash21, Eurographics Association, juillet 2004. PDF (couleur, 7 648 ko, 11 pages). Les chercheurs ont proposé plusieurs algorithmes à base de Delaunay prouvés bons pour la reconstruction de surface à partir d'ensembles de points non organisés. Cependant, en présence de sous-échantillonnage, de bruit et de valeurs aberrantes, ils ne sont ni "probablement bons" ni robustes dans la pratique. Notre croûte propre L'algorithme utilise un partitionneur de graphe spectral pour prendre des décisions robustes sur les tétraèdres de Delaunay qui sont à l'intérieur de la surface et ceux qui sont à l'extérieur. En pratique, l'algorithme Eigencrust gère assez bien le sous-échantillonnage, le bruit et les valeurs aberrantes, tout en donnant essentiellement les mêmes résultats que les algorithmes Tight Cocone ou Powercrust, qui ont fait leurs preuves, sur les ensembles de points &ldquoclean&rdquo. (Il n'y a aucune théorie dans cet article, cependant.)

    Robustesse géométrique

    Pour réaliser rapidement des tests géométriques robustes, je propose deux nouvelles techniques (qui peuvent également être appliquées à d'autres problèmes de précision numérique). Tout d'abord, je développe et prouve l'exactitude d'algorithmes de niveau logiciel pour l'arithmétique à virgule flottante à précision arbitraire. Ces algorithmes sont des raffinements (notamment en ce qui concerne la vitesse) des algorithmes suggérés par Douglas Priest, et sont environ cinq fois plus rapides que la meilleure méthode concurrente disponible lorsque des valeurs de précision petite ou intermédiaire (centaines ou milliers de bits) sont utilisées. Deuxièmement, je montre comment des expressions simples (dont les seules opérations sont l'addition, la soustraction et la multiplication) peuvent être calculées de manière adaptative, en échangeant la précision et la vitesse nécessaires pour satisfaire une erreur liée aussi rapidement que possible. (Cette technique est probablement applicable à n'importe quel schéma arithmétique exact.) J'applique ces idées pour construire rapidement et correctement orientation et encercler tests en deux et trois dimensions, et de rendre robustes les implémentations de la triangulation de Delaunay en deux et trois dimensions en Triangle et Pyramide. Des mesures détaillées montrent que dans la plupart des circonstances, ces programmes s'exécutent presque aussi rapidement avec mes prédicats adaptatifs qu'avec des prédicats non robustes.

      Arithmétique à virgule flottante de précision adaptative et prédicats géométriques rapides et robustes, Discret & Géométrie computationnelle 18(3):305&ndash363, octobre 1997. PostScript (775k, 55 pages), PDF (556k, 55 pages). Apparaît également au chapitre 6 de ma thèse.


    Voir la vidéo: NATURAL JOIN in SQL (Octobre 2021).