I'm in the process of writing a "Paint" application in Java consisting of rectangular nodes and undirected edges. The problem is that the beginning of the edge is in the center of the rectangle the edge is connected to, and the end of the edge is in the center of the other rectangle this edge is connected to.
To avoid drawing the intersection between the rectangle and the edge, I draw edges first and nodes afterwards, so that they are placed on top of the edges, thus hiding the intersection.
The problem arises when another node, which does not correspond to that edge is placed along the edge. In this scenario, because edges are drawn first, the node appears on top of the edge. However, that is not what I want. I want the edge to show on top of the node.
Images:
how it is and how it should be
The most comprehensive way I can think of to fix this would be to draw nodes first and afterwards draw the edges avoiding the intersections of the edge with the two nodes it is connected to. However that is difficult to do on paper because I draw edges using drawLine, and I do not have the possibility to check for intersections.
This is why I draw edges first, but then the problem I mentioned arises. Any ideas?
What you need is a solution to problem #1. You need to "move" the edge's endpoints away from the center of the rectangle. That way you won't have to draw the nodes last and automatically solve your question at hand.
My proposed solution in Step 2 only works if the connecting nodes are left and right of each other, otherwise you need slightly more advanced math of which I made a start in Step 2.1.
Step 1: an edge is nothing more than two Points where a Point is just an x and y value. Find the left and right ends of the edge by comparing the x of each edge. We'll save this as xLeft, xRight, yLeft and yRight for simplicity. Maybe you have something else for this, but you get the idea.
Step 2: move the xLeft half the width of the rectangle to the right and subtract half the width of the rectangle from xRight.
(Optional) Step 2.1: in case two connecting nodes are above each other, you can use Math.atan2(yRight-yLeft, xRight-xLeft) to calculate the angle. If the value is in the lower spectrum (between -3pi/4 and -pi/4) add and subtract half the height of the rectangle on the respective y values. You can fiddle around with this to create the math and logic for all 4 directions if you want.
Step 3: draw the new edges after having drawn the nodes. The edges are now "connected" to the edge(s) of your rectangles.
Feel free to ask questions, although I suggest you try putting this into code first.
Related
How to invert Y axis? When I touch on bottom or top of the screen, the Y value is opposite I want
You can't invert an axis per se. You see, in computer graphics, the 2D coordinate system is a bit different from the canonical one taught at school in maths. The difference is that in computer graphics the y-axis is in the opposite direction, that is, from the origin to the bottom it has positive values and from the origin to the top it has negative values. Also, the origin is at the top left corner of the screen. If you can't get used to it then you can always take the opposite value to what you get, for this, asume ycoord holds the value obtained then you can do ycoord = -ycoord and that will get you the value as you're used to. Also, if you want the origin to be in the bottom left corner then you should check your y-coordinate, if it's positive then substract the vertical resolution to it, and if it's negative then add the vertical resolution to it.
But keep mind that you're going against the standard definition for coordinate systems in computer graphics.
I would say this is a duplicate questions of this one:
Move a shape to place where my finger is touched
Check on my answer there, so I won't repeat my self.
Or in short - use camera.unproject() method to get world coordinates from screen coordinates.
I'm building a prototype android app and I'm trying to make a circular layout. Basically, I have a centre point, and I want to be able to place other elements in a circle around it, like this. There's a library called ArcLayout that I tried using, and it works well, but it doesn't quite work for what I want to do. The elements I'm trying to place have a dynamic distance from the centre, and may have similar or identical distances at any given time.
I could just create a new arc layout for each distance level, but I'm trying to avoid something like this. Ideally, each element in the layout should position itself at a maximum distance from all other elements, while staying at the correct distance from the centre.
I've looked up a lot of different things from radar graphs, to orbiting animations, and none of them seem to work with what I want to do. How would I go about making something like this?
Here is a high level description of how I would do this:
Make your original view extend View class. In your ondraw method, do the following:
first draw the circle in the center of the view by getting the coordinate for the small circle by getWidth()/2, getHeight()/2. set some fixed radius. Store the center as cx,cy
Now, you need to draw other circles at the right position, for that you need the center of each circle. Now, from cx,cy if you have the angle it makes with x - axis and the distance from cx,cy to the new point, you can get the coordinates to the new points as follows:
cx1 = cx + r*cos(theta) and cy2 = cy + r*sin(theta).
where r is the distance between the points and theta is the angle between line joining the points and the positive x-axis.
Just remember to convert degrees to radians in your calculations.
Once you get coordinates for the new circle, just draw it using canvas.drawCircle method.
Repeat this method as often as needed.
I am making a game in which the user player places circles on the screen. It is important that the circles never overlap, so I need to figure out the nearest possible free spot from the cursor. I have found circle packing algorithms, but they do not seem a fit for my problem. I have also solved a similar problem in the past for boxes (here), but with circles, I cannot seem to figure it out.
I figured out how I can find the nearest free position when it intersects with one circle, or even when two are involved. However, I cannot find a robust algorithm that can deal with complex cases that have any number of circles in any arrangement.
Precise description of problem:
I have a 2D space with any number of non-intersecting circles, all with identical radii (though that may not matter). I want to find a position for the next circle that will make it not intersect with any other circle, and which center [x,y] is nearest to a specified location [x,y].
Suggestions of any kind appreciated (references, approaches, or (Java) libraries).
p.s. Bonus points if the solution includes making sure the circle stays within a specific bounding box (i.e. display).
My final solution: (based on David Wallace's suggestions)
Calculate the minimal distance between the centers of two circles (in my case, all circles are the same size, so always 2*radius)
Make a list of all circles that are closer to the mouse position than the minimum distance
If 0 overlaps: all good!
If 1 overlap: move the new circle's center to the minimum distance from the compared circle's center, along the vector that runs from compared circle's center to mouse position
If 2 overlap: find out where the two overlapping circles intersect. Place the new circle on the intersection closest to the mouse position. If this position still overlaps with any circle, move to the other intersection. If that one doesn't work, leave the new circle were it is.
If 3 overlap: same as in 2 overlap, just take the two circles closest to the new circle.
Note that this does not work perfectly, but good enough in my case, where a user is dragging the new circle on the screen. It works in most cases and in those it doesn't, usually when there are many circles very close together, the new circle simply stays in the last position (which was valid). The user can then decide to drag it a fit further and be more precise in where he wants the new circle to go.
This isn't a complete answer, but you may be able to make it into one.
Suppose you've already placed circles of radii r1, r2, r3 ... rn with centres C1, C2, C3 ... Cn, and you're looking to place a new circle of radius rz, the new circle's centre will have to be outside all of a set of "enlarged" circles, centred at C1, C2, C3 ... Cn; with radii (r1+rz), (r2+rz), (r3+rz) ... (rn+rz). So if the cursor is at point P, then there are some cases to consider.
(1) If P is not in any of the enlarged circles, then the problem is solved.
(2) If P is in just one of the enlarged circles, then move outwards along a radius of that circle, until you either reach a point that's outside all of the enlarged circles, or until you reach another enlarged circle. The former case reduces to scenario (1); the latter reduces to scenario (2). Pick an arbitrary direction if P happens to be the centre of the circle.
(3) If P is in several of the circles, then find the directions from P to each centre of a circle that it's in. Find the pair of directions that have the widest interval between them, and bisect that angle, to work out which direction to head along. For example, if the directions to the centres of the circles are 30deg, 120deg and 330deg, then bisect the angle between 120deg and 330deg - then head in a direction of 225deg. Head in that direction until you reach the edge of a circle, then recalculate. Keep doing this until you get back to scenario (2).
The thing that I can't work out is what to do if you get stuck in scenario (3). Maybe only allow a certain number of steps, then exit. After all, it's possible that there's no suitable place to put the circle.
To calculate the distance between a point and a circle is with the center, considering your Circle class is like this one:
public class Circle{
int x;
int y;
int radius;
}
public interface CircleHelper{
public int distanceBetweenCircleAndPoint(Circle c, Point p);
public int distanceBetweenTwoCircles(Circle c1, Circle c2);
}
First of all, I would think about using Quadtrees and check if there is any quad without surrounding circles
The quadtree deep can be selected considering the radius of the circles.
so if you have a point in one of the quads, you would look to its surrounding quads to check if there is any circle there and move from the point in the direction of empty quads.
I hope you understand my approach
Here is a solution that will work for varying radiuses, and can be simplified if all radiuses are equal, as in your case. We first transform the problem slightly. Instead of fitting a circle among other circles, we extend the radiuses of all other circles by the radius of our circle to place, and instead try to place a point outside of these extended circles. This is equivalent to the original problem. We proceed as follows:
First a special case. If the point is outside of all circles, we have a trivial solution.
Find all the circles the point is inside. Calculate the closest point on their circumference (just move out from the original point along the radius).
Find all the intersection points between pairs of circles.
Combine the sets of points from steps 2 and 3, and filter these by finding the ones that are not covered by any other circle.
Pick the closest point from the remaining set. Done!
This seems to be O(n^3), so not terribly fast, but should be doable if your set is not too huge.
I am building a Java application that is going to feature two circles of random sizes that need to be clicked by the user. The time between the click on the first and the second circle is going to be measured. Unfortunately, since I am new to Java so things have been slow for me. Currently I have my application draw circles and measure time between clicks using System.nanoTime() but now I am running into a problem.
Because the circles need to be a fixed distance away from eachother I want to use the center of the circles as the origin points. So basically I want to be able to provide coordinates for the circle so that the center of the circle should be at those coordinates. The distance between the circles then describes the distance between the centers. My circle currently is embedded into a JPanel but if I set the JPanel's position it moves the top left to that position.
Of course I have done some searching read that I may need to play around with either AffineTransform or Graphics2D.translate() which I have tried in paintComponent() but this got a bit confusing so then I tried to override setlocation and subtract the radius from the position. It sort of works but it is not the most clean solution. Can aonyone give me some pointers on how to do this?
Thanks in advance.
If I understand the problem statement, all such pairs of circles will lie on opposite sides of a circle centered in the enclosing panel, as shown here. Simply choose a random 0 ≤ θ < π and find its opposite at π - θ. Note how the example's rendering scales as the panel is resized.
As an aside, the example uses setPreferredSize() to establish the dimensions of the drawing panel, but you may want to override getPreferredSize() instead.
Addendum: The example uses fillOval() to render the circles, but you can use draw() with any desired Shape; the latter provides several contains() methods suitable for hit testing, as mentioned here.
You have the coordinates for the two center for the circle (x1, y1) and (x2, y2).
The size of the radius is random.
Once you have the radius of the two, r1 and r2, simply position them at (x1-r1, y1-r1) and (x2-r2, y2-r2).
You can use java.awt.Point to represent the center, and use
center.translate(-radius, -radius)
and use the new translated value as position for the drawing.
Maybe you think it is not a clean solution, but why not? Everything in Java is painted by giving the top left corner for the position, so is the use of the center that is not clean :).
To calculate the left top position by doing -radius is clean :)
I have a program that needs to take in a photo taken by an iphone (or any kind of decent camera) of a 7x10 grid with a thick black boarder around the edges. This image can be received rotated to the right or to the left (there's no need to worry about skew). I have an image of the grid in its original state already, but I need to get the picture that I'm taking in and rotate it to its "perfect/original" state.
Idea 1: Performance Hog/Bad Results
Threshold the picture that I receive and the perfect grid Image I already have. Compare each pixel for 0 rotation, get a total score, and save it. Do do this rotating the image of increments by 1 to 359. The lowest score is the rotation we need to get the picture back to its original state.
Idea 2: Still Unsure How To Go About Doing This
Threshold the picture that I receive and the perfect grid Image I already have. Draw a a line through the center of the picture vertically and horizontally. Find the rotation based on the black pixel count that the vertical and horizontal line passed through. This would require some sort of Trigonometry that I'm not to great with understanding.
Does anyone have any other ideas for getting this working?
Any help for pointing me in the right direction would be greatly appreciated!
Thanks!
Instead of drawing one horizontal and one vertical line, draw instead two horizontal lines (say, each at a third of the picture). Only look at the left halves of these lines and calculate how many black pixels there are on the path of each (a1 and a2). You also have to keep track of the distance between the two red lines, so the number of pixels d.
Using this notation in the figure above, your desired angle is:
alpha=atan2((a2-a1),d)
and a counterclockwise rotation by alpha will bring the white portion of the picture into proper alignment.