如何在Android中处理WKT数据?

时间:2012-09-11 11:22:31

标签: android google-maps wkt

我有这种格式的数据:

POINT(73.0166738279393 33.6788721326803)
MULTILINESTRING((73.0131224998036 33.679001500419,73.0119635003153 33.678392400389,73.0119205001311 33.6783781002692),(73.0131224998036 33.679001500419,73.0136031002029 33.6783443999742),(73.0136031002029 33.6783443999742,73.0147099372139 33.67685138958),(73.0147099372139 33.67685138958,73.0150124997272 33.6770292997624,73.0154158996241 33.6773507003746,73.0157677998441 33.6776577999676,73.016042399737 33.6779721004322,73.0162998999205 33.6783149004124,73.0166738279393 33.6788721326803))

现在我想在Android上的Google地图上绘制它。我制作了一系列名称和坐标。

ArrayList<String> coordinates = new ArrayList<String>
coordinates.add(tvcoor.getText().toString());

这会产生错误:当我运行我的应用程序时,它会强制停止。 我怎样才能在地图上绘制它?

5 个答案:

答案 0 :(得分:2)

试试这个,

String str;
ArrayList<String> coordinates = new ArrayList<String>();

首先从textview获取字符串。

str = textview.getText().toString();

第二个删除括号。

str = str.replaceAll("\\(", "");
str = str.replaceAll("\\)", "");

然后用逗号分割并将值添加到arraylist。

String[] commatokens = str.split(",");
        for (String commatoken : commatokens) {
            System.out.println("-" + commatoken + "-");
            coordinates.add(commatoken);
        }

然后我们在索引位置获得单独的坐标值,

 for (int i = 0; i < coordinates.size(); i++) {

            String[] tokens = coordinates.get(i).split("\\s");
            for (String token : tokens) {
                System.out.println("-" + token + "-");
            }
        }

答案 1 :(得分:1)

对于拥有相同场景的任何其他人,我找到了一个名为JTS Topology Suite的开源库,它能够解析Java中的WKT字符串。我的应用程序的基本示例如下所示:

WKTReader wktReader = new WKTReader();
Geometry geometry = wktReader.read(routeResponse.get(yourWKTMultilineString);

然后你可以像这样迭代各行:

for(int lineIndex = 0; lineIndex < geometry.getNumGeometries(); lineIndex++){
    Geometry lineGeometry = geometry.getGeometryN(lineIndex);
    //... other stuff
}

如有必要,您可以像这样获得每一行的各个坐标:

Coordinate[] lineCoordinates = lineGeometry.getCoordinates();

请注意,以上是一个非常一般的例子,它遵循OP的代码。

最终,这可能会使其他人无需使用自己的WKT解析器。


Nutiteq专用代码:
在我的例子中,我需要在Nutiteq map上绘制一个多线字符串作为矢量图层。我意识到OP正在询问谷歌地图android API,但是如果任何读者也使用Nutiteq(或者如果此算法与其他地图API相关),这是nutiteq特定代码:

geomLayer.clear(); // clear the old vector data

Projection projection = geomLayer.getProjection(); // Map's projection type

// Iterate through the individual lines of our multi-line geometry
for(int lineIndex = 0; lineIndex < geometry.getNumGeometries(); lineIndex++){
    Geometry lineGeometry = geometry.getGeometryN(lineIndex);
    ArrayList<MapPos> linePositions = new ArrayList<MapPos>(lineGeometry.getCoordinates().length);

    // Iterate through this line's coordinates
    for(Coordinate coordinate : lineGeometry.getCoordinates()){
        // My server returns coordinates in WGS84/EPSG:4326 projection while the map
        // uses EPSG3857, so it is necessary to convert before adding to the
        // array list.
        MapPos linePosition = new MapPos(projection.fromWgs84(coordinate.x, coordinate.y));
        linePositions.add(linePosition);
    }

    // Finally, add the line data to the vector layer
    Line line = new Line(linePositions, new DefaultLabel("some label"), lineStyle), null);
    geomLayer.add(line);
}

请注意,lineStyleSetgeomLayer之前已在活动的onCreate中创建,可以进行研究heregeomLayer很简单;这是我的lineStyleSet

关于lineStyle的注释,它是先前创建的,并保存为实例变量,如下所示:

Bitmap lineMarker = UnscaledBitmapLoader.decodeResource(getResources(), R.drawable.line);

this.lineStyleSet = new StyleSet<LineStyle>();
LineStyle lineStyle = LineStyle.builder().setLineJoinMode(LineStyle.NO_LINEJOIN).setWidth(0.2f).setColor(Color.RED).setBitmap(lineMarker).build();
lineStyleSet.setZoomStyle(minZoom, lineStyle);

答案 2 :(得分:1)

这是我写的一个函数,用于将WKT中给出的简单(无孔等)多边形转换为LatLang数组:

public static LatLng[] GetPolygonPoints(String poligonWkt){
    ArrayList<LatLng> points = new ArrayList<LatLng>();
    Pattern p = Pattern.compile("(\\d*\\.\\d+)\\s(\\d*\\.\\d+)");
    Matcher m = p.matcher(poligonWkt);
    String point;

    while (m.find()){
        point =  poligonWkt.substring(m.start(), m.end());
        points.add(new LatLng(Double.parseDouble(m.group(2)), Double.parseDouble(m.group(1))));
    }
    return points.toArray(new LatLng[points.size()]);
}

然后,您可以使用该数组在地图上添加多边形:

LatLng[] points = GeographyHelper.GetPolygonPoints(shapeWkt);

Polygon p = mMap.addPolygon(
   new PolygonOptions()
      .add(points)
      .strokeWidth(4)
      .strokeColor(Color.RED));

答案 3 :(得分:1)

只是为了扩展保罗的答案,因为他的答案对我帮助很大......

private void setUpMap(SomeObjectWithLocationAsWKT r) {

    List<LatLng> points = new ArrayList<LatLng>();
    WKTReader wktReader = new WKTReader();
    LineString line = null;
    Coordinate lineCentroid = null;
    Coordinate[] lineCoordinates = null;

    // if our object's WKT geometry is not null - map it
    if (r.geowkt != null) {

        // use the JTS (Java Topology Suite) WKTReader to read that WKT!
        try {
            line = (LineString) wktReader.read(r.geowkt);
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        // using (JTS) again to getCoordinates of the linestring
        lineCoordinates = line.getCoordinates();

        // Iterate through the line's coordinates & assign to List<LatLng> points
        for(Coordinate coordinate : lineCoordinates){
            points.add(new LatLng(coordinate.x, coordinate.y));
        }

        // add Polyline to Google Map
        Polyline p = mMap.addPolyline(
        new PolylineOptions()
        .addAll(points)
        .width(4)
        .color(Color.RED));
    }
}

// an example of zooming to the centroid of the WKT geometry 
// again, using (JTS - Java Topology Suite)
private void handleNewLocation(Location location) {
    LatLng latLng = null; 
    WKTReader wktReader = new WKTReader();
    LineString line = null;
    Coordinate lineCentroid = null; 

    // if our object's WKT geometry is not null - zoom to it
    if (r.geowkt != null) {
        try {
            line = (LineString) wktReader.read(r.geowkt);
            lineCentroid = line.getCentroid().getCoordinate();
            latLng = new LatLng(lineCentroid.x, lineCentroid.y);
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    } else {
        // just default to whatever location was passed in
        Log.d(TAG, location.toString());
        double currentLatitude = location.getLatitude();
        double currentLongitude = location.getLongitude();
        latLng = new LatLng(currentLatitude, currentLongitude);
    }
    CameraUpdate yourLocation = CameraUpdateFactory.newLatLngZoom(latLng, 19);
    mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
    mMap.animateCamera(yourLocation);
}

答案 4 :(得分:1)

WKT (众所周知的文本)文件描述了ISO 19107几何。我个人试图避免重新发明轮子,或者用自己编写的解析器“混乱”它们(你永远都不知道,你的功能是否涵盖所有情况只是因为它工作了一次)。

所以这是另一个漂亮的开源API,包含示例,教程:

http://docs.geotools.org/

这里是WKTParser类

http://docs.geotools.org/stable/javadocs/org/geotools/geometry/text/WKTParser.html

Android Studio: 只需将其添加到您的应用build.gradle文件中:

dependencies {
    /* your other dependencies */
    compile 'org.opengis:geoapi:3.0.0'
}