经纬度采用度分秒记录其实就是六十进制,采用小数形式一般就是十进制。以下就是实现六十进制与十进制之间的相互转换。
1.怎么把经纬度十进制单位转换成标准的度分秒单位计算公式是,十进制的经度,纬度数的整数部分就是度数(°),小数部分乘以60得到的数取整数部分就是分数(′),再用该数的小数部分乘以60就是秒数(″)。如一个经度的十进制为:117.121806,那么:
第一步:度数(°)117°,
第二步:分数(′)7′(0.121806×60=7.308360189199448,取整数部分为7),
第三步:秒数(″)18.501611351966858″(0.30836018919944763×60=18.501611351966858),即度分秒为117°7′18.501611351966858″。
2.怎么把经纬度度分秒单位转换成十进制单位
将度分秒转换为十进制则刚好相反,将秒数(″)除以60,得到的数就是分数(′)的小数部分,将该小数加上分数(′)整数部
分就是整个分数(′),再将该分数(′)除以60,得到的小数就是度数(°)的小数部分,在加上度数的整数部分就是经纬度的十进制形式。例如,将一个纬度为37°25′19.222″的六十进制转换为十进制的步骤为:
第一步(对应上面的第三步):19.222/60=0.3203666666666667,0.3203666666666667为分数(′)的小数部分,
第二步(对应上面的第二步):25+0.3203666666666667=25.3203666666666667,25.3203666666666667分数(′)
第三步(对应上面的第一步):25.3203666666666667/60=0.4220061111111111,0.4220061111111111为度数(°)的小数部分
37°25′19.222″转换的最终结果为37+0.4220061111111111=37.4220061111111111
3.程序实现(java)
根据原理,程序的实现方式就比较简单了。以下是源代码。
import java.math.BigDecimal;
public class ConvertLatlng {
//经纬度度分秒转换为小数
public double convertToDecimal(double du,double fen,double miao){
if(du<0)
return -(Math.abs(du)+(Math.abs(fen)+(Math.abs(miao)/60))/60);
return Math.abs(du)+(Math.abs(fen)+(Math.abs(miao)/60))/60;
}
//以字符串形式输入经纬度的转换
public double convertToDecimalByString(String latlng){
double du=Double.parseDouble(latlng.substring(0, latlng.indexOf("°")));
double fen=Double.parseDouble(latlng.substring(latlng.indexOf("°")+1, latlng.indexOf("′")));
double miao=Double.parseDouble(latlng.substring(latlng.indexOf("′")+1, latlng.indexOf("″")));
if(du<0)
return -(Math.abs(du)+(fen+(miao/60))/60);
return du+(fen+(miao/60))/60;
}
//将小数转换为度分秒
public String convertToSexagesimal(double num){
int du=(int)Math.floor(Math.abs(num)); //获取整数部分
double temp=getdPoint(Math.abs(num))*60;
int fen=(int)Math.floor(temp); //获取整数部分
double miao=getdPoint(temp)*60;
if(num<0)
return "-"+du+"°"+fen+"′"+miao+"″";
return du+"°"+fen+"′"+miao+"″";
}
//获取小数部分
public double getdPoint(double num){
double d = num;
int fInt = (int) d;
BigDecimal b1 = new BigDecimal(Double.toString(d));
BigDecimal b2 = new BigDecimal(Integer.toString(fInt));
double dPoint = b1.subtract(b2).floatValue();
return dPoint;
}
public static void main(String[] args) {
ConvertLatlng convert=new ConvertLatlng();
double latlng1=convert.convertToDecimal(37, 25, 19.222);
double latlng2=convert.convertToDecimalByString("-37°25′19.222″");
String latlng3=convert.convertToSexagesimal(121.084095);
String latlng4=convert.convertToSexagesimal(-121.084095);
System.out.println("转换小数(数字参数)"+latlng1);
System.out.println("转换小数(字符串参数)"+latlng2);
System.out.println("转换度分秒:"+latlng3);
System.out.println("转换度分秒:"+latlng4);
}
}
复制代码
4.Android程序的实现
其实用android实现经纬度进制的转换才是写这篇文章的初衷。所以写了一个Android客户端的软件,如图-1所示。
这样的软件可能使用性不大,于是添加了一些小功能进去,例如添加复制转换结果,根据当前位置获取经纬度并转换十进制或六十进制。
图-1 android实现经纬度转换的界面
主要功能并不复杂,都是基本的控件使用,代码中也有注解。以下是源代码。
1.ConvertLatlngActivity.java
import java.math.BigDecimal;
import android.app.Activity;
import android.content.Context;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.text.ClipboardManager;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
public class ConvertLatlngActivity extends Activity {
/** Called when the activity is first created. */
TextView result;
EditText du;
EditText fen;
EditText miao;
Button decimal;
EditText latlng;
Button sexagesimal;
Button copy;
Button bydecimal;
Button bySexagesimal;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
result=(TextView)findViewById(R.id.result);
du=(EditText)findViewById(R.id.du);
fen=(EditText)findViewById(R.id.fen);
miao=(EditText)findViewById(R.id.miao);
//转换十进制
decimal=(Button)findViewById(R.id.to_decimal);
decimal.setOnClickListener(decimalClick);
latlng=(EditText)findViewById(R.id.latlng);
//转换六十进制
sexagesimal=(Button)findViewById(R.id.to_sexagesimal);
sexagesimal.setOnClickListener(sexagesimalClick);
//复制结果
copy=(Button)findViewById(R.id.copy);
copy.setOnClickListener(copyClick);
//获取十进制经纬度
bydecimal=(Button)findViewById(R.id.by_decimal);
bydecimal.setOnClickListener(byDecimalClick);
//获取六十进制经纬度
bySexagesimal=(Button)findViewById(R.id.by_sexagesimal);
bySexagesimal.setOnClickListener(bySexagesimalClick);
}
//转换十进制事件响应
OnClickListener decimalClick=new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
String dStr=du.getText().toString();
String fStr=fen.getText().toString();
String mStr=miao.getText().toString();
if(dStr==null||dStr.equals("")){
Toast.makeText(v.getContext(), "The du number is empty!", Toast.LENGTH_SHORT).show();
du.requestFocus();
}else if(fStr==null||fStr.equals("")){
Toast.makeText(v.getContext(), "The fen number is empty!", Toast.LENGTH_SHORT).show();
fen.requestFocus();
}else if(mStr==null||mStr.equals("")){
Toast.makeText(v.getContext(), "The miao number is empty!", Toast.LENGTH_SHORT).show();
miao.requestFocus();
}else{
double d_du=Double.parseDouble(du.getText().toString());
double d_fen=Double.parseDouble(fen.getText().toString());
double d_miao=Double.parseDouble(miao.getText().toString());
String rs=String.valueOf(convertToDecimal(d_du, d_fen, d_miao));
result.setText(rs);
}
}
};
//转换六十进制时间响应
OnClickListener sexagesimalClick=new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
String s=latlng.getText().toString();
if(s==null||s.equals("")){
Toast.makeText(v.getContext(), "The number is empty!", Toast.LENGTH_SHORT).show();
latlng.requestFocus();
}
else{
double num=Double.parseDouble(latlng.getText().toString());
result.setText(convertToSexagesimal(num));
}
}
};
//复制
OnClickListener copyClick=new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
ClipboardManager clip = (ClipboardManager)getSystemService(Context.CLIPBOARD_SERVICE);
clip.setText(result.getText().toString());
}
};
//获取十进制经纬度
OnClickListener byDecimalClick=new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Location location=getCurrentLocation();
if(location!=null){
double lat=location.getLatitude();
double lng=location.getLongitude();
result.setText("Latitude:"+lat+"\nLongitude:"+lng);
}else{
//没有定位
Toast.makeText(v.getContext(), "No position!", Toast.LENGTH_SHORT).show();
}
}
};
//获取六十进制经纬度
OnClickListener bySexagesimalClick=new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Location location=getCurrentLocation();
if(location!=null){
double lat=location.getLatitude();
double lng=location.getLongitude();
result.setText("Latitude:"+convertToSexagesimal(lat)+
"\nLongitude:"+convertToSexagesimal(lng));
}else{
//没有定位
Toast.makeText(v.getContext(), "No position!", Toast.LENGTH_SHORT).show();
}
}
};
private Location getCurrentLocation(){
LocationManager loctionManager;
String contextService=Context.LOCATION_SERVICE;
//通过系统服务,取得LocationManager对象
loctionManager=(LocationManager) getSystemService(contextService);
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);//高精度
criteria.setAltitudeRequired(false);//不要求海拔
criteria.setBearingRequired(false);//不要求方位
criteria.setCostAllowed(true);//允许有花费
criteria.setPowerRequirement(Criteria.POWER_LOW);//低功耗
//从可用的位置提供器中,匹配以上标准的最佳提供器
String provider = loctionManager.getBestProvider(criteria, true);
//获得最后一次变化的位置
Location location = loctionManager.getLastKnownLocation(provider);
//监听位置变化,2秒一次,距离10米以上
loctionManager.requestLocationUpdates(provider, 2000, 10, locationListener);
return location;
}
//位置监听器 空实现
private final LocationListener locationListener = new LocationListener() {
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onProviderDisabled(String provider) {
}
//当位置变化时触发
@Override
public void onLocationChanged(Location location) {
}
};
//经纬度度分秒转换为小数
public double convertToDecimal(double du,double fen,double miao){
if(du<0)
return -(Math.abs(du)+(Math.abs(fen)+(Math.abs(miao)/60))/60);
return Math.abs(du)+(Math.abs(fen)+(Math.abs(miao)/60))/60;
}
//将小数转换为度分秒
public String convertToSexagesimal(double num){
int du=(int)Math.floor(Math.abs(num)); //获取整数部分
double temp=getdPoint(Math.abs(num))*60;
int fen=(int)Math.floor(temp); //获取整数部分
double miao=getdPoint(temp)*60;
if(num<0)
return "-"+du+"°"+fen+"′"+miao+"″";
return du+"°"+fen+"′"+miao+"″";
}
//获取小数部分
public double getdPoint(double num){
double d = num;
int fInt = (int) d;
BigDecimal b1 = new BigDecimal(Double.toString(d));
BigDecimal b2 = new BigDecimal(Integer.toString(fInt));
double dPoint = b1.subtract(b2).floatValue();
return dPoint;
}
}
2.main.xml
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
android:layout_height="wrap_content"
android:text="Result:"
android:layout_marginTop="12dip"/>
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text=""
android:layout_marginTop="12dip"/>
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="12dip">
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:singleLine="true"
android:numeric="signed"/>
android:layout_height="wrap_content"
android:text="度(°)"
android:layout_weight="1"
android:paddingLeft="6dip"/>
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:singleLine="true"
android:numeric="integer"/>
android:layout_height="wrap_content"
android:text="分(′)"
android:layout_weight="1"
android:paddingLeft="6dip"/>
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:singleLine="true"
android:imeOptions="actionDone"
android:numeric="decimal"/>
android:layout_height="wrap_content"
android:text="秒(″)"
android:layout_weight="1"
android:paddingLeft="6dip"/>
android:layout_width="112dip"
android:layout_height="wrap_content"
android:text="toDecimal"
android:layout_marginTop="12dip"/>
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="12dip">
android:layout_height="wrap_content"
android:text="经纬度(Lat/Lng):"
android:paddingRight="6dip"/>
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:inputType="numberSigned|numberDecimal"/>
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="12dip">
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="toSexagesimal"
android:layout_marginTop="6dip"/>
android:layout_width="112dip"
android:layout_height="wrap_content"
android:text="copy Result"
android:layout_marginTop="6dip"/>
android:layout_width="224dip"
android:layout_height="wrap_content"
android:text="current location by decimal"
android:layout_marginTop="6dip"/>
android:layout_width="224dip"
android:layout_height="wrap_content"
android:text="current location by sexagesimal"
android:layout_marginTop="6dip"/>
下面是数字键盘的一些属性:
android:numeric=”decimal” 允许输入十进制数字,但不能输入负数,显示数字键盘;
android:numeric=”signed” 只允许输入整数,包括负整数,显示数字键盘;
android:numeric=”integer” 只允许输入正整数,显示数字键盘;
android:inputType=”numberSigned|numberDecimal” 允许输入十进制,包括负数,显示数字键盘;
android:digits=”1234567890.+-*/% ()” 只允许输入里面定义的字符,不验证是否为数字,如可以输入如”–11.23–“,键盘显示常规输入键盘。
因为使用了GPS定位,所以需要加入相应的权限: