GH_Structure problem with branches in Visual Studio/C#

Hi

I am doing a component in VS C# and I have a problem. I play with some boid algorithm and want to output boid trails as a tree of points. For every looped boid i aim to create a branch with all its recorded locations from all iterations. But, regardless of what i do, result is outputted as a flattened tree (sort of). I try to set ghPath but it doesn change anything.

I have tested outputted result in grasshopper and it is simply flattened tree - i can build it to a proper structure using partition list etc, but i want the result to be correct already in the component.

code is long, so i post main loop g:

public void UpdatePositions()
{
  for (int i = 0; i < boidPositions.Count; i++)
  {
    Grasshopper.Kernel.Data.GH_Path ghPath;
    ghPath = new Grasshopper.Kernel.Data.GH_Path(i,Iterations);
    if (totalWeights[i] == 0.0) continue;

    Vector3d move = totalWeightedMoves[i];
    double length = move.Length;
    if (Unitize)
    {
      move.Unitize();
    }
    else
    {
      move.Unitize();
      move = move * (length / totalWeights[i]);
    }
    
    Point3d movedBoid = boidPositions[i] + move;
    totalMoves[i] = move;
    boidPositions[i] = movedBoid;
     
    if (Trail)
    {
      Grasshopper.Kernel.Types.GH_Point movedBoidTree = new Grasshopper.Kernel.Types.GH_Point(movedBoid);

       treeTrails.Insert(movedBoidTree, ghPath, Iterations);
      // treeTrails.Append(movedBoidTree, ghPath);
    }
  }
}

Code is incomplete so I can’t run it and see for myself.

As a quick fix, have you considered not outputting lists of points for trails but just individual polylines? That way you don’t have to worry about keeping the data in separate branches.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Grasshopper.Kernel;
using Rhino.Geometry;

namespace dynarek.Swarm
{
class SwarmSystem
{

    public int Iterations = 0;
    public bool Flock = false;
    public bool Unitize = false;
    public bool Trail = false;
    public List<Point3d> boidPositions = new List<Point3d>();
    public double AttractionStrength = 0.0;
    public double CohesionStrength = 0.0;
    public double RepulsionStrength = 0.0;
    public double RandomStrength = 0.0;
    public double AttractionDistance = 0.0;
    public double CohesionDistance = 0.0;
    public double RepulsionDistance = 0.0;


    private List<Vector3d> totalWeightedMoves;
    private List<double> totalWeights;
    private List<Vector3d> totalMoves;

    Grasshopper.Kernel.Data.GH_Structure<Grasshopper.Kernel.Types.IGH_Goo> treeTrails = new Grasshopper.Kernel.Data.GH_Structure<Grasshopper.Kernel.Types.IGH_Goo>();
    

    public SwarmSystem(List<Point3d> startingPoints)
    {
        boidPositions = startingPoints;
        totalWeightedMoves = new List<Vector3d>();
        totalWeights = new List<double>();
        totalMoves = new List<Vector3d>();
        

        for (int i = 0; i < boidPositions.Count; i++)
        {
            /*
            Random startRandomVector = new Random();
            double xP = (startRandomVector.NextDouble() * 2) - 1;
            double yP = (startRandomVector.NextDouble() * 2) - 1;
            double zP = (startRandomVector.NextDouble() * 2) - 1;

            Vector3d randVecStart = new Vector3d(xP, yP, zP);

            totalMoves.Add(randVecStart);
            totalWeightedMoves.Add(randVecStart);
            totalWeights.Add(1);

*/

            totalMoves.Add(new Vector3d(0,0,0));
            totalWeightedMoves.Add(new Vector3d(0, 0, 0));
            totalWeights.Add(0);
            Grasshopper.Kernel.Data.GH_Path ghPath;
            ghPath = new Grasshopper.Kernel.Data.GH_Path(i,0);
            
            Grasshopper.Kernel.Types.GH_Point startBoidPosition = new Grasshopper.Kernel.Types.GH_Point(boidPositions[i]);
            treeTrails.Insert(startBoidPosition, ghPath, 0);
        }
    }

    public List<Point3d> GetPoints()
    {
        return boidPositions;
    }

    public List<Vector3d> GetVectors()
    {
        return totalMoves;
    }

    public Grasshopper.Kernel.Data.GH_Structure<Grasshopper.Kernel.Types.IGH_Goo> GetTrails()
    {
        List<Curve> trailCurves = new List<Curve>();
        for (int i = 0; i < treeTrails.Branches.Count; i++ )
        {
           // List<Point3d> trailPoints = treeTrails.Branches[i].Cast<>
           // Curve trailCurve = Curve.CreateInterpolatedCurve(treeTrails.Branches[i], 2);
            //trailCurves.Add(treeTrails.Branches
        }
        return treeTrails; 
    }
    

    public void Update()
    {
        if (Flock)
        {
          // RandomMove();
        //    Cohesion();
            Attraction();
         //   Repulsion();
            UpdatePositions();
            Iterations += 1;
        }
    }

    public void UpdatePositions()
    {

        for (int i = 0; i < boidPositions.Count; i++)
        {
            Grasshopper.Kernel.Data.GH_Path ghPath;
            ghPath = new Grasshopper.Kernel.Data.GH_Path(i,Iterations);
            if (totalWeights[i] == 0.0) continue;

            Vector3d move = totalWeightedMoves[i];
            double length = move.Length;
            if (Unitize)
            {
                move.Unitize();
            }

            else
            {
                move.Unitize();
                move = move * (length / totalWeights[i]);
            }
            
            Point3d movedBoid = boidPositions[i] + move;
            totalMoves[i] = move;
            boidPositions[i] = movedBoid;

             
            if (Trail)
            {
               // ghPath.
                Grasshopper.Kernel.Types.GH_Point movedBoidTree = new Grasshopper.Kernel.Types.GH_Point(movedBoid);

                 treeTrails.Insert(movedBoidTree, ghPath, Iterations);
               // treeTrails.Append(movedBoidTree, ghPath);

            }
        }
    }

    public void RandomMove()
    {
        if (RandomStrength>0)
        { 
        Random random = new Random();

            for (int i = 0; i < boidPositions.Count; i++)
            {
                double xP = (random.NextDouble() * 2) - 1;
                double yP = (random.NextDouble() * 2) - 1;
                double zP = (random.NextDouble() * 2) - 1;

                Vector3d randVec = new Vector3d(xP, yP, zP);

                totalWeightedMoves[i] += randVec * RandomStrength;
                totalWeights[i] += RandomStrength;
            }
        }

    }

    public void Cohesion()
    {
        if (CohesionStrength > 0)
        {
            for (int i = 0; i < boidPositions.Count; i++)
            {
                for (int j = 0; j < boidPositions.Count; j++)
                {
                    if (boidPositions[i].DistanceTo(boidPositions[j]) < CohesionDistance)
                    {
                        totalWeightedMoves[i] += totalMoves[j] * CohesionStrength;
                        totalWeights[i] += CohesionStrength;
                    }
                    else
                    {
                        totalWeightedMoves[i] = totalWeightedMoves[i];
                        totalWeights[i] = totalWeights[i];
                    }

                }
            }
        }
    }

    public void Attraction()
    {
        if (AttractionStrength > 0)
        {
            for (int i = 0; i < boidPositions.Count; i++)
            {
                for (int j = 0; j < boidPositions.Count; j++)
                {
                    if (boidPositions[i].DistanceTo(boidPositions[j]) < AttractionDistance)
                    {
                        Point3d position = boidPositions[i];   // zmienic na boidpositions
                        Point3d nextPosition = boidPositions[j];

                        Vector3d moveAttraction = nextPosition - position;
                        // Vector3d moveAttraction =   totalMoves[j] - totalMoves[i];
                        totalWeightedMoves[i] += moveAttraction * AttractionStrength;
                        totalWeights[i] += AttractionStrength;
                    }
                }
            }
        }
    }

    public void Repulsion()
    {
        if (RepulsionStrength > 0)
        {
            for (int i = 0; i < boidPositions.Count; i++)
            {
                for (int j = 0; j < boidPositions.Count; j++)
                {
                    if (boidPositions[i].DistanceTo(boidPositions[j]) < RepulsionDistance)
                    {
                        Point3d position = boidPositions[i];   // zmienic na boidpositions
                        Point3d nextPosition = boidPositions[j];

                        Vector3d moveAttraction = (nextPosition - position) * (-1);
                        // Vector3d moveAttraction =   totalMoves[j] - totalMoves[i];
                        totalWeightedMoves[i] += moveAttraction * RepulsionStrength;
                        totalWeights[i] += RepulsionStrength;
                    }
                }
            }
        }
    }
}

}

Hello
I didn’t go in depth in your program. Here something that outputs data as DataTree.
Swarm dynarek.gh (5.1 KB)

I just use DataTree.Add(data, new GH_Path(index)) !!!
And no GH_Point, Point3d seems enough for me

i think i may have found a bug

I tested multiple ways the tree in VS and inside a class all seems to work fine - there is a reuqired number of branches etc.

but problem appears when i Set it in actual component interface

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Grasshopper.Kernel;
using Rhino.Geometry;

namespace dynarek.Swarm
{
public class Comp_Swarm : GH_Component
{

    private SwarmSystem mySwarm;

    public Comp_Swarm()
      : base("Swarm", "Swarm",
          "Basic Swarm Intelligence",
          "Wtyczka_Dynarek", "Swarm")
    {
    }

   
    protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
    {
        pManager.AddBooleanParameter("Reset", "Reset", "Reset", GH_ParamAccess.item);
        pManager.AddPointParameter("Starting Points", "Starting Points", "Starting Points", GH_ParamAccess.list);
        
        
        pManager.AddBooleanParameter("Flock", "Flock", "Flock", GH_ParamAccess.item);
        pManager.AddBooleanParameter("Trail", "Trail", "Trail", GH_ParamAccess.item);
        pManager.AddBooleanParameter("RTree", "RTree", "RTree", GH_ParamAccess.item);
        pManager.AddBooleanParameter("Unitize", "Unitize", "Unitize", GH_ParamAccess.item);

        //  pManager.AddNumberParameter("Random Strength", "Random Strength", "Random Strength", GH_ParamAccess.item);

        pManager.AddNumberParameter("Attraction Strength", "Attraction Strength", "Attraction Strength", GH_ParamAccess.item);
        pManager.AddNumberParameter("Cohesion Strength", "Cohesion Strength", "Cohesion Strength", GH_ParamAccess.item);
        pManager.AddNumberParameter("Repulsion Strength", "Repulsion Strength", "Repulsion Strength", GH_ParamAccess.item);

        pManager.AddNumberParameter("Attraction Distance", "Attraction Distance", "Attraction Distance", GH_ParamAccess.item);
        pManager.AddNumberParameter("Cohesion Distance", "Cohesion Distance", "Cohesion Distance", GH_ParamAccess.item);
        pManager.AddNumberParameter("Repulsion Distance", "Repulsion Distance", "Repulsion Distance", GH_ParamAccess.item);
        pManager.AddNumberParameter("Random Strength", "Random Strength", "Random Strength", GH_ParamAccess.item);

    }

   
    protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
    {
        pManager.AddPointParameter("Points", "Points", "Points", GH_ParamAccess.list);
        pManager.AddVectorParameter("Vectors", "Vectors", "Vectors", GH_ParamAccess.list);
        pManager.AddIntegerParameter("Iterations", "Iterations", "Iterations", GH_ParamAccess.item);
        pManager.AddPointParameter("Trails", "Trails", "Trails", GH_ParamAccess.tree);
        pManager.AddIntegerParameter("Test", "Test", "Test", GH_ParamAccess.item);
        //pManager.AddPointParameter("Trails", "Trails", "Trails", );
        //  pManager.


        //  pManager.AddPointParameter()
        //  pManager.AddCurveParameter("Trails", "Trails", "Trails", GH_ParamAccess.list);
    }

  
    protected override void SolveInstance(IGH_DataAccess DA)
    {
        bool iReset = true;
        bool iFlock = true;
        bool iTrails = true;
        bool iRTree = true;
        bool iUnitize = true;
        List<Point3d> iStartingPoints = new List<Point3d>();


        double iRandomStrength = 0.0;
        double iAttractionStrength = 0.0;
        double iCohesionStrength = 0.0;
        double iRepulsionStrength = 0.0;
        double iAttractionDistance = 0.0;
        double iCohesionDistance = 0.0;
        double iRepulsionDistance = 0.0;

        //int iIterations = 0;


        DA.GetData("Reset", ref iReset);
        DA.GetData("Flock", ref iFlock);
        DA.GetData("Trail", ref iTrails);
        DA.GetData("RTree", ref iRTree);
        DA.GetData("Unitize", ref iUnitize);

        DA.GetDataList("Starting Points",  iStartingPoints);

        DA.GetData("Random Strength", ref iRandomStrength);
        DA.GetData("Attraction Strength", ref iAttractionStrength);
        DA.GetData("Cohesion Strength", ref iCohesionStrength);
        DA.GetData("Repulsion Strength", ref iRepulsionStrength);
        DA.GetData("Attraction Distance", ref iAttractionDistance);
        DA.GetData("Cohesion Distance", ref iCohesionDistance);
        DA.GetData("Repulsion Distance", ref iRepulsionDistance);



        if (iReset || mySwarm == null)
        {
            mySwarm = new SwarmSystem(iStartingPoints);
            mySwarm.Iterations = 0;

        }

        mySwarm.Flock = iFlock;
        mySwarm.RandomStrength = iRandomStrength;
        mySwarm.CohesionDistance = iCohesionDistance;
        mySwarm.CohesionStrength = iCohesionStrength;
        mySwarm.AttractionDistance = iAttractionDistance;
        mySwarm.AttractionStrength = iAttractionStrength;
        mySwarm.Unitize = iUnitize;
        mySwarm.RepulsionDistance = iRepulsionDistance;
        mySwarm.RepulsionStrength = iRepulsionStrength;
        mySwarm.Trail = iTrails;

        mySwarm.Update();
        //mySwarm.Iterations += 1;

        List<Point3d> outputPoints = mySwarm.GetPoints();

       
        DA.SetDataList("Points", outputPoints);
        DA.SetDataList("Vectors", mySwarm.GetVectors());
        DA.SetData("Iterations", mySwarm.Iterations);
        DA.SetData("Test", mySwarm.testInteger);
        if (iTrails)
            DA.SetDataTree("Trails", mySwarm.GetTrails());
           //DA.SetDataList("Trails", mySwarm.treeTrails);

    }


    protected override System.Drawing.Bitmap Icon
    {
        get
        {
            return Properties.Resources.SwarmSystemIcon;
        }
    }


    public override Guid ComponentGuid
    {
        get { return new Guid("3ffc5bfa-16ee-43cb-8530-bc3891aed948"); }
    }
}

}

When i use SetDataList, tree seems to be outputted flattened. But if i try to use SetDataTree, it seems to be an error on casting GH_Structure to IGH_DataTree

Lauren Delrieu, it all works fine in c# component, and i have no problem there, but it doesnt work in Visual Studio

As I use it quite often it is strange it doesn’t work. I made modifications in many parts.
Don’t forget to put the constructor DataTree traceTrails= new DataTree(); in your constructor SwarmSystem …

but you use it in visual studio? or in scripting component?

because i read that using DataTree in VS would not work, thats why i moved to GH_Structure

I use it in VisualStudio for dll creation which are then used in Grasshopper … It works.

Ok I see the discussion

doesnt work when i do it… i do not know whats wrong

image

You forgot () at the end !
DataTree"""" traceTrails= new DataTree"""""();

it still does not see anything like “DataTree”

Are you using
using Grasshopper.Kernel.Data; ? needed for GH_Path
no () at the beginning !!!
image

i deleted first () and still, VS does not recognize DataTree


So it seems you need addind this using
using Grasshopper;

nnOOOOOooooOOOoo there must be the way