Index: trunk/FACT++/src/InterpreterV8.cc
===================================================================
--- trunk/FACT++/src/InterpreterV8.cc	(revision 14577)
+++ trunk/FACT++/src/InterpreterV8.cc	(revision 14578)
@@ -1,3 +1,8 @@
 #include "InterpreterV8.h"
+
+#ifdef HAVE_NOVA
+#include <libnova/lunar.h>
+#include <libnova/transform.h>
+#endif
 
 #ifdef HAVE_SQL
@@ -195,5 +200,5 @@
     code +=        ");";
 
-    const HandleScope handle_scope;
+    HandleScope handle_scope;
 
     // It is not strictly necessary to catch the exception, instead
@@ -206,5 +211,5 @@
     const Handle<Value>  result = script->Run();
 
-    return exception.HasCaught() ? exception.ReThrow() : result;
+    return exception.HasCaught() ? exception.ReThrow() : handle_scope.Close(result);
 
     /*
@@ -230,5 +235,5 @@
         return ThrowException(String::New("Argument 1 must be a string."));
 
-    const HandleScope handle_scope;
+    HandleScope handle_scope;
 
     const String::Utf8Value str(args[0]);
@@ -246,5 +251,5 @@
     }
 
-    return Boolean::New(JsSend(command));
+    return handle_scope.Close(Boolean::New(JsSend(command)));
 }
 
@@ -275,12 +280,17 @@
         "})();";
 
-    const HandleScope handle_scope;
+    HandleScope handle_scope;
 
     const Handle<Script> script = Script::Compile(String::New(code.c_str()));
-    return script->Run();
+
+    return handle_scope.Close(script->Run());
 
     //JsSleep(args[0]->Int32Value());
     //return Undefined();
 }
+
+// ==========================================================================
+//                               State control
+// ==========================================================================
 
 Handle<Value> InterpreterV8::FuncState(const Arguments& args)
@@ -335,5 +345,5 @@
         return ThrowException(String::New("Argument 3 must be a string."));
 
-    const HandleScope handle_scope;
+    HandleScope handle_scope;
 
     const uint32_t index   = args[0]->Int32Value();
@@ -358,5 +368,5 @@
     }
 
-    return Boolean::New(JsNewState(index, name, comment));
+    return handle_scope.Close(Boolean::New(JsNewState(index, name, comment)));
 }
 
@@ -369,5 +379,5 @@
         return ThrowException(String::New("Argument must be an unint32 or a  string."));
 
-    const HandleScope handle_scope;
+    HandleScope handle_scope;
 
     int index = -2;
@@ -387,6 +397,10 @@
         return ThrowException(String::New("State must be in the range [10, 255]."));
 
-    return Boolean::New(JsSetState(index));
-}
+    return handle_scope.Close(Boolean::New(JsSetState(index)));
+}
+
+// ==========================================================================
+//                             Internal functions
+// ==========================================================================
 
 Handle<Value> InterpreterV8::FuncExit(const Arguments &)
@@ -478,4 +492,8 @@
 }
 
+// ==========================================================================
+//                                 Database
+// ==========================================================================
+
 Handle<Value> InterpreterV8::FuncDbClose(const Arguments &args)
 {
@@ -484,5 +502,5 @@
     void *ptr = Handle<External>::Cast(args.This()->GetInternalField(0))->Value();
     if (!ptr)
-        return Boolean::New(false);
+        return handle_scope.Close(Boolean::New(false));
 
 #ifdef HAVE_SQL
@@ -495,5 +513,5 @@
     args.This()->SetInternalField(0, External::New(0));
 
-    return Boolean::New(true);
+    return handle_scope.Close(Boolean::New(true));
 }
 Handle<Value> InterpreterV8::FuncDbQuery(const Arguments &args)
@@ -684,4 +702,8 @@
 #endif
 }
+
+// ==========================================================================
+//                                 Services
+// ==========================================================================
 
 Handle<Value> InterpreterV8::Convert(char type, const char* &ptr)
@@ -720,5 +742,5 @@
 Handle<Value> InterpreterV8::FuncClose(const Arguments &args)
 {
-    const HandleScope handle_scope;
+    HandleScope handle_scope;
 
     //const void *ptr = Local<External>::Cast(args.Holder()->GetInternalField(0))->Value();
@@ -735,5 +757,5 @@
     args.Holder()->Set(String::New("isOpen"), Boolean::New(false), ReadOnly);
 
-    return Boolean::New(JsUnsubscribe(*str));
+    return handle_scope.Close(Boolean::New(JsUnsubscribe(*str)));
 }
 
@@ -1119,4 +1141,242 @@
 }
 
+// ==========================================================================
+//                            Astrometry
+// ==========================================================================
+#ifdef HAVE_NOVA
+
+double InterpreterV8::GetDataMember(const Arguments &args, const char *name)
+{
+    return args.This()->Get(String::New(name))->NumberValue();
+}
+
+Handle<Value> InterpreterV8::LocalToString(const Arguments &args)
+{
+    return String::New("[object Local]");
+    /*
+    HandleScope handle_scope;
+
+    const Handle<Object> This = args.This();
+
+    Handle<String> zd = This->Get(String::New("zd"))->ToString();
+    Handle<String> az = This->Get(String::New("az"))->ToString();
+
+    return String::New("TEST");
+    */
+}
+
+Handle<Value> InterpreterV8::SkyToString(const Arguments &args)
+{
+    return String::New("[object Sky]");
+}
+
+Handle<Value> InterpreterV8::MoonToString(const Arguments &args)
+{
+    return String::New("[object Moon]");
+}
+
+Handle<Value> InterpreterV8::ConstructLocal(double zd, double az, Handle<Value> time)
+{
+    Handle<ObjectTemplate> loc = ObjectTemplate::New();
+
+    loc->Set(String::New("zd"), Number::New(zd), ReadOnly);
+    loc->Set(String::New("az"), Number::New(az), ReadOnly);
+    loc->Set(String::New("toSky"),    FunctionTemplate::New(LocalToSky), ReadOnly);
+    loc->Set(String::New("toString"), FunctionTemplate::New(LocalToString), ReadOnly);
+    if (!time.IsEmpty())
+        loc->Set(String::New("time"), time);
+
+    return loc->NewInstance();
+}
+
+Handle<Value> InterpreterV8::ConstructSky(double ra, double dec, Handle<Value> time, bool ismoon)
+{
+    Handle<ObjectTemplate> sky = ObjectTemplate::New();
+
+    sky->Set(String::New("ra"),  Number::New(ra),  ReadOnly);
+    sky->Set(String::New("dec"), Number::New(dec), ReadOnly);
+    sky->Set(String::New("toLocal"),  FunctionTemplate::New(ismoon?MoonToLocal :SkyToLocal),  ReadOnly);
+    sky->Set(String::New("toString"), FunctionTemplate::New(ismoon?MoonToString:SkyToString), ReadOnly);
+    if (!time.IsEmpty())
+        sky->Set(String::New("time"), time);
+
+    return sky->NewInstance();
+}
+
+Handle<Value> InterpreterV8::MoonDisk(const Arguments &args)
+{
+    return Undefined();
+}
+
+Handle<Value> InterpreterV8::LocalToSky(const Arguments &args)
+{
+    HandleScope handle_scope;
+
+    if (args.Length()>1)
+        return ThrowException(String::New("toSky must not be called with more than one argument."));
+
+    ln_hrz_posn hrz;
+    hrz.alt = 90-GetDataMember(args, "zd");
+    hrz.az  =    GetDataMember(args, "az");
+
+    if (!finite(hrz.alt) || !finite(hrz.az))
+        return ThrowException(String::New("zd and az must be finite."));
+
+    // It is important to catch the exception thrown
+    // by Date::New in case of thread termination!
+    TryCatch exception;
+
+    const Local<Value> date =
+        args.Length()==0 ? Date::New(Time().JavaDate()) : args[0];
+    if (exception.HasCaught())
+        return exception.ReThrow();
+
+    const uint64_t v = uint64_t(args[0]->NumberValue());
+    const Time utc(v/1000, v%1000);
+
+    ln_lnlat_posn obs;
+    obs.lng = -(17.+53./60+26.525/3600);
+    obs.lat =   28.+45./60+42.462/3600;
+
+    ln_equ_posn equ;
+    ln_get_equ_from_hrz(&hrz, &obs, utc.JD(), &equ);
+
+    return handle_scope.Close(ConstructSky(equ.ra/15, equ.dec, date));
+}
+
+Handle<Value> InterpreterV8::SkyToLocal(const Arguments &args)
+{
+    HandleScope handle_scope;
+
+    if (args.Length()>1)
+        return ThrowException(String::New("toLocal must not be called with more than one argument."));
+
+    ln_equ_posn equ;
+    equ.ra  = GetDataMember(args, "ra")*15;
+    equ.dec = GetDataMember(args, "dec");
+
+    if (!finite(equ.ra) || !finite(equ.dec))
+        return ThrowException(String::New("Ra and dec must be finite."));
+
+    // It is important to catch the exception thrown
+    // by Date::New in case of thread termination!
+    TryCatch exception;
+
+    const Local<Value> date =
+        args.Length()==0 ? Date::New(Time().JavaDate()) : args[0];
+    if (exception.HasCaught())
+        return exception.ReThrow();
+
+    const uint64_t v = uint64_t(args[0]->NumberValue());
+    const Time utc(v/1000, v%1000);
+
+    ln_lnlat_posn obs;
+    obs.lng = -(17.+53./60+26.525/3600);
+    obs.lat =   28.+45./60+42.462/3600;
+
+    ln_hrz_posn hrz;
+    ln_get_hrz_from_equ(&equ, &obs, utc.JD(), &hrz);
+
+    return handle_scope.Close(ConstructLocal(90-hrz.alt, hrz.az, date));
+}
+
+Handle<Value> InterpreterV8::MoonToLocal(const Arguments &args)
+{
+    HandleScope handle_scope;
+
+    if (args.Length()>0)
+        return ThrowException(String::New("toLocal must not be called with arguments."));
+
+    ln_equ_posn equ;
+    equ.ra  = GetDataMember(args, "ra")*15;
+    equ.dec = GetDataMember(args, "dec");
+
+    if (!finite(equ.ra) || !finite(equ.dec))
+        return ThrowException(String::New("ra and dec must be finite."));
+
+    // It is important to catch the exception thrown
+    // by Date::New in case of thread termination!
+    TryCatch exception;
+
+    const Local<Value> date =
+        args.Length()==0 ? Date::New(Time().JavaDate()) : args.This()->Get(String::New("time"));
+    if (exception.HasCaught())
+        return exception.ReThrow();
+
+    const uint64_t v = uint64_t(args[0]->NumberValue());
+    const Time utc(v/1000, v%1000);
+
+    ln_lnlat_posn obs;
+    obs.lng = -(17.+53./60+26.525/3600);
+    obs.lat =   28.+45./60+42.462/3600;
+
+    ln_hrz_posn hrz;
+    ln_get_hrz_from_equ(&equ, &obs, utc.JD(), &hrz);
+
+    return handle_scope.Close(ConstructLocal(90-hrz.alt, hrz.az, date));
+}
+
+Handle<Value> InterpreterV8::ConstructorMoon(const Arguments &args)
+{
+    HandleScope handle_scope;
+
+    if (args.Length()>1)
+        return ThrowException(String::New("Moon constructor must not be called with more than one argument."));
+
+    // It is important to catch the exception thrown
+    // by Date::New in case of thread termination!
+    TryCatch exception;
+
+    const Local<Value> date =
+        args.Length()==0 ? Date::New(Time().JavaDate()) : args[0];
+    if (exception.HasCaught())
+        return exception.ReThrow();
+
+    const uint64_t v = uint64_t(args[0]->NumberValue());
+    const Time utc(v/1000, v%1000);
+
+    ln_equ_posn equ;
+    ln_get_lunar_equ_coords_prec(utc.JD(), &equ, 0.01);
+
+    return handle_scope.Close(ConstructSky(equ.ra/15, equ.dec, date, true));
+}
+
+Handle<Value> InterpreterV8::ConstructorSky(const Arguments &args)
+{
+    HandleScope handle_scope;
+
+    if (args.Length()!=2)
+        return ThrowException(String::New("Sky constructor takes two arguments."));
+
+    const double ra  = args[0]->NumberValue();
+    const double dec = args[1]->NumberValue();
+
+    if (!finite(ra) || !finite(dec))
+        return ThrowException(String::New("Both arguments to Sky must be valid numbers."));
+
+    return handle_scope.Close(ConstructSky(ra, dec));
+}
+
+Handle<Value> InterpreterV8::ConstructorLocal(const Arguments &args)
+{
+    HandleScope handle_scope;
+
+    if (args.Length()!=2)
+        return ThrowException(String::New("Local constructor takes two arguments."));
+
+    const double zd = args[0]->NumberValue();
+    const double az = args[1]->NumberValue();
+
+    if (!finite(zd) || !finite(az))
+        return ThrowException(String::New("Both arguments to Local must be valid numbers."));
+
+    return handle_scope.Close(ConstructLocal(zd, az));
+}
+#endif
+
+// ==========================================================================
+//                                  CORE
+// ==========================================================================
+
 bool InterpreterV8::JsRun(const string &filename, const map<string, string> &map)
 {
@@ -1154,4 +1414,16 @@
     global->Set(String::New("version"), FunctionTemplate::New(InterpreterV8::FuncVersion), ReadOnly);
 
+#ifdef HAVE_NOVA
+    Handle<FunctionTemplate> sky = FunctionTemplate::New(ConstructorSky);
+    global->Set(String::New("Sky"), sky, ReadOnly);
+
+    Handle<FunctionTemplate> loc = FunctionTemplate::New(ConstructorLocal);
+    global->Set(String::New("Local"), loc, ReadOnly);
+
+    Handle<FunctionTemplate> moon = FunctionTemplate::New(ConstructorMoon);
+    moon->Set(String::New("disk"), FunctionTemplate::New(MoonDisk), ReadOnly);
+    global->Set(String::New("Moon"), moon, ReadOnly);
+#endif
+
     // Persistent
     Persistent<Context> context = Context::New(NULL, global);
@@ -1225,2 +1497,74 @@
 
 #endif
+// ========================================================================
+/*
+ const double lon = -(17.+53./60+26.525/3600);
+ const double lat =   28.+45./60+42.462/3600;
+
+ Time now;
+
+ const double disk = ln_get_lunar_disk(now.JD();
+
+ ln_lnlat_posn obs;
+ obs.lng = lon;
+ obs.lat = lat;
+
+ ln_equ_posn equ;
+ ln_hrz_posn hrz;
+
+ // Source
+ equ.ra  = ra*15;
+ equ.dec = dec;
+
+ // Moon
+ ln_get_lunar_equ_coords_prec(now.JD(), &moon, 0.01);
+
+ ln_get_hrz_from_equ(&equ, &obs, now.JD(), &hrz);
+ ln_get_equ_from_hrz(&hrz, &obs, now.JD(), &equ);
+*/
+
+/*
+ Sky   { ra, dec, toLocal(time[, obs]), moon(time) }
+ Local { zd, az,  toSky  (time[, obs]), moon(time) }
+
+ {zd, az} = getLocalCoordinates({ra, dec}[, time [, obs]]);
+ {zd, az} = getMoonPosition(time);
+ float    = getMoonDisk(time);
+
+ // -----------------------------------------------------------------------
+
+ void Callack(Arguments &args)
+ {
+ }
+
+ Handle<ObjectTemplate> sky = ObjectTemplate::New();
+ sky->SetCallAsFunctionHandler(Callback);
+ dim->Set(String::New("Sky"), sky, ReadOnly);
+
+ void v8::ObjectTemplate::SetCallAsFunctionHandler	(	InvocationCallback 	callback,
+ Handle< Value > 	data = Handle< Value >()
+)			
+
+    Handle<ObjectTemplate> sky = ObjectTemplate::New();
+    sky->Set(String::New("toLocal"), FunctionTemplate::New(WrapToLocal), ReadOnly);
+    sky->Set(String::New("ra"),  Float::New(ra));
+    sky->Set(String::New("dec"), Float::New(dec));
+    return sky::NewInstance();
+
+    Handle<ObjectTemplate> loc = ObjectTemplate::New();
+    loc->Set(String::New("toSky"), FunctionTemplate::New(WrapToSky), ReadOnly);
+    loc->Set(String::New("zd"), Float::New(zd));
+    loc->Set(String::New("az"), Float::New(az));
+    return loc::NewInstance();
+
+
+
+
+
+
+ */
+
+
+
+
+
Index: trunk/FACT++/src/InterpreterV8.h
===================================================================
--- trunk/FACT++/src/InterpreterV8.h	(revision 14577)
+++ trunk/FACT++/src/InterpreterV8.h	(revision 14578)
@@ -64,4 +64,19 @@
     v8::Handle<v8::Value> FuncDbClose(const v8::Arguments &args);
     v8::Handle<v8::Value> OnChangeSet(v8::Local<v8::String>, v8::Local<v8::Value>, const v8::AccessorInfo &);
+
+    static double GetDataMember(const v8::Arguments &args, const char *name);
+
+    static v8::Handle<v8::Value> LocalToString(const v8::Arguments &args);
+    static v8::Handle<v8::Value> SkyToString(const v8::Arguments &args);
+    static v8::Handle<v8::Value> MoonToString(const v8::Arguments &args);
+    static v8::Handle<v8::Value> ConstructLocal(double zd, double az, v8::Handle<v8::Value> time=v8::Handle<v8::Value>());
+    static v8::Handle<v8::Value> ConstructSky(double ra, double dec, v8::Handle<v8::Value> time=v8::Handle<v8::Value>(), bool ismoon=false);
+    static v8::Handle<v8::Value> MoonDisk(const v8::Arguments &args);
+    static v8::Handle<v8::Value> LocalToSky(const v8::Arguments &args);
+    static v8::Handle<v8::Value> SkyToLocal(const v8::Arguments &args);
+    static v8::Handle<v8::Value> MoonToLocal(const v8::Arguments &args);
+    static v8::Handle<v8::Value> ConstructorMoon(const v8::Arguments &args);
+    static v8::Handle<v8::Value> ConstructorSky(const v8::Arguments &args);
+    static v8::Handle<v8::Value> ConstructorLocal(const v8::Arguments &args);
 
     static v8::Handle<v8::Value> FuncVersion(const v8::Arguments&);
