用两点绘制等腰三角形/箭头

时间:2015-02-10 00:00:24

标签: java geometry trigonometry

我一直试图想出这个有一段时间了,我正在制作一个程序,使用三角形作为箭头,并试图弄清楚如何制作一个带有两个点的箭头,这意味着第一点将位于三角形底边的中点,而第二个点位于远离第一个点的方向的顶端。

这张原油画图应该有助于弄清楚我在说什么 http://i.stack.imgur.com/f3ktz.png(会提供直接图像,但没有足够的代表)

现在,我经历了尝试弄清楚如何计算三角形的其他两个端点,以便我可以制作多边形,但我没有正确地做,因为我得到一个不是等腰的三角形和端点不要创建垂直于原始线的线。

我目前得到的东西(有些人用它来表示要点) http://i.stack.imgur.com/dljsn.png

我当前的代码

public class Triangle extends Shape{

private boolean assigned = false;

private int[] x;

private int[] y;

public Triangle(Point startPoint, Point endPoint){
    this.startPoint = startPoint;
    this.endPoint = endPoint;
}

@Override
public void draw(Graphics g) {
    g.setColor(Color.white);
    if(!assigned) {
        x = new int[3];
        y = new int[3];
        double distance = startPoint.distance(endPoint);
        double halfDistance = distance/2;
        double angle = getAngle(startPoint,endPoint)- Math.PI/2.0;

        x[0] = (int)endPoint.getX();
        y[0] = (int)endPoint.getY();

        x[1] = (int)((Math.sin(angle)*halfDistance) + startPoint.getX());
        y[1] = (int)((Math.cos(angle)*halfDistance) + startPoint.getY());

        x[2] = (int)(startPoint.getX() - (Math.sin(angle)*halfDistance));
        y[2] = (int)(startPoint.getY() - (Math.cos(angle)*halfDistance));


        assigned = true;
        if(endPoint.distance(x[1],y[1]) == (Math.sqrt(5)*halfDistance))
            System.out.println("DEBUG: Confirm Correct 1");
        if(endPoint.distance(x[1],y[1]) == endPoint.distance(x[2],y[2]))
            System.out.println("DEBUG: Confirm Correct 2");
    }
    g.fillPolygon(x,y,3);
    g.setColor(Color.blue);
}

private double getAngle(Point pointOne, Point pointTwo){
    double angle = Math.atan2(pointTwo.getY()- pointOne.getY(),pointTwo.getX()-pointOne.getX());
    while(angle < 0){
        angle += (2.0*Math.PI);
    }
    return angle;
}

}

我已经在这工作了好几个小时,似乎无法弄清楚,有人请求帮助。

2 个答案:

答案 0 :(得分:0)

所以,我最终用double angle = getAngle(startPoint,endPoint)- Math.PI/2.0;

之类的内容替换了double angle = -Math.atan2(endPoint.y - startPoint.y, endPoint.x - startPoint.x);

我写了这个小测试程序,它允许你移动到一个圆圈周围的点,并产生生成的三角形......

Tri

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Point;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

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();
                }

                TestPane tp = new TestPane();
                JPanel control = new JPanel(new BorderLayout());
                control.add(tp);

                final JSlider startAngel = new JSlider(0, 359);
                final JSlider endAngel = new JSlider(0, 359);

                JPanel sliders = new JPanel(new GridLayout(1, 2));
                sliders.add(startAngel);
                sliders.add(endAngel);

                startAngel.addChangeListener(new ChangeListener() {
                    @Override
                    public void stateChanged(ChangeEvent e) {
                        tp.setStartAngle(startAngel.getValue());
                    }
                });
                endAngel.addChangeListener(new ChangeListener() {
                    @Override
                    public void stateChanged(ChangeEvent e) {
                        tp.setEndAngle(endAngel.getValue());
                    }
                });

                startAngel.setValue(0);
                endAngel.setValue(180);

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(control);
                frame.add(sliders, BorderLayout.SOUTH);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private Point startPoint, endPoint;
        private float startAngle = 0;
        private float endAngle = 180;

        public TestPane() {
        }

        @Override
        public void invalidate() {
            super.invalidate();
            recalculate();
        }

        protected void recalculate() {

            int dim = Math.min(getWidth(), getHeight());
            dim -= 50;
            float radius = dim / 2f;

            startPoint = getPointOnCircle(startAngle, radius);
            endPoint = getPointOnCircle(endAngle, radius);

            repaint();
        }

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

        protected Point getPointOnCircle(float degress, float radius) {

            int x = Math.round(getWidth() / 2);
            int y = Math.round(getHeight() / 2);

            double rads = Math.toRadians(degress - 90); // 0 becomes the top

            // Calculate the outter point of the line
            int xPosy = Math.round((float) (x + Math.cos(rads) * radius));
            int yPosy = Math.round((float) (y + Math.sin(rads) * radius));

            return new Point(xPosy, yPosy);

        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();

            int[] x = new int[3];
            int[] y = new int[3];
            double distance = startPoint.distance(endPoint);
            double halfDistance = distance / 2;
            double angle = -Math.atan2(endPoint.y - startPoint.y, endPoint.x - startPoint.x);

            System.out.println(angle);

            x[0] = (int) endPoint.getX();
            y[0] = (int) endPoint.getY();

            x[1] = (int) ((Math.sin(angle) * halfDistance) + startPoint.getX());
            y[1] = (int) ((Math.cos(angle) * halfDistance) + startPoint.getY());

            x[2] = (int) (startPoint.getX() - (Math.sin(angle) * halfDistance));
            y[2] = (int) (startPoint.getY() - (Math.cos(angle) * halfDistance));

            g2d.setColor(Color.RED);
            g2d.fillPolygon(x, y, 3);

            g2d.setColor(Color.BLUE);
            g2d.fillOval(startPoint.x - 5, startPoint.y - 5, 10, 10);
            g2d.setColor(Color.GREEN);
            g2d.fillOval(endPoint.x - 5, endPoint.y - 5, 10, 10);

            g2d.dispose();
        }

        public void setStartAngle(float value) {
            startAngle = value;
            recalculate();
        }

        public void setEndAngle(float value) {
            endAngle = value;
            recalculate();
        }

    }

}

如果仍然给你一些奇怪的结果,除了分享一些测试数据,我可能会考虑使用类似Math.atan2(Math.abs(endPoint.y - startPoint.y), Math.abs(endPoint.x - startPoint.x))或类似

的东西

答案 1 :(得分:0)

您根本不需要计算角度。

    double startX = 40;
    double startY = 120;
    double endX = 110;
    double endY = 15;

    double deltaX =  ( startY - endY ) / 2;
    double deltaY =  ( endX - startX ) / 2;

    double[] polygonX = new double[3];
    double[] polygonY = new double[3];

    polygonX[0] = endX;
    polygonY[0] = endY;

    polygonX[1] = startX - deltaX;
    polygonY[1] = startY - deltaY;

    polygonX[2] = startX + deltaX;
    polygonY[2] = startY + deltaY;

Same angle

绘图非常糟糕:D,但重点是:

cos(ang) = 'distance' / ( startY - endY )cod(ang) = ('distance'/2) / deltaX 所以 deltaX = ( startY - endY ) / 2

同样适用于deltaY = ( endX - startX ) / 2

所以三角形的另外两个点将是startPoint减去并加上那些增量。