简体   繁体   English

检查矩形是否与文本相交

[英]Checking if a rectangle intersects text

I have a class called 'MapObject' which allows you to define what it is, what it does.我有一个叫做“MapObject”的类,它允许你定义它是什么,它做什么。 I have recently added text to this, and it works fine however the collisions is a rectangle, which in some scenarios isn't horrible, however I would prefer to have a collision box matching the text (aka check if a 1x1 rectangle collides with the text but can still be inbetween letters)我最近为此添加了文本,它工作正常,但是碰撞是一个矩形,在某些情况下并不可怕,但是我更喜欢有一个与文本匹配的碰撞框(也就是检查 1x1 矩形是否与文本,但仍然可以在字母之间)

I have tried the following:我尝试了以下方法:

GlyphVector vec = ob.font.createGlyphVector(new Canvas().getFontMetrics(ob.font).getFontRenderContext(), ob.text);
Shape textSh = vec.getOutline();
Area obSh = new Area(new Rectangle(x,y,o.width,o.height));
obSh.intersect(new Area(textSh));
boolean inter = !obSh.isEmpty();

However it just doesn't work, I imagine because of the location, however I don't know how to add a location into it.但是它不起作用,我想是因为位置,但是我不知道如何在其中添加位置。 Thanks.谢谢。

One of the things you probably need to do is translate either the GlyphVector or Rectangle to the correct context.您可能需要做的一件事是将GlyphVectorRectangle转换为正确的上下文。

What I mean is, the GlyphVector only represents the text at a origin point of 0x0 , so if the text is displayed somewhere else on the screen, then you're not getting the correct representation.我的意思是, GlyphVector仅表示原点0x0的文本,因此如果文本显示在屏幕上的其他位置,那么您将无法获得正确的表示。

Luckily, someone actually thought about this use case and provided some functionality to do it.幸运的是,有人真的考虑过这个用例并提供了一些功能来实现它。 See GlyphVector#getOutline(float, float) for more details.有关更多详细信息GlyphVector#getOutline(float, float)请参阅GlyphVector#getOutline(float, float)

You could then use it something like...然后你可以使用它像......

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.font.FontRenderContext;
import java.awt.font.GlyphVector;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private List<Rectangle> boxes;
        private Map<Rectangle, Point> vectors;

        public TestPane() {
            boxes = new ArrayList<>(25);
            vectors = new HashMap<>(25);
            Random random = new Random();
            for (int index = 0; index < 10; index++) {
                int x = random.nextInt(400 - 10);
                int y = random.nextInt(400 - 10);

                Rectangle box = new Rectangle(x, y, 10, 10);
                boxes.add(box);

                int xDelta = random.nextBoolean() ? 1 : -1;
                int yDelta = random.nextBoolean() ? 1 : -1;

                vectors.put(box, new Point(xDelta, yDelta));
            }

            Timer timer = new Timer(40, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    for (Rectangle box : boxes) {
                        Point delta = vectors.get(box);

                        if (delta == null) {
                            int xDelta = random.nextBoolean() ? 1 : -1;
                            int yDelta = random.nextBoolean() ? 1 : -1;
                            delta = new Point(xDelta, yDelta);
                        }

                        int x = box.x + delta.x;
                        int y = box.y + delta.y;

                        if (x < 0) {
                            x = 0;
                            delta.x *= -1;
                        } else if (x + box.width > getWidth()) {
                            x = getWidth() - box.width;
                            delta.x *= -1;
                        }
                        if (y < 0) {
                            y = 0;
                            delta.y *= -1;
                        } else if (y + box.height > getHeight()) {
                            y = getHeight() - box.height;
                            delta.y *= -1;
                        }

                        box.setLocation(x, y);
                        vectors.put(box, delta);
                    }
                    repaint();
                }
            });
            timer.start();
        }

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

        protected Shape getTextShape() {
            Graphics2D g2d = (Graphics2D) getGraphics();
            if (g2d == null) {
                return null;
            }
            Font font = new Font("Arial", Font.BOLD, 48);
            g2d.setFont(font);

            FontRenderContext frc = g2d.getFontRenderContext();
            GlyphVector gv = font.createGlyphVector(frc, "Cats with hats");
            Rectangle2D box = gv.getVisualBounds();

            // Calclate the location of the text and offset the glyph shape...
            float x = (float) (getWidth() - box.getWidth()) / 2f;
            float y = (float) (((getHeight() - box.getHeight()) / 2f) + (-box.getY()));

            return gv.getOutline(x, y);
        }

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

            Shape shape = getTextShape();

            g2d.setColor(Color.BLACK);
            g2d.fill(shape);
            g2d.setColor(Color.RED);
            g2d.draw(shape);

            for (Rectangle box : boxes) {
                g2d.setColor(Color.BLACK);
                if (shape.intersects(box)) {
                    g2d.setColor(Color.RED);
                }
                g2d.draw(box);
            }
        }

    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM