Tuesday, January 31, 2012

Animated GIF image Field With Text

This is a sample code for an animated GIF image field with a text at the bottom:
import net.rim.device.api.ui.Color;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.system.EncodedImage;
import net.rim.device.api.system.GIFEncodedImage;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.component.BitmapField;

//A field that displays an animated GIF.

public class ImageTextField extends BitmapField
{
    private GIFEncodedImage gifimage;     //The image to draw.
    private String text;
    private int currentFrame;          //The current frame in the animation sequence.
    private AnimatorThread animatorThread;
    
    private final int vSpace = 6; 
 private final int padding = 5;
 
 private int xImage = 0;
 private int yImage = 0;
 private int xText = 0;
 private int yText = 0;
    
    public ImageTextField(EncodedImage image, String txt)
    {
     super(image.getBitmap(), 0);
     byte[] arr = image.getData();
  gifimage = (GIFEncodedImage) EncodedImage.createEncodedImage(arr, 0, arr.length);
  text = txt;
  
  animatorThread = new AnimatorThread(this);
        animatorThread.start();
    }
    
    public ImageTextField(EncodedImage image, String txt, long style)
    {
     super(image.getBitmap(), style);
     byte[] arr = image.getData();
  gifimage = (GIFEncodedImage) EncodedImage.createEncodedImage(arr, 0, arr.length);
  text = txt;
  
 animatorThread = new AnimatorThread(this);
        animatorThread.start();
    }
    
    public int getPreferredWidth() {
  return (gifimage==null ? 0 : gifimage.getWidth()) + 50;
    }


 public int getPreferredHeight() {
  int imageHeight = gifimage==null ? 0 : gifimage.getHeight();
  int textHeight = getFont().getHeight();
  return imageHeight + vSpace + textHeight + 2 * padding;
 }
 

 protected void layout(int width, int height) {
  width = Math.min(width, getPreferredWidth());
  height = Math.min(getPreferredHeight(), height);
  
  int imageWidth = (gifimage==null ? 0 : gifimage.getWidth());
  int imageHeight = (gifimage==null ? 0 : gifimage.getHeight());

  xImage = (width - imageWidth) / 2;
  yImage = padding;

  xText = (width - getFont().getAdvance(text)) / 2;
  yText = yImage + imageHeight + vSpace;

  setExtent(width, height);
 }

    protected void paint(Graphics graphics)
    {

        graphics.drawImage(xImage, yImage,
        gifimage.getFrameWidth(currentFrame), gifimage.getFrameHeight(currentFrame), gifimage, currentFrame, 0, 0);
        
        int oldColor = graphics.getColor();
        graphics.setColor(Color.WHITE);
        graphics.drawRoundRect(0, 0, getWidth(), getHeight(), 5, 5);
        graphics.drawText(text, xText, yText);
        graphics.setColor(oldColor);
    }

    //Stop the animation thread when the screen the field is on is
    //popped off of the display stack.
    protected void onUndisplay()
    {
        animatorThread.stop();
        super.onUndisplay();
    }


    //A thread to handle the animation.
    private class AnimatorThread extends Thread
    {
        private ImageTextField theImageField;
        private boolean keepGoing = true;
        private int totalFrames;     //The total number of frames in the image.
        private int loopCount;       //The number of times the animation has looped (completed).
        private int totalLoops;      //The number of times the animation should loop (set in the image).

        public AnimatorThread(ImageTextField theField)
        {
            theImageField = theField;
            totalFrames = gifimage.getFrameCount();
            totalLoops = gifimage.getIterations();

        }

        public synchronized void stop()
        {
            keepGoing = false;
        }

        public void run()
        {
            while(keepGoing)
            {
                //Invalidate the field so that it is redrawn.
                UiApplication.getUiApplication().invokeAndWait(new Runnable()
                {
                    public void run()
                    {
                        theImageField.invalidate();
                    }
                });

                try
                {
                    //Sleep for the current frame delay before
                    //the next frame is drawn.
                    sleep(gifimage.getFrameDelay(currentFrame) * 10);
                }
                catch (InterruptedException iex)
                {} //Couldn't sleep.

                //Increment the frame.
                ++currentFrame;

                if (currentFrame == totalFrames)
                {
                    //Reset back to frame 0 if we have reached the end.
                    currentFrame = 0;

                    ++loopCount;

                    //Check if the animation should continue.
                    if (loopCount == totalLoops)
                    {
                        keepGoing = false;
                    }
                }
            }
        }
    }
}
Now this animated image field can be added to a manager:
VerticalFieldManager mainLayout = getCustomManager();
mainLayout.setBackground(BackgroundFactory.createSolidBackground(Color.BLACK));
EncodedImage ec = EncodedImage.getEncodedImageResource("myimage.gif");
ImageTextField ag = new ImageTextField(ec, "My Text", FIELD_HCENTER);
mainLayout.add(ag);

Tuesday, January 10, 2012

Calculate Distance on Sphere ( Given latitude & longitude values)

This is the code for calculating the distance between two given points by their latitude and longitude values.
public static double getOrthodromicDistance(
   double lat1,
   double lon1,
   double lat2,
   double lon2)
 {
  double R = 6371.0; // km
  double dLat = convertDegreeToRadians((lat2 - lat1));
  double dLon = convertDegreeToRadians((lon2 - lon1));
  lat1 = convertDegreeToRadians(lat1);
  lat2 = convertDegreeToRadians(lat2);

  double a =  Math.sin(dLat / 2) * Math.sin(dLat / 2) +
     Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(lat1) * Math.cos(lat2);
  double c = 2 * MathUtilities.atan2(Math.sqrt(a), Math.sqrt(1 - a));
  double distance = R * c;
  return distance;
 }

The formula was taken from here.

The MathUtilities.atan2() method is found only in BlackBerry API 4.6 or higher See The definition of atan2 here
This can also be calculated like this:
double atan2t(double y, double x) {
    double lo, hi, res, val, resval;
    double ERR = 1e-9;
    if (Math.abs(x) < ERR) {
        if (Math.abs(y) >= ERR) {
            return ((y / Math.abs(y)) * PI / 2.0);
        } else {
            return (0.0);
        }
    }

    val = Math.abs(y / x);
    lo = 0.0;

    hi = PI / 2;
    res = (lo + hi) / 2.0;
    resval = Math.tan(res);

    while (Math.abs(hi - lo) > ERR) {
        if (resval > val) {
            hi = res;
        } else {
            lo = res;
        }

        res = (hi + lo) / 2.0;
        resval = Math.tan(res);
    }

    if (x < 0.0) {
        res = PI - res;
    }

    if (Math.abs(y) >= ERR) {
        return ((y / Math.abs(y)) * res);
    } else {
        return res;
    }
}