Android之解析GML并显示

本例主要实现在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;@Overrideprotected 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() {@Overridepublic void onDrawerOpened() {}@Overridepublic void onDrawerClosed() {}});mButton = (TextView) findViewById(R.id.bt_chou);mButton.setOnClickListener(new OnClickListener() {@Overridepublic 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(){@Overridepublic boolean onTouch(View v, MotionEvent event) {// TODO Auto-generated method stubmGestureDetector.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(){@Overridepublic void onClick(View v) {// TODO Auto-generated method stubString 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();elsem_webview.loadUrl("javascript:searchByid('"+id+"')");m_edit.setText("");}}});m_btzoomin.setOnClickListener(new OnClickListener(){@Overridepublic void onClick(View v) {// TODO Auto-generated method stubm_webview.loadUrl("javascript:ZoomIn()");}});m_btzoomout.setOnClickListener(new OnClickListener(){@Overridepublic void onClick(View v) {// TODO Auto-generated method stubm_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 blockresult = 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 {@Overridepublic void run() {Message msg = handler.obtainMessage();if (GmlRead()) {SvgWrite m_writer = new SvgWrite(Activity_Main.this);if (m_writer.Write())msg.what = 0;// SVG生成成功elsemsg.what = 2;// svg生成失败} elsemsg.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); // 创建视图容器并设置上下文}@Overridepublic int getCount() {// TODO Auto-generated method stubreturn layers.size();}@Overridepublic Object getItem(int arg0) {// TODO Auto-generated method stubreturn layers.get(arg0);}@Overridepublic long getItemId(int arg0) {// TODO Auto-generated method stubreturn arg0;}@Overridepublic View getView(int arg0, View arg1, ViewGroup arg2) {// TODO Auto-generated method stubViews 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() {@Overridepublic void onClick(View v) {m_webview.loadUrl("javascript:changeVisible('L_"+v.getTag()+"')");}});/*m_views.button.setOnClickListener(new OnClickListener(){@Overridepublic void onClick(View v) {// TODO Auto-generated method stubIntent intent=new Intent(Activity_Main.this,Activity_attr.class);intent.putExtra("name", "L_"+v.getTag());startActivity(intent);}});*/return arg1;}}class MyOnGestureListener extends SimpleOnGestureListener{//滑动    Drag@Overridepublic boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {m_webview.loadUrl("javascript:scrool("+distanceX+","+distanceY+")");return false;}@Overridepublic boolean onDoubleTap(MotionEvent e) {m_webview.loadUrl("javascript:ZoomIn()");return false;}//抬起@Overridepublic boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {return false;}@Overridepublic void onShowPress(MotionEvent e) {}@Overridepublic 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;}elseeventType = 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);}elsem_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;elsem_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 blockdb.close();result=false;} catch (IOException e) {// TODO Auto-generated catch blockdb.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 blockresult = 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 blockresult = 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:zif(i%2==0){double x=Double.parseDouble(poslist[i]);if(i==0)lowerx=x;elselowerx=(lowerx>x)?x:lowerx;upperx=(upperx<x)?x:upperx;}else{double y=Double.parseDouble(poslist[i]);if(i==1)lowery=y;elselowery=(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]); // LeftXviewBoxValues[1] = parseFloat(viewBoxValues[1]); // UpYviewBoxValues[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]); // LeftXviewBoxValues[1] = parseFloat(viewBoxValues[1]); // UpYviewBoxValues[2] = parseFloat(viewBoxValues[2]); // UWdithviewBoxValues[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]); // LeftXviewBoxValues[1] = parseFloat(viewBoxValues[1]); // UpYviewBoxValues[2] = parseFloat(viewBoxValues[2]); // UWdithviewBoxValues[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]); // LeftXviewBoxValues[1] = parseFloat(viewBoxValues[1]); // UpYviewBoxValues[2] = parseFloat(viewBoxValues[2]); // UWdithviewBoxValues[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]); // LeftXviewBoxValues[1] = parseFloat(viewBoxValues[1]); // UpYviewBoxValues[2] = parseFloat(viewBoxValues[2]); // UWdithviewBoxValues[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

完成,效果如下

这里写图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/494243.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

中国电子学会发布《新一代人工智能领域十大最具成长性技术展望(2018-2019年)》...

来源&#xff1a;中国电子学会当前&#xff0c;全球正在经历科技和产业高度耦合、深度迭加的新一轮变革&#xff0c;大数据的形成、理论算法的革新、计算能力的提升及网络设施的演进驱动人工智能进入新一轮创新发展高峰期&#xff0c;新技术持续获得突破性进展&#xff0c;呈现…

晓得不,中间表是这样被消灭的

目录 一、中间表的产生 1、一步算不出来 2、实时计算等待时间过长 3、多样性数据源参加计算 4、中间表难以删除 二、文件计算 三、高性能文件格式 四、易管理性 五、多数据源支持 六、集成性 七、资料 一、中间表的产生 中间表是数据库中专门存放中间计算结果的数据…

美国五大科技巨头的人工智能竞赛

来源&#xff1a;资本实验室毫无疑问&#xff0c;人工智能已经开始渗透到各行各业&#xff0c;并正在改变我们的工作方式和生活方式。2017年&#xff0c;全球与人工智能相关的资金投入总额达到152亿美元&#xff0c;比上一年增加144&#xff05;。而无论在投资&#xff0c;还是…

模拟Struts2实现

本文主要是一个模拟的Struts2的简单实现 真正的MVC架构 实现主要思路 定义一个过滤器&#xff0c;接收传递过去的Action&#xff0c;根据处理的结果重定向或者转发。 首先定义index.jsp <% page language"java" import"java.util.*" pageEncoding&q…

实战教学--怎样提高报表呈现的性能?

报表的性能很重要&#xff0c;是一个总被谈及的问题&#xff0c;跑的慢的报表用户体验恶劣&#xff0c;无法忍受。解决这些慢的性能问题&#xff0c;也成了项目方和工程师头疼的事情。一出状况&#xff0c;就得安排技术好的&#xff0c;能力强的工程师去救火&#xff0c;本来利…

WiFi共享精灵 - 不需路由器一键轻松把网线共享给手机、笔记本等同时无线上网...

现在人们身边手机、游戏机等各种使用WiFi上网的设备已经越来越多&#xff0c;但经常遇到一些地方只有有线网络&#xff0c;或者没有无线路由器的情况&#xff0c;这时&#xff0c;用笔记本上网&#xff0c;然后把网络通过WiFi共享给其他设备上网那么就最合适了。我们之前有介绍…

干货|李开复最新刷屏演讲:人工智能最难取代这13种工作,也最容易威胁人性与爱!...

来源&#xff1a;澎湃新闻这两年&#xff0c;创新工场董事长兼首席执行官李开复&#xff0c;一直为人工智能站台和奔走&#xff0c;还出新书帮助人们规划未来的AI生活。他预言&#xff0c;中国有望在全球范围内首先实现OMO&#xff08;Online-Merge-Offline&#xff0c;线上线下…

Apifox vs Eolink,国内 Api 工具哪家强?

目前行业内有 postman、jmeter 为代表开源 Api 工具派系&#xff0c;我想对大家对这两个词并不陌生。虽然它们能解决基本的接口测试&#xff0c;但是无法解决接口链路上的所有问题&#xff0c;一个工具难以支持整个过程。 在国内&#xff0c;我们可以看到有国产 API 管理工具&…

人工智能、区块链、混合现实:2019年新闻、媒体与技术趋势

来源&#xff1a;资本实验室近日&#xff0c;未来今日研究所&#xff08;Future Today Institute&#xff09;发布了《2019年新闻、媒体与技术趋势报告》&#xff0c;报告提出了涵盖多个领域的108个新兴技术趋势。报告显示&#xff0c;未来的新闻、媒体等行业将受到各种技术错综…

活久见:都 2203 年了,你还在使用 word 调试 API

随着信息技术的发展&#xff0c;API 变得无处不在&#xff0c;无处不用。但令人费解的是&#xff0c;都 2203 年了&#xff0c;竟然还有很多人使用 word 调试 API&#xff1f; 今天&#xff0c;西红柿将带领大家打开新世界的大门&#xff0c;放下诺基亚&#xff0c;抄起智能机&…

Struts2基础知识

本文主要包括以下内容 struts2常用常量的定义与意义struts2处理流程拆分struts动态方法调用,使用通配符接收请求参数中文编码问题自定义类型转化器访问或添加request/session/application常用servlet对象的获取 struts2常用常量的定义与意义 struts2处理流程 每一次请求都会创…

自动驾驶汽车测试在美惹争议,原因为何?

来源&#xff1a;中国汽车报摘要&#xff1a;近日&#xff0c;针对美国总统特朗普提出的&#xff0c;汽车制造商需自愿提交他们在公共道路上测试自动驾驶汽车安全报告一事&#xff0c;回应者寥寥&#xff0c;目前只有三家汽车公司响应了上述要求&#xff0c;提交了相关材料。据…

Struts2基础知识(二)

本文主要包括以下内容 文件上传&#xff0c;多文件上传 自定义拦截器 用户输入验证国际化 文件上传 将头设置为enctype”multipart/form-data” <body><form action"${pageContext.request.contextPath}/upload/upload1.action" method"post" …

想做自动驾驶技术的入,这回分享一个简单好用的开放平台

前言 自动驾驶已经是现在技术开发领域最热门的方向之一&#xff0c;作为程序员&#xff0c;很多人也都想来这个领域试试水。但是这个领域的门槛也挺高&#xff0c;不过想开始的话&#xff0c;其实可以从一些专门针对自动驾驶的开放平台开始入手&#xff0c;目前比较主流的可以…

潘建伟团队再登Nature:全球首次实现器件无关量子随机数,量子保密通信安全再升级...

岳排槐 编辑量子位 出品 | 公众号 QbitAI据消息&#xff0c;潘建伟团队日前成功实现了器件无关的量子随机数&#xff0c;将在数值模拟、密码学等领域广泛应用&#xff0c;并有望形成新的随机数国际标准。相关研究成果于北京时间20日由国际权威学术期刊《自然》在线发表&#xf…

一篇文章搞懂数据仓库:数据治理(目的、方法、流程)

目录 1、什么是数据治理 2、数据治理的目的 3、数据治理的方法 4、数据质量8个衡量标准 5、数据治理流程 1、什么是数据治理 数据治理&#xff08;Data Governance&#xff09;是组织中涉及数据使用的一整套管理行为。由企业数据治理部门发起并推行&#xff0c;关于如何制…

在OEL5上安装配置Oracle Gird Control 10.2.0.5

早期的Grid Control问题实在太多了&#xff0c;以至于把10.2.0.1的Grid Control升级到10.2.0.5几乎是不可能完成的任务&#xff1b;此外10.2.0.5以前的gc不支持11g作为repository database仓库数据库&#xff0c;不仅于此10.2.0.1版本是不支持rhel5或OEL5的&#xff0c;如果想安…

Struts2基础知识(三)

本文主要包括以下内容 OGNL表达式标签 防止表单重复提交 使用第三方插件tomcat启动时struts2容器做的事 OGNL表达式 OGNL是Object Graphic Navigation Language(对象图导航语言)的缩写&#xff0c;它是一个开源项目。Struts2框架使用OGNL作为默认的表达式语言。 相对EL表达…

70行Python代码,获取中国数据库大会(DTCC)全部PPT

大家好&#xff0c;我是明月十四桥&#xff01; 擅长领域&#xff1a;python黑科技、大数据后端研发、数据仓库 今日重点&#xff1a; ① 学会使用python 获取各种网站的ppt&#xff0c;可见即可爬&#xff1b; ② 中国数据库大会一年一届&#xff0c;门票昂贵&#xff0c;干货…

半导体产业格局:行稳而致远,强者将恒强

来源&#xff1a;华泰证券▌中国半导体产业链渐趋完善&#xff0c;产业生态体系逐步成形目前我国垂直分工模式的芯片产业链初步搭建成形&#xff0c;产业上中下游已然打通&#xff0c;涌现出一批实力较强的代表性本土企业。集成电路是基础性、先导性产业&#xff0c;涉及国家信…