Go Back   Forums > Community Chatterbox > Tech Corner > Programming
Memberlist Forum Rules Today's Posts
Search Forums:
Click here to use Advanced Search

Reply
 
Thread Tools Display Modes
Old 24-09-2010, 10:26 PM   #1
Japo
Autonomous human
 
Japo's Avatar


 
Join Date: Mar 2006
Location: ,
Posts: 4,613
Default Japo's code

Most of the programs I make at work are not suitable or interesting to post here, but I have also made some reusable libraries, and some curious side projects.

I'll start with one of the latter, made in Maple. It calculates the equations of the position of the Sun, relative to any point on the Earth, as a function of the time of the year.

Code:
# speed of Earth's orbit in rad/h
oo_t:= evalf(2*Pi/(365.25*24)):

# speed of Earth's rotation in rad/h
oo_r:= evalf(2*Pi/24):

# tilt of Earth's rotation axis
tilt:= evalf(23.44*Pi/180):

# latitude: 41º 38' N
lat:= evalf(( 41 + 38 /60)*Pi/180):

# longitude: 4º 43' W
lon:= evalf(( -4 - 43 /60)*Pi/180):

x:= evalf(Vector(3,  [cos(oo_t*t),  -sin(oo_t*t),  0])):

# changes of basis
B:= simplify(evalf(Matrix(3,  3,  [
cos(tilt),  0,  sin(tilt),  
0, 1, 0, 
-sin(tilt), 0, cos(tilt)
]).Matrix(3, 3, [
cos(oo_r*t), -sin(oo_r*t), 0, 
sin(oo_r*t), cos(oo_r*t), 0, 
0, 0, 1
]).Matrix(3, 3, [
cos(lon), -sin(lon), 0, 
sin(lon), cos(lon), 0, 
0, 0, 1
]).Matrix(3, 3, [
sin(lat), 0, cos(lat), 
0, 1, 0, 
-cos(lat), 0, sin(lat)
]))^%T):

# finally, parametric equation of position
r:= simplify(B.x):
The algebra behind it is sketched here:


(click)


The purpose is to know the position of the sun at any hour of any day of the year, but I think the most visual result is had by plotting the Sun's trajectory along a whole year.

Code:
plots[spacecurve]( r, t=0..365.25*24, numpoints=87660, axes=normal, labels=["S-N", "E-W", "z-n"], tickmarks=[0, 0, 0], shading=zhue, thickness=2, orientation=[130, 60]);
For example in Valladolid, Spain:


(click)


One axis goes from South to North, another from East to West, and the other is the verticality. The colours colder than blueish green are below the horizon--it's night.

Another example: the Equator, you can see why there's no Summer or Winter over there:


(click)


And Murmansk, Russia, above the Arctic Circle. Notice how the Sun doesn't set during some Summer days, and it doesn't dawn during some Winter ones.


(click)
__________________
Life starts every day anew. Prospects not so good...

Last edited by Japo; 24-09-2010 at 10:46 PM.
Japo is offline                         Send a private message to Japo
Reply With Quote
Old 26-09-2010, 01:17 PM   #2
Japo
Autonomous human
 
Japo's Avatar


 
Join Date: Mar 2006
Location: ,
Posts: 4,613
Default xThreading 1

Something more useful today. My preferred programming framework is .NET, and my preferred language C#. With .NET it's very easy to take do multi-threading, so you can perform tasks in parallel, taking advantage of modern CPUs; and most important, so your user interface doesn't stop responding whenever you have to perform a task that takes some time, instead you can perform it in the background while the UI thread goes on in parallel.

Even though the .NET class library does most of the work, I made a little library to take care of some common tasks when multi-threading and cross-threading, I called it "xThreading".

First it has a simple extension method to make thread-safe calls to Controls (actually any ISynchronizeInvoke) as detailed here. The arguments it takes are a delegate to the method that you want to run in the Control's thread, and the parameters, if any. (I provided an overload for the frequent case when the method has no parameters nor return value--is a System.Action delegate--because just "Delegate" isn't strongly typed (System.Delegate is abstract) and you'd need an instantiated delegate every time you used this, but the compiler can't infer it because Delegate is abstract. You could make additional overloads for other recurrent situations.)

Code:
using System;
using System.ComponentModel;

namespace SEADM.xThreading
{
   public static class xExtensions
   {
      public static object xInvoke(this ISynchronizeInvoke thread,
         Delegate method, params object[] args)
      {
         if(args.Length == 0) args = null; // if the Delegate takes no arguments
            // we must pass null to ISynchronizeInvoke.Invoke() or Delegate.DynamicInvoke(),
            // not an empty array.

         if(thread.InvokeRequired)
            return thread.Invoke(method, args);
         else
            return method.DynamicInvoke(args);
      }

      // Handy overload:
      public static void xInvoke(this ISynchronizeInvoke thread,
         Action method)
      { xInvoke(thread, method, null); }
   }
}
So let's say you have a reference to a Form called "frm" for example, and you want to close it from a different thread from where the Form was created. You can't call frm.Close() directly, you'll get an exception if debugging, and things will probably hang if you're running the program normally. Using the xInvoke() extension method you can write instead
Code:
frm.xInvoke( () => frm.Close() );
OK it's still verbose and clumsy and hard to look at. That's why this library defines some classes in addition to this method, that I'll post right away. But I still leave xInvoke() public, so I have flexibility to make the calls I want. Specially if you want to access several members of a Control in one go, since each cross-thread call is in principle bad for performance, it's best to bundle everything you want to do with the Control into a single Delegate, and just pass it to xInvoke():
Code:
frm.xInvoke( () =>
{
   frm.lbl.Text = "Done! :)";
   frm.btn.Enabled = true;
   // etc...
} );
It's OK to access child Controls for example, provided they were created in the same thread as their Parent.
__________________
Life starts every day anew. Prospects not so good...

Last edited by Japo; 05-01-2011 at 06:38 PM. Reason: added overload
Japo is offline                         Send a private message to Japo
Reply With Quote
Old 26-09-2010, 01:56 PM   #3
Japo
Autonomous human
 
Japo's Avatar


 
Join Date: Mar 2006
Location: ,
Posts: 4,613
Default xThreading 2

So what I wanted at this point, were classes that presented the same properties and methods as the different Controls. I want them to reference cross-thread Controls, and when anyone calls their members as if they were the Controls themselves, under the hood they'll be using xInvoke() to make the calls in a thread-safe way.

For example, having created one of these objects referencing our Form,
Code:
xfrm = new xForm(frm);
at any other time in any other place where we want to close the form, we just have to write
Quote:
xfrm.Close();
We're not calling Close() in the Form, but a like called method in the xForm that references it, which will make everything necessary under the hood.

Of course I haven't implemented all the functionality of Windows Forms in the corresponding xControls; actually I have defined very little classes with very little members, whatever I have needed myself so far. For example:
Code:
using System.Windows.Forms;

namespace SEADM.xThreading
{
   public class xForm:xISynchronizeInvoke<Form>
   {
      public xForm(Form reference)
         :base(reference) { }

      public void Close() { methodCall("Close"); }
   }

   public class xLabel:xISynchronizeInvoke<Label>
   {
      public xLabel(Label reference)
         :base(reference) { }

      public string Text {
         get { return (string)propertyGet("Text"); }
         set { propertySet("Text", value); }
      }
   }
}
How does that even work? Of course all the functionality is in that (generic) xISynchronizeInvoke class that xForm (and every other "xControl") inherits. I could have done everything without a base class with xInvoke, and as you'll see it would have meant less run-time overhead, but meh. This way it's very easy to extend xControls and write new ones.

Here goes xISynchronizeInvoke<T>, be warned, lots of reflection going on:
Code:
using System;
using System.ComponentModel;

namespace SEADM.xThreading
{
   public abstract class xISynchronizeInvoke<T>
      where T :ISynchronizeInvoke
   {
      private ISynchronizeInvoke xThis;

      protected xISynchronizeInvoke(T reference)
      {
         xThis = reference;
      }
      
      protected object methodCall(string methodName, params object[] arguments)
      {
         return xThis.xInvoke(new Func<object>( () => {
            return xThis.GetType().GetMethod(methodName).Invoke(xThis, arguments);
         } ));
      }

      protected object propertyGet(string propertyName)
      {
         return xThis.xInvoke(new Func<object>( () => {
            return xThis.GetType().GetProperty(propertyName).GetValue(xThis, null);
         } ));
      }

      protected void propertySet(string propertyName, object value)
      {
         xThis.xInvoke( () =>
            xThis.GetType().GetProperty(propertyName).SetValue(xThis, value, null) );
      }
   }
}
__________________
Life starts every day anew. Prospects not so good...

Last edited by Japo; 05-01-2011 at 06:27 PM.
Japo is offline                         Send a private message to Japo
Reply With Quote
Old 26-09-2010, 02:47 PM   #4
Japo
Autonomous human
 
Japo's Avatar


 
Join Date: Mar 2006
Location: ,
Posts: 4,613
Default xThreading 3

And then I wanted another thing--actually this was the first one I wanted to make, and what got me into authoring the rest, that this is built onto. I wanted a splash window to show while a parallel task is carried out in the background, but I wanted the background task to be able to show its status in the splash screen.

Here it is. The constructor takes a delegate to the action you want to perform in parallel, and just creating the splash window starts the task immediately. You won't even need to keep a reference to the window most times, as it closes itself down when the task is done; so even this minimal statement works:
Code:
new xSplash(method);
without assigning a reference to the created method to any variable. The "method" has to match the Action<xLabel> delegate.

The class doesn't provide for returning values from the Task (an System.Action<> returns void), passing parameters to it, or cancelling it from the main thread, simply because I haven't needed it; although it wouldn't be hard to add that.

By the way, if a parallel thread throws an exception, it doesn't reach the main thread immediately. But with xSplash, every time you click on it, it will check the task for exceptions, and if there's any it will be thrown back into the main thread; if there's none, nothing will happen. (I guess if the user sees that the task is taking too long and the splash window remains there forever without reporting any change of status, he will instinctively click on it.)

Here's the code:
Code:
using System.Windows.Forms;
using System.Threading.Tasks;

namespace SEADM.xThreading
{
   public class xSplash:Form
   {
      Task guest;

      Label lbl;

      public xSplash(Action<xLabel> method)
      {
         InitializeComponent();
         var frmSplash = new xForm(this);
         var lblSplash = new xLabel(lbl);
         guest = Task.Factory.StartNew( () =>
         {
            method(lblSplash);
            frmSplash.Close();
         } );
         MouseDown += frm_Click;
         lbl.MouseDown += frm_Click;
         Show();
      }

      void frm_Click(object sender, MouseEventArgs e)
      {
         if(guest.IsFaulted) throw guest.Exception;
         // don't use Task.Wait() instead, in case
         // the splash is clicked before guest is through.
      }
   }
}
Notice that the delegate taken by the constructor requires one argument, and the argument to that delegate will be provided by xSplash, it's actually a xLabel to its own Label, which will display the status of the task. At every point of the function pointed by the delegate, that you want to report the status, you simply assign the Text property of the xSplash parameter.

There's actually more code of course (InitializeComponent() etc.), what was written automatically with the Visual Studio designer, including non default values for some properties, to make the splash window look the way I wanted--even though it's really nothing fancy and has no graphics etc. I used dynamic layout (everyone should), so the label and the window resize automatically according to the text, depending of the system font size etc.

Also you shouldn't let the user close the window, in principle, otherwise when the task is finished and it tries to close it again, you'll get an exception--and without the splash you won't have any way to retrieve it.
__________________
Life starts every day anew. Prospects not so good...

Last edited by Japo; 05-01-2011 at 06:34 PM.
Japo is offline                         Send a private message to Japo
Reply With Quote
Reply


Similar Threads
Thread Thread Starter Forum Replies Last Post
Japo's status report Japo Introductions, Farewells and Returns 30 05-10-2012 08:14 PM
Code Share Burger Meister Programming 5 10-02-2009 07:22 AM
Somebody Who Knows Php Code? andy_blah Blah, blah, blah... 14 11-06-2006 03:11 AM
Need The Code.... TalonStriker Troubleshooting 1 14-04-2006 07:21 PM


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump
 


The current time is 06:01 PM (GMT)

 
Powered by vBulletin® Version 3.7.1
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.