#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, поэтому я обязательно проверю его и попробую использовать это. Спасибо!