@Override public void processPolygon(OsmPolygon osmPolygon) throws Osm2xpBusinessException { // polygon is null or empty don't process it if (osmPolygon.getNodes() != null && !osmPolygon.getNodes().isEmpty()) { // polygon MUST be in clockwise order osmPolygon.setPolygon(GeomUtils.forceClockwise(osmPolygon.getPolygon())); // if we're on a single pass mode // here we must check if the polygon is on more than one tile // if that's the case , we must split it into several polys List<OsmPolygon> polygons = new ArrayList<OsmPolygon>(); if (GuiOptionsHelper.getOptions().isSinglePass()) { polygons.addAll(osmPolygon.splitPolygonAroundTiles()); } // if not on a single pass mode, add this single polygon to the poly // list else { polygons.add(osmPolygon); } // try to transform those polygons into dsf objects. for (OsmPolygon poly : polygons) { // look for light rules processLightObject(poly); // try to generate a 3D object if (!process3dObject(poly)) { // nothing generated? try to generate a facade building. if (!processBuilding(poly)) { // nothing generated? try to generate a forest. processForest(poly); } } } } }
@Override public Boolean mustStoreNode(Node node) { Boolean result = true; if (!GuiOptionsHelper.getOptions().isSinglePass()) { result = GeomUtils.compareCoordinates(currentTile, node); } return result; }
@Override public void complete() { // if smart exclusions enabled and tile is not empty, send them to // writer if (!StatsHelper.isTileEmpty(stats) && XplaneOptionsHelper.getOptions().isSmartExclusions()) { String exclusions = exclusionsHelper.exportExclusions(); writer.complete(exclusions); } else { writer.complete(null); } if (!StatsHelper.isTileEmpty(stats)) { Osm2xpLogger.info( "Tile " + (int) currentTile.x + "/" + (int) currentTile.y + " stats : " + stats.getBuildingsNumber() + " buildings, " + stats.getForestsNumber() + " forests, " + stats.getStreetlightsNumber() + " street lights, " + stats.getObjectsNumber() + " objects. (generation took " + MiscUtils.getTimeDiff(startTime, new Date()) + ")"); // stats try { if (XplaneOptionsHelper.getOptions().isGenerateXmlStats() || XplaneOptionsHelper.getOptions().isGeneratePdfStats()) { StatsHelper.getStatsList().add(stats); } if (XplaneOptionsHelper.getOptions().isGenerateXmlStats()) { StatsHelper.saveStats(folderPath, currentTile, stats); } if (XplaneOptionsHelper.getOptions().isGeneratePdfStats()) { StatsHelper.generatePdfReport(folderPath, stats); } } catch (Osm2xpBusinessException e) { Osm2xpLogger.error("Error saving stats file for tile " + currentTile, e); } } else if (!GuiOptionsHelper.getOptions().isSinglePass()) { Osm2xpLogger.info( "Tile " + (int) currentTile.x + "/" + (int) currentTile.y + " is empty, no dsf generated"); } }
@Override public void processNode(Node node) throws Osm2xpBusinessException { // process the node if we're on a single pass mode. // if not on single pass, only process if the node is on the current // lat/long tile if (XplaneOptionsHelper.getOptions().isGenerateObj()) { if ((!GuiOptionsHelper.getOptions().isSinglePass() && GeomUtils.compareCoordinates(currentTile, node)) || GuiOptionsHelper.getOptions().isSinglePass()) { // write a 3D object in the dsf file if this node is in an // object // rule XplaneDsf3DObject object = dsfObjectsProvider.getRandomDsfObjectIndexAndAngle(node.getTag(), node.getId()); if (object != null) { List<Node> nodes = new ArrayList<Node>(); nodes.add(node); object.setPolygon(new OsmPolygon(node.getId(), node.getTag(), nodes)); writeObjectToDsf(object); } } } }
/** * choose and write a 3D object in the dsf file. * * @param polygon osm polygon. * @return true if a 3D object has been written in the dsf file. */ private boolean process3dObject(OsmPolygon osmPolygon) { Boolean result = false; if (XplaneOptionsHelper.getOptions().isGenerateObj()) { // simplify shape if checked and if necessary if (GuiOptionsHelper.getOptions().isSimplifyShapes() && !osmPolygon.isSimplePolygon()) { osmPolygon.simplifyPolygon(); } XplaneDsfObject object = dsfObjectsProvider.getRandomDsfObject(osmPolygon); if (object != null) { object.setPolygon(osmPolygon); try { writeObjectToDsf(object); result = true; } catch (Osm2xpBusinessException e) { result = false; } } } return result; }
/** * Construct and write a facade building in the dsf file. * * @param osmPolygon osm polygon * @return true if a building has been gennerated in the dsf file. */ private boolean processBuilding(OsmPolygon osmPolygon) { Boolean result = false; if (XplaneOptionsHelper.getOptions().isGenerateBuildings() && OsmUtils.isBuilding(osmPolygon.getTags()) && !OsmUtils.isExcluded(osmPolygon.getTags(), osmPolygon.getId()) && osmPolygon.getPolygon().getVertexNumber() > BUILDING_MIN_VECTORS && osmPolygon.getPolygon().getVertexNumber() < BUILDING_MAX_VECTORS) { // check that the largest vector of the building // and that the area of the osmPolygon.getPolygon() are over the // minimum values set by the user Double maxVector = osmPolygon.getMaxVectorSize(); if (maxVector > XplaneOptionsHelper.getOptions().getMinHouseSegment() && maxVector < XplaneOptionsHelper.getOptions().getMaxHouseSegment() && ((osmPolygon.getPolygon().getArea() * 100000) * 100000) > XplaneOptionsHelper.getOptions().getMinHouseArea()) { // simplify shape if checked and if necessary if (GuiOptionsHelper.getOptions().isSimplifyShapes() && !osmPolygon.isSimplePolygon()) { osmPolygon.simplifyPolygon(); } // compute height and facade dsf index osmPolygon.setHeight(computeBuildingHeight(osmPolygon)); Integer facade = computeFacadeIndex(osmPolygon); // write building in dsf file writeBuildingToDsf(osmPolygon, facade); // Smart exclusions if (XplaneOptionsHelper.getOptions().isSmartExclusions()) { exclusionsHelper.addTodoPolygon(osmPolygon); exclusionsHelper.run(); } result = true; } } return result; }
@Override protected void parseDense(DenseNodes nodes) { // parse nodes only if we're not on a single pass mode, or if the nodes // collection of single pass mode is done if (this.nodesRefCollectionDone) { long lastId = 0, lastLat = 0, lastLon = 0; int j = 0; DenseInfo di = null; if (nodes.hasDenseinfo()) { di = nodes.getDenseinfo(); } for (int i = 0; i < nodes.getIdCount(); i++) { List<Tag> tags = new ArrayList<Tag>(); long lat = nodes.getLat(i) + lastLat; lastLat = lat; long lon = nodes.getLon(i) + lastLon; lastLon = lon; long id = nodes.getId(i) + lastId; lastId = id; double latf = parseLat(lat), lonf = parseLon(lon); if (nodes.getKeysValsCount() > 0) { while (nodes.getKeysVals(j) != 0) { int keyid = nodes.getKeysVals(j++); int valid = nodes.getKeysVals(j++); Tag tag = new Tag(); tag.setKey(getStringById(keyid)); tag.setValue(getStringById(valid)); tags.add(tag); } j++; } if (di != null) { com.osm2xp.model.osm.Node node = new com.osm2xp.model.osm.Node(); node.setId(id); node.setLat(latf); node.setLon(lonf); node.getTag().addAll(tags); try { // give the node to the translator for processing translator.processNode(node); // ask translator if we have to store this node if we // aren't on a single pass mode if (!GuiOptionsHelper.getOptions().isSinglePass()) { if (translator.mustStoreNode(node)) { processor.storeNode(node); } } // if we're on a single pass mode, and if // nodesRefCollectionDone is true it means we already // have the reference of usefull nodes, so we check if // this node is one of them, if yes, store it else { if (processor.getNode(node.getId()) != null) { processor.storeNode(node); } } } catch (Osm2xpBusinessException e) { Osm2xpLogger.error("Error processing node.", e); } catch (DataSinkException e) { Osm2xpLogger.error("Error processing node.", e); } } } } }