Divide Close Curve(Polyline) By List Of Area

10 minutes rework
Here a solution with only Rhinocommon and no plugin
The inputs must be closed curves. But it is possible to have a cutter not using a closed curve and close it in the code. It is also possible to the other things inside.

I reuse 2 codes
Daniel Piker tool

And John D. Cook one

divide Area LD v3.gh (15.6 KB)

 private void RunScript(Curve cutter, Curve cutted, double area, ref object vector)
  {
    //Laurent Delrieu 21/04/2023
    double tolerance = 0.001;
    sCC = new sliceClosedCurve(cutter, cutted, tolerance);
    double dy = RootFinding.Brent(new FunctionOfOneVariable(f), 0, sCC.maxYtranslation, tolerance, area);

    //Mouvement of cutter in order to have the area
    vector = new Vector3d(0, -dy, 0);

  }

  // <Custom additional code> 
  static sliceClosedCurve sCC;

  /// <summary>
  /// Daniel Piker tool transformed
  ///https://discourse.mcneel.com/t/sweep-plane-until-lower-section-has-a-certain-volume/128708/36
  /// </summary>
  public class sliceClosedCurve
  {
    Curve cutter;
    Curve cutted;
    public double maxYtranslation;
    double tolerance;


    public  sliceClosedCurve(Curve c_cutter, Curve c_cutted, double tol)
    {
      cutter = c_cutter.DuplicateCurve();
      cutted = c_cutted.DuplicateCurve();
      tolerance = tol;

      BoundingBox bb_cutted = cutted.GetBoundingBox(true);
      BoundingBox bb_cutter = cutter.GetBoundingBox(true);

      maxYtranslation = bb_cutter.Center.Y - bb_cutter.Diagonal.Y / 2 - (bb_cutted.Center.Y - bb_cutted.Diagonal.Y / 2 ) * 1.2;
    }
    public double getArea(double dy)
    {
      Vector3d vY = new Vector3d(0, -dy, 0);
      Curve cutterTranslated = cutter.DuplicateCurve();
      cutterTranslated.Transform(Transform.Translation(vY));


      Curve[] tab_curves = Curve.CreateBooleanIntersection(cutterTranslated, cutted, tolerance);

      double area = 0;
      foreach (Curve curve in tab_curves)
      {

        var s = Rhino.Geometry.AreaMassProperties.Compute(curve);
        area += s.Area;
      }

      return area;
    }
  }

  public static double f(double x)
  {
    return sCC.getArea(x);
  }

  /// John D. Cook
  /// https://www.codeproject.com/Articles/79541/Three-Methods-for-Root-finding-in-C
  /// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  public delegate double FunctionOfOneVariable(double x);

  public static class RootFinding
  {
    const int maxIterations = 50;
    /// <summary>
    /// John D. Cook
    /// https://www.codeproject.com/Articles/79541/Three-Methods-for-Root-finding-in-C
    /// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    /// </summary>
    /// <param name="f"></param>
    /// <param name="left"></param>
    /// <param name="right"></param>
    /// <param name="tolerance"></param>
    /// <param name="target"></param>
    /// <returns></returns>
    public static double Bisect
      (
      FunctionOfOneVariable f,
      double left,
      double right,
      double tolerance = 1e-6,
      double target = 0.0
      )
    {
      // extra info that callers may not always want
      int iterationsUsed;
      double errorEstimate;

      return Bisect(f, left, right, tolerance, target, out iterationsUsed, out errorEstimate);
    }

    public static double Bisect
      (
      FunctionOfOneVariable f,
      double left,
      double right,
      double tolerance,
      double target,
      out int iterationsUsed,
      out double errorEstimate
      )
    {
      if (tolerance <= 0.0)
      {
        string msg = string.Format("Tolerance must be positive. Recieved {0}.", tolerance);
        throw new ArgumentOutOfRangeException(msg);
      }

      iterationsUsed = 0;
      errorEstimate = double.MaxValue;

      // Standardize the problem.  To solve f(x) = target,
      // solve g(x) = 0 where g(x) = f(x) - target.
      FunctionOfOneVariable g = delegate(double x) { return f(x) - target; };


      double g_left = g(left);  // evaluation of f at left end of interval
      double g_right = g(right);
      double mid;
      double g_mid;
      if (g_left * g_right >= 0.0)
      {
        string str = "Invalid starting bracket. Function must be above target on one end and below target on other end.";
        string msg = string.Format("{0} Target: {1}. f(left) = {2}. f(right) = {3}", str, g_left + target, g_right + target);
        throw new ArgumentException(msg);
      }

      double intervalWidth = right - left;

      for
        (
        iterationsUsed = 0;
        iterationsUsed < maxIterations && intervalWidth > tolerance;
        iterationsUsed++
        )
      {
        intervalWidth *= 0.5;
        mid = left + intervalWidth;

        if ((g_mid = g(mid)) == 0.0)
        {
          errorEstimate = 0.0;
          return mid;
        }
        if (g_left * g_mid < 0.0)           // g changes sign in (left, mid)
          g_right = g(right = mid);
        else                            // g changes sign in (mid, right)
          g_left = g(left = mid);
      }
      errorEstimate = right - left;
      return left;
    }

    public static double Brent
      (
      FunctionOfOneVariable f,
      double left,
      double right,
      double tolerance = 1e-6,
      double target = 0.0
      )
    {
      // extra info that callers may not always want
      int iterationsUsed;
      double errorEstimate;

      return Brent(f, left, right, tolerance, target, out iterationsUsed, out errorEstimate);
    }

    public static double Brent
      (
      FunctionOfOneVariable g,
      double left,
      double right,
      double tolerance,
      double target,
      out int iterationsUsed,
      out double errorEstimate
      )
    {
      if (tolerance <= 0.0)
      {
        string msg = string.Format("Tolerance must be positive. Recieved {0}.", tolerance);
        throw new ArgumentOutOfRangeException(msg);
      }

      errorEstimate = double.MaxValue;

      // Standardize the problem.  To solve g(x) = target,
      // solve f(x) = 0 where f(x) = g(x) - target.
      FunctionOfOneVariable f = delegate(double x) { return g(x) - target; };

      // Implementation and notation based on Chapter 4 in
      // "Algorithms for Minimization without Derivatives"
      // by Richard Brent.

      double c, d, e, fa, fb, fc, tol, m, p, q, r, s;

      // set up aliases to match Brent's notation
      double a = left; double b = right; double t = tolerance;
      iterationsUsed = 0;

      fa = f(a);
      fb = f(b);

      if (fa * fb > 0.0)
      {
        string str = "Invalid starting bracket. Function must be above target on one end and below target on other end.";
        string msg = string.Format("{0} Target: {1}. f(left) = {2}. f(right) = {3}", str, target, fa + target, fb + target);
        throw new ArgumentException(msg);
      }

      label_int:
        c = a; fc = fa; d = e = b - a;
      label_ext:
        if (Math.Abs(fc) < Math.Abs(fb))
        {
          a = b;  b = c;  c = a;
          fa = fb; fb = fc; fc = fa;
        }

      iterationsUsed++;

      tol = 2.0 * t * Math.Abs(b) + t;
      errorEstimate = m = 0.5 * (c - b);
      if (Math.Abs(m) > tol && fb != 0.0) // exact comparison with 0 is OK here
      {
        // See if bisection is forced
        if (Math.Abs(e) < tol || Math.Abs(fa) <= Math.Abs(fb))
        {
          d = e = m;
        }
        else
        {
          s = fb / fa;
          if (a == c)
          {
            // linear interpolation
            p = 2.0 * m * s; q = 1.0 - s;
          }
          else
          {
            // Inverse quadratic interpolation
            q = fa / fc; r = fb / fc;
            p = s * (2.0 * m * q * (q - r) - (b - a) * (r - 1.0));
            q = (q - 1.0) * (r - 1.0) * (s - 1.0);
          }
          if (p > 0.0)
            q = -q;
          else
            p = -p;
          s = e; e = d;
          if (2.0 * p < 3.0 * m * q - Math.Abs(tol * q) && p < Math.Abs(0.5 * s * q))
            d = p / q;
          else
            d = e = m;
        }
        a = b; fa = fb;
        if (Math.Abs(d) > tol)
          b += d;
        else if (m > 0.0)
          b += tol;
        else
          b -= tol;
        if (iterationsUsed == maxIterations)
          return b;

        fb = f(b);
        if ((fb > 0.0 && fc > 0.0) || (fb <= 0.0 && fc <= 0.0))
          goto label_int;
        else
          goto label_ext;
      }
      else
        return b;
    }

    public static double Newton
      (
      FunctionOfOneVariable f,
      FunctionOfOneVariable fprime,
      double guess,
      double tolerance = 1e-6,
      double target = 0.0
      )
    {
      // extra info that callers may not always want
      int iterationsUsed;
      double errorEstimate;

      return Newton(f, fprime, guess, tolerance, target, out iterationsUsed, out errorEstimate);
    }

    public static double Newton
      (
      FunctionOfOneVariable f,
      FunctionOfOneVariable fprime,
      double guess,
      double tolerance,
      double target,
      out int iterationsUsed,
      out double errorEstimate
      )
    {
      if (tolerance <= 0)
      {
        string msg = string.Format("Tolerance must be positive. Recieved {0}.", tolerance);
        throw new ArgumentOutOfRangeException(msg);
      }

      iterationsUsed = 0;
      errorEstimate = double.MaxValue;

      // Standardize the problem.  To solve f(x) = target,
      // solve g(x) = 0 where g(x) = f(x) - target.
      // Note that f(x) and g(x) have the same derivative.
      FunctionOfOneVariable g = delegate(double x) { return f(x) - target; };

      double oldX, newX = guess;
      for
        (
        iterationsUsed = 0;
        iterationsUsed < maxIterations && errorEstimate > tolerance;
        iterationsUsed++
        )
      {
        oldX = newX;
        double gx = g(oldX);
        double gprimex = fprime(oldX);
        double absgprimex = Math.Abs(gprimex);
        if (absgprimex > 1.0 || Math.Abs(gx) < double.MaxValue * absgprimex)
        {
          // The division will not overflow
          newX = oldX - gx / gprimex;
          errorEstimate = Math.Abs(newX - oldX);
        }
        else
        {
          newX = oldX;
          errorEstimate = double.MaxValue;
          break;
        }
      }
      return newX;
    }
  }
1 Like