Method GetDataTree Question: Can not Collected Data Correctly

Hi everyone, I have an problem about the Method GetDataTree, it could not collected data correctly. This was the first time I get the thus error, and I have check my code many time. And unfortunately I still didn’t what the problem with the Code, what’s more, when I debug the code with Visual Studio 2015 the GetDataTree did not collect the point data. If anyone can help me, thanks

The Problem is decribe as an Gif animation. And The full Code is as an attachment at below

        protected override void SolveInstance(IGH_DataAccess DA)
        {
            GH_Structure<GH_Point> InputPtsTree = new GH_Structure<GH_Point>();
            GH_Structure<GH_Point> OutputPts = new GH_Structure<GH_Point>();

            double ThreadHold = default(double);
            string Sign = default(string);
            int j;
            int i;
            double Result = 0;
            GH_Path BasePath;

            if(!DA.GetDataTree(0, out InputPtsTree))return;
            if(!DA.GetData(1, ref ThreadHold))return;
            if(!DA.GetData(2, ref Sign))return;

            int TreeBranchCount = InputPtsTree.Branches.Count;
            
            for(int Index = 0; Index < TreeBranchCount; Index++)
            {
                List<GH_Point> BranchsPts = InputPtsTree.Branches[Index];
                BasePath = InputPtsTree.Paths[Index];
                i = 0;
                for (; BranchsPts.Count>0;)
                {

                    List<GH_Point> NewBranch = new List<GH_Point>();
                    GH_Point i_Pt = BranchsPts[0];
                    NewBranch.Add(BranchsPts[0]);
                    BranchsPts.RemoveAt(0);
                    j = 0;

                    for(;j < BranchsPts.Count; j++)
                    {
                        GH_Point j_Pt = BranchsPts[j];
                        Result = Math.Abs(i_Pt.Value.DistanceTo(j_Pt.Value));
                        if(Result <= ThreadHold)
                        {
                            NewBranch.Add(BranchsPts[j]);
                            BranchsPts.RemoveAt(j);
                            j = j - 1;
                        }
                    }
                    GH_Path NewPath = BasePath.AppendElement(i);
                    i++;
                    OutputPts.AppendRange(NewBranch, NewPath);
                }
            }
            DA.SetDataTree(0, OutputPts);
        }

ClusterPts.cs (6.2 KB)

The problem is you’re modifying the actual tree you’re getting out of the input:

List<GH_Point> BranchsPts = InputPtsTree.Branches[Index];
...
BranchsPts.RemoveAt(0);

This tree is shared amongst all parameters which are connected by wires, so you’re not ever supposed to change a tree that comes from an input. When inside your code you one-by-one remove all the points from it, the tree which is stored inside the parameter becomes entirely empty, which is why the second time the SolveInstance() method runs you’re not getting any points. They no longer exist.

I think this will do what you’re after:

protected override void SolveInstance(IGH_DataAccess DA)
{
  GH_Structure<GH_Point> points;
  if (!DA.GetDataTree(0, out points)) return;

  double threshold = 0.0;
  if (!DA.GetData(1, ref threshold)) return;

  var clusters = new GH_Structure<GH_Point>();
  for (int i = 0; i < points.PathCount; i++)
  {
    // We'll make a copy of the branch, so we can remove items from it
    // without modifying the original. We'll also remove all nulls from
    // this copy as I assume you don't want them at all in the output.
    var list = new List<GH_Point>(points.Branches[i]);
    list.RemoveAll(point => point is null);

    var path = points.Paths[i];
    var increment = 0;
    while (list.Count > 0)
    {
      // Move the first point from the original list into the cluster.
      var cluster = new List<GH_Point> { list[0] };
      list.RemoveAt(0);

      // Find all points in the remaining list which are closer than 'threshold' to the first point.
      for (int k = 0; k < list.Count; k++)
      {
        var distance = cluster[0].Value.DistanceTo(list[k].Value);
        if (distance <= threshold)
        {
          cluster.Add(list[k]);
          list.RemoveAt(k);
          k--; // We removed a point, so our iteration counter should also be decremented.
        }
      }

      clusters.AppendRange(cluster, path.AppendElement(increment++));
    }
  }
  DA.SetDataTree(0, clusters);
}
1 Like

Thanks, David It Works :grinning::slightly_smiling_face:

Hi David, But I have a problerm about that. When I just copy the code into Grasshopper’s C# component And it run very well and have nothing problerm like that.
So , What the diffenent between the code running in the Origin Component (Using C# and Visual Studio Created) and in C# Component?

The C# script components preprocess all inputs and duplicate data when needed. Inside the script components DataTree<T> is used instead of GH_Structure<T>, which already means you’re not operating on the actual data stored inside the parameters.

OK, Thanks.