Introduction
This is an Android application for drawing a radar screen using user's data like measuring data from sensors. You can simply draw a life-like radar screen by using this control.
This control will be displayed by three kinds of data, the first is data on a previous scanning stage, the second is data on a current scanning stage, and the last will be the average for previous and current values. If necessary, it can be changed to control shape that is a half circle screen having 0~180 degrees operating ranges or a full circle having 0~360 degrees.
Background
In my project to build a mobile robotic system, I needed to visualize measuring data from a sensor. Meanwhile, I was finding a similar project on surfing the Internet. What I found out was Larry's homepages (http://luckylarry.co.uk) But that example is of no use to me since that program is PC based code with the processing (the compiler developed by the non-profit foundation). So, I decided to develop newly a data visualization program based on Android system because there is a plan to develop the robotic system remotely controlled by a mobile device. However, because of being helped much by Larry's homepages, I express my gratitude for Mr. Larry.
Using the Code
This code is used simply by your project. First RadarView.java is added to your project. Then you edit resources file of the activity file that you want to display.
Definition
enum radarColor{LAY, PREVSWEEP,
CURSWEEP, AVRSWEEP}
| This is an enum value for the setting color of scanned values. |
void setDisplayColor(radarColor what,
int color)
| A color variable will be set by Color.argb() , this has properties of alpha, red, green, blue. |
void setDrawMode(boolean bPreSweep,
boolean bCurSweep ,boolean bAvrSweep)
| This is the option whether each value for three kinds of data is visible or not.
bPreSweep : Previous data visualization is enabled or disabled
bCurSweep : Current data visualization is enabled or disabled
bAvrSweep : Average data visualization is enabled or disabled [Average = (Previous data+Current data)/2] |
void setHalfSweep(boolean ck) | If a input variable is true Display screen will be half-circle, else it will be Full-circle. Display data range is 0 to 180 degrees for a half circle and 0 to 360 degree for a full circle.
[input: true] half-circle mode
[input: false] full-circle mode |
void setMaxDistance(int val) | This function is used to set maximum indicate value for detecting distance.
val : maximum distance. |
void setValue(int index, int val) | This is a function for setting current value.
index : a scanning angle with degree
val : a detecting value for distance |
Resource
Add resource as below code in your layout.xml file. You have to change this package name (com.example.bskim
).
="1.0"="utf-8"
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
....
tools:context="com.example.myradarctrlapp.MainActivity">
<com.example.bskim.RadarView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/RadarView"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_alignParentBottom="true">
</RelativeLayout>
Implementation
full scan half scan
RadarView Class (RadarView.java)
Scanned data is described by solid line from origin to sensing point. The line length is the distance between sensor and any object and the angle of line is detected orientation from base line(x-axis).
Sweep motion for detecting object is implemented by fan-shape.
public class RadarView extends View {
......
void DrawDisplay(Canvas canvas, int radius, int centerx, int centery) {
float x, y;
boolean clockwise = false;
float ratio = (float)radius/ (float)widthp*3.0f;
int textsize = (int)(25.0* ratio);
if ( (dectAngle - oldDectAngle) >= 0) {
clockwise = false;
} else {
clockwise = true;
}
Paint paint=new Paint();
paint.setStyle(Paint.Style.FILL_AND_STROKE);
if(mbPrevSweep == true) {
paint.setARGB(64, 0, 32, 0);
Path path1st = new Path();
path1st.reset();
path1st.moveTo(centerx, centery);
for (int i = 0; i < sweepAngle; i++) {
x = centerx + (int) (Math.cos(Math.toRadians((-i))) * ((float) oldDistValue[i]));
y = centery + (int) (Math.sin(Math.toRadians((-i))) * ((float) oldDistValue[i]));
path1st.lineTo(x, y);
}
canvas.drawPath(path1st, paint);
}
if(mbCurSweep == true) {
paint.setARGB(128, 0, 200, 0);
Path path2nd = new Path();
path2nd.reset();
path2nd.moveTo(centerx, centery);
for (int i = 0; i < sweepAngle; i++) {
x = centerx + (int) (Math.cos(Math.toRadians((-i))) * ((float) distValue[i]));
y = centery + (int) (Math.sin(Math.toRadians((-i))) * ((float) distValue[i]));
path2nd.lineTo(x, y);
}
canvas.drawPath(path2nd, paint);
}
if(mbAvrSweep == true) {
paint.setStyle(Paint.Style.STROKE);
paint.setARGB(255, 0, 0, 255);
Path pathavg = new Path();
pathavg.reset();
pathavg.moveTo(centerx, centery);
for (int i = 0; i < sweepAngle; i++) {
x = centerx + (int) (Math.cos(Math.toRadians((-i))) *
((float) ((distValue[i] + oldDistValue[i]) / 2)));
y = centery + (int) (Math.sin(Math.toRadians((-i))) *
((float) ((distValue[i] + oldDistValue[i]) / 2)));
pathavg.lineTo(x, y);
}
canvas.drawPath(pathavg, paint);
}
if(mbSweepMotion==true) {
paint.setAntiAlias(true);
paint.setStrokeWidth(7);
int gradationAngle = 30;
if(dectAngle < gradationAngle) gradationAngle = dectAngle;
if(dectAngle> (sweepAngle-gradationAngle)) gradationAngle = sweepAngle-dectAngle;
if (clockwise == false) {
for (int i = gradationAngle; i >= 0; i--) {
if(i==0)
paint.setColor(mLayColor);
else paint.setARGB(128, 150+(100/gradationAngle * i),
150+(100/gradationAngle * i), 150+(100/gradationAngle * i));
canvas.drawLine(centerx, centery, centerx +
(int)(Math.cos(Math.toRadians(-dectAngle + (i))) *
(float)radius), centery + (int) (Math.sin(Math.toRadians(-dectAngle + (i))) *
(float)radius), paint);
}
} else {
for (int i = 0; i <= gradationAngle; i++) {
if(i==0)
paint.setColor(mLayColor);
else paint.setARGB(128, 150+(100/gradationAngle * i),
150+(100/gradationAngle * i), 150+(100/gradationAngle * i));
canvas.drawLine(centerx, centery, centerx +
(int) (Math.cos(Math.toRadians(-dectAngle + (-i))) * (float) radius),
centery + (int) (Math.sin(Math.toRadians(-dectAngle + (-i))) *
(float) radius), paint);
}
}
}
......
}
}
By changing a scanning orientation, the shadow's direction for scanning motion will be changed.
Clockwise Scan (180o,179o,....,2o,1o,0o) Counter-Clockwise Scan (0o,1o,2o,....,179o,180o)
Create View and Example of this Use
Create the object instance of RadarView
and configure its properties.
For example, Full-circle mode, Scanning line color is green. A scanning distance range is set by constant value, MAX_DISTANCE
and we can get a resource from pre-defined XML file as using findViewById()
. R.id.RadarView
is defined as android:id="@+id/RadarView"
in layout.xml.
RadarView mRadarView;
mRadarView = (RadarView) findViewById(R.id.RadarView);
mRadarView.setHalfSweep(false);
mRadarView.setDisplayColor(RadarView.radarColor.LAY, Color.argb(255,0,255,0));
mRadarView.setMaxDistance(MAX_DISTANCE);
mRadarView.setSweepMotion(true);
The below code shows the usage of this class. The data buffer to be drawn is filled by setValue(..)
and it is used handler so that view is updated safely.
TimerTask mTask;
Timer mTimer;
mTask = new TimerTask() {
@Override
public void run() {
if(mRadarView.isHalfMode()==true) {
if (angle > 180) flag = 0;
if (angle <= 0) flag = 1;
if (flag == 0) angle--;
else angle++;
}else {
if(angle>360) angle = 0;
else angle++;
}
int distance = mRandVal.nextInt(MAX_DISTANCE);
mRadarView.setValue(angle, distance);
RadarViewInvalidate();
}
};
mTimer = new Timer();
mTimer.schedule(mTask, 500, 100);
After you input new data from sensor by using setValue(..)
, you should call RadaViewInvalidate()
to update view.
Handler mDrawHandler = new Handler();
private void RadarViewInvalidate() {
mDrawHandler.post(new Runnable() {
@Override
public void run() {
mRadarView.invalidate();
}
});
}
That's it! I hope you could follow me easily. Thanks to everyone for reading this article.
Points of Interest
I would like to pay attention to creating a new graphic view class and a resource.
History
This article will be updated soon.