protected void setPosition(
     PositionSettings pos, List<HeightInfo> heights, BasicModelData obj, int heightPos) {
   HeightInfo height = heights.get(heightPos);
   obj.setPosition(
       height.getX() + randomizeDouble(-xRatio, xRatio),
       randomizeDouble(pos.getMinY(), pos.getMaxY()),
       height.getZ() + randomizeDouble(-zRatio, zRatio));
   correctPosition(obj, pos, heights);
 }
 protected void correctPosition(
     BasicModelData obj, PositionSettings pos, List<HeightInfo> positions) {
   double xVar = xRatio;
   double zVar = zRatio;
   double x = obj.getX();
   double z = obj.getZ();
   if (!positions.isEmpty() || collisionTree != null) {
     HeightInfo actual = new HeightInfo(obj.getX(), 0, obj.getZ());
     HeightInfo nearest = new HeightInfo(Double.MAX_VALUE, 0, Double.MAX_VALUE);
     if (!positions.isEmpty()) {
       nearest = findNearest(positions, actual, nearest);
       x = nearest.getX();
       z = nearest.getZ();
     }
     if (collisionTree != null) {
       actual.setSx(obj.getSx());
       actual.setSz(obj.getSz());
       TreeNode place = collisionTree.findPlace(actual);
       if (place != null) {
         x = place.getMid()[0];
         z = place.getMid()[1];
         double nodeRange = place.getRange();
         xVar = nodeRange + 1 - actual.getSx();
         zVar = nodeRange + 1 - actual.getSz();
         TreeNode.mark(place);
       } else {
         collisionDetected = true;
       }
     }
   }
   obj.setX(x + randomizeDouble(-xVar, xVar));
   obj.setZ(z + randomizeDouble(-zVar, zVar));
   correctPosition(obj, pos);
 }
  public List<GeneratedObject> generate(GenerationInfo info) {
    long time = System.currentTimeMillis();
    int collisionsValue = info.getArgs().get(Consts.COLLISIONS).intValue();
    collisions = collisionsValue == 1 ? true : false;
    Dimension mapDimensions = Mediator.getMapDimensions();
    if (mapDimensions == null) {
      WindowUtil.displayError(PropertiesKeys.NO_HEIGHTMAP);
      return new ArrayList<>();
    }
    if (collisions) {
      collisionTree =
          TreeNode.createTree(
              Mediator.getMapWidth(),
              Mediator.getMapHeight(),
              (short) (Math.log(mapDimensions.getWidth()) / Math.log(2)));
    }
    xRatio = Mediator.getMapWidth() / mapDimensions.width;
    zRatio = Mediator.getMapHeight() / mapDimensions.height;
    yRatio = Mediator.getMapMaxYSetting() / Mediator.getMapMaxY();
    HeightInfo.setThreshold((xRatio + zRatio) / 2.0);

    List<GeneratedObject> result = generationMethod(info);
    Mediator.updateModels(result);
    time = System.currentTimeMillis() - time;
    System.out.println("Time used: " + time + " ms.");
    time /= 1000F;
    collisionTree = null;
    int size = result.size();
    if (collisionDetected) {
      collisionDetected = false;
      WindowUtil.displayError(PropertiesKeys.COLLISION, size, time);
    } else {
      if (size > 0) {
        WindowUtil.displayInfo(PropertiesKeys.RESULT, size, time);
      } else {
        WindowUtil.displayError(PropertiesKeys.NO_RESULT);
      }
    }
    return result;
  }
 private HeightInfo findNearest(
     List<HeightInfo> positions, HeightInfo actual, HeightInfo nearest) {
   double minLength = Double.MAX_VALUE;
   Collections.shuffle(positions);
   for (HeightInfo i : positions) {
     if (i.equals(actual)) {
       return i;
     }
     double tempLenght = getLength(i.getX(), nearest.getX(), i.getZ(), nearest.getZ());
     if (minLength < 0.5) {
       break;
     }
     if (tempLenght < minLength) {
       minLength = tempLenght;
       nearest = i;
     }
   }
   return nearest;
 }