private static float MaxErrorLocation(ArcOfSphere arc, float begin, float end) { Vector2 L1 = SpaceConverter.SphereToUV(arc.Evaluate(begin)); Vector2 L2 = SpaceConverter.SphereToUV(arc.Evaluate(end)); // 2) use binary / bisection search to find the point of maximal error while (end - begin > delta) { float midpoint = (begin + end) / 2; float error_left = Point_Line_Distance(L1, L2, SpaceConverter.SphereToUV(arc.Evaluate(midpoint - delta))); float error_right = Point_Line_Distance(L1, L2, SpaceConverter.SphereToUV(arc.Evaluate(midpoint + delta))); if (error_left < error_right) //error begin should be replaced since it has less error { begin = midpoint; } else //error end should be replaced since it has less error { end = midpoint; } } return((begin + end) / 2); // return location of max error }
public static void AddLine(ArcOfSphere edge, float begin, float end) { Vector2 begin_UV = SpaceConverter.SphereToUV(edge.Evaluate(begin)); Vector2 end_UV = SpaceConverter.SphereToUV(edge.Evaluate(end)); if (Vector2.Distance(begin_UV, end_UV) > threshold) { Vector2 delta_begin_UV = SpaceConverter.SphereToUV(edge.Evaluate(begin + 64 * delta)); Vector2 delta_end_UV = SpaceConverter.SphereToUV(edge.Evaluate(end - 64 * delta)); Vector2 control_point = Intersection(begin_UV, delta_begin_UV, delta_end_UV, end_UV); DebugUtility.Log("AddLine:", begin_UV, end_UV); lines.Add(new QuadraticBezier(edge, begin_UV, control_point, end_UV, begin, end)); } }
private static void Subdivide(ArcOfSphere arc, float begin, float end) { float midpoint = MaxErrorLocation(arc, begin, end); Vector2 L1 = SpaceConverter.SphereToUV(arc.Evaluate(begin)); Vector2 L2 = SpaceConverter.SphereToUV(arc.Evaluate(end)); Vector2 P = SpaceConverter.SphereToUV(arc.Evaluate(midpoint)); if (Point_Line_Distance(L1, L2, P) > threshold) // if the max error is greater than a threshold, recursively add the left and right halves into the list of lines { Subdivide(arc, begin, midpoint); Subdivide(arc, midpoint, end); } else { AddLine(arc, begin, end); } }