Search code examples
javascriptcssmathsvganalytics

Calculating volume of area within SVG element


Given an SVG such as this fish bowl, I'm trying to calculate the volume of the area defined in pink as a percentage of the area between the "fill level" and "empty level".

I can't do a a simple percentage from top to bottom, as the fish bowl is irregularly shaped, and this will throw off the calculation by at least a few percentage points. I need to do this for many fish bowls of different shapes, so an algorithm is needed to determine the volume of each bowl.

Is there any way I can do this with javascript on an SVG element, and if so, is there any way I can go about figuring this out within element areas as a percentage?

enter image description here

Update: Uploaded sample SVG to jsfiddle


Solution

  • First you need to parse the SVG path to lines. Since they all don't cross the Y axis, this reduces to finding the area under the curve caused by the fish bowl, also known as the integral.

    Let {x_0, x_1, ..., x_n} be the absolute value of the X coordinates of the line segments.

    The function representing the graph of the fishbowl is the piecewise function:

    f(x) = 
     { (x - x_0)/(x_1 - x_0) if x_0 <= x < x_1
     { (x - x_1)/(x_2 - x_1) if x_1 <= x < x_2
     {  ... 
     { (x - x_(n-1))/(x_n - x_(n-1)) if x_(n-1) <= x < x_(n)
    

    Then the volume of the fishbowl equals the integral of πf(x)2 (the solid of revolution formed by that function).

    Let e be the empty level, v the fill level, and w the water level.

    Then the ratio of the filled portion of the fishbowl is:

    (∫ew πf(x)2 dx) / (∫ev πf(x)2 dx)

    If instead your fishbowl is generated by the graph of a function, use that function as f(x) and then calculate the integral given above.

    An integral can be approximated using numerical integration techniques such as Simpson's rule or a Newton-Cotes method.