public List <Curve> GenerateSubCurves(double[] _startData, double[] _xl, double[] _xu) { // Generate Initial values and variable Bounds for the optimization problem. // Only using first variable for now, the extra variable is just to make it work. double[] startData = _startData; double[] xl = _xl; double[] xu = _xu; List <Curve> pieceWiseList = new List <Curve>(); pieceWiseList.Add(selectedGeodesic); if (bestFitInterval.Length != 0) { pieceWiseList[0] = CutCurveBetweenPerpIndexes(pieceWiseList[0], perpGeodesics, bestFitInterval[0], bestFitInterval[1]); if (bestFitInterval[1] < (perpGeodesics.Count - 1)) { List <Curve> tempGeodesics = perpGeodesics.GetRange(bestFitInterval[1], (perpGeodesics.Count - bestFitInterval[1])); List <double> tempParameters = perpParameters.GetRange(bestFitInterval[1], (perpGeodesics.Count - bestFitInterval[1])); Vector3d tangent = pieceWiseList[0].TangentAtEnd; double t; tempGeodesics[0].ClosestPoint(pieceWiseList[0].PointAtEnd, out t); tempParameters[0] = t; BestFitPieceWiseGeodesic tempBestFit = new BestFitPieceWiseGeodesic(mesh, tempGeodesics, tempParameters, maxIter / 2, false, 0, threshold, tangent); var tempOptimizer = new Bobyqa(2, tempBestFit.ComputeError, xl, xu); var tempResult = tempOptimizer.FindMinimum(startData); pieceWiseList.AddRange(tempBestFit.GenerateSubCurves(startData, xl, xu)); } if (bestFitInterval[0] > 0) { List <Curve> tempGeodesics = perpGeodesics.GetRange(0, bestFitInterval[0] + 1); List <double> tempParameters = perpParameters.GetRange(0, bestFitInterval[0] + 1); double t; Vector3d tangent = pieceWiseList[0].TangentAtStart; tempGeodesics[tempGeodesics.Count - 1].ClosestPoint(pieceWiseList[0].PointAtStart, out t); tempParameters[tempGeodesics.Count - 1] = t; BestFitPieceWiseGeodesic tempBestFit = new BestFitPieceWiseGeodesic(mesh, tempGeodesics, tempParameters, maxIter / 2, false, tempGeodesics.Count - 1, threshold, -tangent); var tempOptimizer = new Bobyqa(2, tempBestFit.ComputeError, xl, xu); var tempResult = tempOptimizer.FindMinimum(startData); pieceWiseList.AddRange(tempBestFit.GenerateSubCurves(startData, xl, xu)); } } return(pieceWiseList); }
/// <summary> /// Generates the sub curves. /// </summary> /// <returns>The sub curves.</returns> /// <param name="_startData">Start data.</param> /// <param name="_xl">Xl.</param> /// <param name="_xu">Xu.</param> /// <param name="type">Generation type: 0 for doubleside, 1 for end side, -1 for start side of curve</param> public List <Curve> GenerateSubCurves(double[] _startData, double[] _xl, double[] _xu, int type) { // Generate Initial values and variable Bounds for the optimization problem. // Only using first variable for now, the extra variable is just to make it work. double[] startData = _startData; double[] xl = _xl; double[] xu = _xu; List <Curve> pieceWiseList = new List <Curve>(); pieceWiseList.Add(selectedGeodesic); if (bestFitInterval.Length != 0) { switch (type) { // End point case 1: pieceWiseList[0] = CutCurveBetweenPerpIndexes(pieceWiseList[0], perpGeodesics, 0, bestFitInterval[1]); break; // Start point case -1: pieceWiseList[0] = CutCurveBetweenPerpIndexes(pieceWiseList[0], perpGeodesics, bestFitInterval[0], perpGeodesics.Count - 1); break; default: pieceWiseList[0] = CutCurveBetweenPerpIndexes(pieceWiseList[0], perpGeodesics, bestFitInterval[0], bestFitInterval[1]); break; } if ((bestFitInterval[1] < (perpGeodesics.Count - 1)) && (type == 0 || type == 1)) { List <Curve> tempGeodesics = perpGeodesics.GetRange(bestFitInterval[1], (perpGeodesics.Count - bestFitInterval[1])); List <double> tempParameters = perpParameters.GetRange(bestFitInterval[1], (perpGeodesics.Count - bestFitInterval[1])); Vector3d tangent = pieceWiseList[0].TangentAtEnd; double t; tempGeodesics[0].ClosestPoint(pieceWiseList[0].PointAtEnd, out t); tempParameters[0] = t; BestFitPieceWiseGeodesic tempBestFit = new BestFitPieceWiseGeodesic(mesh, tempGeodesics, tempParameters, maxIter, false, 0, threshold, tangent); var tempOptimizer = new Bobyqa(2, tempBestFit.ComputeError, xl, xu); var tempResult = tempOptimizer.FindMinimum(startData); if (tempBestFit.bestFitInterval.Length == 0) { pieceWiseList[0] = selectedGeodesic; //No best fit found } else { pieceWiseList.AddRange(tempBestFit.GenerateSubCurves(startData, xl, xu, 1)); } } //if (bestFitInterval[0] > 0 && (type == 0 || type == -1)) //{ // List<Curve> tempGeodesics = perpGeodesics.GetRange(0, bestFitInterval[0] + 1); // List<double> tempParameters = perpParameters.GetRange(0, bestFitInterval[0] + 1); // double t; // Vector3d tangent = pieceWiseList[0].TangentAtStart; // //tangent.Rotate(Math.PI, mesh.NormalAt(mesh.ClosestMeshPoint(pieceWiseList[0].PointAtStart, 0.0))); // tempGeodesics[tempGeodesics.Count - 1].ClosestPoint(pieceWiseList[0].PointAtStart, out t); // tempParameters[tempGeodesics.Count - 1] = t; // BestFitPieceWiseGeodesic tempBestFit = new BestFitPieceWiseGeodesic(mesh, tempGeodesics, tempParameters, maxIter, false, tempGeodesics.Count - 1, threshold, -tangent); // var tempOptimizer = new Bobyqa(2, tempBestFit.ComputeError, xl, xu); // var tempResult = tempOptimizer.FindMinimum(startData); // if (tempBestFit.bestFitInterval.Length == 0) // { // pieceWiseList.Add(tempBestFit.selectedGeodesic); // No best fit found; // } // else // { // tempBestFit.selectedGeodesic.Reverse(); // pieceWiseList.AddRange(tempBestFit.GenerateSubCurves(startData, xl, xu, -1)); // } //} } return(pieceWiseList); }
protected override void SolveInstance(IGH_DataAccess DA) { // Properties Mesh mesh = null; List <Curve> perpGeodesics = new List <Curve>(); List <double> perpParameters = new List <double>(); int maxIter = 0; bool bothDir = false; int startIndex = 0; mesh = null; perpGeodesics = new List <Curve>(); perpParameters = new List <double>(); double threshold = 0.0; // Set the input data if (!DA.GetData(0, ref mesh)) { return; } if (!DA.GetDataList(1, perpGeodesics)) { return; } if (!DA.GetDataList(2, perpParameters)) { return; } if (!DA.GetData(3, ref maxIter)) { return; } if (!DA.GetData(4, ref bothDir)) { return; } if (!DA.GetData(5, ref startIndex)) { return; } if (!DA.GetData(6, ref threshold)) { return; } // Data validation if (maxIter == 0) { AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "MaxIter cannot be 0"); } if (!mesh.IsValid) { AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Mesh is invalid"); } if (perpGeodesics.Count < 2) { AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "There must be at least 2 perpendicular geodesics"); } if (perpParameters.Count != perpGeodesics.Count) { AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Curves and Params list must have the same number of items"); } // Generate Initial values and variable Bounds for the optimization problem. // Only using first variable for now, the extra variable is just to make it work. double[] startData = { 0.010, 0 }; double[] xl = new double[] { -0.15, -1 }; double[] xu = new double[] { 0.15, 1 }; BestFitPieceWiseGeodesic bestFitG = new BestFitPieceWiseGeodesic(mesh, perpGeodesics, perpParameters, maxIter, bothDir, startIndex, threshold, Vector3d.Unset); var optimizer = new Bobyqa(2, bestFitG.ComputeError, xl, xu); var result = optimizer.FindMinimum(startData); if (bestFitG.bestFitInterval.Length == 0) { AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "No best interval found?!"); return; } // Sub curves methods go here List <Curve> pieceWiseList = new List <Curve>(); pieceWiseList = bestFitG.GenerateSubCurves(startData, xl, xu); DA.SetDataList(0, pieceWiseList); DA.SetDataList(1, result.X); }