shapes.py

Created by airopi

Created on March 22, 2022

5.3 KB

Un script python pour dessiner des figures géométriques ! (Cercles, triangles, hexagones, étoiles… shurikens ?)

Même ce que vous voulez enfaite !

Utilisation :

Les fonctions de dessins :

polygone(x,y,nb_sides,side?,r?,orient?,co?) : dessiner un polygone régulier
figure(points,co?) : dessiner une figure avec des points
line(pt1,pt2,co?) : dessiner une ligne
lines(points,close?,co?) : dessiner des ligne entre plusieurs points
circle(x,y,r,inside_r,co?) : tracer un cercle
rectangle(x,y,width,height,co?) : tracer un rectangle
triangle(x,y,side,orient?,co?) : tracer un triangle
etoile(x,y,nb_sides,outside_r,inside_r,orient?) : tracer une étoile
shuriken(x,y,nb_sides,outside_r,inside_r,orient?) : tracer un shuriken
random(co?) : tracer une forme aléatoire

Quelques variables à connaitre :

y int : coordonnée y
x int : coordonée x
width int : largeur du rectangle
height int : hauteur du rectangle
side int : longueur d’un coté
r int : le rayon d’un cercle ou d’un polygone
outside_r int : le rayon du cercle extérieur
inside_r int : le rayon du cercle intérieur
nb_sides int : le nombre de cotés d’un polygone
orient int : l’orientation d’un polygone
co tuple[int] : la couleur d’une figure
pt tuple[int] : un point
points tuple[int] | tuple[tuple[int]] : une liste de points
close bool : si la figure est fermée ou no

Quelques exemples :

etoile(160,111,5,100,30,45,(255,100,100))
shuriken(160,111,5,100,-30,45)
circle(160,111,100,50,(100,255,100))

Les fonctions bonus :

Ces commandes peuvent être supprimées du programme.

help_shapes() : afficher les fonctions de dessin
exemples() : afficher des exemples


from kandinsky import *
from math import *
from random import randint

default_co=(100,100,100)

# Utility functions

def _radius(side,nb_sides):
  alpha=radians(360/nb_sides)
  return (side/2)/sin(alpha/2)

def _lenght_side(r,nb_sides):
  alpha=radians(360/nb_sides)
  return 2*r*sin(alpha/2)

def _diagonal_from_side(side,nb_sides):
  r=_radius(side,nb_sides)
  if nb_sides%2==0:
    return r*2
  q=sqrt(r**2-(side/2)**2)
  return q+r

def _diagonal_from_radius(r,nb_sides):
  if nb_sides%2==0:
    return r*2
  ln_s=_lenght_side(r,nb_sides)
  q=sqrt(r**2-(ln_s/2)**2)
  return q+r

def _minmax(array):
  return min(array), max(array)

def _line_eq(pt1,pt2,from_x=True):
  if from_x:
    return lambda x:round(pt1[1]+(pt2[1]-pt1[1])*(x-pt1[0])/(pt2[0]-pt1[0])) if pt2[0]-pt1[0] else pt1[0]
  else:
    return lambda y:round(pt1[0]+(pt2[0]-pt1[0])*(y-pt1[1])/(pt2[1]-pt1[1])) if pt2[1]-pt1[1] else pt1[1]


# Base functions :

def figure(points,co=default_co):
  _co=color(*co)

  vectors=[]

  def _append_vectors(pts):
    vectors.extend((pts[i-1], pts[i]) for i in range(len(pts)))

  if isinstance(points[0][0], int):  # ((x,y),(x,y),...)
    _append_vectors(points)
  else:  # (((x,y),(x,y),...),((x,y),(x,y),...),...)
    for sub_points in points:
      _append_vectors(sub_points)
    points=[p for pts in points for p in pts]

  x_values=tuple(p[0] for p in points)
  min_x=min(x_values)
  max_x=max(x_values)

  for x in range(min_x,max_x):
    if (x-1) in x_values or x == min_x:
      precedent=None
      path_vectors=[]
      for vector in vectors:
        if not min(vector[0][0], vector[1][0]) <= x <= max(vector[0][0],vector[1][0]):continue
        if precedent and precedent[1][0]==vector[0][0]:
          if not ((precedent[0][0]<vector[0][0] and vector[1][0]<vector[0][0])
            or (precedent[0][0]>vector[0][0] and vector[1][0]>vector[0][0])):continue
        precedent=vector
        path_vectors.append(precedent)

    path=tuple(sorted(_line_eq(*vector)(x) for vector in path_vectors))

    for i in range(0, len(path), 2):
      try:fill_rect(x,path[i],1,path[i+1]-path[i],_co)
      except:pass #sometimes something messup idk why

def _polygone_points(x,y,nb_sides,side=None,r=None,orient=0):
  if side and r:
    raise ValueError("You can't give both side and r")
  elif side:
    h=_diagonal_from_side(side,nb_sides)
    r=_radius(side,nb_sides)
  elif r:
    h=_diagonal_from_radius(r,nb_sides)
  else:
    raise ValueError("Missing side or r")

  orient=radians(orient)
  alpha=radians(360/nb_sides)

  points=[]
  for i in range(nb_sides):
    points.append(
      (round(x+r*cos(orient+i*alpha+pi/nb_sides)),
      round(y-r*sin(orient+i*alpha+pi/nb_sides)))
    )

  return points

def polygone(x,y,nb_sides,side=None,r=None,orient=0,co=default_co):
  points=_polygone_points(x,y,nb_sides,side,r,orient)
  figure(points,co)

def line(pt1,pt2,co=default_co):
  _co=color(*co)

  xy=_line_eq(pt1,pt2)
  yx=_line_eq(pt1,pt2,False)

  for x in range(min(pt1[0],pt2[0]),max(pt1[0],pt2[0])):
    set_pixel(x,xy(x),_co)
  for y in range(min(pt1[1],pt2[1]),max(pt1[1],pt2[1])):
    set_pixel(yx(y),y,_co)

def lines(points,close=False,co=default_co):
  if close:
    points=tuple(points)+(points[0],)
  for i in range(len(points)-1):
    line(points[i],points[i+1],co)


# Child functions

def rectangle(x,y,width,height,co=default_co):
  _co=color(*co)
  fill_rect(x,y,width,height,_co)

def triangle(x,y,side,orient=0,co=default_co):
  polygone(x,y,3,side=side,orient=orient,co=co)

def shuriken(x,y,nb_sides,outside_r,inside_r,orient=0,co=default_co):
  points_out=_polygone_points(x,y,nb_sides,r=outside_r,orient=orient)
  points_in=_polygone_points(x,y,nb_sides,r=inside_r,orient=360/nb_sides+orient)
  points=[x for y in zip(points_out,points_in) for x in y]
  figure(points,co)

def etoile(x,y,nb_sides,outside_r,inside_r,orient=0,co=default_co):
  points_out=_polygone_points(x,y,nb_sides,r=outside_r,orient=orient)
  points_in=_polygone_points(x,y,nb_sides,r=inside_r,orient=180/nb_sides+orient)
  points=[x for y in zip(points_out,points_in) for x in y]
  figure(points,co)

def circle(x,y,r,inside_r=0,co=default_co):
  _co=color(100,100,100)

  if not inside_r:
    for i in range(r):
      h=int(r*sin(acos(i/r)))
      fill_rect(x+i,y-h,1,h*2,_co)
      fill_rect(x-i,y-h,1,h*2,_co)
  else:
    for i in range(r):
      h=int(r*sin(acos(i/r)))
      ih=int(inside_r*sin(acos(i/inside_r))) if i<=inside_r else 0

      fill_rect(x+i,y-h,1,h-ih,_co)
      fill_rect(x+i,y+h,1,-h+ih,_co)
      fill_rect(x-i,y-h,1,h-ih,_co)
      fill_rect(x-i,y+h,1,-h+ih,_co)

def random(co=default_co):
  points=[]
  for i in range(randint(20,30)):
    points.append((randint(0,320),randint(0,222)))

  lines(points,True,co)
  figure(points,co)


# Other functions

def help_shapes():
  print("polygone(x,y,nb_sides,side?,r?,orient?,co?)")
  print("figure(points,co?)")
  print("line(pt1,pt2,co?)")
  print("lines(points,close?,co?)")
  print()
  print("circle(x,y,r,inside_r,co?)")
  print("rectangle(x,y,width,height,co?)")
  print("triangle(x,y,side,orient=0,co?)")
  print("etoile(x,y,nb_sides,outside_r,inside_r,orient=0,co?)")
  print("shuriken(x,y,nb_sides,outside_r,inside_r,orient=0,co?)")
  print("random(co?)")

def exemples():
  print("etoile(160,111,5,100,30,45,(255,100,100))")
  print("shuriken(160,111,5,100,-30,45)")
  print("circle(160,111,100,50,(100,255,100))")

During your visit to our site, NumWorks needs to install "cookies" or use other technologies to collect data about you in order to:

With the exception of Cookies essential to the operation of the site, NumWorks leaves you the choice: you can accept Cookies for audience measurement by clicking on the "Accept and continue" button, or refuse these Cookies by clicking on the "Continue without accepting" button or by continuing your browsing. You can update your choice at any time by clicking on the link "Manage my cookies" at the bottom of the page. For more information, please consult our cookies policy.