Модераторы: LSD, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Содержит ли точку QuadCurve2D? Содержать точку должна только кривая! 
V
    Опции темы
User1302
Дата 11.10.2011, 16:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 17.11.2010

Репутация: нет
Всего: нет



Пытаюсь рисовать граф:
user posted image
на холсте.

При наведении мышки на фигуру, будь то вершина графа, или ребро, нужно понять находится ли курсор над холстом или над фигурой.
Это нужно, чтоб в зависимости от содержимого под курсором вызывать соответствующее контекстное меню.

Если для фигуры я могу использовать Ellipse2D и его метод contains(Point2D p) для этого, то с ребром не понятно, как это сделать.
Для ребра планировал сделать QuadCurve2D, но его метод contains(Point2D p) возвращает true, даже если курсор находится не над фигурой.

Подскажите, как определить, находится ли мышка над кривой?
Как лучше такое сделать?

P.S. Линия обязательно кривая, потому, что между двумя вершинами может быть > 1 ребра. Еще там будет стрелка.

Заранее благодарю!

Это сообщение отредактировал(а) User1302 - 11.10.2011, 16:30
PM MAIL   Вверх
Skipy
Дата 11.10.2011, 16:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 487
Регистрация: 24.8.2006
Где: Москва, Россия

Репутация: 4
Всего: 16



1. Создаете вокруг курсора прямоугольник размером 3х3 - иначе в линию с нецелыми координатами Вы никогда не попадете.
2. На Вашей кривой (кстати, что это конкретно? Надеюсь, наследует Shape?) вызываете метод Shape.intersects(Rectangle2D), который уже точно вычислит, пересекается ли прямоугольник с кривой. 

Можете уменьшить размер прямоугольника, но тогда на кривую попасть сложнее будет.


--------------------
С уважением,
Евгений aka Skipy
www.skipy.ru
PM MAIL WWW ICQ   Вверх
User1302
Дата 11.10.2011, 17:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 17.11.2010

Репутация: нет
Всего: нет



Цитата

Надеюсь, наследует Shape?

QuadCurve2D implements Shape

Спасибо Skipy, согласен, только в том и загвоздка, что QuadCurve2D.intersects работает так же, как и QuadCurve2D.contains!!!
А именно, выдает true даже в том случае, если курсор - не над фигурой.

Получается, фигура не ограничивается видимыми очертаниями самой кривой, а занимает область, ограниченную кривой и прямой, которая соединяет концы видимой кривой. Поэтому возвращается true, если курсор находится (прямоугольник 3х3 пересекается) в этой области!

Для наглядности сделал пример, если есть возможность, Skipy, попробуйте запустить:
Код

import java.awt.Cursor;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Line2D;
import java.awt.geom.QuadCurve2D;
import javax.swing.JComponent;
import javax.swing.JFrame;


public class TestCurve {
    
    public static void main(String[] args){
        JFrame frame = new JFrame();
        
        final Canvas canvas = new Canvas();
        canvas.addMouseMotionListener(new MouseAdapter() {

            @Override
            public void mouseMoved(MouseEvent e) {
//                boolean locate = canvas.getCurve().contains(e.getPoint());
                boolean locate = canvas.getCurve().intersects(e.getPoint().x, e.getPoint().y, 3, 3);
                if (locate) {
                    canvas.setCursor(new Cursor(Cursor.HAND_CURSOR));
                } else {
                    canvas.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
                }
            }
        });
        frame.add(canvas);
        
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setBounds(100, 100, 600, 600);
        frame.setVisible(true);
    }
}

class Canvas extends JComponent {
    
//    private Shape curve = new Line2D.Double(100, 100, 400, 400);
    private Shape curve = new QuadCurve2D.Float(50, 300, 320, 300, 350, 400);
    
    public Shape getCurve(){
        return curve;
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.draw(curve);
    }
}


Можно ли как-то обойтись без Shape?
Может как-то просто линии рисовать? Тогда как выделять? - непонятно...
PM MAIL   Вверх
kamre
Дата 14.10.2011, 12:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 330
Регистрация: 24.3.2006

Репутация: 2
Всего: 13



Можно, например, превратить кривую в набор отрезков и проверять на близость координат  мыши с отрезком. Вроде такого:
Код

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.Line2D;
import java.awt.geom.Path2D;
import java.awt.geom.PathIterator;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

@SuppressWarnings("serial")
public class ShapeHover extends JComponent {
    private Shape shape;
    private List<Line2D> segments;
    private boolean highlight;

    public ShapeHover() {
        Path2D path = new Path2D.Double();
        path.moveTo(150, 10);
        path.lineTo(10, 10);
        path.curveTo(20, 150, 180, 50, 180, 250);
        path.lineTo(50, 250);
        shape = path;
        updateSegments(1.0);
        addMouseMotionListener(new MouseAdapter() {
            @Override
            public void mouseMoved(MouseEvent e) {
                boolean mouseOver = isNearToSegments(e.getPoint(), 3.0);
                if (mouseOver != highlight) {
                    highlight = mouseOver;
                    repaint();
                }
            }
        });
    }

    private boolean isNearToSegments(Point2D point, double tolerance) {
        for (Line2D seg : segments) {
            if (seg.ptSegDist(point) <= tolerance)
                return true;
        }
        return false;
    }

    private void updateSegments(double flatness) {
        segments = new ArrayList<Line2D>();
        PathIterator pathIterator = shape.getPathIterator(new AffineTransform(), flatness);
        double[] coords = new double[6];
        Point2D prev = null;
        while (!pathIterator.isDone()) {
            int type = pathIterator.currentSegment(coords);
            Point2D cur = new Point2D.Double(coords[0], coords[1]);
            if (type == PathIterator.SEG_LINETO) {
                segments.add(new Line2D.Double(prev, cur));
            }
            pathIterator.next();
            prev = cur;
        }
    }

    @Override
    protected void paintComponent(Graphics g) {
        g.setColor(Color.white);
        g.fillRect(0, 0, getWidth(), getHeight());
        Graphics2D g2d = (Graphics2D) g;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setColor(highlight ? Color.red : Color.black);
        g2d.setStroke(new BasicStroke(1.5f));
        g2d.draw(shape);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame("Shape Hover");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setSize(200, 300);
                frame.add(new ShapeHover());
                frame.setVisible(true);
            }
        });
    }
}


PM MAIL   Вверх
User1302
Дата 18.10.2011, 12:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 23
Регистрация: 17.11.2010

Репутация: нет
Всего: нет



Kamre, спасибо за совет, это можно использовать!

Сейчас решил использовать JGraphX. Время, потраченное на изучение доков будет меньше, чем самому реализовывать подобное, пусть даже и значительно менее функциональное.

До этого реализовал FORCE-DIRECTED LAYOUT, думал, буду сам рисовать графы и позиционировать, - получается зря время потратил.

Модератор, поставьте Kamre "+"

Всем спасибо!
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   jk1
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, jk1.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: GUI и Java FX приложения | Следующая тема »


 




[ Время генерации скрипта: 0.4003 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.