If I have two java.awt.geom.Area's made out of the union of various simple Shapes (Polygons and Ellipses), is there a method out there to find the distance (i.e. closest distance) between the two Areas?
To clarify: suppose I have two arbitrary Areas, each of which is created from the union of shapes of any sort:
//Define the first area
Area a = new Area(new Ellipse2D.Double(50, 50, 100, 100));
a.add(new Area(new Rectangle2D.Double(100, 100, 100, 100)));
//Define the second area
Area b = new Area(new Ellipse2D.Double(200, 300, 100, 100));
b.add(new Area(new Ellipse2D.Double(250, 250, 100, 100)));
What I want is a method getDistance(Area a, Area b) that gives me a double representing the shortest distance between any point in Area a and any point in Area b. Here's an image of the above two Areas with a line in blue indicating the distance I'm interested in:
Is there a method out there to do this? If not, how might I implement one?
There doesn't seem to be a method that does that exactly; however, using PathIterators, you should be able to compare point to point along the outline of the shapes and find the distance manually.
http://docs.oracle.com/javase/6/docs/api/java/awt/geom/PathIterator.html
This Wikipedia article describes how you could efficiently implement this to avoid the quadratic obvious implementation.
Use Hausdorff Distance
Check this very clear explanation of how to use hausdorff Distance:
http://cgm.cs.mcgill.ca/~godfried/teaching/cg-projects/98/normand/main.html
Related
There is a Rectangle2D.Double object named rect2d and a Line2D.Double object named line2d.
Please consider the following situation:
Question 1:
What will this line of code return?
boolean intersect = line2d.getBounds2D().intersects(rect2d);
Question 2:
The width/thickness of line2d is 1 pixel. It's height/length is 20 pixels.
What would be the width and height values of the Rectangle2D object returned by line2d.getBounds2D()?
It will return:
false
java.awt.geom.Rectangle2D$Double[x=10.0,y=10.0,w=0.0,h=20.0]
With this code:
Line2D.Double line2d = new Line2D.Double(10, 10, 10, 30);
Rectangle2D.Double rect2d = new Rectangle2D.Double(0, 0, 100, 100);
boolean intersect = line2d.getBounds2D().intersects(rect2d);
System.out.println(intersect);
System.out.println(line2d.getBounds2D());
Although, it's useless to say that a line is 1 pixel, because it can't be other way using Line2D.Double.
Indeed, for Java, this vertical line as a 0-pixel width boundary, so that's why it will never intersect with any other shape. With a non-vertical and non-horizontal line, its bounds intersect.
Do not use bounds to compute intersection, but directly the Shape:
boolean intersect = line2d.intersects(rect2d);
You may check RectangularShape.intersects() Javadoc for more information on how this method computes intersection.
From the docs, here and here, the first would return false and the second a bounding box at least the size of the dimensions of the line.
I have this code:
public void paint(Graphics g) {
g.setColor(Color.black);
g.fill3DRect(myX, myY, 20, 20,true);
g.setColor(Color.red);
g.fillOval(nX, nY, 20, 20);
}
Coordinates of the 2 shapes are given by the user, how can i know if there's a intersection between them?
(I don't need coordinates of the intersection, just need to know if there is or not)
Thanks in advance!
It heavily depends on the context and the actual intention. A very simple solution is to use the Area class: Just create one Area object for each of the shapes that you want to check, and intersect these areas:
Shape shape0 = new Rectangle2D.Double(mxY, myY, 20, 20);
Shape shape1 = new Ellipse2D.Double(nX, nY, 20, 20);
Area a0 = new Area(shape0);
Area a1 = new Area(shape1);
a0.intersect(a1);
if (!a0.isEmpty()) { /* They intersect! */ }
(BTW: You can cast your Graphics object to Graphics2D and then paint the Shape objects directly)
Important : Note that this solution may be very inefficient compared to an analytic solution. If you only have to check "simple" objects (circles, rectangles...) for intersection, you might want to implement an analytic solution, especially if you have to check "many" of these simple objects. The advantage of the Area solution is its simplicity and genericity: It works for arbitrary shapes, even complex shapes like font letters or manually created Path2D objects.
Ok dear folks, i've got this question and i don't really know a certain way to solve it.
I'm doing like a "Paint application" in java, i know everything is ready, but I need to paint the shapes with Computer Graphics Algorithms.
So, the thing is, once the shape is painted in the container how could I convert it like sort of an "Object" to be able to select the shape and move it around (I have to move it with another algorithm) I just want to know how could I know that some random point clicked in the screen belongs to an object, knowing that, I would be able to fill it(with algorithm).
I was thinking that having a Point class, and a shape class, if i click on the screen, get the coordinates and look within all the shapes and their points, but this may not be very efficient.
Any ideas guys ?
Thanks for the help.
Here is some of my code:
public class Windows extends JFrame{
private JPanel panel;
private JLabel etiqueta,etiqueta2;
public Windows() {
initcomp();
}
public void initcomp()
{
panel = new JPanel();
panel.setBounds(50, 50, 300, 300);
etiqueta = new JLabel("Circulo Trigonometrico");
etiqueta.setBounds(20, 40, 200, 30);
etiqueta2 = new JLabel("Circulo Bresenham");
etiqueta2.setBounds(150, 110, 200, 30);
panel.setLayout(null);
panel.add(etiqueta);
panel.add(etiqueta2);
panel.setBackground(Color.gray);
this.add(panel);
this.setLayout(null);
this.setVisible(true);
this.setSize(400,400);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public void paint(Graphics g){
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.red);
g2d.setStroke(new BasicStroke(2));
dibujarCirculo_bresenham(g2d, 50, 260, 260);
dibujarCirculo_trigonometrico(g2d, 50, 130, 200);
}
/*This functions paints a Circle*/
public void dibujarCirculo_trigonometrico(Graphics g,int R,int xc,int yc)
{
int x,y;
for (int i = 0; i < 180; i++) {
double angulo = Math.toRadians(i);
x = (int) (Math.cos(angulo)*R);
y = (int) (Math.sin(angulo)*R);
g.drawLine(x+xc, y+yc, x+xc, y+yc);
g.drawLine((-x+xc), (-y+yc), (-x+xc), (-y+yc));
}
}
I assume that any image is a valid (isn't constrained to a particular set of shapes). To get an contiguous area with similar properties, try using a flood fill.
To colour in or move a particular shape around, you can use flood fill to determine the set of pixels and manipulate the set accordingly. You can set a tolerance for similar hue, etc so that it's not as rigid as in Paint, and becomes more like the magic selection tool in Photoshop.
There are a couple of approaches to take here depending on what precisely you want.
1) is to have objects, one for each drawn thing on screen, with classes like Circle and Rectangle and Polygon so on. They would define methods like paint (how to draw them on screen), isCLickInsideOf (is a click at this point on screen contained by this shape, given size/position/etc?) and so on. Then, to redraw the screen draw each object, and to test if an object is being clicked on ask each object what it thinks.
2) is, if objects have the property of being uniform in colour, you can grab all pixels that make up a shape when the user clicks on one of the pixels by using a floodfill algorithm. Then you can load these into some kind of data structure, move them around as the user moves the mouse around, etc. Also, if every object is guaranteed to have a unique colour, you can test which object is being clicked on by just looking at colour. (Libraries like OpenGL use a trick like this sometimes to determine what object you have clicked on - drawing each object as a flat colour on a hidden frame and testing what pixel colour under the mouse pointer is)
I need to plot a polynomial given a start point and an end point. I've looked at using the paincomponent to do do it, but I'm getting confused because the origin is in the top left corner and I need my grid lines to be dynamic.
How do I make it so I can create a dynamic scale and what java class is best used for plotting a function?
For example if the user were to enter -2 2 x^2 the plotter would need to create a grid that goes from -2 has 0 in the middle and 2 on the right for the x coordinates. However if the user enters x^3 we have negative coordinates in the y plane and I'll need to slide the line containing the x coordinates up to accomidate.
Thanks!
The way I think you could do this(and I may be wrong) is to draw the y-line and x-line of your graph, and label the values for x and y using drawString at the correct position.
To illustrate this I did this example for you:
public void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
Point2D.Double from = new Point2D.Double(300, 100);
Point2D.Double to = new Point2D.Double(300, 300);
Line2D.Double line = new Line2D.Double(from, to);
g2.draw(line);
Point2D.Double from2 = new Point2D.Double(150, 200);
Point2D.Double to2 = new Point2D.Double(450, 200);
Line2D.Double line2 = new Line2D.Double(from2, to2);
g2.draw(line2);
g2.drawString("-1", 290, 215);
}
The drawString method would draw "-1" below 0. So you could use the same thing to draw -2 below -1, etc.
I know this sounds inefficient, but it's the only way I can think of.
Hope someone else will have a better solution for you.
It shouldn't be too difficult to transform the y-coordinate if you know the size of area you want to paint to. But to be honest, why don't you use one of the plotting libs like JFreeChart, ...?
Ok so I have a number of polygons (outlined in white in the image).
In an attempt to add all the polygons together so that I get one polygon, which is the outer bounds of all of them, I have converted each Polygon (java class) to an Area(java class) and then added the areas together with the add(Area a) method provided by the Area class.
From there I converted the area back to a polygon and drew it as a filled Polygon (the purple area in the image).
This however is not what I was expecting. Can anyone think of a was where I can do this correctly, or at least just add the triangle area to my polygon?
When I just draw all the separate polygons with a fill I get what I want (drawn) but I need a Polygon representation of it.
I can recommend to use JTS. Just create your geometries you want to combine and use the union method. Afterwards you can use the new geometry and paint it using your previous code. Simple code example for union:
// build polygon p1
Polygon p1 = new GeometryFactory().createPolygon(new Coordinate[]{new Coordinate(0,0), new Coordinate(0,10), new Coordinate(10,10), new Coordinate(10,0), new Coordinate(0,0)});
// build polygon p2
Polygon p2 = new GeometryFactory().createPolygon(new Coordinate[]{new Coordinate(0,0), new Coordinate(0,30), new Coordinate(5,30), new Coordinate(5,0), new Coordinate(0,0)});
// calculate polygon3 as the union of p1 and p2
Polygon p3 = (Polygon) p1.union(p2);
// print simple WKT
System.out.println(p3.toText());
Output in this case is (like expected):
POLYGON ((0 0, 0 10, 0 30, 5 30, 5 10, 10 10, 10 0, 5 0, 0 0))