有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java确定一个形状是否高于另一个形状

我试图确定一个四边形是否高于另一个四边形,并返回未覆盖量的比率。我对“未覆盖”的定义是,如果在y轴上被检查的形状上方没有其他形状,以及它们在x轴上相交的程度

例如:

two shapes

在上图中,所需输出应为0.6363。在110个像素中,70个与上面的对象相交,70/110=0.6363

另一个例子:

example 2

在本例中,所需输出为0.3636

到目前为止,我尝试的是从double out = 1;开始,然后如果形状2的y轴小于形状1,我从带有out-=(c.getX2()-b.getX2())/Math.abs(c.getX1()-c.getX2());变量的比率中减去两个形状在x轴上相交的量

然而,这似乎不起作用,我试图更正代码的尝试似乎只是增加了越来越多不必要的复杂性。我想有一种更简单的方法来做我想做的事情,但我对几何不太在行

c是正在检查的当前形状,而b是正在与之进行比较的形状

if(((b.getX2() < c.getX2()) && (b.getX2()>c.getX1()))||((b.getX2()>c.getX2())&&(b.getX2()<c.getX1()))||((b.getX1()>c.getX2())&&(b.getX1()<c.getX1()))) {
    if(b.getY2() < c.getY2()) {
        if((b.getX2() < c.getX2()) && (b.getX2()>c.getX1())) {
            out-= (c.getX2()-b.getX2())/Math.abs(c.getX1()-c.getX2());
        }
        if(((b.getX2()>c.getX2())&&(b.getX2()<c.getX1()))) {
            out-=(b.getX2()-c.getX2())/Math.abs(c.getX1()-c.getX2());
        }
        if(((b.getX1()>c.getX2())&&(b.getX1()<c.getX1()))) {
            out-=(c.getX2()-b.getX2())/Math.abs(c.getX1()-c.getX2());
        }
    }
}

共 (1) 个答案

  1. # 1 楼答案

    我认为您的方法非常复杂,您可能只是在所有不同的可能条件和配置中迷失了方向

    如果我理解正确,那么最简单的解决方案是根据两种形状的最小和最大X值进行计算


    旁注:

    您没有说明您的“形状”对象bc是什么类型。从您正在调用的方法来看,它们可能是^{}对象,但它们并不是真正的“四边形”。在任何情况下,您都可以计算最小值和最大值,如下所示:

    double bMinX = Math.min(b.getX1(), b.getX2());
    double bMaxX = Math.max(b.getX1(), b.getX2());
    double cMinX = Math.min(c.getX1(), c.getX2());
    double cMaxX = Math.max(c.getX1(), c.getX2());
    

    在下面的程序中,我使用实际的Shape对象并调用getBounds2D方法来获得边界框,它方便地提供这些最小/最大值。但您也可以手动执行此操作


    当具有这些最小/最大值时,可以排除对象完全位于另一个对象左侧或右侧的情况。如果不是这样,它们是重叠的。在这种情况下,您可以计算重叠的最小值和最大值,然后将其除以相关对象的宽度

    下面是一个程序,其中一个示例对象是根据您在问题中给出的坐标创建的。可以使用鼠标在对象周围拖动。将绘制重叠部分并打印其值

    Overlap

    计算在computeOverlap方法中进行

    import java.awt.Color;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Point;
    import java.awt.RenderingHints;
    import java.awt.Shape;
    import java.awt.event.MouseEvent;
    import java.awt.event.MouseListener;
    import java.awt.event.MouseMotionListener;
    import java.awt.geom.Path2D;
    import java.awt.geom.Point2D;
    import java.awt.geom.Rectangle2D;
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.List;
    
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    
    
    public class ShapeOverlap
    {
        public static void main(String[] args) throws IOException
        {
            SwingUtilities.invokeLater(() -> createAndShowGUI());
        }
    
        private static void createAndShowGUI()
        {
            JFrame f = new JFrame();
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.getContentPane().add(new ShapeOverlapPanel());
            f.setSize(900,500);
            f.setLocationRelativeTo(null);
            f.setVisible(true);
        }
    }
    
    class ShapeOverlapPanel extends JPanel
        implements MouseListener, MouseMotionListener
    {
        private final List<Point2D> points0;
        private final List<Point2D> points1;
        private final List<Point2D> draggedPoints;
        private Point previousMousePosition;
    
        ShapeOverlapPanel()
        {
            points0 = new ArrayList<Point2D>();
            points0.add(new Point2D.Double(160, 200));
            points0.add(new Point2D.Double(180, 200));
            points0.add(new Point2D.Double(270, 260));
            points0.add(new Point2D.Double(250, 260));
    
            points1 = new ArrayList<Point2D>();
            points1.add(new Point2D.Double(200, 280));
            points1.add(new Point2D.Double(220, 280));
            points1.add(new Point2D.Double(310, 340));
            points1.add(new Point2D.Double(290, 340));
    
            draggedPoints = new ArrayList<Point2D>();
    
            addMouseListener(this);
            addMouseMotionListener(this);
        }
    
    
        @Override
        protected void paintComponent(Graphics gr)
        {
            super.paintComponent(gr);
            Graphics2D g = (Graphics2D)gr;
            g.setRenderingHint(
                RenderingHints.KEY_ANTIALIASING,  
                RenderingHints.VALUE_ANTIALIAS_ON);
            g.setColor(Color.WHITE);
            g.fillRect(0, 0, getWidth(), getHeight());
    
            Shape s0 = createShape(points0);        
            Shape s1 = createShape(points1);
    
            g.setColor(Color.RED);
            g.fill(s0);
            g.setColor(Color.BLUE);
            g.fill(s1);
    
            g.setColor(Color.GRAY);
            drawOverlap(g, s0, s1);
    
            double overlap = computeOverlap(s0, s1);
            g.drawString("Overlap of red from blue: "+overlap, 10, 20);
        }
    
        private static double computeOverlap(Shape s0, Shape s1)
        {
            Rectangle2D b0 = s0.getBounds2D();
            Rectangle2D b1 = s1.getBounds2D();
    
            if (b0.getMaxX() < b1.getMinX())
            {
                System.out.println("Shape 0 is left of shape 1");
                return Double.NaN;
            }
            if (b0.getMinX() > b1.getMaxX())
            {
                System.out.println("Shape 0 is right of shape 1");
                return Double.NaN;
            }
    
            double overlapMinX = Math.max(b0.getMinX(), b1.getMinX());
            double overlapMaxX = Math.min(b0.getMaxX(), b1.getMaxX());
            double overlapSize = overlapMaxX - overlapMinX;
    
            double relativeOverlap = overlapSize / b0.getWidth();
            return relativeOverlap;
        }
    
        private void drawOverlap(Graphics2D g, Shape s0, Shape s1)
        {
            Rectangle2D b0 = s0.getBounds2D();
            Rectangle2D b1 = s1.getBounds2D();
    
            if (b0.getMaxX() < b1.getMinX())
            {
                return;
            }
            if (b0.getMinX() > b1.getMaxX())
            {
                return;
            }
    
            double overlapMinX = Math.max(b0.getMinX(), b1.getMinX());
            double overlapMaxX = Math.min(b0.getMaxX(), b1.getMaxX());
    
            g.drawLine((int)overlapMinX, 0, (int)overlapMinX, getHeight());
            g.drawLine((int)overlapMaxX, 0, (int)overlapMaxX, getHeight());
        }
    
    
        private static Shape createShape(Iterable<? extends Point2D> points)
        {
            Path2D path = new Path2D.Double();
            boolean first = true;
            for (Point2D p : points)
            {
                if (first)
                {
                    path.moveTo(p.getX(), p.getY());
                    first = false;
                }
                else
                {
                    path.lineTo(p.getX(), p.getY());
                }
            }
            path.closePath();
            return path;
        }
    
        @Override
        public void mouseDragged(MouseEvent e)
        {
            int dx = e.getX() - previousMousePosition.x;
            int dy = e.getY() - previousMousePosition.y;
            for (Point2D p : draggedPoints)
            {
                p.setLocation(p.getX() + dx, p.getY() + dy);
            }
            repaint();
            previousMousePosition = e.getPoint();
        }
    
        @Override
        public void mouseMoved(MouseEvent e)
        {
        }
    
        @Override
        public void mouseClicked(MouseEvent e)
        {
        }
    
        @Override
        public void mousePressed(MouseEvent e)
        {
            draggedPoints.clear();
            Shape s0 = createShape(points0);
            Shape s1 = createShape(points1);
            if (s0.contains(e.getPoint()))
            {
                draggedPoints.addAll(points0);
            }
            else if (s1.contains(e.getPoint()))
            {
                draggedPoints.addAll(points1);
            }
            previousMousePosition = e.getPoint();
        }
    
        @Override
        public void mouseReleased(MouseEvent e)
        {
            draggedPoints.clear();
        }
    
        @Override
        public void mouseEntered(MouseEvent e)
        {
        }
    
        @Override
        public void mouseExited(MouseEvent e)
        {
        }
    
    
    }