I got this method:
-(CGPoint) getPointOnaLine: (CGPoint) p1: (CGPoint) p2: (int) dt {
CGPoint tempPoint;
float myY = p1.y;
float len = getLineLength( p1, p2 );
float res = 1000;
// do not bother with calculation with small widths
if ( dt == 0 )
return p1;
if ( len < (2 / res ) )
return p2;
float increm = len / res;
// int min = 2;
float dY = p2.y - p1.y;
float dx = p2.x - p1.x;
if ( dx != 0 ) { // slope is infinite
float slope = dY / dx;
float b = p1.y - slope * p1.x;
if ( p1.x < p2.x ) {
for ( float i= p1.x; i<=p2.x; i=i+increm ) {
myY = (slope * i + b);
tempPoint = ccp(i,myY);
len = getLineLength( p1, tempPoint);
if ( len >= dt)
return tempPoint;
}
} else if ( p1.x > p2.x )
for ( float i= p2.x; i<=p1.x; i=i+increm) {
myY = (slope * i + b);
tempPoint = ccp(i,myY);
len = getLineLength( p2, tempPoint);
if ( len >= dt )
return tempPoint;
}
} else {
return p2;
}
return p1;
}
I use it in another method:
CGPoint b1, b2, pt;
b1 = getPointOnaLine(originalPoint, bezierPoint, (int)t*stepLine1);
b2 = getPointOnaLine(bezierPoint, targetPoint, (int)t*stepLine2);
bLen = getLineLength(b1,b2);
stepLine3 = bLen / frames;
pt = getPointOnaLine(b1,b2,(int)self.tCGPoint b1, b2, pt;
The compiler keep telling me "Incompatable types in assignment" where I declare b1, b2, and pt. The interface is:
-(CGPoint) getPointOnaLine: (CGPoint) p1: (CGPoint) pt2: (int) dt;
If I remove the assignment it just gives me an Implicit declaration warning. I'm really confused about why this won't compile.
Chris
You've defined a method (though with oddly unnamed parameters) but you're calling it as a function.
Try:
b1 = [self getPointOnaLine:originalPoint :bezierPoint :(int)t*stepLine1];
(Better still, declare it with parameter names to make reading easier for your future self.)
You are calling objective-c messages in the c-function style, instead use it as
b1 = [self getPointOnaLine:originalPoint :bezierPoint :(int)t*stepLine1];
b2 = [self getPointOnaLine:bezierPoint :targetPoint :(int)t*stepLine2];
if b1 and b2 are initialized in the same class, otherwise self is to be replaced by the object that has getPointOnaLine:bezierPoint method defined.
Related
I am writing a simple monte carlo code for simulation of electron scattering. I ran the Kernel for 10 million electron and it runs fine, but when I increase the number of electrons to a higher number, say 50 million, the code just wouldn't finish and the computer freezes. I wanted to know if this is a hardware issue or if there is a possible bug in the code. I am running the code on a iMac with ATI Radeon HD 5870.
int rand_r (unsigned int seed)
{
unsigned int next = seed;
int result;
next *= 1103515245;
next += 12345;
result = (unsigned int) (next / 65536) % 2048;
next *= 1103515245;
next += 12345;
result <<= 10;
result ^= (unsigned int) (next / 65536) % 1024;
next *= 1103515245;
next += 12345;
result <<= 10;
result ^= (unsigned int) (next / 65536) % 1024;
seed = next;
return result;
}
__kernel void MC(const float E, __global float* bse, const int count) {
int tx, ty;
tx = get_global_id(0);
ty = get_global_id(1);
float RAND_MAX = 2147483647.0f;
int rand_seed;
int seed = count*ty + tx;
float rand;
float PI;
PI = 3.14159f;
float z;
z = 28.0f;
float rho;
rho = 8.908f;
float A;
A = 58.69f;
int num;
num = 10000000/(count*count);
int counter, counter1, counter2;
counter = 0;
float4 c_new, r_new;
float E_new, alpha, de_ds, phi, psi, mfp,sig_eNA,step, dsq, dsqi, absc0z;
float J;
J = (9.76f*z + 58.5f*powr(z,-0.19f))*1E-3f;
float4 r0 = (float4)(0.0f, 0.0f, 0.0f, 0.0f);
float2 tilt = (float2)((70.0f/180.0f)*PI , 0.0f);
float4 c0 = (float4)(cos(tilt.y)*sin(tilt.x), sin(tilt.y)*sin(tilt.x), cos(tilt.x), 0.0f);
for (int i = 0; i < num; ++i){
rand_seed = rand_r(seed);
seed = rand_seed;
rand = rand_seed/RAND_MAX; //some random no. generator in gpu
r0 = (float4)(0.0f, 0.0f, 0.0f, 0.0f);
c0 = (float4)(cos(tilt.y)*sin(tilt.x), sin(tilt.y)*sin(tilt.x), cos(tilt.x), 0.0f);
E_new = E;
c_new = c0;
alpha = (3.4E-3f)*powr(z,0.67f)/E_new;
sig_eNA = (5.21f * 602.3f)*((z*z)/(E_new*E_new))*((4.0f*PI)/(alpha*(1+alpha)))*((E_new + 511.0f)*(E_new + 511.0f)/((E_new + 1024.0f)*(E_new + 1024.0f)));
mfp = A/(rho*sig_eNA);
step = -mfp * log(rand);
r_new = (float4)(r0.x + step*c_new.x, r0.y + step*c_new.y, r0.z + step*c_new.z, 0.0f);
r0 = r_new;
counter1 = 0;
counter2 = 0;
while (counter1 < 1000){
alpha = (3.4E-3f)*powr(z,0.67f)/E_new;
sig_eNA = (5.21f * 602.3f)*((z*z)/(E_new*E_new))*((4*PI)/(alpha*(1+alpha)))*((E_new + 511.0f)*(E_new + 511.0f)/((E_new + 1024.0f)*(E_new + 1024.0f)));
mfp = A/(rho*sig_eNA);
rand_seed = rand_r(seed);
seed = rand_seed;
rand = rand_seed/RAND_MAX; //some random no. generator in gpu
step = -mfp * log(rand);
de_ds = -78500.0f*(z/(A*E_new)) * log((1.66f*(E_new + 0.85f*J))/J);
rand_seed = rand_r(seed);
seed = rand_seed;
rand = rand_seed/RAND_MAX; //new random no.
phi = acos(1 - ((2*alpha*rand)/(1 + alpha - rand)));
rand_seed = rand_r(seed);
seed = rand_seed;
rand = rand_seed/RAND_MAX; //third random no.
psi = 2*PI*rand;
if ((c0.z >= 0.999f) || (c0.z <= -0.999f) ){
absc0z = abs(c0.z);
c_new = (float4)(sin(phi) * cos(psi), sin(phi) * sin(psi), (c0.z/absc0z)*cos(phi), 0.0f);
}
else {
dsq = sqrt(1-c0.z*c0.z);
dsqi = 1/dsq;
c_new = (float4)(sin(phi)*(c0.x*c0.z*cos(psi) - c0.y*sin(psi))*dsqi + c0.x*cos(phi), sin(phi) * (c0.y * c0.z * cos(psi) + c0.x * sin(psi)) * dsqi + c0.y * cos(phi), -sin(phi) * cos(psi) * dsq + c0.z * cos(phi), 0.0f);
}
r_new = (float4)(r0.x + step*c_new.x, r0.y + step*c_new.y, r0.z + step*c_new.z, 0.0f);
r0 = r_new;
c0 = c_new;
E_new += step*rho*de_ds;
if (r0.z <= 0 && counter2 == 0){
counter++ ;
counter2 = 1;
}
counter1++ ;
}
}
bse[count*ty + tx] = counter;
}
As part of a calculator app, I am trying to implement uses with sigma notation. However, the result it prints out is always a decimal, and the rest isn't important. I simply want to change the decimal to a fraction.
I already have the reduce function, the problem I'm having is getting from a decimal like this: '0.96875' to it's fractional value, '31/32'
Thanks!
PS: I've looked into just about everything, and for the life of me, I can't figure this out. All I need at this point is how to take the decimal out of it, and I can then reduce it.
Here is my reduce method:
-(void)reduce {
int u = numerator;
int v = denominator;
int temp;
while (v != 0) {
temp = u % v;
u = v;
v = temp;
}
numerator /= u;
denominator /= u;
}
Found this out myself. What I did was multiply the numerator and denominator by 1000000 (recalling that the decimal looked like .96875/1) so that it looked like 96875/100000.
Then, I used this reduce method to bring it into lowest terms:
-(void)reduce {
int u = numerator;
int v = denominator;
int temp;
while (v != 0) {
temp = u % v;
u = v;
v = temp;
}
numerator /= u;
denominator /= u;
}
And finally,I used a print method to get it into fraction form:
//In the .h
#property int numerator, denominator, mixed;
-(void)print;
//In the .m
#synthesize numerator, denominator, mixed;
-(void)print {
if (numerator > denominator) {
//Turn fraction into mixed number
mixed = numerator/denominator;
numerator -= (mixed * denominator);
NSLog(#"= %i %i/%i", mixed, numerator, denominator);
} else if (denominator != 1) {
//Print fraction normally
NSLog(#"= %i/%i", numerator, denominator);
} else {
//Print as integer if it has a denominator of 1
NSLog(#"= %i", numerator);
}
}
And got my desired output:
31/32
I found a fairly good way of doing this a while back, although I don't recall where from. Anyway, it works recursively like this (this is pseudocode, not C):
function getRational(float n)
let i = floor(n); (the integer component of n)
let j = n - i;
if j < 0.0001 (use abritrary precision threshold here), return i/1
let m/n = getRational(1 / j)
return ((i * m) + n) / m
For example, take 3.142857 as a starting point.
i = 3
j = 0.142857
m/n = getRational(7)
i = 7
j = 0
return 7/1
m/n = 7/1
return ((3*7)+1) / 7 = 22/7
Or a more complicated example, 1.55:
i = 1
j = 0.55
m/n = getRational(1.81818181)
i = 1
j = 0.81818181
m/n = getRational(1.22222222)
i = 1
j = 0.22222222
m/n = getRational(4.5)
i = 4
j = 0.5
m/n = getRational(2)
i = 2
j = 0
return 2/1
m/n = 2/1
return ((4*2)+1)/2 = 9/2
m/n = 9/2
return ((1*9)+2)/9 = 11/9
m/n = 11/9
return ((1*11)+9)/11) = 20/11
m/n = 20/11
return ((1*20)+11)/20 = 31/20
I tried this with PI once. It would have gone on a while, but if you set your threshold to 0.01, it only goes down a few recursions before returning 355/113.
There's a bit of a gotcha that you might end up with integers that are too large if it goes down too deep when it returns; I haven't really looked into a good way of allowing for that, except setting the precision threshold to something fairly lax, such as 0.01.
Try this :
-(NSString *)convertToFraction:(CGFloat)floatValue{
double tolerance = 1.0E-6;
CGFloat h1 = 1;
CGFloat h2 = 0;
CGFloat k1 = 0;
CGFloat k2 = 1;
CGFloat b = floatValue;
do{
CGFloat a = floor(b);
CGFloat aux = h1;
h1 = a*h1+h2;
h2 = aux;
aux = k1;
k1 = a*k1+k2;
k2 = aux;
b = 1/(b-a);
}while (ABS(floatValue-h1/k1) > floatValue*tolerance) ;
return k1 > 1 ? [NSString stringWithFormat:#"%.0f/%.0f",h1,k1] : [NSString stringWithFormat:#"%.0f",h1];
}
I have a code that lets the user draw a shape, I'm using UIBezierPath for this. But I need to see if the shape crosses itself, for example like this: http://upload.wikimedia.org/wikipedia/commons/0/0f/Complex_polygon.svg
Then it's not a a valid shape.
How can I find this?
Edit:
I still haven't solved this. I save all the points between the lines in the path in a array. And then I loop through the array and try to find if any lines intersects. But it does not work, sometimes it says that there is an intersection when it isn't.
I think that the problem is somewhere in this method.
-(BOOL)pathIntersects:(double *)x:(double *)y {
int count = pathPoints.count;
CGPoint p1, p2, p3, p4;
for (int a=0; a<count; a++) {
//Line 1
if (a+1<count) {
p1 = [[pathPoints objectAtIndex:a] CGPointValue];
p2 = [[pathPoints objectAtIndex:a+1] CGPointValue];
}else{
return NO;
}
for (int b=0; b<count; b++) {
//Line 2
if (b+1<count) {
p3 = [[pathPoints objectAtIndex:b] CGPointValue];
p4 = [[pathPoints objectAtIndex:b+1] CGPointValue];
}else{
return NO;
}
if (!CGPointEqualToPoint(p1, p3) && !CGPointEqualToPoint(p2, p3) && !CGPointEqualToPoint(p4, p1) && !CGPointEqualToPoint(p4, p2)
&& !CGPointEqualToPoint(p1, p2) && !CGPointEqualToPoint(p3, p4)) {
if (LineIntersect(p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y, x, y)) {
return YES;
}
}
}
}
return NO;
}
This is the code I found to see if two lines intersects, It's in C but I should work.
int LineIntersect(
double x1, double y1,
double x2, double y2,
double x3, double y3,
double x4, double y4,
double *x, double *y)
{
double mua,mub;
double denom,numera,numerb;
denom = (y4-y3) * (x2-x1) - (x4-x3) * (y2-y1);
numera = (x4-x3) * (y1-y3) - (y4-y3) * (x1-x3);
numerb = (x2-x1) * (y1-y3) - (y2-y1) * (x1-x3);
/* Are the line coincident? */
if (ABS(numera) < 0.00001 && ABS(numerb) < 0.00001 && ABS(denom) < 0.00001) {
*x = (x1 + x2) / 2;
*y = (y1 + y2) / 2;
return(TRUE);
}
/* Are the line parallel */
if (ABS(denom) < 0.00001) {
*x = 0;
*y = 0;
return(FALSE);
}
/* Is the intersection along the the segments */
mua = numera / denom;
mub = numerb / denom;
if (mua < 0 || mua > 1 || mub < 0 || mub > 1) {
*x = 0;
*y = 0;
return(FALSE);
}
*x = x1 + mua * (x2 - x1);
*y = y1 + mua * (y2 - y1);
return(TRUE);
}
It depends on how complex the polygon drawn by the user can be and the number of points in the path. Ideally, there would be a point for all the vertices in the shape and nothing more. Get a CGPath from the UIBezierPath and use GCPathApply to hand the elements to a function, which adds each point to an array. Traverse the array with two for loops, one nested in the other, which checks each line segment against every line segment after it using a standard line-line intersection test. As soon as an intersection has been found, break from the loop. Or, if this were a convenience method, return a BOOL. That's the simplest way.
EDIT: Here's an example of a line-line intersection function which returns a BOOL telling you whether or not two segments cross. Pass in the two points that create the first segment followed by the two points that make the second segment. It was hastily modified from a piece of source code I found online quickly, but it works.
CGPoint lineSegmentsIntersect(CGPoint L1P1, CGPoint L1P2, CGPoint L2P1, CGPoint L2P2)
{
float x1 = L1P1.x, x2 = L1P2.x, x3 = L2P1.x, x4 = L2P2.x;
float y1 = L1P1.y, y2 = L1P2.y, y3 = L2P1.y, y4 = L2P2.y;
float bx = x2 - x1;
float by = y2 - y1;
float dx = x4 - x3;
float dy = y4 - y3;
float b_dot_d_perp = bx * dy - by * dx;
if(b_dot_d_perp == 0) {
return NO;
}
float cx = x3 - x1;
float cy = y3 - y1;
float t = (cx * dy - cy * dx) / b_dot_d_perp;
if(t < 0 || t > 1) {
return NO;
}
float u = (cx * by - cy * bx) / b_dot_d_perp;
if(u < 0 || u > 1) {
return NO;
}
return YES;
}
You can use it like this.
if (lineSegmentsIntersect(lineOnePointOne,lineOnePointTwo,lineTwoPointOne,lineTwoPointTwo)){
//segments intersect
} else {
//segments did not intersect
}
It's up to you to create the double loop to check the correct segments against one another.
I found an answer here, but can't understand how to transfer the math to Objective C
Find the third point
I have two points and I also have the angle relative to the axes. How do I find a third point which will form a straight line? The distance should be variable.
This is the code that I am using:
float distanceFromPx2toP3 = 1300.0;
float mag = sqrt(pow((px2.x - px1.x),2) + pow((px2.y - px1.y),2));
float P3x = px2.x + distanceFromPx2toP3 * (px2.x - px1.x) / mag;
float P3y = px2.y + distanceFromPx2toP3 * (px2.y - px1.y) / mag;
CGPoint P3 = CGPointMake(P3x, P3y);
Let's say I have two points pointA and pointB. The slope of the line formed by the two points m is:
static CGFloat calculateSlope(CGPoint pointA, CGPoint pointB) {
CGFloat m = (pointB.y - pointA.y) / (pointB.x - pointA.x);
return m;
}
A third point pointC a distance d from pointA on the line would be given by:
static CGPoint calculatePointOnLine(
CGPoint pointA, CGPoint pointB, CGFloat d, BOOL startAtB) {
CGFloat m = calculateSlope(pointA, pointB);
CGFloat dX = pointB.x - pointA.x;
CGFloat dY = pointB.y - pointA.y;
CGFloat signDX = dX / fabsf(dX);
CGFloat signDY = dY / fabsf(dY);
CGFloat dSquared = d * d;
CGFloat mSquared = m * m;
// We know pointC is distance d from pointA,
// and that pointA and pointC are on the
// same line
// dXSquared + dYSquared = dSquared
// m = dY / dX
// dY = m * dX
// dXSquared + mSquared * dXSquared = dSquared
// dXSquared * ( 1 + mSquared ) = dSquared
// dXSquared = dSquared / ( 1 + mSquared )
// Handle a vertical line, dX == 0, and a horizontal line, dY == 0
if (dX != 0 && dY != 0) {
// Account for the sign of dX
dX = signDX * sqrtf(dSquared / ( 1 + mSquared ));
// Account for the sign of dY
dY = signDY * m * dX;
}
// Handle a vertical line, dX == 0
if (dX == 0 && dY != 0) {
dY = signDY * d;
}
// Handle a horizontal line, dY == 0
if (dY == 0 && dX != 0) {
dX = signDX * d;
}
CGPoint startingPoint = pointA;
if (startAtB) {
startingPoint = pointB;
}
CGPoint pointC = CGMakePoint(startingPoint.x + dX,
startingPoint.y + dY);
return pointC;
}
pointC will now always lie a distance d along the line from pointA,
in the direction from pointA to pointB. Pass startAtB to have pointC
lie a distance d along the line from pointB, in the direction from
pointA to pointB.
Exchange the order of piintA and pointB in the call to calculatPointOnLine
to calculate a pointC which lies a distance d along the line from
PointB, in the direction from pointB to pointA.
You can use these two functions to calculate a third point on the line.
Thanks for accepting this answer if this helps you.
I have two points A and B that define a line segment on a device screen plus another point C. Using efficient and short algorithm that is easy to code (preferably using standard math library), how do I check if the line segment AB is within a distance R from C?
I know there is a simple way to find the shortest distance from a point to a line, but it assume the line is infinitely long. What I have is a line segment with two endpoints.
I considered posting this in Math SE but decided not to since I don't want to get all those long math formula as the answer like in https://math.stackexchange.com/questions/2837/how-to-tell-if-a-line-segment-intersects-with-a-circle . What I need is an efficient and readable computer algorithm, not a formal math theorem.
p/s: I have the following Objective-C method skeleton that needs to be implemented:
typedef struct {
CGPoint a;
CGPoint b;
} CGLineSegment;
+ (BOOL)isLineSegment:(CGLineSegment)line withinRadius:(CGFloat)radius fromPoint:(CGPoint)point {
}
EDIT WITH SOLUTION:
thanks to answer from veredesmarald (which I already accepted) I've implemented the method, put here as reference for other people:
+ (BOOL)isLineSegment:(CGLineSegment)line withinRadius:(CGFloat)radius fromPoint:(CGPoint)point {
CGPoint v = CGPointMake(line.b.x - line.a.x, line.b.y - line.a.y);
CGPoint w = CGPointMake(point.x - line.a.x, point.y - line.a.y);
CGFloat c1 = dotProduct(w, v);
CGFloat c2 = dotProduct(v, v);
CGFloat d;
if (c1 <= 0) {
d = distance(point, line.a);
}
else if (c2 <= c1) {
d = distance(point, line.b);
}
else {
CGFloat b = c1 / c2;
CGPoint Pb = CGPointMake(line.a.x + b * v.x, line.a.y + b * v.y);
d = distance(point, Pb);
}
return d <= radius;
}
CGFloat distance(const CGPoint p1, const CGPoint p2) {
return sqrt(pow(p2.x - p1.x, 2) + pow(p2.y - p1.y, 2));
}
CGFloat dotProduct(const CGPoint p1, const CGPoint p2) {
return p1.x * p2.x + p1.y * p2.y;
}
When I had to implement a method to determine the distance from a point to an interval for a graphics assignment, I found this page very informative: About Lines and Distance of a Point to a Line
In particular, the section Distance of a Point to a Ray or Segment should be of interest to you.
Pseudocode from the article (where · is dot product and d() is distance between two points):
distance( Point P, Segment P0:P1 )
{
v = P1 - P0
w = P - P0
if ( (c1 = w·v) <= 0 )
return d(P, P0)
if ( (c2 = v·v) <= c1 )
return d(P, P1)
b = c1 / c2
Pb = P0 + bv
return d(P, Pb)
}
This method relies on the dot product to determine if the base of the perpendicular is within the interval, and if not which end point is closer.