Как найти, где программно пересекаются два линейных сегмента

#java #math #grid #coordinates #line-segment

Вопрос:

Предположим, у вас есть следующая область положительных координат ниже:введите описание изображения здесь

В этой области у нас есть прямоугольник, представляющий окно компьютера. Как вы можете видеть, есть также линейные сегменты, охватывающие регион. Я пытаюсь попытаться решить проблему, в которой я буду обрезать сегменты линий, когда они находятся за пределами окна.

Например, левая верхняя координата окна ниже будет (20,80), его левая нижняя координата будет (20, 20), его правая верхняя координата будет (120, 80), а его правая нижняя координата будет (120, 20). Отрезок линии B имеет начальную координату (55, 65) и конечную координату (90, 90).

Однако, если бы я обрезал сегмент B, у него была бы начальная координата (55,65) и конечная координата (76, 80).

Программно, как бы я мог рассчитать, где сегмент линии пересекает сегмент линии окна? Аналогично, как бы я обнаружил, что они вообще не пересекаются, как сегмент E.

Ответ №1:

Попробуй это.

 public static boolean clipLine(Line2D line, Rectangle2D rect) {   double x1 = line.getX1(), y1 = line.getY1(), x2 = line.getX2(), y2 = line.getY2();  double minX = rect.getMinX(), maxX = rect.getMaxX(), minY = rect.getMinY(), maxY = rect.getMaxY();  int f1 = rect.outcode(x1, y1);  int f2 = rect.outcode(x2, y2);   while ((f1 | f2) != 0) {  if ((f1 amp; f2) != 0) {  return false;  }  double dx = (x2 - x1);  double dy = (y2 - y1);  // update (x1, y1), (x2, y2) and f1 and f2 using intersections  // then recheck  if (f1 != 0) {  // first point is outside, so we update it against one of the  // four sides then continue  if ((f1 amp; Rectangle2D.OUT_LEFT) == Rectangle2D.OUT_LEFT  amp;amp; dx != 0.0) {  y1 = y1   (minX - x1) * dy / dx;  x1 = minX;  }  else if ((f1 amp; Rectangle2D.OUT_RIGHT) == Rectangle2D.OUT_RIGHT  amp;amp; dx != 0.0) {  y1 = y1   (maxX - x1) * dy / dx;  x1 = maxX;  }  else if ((f1 amp; Rectangle2D.OUT_BOTTOM) == Rectangle2D.OUT_BOTTOM  amp;amp; dy != 0.0) {  x1 = x1   (maxY - y1) * dx / dy;  y1 = maxY;  }  else if ((f1 amp; Rectangle2D.OUT_TOP) == Rectangle2D.OUT_TOP  amp;amp; dy != 0.0) {  x1 = x1   (minY - y1) * dx / dy;  y1 = minY;  }  f1 = rect.outcode(x1, y1);  }  else if (f2 != 0) {  // second point is outside, so we update it against one of the  // four sides then continue  if ((f2 amp; Rectangle2D.OUT_LEFT) == Rectangle2D.OUT_LEFT  amp;amp; dx != 0.0) {  y2 = y2   (minX - x2) * dy / dx;  x2 = minX;  }  else if ((f2 amp; Rectangle2D.OUT_RIGHT) == Rectangle2D.OUT_RIGHT  amp;amp; dx != 0.0) {  y2 = y2   (maxX - x2) * dy / dx;  x2 = maxX;  }  else if ((f2 amp; Rectangle2D.OUT_BOTTOM) == Rectangle2D.OUT_BOTTOM  amp;amp; dy != 0.0) {  x2 = x2   (maxY - y2) * dx / dy;  y2 = maxY;  }  else if ((f2 amp; Rectangle2D.OUT_TOP) == Rectangle2D.OUT_TOP  amp;amp; dy != 0.0) {  x2 = x2   (minY - y2) * dx / dy;  y2 = minY;  }  f2 = rect.outcode(x2, y2);  }  }   line.setLine(x1, y1, x2, y2);  return true; // the line is visible - if it wasn't, we'd have  // returned false from within the while loop above  }  

и

 public static void main(String[] args) {  Rectangle2D.Double rectangle = new Rectangle2D.Double(20, 20, 100, 60); // x, y, width, height  Line2D.Double line = new Line2D.Double(55, 65, 90, 90); // x1, y1, x2, y2  boolean result = clipLine(line, rectangle);  System.out.println("result="   result    " x1="   line.x1   " y1="   line.y1    " x2="   line.x2   " y2="   line.y2); }  

выход:

 result=true x1=55.0 y1=65.0 x2=76.0 y2=80.0  

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

1. Это кажется действительно хорошим. Никогда раньше не использовал Rectangle2D, поэтому я обязательно проверю его и попробую использовать это. Спасибо!