Limit line lenght

Blitz3D Forums/Blitz3D Programming/Limit line lenght

Jokkeri(Posted 2005) [#1]
I made limitWallLenght()-function, but the line (code below) shakes and angle limit function doesn't work if wall length are smaller than 30 px. Can anyone help me?

Graphics 800,600,32,2
AppTitle "Angle Test"

SetBuffer BackBuffer()

Global GLOBAL_X1#, GLOBAL_Y1#

Local Ax0# = 10, Ay0# = 10, Ax1# = 200, Ay1# = 200, Bx0# = 200, By0# = 200, Bx1# = 500, By1# = 500, angle#


While Not KeyHit(1)

	Cls
	Bx1 = MouseX()
	By1 = MouseY()

	angle = getAngleOfTwoLines(Ax0, Ay0, Ax1, Ay1, Bx0, By0, Bx1, By1)

	If angle < 45 Then limitWallAngle(Ax0, Ay0, Ax1, Ay1, Bx0, By0, Bx1, By1, 45)
	limitWallLength(30, Bx0, By0, Bx1, By1)
	Bx1 = MouseX()
	By1 = MouseY()

	Line Ax0, Ay0, Ax1, Ay1
	Line Bx0, By0, Bx1, By1

	Flip

Wend


Function limitWallAngle(Ax0#, Ay0#, Ax1#, Ay1#, Bx0#, By0#, Bx1#, By1#, ang#)

	Local A_length#, B_length#, Vx#, Vy#, V_pituus#, Ux#, Uy#, Angle#
	B_length = Sqr((Bx1-Bx0)^2+(By1-By0)^2)

	Vx = Ax0 - Ax1
	Vy = Ay0 - Ay1
	V_pituus = B_length/Sqr(Vx^2+Vy^2)
	Vx=Vx*V_pituus
	Vy=Vy*V_pituus

	U0x = Vx * Cos(ang#) - Vy * Sin(ang#)
	U0y = Vy * Sin(ang#) + Vx * Cos(ang#)

	U1x = Vx * Cos(ang#) + Vy * Sin(ang#)
	U1y = Vy * Sin(ang#) - Vx * Cos(ang#)
	MX=MouseX()-Bx0
	MY=MouseY()-By0

	If ((U0x-MX)^2+(U0y-MY)^2)<((U1x-MX)^2+(U1y-MY)^2)
		GLOBAL_X1 = Bx0 + U0x
		GLOBAL_Y1 = By0 + U0y
		MoveMouse global_x1, global_y1
	Else
		GLOBAL_X1 = Bx0 + U1x
		GLOBAL_Y1 = By0 - U1y
		MoveMouse global_x1, global_y1
	EndIf

End Function


Function limitWallLength(min_length#, x0#, y0#, x1#, y1#, o_x% = 0, o_y% = 0)
	
	Local length_a#, length_b#, length_hypotenuse#, angle#, limit_x1#, limit_y1#
	
	length_b = x1 - x0
	length_a = y1 - y0
	length_hypotenuse = Sqr(length_a^2 + length_b^2)

	If length_hypotenuse < min_length
		angle = ASin(length_a/length_hypotenuse)
		length_hypotenuse = min_length

		If x1 < x0
			length_a = -Cos(angle) * length_hypotenuse
		Else
			length_a = Cos(angle) * length_hypotenuse			
		EndIf	
		
		length_b = Sin(angle) * length_hypotenuse
		
		limit_x1 = x0 + length_a
		limit_y1 = y0 + length_b
		
		MoveMouse limit_x1 + o_x, limit_y1 + o_y
	EndIf

End Function



Function getAngleOfTwoLines(Ax#, Ay#, Bx#, By#, Cx#, Cy#, Dx#, Dy#)

Local ACx#, ACy#, BCx#, BCy#
Local dot_production#, angle#
Local lengthAC#, lengthBC#

ACx = Bx - Ax
ACy = By - Ay

BCx = Cx - Dx
BCy = Cy - Dy

dot_production = ACx * BCx + ACy * BCy

lengthAC = Sqr(ACx^2 + ACy^2)
lengthBC = Sqr(BCx^2 + BCy^2)

angle = ACos(dot_production / (lengthAC * lengthBC))

Return angle#
End Function



octothorpe(Posted 2005) [#2]
You cannot rely on the mouse's position for storing information (i.e. MouseMove().) The mouse may move between the time when you set its position and read its position back to set the end point of your line.

Instead of setting the position of the mouse in your "limit" functions, return the position. Since a position is composed of two scalar variables, you can either return a type object or set a couple globals. Set the mouse's position when you're all finished with your calculations.

I also recommend testing MouseX() and MouseY() only once per loop. Store the mouse position in a global type object or two global variables if you must. When limiting the length of the wall, the mouse may have moved and start violating the angle constraints you just finished testing for.