예제 #1
0
        void    UpdateGraph1D()
        {
            double time = (DateTime.Now - m_startTime).TotalSeconds;

            if (checkBoxGPU.Checked)
            {
                UpdateGraph1D_GPU(time);
                return;
            }

            TestTransform1D(time);

            m_image.Clear(float4.One);

            float2 rangeX = new float2(0.0f, SIGNAL_SIZE);
            float2 rangeY = new float2(-1, 1);

            // Plot input signal
            if (checkBoxShowInput.Checked)
            {
//				m_image.PlotGraphAutoRangeY( m_black, rangeX, ref rangeY, ( float x ) => {
                m_image.PlotGraph(m_black, rangeX, rangeY, ( float x ) => {
                    int X = Math.Max(0, Math.Min(SIGNAL_SIZE - 1, (int)x));
                    return((float)m_signalSource[X].r);
                });
            }

            // Plot reconstructed signals (Real and Imaginary parts)
            if (checkBoxShowReconstructedSignal.Checked)
            {
                m_image.PlotGraph(m_red, rangeX, rangeY, ( float x ) => {
                    int X = Math.Max(0, Math.Min(SIGNAL_SIZE - 1, (int)x));
                    return((float)m_signalReconstructed[X].r);
                });
                m_image.PlotGraph(m_blue, rangeX, rangeY, ( float x ) => {
                    int X = Math.Max(0, Math.Min(SIGNAL_SIZE - 1, (int)x));
                    return((float)m_signalReconstructed[X].i);
                });
            }

            m_image.PlotAxes(m_black, rangeX, rangeY, 16.0f, 0.1f);

            //////////////////////////////////////////////////////////////////////////
            // Render spectrum as (Real=Red, Imaginary=Blue) vertical lines for each frequency
            float2 cornerMin = m_image.RangedCoordinates2ImageCoordinates(rangeX, rangeY, new float2(rangeX.x, -1.0f));
            float2 cornerMax = m_image.RangedCoordinates2ImageCoordinates(rangeX, rangeY, new float2(rangeX.y, +1.0f));
            float2 delta     = cornerMax - cornerMin;
            float  zeroY     = cornerMin.y + 0.5f * delta.y;

            float2 Xr0 = new float2(0, zeroY);
            float2 Xr1 = new float2(0, 0);
            float2 Xi0 = new float2(0, zeroY);
            float2 Xi1 = new float2(0, 0);

            float scale = 10.0f;

            float4 spectrumColorRe = new float4(1, 0.25f, 0, 1);
            float4 spectrumColorIm = new float4(0, 0.5f, 1, 1);
            int    size            = m_spectrum.Length;
            int    halfSize        = size >> 1;

            for (int i = 0; i < m_spectrum.Length; i++)
            {
                float X = cornerMin.x + i * delta.x / m_spectrum.Length;
//				int		frequencyIndex = i;							// Show spectrum as output by FFT
                int frequencyIndex = (i + halfSize) % size;                                     // Show offset spectrum with DC term in the middle
                Xr0.x = X;
                Xr1.x = X;
                Xr1.y = cornerMin.y + 0.5f * (scale * (float)m_spectrum[frequencyIndex].r + 1.0f) * delta.y;
                Xi0.x = X + 1;
                Xi1.x = X + 1;
                Xi1.y = cornerMin.y + 0.5f * (scale * (float)m_spectrum[frequencyIndex].i + 1.0f) * delta.y;

                m_image.DrawLine(spectrumColorRe, Xr0, Xr1);
                m_image.DrawLine(spectrumColorIm, Xi0, Xi1);
            }

            imagePanel.Bitmap = m_image.AsBitmap;
        }
        /// <summary>
        /// Computes the radius of the sphere tangent to a vertex given a set of neighbor vertices
        /// </summary>
        /// <param name="_P"></param>
        /// <param name="_N"></param>
        /// <param name="_neighbors"></param>
        /// <returns></returns>
        float   ComputeTangentSphereRadius_SUPER_SLOW(float3 _P, float3 _N, float3[] _neighbors)
        {
            ImageFile graph = new ImageFile((uint)panelOutputGraph.Width, (uint)panelOutputGraph.Height, PIXEL_FORMAT.BGRA8, new ColorProfile(ColorProfile.STANDARD_PROFILE.sRGB));

            graph.Clear(float4.One);

            Func <float3, float, float3[], float> SquareDistance = (float3 _C, float _R, float3[] _Pns) => { float result = 0.0f; foreach (float3 Pn in _Pns)
                                                                                                             {
                                                                                                                 result += (Pn - _C).LengthSquared - _R * _R;
                                                                                                             }
                                                                                                             return(Math.Abs(result)); };
//			Func<float3,float3[],float>		SquareDistance = ( float3 _C, float3[] _Pns ) => { float result = 0.0f; foreach ( float3 Pn in _Pns ) result += (Pn - _C).Length; return result / _Pns.Length; };

            float2 rangeX = new float2(0, 4), rangeY = new float2(-50, 50);

            graph.PlotAxes(float4.UnitW, rangeX, rangeY, 0.5f, 5.0f);
            graph.PlotGraph(float4.UnitW, rangeX, rangeY, ( float x ) => { return(SquareDistance(_P - x * _N, x, _neighbors)); });

            const float eps = 0.01f;
            const float tol = 1e-3f;

            float  previousR           = -float.MaxValue;
            float  R                   = 0.0f;
            float  step                = 0.1f;
            float3 C                   = _P;
            int    iterationsCount     = 0;
            float  previousSqDistance  = float.MaxValue;
            float  bestSqDistance      = float.MaxValue;
            float  bestR               = 0.0f;
            int    bestIterationsCount = 0;

            while (step > tol && R < 10000.0f && iterationsCount < 1000)
            {
                // Compute gradient
                float sqDistance  = SquareDistance(C, R, _neighbors);
                float sqDistance2 = SquareDistance(C - eps * _N, R + eps, _neighbors);
                float grad        = (sqDistance2 - sqDistance) / eps;

                if (previousSqDistance < sqDistance)
                {
                    step *= 0.95f;                      // Climbing up again, roll down slower...
                }

                // Follow opposite gradient direction toward minimum
                previousR = R;
                R        -= step * grad;
                C         = _P - R * _N;
                iterationsCount++;

                previousSqDistance = sqDistance;
                if (sqDistance < bestSqDistance)
                {
                    bestSqDistance      = sqDistance;
                    bestR               = previousR;
                    bestIterationsCount = iterationsCount;
                }

                graph.DrawLine(new float4(1, 0, 0, 1), graph.RangedCoordinates2ImageCoordinates(rangeX, rangeY, new float2(previousR, sqDistance)), graph.RangedCoordinates2ImageCoordinates(rangeX, rangeY, new float2(R, SquareDistance(_P - R * _N, R, _neighbors))));

                float k = 0.1f;
                graph.DrawLine(new float4(0, 0.5f, 0, 1), graph.RangedCoordinates2ImageCoordinates(rangeX, rangeY, new float2(previousR, k * (iterationsCount - 1))), graph.RangedCoordinates2ImageCoordinates(rangeX, rangeY, new float2(R, k * iterationsCount)));
            }

            // Since we crossed the minimum, take the average for a better result
            R = 0.5f * (R + previousR);

            panelOutputGraph.m_bitmap = graph.AsBitmap;
            panelOutputGraph.Refresh();
            labelResult.Text = "R = " + R + " (" + previousSqDistance + ") in " + iterationsCount + " iterations...\r\nBest = " + bestR + " (" + bestSqDistance + ") in " + bestIterationsCount + " iterations...";

            return(R);
        }
예제 #3
0
        void    UpdateLevels()
        {
//          const uint	BUCKETS_PER_LAYER = LEVEL_BUCKETS_COUNT / LAYERS_COUNT;
//
//          float	normalizer = 1.0f / (LAYERS_COUNT-1);
//          uint	bucketIndex = 0;
//          for ( uint layerIndex=0; layerIndex < LAYERS_COUNT; layerIndex++ ) {
//              for ( uint i=0; i < BUCKETS_PER_LAYER; i++ ) {
//                  float	t = (float) i / BUCKETS_PER_LAYER;
//                  m_levels[bucketIndex++] = normalizer * (layerIndex + t);
//              }
//          }

                        #if CUBIC_SPLINES
            float F      = 4.0f;
            float T0     = F * (0 * 1.0f + floatTrackbarControlTangent0.Value);
            float T1_in  = F * (0 * 1.0f + floatTrackbarControlTangent1.Value);
            float T1_out = checkBoxSplit1.Checked ? F * (0 * 1.0f + floatTrackbarControlTangent1_Out.Value) : T1_in;
            float T2_in  = F * (0 * 1.0f + floatTrackbarControlTangent2.Value);
            float T2_out = checkBoxSplit2.Checked ? F * (0 * 1.0f + floatTrackbarControlTangent2_Out.Value) : T2_in;
            float T3     = F * (0 * 1.0f + floatTrackbarControlTangent3.Value);

            float4[] hermites = new float4[6];
//              hermites[0].Set( 0.0f, T0, 1.0f, T1 );
//              hermites[1].Set( 0.0f, T1, 1.0f, T2 );
//              hermites[2].Set( 0.0f, T2, 1.0f, T3 );

            hermites[0].Set(0.0f, T0, 0.5f, -0.5f * (T0 - T1_in));
            hermites[1].Set(0.5f, -0.5f * (T0 - T1_in), 1.0f, T1_in);
            hermites[2].Set(0.0f, T1_out, 0.5f, 0.5f * (T1_out + T2_in));
            hermites[3].Set(0.5f, 0.5f * (T1_out + T2_in), 1.0f, T2_in);
            hermites[4].Set(0.0f, T2_out, 0.5f, 0.5f * (T2_out + T3));
            hermites[5].Set(0.5f, 0.5f * (T2_out + T3), 1.0f, T3);
                        #elif POWERS
//              float[]		powers = new float[LAYERS_COUNT-1];
//              powers[0] = floatTrackbarControlTangent0.Value;
//              powers[1] = floatTrackbarControlTangent1.Value;
//              powers[2] = floatTrackbarControlTangent2.Value;
//              powers[0] = powers[0] < 0.0f ? 1.0f / (1.0f - 9.0f * powers[0]) : 1.0f + 9.0f * powers[0];
//              powers[1] = powers[1] < 0.0f ? 1.0f / (1.0f - 9.0f * powers[1]) : 1.0f + 9.0f * powers[1];
//              powers[2] = powers[2] < 0.0f ? 1.0f / (1.0f - 9.0f * powers[2]) : 1.0f + 9.0f * powers[2];

            float[] powers  = new float[LAYERS_COUNT - 1];
            float[] scalesX = new float[LAYERS_COUNT - 1];
            float[] scalesY = new float[LAYERS_COUNT - 1];
            powers[0] = floatTrackbarControlTangent0.Value;
            powers[1] = floatTrackbarControlTangent1.Value;
            powers[2] = floatTrackbarControlTangent2.Value;
//              powers[0] = powers[0] < 0.0f ? 1.0f / (1.0f - 9.0f * powers[0]) : 1.0f + 9.0f * powers[0];
//              powers[1] = powers[1] < 0.0f ? 1.0f / (1.0f - 9.0f * powers[1]) : 1.0f + 9.0f * powers[1];
//              powers[2] = powers[2] < 0.0f ? 1.0f / (1.0f - 9.0f * powers[2]) : 1.0f + 9.0f * powers[2];
            powers[0]  = (float)Math.Pow(10.0, 3.0 * powers[0]);
            powers[1]  = (float)Math.Pow(10.0, 3.0 * powers[1]);
            powers[2]  = (float)Math.Pow(10.0, 3.0 * powers[2]);
            scalesX[0] = 1.0f;                    // + 0.5f * Math.Max( 0.0f,  floatTrackbarControlTangent0.Value );
            scalesY[0] = 1.0f;                    // + 0.5f * Math.Max( 0.0f, -floatTrackbarControlTangent0.Value );
            scalesX[1] = 1.0f;                    // + 0.5f * Math.Max( 0.0f,  floatTrackbarControlTangent1.Value );
            scalesY[1] = 1.0f;                    // + 0.5f * Math.Max( 0.0f, -floatTrackbarControlTangent1.Value );
            scalesX[2] = 1.0f;                    // + 0.5f * Math.Max( 0.0f,  floatTrackbarControlTangent2.Value );
            scalesY[2] = 1.0f;                    // + 0.5f * Math.Max( 0.0f, -floatTrackbarControlTangent2.Value );
                        #endif

            for (uint bucketIndex = 0; bucketIndex < LEVEL_BUCKETS_COUNT; bucketIndex++)
            {
                float maskIn = (float)bucketIndex / (LEVEL_BUCKETS_COUNT - 1);

                float scaledMask = (LAYERS_COUNT - 1) * maskIn;
                uint  layerStart = Math.Min(LAYERS_COUNT - 2, (uint)Math.Floor(scaledMask));
                float t          = scaledMask - layerStart;

                                #if CUBIC_SPLINES
                // Compute Hermite curves
//                  float4	hermite = hermites[layerStart];
//                  float	maskOut = hermite.x * (1+2*t)*(1-t)*(1-t)
//                                  + hermite.y * t*(1-t)*(1-t)
//                                  + hermite.z * t*t*(3-2*t)
//                                  + hermite.w * t*t*(t-1);

                t = 2.0f * t;
                uint hermiteIndex = 2 * layerStart;
                if (t > 1.0f)
                {
                    hermiteIndex++;
                    t -= 1.0f;
                }
                float4 hermite = hermites[hermiteIndex];
                float  maskOut = hermite.x * (1 + 2 * t) * (1 - t) * (1 - t)
                                 + hermite.y * t * (1 - t) * (1 - t)
                                 + hermite.z * t * t * (3 - 2 * t)
                                 + hermite.w * t * t * (t - 1);
                                #elif POWERS
//                  // Apply curves
//                  float	tIn = 2.0f * t - 1.0f;
//                  float	tOut = Math.Sign( tIn ) * (float) Math.Pow( Math.Abs( tIn ), powers[layerStart] );
//                  float	maskOut = (layerStart + 0.5f * (1.0f + tOut)) / (LAYERS_COUNT-1);

                float maskOut = scalesY[layerStart] * (float)Math.Pow(t / scalesX[layerStart], powers[layerStart]);
                                #endif

                maskOut = Math.Max(0, Math.Min(1, maskOut));
                maskOut = (layerStart + maskOut) / (LAYERS_COUNT - 1);
                m_levels[bucketIndex] = maskOut;
            }

            // Redraw levels
            float2 rangeX = new float2(0, 1);
            float2 rangeY = new float2(0, 1);
            m_imageLevels.Clear(float4.One);
            m_imageLevels.PlotAxes(float4.UnitW, rangeX, rangeY, 1.0f / (LAYERS_COUNT - 1), 1.0f / (LAYERS_COUNT - 1));
            m_imageLevels.PlotGraph(float4.UnitW, rangeX, rangeY, ( float x ) => { return(m_levels[Math.Min(LEVEL_BUCKETS_COUNT - 1, (uint)((LEVEL_BUCKETS_COUNT - 1) * x))]); });
            for (int layerIndex = 1; layerIndex < LAYERS_COUNT; layerIndex++)
            {
                m_imageLevels.DrawLine(new float4(0.2f, 0.5f, 0.75f, 1), m_imageLevels.RangedCoordinates2ImageCoordinates(rangeX, rangeY, new float2((float)layerIndex / (LAYERS_COUNT - 1), 0)), m_imageLevels.RangedCoordinates2ImageCoordinates(rangeX, rangeY, new float2((float)layerIndex / (LAYERS_COUNT - 1), 1)));
                m_imageLevels.DrawLine(new float4(0.2f, 0.5f, 0.75f, 1), m_imageLevels.RangedCoordinates2ImageCoordinates(rangeX, rangeY, new float2(0, (float)layerIndex / (LAYERS_COUNT - 1))), m_imageLevels.RangedCoordinates2ImageCoordinates(rangeX, rangeY, new float2(1, (float)layerIndex / (LAYERS_COUNT - 1))));
            }
            panelOutputLevels.m_bitmap = m_imageLevels.AsBitmap;
            panelOutputLevels.Refresh();
        }
        /// <summary>
        /// Computes the radius of the sphere tangent to a vertex given a set of neighbor vertices
        /// </summary>
        /// <param name="_P"></param>
        /// <param name="_N"></param>
        /// <param name="_neighbors"></param>
        /// <returns></returns>
        float   ComputeTangentSphereRadius(float3 _P, float3 _N, float3[] _neighbors, bool _debugGraph)
        {
            Func <float3, double, float3[], double> SquareDistance = (float3 _C, double _R, float3[] _Pns) => {
                double result = 0.0f;
                foreach (float3 Pn in _Pns)
                {
                    result += (Pn - _C).LengthSquared - _R * _R;
                }
                return(result);
            };

            float2 rangeX = new float2(-4, 4), rangeY = new float2(-50, 50);

            if (_debugGraph)
            {
                graph.Clear(float4.One);
                graph.PlotAxes(float4.UnitW, rangeX, rangeY, 0.5f, 5.0f);
                graph.PlotGraph(float4.UnitW, rangeX, rangeY, ( float x ) => { return((float)SquareDistance(_P - x * _N, x, _neighbors)); });
            }

            const float  eps = 0.01f;
            const double tol = 1e-3;

            double previousR           = -double.MaxValue;
            double R                   = 0.0f;
            float3 C                   = _P;
            int    iterationsCount     = 0;
            double previousSqDistance  = double.MaxValue;
            double bestSqDistance      = double.MaxValue;
            double bestR               = 0.0f;
            int    bestIterationsCount = 0;

            while (Math.Abs(R) < 10000.0f && iterationsCount < 1000)
            {
                // Compute gradient
                double sqDistance  = SquareDistance(C, R, _neighbors);
                double sqDistance2 = SquareDistance(C - eps * _N, R + eps, _neighbors);
                double grad        = (sqDistance2 - sqDistance) / eps;

                // Compute intersection with secant Y=0
                double t = -sqDistance * (Math.Abs(grad) > 1e-6f ? 1.0f / grad : (Math.Sign(grad) * 1e6));
                if (Math.Abs(t) < tol)
                {
                    break;
                }

                previousR = R;
                R        += t;
                C         = _P - (float)R * _N;
                iterationsCount++;

                previousSqDistance = sqDistance;
                if (sqDistance < bestSqDistance)
                {
                    bestSqDistance      = sqDistance;
                    bestR               = previousR;
                    bestIterationsCount = iterationsCount;
                }

                if (_debugGraph)
                {
                    graph.DrawLine(new float4(1, 0, 0, 1), graph.RangedCoordinates2ImageCoordinates(rangeX, rangeY, new float2((float)previousR, (float)sqDistance)), graph.RangedCoordinates2ImageCoordinates(rangeX, rangeY, new float2((float)R, (float)SquareDistance(_P - (float)R * _N, R, _neighbors))));
                    float k = 0.1f;
                    graph.DrawLine(new float4(0, 0.5f, 0, 1), graph.RangedCoordinates2ImageCoordinates(rangeX, rangeY, new float2((float)previousR, k * (iterationsCount - 1))), graph.RangedCoordinates2ImageCoordinates(rangeX, rangeY, new float2((float)R, k * iterationsCount)));
                }
            }

            if (_debugGraph)
            {
                panelOutputGraph.m_bitmap = graph.AsBitmap;
                panelOutputGraph.Refresh();
                labelResult.Text = "R = " + R + " (" + previousSqDistance + ") in " + iterationsCount + " iterations...\r\nBest = " + bestR + " (" + bestSqDistance + ") in " + bestIterationsCount + " iterations...";
            }

//          if ( R < 1000.0 )
//              throw new Exception( "Maybe R should be Math.Abs()'ed? (neighbors are all lying on a flat plane or in a ?" );
            R = Math.Max(-10000.0, Math.Min(10000.0, R));

            return((float)R);
        }