2016-02-26 3 views
-1

Я хочу, чтобы линия была нарисована до края экрана, когда я предоставляю ему 2 точки и угол (для направления). Например, если первая точка мыши равна 4,4, а следующая точка мыши - 6,6, то из тех точек, которые вы знаете, что линия имеет северо-восточное направление, тогда строка должна быть отложена с 4,4 до конца экран и прохождение через 6,6. Примечание: после того, как мышь дойдет до 6,6, линия должна быть нарисована до края экрана, пока мышь все еще находится на уровне 6,6.Как нарисовать линию с направлением и фиксированной длиной

enter image description here

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

+0

Вы можете разместить код? вы что-то пробовали? где вы застряли? – elyashiv

+0

Почему вам нужны две точки и угол? вам нужна точка и угол, или две точки, чтобы нарисовать линию ... – elyashiv

+0

Итак, в основном то, что у вас есть, - это проблема «что такое точка на круге для заданного угла». Начните с понимания того, как решить эту проблему. Когда вы знаете, как это сделать, создайте виртуальный круг, радиус которого равен «Math.max (width/2, height/2)», вычислите точку на круге для данного ангела и нарисуйте линию к ней. – MadProgrammer

ответ

3

Вы должны разорвать вас проблемы вниз ...

Во-первых, вы должны быть в состоянии вычислить угол между двумя точками

double angle = Math.atan2(toY - fromY, toY - fromY); 

вау, это было своего рода легко (спасибо Internet)

Далее, мы должны уметь вычислить точку на радиусе круга (хорошо, это может показаться странным, но это самое простое решение, которое я мог бы придумать ... и я знаю, что смогу его решить, спасибо вы Internet)

toX = (int) (Math.round(fromX + (radius * Math.cos(angle)))); 
toY = (int) (Math.round(fromY + (radius * Math.sin(angle)))); 

Что мы собираемся делать, создайте круг настолько большой, чтобы он расширялся за пределы видимых границ рамки и выводил нашу линию! Легко!

Follow the dots

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.Point; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 

public class Test { 

    public static void main(String[] args) { 
     new Test(); 
    } 

    public Test() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
        ex.printStackTrace(); 
       } 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.add(new TestPane()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class TestPane extends JPanel { 

     private Point from; 
     private Point clickTo; 
     private Point to; 

     public TestPane() { 
      addMouseListener(new MouseAdapter() { 
       @Override 
       public void mouseClicked(MouseEvent e) { 
        if (to != null) { 
         to = null; 
         clickTo = null; 
         from = null; 
        } 
        if (from != null) { 
         to = e.getPoint(); 
         clickTo = new Point(to); 
         double angle = Math.atan2(to.y - from.y, to.x - from.x); 
         int radius = Math.max(getWidth(), getHeight()) * 2; 

         to.x = (int) (Math.round(from.x + (radius * Math.cos(angle)))); 
         to.y = (int) (Math.round(from.y + (radius * Math.sin(angle)))); 
        } else { 
         from = e.getPoint(); 
        } 
        repaint(); 
       } 
      }); 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(200, 200); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      Graphics2D g2d = (Graphics2D) g.create(); 
      if (from != null) { 
       g2d.setColor(Color.RED); 
       g2d.fillOval(from.x - 4, from.y - 4, 8, 8); 

       if (to != null) { 
        g2d.setColor(Color.GREEN); 
        g2d.fillOval(clickTo.x - 4, clickTo.y - 4, 8, 8); 

        g2d.setColor(Color.BLUE); 
        g2d.drawLine(from.x, from.y, to.x, to.y); 
       } 
      } 
      g2d.dispose(); 
     } 

    } 

} 

С центральной точкой анкерного ....

и MouseMotionListener поддержка

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.Point; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.awt.event.MouseMotionAdapter; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 

public class Test { 

    public static void main(String[] args) { 
     new Test(); 
    } 

    public Test() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
        ex.printStackTrace(); 
       } 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.add(new TestPane()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class TestPane extends JPanel { 

     private Point from; 
     private Point clickTo; 
     private Point to; 

     public TestPane() { 
      addMouseMotionListener(new MouseMotionAdapter() { 
       @Override 
       public void mouseMoved(MouseEvent e) { 
        from = new Point(getWidth()/2, getHeight()/2); 
        to = e.getPoint(); 
        clickTo = new Point(to); 
        double angle = Math.atan2(to.y - from.y, to.x - from.x); 
        int radius = Math.max(getWidth(), getHeight()) * 2; 

        to.x = (int) (Math.round(from.x + (radius * Math.cos(angle)))); 
        to.y = (int) (Math.round(from.y + (radius * Math.sin(angle)))); 
        repaint(); 
       } 

      }); 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(200, 200); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      Graphics2D g2d = (Graphics2D) g.create(); 
      if (from != null) { 
       g2d.setColor(Color.RED); 
       g2d.fillOval(from.x - 4, from.y - 4, 8, 8); 

       if (to != null) { 
        g2d.setColor(Color.GREEN); 
        g2d.fillOval(clickTo.x - 4, clickTo.y - 4, 8, 8); 

        g2d.setColor(Color.BLUE); 
        g2d.drawLine(from.x, from.y, to.x, to.y); 
       } 
      } 
      g2d.dispose(); 
     } 

    } 

} 

Еще одна маленькая вещь, я нужна строка, чтобы иметь гибкую длину , я имею в виду, что он должен находиться внутри экрана, и поскольку это прямоугольник, тогда ширина и высота будут отличаются, а фиксированная длина будет создавать проблемы, потому что она будет длинной в некоторых частях и короткой в ​​других, любая идея?

Таким образом, вы должны знать, где сталкивается линия с границами прямоугольника, которая в основном сводится к обнаружению линии столкновения (потому что прямоугольник всего четыре линии)

Так, Internet to the rescue

Я принял идею немного дальше и сделал метод, который принял Rectangle и Line2D, и возвратил либо Point2D, где встречается точка столкновения, либо null, если не произошло столкновение (в данном случае нам должно быть 99.9% гарантировали столкновение)

Shortended

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.Point; 
import java.awt.Rectangle; 
import java.awt.event.MouseEvent; 
import java.awt.event.MouseMotionAdapter; 
import java.awt.geom.Ellipse2D; 
import java.awt.geom.Line2D; 
import java.awt.geom.Point2D; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 

public class Test { 

    public static void main(String[] args) { 
     new Test(); 
    } 

    public Test() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
        ex.printStackTrace(); 
       } 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.add(new TestPane()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class TestPane extends JPanel { 

     private Point from; 
     private Point clickTo; 
     private Point to; 

     public TestPane() { 
      addMouseMotionListener(new MouseMotionAdapter() { 
       @Override 
       public void mouseMoved(MouseEvent e) { 
        from = new Point(getWidth()/2, getHeight()/2); 
        to = e.getPoint(); 
        clickTo = new Point(to); 
        double angle = Math.atan2(to.y - from.y, to.x - from.x); 
        int radius = Math.max(getWidth(), getHeight()) * 2; 

        to.x = (int) (Math.round(from.x + (radius * Math.cos(angle)))); 
        to.y = (int) (Math.round(from.y + (radius * Math.sin(angle)))); 
        repaint(); 
       } 

      }); 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(200, 200); 
     } 

     public Point2D getIntersectionPoint(Line2D line1, Line2D line2) { 
      if (!line1.intersectsLine(line2)) { 
       return null; 
      } 
      double px = line1.getX1(), 
        py = line1.getY1(), 
        rx = line1.getX2() - px, 
        ry = line1.getY2() - py; 
      double qx = line2.getX1(), 
        qy = line2.getY1(), 
        sx = line2.getX2() - qx, 
        sy = line2.getY2() - qy; 

      double det = sx * ry - sy * rx; 
      if (det == 0) { 
       return null; 
      } else { 
       double z = (sx * (qy - py) + sy * (px - qx))/det; 
       if (z == 0 || z == 1) { 
        return null; // intersection at end point! 
       } 
       return new Point2D.Float(
         (float) (px + z * rx), (float) (py + z * ry)); 
      } 
     } // end intersection line-line 

     public Point2D getIntersectionPoint(Line2D line, Rectangle bounds) { 
      Point2D top = getIntersectionPoint(line, new Line2D.Double(bounds.x, bounds.y, bounds.x + bounds.width, bounds.y)); 
      Point2D bottom = getIntersectionPoint(line, new Line2D.Double(bounds.x, bounds.y + bounds.height, bounds.x + bounds.width, bounds.y + bounds.height)); 
      Point2D left = getIntersectionPoint(line, new Line2D.Double(bounds.x, bounds.y, bounds.x, bounds.y + bounds.height)); 
      Point2D right = getIntersectionPoint(line, new Line2D.Double(bounds.x + bounds.width, bounds.y, bounds.x + bounds.width, bounds.y + bounds.height)); 

      return top != null ? top 
        : bottom != null ? bottom 
        : left != null ? left 
        : right != null ? right 
        : null; 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 

      Graphics2D g2d = (Graphics2D) g.create(); 
      Rectangle bounds = new Rectangle(50, 50, getWidth() - 100, getHeight() - 100); 
      g2d.draw(bounds); 

      if (from != null) { 
       g2d.setColor(Color.RED); 
       g2d.fillOval(from.x - 4, from.y - 4, 8, 8); 

       if (to != null) { 
        g2d.setColor(Color.GREEN); 
        g2d.fillOval(clickTo.x - 4, clickTo.y - 4, 8, 8); 

        Line2D line = new Line2D.Double(from, to); 
        g2d.setColor(Color.BLUE); 
        g2d.draw(line); 

        Point2D intersectPoint = getIntersectionPoint(line, bounds); 

        g2d.setColor(Color.MAGENTA); 
        g2d.fill(new Ellipse2D.Double(intersectPoint.getX() - 4, intersectPoint.getY() - 4, 8, 8)); 

        g2d.draw(new Line2D.Double(from, intersectPoint)); 
       } 
      } 
      g2d.dispose(); 
     } 

    } 

} 

Так, знаю, у вас есть проекция линии за видимые границами компоненты (который будет полезной в вашем другом вопросе) и знать, где линию интересует внутренние границы

+0

Спасибо большое, и мне жаль, но когда математика встречается с java, я теряюсь. – Sherif

+0

Один маленький вопрос. использовал его в моем коде, и это сработало, но проблема в том, что угол в прыжке, поэтому линия не точна, также я получаю точки мыши от перемещенной мыши. – Sherif

+0

как я могу заставить угол содержать больше цифр, тем самым я имею в виду не прыгать , А не 90, 45, 270. Но вместо этого может быть так: 91,92,93 ... и т. Д. – Sherif

Смежные вопросы