# Emacs Lisp: stockpile.el calculates volumes of stockpiles, heaps, piles, mounds

This set of function is calculating stockpile volumes depending of sizes of piles, mounds, or heaps. Engineers may be able to dissect various parts of stockpiles and then calculate their volumes by using these functions.

We use those functions in the business consulting program Start Your Own Gold Mine that is as of 2019 provided mostly in East African countries Uganda, Rwanda, Kenya and Tanzania. Many piles and heaps of gold bearing ores are standing around and their volumes need to be calculated to estimate the profitability. Gold prospecting and sampling of the heap and accurate determination of its specific density is also used to calculate estimates of gold in such stockpiles. Yet, these Emacs Lisp functions could be used for other engineering purposes.

```
;;; stockpile.el --- Stockpile volume calculations
;; Copyright (C) 2016-2020 by Jean Louis
;; Author: Jean Louis <bugs@gnu.support>
;; Version: 1.3
;; Package-Requires: ((rcd-utilities))
;; Keywords: convenience
;; URL: https://www.startyourowngoldmine.com/
;; This file is not part of GNU Emacs.
;; This program is free software: you can redistribute it and/or
;; modify it under the terms of the GNU General Public License as
;; published by the Free Software Foundation, either version 3 of the
;; License, or (at your option) any later version.
;;
;; This program is distributed in the hope that it will be useful, but
;; WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;; General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;;
;; This program is useful to calculate volumes stock piles of sand,
;; gravel, possibly timber, bricks or other goods. It helps engineers
;; to sell the tailings
;;
;; References:
;; <https://depts.washington.edu/nwfire/piles/support/pile_proc.pdf>
;; <https://www.aqua-calc.com/calculate/volume-truncated-pyramid>
;; <https://www.calculatorsoup.com/calculators/geometry-solids/surfacearea.php#calculationImage>
;;
;; The abbreviation spv relates to Stockpile Volume
;;
;; TODO: For each stockpile shape to make SVG files.
;;; Change Log:
;; 2020-10-25 Jean Louis <bugs@gnu.support>
;;
;; * stockpile.el: improved several docstrings
;;; Code:
require 'rcd-utilities)
(
defun spv-half-sphere (height)
("Return volume for proper half-sphere stockpile.
HEIGHT represents the height or radius of the half-sphere of a
stockpile or part of stockpile. It is also known as hemisphere
shape."
let ((volume (/ (* 2 pi (expt height 3)) 3)))
(
volume))
defun spv-half-sphere-i (height)
("Return calculation for proper half-sphere stockpile interactively.
HEIGHT represents the height or radius of the half-sphere shapes
stockpile.
Message is displayed in the minibuffer and copied in memory for
easy insertion."
"nHeight of half-sphere: ")
(interactive let* ((volume (spv-half-sphere height))
(format "%.2f" volume))
(volume (format "Volume of half-sphere stockpile with height of %s m is %s ㎥." height volume)))
(message (
(kill-new message)
(message message)))
defun spv-paraboloid (height width)
("Return volume for paraboloid stockpile for WIDTH and HEIGHT."
let ((volume (/ (* pi height (expt width 2)) 8)))
(
volume))
defun spv-paraboloid-i (height width)
("Return volume for paraboloid stockpile for WIDTH and HEIGHT.
This is interactive function. A message with the calculation
statement is displayed in the minibuffer and copied in memory for
easy insertion."
"nHeight of paraboloid: \nnWidth of paraboloid: ")
(interactive let* ((volume (spv-paraboloid height width))
(format "%.2f" volume))
(volume (format "Volume of paraboloid stockpile with height of %s m and width of %s m is %s ㎥." height width volume)))
(message (
(kill-new message)
(message message)))
defun spv-half-cylinder (height width length)
("Return the volume of half-cylinder stockpile.
It requires HEIGHT, WIDTH and LENGTH of a stockpile."
let ((volume (/ (* pi height width length) 4)))
(
volume))
defun spv-half-cylinder-i (height width length)
("Return the volume of half-cylinder stockpile interactively.
It requires HEIGHT, WIDTH and LENGTH of the stockpile. A message
with the calculation statement is displayed in the minibuffer and
copied in memory for easy insertion."
"nHeight of half-cylinder: \nnWidth of half-cylinder: \nnLength of half-cylinder: ")
(interactive let* ((volume (spv-half-cylinder height width length))
(format "%.2f" volume))
(volume (format "Volume of half-cylinder stockpile with height of %s m, width of %s m and length of %s m is %s ㎥." height width length volume)))
(message (
(kill-new message)
(message message)))
defun spv-half-frustum-of-a-cone-1 (height-1 height-2 length)
("Return volume of half frustum of a cone stockpile, version 1.
Requires arguments HEIGHT-1 as first height of the stockpile,
HEIGHT-2 as second height and LENGTH of the stockpile."
let* ((heights (+ (expt height-1 2) (expt height-2 2) (* height-1 height-2)))
(/ (* pi length heights) 6)))
(volume (
volume))
defun spv-half-frustum-of-a-cone-1-i (height-1 height-2 length)
("Return volume of half frustum of a cone stockpile, version 1.
This is interactive function that will ask user for first
HEIGHT-1 and second HEIGHT-2 and LENGTH of the stockpile.
A message with the calculation statement is displayed in the
minibuffer and copied in memory for easy insertion."
"nFirst height of half-frustum of a cone: \nnSecond height of half-frustum of a cone: \nnLength of half-frustum of a cone: ")
(interactive let* ((volume (spv-half-frustum-of-a-cone-1 height-1 height-2 length))
(format "%.2f" volume))
(volume (format "Volume of half-frustum of a cone stockpile with first height of %s m, second height of %s m and length of %s m is %s ㎥." height-1 height-2 length volume)))
(message (
(kill-new message)
(message message)))
defun spv-half-frustum-of-a-cone-2 (width-1 width-2 length)
("Return volume of half frustum of a cone stockpile, version 2.
Requires arguments WIDTH-1 and WIDTH-2 with the LENGTH of the
stockpile. See references"
let* ((widths (+ (expt width-1 2) (expt width-2 2) (* width-1 width-2)))
(/ (* pi length widths) 24)))
(volume (
volume))
defun spv-half-frustum-of-a-cone-2-i (width-1 width-2 length)
("Return volume of half frustum of a cone stockpile, version 2.
It asks user for first WIDTH-1 and second WIDTH-2 with the LENGTH
of the stockpile. See references. A message with the
calculation statement is displayed in the minibuffer and copied
in memory for easy insertion."
"nFirst width of half-frustum of a cone: \nnSecond width of half-frustum of a cone: \nnLength of half-frustum of a cone: ")
(interactive let* ((volume (spv-half-frustum-of-a-cone-2 width-1 width-2 length))
(format "%.2f" volume))
(volume (format "Volume of half-frustum of a cone stockpile with first width of %s m, second width of %s m and length of %s m is %s ㎥." width-1 width-2 length volume)))
(message (
(kill-new message)
(message message)))
defun spv-half-frustum-of-a-cone-with-rounded-ends (width-1 width-2 length)
("Return volume of half frustum of a cone stockpile with rounded ends.
Requires arguments WIDTH-1 and WIDTH-2 with the LENGTH of the
stockpile."
let* ((widths (+ (expt width-1 2) (expt width-2 2) (* width-1 width-2)))
(* pi (/ (+ (* length widths) width-1 width-2) 24))))
(volume (
volume))
defun spv-half-frustum-of-a-cone-with-rounded-ends-i (width-1 width-2 length)
("Return volume of half frustum of a cone stockpile with rounded end.
The interactive function asks users for the first WIDTH-1 and
second WIDTH-2 with the LENGTH of the stockpile. A message with
the calculation statement is displayed in the minibuffer and
copied in memory for easy insertion."
"nFirst width of half-frustum of a cone with rounded ends: \nnSecond width of half-frustum of a cone with rounded ends: \nnLength of half-frustum of a cone with rounded ends: ")
(interactive let* ((volume (spv-half-frustum-of-a-cone-with-rounded-ends width-1 width-2 length))
(format "%.2f" volume))
(volume (format "Volume of half-frustum of a cone with rounded ends stockpile with first width of %s m, second width of %s m and length of %s m is %s ㎥." width-1 width-2 length volume)))
(message (
(kill-new message)
(message message)))
defun spv-half-ellipsoid (height width length)
("Return volume of half ellipsoid stockpile.
Argument HEIGHT is height of stockpile.
Argument WIDTH represents width of the stockpile.
Argument LENGTH represents length of the stockpile."
let ((volume (/ (* pi height width length) 6)))
(
volume))
defun spv-half-ellipsoid-i (height width length)
("Return calculation statement for volume of half ellipsoid stockpile.
User enters HEIGHT, WIDTH and LENGTH of the ellipsoid shaped
stockpile. A message with the calculation statement is displayed
in the minibuffer and copied in memory for easy insertion."
"nHeight of half-ellipsoid stockpile: \nnWidth of half-ellipsoid stockpile: \nnLength of half-ellipsoid stockpile: ")
(interactive let* ((volume (spv-half-ellipsoid height width length))
(format "%.2f" volume))
(volume (format "Volume of half-ellipsoid stockpile with height of %s m, width of %s m and length of %s m is %s ㎥." height width length volume)))
(message (
(kill-new message)
(message message)))
defun spv-irregular-solid (height-1 height-2 width-1 width-2 length-1 length-2)
("Return volume of irregular solid stockpil
Argument HEIGHT-1 is first height.e."
let* ((volume (/ (* (+ length-1 length-2) (+ width-1 width-2) (+ height-1 height-2)) 8)))
(
volume))
defun spv-irregular-solid-i (height-1 height-2 width-1 width-2 length-1 length-2)
("Return volume of irregular solid stockpile.
User interactively enters first HEIGHT-1 and WIDTH-1, then second
HEIGHT-2 and WIDTH-2 with LENGTH-1 and LENGTH-2.
A message with the calculation statement is displayed in the
minibuffer and copied in memory for easy insertion."
"nFirst height of irregular solid stockpile: \nnSecond height of irregular solid stockpile: \nnFirst width of irregular solid stockpile: \nnSecond width of irregular solid stockpile: \nnFirst length of irregular solid stockpile: \nnSecond length of irregular solid stockpile: ")
(interactive let* ((volume (spv-irregular-solid height-1 height-2 width-1 width-2 length-1 length-2))
(format "%.2f" volume))
(volume (format "Volume of irregular solid stockpile with first height of %s m and width of %s m, and second height of %s m and width of %s m, and first length of %s and second length of %s m is %s ㎥." height-1 width-1 height-2 width-2 length-1 length-2 volume)))
(message (
(kill-new message)
(message message)))
defun spv-truncated-pyramid (bottom-width bottom-length top-width top-length height)
("Return volume of a truncated pyramid.
Truncated pyramid or frustum of a pyramid is a pyramid whose
vertex is cut away by a plane parallel to the base. Formula
obtained from:
https://www.aqua-calc.com/calculate/volume-truncated-pyramid
Argument BOTTOM-WIDTH refers to bottom width of the stockpile."
let* ((base (* bottom-width bottom-length))
(* top-width top-length))
(top (* (/ 1 6.0) height (+ base (* (+ bottom-width top-width) (+ bottom-length top-length)) top))))
(volume (;; (volume (* (/ 1 6.0) height (+ (* bottom-width bottom-length) (* (+ bottom-width top-width) (+ bottom-length top-length)) (* top-width top-length)))))
volume))
defun spv-truncated-pyramid-i (bottom-width bottom-length top-width top-length height)
("Return volume of a truncated pyramid.
Truncated pyramid or frustum of a pyramid is a pyramid whose
vertex is cut away by a plane parallel to the base. Formula
obtained from:
https://www.aqua-calc.com/calculate/volume-truncated-pyramid.
User enters interactively BOTTOM-WIDTH, BOTTOM-LENGTH, TOP-WIDTH
and TOP-LENGTH with the HEIGHT of stockpile. A message with the
calculation statement is displayed in the minibuffer and copied
in memory for easy insertion."
"nBottom width: \nnBottom length: \nnTop width: \nnTop Length: \nnHeight: ")
(interactive let* ((volume (spv-truncated-pyramid bottom-width bottom-length top-width top-length height))
(format "%.2f" volume))
(volume (format "Volume of truncated pyramid or frustum of a pyramid with bottom width of %s m and bottom length of %s m, with top width of %s m and top length of %s m and height of %s m is %s ㎥." bottom-width bottom-length top-width top-length height volume)))
(message (
(kill-new message)
(message message)))
defun spv-conical-frustum (bottom-radius top-radius central-height)
("Return volume of a conical frustum shape.
From:
https://www.calculatorsoup.com/calculators/geometry-solids/surfacearea.php#calculationImage
Argument BOTTOM-RADIUS is radius at the bottom of the stockpile."
let ((volume (* (/ 1 3.0) pi central-height (+ (expt top-radius 2) (expt bottom-radius 2) (* bottom-radius top-radius)))))
(
volume))
defun spv-conical-frustum-i (bottom-radius top-radius central-height)
("Insert the snippet of volume calculation of of a conical frustum shape.
From:
https://www.calculatorsoup.com/calculators/geometry-solids/surfacearea.php#calculationImage
Argument BOTTOM-RADIUS is radius at the bottom of the stockpile."
"nBottom radius: \nnTop radius: \nnCentral height: ")
(interactive let* ((volume (spv-conical-frustum bottom-radius top-radius central-height))
(format "%.2f" volume))
(volume (format "Volume of conical frustum with the bottom radius being %s m, top radius being %s m and central height of %s m is %s ㎥." bottom-radius top-radius central-height volume)))
(message (
(kill-new message)
(message message)))
defun spv-cone (radius height)
("Return the volume of a cone.
From:
https://www.calculatorsoup.com/calculators/geometry-solids/volume.php
Argument RADIUS is radius at the bottom of the stockpile."
let ((volume (* (/ 1 3.0) pi (expt radius 2) height)))
(
volume))
defun spv-cone-i (radius height)
("Insert the snippet with the calculation of a cone volum
Argument RADIUS is radius at the bottom of the stockpile.e."
"nRadius of a cone: \nnHeight of a cone: ")
(interactive let* ((volume (spv-cone radius height))
(format "%.2f" volume))
(volume (format "Volume of a cone with radius of %s m and height of %s m is %s ㎥." radius height volume)))
(message (
(kill-new message)
(message message)))
defun spv-cylinder (radius height)
("Return the volume of a cylinder by using RADIUS and HEIGHT.
Argument RADIUS refers to the bottom radius of the stockpile."
let ((volume (* pi (expt radius 2) height)))
(
volume))
defun spv-cylinder-i (radius height)
("Insert the volume of a cylinder by providing its radius
and height"
"nRadius of cylinder: \nnHeight of cylinder: ")
(interactive let* ((volume (spv-cylinder radius height))
(format "%.2f" volume))
(volume (format "Volume of a cylinder with radius of %s m and height of %s m is %s ㎥." radius height volume)))
(message (
(kill-new message)
(message message)))
;;;###autoload
defun stockpile ()
("Interactively chooses one of stockpile volume calculation functions.
User interactively enters specific parameters of the selected
stockpile shape such as its widths, heights or lenghts and then
receives a message with the stockpile volume calculation.
Message is stored or killed in the temporary memory for easy
insertion or yanking into the buffer."
(interactive)let ((list '(("Halph sphere" . 'spv-half-sphere-i)
("Paraboloid" . 'spv-paraboloid-i)
("Half cylinder" . 'spv-half-cylinder-i)
("Half frustum of a cone (1)" . 'spv-half-frustum-of-a-cone-1-i)
("Half frustum of a cone (2)" . 'spv-half-frustum-of-a-cone-2-i)
("Half frustum of a cone with rounded ends" . 'spv-half-frustum-of-a-cone-with-rounded-ends-i)
("Half ellipsoid" . 'spv-half-ellipsoid-i)
("Irregular solid" . 'spv-irregular-solid-i)
("Truncated pyramid" . 'spv-truncated-pyramid-i)
("Conical frustum" . 'spv-conical-frustum-i)
("Cone" . 'spv-cone-i)
("Cylinder" . 'spv-cylinder))))
(let ((choice (caddr (assoc (completing-read "Choose stockpile formula: " list nil t) list))))
(
(call-interactively choice))))
provide 'stockpile)
(;;; stockpile.el ends here
```

Let me know if you see any error or problem with these functions.

## Leave Your Comment or Contact GNU.Support

Contact GNU.Support now. **There is a simple rule at
GNU.Support: if we can help you, we do, whenever and wherever
necessary, and it's the way we've been doing business since 2002,
and the only way we know**