Example #1
0
        // M code must ensure that the only types that can arrive in this function are ones that are currently handled here.
        public static bool ReadAndStoreResult(string type, int index, IKernelLink link, IGH_DataAccess DA, GH_ParamAccess accessType, GH_Component component)
        {
            try
            {
                switch (accessType)
                {
                case GH_ParamAccess.item:
                {
                    object res = ReadSingleItemAsType(type, link);
                    DA.SetData(index, res);
                    break;
                }

                case GH_ParamAccess.list:
                {
                    ILinkMark mark   = link.CreateMark();
                    int       length = 1;
                    bool      isList = false;
                    try
                    {
                        length = link.CheckFunction("List");
                        isList = true;
                    }
                    catch (MathLinkException)
                    {
                        link.ClearError();
                    }
                    finally
                    {
                        link.SeekMark(mark);
                        link.DestroyMark(mark);
                    }
                    if (isList)
                    {
                        IList list = ReadListOfItemsAsType(type, link);
                        DA.SetDataList(index, list);
                    }
                    else
                    {
                        object item = ReadSingleItemAsType(type, link);
                        DA.SetData(index, item);
                    }
                    break;
                }

                case GH_ParamAccess.tree:
                {
                    // Quick and dirty method. Only support numbers. Read as Expr, then use Dimensions, etc.
                    // TODO: Handle objects. See how it is done in ReadSingleItemAsType().
                    // This read-as-expr method shows problems for tree type. It would be better, for tree, to not use
                    // the expr, but rather re-read the data from the link (as is done for item, list). In the curremt
                    // method, I don't see any good way to handle "Any".
                    // WAIT, IT'S WORSE. Expr.AsArray() only does Integer, Real, and only up to depth 2.
                    ILinkMark mark = link.CreateMark();
                    try
                    {
                        Expr  e    = link.GetExpr();
                        int[] dims = e.Dimensions;
                        if (dims.Length == 0)
                        {
                            link.SeekMark(mark);
                            object res = ReadSingleItemAsType(type, link);
                            DA.SetData(index, res);
                        }
                        else if (dims.Length == 1)
                        {
                            link.SeekMark(mark);
                            IList list = ReadListOfItemsAsType(type, link);
                            DA.SetDataList(index, list);
                        }
                        else if (dims.Length == 2)
                        {
                            // This code could be cleaner with GH_Structure, but I dont quite understand that class...
                            switch (type)
                            {
                            case "Number":
                            {
                                DataTree <double> tree      = new DataTree <double>();
                                Array             dataArray = e.AsArray(ExpressionType.Real, 2);
                                for (int i = 0; i < dims[0]; i++)
                                {
                                    GH_Path pth = new GH_Path(i);
                                    for (int j = 0; j < dims[1]; j++)
                                    {
                                        tree.Add((double)dataArray.GetValue(i, j), pth);
                                    }
                                }
                                DA.SetDataTree(index, tree);
                                break;
                            }

                            case "Integer":
                            {
                                DataTree <int> tree      = new DataTree <int>();
                                Array          dataArray = e.AsArray(ExpressionType.Integer, 2);
                                for (int i = 0; i < dims[0]; i++)
                                {
                                    GH_Path pth = new GH_Path(i);
                                    for (int j = 0; j < dims[1]; j++)
                                    {
                                        tree.Add((int)dataArray.GetValue(i, j), pth);
                                    }
                                }
                                DA.SetDataTree(index, tree);
                                break;
                            }

                            default:
                                // Can't handle this.
                                return(false);
                            }
                        }
                        else
                        {
                            // TODO. At least set a RuntimeMessage before returning false.
                            return(false);
                        }
                    }
                    finally
                    {
                        link.DestroyMark(mark);
                    }
                    break;

                    // Problem with the read-and-fill-element-by-element approach is that this is a GH_Structure<IGH_Goo>,
                    // so I need to create an IGH_Goo pbjectout of every piece of data. But there are zillions of IGH_Goo
                    // objects out there. I don't want to map every object to its IGH_Goo type (e.g., Circle --> GH_Circle).
                    // For lists, I could simply create a List<anything> and apparently it gets converted to the appopriate
                    // IGH_Goo object later on. But with trees, I don't see the corresponding technique. Compare the signature
                    // of DA.SetDataList() and DA.SetDataTree().

                    /*
                     *  ILinkMark mark3 = link.CreateMark();
                     *  int length = 1;
                     *  try {
                     *      length = link.CheckFunction("List");
                     *      // Don't catch; allow to fail. Must be a list arriving for tree results.
                     *  } finally {
                     *      link.DestroyMark(mark3);
                     *  }
                     *  GH_Structure<IGH_Goo> structure = new GH_Structure<IGH_Goo>();
                     *  GH_Path path = new GH_Path(0);
                     *  int pathLen = 1;
                     *  int pathIndex = 0;
                     *  for (int i = 0; i < length; i++) {
                     *      if (isListWaitingOnLink(link)) {
                     *           path.
                     *      } else {
                     *          structure.Append(
                     *      }
                     *  }
                     */
                }
                }
            }
            catch (Exception)
            {
                component.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Unexpected type of result from Wolfram Engine");
                link.ClearError();
                link.NewPacket();
                return(false);
            }
            return(true);
        }