# Optical Forums > Ophthalmic Optics >  Axis problem in oblique cross-cylinder calculation

## Wlada

Hello, I tried to make some spreadsheet where I will solve oblique cross-cylinders. I am comparing results with Crossed Cylinders Calculation Form (http://www.opticampus.com/tools/cylinders.php) and only where I failed is in orientation of resulting axis. I really tried to fix this but I can not see the right rules for that, so please help me. Here is, in pdf file, way how I done calculation. In the same example calculator on Opticampus find axis on 74 degree ("-" cylinder form) and my result is 164 (90 degrees of diff.).
Thanks in advance

----------


## MakeOptics

The ATAN function returns a value between -pi/2 to pi/2 or -90 to 90, tangent functions have a domain the cross cyl formula doubles the axis, so either check the axis while doubled to see if it falls within the domain and add 180 or divide the doubled angle and then check it, adding 90 if the axis is negative.

PS - don't use the cross cyl formula you find in books, it is a convoluted version of a lens summation which is simpler to memorize and where the cross cyl formula was derived.

MRE = Sph + Cyl/2
C000 = C * cos(2*axis)
C045 = C * sin(2*axis)

You can add the two prescriptions Mean Refractive Errors and Cylinder powers at 000 and 045 together to come up with the total power, the advantage is that you can have a series of lenses and add them all together with this simple methods rather than performing the cross cyl method on two sets of lenses then using the result to add another lens when required.

To covert back to prescription notation:

Cyl = Sqrt(C000^2 + C045^2)
Axis = tan-1(C045/C000)/2
Sph = MRE - Cyl/2

Excel provided below with logic and radians to degree and back.

----------


## Wlada

Thanks for yours reply and spreadsheet. I tested yours formulas, and for now there is a problem for axis when both cylinder are positive and when both axes are between 0-90 degree. For example: 
L1: 0,00=+10,00 ax 0 and 
L2: 0,00=+2,00 ax15 
gives 
+11,89=-11,77 ax2 
but it should be ax92.

----------


## MakeOptics

> Thanks for yours reply and spreadsheet. I tested yours formulas, and for now there is a problem for axis when both cylinder are positive and when both axes are between 0-90 degree. For example: 
> L1: 0,00=+10,00 ax 0 and 
> L2: 0,00=+2,00 ax15 
> gives 
> +11,89=-11,77 ax2 
> but it should be ax92.


I probably ignored my own advice, I'll take a peak tonight.  Thanks.

----------


## lensgrinder

Opticampus  transposes to minus cylinder form before the calculations are performed.
Your pdf is correct for both minus and plus cylinder form your result is 74 because you performed the calculations in plus cylinder.

Your exapmle Rx

0.00 +10.00 X 165
0.00 -0.50 X 5

Transpose to minus cylinder

+10.00 -10.00 X 75
0.00 -0.50 X 5

This will not change your result of -20.96 except that you will add this to 5 instead of 95

New axis is 5 + (-20.96) =  -15.96

360 + (-15.96) = 344.04 - 180 = 164.04

This is your axis in minus cylinder form.

----------


## MakeOptics

> Thanks for yours reply and spreadsheet. I tested yours formulas, and for now there is a problem for axis when both cylinder are positive and when both axes are between 0-90 degree. For example: 
> L1: 0,00=+10,00 ax 0 and 
> L2: 0,00=+2,00 ax15 
> gives 
> +11,89=-11,77 ax2 
> but it should be ax92.


Good catch, in a rush to throw an example up I skipped a step in the sheet.  The resultant cylinder is always in plus form so the axis was for the plus cyl in my calc, I didn't add 90 to it.  I updated it so you have a working example to see.

----------


## Wlada

> Good catch, in a rush to throw an example up I skipped a step in the sheet.  The resultant cylinder is always in plus form so the axis was for the plus cyl in my calc, I didn't add 90 to it.  I updated it so you have a working example to see.


Between two vectors must be resultant vector. But if I put 
L1: 0.00=+10.00 ax170 and
L2: 0.00=+1.00 ax 55
with yours spreadsheet result is
+0.81=    +9.39 ax172
Angle 172 is not between 55-170.
This is occurs when diff. between  ax L1 and ax L2 is >90.

----------


## lensgrinder

> Between two vectors must be resultant vector. But if I put 
> L1: 0.00=+10.00 ax170 and
> L2: 0.00=+1.00 ax 55
> with yours spreadsheet result is
> +0.81=    +9.39 ax172
> Angle 172 is not between 55-170.
> This is occurs when diff. between  ax L1 and ax L2 is >90.


You should not get 172.  You are adding  to axis 55, if you are keeping it in plus cylinder form.



2 X 115 = 230



Now add 23.64 to your lower axis value(55).
55+23.64 = 78.64

78.64 is your axis in plus cylinder form.

----------


## Wlada

> You should not get 172.  You are adding  to axis 55, if you are keeping it in plus cylinder form.
> 
> 
> 
> 2 X 115 = 230
> 
> 
> 
> 
> ...


Lensgrinder, you using tan_Θ_=10*sin(230)/11*cos(230)
About  lower part 11*cos(230): are you first sum C1 and C2? Becuse that is  different case and result. I found formula in text book as  C1+C2*cos2[alpha], not (C1+C2)*cos2[alpha].

----------


## Wlada

> Good catch, in a rush to throw an example up I skipped a step in the sheet.  The resultant cylinder is always in plus form so the axis was for the plus cyl in my calc, I didn't add 90 to it.  I updated it so you have a working example to see.


MakeOptics, if I have
L1: 0,00=-10,00 ax 170 and 
L2: 0,00=-1,00 ax55 
your new spreadsheet gives
-0.81=-9.39 ax82 
but Crossed Cylinders Calculation on OptiCampus gives ax172.

----------


## lensgrinder

> Lensgrinder, you using tan_Θ_=10*sin(230)/11*cos(230)
> About lower part 11*cos(230): are you first sum C1 and C2? Becuse that is different case and result. I found formula in text book as C1+C2*cos2[alpha], not (C1+C2)*cos2[alpha].


Thanks!
Sorry I was in a hurry, but this did get me to looking at MakeOptics spreadsheet.






> MakeOptics, if I have
> L1: 0,00=-10,00 ax 170 and 
> L2: 0,00=-1,00 ax55 
> your new spreadsheet gives
> -0.81=-9.39 ax82 
> but Crossed Cylinders Calculation on OptiCampus gives ax172.


According to "Ophthalmic Mechanics and Dispensing", Epting and Morgret



First - divide  by 2 and add to smaller axis
Second - subtract  from 180, divide by 2, and add to smaller axis
Third - add  to 180, divide by 2, and add to smaller axis
Fourth - subtract  from 360, divide by 2, and add to the smaller axis



Using the above logic since it is  it is in the first quadrant, you will divide 54.67 by 2  and add to 55.



Use +10.00 X 170 and +1.00 X 55


Since it is  it is in the third quadrant, you will add 54.67 to 180, divide by 2,  and add to 55.

----------


## lensgrinder

When you perform all of Thompson's formulae, it makes more sense.  I was concentrating on the axis and could not understand why it gave an axis of 82 for the minus cylinder and 172 for the plus cylinder.  I performed a Stokes Construction(attached) which shows the minus cylinder transposed to plus and where the angle bisector to C and F1 ends up in quadrant 1.



So then I performed all the calculations:

Pl -10.00 X 170
Pl -1.00 X 55





The axis from the above post is 82, so you have -10.20 + 9.39 X 82
Transposed to minus cylinder, like Opticampus, -0.81 - 9.39 X 172

Pl +10.00 X 170
Pl +1.00 X 55





The axis from the above post is 172, so you have 0.81 + 9.39 X 172
Transposed to minus cylinder, like Opticampus, 10.20 - 9.39 X 82

----------


## MakeOptics

I literally just whipped that sheet together and didnt intend for it to be a complete production calculator just an example to show how it could be coded and the algorithm simplified.

----------


## Wlada

--

----------


## Wlada

> When you perform all of Thompson's formulae, it makes more sense.  I was concentrating on the axis and could not understand why it gave an axis of 82 for the minus cylinder and 172 for the plus cylinder.  I performed a Stokes Construction(attached) which shows the minus cylinder transposed to plus and where the angle bisector to C and F1 ends up in quadrant 1.


Thanks for clarification. One question. How do you perform claculation when tang2{theta}= {some number}/{0}?

----------


## Wlada

> Swap out the atan2 function that shoulg work 360 around.  I literally just whipped that sheet together and didnt intend for it to be a complete production calculator just an example to show how it could be coded and the algorithm simplified.


The same question: what if C0 is 0?
There is some trick like if cell for C0 is 0 than put value 0.00000000000000000000000001, but this is not perfect solution...

----------


## MakeOptics

For any individual prescription that will never be the case since the angle is being doubled and then cosine of the doubled angle, their exists no cases where the result would be 0 for C000, however if the cyl is 0 then the product will be 0 in which case you have a sphere and the this could be checked for as a condition before the calculations begin.  Their may be a rare case where the results of two scripts could cause their C000 components to cancel causing a 0 result for C000, the most obvious would be oblique cyls, however adding a small value like you proposed in your post will overcome this problem and provide negligible inaccuracy to the result.  If that answer is not satisfactory, then you need to consider that floating point numbers on computers have always been inaccurate.

----------


## Wlada

Thanks for effort and clarifications. I think that I finished my work. MakeOptics, your way is much better for spreadsheet way of thinking, and yes, in yours way it can calculate more lenses then two. I introduced some changes, and I think that it works nice. I am in phase where compare this two ways of calculations with cross cyl calculator on OptiCampus, but, for now, I can not find differences. But, can you now some specific combination of lenses and axis where I can tested robustness of my spreadsheet functions?

----------


## MakeOptics

> Thanks for effort and clarifications. I think that I finished my work. MakeOptics, your way is much better for spreadsheet way of thinking, and yes, in yours way it can calculate more lenses then two. I introduced some changes, and I think that it works nice. I am in phase where compare this two ways of calculations with cross cyl calculator on OptiCampus, but, for now, I can not find differences. But, can you now some specific combination of lenses and axis where I can tested robustness of my spreadsheet functions?


Decomposition:
MRE = Sph + Cyl/2
C000 = C * cos(2*axis)
C045 = C * sin(2*axis)

Conversion:
Cyl = ±Sqrt(C000^2 + C045^2)
Axis = tan-1(C045/C000)/2
Sph = MRE - Cyl/2

The two above macro steps are the main components of the calculations, so I would look at domain and range on each component.  The only problems I see are:

Sum of C000 = Cannot be equal to zero or a division by zero error.C000 of Rx1 and C000 of Rx2 = Cannot cancel out to zero or a division by zero error.

For case 1, the cosine of any angle cannot be equal to "0", even the case of 090 in excel computes to 0.00000000000000006 because of the floating point error in computers this floating point error works in our favor since we don't need a separate case for this scenario and the inaccuracy is minuscule.

For case 2, case 2 exists because cos and sin are essentially the same function out of phase, we need to make sure that the scenario cos(x-90) doesn't exist or the possibility of the two C000 components cancelling each other out are a real possibility.  That means making sure that the two prescriptions cannot be simply added together first by transposition of one Rx or the other.

----------


## Wlada

Lensgrinder explained how to get good results in classic way, using formulas from textbooks. MakeOptics, approach what you described  (C000 and C045) also get the same results, but not for axis. I was tested and here is results, or method how to get good axis for resultant cilinder:

2Θ = tan-1(C045/C000)

If C000>0 and C045>0 then ABS(2Θ)/2
If C000<0 and C045>=0 then (360-ABS(2Θ))/2-90
If C000<0 and C045<0 then ABS(2Θ)/2+90
If C000>0 and C045<=0 then (360-ABS(2Θ))/2

----------


## MakeOptics

They are essentially the same formula presented in different ways.  Still good to learn it multiple ways so you can spot them when you see them and understand what is happening.  I had another typo in the sheets from above, fixed.

----------


## Wlada

> I had another typo in the sheets from above, fixed.


 Can you clarify?

----------


## MakeOptics

> Can you clarify?


Since the cos function in excel has a range of -pi/2 to pi/2, which is -90 to 90 and the angle was doubled I was adding 180 to the result which I thought was a way to avoid an error in reality it was adding an error.  I was overthinking the solution, instead of going with my gut.  I looked into the cos function as well and ran every integer of a real angle through excel and cos never returns a 0 so division by 0 errors won't happen in the function.

When I was in school I was deducted points on an exam for using astigmatic decomposition over Thompson's, my response was use Thompson's to subtract two obliquely crossed cylinders.  The result was I was given my points back, after a good friend in NC confirmed my answers.

----------


## Wlada

Just to summarise, and everything to be in one place:
Rules how to solve oblique crossed cylinders:
1. Do transpositions that all cylinders be in "+" form.
         For any lens do next calculation:
2. SE (spherical equivalent) = sph + cyl/2
3. C000 = C*cos(2*axis)
4. C045 = C*sin(2*axis) 
5. Sum all spherical equivalent of all lenses (SumSE)
5. Sum all C000 (SumC000)
6. Sum all C045 (SumC045)
           Resultant (r) lens:
7. CYL(r) = sqrt(C000^2 + C045^) - cylinder is always „+“
8. SPH(r) = SumSE – CYL(r)
9. AX(r) =
         2Θ = Arctang(SumC045/SumC000)
        If SumC000>0 and SumC045>0 then ABS(2Θ)/2
        If SumC000<0 and Sum C045>=0 then (360-ABS(2Θ))/2-90
        If SumC000<0 and SumC045<0 then ABS(2Θ)/2+90
        If SumC000>0 and SumC045<=0 then (360-ABS(2Θ))/2
10. If you need, do the transposition to get resultant lens with cylinders in „-“ form.

If someone want calculation in way what is described by LensGrinder, look his posts above.

Once again, Lensgrinder, MakeOptis, thanks for your time and effort.

----------


## MakeOptics

> Just to summarise, and everything to be in one place:
> Rules how to solve oblique crossed cylinders:
> 1. Do transpositions that all cylinders be in "+" form.
>          For any lens do next calculation:
> 2. SE (spherical equivalent) = sph + cyl/2
> 3. C000 = C*cos(2*axis)
> 4. C045 = C*sin(2*axis) 
> 5. Sum all spherical equivalent of all lenses (SumSE)
> 5. Sum all C000 (SumC000)
> ...



1. SE (spherical equivalent) = sph + cyl/2
2. C000 = C*cos(2*axis)
3. C045 = C*sin(2*axis) 
4. Sum all spherical equivalent of all lenses (SumSE)
5. Sum all C000 (SumC000)
6. Sum all C045 (SumC045)
Resultant (rx) lens:
7. CYL(rx) = sqrt(C000^2 + C045^2) [cylinder is always "+"]
8. SPH(rx) = SumSE – CYL(rx)/2 (subtracting the cylinder/2 out of the spherical equivalent gives the the sphere)
9. AX(rx) = Arctan(SumC045/SumC000)/2 (this is the axis not to be added to the axis)
If SumC000<0 Axis+90 (arctan only returns values from -pi/2 to pi/2 which is well within the normal bounds of a prescription except on the negative scale in which case since we divided by 2 we can add 90 only if the value is negative, every other value is valid)
10. If you need, do the transposition to get resultant lens with cylinders in "-" form.

----------


## Wlada

> 8. SPH(rx) = SumSE – CYL(rx)/2 (subtracting the cylinder/2 out of the spherical equivalent gives the the sphere)


Thanks MakeOptics, I just accidentally droped that part.



> 9. AX(rx) = Arctan(SumC045/SumC000)/2 (this is the axis not to be added to the axis)
> If SumC000<0 Axis+90 (arctan only returns  values from -pi/2 to pi/2 which is well within the normal bounds of a  prescription except on the negative scale in which case since we divided  by 2 we can add 90 only if the value is negative, every other value is  valid)


I have reserve about your way to find axis, simply it returns results which is not the same with other sources/methods. For example, for next case:
L1: 0.00=-10.00 ax88
L2: 0.00=-2.00 ax0
your way to finding axis return value -2.00=-8.01 ax*178*
I compare calculation described by Lensgrinder, Crossed cyl calculator on OptiCampus and way to find axis what I was described. All these three clculations gives the same results: -2.00=-8.01 ax*88. 
* So, I would rather to stay on my method to calculate axis, because it gives the same results  as calculator on OptiCampus and method described by Lensgrinder.
Some useful information I found here, maybe it helps.
https://sites.google.com/site/algebr...ar-coordinates

----------


## MakeOptics

I need to look at the books again, I thought I had that down, I have an error somewhere yes you are correct the axis should be closer to the 88 then the 178 due to the higher power having the most influence.

Yes vector's are what these formulas represent, good resource.

----------


## MakeOptics

Yet another method:

Convert the prescription into a power matrix and add them together then convert them back.



I will find the decomposition method again and check out where the error is, I am probably not remembering it correctly, which means time for a refresher.

Looks like the formula in my book has an error in it.  I don't have the correct version of astigmatic decomposition anymore.  I gave away my copy of a great book and my new book has a clear typo and both ways with and without the typo in the example are wrong.  That's funny I had it memorized for so long that when I went to reference now I have a gap in knowledge.  I was able to whip something up with the above formula that works well but it's in javascript which is easier for me then excel.

JSFiddle: http://jsfiddle.net/harrychiling/dx0vefop/

----------


## MakeOptics

Working backwards with a known good formula I have derived the components and they work:



Sum all the components and then decompose.

----------


## Wlada

> 


Still problem with axis. Try with
L1: 0.00=10.00 ax155
L2: 0.00=-2.00 ax0 

If I was correctly applied your formula in previous post (#29), I can't get comparable result about axis. Your formula give me +8,42=-8,85 *ax120*, but it should be *ax60*.Your approach telling me that you want to solve axis with one formula withouth _any if_ statement. But, because we deal with polar circle, there is 4 quadrants, and for 4 quadrants you need different 4 _if_ statements how to do calculation for every particular case. Lensgrinder also showed that we must consider what quadrant is about. Combination of positive or negative value of x and y give us that feedback (in arctan(y/x)). Consider SumC000 as X value, and SumC045 as Y value which telling us what are xy-coordinates, and that is the key. 
I quadrant: +x,+y
II quadrant: -x,+y
III quadrant: -x,-y
IV quadrant: +x,-y
(look internet page with my link in post #26).

Also look here: http://www.opticampus.com/files/intr...mic_optics.pdf page 116 and especialy page 117, on the top.

----------


## MakeOptics

> Still problem with axis. Try with
> L1: 0.00=10.00 ax155
> L2: 0.00=-2.00 ax0 
> 
> If I was correctly applied your formula in previous post (#29), I can't get comparable result about axis. Your formula give me +8,42=-8,85 *ax120*, but it should be *ax60*.*Your approach telling me that you want to solve axis with one formula withouth any if statement. But, because we deal with polar circle, there is 4 quadrants, and for 4 quadrants you need different 4 if statements how to do calculation for every particular case.* Lensgrinder also showed that we must consider what quadrant is about. Combination of positive or negative value of x and y give us that feedback (in arctan(y/x)). Consider SumC000 as X value, and SumC045 as Y value which telling us what are xy-coordinates, and that is the key. 
> I quadrant: +x,+y
> II quadrant: -x,+y
> III quadrant: -x,-y
> IV quadrant: +x,-y
> ...


Yes, I know the commonly available formula's but there is a method to remove the if statements.  I think I have found it, the original formula substituting ATAN(C045/C000) with ATAN2(C045,C000), this changes the constrints from -pi/2 to pi/2 to pi to -pi.  Then the only if statement necessary is the one to check if it is a negative value which would then have 180 applied to it.

Sorry for the many post and different formula's but I am trying to rework the formula to program easier, that is my goal.

----------


## MakeOptics

> Still problem with axis. Try with
> L1: 0.00=10.00 ax155
> L2: 0.00=-2.00 ax0 
> 
> If I was correctly applied your formula in previous post (#29), I can't get comparable result about axis. Your formula give me +8,42=-8,85 *ax120*, but it should be *ax60*.Your approach telling me that you want to solve axis with one formula withouth _any if_ statement. But, because we deal with polar circle, there is 4 quadrants, and for 4 quadrants you need different 4 _if_ statements how to do calculation for every particular case. Lensgrinder also showed that we must consider what quadrant is about. Combination of positive or negative value of x and y give us that feedback (in arctan(y/x)). Consider SumC000 as X value, and SumC045 as Y value which telling us what are xy-coordinates, and that is the key. 
> I quadrant: +x,+y
> II quadrant: -x,+y
> III quadrant: -x,-y
> IV quadrant: +x,-y
> ...


Thank you for your vigilance in error checking, I mentioned previously the atan2 function and the constraints of the atan function in many programming languages.  It didn't click until this post that I wasn't using it.  I ran a truth table to show that each (x,y) scenario outputs a unique variable thus giving accurate results.  The original formula is correct, but to translate it to a computer was where I kept failing.  I learned a lot from this thread.  Here is a picture of the truth table and the results.

----------


## Wlada

Yes your formula works. Nice way to avoid divide-by-zero error.
Wow, now we have a plenty formulas for the same job! But, your last is the shorter. Thanks, I also learn a lot.

----------


## MakeOptics

> Yes your formula works. Nice way to avoid divide-by-zero error.
> Wow, now we have a plenty formulas for the same job! But, your last is the shorter. Thanks, I also learn a lot.


I have been trying a new challenge with these types of formulas, try to fit a calculator into a tweet.  I have this one down to a little under two tweets.



```
javascript:m=Math,a=0,b=-10,c=88,e=0,f=-2,g=0;function r(x){return x*m.PI/180};h=a+b/2+e+f/2;i=b*m.cos(r(2*c))+f*m.cos(r(2*g));j=b*m.sin(r(2*c))+f*m.sin(r(2*g));k=m.sqrt(m.pow(i,2)+m.pow(j,2));l=h-k/2;m=(m.atan2(j,i)/2)*180/m.PI;m=(m<0)?m+180:m;alert("S:"+l+"C:"+k+"A:"+m);
```

----------


## Wlada

> try to fit a calculator into a tweet


How? What language it is? I know something to do only in BASIC in OpenOffice.

----------


## MakeOptics

javascript, it can be done in basic very simply as well.  If you copy the code, then delete the location in your browser then paste it should put up a prompt of an example you gave earlier.

----------


## Wlada

> Yes, I know the commonly available formula's but there is a method to remove the if statements.  I think I have found it, the original formula substituting ATAN(C045/C000) with ATAN2(C045,C000)


The truth is that atan2 has inside this if statements, so it is easier for user to deal with this function (if we talking about atan2 function in spreadsheet).
https://en.wikipedia.org/wiki/Atan2

----------


## Wlada

> javascript, it can be done in basic very simply as well.  If you copy the code, then delete the location in your browser then paste it should put up a prompt of an example you gave earlier.


Ok, I think I figure. I will tell you what I done. I must refresh my memory about HTML, CSS...

----------

