Как обрабатывать данные WKT в Android?

У меня есть данные в таком формате:

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))

Теперь я хочу нарисовать его на Google Maps в Android. Я делаю массив имен и координат.

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

Это приводит к ошибке: когда я запускаю свое приложение, оно принудительно останавливается. А как его нарисовать на карте?


person Sarah Salar    schedule 11.09.2012    source источник
comment
Жиль, я добавляю оператор if, потому что textView также получил другие данные. но я хочу хранить только координаты данных в списке массивов   -  person Sarah Salar    schedule 12.09.2012
comment
спасибо, по крайней мере, я решил свою ошибку   -  person Sarah Salar    schedule 12.09.2012
comment
скажите, корректен ли этот код для добавления значений в форму списка массивов textviewif((tvTextIn.equals(new String (POINT)))||(tvTextIn.equals(new String (MULTILINES)))) { координаты.add(tvcoor. получитьтекст().toString()); }   -  person Sarah Salar    schedule 12.09.2012
comment
когда я запускаю этот код ArrayList‹String› координаты = новый ArrayList‹String› координаты.add(tvcoor.getText().toString()); он не хранит значения в списке массивов, все значения равны нулю, он создал размер, но все значения равны нулю   -  person Sarah Salar    schedule 15.09.2012
comment
вы получили значение textview? . пожалуйста, опубликуйте свой полный код.   -  person rajeshwaran    schedule 15.09.2012
comment
есть ли способ в Android анализировать данные WKT. извлечь из него латлонг   -  person Sarah Salar    schedule 16.09.2012
comment
я сохраняю данные WKT (упомянутые в моем посте) в текстовом виде переменной формы, затем я добавляю эти данные в ararylist for (int i = 0; i‹values.length(); i++) { coor.add (values.split (,) .нанизывать()); } но сохраняет [[Ljava.lang.String;@44f08800] в каждой позиции   -  person Sarah Salar    schedule 16.09.2012


Ответы (5)


Попробуй это ,

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 + "-");
            }
        }
person rajeshwaran    schedule 17.09.2012
comment
спасибо, Раджеш, за помощь, но я не могу понять последний шаг, и когда я отправляю этот массив координаторов в активность карты, а затем из активности карты в класс наложения и рисую точку - person Sarah Salar; 17.09.2012
comment
Намерение в = getIntent(); loc = in.getStringArrayListExtra (имя строки); mapOverlays = mapView.getOverlays(); проект = mapView.getProjection(); оверлей = новый MyOverlay (местоположения); и нарисуйте точку, подобную этой: int)(Integer.parseInt(locations.get(1))*1E6)); затем приложение неожиданно останавливается - person Sarah Salar; 17.09.2012
comment
она имеет некоторые проблемы в первом положении, она сохраняет [0] = POINT (73,0166738279393 33,6788721326803) MultiLineString ((73,0131224998036 +33,679001500419; [1] = 73,0119635003153 +33,678392400389, а затем снова [2] = POINT (+73,0166738279393 +33,6788721326803) MultiLineString ((+73,0131224998036 33,679001500419; - person Sarah Salar; 17.09.2012
comment
когда я использую \\s, он не разделяет первую строку, а когда я использовал, он разделяет последние значения - person Sarah Salar; 18.09.2012
comment
Спасибо Раджеш за большую помощь от вас, я решил эту проблему. теперь буду рисовать на карте гугл - person Sarah Salar; 18.09.2012

Для всех, у кого такой же сценарий, я нашел библиотеку с открытым исходным кодом под названием JTS Topology Suite. , который может анализировать строки WKT в Java. Базовый пример из моего приложения выглядит так:

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. Я понимаю, что ОП спрашивал об API-интерфейсе карты Google для Android, однако, если какой-либо читатель также использует 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);
}

Обратите внимание, что lineStyleSet и geomLayer созданы ранее в onCreate активности и могут быть исследованы здесь. geomLayer прост; вот мой 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);
person Paul Richter    schedule 13.02.2014

Файл 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'
}
person CaptainCrunch    schedule 04.02.2016

Вот функция, которую я написал для преобразования простого (без отверстий и т. д.) многоугольника, заданного в 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));
person Assaf S.    schedule 01.02.2015

Просто чтобы расширить ответ Пола, так как его ответ мне очень помог...

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);
}
person cm1    schedule 30.10.2015
comment
Стандарт Well Known Text охватывает все виды геопространственных объектов, и это решение, по крайней мере, пытается преобразовать его в LineString. Это, вероятно, крах. - person russellhoff; 20.05.2020