static float ABFComputeGradAlpha(ABFSystem sys, ABFFace f, ABFHalfEdge e) { ABFVertex v = e.Vertex, v1 = e.Next.Vertex, v2 = e.Next.Next.Vertex; float deriv = (sys.Alpha[e.AngleID] - sys.Beta[e.AngleID]) * sys.Weight[e.AngleID]; deriv += sys.LambdaTriangle[f.AngleID]; if (!v.PVertex.IsBorder) { deriv += sys.LambdaPlanar[v.AngleID]; } if (!v1.PVertex.IsBorder) { float product = ABFComputeSinProduct(sys, v1, e.AngleID); deriv += sys.LambdaLength[v1.AngleID] * product; } if (!v2.PVertex.IsBorder) { float product = ABFComputeSinProduct(sys, v2, e.AngleID); deriv += sys.LambdaLength[v2.AngleID] * product; } return(deriv); }
/// <summary> /// ベクトルの成す角を返す /// </summary> /// <param name="v1">先端1</param> /// <param name="v2">対象点</param> /// <param name="v3">先端2</param> /// <returns>点v2における角度</returns> static float ABFVectorAngle(ABFVertex v1, ABFVertex v2, ABFVertex v3) { V3 d1, d2; d1 = (v1.PVertex.Position - v2.PVertex.Position); d1.Normalize(); d2 = (v3.PVertex.Position - v2.PVertex.Position); d2.Normalize(); var cos = d1.Dot(d2) / (d1.LengthSq() * d2.LengthSq()); return((float)Math.Acos(cos)); }
static float ABFComputeSinProduct(ABFSystem sys, ABFVertex v, int aid) { ABFHalfEdge e, e1, e2; float sin1, sin2; sin1 = sin2 = 1f; e = v.HEdge; do { e1 = e.Next; e2 = e.Next.Next; if (aid == e1.AngleID) { /* we are computing a derivative for this angle, * so we use cos and drop the other part */ sin1 *= sys.Cosine[e1.AngleID]; sin2 = 0f; } else { sin1 *= sys.Sine[e1.AngleID]; } if (aid == e2.AngleID) { /* see above */ sin1 = 0f; sin2 *= sys.Cosine[e2.AngleID]; } else { sin2 *= sys.Sine[e2.AngleID]; } e = e.Next.Next.Pair; } while (e != v.HEdge); return(sin1 - sin2); }