다이아몬드를 클릭하면 감지하고 싶습니다. 내가 가진 유일한 것은 클릭의 좌표 (x, y), 다이아몬드의 중심 (x, y) 및 다이아몬드의 너비/높이입니다.다이아몬드에서 클릭 감지
찾았지만 문제가 다릅니다. pixel coordinates on diamond
다이아몬드를 클릭하면 감지하고 싶습니다. 내가 가진 유일한 것은 클릭의 좌표 (x, y), 다이아몬드의 중심 (x, y) 및 다이아몬드의 너비/높이입니다.다이아몬드에서 클릭 감지
찾았지만 문제가 다릅니다. pixel coordinates on diamond
링크 된 답변에는 실제로 필요한 모든 것이 들어 있습니다. "직접 점 위치 확인"을 통해 포인트가 다이아몬드 안에 있는지 여부를 확인할 수 있습니다.
다이아몬드는 회전 할 수 없다고 가정합니다. 그렇지 않으면 그 질문은 끔찍하게 부정확했을 것입니다. 여기
는 예를 들어 자바/스윙 구현 MCVE이다
관련 부분은 실제로 찍은 코드의 4 개 라인으로 구성 아래쪽 Diamond#contains
방법이며 당신은 다이아몬드의 중심이있는 경우 다른 대답 ....
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Path2D;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class DiamondClickTest
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
createAndShowGUI();
}
});
}
private static void createAndShowGUI()
{
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
List<Diamond> diamonds = new ArrayList<Diamond>();
diamonds.add(new Diamond("A", new Point(100,100), 180, 140));
diamonds.add(new Diamond("B", new Point(300,100), 110, 160));
diamonds.add(new Diamond("C", new Point(100,300), 110, 180));
diamonds.add(new Diamond("D", new Point(300,300), 130, 150));
DiamondClickTestPanel p = new DiamondClickTestPanel(diamonds);
f.getContentPane().add(p);
f.setSize(400,430);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
class DiamondClickTestPanel extends JPanel implements MouseMotionListener
{
private List<Diamond> diamonds;
private Diamond highlighedDiamond = null;
DiamondClickTestPanel(List<Diamond> diamonds)
{
this.diamonds = diamonds;
addMouseMotionListener(this);
}
@Override
protected void paintComponent(Graphics gr)
{
super.paintComponent(gr);
Graphics2D g = (Graphics2D)gr;
g.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
for (Diamond diamond : diamonds)
{
draw(g, diamond);
}
}
private void draw(Graphics2D g, Diamond diamond)
{
Point2D c = diamond.getCenter();
double x0 = c.getX() + diamond.getWidth() * 0.5;
double y0 = c.getY();
double x1 = c.getX();
double y1 = c.getY() - diamond.getHeight() * 0.5;
double x2 = c.getX() - diamond.getWidth() * 0.5;
double y2 = c.getY();
double x3 = c.getX();
double y3 = c.getY() + diamond.getHeight() * 0.5;
Path2D p = new Path2D.Double();
p.moveTo(x0, y0);
p.lineTo(x1, y1);
p.lineTo(x2, y2);
p.lineTo(x3, y3);
p.closePath();
if (diamond == highlighedDiamond)
{
g.setColor(Color.RED);
g.fill(p);
}
g.setColor(Color.BLACK);
g.draw(p);
g.drawString(diamond.getName(), (int)c.getX()-4, (int)c.getY()+8);
}
@Override
public void mouseDragged(MouseEvent e)
{
}
@Override
public void mouseMoved(MouseEvent e)
{
double x = e.getX();
double y = e.getY();
highlighedDiamond = null;
for (Diamond diamond : diamonds)
{
if (diamond.contains(x, y))
{
highlighedDiamond = diamond;
}
}
repaint();
}
}
class Diamond
{
private String name;
private Point2D center;
private double width;
private double height;
Diamond(String name, Point2D center, double width, double height)
{
this.name = name;
this.center = center;
this.width = width;
this.height = height;
}
String getName()
{
return name;
}
Point2D getCenter()
{
return center;
}
double getWidth()
{
return width;
}
double getHeight()
{
return height;
}
boolean contains(double x, double y)
{
double dx = Math.abs(x - center.getX());
double dy = Math.abs(y - center.getY());
double d = dx/width + dy/height;
return d <= 0.5;
}
}
감사합니다. 게시물 도움과 작업. 나는 네가 마지막 기능에서했던 것처럼했다. 왜 d가 0.5보다 작아야합니까? – ILoveWaffle
"d"는 실제로 앤드류 (Andand)의 답변에 설명 된 것처럼 "반경"입니다. 그러나 너비와 높이는 "직경"(반경의 두 배)입니다. 그것이 <= 0.5'이고 <= 1.0'이 아닌 이유입니다. – Marco13
l(1) norm을 기준으로 거리 측정 값을 공식화 할 수 있습니다.이 값은 points of fixed distance from some center point form an axially aligned diamond with vertices equidistant from the center입니다.
이 경우 다이아몬드의 꼭지점이 원점을 기준으로 한 좌표 축에 배치 된 정규형으로 다이아몬드를 배치하려면 적절한 아핀 변환을 적용해야합니다. 이 거리를 r
이라고 부르십시오. 원래의 다이아몬드의 형태에 따라, 이것은 (다이아몬드가 원점에 중심 맞춤되지 않은 경우) 이동 (회전 (다이아몬드의 대각선이 축 방향으로 정렬되지 않은 경우)과 스케일링 (대각선 길이가 동일하지 않은 경우) 당신이 적용 할 affine 변환의 기초를 형성하는 연산. 그런 다음이 동일한 아핀 변환을 마우스 클릭에 적용하고 결과 지점의 각 구성 요소의 절대 값을 합산합니다. 이 금액을 d
라고 부르십시오. r > d
이면 포인트가 다이아몬드 내부에 놓입니다. d > r
포인트가 다이아몬드 외부에 있고, r = d
인 경우 포인트가 다이아몬드 가장자리에 놓입니다.
이것은 완전히 정확하지만 OP의 이점으로 중요한 비트는 "각 구성 요소의 절대 값을 합한 것"이라고 지적하고 싶습니다. 아마도 솔루션을 설명하는 더 짧은 방법은 L1 표준에서 일정한 거리의 곡선이 다이아몬드임을 지적하는 것입니다. –
@RobertDodier : 좋은 지적입니다. 이 단순화를 반영하여 업데이트되었습니다. – andand
당신은 충분한 정보를 가지고 있지 않습니다. –
정보가 충분하지 않습니다. 우리는 다이아몬드가 얼마나 큰 지 알지 못합니다 (1 픽셀, 100 픽셀, 1000 픽셀, ...). 우리는 또한 다이아몬드의 크기를 모른다. 높이가 10 : 1이고 높이가 너비 일 수도 있고 회전 된 사각형이 될 수도 있습니다 (너비와 높이의 비율이 1 : 1). 이 정보가 없으면 질문에 대답 할 수 없습니다. – Degustaf
미안하지만, 나는 그걸 가질 수 있다는 것을 잊어 버렸다. – ILoveWaffle