random lines between rendered objects python - python

I am making a very basic 3d engine. When I render 2 or more objects, it draws lines between them. I do not know why this happens, as I coded the pen to go up after drawing every triangle. A strange thing is that when I draw a background line, each object also draws lines to the background line. I am confused. There is only 1 reason I could think of; it uses the last point of the other object as the first point of the first triangle of the main object. However, it does not seem like this is the case, as it is even happening with a simple line in the background as well.
from turtle import*
from time import*
from math import*
wn=Screen()
speed(0)
ht()
pu()
wn.tracer(0,0)
fov=200
camx=0
camy=0
camz=-5
xoff=0
yoff=0
zoff=0
xrot=pi*2
yrot=pi
zrot=pi
def goto3d(x,y,z):
rotxx=x
rotxy=y*cos(yrot)-z*sin(yrot)
rotxz=y*sin(yrot)+z*cos(yrot)
rotyx=rotxx*cos(xrot)+rotxz*sin(xrot)
rotyy=rotxy
rotyz=rotxz*cos(xrot)-rotxx*sin(xrot)
rotzx=rotyx*cos(zrot)-rotyy*sin(zrot)
rotzy=rotyx*sin(zrot)+rotyy*cos(zrot)
rotzz=rotyz
transx=rotzx-xoff
transy=rotzy-yoff
transz=rotzz-zoff
newx=fov*transx/transz
newy=fov*transy/transz
if transz<0.1 or newx<=-200 or newy<=-200 or newx>=200 or newy>=200:
return
goto(newx,newy)
def triangle(p1x,p1y,p1z,p2x,p2y,p2z,p3x,p3y,p3z):
goto3d(p1x,p1y,p1z)
pd()
goto3d(p2x,p2y,p2z)
goto3d(p3x,p3y,p3z)
goto3d(p1x,p1y,p1z)
pu()
def face(p1x,p1y,p1z,p2x,p2y,p2z,p3x,p3y,p3z,p4x,p4y,p4z,r,g,b,a):
fillcolor(r,g,b,a)
begin_fill()
triangle(p1x,p1y,p1z,p2x,p2y,p2z,p3x,p3y,p3z)
end_fill()
begin_fill()
triangle(p2x,p2y,p2z,p3x,p3y,p3z,p4x,p4y,p4z)
end_fill()
def bbox(x,y,z,w,h,l,r,g,b,a):
x+=camx
y+=camy
z+=camz
face(x+-w,y+h,z+l,x+w,y+h,z+l,x+-w,y+-h,z+l,x+w,y+-h,z+l,r,g,b,a)
face(x+-w,y+h,z+-l,x+w,y+h,z+-l,x+-w,y+-h,z+-l,x+w,y+-h,z+-l,r,g,b,a)
face(x+-w,y+h,z+l,x+-w,y+h,z+-l,x+-w,y+-h,z+l,x+-w,y+-h,z+-l,r,g,b,a)
face(x+w,y+h,z+l,x+w,y+h,z+-l,x+w,y+-h,z+l,x+w,y+-h,z+-l,r,g,b,a)
face(x+-w,y+-h,z+l,x+-w,y+-h,z+-l,x+w,y+-h,z+l,x+w,y+-h,z+-l,r,g,b,a)
face(x+-w,y+h,z+l,x+-w,y+h,z+-l,x+w,y+h,z+l,x+w,y+h,z+-l,r,g,b,a)
def box(x,y,z,w,h,l,r,g,b):
if w>=2 or h>=2 or l>=2:
bbox(x-(w/4),y-(h/4),z-(l/4),w/4,h/4,l/4,r,g,b,.2)
bbox(x+(w/4),y-(h/4),z-(l/4),w/4,h/4,l/4,r,g,b,.2)
bbox(x+(w/4),y+(h/4),z-(l/4),w/4,h/4,l/4,r,g,b,.2)
bbox(x-(w/4),y+(h/4),z-(l/4),w/4,h/4,l/4,r,g,b,.2)
bbox(x-(w/4),y-(h/4),z+(l/4),w/4,h/4,l/4,r,g,b,.2)
bbox(x+(w/4),y-(h/4),z+(l/4),w/4,h/4,l/4,r,g,b,.2)
bbox(x+(w/4),y+(h/4),z+(l/4),w/4,h/4,l/4,r,g,b,.2)
bbox(x-(w/4),y+(h/4),z+(l/4),w/4,h/4,l/4,r,g,b,.2)
else:
bbox(x,y,z,w,h,l,r,g,b,.5)
def render():
goto(-200,-5)
pd()
goto(200,-5)
pu()
### ||| objects go here ||| ###
### ||| format is box(x,y,z,width,height,length,r,g,b) ||| ###
box(2,0,-5,2,2,2,0,255,255)
box(0,0,0,1,1,1,255,0,0)
def tl():
global xrot
xrot-=pi/40
def tr():
global xrot
xrot+=pi/40
def f():
global camx
global camz
camz+=.3*cos(-xrot)
camx+=-(.3*sin(-xrot))
def b():
global camx
global camz
camz+=-(.3*cos(-xrot))
camx+=.3*sin(-xrot)
wn.onkey(tl,'Left')
wn.onkey(tr,'Right')
wn.onkey(f,'Up')
wn.onkey(b,'Down')
wn.listen()
while True:
clear()
render()
update()

When I render 2 or more objects, it draws lines between them. I do not
know why this happens
The problem happens even when you only have one object -- comment out your first (small blue) box and just move the second (large red) one:
The problem is in goto3d() and triangle() as goto3d() has a failure situation (which it tests for) that it doesn't signal back to triangle() so it goes ahead and continues drawing.
Below is my rework of your code to patch this issue (and translate the code into Python ;-)
from turtle import Screen, Turtle
from math import pi, sin, cos
fov = 200
camx = 0
camy = 0
camz = -5
xoff = 0
yoff = 0
zoff = 0
xrot = pi * 2
yrot = pi
zrot = pi
def goto3d(x, y, z):
rotxx = x
rotxy = y * cos(yrot) - z * sin(yrot)
rotxz = y * sin(yrot) + z * cos(yrot)
rotyx = rotxx * cos(xrot) + rotxz * sin(xrot)
rotyy = rotxy
rotyz = rotxz * cos(xrot) - rotxx * sin(xrot)
rotzx = rotyx * cos(zrot) - rotyy * sin(zrot)
rotzy = rotyx * sin(zrot) + rotyy * cos(zrot)
rotzz = rotyz
transx = rotzx - xoff
transy = rotzy - yoff
transz = rotzz - zoff
if transz < 0.1:
return False
newx = fov * transx/transz
newy = fov * transy/transz
if not -200 < newx < 200 or not -200 < newy < 200:
return False
turtle.goto(newx, newy)
return True
def triangle(p1x, p1y, p1z, p2x, p2y, p2z, p3x, p3y, p3z):
if goto3d(p1x, p1y, p1z):
turtle.pendown()
turtle.begin_fill()
goto3d(p2x, p2y, p2z)
goto3d(p3x, p3y, p3z)
goto3d(p1x, p1y, p1z)
turtle.end_fill()
turtle.penup()
def face(p1x, p1y, p1z, p2x, p2y, p2z, p3x, p3y, p3z, p4x, p4y, p4z, color):
turtle.fillcolor(color)
triangle(p1x, p1y, p1z, p2x, p2y, p2z, p3x, p3y, p3z)
triangle(p2x, p2y, p2z, p3x, p3y, p3z, p4x, p4y, p4z)
def bbox(x, y, z, w, h, l, color):
x += camx
y += camy
z += camz
face(x - w, y + h, z + l, x + w, y + h, z + l, x - w, y - h, z + l, x + w, y - h, z + l, color)
face(x - w, y + h, z - l, x + w, y + h, z - l, x - w, y - h, z - l, x + w, y - h, z - l, color)
face(x - w, y + h, z + l, x - w, y + h, z - l, x - w, y - h, z + l, x - w, y - h, z - l, color)
face(x + w, y + h, z + l, x + w, y + h, z - l, x + w, y - h, z + l, x + w, y - h, z - l, color)
face(x - w, y - h, z + l, x - w, y - h, z - l, x + w, y - h, z + l, x + w, y - h, z - l, color)
face(x - w, y + h, z + l, x - w, y + h, z - l, x + w, y + h, z + l, x + w, y + h, z - l, color)
def box(x, y, z, w, h, l, color):
if w >= 2 or h >= 2 or l >= 2:
# transparent_color = (*color, 0.2)
transparent_color = color
bbox(x - w/4, y - h/4, z - l/4, w/4, h/4, l/4, transparent_color)
bbox(x + w/4, y - h/4, z - l/4, w/4, h/4, l/4, transparent_color)
bbox(x + w/4, y + h/4, z - l/4, w/4, h/4, l/4, transparent_color)
bbox(x - w/4, y + h/4, z - l/4, w/4, h/4, l/4, transparent_color)
bbox(x - w/4, y - h/4, z + l/4, w/4, h/4, l/4, transparent_color)
bbox(x + w/4, y - h/4, z + l/4, w/4, h/4, l/4, transparent_color)
bbox(x + w/4, y + h/4, z + l/4, w/4, h/4, l/4, transparent_color)
bbox(x - w/4, y + h/4, z + l/4, w/4, h/4, l/4, transparent_color)
else:
# transparent_color = (*color, 0.5)
transparent_color = color
bbox(x, y, z, w, h, l, transparent_color)
def render():
turtle.clear()
turtle.goto(-200, -5)
turtle.pendown()
turtle.goto(200, -5)
turtle.penup()
### ||| objects go here ||| ###
### ||| format is box(x, y, z, width, height, length, (r, g, b)) ||| ###
box(2, 0, -5, 2, 2, 2, (0, 255, 255))
box(0, 0, 0, 1, 1, 1, (255, 0, 0))
screen.update()
screen.ontimer(render)
def tl():
global xrot
xrot -= pi/40
def tr():
global xrot
xrot += pi/40
def f():
global camx, camz
camz += 0.3 * cos(-xrot)
camx += -(0.3 * sin(-xrot))
def b():
global camx, camz
camz += -(0.3 * cos(-xrot))
camx += 0.3 * sin(-xrot)
screen = Screen()
screen.tracer(0)
screen.colormode(255)
turtle = Turtle()
turtle.hideturtle()
turtle.penup()
screen.onkey(tl, 'Left')
screen.onkey(tr, 'Right')
screen.onkey(f, 'Up')
screen.onkey(b, 'Down')
screen.listen()
render()
screen.mainloop()
I disabled transparency as my system doesn't support it, but you can uncomment the appropriate lines to put it back.

Related

Trajectory plalnification

I have a program that generates circles and lines, where the circles can not collide with each other and the lines can not collide with the circles, the problem is that it only draws a line but not the others, it does not mark any error and as much as I think the reason I do not understand why, (I'm new to python, so excuse me if maybe the error is obvious)
I tried to remove the for from my CreaLin class and it does generate the lines but they all collide with the circles, I also thought that the collisionL function could be the problem since the method does not belong as such to the line class, but I need values from the circle class, so I don't know what would be another way to do it, I would like to know a method.
my code:
class CreaCir:
def __init__(self, figs):
self.figs = figs
def update(self):
if len(self.figs) <70:
choca = False
r = randint(5, 104)
x = randint(0, 600 + r)
y = randint(0, 400 + r)
creOne = Circulo(x, y, r)
for fig in (self.figs):
choca = creOne.colisionC(fig)
if choca == True:
break
if choca == False:
self.figs.append(creOne)
def dibujar(self, ventana):
pass
class CreaLin:
def __init__(self, lins):
self.lins = lins
def update(self):
if len(self.lins) <70:
choca = False
x = randint(0, 700)
y = randint(0, 500)
a = randint(0, 700)
b = randint(0, 500)
linOne = Linea(x, y, a, b)
for lin in (self.lins):
choca = linOne.colisionL(lin)
if choca == True:
break
if choca == False:
self.lins.append(linOne)
def dibujar(self, ventana):
pass
class Ventana:
def __init__(self, Ven_Tam= (700, 500)):
pg.init()
self.ven_tam = Ven_Tam
self.ven = pg.display.set_caption("Linea")
self.ven = pg.display.set_mode(self.ven_tam)
self.ven.fill(pg.Color('#404040'))
self.figs = []
self.lins = []
self.reloj = pg.time.Clock()
def check_events(self):
for event in pg.event.get():
if event.type == pg.QUIT or (event.type == pg.KEYDOWN and event.key == pg.K_ESCAPE):
quit()
pg.display.flip()
def run(self):
cirCreater = CreaCir(self.figs)
linCreater = CreaLin(self.lins)
while True:
self.check_events()
cirCreater.update()
linCreater.update()
for fig in self.figs:
fig.dibujar(self.ven)
for lin in self.lins:
lin.dibujar(self.ven)
self.reloj.tick(60)
if __name__ == '__main__':
ven = Ventana()
ven.run()
class Circulo:
class Circulo(PosGeo):
def __init__(self, x, y, r):
self.x = x
self.y = y
self.radio = r
self.cx = x+r
self.cy = y+r
def __str__(self):
return f"Circulo, (X: {self.x}, Y: {self.y}), radio: {self.radio}"
def dibujar(self, ventana):
pg.draw.circle(ventana, "white", (self.cx, self.cy), self.radio, 1)
pg.draw.line(ventana, "white", (self.cx+2, self.cy+2),(self.cx-2, self.cy-2))
pg.draw.line(ventana, "white", (self.cx-2, self.cy+2),(self.cx+2, self.cy-2))
def update(self):
pass
def colisionC(self, c2):
return self.radio + c2.radio > sqrt(pow(self.cx - c2.cx, 2) + pow(self.cy - c2.cy, 2))
def colisionL(self, L2):
l0 = [L2.x, L2.y]
l1 = [L2.a, L2.b]
cp = [self.cx, self.cy]
x1 = l0[0] - cp[0]
y1 = l0[1] - cp[1]
x2 = l1[0] - cp[0]
y2 = l1[1] - cp[1]
dx = x2 - x1
dy = y2 - y1
dr = sqrt(dx*dx + dy*dy)
D = x1 * y2 - x2 * y1
discriminant = self.radio*self.radio*dr*dr - D*D
if discriminant < 0:
return False
else:
return True`
and finally my class line:
class Linea(PosGeo):
def __init__(self, x, y, a, b):
super().__init__(x, y)
self.x = x
self.y = y
self.a = a
self.b = b
def dibujar(self, ventana):
pg.draw.line(ventana, "#7B0000", (self.x, self.y), (self.a, self.b))
def update(self):
pass
def colisionL(self, l1):
pass
Result:
You need to implement the colisionC and colisionL methods in Linea and Circulo. See Problem with calculating line intersections for the line-line intersection algorithm. When checking for collisions between lines and circles, in addition to checking for collisions between circles and endless lines, you must also consider the beginning and end of the line segment:
class Linea:
# [...]
def colisionC(self, c2):
return c2.colisionL(self)
def colisionL(self, l1):
return Linea.intersect_line_line((self.x, self.y), (self.a, self.b), (l1.x, l1.y), (l1.a, l1.b))
def intersect_line_line(P0, P1, Q0, Q1):
d = (P1[0]-P0[0]) * (Q1[1]-Q0[1]) + (P1[1]-P0[1]) * (Q0[0]-Q1[0])
if d == 0:
return None
t = ((Q0[0]-P0[0]) * (Q1[1]-Q0[1]) + (Q0[1]-P0[1]) * (Q0[0]-Q1[0])) / d
u = ((Q0[0]-P0[0]) * (P1[1]-P0[1]) + (Q0[1]-P0[1]) * (P0[0]-P1[0])) / d
if 0 <= t <= 1 and 0 <= u <= 1:
return P1[0] * t + P0[0] * (1-t), P1[1] * t + P0[1] * (1-t)
return None
class Circulo
# [...]
def colisionC(self, c2):
return self.radio + c2.radio > sqrt(pow(self.cx - c2.cx, 2) + pow(self.cy - c2.cy, 2))
def colisionL(self, L2):
l0 = [L2.x, L2.y]
l1 = [L2.a, L2.b]
cp = [self.cx, self.cy]
x1 = l0[0] - cp[0]
y1 = l0[1] - cp[1]
x2 = l1[0] - cp[0]
y2 = l1[1] - cp[1]
if sqrt(x1*x1+y1*y1) < self.radio or sqrt(x2*x2+y2*y2) < self.radio:
return True
dx = x2 - x1
dy = y2 - y1
dr = sqrt(dx*dx + dy*dy)
D = x1 * y2 - x2 * y1
discriminant = self.radio*self.radio*dr*dr - D*D
if discriminant < 0:
return False
sign = lambda x: -1 if x < 0 else 1
xa = (D * dy + sign(dy) * dx * sqrt(discriminant)) / (dr * dr)
xb = (D * dy - sign(dy) * dx * sqrt(discriminant)) / (dr * dr)
ya = (-D * dx + abs(dy) * sqrt(discriminant)) / (dr * dr)
yb = (-D * dx - abs(dy) * sqrt(discriminant)) / (dr * dr)
ta = (xa-x1)*dx/dr + (ya-y1)*dy/dr
tb = (xb-x1)*dx/dr + (yb-y1)*dy/dr
return 0 < ta < dr or 0 < tb < dr
Put all objects into one container. Before you add a new Linea you have to check if the new "Line" intersects another object with "ColisionL". Before you add a new Circulo, you must check if the new "Line" intersects another object with CollisionC:
class CreaObjects:
def __init__(self, figs):
self.figs = figs
self.no_lines = 0
self.no_circles = 0
def update(self):
if self.no_circles <70:
r = randint(5, 104)
creOne = Circulo(randint(0, 600 - 2*r), randint(0, 400 - 2*r), r)
if not any(fig.colisionC(creOne) for fig in self.figs):
self.figs.append(creOne)
self.no_circles += 1
if self.no_lines <70:
linOne = Linea(randint(0, 700), randint(0, 500), randint(0, 700), randint(0, 500))
if not any(fig.colisionL(linOne) for fig in self.figs):
self.figs.append(linOne)
self.no_lines += 1
Complete example:
import pygame as pg
from random import randint
from math import sqrt, hypot
class Linea:
def __init__(self, x, y, a, b):
self.x = x
self.y = y
self.a = a
self.b = b
def dibujar(self, ventana):
pg.draw.line(ventana, "#7B0000", (self.x, self.y), (self.a, self.b))
def update(self):
pass
def colisionC(self, c2):
return c2.colisionL(self)
def colisionL(self, l1):
return Linea.intersect_line_line((self.x, self.y), (self.a, self.b), (l1.x, l1.y), (l1.a, l1.b))
def intersect_line_line(P0, P1, Q0, Q1):
d = (P1[0]-P0[0]) * (Q1[1]-Q0[1]) + (P1[1]-P0[1]) * (Q0[0]-Q1[0])
if d == 0:
return None
t = ((Q0[0]-P0[0]) * (Q1[1]-Q0[1]) + (Q0[1]-P0[1]) * (Q0[0]-Q1[0])) / d
u = ((Q0[0]-P0[0]) * (P1[1]-P0[1]) + (Q0[1]-P0[1]) * (P0[0]-P1[0])) / d
if 0 <= t <= 1 and 0 <= u <= 1:
return P1[0] * t + P0[0] * (1-t), P1[1] * t + P0[1] * (1-t)
return None
class Circulo:
def __init__(self, x, y, r):
self.x = x
self.y = y
self.radio = r
self.cx = x+r
self.cy = y+r
def __str__(self):
return f"Circulo, (X: {self.x}, Y: {self.y}), radio: {self.radio}"
def dibujar(self, ventana):
pg.draw.circle(ventana, "white", (self.cx, self.cy), self.radio, 1)
pg.draw.line(ventana, "white", (self.cx+2, self.cy+2),(self.cx-2, self.cy-2))
pg.draw.line(ventana, "white", (self.cx-2, self.cy+2),(self.cx+2, self.cy-2))
def update(self):
pass
def colisionC(self, c2):
return self.radio + c2.radio > sqrt(pow(self.cx - c2.cx, 2) + pow(self.cy - c2.cy, 2))
def colisionL(self, L2):
l0 = [L2.x, L2.y]
l1 = [L2.a, L2.b]
cp = [self.cx, self.cy]
x1 = l0[0] - cp[0]
y1 = l0[1] - cp[1]
x2 = l1[0] - cp[0]
y2 = l1[1] - cp[1]
if sqrt(x1*x1+y1*y1) < self.radio or sqrt(x2*x2+y2*y2) < self.radio:
return True
dx = x2 - x1
dy = y2 - y1
dr = sqrt(dx*dx + dy*dy)
D = x1 * y2 - x2 * y1
discriminant = self.radio*self.radio*dr*dr - D*D
if discriminant < 0:
return False
sign = lambda x: -1 if x < 0 else 1
xa = (D * dy + sign(dy) * dx * sqrt(discriminant)) / (dr * dr)
xb = (D * dy - sign(dy) * dx * sqrt(discriminant)) / (dr * dr)
ya = (-D * dx + abs(dy) * sqrt(discriminant)) / (dr * dr)
yb = (-D * dx - abs(dy) * sqrt(discriminant)) / (dr * dr)
ta = (xa-x1)*dx/dr + (ya-y1)*dy/dr
tb = (xb-x1)*dx/dr + (yb-y1)*dy/dr
return 0 < ta < dr or 0 < tb < dr
class CreaObjects:
def __init__(self, figs):
self.figs = figs
self.no_lines = 0
self.no_circles = 0
def update(self):
if self.no_circles <70:
r = randint(5, 104)
creOne = Circulo(randint(0, 600 - 2*r), randint(0, 400 - 2*r), r)
if not any(fig.colisionC(creOne) for fig in self.figs):
self.figs.append(creOne)
self.no_circles += 1
if self.no_lines <70:
linOne = Linea(randint(0, 700), randint(0, 500), randint(0, 700), randint(0, 500))
if not any(fig.colisionL(linOne) for fig in self.figs):
self.figs.append(linOne)
self.no_lines += 1
class Ventana:
def __init__(self, Ven_Tam= (700, 500)):
pg.init()
self.ven_tam = Ven_Tam
self.ven = pg.display.set_caption("Linea")
self.ven = pg.display.set_mode(self.ven_tam)
self.figs = []
self.reloj = pg.time.Clock()
def check_events(self):
for event in pg.event.get():
if event.type == pg.QUIT or (event.type == pg.KEYDOWN and event.key == pg.K_ESCAPE):
quit()
def run(self):
cirCreater = CreaObjects(self.figs)
while True:
self.check_events()
cirCreater.update()
self.ven.fill(pg.Color('#404040'))
for fig in self.figs:
fig.dibujar(self.ven)
pg.display.flip()
self.reloj.tick(60)
if __name__ == '__main__':
ven = Ventana()
ven.run()

CV2 is not saving images

The code is supposed to save the roi I have set using the coordinates of detected objects. No errors were found on this part, but it doesnt save the image.
path = "C:\HelmetDetection"
dt = str(datetime.now().strftime("%Y%m%d-%H:%M:%S"))
overlapping = bool()
instance = None
def check_if_overlapping(x1, y1, trc1, blc1, x2, y2, trc2, blc2):
check_instance(x1, y1, trc1, blc1, x2, y2, trc2, blc2)
if instance == "ins1":
global overlapping
overlapping = True
else:
overlapping = False
def save_image(roi):
status = cv2.imwrite(os.path.join(path, dt + '.jpg'), roi)
print(status)
def check_instance(x1, y1, trc1, blc1, x2, y2, trc2, blc2):
global instance
if x1 < x2 and y1 > y2 and trc1 > trc2 and blc1 < blc2:
instance = "ins1"
if label == "motorcycle":
cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 0), 1)
cv2.putText(img, label + " " + f'{confidence * 100}%', (x, y + 20), font, 1, (0, 0, 0), 1)
mcoords = []
mcoords.append((x, y, x + w, y + h))
if len(mcoords) == 1:
x1, y1, trc1, blc1 = x, y, x + w, y + h
else:
x1, y1, trc1, blc1 = mcoords[0]
if label == "bicycle":
cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 0), 1)
cv2.putText(img, label + " " + f'{confidence * 100}%', (x, y + 20), font, 1, (0, 0, 0), 1)
x1, y1, trc1, blc1 = x, y, x + w, y + h
bcoords = []
bcoords.append((x, y, x + w, y + h))
if len(bcoords) == 1:
x1, y1, trc1, blc1 = x, y, x + w, y + h
else:
x1, y1, trc1, blc1 = bcoords[0]
if label == "person":
cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 0), 1)
cv2.putText(img, label + " " + f'{confidence * 100}%', (x, y + 20), font, 1, (0, 0, 0), 1)
hcoords = []
hcoords.append((x, y, x + w, y + h))
if len(hcoords) == 1:
x2, y2, trc2, blc2 = x, y, x + w, y + h
else:
x2, y2, trc2, blc2 = hcoords[0]
if 'x1' and 'y1' and 'trc1' and 'blc1' and 'x2' and 'y2' and 'trc2' and 'blc2' in locals():
check_if_overlapping(x1, y1, trc1, blc1, x2, y2, trc2, blc2)
!!!
if overlapping == True:
check_instance()
if instance == "ins1":
if (y2 or blc2 or x1 or trc1) > 100:
roi = img[y2 - 100:blc2 + 100, x1 - 100:trc1 + 100]
save_image(roi)
!!!
It returns False, which as I have read, means the image failed to save. Can I get some easily understandable solutions?
A/N: These are just snippets, it is kind of a long project, so just tell me if you need more information about the codes used.
Something I always like to do is to test my filepath setup using open() as it throws much more useful errors.
In your case it throws an invalid path error, which if you start eliminating weird characters is due to the “:##:” in the date/time format
I would recommend switching your format to not contain colons

How to draw a dashed curved line with pygame?

I need to draw sine and cosine waves on a coordinate system exactly like in this picture. I did all the work well except I failed to represent dashed and curved line with pygame. I have smth similar to what I need, but how can I make it curved? Or how can I improve this to make it like pygame.draw.lines, not pygame.draw.line?
import pygame
import math
class Point:
# constructed using a normal tupple
def __init__(self, point_t = (0,0)):
self.x = float(point_t[0])
self.y = float(point_t[1])
# define all useful operators
def __add__(self, other):
return Point((self.x + other.x, self.y + other.y))
def __sub__(self, other):
return Point((self.x - other.x, self.y - other.y))
def __mul__(self, scalar):
return Point((self.x*scalar, self.y*scalar))
def __div__(self, scalar):
return Point((self.x/scalar, self.y/scalar))
def __len__(self):
return int(math.sqrt(self.x**2 + self.y**2))
# get back values in original tuple format
def get(self):
return (self.x, self.y)
def draw_dashed_line(surf, color, start_pos, end_pos, width=1, dash_length=4):
origin = Point(start_pos)
target = Point(end_pos)
displacement = target - origin
length = len(displacement)
slope = displacement.__div__(length)
for index in range(0, int(length/dash_length), 2):
start = origin + (slope * index * dash_length)
end = origin + (slope * (index + 1) * dash_length)
pygame.draw.line(surf, color, start.get(), end.get(), width)
pygame.init()
screen = pygame.display.set_mode((400, 300))
done = False
while not done:
draw_dashed_line(screen,(0,255,0),(0,0),(110,110))
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
pygame.display.flip()
Write a function that operates similar as pygame.draw.line() but draws a dashed straight line. The function has an additional argument prev_line_len which indicates where the line segment is within a consecutive curve. Compute the Euclidean distance between the points and the Unit vector that points from the beginning of the line segment to its end. Distribute the strokes along the line:
def draw_dashed_line(surf, color, p1, p2, prev_line_len, dash_length=8):
dx, dy = p2[0]-p1[0], p2[1]-p1[1]
if dx == 0 and dy == 0:
return
dist = math.hypot(dx, dy)
dx /= dist
dy /= dist
step = dash_length*2
start = (int(prev_line_len) // step) * step
end = (int(prev_line_len + dist) // step + 1) * step
for i in range(start, end, dash_length*2):
s = max(0, start - prev_line_len)
e = min(start - prev_line_len + dash_length, dist)
if s < e:
ps = p1[0] + dx * s, p1[1] + dy * s
pe = p1[0] + dx * e, p1[1] + dy * e
pygame.draw.line(surf, color, pe, ps
Write another function that behaves similarly to pygame.draw.lines(), but uses the former function (draw_dashed_line) to draw the dashed curve. Calculate the length from the beginning of the curve to the beginning of each line segment and pass it to the function:
def draw_dashed_lines(surf, color, points, dash_length=8):
line_len = 0
for i in range(1, len(points)):
p1, p2 = points[i-1], points[i]
dist = math.hypot(p2[0]-p1[0], p2[1]-p1[1])
draw_dashed_line(surf, color, p1, p2, line_len, dash_length)
line_len += dist
Minimal example:
repl.it/#Rabbid76/DashedLine
import pygame
import math
def draw_dashed_line(surf, color, p1, p2, prev_line_len, dash_length=8):
dx, dy = p2[0]-p1[0], p2[1]-p1[1]
if dx == 0 and dy == 0:
return
dist = math.hypot(dx, dy)
dx /= dist
dy /= dist
step = dash_length*2
start = (int(prev_line_len) // step) * step
end = (int(prev_line_len + dist) // step + 1) * step
for i in range(start, end, dash_length*2):
s = max(0, start - prev_line_len)
e = min(start - prev_line_len + dash_length, dist)
if s < e:
ps = p1[0] + dx * s, p1[1] + dy * s
pe = p1[0] + dx * e, p1[1] + dy * e
pygame.draw.line(surf, color, pe, ps)
def draw_dashed_lines(surf, color, points, dash_length=8):
line_len = 0
for i in range(1, len(points)):
p1, p2 = points[i-1], points[i]
dist = math.hypot(p2[0]-p1[0], p2[1]-p1[1])
draw_dashed_line(surf, color, p1, p2, line_len, dash_length)
line_len += dist
pygame.init()
screen = pygame.display.set_mode((400, 300))
done = False
line = [(i, 150 + math.sin(math.radians(i*2)) * 100) for i in range(400)]
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
draw_dashed_lines(screen, (255, 255, 255), line)
pygame.display.flip()

Updating pixel size tkinter

I'm trying to update the pixel size of my grid once I press the zoom in or zoom out buttons. When I click on the zoom in, the pixel size should increase it's size by one, when I zoom out, the pixel size should decrease by 1. I'm having trouble updating the grid without deleting what has been drawn in it. This is my code
from tkinter import *
from tkinter import colorchooser
import math
PixelSize = 10
class Grilla:
colorCelda = "black"
colorDefault = "white"
colorBorde = "black"
bordeDefault = "black"
def __init__(self, root, master, x, y, size):
self.master = master
self.abs = x
self.ord = y
self.size = size
self.fill = False
def switch(self):
self.fill = not self.fill
def reset(self):
self.fill = False
def draw(self):
if self.master is not None:
outline = Grilla.colorBorde
fill = Grilla.colorCelda
if not self.fill:
outline = Grilla.bordeDefault
fill = Grilla.colorDefault
xmin = self.abs * self.size
xmax = xmin + self.size
ymin = self.ord * self.size
ymax = ymin + self.size
self.master.create_rectangle(xmin, ymin, xmax, ymax, fill=fill, outline=outline)
class CellGrilla(Canvas):
def __init__(self, master, numFil, numCol, tamGrid, *args, **kwargs):
Canvas.__init__(self, master, width=tamGrid * numCol, height=tamGrid * numFil, *args, **kwargs)
self.bind("<Button-1>", self.square_clicked)
self.cellSize = tamGrid
self.pen = "draw"
self._grid = []
for row in range(numFil):
line = []
for column in range(numCol):
line.append(Grilla(master, self, column, row, tamGrid))
self._grid.append(line)
self.switched = []
self.draw()
def square_clicked(self, event):
row, column = self._coordenadas(event)
cell = self._grid[row][column]
if self.pen == "draw":
cell.switch()
if cell.fill:
self.switched.append(cell)
else:
self.switched.remove(cell)
cell.draw()
def draw(self):
for row in self._grid:
for cell in row:
cell.draw()
def _coordenadas(self, event):
row = event.y // self.cellSize
column = event.x // self.cellSize
return row, column
def switch_to_draw(self):
self.pen = "draw"
def color(self):
colorSelec = colorchooser.askcolor()[1]
if colorSelec:
Grilla.colorCelda = colorSelec
Grilla.colorBorde = colorSelec
def clear(self):
self.switched = []
for row in self._grid:
for cell in row:
cell.reset()
cell.draw()
def DDA(self):
x1 = self.switched[0].abs
x2 = self.switched[1].abs
y1 = self.switched[0].ord
y2 = self.switched[1].ord
length = abs(x2 - x1) if abs(x2 - x1) > abs(y2 - y1) else abs(y2 - y1)
dx = abs(x1 - x2) / float(length)
dy = abs(y1 - y2) / float(length)
x, y = x1, y1
for i in range(length):
if x1 < x2:
x += dx
else:
x -= dx
if y1 < y2:
y += dy
else:
y -= dy
cell = self._grid[int(y)][int(x)]
cell.switch()
cell.draw()
def bresenhamLine(self):
x1 = self.switched[0].abs
x2 = self.switched[1].abs
y1 = self.switched[0].ord
y2 = self.switched[1].ord
dx = x2 - x1
dy = y2 - y1
D = 2 * dy - dx
x, y = x1, y1
for x in range(x1 + 1, x2 + 1):
if D > 0:
y += 1
D += (2 * dy - 2 * dx)
else:
D += 2 * dy
cell = self._grid[int(y)][int(x)]
cell.switch()
cell.draw()
def bresenhamCircle(self):
x1 = self.switched[0].abs
x2 = self.switched[1].abs
y1 = self.switched[0].ord
y2 = self.switched[1].ord
radius = int(math.sqrt(math.pow(x2 - x1, 2) + math.pow(y2 - y1, 2)))
x = 0
y = radius
switch = 3 - (2 * radius)
self.dibujarCirculo(x1, y1, x, y)
while x <= y:
x = x + 1
if switch < 0:
switch = switch + (4 * x) + 6
else:
switch = switch + (4 * (x - y)) + 10
y = y - 1
self.dibujarCirculo(x1, y1, x, y)
def dibujarCirculo(self, xc, yc, x, y):
self.drawPoint(xc + x, yc + y)
self.drawPoint(xc + x, yc - y)
self.drawPoint(xc + y, yc + x)
self.drawPoint(xc + y, yc - x)
self.drawPoint(xc - x, yc + y)
self.drawPoint(xc - x, yc - y)
self.drawPoint(xc - y, yc + x)
self.drawPoint(xc - y, yc - x)
def drawPoint(self, x, y):
cell = self._grid[int(y)][int(x)]
cell.switch()
cell.draw()
def Ellipse(self):
x1 = self.switched[0].abs
x2 = self.switched[1].abs
y1 = self.switched[0].ord
y2 = self.switched[1].ord
radius = int(math.sqrt(math.pow(x2 - x1, 2) + math.pow(y2 - y1, 2)))
x = 0
y = radius
switch = 3 - (2 * radius)
self.dibujarElipse(x1, y1, x, y)
while x <= y:
x = x + 1
if switch < 0:
switch = switch + (4 * x) + 6
else:
switch = switch + (4 * (x - y)) + 10
y = y - 1
self.dibujarElipse(x1, y1, x, y)
def dibujarElipse(self, xc, yc, x, y):
self.drawPoint(xc + x, yc + y)
self.drawPoint(xc + x, yc - y)
self.drawPoint(xc + y, yc + x)
self.drawPoint(xc + y, yc - x)
self.drawPoint(xc - x, yc + y)
self.drawPoint(xc - x, yc - y)
self.drawPoint(xc - y, yc + x)
self.drawPoint(xc - y, yc - x)
def zoomIn(self):
global PixelSize
if PixelSize >= 10:
PixelSize = PixelSize + 1
def zoomOut(self):
global PixelSize
if PixelSize > 11:
PixelSize = PixelSize - 1
# def floodFill(self, grid, fila, columna, nuevoColor):
# color = grid[fila][columna]
if __name__ == "__main__":
app = Tk()
grid = CellGrilla(app, 75, 75, PixelSize)
grid.grid(row=1, column=1, rowspan=4, sticky="news")
colorBoton = Button(app, text="Elegir color", command=grid.color, height=1, width=30)
ddaBoton = Button(app, text="DDA", command=grid.DDA, height=1, width=30)
zoomInBoton = Button(app, text="Zoom in", command=grid.zoomIn, height=1, width=30)
zoomOutBoton = Button(app, text="Zoom out", command=grid.zoomOut, height=1, width=30)
reset_btn = Button(app, text="Borrar", command=grid.clear, height=1, width=30)
BresenhamLine = Button(app, text="Bresenham Line", command=grid.bresenhamLine, height=1, width=30)
BresenhamCircle = Button(app, text="Bresenham Circle", command=grid.bresenhamCircle, height=1, width=30)
Ellipse = Button(app, text="Elipse", command=grid.bresenhamCircle, height=1, width=30)
# FloodFill = Button(app, text="Rellenar", command=grid.bresenhamCircle, height=1, width=30)
zoomInBoton.grid(row=1, column=2, sticky="news")
zoomOutBoton.grid(row=2, column=2, sticky="news")
colorBoton.grid(row=3, column=2, sticky="news")
ddaBoton.grid(row=4, column=2, sticky="news")
reset_btn.grid(row=1, column=3, sticky="news")
BresenhamLine.grid(row=2, column=3, sticky="news")
BresenhamCircle.grid(row=3, column=3, sticky="news")
Ellipse.grid(row=4, column =3, sticky="news")
# FloodFill.grid(row=1, column=4, sticky="news")
app.mainloop()

Incorrect Rotation of Shape in Python

I'm trying to create a rotating plane in pygame. I'm converting 3d (x, y, z) coordinates to screen coordinates (x, y), and then rotating the screen coordinates. This seems to work when its rotating on both the x and y axis, but when it's rotating on only one axis (I commented out the y axis rotation) it is slanted. I can't seem to figure out why?
import pygame
import math
red = (255, 0, 0)
class Vector3:
def __init__(self, _x, _y, _z):
self.x = _x
self.y = _y
self.z = _z
class Vector2:
def __init__(self, _x, _y):
self.x = _x
self.y = _y
class Plane:
def draw(self, screen, value):
scale = 25
points = []
vertices = [Vector3(0, 1, 0),
Vector3(1, 1, 0),
Vector3(1, 0, 0),
Vector3(0, 0, 0)]
for vert in vertices:
x, y = vec3to2(vert)
points.append(Vector2(x * scale + 40, y * scale + 100))
print((x, y))
centerx = (points[0].x + points[1].x + points[2].x + points[3].x) / 4
centery = (points[0].y + points[1].y + points[2].y + points[3].y) / 4
for point in points:
rotx, roty = vec3rot(point, math.radians(value), centerx, centery)
point.x = rotx
#point.y = roty
pygame.draw.line(screen, red, (points[0].x, points[0].y), (points[1].x, points[1].y))
pygame.draw.line(screen, red, (points[1].x, points[1].y), (points[2].x, points[2].y))
pygame.draw.line(screen, red, (points[0].x, points[0].y), (points[3].x, points[3].y))
pygame.draw.line(screen, red, (points[3].x, points[3].y), (points[2].x, points[2].y))
pygame.draw.circle(screen, red, (int(centerx), int(centery)), 1)
def vec3to2(vect3):
try:
_x = vect3.x / vect3.z
except ZeroDivisionError:
_x = vect3.x
try:
_y = vect3.y / vect3.z
except ZeroDivisionError:
_y = vect3.y
return(_x, _y)
def vec3rot(vect3, theta, centerx, centery):
_x = centerx + (vect3.x - centerx) * math.cos(theta) - (vect3.y - centery) * math.sin(theta)
_y = centery + (vect3.x - centerx) * math.sin(theta) + (vect3.y - centery) * math.cos(theta)
return(_x, _y)
def main():
pygame.init()
screen = pygame.display.set_mode((640, 480))
v = 0
plane = Plane()
running = True
while running:
screen.fill((0, 0, 0))
plane.draw(screen, v)
pygame.display.flip()
v += 0.1
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
main()

Categories