如何绘制一个方向和一个固定长度的线

问题描述:

我想画一条直到屏幕边缘,当我提供给它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

您需要打破你的问题了下来...

首先,你需要能够计算出两点

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

我稍微想了一些想法,并提出了一个方法,它采取了RectangleLine2D,并返回了发生碰撞点的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 ... etc – Sherif