In a vector graphics program I am writing using Java, ideally any shape would be represented by a modified form of the Path2D class, which uses quadratic Bezier curves. Ideally ellipses would be represented as Path2D objects as well. There is heavy documentation on the internet for approximating quadrants of a circle using cubic Bezier curves, but using the Path2D class, cubic Bezier curves are not possible. I have been using Desmos to try to find an approximation of the octant of a circle, and the middle point (between the two control points) for a circle of radius 1 centered at (0, 0) is approximately (0.993, 0.412). Surely there is some irrational number that can more precisely be expressed as a formula using square roots or trigonometric functions.
I have attempted using the formula 4*tan(pi/(2*n))/3. Either that formula does not apply to octants or it was poorly explained where I found it.
t would help if you said where you found it - the formulae for arbitrary angles (which obviously includes octants, just plug in PI/4 as your angle) are rather different from what you show. Find the real formulae, and explanation, over on https://pomax.github.io/bezierinfo/#circles.
Quadratic curves are dead simple in the sense that the control point is a linear intersection of the end point tangents. So, given start point (1,0) with vertical tangent (because it's a circle, that's how circles work) and end point (cos(phi), sin(phi)) for some angle phi, with tangent (sin(phi), -cos(phi)), we can determine the control point for this curve as:
Cx = cos(phi) - b * sin(phi)
Cy = sin(phi) + b * cos(phi)
where:
cos(phi) - 1
b = ------------
sin(phi)
(The actual maths here is explained in the link above).
Plugging in PI/4 to compute the first octant means we get:
Cx = 1 (obviously; it's a vertical tangent, so the x coordinate is fixed)
Cy = sqrt(2) - 1
And you're done: you don't need to derive any other values, because all the other octants are just reflections of these values that you literally just write out on some paper by drawing a circle, draw lines to show octants, mark the first octant with its coordinate values, and then go "oh, obviously the other coordinates are: ..." -- also the above formulae are for circles with radius 1, but you know how to multiply so you know how to scale the values so that they match your desired circle.
I would be curious why you want quadratic curves, though, because they're objectively pretty terrible compared to cubics. For example: you need 16 points to model a circle with quadratic octants, whereas you only need 12 points for cubic quarters, which have higher precision.
Also, even if you're dead set only ever using quadratics, users of your software might move to other software. They expect cubics to be available to the point where they will petition you for them if the rest of your software is worth using. Plan for that, or ideally just support quadratic and cubic from the start. After all, SVG etc. already do.
Related
The following problem im working on is for one of my favorite past-times: game development.
Problem:
We're in 3D space. I'm trying to determine if a line between two vectors in said space is passing through a circle; the latter of which consists of: center vector, radius, yaw & pitch.
In order to determine that, my aim is to convert the circle to a plane which can either be infinite or just have the diameter of the circle for all it's sides.
Should the line between the two vectors in fact pass through that plane, i am left with the simple task of determining wether that intersection point is within the radius of the circle, in which case i can return either true or false.
What's already working:
I have my circles set up and the general framework is there. The circles are appearing/rendered in the 3D space exactly as specified, great!
What was already tried:
Copied some github gist codes and tried to make them work for my purposes. I kinda worked, sometimes at least. Unfortunately due to the nature of how the code was written, i had no idea what it was doing and just scrapped all of that.
Researched the topic a lot, too. But due to me not really understanding the language people speak when talking about line/plane intersections, i could have read the answer without recognizing it as such.
Question:
I'm stuck at line intersections. No idea where to go and how it works logically! So, where do i go from here and how can one comprehend all of this?
Note:
I did tag this issue as "java", but i'm not looking for spoon-fed code. It's a logical issue i'm trying to get past. If explained well enough, i will make the code work with trial and error!
Say if your circle is a circle in the XY plane with its centre on (0,0,0) and radius 1. How would you solve that?
You would check the values of X and Y when Z is equal to zero. And X squared plus Y squared would be less than 1 (radius squared) if the line passes through the circle.
In other words, you could transform the 3D coordinates to a simpler reference frame. So I think you need to learn transformation of 3D coordinates, which is really not too hard to do. You need to rotate the 3D space around until the centre vector only has a Z component, and yaw and pitch are zero. And then offset the coordinates so the circle centre is in (0, 0, 0). Then apply the same transformation to the line. You could lastly scale by radius, but to be honest that is not so important since the circle math is easy.
I have a position given in decimal degrees (x.xxxxxxxx and y.yyyyyyyy). I need to draw a rectangle around it. The center of the rectangle matches the position. The dimensions of the rectangle is given in meters and it has a rotation ranging from 0-360 degrees.
Question
How can I calculate the four corners of the rectangle and return the result as four decimal degree values? Like arrayOf<LatLon> getRectangle(LatLon position, int rectWidthCm, int rectLengthCm, double rectRotation).
Example
I have a position given in LatLon format with two two values: latitude and longitude. We will assume this location is precise.
The main task is to draw a rectangle based on this position in a Google Maps chart. The rectangle can have any dimentions but let's use these in this example: Width = 0.9 meter and Length = 1.2 meters. Any heading may also be given so lets use this heading: 45. 0 Is north and going clockwise round (east = 90, south = 180 and west = 270). When the rectangle is pointing north it has the length in the north/south direction. Finally, the rectangle center should be equal to the given position.
Note: The project setup is an Android application with Kotlin support and a google maps chart. I am interested in a modern approach to this problem. Regarding precision loss it should at most be within centimeters.
I understand that you are looking for a function geo_rect(x,y,w,h,a) with the following parameters
x is the longitude according to WGS84
y is the latitude
w is the width of the rectangle in meters
h is the height of the rectangle in meters
a is the angle to which the rectangle is turned from w being horizontal (meaning pointing exactly West to East). I suggest to allow values ranging within the open interval (-90°,90°) as this makes the math either to understand.
Your function getRectangle(LatLon position, int rectWidthCm, int rectLengthCm, double rectRotation) deliver all the required information, you need a small wrapper function which determines w, h, and a from rectWidthCm, rectLengthCm and rectRotation, with the latter being within [0°,360°).
The function geo_rect() will return an arrayOf<LatLon> of length four, namely the coordinates of all four corners, starting on the top left and then going clockwise. We will refer to the points as P_NE,P_NW,P_SE, and P_SW respectively.
Assumptions
In order to keep things mathematically feasible, we make some assumptions
We assume that we can use as approximation that the rectangle is a plane, which is okay if w ~ h << r with r = 6378 km being the radius of the Earth.
We further assume that the Earth is a ideal sphere rather than an ellipsoid or even more bumpy. For an accessible article on that issue, see e.g. Zachary C. Eilon's blog
Basic structure of the algorithm
The algorithm could be structured as follows:
Determine the distance d from (x,y) to all four end points. Because of our first assumption we can use simple Euclidian geometry rather than intricate Spherical geometry. Pythagoras holds: d^2 = (w/2)^2 + (h/2)^2.
We also need the four bearings, e.g. b_NW for the angle between the vector pointing to the North Pole and the vector pointing from (x,y) to point P_NW.
Given the information (x,y,d,b_NW, b_NE, b_SW, b_SE) from the previous steps, we can now follow Get lat/long given current point, distance and bearing to calculate the position of all four points. This is the mathematically hard part where I suggest to use a well-established and tested library for.
Last but not least, let us double-check whether the calculation went well by evaluating Great circle distances between some or all pairs of points. For instance d(P_NE,P_NW) should approximately be w, d(P_NW,P_SW) should approximately be h. Don't be surprised if there is actually a difference - this errors are due the assumptions we made. Normal GPS under usual conditions will anyhow not allow you to determine your position up to the centimeter, you will need DPGS for that.
Further reading
At https://www.movable-type.co.uk/scripts/latlong-vectors.html you can experiment online to determine a destination point along a great-circle given the distance and bearing from a start point (in our case: the center of the rectangle).
Old, but amazingly documented and well tested tool kit for geo-applications in general are the https://www.generic-mapping-tools.org/ - you might want to look at the command gmtvector.
If you are looking for java implementations, I found e.g.
https://introcs.cs.princeton.edu/java/12types/GreatCircle.java.html on of many implementations for calculating great circle distances
Need a standalone Java library for performing spatial calculations on lat/lon data
Calculate point based on distance and direction
I've looked many places and haven't found any resources (that I understand) that explain how to turn the standard Midpoint circle algorithm (which uses octants to create the whole circle) into only considering a specific 'slice' of the circle. I'm using this to find the tiles within a line of sight radius.
the code I'm using is the basic Wikipedia code of how to implement the algorithm.
I'm using java inside "Processing" to prototype things out.
I'm trying to understand how this algorithm works so I can modify it, but I'm having trouble.
The midpoint algorithm or Bresenham algorithm can be extended with a condition if the point you are rasterizing falls into the range you have specified by the angles (points). To get the range you would have to find the starting and ending point on the circle. This can be easily accomplished with help of polar coordinates. If we have a circle with radius r, angle theta and center C(x0,y0) the point on the circle can be computed as pCircle(x,y) = (x0 + r * cos theta, y0 + r * sin theta). Note that the angle is in radians.
I am programming on a 2D castle defense and I faced a problem today that I was not able to find a good solution for. See the following picture:
http://imgur.com/zOe2Muv
I want to find the closest possible position to place the red rectangle in this field of rectangles without overlapping any rectangles. By closest possible position I mean the position closest to the current mouse position, so generally the closest possible position to any given point.
What is the right algorithm for that problem?
Thanks!!!
This is an optimization problem where your constraints are linear and your objective function is (piecewise) quadratic or linear, depending on how you want to define distance from the cursor.
Assuming that the rectangles are defined by
x_i, y_i, w_i, h_i for i=1..n
and the red rectangle has size w, h, the decision variables are the x, y position for the red rectangle.
The non-overlapping constraints are then:
x >= x_i + w_i or y >= y_i + h_i or x <= x_i - w or y <= y_i - h for all i=1..n
There are multiple ways you could define your objective (the distance of the red rectangle from the cursor):
proper Eucledian squared distance between the cursor and the nearest point of the red rectangle (results in a piecewise quadratic function I think)
the Eucledian squared distance from the center of the red rectangle (quadratic)
Manhattan distance from the center of the red rectangle (piecewise linear)
Then you could use a quadratic programming solver or MILP (mixed-integer linear programming) solver to find the answer. If the number of rectangles is not too big (say less than a hundred) then it would be quite fast I think even with free solvers like GLPK or LP Solve.
Note that to express the constraints properly for these solvers, you might have to transform the constraints and the objective, for example use the big M method for the constraints, or transform your problem to linear objective. This means you will have additional binary variables, and a couple of more constraints (the number of additional variables and constraints will be proportional to the number of rectangles).
I want to generate N points within a square (uniformly).
how i can achieve this ?
Pretty cool problem, and a lot harder than I imagined but here's the idea. There are papers on this for n-gons but I will just do the square. So uniform distribution from a circle is a common problem and you can't just sample the radius, r, and the angle, theta, independently since more weight is given to a large radius, ie if we take an infinitismally small annulus, you have more area coming from a larger radius further away from the center so we sample uniformly from r^2 since the area is a function of r^2.
Now the idea is similar for a rectangle, its symmetry lends itself to be captured with a some measure of rotation (angle) and distance from origin (radius) but notice that the radius changes dramatically as you rotate about a circle, goes up then down then up then down. we need a way to prescribe the radius based on the angle so its mass at about any given point is uniform.
Consider the following construction (we can orient the square such that it sits on one of its sides but this is more intuitive) Sorry my diagrams are badly drawn
A
X
B O C
D
Here is our square, with A,B,C,D being the corners and O being the origin. We'll explain X later. Let's start at the point C and rotate counterclockwise and the angle will be denoted Theta. X is the point of intersection with the edge of the square if we draw a line from O with angle Theta. In other words, X = r(Theta). What we are trying to do is capture the distance r as a function of theta as to make this a uniform probability distribution of Theta. That's the whole idea..
we can write the following with the law of sines
Sin(pi - Theta - pi/4)/c = sin(pi/4)/r(Theta) where C sits at (c,0)
do some algebra and arrive at
r(Theta) = sqrt(2)*c / (2sin(3pi/4 - Theta)
now we need a constant k such that integrating k*r(Theta) will give you 1, which you can easily do.
I got
a*sin(pi/4)ln|tan((Theta+pi/4)/2)| evaluated from 0 to pi/4
you've successfully build the p.d.f. (probability distribution function) for your r(Theta), now calculate the c.d.f. (cumulative distribution function), set it to uniform and get a closed form expression for your Theta.
up to now we've constructed the random Theta, to build the radius r, realize that much like a circle we have more mass further away and we can construct it as
R = r(Theta)/s where s is uniform from 0 to 1.
we use r(Theta) because it's the max possible value given Theta.