//Duplication public Type_KDTree DuplicateKDTree() { GH_Cloud newCloud = (GH_Cloud)this.Value.Item2.Duplicate(); KDTree <int> newTree = KDTreeLib.DubplicateTree(this.Value.Item1); return(new Type_KDTree(newTree, newCloud)); }
public override IGH_Goo Duplicate() { PointCloud newCloud = (PointCloud)this.Value.Item2.Duplicate(); KDTree <int> newTree = KDTreeLib.DubplicateTree(this.Value.Item1); return(new KDTree(newTree, newCloud)); }
private void calcNormal(List <int>[] idc, ref PointCloud MyCloud, ref int count, int i) { List <Point3d> normalPts = new List <Point3d>(); normalPts.Add(GlobalCloud[i].Location); List <int> ids = idc[i]; if (ids.Count >= 3) { for (int j = 0; j < ids.Count; j++) { Point3d nPt = GlobalCloud[ids[j]].Location; normalPts.Add(nPt); } //Get not-oriented normal from Z-Axis of best fit plane to NormalPoints. Plane normalPln = new Plane(); Plane.FitPlaneToPoints(normalPts, out normalPln); Vector3d notOriNormal = normalPln.ZAxis; //Orient not-oriented NormalVector according to the guiding vector. Vector3d guideVector = new Vector3d(); if (insV_GuideStyle == true) { guideVector = insV_GuideVector; } else if (insV_GuideStyle == false) { guideVector = Point3d.Subtract(GlobalCloud[i].Location, new Point3d(insV_GuideVector)); } guideVector.Unitize(); Vector3d normalVector = new Vector3d(); double vecAngle = Vector3d.VectorAngle(notOriNormal, guideVector); if (vecAngle < Math.PI / 2) { normalVector = notOriNormal; } else { normalVector = notOriNormal; normalVector.Reverse(); } //Add normal to Cloud. Cloud_Utils.AddItem_FromOtherCloud(ref MyCloud, GlobalCloud, i); MyCloud[count].Normal = normalVector; if (insV_Colorize) { MyCloud[count].Color = KDTreeLib.normalColors(1, normalVector, GlobalCloud[i].Color); } count += 1; } }
/// <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) { KDTreeType treeT = null; double NeighborRange = new double(); int NeighborAmount = 5; Vector3d GuideVector = Vector3d.ZAxis; int GuideStyle = 0; int Color = 1; bool Unify = false; if (!DA.GetData(0, ref treeT)) { return; } if (!DA.GetData(1, ref NeighborRange)) { return; } if (!DA.GetData(2, ref NeighborAmount)) { return; } if (!DA.GetData(3, ref GuideVector)) { return; } if (!DA.GetData(4, ref GuideStyle)) { return; } if (!DA.GetData(5, ref Color)) { return; } Tuple <KDTree <int>, PointCloud> KDTreeCloud = treeT.Value; if (NeighborAmount < 3) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Minimum Amount of Neighboring Points to calculate Normal is 3."); return; } Tuple <KDTree <int>, PointCloud> newKDTreeCloud = KDTreeLib.CalcNormals(KDTreeCloud, NeighborRange, NeighborAmount, GuideVector, GuideStyle, Color); DA.SetData(0, new KDTreeType(newKDTreeCloud.Item1, newKDTreeCloud.Item2)); }
/// <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) { PointCloud cloud = null; if (!DA.GetData(0, ref cloud)) { return; } KDTree <int> tree = KDTreeLib.ConstructKDTree(cloud); DA.SetData(0, new KDTreeType(tree, cloud)); }
/// <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_Cloud GHcloud = null; if (!DA.GetData(0, ref GHcloud)) { return; } PointCloud cloud = (PointCloud)GHcloud.Value; KDTree <int> tree = KDTreeLib.ConstructKDTree(cloud); DA.SetData(0, new Type_KDTree(tree, GHcloud)); }
/// <summary> /// This is the method that actually does the work. /// </summary> /// <param name="DA">The DA object can be used to retrieve data from input parameters and /// to store data in output parameters.</param> protected override void SolveInstance(IGH_DataAccess DA) { // PointCloud to meassure Distance From. PointCloud cloudFrom = null; // PointCloud/KDTree to meassure Distance From. Type_KDTree treeT = null; // Amount int amount = 1; //UserData Key String. string key = "CloCloD"; if (!DA.GetData(0, ref cloudFrom)) { return; } if (!DA.GetData(1, ref treeT)) { return; } if (!DA.GetData(2, ref amount)) { return; } if (!DA.GetData(3, ref key)) { return; } Tuple <KDTree <int>, GH_Cloud> KDTreeCloud = treeT.Value; //Make Duplicate to make sure I dont change UserData in input Cloud. cloudFrom = (PointCloud)cloudFrom.Duplicate(); //Calculate closestPoint distances between the two Clouds. double[] dist = KDTreeLib.CloudCloudDist(cloudFrom, KDTreeCloud, amount); //Add Distances to UserDictionary cloudFrom.UserDictionary.Set(key, dist); //Output DA.SetData(0, cloudFrom); }
/// <summary> /// Parallel Computing Setup for Code to Execute. /// </summary> /// <param name="pointCloud">ByRef PointCloud to Execute Code on.</param> /// <returns></returns> public override bool Execute(ref PointCloud pointCloud) { //Set Global Variables LastPercentReported = 0; PointCounter = 0; if (insV_KDTree == null) { tree = KDTreeLib.ConstructKDTree(pointCloud); } else { tree = insV_KDTree; } Dict_Utils.CastDictionary_ToArrayDouble(ref pointCloud); GlobalCloud = pointCloud; NewCloud = new PointCloud(); CloudPieces = null; CloudPieces = new PointCloud[ProcCount]; DictPieces = new object[ProcCount]; pts = pointCloud.GetPoints().ToList(); // Setup the cancellation mechanism. po.CancellationToken = cts.Token; //Create Partitions for multithreading. var rangePartitioner = System.Collections.Concurrent.Partitioner.Create(0, GlobalCloud.Count, (int)Math.Ceiling((double)GlobalCloud.Count / ProcCount)); Dict_Utils.CastDictionary_ToArrayDouble(ref GlobalCloud); //Search for NearestNeighbors per point in PointCloud. Gets the indices in the Cloud for the neighbors to each Point. List <double> NRange = new List <double> { double.MaxValue }; List <int>[] idc = KDTreeLib.NearestNeighborSearch(tree, pts, NRange, insV_NumN); //Run MultiThreaded Loop. Parallel.ForEach(rangePartitioner, po, (rng, loopState) => { //Initialize Local Variables. /// Get Index for Processor to be able to merge clouds in ProcesserIndex order in the end. int MyIndex = (int)(rng.Item1 / Math.Ceiling(((double)GlobalCloud.Count / ProcCount))); /// Initialize Partial PointCloud PointCloud MyCloud = new PointCloud(); /// Get Total Count Fraction to calculate Operation Percentage. double totc = (double)1 / GlobalCloud.Count; int count = 0; if (GlobalCloud.UserDictionary.Count > 0) { /// Initialize Partial Dictionary Lists List <double>[] MyDict = new List <double> [GlobalCloud.UserDictionary.Count]; //Get Dictionary Values from PointCloud List <double[]> GlobalDict = new List <double[]>(); GlobalDict.Clear(); Dict_Utils.Initialize_Dictionary(ref GlobalDict, ref MyDict, GlobalCloud); //Loop over individual RangePartitions per processor. for (int i = rng.Item1; i < rng.Item2; i++) { //Operation Percentage Report ///Safe Counter Increment. Interlocked.Increment(ref PointCounter); ///Calculate and Report Percentage. if (LastPercentReported < ((PointCounter * totc) * 100)) { LastPercentReported = (int)(5 * Math.Ceiling((double)(PointCounter * totc) * 20)); this.ReportPercent = LastPercentReported; } calcNormal(idc, ref MyCloud, ref count, i); Dict_Utils.AddItem_FromGlobalDict(ref MyDict, GlobalDict, i); } //Add MyCloud to CloudPieces at ProcesserIndex. CloudPieces[(int)MyIndex] = MyCloud; //Set DictPieces. DictPieces[(int)MyIndex] = MyDict; } else { //Loop over individual RangePartitions per processor. for (int i = rng.Item1; i < rng.Item2; i++) { //Operation Percentage Report ///Safe Counter Increment. Interlocked.Increment(ref PointCounter); ///Calculate and Report Percentage. if (LastPercentReported < ((PointCounter * totc) * 100)) { LastPercentReported = (int)(5 * Math.Ceiling((double)(PointCounter * totc) * 20)); this.ReportPercent = LastPercentReported; } calcNormal(idc, ref MyCloud, ref count, i); } //Add MyCloud to CloudPieces at ProcesserIndex. CloudPieces[(int)MyIndex] = MyCloud; } //Enable Parrallel Computing Cancellation po.CancellationToken.ThrowIfCancellationRequested(); } ); //Merge PointCloud Pieces into One PointCloud. Cloud_Utils.MergeClouds(ref NewCloud, CloudPieces); if (GlobalCloud.UserDictionary.Count > 0) { List <double>[] NewDict = new List <double> [GlobalCloud.UserDictionary.Count]; Dict_Utils.Merge_DictPieces(ref NewDict, DictPieces); Dict_Utils.SetUserDict_FromDictLists(ref NewCloud, NewDict, GlobalCloud.UserDictionary.Keys); } //Dispose of Global Clouds. GlobalCloud.Dispose(); pointCloud.Dispose(); /* * //Colorize * if (insV_Colorize) * { * List<double> colorValues = Color_Utils.ColorValues_Std_pos(NewCloud, insV_Key); * List<Color> Colors = Color_Utils.ColorGradient_Std_GtoR(); * * Instruction.Instr_Dict_Color col = new Instruction.Instr_Dict_Color(insV_Key, colorValues, Colors, -1, 0.00); * Boolean ColResult = col.Execute(ref NewCloud); * * //Set ColorGradient UserData * Color_Utils.Set_ColorGradient_Dict(ref NewCloud, Colors, colorValues); * } */ pointCloud = (PointCloud)NewCloud.Duplicate(); //Dispose of PointCloud Pieces and NewCloud. GlobalCloud.Dispose(); NewCloud.Dispose(); //Return True on Finish return(true); }
/// <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) { Type_KDTree treeT = null; List <Point3d> pts = new List <Point3d>(); List <double> range = new List <double>(); int maxReturned = 100; if (!DA.GetData("KDTree", ref treeT)) { return; } if (!DA.GetDataList("Points", pts)) { return; } if (!DA.GetDataList("Range", range)) { return; } DA.GetData("Number of Neighbors", ref maxReturned); Tuple <KDTree <int>, GH_Cloud> KDTreeCloud = treeT.Value; KDTree <int> tree = KDTreeCloud.Item1; PointCloud cloud = KDTreeCloud.Item2.Value; if (range.Count > 1 && range.Count < pts.Count) { AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Amount of Range values should be a single value, or match the amount of search points."); return; } List <int>[] idc = KDTreeLib.NearestNeighborSearch(tree, pts, range, maxReturned); var path1 = DA.ParameterTargetPath(0); DataTree <Point3d> pointT = new DataTree <Point3d>(); DataTree <Vector3d> normalT = new DataTree <Vector3d>(); DataTree <Color> colorT = new DataTree <Color>(); DataTree <double> distanceT = new DataTree <double>(); GH_Structure <GH_Integer> idxT = new GH_Structure <GH_Integer>(); for (int i = 0; i < pts.Count; i++) { List <int> ids = idc[i]; for (int j = 0; j < ids.Count; j++) { pointT.Add(cloud[ids[j]].Location, path1.AppendElement(i)); if (cloud.ContainsNormals) { normalT.Add(cloud[ids[j]].Normal, path1.AppendElement(i)); } if (cloud.ContainsColors) { colorT.Add(cloud[ids[j]].Color, path1.AppendElement(i)); } //Distance betwen Points double D = pts[i].DistanceTo(cloud[ids[j]].Location); distanceT.Add(D, path1.AppendElement(i)); } idxT.AppendRange(ids.Select(x => new GH_Integer(x)), path1.AppendElement(i)); } DA.SetDataTree(0, pointT); DA.SetDataTree(1, normalT); DA.SetDataTree(2, colorT); DA.SetDataTree(3, distanceT); DA.SetDataTree(4, idxT); }