Finding a central angle from a circle segment area - center

I'm trying to divide a circle into 2 segments based on 2 percentages. Like a pie chart but creating the segments with a single vertical slice.
I've found this formula for area, but haven't been able to solve for C (central angle) when I know the radius and area:
(R(squared) / 2) * ( ((pi/180)* C) - sin(C) )
Once I've got C I can use cos, tan and R(radius) to find my x and y points on the circle.
At first I thought I could simply multiply 180 * (smallerPercent / 50), but I realized that's a 'no'.

This is a good application for Newton's method. The following C program can easily be modified to
solve the problem. You can change it to calculate the desired area as a percentage of the area of
the circle, or calculate the desired area separately and enter it.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
double chordangle(double r,double a)
{
double x = a/2.0;
do{
x = ((x * r * r / M_PI) - (sin(x) * r * r / 2.0) - a ) /
(r * r / M_PI - (r * r / 2.0) * cos(x));
}while(((x * r * r / M_PI) - (sin(x) * r * r / 2.0 ) - a) > 1e-11);
return x;
}
int main()
{
double a,r;
printf("Enter radius: ");
if(scanf("%lf",&r)!=1)
{
printf("You must enter a number.\n");
exit(1);
}
printf("Enter desired area of slice: ");
if(scanf("%lf",&a)!=1)
{
printf("You must enter a number.\n");
exit(1);
}
printf("The angle in radians is %lf.\n",chordangle(r,a));
printf("The angle in degrees is %lf.\n",chordangle(r,a)*180.0/M_PI);
return 0;
}

I have updated this answer (the original is at the very bottom).
You already know the radius of the circle, it's area (PI * r squared) and the area of the segment you are trying to construct (smallerPercentage / 100 * areaOfCircle).
If I understand the problem correctly, there is no formula to work out the angle that is required to create a segment of a given area and radius.
However all is not lost.
If you knew the angle you could also work out the area with the formula you already have.
A = 0.5 * r squared * ( ((PI/180) * Θ) - sin(Θ)) where Θ is the angle.
So, the only solution is to start making methodical guesses at Θ and see if the area calculated matches what you are expecting (within a certain tolerance).
And given that the percentage will be less than 50 (and greater than 0) then: 0 < angle < 180.
So, I would make my first guess at 90 degrees. If the area is too big guess again at 45, too small try 135. Keep halving the size each time and add or subtract it from the previous angle. Keep narrowing it down until you get an area that is within a tolerance of the area you are expecting. Less than 10 guesses should get you there.
I think this is called the "1/4 Tank dipstick problem": see: Link
I hope this helps.
This was my original answer, before I properly understood what you were trying to do:
I'm not sure I fully understand what you are trying to achieve, but you can work out the angles you want (in degrees) like this:
smallAngle = 360/100 * smallerPercentage;
largeAngle = 360 - smallAngle;
And you can always multiply degrees by (PI/180) to get radians.

Related

circle vs circle sweep test that returns touch point

I'm looking for an algorithm that takes two dynamic circles and returns point of contact. For some reason when trying to search for this I can only find resources like: http://ericleong.me/research/circle-circle/ which describe algorithms that return resulting velocities.
You have not defined problem well.
Let circles centers are moving with equations
cx1 = cx1_0 + t * vx1
cx2 = cx2_0 + t * vx2
cy1 = cy1_0 + t * vy1
cy2 = cy2_0 + t * vy2
where cx1_0 is starting X-coordinate of the first circle, vx1 is x-component of its velocity.
Circles touch each other when center-center distance is equal to the sum of radii. We can use squared values:
(cx1 - cx2)^2 + (cy1 - cy2)^2 = (r1 + r2)^2
Substitute expressions above, open parentheses, solve quadratic equation for unknown parameter t. You can get 0, 1 or two solutions (no interaction, one touching, intersection period exists). Then calculate centers coordinates for moment of touch and get touch point for external touching:
x_touch = (cx1 * r1 + cx2 * r2) / (r1 + r2)
similar for y
Note that I emphasize external because internal touching might occur (in that case distance is equal to the difference of radii, but I think such case is not interesting for you)

Function for Creating Spiral Stripes with Orientation 45 Degrees to Radial?

I am trying to reconstruct the spiral pattern in the depicted image for a neuroscience experiment. Basically, the pattern has the properties that:
1) Every part of the spiral has local orientation 45 degrees to radial
2) The thickness of each arm of the spiral increases in direct proportion with the radius.
Ideally I would like to be able to parametrically vary the number of arms of the spiral as needed. You can ignore the blank circle in the middle and the circular boundaries, those are very easy to add.
Does anybody know if there is a function in terms of the number of spiral arms and local orientation that would be able to reconstruct this spiral pattern? For what it's worth I'm coding in Matlab, although if someone has the mathematical formula I can implement it myself no problem.
Your spiral image does not satisfy your property 1, as can be seen by overlaying the spiral with a flipped copy (the angles at the outer edge are more perpendicular to the radial direction than 45deg, and more parallel at the inner edge):
As I commented, a logarithmic spiral can satisfy both properties. I implemented it in GLSL using Fragmentarium, here is the code:
#include "Progressive2D.frag"
#group Spiral
uniform int Stripes; slider[1,20,100]
const float pi = 3.141592653589793;
vec2 cLog(vec2 z)
{
return vec2(log(length(z)), atan(z.y, z.x));
}
vec3 color(vec2 p)
{
float t = radians(45.0);
float c = cos(t);
float s = sin(t);
mat2 m = mat2(c, -s, s, c);
vec2 q = m * cLog(p);
return vec3(float
( mod(float(Stripes) * q.y / (sqrt(2.0) * pi), 1.0) < 0.5
|| length(p) < 0.125
|| length(p) > 0.875
));
}
And the output:

Is there a way to convert "QRST-code" to longitude/latitude?

I did a lot of research for that topic - but it seems not enough, so I'm here asking for help :-)
Google Maps could use QRST-code for specifing a location. I've got a line like that:
trtqtqsss...
and so on. In some other forums I've found out that GM once used that in an URL-Syntax. But now it seems it doesn't work anymore - or at least I don't know how.
Here is an example of the link that won't work anymore:
kh0.google.com/kh?n=404&v=8&t=tq
kh1.google.com/kh?n=404&v=8&t=tr
In this URL, the quadrants are specified with the string after t=.
Is there a converter or something like that?
Thank you in advance!
Partial answer:
From what I gather, the long string of trtqtqss indicates, in essence, a binary search for the location. It roughly translates like this:
Start with the letter t. This gives you "the sholw world"
Look for your point on the map. If it's in the top left quadrant, add a q. If top right, add r. Bottom right, add s. Bottom left, add t.
Zoom in on the new quadrant. Repeat.
Every time you add a letter you halve the size of the tile, and find a new bottom left corner. If we think of the world map as a rectangle of width and height = 1, we can find a new corner for each character added. This is the essence of the algorithm you linked in your comment.
With that, plus the "Rosetta stone" (again from your link) of a known string-to-satellite image translation, I give you the following code. This will give you the Longitude/Latitude of a point based on your string. Compile it, then pass the string as argument to the executable:
#include <stdio.h>
#include <string.h>
#include <math.h>
double NormalToMercator(double y) {
double pi;
pi = 2 * asin(1);
y -= 0.5;
y *= 2 * pi;
y = exp( 2 * y );
y = ( y - 1 ) / ( y + 1 );
y = -asin( y );
return -y * 180 / pi;
}
int main(int argc, char* argv[]) {
double x=0, y=0, scale=1;
char buf[100]={' '};
int ii;
buf[0]=argv[1][0];
for(ii = 1; ii < strlen(argv[1]); ii++) {
buf[ii-1]=argv[1][ii];
scale *= 0.5;
switch (tolower(argv[1][ii])) {
case 'q':
y+=scale;
break;
case 'r':
y+=scale;
x+=scale;
break;
case 's':
x+=scale;
break;
case 't':
break;
default:
break;
}
printf("the string %s gets you to (x,y): %.9lf, %.9lf\n", \
buf, x, y);
}
printf("the final lat/long is %.5lf, %.5lf\n", 360.0 * (x - 0.5), NormalToMercator(y));
}
The intermediate printf statement is there to show you how the algorithm is slowly making its way to the right location. I tested this with the string from the link in your comment (tsrrtrsqsqqqrqrtsst), and got the coordinates 153.39935ºE 28.32372ºS (note - a negative number for longitude means "W", and a negative number for latitude means "S". I got 153.39935, -28.32372). When I entered those in Google maps, I got the picture of the hospital that you get when entering the link from blog post.

Bezier Curve always the same length

I'm working on a game in HTML5 canvas.
I want is draw an S-shaped cubic bezier curve between two points, but I'm looking for a way to calculate the coordinates of the control points so that the curve itself is always the same length no matter how close those points are, until it reaches the point where the curve becomes a straight line.
This is solvable numerically. I assume you have a cubic bezier with 4 control points.
at each step you have the first (P0) and last (P3) points, and you want to calculate P1 and P2 such that the total length is constant.
Adding this constraint removes one degree of freedom so we have 1 left (started with 4, determined the end points (-2) and the constant length is another -1). So you need to decide about that.
The bezier curve is a polynomial defined between 0 and 1, you need to integrate on the square root of the sum of elements (2d?). for a cubic bezier, this means a sqrt of a 6 degree polynomial, which wolfram doesn't know how to solve. But if you have all your other control points known (or known up to a dependency on some other constraint) you can have a save table of precalculated values for that constraint.
Is it really necessary that the curve is a bezier curve? Fitting two circular arcs whose total length is constant is much easier. And you will always get an S-shape.
Fitting of two circular arcs:
Let D be the euclidean distance between the endpoints. Let C be the constant length that we want. I got the following expression for b (drawn in the image):
b = sqrt(D*sin(C/4)/4 - (D^2)/16)
I haven't checked if it is correct so if someone gets something different, leave a comment.
EDIT: You should consider the negative solution too that I obtain when solving the equation and check which one is correct.
b = -sqrt(D*sin(C/4)/4 - (D^2)/16)
Here's a working example in SVG that's close to correct:
http://phrogz.net/svg/constant-length-bezier.xhtml
I experimentally determined that when the endpoints are on top of one another the handles should be
desiredLength × cos(30°)
away from the handles; and (of course) when the end points are at their greatest distance the handles should be on top of one another. Plotting all ideal points looks sort of like an ellipse:
The blue line is the actual ideal equation, while the red line above is an ellipse approximating the ideal. Using the equation for the ellipse (as my example above does) allows the line to get about 9% too long in the middle.
Here's the relevant JavaScript code:
// M is the MoveTo command in SVG (the first point on the path)
// C is the CurveTo command in SVG:
// C.x is the end point of the path
// C.x1 is the first control point
// C.x2 is the second control point
function makeFixedLengthSCurve(path,length){
var dx = C.x - M.x, dy = C.y - M.y;
var len = Math.sqrt(dx*dx+dy*dy);
var angle = Math.atan2(dy,dx);
if (len >= length){
C.x = M.x + 100 * Math.cos(angle);
C.y = M.y + 100 * Math.sin(angle);
C.x1 = M.x; C.y1 = M.y;
C.x2 = C.x; C.y2 = C.y;
}else{
// Ellipse of major axis length and minor axis length*cos(30°)
var a = length, b = length*Math.cos(30*Math.PI/180);
var handleDistance = Math.sqrt( b*b * ( 1 - len*len / (a*a) ) );
C.x1 = M.x + handleDistance * Math.sin(angle);
C.y1 = M.y - handleDistance * Math.cos(angle);
C.x2 = C.x - handleDistance * Math.sin(angle);
C.y2 = C.y + handleDistance * Math.cos(angle);
}
}

Finding points on a line with a given distance

I have a question i know a line i just know its slope(m) and a point on it A(x,y) How can i calculate the points(actually two of them) on this line with a distance(d) from point A ???
I m asking this for finding intensity of pixels on a line that pass through A(x,y) with a distance .Distance in this case will be number of pixels.
I would suggest converting the line to a parametric format instead of point-slope. That is, a parametric function for the line returns points along that line for the value of some parameter t. You can represent the line as a reference point, and a vector representing the direction of the line going through that point. That way, you just travel d units forward and backward from point A to get your other points.
Since your line has slope m, its direction vector is <1, m>. Since it moves m pixels in y for every 1 pixel in x. You want to normalize that direction vector to be unit length so you divide by the magnitude of the vector.
magnitude = (1^2 + m^2)^(1/2)
N = <1, m> / magnitude = <1 / magnitude, m / magnitude>
The normalized direction vector is N. Now you are almost done. You just need to write the equation for your line in parameterized format:
f(t) = A + t*N
This uses vector math. Specifically, scalar vector multiplication (of your parameter t and the vector N) and vector addition (of A and t*N). The result of the function f is a point along the line. The 2 points you are looking for are f(d) and f(-d). Implement that in the language of your choosing.
The advantage to using this method, as opposed to all the other answers so far, is that you can easily extend this method to support a line with "infinite" slope. That is, a vertical line like x = 3. You don't really need the slope, all you need is the normalized direction vector. For a vertical line, it is <0, 1>. This is why graphics operations often use vector math, because the calculations are more straight-forward and less prone to singularities.
It may seem a little complicated at first, but once you get the hang of vector operations, a lot of computer graphics tasks get a lot easier.
Let me explain the answer in a simple way.
Start point - (x0, y0)
End point - (x1, y1)
We need to find a point (xt, yt) at a distance dt from start point towards end point.
The distance between Start and End point is given by d = sqrt((x1 - x0)^2 + (y1 - y0)^2)
Let the ratio of distances, t = dt / d
Then the point (xt, yt) = (((1 - t) * x0 + t * x1), ((1 - t) * y0 + t * y1))
When 0 < t < 1, the point is on the line.
When t < 0, the point is outside the line near to (x0, y0).
When t > 1, the point is outside the line near to (x1, y1).
Here's a Python implementation to find a point on a line segment at a given distance from the initial point:
import numpy as np
def get_point_on_vector(initial_pt, terminal_pt, distance):
v = np.array(initial_pt, dtype=float)
u = np.array(terminal_pt, dtype=float)
n = v - u
n /= np.linalg.norm(n, 2)
point = v - distance * n
return tuple(point)
Based on the excellent answer from #Theophile here on math stackexchange.
Let's call the point you are trying to find P, with coordinates px, py, and your starting point A's coordinates ax and ay. Slope m is just the ratio of the change in Y over the change in X, so if your point P is distance s from A, then its coordinates are px = ax + s, and py = ay + m * s. Now using Pythagoras, the distance d from A to P will be d = sqrt(s * s + (m * s) * (m * s)). To make P be a specific D units away from A, find s as s = D/sqrt(1 + m * m).
I thought this was an awesome and easy to understand solution:
http://www.physicsforums.com/showpost.php?s=f04d131386fbd83b7b5df27f8da84fa1&p=2822353&postcount=4