在 2 个 Path2D onMouseDragged 之间保持相同的距离
Keep the same distance between 2 Path2D onMouseDragged
我假设有两个 Path2D,一个包含另一个。当我从第一个形状移动一个点时,第二个形状移动相同,但由于角度变化,形状之间的距离也发生变化(以及最终结果......)。
到目前为止我有这个,第二个三角形(innerTriangle)有硬编码点:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Shape;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Path2D;
import java.awt.geom.Rectangle2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
class DragTest extends JPanel {
private final class MouseDrag extends MouseAdapter {
private boolean dragging = false;
private Point last;
@Override
public void mousePressed(MouseEvent m) {
if(dRect.contains(m.getPoint())){
last = m.getPoint();
dragging = isInsideRect(dRect, last);
if (!dragging) {
x = last.x;
y = last.y;
width = 0;
height = 0;
}
}
repaint();
}
@Override
public void mouseReleased(MouseEvent m) {
last = null;
dragging = false;
repaint();
}
@Override
public void mouseDragged(MouseEvent m) {
if(dRect.contains(m.getPoint())){
int dx = m.getX() - last.x;
int dy = m.getY() - last.y;
if (dragging) {
x += dx;
y += dy;
} else {
width += dx;
height += dy;
}
last = m.getPoint();
}
repaint();
}
}
private int x;
private int y;
private int width;
private int height;
private Rectangle2D.Float dRect ;
private Path2D triangle = new Path2D.Float();
private Path2D innerTriangle = new Path2D.Float();
private Point p1;
private Point p2 = new Point(5,200);
private Point p3 = new Point(400,200);
private MouseDrag mouseDrag;
public DragTest() {
setBackground(Color.WHITE);
dRect = new Rectangle2D.Float(x, y, 10+width, 10+height);
mouseDrag = new MouseDrag();
addMouseListener(mouseDrag);
addMouseMotionListener(mouseDrag);
}
public boolean isInsideRect(Shape s, Point point) {
return s.contains(point);
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
dRect = new Rectangle2D.Float(x, y , 10, 10);
g2.draw(dRect);
triangle.reset();
triangle.moveTo(dRect.getCenterX(), dRect.getCenterY());
p1 = new Point((int)dRect.getCenterX(), (int)dRect.getCenterY());
triangle.lineTo(p2.x, p2.y);
triangle.lineTo(p3.x, p3.y);
triangle.closePath();
innerTriangle.reset();
innerTriangle.moveTo(p1.x+10, p1.y+17);
innerTriangle.lineTo(p2.x+10, p2.y-10);
innerTriangle.lineTo(p3.x-47, p3.y-10);
innerTriangle.closePath();
g2.draw(triangle);
g2.draw(innerTriangle);
g2.dispose();
}
public static void main(String[] args) {
JFrame jFrame = new JFrame();
jFrame.setSize(800, 600);
jFrame.add(new DragTest());
jFrame.setVisible(true);
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
如何以编程方式在周围保持相同的距离(比如 10px)?
外三角形和红色(内)三角形之间的距离在所有方向上应该始终相同。有什么想法吗?
SEE IMAGE
目前我正在做一些事情:
// Calculate distance from point to line
public double pointToLineDistance(Point A, Point B, Point P) {
double normalLength = Math.sqrt((B.x-A.x)*(B.x-A.x)+(B.y-A.y)*(B.y-A.y));
return Math.abs((P.x-A.x)*(B.y-A.y)-(P.y-A.y)*(B.x-A.x))/normalLength;
}
// initially set :
// pi1.x = p1.x;
// pi1.y = p1.y;
// -------------------- Then ------------------------------
while(pointToLineDistance(p1, p3, pi1) == 10 && pointToLineDistance(p1, p2, pi1) == 10){
pi1.y++;
pi1.x++;
pi1.setLocation(pi1.x, pi1.y);
}
...但不起作用。帮助!!! :)
SEE IMAGE FOR THE CODE ABOVE
谢谢!
在行连接处保持均匀间距。
这个问题需要一张图来帮助解释。该解决方案适用于一个角,但该过程适用于您想要的任意多个角。
给定在一端连接的两条线,求两条线从两条线偏移固定量
粗体字母(例如A)代表分数。从头到尾以粗体连接字母的行(例如 AB 是从 A 到 B 和 BA 是从 B 到 A)
的直线
给定行 AB 和 BC 找到行 A1D 和 DC1 使得面积 x 与原始线的距离。
// all variables are assumed declared and floats or doubles (up to you)
Ax = 10; // x of Point A
Ay = 200; // y of A
Bx = 200; // x,y of B
By = 200;
Cx = 40; // C
Cy = 10;
Dist = 40; // distance from the line
查看图像,我们可以看到一些很好的对称性,可以利用它来找到解决方案。 EB、BF、FD 和 DE 行是都一样长。这意味着如果我们求解直角三角形 gBF 我们可以沿着线 BA 从 B 移动到g 从 g 到 h 因为 gh 是与 FB
相同的长度
从这一点开始,线 AB 转向 BA
找到一个点 x 到一条线的距离
要找到点 A1 我们找到沿直线 BA 的归一化向量
查找 A1
// get the vector from B to A and normalise it
BAx = Ax - Bx;
BAy = Ay - By;
leng = Math.sqrt(BAx * BAx + BAy * BAy);
BAx /= leng; // The vector BA is 1 pixel (unit long)
BAy /= leng;
法线沿直线移动 90 度只需交换 x
和 y
否定 y
A1x = Ax - BAy * Dist;
A1y = Ay + BAx * Dist;
现在对点C1
做同样的事情
BCx = Cx - Bx;
BCy = Cy - By;
leng = Math.sqrt(BCx * BCx + BCy * BCy);
BCx /= leng;
BCy /= leng;
C1x = Cx + BCy * Dist; // move in the opposite direction than from A
C1y = Cy - BCx * Dist;
求解三角形FBg
求D
如果您只需要找到 D(例如,您在一条封闭的直线、三角形上执行此操作),您仍然需要获得归一化向量 BA 和 BC 是上面计算出来的。 BAx
、BAy
和 BCx
、BCy
求角度的正弦值 EBF 使用两个归一化向量 BA 和 的叉积公元前。角的正弦将三角形的对边 Fg 与斜边 BF 关联为 sin(ang) = opp/hypt
cross = BAx * BCy - BAy * BCx; // gets the sin of the angle
// you should check cross of zero. If so there is no solution
FBlen = Dist / cross; // gets the hypot the length of FB
现在我们有 FB 我们知道距离 gh 我们可以得到 gB 因为我们有直角三角形的两条边和 gB = sqrt(FB*FB+Dist*Dist)
的长度,但是如果 ABC 的角度大于 90 度,这将成为一个问题。我们不仅需要知道长度,还需要知道方向(正向或负向)。
我们可以使用点积求解 Bg,该点积求角 ABC 的余弦,它与斜边相关联直角三角形 cos(ang) = BF/Bg
dot = BAx * BCx + BAy * BCy;
Bglen = FBlen * dot;
现在我们可以沿着线BA移动到g然后到h然后转向90 度向外 D
// move from B to h using the normal vec of the line BA time the sum
// of the length FB
hx = Bx + BAx * (FBlen + BgLen);
hy = By + BAy * (FBlen + BgLen);
Dx = hx - BAy * Dist; // then at 90 deg dist along to D
Dy = hy + BAx * Dist;
你已经完成了你的积分 A1, D, C1
一次代码
您可能还更喜欢使用向量库来进行加法、归一化、叉积等...
Ax = 10; // x of Point A
Ay = 200; // y of A
Bx = 200; // x,y of B
By = 200;
Cx = 40; // C
Cy = 10;
Dist = 40; // dist out
BAx = Ax - Bx;
BAy = Ay - By;
BCx = Cx - Bx;
BCy = Cy - By;
leng = Math.sqrt(BAx * BAx + BAy * BAy);
BAx /= leng;
BAy /= leng;
leng = Math.sqrt(BCx * BCx + BCy * BCy);
BCx /= leng;
BCy /= leng;
// get inside end points
A1x = Ax - BAy * Dist;
A1y = Ay + BAx * Dist;
C1x = Cx + BCy * Dist;
C1y = Cy - BCx * Dist;
FBlen = Dist / (BAx * BCy - BAy * BCx);
FBlen += FBlen * (BAx * BCx + BAy * BCy);
Dx = Bx + BAx * FBlen - BAy * Dist;;
Dy = By + BAy * FBlen + BAx * Dist;
边缘案例
您可以对任意数量的线执行此操作,只要您沿同一方向行进并且您的向量是从角向外。有一些注意事项。
- 如果两个角点之间的距离太短,内线会重叠并导致问题。除了固定角间距和限制宽度外,没有简单的解决方案。
- 如果直线平行则失败。检查叉积的结果,当零或非常接近零时线 AB 和 BC 接近平行。
- 斜接范围。当两条线之间的角度开始接近 360 度时,点 D 将开始越来越远。随着角度接近 360 度或 2 弧度,从 B 到 D 的距离将接近无穷大。再次检查叉积是否为零或接近零。您还可以通过倒圆角来设置斜接限制。或截断它。
斜接一个角。以上答案为您提供了解决上图所需的信息。如果点 B 比 F 从 D 然后找到点F。寻找对称性,像三角形一样找到其他点。
如果您排长队,最好在队伍的每一侧都排好队。通过定义中心而不是边缘,您可以获得更好的结果。
我假设有两个 Path2D,一个包含另一个。当我从第一个形状移动一个点时,第二个形状移动相同,但由于角度变化,形状之间的距离也发生变化(以及最终结果......)。
到目前为止我有这个,第二个三角形(innerTriangle)有硬编码点:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Shape;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Path2D;
import java.awt.geom.Rectangle2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
class DragTest extends JPanel {
private final class MouseDrag extends MouseAdapter {
private boolean dragging = false;
private Point last;
@Override
public void mousePressed(MouseEvent m) {
if(dRect.contains(m.getPoint())){
last = m.getPoint();
dragging = isInsideRect(dRect, last);
if (!dragging) {
x = last.x;
y = last.y;
width = 0;
height = 0;
}
}
repaint();
}
@Override
public void mouseReleased(MouseEvent m) {
last = null;
dragging = false;
repaint();
}
@Override
public void mouseDragged(MouseEvent m) {
if(dRect.contains(m.getPoint())){
int dx = m.getX() - last.x;
int dy = m.getY() - last.y;
if (dragging) {
x += dx;
y += dy;
} else {
width += dx;
height += dy;
}
last = m.getPoint();
}
repaint();
}
}
private int x;
private int y;
private int width;
private int height;
private Rectangle2D.Float dRect ;
private Path2D triangle = new Path2D.Float();
private Path2D innerTriangle = new Path2D.Float();
private Point p1;
private Point p2 = new Point(5,200);
private Point p3 = new Point(400,200);
private MouseDrag mouseDrag;
public DragTest() {
setBackground(Color.WHITE);
dRect = new Rectangle2D.Float(x, y, 10+width, 10+height);
mouseDrag = new MouseDrag();
addMouseListener(mouseDrag);
addMouseMotionListener(mouseDrag);
}
public boolean isInsideRect(Shape s, Point point) {
return s.contains(point);
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
dRect = new Rectangle2D.Float(x, y , 10, 10);
g2.draw(dRect);
triangle.reset();
triangle.moveTo(dRect.getCenterX(), dRect.getCenterY());
p1 = new Point((int)dRect.getCenterX(), (int)dRect.getCenterY());
triangle.lineTo(p2.x, p2.y);
triangle.lineTo(p3.x, p3.y);
triangle.closePath();
innerTriangle.reset();
innerTriangle.moveTo(p1.x+10, p1.y+17);
innerTriangle.lineTo(p2.x+10, p2.y-10);
innerTriangle.lineTo(p3.x-47, p3.y-10);
innerTriangle.closePath();
g2.draw(triangle);
g2.draw(innerTriangle);
g2.dispose();
}
public static void main(String[] args) {
JFrame jFrame = new JFrame();
jFrame.setSize(800, 600);
jFrame.add(new DragTest());
jFrame.setVisible(true);
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
如何以编程方式在周围保持相同的距离(比如 10px)?
外三角形和红色(内)三角形之间的距离在所有方向上应该始终相同。有什么想法吗?
SEE IMAGE
目前我正在做一些事情:
// Calculate distance from point to line
public double pointToLineDistance(Point A, Point B, Point P) {
double normalLength = Math.sqrt((B.x-A.x)*(B.x-A.x)+(B.y-A.y)*(B.y-A.y));
return Math.abs((P.x-A.x)*(B.y-A.y)-(P.y-A.y)*(B.x-A.x))/normalLength;
}
// initially set :
// pi1.x = p1.x;
// pi1.y = p1.y;
// -------------------- Then ------------------------------
while(pointToLineDistance(p1, p3, pi1) == 10 && pointToLineDistance(p1, p2, pi1) == 10){
pi1.y++;
pi1.x++;
pi1.setLocation(pi1.x, pi1.y);
}
...但不起作用。帮助!!! :)
SEE IMAGE FOR THE CODE ABOVE
谢谢!
在行连接处保持均匀间距。
这个问题需要一张图来帮助解释。该解决方案适用于一个角,但该过程适用于您想要的任意多个角。
给定在一端连接的两条线,求两条线从两条线偏移固定量
粗体字母(例如A)代表分数。从头到尾以粗体连接字母的行(例如 AB 是从 A 到 B 和 BA 是从 B 到 A)
的直线给定行 AB 和 BC 找到行 A1D 和 DC1 使得面积 x 与原始线的距离。
// all variables are assumed declared and floats or doubles (up to you)
Ax = 10; // x of Point A
Ay = 200; // y of A
Bx = 200; // x,y of B
By = 200;
Cx = 40; // C
Cy = 10;
Dist = 40; // distance from the line
查看图像,我们可以看到一些很好的对称性,可以利用它来找到解决方案。 EB、BF、FD 和 DE 行是都一样长。这意味着如果我们求解直角三角形 gBF 我们可以沿着线 BA 从 B 移动到g 从 g 到 h 因为 gh 是与 FB
相同的长度从这一点开始,线 AB 转向 BA
找到一个点 x 到一条线的距离
要找到点 A1 我们找到沿直线 BA 的归一化向量
查找 A1
// get the vector from B to A and normalise it
BAx = Ax - Bx;
BAy = Ay - By;
leng = Math.sqrt(BAx * BAx + BAy * BAy);
BAx /= leng; // The vector BA is 1 pixel (unit long)
BAy /= leng;
法线沿直线移动 90 度只需交换 x
和 y
否定 y
A1x = Ax - BAy * Dist;
A1y = Ay + BAx * Dist;
现在对点C1
做同样的事情BCx = Cx - Bx;
BCy = Cy - By;
leng = Math.sqrt(BCx * BCx + BCy * BCy);
BCx /= leng;
BCy /= leng;
C1x = Cx + BCy * Dist; // move in the opposite direction than from A
C1y = Cy - BCx * Dist;
求解三角形FBg
求D如果您只需要找到 D(例如,您在一条封闭的直线、三角形上执行此操作),您仍然需要获得归一化向量 BA 和 BC 是上面计算出来的。 BAx
、BAy
和 BCx
、BCy
求角度的正弦值 EBF 使用两个归一化向量 BA 和 的叉积公元前。角的正弦将三角形的对边 Fg 与斜边 BF 关联为 sin(ang) = opp/hypt
cross = BAx * BCy - BAy * BCx; // gets the sin of the angle
// you should check cross of zero. If so there is no solution
FBlen = Dist / cross; // gets the hypot the length of FB
现在我们有 FB 我们知道距离 gh 我们可以得到 gB 因为我们有直角三角形的两条边和 gB = sqrt(FB*FB+Dist*Dist)
的长度,但是如果 ABC 的角度大于 90 度,这将成为一个问题。我们不仅需要知道长度,还需要知道方向(正向或负向)。
我们可以使用点积求解 Bg,该点积求角 ABC 的余弦,它与斜边相关联直角三角形 cos(ang) = BF/Bg
dot = BAx * BCx + BAy * BCy;
Bglen = FBlen * dot;
现在我们可以沿着线BA移动到g然后到h然后转向90 度向外 D
// move from B to h using the normal vec of the line BA time the sum
// of the length FB
hx = Bx + BAx * (FBlen + BgLen);
hy = By + BAy * (FBlen + BgLen);
Dx = hx - BAy * Dist; // then at 90 deg dist along to D
Dy = hy + BAx * Dist;
你已经完成了你的积分 A1, D, C1
一次代码
您可能还更喜欢使用向量库来进行加法、归一化、叉积等...
Ax = 10; // x of Point A
Ay = 200; // y of A
Bx = 200; // x,y of B
By = 200;
Cx = 40; // C
Cy = 10;
Dist = 40; // dist out
BAx = Ax - Bx;
BAy = Ay - By;
BCx = Cx - Bx;
BCy = Cy - By;
leng = Math.sqrt(BAx * BAx + BAy * BAy);
BAx /= leng;
BAy /= leng;
leng = Math.sqrt(BCx * BCx + BCy * BCy);
BCx /= leng;
BCy /= leng;
// get inside end points
A1x = Ax - BAy * Dist;
A1y = Ay + BAx * Dist;
C1x = Cx + BCy * Dist;
C1y = Cy - BCx * Dist;
FBlen = Dist / (BAx * BCy - BAy * BCx);
FBlen += FBlen * (BAx * BCx + BAy * BCy);
Dx = Bx + BAx * FBlen - BAy * Dist;;
Dy = By + BAy * FBlen + BAx * Dist;
边缘案例
您可以对任意数量的线执行此操作,只要您沿同一方向行进并且您的向量是从角向外。有一些注意事项。
- 如果两个角点之间的距离太短,内线会重叠并导致问题。除了固定角间距和限制宽度外,没有简单的解决方案。
- 如果直线平行则失败。检查叉积的结果,当零或非常接近零时线 AB 和 BC 接近平行。
- 斜接范围。当两条线之间的角度开始接近 360 度时,点 D 将开始越来越远。随着角度接近 360 度或 2 弧度,从 B 到 D 的距离将接近无穷大。再次检查叉积是否为零或接近零。您还可以通过倒圆角来设置斜接限制。或截断它。
斜接一个角。以上答案为您提供了解决上图所需的信息。如果点 B 比 F 从 D 然后找到点F。寻找对称性,像三角形一样找到其他点。
如果您排长队,最好在队伍的每一侧都排好队。通过定义中心而不是边缘,您可以获得更好的结果。