从矩形构造椭圆
Construct ellipse from rectangle
我正在制作一个有点像 Paint
light 的程序,我已经到了我希望用户能够 select 椭圆区域的地步。我最初的想法是,一定有某种方程可以让我根据矩形的宽度和高度构造一个椭圆。但是,到目前为止,我还没有发现任何如此直接的东西。
这是我的代码,用于在用户拖动鼠标时 select 设置一个矩形区域(位于 MouseAdapter 内):
@Override
public void mouseDragged(MouseEvent e) {
dragPoint = e.getPoint();
if (selectionType.equalsIgnoreCase("Rectangle")) {
int width = dragPoint.x - mouseAnchor.x;
int height = dragPoint.y - mouseAnchor.y;
subHeight = height;
subWidth = width;
int x = mouseAnchor.x;
int y = mouseAnchor.y;
if (width < 0) {
x = dragPoint.x;
width *= -1;
}
if (height < 0) {
y = dragPoint.y;
height *= -1;
}
selectionPane.setBounds(x, y, width, height);
selectionPane.revalidate();
repaint();
}
}
SelectionPane
是扩展 JPanel
的自定义 class 的实例。我的想法是,我想从 selected 区域绘制一个填充的椭圆,这样用户就可以看到他们 selected 的内容。
在这个程序的第二部分,我也遇到了一些困惑。在用户制作他或她的 selection 之后,我想使用 selected 区域作为指导对图像位应用掩码。所以我也在使用字节数组。如何根据子图像的宽度、高度和原点找到计算出的椭圆中包含哪些字节?下面是我根据矩形 selection 获取子图像的代码(供参考):
@Override
public void mouseReleased(MouseEvent e) {
if (subWidth != 0 && subHeight != 0) {
try {
//numCols * (numRows - 1) + xPos
int startPos = img.getWidth() * (img.getHeight() - 1) + mouseAnchor.x;//the starting position for the total byte array of the original image. The mask will start here.
Main.setStartingPos(startPos);
Main.setSubImage(img.getSubimage(mouseAnchor.x, mouseAnchor.y, Math.abs(subWidth), Math.abs(subHeight)));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(Main.getSubImage(), "bmp", baos);
Main.setImageRegion(baos.toByteArray()); //sets the region bytes in the Main class
Main.generateImageMask();//generates the mask after everything's been calculated.
} catch (IOException ex) {
Logger.getLogger(SelectionRectangle.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
如果有任何方法可以让我的问题更清楚,请告诉我。
对于轴对齐的椭圆使用参数方程(中心)
x = x0 + rx*cos(a)
y = y0 + ry*sin(a)
x0,y0
为椭圆中心
rx,ry
是半轴尺寸(矩形边的一半尺寸)
a
是你要获取的点的角度
区域一般按角度区间选择。角度通常由从中心 (x0,y0
) 到实际鼠标位置 (mx,my
) 或某个控制点的直线确定,如
ai = atan2(my-y0,mx-x0)
所以 a = < a0,a1 >
其中 ai = { a0,a1 }
是你的间隔角度。对于全椭圆 a =< 0,2*M_PI> [rad]
这只是角度的圆近似值,所以如果您想获得更精确的角度,请查找
- solving Kepler equation ...
或应用 circle/ellipse 修正比例 ...
你可以从矩形中得到椭圆,如下所示:
Ellispe2D.Double el=new Ellispe2D.Double(x, y, width, height);
然后就可以把椭圆下面遮住的位置屏蔽掉了,如下:
Rectangle r=el.getBounds();
for(i=0; i<r.width; i++)
for(j=0; j<r.height; j++)
if(el.contains(r.x+i, r.y+j)) ... do whatever with this pixel add it to a list etc
--
对于像素 r.x+i、r.y+j,您可以获得 RGB 并从中获取各个字节:
int pixel=image.getRGB(r.x+i, r.y+j);
int red=(pixel&0x00ff0000)>>16, green=(pixel&0x0000ff00)>>8, blue=pixel&0x000000ff;
我正在制作一个有点像 Paint
light 的程序,我已经到了我希望用户能够 select 椭圆区域的地步。我最初的想法是,一定有某种方程可以让我根据矩形的宽度和高度构造一个椭圆。但是,到目前为止,我还没有发现任何如此直接的东西。
这是我的代码,用于在用户拖动鼠标时 select 设置一个矩形区域(位于 MouseAdapter 内):
@Override
public void mouseDragged(MouseEvent e) {
dragPoint = e.getPoint();
if (selectionType.equalsIgnoreCase("Rectangle")) {
int width = dragPoint.x - mouseAnchor.x;
int height = dragPoint.y - mouseAnchor.y;
subHeight = height;
subWidth = width;
int x = mouseAnchor.x;
int y = mouseAnchor.y;
if (width < 0) {
x = dragPoint.x;
width *= -1;
}
if (height < 0) {
y = dragPoint.y;
height *= -1;
}
selectionPane.setBounds(x, y, width, height);
selectionPane.revalidate();
repaint();
}
}
SelectionPane
是扩展 JPanel
的自定义 class 的实例。我的想法是,我想从 selected 区域绘制一个填充的椭圆,这样用户就可以看到他们 selected 的内容。
在这个程序的第二部分,我也遇到了一些困惑。在用户制作他或她的 selection 之后,我想使用 selected 区域作为指导对图像位应用掩码。所以我也在使用字节数组。如何根据子图像的宽度、高度和原点找到计算出的椭圆中包含哪些字节?下面是我根据矩形 selection 获取子图像的代码(供参考):
@Override
public void mouseReleased(MouseEvent e) {
if (subWidth != 0 && subHeight != 0) {
try {
//numCols * (numRows - 1) + xPos
int startPos = img.getWidth() * (img.getHeight() - 1) + mouseAnchor.x;//the starting position for the total byte array of the original image. The mask will start here.
Main.setStartingPos(startPos);
Main.setSubImage(img.getSubimage(mouseAnchor.x, mouseAnchor.y, Math.abs(subWidth), Math.abs(subHeight)));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(Main.getSubImage(), "bmp", baos);
Main.setImageRegion(baos.toByteArray()); //sets the region bytes in the Main class
Main.generateImageMask();//generates the mask after everything's been calculated.
} catch (IOException ex) {
Logger.getLogger(SelectionRectangle.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
如果有任何方法可以让我的问题更清楚,请告诉我。
对于轴对齐的椭圆使用参数方程(中心)
x = x0 + rx*cos(a)
y = y0 + ry*sin(a)
x0,y0
为椭圆中心
rx,ry
是半轴尺寸(矩形边的一半尺寸)
a
是你要获取的点的角度
区域一般按角度区间选择。角度通常由从中心 (x0,y0
) 到实际鼠标位置 (mx,my
) 或某个控制点的直线确定,如
ai = atan2(my-y0,mx-x0)
所以 a = < a0,a1 >
其中 ai = { a0,a1 }
是你的间隔角度。对于全椭圆 a =< 0,2*M_PI> [rad]
这只是角度的圆近似值,所以如果您想获得更精确的角度,请查找
- solving Kepler equation ...
或应用 circle/ellipse 修正比例 ...
你可以从矩形中得到椭圆,如下所示:
Ellispe2D.Double el=new Ellispe2D.Double(x, y, width, height);
然后就可以把椭圆下面遮住的位置屏蔽掉了,如下:
Rectangle r=el.getBounds();
for(i=0; i<r.width; i++)
for(j=0; j<r.height; j++)
if(el.contains(r.x+i, r.y+j)) ... do whatever with this pixel add it to a list etc
--
对于像素 r.x+i、r.y+j,您可以获得 RGB 并从中获取各个字节:
int pixel=image.getRGB(r.x+i, r.y+j);
int red=(pixel&0x00ff0000)>>16, green=(pixel&0x0000ff00)>>8, blue=pixel&0x000000ff;