Sweep Plane until Lower Section has a certain volume

As a check, look at weight/volume to make sure your object isn’t denser than the liquid it’s floating in.

I’ll try and make a root finding script example.

I’ve been using variations of this boat for years. Length is in feet (~70 feet), displacement is pounds (21705 pounds.) I’m sure the scale is off somewhere.

Weight appears to be off by exactly a factor of 100.


Sea water weighs 63.926 pounds per cubic foot so this boat should float.

P.S. The boat is sitting on its designed waterline, the ‘World XY’ plane. Sorry to be dense about this.

The rest of the definition is set up assuming all metric, so the model dimensions are in m
Also - it looks like the lbs to kg conversion is inverted in your last definition.

Does that mean I have to scale my hull up to use this? Doing that and fixing lbs to kg conversion certainly looks more correct, but I’m concerned about what that means for the values returned and for orienting the original brep? It looks like the boat is raised slightly, though the scale is confusing me about how much? Inches definitely matter! ~1500 PPI (Pounds Per Inch immersion) in this case. I set the ‘Specific gravity of fluid’ to 1.026 for seawater but is there more to it?

Using the “No Torque” option is stable but the default “torque stuff” is definitely not.

buoyancy_archimedes_2023Mar10b.gh (186.0 KB)

By the way, the torque stuff is definitely interesting for conventional boats that are not symmetrical end-to-end like this one. The CG for this boat (most boats?) is not at the center of volume either, but that is easily specified in this model.

I’m sorry Daniel, this has become as embarrassing and frustrating for me as it must be annoying to you.

I’ve been utterly lost in scaling errors, trying to understand differences between what this model is showing vs. what I know to be true. That includes draft and COG, which of course rolls with the boat… By other means, I believe the COG is at X=0, Y=7.913 feet and Z=~5 feet.

Precision is critical for boats, which is one reason I’ve always preferred NURBS to mesh surfaces. Can I get that from Kangaroo?

For this kind of boat (a Pacific proa that always keeps the smaller hull to windward), it’s very important to get the ‘No Torque’ solution because that’s where it starts to gain stability (righting moment) when the leeward “pod” dips into the water - around 35 degrees of heel.

Corrected the feet to meters conversion so the boat gets smaller and sinks again. :man_facepalming:
What makes this model metric? Can that be avoided and use imperial units somehow?

buoyancy_archimedes_2023Mar10c.gh (316.2 KB)

I might be completely wrong here, but wouldn’t it be more reliable to import the entire thing into a metric rhino file? Haven’t tested anything, just a thought.

That won’t fit my work flow. I don’t think Rhino units have any effect at all on these numbers. I’m not used to thinking metric, especially boat displacement in liters instead of cubic feet, but I’m beginning to understand - sort of.

There are 28.31685 liters per cubic foot. So if my static displacement is 21704.834393 pounds and seawater weighs 63.926 pounds per cubic foot, then my displacement is 339.53062 cubic feet or 9614.437628 liters. My conversion using Kg per Pound says 9845.21436 kg, which is a difference of 1.024. Very close to the ‘Specific gravity of fluid’ slider I set to 1.026, so I suppose it accounts for that?

The weight of seawater per liter is 1.03kg.

Sigh. This doesn’t clearly address the issue of how to scale my boat. I don’t even know which point I should use as center for scaling? The origin? Or the COB? (Center Of Buoyancy)

By trial and error, I find that if I scale my boat by a factor of 3.0825 using the origin, it floats at the expected position. But this is all too loosey-goosey for me. My Anemone solver is cumbersome to use but I have a very high degree of confidence in its results. Not so yet with Daniel’s cool model.

The total volume of the boat/bear are irrelevant. Their weight and size/shape determines what volume of seawater is displaced below the waterline.

I was thinking that maybe instead of scaling my geometry I should fudge the weight…? So by trial and error, I multiplied my displacement in pounds by a factor of 0.015500 to get the unscaled boat to float on its lines. Then realized the result was very close to the cubic feet displacement I mentioned, 339.53. So I used that instead and low and behold, it’s on the money!!

I don’t know why yet? But if it makes sense, maybe this is the solution?

buoyancy_archimedes_2023Mar10d.gh (310.5 KB)

The COG position still needs work, especially rotating it with the hull - as @Ben_Harker suggested.

P.S. I broke the bear in this code but will fix it in the morning, along with a more accurate COG for the boat, “Normal” and “Rolled”. When the torque solver is used, that COG for the rolled boat needs to move with the boat.

As to why cubic feet displacement works, I’ll leave that to Daniel but it makes sense as a measure of displacement by volume, appropriate for the boat’s dimensions in imperial units, eh?

P.P.S. Using the default Buoyancy goal (with torque), it looks like the boat pitches for no good reason and finally settles with one end higher than the other, which shouldn’t happen.

I’ve integrated the Kangaroo model (unchanged) with my old Hydrostatics code. (work in progress)


  1. ‘MODEL’ selection, cyan blob at top
  2. ‘Bear | Boat’ selection and ‘Reset Solver’, cyan group at the bottom
  3. ‘Data Dam’ after solver, red group

There is an abbreviated copy of the Hydrostatics code after the Kangaroo Solver, protected by a Data Dam. It has a ‘Difference’ text panel that compares the displaced volume before and after the solver. Appears to be 1.01 or less, which is 1% ? That’s 3.6 cubic feet or 231 pounds in this case, which is not quite as accurate as I would like but it’s in the ball park. Better when the boat is rolled. ‘No Torque’ solver remains unstable. Both solvers run for a long time.

Not sure what I can do to improve accuracy? Improve the mesh? Adjust ‘Threshold’, ‘Tolerance’, ‘Damping’ and/or ‘Iterations’ ?

Hydrostatics_2023Mar11a.gh (263.6 KB)

1 Like

Hard topic, I hope you find the solution :hand_with_index_finger_and_thumb_crossed:
The only thing I just saw right now is that the mesh coming out seems to have pretty big triangles, which COULD lead to a volume difference of about 1%. update: Just quickly baked the volume from Brep and the converted mesh from your last script and the volumes are already about 0.5% off before you make any calculations (that I don’t understand bc I’m not in the boat business at all) I guess this is why you prefer working with NURBS. I’d try and improve the mesh, even if this means heating up the room with your pc, but just to know if this causes the deviation after calculations.

But I think you should stick to your nurbs solution if it works fine, kangaroo is a optimizer, not exactly for precise calculations of this kind I think.


I think so too. I messed around with finer meshes but didn’t see any improvement in precision. It only got slower and slower to the point of being useless. My old Anemone loop is accurate to any number of decimal places (default 3), so it is very precise indeed!

I’m looking at updating the Anemone loop, perhaps using ‘Fast’ components but wow, it’s complex with two nested loops that search an arbitrary domain, written with the flexibility to solve a variety of similar search problems. I may give up on that now and focus only on floating the rolled/pitched boat.

1 Like

This isn’t really correct - Optimisation can give you answers as precise as needed (within the limits of floating point precision), provided everything is set up correctly.

To go back to my earlier point about root finding though - using Kangaroo here feels like a bit of a sledgehammer to crack a nut.

The original question is essentially a 1 dimensional search where we have a single scalar valued parameter to optimise for a single scalar output. So a root-finding algorithm is what’s needed.
What’s more, we know the plane must lie somewhere between the top and bottom of the solid, so we can use bracketing methods which can be very efficient.

The simplest of these is bisection, where you chop the search domain in half each time. For faster convergence we can use various types of interpolation instead of just halving it.
I made an example trying both Bisection and Brent-Dekker root finding:
volumeportion_rootfind.gh (57.0 KB)

Here you can see it finds the plane height to split a shape at to give an accurate volume in a few ms.

(I think this same root finding code could come in handy anywhere you have this sort of optimisation of a single value where the root lies between known bounds. Just replace the ‘SliceVolume’ class here with the thing you want to optimise for)


Thanks for the clearification. I am still learning about kangaroo, which I admit is pretty complex and I still lack of much university math knowledge. I figuered it is mostly used for cases, where many constrains come together and a perfect solution is not necessarily possible. I didn’t feel this would be the case here for the boat question.

btw, I admire your work and am very impressed of your level of knowledge about meshes and computional geometry. The more I dig into kangaroo, the more I am impressed… :star_struck:

Thanks - and you’re quite right about Kangaroo being mainly intended for more complex problems with many variables and where an algebraic or closed form solution isn’t possible.

Whenever there’s a direct and non-iterative method available it is generally preferable to use that over a numerical method, because then we don’t have to think about convergence or accuracy.

This problem of finding the plane height for splitting any solid with a given volume doesn’t have a closed form solution, so we can’t avoid using some sort of numerical method here, but because it’s a single variable this can be a simpler method with guaranteed convergence.



This is EXTREMELY IMPRESSIVE! Big thank you, Daniel (@DanielPiker).

It’s been a very long time since I did a “binary search” in a conventional language. I tried with Anemone over the weekend and failed - many times.

This is a game changer. I replaced Kangaroo with this C# code at the bottom (green group). I’ll be studying this C# code with interest. I see you are using the “Brent–Dekker method” and have commented out the “simple bisection method”. Wow. So cool. :+1: Thank you, thank you!

Hydrostatics_2023Mar13a.gh (217.2 KB)

P.S. It’s so fast that I removed the Data Dam, though might refine that further.

1 Like

I found a mysterious error when setting the roll angle to 55 degrees. Above or below that is fine.

error: Object reference not set to an instance of an object. (line: 101)

Looks like Brep booleans are failing on your solid at certain heights.
Here just the boolean part without the script:
boolean_error.gh (135.0 KB)

You can get around it by changing the tolerance
(in the script change this.RhinoDocument.ModelAbsoluteTolerance to 0.01)
but it would be good to find out why the boolean is failing

1 Like

Yes, but thanks for the work around.

In my defense… I just discovered that a so-called optimization I had done regarding the volume of split pieces was flawed! Entirely unrelated to the various Anemone algorithms I tried, but it broke them all, it worked when the boat was level but easily failed on the rolled boat. I discovered it now because I copied that same “optimization” into my hydrostatics file with your C# code, corrupting a good result.

Classic example of the hazards of messing around with working code, unrelated to the task at hand.

“Premature optimization” is a phrase used to describe a situation where a programmer lets performance considerations affect the design of a piece of code. This can result in a design that is not as clean as it could have been or code that is incorrect, because the code is complicated by the optimization and the programmer is distracted by optimizing.
Program optimization - Wikipedia

Hi this looks really great thank you… But I’m just trying to open it and study to use for my work but I’ve been getting some errors
Screenshot 2023-05-06 at 12.39.33
Screenshot 2023-05-06 at 12.39.51
Screenshot 2023-05-06 at 12.40.54
Also the object doesn’t float like in your video, it just goes right through the water. is there something I’m supposed to switch on? I’m very new to using rhino and grasshopper and it says I don’t need to install kangaroo since I’m using a rhino 7? Please help I’m not sure how to solve these problems. thank you!

Hi Daniel @DanielPiker thank you for your solution on the buoyancy element!
This is great thank you! I’ve used this example to get my object to float but can you please help show how to keep the object floating in one place? along the z-axis.

I want to float a cylinder that has a pole going through it., so the cylinder floats up and down the pole in the z axis, without tilting and falling over like it does in the file (attached).

I have tried the anchor xyz connected to the bouncy solver (after load and other have been applied) but it still doesnt work. The cylinder floats away! (which is great but not all I need sadly).
Please can you help?
Please see the screenshots and file below:

Buoyant cylinder.gh (76.0 KB)