private List<RouteSegmentResult> prepareResult(
      RoutingContext ctx,
      RouteSegment start,
      RouteSegment end,
      long startNanoTime,
      RouteSegment finalDirectRoute,
      RouteSegment finalReverseRoute) {
    List<RouteSegmentResult> result = new ArrayList<RouteSegmentResult>();

    RouteSegment segment = finalReverseRoute;
    int parentSegmentStart = segment == null ? 0 : segment.segmentEnd;
    while (segment != null) {
      RouteSegmentResult res = new RouteSegmentResult();
      res.object = segment.road;
      res.endPointIndex = segment.segmentStart;
      res.startPointIndex = parentSegmentStart;
      parentSegmentStart = segment.parentSegmentEnd;
      segment = segment.parentRoute;
      // reverse start and end point for start if needed
      // rely that point.segmentStart <= point.segmentEnd for end, start
      if (segment == null
          && res.startPointIndex >= res.endPointIndex
          && res.endPointIndex < res.object.getPointsLength() - 1) {
        res.endPointIndex++;
      }
      // do not add segments consists from 1 point
      if (res.startPointIndex != res.endPointIndex) {
        result.add(res);
      }
      res.startPoint = convertPoint(res.object, res.startPointIndex);
      res.endPoint = convertPoint(res.object, res.endPointIndex);
    }
    Collections.reverse(result);

    segment = finalDirectRoute;
    int parentSegmentEnd = segment == null ? 0 : segment.segmentEnd;
    while (segment != null) {
      RouteSegmentResult res = new RouteSegmentResult();
      res.object = segment.road;
      res.endPointIndex = parentSegmentEnd;
      res.startPointIndex = segment.segmentStart;
      parentSegmentEnd = segment.parentSegmentEnd;

      segment = segment.parentRoute;
      // reverse start and end point for start if needed
      // rely that point.segmentStart <= point.segmentEnd for end, start
      if (segment == null && res.startPointIndex < res.endPointIndex) {
        res.startPointIndex++;
      }
      // do not add segments consists from 1 point
      if (res.startPointIndex != res.endPointIndex) {
        result.add(res);
      }
      res.startPoint = convertPoint(res.object, res.startPointIndex);
      res.endPoint = convertPoint(res.object, res.endPointIndex);
    }
    Collections.reverse(result);

    if (PRINT_TO_CONSOLE_ROUTE_INFORMATION_TO_TEST) {
      System.out.println("ROUTE : ");
      double startLat = MapUtils.get31LatitudeY(start.road.getPoint31YTile(start.segmentEnd));
      double startLon = MapUtils.get31LongitudeX(start.road.getPoint31XTile(start.segmentEnd));
      double endLat = MapUtils.get31LatitudeY(end.road.getPoint31YTile(end.segmentStart));
      double endLon = MapUtils.get31LongitudeX(end.road.getPoint31XTile(end.segmentEnd));
      System.out.println(
          MessageFormat.format(
              "<test regions=\"\" description=\"\" best_percent=\"\" vehicle=\"\" \n"
                  + "    start_lat=\"{0}\" start_lon=\"{1}\" target_lat=\"{2}\" target_lon=\"{3}\">",
              startLat + "", startLon + "", endLat + "", endLon + ""));
      for (RouteSegmentResult res : result) {
        // (res.object.getId() >> 1)
        System.out.println(
            MessageFormat.format(
                "\t<segment id=\"{0}\" start=\"{1}\" end=\"{2}\" name=\"{3}\"/>",
                (res.object.getId() >> 1) + "",
                res.startPointIndex,
                res.endPointIndex,
                (res.object.getName() + "").replace(MapRenderingTypes.REF_CHAR, ' ')));
      }
      System.out.println("</test>");
    }

    ctx.timeToCalculate = (System.nanoTime() - startNanoTime);
    log.info(
        "Time to calculate : "
            + ctx.timeToCalculate / 1e6
            + ", time to load : "
            + ctx.timeToLoad / 1e6
            + ", loaded tiles : "
            + ctx.loadedTiles.size()
            + ", visited segments "
            + ctx.visitedSegments);
    return result;
  }