간단한 중력 시뮬레이션을 만들려하는데...

조회수 383회

복수의 물체(원)이 서로 미치는 중력 만을 가지고 시뮬레이션을 만들려 하는데요... 이 분(아래 사이트)의 vector, physics 모듈과 중력 코드를 다듬어서 움직이는 두 물체의 움직임을 구현하는 코드를 만들었습니다. Exception in thread 경고 문이 뜨면서 UI창은 뜨는데 내용이 나오 지가 않습니다 . threading 은 써본 적이 없어서 어떻게 사용해야 할지도 모르겠고, 예외가 발생했는데 뭐가 문젠지도 모르겠네요;; 문제가 어딘지 확인해보니까, thread.start()부분에서 에러가 뜬다는 걸 알아냈는데... 어떻게 해야 할까요?

+만약 위를 해결하고, 물체가 3개일 때 기존의 코드로 해결되지 않는다면... 부탁 드립니다!

"https://oceancoding.blogspot.com/2019/06/blog-post_24.html\"

문제의 코드입니다. (vector과 mover 모듈은 사이트에 있습니다!)

import sys
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtCore import Qt, QRectF
from PyQt5.QtGui import QPainter, QBrush, QColor

from Physics.vector import vector
from Physics.mover import Mover
import threading
from threading import Thread
from random import randint

import time

QApplication.setAttribute(Qt.AA_EnableHighDpiScaling, True)

#물체의 정보(여기서는 움직임)
class Attractor:

    def __init__(self, x, y, vx, vy, mass):
        self.mass = mass
        self.location = vector(x, y)
        self.velocity = vector(vx, vy)
        self.G = 1.0


    def attract(self, mover):
        force = self.location-mover.location
        distance = force.magnitude()

        force.normalize()

        F=(self.G * self.mass)/(distance * distance)

        force *= vector(F,F)
        return force

    def constrain(self, val, min, max):
        if val < min:
            return min
        elif val > max:
            return max
        else:
            return val


class CWidget(QWidget):

    def __init__(self):
        super().__init__()

        self.attractor=[]
        for i in range(2):#물체 갯수 2개
            attractor = Attractor(self.width()*(i+2)/5, self.height()/2, 0, (-1)**i, 50)
            self.attractor.append(attractor)

        self.thread = Thread(target=self.threadFunc)
        self.bThread = False

        self.initUI()


    def initUI(self):#UI창 생성

        self.setWindowTitle('force')        
        self.bThread = True
        self.thread.start()
        print(threading.current_thread())
        self.show()

    def paintEvent(self, e):#attractor 그리기
        qp = QPainter()
        qp.begin(self)
        #attractor의 질량
        d = self.attractor.mass
        r = d/2

        for i in self.attractor:
            rect = QRectF(i.location.x-r, i.location.y-r, d, d)
            qp.setBrush(QColor(255*(1-i), 0, 255*i, 128))
            qp.drawEllipse(rect)
            #qp.drawText(rect, Qt.AlignCenter, 'Mass:{}'.format(i.mass))
        qp.end()


    def threadFunc(self):
        while self.bThread:

            for m in self.attractor:

                v = self.attractor.attract(self.attractor(1-i))
                m.applyForce(v)

                m.velocity += m.acceleration
                #m.velocity.setLimit(1)#
                m.location += m.velocity

                d = m.mass
                r = d/2

                #if m.location.x+r > self.width() and m.location.x-r < 0 and m.location.y+r > self.height() and m.location.y-r < 0:
                #    break
                if m.location.x+r > self.width():
                    m.location.x = self.width()-r
                    m.velocity.x *= -1
                elif m.location.x-r < 0:
                    m.velocity.x *= -1
                    m.location.x = 0+r
                if m.location.y+r > self.height():
                    m.location.y = self.height()-r
                    m.velocity.y *= -1
                elif m.location.y-r < 0:
                    m.velocity.y *= -1
                    m.location.y = 0+r

                # 가속도를 0 설정
                # 뉴턴의 제1법칙(관성)에 따라 속도는 유지
                m.acceleration*=vector(0,0)  

            self.update()

            time.sleep(0.01) 

    def closeEvent(self, e):
        self.bThread = False

if __name__ == '__main__':
app = QApplication(sys.argv)
w = CWidget()
sys.exit(app.exec_())
  • (•́ ✖ •̀)
    알 수 없는 사용자

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)