<commit_before>// __BEGIN_LICENSE__
//  Copyright (c) 2009-2013, United States Government as represented by the
//  Administrator of the National Aeronautics and Space Administration. All
//  rights reserved.
//
//  The NGT platform is licensed under the Apache License, Version 2.0 (the
//  "License"); you may not use this file except in compliance with the
//  License. You may obtain a copy of the License at
//  http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
// __END_LICENSE__

/// \file bathy_correct.cc
///

#include <asp/Core/PointUtils.h>
#include <asp/Core/Macros.h>
#include <asp/Core/Common.h>
#include <asp/Core/StereoSettings.h>

#include <vw/Core/Stopwatch.h>
#include <vw/FileIO/DiskImageUtils.h>
#include <vw/Cartography/shapeFile.h>

#include <vw/Math/RANSAC.h>

#include <Eigen/Dense>

using namespace vw;
using namespace vw::cartography;
namespace po = boost::program_options;
namespace fs = boost::filesystem;

// Compute the 3D locations at the shape corners based on interpolating
// into the DEM and converting to ECEF.
void find_xyz_at_shape_corners(std::vector<vw::geometry::dPoly> const& polyVec,
                               vw::cartography::GeoReference const& shape_georef,
                               vw::cartography::GeoReference const& dem_georef,
                               ImageViewRef< PixelMask<float> > interp_dem,
                               std::vector<Eigen::Vector3d> & xyz_vec) {

  xyz_vec.clear();

  for (size_t p = 0; p < polyVec.size(); p++){
    vw::geometry::dPoly const& poly = polyVec[p];

    const double * xv       = poly.get_xv();
    const double * yv       = poly.get_yv();
    const int    * numVerts = poly.get_numVerts();
    int numPolys            = poly.get_numPolys();

    int start = 0;
    for (int pIter = 0; pIter < numPolys; pIter++){

      if (pIter > 0) start += numVerts[pIter - 1];

      int numV = numVerts[pIter];
      for (int vIter = 0; vIter < numV; vIter++) {

        Vector2 proj_pt(xv[start + vIter], yv[start + vIter]);

        // Convert from projected coordinates to lonlat
        Vector2 lonlat = shape_georef.point_to_lonlat(proj_pt);

        // Convert to DEM pixel
        Vector2 pix = dem_georef.lonlat_to_pixel(lonlat);

        PixelMask<float> h = interp_dem(pix.x(), pix.y());

        if (!is_valid(h))
          continue;

        Vector3 llh;
        llh[0] = lonlat[0];
        llh[1] = lonlat[1];
        llh[2] = h.child();

        Vector3 xyz = dem_georef.datum().geodetic_to_cartesian(llh);

        Eigen::Vector3d eigen_xyz;
        for (size_t coord = 0; coord < 3; coord++)
          eigen_xyz[coord] = xyz[coord];

        xyz_vec.push_back(eigen_xyz);
      }
    }

  }
}

// Best fit plane without outlier removal
std::pair<Eigen::Vector3d, Eigen::Vector3d>
best_plane_from_points(const std::vector<Eigen::Vector3d> & c) {

  // Copy coordinates to a matrix in Eigen format
  size_t num_points = c.size();
  Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic > coord(3, num_points);
  for (size_t i = 0; i < num_points; i++)
    coord.col(i) = c[i];

  // calculate centroid
  Eigen::Vector3d centroid(coord.row(0).mean(), coord.row(1).mean(), coord.row(2).mean());

  // subtract centroid
  for (size_t i = 0; i < 3; i++)
    coord.row(i).array() -= centroid(i);

  // We only need the left-singular matrix here
  // http://math.stackexchange.com/questions/99299/best-fitting-plane-given-a-set-of-points
  auto svd = coord.jacobiSvd(Eigen::ComputeThinU | Eigen::ComputeThinV);
  Eigen::Vector3d plane_normal = svd.matrixU().rightCols<1>();
  return std::make_pair(centroid, plane_normal);
}

// A functor which returns the best fit plane a*x + b*y + c*z + d = 0
// as the vector (a, b, c, d) with a*a + b*b + c*c = 1 to be used
// with RANSAC to remove outliers.

struct BestFitPlaneFunctor {
  typedef vw::Matrix<double, 1, 4> result_type;

    /// A best fit plane requires pairs of data points to make a fit.
    template <class ContainerT>
    size_t min_elements_needed_for_fit(ContainerT const& /*example*/) const { return 3; }

    /// This function can match points in any container that supports
    /// the size() and operator[] methods.  The container is usually a
    /// vw::Vector<>, but you could substitute other classes here as
    /// well.
    template <class ContainerT>
    vw::Matrix<double> operator() (std::vector<ContainerT> const& p1,
                                   std::vector<ContainerT> const& p2,
                                   vw::Matrix<double> const& /*seed_input*/
                                   = vw::Matrix<double>() ) const {

      // check consistency
      VW_ASSERT( p1.size() == p2.size(),
                 vw::ArgumentErr() << "Cannot compute similarity transformation. "
                 << "p1 and p2 are not the same size." );
      VW_ASSERT( !p1.empty() && p1.size() >= min_elements_needed_for_fit(p1[0]),
                 vw::ArgumentErr() << "Cannot compute similarity transformation. "
                 << "Insufficient data.\n");

      std::pair<Eigen::Vector3d, Eigen::Vector3d> plane = best_plane_from_points(p1);

      Eigen::Vector3d & centroid = plane.first;
      Eigen::Vector3d & normal = plane.second;

      Matrix<double> result(1, 4);
      for (int col = 0; col < 3; col++)
        result(0, col) = normal[col];

      result(0, 3) = -normal.dot(centroid);

      // Make the normal always point "up", away from the origin,
      // which means that the free term must be negative
      if (result(0, 3) > 0) {
        for (int col = 0; col < 4; col++)
          result(0, col) *= -1.0;
      }

      return result;
    }
};

// Given a 1x4 matrix H = (a, b, c, d) determining the plane
// a * x + b * y + c * z + d = 0, find the distance to this plane
// from a point xyz.

template<class Vec3>
double dist_to_plane(vw::Matrix<double, 1, 4> const& H, Vec3 const& xyz) {

  double ans = 0.0;
  for (unsigned col = 0; col < 3; col++) {
      ans += H(0, col) * xyz[col];
  }
  ans += H(0, 3);

  return std::abs(ans);
}

// The value p2 is needed by the interface but we don't use it
struct BestFitPlaneErrorMetric {
  template <class RelationT, class ContainerT>
  double operator() (RelationT  const& H, ContainerT const& p1, ContainerT const& p2) const {
    return dist_to_plane(H, p1);
  }
};

struct Options : vw::cartography::GdalWriteOptions {
  std::string shapefile, dem, bathy_plane;
  double outlier_threshold;
  int num_ransac_iterations;
  Options(): outlier_threshold(0.2), num_ransac_iterations(1000) {}
};

void handle_arguments(int argc, char *argv[], Options& opt) {

  po::options_description general_options("General Options");
  general_options.add_options()
    ("shapefile",   po::value(&opt.shapefile),
     "The shapefile with vertices whose coordinates will be looked up in the DEM.")
    ("dem",   po::value(&opt.dem),
     "The DEM to use.")
    ("bathy-plane",   po::value(&opt.bathy_plane),
     "The output file storing the computed plane as four coefficients a, b, c, d, "
     "with the plane being a*x + b*y + c*z + d = 0.")
    ("outlier-threshold",
     po::value(&opt.outlier_threshold)->default_value(0.2),
     "A value, in meters, to determine the distance from a sampled point on the DEM to the "
     "best-fit plane to determine if it will be marked as outlier and not "
     "included in the calculation of that plane.")
    ("num-ransac-iterations",
     po::value(&opt.num_ransac_iterations)->default_value(1000),
     "Number of RANSAC iterations to use to find the best-fitting plane.");

  general_options.add( vw::cartography::GdalWriteOptionsDescription(opt) );

  po::options_description positional("");
  //positional.add_options()
  //   ("input-files", po::value< std::vector<std::string> >(), "Input files");

  po::positional_options_description positional_desc;
  //positional_desc.add("input-files", -1);

  std::string usage("[options]");
  bool allow_unregistered = false;
  std::vector<std::string> unregistered;
  po::variables_map vm =
    asp::check_command_line(argc, argv, opt, general_options, general_options,
                            positional, positional_desc, usage,
                            allow_unregistered, unregistered);

  if (opt.shapefile == "")
    vw_throw( ArgumentErr() << "Missing the input shapefile.\n" << usage << general_options );
  if (opt.dem == "")
    vw_throw( ArgumentErr() << "Missing the input dem.\n" << usage << general_options );
  if (opt.bathy_plane == "")
    vw_throw( ArgumentErr() << "Missing the output bathy plane file.\n"
              << usage << general_options );
}

int main( int argc, char *argv[] ) {

  Options opt;
  try {
    handle_arguments(argc, argv, opt);

    // Read the shapefile
    std::cout << "Reading the shapefile: " << opt.shapefile << std::endl;
    bool has_shape_georef;
    std::vector<vw::geometry::dPoly> polyVec;
    std::string poly_color;
    vw::cartography::GeoReference shape_georef;
    read_shapefile(opt.shapefile, poly_color, has_shape_georef, shape_georef, polyVec);
    if (!has_shape_georef)
      vw_throw( ArgumentErr() << "The input shapefile has no georeference.\n" );

    // Read the DEM and its associated data
    // TODO(oalexan1): Think more about the interpolation method
    std::cout << "Reading the DEM: " << opt.dem << std::endl;
    vw::cartography::GeoReference dem_georef;
    if (!read_georeference(dem_georef, opt.dem))
      vw_throw( ArgumentErr() << "The input DEM has no georeference.\n" );
    double dem_nodata_val = -std::numeric_limits<float>::max(); // note we use a float nodata
    if (!vw::read_nodata_val(opt.dem, dem_nodata_val))
      vw_throw( ArgumentErr() << "Could not read the DEM nodata value.\n");
    std::cout << "Read DEM nodata value: " << dem_nodata_val << std::endl;
    DiskImageView<float> dem(opt.dem);
    std::cout << "The DEM width and height are: " << dem.cols() << ' ' << dem.rows() << std::endl;
    ImageViewRef< PixelMask<float> > interp_dem
      = interpolate(create_mask(dem, dem_nodata_val),
                    BilinearInterpolation(), ConstantEdgeExtension());

    // Find the ECEF coordinates of the shape corners
    std::vector<Eigen::Vector3d> xyz_vec;
    find_xyz_at_shape_corners(polyVec,shape_georef, dem_georef, interp_dem, xyz_vec);

    // Compute the water surface using RANSAC
    std::vector<Eigen::Vector3d> dummy_vec(xyz_vec.size()); // Required by the interface
    std::vector<size_t> inlier_indices;
    double inlier_threshold = opt.outlier_threshold;
    int    min_num_output_inliers = std::max(xyz_vec.size()/2, size_t(3));
    bool   reduce_min_num_output_inliers_if_no_fit = true;
    vw::Matrix<double> H;
    try {
      math::RandomSampleConsensus<BestFitPlaneFunctor, BestFitPlaneErrorMetric>
        ransac(BestFitPlaneFunctor(), BestFitPlaneErrorMetric(),
               opt.num_ransac_iterations, inlier_threshold,
               min_num_output_inliers, reduce_min_num_output_inliers_if_no_fit);

      H = ransac(xyz_vec, dummy_vec);

      inlier_indices = ransac.inlier_indices(H, xyz_vec, dummy_vec);
    } catch (const vw::math::RANSACErr& e ) {
      vw_out() << "RANSAC Failed: " << e.what() << "\n";
    }
    vw_out() << "Found " << inlier_indices.size() << " / " << xyz_vec.size() << " inliers.\n";

    //std::cout << "Final matrix is " << H << std::endl;
    double max_error = - 1.0, max_inlier_error = -1.0;
    for (size_t it = 0; it < xyz_vec.size(); it++)
      max_error = std::max(max_error, dist_to_plane(H, xyz_vec[it]));

    for (size_t it = 0; it < inlier_indices.size(); it++)
      max_inlier_error = std::max(max_inlier_error, dist_to_plane(H, xyz_vec[inlier_indices[it]]));

    std::cout << "Max distance to the plane (meters): " << max_error << std::endl;
    std::cout << "Max inlier distance to the plane (meters): " << max_inlier_error << std::endl;

    std::cout << "Writing: " << opt.bathy_plane << std::endl;
    std::ofstream bp(opt.bathy_plane.c_str());
    bp.precision(17);
    for (int col = 0; col < H.cols(); col++) {
      bp << H(0, col);
      if (col < H.cols() - 1)
        bp << " ";
      else
        bp << "\n";
    }
    bp.close();

  } ASP_STANDARD_CATCHES;

  return 0;
}
<commit_msg>bathy_plane_calc: Print the plane height and off-nadir inclination<commit_after>// __BEGIN_LICENSE__
//  Copyright (c) 2009-2013, United States Government as represented by the
//  Administrator of the National Aeronautics and Space Administration. All
//  rights reserved.
//
//  The NGT platform is licensed under the Apache License, Version 2.0 (the
//  "License"); you may not use this file except in compliance with the
//  License. You may obtain a copy of the License at
//  http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
// __END_LICENSE__

/// \file bathy_correct.cc
///

#include <asp/Core/PointUtils.h>
#include <asp/Core/Macros.h>
#include <asp/Core/Common.h>
#include <asp/Core/StereoSettings.h>

#include <vw/Core/Stopwatch.h>
#include <vw/FileIO/DiskImageUtils.h>
#include <vw/Cartography/shapeFile.h>

#include <vw/Math/RANSAC.h>

#include <Eigen/Dense>

using namespace vw;
using namespace vw::cartography;
namespace po = boost::program_options;
namespace fs = boost::filesystem;

// Compute the 3D locations at the shape corners based on interpolating
// into the DEM and converting to ECEF.
void find_xyz_at_shape_corners(std::vector<vw::geometry::dPoly> const& polyVec,
                               vw::cartography::GeoReference const& shape_georef,
                               vw::cartography::GeoReference const& dem_georef,
                               ImageViewRef< PixelMask<float> > interp_dem,
                               std::vector<Eigen::Vector3d> & xyz_vec) {

  xyz_vec.clear();

  for (size_t p = 0; p < polyVec.size(); p++){
    vw::geometry::dPoly const& poly = polyVec[p];

    const double * xv       = poly.get_xv();
    const double * yv       = poly.get_yv();
    const int    * numVerts = poly.get_numVerts();
    int numPolys            = poly.get_numPolys();

    int start = 0;
    for (int pIter = 0; pIter < numPolys; pIter++){

      if (pIter > 0) start += numVerts[pIter - 1];

      int numV = numVerts[pIter];
      for (int vIter = 0; vIter < numV; vIter++) {

        Vector2 proj_pt(xv[start + vIter], yv[start + vIter]);

        // Convert from projected coordinates to lonlat
        Vector2 lonlat = shape_georef.point_to_lonlat(proj_pt);

        // Convert to DEM pixel
        Vector2 pix = dem_georef.lonlat_to_pixel(lonlat);

        PixelMask<float> h = interp_dem(pix.x(), pix.y());

        if (!is_valid(h))
          continue;

        Vector3 llh;
        llh[0] = lonlat[0];
        llh[1] = lonlat[1];
        llh[2] = h.child();

        Vector3 xyz = dem_georef.datum().geodetic_to_cartesian(llh);

        Eigen::Vector3d eigen_xyz;
        for (size_t coord = 0; coord < 3; coord++)
          eigen_xyz[coord] = xyz[coord];

        xyz_vec.push_back(eigen_xyz);
      }
    }

  }
}

// Best fit plane without outlier removal
std::pair<Eigen::Vector3d, Eigen::Vector3d>
best_plane_from_points(const std::vector<Eigen::Vector3d> & c) {

  // Copy coordinates to a matrix in Eigen format
  size_t num_points = c.size();
  Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic > coord(3, num_points);
  for (size_t i = 0; i < num_points; i++)
    coord.col(i) = c[i];

  // calculate centroid
  Eigen::Vector3d centroid(coord.row(0).mean(), coord.row(1).mean(), coord.row(2).mean());

  // subtract centroid
  for (size_t i = 0; i < 3; i++)
    coord.row(i).array() -= centroid(i);

  // We only need the left-singular matrix here
  // http://math.stackexchange.com/questions/99299/best-fitting-plane-given-a-set-of-points
  auto svd = coord.jacobiSvd(Eigen::ComputeThinU | Eigen::ComputeThinV);
  Eigen::Vector3d plane_normal = svd.matrixU().rightCols<1>();
  return std::make_pair(centroid, plane_normal);
}

// A functor which returns the best fit plane a*x + b*y + c*z + d = 0
// as the vector (a, b, c, d) with a*a + b*b + c*c = 1 to be used
// with RANSAC to remove outliers.

struct BestFitPlaneFunctor {
  typedef vw::Matrix<double, 1, 4> result_type;

    /// A best fit plane requires pairs of data points to make a fit.
    template <class ContainerT>
    size_t min_elements_needed_for_fit(ContainerT const& /*example*/) const { return 3; }

    /// This function can match points in any container that supports
    /// the size() and operator[] methods.  The container is usually a
    /// vw::Vector<>, but you could substitute other classes here as
    /// well.
    template <class ContainerT>
    vw::Matrix<double> operator() (std::vector<ContainerT> const& p1,
                                   std::vector<ContainerT> const& p2,
                                   vw::Matrix<double> const& /*seed_input*/
                                   = vw::Matrix<double>() ) const {

      // check consistency
      VW_ASSERT( p1.size() == p2.size(),
                 vw::ArgumentErr() << "Cannot compute similarity transformation. "
                 << "p1 and p2 are not the same size." );
      VW_ASSERT( !p1.empty() && p1.size() >= min_elements_needed_for_fit(p1[0]),
                 vw::ArgumentErr() << "Cannot compute similarity transformation. "
                 << "Insufficient data.\n");

      std::pair<Eigen::Vector3d, Eigen::Vector3d> plane = best_plane_from_points(p1);

      Eigen::Vector3d & centroid = plane.first;
      Eigen::Vector3d & normal = plane.second;

      Matrix<double> result(1, 4);
      for (int col = 0; col < 3; col++)
        result(0, col) = normal[col];

      result(0, 3) = -normal.dot(centroid);

      // Make the normal always point "up", away from the origin,
      // which means that the free term must be negative
      if (result(0, 3) > 0) {
        for (int col = 0; col < 4; col++)
          result(0, col) *= -1.0;
      }

      return result;
    }
};

// Given a 1x4 matrix H = (a, b, c, d) determining the plane
// a * x + b * y + c * z + d = 0, find the distance to this plane
// from a point xyz.

template<class Vec3>
double dist_to_plane(vw::Matrix<double, 1, 4> const& H, Vec3 const& xyz) {

  double ans = 0.0;
  for (unsigned col = 0; col < 3; col++) {
      ans += H(0, col) * xyz[col];
  }
  ans += H(0, 3);

  return std::abs(ans);
}

// The value p2 is needed by the interface but we don't use it
struct BestFitPlaneErrorMetric {
  template <class RelationT, class ContainerT>
  double operator() (RelationT  const& H, ContainerT const& p1, ContainerT const& p2) const {
    return dist_to_plane(H, p1);
  }
};

struct Options : vw::cartography::GdalWriteOptions {
  std::string shapefile, dem, bathy_plane;
  double outlier_threshold;
  int num_ransac_iterations;
  Options(): outlier_threshold(0.2), num_ransac_iterations(1000) {}
};

void handle_arguments(int argc, char *argv[], Options& opt) {

  po::options_description general_options("General Options");
  general_options.add_options()
    ("shapefile",   po::value(&opt.shapefile),
     "The shapefile with vertices whose coordinates will be looked up in the DEM.")
    ("dem",   po::value(&opt.dem),
     "The DEM to use.")
    ("bathy-plane",   po::value(&opt.bathy_plane),
     "The output file storing the computed plane as four coefficients a, b, c, d, "
     "with the plane being a*x + b*y + c*z + d = 0.")
    ("outlier-threshold",
     po::value(&opt.outlier_threshold)->default_value(0.2),
     "A value, in meters, to determine the distance from a sampled point on the DEM to the "
     "best-fit plane to determine if it will be marked as outlier and not "
     "included in the calculation of that plane.")
    ("num-ransac-iterations",
     po::value(&opt.num_ransac_iterations)->default_value(1000),
     "Number of RANSAC iterations to use to find the best-fitting plane.");

  general_options.add( vw::cartography::GdalWriteOptionsDescription(opt) );

  po::options_description positional("");
  //positional.add_options()
  //   ("input-files", po::value< std::vector<std::string> >(), "Input files");

  po::positional_options_description positional_desc;
  //positional_desc.add("input-files", -1);

  std::string usage("[options]");
  bool allow_unregistered = false;
  std::vector<std::string> unregistered;
  po::variables_map vm =
    asp::check_command_line(argc, argv, opt, general_options, general_options,
                            positional, positional_desc, usage,
                            allow_unregistered, unregistered);

  if (opt.shapefile == "")
    vw_throw( ArgumentErr() << "Missing the input shapefile.\n" << usage << general_options );
  if (opt.dem == "")
    vw_throw( ArgumentErr() << "Missing the input dem.\n" << usage << general_options );
  if (opt.bathy_plane == "")
    vw_throw( ArgumentErr() << "Missing the output bathy plane file.\n"
              << usage << general_options );
}

int main( int argc, char *argv[] ) {

  Options opt;
  try {
    handle_arguments(argc, argv, opt);

    // Read the shapefile
    std::cout << "Reading the shapefile: " << opt.shapefile << std::endl;
    bool has_shape_georef;
    std::vector<vw::geometry::dPoly> polyVec;
    std::string poly_color;
    vw::cartography::GeoReference shape_georef;
    read_shapefile(opt.shapefile, poly_color, has_shape_georef, shape_georef, polyVec);
    if (!has_shape_georef)
      vw_throw( ArgumentErr() << "The input shapefile has no georeference.\n" );

    // Read the DEM and its associated data
    // TODO(oalexan1): Think more about the interpolation method
    std::cout << "Reading the DEM: " << opt.dem << std::endl;
    vw::cartography::GeoReference dem_georef;
    if (!read_georeference(dem_georef, opt.dem))
      vw_throw( ArgumentErr() << "The input DEM has no georeference.\n" );
    double dem_nodata_val = -std::numeric_limits<float>::max(); // note we use a float nodata
    if (!vw::read_nodata_val(opt.dem, dem_nodata_val))
      vw_throw( ArgumentErr() << "Could not read the DEM nodata value.\n");
    std::cout << "Read DEM nodata value: " << dem_nodata_val << std::endl;
    DiskImageView<float> dem(opt.dem);
    std::cout << "The DEM width and height are: " << dem.cols() << ' ' << dem.rows() << std::endl;
    ImageViewRef< PixelMask<float> > interp_dem
      = interpolate(create_mask(dem, dem_nodata_val),
                    BilinearInterpolation(), ConstantEdgeExtension());

    // Find the ECEF coordinates of the shape corners
    std::vector<Eigen::Vector3d> xyz_vec;
    find_xyz_at_shape_corners(polyVec,shape_georef, dem_georef, interp_dem, xyz_vec);

    // Compute the water surface using RANSAC
    std::vector<Eigen::Vector3d> dummy_vec(xyz_vec.size()); // Required by the interface
    std::vector<size_t> inlier_indices;
    double inlier_threshold = opt.outlier_threshold;
    int    min_num_output_inliers = std::max(xyz_vec.size()/2, size_t(3));
    bool   reduce_min_num_output_inliers_if_no_fit = true;
    vw::Matrix<double> H;
    try {
      math::RandomSampleConsensus<BestFitPlaneFunctor, BestFitPlaneErrorMetric>
        ransac(BestFitPlaneFunctor(), BestFitPlaneErrorMetric(),
               opt.num_ransac_iterations, inlier_threshold,
               min_num_output_inliers, reduce_min_num_output_inliers_if_no_fit);

      H = ransac(xyz_vec, dummy_vec);

      inlier_indices = ransac.inlier_indices(H, xyz_vec, dummy_vec);
    } catch (const vw::math::RANSACErr& e ) {
      vw_out() << "RANSAC Failed: " << e.what() << "\n";
    }
    vw_out() << "Found " << inlier_indices.size() << " / " << xyz_vec.size() << " inliers.\n";

    //std::cout << "Final matrix is " << H << std::endl;
    double max_error = - 1.0, max_inlier_error = -1.0;
    for (size_t it = 0; it < xyz_vec.size(); it++)
      max_error = std::max(max_error, dist_to_plane(H, xyz_vec[it]));

    // Do estimates for the mean height and angle of the plane
    Vector3 mean_xyz(0, 0, 0);
    double mean_height = 0.0;
    int num = 0;
    for (size_t it = 0; it < inlier_indices.size(); it++) {
      Eigen::Vector3d p = xyz_vec[inlier_indices[it]];
      Vector3 xyz(p[0], p[1], p[2]);
      max_inlier_error = std::max(max_inlier_error, dist_to_plane(H, xyz));

      Vector3 llh = dem_georef.datum().cartesian_to_geodetic(xyz);
      mean_height += llh[2];
      mean_xyz += xyz;
      num++;
    }

    mean_height /= num;
    mean_xyz /= num;

    Vector3 plane_normal(H(0, 0), H(0, 1), H(0, 2));
    Vector3 surface_normal = mean_xyz / norm_2(mean_xyz); // ignore the datum flattening
    double plane_angle = (180.0 / M_PI) * acos(dot_prod(plane_normal, surface_normal));

    std::cout << "Max distance to the plane (meters): " << max_error << std::endl;
    std::cout << "Max inlier distance to the plane (meters): " << max_inlier_error << std::endl;

    std::cout << std::endl;
    std::cout << "Mean plane height above datum (meters): " << mean_height << std::endl;
    std::cout << "Plane inclination (degrees): " << plane_angle << std::endl;
    std::cout << "The plane inclination is defined as the angle between the plane\n"
              << "normal and the ray going from the Earth center to the mean of\n"
              << "all inlier measurements in ECEF coordinates." << std::endl;
    std::cout << "" << std::endl;

    std::cout << "Writing: " << opt.bathy_plane << std::endl;
    std::ofstream bp(opt.bathy_plane.c_str());
    bp.precision(17);
    for (int col = 0; col < H.cols(); col++) {
      bp << H(0, col);
      if (col < H.cols() - 1)
        bp << " ";
      else
        bp << "\n";
    }
    bp.close();

  } ASP_STANDARD_CATCHES;

  return 0;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: lngmerge.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: nf $ $Date: 2001-04-25 10:17:04 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#include <tools/fsys.hxx>

// local includes
#include "lngmerge.hxx"
#include "utf8conv.hxx"

//
// class LngParser
//

/*****************************************************************************/
LngParser::LngParser( const ByteString &rLngFile, BOOL bUTF8 )
/*****************************************************************************/
                : sSource( rLngFile ),
                nError( LNG_OK ),
                pLines( NULL ),
                bDBIsUTF8( bUTF8 )
{
    pLines = new LngLineList( 100, 100 );

    DirEntry aEntry( String( sSource, RTL_TEXTENCODING_ASCII_US ));
    if ( aEntry.Exists()) {
        SvFileStream aStream( String( sSource, RTL_TEXTENCODING_ASCII_US ), STREAM_STD_READ );
        if ( aStream.IsOpen()) {
            ByteString sLine;
            while ( !aStream.IsEof()) {
                aStream.ReadLine( sLine );
                pLines->Insert( new ByteString( sLine ), LIST_APPEND );
            }
        }
        else
            nError = LNG_COULD_NOT_OPEN;
    }
    else
        nError = LNG_FILE_NOTFOUND;
}

/*****************************************************************************/
LngParser::~LngParser()
/*****************************************************************************/
{
    for ( ULONG i = 0; i < pLines->Count(); i++ )
        delete pLines->GetObject( i );
    delete pLines;
}

/*****************************************************************************/
BOOL LngParser::CreateSDF(
    const ByteString &rSDFFile, const ByteString &rPrj,
    const ByteString &rRoot )
/*****************************************************************************/
{
    SvFileStream aSDFStream( String( rSDFFile, RTL_TEXTENCODING_ASCII_US ),
        STREAM_STD_WRITE | STREAM_TRUNC );
    if ( !aSDFStream.IsOpen()) {
        nError = SDF_COULD_NOT_OPEN;
    }
    nError = SDF_OK;

    DirEntry aEntry( String( sSource, RTL_TEXTENCODING_ASCII_US ));
    aEntry.ToAbs();
    String sFullEntry = aEntry.GetFull();
    aEntry += DirEntry( String( "..", RTL_TEXTENCODING_ASCII_US ));
    aEntry += DirEntry( rRoot );
    ByteString sPrjEntry( aEntry.GetFull(), gsl_getSystemTextEncoding());
    ByteString sActFileName(
        sFullEntry.Copy( sPrjEntry.Len() + 1 ), gsl_getSystemTextEncoding());
    sActFileName.ToLowerAscii();

    ULONG nPos = 0;
    BOOL bGroup = FALSE;
    ByteString sGroup;

    // seek to next group
    while ( nPos < pLines->Count() && !bGroup ) {
        ByteString sLine( *pLines->GetObject( nPos ));
        sLine.EraseLeadingChars( ' ' );
        sLine.EraseTrailingChars( ' ' );
        if (( sLine.GetChar( 0 ) == '[' ) &&
            ( sLine.GetChar( sLine.Len() - 1 ) == ']' ))
        {
            sGroup = sLine.GetToken( 1, '[' ).GetToken( 0, ']' );
            sGroup.EraseLeadingChars( ' ' );
            sGroup.EraseTrailingChars( ' ' );
            bGroup = TRUE;
        }
        nPos ++;
    }

    while ( nPos < pLines->Count()) {

        ByteString Text[ LANGUAGES ];
        ByteString sID( sGroup );

        // read languages
        bGroup = FALSE;

        while ( nPos < pLines->Count() && !bGroup ) {
            ByteString sLine( *pLines->GetObject( nPos ));
            sLine.EraseLeadingChars( ' ' );
            sLine.EraseTrailingChars( ' ' );
            if (( sLine.GetChar( 0 ) == '[' ) &&
                ( sLine.GetChar( sLine.Len() - 1 ) == ']' ))
            {
                sGroup = sLine.GetToken( 1, '[' ).GetToken( 0, ']' );
                sGroup.EraseLeadingChars( ' ' );
                sGroup.EraseTrailingChars( ' ' );
                bGroup = TRUE;
            }
            else if ( sLine.GetTokenCount( '=' ) > 1 ) {
                ByteString sLang = sLine.GetToken( 0, '=' );
                sLang.EraseLeadingChars( ' ' );
                sLang.EraseTrailingChars( ' ' );
                if (( sLang.IsNumericAscii()) &&
                    ( MergeDataFile::GetLangIndex( sLang.ToInt32()) < LANGUAGES ))
                {
                    // this is a valid text line
                    ByteString sText = sLine.GetToken( 1, '\"' ).GetToken( 0, '\"' );
                    USHORT nIndex = MergeDataFile::GetLangIndex( sLang.ToInt32());
                    Text[ nIndex ] = sText;
                }
            }
            nPos ++;
        }
        BOOL bExport = Text[ GERMAN_INDEX ].Len() &&
            ( Text[ ENGLISH_INDEX ].Len() || Text[ ENGLISH_US_INDEX ].Len());
        if ( bExport ) {

            Time aTime;
            ByteString sTimeStamp( ByteString::CreateFromInt64( Date().GetDate()));
            sTimeStamp += " ";
            sTimeStamp += ByteString::CreateFromInt32( aTime.GetHour());
            sTimeStamp += ":";
            sTimeStamp += ByteString::CreateFromInt32( aTime.GetMin());
            sTimeStamp += ":";
            sTimeStamp += ByteString::CreateFromInt32( aTime.GetSec());

            for ( ULONG i = 0; i < LANGUAGES; i++ ) {
                if ( LANGUAGE_ALLOWED( i )) {
                    ByteString sAct = Text[ i ];
                    if ( !sAct.Len() && i )
                        sAct = Text[ GERMAN_INDEX ];

                    ByteString sOutput( rPrj ); sOutput += "\t";
                    if ( rRoot.Len())
                        sOutput += sActFileName;
                    sOutput += "\t0\t";
                    sOutput += "LngText\t";
                    sOutput += sID; sOutput += "\t\t\t\t0\t";
                    sOutput += ByteString::CreateFromInt64( Export::LangId[ i ] ); sOutput += "\t";
                    sOutput += sAct; sOutput += "\t\t\t\t";
                    sOutput += sTimeStamp;

                    if ( bDBIsUTF8 )
                        sOutput = UTF8Converter::ConvertToUTF8( sOutput, Export::GetCharSet( Export::LangId[ i ] ));

                    aSDFStream.WriteLine( sOutput );
                }
            }
        }
    }
    aSDFStream.Close();
    return TRUE;
}

/*****************************************************************************/
BOOL LngParser::Merge(
    const ByteString &rSDFFile, const ByteString &rDestinationFile )
/*****************************************************************************/
{
    SvFileStream aDestination(
        String( rDestinationFile, RTL_TEXTENCODING_ASCII_US ),
        STREAM_STD_WRITE | STREAM_TRUNC );
    if ( !aDestination.IsOpen()) {
        nError = LNG_COULD_NOT_OPEN;
    }
    nError = LNG_OK;

    MergeDataFile aMergeDataFile( rSDFFile, FALSE, RTL_TEXTENCODING_MS_1252, bDBIsUTF8 );

    ULONG nPos = 0;
    BOOL bGroup = FALSE;
    ByteString sGroup;

    // seek to next group
    while ( nPos < pLines->Count() && !bGroup ) {
        ByteString sLine( *pLines->GetObject( nPos ));
        sLine.EraseLeadingChars( ' ' );
        sLine.EraseTrailingChars( ' ' );
        if (( sLine.GetChar( 0 ) == '[' ) &&
            ( sLine.GetChar( sLine.Len() - 1 ) == ']' ))
        {
            sGroup = sLine.GetToken( 1, '[' ).GetToken( 0, ']' );
            sGroup.EraseLeadingChars( ' ' );
            sGroup.EraseTrailingChars( ' ' );
            bGroup = TRUE;
        }
        nPos ++;
    }

    while ( nPos < pLines->Count()) {

        ByteString Text[ LANGUAGES ];
        ByteString sID( sGroup );
        ULONG nLastLangPos = 0;

        ResData  *pResData = new ResData( "", sID );
        pResData->sResTyp = "lngtext";
        PFormEntrys *pEntrys = aMergeDataFile.GetPFormEntrys( pResData );

        // read languages
        bGroup = FALSE;

        while ( nPos < pLines->Count() && !bGroup ) {
            ByteString sLine( *pLines->GetObject( nPos ));
            sLine.EraseLeadingChars( ' ' );
            sLine.EraseTrailingChars( ' ' );
            if (( sLine.GetChar( 0 ) == '[' ) &&
                ( sLine.GetChar( sLine.Len() - 1 ) == ']' ))
            {
                sGroup = sLine.GetToken( 1, '[' ).GetToken( 0, ']' );
                sGroup.EraseLeadingChars( ' ' );
                sGroup.EraseTrailingChars( ' ' );
                bGroup = TRUE;
            }
            else if ( sLine.GetTokenCount( '=' ) > 1 ) {
                ByteString sLang = sLine.GetToken( 0, '=' );
                sLang.EraseLeadingChars( ' ' );
                sLang.EraseTrailingChars( ' ' );
                if (( sLang.IsNumericAscii()) &&
                    ( MergeDataFile::GetLangIndex( sLang.ToInt32()) < LANGUAGES ) &&
                    ( pEntrys ))
                {
                    // this is a valid text line
                    USHORT nIndex = MergeDataFile::GetLangIndex( sLang.ToInt32());
                    ByteString sNewText;
                    pEntrys->GetText( sNewText, STRING_TYP_TEXT, nIndex, TRUE );
                    if ( sNewText.Len()) {
                        ByteString *pLine = pLines->GetObject( nPos );

                        if ( sLang.ToInt32() != GERMAN ) {

                            ByteString sText( sLang );
                            sText += " = \"";
                            sText += sNewText;
                            sText += "\"";
                            *pLine = sText;
                        }
                        Text[ nIndex ] = sNewText;
                    }
                    nLastLangPos = nPos;
                }
            }
            nPos ++;
        }
        if ( nLastLangPos ) {
            for ( USHORT i = 0; i < LANGUAGES; i++ ) {
                if (( i != GERMAN ) && ( !Text[ i ].Len())) {
                    ByteString sNewText;
                    pEntrys->GetText( sNewText, STRING_TYP_TEXT, i, TRUE );
                    if (( sNewText.Len()) &&
                        !(( i == COMMENT ) && ( sNewText == "-" )))
                    {
                        ByteString sLine;
                        if ( Export::LangId[ i ] < 10 )
                            sLine += "0";
                        sLine += Export::LangId[ i ];
                        sLine += " = \"";
                        sLine += sNewText;
                        sLine += "\"";

                        nLastLangPos++;
                        nPos++;

                        pLines->Insert( new ByteString( sLine ), nLastLangPos );
                    }
                }
            }
        }

        delete pResData;
    }

    for ( ULONG i = 0; i < pLines->Count(); i++ )
        aDestination.WriteLine( *pLines->GetObject( i ));

    aDestination.Close();
    return TRUE;
}
<commit_msg>Fix for merging with incorrect lang ids, repairment of wrong merged files<commit_after>/*************************************************************************
 *
 *  $RCSfile: lngmerge.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: nf $ $Date: 2001-05-16 13:06:14 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#include <tools/fsys.hxx>

// local includes
#include "lngmerge.hxx"
#include "utf8conv.hxx"

//
// class LngParser
//

/*****************************************************************************/
LngParser::LngParser( const ByteString &rLngFile, BOOL bUTF8 )
/*****************************************************************************/
                : sSource( rLngFile ),
                nError( LNG_OK ),
                pLines( NULL ),
                bDBIsUTF8( bUTF8 )
{
    pLines = new LngLineList( 100, 100 );

    DirEntry aEntry( String( sSource, RTL_TEXTENCODING_ASCII_US ));
    if ( aEntry.Exists()) {
        SvFileStream aStream( String( sSource, RTL_TEXTENCODING_ASCII_US ), STREAM_STD_READ );
        if ( aStream.IsOpen()) {
            ByteString sLine;
            while ( !aStream.IsEof()) {
                aStream.ReadLine( sLine );
                pLines->Insert( new ByteString( sLine ), LIST_APPEND );
            }
        }
        else
            nError = LNG_COULD_NOT_OPEN;
    }
    else
        nError = LNG_FILE_NOTFOUND;
}

/*****************************************************************************/
LngParser::~LngParser()
/*****************************************************************************/
{
    for ( ULONG i = 0; i < pLines->Count(); i++ )
        delete pLines->GetObject( i );
    delete pLines;
}

/*****************************************************************************/
BOOL LngParser::CreateSDF(
    const ByteString &rSDFFile, const ByteString &rPrj,
    const ByteString &rRoot )
/*****************************************************************************/
{
    SvFileStream aSDFStream( String( rSDFFile, RTL_TEXTENCODING_ASCII_US ),
        STREAM_STD_WRITE | STREAM_TRUNC );
    if ( !aSDFStream.IsOpen()) {
        nError = SDF_COULD_NOT_OPEN;
    }
    nError = SDF_OK;

    DirEntry aEntry( String( sSource, RTL_TEXTENCODING_ASCII_US ));
    aEntry.ToAbs();
    String sFullEntry = aEntry.GetFull();
    aEntry += DirEntry( String( "..", RTL_TEXTENCODING_ASCII_US ));
    aEntry += DirEntry( rRoot );
    ByteString sPrjEntry( aEntry.GetFull(), gsl_getSystemTextEncoding());
    ByteString sActFileName(
        sFullEntry.Copy( sPrjEntry.Len() + 1 ), gsl_getSystemTextEncoding());
    sActFileName.ToLowerAscii();

    ULONG nPos = 0;
    BOOL bGroup = FALSE;
    ByteString sGroup;

    // seek to next group
    while ( nPos < pLines->Count() && !bGroup ) {
        ByteString sLine( *pLines->GetObject( nPos ));
        sLine.EraseLeadingChars( ' ' );
        sLine.EraseTrailingChars( ' ' );
        if (( sLine.GetChar( 0 ) == '[' ) &&
            ( sLine.GetChar( sLine.Len() - 1 ) == ']' ))
        {
            sGroup = sLine.GetToken( 1, '[' ).GetToken( 0, ']' );
            sGroup.EraseLeadingChars( ' ' );
            sGroup.EraseTrailingChars( ' ' );
            bGroup = TRUE;
        }
        nPos ++;
    }

    while ( nPos < pLines->Count()) {

        ByteString Text[ LANGUAGES ];
        ByteString sID( sGroup );

        // read languages
        bGroup = FALSE;

        while ( nPos < pLines->Count() && !bGroup ) {
            ByteString sLine( *pLines->GetObject( nPos ));
            sLine.EraseLeadingChars( ' ' );
            sLine.EraseTrailingChars( ' ' );
            if (( sLine.GetChar( 0 ) == '[' ) &&
                ( sLine.GetChar( sLine.Len() - 1 ) == ']' ))
            {
                sGroup = sLine.GetToken( 1, '[' ).GetToken( 0, ']' );
                sGroup.EraseLeadingChars( ' ' );
                sGroup.EraseTrailingChars( ' ' );
                bGroup = TRUE;
            }
            else if ( sLine.GetTokenCount( '=' ) > 1 ) {
                ByteString sLang = sLine.GetToken( 0, '=' );
                sLang.EraseLeadingChars( ' ' );
                sLang.EraseTrailingChars( ' ' );
                if (( sLang.IsNumericAscii()) &&
                    ( MergeDataFile::GetLangIndex( sLang.ToInt32()) < LANGUAGES ))
                {
                    // this is a valid text line
                    ByteString sText = sLine.GetToken( 1, '\"' ).GetToken( 0, '\"' );
                    USHORT nIndex = MergeDataFile::GetLangIndex( sLang.ToInt32());
                    Text[ nIndex ] = sText;
                }
            }
            nPos ++;
        }
        BOOL bExport = Text[ GERMAN_INDEX ].Len() &&
            ( Text[ ENGLISH_INDEX ].Len() || Text[ ENGLISH_US_INDEX ].Len());
        if ( bExport ) {

            Time aTime;
            ByteString sTimeStamp( ByteString::CreateFromInt64( Date().GetDate()));
            sTimeStamp += " ";
            sTimeStamp += ByteString::CreateFromInt32( aTime.GetHour());
            sTimeStamp += ":";
            sTimeStamp += ByteString::CreateFromInt32( aTime.GetMin());
            sTimeStamp += ":";
            sTimeStamp += ByteString::CreateFromInt32( aTime.GetSec());

            for ( ULONG i = 0; i < LANGUAGES; i++ ) {
                if ( LANGUAGE_ALLOWED( i )) {
                    ByteString sAct = Text[ i ];
                    if ( !sAct.Len() && i )
                        sAct = Text[ GERMAN_INDEX ];

                    ByteString sOutput( rPrj ); sOutput += "\t";
                    if ( rRoot.Len())
                        sOutput += sActFileName;
                    sOutput += "\t0\t";
                    sOutput += "LngText\t";
                    sOutput += sID; sOutput += "\t\t\t\t0\t";
                    sOutput += ByteString::CreateFromInt64( Export::LangId[ i ] ); sOutput += "\t";
                    sOutput += sAct; sOutput += "\t\t\t\t";
                    sOutput += sTimeStamp;

                    if ( bDBIsUTF8 )
                        sOutput = UTF8Converter::ConvertToUTF8( sOutput, Export::GetCharSet( Export::LangId[ i ] ));

                    aSDFStream.WriteLine( sOutput );
                }
            }
        }
    }
    aSDFStream.Close();
    return TRUE;
}

/*****************************************************************************/
BOOL LngParser::Merge(
    const ByteString &rSDFFile, const ByteString &rDestinationFile )
/*****************************************************************************/
{
    SvFileStream aDestination(
        String( rDestinationFile, RTL_TEXTENCODING_ASCII_US ),
        STREAM_STD_WRITE | STREAM_TRUNC );
    if ( !aDestination.IsOpen()) {
        nError = LNG_COULD_NOT_OPEN;
    }
    nError = LNG_OK;

    MergeDataFile aMergeDataFile( rSDFFile, FALSE, RTL_TEXTENCODING_MS_1252, bDBIsUTF8 );

    ULONG nPos = 0;
    BOOL bGroup = FALSE;
    ByteString sGroup;

    // seek to next group
    while ( nPos < pLines->Count() && !bGroup ) {
        ByteString sLine( *pLines->GetObject( nPos ));
        sLine.EraseLeadingChars( ' ' );
        sLine.EraseTrailingChars( ' ' );
        if (( sLine.GetChar( 0 ) == '[' ) &&
            ( sLine.GetChar( sLine.Len() - 1 ) == ']' ))
        {
            sGroup = sLine.GetToken( 1, '[' ).GetToken( 0, ']' );
            sGroup.EraseLeadingChars( ' ' );
            sGroup.EraseTrailingChars( ' ' );
            bGroup = TRUE;
        }
        nPos ++;
    }

    while ( nPos < pLines->Count()) {

        ByteString Text[ LANGUAGES ];
        ByteString sID( sGroup );
        ULONG nLastLangPos = 0;

        ResData  *pResData = new ResData( "", sID );
        pResData->sResTyp = "lngtext";
        PFormEntrys *pEntrys = aMergeDataFile.GetPFormEntrys( pResData );

        // read languages
        bGroup = FALSE;

        while ( nPos < pLines->Count() && !bGroup ) {
            ByteString sLine( *pLines->GetObject( nPos ));
            sLine.EraseLeadingChars( ' ' );
            sLine.EraseTrailingChars( ' ' );
            if (( sLine.GetChar( 0 ) == '[' ) &&
                ( sLine.GetChar( sLine.Len() - 1 ) == ']' ))
            {
                sGroup = sLine.GetToken( 1, '[' ).GetToken( 0, ']' );
                sGroup.EraseLeadingChars( ' ' );
                sGroup.EraseTrailingChars( ' ' );
                bGroup = TRUE;
                nPos ++;
            }
            else if ( sLine.GetTokenCount( '=' ) > 1 ) {
                ByteString sLang = sLine.GetToken( 0, '=' );
                sLang.EraseLeadingChars( ' ' );
                sLang.EraseTrailingChars( ' ' );

                if ( !sLang.IsNumericAscii() || !LANGUAGE_ALLOWED( sLang.ToInt32())) {
                    pLines->Remove( nPos );
                }
                else if (( MergeDataFile::GetLangIndex( sLang.ToInt32()) < LANGUAGES ) &&
                    ( pEntrys ))
                {
                    // this is a valid text line
                    USHORT nIndex = MergeDataFile::GetLangIndex( sLang.ToInt32());
                    ByteString sNewText;
                    pEntrys->GetText( sNewText, STRING_TYP_TEXT, nIndex, TRUE );
                    if ( sNewText.Len()) {
                        ByteString *pLine = pLines->GetObject( nPos );

                        if ( sLang.ToInt32() != GERMAN ) {

                            ByteString sText( sLang );
                            sText += " = \"";
                            sText += sNewText;
                            sText += "\"";
                            *pLine = sText;
                        }
                        Text[ nIndex ] = sNewText;
                    }
                    nLastLangPos = nPos;
                    nPos ++;
                }
                else
                    nPos ++;
            }
            else
                nPos++;
        }
        if ( nLastLangPos ) {
            for ( USHORT i = 0; i < LANGUAGES; i++ ) {
                if (( i != GERMAN ) && ( !Text[ i ].Len())) {
                    ByteString sNewText;
                    pEntrys->GetText( sNewText, STRING_TYP_TEXT, i, TRUE );
                    if (( sNewText.Len()) &&
                        !(( i == COMMENT ) && ( sNewText == "-" )))
                    {
                        ByteString sLine;
                        if ( Export::LangId[ i ] < 10 )
                            sLine += "0";
                        sLine += ByteString::CreateFromInt32( Export::LangId[ i ] );
                        sLine += " = \"";
                        sLine += sNewText;
                        sLine += "\"";

                        nLastLangPos++;
                        nPos++;

                        pLines->Insert( new ByteString( sLine ), nLastLangPos );
                    }
                }
            }
        }

        delete pResData;
    }

    for ( ULONG i = 0; i < pLines->Count(); i++ )
        aDestination.WriteLine( *pLines->GetObject( i ));

    aDestination.Close();
    return TRUE;
}
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "spatial_resampler.h"

namespace webrtc {

VPMSimpleSpatialResampler::VPMSimpleSpatialResampler()
:
_resamplingMode(kFastRescaling),
_targetWidth(0),
_targetHeight(0),
_interpolatorPtr(NULL)
{
}

VPMSimpleSpatialResampler::~VPMSimpleSpatialResampler()
{
    Release();
}

WebRtc_Word32
VPMSimpleSpatialResampler::Release()
{
    if (_interpolatorPtr != NULL)
    {
        delete _interpolatorPtr;
        _interpolatorPtr = NULL;
    }
    return VPM_OK;
}

WebRtc_Word32
VPMSimpleSpatialResampler::SetTargetFrameSize(WebRtc_UWord32 width,
                                              WebRtc_UWord32 height)
{
    if (_resamplingMode == kNoRescaling)
    {
        return VPM_OK;
    }

    if (width < 1 || height < 1)
    {
        return VPM_PARAMETER_ERROR;
    }

    _targetWidth = width;
    _targetHeight = height;

    return VPM_OK;
}

void
VPMSimpleSpatialResampler::SetInputFrameResampleMode(VideoFrameResampling
                                                     resamplingMode)
{
    _resamplingMode = resamplingMode;
}

void
VPMSimpleSpatialResampler::Reset()
{
    _resamplingMode = kFastRescaling;
    _targetWidth = 0;
    _targetHeight = 0;
}

WebRtc_Word32
VPMSimpleSpatialResampler::ResampleFrame(const VideoFrame& inFrame,
                                         VideoFrame& outFrame)
{
    WebRtc_Word32 ret;

    if (_resamplingMode == kNoRescaling)
    {
        return outFrame.CopyFrame(inFrame);
    }
    else if (_targetWidth < 1 || _targetHeight < 1)
    {
        return VPM_PARAMETER_ERROR;
    }

    // Check if re-sampling is needed
    if ((inFrame.Width() == _targetWidth) &&
        (inFrame.Height() == _targetHeight))
    {
        return outFrame.CopyFrame(inFrame);
    }
    if (_resamplingMode == kBiLinear)
    {
        return BiLinearInterpolation(inFrame, outFrame);
    }

    outFrame.SetTimeStamp(inFrame.TimeStamp());

    if (_targetWidth > inFrame.Width() &&
        ( ExactMultiplier(inFrame.Width(), inFrame.Height())))
    {
        // The codec might want to pad this later... adding 8 pixels
        const WebRtc_UWord32 requiredSize = (_targetWidth + 8) *
                                            (_targetHeight + 8) * 3 / 2;
        outFrame.VerifyAndAllocate(requiredSize);
        return UpsampleFrame(inFrame, outFrame);
    }
    else
    {
        // 1 cut/pad
        // 2 scale factor 2X (in both cases if required)
        WebRtc_UWord32 croppedWidth = inFrame.Width();
        WebRtc_UWord32 croppedHeight = inFrame.Height();

        //Calculates cropped dimensions
        CropSize(inFrame.Width(), inFrame.Height(),
                 croppedWidth, croppedHeight);

        VideoFrame* targetFrame;
        outFrame.VerifyAndAllocate(croppedWidth * croppedHeight * 3 / 2);
        targetFrame = &outFrame;

        ConvertI420ToI420(inFrame.Buffer(), inFrame.Width(), inFrame.Height(),
                          targetFrame->Buffer(), croppedWidth, croppedHeight);
        targetFrame->SetWidth(croppedWidth);
        targetFrame->SetHeight(croppedHeight);
        //We have correct aspect ratio, sub-sample with a multiple of two to get
        //close to the target size
        ret = SubsampleMultipleOf2(*targetFrame);

        if (ret != VPM_OK)
        {
            return ret;
        }
    }

    return VPM_OK;
}

WebRtc_Word32
VPMSimpleSpatialResampler::UpsampleFrame(const VideoFrame& inFrame,
                                         VideoFrame& outFrame)
{
    outFrame.CopyFrame(inFrame);
    WebRtc_UWord32 currentLength = inFrame.Width() * inFrame.Height() * 3 / 2;

    float ratioWidth = _targetWidth / (float)inFrame.Width();
    float ratioHeight = _targetHeight / (float)inFrame.Height();

    WebRtc_UWord32 scaledWidth = 0;
    WebRtc_UWord32 scaledHeight = 0;

    if(ratioWidth > 1 || ratioHeight > 1)
    {
        // scale up
        if(ratioWidth <= 1.5 && ratioHeight <= 1.5)
        {
            // scale up 1.5
            currentLength = ScaleI420Up3_2(inFrame.Width(), inFrame.Height(),
                                           outFrame.Buffer(), outFrame.Size(),
                                           scaledWidth, scaledHeight);
        }
        else if(ratioWidth <= 2 && ratioHeight <= 2)
        {
            // scale up 2
            currentLength = ScaleI420Up2(inFrame.Width(), inFrame.Height(),
                                         outFrame.Buffer(), outFrame.Size(),
                                         scaledWidth, scaledHeight);
        }
        else if(ratioWidth <= 2.25 && ratioHeight <= 2.25)
        {
            // scale up 2.25
            currentLength = ScaleI420Up3_2(inFrame.Width(), inFrame.Height(),
                                           outFrame.Buffer(), outFrame.Size(),
                                           scaledWidth, scaledHeight);
            currentLength = ScaleI420Up3_2(scaledWidth, scaledHeight,
                                           outFrame.Buffer(), outFrame.Size(),
                                           scaledWidth, scaledHeight);
        }
        else if(ratioWidth <= 3 && ratioHeight <= 3)
        {
            // scale up 3
            currentLength = ScaleI420Up2(inFrame.Width(), inFrame.Height(),
                                         outFrame.Buffer(), outFrame.Size(),
                                         scaledWidth, scaledHeight);
            currentLength = ScaleI420Up3_2(scaledWidth, scaledHeight,
                                           outFrame.Buffer(), outFrame.Size(),
                                           scaledWidth, scaledHeight);
        }
        else if(ratioWidth <= 4 && ratioHeight <= 4)
        {
            // scale up 4
            currentLength = ScaleI420Up2(inFrame.Width(), inFrame.Height(),
                                         outFrame.Buffer(), outFrame.Size(),
                                         scaledWidth, scaledHeight);
            currentLength = ScaleI420Up2(scaledWidth, scaledHeight,
                                         outFrame.Buffer(), outFrame.Size(),
                                         scaledWidth, scaledHeight);
        }

        //TODO: what if ratioWidth/Height >= 8 ?

        if (scaledWidth <= 0 || scaledHeight <= 0)
        {
            return VPM_GENERAL_ERROR;
        }

        if ((static_cast<WebRtc_UWord32>(scaledWidth) > _targetWidth) ||
            (static_cast<WebRtc_UWord32>(scaledHeight) > _targetHeight))
        {
            currentLength = CutI420Frame(outFrame.Buffer(), scaledWidth,
                                         scaledHeight, _targetWidth,
                                         _targetHeight);
        }
    }
    else
    {
        return VPM_GENERAL_ERROR;
    }

    outFrame.SetWidth(_targetWidth);
    outFrame.SetHeight(_targetHeight);
    outFrame.SetLength(_targetWidth * _targetHeight * 3 / 2);

    return VPM_OK;
}

WebRtc_Word32
VPMSimpleSpatialResampler::CropSize(WebRtc_UWord32 width, WebRtc_UWord32 height,
                                    WebRtc_UWord32& croppedWidth,
                                    WebRtc_UWord32& croppedHeight) const
{
    // Crop the image to a width and height  which is a
    // multiple of two, so that we can do a simpler scaling.
    croppedWidth = _targetWidth;
    croppedHeight = _targetHeight;

    if (width >= 8 * _targetWidth && height >= 8 * _targetHeight)
    {
        croppedWidth = 8 * _targetWidth;
        croppedHeight = 8 * _targetHeight;
    }
    else if (width >= 4 * _targetWidth && height >= 4 * _targetHeight)
    {
        croppedWidth = 4 * _targetWidth;
        croppedHeight = 4 * _targetHeight;
    }
    else if (width >= 2 * _targetWidth && height >= 2 * _targetHeight)
    {
        croppedWidth = 2 * _targetWidth;
        croppedHeight = 2 * _targetHeight;
    }
    return VPM_OK;
}

WebRtc_Word32
VPMSimpleSpatialResampler::SubsampleMultipleOf2(VideoFrame& frame)
{
    WebRtc_UWord32 tempWidth = frame.Width();
    WebRtc_UWord32 tempHeight = frame.Height();

    while (tempWidth / _targetWidth >= 2 && tempHeight / _targetHeight >= 2)
    {
        ScaleI420FrameQuarter(tempWidth, tempHeight, frame.Buffer());
        tempWidth /= 2;
        tempHeight /= 2;
    }
    frame.SetWidth(tempWidth);
    frame.SetHeight(tempHeight);
    frame.SetLength(frame.Width() * frame.Height() * 3 / 2);

    return VPM_OK;
}

bool
VPMSimpleSpatialResampler::ExactMultiplier(WebRtc_UWord32 width,
                                           WebRtc_UWord32 height) const
{
    bool exactMultiplier = false;
    if (_targetWidth % width == 0 && _targetHeight % height == 0)
    {
        // we have a multiple, is it an even multiple?
        WebRtc_Word32 widthMultiple = _targetWidth / width;
        WebRtc_Word32 heightMultiple = _targetHeight / height;
        if ((widthMultiple == 2 && heightMultiple == 2) ||
            (widthMultiple == 4 && heightMultiple == 4) ||
            (widthMultiple == 8 && heightMultiple == 8) ||
            (widthMultiple == 1 && heightMultiple == 1))
        {
            exactMultiplier = true;
        }
    }
    return exactMultiplier;
}

WebRtc_Word32
VPMSimpleSpatialResampler::BiLinearInterpolation(const VideoFrame& inFrame,
                                                 VideoFrame& outFrame)
{
    WebRtc_Word32 retVal;

   if (_interpolatorPtr == NULL)
   {
       _interpolatorPtr = new interpolator();
   }
   // set bi-linear interpolator
   retVal =  _interpolatorPtr->Set(inFrame.Width(), inFrame.Height(),
                                   _targetWidth, _targetHeight,
                                   kI420, kI420, kBilinear );
    if (retVal < 0 )
    {
        return retVal;
    }

    // Verify size of output buffer
    outFrame.VerifyAndAllocate(_targetHeight * _targetWidth * 3 >> 1);
    WebRtc_UWord32 outSz = outFrame.Size();

    // interpolate frame
    retVal = _interpolatorPtr->Interpolate(inFrame.Buffer(),
                                           outFrame.Buffer(), outSz);

    assert(outSz <= outFrame.Size());

    // returns height
    if (retVal < 0)
    {
        return retVal;
    }

    // Set output frame parameters
    outFrame.SetHeight(_targetHeight);
    outFrame.SetWidth(_targetWidth);
    outFrame.SetLength(outSz);
    outFrame.SetTimeStamp(inFrame.TimeStamp());
    return VPM_OK;
}

WebRtc_UWord32
VPMSimpleSpatialResampler::TargetHeight()
{
    return _targetHeight;
}

WebRtc_UWord32
VPMSimpleSpatialResampler::TargetWidth()
{
    return _targetWidth;
}

} //namespace
<commit_msg>Fix unused variable warning in spatial_resampler.cc<commit_after>/*
 *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "spatial_resampler.h"

namespace webrtc {

VPMSimpleSpatialResampler::VPMSimpleSpatialResampler()
:
_resamplingMode(kFastRescaling),
_targetWidth(0),
_targetHeight(0),
_interpolatorPtr(NULL)
{
}

VPMSimpleSpatialResampler::~VPMSimpleSpatialResampler()
{
    Release();
}

WebRtc_Word32
VPMSimpleSpatialResampler::Release()
{
    if (_interpolatorPtr != NULL)
    {
        delete _interpolatorPtr;
        _interpolatorPtr = NULL;
    }
    return VPM_OK;
}

WebRtc_Word32
VPMSimpleSpatialResampler::SetTargetFrameSize(WebRtc_UWord32 width,
                                              WebRtc_UWord32 height)
{
    if (_resamplingMode == kNoRescaling)
    {
        return VPM_OK;
    }

    if (width < 1 || height < 1)
    {
        return VPM_PARAMETER_ERROR;
    }

    _targetWidth = width;
    _targetHeight = height;

    return VPM_OK;
}

void
VPMSimpleSpatialResampler::SetInputFrameResampleMode(VideoFrameResampling
                                                     resamplingMode)
{
    _resamplingMode = resamplingMode;
}

void
VPMSimpleSpatialResampler::Reset()
{
    _resamplingMode = kFastRescaling;
    _targetWidth = 0;
    _targetHeight = 0;
}

WebRtc_Word32
VPMSimpleSpatialResampler::ResampleFrame(const VideoFrame& inFrame,
                                         VideoFrame& outFrame)
{
    WebRtc_Word32 ret;

    if (_resamplingMode == kNoRescaling)
    {
        return outFrame.CopyFrame(inFrame);
    }
    else if (_targetWidth < 1 || _targetHeight < 1)
    {
        return VPM_PARAMETER_ERROR;
    }

    // Check if re-sampling is needed
    if ((inFrame.Width() == _targetWidth) &&
        (inFrame.Height() == _targetHeight))
    {
        return outFrame.CopyFrame(inFrame);
    }
    if (_resamplingMode == kBiLinear)
    {
        return BiLinearInterpolation(inFrame, outFrame);
    }

    outFrame.SetTimeStamp(inFrame.TimeStamp());

    if (_targetWidth > inFrame.Width() &&
        ( ExactMultiplier(inFrame.Width(), inFrame.Height())))
    {
        // The codec might want to pad this later... adding 8 pixels
        const WebRtc_UWord32 requiredSize = (_targetWidth + 8) *
                                            (_targetHeight + 8) * 3 / 2;
        outFrame.VerifyAndAllocate(requiredSize);
        return UpsampleFrame(inFrame, outFrame);
    }
    else
    {
        // 1 cut/pad
        // 2 scale factor 2X (in both cases if required)
        WebRtc_UWord32 croppedWidth = inFrame.Width();
        WebRtc_UWord32 croppedHeight = inFrame.Height();

        //Calculates cropped dimensions
        CropSize(inFrame.Width(), inFrame.Height(),
                 croppedWidth, croppedHeight);

        VideoFrame* targetFrame;
        outFrame.VerifyAndAllocate(croppedWidth * croppedHeight * 3 / 2);
        targetFrame = &outFrame;

        ConvertI420ToI420(inFrame.Buffer(), inFrame.Width(), inFrame.Height(),
                          targetFrame->Buffer(), croppedWidth, croppedHeight);
        targetFrame->SetWidth(croppedWidth);
        targetFrame->SetHeight(croppedHeight);
        //We have correct aspect ratio, sub-sample with a multiple of two to get
        //close to the target size
        ret = SubsampleMultipleOf2(*targetFrame);

        if (ret != VPM_OK)
        {
            return ret;
        }
    }

    return VPM_OK;
}

WebRtc_Word32
VPMSimpleSpatialResampler::UpsampleFrame(const VideoFrame& inFrame,
                                         VideoFrame& outFrame)
{
    outFrame.CopyFrame(inFrame);

    float ratioWidth = _targetWidth / (float)inFrame.Width();
    float ratioHeight = _targetHeight / (float)inFrame.Height();

    WebRtc_UWord32 scaledWidth = 0;
    WebRtc_UWord32 scaledHeight = 0;

    if(ratioWidth > 1 || ratioHeight > 1)
    {
        // scale up
        if(ratioWidth <= 1.5 && ratioHeight <= 1.5)
        {
            // scale up 1.5
            WebRtc_Word32 ret = ScaleI420Up3_2(inFrame.Width(), inFrame.Height(),
                                               outFrame.Buffer(), outFrame.Size(),
                                               scaledWidth, scaledHeight);
            if (ret < 0)
                return VPM_GENERAL_ERROR;
        }
        else if(ratioWidth <= 2 && ratioHeight <= 2)
        {
            // scale up 2
            WebRtc_Word32 ret = ScaleI420Up2(inFrame.Width(), inFrame.Height(),
                                             outFrame.Buffer(), outFrame.Size(),
                                             scaledWidth, scaledHeight);
            if (ret < 0)
                return VPM_GENERAL_ERROR;
        }
        else if(ratioWidth <= 2.25 && ratioHeight <= 2.25)
        {
            // scale up 2.25
            WebRtc_Word32 ret = ScaleI420Up3_2(inFrame.Width(), inFrame.Height(),
                                               outFrame.Buffer(), outFrame.Size(),
                                               scaledWidth, scaledHeight);
            if (ret < 0)
                return VPM_GENERAL_ERROR;
            ret = ScaleI420Up3_2(scaledWidth, scaledHeight,
                                 outFrame.Buffer(), outFrame.Size(),
                                 scaledWidth, scaledHeight);
            if (ret < 0)
                return VPM_GENERAL_ERROR;
        }
        else if(ratioWidth <= 3 && ratioHeight <= 3)
        {
            // scale up 3
            WebRtc_Word32 ret = ScaleI420Up2(inFrame.Width(), inFrame.Height(),
                                             outFrame.Buffer(), outFrame.Size(),
                                             scaledWidth, scaledHeight);
            if (ret < 0)
                return VPM_GENERAL_ERROR;
            ret = ScaleI420Up3_2(scaledWidth, scaledHeight,
                                 outFrame.Buffer(), outFrame.Size(),
                                 scaledWidth, scaledHeight);
            if (ret < 0)
                return VPM_GENERAL_ERROR;
        }
        else if(ratioWidth <= 4 && ratioHeight <= 4)
        {
            // scale up 4
            WebRtc_Word32 ret = ScaleI420Up2(inFrame.Width(), inFrame.Height(),
                                             outFrame.Buffer(), outFrame.Size(),
                                             scaledWidth, scaledHeight);
            if (ret < 0)
                return VPM_GENERAL_ERROR;
            ret = ScaleI420Up2(scaledWidth, scaledHeight,
                               outFrame.Buffer(), outFrame.Size(),
                               scaledWidth, scaledHeight);
            if (ret < 0)
                return VPM_GENERAL_ERROR;
        }

        //TODO: what if ratioWidth/Height >= 8 ?

        if (scaledWidth <= 0 || scaledHeight <= 0)
        {
            return VPM_GENERAL_ERROR;
        }

        if ((static_cast<WebRtc_UWord32>(scaledWidth) > _targetWidth) ||
            (static_cast<WebRtc_UWord32>(scaledHeight) > _targetHeight))
        {
            WebRtc_Word32 ret = CutI420Frame(outFrame.Buffer(),
                                             scaledWidth, scaledHeight,
                                             _targetWidth, _targetHeight);
            if (ret < 0)
                return VPM_GENERAL_ERROR;
        }
    }
    else
    {
        return VPM_GENERAL_ERROR;
    }

    outFrame.SetWidth(_targetWidth);
    outFrame.SetHeight(_targetHeight);
    outFrame.SetLength(_targetWidth * _targetHeight * 3 / 2);

    return VPM_OK;
}

WebRtc_Word32
VPMSimpleSpatialResampler::CropSize(WebRtc_UWord32 width, WebRtc_UWord32 height,
                                    WebRtc_UWord32& croppedWidth,
                                    WebRtc_UWord32& croppedHeight) const
{
    // Crop the image to a width and height  which is a
    // multiple of two, so that we can do a simpler scaling.
    croppedWidth = _targetWidth;
    croppedHeight = _targetHeight;

    if (width >= 8 * _targetWidth && height >= 8 * _targetHeight)
    {
        croppedWidth = 8 * _targetWidth;
        croppedHeight = 8 * _targetHeight;
    }
    else if (width >= 4 * _targetWidth && height >= 4 * _targetHeight)
    {
        croppedWidth = 4 * _targetWidth;
        croppedHeight = 4 * _targetHeight;
    }
    else if (width >= 2 * _targetWidth && height >= 2 * _targetHeight)
    {
        croppedWidth = 2 * _targetWidth;
        croppedHeight = 2 * _targetHeight;
    }
    return VPM_OK;
}

WebRtc_Word32
VPMSimpleSpatialResampler::SubsampleMultipleOf2(VideoFrame& frame)
{
    WebRtc_UWord32 tempWidth = frame.Width();
    WebRtc_UWord32 tempHeight = frame.Height();

    while (tempWidth / _targetWidth >= 2 && tempHeight / _targetHeight >= 2)
    {
        ScaleI420FrameQuarter(tempWidth, tempHeight, frame.Buffer());
        tempWidth /= 2;
        tempHeight /= 2;
    }
    frame.SetWidth(tempWidth);
    frame.SetHeight(tempHeight);
    frame.SetLength(frame.Width() * frame.Height() * 3 / 2);

    return VPM_OK;
}

bool
VPMSimpleSpatialResampler::ExactMultiplier(WebRtc_UWord32 width,
                                           WebRtc_UWord32 height) const
{
    bool exactMultiplier = false;
    if (_targetWidth % width == 0 && _targetHeight % height == 0)
    {
        // we have a multiple, is it an even multiple?
        WebRtc_Word32 widthMultiple = _targetWidth / width;
        WebRtc_Word32 heightMultiple = _targetHeight / height;
        if ((widthMultiple == 2 && heightMultiple == 2) ||
            (widthMultiple == 4 && heightMultiple == 4) ||
            (widthMultiple == 8 && heightMultiple == 8) ||
            (widthMultiple == 1 && heightMultiple == 1))
        {
            exactMultiplier = true;
        }
    }
    return exactMultiplier;
}

WebRtc_Word32
VPMSimpleSpatialResampler::BiLinearInterpolation(const VideoFrame& inFrame,
                                                 VideoFrame& outFrame)
{
    WebRtc_Word32 retVal;

   if (_interpolatorPtr == NULL)
   {
       _interpolatorPtr = new interpolator();
   }
   // set bi-linear interpolator
   retVal =  _interpolatorPtr->Set(inFrame.Width(), inFrame.Height(),
                                   _targetWidth, _targetHeight,
                                   kI420, kI420, kBilinear );
    if (retVal < 0 )
    {
        return retVal;
    }

    // Verify size of output buffer
    outFrame.VerifyAndAllocate(_targetHeight * _targetWidth * 3 >> 1);
    WebRtc_UWord32 outSz = outFrame.Size();

    // interpolate frame
    retVal = _interpolatorPtr->Interpolate(inFrame.Buffer(),
                                           outFrame.Buffer(), outSz);

    assert(outSz <= outFrame.Size());

    // returns height
    if (retVal < 0)
    {
        return retVal;
    }

    // Set output frame parameters
    outFrame.SetHeight(_targetHeight);
    outFrame.SetWidth(_targetWidth);
    outFrame.SetLength(outSz);
    outFrame.SetTimeStamp(inFrame.TimeStamp());
    return VPM_OK;
}

WebRtc_UWord32
VPMSimpleSpatialResampler::TargetHeight()
{
    return _targetHeight;
}

WebRtc_UWord32
VPMSimpleSpatialResampler::TargetWidth()
{
    return _targetWidth;
}

} //namespace
<|endoftext|>


<commit_before>#include "LogSinks.hpp"
#include "macros.hpp"
#include <unistd.h>
#include <iostream>
#include <ctime>

static const char* const ESCAPE_BOLD = "\x1B[1m";
static const char* const ESCAPE_NORMALFONT = "\x1B[0m";
static const char* const ESCAPE_BLACK_FOREGROUND = "\x1B[30m";
static const char* const ESCAPE_RED_FOREGROUND = "\x1B[31m";
static const char* const ESCAPE_GREEN_FOREGROUND = "\x1B[32m";
static const char* const ESCAPE_YELLOW_FOREGROUND = "\x1B[33m";
static const char* const ESCAPE_BLUE_FOREGROUND = "\x1B[34m";
static const char* const ESCAPE_MAGENTA_FOREGROUND = "\x1B[35m";
static const char* const ESCAPE_CYAN_FOREGROUND = "\x1B[36m";
static const char* const ESCAPE_WHITE_FOREGROUND = "\x1B[37m";

static void HOT printDateTime(uint64_t timestamp, std::ostream& stream) {
    //Convert timestamp to timeval
    struct timeval tv;
    tv.tv_sec = timestamp / 1000;
    tv.tv_usec = (timestamp % 1000) * 1000;
    //Format the tm data
    char dateBuffer[32];
    size_t formattedLength = strftime(dateBuffer, 32, "%F %T", localtime(&(tv.tv_sec)));
    assert(formattedLength > 0);
    //Format the subsecond part
    snprintf(dateBuffer + formattedLength, 32 - formattedLength, ".%03lu", (unsigned long) (tv.tv_usec / 1000));
    stream << '[' << dateBuffer << ']';
}

std::string logLevelToString(LogLevel logLevel) {
    switch (logLevel) {
        case LogLevel::Critical: {
            return "[Critical]";
        }
        case LogLevel::Error: {
            return "[Error]";
        }
        case LogLevel::Warn: {
            return "[Warn]";
        }
        case LogLevel::Info: {
            return "[Info]";
        }
        case LogLevel::Debug: {
            return "[Debug]";
        }
        case LogLevel::Trace: {
            return "[Trace]";
        }
        default: {
            return "[Unknown]";
        }
    }
}

LogSink::~LogSink() {

}

StderrLogSink::StderrLogSink() : coloredLogging(isatty(fileno(stderr))) {

}

void StderrLogSink::setColoredLogging(bool value) {
    this->coloredLogging = value;
}

void HOT StderrLogSink::log(LogLevel logLevel, uint64_t timestamp, const std::string& senderName, const std::string& logMessage) {

    switch (logLevel) {
        case LogLevel::Critical: {
            if(coloredLogging) {
                std::cerr << ESCAPE_BOLD << ESCAPE_RED_FOREGROUND;
            }
            printDateTime(timestamp, std::cerr);
            std::cerr << "[Error] " << senderName << " - " << logMessage;
            if(coloredLogging) {
                std::cerr << ESCAPE_NORMALFONT << ESCAPE_BLACK_FOREGROUND;
            }
            std::cerr << std::endl;
            break;
        }
        case LogLevel::Error: {
            if(coloredLogging) {
                std::cerr << ESCAPE_RED_FOREGROUND;
            }
            printDateTime(timestamp, std::cerr);
            std::cerr << "[Error] " << senderName << " - ";
            if(coloredLogging) {
                std::cerr <<  ESCAPE_BLACK_FOREGROUND << std::endl;
            }
            std::cerr << logMessage << std::endl;
            break;
        }
        case LogLevel::Warn: {
            if(coloredLogging) {
                std::cerr << ESCAPE_YELLOW_FOREGROUND;
            }
            printDateTime(timestamp, std::cerr);
            std::cerr << "[Warning] " << senderName << " - ";
            if(coloredLogging) {
                std::cerr << ESCAPE_BLACK_FOREGROUND;
            }
            std::cerr << logMessage << std::endl;
            break;
        }
        case LogLevel::Info: {
            if(coloredLogging) {
                std::cerr << ESCAPE_GREEN_FOREGROUND;
            }
            printDateTime(timestamp, std::cerr);
            std::cerr << "[Info] " << senderName << " - ";
            if(coloredLogging) {
                std::cerr << ESCAPE_BLACK_FOREGROUND;
            }
            std::cerr << logMessage << std::endl;
            break;
        }
        case LogLevel::Debug: {
            if(coloredLogging) {
                std::cerr << ESCAPE_BLUE_FOREGROUND;
            }
            printDateTime(timestamp, std::cerr);
            std::cerr << "[Debug] " << senderName << " - ";
            if(coloredLogging) {
                std::cerr << ESCAPE_BLACK_FOREGROUND;
            }
            std::cerr << logMessage << std::endl;
            break;
        }
        case LogLevel::Trace: {
            if(coloredLogging) {
                std::cerr << ESCAPE_CYAN_FOREGROUND;
            }
            printDateTime(timestamp, std::cerr);
            std::cerr << "[Trace] " << senderName << " - ";
            if(coloredLogging) {
                std::cerr << ESCAPE_BLACK_FOREGROUND;
            }
            std::cerr << logMessage << std::endl;
            break;
        }
        default: {
            printDateTime(timestamp, std::cerr);
            std::cerr << "[Unknown] " << senderName << " - " << logMessage << std::endl;
            break;
        }
    }
}

FileLogSink::FileLogSink(const std::string& filename) : fout(filename.c_str()), filename(filename) {
}

FileLogSink::~FileLogSink() {
    fout.close();
}

void FileLogSink::log(LogLevel logLevel, uint64_t timestamp, const std::string& senderName, const std::string& logMessage) {
    printDateTime(timestamp, fout);
    fout << logLevelToString(logLevel) << senderName << " - " << logMessage << std::endl;
}
<commit_msg>Fix file logging format<commit_after>#include "LogSinks.hpp"
#include "macros.hpp"
#include <unistd.h>
#include <iostream>
#include <ctime>

static const char* const ESCAPE_BOLD = "\x1B[1m";
static const char* const ESCAPE_NORMALFONT = "\x1B[0m";
static const char* const ESCAPE_BLACK_FOREGROUND = "\x1B[30m";
static const char* const ESCAPE_RED_FOREGROUND = "\x1B[31m";
static const char* const ESCAPE_GREEN_FOREGROUND = "\x1B[32m";
static const char* const ESCAPE_YELLOW_FOREGROUND = "\x1B[33m";
static const char* const ESCAPE_BLUE_FOREGROUND = "\x1B[34m";
static const char* const ESCAPE_MAGENTA_FOREGROUND = "\x1B[35m";
static const char* const ESCAPE_CYAN_FOREGROUND = "\x1B[36m";
static const char* const ESCAPE_WHITE_FOREGROUND = "\x1B[37m";

static void HOT printDateTime(uint64_t timestamp, std::ostream& stream) {
    //Convert timestamp to timeval
    struct timeval tv;
    tv.tv_sec = timestamp / 1000;
    tv.tv_usec = (timestamp % 1000) * 1000;
    //Format the tm data
    char dateBuffer[32];
    size_t formattedLength = strftime(dateBuffer, 32, "%F %T", localtime(&(tv.tv_sec)));
    assert(formattedLength > 0);
    //Format the subsecond part
    snprintf(dateBuffer + formattedLength, 32 - formattedLength, ".%03lu", (unsigned long) (tv.tv_usec / 1000));
    stream << '[' << dateBuffer << ']';
}

std::string logLevelToString(LogLevel logLevel) {
    switch (logLevel) {
        case LogLevel::Critical: {
            return "[Critical]";
        }
        case LogLevel::Error: {
            return "[Error]";
        }
        case LogLevel::Warn: {
            return "[Warn]";
        }
        case LogLevel::Info: {
            return "[Info]";
        }
        case LogLevel::Debug: {
            return "[Debug]";
        }
        case LogLevel::Trace: {
            return "[Trace]";
        }
        default: {
            return "[Unknown]";
        }
    }
}

LogSink::~LogSink() {

}

StderrLogSink::StderrLogSink() : coloredLogging(isatty(fileno(stderr))) {

}

void StderrLogSink::setColoredLogging(bool value) {
    this->coloredLogging = value;
}

void HOT StderrLogSink::log(LogLevel logLevel, uint64_t timestamp, const std::string& senderName, const std::string& logMessage) {

    switch (logLevel) {
        case LogLevel::Critical: {
            if(coloredLogging) {
                std::cerr << ESCAPE_BOLD << ESCAPE_RED_FOREGROUND;
            }
            printDateTime(timestamp, std::cerr);
            std::cerr << "[Error] " << senderName << " - " << logMessage;
            if(coloredLogging) {
                std::cerr << ESCAPE_NORMALFONT << ESCAPE_BLACK_FOREGROUND;
            }
            std::cerr << std::endl;
            break;
        }
        case LogLevel::Error: {
            if(coloredLogging) {
                std::cerr << ESCAPE_RED_FOREGROUND;
            }
            printDateTime(timestamp, std::cerr);
            std::cerr << "[Error] " << senderName << " - ";
            if(coloredLogging) {
                std::cerr <<  ESCAPE_BLACK_FOREGROUND << std::endl;
            }
            std::cerr << logMessage << std::endl;
            break;
        }
        case LogLevel::Warn: {
            if(coloredLogging) {
                std::cerr << ESCAPE_YELLOW_FOREGROUND;
            }
            printDateTime(timestamp, std::cerr);
            std::cerr << "[Warning] " << senderName << " - ";
            if(coloredLogging) {
                std::cerr << ESCAPE_BLACK_FOREGROUND;
            }
            std::cerr << logMessage << std::endl;
            break;
        }
        case LogLevel::Info: {
            if(coloredLogging) {
                std::cerr << ESCAPE_GREEN_FOREGROUND;
            }
            printDateTime(timestamp, std::cerr);
            std::cerr << "[Info] " << senderName << " - ";
            if(coloredLogging) {
                std::cerr << ESCAPE_BLACK_FOREGROUND;
            }
            std::cerr << logMessage << std::endl;
            break;
        }
        case LogLevel::Debug: {
            if(coloredLogging) {
                std::cerr << ESCAPE_BLUE_FOREGROUND;
            }
            printDateTime(timestamp, std::cerr);
            std::cerr << "[Debug] " << senderName << " - ";
            if(coloredLogging) {
                std::cerr << ESCAPE_BLACK_FOREGROUND;
            }
            std::cerr << logMessage << std::endl;
            break;
        }
        case LogLevel::Trace: {
            if(coloredLogging) {
                std::cerr << ESCAPE_CYAN_FOREGROUND;
            }
            printDateTime(timestamp, std::cerr);
            std::cerr << "[Trace] " << senderName << " - ";
            if(coloredLogging) {
                std::cerr << ESCAPE_BLACK_FOREGROUND;
            }
            std::cerr << logMessage << std::endl;
            break;
        }
        default: {
            printDateTime(timestamp, std::cerr);
            std::cerr << "[Unknown] " << senderName << " - " << logMessage << std::endl;
            break;
        }
    }
}

FileLogSink::FileLogSink(const std::string& filename) : fout(filename.c_str()), filename(filename) {
}

FileLogSink::~FileLogSink() {
    fout.close();
}

void FileLogSink::log(LogLevel logLevel, uint64_t timestamp, const std::string& senderName, const std::string& logMessage) {
    printDateTime(timestamp, fout);
    fout << logLevelToString(logLevel) << ' ' << senderName << " - " << logMessage << std::endl;
}
<|endoftext|>


<commit_before>#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE Main
#include <boost/test/unit_test.hpp>

#include <time_ordered_set.h>
#include <bucket.h>

class Moc_Storage :public memseries::storage::AbstractStorage {
public:
	size_t writed_count;
	std::vector<memseries::Meas> meases;
	memseries::append_result append(const memseries::Meas::PMeas begin, const size_t size) {
		writed_count+=size;
		return memseries::append_result(size,0);
	}
	memseries::append_result append(const memseries::Meas &value) {
		meases.push_back(value);
		writed_count += 1;
		return memseries::append_result(1,0);
	}
	memseries::storage::Reader_ptr readInterval(const memseries::IdArray &ids, memseries::Flag flag, memseries::Time from, memseries::Time to) {
		return nullptr;
	}

	memseries::storage::Reader_ptr readInTimePoint(const memseries::IdArray &ids, memseries::Flag flag, memseries::Time time_point) {
		return nullptr;
	}
	memseries::Time minTime() {
		return 0;
	}
	/// max time of writed meas
	memseries::Time maxTime() {
		return 0;
	}
};

BOOST_AUTO_TEST_CASE(TimeOrderedSetTest)
{
	const size_t max_size = 10;
	auto base = memseries::storage::TimeOrderedSet{ max_size };

	//with move ctor check
	memseries::storage::TimeOrderedSet tos(std::move(base));
	auto e = memseries::Meas::empty();
	for (size_t i = 0; i < max_size; i++) {
		e.time = max_size - i;
		BOOST_CHECK(!tos.is_full());
		BOOST_CHECK(tos.append(e));
    }

	e.time = max_size;
	BOOST_CHECK(!tos.append(e)); //is_full
	BOOST_CHECK(tos.is_full());

	{//check copy ctor and operator=
		memseries::storage::TimeOrderedSet copy_tos{ tos };
		BOOST_CHECK_EQUAL(copy_tos.size(), max_size);

		memseries::storage::TimeOrderedSet copy_assign{};
		copy_assign = copy_tos;

		auto a = copy_assign.as_array();
		BOOST_CHECK_EQUAL(a.size(), max_size);
		for (size_t i = 1; i <= max_size; i++) {
			auto e = a[i - 1];
			BOOST_CHECK_EQUAL(e.time, i);
		}
		BOOST_CHECK_EQUAL(copy_assign.minTime(), memseries::Time(1));
		BOOST_CHECK_EQUAL(copy_assign.maxTime(), memseries::Time(max_size));
	}
    BOOST_CHECK(tos.is_full());
    e.time=max_size+1;
    BOOST_CHECK(tos.append(e,true));
    BOOST_CHECK_EQUAL(tos.size(),max_size+1);
}

BOOST_AUTO_TEST_CASE(BucketTest)
{
	std::shared_ptr<Moc_Storage> stor(new Moc_Storage);
	stor->writed_count = 0;
    const size_t max_size = 10;
    const size_t max_count = 10;
    auto base = memseries::storage::Bucket{ max_size, max_count,stor};

    //with move ctor check
    memseries::storage::Bucket mbucket(std::move(base));
    BOOST_CHECK_EQUAL(mbucket.max_size(),max_count);
    auto e = memseries::Meas::empty();
    //max time always
    memseries::Time t=100;

	for (size_t i = 0; i < max_size; i++) {
		e.time = t;
		t += 1;
		BOOST_CHECK(mbucket.append(e));
	}

	t = 50;
	for (size_t i = 0; i < max_size; i++) {
		e.time = t;
		t += 1;
		BOOST_CHECK(mbucket.append(e));
	}

	t = 10;
	for (size_t i = 0; i < max_size; i++) {
		e.time = t;
		t += 1;
		BOOST_CHECK(mbucket.append(e));
	}

	t = 70;
	for (size_t i = 0; i < max_size; i++) {
		e.time = t;
		t += 1;
		BOOST_CHECK(mbucket.append(e));
	}

	//buckets count;
    BOOST_CHECK_EQUAL(mbucket.size(), 4);
    //now bucket is full
	//TODO remove this
    //BOOST_CHECK(!mbucket.append(e));

    //insert in exists time
    e.time = 12;
    BOOST_CHECK(mbucket.append(e));
    e.time = 13;
    BOOST_CHECK(mbucket.append(e));
    e.time = 14;
    BOOST_CHECK(mbucket.append(e));

	BOOST_CHECK_EQUAL(mbucket.size(), 2);
	// fill storage to initiate flush to storage
	auto wr = mbucket.writed_count();
	auto end = max_size*max_count - wr;
	for (size_t i = 0; i <end; i++) {
		t ++;
		BOOST_CHECK(mbucket.append(e));
	}

	//bucket must be full;
	BOOST_CHECK(mbucket.is_full());
	auto wcount = mbucket.writed_count();
	//drop part of data to storage;
	e.time++;
	BOOST_CHECK(mbucket.append(e));
	BOOST_CHECK(!mbucket.is_full());
	BOOST_CHECK_EQUAL(stor->writed_count+mbucket.writed_count(),wcount+1);//  one appended when drop to storage.

	//time should be increased
	for (size_t i = 0; i < stor->meases.size() - 1; i++) {
		BOOST_CHECK(stor->meases[i].time<stor->meases[i+1].time);
	}
	stor->meases.clear();
	stor->writed_count = 0;
	mbucket.flush();

	for (size_t i = 0; i < stor->meases.size() - 1; i++) {
		BOOST_CHECK(stor->meases[i].time<=stor->meases[i + 1].time);
	}
}
<commit_msg>gcc build<commit_after>#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE Main
#include <boost/test/unit_test.hpp>

#include <time_ordered_set.h>
#include <bucket.h>

class Moc_Storage :public memseries::storage::AbstractStorage {
public:
	size_t writed_count;
	std::vector<memseries::Meas> meases;
	memseries::append_result append(const memseries::Meas::PMeas begin, const size_t size) {
		writed_count+=size;
		return memseries::append_result(size,0);
	}
	memseries::append_result append(const memseries::Meas &value) {
		meases.push_back(value);
		writed_count += 1;
		return memseries::append_result(1,0);
	}
	memseries::storage::Reader_ptr readInterval(const memseries::IdArray &ids, memseries::Flag flag, memseries::Time from, memseries::Time to) {
		return nullptr;
	}

	memseries::storage::Reader_ptr readInTimePoint(const memseries::IdArray &ids, memseries::Flag flag, memseries::Time time_point) {
		return nullptr;
	}
	memseries::Time minTime() {
		return 0;
	}
	/// max time of writed meas
	memseries::Time maxTime() {
		return 0;
	}
};

BOOST_AUTO_TEST_CASE(TimeOrderedSetTest)
{
	const size_t max_size = 10;
	auto base = memseries::storage::TimeOrderedSet{ max_size };

	//with move ctor check
	memseries::storage::TimeOrderedSet tos(std::move(base));
	auto e = memseries::Meas::empty();
	for (size_t i = 0; i < max_size; i++) {
		e.time = max_size - i;
		BOOST_CHECK(!tos.is_full());
		BOOST_CHECK(tos.append(e));
    }

	e.time = max_size;
	BOOST_CHECK(!tos.append(e)); //is_full
	BOOST_CHECK(tos.is_full());

	{//check copy ctor and operator=
		memseries::storage::TimeOrderedSet copy_tos{ tos };
		BOOST_CHECK_EQUAL(copy_tos.size(), max_size);

		memseries::storage::TimeOrderedSet copy_assign{};
		copy_assign = copy_tos;

		auto a = copy_assign.as_array();
		BOOST_CHECK_EQUAL(a.size(), max_size);
		for (size_t i = 1; i <= max_size; i++) {
			auto e = a[i - 1];
			BOOST_CHECK_EQUAL(e.time, i);
		}
		BOOST_CHECK_EQUAL(copy_assign.minTime(), memseries::Time(1));
		BOOST_CHECK_EQUAL(copy_assign.maxTime(), memseries::Time(max_size));
	}
    BOOST_CHECK(tos.is_full());
    e.time=max_size+1;
    BOOST_CHECK(tos.append(e,true));
    BOOST_CHECK_EQUAL(tos.size(),max_size+1);
}

BOOST_AUTO_TEST_CASE(BucketTest)
{
	std::shared_ptr<Moc_Storage> stor(new Moc_Storage);
	stor->writed_count = 0;
    const size_t max_size = 10;
    const size_t max_count = 10;
    auto base = memseries::storage::Bucket{ max_size, max_count,stor};

    //with move ctor check
    memseries::storage::Bucket mbucket(std::move(base));
    BOOST_CHECK_EQUAL(mbucket.max_size(),max_count);
    auto e = memseries::Meas::empty();
    //max time always
    memseries::Time t=100;

	for (size_t i = 0; i < max_size; i++) {
		e.time = t;
		t += 1;
		BOOST_CHECK(mbucket.append(e));
	}

	t = 50;
	for (size_t i = 0; i < max_size; i++) {
		e.time = t;
		t += 1;
		BOOST_CHECK(mbucket.append(e));
	}

	t = 10;
	for (size_t i = 0; i < max_size; i++) {
		e.time = t;
		t += 1;
		BOOST_CHECK(mbucket.append(e));
	}

	t = 70;
	for (size_t i = 0; i < max_size; i++) {
		e.time = t;
		t += 1;
		BOOST_CHECK(mbucket.append(e));
	}

	//buckets count;
    BOOST_CHECK_EQUAL(mbucket.size(), size_t(4));
    //now bucket is full
	//TODO remove this
    //BOOST_CHECK(!mbucket.append(e));

    //insert in exists time
    e.time = 12;
    BOOST_CHECK(mbucket.append(e));
    e.time = 13;
    BOOST_CHECK(mbucket.append(e));
    e.time = 14;
    BOOST_CHECK(mbucket.append(e));

    BOOST_CHECK_EQUAL(mbucket.size(), size_t(2));
	// fill storage to initiate flush to storage
	auto wr = mbucket.writed_count();
	auto end = max_size*max_count - wr;
	for (size_t i = 0; i <end; i++) {
		t ++;
		BOOST_CHECK(mbucket.append(e));
	}

	//bucket must be full;
	BOOST_CHECK(mbucket.is_full());
	auto wcount = mbucket.writed_count();
	//drop part of data to storage;
	e.time++;
	BOOST_CHECK(mbucket.append(e));
	BOOST_CHECK(!mbucket.is_full());
	BOOST_CHECK_EQUAL(stor->writed_count+mbucket.writed_count(),wcount+1);//  one appended when drop to storage.

	//time should be increased
	for (size_t i = 0; i < stor->meases.size() - 1; i++) {
		BOOST_CHECK(stor->meases[i].time<stor->meases[i+1].time);
	}
	stor->meases.clear();
	stor->writed_count = 0;
	mbucket.flush();

	for (size_t i = 0; i < stor->meases.size() - 1; i++) {
		BOOST_CHECK(stor->meases[i].time<=stor->meases[i + 1].time);
	}
}
<|endoftext|>


<commit_before>// Given a stream of integers and a window size, calculate the moving average of
// all integers in the sliding window.
// For example,
// MovingAverage m = new MovingAverage(3);
// m.next(1) = 1
// m.next(10) = (1 + 10) / 2
// m.next(3) = (1 + 10 + 3) / 3
// m.next(5) = (10 + 3 + 5) / 3

class MovingAverage {
  public:
    /** Initialize your data structure here. */
    MovingAverage(int size) : sz(size) {}

    double next(int val) {
        if (cnt < sz)
            ++cnt;
        else {
            sum -= vals.front();
            vals.pop_front();
        }
        sum += val;
        vals.push_back(val);
        // return cnt ? static_cast<double>(sum) / cnt : DBL_MAX;
        return static_cast<double>(sum) / cnt;
    }

  private:
    int sz = 0, cnt = 0, sum = 0;
    deque<int> vals;
};

/**
 * Your MovingAverage object will be instantiated and called as such:
 * MovingAverage obj = new MovingAverage(size);
 * double param_1 = obj.next(val);
 */<commit_msg>update 346<commit_after>// Given a stream of integers and a window size, calculate the moving average of
// all integers in the sliding window.
// For example,
// MovingAverage m = new MovingAverage(3);
// m.next(1) = 1
// m.next(10) = (1 + 10) / 2
// m.next(3) = (1 + 10 + 3) / 3
// m.next(5) = (10 + 3 + 5) / 3

class MovingAverage {
  public:
    /** Initialize your data structure here. */
    MovingAverage(int size) : sz(size) {}

    double next(int val) {
        sum += val;
        vals.push(val);

        if (vals.size() > sz) {
            sum -= vals.front();
            vals.pop();
        }

        // return cnt ? static_cast<double>(sum) / cnt : DBL_MAX;
        return sum / vals.size();
    }

  private:
    int sz = 0;
    double sum = 0;
    queue<int> vals;
};

/**
 * Your MovingAverage object will be instantiated and called as such:
 * MovingAverage obj = new MovingAverage(size);
 * double param_1 = obj.next(val);
 */<|endoftext|>