Поиск пересечения точки и повернутого прямоугольника
То есть его можно мышкой перемещать, изменять размер и вертеть.
Сначала я реализовал перемещение прямоугольника. Тут все получилось.
Самый интересный момент - определение когда мышка наведена на повернутый на N градусов прямоугольник.
Для этого я написал функцию containsRotated(Point p), которая определяет внутри ли повернутого прямоугольника точка или нет.
Ее основной смысл что коллизия ищется для прямоугольника вдоль осей ХY, а сдвигается только точка. Поясню на картинке.
См вложение "pic1.jpg"
(То есть пользователь видит только черный прямоугольник и красный клик, а на самом деле сравнивается серый и зеленый)
Она выглядит так.
Код:
public boolean containsRotated(Point p) {
// deltaA is diff between X-axe and vector to NW-point.
double deltaX = p.x - x;
double deltaY = p.y - y;
double deltaA = Math.atan2(deltaY, deltaX);
double raduis = Point2D.distance(x, y, p.x, p.y);
double pointRotAngle = deltaA - r;
int rotatedX = (int)(x + raduis*Math.cos(pointRotAngle));
int rotatedY = (int)(y + raduis*Math.sin(pointRotAngle));
Point rotatedPoint = new Point(rotatedX, rotatedY);
setBounds(x,y,w,h);
return contains(new Point(rotatedPoint.x - x, rotatedPoint.y - y));
}
// deltaA is diff between X-axe and vector to NW-point.
double deltaX = p.x - x;
double deltaY = p.y - y;
double deltaA = Math.atan2(deltaY, deltaX);
double raduis = Point2D.distance(x, y, p.x, p.y);
double pointRotAngle = deltaA - r;
int rotatedX = (int)(x + raduis*Math.cos(pointRotAngle));
int rotatedY = (int)(y + raduis*Math.sin(pointRotAngle));
Point rotatedPoint = new Point(rotatedX, rotatedY);
setBounds(x,y,w,h);
return contains(new Point(rotatedPoint.x - x, rotatedPoint.y - y));
}
Дальше решил реализовать скейл, для этого хотел использовать ту же функцию когда мышка не внутри самого прямоугольника, но внутри прямоугольника который на 10 пикселов больше.
См вложение "pic2.jpg"
Но почему-то простое изменение размера входного прямоугольника работает не правильно.
Код:
public boolean containsRotated(Point p, int offset) {
int x = this.x - offset;
int y = this.y - offset;
int w = this.w + offset*2;
int h = this.h + offset*2;
--||--
}
int x = this.x - offset;
int y = this.y - offset;
int w = this.w + offset*2;
int h = this.h + offset*2;
--||--
}
Хотя та же функция работает правильно при перемещении любых прямоугольников.
Может кто видит ошибку, или она вообще не тут?
Код проекта для эклипса и просто код приложены.
Если кто-нибудь бы помог разобраться то я был бы очень благодарен.
Код:
public void mouseDragged(MouseEvent e) {}
код какой-то немного низкоуровневый. задался вопросом, почему вы не используете
Цитата:
[COLOR=#000000]java.awt.geom.AffineTransform;
[/COLOR][COLOR=#000000]java.awt.geom.Rectangle2D;[/COLOR]
[/COLOR][COLOR=#000000]java.awt.geom.Rectangle2D;[/COLOR]
Попробую привести пример. в примере приведена обработка не мышиных лиснеров, а кпопачных лиснеров. Но можно это перенести в вашу идею с мышиными лиснерами. Да и еще одно замечание. когда курсор в вашем примере наведен на область с которой мужно дрогать, с любой стороны прямоугольника устанавливается один и тот же курсор - для дроганья вниз.
я правда уже и сам справился. Дело было в том что я пытался вращать описывающий прямоугольник всегда вокруг точки (х - оффсет, y - оффсет), а это правильно только для вращения с нулевым градусом.
Сейчас исправил.
Я что-то и сам не знаю почему не использую java.awt.geom.AffineTransform. Аааа!, я думал что AffineTransform только для Grapohics2d работает. А обычный прямоугольник нельзя. Походу я был неправ^^
Приду домой посмотрю ваш пример обязательно.
> Да и еще одно замечание. когда курсор в вашем примере наведен на область с которой мужно дрогать, с любой стороны прямоугольника устанавливается один и тот же курсор - для дроганья вниз.
Это да, так у меня там вчера целая таблица получилась - при вращении то все меняется. Уже реализовано. Буду вот сегодня рисайз делать, вчера до 4х ночи сидел^^ И походу надо переписать с АffineTransform, чтоб код понятней был. Еще раз спасибо.
Если интересно могу выложить исходники.
Код:
g2.draw(square);
g2.transform(t);
g2.transform(t);
А мне бы такой метод, который применяет трансформацию к прямоугольнику и возвращает тоже повернутый прямоугольник. А то для рисования то это достаточно, а для определения пересечения нужны уже реальные повернутые координаты. Иначе как я узнаю когда мышка рядом с повернутым на 45 ректом?
Цитата: pink master
Посмотрел текст вашего примера, так там тоже вращается Graphics.
А мне бы такой метод, который применяет трансформацию к прямоугольнику и возвращает тоже повернутый прямоугольник. А то для рисования то это достаточно, а для определения пересечения нужны уже реальные повернутые координаты. Иначе как я узнаю когда мышка рядом с повернутым на 45 ректом?
А мне бы такой метод, который применяет трансформацию к прямоугольнику и возвращает тоже повернутый прямоугольник. А то для рисования то это достаточно, а для определения пересечения нужны уже реальные повернутые координаты. Иначе как я узнаю когда мышка рядом с повернутым на 45 ректом?
Дак без вращения с Graphics это достаточно рутинная операция и код получается низкоуровневым и сложно читаемым. а потом представьте, что решите расширить свой пример и внедрить в продакшен аппликацию. поддерка версионности и поик ошибок превратиться просто в кошмар.
Для определения реальных координат ректа нет никакой проблемы. ну к примеру:
Код:
//Adjustments to put component to at the cursor's tip.
private static final int XFUDGE = 40;
private static final int YFUDGE = 57;
//Make component follow the cursor.
public void mouseMoved(MouseEvent e) {
someComponent.setLocation(e.getX()-XFUDGE, e.getY()-YFUDGE);
}
private static final int XFUDGE = 40;
private static final int YFUDGE = 57;
//Make component follow the cursor.
public void mouseMoved(MouseEvent e) {
someComponent.setLocation(e.getX()-XFUDGE, e.getY()-YFUDGE);
}
А использование [COLOR=#000000]AffineTransform[/COLOR][COLOR=#000000] & Rectangle2D[/COLOR] думаю крайне необходимо для читабельности, поддерки в будующем версионности вашего проекта да и стандартный класс в jdk думаю написан лучше, чем вы сможете реализовать что-то самостоятельно :)
Если есть желание, то выложите ваш пример, переписанный с [COLOR=#000000]AffineTransform[/COLOR][COLOR=#000000] & Rectangle2D. другим будет полезно. а лучше еще закиньте его в раздел "Мои исходники" в вашем аккаунте.
Ну и дам возможно полезную подсказку - некоторые куски кода можно найти через [/COLOR]codefetch. Бывает крайне полезно.