Draw a line at a canvas - line

Currently I have this code:
sample.beginPath();
sample.moveTo(X1.x,Y1.x );
sample.lineTo(X2.x,Y2.y);
sample.stroke();
sample.beginPath();
sample.arc(X2.x, Y2.y, 4, 0, 2 * Math.PI, false);
sample.fill();
sample.lineWidth = 1;
sample.stroke();
This will create this :
This will point in any direction.
What I want is this:
Note:
1.There will only be one line, either Line A or B.
2.They will always point from left to right.
3. They are in 45 degrees.

Take a look at the following figure:
Point (x1,y1) is the starting point of the mouse. Assuming that mouse has moved to the right (you'll have to handle the case when it moves left), new mouse coordinates will be (x2,y2). However, we don't want to draw the line between (x1,y1) and (x2,y2), because the slop of this line (the angle) won't be the desired one. So we must calculate the coordinates of the new point P, that stands on our line. Note: I assumed that x-coordinate of this point will be equal to new mouse-x coordinate x2!
With this assumption and with help of some basic 2D geometry we get:
a = x2 - x1
tan(alpha) = b / a => b = a * tan(alpha)
P.x = x2
Value of the P.y coordinate depends on whether mouse has moved up or down from the start position.
IF (y1 > y2)
P.y = y1 - b // Mouse has moved up (drawing shows this scenario)
ELSE
P.y = y1 + b // Mouse has moved down (not shown in the drawing)
So we have a new point P, and now you can simply draw the line between (x1,y1) and P. You also have to handle some special case such as what if mouse moves to the left of starting point.
In order to get your point P, you should plug-in your desired angle as well (it can be different than 45 degrees, but it has to be a positive angle - you could derive formula that will work fine with negative angles as well).

Related

Code for Archimedean Spiral with equidistant points is inaccurate near center

I need to be able to find x, y coordinates at any length down an Archimedean spiral arm, given a specific distance between each loop of the arm.
I have researched previous questions on Stackoverflow, and across the Internet, and I have found three methods, which are each different, and each plot me a spiral. (I call them the first, second and third method, here.)
The first method, does plot equidistant points, with the pointdist variable = 1, but as this is increased, there is also an aberration of point distances (supposed to be equidistant) near the center of the spiral.
The third method and second method, do not correctly plot equidistant points near the center of the spiral. (See graphs below)
The third method, though, allows me to input any length down the arm and obtain x, y coordinates.
The first and second methods plot equidistant points by a process where they additively sum a variable, each cycle of a loop to plot the equidistant points. Because of how this value is built up instead of calculated from scratch using only the distance along the spiral arm variable, I can't use these two methods to find coordinates at any arbitrary length along the arm [Proofreading this, I just thought, perhaps if I initialize the length to calculate one point each time. However, all three methods have problems even with equidistant points.]
Here is output from the third method:
Here is the code of the "third method". This method uses what an answer to another sprial-related question on Stackoverflow (Placing points equidistantly along an Archimedean spiral) calls the "Clackson scroll formula", which is said to be possibly inaccurate in some ranges.
double thetamax = 10 * Math.PI;
double b = armbandwidth / (2 * Math.PI);
// "armbandwidth” value influences distance between the spiral arms, usually kept between 1 and 20
AddPoint(0,0); // Mark the origin of the spiral
// “pointdist” is the length between points to plot along the spiral, I use 0.1 to 2+
// but it doesn't reveal spiral shape with increasing values
for (double s = pointdist; s < spirallength; s += pointdist)
{
double thetai = Math.Sqrt(2 * s / b);
double xx = b * thetai * Math.Cos(thetai);
double yy = b * thetai * Math.Sin(thetai);
AddPoint(xx, yy);
}
I need to both:
Use a method that does not have aberrations in the equidistance of points along the spiral arm, given equally spaced values of lengths down the spiral arms.
Use a method that allows me to specify the width between the spiral arms (in terms of the same units used for the length along spiral arm between the points, as well).
In case it helps, and to be clear about what I've tried, here are the code and output from the other methods I've found and tested (here called "second method" and "first method") for calculating the coordinates of equidistant points along an Archimedean spiral:
Here is output from the second method (note the uneven distanced points near center):
Here is the code for the second method:
AddPoint(0,0); // Mark the origin of the spiral
double arclength = 0.8; // This value (kept between 0.1 and 20 or so) sets the distance between points to calculate coordinates for along the spiral curve
double r = arclength;
double b = armbandwidth / (2 * Math.PI); // "armbandwidth" value influences distance between the spiral arms, usually kept between 3.5 to 10
double phi = r / b;
double xx = r * Math.Cos(phi);
double yy = r * Math.Sin(phi);
AddPoint(xx, yy);
while( r <= spirallength ) // spirallength determines roughly how many iterations of points to draw
{
phi += arclength / r;
r = b * phi;
xx = r * Math.Cos(phi);
yy = r * Math.Sin(phi);
AddPoint(xx, yy);
}
Because the variable phi is additively increased each iteration, I can't pass in any length down the spiral arm to find coordinates for. (Maybe if I initialized the whole method only to a single arclength each time. - In any case, the points near center are not evenly spaced.)
Here is output from the first method (Equidistant points throughout with pointdist = 1):
Here is the code of the first method:
double separation = 4; // Value influences distance between the spiral arms, usually kept 3.5 to 10+
double angle = 0;
double r;
AddPoint(0,0); // Mark the origin of the spiral
for (double i=0; i <= spirallength; i+=pointdist) // spirallength determines pointdist spaced points to plot
{
r = Math.Sqrt(i+1);
angle += Math.Asin(1/r);
double xx = Math.Cos(angle) * r*separation;
double yy = Math.Sin(angle) * r*separation;
AddPoint(xx, yy);
}
However, when "pointdist" is increased above 1, there are aberrations in equidistance between points near the center of the spiral, even by this method. Here is the output of a graph using the "first method" and pointdist = 9:
Can anyone help me calculate x, y coordinates for any length down the spiral arm from center, for an Archimedes spiral defined by a specified width between loops of the arm?
(It should be able to have equidistant points, accurate even near the center, and be able to take a width between loops of the arm in units the same scale as those used for the distance to a point along the arm passed to the coordinates equation.)
Much appreciated!
I believe this last piece of code is the best (most simple and straightforward) approach:
constant angle variation
For a given angle
calculate the radius
convert Polar coordinates to Cartesian.
However, I understand the Archimedean spiral is defined by the formula: r = a + b * angle (where a=0 to simplify, and b controls the distance between loops.
In short, the position of particle is proportional to the angle θ as time elapses.
So what's up with that? That's not linear at all!
r = Math.Sqrt(i+1);
angle += Math.Asin(1/r);
Here's a simple way to make it.
It's not a running code. But I believe it's very easy to understand.
So just understand the logic and then code it with your own variables:
for (some incrementing t)
{
radius = t/100; //Start at radius = 0. When t = 100, radius=1.
angle = t*2*Pi/200; //It takes 200 points to make a full 360 (2Pi) turn
//Now converting from polar coordinates (r,angle) to (x,y):
x = cos(angle) * r;
y = sin(angle) * r;
AddPoint(x, y);
}
This code generates the following image:
This generates the right trajectory. However, as noticed, this does not produce equidistant points, because each angle increment is multiplied by the radius. So I suggest you to find a correction function and apply it to t. Like so:
function correction(i)
{
// I actually don't know the exact relationship between t and i
t = 1/i
// But I think it converges to t=1/i for very small increments
return t
}
for (some incrementing i)
{
t = correction(i)
...
}

How to find the point of collision between an irregular shape (built out of 3 circles) and a line

I'm making a program in which many weird shapes are drawn onto a canvas. Right now i'm trying to implement the last, and possebly hardest, one.
In this particular shape i need a way to find the location (on a 2d canvas) where the line hits the shape. The following image is an example of what i have right now.
The black dots are the points that a known to me (i also have the location of the center of the three open circles and the radius of these circles). Each of the three outer lines needs a line towards the center dot, ending at the point that it hits the circle. This shape can be turned 90, 180 or 270 degrees.
The shape should look something like the following:
If you need any other information, please ask me in the comments. I'm not very good at math so please be gentle, thanks!
If A and B are points forming a line, then you can describe any point on that line using coordinates:
x = t·Ax + (1−t)·Bx
y = t·Ay + (1−t)·By
0 ≤ t ≤ 1
You can also describe the circle with center M and radius r as
(x − Mx)2 + (y − My)2 = r2
So take the x and y from the equations of the line, and plug them into the equation of the circle. You obtain a quadratic equation in t. Its two solutions describe the two points of intersection between the line and circle. In your example, only one of them lies on the line segment, i.e. satisfies 0 ≤ t ≤ 1. The other describes a point on the extension of the segment past its endpoint. Take the correct value for t back to the equations of the line, and you obtain the x and y coordinates of the point of intersection.
If you don't know up front which circle you want to intersect with a given line, then intersect all three and choose the most appropriate point afterwards. Probably that is the point closest to the outside starting point of the line segment. The same goes in cases where both points of intersection lie on the segment.

How can I find the points in a line - Objective c?

Consider a line from point A (x,y) to B (p,q).
The method CGContextMoveToPoint(context, x, y); moves to the point x,y and the method CGContextAddLineToPoint(context, p, q); will draw the line from point A to B.
My question is, can I find the all points that the line cover?
Actually I need to know the exact point which is x points before the end point B.
Refer this image..
The line above is just for reference. This line may have in any angle. I needed the 5th point which is in the line before the point B.
Thank you
You should not think in terms of pixels. Coordinates are floating point values. The geometric point at (x,y) does not need to be a pixel at all. In fact you should think of pixels as being rectangles in your coordinate system.
This means that "x pixels before the end point" does not really makes sense. If a pixel is a rectangle, "x pixels" is a different quantity if you move horizontally than it is if you move vertically. And if you move in any other direction it's even harder to decide what it means.
Depending on what you are trying to do it may or may not be easy to translate your concepts in pixel terms. It's probably better, however, to do the opposite and stop thinking in terms of pixels and translate all you are currently expressing in pixel terms into non pixel terms.
Also remember that exactly what a pixel is is system dependent and you may or may not, in general, be able to query the system about it (especially if you take into consideration things like retina displays and all resolution independent functionality).
Edit:
I see you edited your question, but "points" is not more precise than "pixels".
However I'll try to give you a workable solution. At least it will be workable once you reformulate your problem in the right terms.
Your question, correctly formulated, should be:
Given two points A and B in a cartesian space and a distance delta, what are the coordinates of a point C such that C is on the line passing through A and B and the length of the segment BC is delta?
Here's a solution to that question:
// Assuming point A has coordinates (x,y) and point B has coordinates (p,q).
// Also assuming the distance from B to C is delta. We want to find the
// coordinates of C.
// I'll rename the coordinates for legibility.
double ax = x;
double ay = y;
double bx = p;
double by = q;
// this is what we want to find
double cx, cy;
// we need to establish a limit to acceptable computational precision
double epsilon = 0.000001;
if ( bx - ax < epsilon && by - ay < epsilon ) {
// the two points are too close to compute a reliable result
// this is an error condition. handle the error here (throw
// an exception or whatever).
} else {
// compute the vector from B to A and its length
double bax = bx - ax;
double bay = by - ay;
double balen = sqrt( pow(bax, 2) + pow(bay, 2) );
// compute the vector from B to C (same direction of the vector from
// B to A but with lenght delta)
double bcx = bax * delta / balen;
double bcy = bay * delta / balen;
// and now add that vector to the vector OB (with O being the origin)
// to find the solution
cx = bx + bcx;
cy = by + bcy;
}
You need to make sure that points A and B are not too close or the computations will be imprecise and the result will be different than you expect. That's what epsilon is supposed to do (you may or may not want to change the value of epsilon).
Ideally a suitable value for epsilon is not related to the smallest number representable in a double but to the level of precision that a double gives you for values in the order of magnitude of the coordinates.
I have hardcoded epsilon, which is a common way to define it's value as you generally know in advance the order of magnitude of your data, but there are also 'adaptive' techniques to compute an epsilon from the actual values of the arguments (the coordinates of A and B and the delta, in this case).
Also note that I have coded for legibility (the compiler should be able to optimize anyway). Feel free to recode if you wish.
It's not so hard, translate your segment into a math line expression, x pixels may be translated into radius of a circe with center in B, make a system to find where they intercept, you get two solutions, take the point that is closer to A.
This is the code you can use
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);
Either you can follow this link also it will give you the detail description -
How to find a third point using two other points and their angle.
You can find out number of points whichever you want to find.

Draw line at center of circle with angle in objective-c

I want to draw line at the center of circle with fixed size. Please check the image, it will explain everything. I have P1 center of the circle and P2 somewhere at the border of the circle. P1 will always remain fixed and P2 will keep changing with mouse move and it will be any point at circle's border. Now, I want to draw line with fixed length shown in green color. I want to find the (x1,y1) and (x2,y2) with fixed distance, every time P2 get changed, i want to draw green line facing towards P2.
Hope, image explains everything, in short i need following.
angle between P1 and P2.
Draw green line with fixed distance with angle at the center of the circle.
Thanks
Since you (apparently) want the green line to be perpendicular to the red line, you don't need to compute the angle between p1 and p2. Rotating a vector by 90˚ is quite trivial.
I assume you have p1 and p2 as CGPoint (or NSPoint) variables.
First let's compute the vector from p1 to p2:
CGPoint p1p2 = CGPointMake(p2.x - p1.x, p2.y - p1.y);
Next we'll compute a vector that is perpendicular to the p1->p2 vector:
CGPoint p1p2Perp = CGPointMake(p1p2.y, -p1p2.x);
Now let's find the length of the perpendicular vector:
CGFloat radius = hypot(p1p2Perp.x, p1p2Perp.y);
Note that if the radius of the circle is constant, you can just use that instead of computing it. If you're on iOS, use hypotf instead of hypot.
So now we can “normalize” the perpendicular vector, making it have length 1, by dividing its coordinates by its length:
p1p2Perp.x /= radius;
p1p2Perp.y /= radius;
Next we can multiply it by half of the desired length of the green line. I assume you have the desired length of the green line in a constant or variable named greenLineLength.
p1p2Perp.x *= greenLineLength / 2;
p1p2Perp.y *= greenLineLength / 2;
Now we can create a path for the green line. I assume your CGContextRef is in a variable named gc:
CGContextBeginPath(gc);
CGContextMoveToPoint(gc, p1.x - p1p2Perp.x, p1.y - p1p2Perp.y);
CGContextAddLineToPoint(gc, p1.x + p1p2Perp.x, p1.y + p1p2Perp.y);
You can stroke the path however you like. For example:
CGContextSetRGBStrokeColor(gc, 0, 1, 0, 1);
CGContextSetLineWidth(gc, 2);
CGContextSetLineCap(gc, kCGLineCapRound);
CGContextStrokePath(gc);
The angle between the two, according to your question, is always perpendicular -- 90˚ or π/2 radians. You can get the angle of the red segment using atan2(); then subtract M_PI_2 for the angle of the green one.
From there, you are trying to find two points on the circumference of a circle whose diameter is the length of the segment. You can think about this in polar coordinates (r, theta) and convert to Cartesian (x, y):
x = (segment_length / 2) * cos(theta)
y = (segment_length / 2) * sin(theta)
Add M_PI to theta to get the other endpoint.

How can I find the first point along a heading that is a specified distance away from a line segment?

Given a starting point, a heading, a distance, and a line segment, find the first point along this heading that is the specified distance away from this line segment.
I covered two cases, but I haven't been able to cover the last one.
First case: heading away from the line. Ignore it even if the starting point is within the specified distance.
Second case: It intersects the line. I solved it using trig and triangles. Initially didn't consider the next case.
Third case: It is heading towards the line, but it does not intersect it. I think this will solve the second case as well if it's done correctly.
Three subcases:
The minimum line distance is greater than the specified distance. Ignore it.
The minimum line distance is equal to the specified distance. Found the points already.
The minimum line distance is less than the specified distance. This means there is a perpendicular line from the along the heading to an endpoint of the line segment that is less than the distance needed. This also means that on either side of this perpendicular line will be two lines of the distance needed. One is perpendicular to the heading, while the other is closest to the same endpoint and not perpendicular to the heading. Just a matter of finding those points and seeing which one is closer to the start point.
This is where I am stuck today. Drawing it up was easy, but doing the vector calc or whatever turned out tricky.
It's possible to rephrase this as:
At what time(s) is P(t) = P0 + t*v at a distance D from the line segment L((x1,y1), (x2,y2))?
v=(sin(heading), -cos(heading)) in my case.
Shoot mang your solution doesn't always work. I found a counter example:
Line Segment = (0,0) -> (0,14)
Start Point = (19, 6) # heading -159.5 or 200.5 in west/counter-clockwise
It will intersect the line at (2.952, 0.0) so I ask, where does it it come within a distance of 0.0.
The result I get is incorrect.
http://img5.imageshack.us/i/failuref.png/
How I can tell which ones will work using your solution and which ones do not work depends whether the minimum starting distance between the point and the line segment creates a perpendicular line.
If I can post another picture in the next post, I will put the successful example.
I would have liked to post some code for Sage which produced those images, but the code tags are accepting python unfortunately.
A successful result where the minimum starting distance between the point and the line segment is perpendicular to the line segment:
http://img46.imageshack.us/i/success.png/
Hi the solution I eventually came up with.
Does the ray intersect line segments that are parallel and the specified distance D away from the line segment. Just drawing a rectangle and checking the sides parallel to the line segment.
Does the ray intersect circles of radius D at each end point of the line segment.
Minimize for total unit time to find the first point along the ray that is D away from the line segment.
Possible Border case: Is the start point within D and heads away from the line? Up to the user how to handle this case.
Thanks, that works.
I found the alpha this way:
heading = 45.0*pi/180. #heading 45 degrees.
if x1 > x2: #line segment (x1,y1)<->(x2,y2)
dx = x2 - x1
dy = y2 - y1
else:
dx = x1 - x2
dy = y1 - y2
segmentHeading = atan2(dx, dy)
if heading > 0:
alpha = segmentHeading + heading
else:
alpha = -segmentHeading + heading
t = abs( (dStart - D) / -cos(alpha) ) #-cos in python, sin in C.