private void sphereViewRotatedZHEncodedFunction_MouseUp(object sender, MouseEventArgs e) { // Determine the position on the sphere Vector AlignAxis = null; if (e.X < sphereViewRotatedZHEncodedFunction.Width / 2) { // Front float fDx = e.X / (.25f * sphereViewRotatedZHEncodedFunction.Width) - 1.0f; float fDy = 1.0f - e.Y / (.5f * sphereViewRotatedZHEncodedFunction.Height); float fSDistance = fDx * fDx + fDy * fDy; if (fSDistance > 1.0f) { return; } AlignAxis = new Vector(fDx, fDy, (float)Math.Sqrt(1.0f - fSDistance)); } else { // Front float fDx = e.X / (.25f * sphereViewRotatedZHEncodedFunction.Width) - 3.0f; float fDy = 1.0f - e.Y / (.5f * sphereViewRotatedZHEncodedFunction.Height); float fSDistance = fDx * fDx + fDy * fDy; if (fSDistance > 1.0f) { return; } AlignAxis = new Vector(fDx, fDy, -(float)Math.Sqrt(1.0f - fSDistance)); } if (AlignAxis == null) { return; } // Compute rotation matrix Matrix3x3 Rotation = Matrix3x3.ComputeRotationMatrix(new Vector(0, 1, 0), AlignAxis); // Rotate the ZH so they lie on an arbitrary axis m_RotatedMappedCoeffsSH = new double[SH_ORDER * SH_ORDER]; for (int LobeIndex = 0; LobeIndex < ZH_LOBES_COUNT; LobeIndex++) { Vector RotatedLobeAxis = SphericalHarmonics.SHFunctions.SphericalToCartesian(m_MappedAxesZH[LobeIndex].x, m_MappedAxesZH[LobeIndex].y) * Rotation; double[] RotatedCoeffsZH = new double[SH_ORDER * SH_ORDER]; SphericalHarmonics.SHFunctions.ComputeRotatedZHCoefficients(m_MappedCoeffsZH[LobeIndex], RotatedLobeAxis, RotatedCoeffsZH); for (int CoefficientIndex = 0; CoefficientIndex < SH_ORDER * SH_ORDER; CoefficientIndex++) { m_RotatedMappedCoeffsSH[CoefficientIndex] += RotatedCoeffsZH[CoefficientIndex]; } } sphereViewRotatedZHEncodedFunction.RebuildSpheres(new SphereView.GetValue(GetValueEvaluatedRotatedMappedZHEncoding)); sphereViewRotatedZHEncodedFunction.Refresh(); }