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;

    @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-1.5" />";
        return result;
    }

    public String DrawPolyGen(String Pos,String fillColor,String strokeColor)
    {
        String result="<polygon points=""+Pos+"" style="fill:"+fillColor+";stroke:"+strokeColor+";stroke-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

完成,效果如下

这里写图片描述

原文地址:https://www.cnblogs.com/jjx2013/p/6223692.html