用两点画等腰triangle/arrow
Drawing an isosceles triangle/arrow with two points
我想弄清楚这个问题已经有一段时间了,我正在制作一个使用三角形作为箭头的程序,并试图弄清楚如何用两个点制作一个箭头,这意味着第一个点位于三角形底部的中点,而第二个点位于远离第一个点的方向的尖端。
这张粗画应该有助于弄清楚我在说什么
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;
}
}
我已经为此工作了几个小时,但似乎无法弄清楚,请有人帮忙。
所以,我最终用 double angle = -Math.atan2(endPoint.y - startPoint.y, endPoint.x - startPoint.x);
替换了 double angle = getAngle(startPoint,endPoint)- Math.PI/2.0;
我编写了这个小测试程序,它允许您移动到圆周周围的点并生成生成的三角形...
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))
或 simular
这样的东西
你根本不需要计算角度。
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;
画得非常糟糕 :D,但重点是:
cos(ang) = 'distance' / ( startY - endY )
和
cod(ang) = ('distance'/2) / deltaX
所以
deltaX = ( startY - endY ) / 2
同样适用于deltaY = ( endX - startX ) / 2
所以三角形的另外 2 个点将是 startPoint 减去和加上那些增量。
我想弄清楚这个问题已经有一段时间了,我正在制作一个使用三角形作为箭头的程序,并试图弄清楚如何用两个点制作一个箭头,这意味着第一个点位于三角形底部的中点,而第二个点位于远离第一个点的方向的尖端。
这张粗画应该有助于弄清楚我在说什么 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;
}
}
我已经为此工作了几个小时,但似乎无法弄清楚,请有人帮忙。
所以,我最终用 double angle = -Math.atan2(endPoint.y - startPoint.y, endPoint.x - startPoint.x);
double angle = getAngle(startPoint,endPoint)- Math.PI/2.0;
我编写了这个小测试程序,它允许您移动到圆周周围的点并生成生成的三角形...
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))
或 simular
你根本不需要计算角度。
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;
画得非常糟糕 :D,但重点是:
cos(ang) = 'distance' / ( startY - endY )
和
cod(ang) = ('distance'/2) / deltaX
所以
deltaX = ( startY - endY ) / 2
同样适用于deltaY = ( endX - startX ) / 2
所以三角形的另外 2 个点将是 startPoint 减去和加上那些增量。