C# :: Aufgabe #190 :: Lösung #3
3 Lösungen
#190
Zählen von Flächensegmenten
Fortgeschrittener - C#
von hollst
- 09.10.2017 um 09:21 Uhr
1) Gegeben sei ein Quadrat mit der Seitenlänge L (z. B. L = 1).
2) Man wähle zufällig N Punktepaare auf den Seitenlinien des Quadrates, wobei nicht beide Punkte auf der gleichen Seitenlinie liegen dürfen.
3) Die Punkte eines Punktepaares werden nun jeweils durch eine Linie miteinander verbunden. Auf diese Weise wird die Fläche des Quadrates
in eine Vielzahl von Flächensegmenten unterteilt - siehe exemplarisch die zwei Abb. 1 und 2 mit N = 5 bzw. N = 6.
4) Man schreibe ein Programm, das die Anzahl der auf die Weise erzeugten Flächensegmente zurückgibt.
2) Man wähle zufällig N Punktepaare auf den Seitenlinien des Quadrates, wobei nicht beide Punkte auf der gleichen Seitenlinie liegen dürfen.
3) Die Punkte eines Punktepaares werden nun jeweils durch eine Linie miteinander verbunden. Auf diese Weise wird die Fläche des Quadrates
in eine Vielzahl von Flächensegmenten unterteilt - siehe exemplarisch die zwei Abb. 1 und 2 mit N = 5 bzw. N = 6.
4) Man schreibe ein Programm, das die Anzahl der auf die Weise erzeugten Flächensegmente zurückgibt.
#3
von daniel59 (4260 Punkte)
- 23.10.2017 um 08:26 Uhr
MainWindow.xaml.cs
C#-Code
MainWindow.xaml.cs
XML-Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;
namespace WpfFlaechensegmenteZaehlen
{
/// <summary>
/// Interaktionslogik für MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
static readonly Random rnd = new Random();
static readonly MathLine[] testLines1 =
{
new MathLine(new Point(0,0), new Point(size,size)),
new MathLine(new Point(0,size/2), new Point(size,size/2)),
new MathLine(new Point(0,size), new Point(size,0)),
new MathLine(new Point(size/2, 0), new Point(size/2,size))
};
const int size = 500;
private List<MathLine> lines;
public MainWindow()
{
InitializeComponent();
}
private void Draw(int lines)
{
canvas.Children.Clear();
this.lines = new List<MathLine>();
for (int i = 0; i < lines; i++)
{
Point start = new Point(), end = new Point();
int startside = rnd.Next(0, 4);
switch (startside)
{
case 0://links
start = new Point(0, rnd.Next(0, size + 1));
break;
case 1://oben
start = new Point(rnd.Next(0, size + 1), 0);
break;
case 2://rechts
start = new Point(size, rnd.Next(0, size + 1));
break;
case 3://unten
start = new Point(rnd.Next(0, size + 1), size);
break;
}
int endside = startside;
while (endside == startside)
{
endside = rnd.Next(0, 4);
}
switch (endside)
{
case 0://links
end = new Point(0, rnd.Next(0, size + 1));
break;
case 1://oben
end = new Point(rnd.Next(0, size + 1), 0);
break;
case 2://rechts
end = new Point(size, rnd.Next(0, size + 1));
break;
case 3://unten
end = new Point(rnd.Next(0, size + 1), size);
break;
}
MathLine ml = new MathLine(start, end);//testLines1[i];
Line l = new Line()
{
X1 = ml.Start.X,
Y1 = ml.Start.Y,
X2 = ml.End.X,
Y2 = ml.End.Y,
Stroke = Brushes.DarkOrange,
StrokeThickness = 2
};
this.lines.Add(ml);
canvas.Children.Add(l);
}
}
private void CountSegments()
{
var intersections = GetIntersections();
int segments = lines.Count + 1 + intersections.Count();
MessageBox.Show($"{segments} Segmente gefunden");
}
private IEnumerable<Point> GetIntersections()
{
List<MathLine> used = new List<MathLine>();
List<Intersection> result = new List<Intersection>();
foreach (var line in lines)
{
used.Add(line);
var intersections = from l in lines.Except(used)
let i = MathLine.GetIntersection(line, l)
where i != null
let p = i.Point
where p.X >= 0 && p.Y >= 0 && p.X <= size && p.Y <= size
select i;
foreach (var i in intersections)
{
if (!result.Contains(i))
{
result.Add(i);
yield return i;
}
}
}
}
private void buttonDraw_Click(object sender, RoutedEventArgs e)
{
int l;
if (int.TryParse(textBoxLines.Text, out l) && l > 0)
{
Draw(l);
}
}
private void buttoCount_Click(object sender, RoutedEventArgs e)
{
CountSegments();
}
}
public class MathLine
{
public Point Start { get; set; }
public Point End { get; set; }
public double m => (End - Start).Y / (End - Start).X;
public double b => Start.Y - m * Start.X;
public MathLine(Point start, Point end)
{
Start = start;
End = end;
}
public static Intersection GetIntersection(MathLine g, MathLine h)
{
double mg = g.m;
double bg = g.b;
double mh = h.m;
double bh = h.b;
if (mh == mg)
{
return null;//new Point(-1, -1);
}
if (double.IsInfinity(g.m))
{
return new Intersection(new Point(g.Start.X, g.Start.X * h.m + h.b), g, h);
}
else if (double.IsInfinity(h.m))
{
return new Intersection(new Point(h.Start.X, h.Start.X * g.m + g.b), g, h);
}
double x = (bh - bg) / (mg - mh);
double y = mg * x + bg;
return new Intersection(new Point(x, y), g, h);
}
}
public class Intersection
{
public Point Point { get; set; }
public MathLine FirstLine { get; set; }
public MathLine SecondLine { get; set; }
public Intersection(Point p, MathLine l1, MathLine l2)
{
Point = p;
FirstLine = l1;
SecondLine = l2;
}
public override bool Equals(object obj)
{
Intersection i = (Intersection)obj;
return Point == i.Point && (FirstLine == i.FirstLine || FirstLine == i.SecondLine);
}
public override int GetHashCode()
{
int hash = 13;
hash = (hash * 7) + Point.GetHashCode();
hash = (hash * 7) + FirstLine.GetHashCode() + SecondLine.GetHashCode();
return hash;
}
public static implicit operator Point(Intersection v)
{
return v.Point;
}
}
}
MainWindow.xaml.cs
<Window x:Class="WpfFlaechensegmenteZaehlen.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfFlaechensegmenteZaehlen"
mc:Ignorable="d"
Title="MainWindow" Height="587" Width="533" ResizeMode="CanMinimize">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" Grid.Row="0">
<TextBlock Text="Linien" Margin="10,13,0,0"/>
<TextBox x:Name="textBoxLines" Width="50" Text="2" Margin="10,10,0,0" TextAlignment="Center"/>
<Button x:Name="buttonDraw" Content="Zeichnen" Width="80" Margin="10,10,0,0" Click="buttonDraw_Click"/>
<Button x:Name="buttoCount" Content="Zählen" Width="80" Margin="10,10,0,0" Click="buttoCount_Click"/>
</StackPanel>
<Canvas x:Name="canvas" Height="500" Width="500" Background="AliceBlue" Margin="10" Grid.Row="1"/>
</Grid>
</Window>
Kommentare:
Für diese Lösung gibt es noch keinen Kommentar
Seite 1 von 0
1
