Code archives/Algorithms/circle to arc.

This code has been declared by its author to be Public Domain code.

Download source code

circle to arc. by Jesse2011
OO circle to arc interaction with bounce. linear movement only, does not integrate time movement, not too difficult to integrate.
SuperStrict
'Create game Object
Type Tgame
	Field stageW:Float
	Field stageH:Float
	Field maxV:Float
	Field gravity:Float
	Field LastTime:Float
	Field arc:TArc
	Field ball:Tball
	
	Method New()
		stageW = 480
		stageH = 400
		ball = Tball.Create(5,5,10,10,40)
		arc = Tarc.Create(170, 195.5, 60,-60,120)
	End Method
	
	Method update()
		Local length:Float = ball.length
		ball.ball2ArcCollision(arc,length)	
	End Method

	'Function To draw the points, lines And show text
	Method drawAll()
		'draw ball path
		'DrawLine ball.p2.x,ball.p2.y,ball.p1.x,ball.p1.y
		ball.display()	
		arc.display()
	End Method
	
End Type

Type Tpoint
	Field x:Float
	Field y:Float
End Type

Type Tvector
	Field p0:Tpoint
	Field p1:Tpoint
	Field length:Float
	Field dx:Float
	Field dy:Float
	Field lx:Float
	Field ly:Float
	Field vx:Float
	Field vy:Float
	
	Field b:Float
	Field f:Float
	Field m:Float
	Field airf:Float
	Field lastTime:Float
	Field timeFrame:Float
	
	Method New()
		p0 = New Tpoint
		p1 = New Tpoint
	End Method

	'Function To find all parameters For the vector
	Method update( frompoints:Int=False)
		'x And y components
		If(frompoints)
			vx=p1.x-p0.x
			vy=p1.y-p0.y
		Else
			p1.x=p0.x+vx
			p1.y=p0.y+vy
		EndIf
		'length of vector
		Length=Sqr(vx*vx+vy*vy)
		'normalized unit-sized components
		If(Length>0)
			dx=vx/Length
			dy=vy/Length
		Else
			dx=0
			dy=0
		EndIf
	End Method

	'find New vector bouncing from v2
	Method bounce:Tvector(v2:Tvector)
		'projection of v1 on v2
		Local dp:Float = vx*v2.dx+vy*v2.dy
		Local vx1:Float = dp*v2.dx
		Local vy1:Float = dp*v2.dy
		'projection of v1 on v2 normal
		dp = vx*v2.lx+vy*v2.ly
		Local vx2:Float = dp*v2.lx
		Local vy2:Float = dp*v2.ly 
		'reverse projection on v2 normal
		Local p2l:Float = Sqr(vx2*vx2+vy2*vy2)
		'add the projections
		vx=vx1+v2.lx*p2l
		vy=vy1+v2.ly*p2l
	End Method
	
	Method display()
		DrawLine p0.x,p0.y,p1.x,p1.y
	End Method
End Type

Type Tball Extends Tvector
	Field vn:Tvector
	Field v2:Tvector
	Field v3:Tvector
	Field v:Tvector
	Field vbounce:Tvector

	Field p2:Tpoint
	
	Field r:Float
	
	Method New()

		 v = New Tvector
		vn = New Tvector
		v2 = New Tvector
		v3 = New Tvector
		vbounce = New Tvector		

		p2 = New Tpoint

	End Method
	
	Function Create:Tball(x1:Float,y1:Float,x2:Float,y2:Float,r:Float)
		Local b:Tball = New Tball
		b.p0.x = x1
		b.p0.y = y1
		b.p1.x = x2
		b.p1.y = y2
		b.r = r
		b.update(True)
		Return b
	End Function
	
	Method display()
		For Local a:Float = 0 Until 360
			Local vx:Float = Cos(a)*r
			Local vy:Float = Sin(a)*r
			Plot p0.x+vx,p0.y+vy
		Next
	End Method

	'find collision between balls
	Method ballvsBall:Tvector(pa:Tpoint, r:Float,Tlen:Float Var)
		'dp for projection of vector between center of points of balls along movement vector	
		Local dp:Float = (pa.x-p0.x) * dx + (pa.y-p0.y) * dy
		'vector To center of arc in direction of movement vectors normal
		vn.p0.x = p0.x+dp*dx
		vn.p0.y = p0.y+dp*dy
		vn.p1.x=pa.x
		vn.p1.y=pa.y
		vn.update(True)
		'sum of radius
		Local totalRadius:Float=Self.r+r
		'check If vn is shorter Then combined radiuses
		Local  diff:Float = totalRadius-vn.Length
		If (diff>0)
			'collision
			'amount To move back moving ball
			Local moveBack:Float=Sqr(totalRadius*totalRadius-vn.Length*vn.Length)
			v2.p0.x = p0.x
			v2.p0.y = p0.y
			v2.p1.x = vn.p0.x-moveBack*dx
			v2.p1.y = vn.p0.y-moveBack*dy
			v2.update(True)
			'check If on the movement vector
			If(v2.Length<Tlen And (v2.vx*vx+v2.vy*vy)>0)
				Return v2
			EndIf
		EndIf
		Return Null
	End Method

	'collision
	Method ball2ArcCollision(arc:Tarc,Tlen:Float)
		'start To calculate movement
		Local vx4:Float,vy4:Float,vx5:Float,vy5:Float,len5:Float
		Local collision:Tvector=ballvsBall(arc.p0, arc.radius,Tlen)
		If collision
			'collision point found
			vx5 = collision.p1.x - arc.p0.x
			vy5 = collision.p1.y - arc.p0.y
			len5 = Sqr(vx5*vx5+vy5*vy5)
			'check If the point is on the Right side of vector between arc points
			'vector between starting point of arc And collision point
			If Len5 > 0
				vx4 = (arc.p0.x+vx5/len5*arc.radius)-arc.arc.p0.x
				vy4 = (arc.p0.y+vy5/len5*arc.radius)-arc.arc.p0.y
			Else
				vx4 = arc.p0.x - arc.arc.p0.x
				vy4 = arc.p0.y - arc.arc.p0.y
			EndIf
			If(vx4*arc.arc.dy-vy4*arc.arc.dx) >= 0
				p2.x=collision.p1.x
				p2.y=collision.p1.y
				v.vx = p2.x - arc.p0.x
				v.vy = p2.y - arc.p0.y
				v.update(False)
				vbounce.dx =  v.dy
				vbounce.dy = -v.dx
				vbounce.lx =  v.dx
				vbounce.ly =  v.dy
			Else
				'Not on the arc
				collision = Null
			EndIf
		EndIf
		'need To check with other side of arc too
		If collision = Null
			If(vn.Length < arc.radius)
				'amount To move back moving ball
				Local r:Float=arc.radius-r
				Local moveForward:Float=Sqr(r*r-vn.Length*vn.Length)
				v3.p0.x = p0.x
				v3.p0.y = p0.y
				v3.p1.x = vn.p0.x+moveForward*dx
				v3.p1.y = vn.p0.y+moveForward*dy
				v3.update(True)
				'check If on the movement vector
				If(v3.Length<=Tlen And (v3.vx*vx+v3.vy*vy)>0)
					'collision point found
					vx5 = v3.p1.x - arc.p0.x
					vy5 = v3.p1.y - arc.p0.y
					len5 = Sqr(vx5*vx5+vy5*vy5)
					'check If the point is on the Right side of vector between arc points
					'vector between starting point of arc And collision point
					If len5>0
						vx4 = (arc.p0.x+vx5/len5*arc.radius) - arc.arc.p0.x
						vy4 = (arc.p0.y+vy5/len5*arc.radius) - arc.arc.p0.y
					Else
						vx4 = arc.p0.x - arc.arc.p0.x
						vy4 = arc.p0.y - arc.arc.p0.y
					EndIf
					If (vx4*arc.arc.dy-vy4*arc.arc.dx) >= 0
						p2.x=v3.p1.x
						p2.y=v3.p1.y
						collision=v3
						v.vx = p2.x - arc.p0.x
						v.vy = p2.y - arc.p0.y
						v.update(False)
						vbounce.dx = -v.dy
						vbounce.dy =  v.dx
						vbounce.lx = -v.dx
						vbounce.ly = -v.dy
						
					EndIf
				EndIf
			EndIf
			
			'now we need To check If endpoints of arc are being hit
			Local nextCollision:Tvector = ballvsBall(arc.arc.p0, 0,Tlen)
			If(nextCollision)
				If(collision=Null Or nextCollision.Length<collision.Length)
					collision = nextCollision
					p2.x=nextCollision.p1.x
					p2.y=nextCollision.p1.y
					v.vx = p2.x - arc.arc.p0.x
					v.vy = p2.y - arc.arc.p0.y
					v.update(False)
					vbounce.dx =  v.dy
					vbounce.dy = -v.dx
					vbounce.lx =  v.dx
					vbounce.ly =  v.dy
				EndIf
			EndIf

			nextCollision=ballvsBall(arc.arc.p1, 0,Tlen)
			If(nextCollision)
				If(collision=Null Or nextCollision.Length<collision.Length)
					collision=nextCollision
					p2.x=nextCollision.p1.x
					p2.y=nextCollision.p1.y
					v.vx = p2.x - arc.arc.p1.x
					v.vy = p2.y - arc.arc.p1.y
					v.update(False)
					vbounce.dx =  v.dy
					vbounce.dy = -v.dx
					vbounce.lx =  v.dx
					vbounce.ly =  v.dy
				EndIf
			EndIf
		EndIf
		
		If collision
			Local vx1:Float = p2.x-p0.x
			Local vy1:Float = p2.y-p0.y
			Tlen :- Sqr(vx1*vx1+vy1*vy1)
			bounce(vbounce)
			p0.x = p2.x
			p0.y = p2.y
			update(False)
			p1.x = p2.x+dx*Tlen
			p1.y = p2.y+dy*Tlen
			ball2ArcCollision(arc,Tlen)
		Else
			If (p1.x>game.stageW+r)
				p1.x = -r
			Else If (p1.x<-r)
				p1.x = game.stageW+r
			EndIf
			If (p1.y>game.stageH+r)
				p1.y = -r
			Else If (p1.y<-r)
			
				p1.y = game.stageH+r
			EndIf
			p0.x = p1.x
			p0.y = p1.y
			update(False)
		EndIf
	End Method
End Type

Type Tarc Extends Tvector
	Field ang1:Float
	Field ang2:Float
	Field degrees:Float
	Field radius:Float
	Field stp:Float
	Field arc:Tvector
	
	Const RATE:Float = Pi/180.0

	Method New()
		arc = New Tvector
	End Method
	
	Function Create:Tarc(x:Float,y:Float,r:Float,a1:Float,a2:Float)
		Local a:Tarc = New Tarc
		a.p0.x = x
		a.p0.y = y
		a.radius = r
		If a1 > a2
			Local ta:Float = a2
			a2 = a1
			a1 = ta
		EndIf
		a.degrees = a2-a1
		If a.degrees > 360 
			a.degrees = 360
			a2 = a1+360
		EndIf
		a.ang1 = a1
		a.ang2 = a2
		a.stp = 1.0/(RATE*r)
		a.findArc()
		Return a
	End Function
	
	'find End points of the arc from angles
	Method findArc()
		'vector between End points of the arc
		arc.p0.x = p0.x+radius*Cos(ang1)
		arc.p0.y = p0.y+radius*Sin(ang1)
		arc.p1.x = p0.x+radius*Cos(ang2)
		arc.p1.y = p0.y+radius*Sin(ang2)
		arc.update(True)
	End Method

	Method Display()
		Local Angle:Float = ang1
		While Angle < (ang1+degrees)
			Plot p0.x + Cos(Angle) * radius, p0.y + Sin((Angle)) * radius
			Angle :+ stp
		Wend
		DrawOval p0.x-1,p0.y-1,2,2
	End Method

End Type

'Create game Object
Global game:Tgame = New Tgame

Graphics game.stageW,game.StageH
Repeat
Cls
game.update()
game.drawAll()
Flip()
Until KeyDown(key_escape)

Comments

None.

Code Archives Forum