Объединение списка прямоугольников

#java #union #awt

#java #объединение #awt

Вопрос:

У меня есть список прямоугольников AWT. Я хочу вычислить объединение прямоугольников элегантным способом. Вот мой код, который работает, но выглядит не очень элегантно.

   Rectangle union(List<Rectangle> rects) {
    if (rects.isEmpty()) {
      return new Rectangle();
    }
    assert !rects.isEmpty();
    final Iterator<Rectangle> iterator = rects.iterator();
    Rectangle rect = iterator.next();
    while (iterator.hasNext()) {
      rect = rect.union( iterator.next() );
    }
    return rect;
  }
  

Я также попробовал следующее, которое не работает:

   Rectangle union(List<Rectangle> rects) {
    Rectangle result = new Rectangle();
    for (Rectangle rect : rects) {
      result.add( rect );
    }
    return resu<
  }
  

Результат rectangle инициализируется значением (0,0,0,0), поэтому объединение всегда будет содержать начало координат.

Есть ли более элегантный способ сделать это на Java?

Комментарии:

1. Почему вы используете union() в первом коде и add() во втором? Я предполагаю, что именно из-за этой разницы это не работает…

Ответ №1:

Во втором примере вам нужно инициализировать result следующим образом:

 Rectangle result = new Rectangle(-1, -1);
  

Имейте в виду, что это работает только начиная с Java SE 6. В предыдущих версиях поведение в отношении отрицательных ширин и высот не определено. Аналогичный пример с набором точек смотрите в записи Javadoc для Rectangle .

Ответ №2:

Я думаю, что ваше решение неплохое. Вот как я бы это сделал:

 public static void main(String[] args) {
    List<Rectangle> rects = new ArrayList<Rectangle>();
    rects.add(new Rectangle(new Point(1, 1), new Dimension(3, 4)));
    rects.add(new Rectangle(new Point(2, 2), new Dimension(5, 7)));
    Rectangle u = union(rects);
    Rectangle a = add(rects);
    System.out.println(u);
    System.out.println(a);
}

public static Rectangle union(List<Rectangle> rects) {
    if (rects.isEmpty())
        throw new IllegalArgumentException();
    Rectangle unionRectangle = new Rectangle(rects.get(0));
    for (int i = 1; i < rects.size(); i  )
        unionRectangle = unionRectangle.union(rects.get(i));
    return unionRectangle;
}

public static Rectangle add(List<Rectangle> rects) {
    if (rects.isEmpty())
        throw new IllegalArgumentException();
    Rectangle unionRectangle = new Rectangle(rects.get(0));
    for (int i = 1; i < rects.size(); i  )
        unionRectangle.add(rects.get(i));
    return unionRectangle;
}
  

Вывод является

 java.awt.Rectangle[x=1,y=1,width=6,height=8]
java.awt.Rectangle[x=1,y=1,width=6,height=8]
  

Некоторые примечания:

  • Если список rects пуст, я бы выдал исключение, а не возвращал Rectangle

  • оба Rectangle.union и Rectangle.add дают одинаковые результаты (см. Выходные данные)

  • Я бы начал с нового, Rectangle равного первому элементу rects , а затем использовал его для вычисления объединения со следующими (или, что эквивалентно, добавил следующие).

Я надеюсь, что это поможет.

Ответ №3:

Согласно прилагаемому javadoc, ваш add основанный должен работать. В нем говорится:

Добавляет прямоугольник к этому прямоугольнику. Результирующий прямоугольник является объединением двух прямоугольников.

Но это работает только при инициализации прямоугольника с размером, меньшим нуля. Вот рабочее решение для метода 2:

 Rectangle union(List<Rectangle> rects) {
  Rectangle result = new Rectangle(-1,-1);  // dimension less than 0
  for (Rectangle rect : rects) {
    result.add( rect );
  }
  return resu<
}
  

Альтернатива: создайте исходный результат на основе первого элемента списка:

 Rectangle union(List<Rectangle> rects) {
  if (rects == null || rects.isEmpty()) return null;

  Rectangle result = new Rectangle(rects.get(0));  
  for (Rectangle rect : rects) {
    result.add( rect );
  }
  return resu<
}