Skip to content

Commit

Permalink
Merge branch 'main' into 188007060-deployment
Browse files Browse the repository at this point in the history
  • Loading branch information
pjanik committed Aug 7, 2024
2 parents 3c551a6 + 14287ff commit 110c94e
Show file tree
Hide file tree
Showing 15 changed files with 173 additions and 14,407 deletions.
14,373 changes: 7 additions & 14,366 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@
},
"dependencies": {
"@types/tz-lookup": "^6.1.2",
"astronomy-engine": "^2.1.19",
"clsx": "^2.1.1",
"dayjs": "^1.11.12",
"eventemitter2": "^6.4.9",
Expand Down
6 changes: 3 additions & 3 deletions src/assets/scss/location-tab.scss
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,13 @@
gap: 3px;

li.token {
padding: 6px 20px;
padding: 6px 12px;
border-radius: 20px;
cursor: pointer;
transition: background-color 0.3s, color 0.3s;
background-color: white;
list-style: none;
margin:4px;
margin:3px;

&.on {
background-color: $codap-teal-lightest;
Expand All @@ -70,7 +70,7 @@
&.off {
background-color: white;
color: #aaa;
border: 1px solid silver;
border: 1px solid $codap-teal;
}
}
}
Expand Down
18 changes: 10 additions & 8 deletions src/components/location-tab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -121,14 +121,16 @@ export const LocationTab: React.FC<LocationTabProps> = ({
<label>Attributes</label>
<ul className="attribute-tokens">
{ kChildCollectionAttributes.map((attr: any, i: number) => (
<li
key={i}
className={`token ${selectedAttrs.includes(attr.name) ? "on" : "off"}`}
onClick={() => handleTokenClick(attr.name)}
>
{ attr.title }
</li>
)) }
attr.hasToken && (
<li
key={i}
className={`token ${selectedAttrs.includes(attr.name) ? "on" : "off"}`}
onClick={() => handleTokenClick(attr.name)}
>
{ attr.title }
</li>
)))
}
</ul>
</div>
<div className="plugin-row data-buttons">
Expand Down
46 changes: 37 additions & 9 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ export const kSimulationTabDimensions = {
height: 630
};

// These are only used in the simplified sunray angle calc
// solstice dates in season calc are based on astronomy-engine Seasons()
export const kBasicSummerSolstice = 172;
export const kEarthTilt = 23.5;

export const kGeonamesService = "https://secure.geonames.org/search";
export const kGeolocService = "https://secure.geonames.org/findNearbyPlaceNameJSON";
export const kGeonamesUser = "codap";
Expand Down Expand Up @@ -40,27 +45,50 @@ export const kChildCollectionAttributes = [
{
name: "date",
title: "Date",
type: "date"
type: "date",
hasToken: true
},
{
name: "dayLength",
title: "Day Length",
type: "numeric",
hasToken: true
},
{
name: "sunrise",
title: "Sunrise",
type: "date"
type: "date",
hasToken: true
},
{
name: "sunset",
title: "Sunset",
type: "date"
},
{
name: "dayLength",
title: "Day Length",
type: "numeric"
type: "date",
hasToken: true
},
{
name: "dayNumber",
title: "Day Number",
type: "numeric"
type: "numeric",
hasToken: false
},
{
name: "sunlightAngle",
title: "Sunlight Angle",
type: "numeric",
hasToken: true
},
{
name: "solarIntensity",
title: "Solar Intensity",
type: "numeric",
hasToken: true
},
{
name: "season",
title: "Season",
type: "categorical",
hasToken: true
}
];

Expand Down
11 changes: 6 additions & 5 deletions src/grasp-seasons/3d-views/ground-rays-view.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import $ from "jquery";
import { sunrayAngle } from "../utils/solar-system-data";
import { colorInterpolation } from "../utils/utils";
import { kEarthTilt } from "../../constants";
import { getSunrayAngleInDegrees } from "../../utils/daylight-utils";

const DEG_2_RAD = Math.PI / 180;

Expand Down Expand Up @@ -75,7 +76,7 @@ export default class {
}

get solarAngle() {
return sunrayAngle(this.props.day, this.props.earthTilt, this.props.lat) * DEG_2_RAD;
return getSunrayAngleInDegrees(this.props.day, this.props.earthTilt ? kEarthTilt : 0, this.props.lat) * DEG_2_RAD;
}

get polarNight() {
Expand Down Expand Up @@ -109,7 +110,7 @@ export default class {
this.ctx.save();
this.ctx.translate(x, skyHeight);
this.drawLine(lineRotationRadians, 5, maxLength);
this.drawArrow(lineRotationRadians);
this.drawArrow(lineRotationRadians, 0.7, 0.7);
this.ctx.restore();
}
}
Expand Down Expand Up @@ -174,7 +175,7 @@ export default class {

drawLine(angle: any, lengthAdjustment: any, length: any) {
this.ctx.save();
this.ctx.lineWidth = 4;
this.ctx.lineWidth = 2;
this.ctx.rotate(angle);
this.ctx.beginPath();
this.ctx.moveTo(0, -lengthAdjustment);
Expand All @@ -191,7 +192,7 @@ export default class {
this.ctx.beginPath();
this.ctx.moveTo(0, 0);
this.ctx.lineTo(-10, -20);
this.ctx.lineTo(0, -16);
this.ctx.lineTo(0, -20);
this.ctx.lineTo(10, -20);
this.ctx.lineTo(0, 0);
this.ctx.fill();
Expand Down
13 changes: 13 additions & 0 deletions src/grasp-seasons/components/seasons.scss
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ body {

.right-col {
width: 280px;
position: relative;
}

.left-col, .right-col {
Expand Down Expand Up @@ -54,6 +55,18 @@ body {
margin-bottom: 5px;
}

.sunlight-at-noon {
position: absolute;
top: 36px;
width: 126px;
height: 24px;
border-radius: 12px;
background-color: rgba(255, 255, 255, 0.7);
display: flex;
align-items: center;
justify-content: center;
}

.ground-view {
width: 252px;
height: 115px;
Expand Down
4 changes: 3 additions & 1 deletion src/grasp-seasons/components/seasons.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { useState, useEffect, useRef, ChangeEvent, useCallback } from "react";
import Slider from "./slider/slider";
import { getSolarNoonIntensity } from "../../utils/daylight-utils";
import InfiniteDaySlider from "./slider/infinite-day-slider";
import CitySelect from "./city-select";
import getURLParam from "../utils/utils";
Expand Down Expand Up @@ -159,7 +160,7 @@ const Seasons: React.FC<IProps> = ({ lang = "en_us", initialState = {}, log = (a
});
};

const solarIntensityValue = 123; // TODO: Calculate solar intensity using lat, long, and time
const solarIntensityValue = getSolarNoonIntensity(simState.day, simState.lat).toFixed(2);

return (
<div className="grasp-seasons">
Expand Down Expand Up @@ -206,6 +207,7 @@ const Seasons: React.FC<IProps> = ({ lang = "en_us", initialState = {}, log = (a
<div className="ground-view">
<RaysViewComp type="ground" simulation={simState} onSimStateChange={handleSimStateChange} />
</div>
<div className="sunlight-at-noon">{ t("~SUNLIGHT_AT_NOON", simLang) }</div>
<div className="solar-intensity">
<label>{ t("~SOLAR_INTENSITY", simLang) }: </label>
{ solarIntensityValue } { t("~SOLAR_INTENSITY_UNIT", simLang) }
Expand Down
2 changes: 1 addition & 1 deletion src/grasp-seasons/translation/en-us.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export default {

// Day Length Plugin
"~GROUND_VIEW": "Ground View",
"~SUNLIGHT_AT_NOOT": "Sunlight at Noon",
"~SUNLIGHT_AT_NOON": "Sunlight at Noon",
"~SOLAR_INTENSITY": "Solar Intensity",
"~SOLAR_INTENSITY_UNIT": "Watts/m²",
"~MY_LOCATIONS": "My Locations",
Expand Down
2 changes: 1 addition & 1 deletion src/grasp-seasons/translation/es-es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export default {

// Day Length Plugin
"~GROUND_VIEW": "Vista del suelo",
"~SUNLIGHT_AT_NOOT": "Luz solar al mediodía",
"~SUNLIGHT_AT_NOON": "Luz solar al mediodía",
"~SOLAR_INTENSITY": "Intensidad solar",
"~SOLAR_INTENSITY_UNIT": "Vatios/m²",
"~MY_LOCATIONS": "Mis localizaciones",
Expand Down
22 changes: 12 additions & 10 deletions src/grasp-seasons/utils/solar-system-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,18 @@ export function earthEllipseLocationByDay(day: any) {
return new THREE.Vector3(x, 0, z);
}

export function sunrayAngle(day: number, earthTilt: number, lat: number) {
// Angle of tilt axis, looked at from above (i.e., projected onto xy plane).
// June solstice = 0, September equinox = pi/2, December solstice = pi, March equinox = 3pi/2.
const tiltAxisZRadians = 2 * Math.PI * (day - SUMMER_SOLSTICE) / 365;
// How much is a given latitude tilted up (+) or down (-) toward the ecliptic?
// -23.5 degrees on June solstice, 0 degrees at equinoxes, +23.5 degrees on December solstice.
const orbitalTiltDegrees = earthTilt ? EARTH_TILT * RAD_2_DEG : 0;
const effectiveTiltDegrees = -Math.cos(tiltAxisZRadians) * orbitalTiltDegrees;
return 90 - (lat + effectiveTiltDegrees);
}
// Use `getSunrayAngleInDegrees` from src/utils/daylight-utils.ts instead so we guarantee the same result in the
// ground view and in the calculated values in the CODAP table.
// export function sunrayAngle(day: number, earthTilt: number, lat: number) {
// // Angle of tilt axis, looked at from above (i.e., projected onto xy plane).
// // June solstice = 0, September equinox = pi/2, December solstice = pi, March equinox = 3pi/2.
// const tiltAxisZRadians = 2 * Math.PI * (day - SUMMER_SOLSTICE) / 365;
// // How much is a given latitude tilted up (+) or down (-) toward the ecliptic?
// // -23.5 degrees on June solstice, 0 degrees at equinoxes, +23.5 degrees on December solstice.
// const orbitalTiltDegrees = earthTilt ? EARTH_TILT * RAD_2_DEG : 0;
// const effectiveTiltDegrees = -Math.cos(tiltAxisZRadians) * orbitalTiltDegrees;
// return 90 - (lat + effectiveTiltDegrees);
// }

export function angleToDay(angle: number, earthTilt: number, lat: number) {
// Inverse sunrayAngle function.
Expand Down
7 changes: 5 additions & 2 deletions src/hooks/useCodapData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export const useCodapData = () => {
const calcOptions: DaylightCalcOptions = {
latitude: Number(latitude),
longitude: Number(longitude),
year: 2024,
year: 2024, //TODO: If data are to be historical, add dynamic year attribute
useRealTimeZones: true
};

Expand Down Expand Up @@ -74,7 +74,10 @@ export const useCodapData = () => {
date: solarEvent.day,
sunrise: solarEvent.sunrise,
sunset: solarEvent.sunset,
dayLength: solarEvent.dayLength
dayLength: solarEvent.dayLength,
season: solarEvent.season,
sunlightAngle: solarEvent.sunlightAngle,
solarIntensity: solarEvent.solarIntensity
};

return record;
Expand Down
3 changes: 3 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ export interface DaylightInfo {
sunset: string;
dayLength: number;
dayAsInteger: number;
season: string;
sunlightAngle: number;
solarIntensity: number;
}

export interface GeoNameSearchOptions {
Expand Down
68 changes: 67 additions & 1 deletion src/utils/daylight-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import dayOfYear from "dayjs/plugin/dayOfYear";
import timezone from "dayjs/plugin/timezone";
import tzlookup from "tz-lookup";
import { getSunrise, getSunset } from "sunrise-sunset-js";
import { Seasons } from "astronomy-engine";
import { DaylightInfo, DaylightCalcOptions } from "../types";
import { kBasicSummerSolstice, kEarthTilt } from "../constants";

extend(utc);
extend(dayOfYear);
Expand All @@ -18,6 +20,67 @@ function getDayLength(sunrise: Dayjs, sunset: Dayjs): number {
return dayLength < 0 ? dayLength + 24 : dayLength;
}

function getSeasonName(dayJsDay: Dayjs, latitude: number): string {
const year = dayJsDay.year();
const { mar_equinox, jun_solstice, sep_equinox, dec_solstice } = Seasons(year);

const springEq = dayjs(mar_equinox.date);
const summerSol = dayjs(jun_solstice.date);
const fallEq = dayjs(sep_equinox.date);
const winterSol = dayjs(dec_solstice.date);

let season: string;

if (dayJsDay.isBefore(springEq) || dayJsDay.isAfter(winterSol) || dayJsDay.isSame(winterSol)) {
season = "Winter";
} else if (dayJsDay.isBefore(summerSol)) {
season = "Spring";
} else if (dayJsDay.isBefore(fallEq)) {
season = "Summer";
} else if (dayJsDay.isBefore(winterSol)) {
season = "Fall";
} else {
throw new Error("Unable to determine season");
}

// Flip seasons for Southern Hemisphere
if (latitude < 0) {
const oppositeSeasons: { [key: string]: string } = {
"Winter": "Summer",
"Spring": "Fall",
"Summer": "Winter",
"Fall": "Spring"
};
return oppositeSeasons[season];
}

return season;
}

export function getSolarNoonIntensity(dayNum: number, latitude: number): number {
const solarConstant = 1361;
const latitudeRad = latitude * Math.PI / 180;
const declination = 23.45 * Math.sin((360/365) * (dayNum - 81) * Math.PI / 180);
const declinationRad = declination * Math.PI / 180;
const dayAngle = 2 * Math.PI * (dayNum - 1) / 365;
// correction factor for Earth's elliptical orbit
const eccentricityFactor = 1 + 0.033 * Math.cos(dayAngle);
// cosine of the solar zenith angle at solar noon
const cosSolarZenithAngle = Math.sin(latitudeRad) * Math.sin(declinationRad) +
Math.cos(latitudeRad) * Math.cos(declinationRad);

const solarNoonIntensity = solarConstant * eccentricityFactor * cosSolarZenithAngle;
return Math.max(0, solarNoonIntensity); // Ensure non-negative value
}

export function getSunrayAngleInDegrees(dayNum: number, earthTilt: number, lat:number): number {
const tiltAxisZRadians = 2 * Math.PI * (dayNum - kBasicSummerSolstice) / 365;
const orbitalTiltDegrees = earthTilt ? earthTilt : 0;
const effectiveTiltDegrees = -Math.cos(tiltAxisZRadians) * orbitalTiltDegrees;
const degrees = 90 - (lat + effectiveTiltDegrees);
return degrees;
}

export function getDayLightInfo(options: DaylightCalcOptions): DaylightInfo[] {
const { latitude, longitude, year, useRealTimeZones } = options;
const results: DaylightInfo[] = [];
Expand Down Expand Up @@ -47,7 +110,10 @@ export function getDayLightInfo(options: DaylightCalcOptions): DaylightInfo[] {
sunrise: tzSunrise.format("YYYY-MM-DDTHH:mmZ"),
sunset: tzSunset.format("YYYY-MM-DDTHH:mmZ"),
dayLength: getDayLength(tzSunrise, tzSunset),
dayAsInteger: currentDay.dayOfYear()
dayAsInteger: currentDay.dayOfYear(),
season: getSeasonName(currentDay, latitude),
sunlightAngle: getSunrayAngleInDegrees(currentDay.dayOfYear(), kEarthTilt, latitude),
solarIntensity: getSolarNoonIntensity(currentDay.dayOfYear(), latitude)
};
results.push(record);
currentDay = currentDay.add(1, "day");
Expand Down
Loading

0 comments on commit 110c94e

Please sign in to comment.