Проверка пересечения фигур

215
15 марта 2018, 07:28

Есть класс фигуры у которой в поле хранится тип(1 - прямоугольник, 2 - отрезок, 3 - круг), нужно написать метод проверки имеются ли общие точки у любой фигуры с прямоугольником. Фигура хранится 2 координатами: верняя левая и правая нижняя, для окружности первая координата - центр, а вторая коородината значение радиуса.

Вот сам класс:

public class Figure
{
    public Figures Type { get;}
    public int Color { get;}
    public Point Top { get;}
    public Point Bottom { get;}
    public double Square => GetSquare();
    public Figure(int type, int topX, int topY, int bottomX, int bottomY, int color)
    {
        Type = (Figures)type;
        Top = new Point(topX, topY);
        Bottom = new Point(bottomX, bottomY);
        if (type == (int) Figures.Circle)
            Bottom.Y = 0;
        Color = color;
    }
    public bool AreIntersected(Figure other)
    {
        if(other.Type is Figures.Rectangle)
            return Top.X<= other.Bottom.X && other.Top.X <= Bottom.X && Top.Y <= other.Bottom.Y && other.Top.Y <= Bottom.Y;
        else if (other.Type is Figures.Segment)
            return false;
        else
            return false;
        return false;
    }
}

Но этот метод для проверки пересечения прямоугольников не работает. Как проще всего проверять пересечение любой фигуры с заданным прямоугольним?

Answer 1

Для начала, давайте вспомним принципы ООП, и будем кодировать фигуры не числом, а типом фигуры.

Получаем:

public abstract class Figure
{
    public int Color { get; }
    public abstract bool AreIntersected(Figure other);
}

и его конкретные реализации:

public class Rectangle : Figure
{
    public Point TopLeft { get; }
    public Point BottomRight { get; }
    public override bool AreIntersected(Figure other) { ... }
}
public class Circle : Figure
{
    public Point Center { get; }
    public double Radius { get; }
    public override bool AreIntersected(Figure other) { ... }
}
public class Segment : Figure
{
    public Point Start { get; }
    public Point End { get; }
    public override bool AreIntersected(Figure other) { ... }
}

Теперь, как реализовать функцию AreIntersected? Вам придётся перебрать все возможные комбинации фигур. Это достаточно длинная, скучная, неприятная работа. Я вам покажу начало, а дальше вы сами.

public class Rectangle : Figure
{
    public Point TopLeft { get; }
    public Point BottomRight { get; }
    public bool override AreIntersected(Figure other)
    {
        if (other is Rectangle rect)
            return AreIntersected(rect);
        else if (other is Circle circle)
            return AreIntersected(circle);
        else if (other is Segment segment)
            return AreIntersected(segment);
        else
            throw new ArgumentException($"Unknown figure type: {other}")
    }
    // случай двух прямоугольников
    bool AreIntersected(Rectangle other)
    {
        if (this.TopLeft.X > other.BottomRight.X)
            return false;
        if (other.TopLeft.X > this.BottomRight.X)
            return false;
        if (this.TopLeft.Y > other.BottomRight.Y)
            return false;
        if (other.TopLeft.Y > this.BottomRight.Y)
            return false;
        return true;
    }
    // случай двух прямоугольника и отрезка
    bool AreIntersected(Segment other)
    {
        var bottomLeft = new Point(topLeft.X, bottomRight.Y);
        var topRight = new Point(bottomRight.X, topRight.Y);
        var intersection =
            other.GetIntersection(new HalfPlane(new Axis(bottomLeft, TopLeft))
                 .GetIntersection(new HalfPlane(new Axis(BottomRight, bottomLeft))
                 .GetIntersection(new HalfPlane(new Axis(topRight, BottomRight))
                 .GetIntersection(new HalfPlane(new Axis(TopLeft, topRight));
        return !intersection.IsEmpty();
    }
    // случай прямоугольника и круга
    bool AreIntersected(Circle other)
    {
        // реализуйте сами
    }
}

Вам придётся существенно расширить вашу геометрическую библиотеку. Дерзайте!

READ ALSO
Таймаут остановки Win-service

Таймаут остановки Win-service

Для теста мне нужен сервис который будет останавливаться 10-15 мин

202
Выполнить Replace по словарю через LINQ

Выполнить Replace по словарю через LINQ

Допустим, есть Dictionary и текст

180
FileStream и пути длинною &gt;260 символов

FileStream и пути длинною >260 символов

Сначала программа валилась на получении списка фалов через DirectoryGetFiles с PathTooLongException

228
Записать в базу текст из динамически созданных textbox- ов

Записать в базу текст из динамически созданных textbox- ов

Одной кнопкой я создаю динамические массивы, введя их количество во второй текстбокс

214