Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright 2019 Gustl22
*
* This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* this program. If not, see .
*/
package org.oscim.renderer.light;
import org.oscim.backend.DateTimeAdapter;
import org.oscim.backend.canvas.Color;
import org.oscim.utils.ColorUtil;
import org.oscim.utils.geom.GeometryUtils;
import org.oscim.utils.math.MathUtils;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
* See https://lexikon.astronomie.info/zeitgleichung
*/
public class Sun {
public static float SHADOW_ALPHA = 0.3f;
private static final DateTimeAdapter date = DateTimeAdapter.instance;
private float mSunrise; // in hours
private float mSunset; // in hours
private float mLatitude; // in degree
private float mLongitude; // in degree
private int mDayOfYear; // up to 366
private float mProgress; // 0 to 2
private float[] mSunPos = new float[3];
private int mLightColor;
private Map mColorMap;
/**
* Track sun position (accuracy of ~1 minute).
*/
public Sun() {
// Init defaults
mDayOfYear = date.getDayOfYear();
setCoordinates(0, 0);
mLightColor = Color.get(SHADOW_ALPHA, 255, 255, 255);
setProgress(0.4f);
updatePosition();
}
/**
* @return the latitude where the sun is in zenith
*/
private float declination() {
return (float) (0.4095 * Math.sin(0.016906 * (mDayOfYear - 80.086)));
}
/**
* The discrepancy of mean time and sun time.
*
* @return discrepancy in hours
*/
private float discrepancyMeanTime() {
return (float) (-0.171 * Math.sin(0.0337 * mDayOfYear + 0.465) - 0.1299 * Math.sin(0.01787 * mDayOfYear - 0.168));
}
/**
* RGB - the color of sun.
* A - the diffuse of shadow.
*/
public int getColor() {
return mLightColor;
}
/**
* Get the colors of day cycle.
*
* @return the color map
*/
public Map getColorMap() {
return mColorMap;
}
public float getLatitude() {
return mLatitude;
}
public float getLongitude() {
return mLongitude;
}
public float[] getPosition() {
return mSunPos;
}
public float getProgress() {
return mProgress;
}
/**
* @return the local sunrise time in hours.
*/
public float getSunrise() {
return mSunrise;
}
/**
* @return the local sunset time in hours.
*/
public float getSunset() {
return mSunset;
}
private void initDefaultColorMap() {
mColorMap = new HashMap<>();
mColorMap.put(0.0f, Color.get((int) (255 * SHADOW_ALPHA), 150, 120, 140)); // Sunrise
mColorMap.put(0.04f, Color.get((int) (255 * SHADOW_ALPHA), 205, 170, 160));
mColorMap.put(0.1f, Color.get((int) (255 * SHADOW_ALPHA), 245, 240, 215));
mColorMap.put(0.2f, Color.get((int) (255 * SHADOW_ALPHA), 255, 255, 255)); // Forenoon
mColorMap.put(0.8f, Color.get((int) (255 * SHADOW_ALPHA), 255, 255, 255)); // Afternoon
mColorMap.put(0.99f, Color.get((int) (255 * SHADOW_ALPHA), 255, 220, 230));
mColorMap.put(1.0f, Color.get((int) (255 * SHADOW_ALPHA), 100, 100, 130)); // Sunset
mColorMap.put(1.9f, Color.get((int) (255 * SHADOW_ALPHA), 100, 100, 130)); // Night
}
/**
* @param color RGB - the color of sun, A - the diffuse of shadow
*/
public void setColor(int color) {
mLightColor = color;
}
/**
* Set the colors of day cycle.
*/
public void setColorMap(Map colorMap) {
mColorMap = colorMap;
}
public void setCoordinates(float latitude, float longitude) {
mLatitude = latitude;
mLongitude = longitude;
updateToDay();
}
/**
* Customize day of the year.
*/
public void setDayOfYear(int day) {
mDayOfYear = day;
}
public void setPosition(float x, float y, float z) {
mSunPos[0] = x;
mSunPos[1] = y;
mSunPos[2] = z;
mSunPos = GeometryUtils.normalize(mSunPos);
}
/**
* Customize progress.
*/
public void setProgress(float progress) {
mProgress = progress;
}
/**
* Customize progress with specified time.
*
* @param hour the hour [0..23]
* @param minute the minute [0..59]
* @param second the second [0..59]
* @return the progress in range 0 to 2
*/
public float setProgress(int hour, int minute, int second) {
float time = hour;
time += minute / 60f;
time += second / 3600f;
float progress = (time - mSunrise) / (mSunset - mSunrise);
if (progress > 1f || progress < 0f) {
progress = ((time + 24 - mSunset) % 24) / (mSunrise + 24 - mSunset);
progress += 1;
}
mProgress = MathUtils.clamp(progress, 0f, 2f);
return mProgress;
}
/**
* @param h the offset of horizon (in radians) e.g. bend of earth / atmosphere etc.
* @return the difference of sunrise or sunset to noon
*/
private float timeDiff(float h) {
float lat = mLatitude * MathUtils.degreesToRadians;
float declination = declination();
return (float) (12 * Math.acos((Math.sin(h) - Math.sin(lat) * Math.sin(declination)) / (Math.cos(lat) * Math.cos(declination))) / Math.PI);
}
/**
* Update sun progress, position and color to current date time.
*/
public void update() {
updateProgress();
updatePosition();
updateColor();
}
public int updateColor() {
if (mColorMap == null)
initDefaultColorMap();
float progressStart, progressEnd;
Iterator prIter = mColorMap.keySet().iterator();
progressStart = progressEnd = prIter.next();
while (prIter.hasNext()) {
float progress = prIter.next();
if (((mProgress + 2f - progress) % 2f) < ((mProgress + 2f - progressStart) % 2f))
progressStart = progress;
else if (((progress + 2f - mProgress) % 2f) < ((progressEnd + 2f - mProgress) % 2f))
progressEnd = progress;
}
if (progressStart == progressEnd) {
mLightColor = mColorMap.get(progressStart);
return mLightColor;
}
float fraction = ((mProgress + 2f - progressStart) % 2f) / ((progressEnd + 2f - progressStart) % 2f);
int colorStart = mColorMap.get(progressStart);
int colorEnd = mColorMap.get(progressEnd);
mLightColor = ColorUtil.blend(colorStart, colorEnd, fraction);
return mLightColor;
}
/**
* Very simple normalized sun coordinates.
*/
public float[] updatePosition() {
mSunPos[0] = (float) Math.cos(mProgress * Math.PI);
mSunPos[1] = (float) Math.sin(mProgress * Math.PI);
mSunPos[2] = 3 * mSunPos[1];
mSunPos = GeometryUtils.normalize(mSunPos);
return mSunPos;
}
/**
* The progress
* of the daylight in range 0 (sunrise) to 1 (sunset) and
* of the night in range 1 (sunset) to 2 (sunrise).
*
* @return the progress in range 0 to 2
*/
public float updateProgress() {
return setProgress(date.getHour(), date.getMinute(), date.getSecond());
}
/**
* Calculate the sunrise and sunset of set day (local time).
*/
public void updateToDay() {
float h = -0.0145f; // -50 latitude minutes
float diff = timeDiff(h);
float discp = discrepancyMeanTime();
float calc = 12 - discp - (mLongitude / 15f) + (date.getTimeZoneOffset() / (60f * 60f * 1000f));
mSunrise = calc - diff;
mSunset = calc + diff;
}
}