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))
Related
I have an XYLineChart and I want to customize the shape of nodes into rings.
Like this:
Here is the code how I try to done this:
Ellipse2D bigCircle = new Ellipse2D.Double(-4, -4, 8, 8);
Ellipse2D smallCircle = new Ellipse2D.Double(-2,-2,4,4);
Area ring = new Area(bigCircle);
ring.subtract(new Area(smallCircle));
Shape ringShape = (Shape)ring;
renderer.setSeriesShape(0, ringShape);
But the result is like in the left image. It is like this renderer.setSeriesShape(0, bigCircle);
What I am doing wrong?
or
Exist a factory with shapes which include my shape?
My code is fine, but the problem is from line. How #samabcde said.
I made a bigger ring to see what exactly is.
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
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, ...?
Is there a clean Java method for merging the points of two given overlapping polygons into one polygon?
What you want is a Convex Hull Algorithm it will take a set of points and return a minimal set of points that encloses the original points. This can be done in n.log n time.
The Area class supports addition of closed polygons.
Convex Hull is different from adding. Adding means making a polygon that looks like the two polygons overlapped which is not necessarily convex.
You can use JTS (Java Topology Suite) for that.
Create your Polygon objects
Use the union method which will return a Set of all points from both polygons
Simple code example:
Given Polygon 1 (as WKT): POLYGON ((0 0, 0 10, 10 10, 10 0, 0 0))
Given Polygon 2 (as WKT): POLYGON ((5 5, 15 5, 15 15, 5 15, 5 5))
// create polygons
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)});
Polygon p2 = new GeometryFactory().createPolygon(new Coordinate[]{new Coordinate(5,5), new Coordinate(15,5), new Coordinate(15,15), new Coordinate(5,15), new Coordinate(5,5)});
// calculate union
Geometry union = p1.union(p2);
// print as WKT
System.out.println(union.toText());
The result is a new polygon:
POLYGON ((0 0, 0 10, 5 10, 5 15, 15 15, 15 5, 10 5, 10 0, 0 0))
Using the algorithm #Charles Keepax provided, you can do something like this:
public static Polygon mergePolygons(Polygon a, Polygon b) {
// create arrays for border of each polygon
Point[] a_pts = new Point[a.npoints];
Point[] b_pts = new Point[b.npoints];
// fill them in an array of Points instead of separate coords.
Arrays.setAll(a_pts, i -> new Point(a.xpoints[i], a.ypoints[i]));
Arrays.setAll(b_pts, i -> new Point(b.xpoints[i], b.ypoints[i]));
// first merge 2 arrays into 1
Point[] all_pts = (Point[]) mergeArrays(a_pts, b_pts);
// apply Convex Hull on resulting array
convexHull(all_pts, all_pts.length);
// separate x and y coordinates back
int[] x_pts = new int[all_pts.length];
int[] y_pts = new int[all_pts.length];
Arrays.setAll(x_pts, i -> all_pts[i].x);
Arrays.setAll(y_pts, i -> all_pts[i].y);
// return polygon object using those coordinates
return new Polygon(x_pts, y_pts, all_pts.length);
}
But of course solution by #Lars is more practical, this is how you could do it in a naive way.
I'm developing project using java to identify components using opencv package but I'm new to javacv and I just want to know how to identify rectangles in a particular source image please can some experience person give some basic guide line to archive this task. I try to use template matching on here but it can identify exact size rectangle only. But In my case I need to identify variable length rectangle ?
import java.util.Arrays;
import static com.googlecode.javacv.cpp.opencv_core.*;
import static com.googlecode.javacv.cpp.opencv_imgproc.*;
import static com.googlecode.javacv.cpp.opencv_highgui.*;
public class TestingTemplate {
public static void main(String[] args) {
//Original Image
IplImage src = cvLoadImage("src\\lena.jpg",0);
//Template Image
IplImage tmp = cvLoadImage("src\\those_eyes.jpg",0);
//The Correlation Image Result
IplImage result = cvCreateImage(cvSize(src.width()-tmp.width()+1, src.height()-tmp.height()+1), IPL_DEPTH_32F, 1);
//Init our new Image
cvZero(result);
cvMatchTemplate(src, tmp, result, CV_TM_CCORR_NORMED);
double[] min_val = new double[2];
double[] max_val = new double[2];
//Where are located our max and min correlation points
CvPoint minLoc = new CvPoint();
CvPoint maxLoc = new CvPoint();
cvMinMaxLoc(result, min_val, max_val, minLoc, maxLoc, null); //the las null it's for
optional mask mat()
System.out.println(Arrays.toString(min_val)); //Min Score
System.out.println(Arrays.toString(max_val)); //Max Score
CvPoint point = new CvPoint();
point.x(maxLoc.x()+tmp.width());
point.y(maxLoc.y()+tmp.height());
cvRectangle(src, maxLoc, point, CvScalar.WHITE, 2, 8, 0); //Draw the rectangule result in original img.
cvShowImage("Lena Image", src);
cvWaitKey(0);
//Release
cvReleaseImage(src);
cvReleaseImage(tmp);
cvReleaseImage(result);
}
}
Please can some one help to accomplish this
(So it is fixed as square.)
For square detection, OpenCV comes with some samples for this. Codes are in C++, C, Python. Hope you can port this to JavaCV.
C++ code , Python Code.
I will just illustrate how it works:
1 - First you split the image to R,G,B planes.
2 - Then for each plane perform edge detection, and in addition to that, threshold for different values like 50, 100, .... etc.
3 - And in all these binary images, find contours ( remember it is processing a lot of images, so may be a little bit slow, if you don't want, you can remove some threshold values).
4 - After finding contours, remove some small unwanted noises by filtering according to area.
5 - Then, approximate the contour. (More about contour approximation).
6 - For a rectangle, it will give you the four corners. For others, corresponding corners will be given.
So filter these contours with respect to number of elements in approximated contour that should be four, which is same as number of corners. First property of rectangle.
7 - Next, there may be some shapes with four corners but not rectangles. So we take second property of rectangles, ie all inner angles are 90. So we find the angle at all the corners using the relation below :
And if cos (theta) < 0.1, ie theta > 84 degree, that is a rectangle.
8 - Then what about the square? Use its property, that all the sides are equal.
You can find the distance between two points by the relation as shown above. Check if they all are equal, then that rectangle is a square.
This is how the code works.
Below is the output I got applying above mentioned code on an image :
EDIT :
It has been asked how to remove the rectangle detected at the border. It is because, opencv finds white objects in black background, so is border. Just inverting the image using cv2.bitwise_not() function will solve the problem. we get the result as below:
You can find more information about contour here : Contours - 1 : Getting Started