Added proper volume calc and size slider

This commit is contained in:
Haldrup-tech 2024-09-26 21:23:03 -04:00
parent b64e2c1afc
commit 1fc270deb4
7 changed files with 136 additions and 17 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

30
main.py
View File

@ -3,19 +3,23 @@ import numpy as np
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
from particle import Particle from particle import Particle
from sensor import Sensor from sensor import Sensor
from slider import Slider
pygame.init() pygame.init()
SCREEN_WIDTH = 800 SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600 SCREEN_HEIGHT = 600
SENSOR_DISTANCE = 200
y_lim = 40000
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
sensor = Sensor(width = 50, distance = 200, space = 200) sensor = Sensor(width = 50, distance = SENSOR_DISTANCE, space = 300)
silica = Particle(speed = 1, size = 20, perm = 4) silica = Particle(speed = 1, size = 60, perm = 4)
time = .1 time = .1
time_data = [] time_data = []
@ -26,13 +30,13 @@ volume_data = []
plt.ion() plt.ion()
fig, ax = plt.subplots() fig, ax = plt.subplots()
line, = ax.plot([], [], 'r-') line, = ax.plot([], [], 'r-')
ax.set_xlim(0, 400) ax.set_xlim(0, 800)
ax.set_ylim(0, 40000) ax.set_ylim(-1000, y_lim)
ax.set_xlabel('Time (s)') ax.set_xlabel('Time (s)')
ax.set_ylabel('Volume') ax.set_ylabel('Volume')
ax.set_title('Volume/time') ax.set_title('Volume/time')
slider1 = Slider(20, 20, 100, 20, 20, SENSOR_DISTANCE / 2, 80)
run = True run = True
while run: while run:
@ -49,12 +53,22 @@ while run:
sensor.generate(SCREEN_WIDTH, SCREEN_HEIGHT, screen) sensor.generate(SCREEN_WIDTH, SCREEN_HEIGHT, screen)
pygame.draw.circle(screen, (255, 255, 255), (distance - silica.size, 300), silica.size) pygame.draw.circle(screen, (255, 255, 255), (distance - silica.size, 300), silica.size)
pygame.draw.circle(screen, (0,255,0), (distance - silica.size, 300), 10)
slider1.draw(screen)
silica.updateSize(slider1.value)
for event in pygame.event.get(): for event in pygame.event.get():
if event.type == pygame.QUIT: if event.type == pygame.QUIT:
run = False run = False
slider1.handle_event(event)
volume = sensor.testSensor1(distance, silica) volume = sensor.getParticleVolume(distance, silica)
if (volume > y_lim):
y_lim = volume + (volume * 1.2)
ax.set_ylim(-1000, y_lim)
time_data.append(time) time_data.append(time)
volume_data.append(volume) volume_data.append(volume)
@ -69,10 +83,6 @@ while run:
pygame.display.update() pygame.display.update()
time = time + 1 time = time + 1
print(volume)
pygame.quit() pygame.quit()

View File

@ -15,4 +15,8 @@ class Particle:
partialVol = (1/3) * math.pi * height * height * ((3 * self.size) - height) partialVol = (1/3) * math.pi * height * height * ((3 * self.size) - height)
return partialVol return partialVol
def updateSize(self, size):
self.size = size
self.volume = (4/3) * math.pi * size * size * size

View File

@ -7,7 +7,7 @@ class Sensor:
self.space = space self.space = space
def generate(self, screenWidth, screenHeight, screen): def generate(self, screenWidth, screenHeight, screen):
self.sensor1_x = (screenWidth / 2) - (self.space / 2) self.sensor1_x = (screenWidth / 2) - (self.space / 2) - self.width
self.sensor1_y = 0 self.sensor1_y = 0
self.sensor1_x_size = self.width self.sensor1_x_size = self.width
self.sensor1_y_size = (screenHeight / 2) - (self.distance / 2) self.sensor1_y_size = (screenHeight / 2) - (self.distance / 2)
@ -20,15 +20,85 @@ class Sensor:
pygame.draw.rect(screen, (0, 0, 255), sensor1a) pygame.draw.rect(screen, (0, 0, 255), sensor1a)
pygame.draw.rect(screen, (0, 0, 255), sensor1b) pygame.draw.rect(screen, (0, 0, 255), sensor1b)
self.sensor2_x = (screenWidth / 2) + (self.space / 2)
self.sensor2_y = 0
self.sensor2_x_size = self.width
self.sensor2_y_size = (screenHeight / 2) - (self.distance / 2)
self.inner2 = self.sensor2_x
self.outer2 = self.inner2 + self.width
sensor2a = pygame.Rect(self.sensor2_x, self.sensor2_y, self.sensor2_x_size, self.sensor2_y_size)
sensor2b = pygame.Rect(self.sensor2_x, self.sensor2_y + self.sensor2_y_size + self.distance, self.sensor2_x_size, self.sensor2_y_size)
pygame.draw.rect(screen, (0, 0, 255), sensor2a)
pygame.draw.rect(screen, (0, 0, 255), sensor2b)
def testSensor1(self, partCenter, particle): def testSensor1(self, partCenter, particle):
if particle.size >= abs(self.inner1 - (partCenter - particle.size)):
volume = particle.partialVol(particle.size - (self.inner1 - (partCenter - particle.size))) particle_x = partCenter - particle.size
particle_right = particle_x + particle.size
particle_left = particle_x - particle.size
# Sensor lines on one half of sphere center
if particle_right > self.outer1 and particle_x < self.inner1:
volume = particle.partialVol(self.width + (particle_right - self.outer1)) - particle.partialVol(particle_right - self.outer1)
print("On right half")
print(volume)
return volume return volume
elif particle.size >= abs(self.outer1 - (partCenter - particle.size)): # if Sensor is on left half of sphere center
volume = particle.volume - particle.partialVol(particle.size - (self.outer1 - (partCenter - particle.size))) elif particle_left < self.inner1 and particle_x > self.outer1:
volume = particle.partialVol(self.width + (self.inner1 - particle_left)) - particle.partialVol(self.inner1 - particle_left)
print("On left half")
print(volume)
return volume return volume
elif ((partCenter - particle.size) >= self.inner1 and (partCenter - particle.size) <= self.outer1): # On bolth halves
elif (particle_x >= self.inner1 and particle_x <= self.outer1) and particle_left < self.inner1 and particle_right > self.outer1:
volume_left = particle.partialVol(self.inner1 - particle_left)
volume_right = particle.partialVol(particle_right - self.outer1)
volume = particle.volume - (volume_left + volume_right)
print("On both halves")
print(volume_left)
print(volume_right)
return volume
elif (particle_right > self.inner1 and particle_right < self.outer1) and particle_x <= self.inner1:
volume = particle.partialVol(particle_right - self.inner1)
print("Approaching from left")
print(volume)
return volume
elif (particle_left > self.inner1 and particle_left < self.outer1) and particle_x >= self.outer1:
volume = particle.partialVol(self.outer1 - particle_left)
print("Leaving from left")
print(volume)
return volume
elif (particle_right > self.inner1 and particle_right <= self.outer1) and (particle_left >= self.inner1 and particle_left < self.outer1):
print("in between")
print(particle.volume)
return particle.volume
else:
return 0
def testSensor2(self, partCenter, particle):
if (particle.size >= abs(self.inner2 - (partCenter - particle.size))) and (particle.size >= abs(self.outer2 - (partCenter - particle.size))):
volume = ((particle.volume / 2) - (particle.partialVol(particle.size - ((partCenter - particle.size) - self.inner2)))) + ((particle.volume / 2) - particle.partialVol(particle.size - (self.outer2 - (partCenter - particle.size))))
return volume
elif particle.size >= abs(self.inner2 - (partCenter - particle.size)):
volume = particle.partialVol(particle.size - (self.inner2 - (partCenter - particle.size)))
return volume
elif particle.size >= abs(self.outer2 - (partCenter - particle.size)):
volume = particle.volume - particle.partialVol(particle.size - (self.outer2 - (partCenter - particle.size)))
return volume
elif ((partCenter - particle.size) >= self.inner2 and (partCenter - particle.size) <= self.outer2):
volume = particle.volume volume = particle.volume
return volume return volume
else: else:
return 0 return 0
def getParticleVolume(self, partCenter, particle):
volume1 = self.testSensor1(partCenter, particle)
volume2 = self.testSensor2(partCenter, particle)
if volume1:
return volume1
elif volume2:
return volume2
else:
return 0

35
slider.py Normal file
View File

@ -0,0 +1,35 @@
import pygame
WHITE = (255, 255, 255)
GRAY = (200, 200, 200)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
class Slider:
def __init__(self, x, y, w, h, min_val, max_val, initial_val):
self.rect = pygame.Rect(x, y, w, h)
self.min_val = min_val
self.max_val = max_val
self.value = initial_val
self.grabbed = False
def draw(self, screen):
# Draw the background
pygame.draw.rect(screen, GRAY, self.rect)
# Draw the handle (circle)
handle_x = self.rect.x + (self.value - self.min_val) / (self.max_val - self.min_val) * self.rect.width
pygame.draw.circle(screen, RED, (int(handle_x), self.rect.centery), self.rect.height // 2)
def handle_event(self, event):
if event.type == pygame.MOUSEBUTTONDOWN:
if self.rect.collidepoint(event.pos):
self.grabbed = True
elif event.type == pygame.MOUSEBUTTONUP:
self.grabbed = False
elif event.type == pygame.MOUSEMOTION:
if self.grabbed:
mouse_x = event.pos[0]
# Constrain the handle within the slider
new_value = (mouse_x - self.rect.x) / self.rect.width * (self.max_val - self.min_val) + self.min_val
self.value = max(self.min_val, min(self.max_val, new_value))