Exemple #1
0
        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);
        }