Null Exception when trying to create GH_Structure<IGH_Goo>

I want to create a data tree (GH_Structure) from two collections of curves (superblocks and parcels), checking which parcels are inside which block and assigning them to the respective block (parent node) as children. Each branch should contain one GH_curve object.
I get a Null Exception (Object reference not set to an instance to an object).
What am I doing wrong? I suspect I dont generate a valid data tree.

    private void RunScript(List<object> x, List<object> y, ref object A, ref object B)
    {
    List<GH_Curve> BlockCurves = new List<GH_Curve>();
    List<GH_Curve> ParcelCurves = new List<GH_Curve>();

    GH_Structure<IGH_Goo> dataTree = new GH_Structure<IGH_Goo>();
    List<GH_Curve> myParcelCurves = new List<GH_Curve>();

    foreach (object crvItem in x)
    {
      GH_Curve gh_curve = new Grasshopper.Kernel.Types.GH_Curve();
      GH_Convert.ToGHCurve(crvItem, GH_Conversion.Both, ref gh_curve);
      BlockCurves.Add(gh_curve);
    }
    Print(BlockCurves.Count.ToString());

    foreach (object crvItem in y)
    {
      GH_Curve gh_curve = new Grasshopper.Kernel.Types.GH_Curve();
      GH_Convert.ToGHCurve(crvItem, GH_Conversion.Both, ref gh_curve);
      ParcelCurves.Add(gh_curve);
    }
    Print(ParcelCurves.Count.ToString());



    // check if information on buildable areas has been passed by user, use respective curve collection

    myParcelCurves = ParcelCurves;

    for (int i = 0; i < BlockCurves.Count; i++)   //for each block create path and fill in GH_Curve
    {
      Polyline block = new Polyline();
      bool cast = BlockCurves[i].Value.TryGetPolyline(out block);
      if (cast && block.IsValid && block.SegmentCount > 2)
      {
        GH_Path pth = new GH_Path(i);
        dataTree.Append(BlockCurves[i], pth);
        Print(pth.ToString());
        //Print(i.ToString());

      }
      else { Exception e = new Exception("Block at index " + i + " is either invalid or not a polyline."); }

      int parcelPathIdx = 0;
      for (int j = 0; j < myParcelCurves.Count; j++)    //for each parcel check if in block, if yes, append to (new) path
      {
        Polyline parcel = new Polyline();
        bool cast1 = myParcelCurves[j].Value.TryGetPolyline(out parcel);
        if (cast1 && parcel.IsValid && parcel.SegmentCount > 2)
        {
          if (IsInside(parcel.CenterPoint(), block))
          {
            GH_Path path = new GH_Path(i, parcelPathIdx);
            dataTree.Append(myParcelCurves[j], path);
            //Print(parcelPathIdx.ToString());
            Print(path.ToString());
            parcelPathIdx++;

          }

        }
        else { Exception e = new Exception("Parcel at index " + j + " is either invalid or not a polyline."); }//check if parcelcurve is inside block
      }

    }
    Print(dataTree.DataCount.ToString());
    //Print(dataTree.AllData().ToString());
    A = dataTree;

    Print(dataTree.PathCount.ToString());
    //B = myPaths;
  }

  // <Custom additional code> 
  public static bool IsInside(Point3d _pt, Polyline _crv)
  {
   //checks if point is within a curve
  }

I’m not sure this is the problem, but I’d write this loop:

foreach (object crvItem in x)
{
  GH_Curve gh_curve = new Grasshopper.Kernel.Types.GH_Curve();
  GH_Convert.ToGHCurve(crvItem, GH_Conversion.Both, ref gh_curve);
  BlockCurves.Add(gh_curve);
}

like so:

foreach (object item in x)
  if (item != null)
  {
    GH_Curve curveGoo = null;
    if (GH_Convert.ToGHCurve(item, GH_Conversion.Both, ref curveGoo))
      BlockCurves.Add(curveGoo);
  }

You don’t need a constructor here either:

Polyline block = new Polyline();
bool cast = BlockCurves[i].Value.TryGetPolyline(out block);

Just declare the polyline:

Polyline block;
bool cast = BlockCurves[i].Value.TryGetPolyline(out block);

That code seems to be the first place where you’re accessing an instance which might be null. Both the .Value may fail if BlockCurves[i] is null, and the .TryGetPolyline() may fail if the Value is null.

I think the conversion check in the loop I posted above should take care of logically the former, and practically the latter problems.

hi David, thanks for your suggestions! The C# Script component works like a dream now.
I am still getting a null exception with its pendant custom grasshopper component. There seems to be the issue that my DataTree is not valid/is null when I try to set it as an Output parameter.

DA.SetDataTree(1, _chromosome.DataTree); is what throws the error.

//grasshopper component class

protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
    { 
        pManager.AddCurveParameter("Blocks", "Blocks", " Add the blocks within which the parcels are  located.", GH_ParamAccess.list);
        pManager.AddCurveParameter("Parcels", "Parcels", "Add the parcels as polyline curves.",  GH_ParamAccess.list);
        pManager.AddCurveParameter("Buildable Parcels", "Buildable Parcels", "Add those parcels that are   buildable (not predefined as green spaces or similar, optional).", GH_ParamAccess.list);

        pManager[2].Optional = true;
       
    }

protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
    {
        //some code
        pManager.AddGenericParameter("Data Tree", "Data Tree", "Data Tree", GH_ParamAccess.tree);
    }

protected override void SolveInstance(IGH_DataAccess DA)
    {
        _chromosome = new Chromosome();
        Initialize(DA);
        DA.SetDataTree(1, _chromosome.DataTree);
    }

public void Initialize(IGH_DataAccess DA)
    {
        // read in blocks 
        List<Curve> _blocks = new List<Curve>();
        DA.GetDataList<Curve>(0, _blocks);

        List<GH_Curve> _ghBlocks = new List<GH_Curve>();
        foreach (object item in _blocks)
        {
            if (item != null)
            {
                GH_Curve curveGoo = null;
                if (GH_Convert.ToGHCurve(item, GH_Conversion.Both, ref curveGoo))
                    _ghBlocks.Add(curveGoo);
            } 
        }
        // read in parcels 
        List<Curve> _parcels = new List<Curve>();
        DA.GetDataList<Curve>(1, _parcels);

        List<GH_Curve> _ghParcels = new List<GH_Curve>();
        foreach (object item in _parcels)
        {
            if (item != null)
            {
                GH_Curve curveGoo1 = null;
                if (GH_Convert.ToGHCurve(item, GH_Conversion.Both, ref curveGoo1))
                    _ghParcels.Add(curveGoo1);
            }
        }
        // read in buildable parcels
        List<Curve> _buildParcels = new List<Curve>();
        DA.GetDataList<Curve>(2, _buildParcels);

        List<GH_Curve> _ghBuildParcels = new List<GH_Curve>();
        foreach (object item in _buildParcels)
        {
            if (item != null)
            {
                GH_Curve curveGoo2 = null;
                if (GH_Convert.ToGHCurve(item, GH_Conversion.Both, ref curveGoo2))
                    _ghBuildParcels.Add(curveGoo2);
            }
        }

        if (!_ghBlocks.Equals(null)) { _chromosome.BlockCurves = _ghBlocks; } else return;
        if (!_ghParcels.Equals(null)) { _chromosome.ParcelCurves = _ghParcels; } else return;
        if (!_ghBuildParcels.Equals(null)) { _chromosome.BuildParcelCurves = _ghBuildParcels; } else       return;

//method of Chromosome class

public void InitialiseDataTree()
    {

        GH_Structure<IGH_Goo> dataTree = new GH_Structure<IGH_Goo>();
        List<GH_Curve> myParcelCurves = new List<GH_Curve>();
        
        // check if information on buildable areas has been passed by user, use respective curve collection
        if ((BuildParcelCurves!=null) && (!BuildParcelCurves.Any())) myParcelCurves = ParcelCurves;
        else myParcelCurves = BuildParcelCurves;

        for (int i = 0; i < BlockCurves.Count; i++)   //for each block create path and fill in GH_Curve
        {
            Polyline block;
            bool cast = BlockCurves[i].Value.TryGetPolyline(out block);
            dataTree.Append(BlockCurves[i], new GH_Path(i));

            int parcelPathIdx = 0;
            for (int j = 0; j < myParcelCurves.Count; j++)    //for each parcel check if in block, if yes, append to data tree 
            {
                Polyline parcel;
                bool cast2 = myParcelCurves[j].Value.TryGetPolyline(out parcel);
         
              
                    if (IsInside(parcel.CenterPoint(), block))
                    {
                        dataTree.Append(myParcelCurves[j], new GH_Path(i, parcelPathIdx));
                        parcelPathIdx++;
                    }
                            
                
                 
            }
            
        }
        this.DataTree = dataTree.Duplicate();
    }

I’ve moved this thread to the “Grasshopper Developer” category…

thanks!

hi David, I have not been able to solve this issue yet – I am sure you are very busy, so I really appreciate your help!
When Debugging (and only if I try to output GH_Structure DataTree from my custom component) I get a null exception. The DataTree.PathCount method gives me 0. I suspect my DataTree is not generated properly (please see the recent code). What am I doing wrong?

Stack Trace:
System.NullReferenceException
HResult=0x80004003
Message=Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt.
Source=Grasshopper
StackTrace:
at Grasshopper.Kernel.GH_Component.GH_StructureIterator.SetDataTree(Int32 index, IGH_Structure tree)

I also get an error message “Output parameter chunk is missing. Archive is corrupt.Object list read” when opening Grasshopper in Debug mode. Again, only if I try to set the GH_Structure type as output parameter.

As always, thanks so much for your help!!