Esempio n. 1
0
        /// <summary>
        /// Needs to calculate Length of the curve. If you have it - create this class passing 'length' parameter.
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        public Percent PercentAt(double t)
        {
            var     subLength = Crv.GetLength(new Interval(Domain.T0, t));
            Percent p         = subLength / Length;

            return(p);
        }
Esempio n. 2
0
        /// <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)
        {
            //字典立面的Key必须唯一,如何保证TempDict的Key值唯一?
            //调换Curve和Dict的顺序
            //这里存在的一个bug
            Point3d      Pt   = default(Point3d);
            List <Curve> Crvs = new List <Curve>();
            int          Num  = 1;
            Dictionary <Curve, double> _TempDict = new Dictionary <Curve, double>();

            if (!DA.GetDataList <Curve>(0, Crvs))
            {
                return;
            }
            if (!DA.GetData(1, ref Pt))
            {
                return;
            }
            if (!DA.GetData(2, ref Num))
            {
                return;
            }

            if (Num == 0)
            {
                this.AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Num为0");
            }

            double Param = 0;

            foreach (var Crv in Crvs)
            {
                if (Crv.ClosestPoint(Pt, out Param))
                {
                    Point3d TempPt = Crv.PointAt(Param);
                    double  Dist   = Pt.DistanceTo(TempPt);
                    _TempDict.Add(Crv, Dist);
                }
            }
            var          ResultDict = _TempDict.OrderByDescending(item => - item.Value).ToDictionary(item => item.Key, item => item.Value);
            List <Curve> TempCrvs   = ResultDict.Keys.ToList();
            List <Curve> ResultCrvs = new List <Curve>();

            if (TempCrvs.Count < Math.Abs(Num))
            {
                this.AddRuntimeMessage(GH_RuntimeMessageLevel.Error, "Num 数值过大");
                return;
            }
            if (this.FindType == 0)
            {
                ResultCrvs = TempCrvs.GetRange(0, Math.Abs(Num));
            }
            else
            {
                ResultCrvs = TempCrvs.GetRange(TempCrvs.Count - Num - 1, TempCrvs.Count);
            }
            DA.SetDataList(0, ResultCrvs);
        }
Esempio n. 3
0
        /// <summary>
        /// Needs to calculate Length of the curve. If you have it - create this class passing 'length' parameter.
        /// </summary>
        /// <param name="point"></param>
        /// <returns></returns>
        public Percent PercentAt(Point3d point)
        {
            double t;

            if (!Crv.ClosestPoint(point, out t))
            {
                throw new Exception("CurveNormalized.P(Point3d point)  failed to get T from 3d point!");
            }
            return(PercentAt(t));
        }
Esempio n. 4
0
        // same as 'T' but use sinlge method call to optimize perfromance
        public double[] T(Percent[] ps)
        {
            foreach (var p in ps)
            {
                p.MustBeInScope01();
            }

            double[] s = ps.Select(o => (double)o).ToArray();
            double[] t = Crv.NormalizedLengthParameters(s, 1E-08); // single method call to Rhinocommon
            if (t != null)
            {
                return(t);
            }
            return(ps.Select(o => T(o)).ToArray());
        }
Esempio n. 5
0
    void OnSceneGUI()
    {
        Handles.color = Col.black;
        List <Vector3> lis = Crv.CatmullRomSpline(hand.points, hand.smooth, hand.spacing);

        for (int i = 1; i < lis.Count; i++)
        {
            Handles.DrawLine(hand.TfPnt(lis[i - 1]), hand.TfPnt(lis[i]));
        }

        Handles.color = Col.red;
        for (int i = 0; i < hand.points.Count; i++)
        {
            hand.points[i] = hand.TfInvPnt(
                Handles.FreeMoveHandle(
                    hand.TfPnt(hand.points[i]),
                    Q.O, 25, V3.O, Handles.CylinderHandleCap
                    )
                );
        }
    }
Esempio n. 6
0
        public double T(Percent p)
        {
            p.MustBeInScope01();

            double t;

            if (Crv.NormalizedLengthParameter(p, out t, 1E-08))
            {
                return(t);
            }

            // very small curves are really hard to get some middle point - so dont bother - show a warning only for normal curves
            var len = Crv.PointAtStart._DistanceTo(Crv.PointAtEnd);

            if (len > 0.0001)
            {
                log.wrong("CurveNormalized.T(Percent p) cannot get value from method 'NormalizedLengthParameter'");
            }
            // at least we can return approximated value
            return(Crv.Domain.T0 + Crv.Domain.Length * p);
        }
Esempio n. 7
0
        /// <summary>
        /// Remove portions of the curve outside the specified interval.
        /// </summary>
        /// <param name="p0"></param>
        /// <param name="p1"></param>
        /// <param name="failReason"></param>
        /// <returns></returns>
        public CurveNormalized Trim(Percent p0, Percent p1, out string failReason)
        {
            failReason = "";
            Curve res = null;

            if (p0.is0percent() && p1.is100percent())
            {
                res = Crv;
            }
            else
            {
                var t0 = T(p0);
                var t1 = T(p1);
                res = Crv.DuplicateCurve().Trim(t0, t1);
            }
            if (res == null)
            {
                failReason = "failed to trim crv";
                return(null);
            }
            return(new CurveNormalized(res));
        }
Esempio n. 8
0
        /// <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)
        {
            List <Curve>            Crvs       = new List <Curve>();
            double                  ThreadHold = 0.1;
            string                  SortSign   = "x";
            GH_Structure <GH_Curve> OutputTree = new GH_Structure <GH_Curve>();

            if (!DA.GetDataList(0, Crvs))
            {
                return;
            }
            if (!DA.GetData(1, ref ThreadHold))
            {
                return;
            }
            if (!DA.GetData(2, ref SortSign))
            {
                return;
            }

            int SortIndex = SortSign.ToLower() == "x" ?
                            0 : SortSign.ToLower() == "y" ?
                            1 : SortSign.ToLower() == "z" ?
                            2 : 0;


            var GroupData = Crvs.GroupBy(Crv => { double Pt_Seg = Crv.PointAtNormalizedLength(0.5)[SortIndex]; return(Pt_Seg * (1 / ThreadHold)); }).ToList();

            for (int Index = 0; Index < GroupData.Count; Index++)
            {
                var TempGroup  = GroupData[Index];
                var TreeBranch = TempGroup.Select(Crv => new GH_Curve(Crv)).ToList();
                OutputTree.AppendRange(TreeBranch, new GH_Path(Index));
            }

            DA.SetDataTree(0, OutputTree);
        }
Esempio n. 9
0
 void Start()
 {
     lis = Crv.CatmullRomSpline(points, smooth, spacing);
 }
Esempio n. 10
0
        /// <summary>
        /// Generate conter-clockwise ordered CurveArray representing enclosed areas based on a bunch of intersected lines
        /// </summary>
        /// <param name="C"></param>
        /// <returns></returns>

        public static List <CurveArray> RegionCluster(List <Curve> C) // , Plane P, ref object CN
        {
            List <Curve> Crvs = new List <Curve>();

            for (int CStart = 0; CStart <= C.Count - 1; CStart++)
            {
                List <double> breakParams = new List <double>();
                for (int CCut = 0; CCut <= C.Count - 1; CCut++)
                {
                    if (CStart != CCut)
                    {
                        // ExtendCrv(C[CCut], 0.005)
                        SetComparisonResult result = C[CStart].Intersect(C[CCut], out IntersectionResultArray results);
                        if (result != SetComparisonResult.Disjoint)
                        {
                            double breakParam = results.get_Item(0).UVPoint.U;
                            breakParams.Add(breakParam);
                            //Debug.Print("Projection parameter is: " + breakParam.ToString());
                        }
                    }
                }
                Crvs.AddRange(SplitCrv(C[CStart], breakParams));
            }

            List <XYZ>   Vtc = new List <XYZ>();                                          // all unique vertices
            List <Curve> HC  = new List <Curve>();                                        // list of all shattered half-curves
            List <int>   HCI = new List <int>();                                          // half curve indices
            List <int>   HCO = new List <int>();                                          // half curve reversed
            List <int>   HCN = new List <int>();                                          // next index for each half-curve (conter-clockwise)
            List <int>   HCV = new List <int>();                                          // vertex representing this half-curve
            List <int>   HCF = new List <int>();                                          // half-curve face
            List <bool>  HCK = new List <bool>();                                         // mark if a half-curve needs to be killed
            // (if it either starts or ends hanging, but does not exclude redundant curves that not exclosing a room)
            Dictionary <int, List <Curve> > F    = new Dictionary <int, List <Curve> >(); // data tree for faces
            Dictionary <int, List <int> >   VOut = new Dictionary <int, List <int> >();   // data tree of outgoing half-curves from each vertex

            foreach (Curve Crv in Crvs)                                                   // cycle through each curve
            {
                for (int CRun = 0; CRun <= 2; CRun += 2)                                  // create two half-curves: first in one direction, and then the other...
                {
                    XYZ testedPt = new XYZ();
                    if (CRun == 0)
                    {
                        HC.Add(Crv);
                        testedPt = Crv.GetEndPoint(0);
                    }
                    else
                    {
                        HC.Add(Crv.CreateReversed());
                        testedPt = Crv.GetEndPoint(1);
                    }
                    HCI.Add(HCI.Count);        // count this iteration
                    HCO.Add(HCI.Count - CRun); // a little index trick
                    HCN.Add(-1);
                    HCF.Add(-1);
                    HCK.Add(false);

                    int VtcSet = -1;

                    for (int VtxCheck = 0; VtxCheck <= Vtc.Count - 1; VtxCheck++)
                    {
                        if (Vtc[VtxCheck].DistanceTo(testedPt) < 0.0000001)
                        {
                            VtcSet = VtxCheck; // get the vertex index, if it already exists
                            break;
                        }
                    }

                    if (VtcSet > -1)
                    {
                        HCV.Add(VtcSet); // If the vertex already exists, set the half-curve vertex
                        VOut[VtcSet].Add(HCI.Last());
                    }
                    else
                    {
                        HCV.Add(Vtc.Count); // if the vertex doesn't already exist, add a new vertex index
                        VOut.Add(Vtc.Count, new List <int>()
                        {
                            HCI.Last()
                        });
                        // add the new half-curve index to the list of outgoing half-curves associated with the vertex
                        Vtc.Add(testedPt);
                        // add the new vertex to the vertex list
                    }
                    Crv.CreateReversed(); // reverse the curve for creating the opposite half-curve in the second part of the loop
                    //Debug.Print("Tested point is (" + testedPt.X.ToString() + ", " + testedPt.Y.ToString() + ")");
                }
            }


            // For each Vertex that has only one outgoing half-curve, kill the half-curve and its opposite
            foreach (KeyValuePair <int, List <int> > path in VOut)
            {
                //Debug.Print("This point has been connected to " + path.Value.Count.ToString() + " curves");
                if (path.Value.Count == 1)
                {
                    HCK[path.Value[0]]      = true;
                    HCK[HCO[path.Value[0]]] = true;
                }
            }
            Debug.Print("Elements inside Crvs are " + Crvs.Count.ToString());
            Debug.Print("Elements inside HC are " + HC.Count.ToString());
            Debug.Print("Elements inside VOut are " + VOut.Count.ToString());
            Debug.Print("Elements inside HCK are " + HCK.Count.ToString());
            //Debug.Print(printb(HCK));


            // Find the "next" half-curve for each starting half curve by identifying the outgoing half-curve from the end vertex
            // that presents the smallest angle by calculating its plane's x-axis angle from x-axis of the starting half-curve's opposite plane
            foreach (int HCIdx in HCI)
            {
                int    minIdx   = -1;
                double minAngle = 2 * Math.PI;
                //Debug.Print(VOut[HCV[HCO[HCIdx]]].Count().ToString());
                foreach (int HCOut in VOut[HCV[HCO[HCIdx]]])
                {
                    if (HCOut != HCO[HCIdx] & HCK[HCIdx] == false & HCK[HCOut] == false)
                    {
                        double testAngle = AngleBetweenCrv(HC[HCOut], HC[HCO[HCIdx]], new XYZ(0, 0, 1));
                        // The comparing order is important to ensure a right-hand angle under z-axis
                        if (testAngle < minAngle)
                        {
                            minIdx   = HCOut;
                            minAngle = testAngle;
                        }
                    }
                }
                HCN[HCIdx] = minIdx;
            }

            Debug.Print("Elements inside HCI are " + HCI.Count.ToString());
            Debug.Print("Elements inside HCN are " + HCN.Count.ToString());
            Debug.Print("Elements in HCN: " + printo(HCN));

            // Sequence half-curves into faces by running along "next" half-curves in order until the starting half-curve is returned to
            List <int> FaceEdges   = new List <int>();
            List <int> DeleteEdges = new List <int>();

            // cycle through each half-curve
            foreach (int HCIdx in HCI)
            {
                int EmExit = 0;
                if (HCF[HCIdx] == -1)
                {
                    int EdgeCounter = 1;
                    int FaceIdx     = F.Count();
                    int CurrentIdx  = HCIdx;
                    F.Add(FaceIdx, new List <Curve>()
                    {
                        HC[CurrentIdx]
                    });
                    HCF[CurrentIdx] = FaceIdx;
                    do
                    {
                        if (HCN[CurrentIdx] == -1)
                        {
                            DeleteEdges.Add(FaceIdx);
                            break;
                        }

                        CurrentIdx = HCN[CurrentIdx];
                        F[FaceIdx].Add(HC[CurrentIdx]);
                        EdgeCounter    += 1;
                        HCF[CurrentIdx] = FaceIdx;
                        if (HCN[CurrentIdx] == HCIdx)
                        {
                            break;
                        }
                        EmExit += 1;
                        if (EmExit == Crvs.Count - 1)
                        {
                            break;
                        }
                    }while (true);
                    // exit once the starting half-curve is reached again
                    // emergency exit prevents infinite loops
                    FaceEdges.Add(EdgeCounter);
                }
            }
            //Debug.Print("Elements in FaceEdges: " + printo(FaceEdges));
            //Debug.Print("Elements in DeleteEdges: " + printo(DeleteEdges));
            //Debug.Print("Elements in F dict: " + printd(F));

            // Find the perimeter by counting edges of a region
            int Perim      = -1;
            int PerimCount = -1;

            for (int FE = 0; FE <= FaceEdges.Count - 1; FE++)
            {
                if (FaceEdges[FE] > PerimCount)
                {
                    Perim      = FE;
                    PerimCount = FaceEdges[FE];
                }
            }
            DeleteEdges.Add(Perim);

            int NewPath = 0;
            List <CurveArray> OutputFaces = new List <CurveArray>();

            // only output those faces that haven't been identified as either the perimeter or open
            foreach (KeyValuePair <int, List <Curve> > kvp in F)
            {
                if (DeleteEdges.Contains(kvp.Key) == false)
                {
                    CurveArray tempLoop = new CurveArray();
                    foreach (Curve element in kvp.Value)
                    {
                        tempLoop.Append(element);
                    }
                    OutputFaces.Add(tempLoop);
                    NewPath += 1;
                }
            }
            // Debug.Print("Elements in OutputFaces dict: " + printd(OutputFaces));

            return(OutputFaces);
        }
Esempio n. 11
0
 public Vector3d TangentAt(Percent p)
 {
     return(Crv.TangentAt(T(p)));
 }
Esempio n. 12
0
 public Point3d PointAt(CurveEnd end)
 {
     return(Crv.PointAt(T(end)));
 }
Esempio n. 13
0
 public Point3d[] PointsAt(Percent[] ps)
 {
     double[] ts = T(ps);
     return(ts.Select(o => Crv.PointAt(o)).ToArray());
 }
Esempio n. 14
0
 public Point3d PointAt(Percent p)
 {
     return(Crv.PointAt(T(p)));
 }