@Override
 public void init() {
   // writer initialization
   writer.init(currentTile);
   // exclusionHelper
   if (XplaneOptionsHelper.getOptions().isSmartExclusions()) {
     exclusionsHelper.run();
   }
 }
  @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");
    }
  }
  /**
   * 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;
  }