草庐IT

使用 XML 解析在 MapView 上绘制长路径的 Android 问题

coder 2023-12-01 原文

我的应用程序出现问题.. 使用 XML 文件我正在获取地理点来绘制两个位置之间的路径..但​​它只显示距离小于 300 公里的路线.. 否则它不会绘制完整路径..

将 xml 文件分成 block 的任何解决方案..或任何替代方案..因为它给出的方向即使对于长距离也是完美的...那么问题是什么?我无法理解..

请帮忙..

编辑: 我发现 KML 文件有问题。 如果距离很长,它会提供两行字符串标签,每个字符串标签都有完整路径的坐标列表,分为多个部分。如下

<GeometryCollection>
<LineString>
<coordinates> 70.799640,22.283370,... </coordinates> </LineString>
<LineString>
<coordinates> 73.005940,21.536300,.... </coordinates> </LineString>
</GeometryCollection>

这就是为什么它将仅在字符串的后半部分的 map 上绘制路线。 所以..任何人都知道如何解决这个问题..

已编辑:-

public class DrivingDirectionsGoogleKML extends DrivingDirections
{
    @Override
    protected void startDrivingTo (GeoPoint startPoint, GeoPoint endPoint, Mode mode, IDirectionsListener listener)
    {
        new LoadDirectionsTask(startPoint, endPoint).execute(mode);
    }

    private class LoadDirectionsTask extends AsyncTask<Mode, Void, RouteImpl>
    {
        private static final String BASE_URL = "http://maps.google.com/maps?f=d&hl=en";
        private static final String ELEMENT_PLACEMARK = "Placemark";
        private static final String ELEMENT_NAME = "name";
        private static final String ELEMENT_DESC = "description";
        private static final String ELEMENT_POINT = "Point";
        private static final String ELEMENT_ROUTE = "Route";
        private static final String ELEMENT_GEOM = "GeometryCollection";

        private GeoPoint startPoint;
        private GeoPoint endPoint;

        public LoadDirectionsTask (GeoPoint startPoint, GeoPoint endPoint)
        {
            this.startPoint = startPoint;
            this.endPoint = endPoint;
        }

        @Override
        protected void onPreExecute() 
        {
            super.onPreExecute();
        }

        @Override
        protected RouteImpl doInBackground(Mode... params)
        {
            // Connect to the Google Maps web service that will return a KML string
            // containing the directions from one point to another.
            //
            StringBuilder urlString = new StringBuilder();
            urlString
                .append(BASE_URL)
                .append("&saddr=")
                .append(startPoint.getLatitudeE6() / 1E6)
                .append(",")
                .append(startPoint.getLongitudeE6() / 1E6)
                .append("&daddr=")
                .append(endPoint.getLatitudeE6() / 1E6)
                .append(",")
                .append(endPoint.getLongitudeE6() / 1E6)
                .append("&ie=UTF8&0&om=0&output=kml");

            if (params[0] == Mode.WALKING) 
            {
                urlString.append("&dirflg=w");
            }

            RouteImpl route = null;
            try 
            {
                URL url = new URL (urlString.toString());

                Log.i("-------- Url",url.toString());

                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                connection.setRequestMethod("GET");
                connection.setDoOutput(true);
                connection.setDoInput(true);
                connection.connect();

                route = parseResponse (connection.getInputStream()); 
            }
            catch (Exception e) 
            {
                route = null;
            }

            return route;
        }

        private RouteImpl parseResponse(InputStream inputStream) throws Exception
        {
            // Parse the KML file returned by the Google Maps web service
            // using the default XML DOM parser.
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document document = builder.parse(inputStream);         
            NodeList placemarkList = document.getElementsByTagName(ELEMENT_PLACEMARK);

            // Get the list of placemarks to plot along the route.
            List<Placemark> placemarks = new ArrayList<Placemark>();
            for (int i = 0; i < placemarkList.getLength(); i++)
            {
                PlacemarkImpl placemark = parsePlacemark (placemarkList.item(i));
                if (placemark != null) {
                    placemarks.add(placemark);
                }
            }

            // Get the route defining the driving directions.
            RouteImpl route = parseRoute (placemarkList);
            route.setPlacemarks(placemarks);
            return route;
        }

        private PlacemarkImpl parsePlacemark(Node item)
        {
            PlacemarkImpl placemark = new PlacemarkImpl ();

            boolean isRouteElement = false;
            NodeList children = item.getChildNodes();
            for (int i = 0; i < children.getLength(); i++)
            {
                Node node = children.item(i);
                if (node.getNodeName().equals(ELEMENT_NAME)) 
                {
                    String name = node.getFirstChild().getNodeValue();
                    if (name.equals(ELEMENT_ROUTE)) 
                    {
                        isRouteElement = true;
                    }
                    else 
                    {
                        isRouteElement = false;
                        placemark.setInstructions(name);
                    }
                }
                else if (node.getNodeName().equals(ELEMENT_DESC)) 
                {
                    if (!isRouteElement) 
                    {
                        String distance = node.getFirstChild().getNodeValue();
                        placemark.setDistance(distance.substring(3).replace("&#160;", " "));
                    }
                }
                else if (node.getNodeName().equals(ELEMENT_POINT)) 
                {
                    if (!isRouteElement) 
                    {
                        String coords = node.getFirstChild().getFirstChild().getNodeValue();
                        String[] latlon = coords.split(",");
                        placemark.setLocation(new GeoPoint ((int) (Double.parseDouble(latlon[1]) * 1E6),(int) (Double.parseDouble(latlon[0]) * 1E6)));
                    }
                }
            }
            return isRouteElement ? null : placemark;
        }

        private RouteImpl parseRoute(NodeList placemarkList)
        {
            RouteImpl route = null;

            for (int i = 0; i < placemarkList.getLength(); i++)
            {
                // Iterate through all the <Placemark> KML tags to find the one
                // whose child <name> tag is "Route".
                //
                Node item = placemarkList.item(i);
                NodeList children = item.getChildNodes();
                for (int j = 0; j < children.getLength(); j++)
                {
                    Node node = children.item(j);
                    if (node.getNodeName().equals(ELEMENT_NAME))
                    {
                        String name = node.getFirstChild().getNodeValue();
                        if (name.equals(ELEMENT_ROUTE))
                        {
                            route = parseRoute (item);
                            break;
                        }
                    }
                }
            }
            return route;
        }

        private RouteImpl parseRoute(Node item)
        {
            RouteImpl route = new RouteImpl ();

            NodeList children = item.getChildNodes();
            for (int i = 0; i < children.getLength(); i++)
            {
                Node node = children.item(i);

                if (node.getNodeName().equals(ELEMENT_DESC)) 
                {
                    // Get the value of the <description> KML tag.
                    String distance = node.getFirstChild().getNodeValue();
                    route.setTotalDistance(distance.split("<br/>")[0].substring(10).replace("&#160;", " "));
                }
                else if (node.getNodeName().equals(ELEMENT_GEOM)) //Here Reading Co-Ordinates..///
                {

                    String path = node.getFirstChild().getFirstChild().getFirstChild().getNodeValue();
                    String[] pairs = path.split(" ");

                    // For each coordinate, get its {latitude, longitude} values and add the corresponding geographical point to the route.

                    List<GeoPoint> geoPoints = new ArrayList<GeoPoint>();
                    for (int p = 0; p < pairs.length; p++) 
                    {
                        String[] coords = pairs[p].split(",");
                        GeoPoint geoPoint = new GeoPoint ((int) (Double.parseDouble(coords[1]) * 1E6),(int) (Double.parseDouble(coords[0]) * 1E6));
                        geoPoints.add (geoPoint);
                    }
                    route.setGeoPoints(geoPoints);

                }
            }

            return route;
        }

        protected void onPostExecute (RouteImpl route)
        {
            if (route == null) 
            {
                DrivingDirectionsGoogleKML.this.onDirectionsNotAvailable();
            }
            else 
            {
                DrivingDirectionsGoogleKML.this.onDirectionsAvailable(route); 
            }
        }
    }
}

最佳答案

我已经找到解决方案了.. 创建的节点列表 <GeometryCollection>....</GeometryCollection> 它将提供两个位置之间的所有坐标..

private RouteImpl parseRoute(Node item)
        {
            RouteImpl route = new RouteImpl ();
            NodeList children = item.getChildNodes();
            for (int i = 0; i < children.getLength(); i++)
            {
                Node node = children.item(i);

                if (node.getNodeName().equals(ELEMENT_DESC)) 
                {
                    // Get the value of the <description> KML tag.
                    //
                    String distance = node.getFirstChild().getNodeValue();
                    route.setTotalDistance(distance.split("<br/>")[0].substring(10).replace("&#160;", " "));
                }
                else if (node.getNodeName().equals(ELEMENT_GEOM)) 
                {
                    // Get the space-separated coordinates of the geographical points defining the route.
                    //

                    List<GeoPoint> geoPoints = new ArrayList<GeoPoint>();

                                    // Create a NodeList  here ..
                    NodeList geoMetryChildren = node.getChildNodes();

                    for(int k=0;k<geoMetryChildren.getLength();k++)
                    {
                        Node geoMetryChildrenNode = geoMetryChildren.item(k);
                        String path = geoMetryChildrenNode.getFirstChild().getFirstChild().getNodeValue();

                        String[] pairs = path.split(" ");

                        for (int p = 0; p < pairs.length; p++) 
                        {
                            String[] coords = pairs[p].split(",");
                            GeoPoint geoPoint = new GeoPoint ((int) (Double.parseDouble(coords[1]) * 1E6),(int) (Double.parseDouble(coords[0]) * 1E6));
                            geoPoints.add (geoPoint);
                        }
                    }
                    route.setGeoPoints(geoPoints);
                }
            }

            return route;
        }

关于使用 XML 解析在 MapView 上绘制长路径的 Android 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5298418/

有关使用 XML 解析在 MapView 上绘制长路径的 Android 问题的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. Ruby 解析字符串 - 2

    我有一个字符串input="maybe(thisis|thatwas)some((nice|ugly)(day|night)|(strange(weather|time)))"Ruby中解析该字符串的最佳方法是什么?我的意思是脚本应该能够像这样构建句子:maybethisissomeuglynightmaybethatwassomenicenightmaybethiswassomestrangetime等等,你明白了......我应该一个字符一个字符地读取字符串并构建一个带有堆栈的状态机来存储括号值以供以后计算,还是有更好的方法?也许为此目的准备了一个开箱即用的库?

  3. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  4. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  5. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  6. ruby - 在 Ruby 中使用匿名模块 - 2

    假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于

  7. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  8. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  9. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

  10. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

随机推荐