mirror of https://github.com/ppy/osu
Fix illegal circle arc with center out of polygon
This commit is contained in:
parent
89859b85b7
commit
a2ec75d824
|
@ -379,37 +379,56 @@ private Vector2[] tryCircleArc(List<Vector2> segment)
|
||||||
double loss = 0;
|
double loss = 0;
|
||||||
Vector2? lastPoint = null;
|
Vector2? lastPoint = null;
|
||||||
Vector2? lastVec = null;
|
Vector2? lastVec = null;
|
||||||
|
Vector2? lastVec2 = null;
|
||||||
int? lastDir = null;
|
int? lastDir = null;
|
||||||
|
int? lastDir2 = null;
|
||||||
double totalWinding = 0;
|
double totalWinding = 0;
|
||||||
|
|
||||||
// Loop through the points and check if they are not too far away from the circular arc.
|
// 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.
|
// Also make sure it curves monotonically in one direction and at most one loop is done.
|
||||||
foreach (var point in points)
|
foreach (var point in points)
|
||||||
{
|
{
|
||||||
loss += Math.Pow((Vector2.Distance(point, circleArc.Centre) - circleArc.Radius) / length, 2);
|
var vec = point - circleArc.Centre;
|
||||||
|
loss += Math.Pow((vec.Length - circleArc.Radius) / length, 2);
|
||||||
if (lastPoint.HasValue)
|
|
||||||
{
|
|
||||||
var vec = point - lastPoint.Value;
|
|
||||||
|
|
||||||
if (lastVec.HasValue)
|
if (lastVec.HasValue)
|
||||||
{
|
{
|
||||||
double dot = Vector2.Dot(vec, lastVec.Value);
|
|
||||||
double det = lastVec.Value.X * vec.Y - lastVec.Value.Y * vec.X;
|
double det = lastVec.Value.X * vec.Y - lastVec.Value.Y * vec.X;
|
||||||
double angle = Math.Atan2(det, dot);
|
int dir = Math.Sign(det);
|
||||||
int dir = Math.Sign(angle);
|
|
||||||
|
|
||||||
if (dir == 0)
|
if (dir == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (lastDir.HasValue && dir != lastDir)
|
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;
|
lastDir = dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
lastVec = vec;
|
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;
|
lastPoint = point;
|
||||||
|
|
Loading…
Reference in New Issue