How to solve the "Curve.CreateBooleanDifference" creating more unwanted curves?

Hi guys,
My goals:1.Red boundaries;2.Short time;(Picture-00,Picture-01)
My problems:1.Emtpy results;2.Missing wanted curves;3.Result include unwanted curves.(Picture-02,Picture-03,Picture-04,Picture-05)
Firstly,I wish to get the curve boundaries inside of the CrvBase which is showen as red area on picture-01.


Secondly,I want the whole operation consume time as short as possible.
My codes with Will_wang’s help for Case A and B:

Curve[] Union_Crvs = Curve.CreateBooleanUnion(ListCrvs, 1.0);
Curve[] Dif_Crvs = Curve.CreateBooleanDifference(CrvBase, Union_Crvs, 1.0);
List<Curve> LCrv = new List<Curve>();
foreach(Curve iCrv in Dif_Crvs)
{
  Point3d iCenPt = Rhino.Geometry.AreaMassProperties.Compute(iCrv).Centroid;
  Rhino.Geometry.PointContainment PtCont = CrvBase.Contains(iCenPt, Plane.WorldXY, 0);
  if(Convert.ToInt32(PtCont) == 1){LCrv.Add(iCrv);}
}
A = LCrv;

Unfortunately,problems have happened.
Case A (CrvBase is a convex curve):
When angle is between 4.64 and 4.67,the results are empty.But the ListCrvs obviously overlap on CrvBase.(picture-2)


When angle is 4.79,the results lost some curves.(picture-03)

Case B (CrvBase is a concave curve):
When anlge is between 1.78 and 1.87,the results show an unwanted curve outside CrvBase as a “wanted” one.(picture-04)

"Centroid " method will not sort it out.
Codes for Case C:
Although I fix the “unwanted” problem,it cost much more time.

Curve[] Union_CrvsTmp = Curve.CreateBooleanUnion(ListCrvs, 0.1);
Curve[] Union_Crvs = Curve.CreateBooleanUnion(Union_CrvsTmp, 0.1);
Curve[] Dif_Crvs = Curve.CreateBooleanDifference(CrvBase, Union_Crvs, 0.1);//find all possible curves
List<Curve> LCrv = new List<Curve>();
if(Dif_Crvs.Length != 1)
{
  List<Curve> Select_Crvs = new List<Curve>();
  List<Curve> Remove_Crvs = new List<Curve>();
  for(int i = 0;i < Dif_Crvs.Length;i++)
  {
    //Inside the CrvBase,IsetCrv.Length != 0
    Curve[] IsetCrv = Curve.CreateBooleanIntersection(Dif_Crvs[i], CrvBase, 0.1);
    if(IsetCrv.Length != 0){Select_Crvs.Add(Dif_Crvs[i]);}
    for(int j = 0;j < Union_Crvs.Length;j++)
    {
      //find the curves outside of the CrvBase,store their indexes
      Curve[] IsetPRBs = Curve.CreateBooleanIntersection(Dif_Crvs[i], Union_Crvs[j], 0.1);
      if(IsetPRBs.Length != 0){Remove_Crvs.Add(Dif_Crvs[i]);}
    }
  }
  LCrv = Select_Crvs.Except(Remove_Crvs).ToList();//remove the outside ones
}
else{LCrv = new List<Curve>(Dif_Crvs);}
A = LCrv;

Case C (CrvBase is a concave curve):
Unluckily,when anlge is between 3.35 and 4.09,the results also lost some curves.(picture-05)


Could anybody help me to solve my 3 problems?I attach relevant documents.
Question.3dm (41.7 KB) Question.gh (15.1 KB)

for starters, you can test Curve.Contains()
somehow get a centroid-like point and exclude those outside of your “CrvBase”
only works for close curves obviously…

Thank you for your suggestion.I successfully select the inside curves.But it still cost much time.Is there any methods to save time?

    Curve[] Union_Crvs = Curve.CreateBooleanUnion(ListCrvs, 1.0);
    Curve[] Union_UnCrvs = Curve.CreateBooleanUnion(Union_Crvs, 1.0);
    Curve[] Dif_Crvs = Curve.CreateBooleanDifference(CrvBase, Union_UnCrvs, 1.0);    
    List<Curve> LCrv = new List<Curve>();
    foreach(Curve iCrv in Dif_Crvs)
    {
      Point3d iCenPt = Rhino.Geometry.AreaMassProperties.Compute(iCrv).Centroid;
      Rhino.Geometry.PointContainment PtCont = CrvBase.Contains(iCenPt, Plane.WorldXY, 0.01);      
      if(Convert.ToInt32(PtCont) == 1){LCrv.Add(iCrv);}
    }
    A = LCrv;

Here is a solution, although it still doesn’t help you reduce computing time.

  private void RunScript(Curve H, List<Curve> S, ref object A)
  {
    double tol = RhinoDoc.ActiveDoc.ModelAbsoluteTolerance;
    Curve[] u = Curve.CreateBooleanUnion(S, tol);
    var rd = nic.Components.FindComponent("RegionDifference");
    object[] args = new object[]{H, u, Plane.WorldXY};
    // you can change the world xy to your curve plane
    string[] msg;
    var results = rd.Evaluate(args, false, out msg);
    A = results[0];
  }

remember to add this reference at the top
using nic = Rhino.NodeInCode;

2 Likes

Thanks a lot ! Your method fixes out the “Red boundaries”.I am trying to reduce time with multi-threading.

Hi Will,
I finally find that the key factor in these problems is the “tolerance”(Curve.CreateBooleanDifference(curveA,curveB,tolerance)).When tolerance is as small as possible,“empty results” and “Missing wanted curves” can be sorted out.Using “RegionDifference” is truely a bright way.Thank you all the same.