private static IntersectionCurve Gradient(IIntersect obj0, IIntersect obj1, Vector2 value0, Vector2 value1, float precision) { var p0 = obj0.Evaluate(value0); var p1 = obj1.Evaluate(value1); var i = 0; var currAlpha = _startGradientAlpha; var dist = Vector3.Distance(p1, p0); while (dist > _gradientEps) { if (++i > 10000) { return(null); } try { var grads = GetGradient(obj0, obj1, value0, value1); value0 -= currAlpha * grads[0]; value1 -= currAlpha * grads[1]; value0.X = Math.Min(1, Math.Max(0, value0.X)); value0.Y = Math.Min(1, Math.Max(0, value0.Y)); value1.X = Math.Min(1, Math.Max(0, value1.X)); value1.Y = Math.Min(1, Math.Max(0, value1.Y)); var pNew0 = obj0.Evaluate(value0); var pNew1 = obj1.Evaluate(value1); var newDist = Vector3.Distance(pNew0, pNew1); if (newDist > dist) { currAlpha /= 2; currAlpha = Math.Max(currAlpha, 0.0001f); } else { currAlpha *= 2; dist = newDist; p0 = pNew0; p1 = pNew1; } } catch (Exception e) { return(null); } } return(MyFriendNewton(obj0, obj1, value0, value1, precision)); }
public static Vector4 GetF(IIntersect obj0, IIntersect obj1, Vector2 uv0, Vector2 uv1, Vector2 uvNew0, Vector2 uvNew1, float alpha) { var P0 = obj0.Evaluate(uv0); var Q = obj1.Evaluate(uvNew1); var P1 = obj0.Evaluate(uvNew0); var dU0 = obj0.EvaluateDU(uv0); var dV0 = obj0.EvaluateDV(uv0); var dU1 = obj1.EvaluateDU(uv1); var dV1 = obj1.EvaluateDV(uv1); var normalT = GetTNormal(dU0, dU1, dV0, dV1); var d = alpha * 10; return(new Vector4(P1 - Q, Vector3.Dot(P1 - P0, normalT) - d)); }
private static List <Vector2> GetGradient(IIntersect obj0, IIntersect obj1, Vector2 point0, Vector2 point1) { var eval0 = obj0.Evaluate(point0); var eval1 = obj1.Evaluate(point1); var diff = eval0 - eval1; var eval0u = obj0.EvaluateDU(point0).Normalized(); var eval0v = obj0.EvaluateDV(point0).Normalized(); var eval1u = obj1.EvaluateDU(point1).Normalized(); var eval1v = obj1.EvaluateDV(point1).Normalized(); var grad0 = new Vector2(Vector3.Dot(diff, eval0u), Vector3.Dot(diff, eval0v)); var grad1 = new Vector2(Vector3.Dot(-diff, eval1u), Vector3.Dot(-diff, eval1v)); return(new List <Vector2>() { grad0, grad1 }); }
private static IntersectionCurve MyFriendNewton(IIntersect obj0, IIntersect obj1, Vector2 uv0, Vector2 uv1, float precision) { var newtonAlpha = _newtonStartAlpha; var uvStart0 = uv0; var uvStart1 = uv1; var uvPrev0 = uvStart0; var uvPrev1 = uvStart1; var backed = false; var finished = false; var pStart = obj0.Evaluate(uvStart0); var countForCylinder = 0; var loops = 0; var pointsList = new List <Vector3>(); var uvList0 = new List <Vector2>(); var uvList1 = new List <Vector2>(); pointsList.Add(obj0.Evaluate(uv0)); uvList0.Add(uv0); uvList1.Add(uv1); while (!finished) { var currAlpha = newtonAlpha; int innerLoops = 0; while (true) { var betterPoint = GetNewtonIterationPoint(obj0, obj1, uvPrev0, uvPrev1, uv0, uv1, currAlpha); var uvDiff0 = new Vector2(betterPoint.X, betterPoint.Y); var ufDivv1 = new Vector2(betterPoint.Z, betterPoint.W); var upd0 = UpdateUV(obj0, uv0, uvDiff0, backed); var upd1 = UpdateUV(obj1, uv1, ufDivv1, backed); uv0 = upd0.UV; uv1 = upd1.UV; if (upd0.End || upd1.End) { finished = true; break; } if (upd0.Back || upd1.Back) { pointsList.Reverse(); uvList0.Reverse(); uvList1.Reverse(); uv0 = uvStart0; uv1 = uvStart1; uvPrev0 = uvStart0; uvPrev1 = uvStart1; newtonAlpha = -_newtonStartAlpha; countForCylinder = 5; backed = true; currAlpha = newtonAlpha; break; } var ev0 = obj0.Evaluate(uv0); var ev1 = obj1.Evaluate(uv1); var dst = Vector3.Distance(ev0, ev1); if (precision > dst) { break; } if (++innerLoops > 30) { return(null); } } uvPrev0 = uv0; uvPrev1 = uv1; var p1 = obj0.Evaluate(uv0); var p2 = obj1.Evaluate(uv1); var dist = Vector3.Distance(p2, p1); if (_alphaEpsilon < Vector3.Distance(p2, p1)) { currAlpha /= 2; } pointsList.Add(obj0.Evaluate(uv0)); uvList0.Add(uv0); uvList1.Add(uv1); if (loops > 1000 || _finalEpsilon > Vector3.Distance(pStart, p1) && countForCylinder > 10) { break; } countForCylinder++; loops++; } return(new IntersectionCurve(pointsList, uvList0, uvList1)); }