107 lines
2.6 KiB
C#
107 lines
2.6 KiB
C#
|
|
using Godot;
|
|
|
|
namespace Rokojori
|
|
{
|
|
|
|
public class SVGArc
|
|
{
|
|
public static Vector2 GetPointOnCenterArc( Vector2 r, float theta, float delta )
|
|
{
|
|
return new Vector2(
|
|
r.X * Mathf.Cos( theta ) * Mathf.Cos( delta ) - r.Y * Mathf.Sin( theta ) * Mathf.Sin( delta ),
|
|
r.X * Mathf.Sin( theta ) * Mathf.Cos( delta ) + r.Y * Mathf.Cos( theta ) * Mathf.Sin( delta )
|
|
);
|
|
|
|
|
|
}
|
|
|
|
public static void EndpointToCenterArc(
|
|
Vector2 start, Vector2 end, Vector2 radius, float xAngle, bool flagA, bool flagS,
|
|
out Vector2 centerPosition,
|
|
out Vector2 centerRadius,
|
|
out Vector2 centerAngles
|
|
)
|
|
{
|
|
var rX = Mathf.Abs( radius.X );
|
|
var rY = Mathf.Abs( radius.Y );
|
|
|
|
var dx2 = ( start.X - end.X ) / 2f;
|
|
var dy2 = ( start.Y - end.Y ) / 2f;
|
|
|
|
var x1p = Mathf.Cos( xAngle ) * dx2 + Mathf.Sin( xAngle ) * dy2;
|
|
var y1p = -Mathf.Sin( xAngle ) * dx2 + Mathf.Cos( xAngle ) * dy2;
|
|
|
|
var rxs = rX * rX;
|
|
var rys = rY * rY;
|
|
var x1ps = x1p * x1p;
|
|
var y1ps = y1p * y1p;
|
|
|
|
var cr = x1ps / rxs + y1ps / rys;
|
|
|
|
if ( cr > 1 )
|
|
{
|
|
var s = Mathf.Sqrt( cr );
|
|
|
|
rX = s * rX;
|
|
rY = s * rY;
|
|
|
|
rxs = rX * rX;
|
|
rys = rY * rY;
|
|
}
|
|
|
|
var dq = ( rxs * y1ps + rys * x1ps );
|
|
var pq = ( rxs * rys - dq ) / dq;
|
|
var q = Mathf.Sqrt( Mathf.Max( 0, pq ) );
|
|
|
|
if ( flagA == flagS )
|
|
{
|
|
q = -q;
|
|
}
|
|
|
|
var cxp = q * rX * y1p / rY;
|
|
var cyp = - q * rY * x1p / rX;
|
|
|
|
var cx = Mathf.Cos( xAngle ) * cxp - Mathf.Sin( xAngle ) * cyp + ( start.X + end.X ) / 2;
|
|
var cy = Mathf.Sin( xAngle ) * cxp + Mathf.Cos( xAngle ) * cyp + ( start.Y + end.Y ) / 2;
|
|
|
|
var theta = Angle( 1f, 0f, ( x1p-cxp ) / rX, ( y1p - cyp ) / rY );
|
|
|
|
var delta = Angle(
|
|
( x1p - cxp ) / rX,
|
|
( y1p - cyp ) / rY,
|
|
( -x1p - cxp ) / rX,
|
|
( -y1p-cyp ) / rY );
|
|
|
|
delta = delta % Mathf.Pi * 2;
|
|
|
|
if ( ! flagS )
|
|
{
|
|
delta -= 2 * Mathf.Pi;
|
|
}
|
|
|
|
centerRadius = new Vector2( rX, rY );
|
|
centerPosition = new Vector2(cx, cy );
|
|
|
|
centerAngles = new Vector2( theta, delta );
|
|
}
|
|
|
|
static float Angle( float ux, float uy, float vx, float vy )
|
|
{
|
|
var u = new Vector2( ux, uy );
|
|
var v = new Vector2( vx, vy );
|
|
|
|
var dot = Math2D.Dot( u, v );
|
|
var len = u.Length( ) * v.Length( );
|
|
|
|
var ang = Mathf.Acos( Mathf.Clamp( dot / len,-1,1 ) );
|
|
|
|
if ( ( u.X * v.Y - u.Y * v.X ) < 0 )
|
|
{
|
|
ang = -ang;
|
|
}
|
|
|
|
return ang;
|
|
}
|
|
}
|
|
} |