# -*- coding: utf-8 -*- from PyQt5.QtWidgets import (QWidget, QSlider, QApplication, QHBoxLayout, QVBoxLayout, QLabel, QLineEdit, QDesktopWidget, QPushButton, QComboBox) from PyQt5.QtCore import QObject, Qt from PyQt5.QtGui import QPainter, QFont, QColor, QPen, QImage, QPixmap from perlin import PerlinNoise,FractalNoise import matplotlib.pyplot as pp import numpy as np from math import floor,ceil from time import sleep import threading import sys #application = QApplication([]) class MapNavigator(QWidget): carte = QLabel() def __init__(self): super().__init__() self.setWindowTitle("Navigateur") ### Centrer la fenetre ### self.resize(750,505) self.initFrame() self.show() self.centrer() def centrer(self): qtRectangle = self.frameGeometry() centerPoint = QDesktopWidget().availableGeometry().center() qtRectangle.moveCenter(centerPoint) self.move(qtRectangle.topLeft()) def initFrame(self): ##### Config ##### globalayout = QHBoxLayout() configl = QVBoxLayout() configl.setAlignment(Qt.AlignTop) ## Fichier ## fichier = QHBoxLayout() fichierlabel = QLabel("Fichier :") fichiertext = QLineEdit() fichier.addWidget(fichierlabel) fichier.addWidget(fichiertext) ## Refresh ## refresh = QPushButton("Refresh") ## Coords ## Xs = QHBoxLayout() posxlabel = QLabel("x:") posxtext = QLineEdit() lxlabel = QLabel("lx:") lxtext = QLineEdit() Xs.addWidget(posxlabel) Xs.addWidget(posxtext) Xs.addWidget(lxlabel) Xs.addWidget(lxtext) Ys = QHBoxLayout() posylabel = QLabel("y:") posytext = QLineEdit() lylabel = QLabel("ly:") lytext = QLineEdit() Ys.addWidget(posylabel) Ys.addWidget(posytext) Ys.addWidget(lylabel) Ys.addWidget(lytext) ## Redraw ## redraw = QPushButton("Redraw") ## Colormap ## colormap = QHBoxLayout() colormaplabel = QLabel("Color map :") colormapchooser = QComboBox()#["Noir","Blanc","Rouge","Vert","Bleu"]) colormap.addWidget(colormaplabel) colormap.addWidget(colormapchooser) configl.addLayout(fichier) configl.addWidget(refresh) configl.addLayout(Xs) configl.addLayout(Ys) configl.addWidget(redraw) configl.addLayout(colormap) globalayout.addLayout(configl) globalayout.addWidget(self.carte) self.setLayout(globalayout) lastx,lasty = None,None def mouseMoveEvent(self,e): dx,dy = e.x() - self.lastx,e.y() - self.lasty print(dx/self.rx,dy/self.ry) self.lastx,self.lasty = e.x(),e.y() self.x += -dy/self.rx self.y += -dx/self.ry self.updateImage()# TODO separer le updateImage dans un autre thread pour éviter de l'appeler 1000 fois. Plutot set un tag indiquant qu'il faudrait l'appeler. def mousePressEvent(self,e): self.lastx,self.lasty = e.x(),e.y() def mouseReleaseEvent(self,e): self.lastx,self.lasty = None,None def closeEvent(self,e): self.generator.running = False x,y = 0,0 rx,ry = 256,256 w,h = 512,512 def getChunk(self,x,y,rx,ry): if (x,y) not in self.generator.generated: self.generator.genqueue.append((x,y)) return np.zeros((rx,ry)) return self.generator.generated[(x,y)] def updateImage(self): x,y = self.x,self.y rx,ry = self.rx,self.ry w,h = self.w,self.h lx,ly = w/rx,h/ry out = np.zeros((self.w,self.h)) x0 = x-lx/2 x1 = x+lx/2 y0 = y-ly/2 y1 = y+ly/2 cx0,cy0 = int((x0-floor(x0))*rx),int((y0-floor(y0))*ry) cx1,cy1 = int((x1-floor(x1))*rx),int((y1-floor(y1))*ry) zx,zy = int((1+floor(x0)-x0)*rx),int((1+floor(y0)-y0)*ry) print(x0,x1,y0,y1,cx0,cy0,w,h,lx,ly) for i in range(floor(x0),floor(x1)+1): for j in range(floor(y0),floor(y1)+1): chk = self.getChunk(i,j,rx,ry) cx,dx = cx0 if i==floor(x0) else 0 , cx1 if i==floor(x1) else rx cy,dy = cy0 if j==floor(y0) else 0 , cy1 if j==floor(y1) else ry ax,ay = 0 if i==floor(x0) else zx+(i-floor(x0)-1)*rx , 0 if j==floor(y0) else zy+(j-floor(y0)-1)*ry bx,by = ax + (dx-cx) , ay + (dy-cy) print(i,j,"->",ax,bx,cx,dx,ay,by,cy,dy) out[ax:bx,ay:by] = chk[cx:dx,cy:dy] self.setImage(out) def setImage(self,im): im = np.uint8((im - im.min())/im.ptp()*255.0) qi = QImage(im.data, im.shape[1], im.shape[0], im.shape[1], QImage.Format_Indexed8) qp = QPixmap.fromImage(qi) self.carte.setPixmap(qp) class Generator(threading.Thread): updatefunc = None noise = None res = None generated = {} genqueue = [] running = True def __init__(self,updatefunc,noise,res): super().__init__() self.updatefunc = updatefunc self.noise = noise self.res = res def run(self): while(self.running): if(len(self.genqueue) > 0): x,y = self.genqueue.pop(0) if (x,y) in self.generated: continue chunk = self.noise.getChunk(x,y,self.res) self.generated[(x,y)] = chunk self.updatefunc() else: sleep(0.01) print('Bybye !') nav = MapNavigator() seed=42 perl1 = PerlinNoise(10 ,seed) perl2 = PerlinNoise(5 ,seed) perl3 = PerlinNoise(1 ,seed) noise = perl1+.1*perl2+.03*perl3 generator = Generator(nav.updateImage,noise,(nav.rx,nav.ry)) nav.generator = generator generator.start() nav.updateImage() ###### Content #####