Last active
July 1, 2021 16:06
-
-
Save zyocum/cb13369a9ea26dcab4b277d9fb1791d0 to your computer and use it in GitHub Desktop.
surface_area_of_cup
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<meta charset="utf-8" emacsmode="-*- markdown -*"> | |
**Surface Area of a Cup with a Straight Outer Edge** | |
Let's say our cup is defined by the following parameters: | |
\begin{align*} | |
r=\,&\text{radius of the top of the cup}\\ | |
b=\,&\text{height of the cup}\\ | |
B=\,&\text{angle of the sloped side of the cup}\\ | |
\end{align*} | |
********************* | |
* B_____C_____* | |
* ┌ \ | /* | |
* │ c\ |b / * | |
* h│ \__|__/ * | |
* │ ┌ \ | * | |
* │ y│ d\| * | |
* └ └ | * | |
* └─┘A * | |
* x * | |
* └─────┘ * | |
* r * | |
* * | |
********************* | |
\begin{align*} | |
A=\,&\text{the angle at the tip of the cone that subsumes our cup}\\ | |
C=\,&\text{the remaining 90 degree angle of our triangle ABC}\\ | |
b=\,&\text{the height of the cup}\\ | |
c=\,&\text{the length of the sloped outer edge of the cup}\\ | |
h=\,&\text{the height of the extended cone}\\ | |
x=\,&\text{the radius of the bottom of the cup}\\ | |
y=\,&h - b\\ | |
\end{align*} | |
From the cross section of half the cup above, there is another triangle we can derive that shares the angle $B$, and has base $r-x$: | |
*********** | |
* * | |
* B'_____C* | |
* ┌|\ |* | |
*b│|c\ |* | |
* └|__\__|* | |
* * | |
* └───┴─┘* | |
* r-x x * | |
* └─────┘* | |
* r * | |
*********** | |
Let's call the outside angle $B'$ the angle that sums to $90\degrees$ with $B$: | |
\begin{align*} | |
B' = A = \,& 90\degrees - B\\ | |
-> \tan{\left(B'\right)} =\,& {{\left(r - x\right)}\over{}b}\\ | |
-> x =\,& -1 \cdot \left(b \cdot \tan{\left( 90\degrees - B \right)} - r\right)\\ | |
-> x =\,& - \left(b \cdot \tan{\left( 90\degrees - B \right)}\right) + r | |
\end{align*} | |
So, we've defined $x$ in terms of $b$, $B$, and $r$ which are the parameters we used to define our cup originally. | |
************* | |
* * | |
* B'_____C * | |
* ┌|\ |┐ * | |
*b│|c\ |│ * | |
* ├|__\__|│ * | |
* │ \ |│h* | |
*y│ d\|│ * | |
* └ |┘ * | |
* └───┴─┘A * | |
* r-x x * | |
* └─────┘ * | |
* r * | |
************* | |
Next we want to derive $h$ which, along with $r$, defines the cone that subsumes the cup. | |
We know $c$ now due to Pythagoras' Theorem: | |
\begin{align*} | |
c^{2} =\,& \left(r-x\right)^{2} + b^{2}\\ | |
c =\,& \sqrt{\left(r-x\right)^{2} + b^{2}}\\ | |
\end{align*} | |
Note that in case $x \leq 0$, then you don't really have a cup, you just have a cone. | |
************ | |
* * | |
* B_____C * | |
* \ |┐ * | |
* \ |│ * | |
* c\ |│ * | |
* \ |│h* | |
* \|│ * | |
* |┘ * | |
* └─────┘A * | |
* r * | |
************ | |
In that case, $h$ can be computed in terms of $r$ and $B$ alone: | |
\begin{align*} | |
\tan\left(B\right) =\,& {{h}\over{r}}\\ | |
h =\,& \tan\left(B\right) \cdot r | |
\end{align*} | |
Otherwise, when $x > 0$, we can derive $d$: | |
\begin{align*} | |
\csc\left(A\right) =\,& {{d}\over{x}}\\ | |
-> {{1}\over{\cos\left(A\right)}}=\,& {{d}\over{x}}\\ | |
-> d =\,& {{x}\over{\cos\left(A\right)}}\\ | |
\end{align*} | |
We know $A$ from above, so: | |
\begin{align*} | |
-> d =\,& {{x}\over{\cos\left(90\degrees - B\right)}}\\ | |
-> d =\,& {{-\left(b \cdot \tan{\left( 90\degrees - B \right)}\right) + r}\over{\cos\left(90\degrees - B\right)}}\\ | |
\end{align*} | |
And from Pythagoras' Theorem, again, we can derive $h$: | |
\begin{align*} | |
h^{2} =\,& \left({c+d}\right)^{2}+x^{2}\\ | |
-> h =\,& \sqrt{\left({c+d}\right)^{2}+x^{2}}\\ | |
-> h =\,& \sqrt{\left({{\sqrt{\left(r-\left({-\left(b \cdot \tan{\left( 90\degrees - B \right)}\right) + r}\right)\right)^{2} + b^{2}}}+{{{-\left(b \cdot \tan{\left( 90\degrees - B \right)}\right) + r}\over{\cos\left(90\degrees - B\right)}}}}\right)^{2}+\left({-\left(b \cdot \tan{\left( 90\degrees - B \right)}\right) + r}\right)^{2}}\\ | |
\end{align*} | |
Now that we have $h$, we can compute the cup's surface area by subtracting the surface area of the cone defining the tip that extends beyond the base (whose triangle cross section has hypotenuse $d$) from the subsuming cone (whose triangle cross section has hypotenuse $d+c$): | |
\begin{align*} | |
\text{subsuming cone surface area}=\,& \pi r \sqrt{r^{2} + h^{2}}\\ | |
\text{tip cone surface area}=\,& \pi x \sqrt{x^{2} + y^{2}}\\ | |
\text{cup surface area}=\,& \left(\pi r \sqrt{r^{2} + h^{2}}\right) - \left(\pi x \sqrt{x^{2} + y^{2}}\right) | |
\end{align*} | |
<!-- Markdeep: --><style class="fallback">body{visibility:hidden;white-space:pre;font-family:monospace}</style><script type="text/javascript" nonce="73ff92345fb24880b2768041be8" src="//local.adguard.org?ts=1625089155390&type=content-script&dmn=casual-effects.com&app=com.apple.SafariTechnologyPreview&css=1&js=1&gcss=1&rel=1&rji=1&sbe=0&stealth=1&uag=&trref=aHR0cHM6Ly9jYXN1YWwtZWZmZWN0cy5jb20v"></script> | |
<script type="text/javascript" nonce="73ff92345fb24880b2768041be8" src="//local.adguard.org?ts=1625089155390&name=Web%20of%20Trust&name=AdGuard%20Popup%20Blocker&name=AdGuard%20Extra&type=user-script"></script><script src="markdeep.min.js" charset="utf-8"></script><script src="https://morgan3d.github.io/markdeep/latest/markdeep.min.js?" charset="utf-8"></script><script>window.alreadyProcessedMarkdeep||(document.body.style.visibility="visible")</script> | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
import math | |
import sys | |
def cone_surface_area(radius, height): | |
"""Compute the surface area of a cone defined by two parameters: | |
radius: the radius of the base of the cone | |
height: the height of the cone | |
""" | |
return math.pi * radius * math.sqrt((radius ** 2) + (height ** 2)) | |
def cylinder_surface_area(radius, height): | |
"""Compute the surface area of a cylinder defined by two parameters: | |
radius: the radius of the base of the cylinder | |
height: the height of the cylinder | |
""" | |
return 2 * math.pi * radius * height | |
def cup_surface_area(radius, height, angle, verbose=False): | |
"""Compute the surface area of a cup defined by three parameters: | |
radius: the radius of the top of the cup | |
height: the height of the cup | |
angle: the angle between the top of the cup and the sloped edge (in radians) | |
""" | |
A = (math.pi / 2) - angle | |
x = -(height * math.tan(A)) + radius | |
b = (radius - x) / math.tan(A) | |
c = math.sqrt(((radius - x) ** 2) + (b ** 2)) | |
d = x / math.cos(A) | |
y = math.sqrt((d ** 2) + (x ** 2)) | |
subsuming_cone_height = math.sqrt(((c + d) ** 2) + (x ** 2)) | |
subsuming_cone_surface_area = cone_surface_area(radius, subsuming_cone_height) | |
tip_cone_surface_area = cone_surface_area(x, y) | |
if verbose: | |
print( | |
f'A={A}', | |
f'x={x}', | |
f'b={b}', | |
f'c={c}', | |
f'd={d}', | |
f'y={y}', | |
f'subsuming_cone_height={subsuming_cone_height}', | |
f'subsuming_cone_surface_area={subsuming_cone_surface_area}', | |
f'tip_cone_surface_area={tip_cone_surface_area}', | |
sep='\n' | |
) | |
if x <= 0: # in case x is not positive, you have a cone, not a cup | |
print( | |
'FYI: based on the radius, angle, and height, this cup is actually a cone', | |
file=sys.stderr | |
) | |
return cone_surface_area(radius, math.tan(angle) * radius) | |
return subsuming_cone_surface_area - tip_cone_surface_area | |
if __name__ == '__main__': | |
import argparse | |
def angle(value): | |
value = float(value) | |
if (value < 0) or (value >= 90): | |
raise argparse.ArgumentError(f'angle must be between 0 and 90 degrees') | |
return math.radians(value) | |
parser = argparse.ArgumentParser( | |
formatter_class=argparse.ArgumentDefaultsHelpFormatter, | |
description=__doc__ | |
) | |
parser.add_argument( | |
'--radius', | |
type=float, | |
required=True, | |
help='cup radius', | |
) | |
parser.add_argument( | |
'--height', | |
type=float, | |
help='cup height' | |
) | |
parser.add_argument( | |
'--angle', | |
type=angle, | |
required=True, | |
help='cup angle (in degrees)' | |
) | |
parser.add_argument( | |
'-v', '--verbose', | |
action='store_true', | |
help='print verbose output', | |
) | |
args = parser.parse_args() | |
cup = args.radius, args.height, args.angle | |
print( | |
f'''A cup with ...''', | |
f'radius={args.radius}', | |
f'height={args.height}', | |
f'angle={math.degrees(args.angle):0.3f} degrees ({args.angle:0.3f} radians)', | |
f'... has surface area of: {cup_surface_area(*cup, verbose=args.verbose)}', | |
sep='\n' | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment