Grasshopperで交差しない二つの曲線の近傍点に関するメモ

C#

普通の交点の求め方

Grasshopperでは曲線の交点を求めるコンポーネントが標準装備されています。

なので、例えば円と直線の交点は

下図のような、ghコンポーネントをつないでやれば求まります。

交差しない場合

中学数学で習ったような、「ねじれの位置」にある場合は次のように既存のコンポーネントでは答えを返しません。私の環境,Large,[mm]では0.01mmでも高さ方向にずれがあると,Grasshopperコンポーネントは交点を計算しませんでした。

この絵は、最初の図からZ方向に20mm直線をオフセットしている。
交差していないのだから交差点は返さない。

これは、当たり前といえば当たり前で円と直線が交差していないためこのような現象は発生します。つまり,交点の有無を調べるためにこのコンポーネントを利用することもよくあるかと思います。

近似的な交点の求め方

実際的には手でモデリングをすることもあって、厳密に交差してなくても交点を取りたいという場合はよくあります。そういう時は,RhinoCommonの関数を利用すると簡単に対応できます。

ここでToleranceは曲線間の距離でこのToleranceの値より曲線間の最短距離が小さい場合,Pointを返します。PtsAはCrvA上の点,PtsBはCrvB上の点を表します。

二つの曲線間の最短距離は,外積を使えば簡単に求まります。近傍点の組をつなぐ直線は必ず,入力される二つの曲線に対し直交するはずです。

直線同士の最短距離はこのサイトに詳しく載っていました。

2直線の交点を求める
2直線の交点を求める方法とプログラミング例

プログラムコード

このコンポーネントは次のようにコーディングすれば作成できます。RhinoCommonの関数を使っただけ…というご指摘はあるかと思います笑

namespace TAKIDAS_GH.Component
{
    public class CurveXCurveComponent : GH_Component
    {
        private Curve crvA, crvB;
        private double tolerance, overlap;

        public CurveXCurveComponent()
          : base("CurveXCurveComponent", "CurveXCurve",
              "CurveXCurve",
              "TAKIDAS", "Utils")
        {
        }

        protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
        {
            pManager.AddCurveParameter("CurveA", "CrvA", "CurveA", GH_ParamAccess.item);
            pManager.AddCurveParameter("CurveB", "CrvB", "CurveB", GH_ParamAccess.item);
            pManager.AddNumberParameter("Tolerance", "Tolerance", "Tolerance", GH_ParamAccess.item,0.0);
            pManager.AddNumberParameter("Overlap", "Overlap", "Overlap", GH_ParamAccess.item,0.0);
        }


        protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
        {
            pManager.AddPointParameter("PointsA", "PtsA", "Points on CurveA", GH_ParamAccess.list);
            pManager.AddPointParameter("PointsB", "PtsB", "Points on CurveB", GH_ParamAccess.list);
            pManager.AddIntegerParameter("Count", "Count", "Count", GH_ParamAccess.item);
            pManager.AddBooleanParameter("IsOverlap", "IsOverlap", "IsOverlap", GH_ParamAccess.list);
            pManager.AddBooleanParameter("IsPoint", "IsPoint", "IsPoint", GH_ParamAccess.list);
        }

        protected override void SolveInstance(IGH_DataAccess DA)
        {
            DA.GetData("CurveA", ref crvA);
            DA.GetData("CurveB", ref crvB);
            DA.GetData("Tolerance", ref tolerance);
            DA.GetData("Overlap", ref overlap);

            CurveIntersections crvIntersections = Intersection.CurveCurve(crvA, crvB, tolerance, overlap);

            List<Point3d> ptsA = new List<Point3d>();
            List<Point3d> ptsB = new List<Point3d>();
            List<bool> bListIsOverlap = new List<bool>();
            List<bool> bListIsPoint = new List<bool>();

            if(crvIntersections != null)
            {
                for(int i = 0; i<crvIntersections.Count; i++)
                {
                    IntersectionEvent ev = crvIntersections[i];
                    ptsA.Add(ev.PointA);
                    ptsB.Add(ev.PointB);
                    bListIsOverlap.Add(ev.IsOverlap);
                    bListIsPoint.Add(ev.IsPoint);
                }
                DA.SetDataList("PointsA", ptsA);
                DA.SetDataList("PointsB", ptsB);
                DA.SetData("Count", crvIntersections.Count);
                DA.SetDataList("IsOverlap", bListIsOverlap);
                DA.SetDataList("IsPoint", bListIsPoint);

            }
            else
            {
                DA.SetData("Count", 0);
            }

        }

        public override Guid ComponentGuid
        {
            get { return new Guid("00000000-0000-0000-0000"); }
        }
    }
}

もし必要なときはお試しあれ~

コメント

タイトルとURLをコピーしました