C# :: Aufgabe #190 :: Lösung #3

3 Lösungen Lösungen öffentlich
#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.
#3
1x
vote_ok
von daniel59 (4260 Punkte) - 23.10.2017 um 08:26 Uhr
MainWindow.xaml.cs
Quellcode ausblenden C#-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
Quellcode ausblenden XML-Code
<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

Bitte melden Sie sich an um eine Kommentar zu schreiben.
Kommentar schreiben
1800889

Du scheinst einen AdBlocker zu nutzen. Ich würde mich freuen, wenn du ihn auf dieser Seite deaktivierst und dich davon überzeugst, dass die Werbung hier nicht störend ist.