mirror of
https://github.com/ppy/osu.git
synced 2024-12-14 10:12:54 +08:00
Fix illegal circle arc with center out of polygon
This commit is contained in:
parent
89859b85b7
commit
a2ec75d824
@ -379,37 +379,56 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
|
||||
double loss = 0;
|
||||
Vector2? lastPoint = null;
|
||||
Vector2? lastVec = null;
|
||||
Vector2? lastVec2 = null;
|
||||
int? lastDir = null;
|
||||
int? lastDir2 = null;
|
||||
double totalWinding = 0;
|
||||
|
||||
// Loop through the points and check if they are not too far away from the circular arc.
|
||||
// Also make sure it curves monotonically in one direction and at most one loop is done.
|
||||
foreach (var point in points)
|
||||
{
|
||||
loss += Math.Pow((Vector2.Distance(point, circleArc.Centre) - circleArc.Radius) / length, 2);
|
||||
|
||||
if (lastPoint.HasValue)
|
||||
{
|
||||
var vec = point - lastPoint.Value;
|
||||
var vec = point - circleArc.Centre;
|
||||
loss += Math.Pow((vec.Length - circleArc.Radius) / length, 2);
|
||||
|
||||
if (lastVec.HasValue)
|
||||
{
|
||||
double dot = Vector2.Dot(vec, lastVec.Value);
|
||||
double det = lastVec.Value.X * vec.Y - lastVec.Value.Y * vec.X;
|
||||
double angle = Math.Atan2(det, dot);
|
||||
int dir = Math.Sign(angle);
|
||||
int dir = Math.Sign(det);
|
||||
|
||||
if (dir == 0)
|
||||
continue;
|
||||
|
||||
if (lastDir.HasValue && dir != lastDir)
|
||||
return null; // Curvature changed, like in an S-shape
|
||||
return null; // Circle center is not inside the polygon
|
||||
|
||||
totalWinding += Math.Abs(angle);
|
||||
lastDir = dir;
|
||||
}
|
||||
|
||||
lastVec = vec;
|
||||
|
||||
if (lastPoint.HasValue)
|
||||
{
|
||||
var vec2 = point - lastPoint.Value;
|
||||
|
||||
if (lastVec2.HasValue)
|
||||
{
|
||||
double dot = Vector2.Dot(vec2, lastVec2.Value);
|
||||
double det = lastVec2.Value.X * vec2.Y - lastVec2.Value.Y * vec2.X;
|
||||
double angle = Math.Atan2(det, dot);
|
||||
int dir2 = Math.Sign(angle);
|
||||
|
||||
if (dir2 == 0)
|
||||
continue;
|
||||
|
||||
if (lastDir2.HasValue && dir2 != lastDir2)
|
||||
return null; // Curvature changed, like in an S-shape
|
||||
|
||||
totalWinding += Math.Abs(angle);
|
||||
lastDir2 = dir2;
|
||||
}
|
||||
|
||||
lastVec2 = vec2;
|
||||
}
|
||||
|
||||
lastPoint = point;
|
||||
|
Loading…
Reference in New Issue
Block a user