Changeset 17994 in josm for trunk/src/org


Ignore:
Timestamp:
2021-07-11T03:49:01+02:00 (3 years ago)
Author:
Don-vip
Message:

see #17177 - see #20971 - MVT robustness, better logs, javadoc

Location:
trunk/src/org/openstreetmap/josm
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/data/imagery/vectortile/mapbox/CommandInteger.java

    r17867 r17994  
    22package org.openstreetmap.josm.data.imagery.vectortile.mapbox;
    33
     4import java.util.Arrays;
    45import java.util.stream.Stream;
    56
     
    3132    /**
    3233     * Add a parameter
    33      * @param parameterInteger The parameter to add (converted to {@link short}).
     34     * @param parameterInteger The parameter to add (converted to {@code short}).
    3435     */
    3536    public void addParameter(Number parameterInteger) {
     
    5859     */
    5960    public boolean hasAllExpectedParameters() {
    60             return this.added >= this.parameters.length;
     61        return this.added >= this.parameters.length;
     62    }
     63
     64    @Override
     65    public String toString() {
     66        return "CommandInteger [type=" + type + ", parameters=" + Arrays.toString(parameters) + ']';
    6167    }
    6268}
  • trunk/src/org/openstreetmap/josm/data/imagery/vectortile/mapbox/Feature.java

    r17914 r17994  
    167167     * Get the an object with shapes for the geometry
    168168     * @return An object with usable geometry information
     169     * @throws IllegalArgumentException if the geometry object cannot be created because arguments are not understood
     170     *                                  or the shoelace formula returns 0 for a polygon ring.
    169171     */
    170172    public Geometry getGeometryObject() {
     
    174176        return this.geometryObject;
    175177    }
     178
     179    @Override
     180    public String toString() {
     181        return "Feature [geometry=" + geometry + ", "
     182                + "geometryType=" + geometryType + ", id=" + id + ", "
     183                + (tags != null ? "tags=" + tags + ", " : "")
     184                + (geometryObject != null ? "geometryObject=" + geometryObject : "") + ']';
     185    }
    176186}
  • trunk/src/org/openstreetmap/josm/data/imagery/vectortile/mapbox/Geometry.java

    r17867 r17994  
    2525     * @param geometryType The type of geometry
    2626     * @param commands The commands used to create the geometry
     27     * @throws IllegalArgumentException if arguments are not understood or if the shoelace formula returns 0 for a polygon ring.
    2728     */
    2829    public Geometry(GeometryTypes geometryType, List<CommandInteger> commands) {
     
    3435                    for (int i = 0; i < operations.length / 2; i++) {
    3536                        // Just using Ellipse2D since it extends Shape
    36                         shapes.add(new Ellipse2D.Float(operations[2 * i],
    37                                 operations[2 * i + 1], 0, 0));
     37                        shapes.add(new Ellipse2D.Float(operations[2 * i], operations[2 * i + 1], 0, 0));
    3838                    }
    3939                } else {
  • trunk/src/org/openstreetmap/josm/data/imagery/vectortile/mapbox/MapboxVectorTileSource.java

    r17867 r17994  
    55import java.io.IOException;
    66import java.io.InputStream;
     7import java.nio.file.InvalidPathException;
    78import java.util.List;
    89import java.util.Objects;
     
    4849                mapBoxVectorStyle = MapboxVectorStyle.getMapboxVectorStyle(info.getUrl());
    4950            }
    50         } catch (IOException | JsonException e) {
     51        } catch (IOException | InvalidPathException | JsonException e) {
    5152            Logging.trace(e);
    5253        }
  • trunk/src/org/openstreetmap/josm/data/vector/VectorDataStore.java

    r17867 r17994  
    11// License: GPL. For details, see LICENSE file.
    22package org.openstreetmap.josm.data.vector;
     3
     4import static java.util.stream.Collectors.toCollection;
     5import static java.util.stream.Collectors.toList;
     6
     7import java.awt.Shape;
     8import java.awt.geom.Area;
     9import java.awt.geom.Ellipse2D;
     10import java.awt.geom.Path2D;
     11import java.awt.geom.PathIterator;
     12import java.util.ArrayList;
     13import java.util.Collection;
     14import java.util.Collections;
     15import java.util.List;
     16import java.util.Objects;
    317
    418import org.openstreetmap.gui.jmapviewer.Coordinate;
     
    721import org.openstreetmap.josm.data.IQuadBucketType;
    822import org.openstreetmap.josm.data.imagery.vectortile.VectorTile;
     23import org.openstreetmap.josm.data.imagery.vectortile.mapbox.Feature;
    924import org.openstreetmap.josm.data.imagery.vectortile.mapbox.Layer;
    1025import org.openstreetmap.josm.data.osm.BBox;
     
    2136import org.openstreetmap.josm.tools.JosmRuntimeException;
    2237import org.openstreetmap.josm.tools.Logging;
    23 
    24 import java.awt.geom.Area;
    25 import java.awt.geom.Ellipse2D;
    26 import java.awt.geom.Path2D;
    27 import java.awt.geom.PathIterator;
    28 import java.util.ArrayList;
    29 import java.util.Collection;
    30 import java.util.Collections;
    31 import java.util.List;
    32 import java.util.Objects;
    33 import java.util.stream.Collectors;
    3438
    3539/**
     
    9599        Collection<VectorWay> relationWayList = members.stream().map(VectorRelationMember::getMember)
    96100          .filter(VectorWay.class::isInstance)
    97           .map(VectorWay.class::cast).collect(Collectors.toCollection(ArrayList::new));
     101          .map(VectorWay.class::cast).collect(toCollection(ArrayList::new));
    98102        // Only support way-only relations
    99103        if (relationWayList.size() != relation.getMemberPrimitivesList().size()) {
     
    206210        final PathIterator pathIterator = shape.getPathIterator(null);
    207211        final List<VectorWay> ways = pathIteratorToObjects(tile, layer, featureObjects, pathIterator).stream()
    208           .filter(VectorWay.class::isInstance).map(VectorWay.class::cast).collect(
    209             Collectors.toList());
     212          .filter(VectorWay.class::isInstance).map(VectorWay.class::cast).collect(toList());
    210213        // These nodes technically do not exist, so we shouldn't show them
    211214        ways.stream().flatMap(way -> way.getNodes().stream())
     
    258261    private <T extends Tile & VectorTile> VectorRelation areaToRelation(T tile, Layer layer,
    259262      Collection<VectorPrimitive> featureObjects, Area area) {
    260         final PathIterator pathIterator = area.getPathIterator(null);
    261         final List<VectorPrimitive> members = pathIteratorToObjects(tile, layer, featureObjects, pathIterator);
    262263        VectorRelation vectorRelation = new VectorRelation(layer.getName());
    263         for (VectorPrimitive member : members) {
     264        for (VectorPrimitive member : pathIteratorToObjects(tile, layer, featureObjects, area.getPathIterator(null))) {
    264265            final String role;
    265266            if (member instanceof VectorWay && ((VectorWay) member).isClosed()) {
     
    280281    public <T extends Tile & VectorTile> void addDataTile(T tile) {
    281282        for (Layer layer : tile.getLayers()) {
    282             layer.getFeatures().forEach(feature -> {
    283                 org.openstreetmap.josm.data.imagery.vectortile.mapbox.Geometry geometry = feature
    284                   .getGeometryObject();
    285                 List<VectorPrimitive> featureObjects = new ArrayList<>();
    286                 List<VectorPrimitive> primaryFeatureObjects = new ArrayList<>();
    287                 geometry.getShapes().forEach(shape -> {
    288                     final VectorPrimitive primitive;
    289                     if (shape instanceof Ellipse2D) {
    290                         primitive = pointToNode(tile, layer, featureObjects,
    291                           (int) ((Ellipse2D) shape).getCenterX(), (int) ((Ellipse2D) shape).getCenterY());
    292                     } else if (shape instanceof Path2D) {
    293                         primitive = pathToWay(tile, layer, featureObjects, (Path2D) shape).stream().findFirst()
    294                           .orElse(null);
    295                     } else if (shape instanceof Area) {
    296                         primitive = areaToRelation(tile, layer, featureObjects, (Area) shape);
    297                         primitive.put(RELATION_TYPE, MULTIPOLYGON_TYPE);
    298                     } else {
    299                         // We shouldn't hit this, but just in case
    300                         throw new UnsupportedOperationException();
    301                     }
    302                     primaryFeatureObjects.add(primitive);
    303                 });
    304                 final VectorPrimitive primitive;
    305                 if (primaryFeatureObjects.size() == 1) {
    306                     primitive = primaryFeatureObjects.get(0);
    307                     if (primitive instanceof IRelation && !primitive.isMultipolygon()) {
    308                         primitive.put(JOSM_MERGE_TYPE_KEY, "merge");
    309                     }
    310                 } else if (!primaryFeatureObjects.isEmpty()) {
    311                     VectorRelation relation = new VectorRelation(layer.getName());
    312                     primaryFeatureObjects.stream().map(prim -> new VectorRelationMember("", prim))
    313                       .forEach(relation::addRelationMember);
    314                     primitive = relation;
    315                 } else {
    316                     return;
    317                 }
    318                 primitive.setId(feature.getId());
    319                 // Version 1 <i>and</i> 2 <i>do not guarantee</i> that non-zero ids are unique
    320                 // We depend upon unique ids in the data store
    321                 if (feature.getId() != 0 && this.primitivesMap.containsKey(primitive.getPrimitiveId())) {
    322                     // This, unfortunately, makes a new string
    323                     primitive.put(ORIGINAL_ID, Long.toString(feature.getId()));
    324                     primitive.setId(primitive.getIdGenerator().generateUniqueId());
    325                 }
    326                 if (feature.getTags() != null) {
    327                     feature.getTags().forEach(primitive::put);
    328                 }
    329                 featureObjects.forEach(this::addPrimitive);
    330                 primaryFeatureObjects.forEach(this::addPrimitive);
     283            for (Feature feature : layer.getFeatures()) {
    331284                try {
    332                     this.addPrimitive(primitive);
    333                 } catch (JosmRuntimeException e) {
    334                     Logging.error("{0}/{1}/{2}: {3}", tile.getZoom(), tile.getXtile(), tile.getYtile(), primitive.get("key"));
    335                     throw e;
    336                 }
    337             });
     285                    addFeatureData(tile, layer, feature);
     286                } catch (IllegalArgumentException e) {
     287                    Logging.error("Cannot add vector data for feature {0} of tile {1}: {2}", feature, tile, e.getMessage());
     288                    Logging.error(e);
     289                }
     290            }
    338291        }
    339292        // Replace original_ids with the same object (reduce memory usage)
    340293        // Strings aren't interned automatically in some GC implementations
    341         Collection<IPrimitive> primitives = this.getAllPrimitives().stream().filter(p -> p.hasKey(ORIGINAL_ID))
    342                 .collect(Collectors.toList());
    343         List<String> toReplace = primitives.stream().map(p -> p.get(ORIGINAL_ID)).filter(Objects::nonNull).collect(Collectors.toList());
     294        Collection<IPrimitive> primitives = this.getAllPrimitives().stream().filter(p -> p.hasKey(ORIGINAL_ID)).collect(toList());
     295        List<String> toReplace = primitives.stream().map(p -> p.get(ORIGINAL_ID)).filter(Objects::nonNull).collect(toList());
    344296        primitives.stream().filter(p -> toReplace.contains(p.get(ORIGINAL_ID)))
    345297                .forEach(p -> p.put(ORIGINAL_ID, toReplace.stream().filter(shared -> shared.equals(p.get(ORIGINAL_ID)))
    346298                        .findAny().orElse(null)));
     299    }
     300
     301    private <T extends Tile & VectorTile> void addFeatureData(T tile, Layer layer, Feature feature) {
     302        List<VectorPrimitive> featureObjects = new ArrayList<>();
     303        List<VectorPrimitive> primaryFeatureObjects = feature.getGeometryObject().getShapes().stream()
     304                .map(shape -> shapeToPrimaryFeatureObject(tile, layer, shape, featureObjects)).collect(toList());
     305        final VectorPrimitive primitive;
     306        if (primaryFeatureObjects.size() == 1) {
     307            primitive = primaryFeatureObjects.get(0);
     308            if (primitive instanceof IRelation && !primitive.isMultipolygon()) {
     309                primitive.put(JOSM_MERGE_TYPE_KEY, "merge");
     310            }
     311        } else if (!primaryFeatureObjects.isEmpty()) {
     312            VectorRelation relation = new VectorRelation(layer.getName());
     313            primaryFeatureObjects.stream().map(prim -> new VectorRelationMember("", prim))
     314              .forEach(relation::addRelationMember);
     315            primitive = relation;
     316        } else {
     317            return;
     318        }
     319        primitive.setId(feature.getId());
     320        // Version 1 <i>and</i> 2 <i>do not guarantee</i> that non-zero ids are unique
     321        // We depend upon unique ids in the data store
     322        if (feature.getId() != 0 && this.primitivesMap.containsKey(primitive.getPrimitiveId())) {
     323            // This, unfortunately, makes a new string
     324            primitive.put(ORIGINAL_ID, Long.toString(feature.getId()));
     325            primitive.setId(primitive.getIdGenerator().generateUniqueId());
     326        }
     327        if (feature.getTags() != null) {
     328            feature.getTags().forEach(primitive::put);
     329        }
     330        featureObjects.forEach(this::addPrimitive);
     331        primaryFeatureObjects.forEach(this::addPrimitive);
     332        try {
     333            this.addPrimitive(primitive);
     334        } catch (JosmRuntimeException e) {
     335            Logging.error("{0}/{1}/{2}: {3}", tile.getZoom(), tile.getXtile(), tile.getYtile(), primitive.get("key"));
     336            throw e;
     337        }
     338    }
     339
     340    private <T extends Tile & VectorTile> VectorPrimitive shapeToPrimaryFeatureObject(
     341            T tile, Layer layer, Shape shape, List<VectorPrimitive> featureObjects) {
     342        final VectorPrimitive primitive;
     343        if (shape instanceof Ellipse2D) {
     344            primitive = pointToNode(tile, layer, featureObjects,
     345                    (int) ((Ellipse2D) shape).getCenterX(), (int) ((Ellipse2D) shape).getCenterY());
     346        } else if (shape instanceof Path2D) {
     347            primitive = pathToWay(tile, layer, featureObjects, (Path2D) shape).stream().findFirst().orElse(null);
     348        } else if (shape instanceof Area) {
     349            primitive = areaToRelation(tile, layer, featureObjects, (Area) shape);
     350            primitive.put(RELATION_TYPE, MULTIPOLYGON_TYPE);
     351        } else {
     352            // We shouldn't hit this, but just in case
     353            throw new UnsupportedOperationException(Objects.toString(shape));
     354        }
     355        return primitive;
    347356    }
    348357
  • trunk/src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSStyleSource.java

    r17112 r17994  
    432432    @Override
    433433    public String toString() {
    434         return rules.stream().map(MapCSSRule::toString).collect(Collectors.joining("\n"));
     434        // Avoids ConcurrentModificationException
     435        return new ArrayList<>(rules).stream().map(MapCSSRule::toString).collect(Collectors.joining("\n"));
    435436    }
    436437}
Note: See TracChangeset for help on using the changeset viewer.