[PR]
×
[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。
プログラミング、3DCGとその他いろいろについて
[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。
前回かんたんなL-systemのプログラムを書きました。
しかしその実行結果はわけがわからないものでした。
ABAABABAABAABABAABABA
というふうに、文字だけで、おもしろくありません。
L-systemはやはり描画してこそでしょう。
using System; using System.Collections.Generic; namespace LSystem.Algae { public class Algae { public AlgaeCell Root = new AlgaeCell { IsBig = false }; public List<AlgaeCell> Cells = new List<AlgaeCell>(); public Algae() { Cells.Add(Root); } public void Develop() { foreach (var cell in Cells) { cell.Update(); } var newCells = new List<AlgaeCell>(); foreach (var cell in Cells) { newCells.Add(cell); if (cell.CreatedChildren) { newCells.Add(cell.Child1); newCells.Add(cell.Child2); } } this.Cells = newCells; } public void ForEachTerminal(Action<AlgaeCell> executedInTerminal) { ForEachTerminal(executedInTerminal, Root); } public void ForEachTerminal(Action<AlgaeCell> executedInTerminal, AlgaeCell cell) { if (cell.HasChildren) { ForEachTerminal(executedInTerminal, cell.Child1); ForEachTerminal(executedInTerminal, cell.Child2); } else { executedInTerminal(cell); } } } public class AlgaeCell { public bool IsBig; public AlgaeCell Child1; public AlgaeCell Child2; public bool HasChildren { get { return Child1 != null; } } public bool CreatedChildren { get; private set; } public void Update() { CreatedChildren = false; if (HasChildren) { return; } if (IsBig) { this.Child1 = new AlgaeCell { IsBig = true }; this.Child2 = new AlgaeCell { IsBig = false }; CreatedChildren = true; } else { IsBig = true; } } } }
using System.Windows; using System.Windows.Media; using System.Windows.Shapes; namespace LSystem.Algae { public partial class MainWindow : Window { Algae algae = new Algae(); public MainWindow() { InitializeComponent(); } private void Button_Click(object sender, RoutedEventArgs e) { algae.Develop(); Title = getText(algae.Root); canvas.Children.Clear(); draw(algae.Root, new Vector(300, 100), 0); } private string getText(AlgaeCell cell) { var text = ""; algae.ForEachTerminal((c) => text += c.IsBig ? "A" : "B"); return text; } private void draw(AlgaeCell cell, Vector position, double angle) { var transform = new TransformGroup(); transform.Children.Add( new ScaleTransform(cell.IsBig ? 1 : 0.5, cell.IsBig ? 1 : 0.5) ); transform.Children.Add(new RotateTransform(angle)); var endPosition = position + transform.Value.Transform(new Vector(0, 100)); var line = new Line { X1 = position.X, Y1 = position.Y, X2 = endPosition.X, Y2 = endPosition.Y, Stroke = cell.IsBig ? Brushes.Green : Brushes.LightGreen, StrokeThickness = 5 }; canvas.Children.Add(line); if (cell.HasChildren) { draw( cell.Child1, endPosition, angle + 8 ); draw( cell.Child2, endPosition, angle - 8 ); } } } }
<Window x:Class="LSystem.Algae.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <Grid> <Canvas x:Name="canvas"> </Canvas> <Button Height="24" VerticalAlignment="Bottom" HorizontalAlignment="Right" Width="58" Margin="0,0,10,10" Click="Button_Click">Next</Button> </Grid> </Window>
このプログラムを実行するとこうなります:
おお!!
なんとなく、藻類のように見えなくもないような気がしますね。
ただ、再帰で適当に描いたのとたいして変わりないじゃないかと言われると困りますが。
本来L-systemは文字とその変換だけでプログラムはすむはずなのですが、
ここではイメージというかフレイバーというかそういったものにこだわったソースコードにしてみました。
それにしては成長しきった細胞がいきなり現れたりという変な感じはしますが……