mourner / suncalc

A tiny JavaScript library for calculating sun/moon positions and phases.
BSD 2-Clause "Simplified" License
3.1k stars 417 forks source link

Adding sun position for mid-afternoon #28

Closed acamarata closed 10 years ago

acamarata commented 10 years ago

Thanks for the great module. I am looking at the different results that come in the calculation and wished to add one data point. Is it possible to know the time when the sun would create a shadow of equal height as the object it's self (example: a 1 meter tall stick in the ground creates a 1 meter long shadow)?

acamarata commented 10 years ago

I would also like to know if it is possible to get when the shadow would be double, though that is less important. I am looking at all the data available currently and have a formula from another site but am unsure of the accuracy.

mourner commented 10 years ago

Shadow will be equal object height when the sun is 45 degrees above the horizon.

SunCalc.addTime(45, 'midAfternoon', '45BelowHorizon');

For shadow double the height, the angle will be:

var deg = Math.atan2(2, 1) * 180 / Math.PI; // ~63 degrees

You can get similar calculations for any shadow height proportion.

acamarata commented 10 years ago

When I use "deg" or even manually 63 in the addTime function I am getting "midAfternoon: Invalid Date" in my debugging as it's value.

mourner commented 10 years ago

This probably means that the sun never reaches 63 degrees on that particular day. I should probably change Invalid Date to null or undefined.

acamarata commented 10 years ago

Got it, though there is always a point between noon when your shadow is same as your height and when it is double your height. I can eyeball verify for my own location but wanted a global formula if manual angles aren't always good. I'll review the formula on another site myself but if you have any suggestions let me know.

mourner commented 10 years ago

Small mistake (63 is half height), double height is actually this:

Math.atan2(1, 2) * 180 / Math.PI; // ~26.6 degrees

there is always a point between noon when your shadow is same as your height

No. E.g. at winter in most places, the sun never rises high enough — it's near the horizon so shadows are always long. There are even places on earth where it never rises (polar night), so no shadows for months.

acamarata commented 10 years ago

Yes agreed (on the winter angles), but I am also testing using coordinates near the equator at the moment. Thank you for looking at that as I hadn't noticed that yet.

acamarata commented 10 years ago

Thank you immensely for your previous responses they have helped a ton. Hopefully this is the last question on this subject. I understand 45 degrees will give you when the shadow is exactly the height of the object (and it works perfect)... but is there a way to factor in the height of an object's shadow at solar noon into the equation? So x = the height of the object and y = the object's shadow at solar noon. I would want to be able to find when the objects shadow would be x+y and also 2x+y.

Example: We have a 50cm tall object. At solar noon it has a shadow of 10cm. How would we calculate the time when it's shadow would be 60cm (and alternatively 110cm).

mourner commented 10 years ago

You just calculate the angle height of the sun at solar noon, then use Math.atan(Math.tan(noonHeight) / multiplier) as a new angle.

mourner commented 10 years ago

@alisalaah first get the time of solarNoon, then get position of the sun at that time.

acamarata commented 10 years ago

Working on that now, thank you!

acamarata commented 10 years ago

solarNoon = Object {azimuth: 3.1382031564893658, altitude: 1.0950852659916888}

I was getting the shadow as 1x and 2x it's height with:

SunCalc.addTime(45, 'midMorning', 'midAfternoon'); // Math.atan2(1, 1) * 180 / Math.PI SunCalc.addTime(26.565, 'dblMorning', 'dblAfternoon'); // Math.atan2(1, 2) * 180 / Math.PI

So should I do:

var angle = 45 / Math.atan(Math.tan(1.0950852659916888) / 1); // 41.09269058537542 SunCalc.addTime(angle, 'midMorning', 'midAfternoon'); // shadow = noonShadow + objectHeight??

The time I got back for "midAfternoon" did not seem correct.

mourner commented 10 years ago

No. If you read what is tangens, how to convert radians into degrees, and work out some geometric calculations on paper, I'm sure you'll get it right.

acamarata commented 10 years ago

var noonAlt = 1.0950852659916888; var noonAzi = 3.1382031564893658;

// One var angle = Math.atan(Math.tan(noonAlt) / noonAzi) * 57.2957795; // 31.73840584365187 SunCalc.addTime(angle, 'midMorning', 'midAfternoon'); // 15:30:40

// Two var angle = Math.atan2((Math.tan(noonAlt) / noonAzi), 1) * 180 / Math.PI; 31.738405850898687 SunCalc.addTime(angle, 'midMorning', 'midAfternoon'); // 15:30:40

// Both came back as 15:30:40 while I was expecting around 15:22 from other calculators. It seems correct (maybe they're wrong?) to the best of my efforts. Can you confirm if the above was done correctly?

acamarata commented 10 years ago

@mourner I'm stuck on understanding what the "multiplier" is?

acamarata commented 10 years ago

I really was hoping to get this without asking you but if you could please help me figure this out. I've been looking at sites about calculating altitudes to sun angles and can't figure this out. Every formula or values I tried to put in for the last couple days seemed to not even get me close. I'm truly perplexed how to get the following angles to then use in SunCalc.addTime():

A1 :: shadow = shadowHeightAtNoon + objectHeight A2 :: shadow = shadowHeightAtNoon + objectHeight*2

From your calculator I can easily get noon, 45° (shadow equal = objectHeight), and sunset.

azimuth: 3.1379236906897656, altitude: 1.1080261016193622; // 12:00:56 - solarNoon - ~63.49° azimuth: 2.2159473525072393, altitude: 0.7842224401817359; // 14:28:56 - shadowEq - 45° azimuth: 1.9263552130558472, altitude: -0.0067263194645334; // 17:53:02 - sunsetStart - 0°

But then I used someone else's calculator to get the time of A1 and A2 the getPosition() on that below:

azimuth: 2.0853253931728837, altitude: 0.5888123941932467; // 15:22:40 - A1 - ~33.74° azimuth: 2.0032257896634356, altitude: 0.3800253454558505; // 16:16:41 - A2 - ~21.77°

So I want to be able to get 33.75 and 21.79 some how from the solarNoon data but none of the formulas I tried basing on your last advice could get me near those angles. Thank you for your help and time if you can spare it.. I've been smashing my head against the wall for awhile now on this.

Note: I understand how to get the angle of A1 and A2 with the above altitude by * 180/PI - but I only got the above altitude value after using the other calculator to get the DateTime first... I can not get those values working from the information I get from your calculator solely.

acamarata commented 10 years ago

@mourner I figured this out today after spinning my wheels. Thank you so much for your original formula as it got me to where I wanted to be only I had to figure out the details. My initial testing seems that this is correct but I haven't tested all locations yet.

var a1 = ( Math.atan( 1 / ( 1 / Math.tan(noon['altitude']) + 1 ) ) ) * 180/Math.PI; var a2 = ( Math.atan( 1 / ( 1 / Math.tan(noon['altitude']) + 2 ) ) ) * 180/Math.PI;