float DAYS_TO_RECORD = 3; integer PRIMS_MAX = 180; float gInterval; integer gLongevity; float gLastSunZ; float gLastSunZD; // last delta of sun motion, only valid after first 2 ticks vector gSunMarkerColor = <1,1,0>; vector gMoonMarkerColor = <.3,.3,.3>; integer gMarkerCount = 0; integer PLOTTER_CHANNEL = 8080; string twoDigits(integer n) { string result = (string)n; if(n < 10) result = "0" + result; return result; } string seconds2Time(float secondsF) { integer seconds = (integer)secondsF; integer hours = seconds / 3600; seconds %= 3600; integer minutes = seconds / 60; seconds %= 60; string time = (string)hours + ":" + twoDigits(minutes) + ":" + twoDigits(seconds); return time; } tellMarker(list messageL) { string message = llDumpList2String(messageL,"++"); if(message != "") { llSay(PLOTTER_CHANNEL,message); } } string twoDecimalPlaces(float x) { string result; if(x < 0) { x = -x; result += "-"; } integer whole = llFloor(x); result += (string)whole; result += "."; integer hundredths = (integer)((x - whole) * 100); if(hundredths < 10) result += "0"; result += (string)hundredths; return result; } list ANGLE2COMPASS = ["E","ENE","NE","NNE", "N","NNW","NW","WNW", "W","WSW","SW","SSW", "S","SSE","SE","ESE", "E"]; string angle2Compass(float x, float y) { if(x == 0 && y == 0) return ""; float angle = llAtan2(y,x); // in radians, hey float compassAngle = angle * 16 / (2 * PI); integer compassIndex = llFloor(compassAngle + 0.5); while(compassIndex < 0) compassIndex += 16; compassIndex %= 16; string compass = llList2String(ANGLE2COMPASS,compassIndex); return compass; } string getBearings(vector v) { vector dropV = v; dropV.z = 0; v = llVecNorm(v); dropV = llVecNorm(dropV); float elevation = llAcos(v * dropV) * 57.29577951; if(v.z < 0) elevation = -elevation; float heading = llAtan2(v.y,v.x) * 57.29577951; string result = "Heading: " + twoDecimalPlaces(heading) + " (" + angle2Compass(v.y,v.x) + "), Elevation: " + twoDecimalPlaces(elevation); return result; } list POSITION_NAMES = [ "", " Sunrise", " Apogee", " Sunset", " Perigee" ]; list MOON_POSITION_NAMES = [ "", " Moonset", " Perigee", " Moonrise", " Apogee" ]; integer gSamples = 0; doSun(integer evenIfNotSpecial) { gSamples++; vector sunV = llGetSunDirection(); sunV = llVecNorm(sunV); vector moonV = -sunV; float sunZ = sunV.z; integer specialPosition = 0; // 1 sunrise,2 apogee,3 sunset,4 perigee float sunZD = sunZ - gLastSunZ; if(gSamples > 3) { if(sunZ > 0 && gLastSunZD > 0 && sunZD < 0) specialPosition = 2; else if(sunZ < 0 && gLastSunZD < 0 && sunZD > 0) specialPosition = 4; } gLastSunZD = sunZD; if(gLastSunZ < 0 && sunZ >= 0) specialPosition = 1; else if(gLastSunZ > 0 && sunZ <= 0) specialPosition = 3; // we now know if it's a special time... if(!specialPosition && !evenIfNotSpecial) return; vector sunMarkerPos = llGetPos() + sunV; vector moonMarkerPos = llGetPos() + moonV * .5; vector sunMarkerScale = <.1,.1,.1>; vector moonMarkerScale = <.5,.5,.5>; string srTime = "Sidereal Time: " + seconds2Time(llGetTimeOfDay()); string slTime = "Standard Time: " + seconds2Time(llGetWallclock()); gMarkerCount++; float longevity = gLongevity; if(specialPosition) { longevity = 10 * longevity; moonMarkerScale *= 1.5; sunMarkerScale *= 1.3; } // midnight: bump the colors! if(specialPosition == 4) { gSunMarkerColor = <.6 + llFrand(.4),.6 + llFrand(.4),0>; float g = llFrand(.3) + .3; gMoonMarkerColor = ; } string numDat = " " + (string)gMarkerCount + " " + llGetDate(); llRezObject("solar_plotter_marker", llGetPos() + sunV, <0,0,0>, ZERO_ROTATION, PLOTTER_CHANNEL); tellMarker(["color",gSunMarkerColor]); tellMarker(["size",sunMarkerScale]); string sunName = "Sun " + numDat + llList2String(POSITION_NAMES,specialPosition); tellMarker(["name",sunName]); tellMarker(["data",sunName]); tellMarker(["data",srTime]); tellMarker(["data",slTime]); tellMarker(["data",getBearings(sunV)]); tellMarker(["ttl",longevity]); tellMarker(["done"]); // no more commands to this one llRezObject("solar_plotter_marker", llGetPos() + moonV, <0,0,0>, ZERO_ROTATION, PLOTTER_CHANNEL); tellMarker(["color",gMoonMarkerColor]); tellMarker(["size",moonMarkerScale]); string moonName = "Moon " + numDat + llList2String(MOON_POSITION_NAMES,specialPosition); tellMarker(["name",moonName]); tellMarker(["data",moonName]); tellMarker(["data",srTime]); tellMarker(["data",slTime]); tellMarker(["data",getBearings(moonV)]); tellMarker(["ttl",longevity]); tellMarker(["done"]); // no more commands to this one } default { state_entry() { gLongevity = (integer)(DAYS_TO_RECORD * 4 * 60 * 60); // seconds of data gInterval = (float)gLongevity / ((float)PRIMS_MAX / 2); gMarkerCount = 0; llSetTimerEvent(gInterval); doSun(TRUE); } timer() { doSun(TRUE); } touch_start(integer n) { llSay(0,"Capture gInterval: " +(string)gInterval); llSay(0,"Marker gLongevity: " +(string)gLongevity); } } // end of file