You could instead simply replace the trig function implementations with versions that use degrees...
Look at the angle configuration example in the MathJS docs. You can use the math.import
function to provide your own function implementations for sin
, cos
, etc., and you can refer to the original ones by first saving a reference to them.
Here is the full example from the linked docs as runnable snippet (copyright © 2013-2021 jos de jong):
let replacements = {}
// our extended configuration options
const config = {
angles: 'deg' // 'rad', 'deg', 'grad'
}
// create trigonometric functions replacing the input depending on angle config
const fns1 = ['sin', 'cos', 'tan', 'sec', 'cot', 'csc']
fns1.forEach(function(name) {
const fn = math[name] // the original function
const fnNumber = function (x) {
// convert from configured type of angles to radians
switch (config.angles) {
case 'deg':
return fn(x / 360 * 2 * Math.PI)
case 'grad':
return fn(x / 400 * 2 * Math.PI)
default:
return fn(x)
}
}
// create a typed-function which check the input types
replacements[name] = math.typed(name, {
'number': fnNumber,
'Array | Matrix': function (x) {
return math.map(x, fnNumber)
}
})
})
// create trigonometric functions replacing the output depending on angle config
const fns2 = ['asin', 'acos', 'atan', 'atan2', 'acot', 'acsc', 'asec']
fns2.forEach(function(name) {
const fn = math[name] // the original function
const fnNumber = function (x) {
const result = fn(x)
if (typeof result === 'number') {
// convert to radians to configured type of angles
switch(config.angles) {
case 'deg': return result / 2 / Math.PI * 360
case 'grad': return result / 2 / Math.PI * 400
default: return result
}
}
return result
}
// create a typed-function which check the input types
replacements[name] = math.typed(name, {
'number': fnNumber,
'Array | Matrix': function (x) {
return math.map(x, fnNumber)
}
})
})
// import all replacements into math.js, override existing trigonometric functions
math.import(replacements, {override: true})
// pointers to the input elements
const expression = document.getElementById('expression')
const evaluate = document.getElementById('evaluate')
const result = document.getElementById('result')
const angles = document.getElementById('angles')
// attach event handlers for select box and button
angles.onchange = function () {
config.angles = this.value
config.angles = this.value
}
evaluate.onclick = function () {
result.innerHTML = math.evaluate(expression.value)
}
<script src="https://unpkg.com/mathjs@10.0.2/lib/browser/math.js"></script>
<table>
<tr>
<th>Angles</th>
<td>
<select id="angles">
<option value="deg">deg</option>
<option value="grad">grad</option>
<option value="rad">rad</option>
</select>
</td>
</tr>
<tr>
<th>Expression</th>
<td>
<input id="expression" type="text" value="sin(45)" />
<input id="evaluate" type="button" value="Evaluate">
</td>
</tr>
<tr>
<th>Result</th>
<td id="result"></td>
</tr>
</table>
EDIT: To respond to the edit in the question:
Edit: Yes I have looked at the angle configuration example. No, that doesn't solve my problem: It assumes the user is implementing a single value to calculate the sine of, I am trying to calculate full expressions with a degree mode (mathjs.evaluate())
That's not true. It doesn't assume that. The example uses math.evaluate
just as you said. It should work exactly as you need it to. The way it works is just that the new, replaced functions refer to the config.angles
value when deciding as what to interpret the input (or in case of the arcus functions, to what to convert their result before returning it).