-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #10 from open-pv/feature-4-diffuse-radiation-from-…
…file Feature 4 diffuse radiation and elevation
- Loading branch information
Showing
12 changed files
with
554 additions
and
45 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import { CartesianPoint, SphericalPoint } from './utils'; | ||
|
||
export function fillMissingAltitudes(maxAngles: SphericalPoint[]): void { | ||
// First copy the maxAngles to a newAngles list, so that changes | ||
// in the list do not affect the algorithm | ||
let newAngles = maxAngles.map((angle) => ({ ...angle })); | ||
for (let i = 0; i < newAngles.length; i++) { | ||
if (newAngles[i].altitude != -Infinity) { | ||
continue; | ||
} | ||
let distance = 1; | ||
while (true) { | ||
let prevIndex = (i - distance + newAngles.length) % newAngles.length; | ||
let nextIndex = (i + distance) % newAngles.length; | ||
|
||
if (maxAngles[nextIndex].altitude !== -Infinity) { | ||
newAngles[i].altitude = maxAngles[nextIndex].altitude; | ||
break; | ||
} else if (maxAngles[prevIndex].altitude !== -Infinity) { | ||
newAngles[i].altitude = maxAngles[prevIndex].altitude; | ||
break; | ||
} else distance++; | ||
} | ||
} | ||
// Overwrite the maxAngles to make changes in this vector global | ||
for (let i = 0; i < maxAngles.length; i++) { | ||
maxAngles[i] = newAngles[i]; | ||
} | ||
} | ||
|
||
/** | ||
* Returns the vector from start to end in the Horizontal coordinate system | ||
* @param start | ||
* @param end | ||
* @returns | ||
*/ | ||
export function calculateSphericalCoordinates(start: CartesianPoint, end: CartesianPoint): SphericalPoint { | ||
const dx = end.x - start.x; | ||
const dy = end.y - start.y; | ||
const dz = end.z - start.z; | ||
if (dx == 0 && dy == 0) { | ||
return { radius: 1, azimuth: 0, altitude: 0 }; | ||
} | ||
|
||
const r = Math.sqrt(dx * dx + dy * dy + dz * dz); | ||
const altitude = Math.asin(dz / r); | ||
|
||
let azimuth = (2 * Math.PI - Math.atan2(dy, dx)) % (2 * Math.PI); | ||
|
||
return { radius: 1, azimuth, altitude }; | ||
} | ||
|
||
/** | ||
* Calculates the maximum heights visible from an observer in a set of directions. | ||
* Returns a list of spherical points of length numDirections. | ||
* @param elevation list of points with x,y,z component | ||
* @param observer Point of interest for which the elevation angles are calculated. | ||
* @param numDirections Number of steps for the azimuth angle. | ||
* @returns | ||
*/ | ||
export function getMaxElevationAngles( | ||
elevation: CartesianPoint[], | ||
observer: CartesianPoint, | ||
numDirections: number, | ||
): SphericalPoint[] { | ||
let maxAngles: SphericalPoint[] = Array.from({ length: numDirections }, (_, index) => ({ | ||
radius: 1, | ||
azimuth: index * ((2 * Math.PI) / numDirections), | ||
altitude: -Infinity, | ||
})); | ||
|
||
for (let point of elevation) { | ||
const { azimuth, altitude } = calculateSphericalCoordinates(observer, point); | ||
const closestIndex = Math.round(azimuth / ((2 * Math.PI) / numDirections)) % numDirections; | ||
if (altitude > maxAngles[closestIndex].altitude) { | ||
maxAngles[closestIndex].altitude = altitude; | ||
} | ||
} | ||
fillMissingAltitudes(maxAngles); | ||
return maxAngles; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.