|
| MAS ETH ARCH/CAAD - 2004/05 - STUDENT PAGES Master of Advanced Studies in Architecture, Specialization in Computer Aided Architectural Design | 065-0005/6 Supervision: Prof. Dr. Ludger Hovestadt, Philipp Schaerer Chair of CAAD, ETH Zurich Script{{$debug} (* {-------------------------------------------------------------------------------------------------------------} pilz auf- / untersicht sebastian gmelin - nds caad 04/05 - ethz umriss - kreis mit radius "radius" / konstante = 100 umrisskreis wird in x (unterteilungen) gleichgroße "kuchenstücke" geteilt diese kuchenstücke werden zufällig um den kreismittelpunkt gedreht, so daß sie zueinander den winkel "zerfallswinkel_min" nicht unter- und "zerfallswinkel_max" nicht überschreiten die schnittpunkte dieser geraden mit dem kreis werden zufällig radial verschoben, maximal um +/-"kreisverschiebung" / 100 * radius umrisskreis die entstehenden verbindungsstrecken zwischen den umrisspunkten werden durch kreissegmente konvex ausgerundet. "kruemmung" gibt den maximalen radius der kreissegmente prozentual zur streckenlänge an. die einzelnen krümmungssegmente wiederum werden durch kreissegmente weich ausgerundet. die weichheit der kontur wird durch "ausrundung" in prozent angegeben: 100 sehr weich bis 0 hart. "zerfall_prozent" gibt an, wie viele der umrisssegmente eingerissen sind. die stärke der beschädigung wird über "risstiefe" definiert (prozentual zum kreisradius) "rissvarianz" gibt die zufälligkeit der risstiefe an: 0 - alle risse haben die länge "risstiefe" 100 - die risstiefe variiert bis maximal "risstiefe" die risse werden an ihrem scheitelpunkt nach folgenden kriterien ausgerundet: "rissausrundung" : 0: sehr nahe am scheitelpunkt, 100: nah am pilzrand "rissausrundungsvarianz" : 0: kein zufall, 100: sehr zufällig "ausrundungsverhaeltnis": 0: alle rund, 100: keine ausrundung {--------------------------------------------------------------------------------------------------------------}*) type ausrundungen = structure radius : real; mittelpunkt : vector; startwinkel, endwinkel : real; aussen : boolean; end; einriss = structure scheitelpunkt : vector; scheitelmittelpunkt : vector; scheitelradius : real; risstiefe : real; scheitelstartwinkel : real; scheitelendwinkel : real; scheitelstartpunkt : vector; scheitelendpunkt : vector; radiuslinks : real; radiusrechts : real; startwinkellinks : real; startwinkelrechts : real; endwinkellinks : real; endwinkelrechts : real; mittelpunktlinks : point; mittelpunktrechts : point; endpunktlinks : point; endpunktrechts : point; end; var i, k, l, m : integer; {zählervariablen} unterteilungswinkel : dynarray[] of real; hilfsobjekte : dynarray[] of handle; hilfsobjektzaehler : longint; kreispunkte : dynarray[] of vector; kruemmungen : dynarray[,] of ausrundungen; kruemmungspunkte : dynarray[] of vector; umrissobjekte : dynarray[] of handle; umrissobjektezaehler : longint; einriss_segmente : dynarray[] of boolean; einrisse : dynarray[] of einriss; umrissobjekt : handle; {benutzervariablen} radius : real; {ca. radius des pilzes in eingestellten einheiten} x, y : real; {mittelpunkt} unterteilungen : integer; {summe einschnürungen und zerfall} zerfall : integer; {beschädigungen an den einschnürungen} zerfallswinkel_min : real; zerfallswinkel_max : real; {einschränkungen} kreisverschiebung : real; {radiale punktverschiebung, prozentual zum radius} kruemmung : real; {krümmung der einzelsegmente, prozentual} ausrundung : integer; {radius der ausrundungen prozentual zu krümmungsradien} risstiefe : integer; {maximale risstiefe prozentual zum gesamtradius} rissvarianz : integer; {prozentuale zufallsgewichtung: 100 sehr zufällig 0 kein zufall} rissausrundung : integer; {mittelpunkt der ausrundung prozentual zum radius} rissausrundungsvarianz : integer; {prozentuale zufallsgewichtung: 100 sehr zufällig 0 kein zufall} ausrundungsverhaeltnis : integer; {verhältnis prozentual ausgerundet (0) oder scharfe scheitelkante (100)} {--------------------------------------------------------------------------------------------------------------} procedure hilfskonstruktion; begin nameclass('hilfskonstruktion'); penfore(256*180, 256*180, 256*180); pensize(1); end; {--------------------------------------------------------------------------------------------------------------} procedure konstruktion; begin nameclass('konstruktion'); penfore(0, 0, 0); pensize(40); end; {--------------------------------------------------------------------------------------------------------------} procedure objektzuhilfsliste; begin hilfsobjektzaehler := hilfsobjektzaehler + 1; allocate hilfsobjekte[1..hilfsobjektzaehler]; hilfsobjekte[hilfsobjektzaehler] := lnewobj; end; {--------------------------------------------------------------------------------------------------------------} procedure objektzuumrissliste(_lobj : handle); begin umrissobjektezaehler := umrissobjektezaehler + 1; allocate umrissobjekte[1..umrissobjektezaehler]; umrissobjekte[umrissobjektezaehler] := _lobj; end; {--------------------------------------------------------------------------------------------------------------} procedure aussenkreis (_x, _y, _radius : real); begin hilfskonstruktion; oval(_x - _radius, _y - _radius, _x + _radius, _y + _radius); objektzuhilfsliste; end; {--------------------------------------------------------------------------------------------------------------} procedure unterteilen (_unterteilungen : integer); var a : integer; begin for a := 1 to _unterteilungen do begin unterteilungswinkel[a] := a * (360 / _unterteilungen); end; end; {--------------------------------------------------------------------------------------------------------------} procedure zerfall_zufall (_x, _y, _radius : real; _unterteilungen : integer); var a, b : integer; _min, _max : boolean; _durchlauf : longint; _rechts, _links : real; _abweichung : real; _winkel : real; _ok : boolean; _notbremse : integer; begin _min := false; _max := false; _durchlauf := 0; repeat for a := 1 to _unterteilungen do begin {nachbarn im array definieren} _links := a-1; _rechts:= a+1; case a of 1 : _links := _unterteilungen; _unterteilungen : _rechts := 1; end; _winkel := unterteilungswinkel[_rechts] - unterteilungswinkel[_links]; if _winkel < 0 then _winkel := _winkel + 360; _ok := false; _notbremse := 0; repeat _abweichung := random * _winkel; if _abweichung >= zerfallswinkel_min then begin if _abweichung <= zerfallswinkel_max then begin<br> if _winkel - _abweichung >= zerfallswinkel_min then begin if _winkel - _abweichung <= zerfallswinkel_max then begin<br> _ok := true; end; end; end; end; _notbremse := _notbremse + 1; until ((_ok = true) or (_notbremse > 50)); if _notbremse <= 50 then unterteilungswinkel[a] := unterteilungswinkel[_links] + _abweichung;<br> if unterteilungswinkel[a] < 0 then unterteilungswinkel[a] := unterteilungswinkel[a] + 360; if unterteilungswinkel[a] > 360 then unterteilungswinkel[a] := unterteilungswinkel[a] - 360; if _abweichung <= zerfallswinkel_min * 1.15 then _min := true;<br> if _abweichung >= zerfallswinkel_max * 0.85 then _max := true; end; _durchlauf := _durchlauf + 1; until (((_min=true) and (_max=true)) or (_durchlauf > 100)); {array zur sicherheit sortieren} for a := 1 to _unterteilungen do begin if unterteilungswinkel[a] < 0 then unterteilungswinkel[a] := unterteilungswinkel[a] + 360; if unterteilungswinkel[a] > 360 then unterteilungswinkel[a] := unterteilungswinkel[a] - 360; end; sortarray(unterteilungswinkel, _unterteilungen, 0); for a := 1 to _unterteilungen do begin kreispunkte[a].x := sin(deg2rad(unterteilungswinkel[a])) * _radius; kreispunkte[a].y := cos(deg2rad(unterteilungswinkel[a])) * _radius; hilfskonstruktion; moveto (_x, _y); line(kreispunkte[a].x, kreispunkte[a].y); objektzuhilfsliste; end; {einrisse definieren} for a := 1 to _unterteilungen do begin einriss_segmente[a] := false; end; for a := 1 to zerfall do begin repeat b := trunc(1 + (random * (_unterteilungen-1))); _links := b-1; _rechts:= b+1; case b of 1 : _links := _unterteilungen; _unterteilungen : _rechts := 1; end; until ((einriss_segmente[b] = false) and (einriss_segmente[_links] = false) and (einriss_segmente[_rechts] = false)); {until einriss_segmente[b] = false;} einriss_segmente[b] := true; end; end; {--------------------------------------------------------------------------------------------------------------} procedure radialverschiebung (_x, _y, _kreisverschiebung, _kruemmung, _radius : real; _unterteilungen : integer); var a, _links, _rechts : integer; _hilfsvektor : vector; _winkel_rechts, _winkel_links : real; _winkel : real; begin {kreispunkte zufällig radial verschieben} for a := 1 to _unterteilungen do begin _links := a-1; _rechts:= a+1; if _links = 0 then _links := _unterteilungen; if _rechts > _unterteilungen then _rechts := 1; _winkel_rechts := angbvec(kreispunkte[_rechts], kreispunkte[a]); _winkel_links := angbvec(kreispunkte[a], kreispunkte[_links]); if _winkel_rechts > _winkel_links then begin _winkel := _winkel_links; end else begin _winkel := _winkel_rechts; end; _hilfsvektor.x := kreispunkte[a].x - _x; _hilfsvektor.y := kreispunkte[a].y - _y; _hilfsvektor := (unitvec(_hilfsvektor)) * (_radius - 10 * _winkel * ((_kreisverschiebung * (random - 0.5))) / 100); kreispunkte[a] := _hilfsvektor; end; {hilfs- verbindungslinien zeichnen} moveto (kreispunkte[_unterteilungen].x, kreispunkte[_unterteilungen].y); hilfskonstruktion; for a := 1 to _unterteilungen do begin lineto (kreispunkte[a].x, kreispunkte[a].y); moveto (kreispunkte[a].x, kreispunkte[a].y); objektzuhilfsliste; end; {kruemmung über 3. punkt definieren} for a := 1 to _unterteilungen do begin _links := a-1; if _links = 0 then _links := _unterteilungen; _hilfsvektor := kreispunkte[a] + ((kreispunkte[_links] - kreispunkte[a]) * 0.5); moveto (_hilfsvektor.x, _hilfsvektor.y); _hilfsvektor := (kreispunkte[_links] - kreispunkte[a]) * 0.5; _hilfsvektor := perp(_hilfsvektor); _hilfsvektor := _hilfsvektor * (_kruemmung * (random/2 + 0.5)) / 100; _hilfsvektor := _hilfsvektor + kreispunkte[a] + ((kreispunkte[_links] - kreispunkte[a]) * 0.5); lineto (_hilfsvektor.x, _hilfsvektor.y); kruemmungspunkte[a] := _hilfsvektor; objektzuhilfsliste; end; end; {--------------------------------------------------------------------------------------------------------------} procedure kruemmen (_x, _y, _unterteilungen : integer); var a, _links : integer; _radius, _laenge, _hoehe : real; _mittelpunkt : vector; _senkrechte : vector; _startwinkel, _endwinkel : real; begin for a := 1 to _unterteilungen do begin _links := a-1; if _links = 0 then _links := _unterteilungen; _laenge := norm(kreispunkte[a] - kreispunkte[_links]); _hoehe := norm(kruemmungspunkte[a] - 0.5 * (kreispunkte[_links] - kreispunkte[a]) - kreispunkte[a]); _radius := ((sqr(_laenge)) / (8*_hoehe)) + 0.5 * _hoehe; _senkrechte := _radius * unitvec(kruemmungspunkte[a] - 0.5 * (kreispunkte[_links] - kreispunkte[a]) - kreispunkte[a]); _mittelpunkt := kruemmungspunkte[a] - _senkrechte; _startwinkel := vec2ang(kreispunkte[a] - _mittelpunkt); _endwinkel := angbvec(kreispunkte[_links] - _mittelpunkt, kreispunkte[a] - _mittelpunkt); kruemmungen[a,1].radius := _radius; kruemmungen[_links,2].radius := _radius; kruemmungen[a,1].mittelpunkt := _mittelpunkt; kruemmungen[_links,2].mittelpunkt := _mittelpunkt; kruemmungen[a,1].startwinkel := _startwinkel; kruemmungen[_links,2].startwinkel := _startwinkel; kruemmungen[a,1].endwinkel := _endwinkel; kruemmungen[_links,2].endwinkel := _endwinkel; hilfskonstruktion; oval(_mittelpunkt.x - _radius, _mittelpunkt.y - _radius, _mittelpunkt.x + _radius, _mittelpunkt.y + _radius); objektzuhilfsliste; end; end; {--------------------------------------------------------------------------------------------------------------} procedure ausrunden (_x, _y, _unterteilungen : integer); var a, b, _links, _rechts : integer; _rechts_rechts : integer; _delta_radius : real; _schnitt : integer; _schnittpunkte : array[1..4] of point; _kreis : array[1..2, 1..2] of point; _abstand1, _abstand2 : real; _hilfsvektor : vector; _winkel_vec_1, _winkel_vec_2 : vector; _winkel : real; begin for a := 1 to _unterteilungen do begin _links := a-1; _rechts := a+1; if _links = 0 then _links := _unterteilungen; if _rechts > _unterteilungen then _rechts := 1; _rechts_rechts := _rechts +1; if _rechts_rechts > _unterteilungen then _rechts_rechts := 1; if kruemmungen[a,1].radius >= kruemmungen[a,2].radius then begin _delta_radius := kruemmungen[a,2].radius; end else begin _delta_radius := kruemmungen[a,1].radius; end; _delta_radius := _delta_radius * (100 + ausrundung / 2) / 100 - _delta_radius; {if ((einriss_segmente[a] = true) or (einriss_segmente[_rechts] = true)) then _delta_radius := 0;} {ausrundung innen oder außen?} {vergleich der winkeldifferenzen der krümmungsbögen} kruemmungen[a,3].aussen := true; _winkel_vec_1 := kreispunkte[a] - kruemmungen[a,1].mittelpunkt; _winkel_vec_2 := kreispunkte[a] - kruemmungen[a,2].mittelpunkt; _winkel := vec2ang(_winkel_vec_1) - vec2ang(_winkel_vec_2); if _winkel < 360 then _winkel := _winkel + 360; if _winkel > 360 then _winkel := _winkel - 360; if _winkel < 180 then begin _delta_radius := _delta_radius * -1; kruemmungen[a,3].aussen := false; end; kruemmungen[a,1].radius := kruemmungen[a,1].radius + _delta_radius; kruemmungen[a,2].radius := kruemmungen[a,2].radius + _delta_radius; kruemmungen[a,3].radius := _delta_radius; _kreis[1,1].x := kruemmungen[a,1].mittelpunkt.x - kruemmungen[a,1].radius; _kreis[1,1].y := kruemmungen[a,1].mittelpunkt.y - kruemmungen[a,1].radius; _kreis[1,2].x := kruemmungen[a,1].mittelpunkt.x + kruemmungen[a,1].radius; _kreis[1,2].y := kruemmungen[a,1].mittelpunkt.y + kruemmungen[a,1].radius; _kreis[2,1].x := kruemmungen[a,2].mittelpunkt.x - kruemmungen[a,2].radius; _kreis[2,1].y := kruemmungen[a,2].mittelpunkt.y - kruemmungen[a,2].radius; _kreis[2,2].x := kruemmungen[a,2].mittelpunkt.x + kruemmungen[a,2].radius; _kreis[2,2].y := kruemmungen[a,2].mittelpunkt.y + kruemmungen[a,2].radius; _schnitt := ellipseellipseintersect(_kreis[1,1], _kreis[1,2], _kreis[2,1], _kreis[2,2], _schnittpunkte[1], _schnittpunkte[2], _schnittpunkte[3], _schnittpunkte[4]); if _schnitt > 1 then begin kruemmungen[a,3].mittelpunkt.x := _schnittpunkte[1].x; kruemmungen[a,3].mittelpunkt.y := _schnittpunkte[1].y; _abstand1 := norm(kruemmungen[a,3].mittelpunkt - kreispunkte[a]); _hilfsvektor.x := _schnittpunkte[2].x; _hilfsvektor.y := _schnittpunkte[2].y; _abstand2 := norm(_hilfsvektor - kreispunkte[a]); if _abstand2 < _abstand1 then kruemmungen[a,3].mittelpunkt := _hilfsvektor; hilfskonstruktion; oval(_kreis[1,1].x, _kreis[1,1].y, _kreis[1,2].x, _kreis[1,2].y); objektzuhilfsliste; oval(_kreis[2,1].x, _kreis[2,1].y, _kreis[2,2].x, _kreis[2,2].y); objektzuhilfsliste; if kruemmungen[a,3].radius > 0 then begin oval(kruemmungen[a,3].mittelpunkt.x - kruemmungen[a,3].radius, kruemmungen[a,3].mittelpunkt.y - kruemmungen[a,3].radius, kruemmungen[a,3].mittelpunkt.x + kruemmungen[a,3].radius, kruemmungen[a,3].mittelpunkt.y + kruemmungen[a,3].radius); objektzuhilfsliste; end; moveto (kruemmungen[a,1].mittelpunkt.x, kruemmungen[a,1].mittelpunkt.y); lineto (kruemmungen[a,3].mittelpunkt.x, kruemmungen[a,3].mittelpunkt.y); objektzuhilfsliste; moveto (kruemmungen[a,2].mittelpunkt.x, kruemmungen[a,2].mittelpunkt.y); lineto (kruemmungen[a,3].mittelpunkt.x, kruemmungen[a,3].mittelpunkt.y); objektzuhilfsliste; end; kruemmungen[a,1].radius := kruemmungen[a,1].radius - _delta_radius; kruemmungen[a,2].radius := kruemmungen[a,2].radius - _delta_radius; end; end; {--------------------------------------------------------------------------------------------------------------} procedure umriss (_x, _y, _unterteilungen : integer); var a, b, _links, _rechts : integer; begin for a := 1 to _unterteilungen do begin _links := a-1; _rechts := a+1; if _links = 0 then _links := _unterteilungen; if _rechts > _unterteilungen then _rechts := 1; kruemmungen[a,1].startwinkel := vec2ang(kruemmungen[a,3].mittelpunkt - kruemmungen[a,1].mittelpunkt); kruemmungen[a,1].endwinkel := angbvec(kruemmungen[_links,3].mittelpunkt - kruemmungen[a,1].mittelpunkt, kruemmungen[a,3].mittelpunkt - kruemmungen[a,1].mittelpunkt); kruemmungen[a,3].startwinkel := vec2ang(kruemmungen[a,3].mittelpunkt - kruemmungen[a,1].mittelpunkt) + 180; kruemmungen[a,3].endwinkel := angbvec(kruemmungen[a,3].mittelpunkt - kruemmungen[a,2].mittelpunkt, kruemmungen[a,3].mittelpunkt - kruemmungen[a,1].mittelpunkt); if kruemmungen[a,3].aussen = false then kruemmungen[a,3].startwinkel := kruemmungen[a,3].startwinkel + 180 - kruemmungen[a,3].endwinkel; if kruemmungen[a,3].radius < 0 then kruemmungen[a,3].radius := kruemmungen[a,3].radius * -1; konstruktion; if einriss_segmente[a] = false then begin arcbycenter(kruemmungen[a,1].mittelpunkt.x, kruemmungen[a,1].mittelpunkt.y, kruemmungen[a,1].radius, kruemmungen[a,1].startwinkel, kruemmungen[a,1].endwinkel); objektzuumrissliste(lobject); if ((einriss_segmente[_rechts] = false) and (kruemmungen[a,3].radius > 0)) then begin arcbycenter(kruemmungen[a,3].mittelpunkt.x, kruemmungen[a,3].mittelpunkt.y, kruemmungen[a,3].radius, kruemmungen[a,3].startwinkel, kruemmungen[a,3].endwinkel); objektzuumrissliste(lobject); end; end; end; end; {--------------------------------------------------------------------------------------------------------------} procedure einreissen (_x, _y, _unterteilungen, _zerfall : integer); var a, b, _links, _rechts : integer; _winkelhalbierende : vector; begin b := 0; for a := 1 to _unterteilungen do begin _links := a-1; _rechts := a+1; if _links = 0 then _links := _unterteilungen; if _rechts > _unterteilungen then _rechts := 1; if einriss_segmente[a] = true then begin b := b + 1; hilfskonstruktion; moveto(kreispunkte[a].x, kreispunkte[a].y); lineto(_x,_y); objektzuhilfsliste; moveto(kreispunkte[_links].x, kreispunkte[_links].y); lineto(_x,_y); objektzuhilfsliste; {winkelhalbierende} _winkelhalbierende := unitvec(kreispunkte[a] + random * kreispunkte[_links]); einrisse[b].scheitelpunkt := _winkelhalbierende * radius * ((100 - risstiefe) / 100 + (random * rissvarianz / 100) * (risstiefe - 5) / 100); einrisse[b].risstiefe := norm(kreispunkte[a] + 0.5 * (kreispunkte[_links] - kreispunkte[a]) - einrisse[b].scheitelpunkt); hilfskonstruktion; moveto(einrisse[b].scheitelpunkt.x, einrisse[b].scheitelpunkt.y); lineto(kreispunkte[a].x, kreispunkte[a].y); objektzuumrissliste(lnewobj); moveto(einrisse[b].scheitelpunkt.x, einrisse[b].scheitelpunkt.y); lineto(kreispunkte[_links].x, kreispunkte[_links].y); objektzuumrissliste(lnewobj); end; end; end; {--------------------------------------------------------------------------------------------------------------} {--------------------------------------------------------------------------------------------------------------} begin {benutzervariablen} radius := 100; {eingabe in eingestellten einheiten} unterteilungen := 30; {eingabe von 1 bis 100} zerfall := 5; {prozentualer anteil von einrissen} zerfallswinkel_max := 50; {größter radialer unterteilungswinkel in grad} zerfallswinkel_min := 2; {kleinster radialer unterteilungswinkel in grad} kreisverschiebung := 10; {radiale verschiebung der unterteilungspunkte, prozentual zu winkel} kruemmung := 60; {prozentuale kruemmung (100% = 0.5 laenge der verbindungsgeraden zweier punkte)} ausrundung := 80; {ausrundung prozentual zu krümmungsradien} risstiefe := 80; {maximale risstiefe prozentual zum gesamtradius} rissvarianz := 70; {prozentuale zufallsgewichtung: 100 sehr zufällig 0 kein zufall} rissausrundung := 40; {mittelpunkt der ausrundung prozentual zum radius} rissausrundungsvarianz := 100; {prozentuale zufallsgewichtung: 100 sehr zufällig 0 kein zufall} ausrundungsverhaeltnis := 50; {verhältnis prozentual ausgerundet (0) oder scharfe scheitelkante (100)} {variablen} if unterteilungen > 100 then unterteilungen := 100; if zerfall > unterteilungen / 2 then zerfall := unterteilungen / 2; if zerfallswinkel_min * unterteilungen > 360 then zerfallswinkel_min := 360 / unterteilungen; if zerfallswinkel_max * unterteilungen < 360 then zerfallswinkel_max := 360 / unterteilungen; if risstiefe < 5 then risstiefe := 5; allocate unterteilungswinkel[1..unterteilungen+1]; allocate kreispunkte[1..unterteilungen+1]; allocate kruemmungspunkte[1..unterteilungen+1]; allocate kruemmungen[1..unterteilungen+1,1..3]; allocate einriss_segmente[1..unterteilungen+1]; allocate einrisse[1..zerfall+1]; hilfsobjektzaehler := 0; umrissobjektezaehler := 0; x := 0; y := 0; fillpat (0); aussenkreis (x, y, radius); unterteilen (unterteilungen); zerfall_zufall (x, y, radius, unterteilungen); radialverschiebung (x, y, kreisverschiebung, kruemmung, radius, unterteilungen); kruemmen (x, y, unterteilungen); ausrunden (x, y, unterteilungen); umriss (x, y, unterteilungen); einreissen (x, y, unterteilungen, zerfall); dselectall; nameclass ('konstruktion'); setclassoptions(1) ; selectall; umrissobjekt := combineintosurface(0,0); setfpat (umrissobjekt,1); setfillfore (umrissobjekt, 255*256, 255*256,0) end; {--------------------------------------------------------------------------------------------------------------} {--------------------------------------------------------------------------------------------------------------} run(pilz);
|
This website has been archived and is no longer maintained.