/// <summary>
        /// This is the method that actually does the work.
        /// </summary>
        /// <param name="DA">The DA object can be used to retrieve data from input parameters and
        /// to store data in output parameters.</param>
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            bool           reset = false;
            List <Point3d> FixedPoint = new List <Point3d>();
            List <Curve>   BoundaryCurves = new List <Curve>();
            double         SpringStrength = 1, PullStrengthM = 1, PullStrengthC = 1;

            DA.GetData <Mesh>(0, ref M);          //获取第0个输入值
            DA.GetData <Mesh>(1, ref TargetMesh); //获取第0个输入值
            //DA.GetDataList<Point3d>(1, FV);
            DA.GetDataList <Curve>(2, BoundaryCurves);
            //DA.GetDataList<Line>(1, FL);
            // DA.GetData<int>(2, ref restLength);
            DA.GetData <double>(3, ref PullStrengthM);
            DA.GetData <double>(4, ref PullStrengthC);
            DA.GetData <double>(5, ref SpringStrength);
            DA.GetData <bool>(6, ref reset);
            DA.GetDataList <Point3d>(7, FixedPoint);

            //内部计算过程start

            //initialize the solver

            if (reset || initialized == false)
            {
                #region reset
                counter     = 0;
                PS          = new KangarooSolver.PhysicalSystem();
                Goals       = new List <IGoal>();
                initialized = true;
                //get the Mesh points and boundary status
                //数组转列表
                List <Point3d> Pts      = new List <Point3d>(M.Vertices.ToPoint3dArray());
                List <Point3d> NakedPts = new List <Point3d>();
                //var IndexList = Enumerable.Range(0, PS.ParticleCount()).ToList();
                List <int> Is      = new List <int>();
                List <int> NakedIs = new List <int>();
                bool[]     Naked   = M.GetNakedEdgePointStatus();

                for (int i = 0; i < M.Vertices.Count; i++)
                {
                    PS.AddParticle(Pts[i], 1); //add a particle for every mesh vertex
                    Is.Add(i);
                    if (Naked[i])
                    //{ Goals.Add(new KangarooSolver.Goals.Anchor(i, Pts[i], 10000)); }// fix the boundaries strongly in place
                    {
                        NakedPts.Add(Pts[i]);
                        NakedIs.Add(i);
                    }
                }
                //Goals.Add(new KangarooSolver.Goals.OnCurve(NakedPts, BoundaryCurves[0], PullStrengthC));
                Goals.Add(new KangarooSolver.Goals.OnCurve(NakedIs, BoundaryCurves[0], PullStrengthC));
                //Goals.Add(new KangarooSolver.Goals.OnMesh(Pts, TargetMesh, 1));
                Goals.Add(new KangarooSolver.Goals.OnMesh(Is, TargetMesh, PullStrengthM));
                double sum_length = 0;
                for (int i = 0; i < M.TopologyEdges.Count; i++)
                {
                    Line   line   = M.TopologyEdges.EdgeLine(i);
                    double length = line.Length;
                    sum_length += length;
                }
                double average_length = sum_length / M.TopologyEdges.Count;
                for (int i = 0; i < M.TopologyEdges.Count; i++)
                {
                    var Ends = M.TopologyEdges.GetTopologyVertices(i);

                    int Start = M.TopologyVertices.MeshVertexIndices(Ends.I)[0];
                    int End   = M.TopologyVertices.MeshVertexIndices(Ends.J)[0];
                    //for each edge, a spring with rest length average_length, and strength 1
                    //Goals.Add(new KangarooSolver.Goals.Spring(Pts[Start], Pts[End], average_length, 1));
                    Goals.Add(new KangarooSolver.Goals.Spring(Start, End, average_length, SpringStrength));
                }
                for (int j = 0; j < FixedPoint.Count; j++)
                {
                    int index = PS.FindParticleIndex(FixedPoint[j], threshold, true);
                    Goals.Add(new KangarooSolver.Goals.Anchor(index, FixedPoint[j], 10000));
                }// fix the boundaries strongly in place
                 // foreach (IGoal G in Goals)
                 //  {
                 //     PS.AssignPIndex(G, 0.01);
                 // }
                 //GH_ObjectWrapper ow=new GH_ObjectWrapper(M);
                 //var gl = new KangarooSolver.Goals.Locator(ow);
                 // Goals.Add(gl);
                 //foreach (IGoal G in Goals) //Assign indexes to the particles in each Goal:
                 //{
                 //    PS.AssignPIndex(G, 0.0001); // the second argument is the tolerance distance below which points combine into a single particle
                 //    GoalList.Add(G);
                 //}
                #endregion
            }
            else
            {
                /*
                 * else
                 * {
                 *  int count = Springs.Count;
                 *
                 *  for (int i = 0; i < count; i++)
                 *  {
                 *      Spring S = Springs[i] as Spring;
                 *      Point3d Start = PS.GetPosition(S.PIndex[0]);
                 *      Point3d End = PS.GetPosition(S.PIndex[1]);
                 *
                 *      double LineLength = Start.DistanceTo(End);
                 *      if (LineLength > splitLength)
                 *      {
                 *          Point3d MidPt = 0.5 * (Start + End);
                 *          PS.AddParticle(MidPt, 1);
                 *          int newParticleIndex = PS.ParticleCount() - 1;
                 *          int endIndex = S.PIndex[1];
                 *          //set the end of the original spring to be the newly created midpoint
                 *          //and make a new spring from the midpoint to the original endpoint
                 *          S.PIndex[1] = newParticleIndex;
                 *          S.RestLength = 0.5 * LineLength;
                 *          Spring otherHalf = new Spring(newParticleIndex, endIndex, 0.5 * LineLength, 1);
                 *          Springs[i] = S;
                 *          Springs.Add(otherHalf);
                 *      }
                 *      else
                 *      {
                 *          S.RestLength += increment;
                 *          Springs[i] = S;
                 *      }
                 *  }
                 */


                //Step forward, using these goals, with multi-threading on, and stopping if the threshold is reached
                if (counter == 0 || (PS.GetvSum() > threshold && counter < 100))
                {
                    PS.Step(Goals, true, threshold);
                    double sum = PS.GetvSum();
                    counter++;
                }
                //内部计算过程end
                //Output the mesh, and how many iterations it took to converge
                //object Out = PS.GetOutput(GoalList);
                //DA.SetData(0, Out);
                M.Vertices.Clear();
                M.Vertices.AddVertices(PS.GetPositions());
            }
            DA.SetData(0, M);
            List <Point3d> pout = new List <Point3d>();
            pout = PS.GetPositions().ToList();
            DA.SetDataList(1, pout); //输出第一个输出值
            DA.SetData(2, counter);
        }
        /// <summary>
        /// This is the method that actually does the work.
        /// </summary>
        /// <param name="DA">The DA object can be used to retrieve data from input parameters and
        /// to store data in output parameters.</param>
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            double         threshold = 1e-3, subIteration = 10, maxIteration = 100;
            Mesh           TargetMesh = new Mesh();
            List <Point3d> Points = new List <Point3d>();
            List <Curve>   BoundaryCurves = new List <Curve>();
            List <IGoal>   CurvePull = new List <IGoal>();
            List <IGoal>   MeshSpring = new List <IGoal>();
            double         PullStrengthM = 1, SpringStiffness = 1, PullStrengthC = 1;
            int            row = 1, column = 1;
            bool           reset = false, bRing = false;

            DA.GetData <Mesh>(0, ref TargetMesh); //获取第0个输入值
            DA.GetDataList <Point3d>(1, Points);
            //DA.GetDataList<Curve >(2, BoundaryCurves);
            DA.GetDataList <IGoal>(2, MeshSpring);
            DA.GetDataList <IGoal>(3, CurvePull);
            DA.GetData <double>(4, ref SpringStiffness);
            DA.GetData <double>(5, ref PullStrengthM);
            //DA.GetData<double>(5, ref PullStrengthC);
            DA.GetData <int>(6, ref row);
            column = Points.Count / row;
            DA.GetData <double>(7, ref threshold);
            DA.GetData <double>(8, ref subIteration);
            DA.GetData <double>(9, ref maxIteration);
            DA.GetData <bool>(10, ref reset);
            DA.GetData <bool>(11, ref bRing);
            //内部计算过程start
            //initialize the solver

            if (reset || initialized == false)
            {
                counter     = 0;
                PS          = new KangarooSolver.PhysicalSystem();
                Goals       = new List <IGoal>();
                initialized = true;
                //grids = new List<List<Point3d>>();
                //indexs = new List<int>();
                for (int i = 0; i < row; i++)
                {
                    //List<Point3d> ps = new List<Point3d>();
                    for (int j = 0; j < column; j++)
                    {
                        PS.AddParticle(Points[i * column + j], 1);
                    }
                }
                //拉取到目标mesh
                Goals.Add(new KangarooSolver.Goals.OnMesh(Points, TargetMesh, PullStrengthM));
                //裸露点拉到边界线
                Goals.AddRange(CurvePull);
                Goals.AddRange(MeshSpring);
                //List<IGoal> GoalList = new List<IGoal>();
                foreach (IGoal G in Goals)      //Assign indexes to the particles in each Goal:
                {
                    PS.AssignPIndex(G, 0.0001); // the second argument is the tolerance distance below which points combine into a single particle
                }
                numIGoal_in = 1 + CurvePull.Count + MeshSpring.Count;
            }
            else
            {
                //前numIGoal_in个目标不变,而杆长弹簧力跟节点位置有关
                Goals  = Goals.GetRange(0, numIGoal_in);
                Points = PS.GetPositions().ToList();
                grids  = new List <List <Point3d> >();
                for (int i = 0; i < row; i++)
                {
                    List <Point3d> ps = new List <Point3d>();
                    for (int j = 0; j < column; j++)
                    {
                        ps.Add(Points[(i * column + j)]);
                        PS.AddParticle(Points[i * column + j], 1);
                        if (bRing && j == column - 1)
                        {
                            ps.Add(Points[(i * column)]);
                        }
                    }
                    grids.Add(ps);
                }
                List <double>         length_row    = new List <double>();
                List <double>         length_column = new List <double>();
                List <List <double> > gridLengths   = new List <List <double> >();
                //计算各条多线段的长度
                for (int i = 0; i < row; i++)
                {
                    double        sumLength = 0;
                    List <double> lengths   = new List <double>();
                    for (int j = 0; j < grids[i].Count - 1; j++)
                    {
                        double length = grids[i][j].DistanceTo(grids[i][j + 1]);;
                        lengths.Add(length);
                        sumLength += length;
                    }
                    //边界线上的多线段长度之和直接固定为首次的结果就好了,避免重叠后导致长度边长
                    gridLengths.Add(lengths);
                    if (counter == 0)
                    {
                        if (i == 0)
                        {
                            length_row_start = sumLength;
                        }
                        if (i == row - 1)
                        {
                            length_row_end = sumLength;
                        }
                    }
                    else
                    {
                        if (i == 0)
                        {
                            sumLength = length_row_start;
                        }
                        if (i == row - 1)
                        {
                            sumLength = length_row_end;
                        }
                    }
                    length_row.Add(sumLength);
                }
                List <double> length_row2    = length_row.GetRange(1, row - 2);
                double        length_row_sum = (length_row.Sum() + length_row2.Sum()) / 2;
                for (int j = 0; j < grids[0].Count; j++)
                {
                    double sumLength = 0;
                    for (int i = 0; i < row - 1; i++)
                    {
                        double length = grids[i][j].DistanceTo(grids[i + 1][j]);
                        sumLength += length;
                    }
                    if (counter == 0)
                    {
                        if (j == 0)
                        {
                            length_column_start = sumLength;
                        }
                        if (j == column - 1)
                        {
                            length_column_end = sumLength;
                        }
                    }
                    else
                    {
                        if (j == 0)
                        {
                            sumLength = length_column_start;
                        }
                        if (j == row - 1)
                        {
                            sumLength = length_column_end;
                        }
                    }
                    length_column.Add(sumLength);
                }
                List <double> length_column2    = length_column.GetRange(1, column - 2);
                double        length_column_sum = (length_column.Sum() + length_column2.Sum()) / 2;
                //弹簧
                for (int i = 0; i < row; i++)
                {
                    for (int j = 0; j < grids[i].Count - 1; j++)
                    {
                        double relativeLength = (length_column[j] + length_column[j + 1]) / 2 / length_column_sum;
                        if (bRing && j == grids[i].Count - 2)
                        {
                            Goals.Add(new KangarooSolver.Goals.Spring(
                                          i * column + j, i * column, relativeLength * length_row[i] * factor, SpringStiffness * length_row.Sum() / row / length_row[i]));
                        }
                        else
                        {
                            Goals.Add(new KangarooSolver.Goals.Spring(
                                          i * column + j, i * column + j + 1, relativeLength * length_row[i] * factor, SpringStiffness * length_row.Sum() / row / length_row[i]));
                        }
                    }
                }
                //弹簧
                for (int j = 0; j < column; j++)
                {
                    for (int i = 0; i < row - 1; i++)
                    {
                        double relativeLength = (length_row[i] + length_row[i + 1]) / 2 / length_row_sum;
                        Goals.Add(new KangarooSolver.Goals.Spring(
                                      (i + 1) * column + j, i * column + j, relativeLength * length_column[j] * factor, SpringStiffness * length_column.Sum() / column / length_column[j]));
                    }
                }
                //Step forward, using these goals, with multi-threading on, and stopping if the threshold is reached
                PS = new KangarooSolver.PhysicalSystem();
                for (int i = 0; i < row; i++)
                {
                    //List<Point3d> ps = new List<Point3d>();
                    for (int j = 0; j < column; j++)
                    {
                        PS.AddParticle(Points[i * column + j], 1);
                    }
                }
                if (counter == 0 || (vSum > threshold && counter < maxIteration))
                {
                    for (int i = 0; i < subIteration; i += 1)
                    {
                        PS.Step(Goals, true, threshold);
                        counter++;
                    }
                    vSum = PS.GetvSum();
                }
                //内部计算过程end
                //Output the mesh, and how many iterations it took to converge
            }
            List <Point3d> pout = PS.GetPositions().ToList();

            DA.SetDataList(0, pout); //输出第一个输出值
            DA.SetData(1, counter);
            //List<double> ars = SphereCollide_wqs.ars;
            //DA.SetDataList(2, ars); //输出第一个输出值
            //List<Point3d> pp = Goals[1].PPos.ToList();
            // DA.SetDataList(3, pout); //输出第一个输出值
        }