Exemplo n.º 1
0
    /// <summary>
    /// Define al FEM triangle functions and add them to the given list of energy functions.
    /// </summary>
    /// <param name="efs"></param>
    private void initFEMTriangleFunctions(List <EnergyFunction> efs)
    {
        // Initial values taken from https://github.com/InteractiveComputerGraphics/PositionBasedDynamics/blob/master/Demos/Simulation/SimulationModel.cpp#L11 onwards.
        const float youngsModulusX     = 1;
        const float youngsModulusY     = 1;
        const float youngsModulusShear = 1;
        const float poissonRatioXY     = 0.3f;
        const float poissonRatioYX     = 0.3f;

        // https://github.com/InteractiveComputerGraphics/PositionBasedDynamics/blob/master/Demos/ClothDemo/main.cpp#L354
        // loop over every triangle



        foreach (Util.Triangle triangle in triangles)
        {
            // Only add FEMTetConstriant for now
            EnergyFunction fem = FEMTriangleFunction.create(this, triangle.a, triangle.b, triangle.c, youngsModulusX, youngsModulusY, youngsModulusShear, poissonRatioXY, poissonRatioYX);
            if (fem != null)
            {
                efs.Add(fem);
            }

            // TODO: OR we can only add Distance and Volume constraints
            // https://github.com/InteractiveComputerGraphics/PositionBasedDynamics/blob/master/Demos/ClothDemo/main.cpp#L340
        }
        Debug.Log(efs.Count + " FEMFunctions created for " + triangles.Length + " triangles");
    }
Exemplo n.º 2
0
        // find state that has minimum energy
        public static double FindMinimumState(double initialState, EnergyFunction energyFunc, SimulatedAnnealingParams param, NotifyProgressFunction notifyFunc)
        {
            double currentState  = initialState;
            double currentEnergy = energyFunc(currentState);
            double bestState     = currentState;
            double bestEnergy    = currentEnergy;
            double T             = param.initialTemp;
            double coolingFactor = CalculateCoolingFactor(param.initialTemp, param.maxIteration, param.freezeIteration);

            Console.WriteLine("state {0} energy {1} T {2} cooling {3} ", currentState, currentEnergy, T, coolingFactor);

            int i = 0;

            notifyFunc(i);
            // count how many times in a row the random walk has met a higher energy neighbour and not switch state
            // the search area should be wider as the count is higher
            int    noSwitchCount = 0;
            double stepModifier  = 1.0;

            while (i < param.maxIteration)
            {
                if (bestEnergy <= EPSILON && stepModifier <= EPSILON)
                {
                    break;
                }

                double newState = NeighborFunction(currentState, param.stepSize * stepModifier);
                if (newState != currentState)
                {
                    double newEnergy = energyFunc(newState);

                    Console.WriteLine("iteration {0} modifier {1} state {2} energy {3} newstate {4} energy {5} ", i, stepModifier, currentState, currentEnergy, newState, newEnergy);

                    bool takeStep = false;
                    if (Double.IsNaN(newEnergy))
                    {
                        // new energy has bad value, skip
                    }
                    else
                    {
                        if (newEnergy < bestEnergy)
                        {
                            bestState  = newState;
                            bestEnergy = newEnergy;
                        }

                        if (newEnergy < currentEnergy)
                        {
                            takeStep = true;
                        }
                        else
                        {
                            double r    = rand.NextDouble();
                            double prob = AcceptanceProbability(currentEnergy, newEnergy, T, param.boltzmanConstant);
                            takeStep = r < prob;
                            Console.WriteLine("energy {0} newenergy {1} T {2} prob {3}", currentEnergy, newEnergy, T, prob);
                        }

                        // use local gradient to estimate step modifier bounds
                        double gradient = Math.Min(Math.Max(Math.Abs((newEnergy - currentEnergy) / (newState - currentState)), EPSILON), 1.0e10);
                        if (takeStep)
                        {
                            noSwitchCount = 0;
                            currentState  = newState;
                            currentEnergy = newEnergy;
                        }
                        else
                        {
                            ++noSwitchCount;
                        }

                        if (currentEnergy > T)
                        {
                            stepModifier = Math.Max(Math.Min(stepModifier * 2.0, bestEnergy / gradient), EPSILON);
                        }
                        else
                        {
                            stepModifier = Math.Max(stepModifier / 2.0, currentEnergy / gradient);
                        }
                    }
                }
                else
                {
                    // if newState == currentState skip
                }

                T = Math.Max(T * coolingFactor, MIN_TEMPERATURE);
                ++i;
                notifyFunc(i);
            }
            // rounding for cleaner result
            bestState = Math.Round(bestState, 9);

            return(bestState);
        }
Exemplo n.º 3
0
 public void Add(EnergyFunction f)
 {
     functions.Add(f);
 }