Saturday, October 1, 2011

Part 7: Thoughts of “How we do?” - Reading from Near vs Far


Say you are traveling in a bus and trying to read a board on both sides of the road. First board is on the same side where you are traveling and the second board on the other side of the road. Both has same text. And the board on the opposite side has enough font size to read it from the bus which you are traveling. Normally we can only star reading once we come inside the visual angle of the board.

Assume you are reading both boards in two different situation from start to end while bus moving in same speed. You will understand that, you can read more from the board which is in the opposite side. So when we are traveling, without reducing our speed, we can't read more from near, rather from far we can. But the distance should be enough to identify the letters, that all.

Now, let see how we can apply this into a real life situations.

Team leaders, if your team members are currently working in a project with a constant speed. And you are hearing some new project opportunity. It is not good to wait until your project got confirm and then bring it to the members to their close attention. Because members have to slowdown their current project in order to prepare the new project. Instead of that, if you let them prepare the new project early as possible in a relax mode,  this will not much affect the current project speed.

Here one of the different between close attention and relax mode would be, in close attention team leader will expect and check for updates very frequently, rather in relax mode leader could wait until the team member bring updates to leaders' table or expect and check update occasionally.

One concern may be: change in the project detail will make the preparation waste, but that is not fully true. Because if we have already prepared and then you summaries the different from early draft we don't need much effect to override the new changes. If the project details totally change, then of cause all the initial preparation is waste. Mostly that not the case.

But for the success of relax mode approach, team member should have enough skill level. They should be proactive to prepare project in early stage, self motivated to prepare project and provide updates. They should be able manage and balance work load in preparation new project with the current project.

Feather more, letting the team member to prepare the project early will lead to understand any unclear or impossible areas in the project so that the project could be modify accordingly. This will help in project executions very much.

So, I feel it is better to do go for a early preparation of new project. Both team leaders and members should understand the pros and cons in this approach and should act accordingly. This will bring a best team and best product in the end.

Let me find out another real example as above and meet you another post. Bye 

Android : Drawing View with shapes plotted in r theta (r,θ) relation

r = 0.875*width/2+0.125cos(12θ)
r - width/2*cos(4θ)
r - width/2
Say you want to create views which contains shares as shown above. In those each circle drawn in (r,θ) relation. I implemented following onDraw method with possible two options.
Option 1. Rotating canvas and drawing circles - this is direct use of (r , θ)
Option 2. Converting points into x,y plan coordinate and drawing the circle.


@Override
protected void onDraw(Canvas canvas) {
float width = getWidth()/2;
float height = getHeight()/2;
Paint paint = new Paint();
paint.setColor(Color.RED);
        //Option 1
long time = System.currentTimeMillis();
canvas.save();
canvas.translate(width, height);
for(int i = 0 ; i < 13;i++){
canvas.drawCircle(width, 0, width*0.2f, paint);
canvas.rotate(-15);
}
canvas.restore();
Log.i(TAG, "::onDraw:" + "time 1 = " + (System.currentTimeMillis()-time));
        //Option 2
long time1 = System.currentTimeMillis();
canvas.save();
canvas.translate(width, height);
float angle = 0;
for(int i = 0 ; i < 13;i++){
float radian = (float) (Math.PI*angle/180.0f);
canvas.drawCircle((float) (width*Math.cos(radian)),
(float) (width*Math.sin(radian)), width*0.2f, paint);
angle+=15;
}
canvas.restore();
Log.i(TAG, "::onDraw:" + "time 2 = " + (System.currentTimeMillis()-time1));
}

Since above coding draw only 13 circles, I couldn't find a clear different in execution time for both options. So I change the code to draw 180 circle as follows:


@Override
protected void onDraw(Canvas canvas) {
float width = getWidth()/2;
float height = getHeight()/2;
Paint paint = new Paint();
paint.setColor(Color.RED);
long time1 = System.currentTimeMillis();
canvas.save();
canvas.translate(width, height);
for(int i = 0 ; i < 180;i++){
float radius = width;
canvas.drawCircle(radius, 0, 2.0f, paint);
canvas.rotate(-1);
}
canvas.restore();
time1 = System.currentTimeMillis()-time1;
long time2 = System.currentTimeMillis();
canvas.save();
canvas.translate(width, height);
for(int i = 0 ; i < 180;i++){
float radian = (float) (Math.PI*i/180.0f);
float radius = width;
canvas.drawCircle((float) (radius*Math.cos(radian)),
(float) (radius*Math.sin(radian)), 2.0f, paint);
}
canvas.restore();
time2 = System.currentTimeMillis()-time2;
Log.i(TAG, "::onDraw:" + "time1,time2, (time1-time2) = "
+ time1 + ","+time2+","+(time1-time2));
}

Now i could see clear different and Option 2 is faster than Option 1.



INFO/demo.theta.DemoRTheta(5302): ::onDraw:time1,time2, (time1-time2) = 62,35,27
INFO/demo.theta.DemoRTheta(5302): ::onDraw:time1,time2, (time1-time2) = 66,36,30
INFO/demo.theta.DemoRTheta(5302): ::onDraw:time1,time2, (time1-time2) = 66,37,29
INFO/demo.theta.DemoRTheta(5302): ::onDraw:time1,time2, (time1-time2) = 63,35,28
INFO/demo.theta.DemoRTheta(5302): ::onDraw:time1,time2, (time1-time2) = 68,34,34
INFO/demo.theta.DemoRTheta(5302): ::onDraw:time1,time2, (time1-time2) = 63,35,28
INFO/demo.theta.DemoRTheta(5302): ::onDraw:time1,time2, (time1-time2) = 61,35,26
INFO/demo.theta.DemoRTheta(5302): ::onDraw:time1,time2, (time1-time2) = 59,35,24
INFO/demo.theta.DemoRTheta(5302): ::onDraw:time1,time2, (time1-time2) = 68,40,28
INFO/demo.theta.DemoRTheta(5302): ::onDraw:time1,time2, (time1-time2) = 75,32,43
INFO/demo.theta.DemoRTheta(5302): ::onDraw:time1,time2, (time1-time2) = 65,32,33
INFO/demo.theta.DemoRTheta(5302): ::onDraw:time1,time2, (time1-time2) = 52,36,16


Here you have expresions for other above graphs. 

float radian = (float) (Math.PI*i/180.0f);

float radius = width;
float radius = (float) (width*Math.cos(4*radian));
float radius = (float) (0.875f*width+0.125f*width*Math.cos(12*radian));



But Option 2 needs some extra calculation to translate  (r , θ) into (x, y), in above examples we needed to determine only center of the circle.
Let see some of the view as follows.
canvas.save();
canvas.translate(width, height);
for(int i = 0 ; i < 72;i++){
canvas.drawLine(width*0.8F, 0, width*1.0f, 0, paint);
canvas.rotate(5);
}
canvas.restore();

Now we have to find start x,y and end x,y that need extra calculation and extra analysis effect to come up with that expresion.
Next one is more interesting need to use Path.

canvas.save();
canvas.translate(width, height);
for(int i = 0 ; i < 18;i++){
Path path = new Path();
path.moveTo(width*0.8F, 0);
path.lineTo(width, width*0.1F);
path.lineTo(width, -width*0.1F);
path.lineTo(width*0.8F, 0);
canvas.drawPath(path, paint);
canvas.rotate(20);
}
canvas.restore();

Now you can find translation expression and can find out which one is faster in each cases.
Enjoy!

Tuesday, September 27, 2011

Grid, Adaptor, left to right into top to bottom

Say we have list of object as follows,
list =
.size() = 14
and need to show it in grid control that scroll vertically as follows,
// assume we want three columns.
int columns = 3;
// first calculate number of rows.
int rows = (columns-1+list.size())/columns;

Or into grid control that scroll horizontally as follows,
//assume we want three rows.
int rows = 3;
// first calculate number of rows.
int columns = (rows-1+list.size())/rows;

Mostly we use adaptor to fetch the item to show in each cell.
In this case adaptor can choose the index equal to position, 

int index = position;
return list.get(index); 

But say some cases we may have to change to order in display. for example. top to bottom as shown below:
But if the control fetch base on position from left to right as show below:
then, we need to add proper calculation inside the adaptor:

int index =position/columns+position%columns*rows;
return list.get(index); 

Thursday, September 15, 2011

Android: Aligning Custom Views at Base Line

Have you ever try to align a non-symmetric custom view at a custom base line as follows?


I tried it using base line attribute of Relative Layout.
First adjust the size of view:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//Height should be always width * 7 / 12
setMeasuredDimension(getMeasuredWidth(), getMeasuredWidth()*7/12);
}


Then Override the getBaseLine method:
@Override
public int getBaseline() {
//base line is from bottom to width/12 (radius of the blue circle)
return getMeasuredHeight()-getMeasuredWidth()/12;
}


Following onDraw method would explain the reason for the above calculation:

@Override
protected void onDraw(Canvas canvas) {
Paint paint = new Paint();
paint.setAntiAlias(true);
//Draw the half circle
paint.setColor(Color.GRAY);
float width = getWidth();
float height = getHeight();
canvas.save();
canvas.translate(width/2, height-width/12);
canvas.drawArc(new RectF(-width/3, -width/3, +width/3, width/3), 0, -180, true, paint);
//Draw small circles
paint.setColor(Color.DKGRAY);
RectF rectF = new RectF(-width/2+width/24, -width/12+width/24, -width/3-width/24,                +width/12-width/24);
canvas.drawOval(rectF, paint);
for(int i = 0 ; i < 15 ;i++){
canvas.rotate(12f);
canvas.drawOval(rectF, paint);
}
//Draw blue circle
paint.setColor(Color.BLUE);
canvas.rotate(-180+30);
canvas.drawOval(new RectF(-width/2, -width/12, -width/3, +width/12), paint);
//Draw red arrow
paint.setColor(Color.RED);
Path path = new Path();
path.moveTo(-width*5/12, 0);
path.lineTo(10, -width/12);
path.lineTo(0, 0);
path.lineTo(10, +width/12);
path.close();
canvas.drawPath(path, paint);
canvas.restore();
}


Finally, create a layout xml as following:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<demo.ui.testing.DemoUITesting
android:layout_height="fill_parent" android:layout_width="fill_parent"
android:layout_alignBaseline="@+id/radioButton1"
android:layout_toRightOf="@+id/radioButton1">
<RadioButton android:layout_width="wrap_content"
android:layout_height="wrap_content" android:id="@+id/radioButton1"
android:layout_centerVertical="true">
</RelativeLayout>

Enjoy!.

Wednesday, September 14, 2011

Android: convert Immutable Bitmap into Mutable

Android provide Bitmap class to manipulate images. We can load, draw, edit or save. But incase of editing bitmap should be mutable.

For example:
Canvas canvas = new Canvas(mBitmap);
Will throw IllegalArgumentException: image is immuable ...

An image file can be loaded in to bitmap using BitmapFactory as follows:

mBitmap = BitmapFactory.decodeFile(path);

But this will be an immutable bitmap. This will not be able to edited.

Anyway can load image using BitmapFactory.decodeFile(path,options);
Here BitmapFactory.Options options = new BitmapFactory.Options();

But from API Level 11 only options.inMutable available to load the file into a mutable bitmap.

So, if we are building application with API level less than 11, then we have to find some other alternatives.

One alternative is creating another bitmap by copying the source bitmap.
mBitmap = mBitmap.copy(ARGB_8888 ,true);

But the will throw OutOfMemoryException if the source file is big. Actually incase if we want to edit an original file, then we will face this issue. We should be able to load at-least image into memory, but most we can not allocate another copy into memory.

So, we have to save the decoded bytes into some where and clear existing bitmap, then create a new mutable bitmap and load back the  saved bytes into bitmap again. Even to copy bytes we cannot create another ByteBuffer inside the memory. In that case need to use MappedByteBuffer that will allocate bytes inside a disk file.

Following code would explain clearly:

//this is the file going to use temporally to save the bytes. 

File file = new File("/mnt/sdcard/sample/temp.txt");
file.getParentFile().mkdirs();

//Open an RandomAccessFile
/*Make sure you have added uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
into AndroidManifest.xml file*/
RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw"); 

// get the width and height of the source bitmap.
int width = bitmap.getWidth();
int height = bitmap.getHeight();

//Copy the byte to the file
//Assume source bitmap loaded using options.inPreferredConfig = Config.ARGB_8888;
FileChannel channel = randomAccessFile.getChannel();
MappedByteBuffer map = channel.map(MapMode.READ_WRITE, 0, width*height*4);
bitmap.copyPixelsToBuffer(map);
//recycle the source bitmap, this will be no longer used.
bitmap.recycle();
//Create a new bitmap to load the bitmap again.
bitmap = Bitmap.createBitmap(width, height, Config.ARGB_8888);
map.position(0);
//load it back from temporary 
bitmap.copyPixelsFromBuffer(map);
//close the temporary file and channel , then delete that also
channel.close();
randomAccessFile.close();

Hope this wil help you.

I have uploaded the sample source code here:
http://dl.dropbox.com/u/7717254/DemoPaint.zip
In which application, user can load a image and draw and save back. In case of saving back to original image size.


Friday, June 10, 2011

எப்படியும் ஒருநாள் எம் முற்றம் மிதிப்போம்தானே!




இருவது வருஷம் ஆச்சு...
இருநூறு வசந்தம் போச்சு...

குண்டுபோட்டு கலைத்தனர் - வந்து
கூரை குலைத்து போயினர்
கல்லை மட்டு விட்டதனால் - வெறும்
கட்டிடமாய் நிண்டு கொண்டு - என்னிடம்
இன்று நீ என்ன தான் கேட்கிறாய்?
இத்தனை நாளாய் நாம் எங்கிருந்தோம் என்றா?

அங்க...
ஆக்கிரமித்தவன் நின்டிருப்பான்,
அவன் கூலிக்காரன் வந்திருப்பான்
வேறுசிலர் கண்டிருப்பாய் - அவர்கள்
வேவுபாக்க நுழைந்திருப்பர் - நமக்காய்
போராட துணிந்தவர்கள்,
படைகள் பல அமைத்தவர்கள்
உயர் பாதுகாப்பிலும்
ஊடுருவ துணிந்தவங்கள்
இவர் எல்லாம் இருந்தும் நானோ...
போராளி ஆகவில்லை
போர்க்களம் ஒன்றும் போகவில்லை

ஊர் ஊராய் ஓடி,
உணவு, உடுப்பு...
அது கிடக்க - அல்லது
அது கிடைக்க,
படிப்பு படிப்பு என்று அலைந்து,
பல்கலைக்கழகம் சென்று, பட்டமும் பெற்று,
பட்டமளிப்பு விழாவுக்கு, பட்டாளத்துடன் போய்
படம் எடுத்து, பெரிசாக்கி - அதுக்கும் சட்டம் போட்டு - கடைசீல
அதை மாட்ட சுவரில்லை
அன்றரிந்தேன் உன்னிலையை.
நீ மட்டும் இல்லை - நானும்
வெறும் கட்டிடம் தானென்று.

அன்று...
நிமிர்ந்து நீ நிக்க, - உன்
நினைவாக எடுத்த படம்
கடைசிமட்டு இருந்ததுதான் - அதுவும்
கடைசி போரில் கைவிட்டு போனதல்லே

உயிர் பயத்தில் நான் இங்கு
உயர் பாதுகாப்பில் நீ அங்கு - அன்று
நிழலுக்காய் நட்டமரம் வேர்விட்டு - இன்று உன்னை
நிலைகுலைக்க போகுதாம்
அந்நிய நாட்டவர் எல்லாம்
அவனோட சேந்து, நாடகம் போட்டு,
அத்தனையும் அளித்துவிட்டு
நடைபிணமாய் எம்மை எல்லாம்
நாட்டை விட்டே துரத்திவிட்டு
எங்கள் சொந்த வீட்டை பாக்க
எமக்கே அனுமதிகுடுக்க
அண்ணாவும், தங்கையும் அத்தானும் - உன்னை
ஆசையா பாக்கவந்து
அத்தனையும் சொன்னார்கள்.
உனக்கு மட்டுமல்ல, உலகத்துக்கும் உதேநிலைதான்

இத்தனை கடந்தும்
இன்றைக்கும் சொல்கிறேன் நான்
எப்படியும் ஒருநாள் எம் முற்றம் மிதிப்போம்தானே!


Saturday, February 12, 2011

Part 6: Thoughts of “How we do?” - Easy to Understand or Efficient in Execution


Task is this, we need to hang advertisement cards on the handrail of this train. But we have two types of advertisement cards say red and blue and the pattern should be like red blue red blue red, red blue red blue red.
Anyway, you are not suppose do this, workers will be given to you, you have to give him instructions and ask him to do.
You have two options to do this:
Option 1:
First give the red advertisement cards to the worker and hang on the start, middle and end of each handrails, then give the blue advertisement cards and ask to hang in between every red advertisement cards.
Option 2:
Ask the worker to arrange the advertisement cards as RBRBRRBRBR... then get one by one from the bundle and hang 5 in each handrail.

Lets check these options; in the 2nd option, we do some prearrangement, that means we have added another layer of abstraction and complexity. Need to analyze and understand that layer and test completely before use. In first option worker has to go along train two times, but in 2nd option if he goes once it is enough, the execution is efficient. But in first option we can start the task immediately or need very less time to analyze and understand. In 2nd option, need to spend some more time before start the task, to analyze and understand , is not easy to understand.

This is a simple example, but you may face lot more complex sample in your life. In business, sometimes, the start time of task is more critical than efficient of execution. for example, in option 1, you may be able to add another worker to hang blue cards. If you spend more time in analyzing then there are chances to loose the business. But sure, you cannot execute the business for long with an inefficient execution, you should analyze and make execution efficient. It is your choice to take according to your situation. But keep in your mind you have these options to choose from.

For programers, here is an example in Android, say you want to resize and crop an image.

Option 1 would be:


intermediate = Bitmap.createScaledBitmap(source, dstWidth, dstHeight, filter);

target = Bitmap.createBitmap(intermidiate, x, y, width, height);


Option 2 would be:


Canvas canvas = new Canvas(target);

Matrix matrix = new Matrix();

matrix.preScale(sx, sy);

matrix.postTranslate(dx, dy);

canvas.drawBitmap(source, matrix, paint);


Sure, there are lot more examples, you can find yourself and enjoy.