/// <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) { Mesh TargetMesh = new Mesh(); List <Point3d> Points = new List <Point3d>(); double PullStrengthM = 100, CollideStrength = 1; double radius = 1; bool reset = true; double k_SpecialPoint = 1, g_SpecialPoint = 1, k_SpecialCurve = 1, g_SpecialCurve = 1, k_ReferCurve = 1, g_ReferCurve = 1, k_ReferSurface = 1, g_ReferSurface = 1; List <Point3d> SpecialPoints = new List <Point3d>(); List <Curve> SpecialCurves = new List <Curve>(); List <Curve> ReferCurves = new List <Curve>(); List <Point3d> ReferCurvePoints = new List <Point3d>(); List <Surface> ReferSurfaces = new List <Surface>(); List <Point3d> ReferSurfacePoints = new List <Point3d>(); DA.GetData <Mesh>(0, ref TargetMesh); //获取第0个输入值 DA.GetDataList <Point3d>(1, Points); DA.GetData <double>(2, ref PullStrengthM); DA.GetData <double>(3, ref CollideStrength); DA.GetData <double>(4, ref radius); //暂无 DA.GetData <double>(6, ref threshold); DA.GetData <double>(7, ref subIteration); DA.GetData <double>(8, ref maxIteration); DA.GetData <bool>(9, ref reset); DA.GetDataList <Point3d>(10, SpecialPoints); DA.GetData <double>(11, ref k_SpecialPoint); DA.GetData <double>(12, ref g_SpecialPoint); DA.GetDataList <Curve>(13, SpecialCurves); DA.GetData <double>(14, ref k_SpecialCurve); DA.GetData <double>(15, ref g_SpecialCurve); DA.GetDataList <Curve>(16, ReferCurves); DA.GetDataList <Point3d>(17, ReferCurvePoints); DA.GetData <double>(18, ref k_ReferCurve); DA.GetData <double>(19, ref g_ReferCurve); DA.GetDataList <Surface>(20, ReferSurfaces); DA.GetDataList <Point3d>(21, ReferSurfacePoints); DA.GetData <double>(22, ref k_ReferSurface); DA.GetData <double>(23, ref g_ReferSurface); //内部计算过程start //initialize the solver if (reset || initialized == false) { #region reset counter = 0; PS = new KangarooSolver.PhysicalSystem(); Goals = new List <IGoal>(); initialized = true; //var IndexList = Enumerable.Range(0, PS.ParticleCount()).ToList(); //Goals.Add(new KangarooSolver.Goals.OnCurve(NakedPts, BoundaryCurves[0], PullStrengthC)); //Goals.Add(new KangarooSolver.Goals.OnMesh(Pts, TargetMesh, 1)); Goals.Add(new KangarooSolver.Goals.OnMesh(Points, TargetMesh, PullStrengthM)); Goals.Add(new KangarooSolver.Goals.SphereCollide_wqs(Points, radius, CollideStrength, SpecialPoints, k_SpecialPoint, g_SpecialPoint, SpecialCurves, k_SpecialCurve, g_SpecialCurve, ReferCurves, ReferCurvePoints, k_ReferCurve, g_ReferCurve, ReferSurfaces, ReferSurfacePoints, k_ReferSurface, g_ReferSurface )); //public SphereCollide_wqs(List<Point3d> V, List<Point3d> SV, double radius, double k, double kSV0, double gSV0) //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 //GoalList.Add(G); } #endregion } else { //Step forward, using these goals, with multi-threading on, and stopping if the threshold is reached if (counter == 0 || (PS.GetvSum() > threshold && counter < 100)) { for (int i = 0; i < subIteration; i += 1) { PS.Step(Goals, true, threshold); counter++; } double sum = PS.GetvSum(); } //内部计算过程end //Output the mesh, and how many iterations it took to converge } List <Point3d> pout = new List <Point3d>(); pout = PS.GetPositions().ToList(); DA.SetDataList(0, pout); //输出第一个输出值 DA.SetData(1, counter); List <double> brs = SphereCollide_wqs.brs; DA.SetDataList(2, brs); //输出气泡半径 List <Point3d> pp = Goals[1].PPos.ToList(); DA.SetDataList(3, pp); //输出第一个输出值 }
/// <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); //输出第一个输出值 }