Draw a line from a point to opposite tangents in a circle? Cone / wedge shape in AS3

It should be a little simple geometry: how to calculate points for drawing lines in the code below so that it makes a 2D cone or wedge shape?

import flash.geom.Point; //draw circle var mc=new Sprite() mc.graphics.lineStyle(0,0) mc.graphics.drawCircle(0,0,30) mc.x=mc.y=Math.random()*300+100 addChild(mc) //draw lines: graphics.lineStyle(0,0) var p=new Point(Math.random()*500,Math.random()*400) graphics.moveTo(px, py) graphics.lineTo(mc.x,mc.y) // << should be point on edge of circle graphics.moveTo(px, py) graphics.lineTo(mc.x,mc.y) // << should be point on opposite edge of circle 

UPDATE:
Thanks guys, I should have mentioned that my goal is not to draw a wedge-shaped shape, but to draw a line from a random point to the edge of an existing circle.

If you like algebra more than actioncript, maybe you could take a look at this graphic and post the formula for me? tangents

+7
source share
5 answers

Your question on the Thales theorem (see http://en.wikipedia.org/wiki/Thales%27_theorem ).

The following theorem is slightly modified to work with AS3.

import flash.geom.Point;

 // The radius of the circle var r1:Number = 30; // The center point of the circle var cp:Number = Math.random() * 300+100; var c:Point = new Point(cp, cp); // draw circle var mc=new Sprite(); mc.graphics.lineStyle(0,0); mc.graphics.drawCircle(0,0,r1); mc.x = mc.y = cp; addChild(mc); // The point var p = new Point(Math.random() * 500, Math.random() * 400); // Calculate points for intesecting circle var c2:Point = Point.interpolate(c, p, 0.5); var r2:Number = Point.distance(c2, c); var d:Number = Point.distance(c, c2); // Remove comment below to see intersecting circle //graphics.beginFill(0xFF0000, 0.25); //graphics.drawCircle(c2.x, c2.y, r2); var a:Number = (r1*r1 - r2*r2 + d*d) / (2*d); var p2x:Number = cx + a * ( c2.x - cx ) / d; var p2y:Number = cy + a * ( c2.y - cy ) / d; var h:Number = Math.sqrt(r1*r1 - a*a); var d1x:Number = p2x + h * ( c2.y - cy ) / d; var d1y:Number = p2y - h * ( c2.x - cx ) / d; var d2x:Number = p2x - h * ( c2.y - cy ) / d; var d2y:Number = p2y + h * ( c2.x - cx ) / d; // Draw lines graphics.lineStyle(1, 0xFF00FF, 0.5); graphics.moveTo(px, py); graphics.lineTo(d1x, d1y); graphics.moveTo(px, py); graphics.lineTo(d2x, d2y); 

Final product:

enter image description here

When drawing the second circle (in fact, you do not need to draw in the second circle, you just need its center point and radius)

enter image description here

Checkout the following SWF to see in action (update to see different random circles):

http://megaswf.com/serve/1097652

+2
source

We designate your point as P, the center of the circle as M, and the tangent point on the circle as X. The triangle PMT is a right-angled triangle. You may want to jot it down on paper when you go through it to make it easier to follow.

The position of X is simply the position of M plus the radial vector to X, i.e. MX edge. Then, the calculation of the MX vector is computed.

The MX vector can be decomposed into two perpendicular components. One that is parallel to MP, and one that is perpendicular to MP. The first thing to do is get unit vectors in these two directions. The first is easy, as it is a normalized version of MP. The perpendicular vector to this is easily obtained in 2D by replacing components and negating one component. Which component that you deny is irrelevant here, since you end up needing both tangent lines.

Now that we have our two unit vectors, we need to figure out how many of them are required to create the radial vector MX. Denoting the angle PMX by tta, we have from simple right triangles that cos (theta) = r / | MP | where r is the radius of your circle and | MP | this is the length of the MP (which you already calculated to get your unit vector above).

Dropping the perpendicular from X to MP gives another rectangular triangle involving theta, the opposite and adjacent sides of which are the two components we want. The lengths of these sides are r * cos (theta) in the MP direction and r * sin (theta) in the perpendicular direction.

So, your end result is essentially

X = M + r * cos (theta) * unit_MP + r * sin (theta) * unit_MP_perp_1

for one of the tangent points and

X = M + r * cos (theta) * unit_MP + r * sin (theta) * unit_MP_perp_2

for another. Unit_MP and unit_MP_perp_1 / 2 are the unit vectors that we developed earlier. Version 1/2 of perp vector matches the negation of either the first or second components after the exchange.

Edit

In terms of the added chart, the equation becomes

x1 = cx + R * cos (theta) * Ux + R * sin (theta) * U1x
y1 = cy + R * cos (theta) * Uy + R * sin (theta) * U1y

with similar equations (x2, y2). In these equations

cos (theta) = r / D
sin (theta) = A / D

where D = sqrt ((px - cx) ^ 2 + (py - cy) ^ 2)

and

Ux = (px -cx) / D
Uy = (py -cy) / D

and therefore

U1x = -Uy
U1y = Ux

The perpendicular unit vector for another tangent point would be

U2x = Uy
U2y = -Ux

+1
source

Let (xP, yP) be the intersection of the tangents, (xC,yY) center of the circle, where you look for the coordinates (xT,yT) tangent points. Next, let T be the tangent vector and R the radius vector. Since they are perpendicular, you are R . T = 0 R . T = 0 .

It gives us

 (xT-xC,yT-yC) . (xT-xP, yT-yP) = 0 

Let R be the radius of the circle and x:=xT-xC, y:=yT-yC, xp:=xP-xC, yp:=yP-yC (basically, we move the circle to (0,0) ). The tangent point is on the circle, so you have x²+y²=r² and therefore also y=sqrt(r²-x²) .

Variable substitution applied to the above equation gives us:

 (x,y) . (x-xp, y-yp) = 0 x²-xp*x + y²-yp*y = 0 

Using the information about the circle, we have:

 r² -xp*x - yp*sqrt(r²-x²) = 0 r² -xp*x = yp*sqrt(r²-x²) r^4 - 2*r²*xp*x + xp²*x² = yp²*(r²-x²) (yp²+xp²)*x² - 2*r²*xp*x + r^4-yp²*r² = 0 now let a:=yp²+xp², b:=2*r²*xp, c:= (r²-yp²)*r² => ax² + bx + c = 0 

This is a quadratic equation with 0, 1 or 2 solutions. 0 if P is in a circle, 1 if P is on a circle and 2 if P is out of a circle.

I won’t get an explicit solution here, since it’s a hellish formula, and it’s much easier to write if you map the variables entered here to variables in your code like:

 var sq:Function = function (f:Number) { return f*f; }, sqrt:Function = Math.sqrt; var xp:Number = xP-xC, yp:Number = yP-yC, a:Number = sq(xp)+sq(yp), b:Number = 2*sq(r)*xp, c:Number = sq(r)*(sq(r)-sq(yp)); var x1:Number = (-b+sqrt(sq(b)-4*a*c)) / (2 * a), x2:Number = (-b+sqrt(sq(b)-4*a*c)) / (2 * a); if (isNan(x1)) return []; var p1:Point = new Point(x1+cX, sqrt(sq(r)-sq(x1))+cY),//calculate y and undo shift p2:Point = new Point(x2+cX, sqrt(sq(r)-sq(x2))+cY); return p1.equals(p2) ? [p1] : [p1, p2]; 

Good luck with this, because I am very poor at calculus, plus it's 04:00 here, so you can bet there is a mistake somewhere, but it should help you in the right direction;)

+1
source

graphics.curveTo(controlX,ControlY,endX,endY);

Draws a Bézier between the current point and the end (x, y) with the control (x, y) being the point at which the curve is curved (for example, the pen tool in Photoshop). Set half the delta X and use Y to adjust its strength.

0
source

Here is a snippet for drawing a 2D wedge shape. You can adjust the startAngle and angle to control the angle of the wedge. The radius will determine the width of the shape. This should be used both in Shape, Sprite, MovieClip, and in a subclass that has a graphic object.

 var i:int; var p:Point = new Point(); var g:Graphics = graphics; var radius:Number = 100; var startAngle:Number = 130; var angle:Number = 280; var segments:Number = 40; var degrees:Number = ( startAngle + ( angle - startAngle ) ) / segments; g.beginFill( 0xFF0000, 1 ); for( i = 0; i <= segments; i++ ) { px = Math.cos( ( ( degrees * i ) + startAngle ) * Math.PI / 180 ) * radius; py = Math.sin( ( ( degrees * i ) + startAngle ) * Math.PI / 180 ) * radius; g.lineTo( px, py ); } g.endFill(); 
0
source

All Articles