本例主要实现在APP中解析GML数据并显示

GML,地理标记语言(外语全称:Geography MarkupLanguage、外语缩写:GML),它由开放式地理信息系统协会(外语缩写:OGC)于1999年提出,并得到了许多公司的大力支持,如Oracle、Galdos、MapInfo、CubeWerx等。GML能够表示地理空间对象的空间数据和非空间属性数据

实现思路

GML文档解析

GML文档的本质还是Xml文档,所以可以用Xml解析器进行解析,在Android中可以使用自带的XmlPullParser进行解析,当然你也可以用SAX解析器可DOM解析器。在GML文档中有两种属性,一类是空间属性,另外一个就是非空间属性。其中空间属性是至关重要的,因为要进行地图显示必须要用空间属性;而非空间属性可以不用,但是由于要进行查询操作,所以我将非空间属性也进行存储。

在读GML文档时,首先读取图层,然后判断图层中的属性都有哪些,如果是非空间属性,将其存储起来(我用的是Sqlite数据库),如果是空间属性,那么第一个空间属性肯定是关于图层类型的,即他是Polygen,Polyline或是Point,然后在或标签下存储的位置信息,将位置信息存储起来即可。

以上就是大致的读取GML文档的思路。

地图显示

地图显示的方法有很多种,我简单介绍两种,一种是使用画布canvas进行绘制,另外一种就是使用SVG进行显示。由于我的水平有限,想不出解决canvas加载重绘时卡顿的问题,所以我就使用svg进行显示,使用svg最大的好处就是只在首次使用的时候生成SVG文件而花费的时间较长,而在之后的使用中加载时间在1s以内;另外就是使用svg进行功能实现时不会出现卡顿或者说是卡顿比前一种方法小的多。(在文件夹中包含的使用canvas绘制的工程是我找我的学长要的,哈哈)。

关于SVG大家有不明白的直接去百度,那里面比我讲的清楚的多,在写SVG的时候注意下面几个事项就行:

  1. 由于GML文件里面位置数据过大,所以需要在SVG中设置ViewBox保证地图能够全部显示(关于ViewBox也去百度吧)。

  2. 坐标转换,在GML中默认的坐标原点是左下角,而SVG的坐标原点是左上角,这点我想大家都因应该在之前接触过,所以需要进行坐标转换,就是进行垂直翻转而已。最初我使用的方法是将每个坐标的纵坐标变成相反数,然后就导致写SVG文件花了2分钟……。这样当然不行啊,找别的方法吧,后来终于找到个好办法,用矩阵变换,就是SVG里面的matrix属性,一下就变成10s以内,真是……

  3. 图层顺序,写SVG的时候图层显示应该按照面线点文字的顺序,这样可以保证所有图层都能够显示

参考链接

理解SVG坐标系统和变换: transform属性 - 推酷

功能实现

因为我用的SVG,所以没必要再进行SVG解析,直接用浏览器就可以查看,所以我只需要实现一个浏览器的功能就行了,用WebView控件,由于SVG的放大缩小平移可以用Javascript实现,所以我的所有功能都是在Javascript中的。但是在Android里面直接加载SVG文件会导致Javascript失效,所以用html内联SVG,这个也不再多说,大家参考html文件即可。

放大缩小:放大缩小的功能就是变化ViewBox即可,大家可以参考文件夹里面的js文件。

平移:平移功能要重写WebView的ontouch事件,然后再调用Javascript函数,具体也不多说,大家自己看吧。

搜索:搜索分为两部分,首先是从数据库中按照搜索条件查询出对象的ID,然后调用Javascript搜索的相关函数搜索出SVG中对应的对象。

参考链接

Android WebView 开发详解(一) - typename 记录点滴 - 博客频道 - CSDN.NET

实现

第一次进入应用时,先解析GML,将数据存储在数据库中,生成SVG,用webView显示HTML来显示SVG,在里面用JS实现一些功能控制,第二次进入时直接加载SVG即可

主Activity

package com.gmlmap.activity;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList; import com.gmlmap.data.LayerInfo;
import com.gmlmap.readfile.GmlPullParser;
import com.gmlmap.readfile.SvgWrite;
import com.gmlmap.util.SetViewHeight;
import com.gmlmap.util.SharedUtils;
import com.gmlmap.view.DrawerGarment;
import com.gmlmap.view.DrawerGarment.IDrawerCallbacks; import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.DragEvent;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnDragListener;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.view.Window;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast; public class Activity_Main extends Activity { private ProgressDialog dialog;
private WebView m_webview;
private Button m_btzoomin;
private Button m_btzoomout;
private Button m_btser;
private EditText m_edit;
private GestureDetector mGestureDetector; //抽屉使用
private DrawerGarment mDrawerGarment;
private TextView mButton;
private TextView m_text;
private ListView m_listview;
private MAdapter m_adapter;
private ArrayList<LayerInfo> m_layers; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
setContentView(R.layout.activity_main);
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.title); //titlebar为自己标题栏的布局
getSvg(); } private void InitCtView()
{
mDrawerGarment = new DrawerGarment(this, R.layout.drawer);
m_layers=SharedUtils.getLayers(getApplicationContext(), "TestData");
m_text=(TextView)this.findViewById(R.id.textView1);
m_text.setText("图层");
m_listview=(ListView)this.findViewById(R.id.listview);
m_adapter=new MAdapter(this,m_layers);
m_listview.setAdapter(m_adapter);
SetViewHeight.setLvHeight(m_listview);
mDrawerGarment.setDrawerCallbacks(new IDrawerCallbacks() { @Override
public void onDrawerOpened() { } @Override
public void onDrawerClosed() {
}
}); mButton = (TextView) findViewById(R.id.bt_chou);
mButton.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
mDrawerGarment.toggleDrawer();
}
});
} String move=""; @SuppressLint("SetJavaScriptEnabled")
private void initwebview() {
m_webview = (WebView) findViewById(R.id.webview);
WebSettings webSettings = m_webview.getSettings();
webSettings.setLoadWithOverviewMode(true);
webSettings.setJavaScriptEnabled(true);
m_webview.setWebViewClient(new WebViewClient());
m_webview.setWebChromeClient(new WebChromeClient());
// SVG图所在路径
String svg_path="file:///mnt/sdcard/GmlParser/TestData/index.html";
m_webview.loadUrl(svg_path);
mGestureDetector = new GestureDetector(this, new MyOnGestureListener()); m_webview.setOnTouchListener(new OnTouchListener(){ @Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
mGestureDetector.onTouchEvent(event);
return true;
}});
m_edit=(EditText)this.findViewById(R.id.edittext);
m_btzoomin=(Button)this.findViewById(R.id.mapzoomin);
m_btzoomout=(Button)this.findViewById(R.id.mapzoomout);
m_btser=(Button)this.findViewById(R.id.bt_search);
m_btser.setOnClickListener(new OnClickListener(){ @Override
public void onClick(View v) {
// TODO Auto-generated method stub
String co=m_edit.getText().toString();
if(co.equals(""))
Toast.makeText(getApplicationContext(), "输入不能为空",Toast.LENGTH_SHORT).show();
else
{
String id=SharedUtils.getOid(getApplicationContext(), "TestData", co);
if(id.equals(""))
Toast.makeText(getApplicationContext(), "没有搜索到结果",Toast.LENGTH_SHORT).show();
else
m_webview.loadUrl("javascript:searchByid('"+id+"')");
m_edit.setText("");
}
}});
m_btzoomin.setOnClickListener(new OnClickListener(){ @Override
public void onClick(View v) {
// TODO Auto-generated method stub
m_webview.loadUrl("javascript:ZoomIn()");
}});
m_btzoomout.setOnClickListener(new OnClickListener(){ @Override
public void onClick(View v) {
// TODO Auto-generated method stub
m_webview.loadUrl("javascript:ZoomOut()");
}});
} private boolean GmlRead() {
boolean result = false;
try {
InputStream is = getAssets().open("TestData.gml");
result = GmlPullParser.parse(is, "TestData", this);
} catch (IOException e) {
// TODO Auto-generated catch block
result = false;
}
return result;
} // Handler
@SuppressLint("HandlerLeak")
Handler handler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case 0:
initwebview();
InitCtView();
break;
case 1:
Toast.makeText(getApplicationContext(), "Gml解析发生错误", Toast.LENGTH_SHORT).show();
break;
case 2:
Toast.makeText(getApplicationContext(), "Svg生成发生错误", Toast.LENGTH_SHORT).show();
break; }
dialog.dismiss(); }
}; class mainThread implements Runnable { @Override
public void run() { Message msg = handler.obtainMessage();
if (GmlRead()) {
SvgWrite m_writer = new SvgWrite(Activity_Main.this);
if (m_writer.Write())
msg.what = 0;// SVG生成成功
else
msg.what = 2;// svg生成失败
} else
msg.what = 1;// gml解析失败
handler.sendMessage(msg);
}
} private void getSvg() {
if (SharedUtils.getBooleanValue(Activity_Main.this, "isStored", false)
&& SharedUtils.getBooleanValue(Activity_Main.this, "isSvg",
false))
{
initwebview();
InitCtView();
}else {
Toast.makeText(getApplicationContext(), "首次进入系统会花费5~20秒的时间进行数据解析,请勿退出~!",Toast.LENGTH_LONG).show();
/**
* 进度条
*/
dialog = new ProgressDialog(Activity_Main.this,
ProgressDialog.THEME_HOLO_LIGHT);
dialog.setMessage("正在解析GML并生成SVG,请稍后……");
dialog.setCanceledOnTouchOutside(false);
dialog.show();
Thread mainThread = new Thread(new mainThread());
// CheckNetworkState();
mainThread.start();
}
} public class MAdapter extends BaseAdapter { private ArrayList<LayerInfo> layers;
private ArrayList<Boolean> status;
private LayoutInflater m_listContainer; // 视图容器
private Context context; class Views{
CheckBox m_check;
LinearLayout button;
} public MAdapter(Context context,ArrayList<LayerInfo> mlayers)
{
this.context=context;
layers=mlayers;
status=new ArrayList<Boolean>();
m_listContainer = LayoutInflater.from(context); // 创建视图容器并设置上下文
} @Override
public int getCount() {
// TODO Auto-generated method stub
return layers.size();
} @Override
public Object getItem(int arg0) {
// TODO Auto-generated method stub
return layers.get(arg0);
} @Override
public long getItemId(int arg0) {
// TODO Auto-generated method stub
return arg0;
} @Override
public View getView(int arg0, View arg1, ViewGroup arg2) {
// TODO Auto-generated method stub
Views m_views;
if (arg1 == null) {
arg1 = m_listContainer.inflate(R.layout.listdetail,
null);
m_views=new Views();
m_views.m_check = (CheckBox) arg1.findViewById(R.id.checkbox);
//m_views.button=(LinearLayout)arg1.findViewById(R.id.bt_attr);
m_views.m_check.setText(layers.get(arg0).Lname);
m_views.m_check.setTag(arg0);
//m_views.button.setTag(layers.get(arg0).Lid);
status.add(false);
arg1.setTag(m_views);
} else {
m_views = (Views) arg1.getTag();
}
m_views.m_check.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
m_webview.loadUrl("javascript:changeVisible('L_"+v.getTag()+"')");
}
});
/*m_views.button.setOnClickListener(new OnClickListener(){ @Override
public void onClick(View v) {
// TODO Auto-generated method stub
Intent intent=new Intent(Activity_Main.this,Activity_attr.class);
intent.putExtra("name", "L_"+v.getTag());
startActivity(intent);
}});*/ return arg1;
} } class MyOnGestureListener extends SimpleOnGestureListener{
//滑动 Drag
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
m_webview.loadUrl("javascript:scrool("+distanceX+","+distanceY+")");
return false;
} @Override
public boolean onDoubleTap(MotionEvent e) {
m_webview.loadUrl("javascript:ZoomIn()");
return false;
}
//抬起
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { return false;
} @Override
public void onShowPress(MotionEvent e) {
} @Override
public boolean onDown(MotionEvent e) { return false;
}
} }

首先解析GML

package com.gmlmap.readfile;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList; import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException; import com.gmlmap.data.LayerInfo;
import com.gmlmap.data.PosInfo;
import com.gmlmap.util.SharedUtils; import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Xml; public class GmlPullParser { public static String GML_PREFIX="http://www.opengis.net/gml" ;
public final static int CASE_NORMAL=0; //一般情况,不进行任何操作,直接跳
public final static int CASE_FIRSTREAD=1; //第一次读featureMember,即读取图层的第一个要素
public final static int CASE_READ=2; //读取图层的第二个以后的要素
public final static int CASE_READLNAME=3; //读取图层名称
public static String SQL_NORMAL_INSERT="insert into";
public static String SQL_NORMAL_CREATE="CREATE TABLE"; public static boolean parse(InputStream is,String filename,Context context){ boolean result=false;
SharedUtils.StorePreferences(context, "filename", filename);
ArrayList<String> AttrNames=new ArrayList<String>();
LayerInfo m_layerinfo=new LayerInfo();
PosInfo m_posinfo=new PosInfo(); int m_curCondition=CASE_NORMAL;//当前位置 //打开或创建数据库
SQLiteDatabase db = context.openOrCreateDatabase(filename+".db", Context.MODE_PRIVATE, null);
db.beginTransaction();
db.execSQL("DROP TABLE IF EXISTS LayersInfo");
db.execSQL("create table LayersInfo (Lid INTEGER primary key,Lname VARCHAR(20),Ltype INTEGER)");
db.execSQL("DROP TABLE IF EXISTS FeaturePositon");
db.execSQL("create table FeaturePositon (Pid INTEGER primary key,Lid INTEGER,OBJECTID INTEGER,Pos TEXT)");
//创建xml pull解析器
XmlPullParser parser = Xml.newPullParser();
try {
parser.setInput(is, "UTF-8"); int eventType = parser.getEventType(); while (eventType!=XmlPullParser.END_DOCUMENT) {
switch (eventType) { case XmlPullParser.START_DOCUMENT:
break; case XmlPullParser.START_TAG:
if (parser.getName().equals("featureMember")) {
m_curCondition=CASE_READLNAME;
}
else if(parser.getName().equals("lowerCorner"))
{
eventType=parser.next();
SharedUtils.StorePreferences(context,"lowerCorner",parser.getText());
}
else if(parser.getName().equals("upperCorner"))
{
eventType=parser.next();
SharedUtils.StorePreferences(context,"upperCorner",parser.getText());
}
else if(m_curCondition!=CASE_NORMAL && parser.getNamespace().equals(GML_PREFIX))
{
m_layerinfo.Ltype=getLayerType(parser.getName());
eventType = parser.next();
while (eventType!=XmlPullParser.END_DOCUMENT)
{
if(parser.getName()!=null && parser.getName().contains("pos"))
{
eventType = parser.next();
m_posinfo.Pos=parser.getText();
db.execSQL(m_posinfo.insertData());
m_posinfo.Pid++;
break;
}
else
eventType = parser.next();
}
}
else
{
switch(m_curCondition)
{
case CASE_READLNAME:
if(!parser.getName().equals(m_layerinfo.Lname))
{
m_layerinfo.Lid++;
m_layerinfo.Ltype=-1;
m_posinfo.Lid=m_layerinfo.Lid;
m_layerinfo.Lname=parser.getName();
m_curCondition=CASE_FIRSTREAD;
AttrNames.removeAll(AttrNames);
}
else
m_curCondition=CASE_READ;
m_layerinfo.InitInfo();
break; case CASE_FIRSTREAD:
boolean ifObj=false;
m_layerinfo.AddInsertName(parser.getName());
AttrNames.add(parser.getName());
if(parser.getName().equals("OBJECTID"))
ifObj=true;
else
m_layerinfo.AddCreate(parser.getName());
eventType = parser.next();
m_layerinfo.AddInsertValue(parser.getText());
if(ifObj)
m_posinfo.OBJECTID=Integer.parseInt(parser.getText());
break; case CASE_READ:
if(AttrNames.contains(parser.getName()))
{
boolean ifObj2=false;
if(parser.getName().equals("OBJECTID"))
ifObj2=true;
m_layerinfo.AddInsertName(parser.getName());
eventType = parser.next();
m_layerinfo.AddInsertValue(parser.getText());
if(ifObj2)
m_posinfo.OBJECTID=Integer.parseInt(parser.getText());
}
break;
}
}
break; case XmlPullParser.END_TAG: if (parser.getName().equals("featureMember")) {
if(m_curCondition==CASE_FIRSTREAD)
{
db.execSQL("DROP TABLE IF EXISTS L_"+m_layerinfo.Lid);
db.execSQL(m_layerinfo.getCreateInfo());
db.execSQL(m_layerinfo.insertData());
}
db.execSQL(m_layerinfo.getInsertInfo());
} break; case XmlPullParser.END_DOCUMENT:
break;
}
eventType = parser.next();
}
//关闭当前数据库
db.setTransactionSuccessful();
db.endTransaction();
db.close();
result=true;
SharedUtils.StorePreferences(context, "isStored", true);
} catch (XmlPullParserException e) {
// TODO Auto-generated catch block
db.close();
result=false;
} catch (IOException e) {
// TODO Auto-generated catch block
db.close();
result=false;
}
return result;
} /*
* 获取图层的类型,-1表示非空间信息,0表示Point,1表示PolyLine,2表示PolyGen
*/
private static int getLayerType(String name)
{
name=name.toLowerCase();
int result=-1;
if(name.contains("point"))
result=0;
else if(name.contains("curve") || name.contains("line") || name.contains("polyline"))
result=1;
else if(name.contains("surface") || name.contains("polygon"))
result=2;
return result;
} }

生成SVG

package com.gmlmap.readfile;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Random; import com.gmlmap.activity.Activity_Main;
import com.gmlmap.data.LayerInfo;
import com.gmlmap.util.SharedUtils;
import com.gmlmap.util.SvgUtils; import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Environment;
import android.widget.Toast; public class SvgWrite { private Context context;
private StringBuilder m_buffer = null;
private List<LayerInfo> m_layerinfos;
private String folderName = ""; public SvgWrite(Context context) {
this.context = context;
} /*
* 创建文件夹
*/
private void createFolder(String foldername) {
String pathUrl = Environment.getExternalStorageDirectory().getPath()
+ "/GmlParser/" + foldername;
File file = new File(pathUrl);
if (!file.exists())
file.mkdirs();
copy("htmfuc.js", pathUrl);
copy("index.html", pathUrl);
} /**
*
* @param ASSETS_NAME
* 要复制的文件名
* @param savePath
* 要保存的路径 testCopy(Context context)是一个测试例子。
*/ private void copy(String ASSETS_NAME, String savePath) {
String filename = savePath + "/" + ASSETS_NAME; File dir = new File(savePath);
// 如果目录不中存在,创建这个目录
if (!dir.exists())
dir.mkdir();
try {
if (!(new File(filename)).exists()) {
InputStream is = context.getResources().getAssets()
.open(ASSETS_NAME);
FileOutputStream fos = new FileOutputStream(filename);
byte[] buffer = new byte[7168];
int count = 0;
while ((count = is.read(buffer)) > 0) {
fos.write(buffer, 0, count);
}
fos.close();
is.close();
}
} catch (Exception e) {
e.printStackTrace();
}
} public void deleteFile(File file) {
if (file.exists()) { // 判断文件是否存在
if (file.isFile()) { // 判断是否是文件
file.delete(); // delete()方法 你应该知道 是删除的意思; }
}
} /*
* 创建文件
*/
public boolean createFile(String foldername) {
boolean result = false;
File fileRoot = new File(Environment.getExternalStorageDirectory()
.getPath() + "/GmlParser");
if (!fileRoot.exists()) {
fileRoot.mkdir();
}
createFolder(foldername);
File file = new File(Environment.getExternalStorageDirectory()
.getPath() + "/GmlParser/" + foldername + "/map.svg");
if (file.exists())
file.delete();
try {
file.createNewFile();
result = true;
} catch (IOException e) {
// TODO Auto-generated catch block
result = false;
}
return result;
} public Boolean Write() {
boolean result = false;
SvgUtils m_svg = new SvgUtils(context);
AddContent(m_svg.getDocumentStart());
folderName = SharedUtils
.getStringValue(context, "filename", "TestData");
// 打开或创建数据库
SQLiteDatabase db = context.openOrCreateDatabase(folderName + ".db",
Context.MODE_PRIVATE, null);
if (m_layerinfos == null)
m_layerinfos = new ArrayList<LayerInfo>();
Cursor c = db.rawQuery(getLinfoSelect(), null);
while (c.moveToNext()) { LayerInfo ainfo = new LayerInfo();
ainfo.Lid = c.getInt(c.getColumnIndex("Lid"));
ainfo.Lname = c.getString(c.getColumnIndex("Lname"));
ainfo.Ltype = c.getInt(c.getColumnIndex("Ltype"));
Random random = new Random();
ainfo.Lstyle = random.nextInt(3);
m_layerinfos.add(ainfo);
}
c.close(); for (int i = 0; i < m_layerinfos.size(); i++) {
int Lid = m_layerinfos.get(i).Lid;
if (m_layerinfos.get(i).Ltype != -1) {
AddContent(m_svg.SetLayerStart(Lid));
c = db.rawQuery(getPinfoSelect(Lid), null);
while (c.moveToNext()) {
String PosList = c.getString(c.getColumnIndex("Pos"));
AddContent(m_svg.Draw(PosList, m_layerinfos.get(i).Ltype,
m_layerinfos.get(i).Lstyle));
}
c.close();
}
else
{
AddContent("</g>"+m_svg.SetLayerStart(Lid));
c = db.rawQuery(getTinfoSelect(Lid), null);
while (c.moveToNext()) {
String PosList = c.getString(c.getColumnIndex("Pos"));
String Name=c.getString(c.getColumnIndex("Name"));
String Oid="O_"+c.getInt(c.getColumnIndex("Oid"));
AddContent(m_svg.DrawText(PosList, Name,Oid));
}
c.close();
}
AddContent(SvgUtils.SVG_LAYER_ENDTAG);
}
AddContent(SvgUtils.SVG_LAYER_ENDTAG + SvgUtils.SVG_ENDDOUCUMENT);
result = WriteContent(this.m_buffer.toString());
if (result)
SharedUtils.StorePreferences(context, "isSvg", result);
return result;
} private void AddContent(String str) {
if (m_buffer == null)
m_buffer = new StringBuilder(); m_buffer.append(str);
} // 向已创建的文件中写入数据库中存储的数据
private boolean WriteContent(String str) {
boolean result = false;
try {
createFile(folderName);
FileWriter fw = null;
BufferedWriter bw = null;
fw = new FileWriter(Environment.getExternalStorageDirectory()
.getPath() + "/GmlParser/" + folderName + "/map.svg", true);//
// 创建FileWriter对象,用来写入字符流
bw = new BufferedWriter(fw); // 将缓冲对文件的输出
bw.write(str); // 写入文件
bw.newLine();
bw.flush(); // 刷新该流的缓冲
bw.close();
fw.close();
result = true; } catch (IOException e) {
// TODO Auto-generated catch block
result = false;
}
return result;
} /*
* 获取图层信息的select语句
*/
private String getLinfoSelect() {
return "select * from LayersInfo order by Ltype DESC";
} private String getPinfoSelect(int Lid) {
return "select Pos from FeaturePositon where Lid=" + Lid;
} //文字
private String getTinfoSelect(int Lid)
{
//String result="select name.TextString Name,pos.Pos Pos from ";
//String name="(Select FeatureId,TextString From L_"+Lid+" ) name,FeaturePositon pos";
//return result+name+"where name.FeatureId=pos.OBJECTID";
return "select name.TextString Name,name.OBJECTID Oid,pos.Pos Pos from (Select OBJECTID,FeatureId,TextString From L_4 ) name,FeaturePositon pos where name.FeatureId=pos.OBJECTID";
}
}

其中要用到SvgUtils

package com.gmlmap.util;

import java.util.Random;

import android.content.Context;

public class SvgUtils {

    public static String[] PolygenColors={"#dfeafc","#faf3df","#fce3e3","#fed4cc"};
public static String[] PolylineColors={"#0c343d","#274e13","#783f04","#073763"};
public static String[] PointColors={"#ff0000","#ff9900","#00ff00","#ffff00"};
public static String[] Stroks={"#330000","#003300","#660000","#000080","#FFD700"}; public static String XML_BASE="<?xml version=\"1.0\" encoding=\"utf-8\"?>";
public static String SVG_BASE="<svg id=\"root\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" ";
public static String SVG_LAYERS="<g id=\"layers\"><g transform=\"matrix(1,0,0,-1,0,0)\">";
public static String SVG_LAYER_STARTTAG="<g id=\"L_";
public static String SVG_LAYER_ENDTAG="</g>";
public static String SVG_ENDDOUCUMENT="</svg>";
private double LOWER_X;
private double LOWER_Y;
private double UPPER_X;
private double UPPER_Y; private Context m_context;
public SvgUtils(Context context)
{
this.m_context=context;
SharedUtils.StorePreferences(context,"lowerCorner","585305.346019984 3338389.98497472");
SharedUtils.StorePreferences(context,"upperCorner","596424.775248615 3345263.17995185");
String lowerCorner=SharedUtils.getStringValue(m_context, "lowerCorner", "0 0");
String upperCorner=SharedUtils.getStringValue(m_context, "upperCorner", "1000 1000");
String poslist1[]=lowerCorner.split(" ");
String poslist2[]=upperCorner.split(" ");
LOWER_X=Double.parseDouble(poslist1[0]);
LOWER_Y=Double.parseDouble(poslist1[1]);
UPPER_X=Double.parseDouble(poslist2[0]);
UPPER_Y=Double.parseDouble(poslist2[1]);} public String getDocumentStart()
{
return XML_BASE+SVG_BASE+" width=\"100%\" height=\"100%\" viewBox=\""+LOWER_X+",-"+UPPER_Y+","+(UPPER_X-LOWER_X)+","+(UPPER_Y-LOWER_Y)
+"\">"+SVG_LAYERS;
} public String SetLayerStart(int Lid)
{
return SVG_LAYER_STARTTAG+Lid+"\">";
} public String Draw(String PosList,int Ltype,int Lstyle)
{
String result="";
switch(Ltype)
{
case 0:
result=DrawPoint(PosList,PointColors[Lstyle]);
break;
case 1:
result=DrawPolyLine(PosList,PolylineColors[Lstyle]);
break;
case 2:
{
Random random = new Random(); result=DrawPolyGen(PosList,PolygenColors[Lstyle],Stroks[ random.nextInt(4)]); }
break;
}
return result;
} //根据点集确定text位置
private String getTextPos(String Pos)
{
String result="";
double lowerx=0,upperx=0,lowery=0,uppery=0;
String[] poslist=Pos.split(" ");
for(int i=0;i<poslist.length;i++)
{
//x? y:z
if(i%2==0)
{
double x=Double.parseDouble(poslist[i]);
if(i==0)
lowerx=x;
else
lowerx=(lowerx>x)?x:lowerx;
upperx=(upperx<x)?x:upperx;
}
else
{
double y=Double.parseDouble(poslist[i]);
if(i==1)
lowery=y;
else
lowery=(lowery>y)?y:lowery;
uppery=(uppery<y)?y:uppery;
} }
result="x=\""+(lowerx+(upperx-lowerx)/4)+"\" y=\"-"+((uppery)-(uppery-lowery)/2)+"\" ";
return result;
} public String DrawText(String Pos,String name,String Oid)
{
String result="";
result="<text id=\""+Oid+"\" "+getTextPos(Pos)+"fill=\"black\" font-size=\"260\">"+name+"</text>";
return result;
} public String DrawPoint(String Pos,String Color)
{
String Poss[]=Pos.split(" ");
String result="<circle cx=\""+Poss[0]+"\" cy=\""+Poss[1]+"\" r=\"15\" fill=\""+Color+"\"/>";
return result;
} public String DrawPolyLine(String Pos,String lineColor)
{
String result="<polyline points=\" "+Pos+"\" style=\"fill:none;stroke:"+lineColor+";stroke-width:1.5\" />";
return result;
} public String DrawPolyGen(String Pos,String fillColor,String strokeColor)
{
String result="<polygon points=\""+Pos+"\" style=\"fill:"+fillColor+";stroke:"+strokeColor+";stroke-width:1.5\"/>";
return result;
} /*
* 坐标转换
*/
private String convertCoorX(String x)
{
return Double.parseDouble(x)-LOWER_X+"";
}
private String convertCoorY(String y)
{
return Double.parseDouble(y)-LOWER_Y+"";
}
}

HTML文件

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title> map </title>
<script src="htmfuc.js" type="text/javascript" ></script>
<style>
.div-a{ position:absolute; left:0px; top:0px;background-color:transparent;width:100%; height:100% }
</style>
</head> <body onload="Init()">
<div class="div-a" filter:alpha(opacity=100,finishopacity=0,style=2></div>
<embed id="map" src="./map.svg" left="0px" top="0px"; width="100%" height="100%" type="image/svg+xml" >
</body>
</html>

JS文件控制

var htmlObj, SVGDoc, SVGRoot, viewBox, goLeft, goRight, innerSVG;
var currentSize, currentPosition, currentRoomId, currentRoomLabel;
var svgns = "http://www.w3.org/2000/svg";
var S_Width,S_Height;
var curtype=0; function Init()
{ htmlObj = document.getElementById("map");
SVGDoc = htmlObj.getSVGDocument();
SVGRoot = SVGDoc.documentElement;
S_Width=screen.width;
S_Height=screen.height;
} function changeVisible(tagname){ var tag=SVGDoc.getElementById(tagname); if(!tag)
{
return;
}
var visible=tag.getAttribute("visibility"); if(visible=="hidden")
{
tag.setAttribute("visibility","visible");
}
else
{
tag.setAttribute("visibility","hidden");
} } function ZoomIn()
{ if(curtype<5)
{
curtype=curtype+1;
var rootElement=SVGDoc.getElementById("root");
var viewBox = rootElement.getAttribute('viewBox'); // Grab the object representing the SVG element's viewBox attribute. var viewBoxValues = viewBox.split(',');
viewBoxValues[0] = parseFloat(viewBoxValues[0]); // LeftX
viewBoxValues[1] = parseFloat(viewBoxValues[1]); // UpY
viewBoxValues[2] = parseFloat(viewBoxValues[2]); // UWdith
viewBoxValues[3] = parseFloat(viewBoxValues[3]);
viewBoxValues[0]=getLower(viewBoxValues[0],viewBoxValues[2],viewBoxValues[2]/2);
viewBoxValues[1]=getLower(viewBoxValues[1],viewBoxValues[3],viewBoxValues[3]/2);
viewBoxValues[2] = viewBoxValues[2]/2;
viewBoxValues[3] = viewBoxValues[3]/2;
rootElement.setAttribute('viewBox', viewBoxValues.join(','));
}
} function ZoomOut()
{
if(curtype>-2)
{
curtype=curtype-1;
var rootElement=SVGDoc.getElementById("root");
var viewBox = rootElement.getAttribute('viewBox'); // Grab the object representing the SVG element's viewBox attribute. var viewBoxValues = viewBox.split(',');
viewBoxValues[0] = parseFloat(viewBoxValues[0]); // LeftX
viewBoxValues[1] = parseFloat(viewBoxValues[1]); // UpY
viewBoxValues[2] = parseFloat(viewBoxValues[2]); // UWdith
viewBoxValues[3] = parseFloat(viewBoxValues[3]);
viewBoxValues[0]=getLower(viewBoxValues[0],viewBoxValues[2],viewBoxValues[2]*2);
viewBoxValues[1]=getLower(viewBoxValues[1],viewBoxValues[3],viewBoxValues[3]*2);
viewBoxValues[2] = viewBoxValues[2]/0.5;
viewBoxValues[3] = viewBoxValues[3]/0.5;
rootElement.setAttribute('viewBox', viewBoxValues.join(','));
}
} function getLower(oldLower,oldValue,newValue)
{
return oldLower+oldValue/2-newValue/2;
} function searchByid(tname)
{
var oElement=SVGDoc.getElementById(tname);
var x=parseFloat(oElement.getAttribute('x'));
var y=parseFloat(oElement.getAttribute('y'));
var rootElement=SVGDoc.getElementById("root");
var viewBox = rootElement.getAttribute('viewBox'); // Grab the object representing the SVG element's viewBox attribute.
var viewBoxValues = viewBox.split(',');
viewBoxValues[2]=parseFloat(viewBoxValues[2]);
viewBoxValues[3]=parseFloat(viewBoxValues[3]);
viewBoxValues[0]=x-viewBoxValues[2]/2;
viewBoxValues[1]=y-viewBoxValues[3]/2;
rootElement.setAttribute('viewBox', viewBoxValues.join(','));
} function Pan()
{
var panRate = 10;
var rootElement=SVGDoc.getElementById("root");
var viewBox = rootElement.getAttribute('viewBox'); // Grab the object representing the SVG element's viewBox attribute.
var viewBoxValues = viewBox.split(',');
viewBoxValues[0] = parseFloat(viewBoxValues[0]); // LeftX
viewBoxValues[1] = parseFloat(viewBoxValues[1]); // UpY
viewBoxValues[2] = parseFloat(viewBoxValues[2]); // UWdith
viewBoxValues[0] += panRate*viewBoxValues[2] /S_Width;
rootElement.setAttribute('viewBox', viewBoxValues.join(','));
} function scrool(distanceX,distanceY)
{
var rootElement=SVGDoc.getElementById("root");
var viewBox = rootElement.getAttribute('viewBox'); // Grab the object representing the SVG element's viewBox attribute.
var viewBoxValues = viewBox.split(',');
viewBoxValues[0] = parseFloat(viewBoxValues[0]); // LeftX
viewBoxValues[1] = parseFloat(viewBoxValues[1]); // UpY
viewBoxValues[2] = parseFloat(viewBoxValues[2]); // UWdith
viewBoxValues[3] = parseFloat(viewBoxValues[3]); // Uheight
viewBoxValues[0] += parseFloat(distanceX)*viewBoxValues[2] /S_Width;
viewBoxValues[1] += parseFloat(distanceY)*viewBoxValues[3] /S_Height;
rootElement.setAttribute('viewBox', viewBoxValues.join(',')); } function Zoom(x,y)
{
if ( evt.detail ==2 ){
var panRate = 10;
var rootElement=SVGDoc.getElementById("root");
var viewBox = rootElement.getAttribute('viewBox'); // Grab the object representing the SVG element's viewBox attribute. var viewBoxValues = viewBox.split(',');
x=parseFloat(x);
y=parseFloat(y);
viewBoxValues[0] = parseFloat(viewBoxValues[0]); // LeftX
viewBoxValues[1] = parseFloat(viewBoxValues[1]); // UpY
viewBoxValues[2] = parseFloat(viewBoxValues[2]); // UWdith
viewBoxValues[3] = parseFloat(viewBoxValues[3]);
viewBoxValues[0]= getBasecor(getTruecorX(x,viewBoxValues[0],viewBoxValues[2] ),viewBoxValues[2]/2);
viewBoxValues[1]= getBasecor(getTruecorY(y,viewBoxValues[1],viewBoxValues[3] ),viewBoxValues[3]/2);
viewBoxValues[2] = viewBoxValues[2]/2;
viewBoxValues[3] = viewBoxValues[3]/2;
rootElement.setAttribute('viewBox', viewBoxValues.join(','));
}
} function getTruecorX(CorX,LowerX,Width)
{
return LowerX+Width/S_Width*CorX;
} function getTruecorY(CorY,LowerY,Height)
{
return LowerY+Height/S_Height*CorY;
} function getBasecor(Cor,value)
{
return Cor-value/2;
}

参考链接

Gml解析并显示(Android) - 下载频道 - CSDN.NET

完成,效果如下

Android之解析GML并显示的更多相关文章

  1. Android 进行解析并显示服务端返回的数据

    例子说明:用户通过访问web资源的最新电影资讯,服务器端生成XML或JSON格式数据,返回Android客户端进行显示. 此案例开发需要两个方面 WEB开发和Android开发. 一.web开发相对比 ...

  2. android XMl 解析神奇xstream 六: 把集合list 转化为 XML文档

    前言:对xstream不理解的请看: android XMl 解析神奇xstream 一: 解析android项目中 asset 文件夹 下的 aa.xml 文件 android XMl 解析神奇xs ...

  3. Android] Android XML解析学习——方式比较

     [Android] Android XML解析学习——方式比较 (ZT)  分类: 嵌入式 (From:http://blog.csdn.net/ichliebephone/article/deta ...

  4. Android JSON解析库Gson和Fast-json的使用对比和图书列表小案例

    Android JSON解析库Gson和Fast-json的使用对比和图书列表小案例 继上篇json解析,我用了原生的json解析,但是在有些情况下我们不得不承认,一些优秀的json解析框架确实十分的 ...

  5. Android DOM解析XML示例程序

    DOM方式解析xml是先把xml文档都读到内存中,然后再用DOM API来访问树形结构,并获取数据的.DOM比较符合人的思维模式,但是其对内存的消耗比较大. activity_main.xml < ...

  6. 第六篇 ANDROID窗口系统机制之显示机制

    第六篇 ANDROID窗口系统机制之显示机制 ANDROID的显示系统是整个框架中最复杂的系统之一,涉及包括窗口管理服务.VIEW视图系统.SurfaceFlinger本地服务.硬件加速等.窗口管理服 ...

  7. Android Json解析与总结

    一.JSON定义 JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式. 易于人阅读和编写.同时也易于机器解析和生成. 它基于JavaScript Progra ...

  8. Android源代码解析之(十三)--&gt;apk安装流程

    转载请标明出处:一片枫叶的专栏 上一篇文章中给大家分析了一下android系统启动之后调用PackageManagerService服务并解析系统特定文件夹.解析apk文件并安装的过程,这个安装过程实 ...

  9. Android全面解析之Context机制

    前言 很高兴遇见你~ 欢迎阅读我的文章. 在文章Android全面解析之由浅及深Handler消息机制中讨论到,Handler可以: 避免我们自己去手动写 死循环和输入阻塞 来不断获取用户的输入以及避 ...

随机推荐

  1. 千万不要误用 java 中的 HashCode 方法

    刚才debug追堆栈的时候发现一个很奇怪的问题 我用IE8和Google的浏览器访问同一个地址 Action的 scope="session" 也设置了 而且两个浏览器提交的参数m ...

  2. 2个比较经典的PHP加密解密函数分享

    项目中有时我们需要使用PHP将特定的信息进行加密,也就是通过加密算法生成一个加密字符串,这个加密后的字符串可以通过解密算法进行解密,便于程序对解密后的信息进行处理. 最常见的应用在用户登录以及一些AP ...

  3. Jenkins 搭建U3D自动发布 Android

    工具 [u3d相关的PostProcessBuildPlayer,PerformBuild.cs] 1.Jenkins 开源包  Java -jar jenkins.war,参考链接 http://w ...

  4. Redis 数据库

    Redis 服务器     Remote Dictionay Server     Redis是一个key-value持久化产品,通常被称为数据结构服务器.   Redis的key是string类型: ...

  5. Linq实现DataTable的分组统计

    DataTable dt = GetTestData(10); //获取10条测试数据 var queryByService = from r in dt.AsEnumerable() group r ...

  6. cad2013

    ## ribbon界面? ribbon界面是一种设计ui, 可以认为是传统的  菜单和工具栏  组合. 是 用于 实时显示 + 面向结果的 设计ui 但并不是所有的程序都适合.  ribbon 并不是 ...

  7. tyvj4221 货车漂移

    背景 蒟蒻中学的蒟蒻遇到了一些小问题. 描述 蒟蒻考完noip也就要回家种田了,他老家的田地在s点,可是种子市场在e点,为了购买种子,中途要经过很多城市,这导致快递费非常的贵(因为快到双11了),于是 ...

  8. sql数据库批量替换dedecms内容关键字

    之前写了一篇dedecms后台批量替换文章中的关键词,这边我们介绍一下用sql数据库批量替换dedecms内容关键字,当然要求你对数据库比较熟悉,修改前请自行做好备份. 1.更改文章中的内容 upda ...

  9. Lua中的捕获

    Lua中的捕获   捕获 捕获是这样一种机制:可以使用模式串的一部分匹配目标串的一部分.将你想捕获的模式用圆括号括起来,就指定了一个捕获.在string.find使用捕获的时候,函数会返回捕获的值作为 ...

  10. PHP+MySQL无限级分类(非递归)

    要实现无限级分类,递归一般是第一个也是最容易想到的,但是递归一般被认为占用资源的方法,所以很多系统是不考虑使用递归的 本文还是通过数据库的设计,用一句sql语句实现 数据库字段大概如下: 字段 说明 ...