protected override void SolveInstance(IGH_DataAccess DA) { GH_Structure <GH_Brep> breps = null; GH_Structure <GH_Brep> cutters = null; //Brep brep = null; //List<Brep> cutters = new List<Brep>(); if (!DA.GetDataTree("Brep", out breps)) { AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Invalid Brep input."); return; } if (!DA.GetDataTree("Cutters", out cutters)) { AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Invalid cutter input."); return; } GH_Structure <GH_Brep> resTree = new GH_Structure <GH_Brep>(); foreach (var path in breps.Paths) { resTree.EnsurePath(path); } List <string> errors = new List <string>(); Parallel.For(0, breps.Paths.Count, index => { GH_Path path = breps.Paths[index]; if (cutters.PathExists(path) && breps[path].Count > 0) { resTree[path].Add(new GH_Brep(breps[path][0].Value.Cut( cutters[path].Select(x => x.Value)))); } else if (cutters.PathCount == 1 && breps[path].Count > 0) // Handle a single list of cutters { try { if (cutters[0].Count > 0 && breps[path][0] != null) { resTree[path].Add(new GH_Brep(breps[path][0].Value.Cut( cutters[cutters.Paths[0]].Select(x => x.Value)))); } } catch (Exception ex) { errors.Add(ex.Message); } } else { resTree[path].AddRange(breps[path]); } }); DA.SetDataTree(0, resTree); DA.SetDataList("Errors", errors); }
protected override void SolveInstance(IGH_DataAccess DA) { /// <summary> /// This is the method that actually does the work. /// </summary> /// /// First, we need to retrieve all data from the input parameters. /// We'll start by declaring variables and assigning them starting values. /// <param name="DA">The DA object is used to retrieve from inputs and store in outputs.</param> // datatree should be accessed through GH_structure (grasshopper.kernal.data namespace) GH_Structure <GH_Point> winnerTree = new GH_Structure <GH_Point>(); GH_Structure <GH_Point> dataTree = new GH_Structure <GH_Point>();; // Then we need to access the input parameters individually. // When data cannot be extracted from a parameter, we should abort this method. if (!DA.GetDataTree(0, out dataTree)) { return; } // body of code while (dataTree.PathCount != 0) { var pointlist = dataTree.Branches[0].GetRange(0, dataTree.Branches[0].Count); // copy data from first branch to winner winnerTree.EnsurePath(dataTree.Paths[0]); winnerTree.AppendRange(pointlist); dataTree.RemovePath(dataTree.Paths[0]); // test other branches for inliers with winner(0), if so delete them for (int i = 0; i < pointlist.Count; i++) { var pointtest = pointlist[i]; for (int branchj = 0; branchj < dataTree.PathCount; branchj++) { for (int listj = 0; listj < dataTree.Branches[branchj].Count; listj++) { if (((pointtest.Value.X - dataTree.get_DataItem(dataTree.Paths[branchj], listj).Value.X) < 0.001) && ((pointtest.Value.Y - dataTree.get_DataItem(dataTree.Paths[branchj], listj).Value.Y) < 0.001) && ((pointtest.Value.Z - dataTree.get_DataItem(dataTree.Paths[branchj], listj).Value.Z) < 0.001)) { dataTree.RemovePath(dataTree.Paths[branchj]); } } } } } /// run some function on the data //// Finally assign the output to the output parameter. DA.SetDataTree(0, winnerTree); //DA.SetDataList(1, output); }
public static GH_Structure <GH_Brep> MakeTreeForBuildings(Dictionary <OSMTag, List <Brep> > foundBuildings) { var output = new GH_Structure <GH_Brep>(); var i = 0; foreach (var entry in foundBuildings) { for (int j = 0; j < entry.Value.Count; j++) { GH_Path path = new GH_Path(i, j); // Need to ensure even an empty path exists to enable data matching output.EnsurePath(path); // Need to ensure even an empty path exists to enable data matching GH_Brep brepForPath = new GH_Brep(entry.Value[j]); output.Append(brepForPath, path); } i++; } return(output); }
/// <summary> /// This is the method that actually does the work. /// </summary> /// <param name="DA">The DA object is used to retrieve from inputs and store in outputs.</param> protected override void SolveInstance(IGH_DataAccess DA) { GH_Structure <GH_Plane> plane_tree = null; GH_Structure <GH_tasPath> path_tree = null; DA.GetDataTree <GH_tasPath>(0, out path_tree); foreach (var path in path_tree.Paths) { for (int i = 0; i < path_tree[path].Count; ++i) { var npath = path.AppendElement(i); plane_tree.EnsurePath(npath); plane_tree[npath].AddRange(path_tree[path][i].Value.ToList().Select(x => new GH_Plane(x))); } } DA.SetDataTree(0, plane_tree); }
public static GH_Structure <GH_Curve> MakeTreeForWays(Dictionary <OSMTag, List <PolylineCurve> > foundWays) { var output = new GH_Structure <GH_Curve>(); var i = 0; foreach (var entry in foundWays) { for (int j = 0; j < entry.Value.Count; j++) { GH_Path path = new GH_Path(i, j); // Need to ensure even an empty path exists to enable data matching output.EnsurePath(path); // Need to ensure even an empty path exists to enable data matching GH_Curve lineForPath = new GH_Curve(entry.Value[j]); output.Append(lineForPath, path); } i++; } return(output); }
private void RecurseNestedLists(object data, GH_Structure <IGH_Goo> tree) { if (data is List <object> list) { for (var i = 0; i < list.Count; i++) { var item = list[i]; if (item is List <object> subList) { //add list index to path _path.Add(i); if (subList.Any()) { RecurseNestedLists(item, tree); } else { tree.EnsurePath(_path.ToArray()); } //reached the bottom of a sublist, step back one level if (_path.Any()) { _path.RemoveAt(_path.Count - 1); } } else { AddLeaf(item, tree); } } } else { AddLeaf(data, tree); } }
/// <summary> /// This is the method that actually does the work. /// </summary> /// <param name="DA">The DA object is used to retrieve from inputs and store in outputs.</param> protected override void SolveInstance(IGH_DataAccess DA) { GH_Structure <GH_Plane> plane_tree = null; GH_Structure <GH_tasPath> path_tree = null; DA.GetDataTree(0, out plane_tree); foreach (var path in plane_tree.Paths) { path_tree.EnsurePath(path); if (plane_tree[path].Count > 1) { path_tree[path].Add( new GH_tasPath( new Path( plane_tree[path].Select(x => x.Value)) ) ); } } DA.SetDataTree(0, path_tree); }
public static GH_Structure <T> DuplicateAs <T>(this IGH_Structure structure, bool shallowCopy) where T : IGH_Goo { // GH_Structure<T> constructor is a bit faster if shallowCopy is true because // it doesn't need to cast on each item. if (structure is GH_Structure <T> structureT) { return(new GH_Structure <T>(structureT, shallowCopy)); } var result = new GH_Structure <T>(); for (int p = 0; p < structure.PathCount; ++p) { var path = structure.get_Path(p); var srcBranch = structure.get_Branch(path); var destBranch = result.EnsurePath(path); destBranch.Capacity = srcBranch.Count; var data = srcBranch.As <T>(); if (!shallowCopy) { data = data.Select(x => x?.Duplicate() is T t ? t : default);
protected override void CaribouSolveInstance(IGH_DataAccess da) { logger.Reset(); #region Input Parsing da.GetDataTree(0, out GH_Structure <IGH_Goo> itemsTree); if (itemsTree.Branches[0][0] as IGH_GeometricGoo == null) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "It looks like you have provided a non-geometry input to the Items parameter. This input should connect to the Nodes, Ways, or Buildings outputs produced by the Extract components."); return; } ProvidedNodes = itemsTree.Branches[0][0] is GH_Point; da.GetDataTree(1, out GH_Structure <GH_String> tagsTree); if (tagsTree.Branches[0].Count >= 3) { if (tagsTree.Branches[0][2].ToString().Contains(" found")) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "It looks like you have provided a Report parameter output as the Tag parameter input. Use a Tag parameter output instead."); return; } } if (itemsTree.PathCount != tagsTree.PathCount) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "The path counts of the Items and Tags do not match - check these are coming from the same component."); } else if (itemsTree.Branches.Count != tagsTree.Branches.Count) { this.AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "The branch structure of the Items and Tags do not match - check these are coming from the same component."); } logger.NoteTiming("Input capture"); #endregion #region Form Data Setup // Setup form-presentable items for tags provided and parsed into OSM objects var requests = new OSMListWithPaths(tagsTree); // Parse provided tree into OSM objects and a dictionary of paths per object logger.NoteTiming("Tag parsing"); // If tags have changed we write out current state so we can try to preserve it in the new tags list if (this.PreviousTagsDescription != null) { if (tagsTree.DataDescription(false, false) != this.PreviousTagsDescription) { this.storedSelectionState = GetStateKeys(); } } // If loading from scratch, or if the tags have changed if (this.storedSelectionState != null) { var availableOSMs = GetSelectableTagsFromInputTree(requests); this.selectableOSMs = TreeGridUtilities.SetSelectionsFromStoredState( availableOSMs, this.storedSelectionState); this.storedSelectionState = null; // Reset flag } else { this.selectableOSMs = GetSelectableTagsFromInputTree(requests); } this.PreviousTagsDescription = tagsTree.DataDescription(false, false); // Track tag input identity this.selectionStateSerialized = GetSelectedKeyValuesFromForm(); logger.NoteTiming("State loading/making"); #endregion #region Outputting // Match geometry paths to selected filters var geometryOutput = new GH_Structure <IGH_Goo>(); var tagOutput = new GH_Structure <GH_String>(); // Setup tracking dictionary for the report tree output var foundItemCountsForResult = new Dictionary <OSMTag, int>(); for (int i = 0; i < this.selectionStateSerialized.Count; i++) { string itemKeyValue = this.selectionStateSerialized[i]; OSMTag osmItem = new OSMTag(itemKeyValue); if (!requests.pathsPerItem.ContainsKey(osmItem)) { continue; } foundItemCountsForResult[osmItem] = 0; // Match keyvalues to OSMListwithpaths for (int j = 0; j < requests.pathsPerItem[osmItem].Count; j++) { GH_Path inputPath = requests.pathsPerItem[osmItem][j]; var geometryItemsForPath = itemsTree.get_Branch(inputPath); var tagItemsForPath = tagsTree.get_Branch(inputPath); if (geometryItemsForPath == null) { continue; // No provided geometry path for that OSM item } foundItemCountsForResult[osmItem] += 1; for (int k = 0; k < geometryItemsForPath.Count; k++) { GH_Path outputPathFor = new GH_Path(i, j); geometryOutput.EnsurePath(outputPathFor); // Need to ensure even an empty path exists to enable data matching tagOutput.EnsurePath(outputPathFor); // Need to ensure even an empty path exists to enable data matching geometryOutput.Append(geometryItemsForPath[k] as IGH_Goo, outputPathFor); foreach (GH_String tag in tagItemsForPath) { tagOutput.Append(tag, outputPathFor); } } } } logger.NoteTiming("Geometry matching"); var requestReport = TreeFormatters.MakeReportForRequests(foundItemCountsForResult); logger.NoteTiming("Tree formatting"); this.OutputMessageBelowComponent(); da.SetDataTree(0, geometryOutput); da.SetDataTree(1, tagOutput); da.SetDataTree(2, requestReport); logger.NoteTiming("Data tree setting"); #endregion }
protected override void SolveInstance(IGH_DataAccess DA) { string path = Environment.SpecialFolder.MyDocuments.ToString() + @"\"; string sheet = "Sheet1"; bool run = false; if (!DA.GetData(0, ref path)) { return; } if (!DA.GetData(1, ref sheet)) { return; } if (!DA.GetData(2, ref run)) { return; } // Uses the GH_Structure instead of DataTree<T> inside a component. GH_Structure <IGH_Goo> headers = new GH_Structure <IGH_Goo>(); GH_Structure <IGH_Goo> values = new GH_Structure <IGH_Goo>(); if (run) { try { System.IO.FileInfo file = new System.IO.FileInfo(path); var package = new ExcelPackage(file); ExcelWorksheet workSheet = package.Workbook.Worksheets[sheet]; for (int j = workSheet.Dimension.Start.Column; j <= workSheet.Dimension.End.Column; j++) { GH_Path ghp = new GH_Path(j); IGH_Goo obj = GH_Convert.ToGoo(workSheet.Cells[1, j].Value); headers.EnsurePath(ghp); headers.Append(obj, ghp); } for (int i = workSheet.Dimension.Start.Row + 1; i <= workSheet.Dimension.End.Row; i++) { for (int j = workSheet.Dimension.Start.Column; j <= workSheet.Dimension.End.Column; j++) { GH_Path ghp = new GH_Path(j); GH_String cellValue = new GH_String(); // Excel does not use zero-base indexing, also, we have skipped the headers. IGH_Goo obj = GH_Convert.ToGoo(workSheet.Cells[i, j].Value); values.EnsurePath(ghp); values.Append(obj, ghp); } } } catch (Exception ex) { log.Add("Read from Excel failed: " + ex.Message); } } DA.SetDataList(0, log); DA.SetDataTree(1, headers); DA.SetDataTree(2, values); }
/// <summary> /// Loop through data structure. /// </summary> protected override void SolveInstance(IGH_DataAccess DA) { int granularity = 0; double tolerance = 0.0; if (!DA.GetDataTree(0, out GH_Structure <GH_Line> lineTree)) { return; } if (!DA.GetData(1, ref tolerance)) { return; } if (!DA.GetData(2, ref granularity)) { return; } if (granularity <= 0) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Cannot operate with negative or zero granularity."); return; } if (tolerance < Rhino.RhinoMath.ZeroTolerance) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Cannot operate with subzero tolerance."); } if (granularity < 100) { AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "Granularity very small. Performance may suffer."); } // Parallelism strategy follows from a few key observations: // a) We can flip all lines so that x1 <= x2. // b) Single-value comparisons are cheap, and good parallel sorts exist for *really* big input sizes. (Further profiling here) // c) Two lines that are duplicates will round to either the same integer or one adjacent, minimizing communication time. // (Actually, we multiply a bunch to distribute the hash values over a wider range, but the principle is there.) // Therefore: // We pre-process the lines before performing the several floating-point comparisons necessary to actually deduplicate them. // Additionally, we incur less data-structure overhead this way than we would using a hash-set / dictionary containing the // entire working set of lines, because of better locality in the problem space. var resultTree = new GH_Structure <GH_Line>(); var debugTree = new GH_Structure <GH_String>(); for (int i = 0; i < lineTree.Branches.Count; i++) { resultTree.EnsurePath(lineTree.Paths[i]); debugTree.EnsurePath(lineTree.Paths[i]); } Parallel.For(0, lineTree.Branches.Count, i => { var branch = lineTree.Branches[i]; // Preprocess lines. var ppx_lines = branch.Select(l => new LineAndInt(l)).OrderBy(l => l.Line.Length).ToArray(); var partitions = (branch.Count / granularity) + 1; var differential = tolerance * 2 * Math.Sqrt(3); HashSet <LineAndInt>[] results = new HashSet <LineAndInt> [partitions]; (int, int)[] bounds = new (int, int)[partitions];