/// <summary>
        /// Solves the instance.
        /// </summary>
        /// <param name="DA">Da.</param>
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            Mesh   mesh      = null;
            Curve  startGeod = null;
            int    Count     = 0;
            double Angle     = 0.0;
            int    Iter      = 0;

            if (!DA.GetData(0, ref mesh))
            {
                return;
            }
            if (!DA.GetData(1, ref startGeod))
            {
                return;
            }
            if (!DA.GetData(2, ref Count))
            {
                return;
            }
            if (!DA.GetData(3, ref Angle))
            {
                return;
            }
            if (!DA.GetData(4, ref Iter))
            {
                return;
            }


            List <Curve> geodesicPattern = MeshGeodesicMethods.ComputeGeodesicPatternByParralelTransport(mesh, startGeod, Count, Angle, Iter);

            DA.SetDataList(0, geodesicPattern);
        }
예제 #2
0
        // Find the best fitting geodesic curve for a set of
        public double ComputeError(int n, double[] x)
        {
            double   alpha  = x[0];
            Curve    curve  = perpGeodesics[startIndex];
            Point3d  pt     = curve.PointAt(perpParameters[startIndex]);
            Vector3d vector = curve.TangentAt(perpParameters[startIndex]);

            MeshPoint mPt    = mesh.ClosestMeshPoint(pt, 0.0);
            Vector3d  normal = mesh.NormalAt(mPt);
            Vector3d  cP     = Vector3d.CrossProduct(vector, normal);

            cP.Rotate(alpha, normal);

            Curve newG = MeshGeodesicMethods.getGeodesicCurveOnMesh(mesh, pt, cP, maxIter).ToNurbsCurve();

            if (bothDir)
            {
                Curve newG2 = MeshGeodesicMethods.getGeodesicCurveOnMesh(mesh, pt, -cP, maxIter).ToNurbsCurve();
                newG = Curve.JoinCurves(new List <Curve> {
                    newG, newG2
                })[0];
            }

            // Assign resulting geodesic to global property for output.
            selectedGeodesic = newG;

            // Calculate error
            double error = 0;

            for (int i = 0; i < perpGeodesics.Count - 1; i++)
            {
                Curve g = perpGeodesics[i];
                CurveIntersections cvInt = Intersection.CurveCurve(newG, g, 0.00001, 0.00001);
                if (cvInt.Count > 0)
                {
                    // Compute distance if intersection is found
                    double   param    = cvInt[0].ParameterB;
                    Interval domain   = new Interval(param, perpParameters[i]);
                    double   distance = g.GetLength(domain);
                    // Add squared distance to error
                    error += Math.Pow(distance, 2);
                }
                else
                {
                    // Penalize if no intersection is found on this perp geodesic
                    error += 10;
                }
            }
            return(error);
        }
예제 #3
0
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            Mesh           mesh           = null;
            Vector3d       startDirection = Vector3d.Unset;
            List <Point3d> points         = new List <Point3d>();

            if (!DA.GetData(0, ref mesh))
            {
                return;
            }
            if (!DA.GetData(1, ref startDirection))
            {
                return;
            }
            if (!DA.GetDataList(2, points))
            {
                return;
            }

            List <Vector3d> vectors = MeshGeodesicMethods.VectorParallelTransport(startDirection, points, mesh);

            DA.SetDataList(0, vectors);
        }
예제 #4
0
        /// <summary>
        /// Solves the instance.
        /// </summary>
        /// <param name="DA">Da.</param>
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            // Properties
            Mesh   mesh              = null;
            Curve  initialCurve      = null;
            double specifiedDistance = 0.0;
            int    maxCount          = 0;
            double threshold         = 0.0;
            double perpStepSize      = 0.0;
            bool   bothDir           = false;
            double minThreshold      = 0.0;

            // Set the input data
            if (!DA.GetData(0, ref mesh))
            {
                return;
            }
            if (!DA.GetData(1, ref initialCurve))
            {
                return;
            }
            if (!DA.GetData(2, ref bothDir))
            {
                return;
            }
            if (!DA.GetData(3, ref maxCount))
            {
                return;
            }
            if (!DA.GetData(4, ref threshold))
            {
                return;
            }
            if (!DA.GetData(5, ref specifiedDistance))
            {
                return;
            }
            if (!DA.GetData(6, ref perpStepSize))
            {
                return;
            }
            if (!DA.GetData(7, ref minThreshold))
            {
                return;
            }

            // Data validation
            if (maxCount == 0)
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Count cannot be 0");
            }
            if (!mesh.IsValid)
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Mesh is invalid");
            }

            // Placeholder properties
            DataTree <Curve> pattern       = new DataTree <Curve>();
            Curve            previousCurve = initialCurve;
            List <Curve>     perpGeods     = new List <Curve>();
            List <double>    perpParams    = new List <double>();

            // Start piecewise evolution process
            for (int i = 0; i < maxCount; i++)
            {
                Debug.WriteLine("Iter " + i);
                //  Create placeholder lists
                perpGeods  = new List <Curve>();
                perpParams = new List <double>();

                // Divide curve
                double[] geodParams = previousCurve.DivideByLength(perpStepSize, true);

                if (geodParams == null)
                {
                    AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "No  points found on iter" + i);
                    break;
                }
                if (geodParams.Length <= 2)
                {
                    AddRuntimeMessage(GH_RuntimeMessageLevel.Remark, "Not enough points found on iter" + i);
                    break;
                }

                // Generate perp geodesics for measurement
                foreach (double t in geodParams)
                {
                    // Get curve tangent vector and mesh normal
                    Point3d  point   = previousCurve.PointAt(t);
                    Vector3d tangent = previousCurve.TangentAt(t);
                    Vector3d normal  = mesh.NormalAt(mesh.ClosestMeshPoint(point, 0.0));

                    // Rotate vector against normals 90 degrees
                    tangent.Rotate(0.5 * Math.PI, normal);

                    // Generate perp geodesic
                    Curve perpGeodesic = MeshGeodesicMethods.getGeodesicCurveOnMesh(mesh, point, tangent, 100).ToNurbsCurve();

                    // Check for success
                    if (perpGeodesic != null && perpGeodesic.GetLength() > specifiedDistance)
                    {
                        // Divide by specified length
                        double perpT = 0.0;
                        perpGeodesic.LengthParameter(specifiedDistance, out perpT);

                        // Add data to lists
                        perpGeods.Add(perpGeodesic);
                        perpParams.Add(perpT);
                    }
                }
                // Clean perp geods of intersections ocurring BEFORE the specified distance
                var result = CleanPerpGeodesics(perpGeods, perpParams, specifiedDistance);
                // Assign clean lists
                perpGeods  = result.perpGeodesics;
                perpParams = result.perpParams;


                // Break if not enough perpGeods remain
                if (perpGeods.Count < 6)
                {
                    AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Not  enough perp geodesics where found for iter " + i);
                    break;
                }

                //Generate the next piecewise geodesic
                List <Curve> iterCurves = GeneratePiecewiseGeodesicCurve(mesh, perpParams, perpGeods, 1000, bothDir, 0, threshold, Vector3d.Unset);

                // Add it to the pattern
                pattern.AddRange(iterCurves, new GH_Path(i));

                // Assign as previous for the next round
                Curve[] joinedResult = Curve.JoinCurves(iterCurves);

                // Error check
                if (joinedResult.Length > 1)
                {
                    AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "More than 1 curve after Join in iter " + i);
                    break;
                }
                //Create points and bisectrix vectors for next round of perp geodesics
                Point3dList ptList = new Point3dList();
                foreach (Curve c in iterCurves)
                {
                    if (!ptList.Contains(c.PointAtStart))
                    {
                        ptList.Add(c.PointAtStart);
                    }
                    if (!ptList.Contains(c.PointAtEnd))
                    {
                        ptList.Add(c.PointAtEnd);
                    }
                }
                Debug.WriteLine("ptList Count: " + ptList.Count);
                // Assign new curve to previous curve
                Curve joinedCurve = joinedResult[0];
                previousCurve = joinedCurve;
            }

            // Assign data to output
            DA.SetDataTree(0, pattern);
            DA.SetDataList(2, perpGeods);
        }
예제 #5
0
        // Find the best fitting geodesic curve for a set of
        public new double ComputeError(int n, double[] x)
        {
            double alpha = x[0];

            bestFitInterval = new int[] { };
            Curve    curve  = perpGeodesics[startIndex];
            Point3d  pt     = curve.PointAt(perpParameters[startIndex]);
            Vector3d vector = curve.TangentAt(perpParameters[startIndex]);

            MeshPoint mPt    = mesh.ClosestMeshPoint(pt, 0.0);
            Vector3d  normal = mesh.NormalAt(mPt);
            Vector3d  cP     = Vector3d.CrossProduct(vector, normal);

            cP.Rotate(alpha, normal);

            if (refDir == Vector3d.Unset)
            {
                refDir = cP;
            }
            double angle = Vector3d.VectorAngle(cP, refDir);

            if (angle >= 0.1 * Math.PI)
            {
                cP = -cP;
            }

            Vector3d.VectorAngle(cP, refDir);
            Curve newG = MeshGeodesicMethods.getGeodesicCurveOnMesh(mesh, pt, cP, maxIter).ToNurbsCurve();

            if (bothDir)
            {
                Curve newG2 = MeshGeodesicMethods.getGeodesicCurveOnMesh(mesh, pt, -cP, maxIter).ToNurbsCurve();
                newG = Curve.JoinCurves(new List <Curve> {
                    newG, newG2
                })[0];
            }

            // Assign resulting geodesic to global property for output.
            selectedGeodesic = newG;

            // Calculate error
            double        error           = 0;
            List <double> distances       = new List <double>();
            List <double> signedDistances = new List <double>();

            for (int i = 0; i < perpGeodesics.Count - 1; i++)
            {
                Curve g = perpGeodesics[i];
                CurveIntersections cvInt          = Intersection.CurveCurve(newG, g, 0.00001, 0.00001);
                double             signedDistance = g.GetLength(new Interval(0, perpParameters[i]));
                signedDistances.Add(signedDistance);
                if (cvInt.Count > 0)
                {
                    // Compute distance if intersection is found
                    double param    = cvInt[0].ParameterB;
                    double distance = g.GetLength(new Interval(0, param));
                    distances.Add(distance);
                    // Add squared distance to error
                    error += Math.Pow(signedDistance - distance, 2);
                }
                else
                {
                    // Penalize if no intersection is found on this perp geodesic
                    distances.Add(1000);
                    error += 1000;
                }
            }

            //Calculate longest interval within threshold.
            for (int k = (distances.Count - 1); k >= 2; k--)
            {
                for (int i = 0; i < (distances.Count - k); i++)
                {
                    //Check if interval i->k is within bounds
                    bool flag = true;
                    for (int j = i; j < i + k; j++)
                    {
                        double Lbound = signedDistances[j] * (1 - threshold);
                        double Ubound = signedDistances[j] * (1 + threshold);
                        if (Lbound > distances[j] || distances[j] > Ubound)
                        {
                            flag = false;
                            break;
                        }
                    }
                    if (flag && bestFitInterval.Length == 0)
                    {
                        bestFitInterval = new int[] { i, i + k };
                    }
                }
            }
            if (bestFitInterval.Length == 0)
            {
                error += 1000000;
                return(error);
            }
            error = error / (bestFitInterval[1] - bestFitInterval[0]);

            //if (invertDir) selectedGeodesic.Reverse();

            return(error);
        }
예제 #6
0
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            // Input variables
            int             iter            = 0;
            Mesh            mesh            = new Mesh();
            List <Point3d>  startPoints     = new List <Point3d>();
            List <Vector3d> startDirections = new List <Vector3d>();
            // Output holders
            List <Curve> polyList = new List <Curve>();
            bool         bothDir  = false;

            // Value setting
            if (!DA.GetData(0, ref iter))
            {
                return;
            }
            if (!DA.GetData(1, ref mesh))
            {
                return;
            }
            if (!DA.GetDataList(2, startPoints))
            {
                return;
            }
            if (!DA.GetDataList(3, startDirections))
            {
                return;
            }
            if (!DA.GetData(4, ref bothDir))
            {
                return;
            }

            // Value checks
            if (startPoints.Count != startDirections.Count)
            {
                AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Start point and vector list must be the same length");
            }

            for (int i = 0; i < startPoints.Count; i++)
            {
                Curve    crv;
                Polyline pl = MeshGeodesicMethods.getGeodesicCurveOnMesh(mesh, startPoints[i], startDirections[i], iter);

                if (bothDir)
                {
                    Polyline pl2 = MeshGeodesicMethods.getGeodesicCurveOnMesh(mesh, startPoints[i], -startDirections[i], iter);
                    crv = Curve.JoinCurves(new List <Curve> {
                        pl.ToNurbsCurve(), pl2.ToNurbsCurve()
                    })[0];
                }
                else
                {
                    crv = pl.ToNurbsCurve();
                }
                polyList.Add(crv);
            }


            // Output results
            DA.SetDataList(0, polyList);
        }