'From Squeak3.8 of ''5 May 2005'' [latest update: #6665] on 15 May 2007 at 10:20:35 am'! DessinsLogo subclass: #Lsystem instanceVariableNames: 'pile niveau reglesDerivation axiome angle longueur box sh sv sdir etat couleur colorMap' classVariableNames: '' poolDictionaries: '' category: 'Cours-Smalltalk-GUI'! !Lsystem commentStamp: '' prior: 0! pile notre pile pour les 'bracketed Lsystems niveau la profondeur de récursion reglesDErivation l'ensemble des règles de réécriture axiome l'axiome angle l'angle longuer la longuer d'un pas box notre bounding box sh position horizontale de la tortue similée sv position verticale de la tortue simulée sdir orientation de la tortue simulée! !Lsystem methodsFor: 'initialisation' stamp: 'hw 3/20/2006 09:11'! defaultBounds ^ 0 @ 0 corner: 400 @ 400 ! ! !Lsystem methodsFor: 'initialisation' stamp: 'hw 3/20/2006 09:11'! initialize super initialize. reglesDerivation := Dictionary new. pile := OrderedCollection new. couleur := 1. colorMap := Color blue wheel: 256. etat := true! ! !Lsystem methodsFor: 'private' stamp: 'hw 3/18/2006 08:28'! avanceS sh := sh + (sdir degreeSin * longueur). "Transcript show: sh; cr." sv := sv + (sdir degreeCos * longueur). self boxUpdate! ! !Lsystem methodsFor: 'private' stamp: 'hw 3/18/2006 08:28'! boiteMin: aString | c x | c := 1. sdir := sh := sv := 0. longueur := 1. box := Rectangle origin: 0 @ 0 corner: 0 @ 0. aString do: [:ele | c := c + 1. (x := 'Ff+-[]|!!' indexOf: ele) > 0 ifTrue: [self perform: (#(#avanceS #avanceS #plusS #moinsS #empileS #depileS #inverseDirS #inverse ) at: x)] ifFalse: [(x := '\/@' indexOf: ele) > 0 ifTrue: [self perform: (#(#increaseS: #decreaseS: #changeLineLength: ) at: x) with: (aString copyFrom: c to: aString size) asNumber]]]! ! !Lsystem methodsFor: 'private' stamp: 'hw 3/18/2006 08:29'! boxUpdate sh < box origin x ifTrue: [box := box withLeft: sh]. sh > box corner x ifTrue: [box := box withRight: sh]. sv < box origin y ifTrue: [box := Rectangle origin: box origin x @ sv corner: box corner]. sv > box corner y ifTrue: [box := box withBottom: sv]! ! !Lsystem methodsFor: 'private' stamp: 'hw 3/18/2006 08:29'! changeLineLength: aNumber longueur := aNumber * longueur ! ! !Lsystem methodsFor: 'private' stamp: 'hw 3/18/2006 08:29'! decreaseS: aNumber sdir := etat ifTrue: [sdir - aNumber] ifFalse: [sdir + aNumber]! ! !Lsystem methodsFor: 'private' stamp: 'hw 3/20/2006 09:10'! depileS longueur := pile removeFirst. sh := pile removeFirst. sv := pile removeFirst. sdir := pile removeFirst! ! !Lsystem methodsFor: 'private' stamp: 'hw 3/20/2006 09:10'! empileS pile addFirst: sdir; addFirst: sv; addFirst: sh; addFirst: longueur ! ! !Lsystem methodsFor: 'private' stamp: 'hw 3/20/2006 09:10'! increaseS: aNumber "Transcript show: aNumber; cr." sdir := etat ifTrue: [sdir + aNumber] ifFalse: [sdir - aNumber]! ! !Lsystem methodsFor: 'private' stamp: 'hw 3/20/2006 09:10'! inverseDirS sdir := sdir + 180 ! ! !Lsystem methodsFor: 'private' stamp: 'hw 3/20/2006 09:10'! moinsS sdir := etat ifTrue: [sdir - angle] ifFalse: [sdir + angle]! ! !Lsystem methodsFor: 'private' stamp: 'hw 3/20/2006 09:10'! normalise | stepX stepY step | stepX := box corner x - box origin x. stepY := box corner y - box origin y. step := form extent x - 20 / stepX min: form extent y - 20 / stepY. "rectabgle origin: point de départ de tortue corner: step @ 0" ^ Rectangle origin: form extent x - (step * (box origin x + box corner x)) / 2 @ (form extent y + (step * (box origin y + box corner y)) / 2) corner: step @ 0! ! !Lsystem methodsFor: 'private' stamp: 'hw 3/20/2006 09:10'! plusS sdir := etat ifTrue: [sdir + angle] ifFalse: [sdir - angle]! ! !Lsystem methodsFor: 'private' stamp: 'hw 3/20/2006 09:11'! setCouleur colorMap := Color red wheel: (FillInTheBlank request: 'niveau?' initialAnswer: 256 asString) asNumber ! ! !Lsystem methodsFor: 'menu' stamp: 'hw 3/22/2006 12:31'! encore niveau := (FillInTheBlank request: 'niveau?' initialAnswer: niveau asString) asNumber. niveau = 0 ifTrue: [^nil]. self lanceLsystem ! ! !Lsystem methodsFor: 'menu' stamp: 'hw 3/18/2006 12:51'! fichier | menu1 listFic | listFic := ((FileDirectory default fileNamesMatching: '*.ll') , (FileDirectory default fileNamesMatching: '*.l')) asSortedCollection. menu1 := MenuMorph new defaultTarget: self. menu1 addTitle: 'Fichiers L-Ssytèmes'; position: Sensor cursorPoint. listFic do: [:fic | menu1 add: fic selector: #show: argument: fic]. menu1 openInWorld! ! !Lsystem methodsFor: 'menu' stamp: 'hw 3/20/2006 09:09'! handlesMouseDown: evt ^ evt yellowButtonPressed ! ! !Lsystem methodsFor: 'menu' stamp: 'hw 3/18/2006 10:56'! lanceLsystem | tmp tmp1 | couleur := 1. self initImage. tmp := self remplace: axiome times: niveau. self boiteMin: tmp. tmp1 := self normalise. pen place: tmp1 origin; color: (couleur asColorOfDepth: Display depth). pen color: pen color asNontranslucentColor. longueur := tmp1 corner x. "Transcript cr; show: tmp." self automate: tmp. self afficheImage! ! !Lsystem methodsFor: 'menu' stamp: 'hw 3/20/2006 09:09'! lSystem | tmp | axiome := FillInTheBlank request: 'axiome?' initialAnswer: 'F'. reglesDerivation := Dictionary new. tmp := FillInTheBlank request: 'derivation 1 ?' initialAnswer: 'F:F+F--F+F'. tmp := tmp copyWithout: $ . tmp = '' ifFalse: [reglesDerivation at: (tmp at: 1) put: (tmp copyFrom: 3 to: tmp size). self getDerivations: (tmp = '' ifTrue: [1] ifFalse: [2])]. angle := (FillInTheBlank request: 'angle?' initialAnswer: '60') asNumber. niveau := 5. self encore! ! !Lsystem methodsFor: 'menu' stamp: 'hw 3/27/2006 09:30'! mouseDown: evt menu := MenuMorph new defaultTarget: self. menu addTitle: 'Choississez un dessin'; add: 'courbe de Koch' action: #koch; add: 'triangle de Sierpinski' action: #sierpinski; add: 'polygone' action: #polyferme; add: 'arbre' action: #arbre2; addLine; add: 'L-System' action: #lSystem; add: 'encore' action: #encore; add: 'lire fichier ?' action: #fichier; add: 'sauver dans ?' action: #sauve; add: 'combien de couleurs ?' action: #setCouleur; addLine; add: 'inspect' action: #inspect; add: 'suicide' action: #suicide; addStayUpItem; popUpAt: Sensor cursorPoint forHand: evt hand in: self world! ! !Lsystem methodsFor: 'actions' stamp: 'hw 3/20/2006 09:04'! automate: aString | c x | c := 1. aString do: [:ele | c := c + 1. (x := 'Ff+-[]|!!' indexOf: ele) > 0 ifTrue: [self perform: (#(#avance #avancef #plus #moins #empile #depile #inverseDir #inverse ) at: x)] ifFalse: [(x := 'C\/@<>' indexOf: ele) > 0 ifTrue: [self perform: (#(#color: #increase: #decrease: #changeLineLength: #incrColor: #decrColor: ) at: x) with: (aString copyFrom: c to: aString size) asNumber]]]! ! !Lsystem methodsFor: 'actions' stamp: 'hw 3/20/2006 09:06'! avance pen go: longueur ! ! !Lsystem methodsFor: 'actions' stamp: 'hw 3/20/2006 09:06'! avancef pen up; go: longueur; down ! ! !Lsystem methodsFor: 'actions' stamp: 'hw 3/20/2006 09:06'! color: aNumber couleur := aNumber. pen color: aNumber ! ! !Lsystem methodsFor: 'actions' stamp: 'hw 3/20/2006 09:06'! decrColor: aNumber self incrColor: 0 - aNumber ! ! !Lsystem methodsFor: 'actions' stamp: 'hw 3/20/2006 09:06'! decrease: aNumber etat ifTrue: [pen turn: 0 - aNumber] ifFalse: [pen turn: aNumber] ! ! !Lsystem methodsFor: 'actions' stamp: 'hw 3/20/2006 09:07'! depile longueur := pile removeFirst. pen location: pile removeFirst direction: pile removeFirst penDown: pile removeFirst ! ! !Lsystem methodsFor: 'actions' stamp: 'hw 3/20/2006 09:07'! empile pile addFirst: pen penDown. pile addFirst: pen direction. pile addFirst: pen location. pile addFirst: longueur ! ! !Lsystem methodsFor: 'actions' stamp: 'hw 3/20/2006 09:07'! getDerivations: n | tmp | tmp := FillInTheBlank request: 'derivation ' , n asString , ' ?' initialAnswer: ''. tmp := tmp copyWithoutAll: {32 asCharacter. 9 asCharacter}. "espace" "tabulation" tmp = '' ifTrue: [^ nil] ifFalse: [reglesDerivation at: (tmp at: 1) put: (tmp copyFrom: 3 to: tmp size). self getDerivations: n + 1]! ! !Lsystem methodsFor: 'actions' stamp: 'hw 3/20/2006 09:07'! incrColor: aNumber pen color: (colorMap atWrap: (couleur := couleur + aNumber))! ! !Lsystem methodsFor: 'actions' stamp: 'hw 3/20/2006 09:07'! increase: aNumber etat ifTrue: [pen turn: aNumber] ifFalse: [pen turn: 0 - aNumber] ! ! !Lsystem methodsFor: 'actions' stamp: 'hw 3/20/2006 09:07'! inverse etat := etat not ! ! !Lsystem methodsFor: 'actions' stamp: 'hw 3/20/2006 09:08'! inverseDir pen turn: 180 ! ! !Lsystem methodsFor: 'actions' stamp: 'hw 3/20/2006 09:08'! moins pen turn: (etat ifTrue: [0 - angle] ifFalse: [angle])! ! !Lsystem methodsFor: 'actions' stamp: 'hw 3/20/2006 09:08'! plus pen turn: (etat ifTrue: [angle] ifFalse: [0 - angle]) ! ! !Lsystem methodsFor: 'actions' stamp: 'hw 3/20/2006 09:08'! remplace: aString | tmp | ^ aString inject: '' into: [:new :ele | (tmp := reglesDerivation at: ele ifAbsent: nil) isNil ifTrue: [new , ele asString] ifFalse: [new , tmp]]! ! !Lsystem methodsFor: 'actions' stamp: 'hw 3/20/2006 09:08'! remplace: aString times: n ^ n = 0 ifTrue: [aString] ifFalse: [self remplace: (self remplace: aString) times: n - 1]! ! !Lsystem methodsFor: 'lecture-ecriture' stamp: 'hw 3/20/2006 07:55'! ajoute: unFichier | fic | fic := FileStream oldFileNamed: unFichier , '.ll'. fic setToEnd; nextPutAll: (FillInTheBlank request: 'nom du L-systeme ?' initialAnswer: 'foo'); nextPutAll: ' {'; nextPut: 10 asCharacter; nextPutAll: 'niveau:'; nextPutAll: niveau asString; nextPut: 10 asCharacter; nextPutAll: 'angle:'; nextPutAll: angle asString; nextPut: 10 asCharacter; nextPutAll: 'axiome:'; nextPutAll: axiome; nextPut: 10 asCharacter; nextPutAll: 'regles:'; nextPut: 10 asCharacter. self ecritRegles: fic. fic nextPut: $}; nextPut: 10 asCharacter.! ! !Lsystem methodsFor: 'lecture-ecriture' stamp: 'hw 3/17/2006 21:53'! autreFichier: nom | menu1 | menu1 := MenuMorph new defaultTarget: self. menu1 addTitle: (nom , '.l ' , '\existe déjà') withCRs; position: Sensor cursorPoint; add: 'écraser ce fichier ?' selector: #sauve1: argument: nom; add: 'nouveau nom ?' action: #sauve; add: 'abandonner ?' action: #yourself. menu1 openInWorld! ! !Lsystem methodsFor: 'lecture-ecriture' stamp: 'hw 3/19/2006 18:01'! chargeEtShow: unLsys | ind | ind := true. reglesDerivation := Dictionary new. unLsys removeFirst. unLsys do: [:ligne | | tmp | tmp := (ligne copyWithout: 32 asCharacter) findTokens: #($: $= ). ind ifTrue: [(tmp at: 1) asSymbol caseOf: { [#axiome] -> [axiome := tmp at: 2]. [#angle] -> [angle := (tmp at: 2) asNumber]. [#niveau] -> [niveau := (tmp at: 2) asInteger]. [#regles] -> [ind := false]}] ifFalse: [self uneOuPlusieurs: (tmp at: 1) asCharacter valeurs: (tmp at: 2 ifAbsent: '')]]. self lanceLsystem! ! !Lsystem methodsFor: 'lecture-ecriture' stamp: 'hw 3/19/2006 22:22'! ecritRegles: fic reglesDerivation keysAndValuesDo: [:c :a | a isString ifTrue: [fic nextPut: c; nextPut: $:; nextPutAll: a; nextPut: 10 asCharacter] ifFalse: [a do: [:r | fic nextPut: c; nextPut: $:; nextPutAll: r; nextPut: 10 asCharacter]]]! ! !Lsystem methodsFor: 'lecture-ecriture' stamp: 'hw 3/19/2006 22:52'! sauve | unFichier | unFichier := FillInTheBlank request: 'nom de fichier' initialAnswer: 'foo'. (FileDirectory default fileExists: unFichier , '.ll') ifTrue: [self ajoute: unFichier] ifFalse: [(FileDirectory default fileExists: unFichier , '.l') ifTrue: [self autreFichier: unFichier] ifFalse: [self sauve1: unFichier]]! ! !Lsystem methodsFor: 'lecture-ecriture' stamp: 'hw 3/19/2006 22:30'! sauve1: unFichier | fic | fic := FileStream forceNewFileNamed: unFichier , '.l'. fic nextPutAll: niveau asString; nextPut: 10 asCharacter; nextPutAll: angle asString; nextPut: 10 asCharacter; nextPutAll: axiome; nextPut: 10 asCharacter. self ecritRegles: fic ! ! !Lsystem methodsFor: 'lecture-ecriture' stamp: 'hw 3/19/2006 11:18'! showMultiples: unFichier | listfic menu1 | listfic := (FileStream fileNamed: unFichier) contents findTokens: $}. menu1 := MenuMorph new defaultTarget: self. menu1 addTitle: 'Ssytèmes\de\Lindenmayer' withCRs; position: Sensor cursorPoint. listfic do: [:fic | | tmp | tmp := fic findTokens: {10 asCharacter}. tmp size < 2 ifFalse: [menu1 add: ((tmp at: 1) copyWithout: ${) selector: #chargeEtShow: argument: tmp]]. menu1 openInWorld! ! !Lsystem methodsFor: 'lecture-ecriture' stamp: 'hw 3/19/2006 17:42'! showUnique: unFichier | fic | fic := (FileStream fileNamed: unFichier) contents. fic := fic findTokens: {10 asCharacter}. "13 asCharacter" niveau := (fic at: 1) asNumber. angle := (fic at: 2) asNumber. axiome := (fic at: 3) copyWithout: 32 asCharacter. reglesDerivation := Dictionary new. 4 to: fic size do: [:i | | tmp | tmp := (fic at: i) copyWithout: 32 asCharacter. self uneOuPlusieurs: (tmp at: 1) valeurs: (tmp copyFrom: 3 to: tmp size)]. self lanceLsystem! ! !Lsystem methodsFor: 'lecture-ecriture' stamp: 'hw 3/20/2006 07:54'! show: unFichier (FileDirectory extensionFor: unFichier) = 'll' ifTrue: [self showMultiples: unFichier] ifFalse: [self showUnique: unFichier]! ! !Lsystem methodsFor: 'lecture-ecriture' stamp: 'hw 3/20/2006 07:53'! uneOuPlusieurs: clef valeurs: valeurs | aux | aux := reglesDerivation at: clef ifAbsent: nil. aux isNil ifTrue: [reglesDerivation at: clef put: valeurs]. ! ! 'From Squeak3.8 of ''5 May 2005'' [latest update: #6665] on 21 March 2008 at 1:07:27 pm'! !Pen methodsFor: 'accessing' stamp: 'hw 3/11/2006 12:01'! penDown "Answer where the receiver is currently located." ^penDown! !