0

我假设有两个 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);
    }
}

如何以编程方式在周围保持相同的距离(比如 10 像素)?

外三角形和红色(内)三角形之间的距离应该在所有方向上始终相同。任何想法?

查看图片

目前我正在做一些事情:

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

...但不起作用。帮助!!!:)

查看上面代码的图像

谢谢你!

4

1 回答 1

0

在线连接处保持均匀的间距。

这个问题需要插图来帮助解释。解决方案是针对一个角落,但该过程将适用于您想要的任意数量的角落。

给定在一端连接的两条线,找到两条线从两条线偏移固定量

在此处输入图像描述

粗体字母(例如A)代表点。从开始到结束的粗体连接字母行(例如AB是从AB的行,BA是从BA的行)

给定线ABBC找到线A 1 DDC 1使得面积 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

查看图像,我们可以看到一些很好的对称性,可以利用这些对称性来找到解决方案。线EBBFFDDE的长度都相同。这意味着如果我们求解直角三角形gBF,我们可以沿着BA线从B移动到g,然后从g移动到h,因为gh的长度与FB相同

从这一点AB线转向BA

从一条线找到一个点 x 距离

为了找到点A 1我们找到沿线BA的归一化向量

寻找A 1

// 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 度,只是交换xy否定y

A1x = Ax - BAy * Dist;
A1y = Ay + BAx * Dist;

现在对点C 1做同样的事情

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(例如,您在闭合线、三角形上执行此操作),您仍然需要获得上面计算出的归一化向量BABCBAx,BAyBCx,BCy

要找到角度EBF的 sin,请使用两个归一化向量BABC的叉积。角的 sin 将三角形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 ,我们知道我们可以得到gB的距离gh ,因为我们有直角三角形的两条边和长度,但是如果ABC的角度大于 90 度,这将成为一个问题。我们不仅需要知道长度,还需要知道方向(正或负)。gB = sqrt(FB*FB+Dist*Dist)

我们可以使用点积来求解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;

你已经完成了,你有点A 1DC 1

一口气编码

您可能还喜欢使用向量库来进行添加、归一化、叉积等...

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 弧度,从BD的距离将接近无穷大。再次检查叉积是否为零或接近零。您还可以通过圆角设置斜接限制。或截断它。

在此处输入图像描述

斜接一个角落。上面的答案为您提供了解决上述图像所需的信息。距离DF固定为最大斜接限制,如果点BDF更远,则找到点F。寻找对称和类似三角形以找到其他点。

如果您要排长队,最好在线路的每一侧进行。通过定义中心而不是边缘,您可以获得更好的结果。

于 2017-07-08T15:18:44.087 回答