Page 1 sur 3

[DEFI] Dessiner

Publié : mer. 26/févr./2014 18:39
par Mesa
Le défi est le suivant :

Créer une procédure qui dessine un rectangle ABCD avec seulement 2 points A et B donnés et où les seuls opérateurs permis sont "+, -, *, /, sqrt, line() et lineXY()".


Donc, interdiction d'utiliser
la fonction box(), ni rectangle_(), ...
ni les api,
ni les opérateurs de trigo comme sin, cos, tan, atan, acos, etc,
pas le droit d'utiliser non plus une table de nombre, pas de tableau, ni de liste, ni de map, ni de datasection, etc,...
ni quoi que ce soit d'autre.

C'est du niveau Lycée, 1ère S.

Défi subsidiaire : Faire tourner ce rectangle.

Réponse dans 7 ou 14 jours avec le code commenté.

Mesa.


REPONSE

Code : Tout sélectionner


Procedure Rectangle(x0, y0, x1, y1, e, couleur)
  ; -----------------------------------
  ;
  ; A(x0,y0)_________________B(x1,y1)
  ;        |                 |
  ;        |                 |
  ;        |                 |
  ; C(x2,y2)_________________D(x3,y3)
  ;
  ; -----------------------------------
  
  ;Tracé de la ligne AB
  LineXY(x0, y0, x1, y1, couleur)
  
  ;Rotation à 90° du point B autour du point A
  ;Les coordonnées de ce point sont x2_90 et y2_90
  x2_90=-(y1-y0)+x0
  y2_90=x1-x0+y0
  
  ; x3_90=(y1-y0)+x0
  ; y3_90=-1*(x1-x0)+y0
  
  ;Calcul de la longueur du segment AB
  L.f=Sqr((x1-x0)*(x1-x0)+(y1-y0)*(y1-y0))
  
  ;Calcul du coefficient de proportionnalité
  ;sans lui, on ne pourrait dessiner que des carrés ou des triangles-rectangles
  H.f=e/L
    
  ;Calcul des coordonnées du point C par homothétie (réduction)
  x2=H*(x2_90-x0)+x0
  y2=H*(y2_90-y0)+y0
  
  ;Tracé de la ligne AC
  LineXY(x0, y0, x2, y2, couleur)
  
  ;Calcul des coordonnées du point D : les vecteurs AB et CD sont colinéaires 
  x3=x1-x0+x2
  y3=y1-y0+y2
  
  ;Tracé de la ligne BD
  LineXY(x1,y1,x3, y3,couleur)
  
  ;Tracé de la ligne CD
  LineXY(x2,y2,x3, y3, couleur)
  
EndProcedure



;- openwindows
If OpenWindow(0, 100, 200, 300, 300, "Test de rotation de rectangle 2D")
  
  If CreateImage(0, 300, 300)
    
    If StartDrawing(ImageOutput(0))
      Box(0,0,300,300,RGB(0,128,128)) ; Fond vert
      Rectangle(10,10,110,10,30,RGB(255,255,255))
      Rectangle(10,60,30,60,100,RGB(255,255,0))
      Rectangle(180,20,220,60,60,RGB(0,255,0))
      Rectangle(100,60,210,160,40,RGB(0,255,0))
      Rectangle(100,260,210,180,25,RGB(0,255,255))
      Rectangle(100,260,210,180,-25,RGB(0,255,255))
      Rectangle(200,240,250,240,50,RGB(255,255,255))
      StopDrawing()
    EndIf      
    
    ; Affichage du rectangle dans un ImageGadget 
    ImageGadget(0, 0, 0, 0, 0, ImageID(0))
    ;Delay(100)
  EndIf
  
  Repeat
    Event = WaitWindowEvent() 
  Until Event = #PB_Event_CloseWindow  
  
EndIf

End 

Défi subsidiaire

Code : Tout sélectionner



Procedure Rectangle(x0, y0, x1, y1, e, couleur)
  ; -----------------------------------
  ;
  ; A(x0,y0)_________________B(x1,y1)
  ;        |                 |
  ;        |                 |
  ;        |                 |
  ; C(x2,y2)_________________D(x3,y3)
  ;
  ; -----------------------------------
  
  ;Tracé de la ligne AB
  LineXY(x0, y0, x1, y1, couleur)
  
  ;Rotation à 90° du point B autour du point A
  ;Les coordonnées de ce point sont x2_90 et y2_90
  x2_90=-(y1-y0)+x0
  y2_90=x1-x0+y0
  
  ; x3_90=(y1-y0)+x0
  ; y3_90=-1*(x1-x0)+y0
  
  ;Calcul de la longueur du segment AB
  L.f=Sqr((x1-x0)*(x1-x0)+(y1-y0)*(y1-y0))
  
  ;Calcul du coefficient de proportionnalité
  ;sans lui, on ne pourrait dessiner que des carrés ou des triangles-rectangles
  H.f=e/L
  
  
  ;Calcul des coordonnées du point C par homothétie (réduction)
  x2=H*(x2_90-x0)+x0
  y2=H*(y2_90-y0)+y0
  
  ;Tracé de la ligne AC
  LineXY(x0, y0, x2, y2, couleur)
  
  ;Calcul des coordonnées du point D : les vecteurs AB et CD sont colinéaires 
  x3=x1-x0+x2
  y3=y1-y0+y2
  
  ;Tracé de la ligne BD
  LineXY(x1,y1,x3, y3,couleur)
  
  ;Tracé de la ligne CD
  LineXY(x2,y2,x3, y3, couleur)
  
EndProcedure



;- openwindows
If OpenWindow(0, 100, 200, 300, 300, "Test de rotation de rectangle 2D")
  
  If CreateImage(0, 300, 300)
    xc=150
    yc=150
    R=100
    For a=0 To 360
      ; Ici les sin et cos ne servent pas à dessiner le rectangle
      ; mais juste à le faire tourner autour de A
      ; ça permet de vérifier que l'on peut dessiner un rectangle dans "toutes les directions"
      x=R*Cos(Radian(a))+xc
      y=R*Sin(Radian(a))+yc
      If StartDrawing(ImageOutput(0))
        Box(0,0,300,300,0)
        Rectangle(xc,yc,x,y,30,RGB(255,255,255))
        StopDrawing()
      EndIf
      
      
      ; Affichage du rectangle dans un ImageGadget 
      ImageGadget(0, 0, 0, 0, 0, ImageID(0))
      ;Delay(100)
    Next a
  EndIf
  
  Repeat
    Event = WaitWindowEvent() 
  Until Event = #PB_Event_CloseWindow  
  
EndIf

End 

M.

Re: [DEFI] Dessiner

Publié : mer. 26/févr./2014 19:51
par GallyHC
Bonjour,

Tu ne donnerais pas AC que AB pour dessiner le rectangle ;) si on part d'un rectangle du style

Code : Tout sélectionner

    A +------------------+ B
      |                  |
      |                  |
      |                  |
    D +------------------+ C
Cordialement,
GallyHC

Re: [DEFI] Dessiner

Publié : mer. 26/févr./2014 20:06
par Micoute
Bonsoir Mesa, comme ça, est-ce que c'est permis

Code : Tout sélectionner

Procedure TraitVertical(X, Y, Hauteur, Epaisseur=1, Couleur=0) ; Trace un trait vertical avec épaisseur et couleur choisies
	Protected i = 0
	
	If Epaisseur >0
		While i < Epaisseur
			Line(x+i,y,1,Hauteur,Couleur)
			i+1
		Wend
	Else
		Line(x,y,1,Hauteur,Couleur)
	EndIf
EndProcedure

Procedure TraitHorizontal(X, Y, Longueur, Epaisseur=1, Couleur=0) ; Trace un trait horizontal avec épaisseur et couleur choisies
	Protected i = 0
	
	If Epaisseur > 0
		While i < Epaisseur
			Line(x,y+i,Longueur,1,Couleur)
			i+1
		Wend
	Else
		Line(x,y,Longueur,1,Couleur)
	EndIf
EndProcedure

Procedure Cadre(x, y, Largeur, Hauteur, Epaisseur=1, CouleurCadre=0); Trace un cadre simple de la couleur choisie
		;Ligne supérieure
		TraitHorizontal(x,y,Largeur, Epaisseur, CouleurCadre)
		;Ligne gauche
		TraitVertical(x,y,Hauteur+Epaisseur,Epaisseur,CouleurCadre)
		;Ligne droite
		TraitVertical(x+Largeur,y,Hauteur+Epaisseur,Epaisseur,CouleurCadre)
    	;Ligne inférieure
    	TraitHorizontal(x,y+Hauteur,Largeur,Epaisseur,CouleurCadre)
EndProcedure

Re: [DEFI] Dessiner

Publié : mer. 26/févr./2014 21:01
par majikeyric
Les points A et B sont des angles opposés dans le rectangle ?

Re: [DEFI] Dessiner

Publié : mer. 26/févr./2014 22:24
par Backup
oui parceque sinon , c'est impossible
on ne connaitrai que la largeur ... pas la hauteur .... (a moins que ça n'ai aucune importance )

Re: [DEFI] Dessiner

Publié : mer. 26/févr./2014 23:41
par falsam
majikeyric a écrit :Les points A et B sont des angles opposés dans le rectangle ?
A mon avis non. Sinon c'est trop facile.

Re: [DEFI] Dessiner

Publié : jeu. 27/févr./2014 0:20
par PAPIPP
Bonjour à tous
Voici une étude théorique du pb
Soit A( Xa,Ya ) et B (Xb Yb) 2 points opposés du rectangle trouvez C et D
Tout rectangle se trouvant sur le cercle de diamètre AB
de centre Xc=Xa+(Xb-Xa)/2 et Yc=Ya+(Yb-Ya)/2
Répond au Pb . En effet l'angle ACB est toujours un angle droit. Le cercle est donc le lieu géométrique des points C ou D
Donc l’équation du cercle en coordonnée cartésienne est
(x − x₀)² + (y − y₀)² = c², où x₀, y₀ et c sont des constantes réelles, avec c > 0.
C'est un cercle de centre (x₀,y₀) et de rayon c.
Image

En remplacement de x₀=Xc=Xa+(Xb-Xa)/2 et y₀=Yc= Ya+(Yb-Ya)/2
Equation du cercle (X-( Xa+(Xb-Xa)/2 )) ²+ (Y-( Ya+(Yb-Ya)/2)) ²=((Xb-Xa)/2) ²+((Yb-Ya)/2) ²
On peut ainsi définir le point C(XXc,YYc) avec cette équation et trouver le point D(XXd,YYd) symétrique au point C par rapport au centre

Remarques :
Comme nous avons une seule équation et 2 inconnues il faut imposer l’une de ces inconnues
Mais on peut remarquer sur le graphique que X ne peut être compris qu’entre 2 valeurs l’une mini et l’autre max
Xmin= Xc-rayon et Xmax=Xc+rayon
Avec rayon² = ((Xb-Xa)/2) ²+((Yb-Ya)/2) ²

A+

Re: [DEFI] Dessiner

Publié : jeu. 27/févr./2014 9:27
par Micoute
Bonjour PAPIPP, voilà ce que j’appelle un très bon raisonnement !

@Mesa, peut-on considérer que les points A et B sont l’hypoténuse de 2 triangles rectangles adjacents et tête-bêche ?

Re: [DEFI] Dessiner

Publié : jeu. 27/févr./2014 10:07
par Mesa
@Tous
Merci de donner un code fonctionnel avec openwindow() etc.
C'est plus facile à tester.

@GallyHC
C'est bien un rectangle de ce type
A +------------------+ B
| |
| |
| |
C +------------------+ D
@Micoute
C'est une bonne solution mais j'ai oublié de préciser que le rectangle doit pouvoir être dessiné dans n'importe quel position (faire tourner le rectangle autour du point A). Par exemple, le côté AB doit pouvoir faire un angle de 47° par rapport à l'horizontal.

@majikeyric
Les points A et B forment l'un des côtés, comme sur le dessin ci-dessus.

@Dobro
D'une façon ou d'une autre, il faut que le programmeur connaisse la longueur et la largeur à partir de 2 points et de quelque chose d'autre (Voir le code de Micoute) ...

@PAPIPP
Comme nous avons une seule équation et 2 inconnues il faut imposer l’une de ces inconnues
C'est vrai :D (Voir le code de Micoute)

@Micoute
peut-on considérer que les points A et B sont l’hypoténuse de 2 triangles rectangles adjacents et tête-bêche ?
Pourquoi pas, mais je n'ai pas utilisé cette voie. Reste à vérifier quand même.

M.

Re: [DEFI] Dessiner

Publié : jeu. 27/févr./2014 11:46
par Micoute
Bonjour à tous, voici mon code :

Code : Tout sélectionner

Procedure TraitHorizontal(X, Y, Longueur, Epaisseur=1, Couleur=0) ; Trace un trait horizontal avec épaisseur et couleur choisies
  Protected i = 0
  
  If Epaisseur > 0
    While i < Epaisseur
      Line(x,y+i,Longueur,1,Couleur)
      i+1
    Wend
  Else
    Line(x,y,Longueur,1,Couleur)
  EndIf
EndProcedure

Procedure TraitVertical(X, Y, Hauteur, Epaisseur=1, Couleur=0) ; Trace un trait vertical avec épaisseur et couleur choisies
	Protected i = 0
	
	If Epaisseur >0
		While i < Epaisseur
			Line(x+i,y,1,Hauteur,Couleur)
			i+1
		Wend
	Else
		Line(x,y,1,Hauteur,Couleur)
	EndIf
EndProcedure

Procedure Cadre(X0,Y0,X1,Y1, Epaisseur=1, CouleurCadre=0) ; Trace un cadre simple de la couleur choisie
  TraitHorizontal(X0, Y0, X1-X0,Epaisseur,CouleurCadre)
  TraitVertical(X1, Y0, Y1-Y0,Epaisseur,CouleurCadre)
  TraitHorizontal(X0, Y1, X1-X0,Epaisseur,CouleurCadre)
  TraitVertical(X0, Y0, Y1-Y0,Epaisseur,CouleurCadre)
EndProcedure

;***TEST***

Largeur=1400 - 10
Hauteur=768 - 30

If OpenWindow(0, 0, 0, Largeur, Hauteur, "Rectangle", #PB_Window_SystemMenu ) 
  If StartDrawing(WindowOutput(0))
    Cadre(240,650,991,160,3,#Blue)
  StopDrawing()    
  EndIf 
  Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow 
EndIf

Re: [DEFI] Dessiner

Publié : jeu. 27/févr./2014 12:09
par Backup
...

Re: [DEFI] Dessiner

Publié : jeu. 27/févr./2014 13:14
par Micoute
Bonjour Dobro, tu a utilisé une fonction interdite à la ligne 23

Code : Tout sélectionner

box(x_pos,y_pos+y,epaisseur,epaisseur,couleur) : box(x_pos+largeur,y_pos+y,epaisseur,epaisseur,couleur)
Je ne voudrais pas être pointilleux, mais un défi, c'est comme un test de laboratoire, il faut jouer le jeu !

Je pense qu'il nous manque le paramètre orientation ! Je pense même qu'on pourrait faire un sprite, ce serait plus facile pour le faire tourner !

Re: [DEFI] Dessiner

Publié : jeu. 27/févr./2014 14:14
par Backup
Micoute a écrit :Bonjour Dobro, tu a utilisé une fonction interdite à la ligne 23

Code : Tout sélectionner

box(x_pos,y_pos+y,epaisseur,epaisseur,couleur) : box(x_pos+largeur,y_pos+y,epaisseur,epaisseur,couleur)
Je ne voudrais pas être pointilleux, mais un défi, c'est comme un test de laboratoire, il faut jouer le jeu !

Je pense qu'il nous manque le paramètre orientation ! Je pense même qu'on pourrait faire un sprite, ce serait plus facile pour le faire tourner !

Dobro a écrit :note que je n'utilise pas la fonction Box pour dessiner le rectangle , mais je m'en sert de Plot()[/b]
pour le prouver, j'ai remplacé mes box par circle !!
le but c'est pas de ne pas employer Box , c'est de ne pas l'employer pour faire le Rectangle !

mais Box peut servir a dessiner un Gros point !! ; c'est ce que je faisais !

note: j'en ai profité pour corriger un petit bug ;)

Re: [DEFI] Dessiner

Publié : jeu. 27/févr./2014 15:03
par Micoute
Ok, ok, ne te fâches pas, je voulais juste faire remarquer qu'il était stipulé
interdiction d'utiliser
la fonction box(), ni rectangle_(), ...
ni les api,
ni les opérateurs de trigo comme sin, cos, tan, atan, acos, etc,
pas le droit d'utiliser non plus une table de nombre, pas de tableau, ni de liste, ni de map, ni de datasection, etc,...
ni quoi que ce soit d'autre.
C'est pourquoi, je ne voulais pas paraître pointilleux, ni emmerdeur, ni un boulet, etc...

Je ne me sens pas net vis-à-vis de toi !

Re: [DEFI] Dessiner

Publié : jeu. 27/févr./2014 15:55
par Mesa
Je ne peux que vous encourager à continuer car les codes proposés ne peuvent pas dessiner un rectangle incliné comme ça :

Image

M.