"""Primitiva GL_POINTS — um círculo de pontos isolados. Aula 02 — Visualização 2D: primitivas gráficas. Exemplo em Python com PySide6 e PyOpenGL (pipeline fixed-function). Execute com: python pontos2d.py Novidades em relação ao ``helloworld2d.py`` (Aula 01): * a **projeção** é definida em ``resizeGL`` (e não em ``paintGL``), pois depende da proporção da janela; * o sistema de coordenadas do mundo vai de -50 a 50, corrigido pelo *aspect ratio* para que o círculo não fique elíptico; * ``glPointSize`` controla o tamanho do ponto rasterizado. Ideias para experimentar: mude o passo do laço (``PASSO``), o raio, o ``glPointSize``, ou habilite ``GL_POINT_SMOOTH`` para pontos arredondados. """ from __future__ import annotations import math import sys from PySide6.QtCore import Qt from PySide6.QtGui import QSurfaceFormat from PySide6.QtWidgets import QApplication from PySide6.QtOpenGLWidgets import QOpenGLWidget from OpenGL.GL import * from OpenGL.GLU import gluOrtho2D RAIO = 20.0 # raio do círculo, em unidades do mundo PASSO = math.pi / 7.0 # incremento angular -> 14 pontos na volta completa class Pontos2D(QOpenGLWidget): """Desenha um círculo de pontos com GL_POINTS.""" def initializeGL(self) -> None: glClearColor(0.10, 0.11, 0.13, 1.0) def resizeGL(self, w: int, h: int) -> None: w, h = max(1, w), max(1, h) # 1) Onde desenhar, em pixels. glViewport(0, 0, w, h) # 2) Que retângulo do mundo é visível. A correção pelo aspect ratio # estende o eixo mais longo, preservando a proporção das formas. glMatrixMode(GL_PROJECTION) glLoadIdentity() if w <= h: gluOrtho2D(-50.0, 50.0, -50.0 * h / w, 50.0 * h / w) else: gluOrtho2D(-50.0 * w / h, 50.0 * w / h, -50.0, 50.0) glMatrixMode(GL_MODELVIEW) glLoadIdentity() def paintGL(self) -> None: glClear(GL_COLOR_BUFFER_BIT) glColor3f(0.92, 0.92, 0.95) glPointSize(5.0) # lado do quadrado do ponto, em pixels # Cada vértice entre glBegin/glEnd vira um ponto independente. glBegin(GL_POINTS) ang = 0.0 while ang < 2 * math.pi: glVertex2f(RAIO * math.cos(ang), RAIO * math.sin(ang)) ang += PASSO glEnd() def keyPressEvent(self, event) -> None: if event.key() == Qt.Key.Key_Escape: self.close() def main() -> int: fmt = QSurfaceFormat() fmt.setVersion(2, 1) # OpenGL 2.1 (fixed-function) # NoProfile é o perfil de compatibilidade, que mantém o fixed-function. fmt.setProfile(QSurfaceFormat.OpenGLContextProfile.NoProfile) fmt.setDepthBufferSize(0) # cena 2D: sem profundidade QSurfaceFormat.setDefaultFormat(fmt) app = QApplication(sys.argv) window = Pontos2D() window.setWindowTitle("Primitivas 2D — GL_POINTS") window.resize(600, 400) window.show() return app.exec() if __name__ == "__main__": raise SystemExit(main())