From 21e998876f637920ebdaf92030f5d8b0d761fdf1 Mon Sep 17 00:00:00 2001 From: Maximilian Weber Date: Wed, 22 Jun 2022 00:45:38 -0700 Subject: [PATCH 001/235] Refactored reconstruction.py with less calls to np.radians Reviewed By: fabianschenk Differential Revision: D37315331 fbshipit-source-id: 5016c6d45d528c2fff5d8e32d03bcf4577c27f47 --- opensfm/reconstruction.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/opensfm/reconstruction.py b/opensfm/reconstruction.py index dac671c0e..117816dc5 100644 --- a/opensfm/reconstruction.py +++ b/opensfm/reconstruction.py @@ -910,6 +910,8 @@ def triangulate_robust( all_combinations = list(combinations(range(len(ids)), 2)) thresholds = len(os) * [reproj_threshold] + min_ray_angle_radians = np.radians(min_ray_angle_degrees) + max_ray_angle_radians = np.pi - min_ray_angle_radians for i in range(ransac_tries): random_id = int(np.random.rand() * (len(all_combinations) - 1)) if random_id in combinatiom_tried: @@ -925,8 +927,8 @@ def triangulate_robust( os_t, bs_t, thresholds, - np.radians(min_ray_angle_degrees), - np.radians(180.0 - min_ray_angle_degrees), + min_ray_angle_radians, + max_ray_angle_radians, ) X = pygeometry.point_refinement(os_t, bs_t, X, iterations) @@ -942,8 +944,8 @@ def triangulate_robust( os[inliers], bs[inliers], len(inliers) * [reproj_threshold], - np.radians(min_ray_angle_degrees), - np.radians(180.0 - min_ray_angle_degrees), + min_ray_angle_radians, + max_ray_angle_radians, ) new_X = pygeometry.point_refinement( os[inliers], bs[inliers], X, iterations @@ -997,12 +999,13 @@ def triangulate( if len(os) >= 2: thresholds = len(os) * [reproj_threshold] + min_ray_angle_radians = np.radians(min_ray_angle_degrees) valid_triangulation, X = pygeometry.triangulate_bearings_midpoint( np.asarray(os), np.asarray(bs), thresholds, - np.radians(min_ray_angle_degrees), - np.radians(180.0 - min_ray_angle_degrees), + min_ray_angle_radians, + np.pi - min_ray_angle_radians, ) if valid_triangulation: X = pygeometry.point_refinement( From c91ed5547075a06c6da721d1dbdbb875d5ee2c23 Mon Sep 17 00:00:00 2001 From: Farooq Zuberi Date: Wed, 22 Jun 2022 08:35:42 -0700 Subject: [PATCH 002/235] Refactor motion_from_plane_homography in openSFM Multiviewpy Reviewed By: fabianschenk Differential Revision: D37341649 fbshipit-source-id: d090ea5977b13ffdd61802f80cd4a412fce613d1 --- opensfm/multiview.py | 52 ++++++++++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/opensfm/multiview.py b/opensfm/multiview.py index cf38d0d6f..65dd3ea07 100644 --- a/opensfm/multiview.py +++ b/opensfm/multiview.py @@ -566,33 +566,43 @@ def motion_from_plane_homography( ] solutions = [] - # Case d' > 0 + # Compute solutions for the two cases (1) case d' > 0 and + # (2) case d' < 0 + for x1, x3 in possible_x1_x3: - sin_theta = (d1 - d3) * x1 * x3 / d2 - cos_theta = (d1 * x3**2 + d3 * x1**2) / d2 - Rp = np.array( + # compute sin and cos for d'>0 (theta, _n) and d'<0 (phi, _n) cases + sin_term = x1 * x3 / d2 + sin_theta = (d1 - d3) * sin_term + sin_phi = (d1 + d3) * sin_term + + d1_x3_2 = (d1 * x3**2) + d3_x1_2 = (d3 * x1**2) + cos_theta = (d3_x1_2 + d1_x3_2) / d2 + cos_phi = (d3_x1_2 - d1_x3_2) / d2 + + # define rotation matrices for both cases + Rp_p = np.array( [[cos_theta, 0, -sin_theta], [0, 1, 0], [sin_theta, 0, cos_theta]] - ) - tp = (d1 - d3) * np.array([x1, 0, -x3]) + ) # case d' > 0 + Rp_n = np.array( + [[cos_phi, 0, sin_phi], [0, -1, 0], [sin_phi, 0, -cos_phi]] + ) # case d' < 0 + + # compute transformations np_ = np.array([x1, 0, x3]) - R = s * np.dot(np.dot(u, Rp), vh) - t = np.dot(u, tp) + + tp_p = (d1 - d3) * np.array([x1, 0, -x3]) # case d' > 0 + tp_n = (d1 + d3) * np_ # case d' < 0 + + R_p = s * np.dot(np.dot(u, Rp_p), vh) # case d' > 0 + R_n = s * np.dot(np.dot(u, Rp_n), vh) # case d' < 0 + t_p = np.dot(u, tp_p) # case d' > 0 + t_n = np.dot(u, tp_n) # case d' < 0 n = -np.dot(vh.T, np_) d = s * d2 - solutions.append((R, t, n, d)) - # Case d' < 0 - for x1, x3 in possible_x1_x3: - sin_phi = (d1 + d3) * x1 * x3 / d2 - cos_phi = (d3 * x1**2 - d1 * x3**2) / d2 - Rp = np.array([[cos_phi, 0, sin_phi], [0, -1, 0], [sin_phi, 0, -cos_phi]]) - tp = (d1 + d3) * np.array([x1, 0, x3]) - np_ = np.array([x1, 0, x3]) - R = s * np.dot(np.dot(u, Rp), vh) - t = np.dot(u, tp) - n = -np.dot(vh.T, np_) - d = -s * d2 - solutions.append((R, t, n, d)) + solutions.append((R_p, t_p, n, d)) # case d' > 0 + solutions.append((R_n, t_n, n, -d)) # case d' < 0 return solutions From 8e7b11c19b76ce39ee7598109087ddffc4502171 Mon Sep 17 00:00:00 2001 From: Fabian Schenk Date: Mon, 27 Jun 2022 03:56:39 -0700 Subject: [PATCH 003/235] Remove unused acceleration_ and add const wherever possible Summary: This diff does the following: - removes the unused `acceleration_` variable - adds `const` to parameters and members in `bundle` wherever possible Reviewed By: tobias-o Differential Revision: D37339308 fbshipit-source-id: 69432532dd706df612004e05602bb16d53808221 --- .../src/bundle/error/absolute_motion_errors.h | 20 +++++++++---------- opensfm/src/bundle/error/error_utils.h | 2 +- .../src/bundle/error/motion_prior_errors.h | 7 +++---- opensfm/src/bundle/error/parameters_errors.h | 6 +++--- opensfm/src/bundle/error/prior_error.h | 2 +- opensfm/src/bundle/error/projection_errors.h | 12 +++++------ 6 files changed, 24 insertions(+), 25 deletions(-) diff --git a/opensfm/src/bundle/error/absolute_motion_errors.h b/opensfm/src/bundle/error/absolute_motion_errors.h index e3bc62c5d..407267a91 100644 --- a/opensfm/src/bundle/error/absolute_motion_errors.h +++ b/opensfm/src/bundle/error/absolute_motion_errors.h @@ -28,7 +28,7 @@ struct UpVectorError { } Vec3d acceleration_; - double scale_; + const double scale_; }; struct PanAngleError { @@ -53,8 +53,8 @@ struct PanAngleError { return true; } - double angle_; - double scale_; + const double angle_; + const double scale_; }; struct TiltAngleError { @@ -77,8 +77,8 @@ struct TiltAngleError { return true; } - double angle_; - double scale_; + const double angle_; + const double scale_; }; struct RollAngleError { @@ -122,8 +122,8 @@ struct RollAngleError { return true; } - double angle_; - double scale_; + const double angle_; + const double scale_; }; struct HeatmapdCostFunctor { @@ -180,12 +180,12 @@ struct TranslationPriorError { template bool operator()(const T* const rig_instance1, const T* const rig_instance2, T* residuals) const { - auto t1 = Eigen::Map>(rig_instance1 + Pose::Parameter::TX); - auto t2 = Eigen::Map>(rig_instance2 + Pose::Parameter::TX); + const auto t1 = Eigen::Map>(rig_instance1 + Pose::Parameter::TX); + const auto t2 = Eigen::Map>(rig_instance2 + Pose::Parameter::TX); residuals[0] = log((t1 - t2).norm() / T(prior_norm_)); return true; } - double prior_norm_; + const double prior_norm_; }; } // namespace bundle diff --git a/opensfm/src/bundle/error/error_utils.h b/opensfm/src/bundle/error/error_utils.h index b038d37c5..2ff7619a1 100644 --- a/opensfm/src/bundle/error/error_utils.h +++ b/opensfm/src/bundle/error/error_utils.h @@ -84,7 +84,7 @@ void WorldToCameraCoordinatesRig(const T* scale, const T* const rig_instance, } template -T DiffBetweenAngles(T a, T b) { +T DiffBetweenAngles(const T a, const T b) { T d = a - b; if (d > T(M_PI)) { return d - T(2 * M_PI); diff --git a/opensfm/src/bundle/error/motion_prior_errors.h b/opensfm/src/bundle/error/motion_prior_errors.h index 7e80c479f..61ef5d3d9 100644 --- a/opensfm/src/bundle/error/motion_prior_errors.h +++ b/opensfm/src/bundle/error/motion_prior_errors.h @@ -47,10 +47,9 @@ struct LinearMotionError { T(position_scale_) * MultRotations(R2_R0t.eval(), R0_R1t); return true; } - double alpha_; - Vec3d acceleration_; - double position_scale_; - double orientation_scale_; + const double alpha_; + const double position_scale_; + const double orientation_scale_; int shot0_rig_camera_index{FUNCTOR_NOT_SET}; int shot1_rig_camera_index{FUNCTOR_NOT_SET}; diff --git a/opensfm/src/bundle/error/parameters_errors.h b/opensfm/src/bundle/error/parameters_errors.h index 9b2613956..394b52c04 100644 --- a/opensfm/src/bundle/error/parameters_errors.h +++ b/opensfm/src/bundle/error/parameters_errors.h @@ -30,8 +30,8 @@ struct ParameterBarrier { return true; } - double lower_bound_; - double upper_bound_; - int index_; + const double lower_bound_; + const double upper_bound_; + const int index_; }; } // namespace bundle diff --git a/opensfm/src/bundle/error/prior_error.h b/opensfm/src/bundle/error/prior_error.h index 695ee888e..40719fac1 100644 --- a/opensfm/src/bundle/error/prior_error.h +++ b/opensfm/src/bundle/error/prior_error.h @@ -107,7 +107,7 @@ struct DataPriorError { VecXd scales_; // Are scale being adjusted for (global multiplier) ? - bool adjust_scales_; + const bool adjust_scales_; static constexpr int parameter_index = 0; static constexpr int transform_index = 1; static constexpr int scale_index = 2; diff --git a/opensfm/src/bundle/error/projection_errors.h b/opensfm/src/bundle/error/projection_errors.h index a103d115a..c8bf8f239 100644 --- a/opensfm/src/bundle/error/projection_errors.h +++ b/opensfm/src/bundle/error/projection_errors.h @@ -22,10 +22,10 @@ class ReprojectionError { use_rig_camera_(use_rig_camera) {} protected: - geometry::ProjectionType type_; - Vec2d observed_; - double scale_; - bool use_rig_camera_; + const geometry::ProjectionType type_; + const Vec2d observed_; + const double scale_; + const bool use_rig_camera_; }; class ReprojectionError2D : public ReprojectionError { @@ -215,8 +215,8 @@ class ReprojectionError3D : public ReprojectionError { const Vec2d& observed, double std_deviation, bool use_rig_camera) : ReprojectionError(type, observed, std_deviation, use_rig_camera) { - double lon = observed[0] * 2 * M_PI; - double lat = -observed[1] * 2 * M_PI; + const double lon = observed[0] * 2 * M_PI; + const double lat = -observed[1] * 2 * M_PI; bearing_vector_[0] = std::cos(lat) * std::sin(lon); bearing_vector_[1] = -std::sin(lat); bearing_vector_[2] = std::cos(lat) * std::cos(lon); From ce5ad2732e2b97ac06d6600317af2aa8e22b537e Mon Sep 17 00:00:00 2001 From: Sebastian Haner Date: Tue, 28 Jun 2022 06:13:32 -0700 Subject: [PATCH 004/235] Fix descriptor dtype issue (#805) Summary: If a user selects the feature type using lower case letters, e.g. "orb", detect_features will cast to upper case and proceed normally. However, when saving the features no casting is performed, and descriptors are saved to disk as float, leading to the wrong matcher being selected in the next stage, silently leading to poor matching performance. Pull Request resolved: https://github.com/mapillary/OpenSfM/pull/805 Reviewed By: YanNoun Differential Revision: D37379909 Pulled By: fabianschenk fbshipit-source-id: 0c6b817bf5f88d2b736eb66c3bb42f9f8cc1e6aa --- opensfm/features.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opensfm/features.py b/opensfm/features.py index 56eac1500..c6bcf048e 100644 --- a/opensfm/features.py +++ b/opensfm/features.py @@ -94,7 +94,7 @@ def mask(self, mask: np.ndarray) -> "FeaturesData": def save(self, fileobject: Any, config: Dict[str, Any]): """Save features from file (path like or file object like)""" - feature_type = config["feature_type"] + feature_type = config["feature_type"].upper() if ( ( feature_type == "AKAZE" From cc222579826bfc6b6f76f811eb68d63904df624a Mon Sep 17 00:00:00 2001 From: Fabian Schenk Date: Tue, 28 Jun 2022 06:13:59 -0700 Subject: [PATCH 005/235] Update pyi files Summary: Update `*.pyi` files Reviewed By: tobias-o Differential Revision: D37451823 fbshipit-source-id: e3a73870358c842fbffa0468930cac5c7687572e --- opensfm/src/bundle/pybundle.pyi | 7 ++++++- opensfm/src/dense/pydense.pyi | 7 ++++++- opensfm/src/features/pyfeatures.pyi | 7 ++++++- opensfm/src/geo/pygeo.pyi | 17 +++++++++++------ opensfm/src/robust/pyrobust.pyi | 7 ++++++- opensfm/src/sfm/pysfm.pyi | 7 ++++++- 6 files changed, 41 insertions(+), 11 deletions(-) diff --git a/opensfm/src/bundle/pybundle.pyi b/opensfm/src/bundle/pybundle.pyi index 4e53f78a8..da53f049e 100644 --- a/opensfm/src/bundle/pybundle.pyi +++ b/opensfm/src/bundle/pybundle.pyi @@ -2,8 +2,13 @@ # Do not manually edit # To regenerate: # $ buck run //mapillary/opensfm/opensfm/src/bundle:pybundle_stubgen -# Use proper mode, e.g. @arvr/mode/linux/dev for arvr # @generated +# +# Tip: Be sure to run this with the build mode you use for your project, e.g., +# @//arvr/mode/linux/opt (or dev) in arvr. +# +# Ignore errors for [5] global variable types and [24] untyped generics. +# pyre-ignore-all-errors[5,24] import numpy import opensfm.pygeometry diff --git a/opensfm/src/dense/pydense.pyi b/opensfm/src/dense/pydense.pyi index 13a398277..afc938c44 100644 --- a/opensfm/src/dense/pydense.pyi +++ b/opensfm/src/dense/pydense.pyi @@ -2,8 +2,13 @@ # Do not manually edit # To regenerate: # $ buck run //mapillary/opensfm/opensfm/src/dense:pydense_stubgen -# Use proper mode, e.g. @arvr/mode/linux/dev for arvr # @generated +# +# Tip: Be sure to run this with the build mode you use for your project, e.g., +# @//arvr/mode/linux/opt (or dev) in arvr. +# +# Ignore errors for [5] global variable types and [24] untyped generics. +# pyre-ignore-all-errors[5,24] import numpy from typing import * diff --git a/opensfm/src/features/pyfeatures.pyi b/opensfm/src/features/pyfeatures.pyi index 755d7c89d..543e1feee 100644 --- a/opensfm/src/features/pyfeatures.pyi +++ b/opensfm/src/features/pyfeatures.pyi @@ -2,8 +2,13 @@ # Do not manually edit # To regenerate: # $ buck run //mapillary/opensfm/opensfm/src/features:pyfeatures_stubgen -# Use proper mode, e.g. @arvr/mode/linux/dev for arvr # @generated +# +# Tip: Be sure to run this with the build mode you use for your project, e.g., +# @//arvr/mode/linux/opt (or dev) in arvr. +# +# Ignore errors for [5] global variable types and [24] untyped generics. +# pyre-ignore-all-errors[5,24] import numpy from typing import * diff --git a/opensfm/src/geo/pygeo.pyi b/opensfm/src/geo/pygeo.pyi index 0e5f2774f..809b80dda 100644 --- a/opensfm/src/geo/pygeo.pyi +++ b/opensfm/src/geo/pygeo.pyi @@ -2,8 +2,13 @@ # Do not manually edit # To regenerate: # $ buck run //mapillary/opensfm/opensfm/src/geo:pygeo_stubgen -# Use proper mode, e.g. @arvr/mode/linux/dev for arvr # @generated +# +# Tip: Be sure to run this with the build mode you use for your project, e.g., +# @//arvr/mode/linux/opt (or dev) in arvr. +# +# Ignore errors for [5] global variable types and [24] untyped generics. +# pyre-ignore-all-errors[5,24] import numpy from typing import * @@ -37,19 +42,19 @@ def ecef_from_topocentric_transform(arg0: float, arg1: float, arg2: float) -> nu @overload def ecef_from_topocentric_transform(arg0: numpy.ndarray) -> numpy.ndarray:... @overload -def ecef_from_topocentric_transform_finite_diff(arg0: numpy.ndarray) -> numpy.ndarray:... -@overload def ecef_from_topocentric_transform_finite_diff(arg0: float, arg1: float, arg2: float) -> numpy.ndarray:... +@overload +def ecef_from_topocentric_transform_finite_diff(arg0: numpy.ndarray) -> numpy.ndarray:... def gps_distance(arg0: numpy.ndarray, arg1: numpy.ndarray) -> float:... @overload def lla_from_ecef(arg0: numpy.ndarray) -> numpy.ndarray:... @overload def lla_from_ecef(arg0: float, arg1: float, arg2: float) -> numpy.ndarray:... @overload -def lla_from_topocentric(arg0: numpy.ndarray, arg1: numpy.ndarray) -> numpy.ndarray:... -@overload def lla_from_topocentric(arg0: float, arg1: float, arg2: float, arg3: float, arg4: float, arg5: float) -> numpy.ndarray:... @overload -def topocentric_from_lla(arg0: numpy.ndarray, arg1: numpy.ndarray) -> numpy.ndarray:... +def lla_from_topocentric(arg0: numpy.ndarray, arg1: numpy.ndarray) -> numpy.ndarray:... @overload def topocentric_from_lla(arg0: float, arg1: float, arg2: float, arg3: float, arg4: float, arg5: float) -> numpy.ndarray:... +@overload +def topocentric_from_lla(arg0: numpy.ndarray, arg1: numpy.ndarray) -> numpy.ndarray:... diff --git a/opensfm/src/robust/pyrobust.pyi b/opensfm/src/robust/pyrobust.pyi index 0846303e9..ec78203b7 100644 --- a/opensfm/src/robust/pyrobust.pyi +++ b/opensfm/src/robust/pyrobust.pyi @@ -2,8 +2,13 @@ # Do not manually edit # To regenerate: # $ buck run //mapillary/opensfm/opensfm/src/robust:pyrobust_stubgen -# Use proper mode, e.g. @arvr/mode/linux/dev for arvr # @generated +# +# Tip: Be sure to run this with the build mode you use for your project, e.g., +# @//arvr/mode/linux/opt (or dev) in arvr. +# +# Ignore errors for [5] global variable types and [24] untyped generics. +# pyre-ignore-all-errors[5,24] import numpy from typing import * diff --git a/opensfm/src/sfm/pysfm.pyi b/opensfm/src/sfm/pysfm.pyi index 78b943472..96df11d6e 100644 --- a/opensfm/src/sfm/pysfm.pyi +++ b/opensfm/src/sfm/pysfm.pyi @@ -2,8 +2,13 @@ # Do not manually edit # To regenerate: # $ buck run //mapillary/opensfm/opensfm/src/sfm:pysfm_stubgen -# Use proper mode, e.g. @arvr/mode/linux/dev for arvr # @generated +# +# Tip: Be sure to run this with the build mode you use for your project, e.g., +# @//arvr/mode/linux/opt (or dev) in arvr. +# +# Ignore errors for [5] global variable types and [24] untyped generics. +# pyre-ignore-all-errors[5,24] import opensfm.pybundle import opensfm.pygeometry From 23550288a376ecd9c9027c75216b462764c1ac41 Mon Sep 17 00:00:00 2001 From: Piero Toffanin Date: Tue, 28 Jun 2022 06:14:42 -0700 Subject: [PATCH 006/235] Fix qhull crash during matching on small image set (#878) Summary: Hey there :hand: When trying to reconstruct a small image set (2 or 3 images) and `matching_graph_rounds` is enabled, the pipeline will fail at the feature matching step: ``` Traceback (most recent call last): File "/code/SuperBuild/install/bin/opensfm/bin/opensfm_main.py", line 25, in commands.command_runner( File "/code/SuperBuild/install/bin/opensfm/opensfm/commands/command_runner.py", line 37, in command_runner command.run(data, args) File "/code/SuperBuild/install/bin/opensfm/opensfm/commands/command.py", line 12, in run self.run_impl(data, args) File "/code/SuperBuild/install/bin/opensfm/opensfm/commands/match_features.py", line 11, in run_impl match_features.run_dataset(dataset) File "/code/SuperBuild/install/bin/opensfm/opensfm/actions/match_features.py", line 14, in run_dataset pairs_matches, preport = matching.match_images(data, {}, images, images) File "/code/SuperBuild/install/bin/opensfm/opensfm/matching.py", line 46, in match_images pairs, preport = pairs_selection.match_candidates_from_metadata( File "/code/SuperBuild/install/bin/opensfm/opensfm/pairs_selection.py", line 630, in match_candidates_from_metadata g = match_candidates_by_graph( File "/code/SuperBuild/install/bin/opensfm/opensfm/pairs_selection.py", line 253, in match_candidates_by_graph triangles = spatial.Delaunay(points).simplices File "qhull.pyx", line 1840, in scipy.spatial.qhull.Delaunay.__init__ File "qhull.pyx", line 356, in scipy.spatial.qhull._Qhull.__init__ scipy.spatial.qhull.QhullError: QH6214 qhull input error: not enough points(2) to construct initial simplex (need 4) While executing: | qhull d Qt Qc Q12 Qbb Qz Options selected for Qhull 2019.1.r 2019/06/21: run-id 521442032 delaunay Qtriangulate Qcoplanar-keep Q12-allow-wide Qbbound-last Qz-infinity-point _pre-merge _zero-centrum Qinterior-keep _maxoutside 0 ``` This is solved by having `match_candidates_by_graph` return early if there's less than 4 input images. Pull Request resolved: https://github.com/mapillary/OpenSfM/pull/878 Reviewed By: YanNoun Differential Revision: D37379926 Pulled By: fabianschenk fbshipit-source-id: 3390446668faa5a5680b772ddeb3bda7f9cc575e --- opensfm/pairs_selection.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opensfm/pairs_selection.py b/opensfm/pairs_selection.py index 0aa3b5ea3..8174c742c 100644 --- a/opensfm/pairs_selection.py +++ b/opensfm/pairs_selection.py @@ -222,7 +222,7 @@ def match_candidates_by_graph( rounds: int, ) -> Set[Tuple[str, str]]: """Find by triangulating the GPS points on X/Y axises""" - if len(images_cand) == 0 or rounds < 1: + if len(images_cand) < 4 or rounds < 1: return set() images_cand_set = set(images_cand) From 2aabdcb1d545ea67f04ef0dbc53365adab724b1d Mon Sep 17 00:00:00 2001 From: Piero Toffanin Date: Tue, 28 Jun 2022 09:02:25 -0700 Subject: [PATCH 007/235] Export image masks to OpenMVS (#921) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: Hello :hand: This PR adds support for exporting image masks to OpenMVS, if they are set. Hope this can be useful to others. :pray: Pull Request resolved: https://github.com/mapillary/OpenSfM/pull/921 Reviewed By: YanNoun Differential Revision: D37410286 Pulled By: fabianschenk fbshipit-source-id: 6a2ea96c95a91e0dc9f36c5ad0ab4931c02b98aa --- opensfm/actions/export_openmvs.py | 5 +++++ opensfm/src/dense/openmvs_exporter.h | 3 ++- opensfm/src/dense/pydense.pyi | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/opensfm/actions/export_openmvs.py b/opensfm/actions/export_openmvs.py index 23a346e11..7d3edc8ab 100644 --- a/opensfm/actions/export_openmvs.py +++ b/opensfm/actions/export_openmvs.py @@ -44,8 +44,13 @@ def export(reconstruction, tracks_manager, udata: UndistortedDataSet, export_onl if shot.camera.projection_type == "perspective": image_path = udata._undistorted_image_file(shot.id) + mask_path = udata._undistorted_mask_file(shot.id) + if not os.path.isfile(mask_path): + mask_path = "" + exporter.add_shot( str(os.path.abspath(image_path)), + str(os.path.abspath(mask_path)), str(shot.id), str(shot.camera.id), shot.pose.get_rotation_matrix(), diff --git a/opensfm/src/dense/openmvs_exporter.h b/opensfm/src/dense/openmvs_exporter.h index e4f7ce15e..088223f7b 100644 --- a/opensfm/src/dense/openmvs_exporter.h +++ b/opensfm/src/dense/openmvs_exporter.h @@ -21,7 +21,7 @@ class OpenMVSExporter { scene_.platforms.push_back(platform); } - void AddShot(const std::string &path, const std::string &shot_id, + void AddShot(const std::string &path, const std::string &maskPath, const std::string &shot_id, const std::string &camera_id, pyarray_d R, pyarray_d C) { const double *C_data = C.data(); @@ -36,6 +36,7 @@ class OpenMVSExporter { MVS::Interface::Image image; image.name = path; + image.maskName = maskPath; image.platformID = platform_id; image.cameraID = 0; image.poseID = pose_id; diff --git a/opensfm/src/dense/pydense.pyi b/opensfm/src/dense/pydense.pyi index afc938c44..498f19bf2 100644 --- a/opensfm/src/dense/pydense.pyi +++ b/opensfm/src/dense/pydense.pyi @@ -43,5 +43,5 @@ class OpenMVSExporter: def __init__(self) -> None: ... def add_camera(self, arg0: str, arg1: numpy.ndarray, arg2: int, arg3: int) -> None: ... def add_point(self, arg0: numpy.ndarray, arg1: list) -> None: ... - def add_shot(self, arg0: str, arg1: str, arg2: str, arg3: numpy.ndarray, arg4: numpy.ndarray) -> None: ... + def add_shot(self, arg0: str, arg1: str, arg2: str, arg3: str, arg4: numpy.ndarray, arg5: numpy.ndarray) -> None: ... def export(self, arg0: str) -> None: ... From 3b3e23694ff6edd3bfeec5834716f92075a83974 Mon Sep 17 00:00:00 2001 From: Lawrence Neal Date: Thu, 30 Jun 2022 05:21:48 -0700 Subject: [PATCH 008/235] Add required opencv requirement for linux (#910) Summary: Fixes `ModuleNotFoundError: No module named 'cv2'` when following the [Building](https://opensfm.readthedocs.io/en/latest/building.html) instructions on Ubuntu 20.04 with virtualenv or similar. Pull Request resolved: https://github.com/mapillary/OpenSfM/pull/910 Reviewed By: YanNoun Differential Revision: D37346114 Pulled By: fabianschenk fbshipit-source-id: 72e2f2d810c31945fe543bc4367ef68997e4a8df --- requirements.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 430906385..947c3ec9b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ cloudpickle==0.4.0 exifread==2.1.2 -flask==1.1.2 +flask==2.1.2 fpdf2==2.4.6 joblib==0.14.1 matplotlib @@ -17,3 +17,4 @@ six xmltodict==0.10.2 wheel opencv-python==4.5.1.48 ; sys_platform == "win32" +opencv-python ; sys_platform == "linux" From 0e7bf61cc3bb32584c2dc362d25e0804cdf441e3 Mon Sep 17 00:00:00 2001 From: Yann Noutary Date: Mon, 4 Jul 2022 05:06:06 -0700 Subject: [PATCH 009/235] feat: non-shrinking motion prior error Summary: This Diff changes the linear motion prior from additive to multiplicative form, in order to avoid shrinking effects that could arise. However, we need to switch back to additive from in case of coincident centers (is breaking error function continuity). Reviewed By: fabianschenk Differential Revision: D37345489 fbshipit-source-id: f69e763f6f797c40b181ceb576bb6ad3be6e547f --- .../src/bundle/error/motion_prior_errors.h | 21 ++++++++++++++++--- opensfm/synthetic_data/synthetic_generator.py | 20 +++++++++++------- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/opensfm/src/bundle/error/motion_prior_errors.h b/opensfm/src/bundle/error/motion_prior_errors.h index 61ef5d3d9..83e4be9ae 100644 --- a/opensfm/src/bundle/error/motion_prior_errors.h +++ b/opensfm/src/bundle/error/motion_prior_errors.h @@ -37,14 +37,29 @@ struct LinearMotionError { Eigen::Map > residual(r); // Position residual : op is translation - residual.segment(0, 3) = - T(position_scale_) * (T(alpha_) * (t2 - t0) + (t0 - t1)); + const auto eps = T(1e-15); + const auto t2_t0 = (t2 - t0); + const auto t1_t0 = (t1 - t0); + const auto t2_t0_norm = t2_t0.norm(); + const auto t1_t0_norm = t1_t0.norm(); + for (int i = 0; i < 3; ++i) { + // in case of non-zero speed, use speed ratio as it isn't subject + // to collapse when used together with position variance estimation + if (t2_t0_norm > eps) { + residual(i) = + T(position_scale_) * (T(alpha_) - t1_t0_norm / t2_t0_norm); + // otherwise, use classic difference between speeds, so one can still + // drag away position if they're coincident + } else { + residual(i) = T(position_scale_) * (T(alpha_) * t2_t0(i) - t1_t0(i)); + } + } // Rotation residual : op is rotation const Vec3 R2_R0t = T(alpha_) * MultRotations(R2.eval(), (-R0).eval()); const Vec3 R0_R1t = MultRotations(R0.eval(), (-R1).eval()); residual.segment(3, 3) = - T(position_scale_) * MultRotations(R2_R0t.eval(), R0_R1t); + T(orientation_scale_) * MultRotations(R2_R0t.eval(), R0_R1t); return true; } const double alpha_; diff --git a/opensfm/synthetic_data/synthetic_generator.py b/opensfm/synthetic_data/synthetic_generator.py index f4c7343a9..daecddb52 100644 --- a/opensfm/synthetic_data/synthetic_generator.py +++ b/opensfm/synthetic_data/synthetic_generator.py @@ -165,10 +165,6 @@ def generate_exifs( causal_gps_noise: bool = False, ) -> Dict[str, Any]: """Generate fake exif metadata from the reconstruction.""" - speed_ms = 10.0 - previous_pose = None - previous_time = 0 - exifs = {} def _gps_dop(shot: pymap.Shot) -> float: gps_dop = 15.0 @@ -178,6 +174,7 @@ def _gps_dop(shot: pymap.Shot) -> float: gps_dop = gps_noise[shot.camera.id] return gps_dop + exifs = {} per_sequence = defaultdict(list) for shot_name in sorted(reconstruction.shots.keys()): shot = reconstruction.shots[shot_name] @@ -193,13 +190,20 @@ def _gps_dop(shot: pymap.Shot) -> float: if shot.camera.projection_type in ["perspective", "fisheye"]: exif["focal_ratio"] = shot.camera.focal - pose = shot.pose.get_origin() + exifs[shot_name] = exif + + speed_ms = 10.0 + previous_pose = None + previous_time = 0 + for rig_instance in sorted( + reconstruction.rig_instances.values(), key=lambda x: x.id + ): + pose = rig_instance.pose.get_origin() if previous_pose is not None: previous_time += np.linalg.norm(pose - previous_pose) / speed_ms previous_pose = pose - exif["capture_time"] = previous_time - - exifs[shot_name] = exif + for shot_id in rig_instance.shots: + exifs[shot_id]["capture_time"] = previous_time for sequence_images in per_sequence.values(): if causal_gps_noise: From 7152fc7bf21d9439e9a9e9adb34eef1615a93bea Mon Sep 17 00:00:00 2001 From: Ihor Ivlev Date: Mon, 4 Jul 2022 08:07:11 -0700 Subject: [PATCH 010/235] Update using.rst (#922) Summary: Fix typo Pull Request resolved: https://github.com/mapillary/OpenSfM/pull/922 Reviewed By: YanNoun Differential Revision: D37601783 Pulled By: fabianschenk fbshipit-source-id: df6ae866e1660238c6d41ff06025f6f38ff3eae7 --- doc/source/using.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/using.rst b/doc/source/using.rst index 2dfb8e80d..36de1ebd6 100644 --- a/doc/source/using.rst +++ b/doc/source/using.rst @@ -8,7 +8,7 @@ Using Quickstart ---------- -An example dataset is available at ``data/berlin``. You can reconstruct it using by running:: +An example dataset is available at ``data/berlin``. You can reconstruct it by running:: bin/opensfm_run_all data/berlin From 3d576f06e1bb502ef6fa3a917980ef4796238a0d Mon Sep 17 00:00:00 2001 From: Fabian Schenk Date: Mon, 4 Jul 2022 08:18:34 -0700 Subject: [PATCH 011/235] Remove unused altitude Summary: The `altitude` is always set to `0`, thus can be safely removed from the `invent_reference_from_gps_and_gcp` computation. Reviewed By: YanNoun Differential Revision: D37453036 fbshipit-source-id: cb561dfb49505e7a2bb45799e88dbbb3f26012bd --- opensfm/dataset.py | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/opensfm/dataset.py b/opensfm/dataset.py index 60fdd3d2e..90aaf9b37 100644 --- a/opensfm/dataset.py +++ b/opensfm/dataset.py @@ -985,8 +985,12 @@ def save_undistorted_reconstruction( def invent_reference_from_gps_and_gcp( data: DataSetBase, images: Optional[List[str]] = None ) -> geo.TopocentricConverter: - lat, lon, alt = 0.0, 0.0, 0.0 - wlat, wlon, walt = 0.0, 0.0, 0.0 + """ Invent the reference from the weighted average of lat/lon measurements. + Most of the time the altitude provided in the metadata is inaccurate, thus + the reference altitude is set equal to 0 regardless of the altitude measurements. + """ + lat, lon = 0.0, 0.0 + wlat, wlon = 0.0, 0.0 if images is None: images = data.images() for image in images: @@ -997,27 +1001,18 @@ def invent_reference_from_gps_and_gcp( lon += w * d["gps"]["longitude"] wlat += w wlon += w - if "altitude" in d["gps"]: - alt += w * d["gps"]["altitude"] - walt += w if not wlat and not wlon: for gcp in data.load_ground_control_points(): if gcp.lla: lat += gcp.lla["latitude"] lon += gcp.lla["longitude"] - wlat += 1 - wlon += 1 - - if gcp.has_altitude: - alt += gcp.lla["altitude"] - walt += 1 + wlat += 1.0 + wlon += 1.0 if wlat: lat /= wlat if wlon: lon /= wlon - if walt: - alt /= walt - return geo.TopocentricConverter(lat, lon, 0) # Set altitude manually. + return geo.TopocentricConverter(lat, lon, 0) From a1a253f148d6e5daf6f2247e43e7d3fd306def53 Mon Sep 17 00:00:00 2001 From: Fabian Schenk Date: Mon, 4 Jul 2022 08:21:42 -0700 Subject: [PATCH 012/235] Default use_altitude_tag to True Summary: Set `use_altitude_tag = True` by default in the `config.py`. This should also solve problems like this [github issue](https://github.com/mapillary/OpenSfM/issues/918), where images are taken several meters above ground, e.g. by a drone, and points actually on the floor are then at a negative distance. Reviewed By: YanNoun Differential Revision: D37481946 fbshipit-source-id: 10247e1afca8c8f0aa31d693f2e14115cf238f89 --- opensfm/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opensfm/config.py b/opensfm/config.py index 55bf4a34f..4ef433a17 100644 --- a/opensfm/config.py +++ b/opensfm/config.py @@ -281,7 +281,7 @@ class OpenSfMConfig: # Params for GPS alignment ################################## # Use or ignore EXIF altitude tag - use_altitude_tag: bool = False + use_altitude_tag: bool = True # orientation_prior or naive align_method: str = "auto" # horizontal, vertical or no_roll From f3a059b5db681201dae9823c12da5275aed8bd86 Mon Sep 17 00:00:00 2001 From: Yann Noutary Date: Mon, 11 Jul 2022 07:43:20 -0700 Subject: [PATCH 013/235] feat: synthetic log for bundle Summary: This Diff adds a synthetic logging for OpenSfM bundle which summarizes if it was GLOBAL or LOCAL and the number of optimized entities (points and shots), as well as the actual running time. Reviewed By: Ahmed-Salama Differential Revision: D37717627 fbshipit-source-id: f51f55c03fc83f99c6f290f22eecce51199c4fd9 --- opensfm/reconstruction.py | 21 +++++++++++++++++---- opensfm/src/sfm/src/ba_helpers.cc | 17 +++++++++++++++-- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/opensfm/reconstruction.py b/opensfm/reconstruction.py index 117816dc5..3de7ebe89 100644 --- a/opensfm/reconstruction.py +++ b/opensfm/reconstruction.py @@ -4,11 +4,11 @@ import enum import logging import math -from abc import abstractmethod, ABC +from abc import ABC, abstractmethod from collections import defaultdict from itertools import combinations from timeit import default_timer as timer -from typing import Dict, Any, List, Tuple, Set, Optional, Union +from typing import Any, Dict, List, Optional, Set, Tuple, Union import cv2 import numpy as np @@ -20,10 +20,10 @@ pygeometry, pymap, pysfm, + reconstruction_helpers as helpers, rig, tracking, types, - reconstruction_helpers as helpers, ) from opensfm.align import align_reconstruction, apply_similarity from opensfm.context import current_memory_usage, parallel_map @@ -47,6 +47,18 @@ def _get_camera_from_bundle( camera.set_parameter_value(k, v) +def log_bundle_stats(bundle_type: str, bundle_report: Dict[str, Any]) -> None: + times = bundle_report["wall_times"] + time_secs = times["run"] + times["setup"] + times["teardown"] + num_images, num_points, num_reprojections = bundle_report["num_images"], bundle_report["num_points"], bundle_report["num_reprojections"] + + msg = f"Ran {bundle_type} bundle in {time_secs:.2f} secs." + if num_points > 0 : + msg += f"with {num_images}/{num_points}/{num_reprojections} ({num_reprojections/num_points:.2f}) " + msg += "shots/points/proj. (avg. length)" + + logger.info(msg) + def bundle( reconstruction: types.Reconstruction, camera_priors: Dict[str, pygeometry.Camera], @@ -62,7 +74,7 @@ def bundle( gcp if gcp is not None else [], config, ) - + log_bundle_stats("GLOBAL", report) logger.debug(report["brief_report"]) return report @@ -102,6 +114,7 @@ def bundle_local( central_shot_id, config, ) + log_bundle_stats("LOCAL", report) logger.debug(report["brief_report"]) return pt_ids, report diff --git a/opensfm/src/sfm/src/ba_helpers.cc b/opensfm/src/sfm/src/ba_helpers.cc index 4e15575a2..abdd55c56 100644 --- a/opensfm/src/sfm/src/ba_helpers.cc +++ b/opensfm/src/sfm/src/ba_helpers.cc @@ -215,6 +215,8 @@ py::tuple BAHelpers::BundleLocal( } } + size_t added_landmarks = 0; + size_t added_reprojections = 0; for (auto* shot : interior) { // Add all points of the shots that are in the interior for (const auto& lm_obs : shot->GetLandmarkObservations()) { @@ -223,10 +225,12 @@ py::tuple BAHelpers::BundleLocal( points.insert(lm); pt_ids.append(lm->id_); ba.AddPoint(lm->id_, lm->GetGlobalPos(), point_constant); + ++added_landmarks; } const auto& obs = lm_obs.second; ba.AddPointProjectionObservation(shot->id_, lm_obs.first->id_, obs.point, obs.scale); + ++added_reprojections; } } for (auto* shot : boundary) { @@ -236,6 +240,7 @@ py::tuple BAHelpers::BundleLocal( const auto& obs = lm_obs.second; ba.AddPointProjectionObservation(shot->id_, lm_obs.first->id_, obs.point, obs.scale); + ++added_reprojections; } } } @@ -298,10 +303,13 @@ py::tuple BAHelpers::BundleLocal( timer_run) .count() / 1000000.0; + report["num_images"] = interior.size(); report["num_interior_images"] = interior.size(); report["num_boundary_images"] = boundary.size(); report["num_other_images"] = map.NumberOfShots() - interior.size() - boundary.size(); + report["num_points"] = added_landmarks; + report["num_reprojections"] = added_reprojections; return py::make_tuple(pt_ids, report); } @@ -332,8 +340,8 @@ bool BAHelpers::TriangulateGCP( os.conservativeResize(added, Eigen::NoChange); if (added >= 2) { const std::vector thresholds(added, reproj_threshold); - const auto& res = geometry::TriangulateBearingsMidpoint(os, bs, thresholds, - min_ray_angle, max_ray_angle); + const auto& res = geometry::TriangulateBearingsMidpoint( + os, bs, thresholds, min_ray_angle, max_ray_angle); coordinates = res.second; return res.first; } @@ -672,6 +680,7 @@ py::dict BAHelpers::Bundle( } } + size_t added_reprojections = 0; for (const auto& shot_pair : map.GetShots()) { const auto& shot = shot_pair.second; @@ -686,6 +695,7 @@ py::dict BAHelpers::Bundle( const auto& obs = lm_obs.second; ba.AddPointProjectionObservation(shot.id_, lm_obs.first->id_, obs.point, obs.scale); + ++added_reprojections; } } @@ -746,6 +756,9 @@ py::dict BAHelpers::Bundle( timer_run) .count() / 1000000.0; + report["num_images"] = map.GetShots().size(); + report["num_points"] = map.GetLandmarks().size(); + report["num_reprojections"] = added_reprojections; return report; } From 1653772e08a65d6301a7252f22ab482f14564fdf Mon Sep 17 00:00:00 2001 From: Yann Noutary Date: Mon, 11 Jul 2022 07:43:20 -0700 Subject: [PATCH 014/235] fix: fix camera instanciation in global bundle Summary: This Diff fix an edge case in global bundle : - We were constructing the camera from the shots, because for > 1 rig instances (with > 1 rig camera), we usually have all the cameras in any of the instance. - In the edge case of individual rig cameras (each instance has a different rig camera), this is not the case during the initial pair bootstrap, as we ignore one of the two shots (we adjust each shot in turn). we fixed that by collecting all the cameras, similarly to the rig cameras collection, and instanciate them at once. Reviewed By: Ahmed-Salama Differential Revision: D37717624 fbshipit-source-id: 9841a4e6538b5a1f75a15756c4eeb15eac01eae7 --- opensfm/src/sfm/src/ba_helpers.cc | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/opensfm/src/sfm/src/ba_helpers.cc b/opensfm/src/sfm/src/ba_helpers.cc index abdd55c56..5e7cc5c40 100644 --- a/opensfm/src/sfm/src/ba_helpers.cc +++ b/opensfm/src/sfm/src/ba_helpers.cc @@ -432,10 +432,16 @@ py::dict BAHelpers::BundleShotPoses( rig_instances_ids.insert(shot.GetRigInstanceId()); } std::unordered_set rig_cameras_ids; + std::unordered_set cameras_ids; for (const auto& rig_instance_id : rig_instances_ids) { auto& instance = map.GetRigInstance(rig_instance_id); for (const auto& shot_n_rig_camera : instance.GetRigCameras()) { - rig_cameras_ids.insert(shot_n_rig_camera.second->id); + const auto rig_camera_id = shot_n_rig_camera.second->id; + rig_cameras_ids.insert(rig_camera_id); + + const auto shot_id = shot_n_rig_camera.first; + const auto camera_id = map.GetShot(shot_id).GetCamera()->id; + cameras_ids.insert(camera_id); } } @@ -446,16 +452,10 @@ py::dict BAHelpers::BundleShotPoses( rig_camera_priors.at(rig_camera_id).pose, fix_rig_camera); } - std::unordered_set added_cameras; - for (const auto& shot_id : shot_ids) { - const auto& shot = map.GetShot(shot_id); - const auto& cam = *shot.GetCamera(); - if (added_cameras.find(cam.id) != added_cameras.end()) { - continue; - } - const auto& cam_prior = camera_priors.at(cam.id); - ba.AddCamera(cam.id, cam, cam_prior, fix_cameras); - added_cameras.insert(cam.id); + for (const auto& camera_id : cameras_ids) { + const auto& cam = map.GetCamera(camera_id); + const auto& cam_prior = camera_priors.at(camera_id); + ba.AddCamera(camera_id, cam, cam_prior, fix_cameras); } std::unordered_set landmarks; From d1ec1d0590f9d6014e65f545741489224098e8d4 Mon Sep 17 00:00:00 2001 From: Yann Noutary Date: Mon, 11 Jul 2022 07:43:20 -0700 Subject: [PATCH 015/235] fix: use rig instances per rig camera Summary: This Diff strengthen the # of rig instances requirements for unleashing rig camera poses. In the Aria case, all rig instances have different cameras, which is over parametrized in that case. Reviewed By: Ahmed-Salama Differential Revision: D37717628 fbshipit-source-id: a24e7a1666af9711b131455864699c8cb7c2494e --- opensfm/src/sfm/src/ba_helpers.cc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/opensfm/src/sfm/src/ba_helpers.cc b/opensfm/src/sfm/src/ba_helpers.cc index 5e7cc5c40..835883eb6 100644 --- a/opensfm/src/sfm/src/ba_helpers.cc +++ b/opensfm/src/sfm/src/ba_helpers.cc @@ -629,8 +629,13 @@ py::dict BAHelpers::Bundle( // setup rig cameras constexpr size_t kMinRigInstanceForAdjust{10}; + const size_t shots_per_rig_cameras = + map.GetRigCameras().size() > 0 + ? static_cast(map.GetShots().size() / + map.GetRigCameras().size()) + : 1; const auto lock_rig_camera = - map.GetRigInstances().size() <= kMinRigInstanceForAdjust; + shots_per_rig_cameras <= kMinRigInstanceForAdjust; for (const auto& camera_pair : map.GetRigCameras()) { // could be set to false (not locked) the day we expose leverarm adjustment const bool is_leverarm = From d1165f9d522aee41f825be464a7e232286f529f1 Mon Sep 17 00:00:00 2001 From: Yann Noutary Date: Mon, 11 Jul 2022 07:43:20 -0700 Subject: [PATCH 016/235] fix: typo in stats Summary: This Diff fixes a typo in stats which was also causing failure in rig camera stats computation. Reviewed By: fabianschenk Differential Revision: D37717626 fbshipit-source-id: b0a1ef809f4733e8351238ae91bb7bc22b8b1ffc --- opensfm/stats.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opensfm/stats.py b/opensfm/stats.py index f4339bb31..5cc3a5151 100644 --- a/opensfm/stats.py +++ b/opensfm/stats.py @@ -424,7 +424,7 @@ def rig_statistics( } for rig_camera_id in rig_cameras: - if rig_camera.id not in stats: + if rig_camera_id not in stats: continue if "optimized_values" not in stats[rig_camera_id]: del stats[rig_camera_id] From cb1fdeeac280f4b32e52f7300506b4831f23ce8f Mon Sep 17 00:00:00 2001 From: Digvijayad Date: Mon, 18 Jul 2022 03:23:12 -0700 Subject: [PATCH 017/235] fixed ply generation to support official ply headers (#932) Summary: This PR is in regards to the issue https://github.com/mapillary/OpenSfM/issues/741. As open3D does not currently support user-defined headers, the following command fails to load colors from the ply file because OpenSfM generates ply file with `diffuse_` prefix to the color headers. ``` import open3d as o3d pcd = o3d.io.read_point_cloud('merged.ply') print(pcd.colors) >>pcd.colors => std::vector with 0 elements. ``` To support [official ply headers](http://paulbourke.net/dataformats/ply/), `point_cloud_to_ply` and `ply_header` functions have been modified in the `OpenSfM/opensfm/io.py`. ``` def point_cloud_to_ply( points: np.ndarray, normals: np.ndarray, colors: np.ndarray, labels: np.ndarray, fp: TextIO, ) -> None: ... fp.write("property uchar red\n") # Changed from diffuse_red fp.write("property uchar green\n") # Changed from diffuse_green fp.write("property uchar blue\n") # Changed from diffuse_blue fp.write("property uchar class\n") fp.write("end_header\n") ... ``` Pull Request resolved: https://github.com/mapillary/OpenSfM/pull/932 Reviewed By: YanNoun Differential Revision: D37817489 Pulled By: fabianschenk fbshipit-source-id: cde2a8172a2bf2f8256c9772a6bad4decaa9de78 --- opensfm/io.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/opensfm/io.py b/opensfm/io.py index 7eb0ac3cb..95eaedfa3 100644 --- a/opensfm/io.py +++ b/opensfm/io.py @@ -1033,9 +1033,9 @@ def ply_header( "property float nx", "property float ny", "property float nz", - "property uchar diffuse_red", - "property uchar diffuse_green", - "property uchar diffuse_blue", + "property uchar red", + "property uchar green", + "property uchar blue", ] else: header = [ @@ -1045,9 +1045,9 @@ def ply_header( "property float x", "property float y", "property float z", - "property uchar diffuse_red", - "property uchar diffuse_green", - "property uchar diffuse_blue", + "property uchar red", + "property uchar green", + "property uchar blue", ] if point_num_views: @@ -1146,9 +1146,9 @@ def point_cloud_to_ply( fp.write("property float nx\n") fp.write("property float ny\n") fp.write("property float nz\n") - fp.write("property uchar diffuse_red\n") - fp.write("property uchar diffuse_green\n") - fp.write("property uchar diffuse_blue\n") + fp.write("property uchar red\n") + fp.write("property uchar green\n") + fp.write("property uchar blue\n") fp.write("property uchar class\n") fp.write("end_header\n") From f6c616b52cc26c817c484f5edbc8651a85860820 Mon Sep 17 00:00:00 2001 From: Fabian Schenk Date: Mon, 18 Jul 2022 03:43:19 -0700 Subject: [PATCH 018/235] Update documentation Summary: Update wrong documentation: - OpenCV Fisheye has 4 radial distortion parameters instead of the 3 mentioned in the doc - Fisheye62 should have `theta^2` Follow-up on two github issues: - https://github.com/mapillary/OpenSfM/issues/930 - https://github.com/mapillary/OpenSfM/issues/929 See Fisheye62 discussion in the [github issue](https://github.com/mapillary/OpenSfM/issues/930). The distortion computation is the same as for OpenCV fisheye just with more parameters. Reviewed By: YanNoun Differential Revision: D37814244 fbshipit-source-id: fe999ef52b6da0865ec410175329c910dd78e331 --- doc/source/geometry.rst | 42 ++++++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/doc/source/geometry.rst b/doc/source/geometry.rst index b209bef01..199672d2e 100644 --- a/doc/source/geometry.rst +++ b/doc/source/geometry.rst @@ -163,34 +163,50 @@ Identifier `fisheye` v = f\ d\ \theta\ \frac{y}{r} \end{array} +Fisheye OpenCV +~~~~~~~~~~~~~~ +Identifier `fisheye_opencv` + +.. math:: + \begin{array}{l} + r = \sqrt(x^2 + y^2) \\ + \theta = \arctan(r / z) \\ + d_r = 1 + k_1\theta^2 + k_2\theta^4 + k_3\theta^6 + k_4\theta^8\\ + u = f\ (d\ \theta\ \frac{x}{r}) + c_x \\ + v = f\ (d\ \theta\ \frac{y}{r}) + c_y + \end{array} + + Fisheye 62 ~~~~~~~~~~~ Identifier `fisheye62` .. math:: \begin{array}{l} - r^2 = x^2 + y^2 \\ + r = \sqrt(x^2 + y^2) \\ \theta = \arctan(r / z) \\ - d_r = 1 + k_1\theta + k_2\theta^2 + k_3\theta^3 + k_4\theta^4 + k_5\theta^5 + k_6\theta^6\\ - d^t_x = 2p_1\ x_n\ y_n + p_2\ (r^2 + 2x)\\ - d^t_y = 2p_2\ x_n\ y_n + p_1\ (r^2 + 2y)\\ + d_r = 1 + k_1\theta^2 + k_2\theta^4 + k_3\theta^6 + k_4\theta^8 + k_5\theta^10 + k_6\theta^12\\ + d^t_x = 2p_1\ x_n\ y_n + p_2\ (\theta^2 + 2\ x_n^2)\\ + d^t_y = 2p_2\ x_n\ y_n + p_1\ (\theta^2 + 2\ y_n^2)\\ u = f\ (d_r\ \theta\ \frac{x}{r} + d^t_x) + c_x \\ v = f\ (d_r\ \theta\ \frac{y}{r} + d^t_y) + c_y \end{array} -Fisheye OpenCV -~~~~~~~~~~~~~~ -Identifier `fisheye_opencv` +Fisheye 624 +~~~~~~~~~~~ +Identifier `fisheye624` .. math:: \begin{array}{l} - r^2 = x^2 + y^2 \\ + r = \sqrt(x^2 + y^2) \\ \theta = \arctan(r / z) \\ - d_r = 1 + k_1\theta^2 + k_2\theta^4 + k_3\theta^6\\ - d^t_x = 2p_1\ x_n\ y_n + p_2\ (r^2 + 2x)\\ - d^t_y = 2p_2\ x_n\ y_n + p_1\ (r^2 + 2y)\\ - u = f\ (d\ \theta\ \frac{x}{r} + d^t_x) + c_x \\ - v = f\ (d\ \theta\ \frac{y}{r} + d^t_y) + c_y + d_r = 1 + k_1\theta^2 + k_2\theta^4 + k_3\theta^6 + k_4\theta^8 + k_5\theta^10 + k_6\theta^12\\ + d^t_x = 2p_1\ x_n\ y_n + p_2\ (\theta^2 + 2\ x_n^2)\\ + d^t_y = 2p_2\ x_n\ y_n + p_1\ (\theta^2 + 2\ y_n^2)\\ + d^s_x = s_0 * theta^2 + s_1 * theta^4\\ + d^s_y = s_2 * theta^2 + s_3 * theta^4\\ + u = f\ (d_r\ \theta\ \frac{x}{r} + d^t_x + d^p_x) + c_x \\ + v = f\ (d_r\ \theta\ \frac{y}{r} + d^t_y + d^p_y) + c_y \end{array} Spherical Camera From c81a19d143cc009aea3a3930575eac54152b7a74 Mon Sep 17 00:00:00 2001 From: Tobias Ollmann Date: Tue, 19 Jul 2022 02:35:04 -0700 Subject: [PATCH 019/235] increase feature timeout Reviewed By: YanNoun Differential Revision: D37609433 fbshipit-source-id: fc642902417c5e7ee9469edbb96303be0a24e471 --- opensfm/features_processing.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/opensfm/features_processing.py b/opensfm/features_processing.py index 78c757408..72513df3e 100644 --- a/opensfm/features_processing.py +++ b/opensfm/features_processing.py @@ -4,10 +4,10 @@ import queue import threading from timeit import default_timer as timer -from typing import Optional, List, Dict, Any, Tuple +from typing import Any, Dict, List, Optional, Tuple import numpy as np -from opensfm import bow, features, io, log, pygeometry, upright, masking +from opensfm import bow, features, io, log, masking, pygeometry, upright from opensfm.context import parallel_map from opensfm.dataset_base import DataSetBase @@ -124,7 +124,7 @@ class Counter(object): some reason, joblib doesn't like a good old threading.Lock (everything is stuck) """ - def __init__(self) ->None: + def __init__(self) -> None: self.number_of_read = 0 self.counter = itertools.count() self.read_lock = threading.Lock() @@ -157,7 +157,7 @@ def read_images( expected: int, force: bool, ) -> None: - full_queue_timeout = 120 + full_queue_timeout = 600 for image in images: logger.info(f"Reading data for image {image} (queue-size={queue.qsize()}") image_array = data.load_image(image) From c011295ed15edb673115058b69a61ee2b75439c6 Mon Sep 17 00:00:00 2001 From: Tobias Ollmann Date: Wed, 27 Jul 2022 05:03:07 -0700 Subject: [PATCH 020/235] set default orientation if not set Reviewed By: YanNoun Differential Revision: D38146475 fbshipit-source-id: e9073bf4b237fbc0908ae40f65c224e5b8a21900 --- opensfm/features_processing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opensfm/features_processing.py b/opensfm/features_processing.py index 72513df3e..ca8e4efa9 100644 --- a/opensfm/features_processing.py +++ b/opensfm/features_processing.py @@ -214,7 +214,7 @@ def bake_segmentation( points[:, :2], width, height, - exif["orientation"], + exif_orientation, new_width=new_width, new_height=new_height, ).astype(int) From e4ee1901abc21e27ec0427deb17dd71bb88c3ac8 Mon Sep 17 00:00:00 2001 From: Tobias Ollmann Date: Wed, 27 Jul 2022 05:03:07 -0700 Subject: [PATCH 021/235] make robust_match work with already filtered matches Summary: Fix robust_match on matches which are already filtered. Masking feature points again would cause out of bounds errors when resolving matches to features Reviewed By: YanNoun Differential Revision: D38146504 fbshipit-source-id: 444b21a959e4eca85b641d02ab59c03e752eb327 --- opensfm/matching.py | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/opensfm/matching.py b/opensfm/matching.py index e85c6979e..55bf8ec6f 100644 --- a/opensfm/matching.py +++ b/opensfm/matching.py @@ -1,6 +1,6 @@ import logging from timeit import default_timer as timer -from typing import Sized, Optional, Dict, Any, Tuple, List, Generator +from typing import Any, Dict, Generator, List, Optional, Sized, Tuple import cv2 import numpy as np @@ -472,6 +472,7 @@ def match_robust( camera2: pygeometry.Camera, data: DataSetBase, config_override: Dict[str, Any], + input_is_masked: bool = True, ) -> np.ndarray: """Perform robust geometry matching on a set of matched descriptors indexes.""" # Override parameters @@ -483,10 +484,16 @@ def match_robust( "matching_use_segmentation" ] # unused but keep using the same cache features_data1 = feature_loader.instance.load_all_data( - data, im1, masked=True, segmentation_in_descriptor=segmentation_in_descriptor + data, + im1, + masked=input_is_masked, + segmentation_in_descriptor=segmentation_in_descriptor, ) features_data2 = feature_loader.instance.load_all_data( - data, im2, masked=True, segmentation_in_descriptor=segmentation_in_descriptor + data, + im2, + masked=input_is_masked, + segmentation_in_descriptor=segmentation_in_descriptor, ) if ( features_data1 is None @@ -516,8 +523,10 @@ def match_robust( rmatches_unfiltered = [] m1 = feature_loader.instance.load_mask(data, im1) m2 = feature_loader.instance.load_mask(data, im2) - if m1 is not None and m2 is not None: + if m1 is not None and m2 is not None and input_is_masked: rmatches_unfiltered = unfilter_matches(rmatches, m1, m2) + else: + rmatches_unfiltered = rmatches robust_matching_min_match = overriden_config["robust_matching_min_match"] logger.debug( @@ -797,7 +806,11 @@ def robust_match_fundamental( def compute_inliers_bearings( - b1: np.ndarray, b2: np.ndarray, R: np.ndarray, t: np.ndarray, threshold: float=0.01 + b1: np.ndarray, + b2: np.ndarray, + R: np.ndarray, + t: np.ndarray, + threshold: float = 0.01, ) -> List[bool]: """Compute points that can be triangulated. @@ -956,7 +969,7 @@ def _non_static_matches( res = [] for match in matches: d = p1[match[0]] - p2[match[1]] - if d[0] ** 2 + d[1] ** 2 >= threshold ** 2: + if d[0] ** 2 + d[1] ** 2 >= threshold**2: res.append(match) static_ratio_threshold = 0.85 @@ -1023,7 +1036,12 @@ def _vermont_valid_mask(p: np.ndarray) -> bool: def _not_on_blackvue_watermark( - p1: np.ndarray, p2: np.ndarray, matches: List[Tuple[int, int]], im1: str, im2: str, data: DataSetBase + p1: np.ndarray, + p2: np.ndarray, + matches: List[Tuple[int, int]], + im1: str, + im2: str, + data: DataSetBase, ) -> List[Tuple[int, int]]: """Filter Blackvue's watermark.""" meta1 = data.load_exif(im1) From b69eb5f8b916a347f2cdf6ca924603e01c8dc365 Mon Sep 17 00:00:00 2001 From: Pyre Bot Jr <> Date: Thu, 4 Aug 2022 21:38:22 -0700 Subject: [PATCH 022/235] upgrade pyre version in `fbcode/mapillary` - batch 1 Differential Revision: D38448211 fbshipit-source-id: 4da716a8adcd2455c71d946fb2d0d62ffe35782a --- opensfm/io.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/opensfm/io.py b/opensfm/io.py index 95eaedfa3..1b1172d81 100644 --- a/opensfm/io.py +++ b/opensfm/io.py @@ -1352,7 +1352,6 @@ def __init__(self) -> None: @classmethod def exists(cls, path: str) -> str: - # pyre-fixme[7]: Expected `str` but got `bool`. return os.path.exists(path) @classmethod @@ -1361,12 +1360,10 @@ def ls(cls, path: str) -> List[str]: @classmethod def isfile(cls, path: str) -> str: - # pyre-fixme[7]: Expected `str` but got `bool`. return os.path.isfile(path) @classmethod def isdir(cls, path: str) -> str: - # pyre-fixme[7]: Expected `str` but got `bool`. return os.path.isdir(path) @classmethod @@ -1422,5 +1419,4 @@ def image_size(cls, path: str) -> Tuple[int, int]: @classmethod def timestamp(cls, path: str) -> str: - # pyre-fixme[7]: Expected `str` but got `float`. return os.path.getmtime(path) From 36ab87b11a98000af53f11aa3b78f01c33b8ab39 Mon Sep 17 00:00:00 2001 From: GaryStebbins <71356237+GaryStebbins@users.noreply.github.com> Date: Mon, 15 Aug 2022 06:09:37 -0700 Subject: [PATCH 023/235] Update features_processing.py (#940) Summary: Add missing parenthesis in log statement Pull Request resolved: https://github.com/mapillary/OpenSfM/pull/940 Reviewed By: YanNoun Differential Revision: D38703078 Pulled By: fabianschenk fbshipit-source-id: 54fe5655e724908e951bf289ae3bce9b71aad8e6 --- opensfm/features_processing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opensfm/features_processing.py b/opensfm/features_processing.py index ca8e4efa9..b48f2aac2 100644 --- a/opensfm/features_processing.py +++ b/opensfm/features_processing.py @@ -159,7 +159,7 @@ def read_images( ) -> None: full_queue_timeout = 600 for image in images: - logger.info(f"Reading data for image {image} (queue-size={queue.qsize()}") + logger.info(f"Reading data for image {image} (queue-size={queue.qsize()})") image_array = data.load_image(image) if data.config["features_bake_segmentation"]: segmentation_array = data.load_segmentation(image) From 9838a39729b56fb32a8191e277724fb54232fec8 Mon Sep 17 00:00:00 2001 From: Tobias Ollmann Date: Mon, 15 Aug 2022 08:21:09 -0700 Subject: [PATCH 024/235] Don't crash if compass accuracy is given as none Summary: `metadata.compass_accuracy.value` is required to be float. If accuracy is set to `None`, the if condition passes, but an error is thrown at runtime Reviewed By: fabianschenk Differential Revision: D38703925 fbshipit-source-id: 932a3022912b0de640e04102bcd36f5a4070b320 --- opensfm/reconstruction_helpers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opensfm/reconstruction_helpers.py b/opensfm/reconstruction_helpers.py index 7c2ac892a..0b8787801 100644 --- a/opensfm/reconstruction_helpers.py +++ b/opensfm/reconstruction_helpers.py @@ -160,7 +160,7 @@ def exif_to_metadata( if "compass" in exif: metadata.compass_angle.value = exif["compass"]["angle"] - if "accuracy" in exif["compass"]: + if exif["compass"].get("accuracy") is not None: metadata.compass_accuracy.value = exif["compass"]["accuracy"] if "capture_time" in exif: From 7bb45cf6482d1018733b306a2cc3992071a44d3a Mon Sep 17 00:00:00 2001 From: AfaqSaeed <45476864+AfaqSaeed@users.noreply.github.com> Date: Thu, 25 Aug 2022 07:32:21 -0700 Subject: [PATCH 025/235] Update using.rst (#938) Summary: Added data format for the tracks.csv file in order to help other people using that file Pull Request resolved: https://github.com/mapillary/OpenSfM/pull/938 Reviewed By: YanNoun Differential Revision: D38908516 Pulled By: fabianschenk fbshipit-source-id: 307207958b36f87290695503d73199e1fab8506f --- doc/source/using.rst | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/doc/source/using.rst b/doc/source/using.rst index 36de1ebd6..bcd3aeee4 100644 --- a/doc/source/using.rst +++ b/doc/source/using.rst @@ -248,6 +248,20 @@ create_tracks ~~~~~~~~~~~~~ This command links the matches between pairs of images to build feature point tracks. The tracks are stored in the `tracks.csv` file. A track is a set of feature points from different images that have been recognized to correspond to the same pysical point. +Format of the data in the genrated tracks.csv file is as follows: + +image_name track_id feature_index normalized_x normalized_y size R G B +02.jpg 1479 2594 0.0379803 -0.0481853 0.00155505 155 145 143 + +image_name -- name of the image file from which the data was extracted +track_id -- id to keep 'track' of the tracks +feature_index -- index of the keypoint from which this track is associated +normalized_x -- x coordinate of the normalized images coordinate system +normalized_y -- y coordinate of the normalized images coordinate system +size -- size value according to the normalized images coordinate system +R -- pixel value for Red channel +G -- pixel value for Green channel +B -- pixel value for Blue channel reconstruct ~~~~~~~~~~~ From ce3054beec8a193eb3d7119745d8e26a91cb3242 Mon Sep 17 00:00:00 2001 From: summitbri <36425892+summitbri@users.noreply.github.com> Date: Thu, 25 Aug 2022 07:33:39 -0700 Subject: [PATCH 026/235] Update sensor_data_detailed.json (#943) Summary: Pull Request resolved: https://github.com/mapillary/OpenSfM/pull/943 Reviewed By: YanNoun Differential Revision: D38908510 Pulled By: fabianschenk fbshipit-source-id: d9db92186064bbfab7cd32d363d2f440343465a0 --- opensfm/data/sensor_data_detailed.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/opensfm/data/sensor_data_detailed.json b/opensfm/data/sensor_data_detailed.json index d07082830..daf8928cd 100644 --- a/opensfm/data/sensor_data_detailed.json +++ b/opensfm/data/sensor_data_detailed.json @@ -4779,6 +4779,13 @@ "Sensor res. (width)": 6016.0, "Sensor res. (height)": 3376.0 }, + "DJI ZENMUSEP1": { + "Sensor height (mm)": 24, + "Sensor width (mm)": 35.9, + "Sensor res. (width)": 8192.0, + "Sensor": "35.9 x 24 mm", + "Sensor res. (height)": 5460.0 + }, "Epson L-500V": { "Sensor height (mm)": 4.32, "Sensor width (mm)": 5.75, From 82459698d665510e595cb1161ff70e2a4fd1c073 Mon Sep 17 00:00:00 2001 From: summitbri <36425892+summitbri@users.noreply.github.com> Date: Thu, 25 Aug 2022 07:59:59 -0700 Subject: [PATCH 027/235] Update sensor_data.json for Zenmuse P1 (#944) Summary: Pull Request resolved: https://github.com/mapillary/OpenSfM/pull/944 Reviewed By: YanNoun Differential Revision: D38908509 Pulled By: fabianschenk fbshipit-source-id: 94d9c79a615bc518564e6bc6a9ea1457ebd52859 --- opensfm/data/sensor_data.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/opensfm/data/sensor_data.json b/opensfm/data/sensor_data.json index 0c90df8c2..4378842e8 100644 --- a/opensfm/data/sensor_data.json +++ b/opensfm/data/sensor_data.json @@ -3705,5 +3705,6 @@ "SONY SLT-A77V": 23.5, "GITUP GIT2": 6.216, "DJI ZH20T": 7.68, - "DJI XT2": 10.88 + "DJI XT2": 10.88, + "DJI ZENMUSEP1": 35.9 } From 28d2adde75eb3d36137adf60ba7f34f17f2a7f09 Mon Sep 17 00:00:00 2001 From: summitbri <36425892+summitbri@users.noreply.github.com> Date: Mon, 12 Sep 2022 06:37:09 -0700 Subject: [PATCH 028/235] Update camera_calibration.yaml (#945) Summary: added zenmuse p1 (mapillary#933) Pull Request resolved: https://github.com/mapillary/OpenSfM/pull/945 Reviewed By: paulinus Differential Revision: D38908505 Pulled By: fabianschenk fbshipit-source-id: e50a16f6a6c1886207ea5598a70701964b2c0ac8 --- opensfm/data/camera_calibration.yaml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/opensfm/data/camera_calibration.yaml b/opensfm/data/camera_calibration.yaml index 2cf333d99..934394deb 100644 --- a/opensfm/data/camera_calibration.yaml +++ b/opensfm/data/camera_calibration.yaml @@ -67,6 +67,18 @@ "focal": 0.5930666527479901, "k1": -0.012137318698010527, "k2": 0.016199087342953698 + }, + "zenmusep1": { + "projection_type": "brown", + "focal_x": 0.993855582350662, + "focal_y": 0.993855582350662, + "c_x": -0.000890260610982073, + "c_y": 0.0017658361729384116, + "k1": -0.04734574598470396, + "k2": 0.00875629525446153, + "p1": 0.002032062604630639, + "p2": -0.0007921675594001833, + "k3": -0.06874708730325006 } } }, From bfa02497513fac5b70c518cb745e83a28a9ffb59 Mon Sep 17 00:00:00 2001 From: kielnino Date: Tue, 29 Nov 2022 08:22:17 -0800 Subject: [PATCH 029/235] Added fisheye62 projection_type to undistort (#957) Summary: The projection_type for the Fisheye62 cameras was missing in the switch-statements. Pull Request resolved: https://github.com/mapillary/OpenSfM/pull/957 Reviewed By: YanNoun Differential Revision: D41580786 Pulled By: fabianschenk fbshipit-source-id: 2bf5cf758fadd1643f289bf77e3c770de1c84691 --- opensfm/undistort.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/opensfm/undistort.py b/opensfm/undistort.py index 010752041..63bae4de6 100644 --- a/opensfm/undistort.py +++ b/opensfm/undistort.py @@ -47,9 +47,15 @@ def undistort_reconstruction( elif shot.camera.projection_type == "brown": urec.add_camera(perspective_camera_from_brown(shot.camera)) subshots = [get_shot_with_different_camera(urec, shot, image_format)] - elif shot.camera.projection_type in ["fisheye", "fisheye_opencv"]: + elif shot.camera.projection_type == "fisheye": urec.add_camera(perspective_camera_from_fisheye(shot.camera)) subshots = [get_shot_with_different_camera(urec, shot, image_format)] + elif shot.camera.projection_type == "fisheye_opencv": + urec.add_camera(perspective_camera_from_fisheye_opencv(shot.camera)) + subshots = [get_shot_with_different_camera(urec, shot, image_format)] + elif shot.camera.projection_type == "fisheye62": + urec.add_camera(perspective_camera_from_fisheye62(shot.camera)) + subshots = [get_shot_with_different_camera(urec, shot, image_format)] elif pygeometry.Camera.is_panorama(shot.camera.projection_type): subshot_width = int(data.config["depthmap_resolution"]) subshots = perspective_views_of_a_panorama( @@ -173,7 +179,7 @@ def undistort_image( return {} projection_type = shot.camera.projection_type - if projection_type in ["perspective", "brown", "fisheye", "fisheye_opencv"]: + if projection_type in ["perspective", "brown", "fisheye", "fisheye_opencv", "fisheye62"]: [undistorted_shot] = undistorted_shots new_camera = undistorted_shot.camera height, width = original.shape[:2] From 5375df1a1038c22219f64acb5e2d2c35c4fcafe2 Mon Sep 17 00:00:00 2001 From: Fabian Schenk Date: Mon, 23 Jan 2023 06:06:45 -0800 Subject: [PATCH 030/235] Update numpy and scipy requirements (#976) Summary: Pull Request resolved: https://github.com/mapillary/OpenSfM/pull/976 This is an extension to https://github.com/mapillary/OpenSfM/pull/972 - Update NUMPY, scipy requirements to make docker run again - A few things were removed in the most recent numpy version, so minor fixes Reviewed By: YanNoun Differential Revision: D42605541 fbshipit-source-id: 4061bd1c705c2625c99a6b1cf2829a8ef93e3802 --- opensfm/features.py | 4 ++-- opensfm/synthetic_data/synthetic_scene.py | 2 +- requirements.txt | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/opensfm/features.py b/opensfm/features.py index c6bcf048e..c48fdcc76 100644 --- a/opensfm/features.py +++ b/opensfm/features.py @@ -2,7 +2,7 @@ import logging import time -from typing import Tuple, Dict, Any, List, Optional +from typing import Any, Dict, List, Optional, Tuple import cv2 import numpy as np @@ -119,7 +119,7 @@ def save(self, fileobject: Any, config: Dict[str, Any]): colors=self.colors, segmentations=semantic.segmentation.astype(np.uint8), instances=instances.astype(np.int16) if instances is not None else [], - segmentation_labels=np.array(semantic.labels).astype(np.str), + segmentation_labels=np.array(semantic.labels).astype(str), OPENSFM_FEATURES_VERSION=self.FEATURES_VERSION, ) else: diff --git a/opensfm/synthetic_data/synthetic_scene.py b/opensfm/synthetic_data/synthetic_scene.py index 3c572d802..81b2c6d5d 100644 --- a/opensfm/synthetic_data/synthetic_scene.py +++ b/opensfm/synthetic_data/synthetic_scene.py @@ -395,7 +395,7 @@ def get_reconstruction(self) -> types.Reconstruction: wall_color = [10, 90, 130] return sg.create_reconstruction( - points=np.asarray([self.floor_points, self.wall_points]), + points=np.asarray([self.floor_points, self.wall_points], dtype=object), colors=np.asarray([floor_color, wall_color]), cameras=self.cameras, shot_ids=self.shot_ids, diff --git a/requirements.txt b/requirements.txt index 947c3ec9b..5b937b629 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,13 +5,13 @@ fpdf2==2.4.6 joblib==0.14.1 matplotlib networkx==2.5 -numpy +numpy>=1.19 Pillow>=8.1.1 pyproj>=1.9.5.1 pytest==3.0.7 python-dateutil>=2.7 pyyaml==5.4 -scipy +scipy>=1.10.0 Sphinx==4.2.0 six xmltodict==0.10.2 From 1a69f7c89b4518976b251f53a4ace8895c40c92e Mon Sep 17 00:00:00 2001 From: kielnino Date: Wed, 25 Jan 2023 02:53:45 -0800 Subject: [PATCH 031/235] fix setting config parameter on the wrong dataset (#975) Summary: Here the `interactive` flag is set on the DataSet but `compute_depthmaps` is called with the `UndistortedDataSet`. So I think the flag need to be set there. Pull Request resolved: https://github.com/mapillary/OpenSfM/pull/975 Reviewed By: YanNoun Differential Revision: D42736827 Pulled By: fabianschenk fbshipit-source-id: 0da4f4eaf5abe07469bc6d9d52693be2c20d9f58 --- opensfm/actions/compute_depthmaps.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opensfm/actions/compute_depthmaps.py b/opensfm/actions/compute_depthmaps.py index 3d1a7e7a1..d16f06e59 100644 --- a/opensfm/actions/compute_depthmaps.py +++ b/opensfm/actions/compute_depthmaps.py @@ -16,7 +16,7 @@ def run_dataset(data: DataSet, subfolder, interactive) -> None: udata_path = os.path.join(data.data_path, subfolder) udataset = dataset.UndistortedDataSet(data, udata_path, io_handler=data.io_handler) - data.config["interactive"] = interactive + udataset.config["interactive"] = interactive reconstructions = udataset.load_undistorted_reconstruction() tracks_manager = udataset.load_undistorted_tracks_manager() dense.compute_depthmaps(udataset, tracks_manager, reconstructions[0]) From 8b97fa780af100db1096fb31404b22e2476b241d Mon Sep 17 00:00:00 2001 From: generatedunixname89002005307016 Date: Thu, 2 Feb 2023 00:29:28 -0800 Subject: [PATCH 032/235] upgrade pyre version in `fbcode/mapillary` - batch 1 Differential Revision: D42946608 fbshipit-source-id: 81f76766e35948ed37d84dca79420b68b23b3c3a --- opensfm/io.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/opensfm/io.py b/opensfm/io.py index 1b1172d81..95eaedfa3 100644 --- a/opensfm/io.py +++ b/opensfm/io.py @@ -1352,6 +1352,7 @@ def __init__(self) -> None: @classmethod def exists(cls, path: str) -> str: + # pyre-fixme[7]: Expected `str` but got `bool`. return os.path.exists(path) @classmethod @@ -1360,10 +1361,12 @@ def ls(cls, path: str) -> List[str]: @classmethod def isfile(cls, path: str) -> str: + # pyre-fixme[7]: Expected `str` but got `bool`. return os.path.isfile(path) @classmethod def isdir(cls, path: str) -> str: + # pyre-fixme[7]: Expected `str` but got `bool`. return os.path.isdir(path) @classmethod @@ -1419,4 +1422,5 @@ def image_size(cls, path: str) -> Tuple[int, int]: @classmethod def timestamp(cls, path: str) -> str: + # pyre-fixme[7]: Expected `str` but got `float`. return os.path.getmtime(path) From 44f4774a531ba185287061c5b99902743ab05636 Mon Sep 17 00:00:00 2001 From: Piero Toffanin Date: Mon, 20 Feb 2023 01:11:25 -0800 Subject: [PATCH 033/235] Adds Mavic 3 Pro camera CCD width (#966) Summary: Adds information for the Mavic 3 Pro camera. Pull Request resolved: https://github.com/mapillary/OpenSfM/pull/966 Reviewed By: YanNoun Differential Revision: D43357430 Pulled By: fabianschenk fbshipit-source-id: 2a08923f71abc3cc979819346f0225f31cdb2af9 --- opensfm/data/sensor_data.json | 1 + 1 file changed, 1 insertion(+) diff --git a/opensfm/data/sensor_data.json b/opensfm/data/sensor_data.json index 4378842e8..ca6a23922 100644 --- a/opensfm/data/sensor_data.json +++ b/opensfm/data/sensor_data.json @@ -1144,6 +1144,7 @@ "GE X500": 6.16, "GE X550": 6.16, "GE X600": 6.16, + "Hasselblad L2D-20c": 17.5, "HP CA350": 6.16, "HP CB350": 6.16, "HP CW450": 6.16, From 0e67e22ca14db034c87fe80ede0081dc83f728a2 Mon Sep 17 00:00:00 2001 From: Piero Toffanin Date: Mon, 20 Feb 2023 01:22:21 -0800 Subject: [PATCH 034/235] Fix match_candidates_by_graph when initial simplex is flat (#969) Summary: Hello :wave:. in certain datasets (e.g. https://hub.dronedb.app/r/saijinnaib/roofer_gaming-13268) the Delaunay triangulation call for `match_candidates_by_graph` fails. ![image](https://user-images.githubusercontent.com/1951843/207391509-c0448204-bac2-4ce6-b01c-1fd927442432.png) We can get around this problem by passing "QbB" (http://www.qhull.org/html/qh-optq.htm#QbB) to the function call, which may reduce some precision, but does not change the topology, which should suffice for the purposes here. First reported on https://github.com/OpenDroneMap/ODM/issues/1564#issuecomment-1347753001 Pull Request resolved: https://github.com/mapillary/OpenSfM/pull/969 Reviewed By: YanNoun Differential Revision: D43357417 Pulled By: fabianschenk fbshipit-source-id: 53e57df8f7d98e9f6e940bb6865c3a4801f895e4 --- opensfm/pairs_selection.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/opensfm/pairs_selection.py b/opensfm/pairs_selection.py index 8174c742c..191ab030e 100644 --- a/opensfm/pairs_selection.py +++ b/opensfm/pairs_selection.py @@ -250,7 +250,13 @@ def produce_edges(triangles): # first round compute scale based on edges (and push delaunay edges) edge_distances = [] - triangles = spatial.Delaunay(points).simplices + try: + triangles = spatial.Delaunay(points).simplices + except spatial.QhullError: + # Initial simplex is flat + # Scale the input to fit the unit cube ("QbB") + triangles = spatial.Delaunay(points, qhull_options="Qbb Qc Qz Q12 QbB").simplices + for (image1, image2), (vertex1, vertex2) in produce_edges(triangles): pairs.add((image1, image2)) edge_distances.append(norm_2d(points[vertex1] - points[vertex2])) From b760b21f5d23a2872e89fc708ac44645623e605a Mon Sep 17 00:00:00 2001 From: Karry Wong Date: Tue, 21 Feb 2023 10:59:27 -0800 Subject: [PATCH 035/235] Add GroundControlPoint Role (#983) Summary: Pull Request resolved: https://github.com/mapillary/OpenSfM/pull/983 A GCP can have two different roles, either OPTIMIZATION or METRICS_ONLY: 1. OPTIMIZATION: CP is used in optimization and logging metrics 2. METRICS_ONLY: CP is only used in logging metrics Reviewed By: chi3x10, mlopezantequera Differential Revision: D43289380 fbshipit-source-id: d4faa53dcd5a80b3c9bbef64d1358b244e71f03c --- opensfm/src/map/ground_control_points.h | 14 ++++++++++++++ opensfm/src/map/pymap.pyi | 15 +++++++++++++++ opensfm/src/map/python/pybind.cc | 6 ++++++ 3 files changed, 35 insertions(+) diff --git a/opensfm/src/map/ground_control_points.h b/opensfm/src/map/ground_control_points.h index c22c1f82c..bab86d74a 100644 --- a/opensfm/src/map/ground_control_points.h +++ b/opensfm/src/map/ground_control_points.h @@ -3,6 +3,17 @@ #include #include namespace map { +enum GroundControlPointRole { + /* A ground control point role in SfM cluster merge and bundle adjuster + + Attributes: + OPTIMIZATION: used in the optimization of map chunks and logging metrics + METRICS_ONLY: only used in logging metrics + + **/ + OPTIMIZATION = 0, + METRICS_ONLY = 1 +}; struct GroundControlPointObservation { /* A ground control point observation. @@ -27,6 +38,8 @@ struct GroundControlPoint { observations: list of observations of the point on images id: a unique id for this point group (survey point + image observations) survey_point_id: a unique id for the point on the ground + role: OPTIMIZATION if gcp is used in SfM optimization, METRICS_ONLY if the + ground control point is used for computing map merging metrics */ GroundControlPoint() = default; LandmarkId id_ = ""; @@ -34,6 +47,7 @@ struct GroundControlPoint { bool has_altitude_ = false; AlignedVector observations_; std::map lla_; + GroundControlPointRole role_; Vec3d GetLlaVec3d() const { return { diff --git a/opensfm/src/map/pymap.pyi b/opensfm/src/map/pymap.pyi index 2c2305924..9af9c042f 100644 --- a/opensfm/src/map/pymap.pyi +++ b/opensfm/src/map/pymap.pyi @@ -20,6 +20,7 @@ __all__ = [ "ErrorType", "GroundControlPoint", "GroundControlPointObservation", +"GroundControlPointRole", "Landmark", "LandmarkView", "Map", @@ -39,7 +40,9 @@ __all__ = [ "ShotView", "TracksManager", "Angular", +"METRICS_ONLY", "Normalized", +"OPTIMIZATION", "Pixel" ] class BiasView: @@ -93,6 +96,10 @@ class GroundControlPoint: @observations.setter def observations(self, arg1: List[GroundControlPointObservation]) -> None:... @property + def role(self) -> GroundControlPointRole:... + @role.setter + def role(self, arg0: GroundControlPointRole) -> None:... + @property def survey_point_id(self) -> int:... @survey_point_id.setter def survey_point_id(self, arg0: int) -> None:... @@ -113,6 +120,12 @@ class GroundControlPointObservation: def uid(self) -> int:... @uid.setter def uid(self, arg0: int) -> None:... +class GroundControlPointRole: + OPTIMIZATION: "GroundControlPointRole" + METRICS_ONLY: "GroundControlPointRole" + __members__: Dict[str, "GroundControlPointRole"] + @property + def name(self) -> str: ... class Landmark: def __init__(self, arg0: str, arg1: numpy.ndarray) -> None: ... def get_observations(self) -> Dict[Shot, int]: ... @@ -470,5 +483,7 @@ class TracksManager: def remove_observation(self, arg0: str, arg1: str) -> None: ... def write_to_file(self, arg0: str) -> None: ... Angular = ... +METRICS_ONLY = ... Normalized = ... +OPTIMIZATION = ... Pixel = ... \ No newline at end of file diff --git a/opensfm/src/map/python/pybind.cc b/opensfm/src/map/python/pybind.cc index b914cbc8e..207fa4066 100644 --- a/opensfm/src/map/python/pybind.cc +++ b/opensfm/src/map/python/pybind.cc @@ -251,6 +251,11 @@ PYBIND11_MODULE(pymap, m) { .def_readwrite("projection", &map::GroundControlPointObservation::projection_); + py::enum_(m, "GroundControlPointRole") + .value("OPTIMIZATION", map::GroundControlPointRole::OPTIMIZATION) + .value("METRICS_ONLY", map::GroundControlPointRole::METRICS_ONLY) + .export_values(); + py::class_(m, "GroundControlPoint") .def(py::init()) .def_readwrite("id", &map::GroundControlPoint::id_) @@ -259,6 +264,7 @@ PYBIND11_MODULE(pymap, m) { .def_readwrite("lla", &map::GroundControlPoint::lla_) .def_property("lla_vec", &map::GroundControlPoint::GetLlaVec3d, &map::GroundControlPoint::SetLla) + .def_readwrite("role", &map::GroundControlPoint::role_) .def_property("observations", &map::GroundControlPoint::GetObservations, &map::GroundControlPoint::SetObservations) .def("add_observation", &map::GroundControlPoint::AddObservation); From 8887d336cdc305427d59d02a96ef9396aa197ad3 Mon Sep 17 00:00:00 2001 From: Piero Toffanin Date: Fri, 21 Apr 2023 04:56:37 -0700 Subject: [PATCH 036/235] FLANN LSH Indexing for binary descriptors (#996) Summary: Hello :wave:, this PR adds support for using the FLANN index while using binary descriptors (e.g. `orb`). Pull Request resolved: https://github.com/mapillary/OpenSfM/pull/996 Reviewed By: YanNoun Differential Revision: D45175480 Pulled By: fabianschenk fbshipit-source-id: 7807ba37ee9c0b6ce98d1724e7699cd9650823f7 --- opensfm/features.py | 10 +++++++++- opensfm/matching.py | 8 -------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/opensfm/features.py b/opensfm/features.py index c48fdcc76..bf07b7973 100644 --- a/opensfm/features.py +++ b/opensfm/features.py @@ -630,6 +630,7 @@ def build_flann_index(descriptors: np.ndarray, config: Dict[str, Any]) -> Any: # FLANN_INDEX_COMPOSITE = 3 # FLANN_INDEX_KDTREE_SINGLE = 4 # FLANN_INDEX_HIERARCHICAL = 5 + FLANN_INDEX_LSH = 6 if descriptors.dtype.type is np.float32: algorithm_type = config["flann_algorithm"].upper() @@ -645,9 +646,16 @@ def build_flann_index(descriptors: np.ndarray, config: Dict[str, Any]) -> Any: "iterations": config["flann_iterations"], "tree": config["flann_tree"], } + elif descriptors.dtype.type is np.uint8: + flann_params = { + "algorithm": FLANN_INDEX_LSH, + "table_number": 10, + "key_size": 24, + "multi_probe_level": 1, + } else: raise ValueError( - "FLANN isn't supported for binary features because of poor-performance. Use BRUTEFORCE instead." + f"FLANN isn't supported for feature type {descriptors.dtype.type}." ) return context.flann_Index(descriptors, flann_params) diff --git a/opensfm/matching.py b/opensfm/matching.py index 55bf8ec6f..068d126e9 100644 --- a/opensfm/matching.py +++ b/opensfm/matching.py @@ -369,14 +369,6 @@ def _match_descriptors_impl( if d1 is None or d2 is None: return dummy_ret - # Prevent using FLANN + Binary (np.uint8) - binary_matcher_override = "BRUTEFORCE" - if matcher_type == "FLANN" and d1.dtype == np.uint8: - logger.warning( - f"{matcher_type} for binary descriptors offers poor performance. Switching to {binary_matcher_override}." - ) - matcher_type = binary_matcher_override - symmetric_matching = overriden_config["symmetric_matching"] if matcher_type == "WORDS": words1 = feature_loader.instance.load_words(data, im1, masked=True) From 5213d0f1e4cb88db7d638f4b24bbb9be777768bb Mon Sep 17 00:00:00 2001 From: Yann Noutary Date: Fri, 5 May 2023 07:27:18 -0700 Subject: [PATCH 037/235] Fix runtime with less iterations and more threads Summary: This Diff fixes ceres 2.0 update in dev/mode which is noticeably slower. Unfortunately, in the short-term, we found no other issues than brute-forcing the threads # and the reducing the maximum number of iterations. Differential Revision: D45604439 Privacy Context Container: L1124100 fbshipit-source-id: 9c27fbb6ba8f3b0de09b2f7994164248be38fc57 --- opensfm/test/test_reconstruction_incremental.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/opensfm/test/test_reconstruction_incremental.py b/opensfm/test/test_reconstruction_incremental.py index 4ad885943..e1513dab5 100644 --- a/opensfm/test/test_reconstruction_incremental.py +++ b/opensfm/test/test_reconstruction_incremental.py @@ -16,6 +16,8 @@ def test_reconstruction_incremental( dataset.config["bundle_compensate_gps_bias"] = True dataset.config["bundle_use_gcp"] = True + dataset.config["bundle_max_iterations"] = 20 + dataset.config["processes"] = 4 _, reconstructed_scene = reconstruction.incremental_reconstruction( dataset, scene_synthetic.tracks_manager ) From 69f16bf851601b9c50add970834f1e44fc5e3b56 Mon Sep 17 00:00:00 2001 From: generatedunixname89002005307016 Date: Tue, 23 May 2023 20:47:14 -0700 Subject: [PATCH 038/235] upgrade pyre version in `fbcode/mapillary` - batch 1 Differential Revision: D46120702 fbshipit-source-id: bc82165733a63e53a01ac924ded4ba78e4193d3e --- opensfm/synthetic_data/synthetic_generator.py | 6 ++++++ opensfm/synthetic_data/synthetic_scene.py | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/opensfm/synthetic_data/synthetic_generator.py b/opensfm/synthetic_data/synthetic_generator.py index daecddb52..6037761fa 100644 --- a/opensfm/synthetic_data/synthetic_generator.py +++ b/opensfm/synthetic_data/synthetic_generator.py @@ -327,8 +327,14 @@ def create_reconstruction( s_cameras, ) in enumerate(zip(rig_shots, rig_positions, rig_rotations, rig_cameras, cameras)): add_shots_to_reconstruction( + # pyre-fixme[6]: For 1st argument expected `List[List[str]]` but got + # `List[List[Tuple[str, str]]]`. s_rig_shots, + # pyre-fixme[6]: For 2nd argument expected `List[ndarray]` but got + # `ndarray`. s_rig_positions, + # pyre-fixme[6]: For 3rd argument expected `List[ndarray]` but got + # `ndarray`. s_rig_rotations, s_rig_cameras, s_cameras, diff --git a/opensfm/synthetic_data/synthetic_scene.py b/opensfm/synthetic_data/synthetic_scene.py index 81b2c6d5d..688717981 100644 --- a/opensfm/synthetic_data/synthetic_scene.py +++ b/opensfm/synthetic_data/synthetic_scene.py @@ -344,7 +344,9 @@ def add_rig_camera_sequence( for j, (rig_camera_p, rig_camera_r) in enumerate( zip(relative_positions, relative_rotations) ): + # pyre-fixme[6]: For 1st argument expected `ndarray` but got `List[float]`. pose_rig_camera = pygeometry.Pose(rig_camera_r) + # pyre-fixme[6]: For 1st argument expected `ndarray` but got `List[float]`. pose_rig_camera.set_origin(rig_camera_p) rotations = [] @@ -370,7 +372,9 @@ def add_rig_camera_sequence( for i, (rig_camera_p, rig_camera_r) in enumerate( zip(relative_positions, relative_rotations) ): + # pyre-fixme[6]: For 1st argument expected `ndarray` but got `List[float]`. pose_rig_camera = pygeometry.Pose(rig_camera_r) + # pyre-fixme[6]: For 1st argument expected `ndarray` but got `List[float]`. pose_rig_camera.set_origin(rig_camera_p) rig_camera_id = f"RigCamera {rig_camera_id_shift + i}" rig_camera = pymap.RigCamera(pose_rig_camera, rig_camera_id) From 5cdc3cee41f3117ec218bbff80662eeb461fbaf6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 24 May 2023 04:51:11 -0700 Subject: [PATCH 039/235] build(deps): Bump flask from 2.1.2 to 2.3.2 (#999) Summary: Bumps [flask](https://github.com/pallets/flask) from 2.1.2 to 2.3.2.
Release notes

Sourced from flask's releases.

2.3.2

This is a security fix release for the 2.3.x release branch.

2.3.1

This is a fix release for the 2.3.x release branch.

2.3.0

This is a feature release, which includes new features, removes previously deprecated code, and adds new deprecations. The 2.3.x branch is now the supported fix branch, the 2.2.x branch will become a tag marking the end of support for that branch. We encourage everyone to upgrade, and to use a tool such as pip-tools to pin all dependencies and control upgrades. Test with warnings treated as errors to be able to adapt to deprecation warnings early.

2.2.4

This is a fix release for the 2.2.x release branch.

2.2.3

This is a fix release for the 2.2.x release branch.

2.2.2

This is a fix release for the 2.2.0 feature release.

2.2.1

This is a fix release for the 2.2.0 feature release.

2.2.0

This is a feature release, which includes new features and removes previously deprecated code. The 2.2.x branch is now the supported bug fix branch, the 2.1.x branch will become a tag marking the end of support for that branch. We encourage everyone to upgrade, and to use a tool such as pip-tools to pin all dependencies and control upgrades.

2.1.3

... (truncated)

Changelog

Sourced from flask's changelog.

Version 2.3.2

Released 2023-05-01

  • Set Vary: Cookie header when the session is accessed, modified, or refreshed.
  • Update Werkzeug requirement to >=2.3.3 to apply recent bug fixes.

Version 2.3.1

Released 2023-04-25

  • Restore deprecated from flask import Markup. :issue:5084

Version 2.3.0

Released 2023-04-25

  • Drop support for Python 3.7. :pr:5072

  • Update minimum requirements to the latest versions: Werkzeug>=2.3.0, Jinja2>3.1.2, itsdangerous>=2.1.2, click>=8.1.3.

  • Remove previously deprecated code. :pr:4995

    • The push and pop methods of the deprecated _app_ctx_stack and _request_ctx_stack objects are removed. top still exists to give extensions more time to update, but it will be removed.
    • The FLASK_ENV environment variable, ENV config key, and app.env property are removed.
    • The session_cookie_name, send_file_max_age_default, use_x_sendfile, propagate_exceptions, and templates_auto_reload properties on app are removed.
    • The JSON_AS_ASCII, JSON_SORT_KEYS, JSONIFY_MIMETYPE, and JSONIFY_PRETTYPRINT_REGULAR config keys are removed.
    • The app.before_first_request and bp.before_app_first_request decorators are removed.
    • json_encoder and json_decoder attributes on app and blueprint, and the corresponding json.JSONEncoder and JSONDecoder classes, are removed.
    • The json.htmlsafe_dumps and htmlsafe_dump functions are removed.
    • Calling setup methods on blueprints after registration is an error instead of a warning. :pr:4997
  • Importing escape and Markup from flask is deprecated. Import them directly from markupsafe instead. :pr:4996

  • The app.got_first_request property is deprecated. :pr:4997

  • The locked_cached_property decorator is deprecated. Use a lock inside the decorated function if locking is needed. :issue:4993

... (truncated)

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=flask&package-manager=pip&previous-version=2.1.2&new-version=2.3.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `dependabot rebase` will rebase this PR - `dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `dependabot merge` will merge this PR after your CI passes on it - `dependabot squash and merge` will squash and merge this PR after your CI passes on it - `dependabot cancel merge` will cancel a previously requested merge and block automerging - `dependabot reopen` will reopen this PR if it is closed - `dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/mapillary/OpenSfM/network/alerts).
Pull Request resolved: https://github.com/mapillary/OpenSfM/pull/999 Reviewed By: YanNoun Differential Revision: D46141368 Pulled By: fabianschenk fbshipit-source-id: 5fc816689e8107ecb91579a1e6f6fa81b30801f3 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 5b937b629..0d50b21ef 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ cloudpickle==0.4.0 exifread==2.1.2 -flask==2.1.2 +flask==2.3.2 fpdf2==2.4.6 joblib==0.14.1 matplotlib From a1f1959806039d1dfbd9436a95b1837360a7f9f1 Mon Sep 17 00:00:00 2001 From: kielnino Date: Wed, 24 May 2023 05:12:43 -0700 Subject: [PATCH 040/235] Plot_inliers / File adapted to changes in the whole project (#1001) Summary: The project was further developed without following the changes to the interfaces in this file. This PR now handles this. Pull Request resolved: https://github.com/mapillary/OpenSfM/pull/1001 Reviewed By: YanNoun Differential Revision: D46141342 Pulled By: fabianschenk fbshipit-source-id: a5db12aa4fe9abff8ae8ebcfa422572fc9e5f4da --- bin/plot_inliers | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/bin/plot_inliers b/bin/plot_inliers index b970318c7..3c6112e7e 100755 --- a/bin/plot_inliers +++ b/bin/plot_inliers @@ -128,7 +128,7 @@ def create_subplot(figure, rows, columns, index, title, x_lim, y_lim, font_size= subplot.set_aspect(aspect) if grid: - pl.grid(b=True, which='major', color='0.3') + pl.grid(visible=True, which='major', color='0.3') return subplot @@ -231,21 +231,21 @@ def reprojection_errors(reprojections, observations, scale): return errors, mean, std, min_norm, max_norm, corr -def triangulate_tracks(tracks, reconstruction, graph, min_ray_angle): +def triangulate_tracks(tracks, reconstruction, tracks_manager, min_ray_angle): """ Triangulates a list of tracks. :param tracks: The array of tracks. :param reconstruction: The reconstruction. - :param: graph, The tracks graph. + :param: tracks_manager, The tracks manager. :param: min_ray_angle: The minimum ray angle difference for a triangulation to be considered valid. :return: An array of booleans determining if each track was successfully triangulated or not. """ succeeded = [] - triangulator = reconstruct.TrackTriangulator(reconstruction, reconstruct.TrackHandlerTrackManager(graph, reconstruction) + triangulator = reconstruct.TrackTriangulator(reconstruction, reconstruct.TrackHandlerTrackManager(tracks_manager, reconstruction)) for track in tracks: # Triangulate with 1 as reprojection threshold to avoid excluding tracks because of error. - triangulator.triangulate(str(track), 1, min_ray_angle) + triangulator.triangulate(str(track), 1, min_ray_angle, iterations=10) succeeded.append(True) if str(track) in reconstruction.points else succeeded.append(False) return np.array(succeeded) if len(succeeded) else np.empty((0,), bool) @@ -319,8 +319,8 @@ def load_common_tracks(im1, im2, tracks_manager): :param tracks_manager: The track manager. :return: An array with rows containing a track id and the corresponding feature id for the first and second image. """ - t1 = tracks_manager.get_shot_observations(im1).items() - t2 = tracks_manager.get_shot_observations(im2).items() + t1 = tracks_manager.get_shot_observations(im1) + t2 = tracks_manager.get_shot_observations(im2) tc, p1, p2 = tracking.common_tracks(tracks_manager, im1, im2) common_tracks = [] @@ -417,7 +417,7 @@ def create_matches_figure(im1, im2, data, save_figs=False, single_column=False): p1 = features_data1.points p2 = features_data2.points - symmetric_matches = matching.match_brute_force_symmetric(f1, f2, data.config) + symmetric_matches = matching.match_brute_force_symmetric(p1, p2, data.config) symmetric_matches = np.array(symmetric_matches) if symmetric_matches.shape[0] < 8: @@ -519,7 +519,7 @@ def plot_opencv_find_homography(fw, ip, index, tracks, track_points1, track_poin threshold, pixels1, pixels2 = thresholds(ip.im1_array, ip.im2_array, 'homography_threshold', 0.004, data) H, inliers = cv2.findHomography(track_points1, track_points2, cv2.RANSAC, threshold) - inliers = np.array(np.squeeze(inliers), np.bool) + inliers = np.array(np.squeeze(inliers), bool) inliers1 = track_points1[inliers, :] inliers2 = track_points2[inliers, :] @@ -554,7 +554,7 @@ def plot_two_view_reconstruction(fw, ip, index, track_points1, track_points2, da threshold, pixels1, pixels2 = thresholds(ip.im1_array, ip.im2_array, 'five_point_algo_threshold', 0.006, data) iterations = data.config['five_point_refine_rec_iterations'] - R, t, inliers = reconstruct.two_view_reconstruction(track_points1, track_points2, camera1, camera2, threshold, iterations) + R, t, inliers, _ = reconstruct.two_view_reconstruction_general(track_points1, track_points2, camera1, camera2, threshold, iterations) inliers1 = track_points1[inliers, :] inliers2 = track_points2[inliers, :] @@ -573,7 +573,7 @@ def plot_two_view_reconstruction(fw, ip, index, track_points1, track_points2, da plot_matches(subplot, ip.im1_array, ip.im2_array, outliers1, outliers2, 'r', 'om') -def plot_bootstrapped_reconstruction(fw, ip, index, p1, p2, robust_tracks, linked_tracks, graph, data): +def plot_bootstrapped_reconstruction(fw, ip, index, p1, p2, robust_tracks, linked_tracks, tracks_manager, data): """ Plot successfully reconstructed and failed 3D points by bootstrapping a reconstruction. :param fw: Figure wrapper. @@ -583,13 +583,13 @@ def plot_bootstrapped_reconstruction(fw, ip, index, p1, p2, robust_tracks, linke :param p2: Feature points for the second image. :param robust_tracks: Tracks corresponding to robust matches. :param linked_tracks: Common tracks linked by other image correspondences. - :param graph: Tracks graph. + :param tracks_manager: The tracks manager. :param data: Data set. """ print_reset = redirect_print() - _, pm1, pm2 = tracking.common_tracks(graph, ip.im1, ip.im2) - reconstruction, _, _ = reconstruct.bootstrap_reconstruction(data, graph, ip.im1, ip.im2, pm1, pm2) + _, pm1, pm2 = tracking.common_tracks(tracks_manager, ip.im1, ip.im2) + reconstruction, _ = reconstruct.bootstrap_reconstruction(data, tracks_manager, ip.im1, ip.im2, pm1, pm2) reset_print(print_reset) threshold, pixels1, pixels2 = thresholds(ip.im1_array, ip.im2_array, 'triangulation_threshold', 0.004, data) @@ -667,7 +667,7 @@ def create_tracks_figure(im1, im2, data, save_figs=False, single_column=False): plot_common_tracks(fw, ip, 1, p1, p2, tracks, robust_tracks, linked_tracks, robust_matches) plot_opencv_find_homography(fw, ip, 2, tracks, track_points1, track_points2, data) plot_two_view_reconstruction(fw, ip, 3, track_points1, track_points2, data) - plot_bootstrapped_reconstruction(fw, ip, 4, p1, p2, robust_tracks, linked_tracks, graph, data) + plot_bootstrapped_reconstruction(fw, ip, 4, p1, p2, robust_tracks, linked_tracks, tracks_manager, data) display_figure(fig, save_figs, data, '{0}_{1}_{2}_tracks.jpg'.format(im1, im2, data.feature_type())) @@ -704,7 +704,7 @@ def plot_reconstructed_tracks(fw, ip, index, p1, p2, tracks, rec_tracks, non_rec plot_matches(subplot, ip.im1_array, ip.im2_array, non_rec_track_points1, non_rec_track_points2, 'r', 'om') -def plot_reprojected_tracks(fw, ip, index, p1, p2, tracks, rec_tracks, non_rec_tracks, reconstruction, graph, data): +def plot_reprojected_tracks(fw, ip, index, p1, p2, tracks, rec_tracks, non_rec_tracks, reconstruction, tracks_manager, data): """ Reprojects tracks included in and excluded from reconstruction and plots reprojections on top of observations. :param fw: Figure wrapper. @@ -716,7 +716,7 @@ def plot_reprojected_tracks(fw, ip, index, p1, p2, tracks, rec_tracks, non_rec_t :param rec_tracks: Common tracks included in the reconstruction. :param non_rec_tracks: Common tracks not included in the reconstruction. :param reconstruction: Reconstruction. - :param graph: Tracks graph. + :param tracks_manager: The tracks manager. :param data: Data set """ @@ -727,7 +727,7 @@ def plot_reprojected_tracks(fw, ip, index, p1, p2, tracks, rec_tracks, non_rec_t rp2 = reproject_tracks(ip.im2, rec_tracks[:, 0], reconstruction) min_ray_angle = data.config['triangulation_min_ray_angle'] - succeeded = triangulate_tracks(non_rec_tracks[:, 0], reconstruction, graph, min_ray_angle) + succeeded = triangulate_tracks(non_rec_tracks[:, 0], reconstruction, tracks_manager, min_ray_angle) reprojected1 = reproject_tracks(ip.im1, non_rec_tracks[succeeded, 0], reconstruction) reprojected2 = reproject_tracks(ip.im2, non_rec_tracks[succeeded, 0], reconstruction) @@ -786,7 +786,7 @@ def create_reconstruction_matches_figure(im1, im2, data, save_figs=False): rec_tracks, non_rec_tracks = reconstruction_tracks(tracks, reconstruction) plot_reconstructed_tracks(fw, ip, 1, p1, p2, tracks, rec_tracks, non_rec_tracks) - plot_reprojected_tracks(fw, ip, 2, p1, p2, tracks, rec_tracks, non_rec_tracks, reconstruction, graph, data) + plot_reprojected_tracks(fw, ip, 2, p1, p2, tracks, rec_tracks, non_rec_tracks, reconstruction, tracks_manager, data) display_figure(fig, save_figs, data, '{0}_{1}_{2}_reconstruction.jpg'.format(im1, im2, data.feature_type())) @@ -833,7 +833,7 @@ def create_complete_reconstruction_figure(im, data, save_figs=False, single_colu plot_points(rec_plot, im_array, rp, '+w') min_ray_angle = data.config['triangulation_min_ray_angle'] - succeeded = triangulate_tracks(non_rec_tracks[:, 0], reconstruction, graph, min_ray_angle) + succeeded = triangulate_tracks(non_rec_tracks[:, 0], reconstruction, tracks_manager, min_ray_angle) reprojected = reproject_tracks(im, non_rec_tracks[succeeded, 0], reconstruction) triangulated_points = p[non_rec_tracks[succeeded, 1]] @@ -887,7 +887,7 @@ def create_reprojection_error_figure(im, data, save_figs=False, single_column=Fa reproj_rec = reproject_tracks(im, rec_tracks[:, 0], reconstruction) min_ray_angle = data.config['triangulation_min_ray_angle'] - succeeded = triangulate_tracks(non_rec_tracks[:, 0], reconstruction, graph, min_ray_angle) + succeeded = triangulate_tracks(non_rec_tracks[:, 0], reconstruction, tracks_manager, min_ray_angle) reproj_non = reproject_tracks(im, non_rec_tracks[succeeded, 0], reconstruction) triang_non = p[non_rec_tracks[succeeded, 1]] @@ -897,7 +897,7 @@ def create_reprojection_error_figure(im, data, save_figs=False, single_column=Fa non_errors, non_mean, non_std, non_min, non_max, non_corr = reprojection_errors(reproj_non, triang_non, scale) triang_thld = data.config['triangulation_threshold'] - bundle_thld = data.config['bundle_outlier_threshold'] + bundle_thld = data.config['bundle_outlier_fixed_threshold'] axis_max = np.max(np.abs(np.vstack((rec_errors, non_errors)))) axis_max = 1.05 * np.max([axis_max, scale * triang_thld, scale * bundle_thld]) From f2df6febb4994c81c2d7fe5db0deb48e7c0d6a67 Mon Sep 17 00:00:00 2001 From: Fabian Schenk Date: Tue, 18 Jul 2023 09:10:33 -0700 Subject: [PATCH 041/235] Update jquery version Summary: TSIA Reviewed By: oscarlorentzon Differential Revision: D47542023 fbshipit-source-id: 04f01aa9c76a234e6d4712d8a48050804c477d97 --- viewer/legacy/js/jquery.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/viewer/legacy/js/jquery.js b/viewer/legacy/js/jquery.js index 45477c0b6..c4c6022f2 100644 --- a/viewer/legacy/js/jquery.js +++ b/viewer/legacy/js/jquery.js @@ -1,2 +1,2 @@ -/*! jQuery v1.8.3 jquery.com | jquery.org/license */ -(function(e,t){function _(e){var t=M[e]={};return v.each(e.split(y),function(e,n){t[n]=!0}),t}function H(e,n,r){if(r===t&&e.nodeType===1){var i="data-"+n.replace(P,"-$1").toLowerCase();r=e.getAttribute(i);if(typeof r=="string"){try{r=r==="true"?!0:r==="false"?!1:r==="null"?null:+r+""===r?+r:D.test(r)?v.parseJSON(r):r}catch(s){}v.data(e,n,r)}else r=t}return r}function B(e){var t;for(t in e){if(t==="data"&&v.isEmptyObject(e[t]))continue;if(t!=="toJSON")return!1}return!0}function et(){return!1}function tt(){return!0}function ut(e){return!e||!e.parentNode||e.parentNode.nodeType===11}function at(e,t){do e=e[t];while(e&&e.nodeType!==1);return e}function ft(e,t,n){t=t||0;if(v.isFunction(t))return v.grep(e,function(e,r){var i=!!t.call(e,r,e);return i===n});if(t.nodeType)return v.grep(e,function(e,r){return e===t===n});if(typeof t=="string"){var r=v.grep(e,function(e){return e.nodeType===1});if(it.test(t))return v.filter(t,r,!n);t=v.filter(t,r)}return v.grep(e,function(e,r){return v.inArray(e,t)>=0===n})}function lt(e){var t=ct.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}function Lt(e,t){return e.getElementsByTagName(t)[0]||e.appendChild(e.ownerDocument.createElement(t))}function At(e,t){if(t.nodeType!==1||!v.hasData(e))return;var n,r,i,s=v._data(e),o=v._data(t,s),u=s.events;if(u){delete o.handle,o.events={};for(n in u)for(r=0,i=u[n].length;r").appendTo(i.body),n=t.css("display");t.remove();if(n==="none"||n===""){Pt=i.body.appendChild(Pt||v.extend(i.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!Ht||!Pt.createElement)Ht=(Pt.contentWindow||Pt.contentDocument).document,Ht.write(""),Ht.close();t=Ht.body.appendChild(Ht.createElement(e)),n=Dt(t,"display"),i.body.removeChild(Pt)}return Wt[e]=n,n}function fn(e,t,n,r){var i;if(v.isArray(t))v.each(t,function(t,i){n||sn.test(e)?r(e,i):fn(e+"["+(typeof i=="object"?t:"")+"]",i,n,r)});else if(!n&&v.type(t)==="object")for(i in t)fn(e+"["+i+"]",t[i],n,r);else r(e,t)}function Cn(e){return function(t,n){typeof t!="string"&&(n=t,t="*");var r,i,s,o=t.toLowerCase().split(y),u=0,a=o.length;if(v.isFunction(n))for(;u)[^>]*$|#([\w\-]*)$)/,E=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,S=/^[\],:{}\s]*$/,x=/(?:^|:|,)(?:\s*\[)+/g,T=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,N=/"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,C=/^-ms-/,k=/-([\da-z])/gi,L=function(e,t){return(t+"").toUpperCase()},A=function(){i.addEventListener?(i.removeEventListener("DOMContentLoaded",A,!1),v.ready()):i.readyState==="complete"&&(i.detachEvent("onreadystatechange",A),v.ready())},O={};v.fn=v.prototype={constructor:v,init:function(e,n,r){var s,o,u,a;if(!e)return this;if(e.nodeType)return this.context=this[0]=e,this.length=1,this;if(typeof e=="string"){e.charAt(0)==="<"&&e.charAt(e.length-1)===">"&&e.length>=3?s=[null,e,null]:s=w.exec(e);if(s&&(s[1]||!n)){if(s[1])return n=n instanceof v?n[0]:n,a=n&&n.nodeType?n.ownerDocument||n:i,e=v.parseHTML(s[1],a,!0),E.test(s[1])&&v.isPlainObject(n)&&this.attr.call(e,n,!0),v.merge(this,e);o=i.getElementById(s[2]);if(o&&o.parentNode){if(o.id!==s[2])return r.find(e);this.length=1,this[0]=o}return this.context=i,this.selector=e,this}return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e)}return v.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),v.makeArray(e,this))},selector:"",jquery:"1.8.3",length:0,size:function(){return this.length},toArray:function(){return l.call(this)},get:function(e){return e==null?this.toArray():e<0?this[this.length+e]:this[e]},pushStack:function(e,t,n){var r=v.merge(this.constructor(),e);return r.prevObject=this,r.context=this.context,t==="find"?r.selector=this.selector+(this.selector?" ":"")+n:t&&(r.selector=this.selector+"."+t+"("+n+")"),r},each:function(e,t){return v.each(this,e,t)},ready:function(e){return v.ready.promise().done(e),this},eq:function(e){return e=+e,e===-1?this.slice(e):this.slice(e,e+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(l.apply(this,arguments),"slice",l.call(arguments).join(","))},map:function(e){return this.pushStack(v.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:[].sort,splice:[].splice},v.fn.init.prototype=v.fn,v.extend=v.fn.extend=function(){var e,n,r,i,s,o,u=arguments[0]||{},a=1,f=arguments.length,l=!1;typeof u=="boolean"&&(l=u,u=arguments[1]||{},a=2),typeof u!="object"&&!v.isFunction(u)&&(u={}),f===a&&(u=this,--a);for(;a0)return;r.resolveWith(i,[v]),v.fn.trigger&&v(i).trigger("ready").off("ready")},isFunction:function(e){return v.type(e)==="function"},isArray:Array.isArray||function(e){return v.type(e)==="array"},isWindow:function(e){return e!=null&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return e==null?String(e):O[h.call(e)]||"object"},isPlainObject:function(e){if(!e||v.type(e)!=="object"||e.nodeType||v.isWindow(e))return!1;try{if(e.constructor&&!p.call(e,"constructor")&&!p.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(n){return!1}var r;for(r in e);return r===t||p.call(e,r)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw new Error(e)},parseHTML:function(e,t,n){var r;return!e||typeof e!="string"?null:(typeof t=="boolean"&&(n=t,t=0),t=t||i,(r=E.exec(e))?[t.createElement(r[1])]:(r=v.buildFragment([e],t,n?null:[]),v.merge([],(r.cacheable?v.clone(r.fragment):r.fragment).childNodes)))},parseJSON:function(t){if(!t||typeof t!="string")return null;t=v.trim(t);if(e.JSON&&e.JSON.parse)return e.JSON.parse(t);if(S.test(t.replace(T,"@").replace(N,"]").replace(x,"")))return(new Function("return "+t))();v.error("Invalid JSON: "+t)},parseXML:function(n){var r,i;if(!n||typeof n!="string")return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,"text/xml")):(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(n))}catch(s){r=t}return(!r||!r.documentElement||r.getElementsByTagName("parsererror").length)&&v.error("Invalid XML: "+n),r},noop:function(){},globalEval:function(t){t&&g.test(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(C,"ms-").replace(k,L)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,n,r){var i,s=0,o=e.length,u=o===t||v.isFunction(e);if(r){if(u){for(i in e)if(n.apply(e[i],r)===!1)break}else for(;s0&&e[0]&&e[a-1]||a===0||v.isArray(e));if(f)for(;u-1)a.splice(n,1),i&&(n<=o&&o--,n<=u&&u--)}),this},has:function(e){return v.inArray(e,a)>-1},empty:function(){return a=[],this},disable:function(){return a=f=n=t,this},disabled:function(){return!a},lock:function(){return f=t,n||c.disable(),this},locked:function(){return!f},fireWith:function(e,t){return t=t||[],t=[e,t.slice?t.slice():t],a&&(!r||f)&&(i?f.push(t):l(t)),this},fire:function(){return c.fireWith(this,arguments),this},fired:function(){return!!r}};return c},v.extend({Deferred:function(e){var t=[["resolve","done",v.Callbacks("once memory"),"resolved"],["reject","fail",v.Callbacks("once memory"),"rejected"],["notify","progress",v.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return v.Deferred(function(n){v.each(t,function(t,r){var s=r[0],o=e[t];i[r[1]](v.isFunction(o)?function(){var e=o.apply(this,arguments);e&&v.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[s+"With"](this===i?n:this,[e])}:n[s])}),e=null}).promise()},promise:function(e){return e!=null?v.extend(e,r):r}},i={};return r.pipe=r.then,v.each(t,function(e,s){var o=s[2],u=s[3];r[s[1]]=o.add,u&&o.add(function(){n=u},t[e^1][2].disable,t[2][2].lock),i[s[0]]=o.fire,i[s[0]+"With"]=o.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=l.call(arguments),r=n.length,i=r!==1||e&&v.isFunction(e.promise)?r:0,s=i===1?e:v.Deferred(),o=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?l.call(arguments):r,n===u?s.notifyWith(t,n):--i||s.resolveWith(t,n)}},u,a,f;if(r>1){u=new Array(r),a=new Array(r),f=new Array(r);for(;t
a",n=p.getElementsByTagName("*"),r=p.getElementsByTagName("a")[0];if(!n||!r||!n.length)return{};s=i.createElement("select"),o=s.appendChild(i.createElement("option")),u=p.getElementsByTagName("input")[0],r.style.cssText="top:1px;float:left;opacity:.5",t={leadingWhitespace:p.firstChild.nodeType===3,tbody:!p.getElementsByTagName("tbody").length,htmlSerialize:!!p.getElementsByTagName("link").length,style:/top/.test(r.getAttribute("style")),hrefNormalized:r.getAttribute("href")==="/a",opacity:/^0.5/.test(r.style.opacity),cssFloat:!!r.style.cssFloat,checkOn:u.value==="on",optSelected:o.selected,getSetAttribute:p.className!=="t",enctype:!!i.createElement("form").enctype,html5Clone:i.createElement("nav").cloneNode(!0).outerHTML!=="<:nav>",boxModel:i.compatMode==="CSS1Compat",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},u.checked=!0,t.noCloneChecked=u.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!o.disabled;try{delete p.test}catch(d){t.deleteExpando=!1}!p.addEventListener&&p.attachEvent&&p.fireEvent&&(p.attachEvent("onclick",h=function(){t.noCloneEvent=!1}),p.cloneNode(!0).fireEvent("onclick"),p.detachEvent("onclick",h)),u=i.createElement("input"),u.value="t",u.setAttribute("type","radio"),t.radioValue=u.value==="t",u.setAttribute("checked","checked"),u.setAttribute("name","t"),p.appendChild(u),a=i.createDocumentFragment(),a.appendChild(p.lastChild),t.checkClone=a.cloneNode(!0).cloneNode(!0).lastChild.checked,t.appendChecked=u.checked,a.removeChild(u),a.appendChild(p);if(p.attachEvent)for(l in{submit:!0,change:!0,focusin:!0})f="on"+l,c=f in p,c||(p.setAttribute(f,"return;"),c=typeof p[f]=="function"),t[l+"Bubbles"]=c;return v(function(){var n,r,s,o,u="padding:0;margin:0;border:0;display:block;overflow:hidden;",a=i.getElementsByTagName("body")[0];if(!a)return;n=i.createElement("div"),n.style.cssText="visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px",a.insertBefore(n,a.firstChild),r=i.createElement("div"),n.appendChild(r),r.innerHTML="
t
",s=r.getElementsByTagName("td"),s[0].style.cssText="padding:0;margin:0;border:0;display:none",c=s[0].offsetHeight===0,s[0].style.display="",s[1].style.display="none",t.reliableHiddenOffsets=c&&s[0].offsetHeight===0,r.innerHTML="",r.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",t.boxSizing=r.offsetWidth===4,t.doesNotIncludeMarginInBodyOffset=a.offsetTop!==1,e.getComputedStyle&&(t.pixelPosition=(e.getComputedStyle(r,null)||{}).top!=="1%",t.boxSizingReliable=(e.getComputedStyle(r,null)||{width:"4px"}).width==="4px",o=i.createElement("div"),o.style.cssText=r.style.cssText=u,o.style.marginRight=o.style.width="0",r.style.width="1px",r.appendChild(o),t.reliableMarginRight=!parseFloat((e.getComputedStyle(o,null)||{}).marginRight)),typeof r.style.zoom!="undefined"&&(r.innerHTML="",r.style.cssText=u+"width:1px;padding:1px;display:inline;zoom:1",t.inlineBlockNeedsLayout=r.offsetWidth===3,r.style.display="block",r.style.overflow="visible",r.innerHTML="
",r.firstChild.style.width="5px",t.shrinkWrapBlocks=r.offsetWidth!==3,n.style.zoom=1),a.removeChild(n),n=r=s=o=null}),a.removeChild(p),n=r=s=o=u=a=p=null,t}();var D=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,P=/([A-Z])/g;v.extend({cache:{},deletedIds:[],uuid:0,expando:"jQuery"+(v.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(e){return e=e.nodeType?v.cache[e[v.expando]]:e[v.expando],!!e&&!B(e)},data:function(e,n,r,i){if(!v.acceptData(e))return;var s,o,u=v.expando,a=typeof n=="string",f=e.nodeType,l=f?v.cache:e,c=f?e[u]:e[u]&&u;if((!c||!l[c]||!i&&!l[c].data)&&a&&r===t)return;c||(f?e[u]=c=v.deletedIds.pop()||v.guid++:c=u),l[c]||(l[c]={},f||(l[c].toJSON=v.noop));if(typeof n=="object"||typeof n=="function")i?l[c]=v.extend(l[c],n):l[c].data=v.extend(l[c].data,n);return s=l[c],i||(s.data||(s.data={}),s=s.data),r!==t&&(s[v.camelCase(n)]=r),a?(o=s[n],o==null&&(o=s[v.camelCase(n)])):o=s,o},removeData:function(e,t,n){if(!v.acceptData(e))return;var r,i,s,o=e.nodeType,u=o?v.cache:e,a=o?e[v.expando]:v.expando;if(!u[a])return;if(t){r=n?u[a]:u[a].data;if(r){v.isArray(t)||(t in r?t=[t]:(t=v.camelCase(t),t in r?t=[t]:t=t.split(" ")));for(i=0,s=t.length;i1,null,!1))},removeData:function(e){return this.each(function(){v.removeData(this,e)})}}),v.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=v._data(e,t),n&&(!r||v.isArray(n)?r=v._data(e,t,v.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=v.queue(e,t),r=n.length,i=n.shift(),s=v._queueHooks(e,t),o=function(){v.dequeue(e,t)};i==="inprogress"&&(i=n.shift(),r--),i&&(t==="fx"&&n.unshift("inprogress"),delete s.stop,i.call(e,o,s)),!r&&s&&s.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return v._data(e,n)||v._data(e,n,{empty:v.Callbacks("once memory").add(function(){v.removeData(e,t+"queue",!0),v.removeData(e,n,!0)})})}}),v.fn.extend({queue:function(e,n){var r=2;return typeof e!="string"&&(n=e,e="fx",r--),arguments.length1)},removeAttr:function(e){return this.each(function(){v.removeAttr(this,e)})},prop:function(e,t){return v.access(this,v.prop,e,t,arguments.length>1)},removeProp:function(e){return e=v.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,s,o,u;if(v.isFunction(e))return this.each(function(t){v(this).addClass(e.call(this,t,this.className))});if(e&&typeof e=="string"){t=e.split(y);for(n=0,r=this.length;n=0)r=r.replace(" "+n[s]+" "," ");i.className=e?v.trim(r):""}}}return this},toggleClass:function(e,t){var n=typeof e,r=typeof t=="boolean";return v.isFunction(e)?this.each(function(n){v(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if(n==="string"){var i,s=0,o=v(this),u=t,a=e.split(y);while(i=a[s++])u=r?u:!o.hasClass(i),o[u?"addClass":"removeClass"](i)}else if(n==="undefined"||n==="boolean")this.className&&v._data(this,"__className__",this.className),this.className=this.className||e===!1?"":v._data(this,"__className__")||""})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;n=0)return!0;return!1},val:function(e){var n,r,i,s=this[0];if(!arguments.length){if(s)return n=v.valHooks[s.type]||v.valHooks[s.nodeName.toLowerCase()],n&&"get"in n&&(r=n.get(s,"value"))!==t?r:(r=s.value,typeof r=="string"?r.replace(R,""):r==null?"":r);return}return i=v.isFunction(e),this.each(function(r){var s,o=v(this);if(this.nodeType!==1)return;i?s=e.call(this,r,o.val()):s=e,s==null?s="":typeof s=="number"?s+="":v.isArray(s)&&(s=v.map(s,function(e){return e==null?"":e+""})),n=v.valHooks[this.type]||v.valHooks[this.nodeName.toLowerCase()];if(!n||!("set"in n)||n.set(this,s,"value")===t)this.value=s})}}),v.extend({valHooks:{option:{get:function(e){var t=e.attributes.value;return!t||t.specified?e.value:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,s=e.type==="select-one"||i<0,o=s?null:[],u=s?i+1:r.length,a=i<0?u:s?i:0;for(;a=0}),n.length||(e.selectedIndex=-1),n}}},attrFn:{},attr:function(e,n,r,i){var s,o,u,a=e.nodeType;if(!e||a===3||a===8||a===2)return;if(i&&v.isFunction(v.fn[n]))return v(e)[n](r);if(typeof e.getAttribute=="undefined")return v.prop(e,n,r);u=a!==1||!v.isXMLDoc(e),u&&(n=n.toLowerCase(),o=v.attrHooks[n]||(X.test(n)?F:j));if(r!==t){if(r===null){v.removeAttr(e,n);return}return o&&"set"in o&&u&&(s=o.set(e,r,n))!==t?s:(e.setAttribute(n,r+""),r)}return o&&"get"in o&&u&&(s=o.get(e,n))!==null?s:(s=e.getAttribute(n),s===null?t:s)},removeAttr:function(e,t){var n,r,i,s,o=0;if(t&&e.nodeType===1){r=t.split(y);for(;o=0}})});var $=/^(?:textarea|input|select)$/i,J=/^([^\.]*|)(?:\.(.+)|)$/,K=/(?:^|\s)hover(\.\S+|)\b/,Q=/^key/,G=/^(?:mouse|contextmenu)|click/,Y=/^(?:focusinfocus|focusoutblur)$/,Z=function(e){return v.event.special.hover?e:e.replace(K,"mouseenter$1 mouseleave$1")};v.event={add:function(e,n,r,i,s){var o,u,a,f,l,c,h,p,d,m,g;if(e.nodeType===3||e.nodeType===8||!n||!r||!(o=v._data(e)))return;r.handler&&(d=r,r=d.handler,s=d.selector),r.guid||(r.guid=v.guid++),a=o.events,a||(o.events=a={}),u=o.handle,u||(o.handle=u=function(e){return typeof v=="undefined"||!!e&&v.event.triggered===e.type?t:v.event.dispatch.apply(u.elem,arguments)},u.elem=e),n=v.trim(Z(n)).split(" ");for(f=0;f=0&&(y=y.slice(0,-1),a=!0),y.indexOf(".")>=0&&(b=y.split("."),y=b.shift(),b.sort());if((!s||v.event.customEvent[y])&&!v.event.global[y])return;n=typeof n=="object"?n[v.expando]?n:new v.Event(y,n):new v.Event(y),n.type=y,n.isTrigger=!0,n.exclusive=a,n.namespace=b.join("."),n.namespace_re=n.namespace?new RegExp("(^|\\.)"+b.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,h=y.indexOf(":")<0?"on"+y:"";if(!s){u=v.cache;for(f in u)u[f].events&&u[f].events[y]&&v.event.trigger(n,r,u[f].handle.elem,!0);return}n.result=t,n.target||(n.target=s),r=r!=null?v.makeArray(r):[],r.unshift(n),p=v.event.special[y]||{};if(p.trigger&&p.trigger.apply(s,r)===!1)return;m=[[s,p.bindType||y]];if(!o&&!p.noBubble&&!v.isWindow(s)){g=p.delegateType||y,l=Y.test(g+y)?s:s.parentNode;for(c=s;l;l=l.parentNode)m.push([l,g]),c=l;c===(s.ownerDocument||i)&&m.push([c.defaultView||c.parentWindow||e,g])}for(f=0;f=0:v.find(h,this,null,[s]).length),u[h]&&f.push(c);f.length&&w.push({elem:s,matches:f})}d.length>m&&w.push({elem:this,matches:d.slice(m)});for(r=0;r0?this.on(t,null,e,n):this.trigger(t)},Q.test(t)&&(v.event.fixHooks[t]=v.event.keyHooks),G.test(t)&&(v.event.fixHooks[t]=v.event.mouseHooks)}),function(e,t){function nt(e,t,n,r){n=n||[],t=t||g;var i,s,a,f,l=t.nodeType;if(!e||typeof e!="string")return n;if(l!==1&&l!==9)return[];a=o(t);if(!a&&!r)if(i=R.exec(e))if(f=i[1]){if(l===9){s=t.getElementById(f);if(!s||!s.parentNode)return n;if(s.id===f)return n.push(s),n}else if(t.ownerDocument&&(s=t.ownerDocument.getElementById(f))&&u(t,s)&&s.id===f)return n.push(s),n}else{if(i[2])return S.apply(n,x.call(t.getElementsByTagName(e),0)),n;if((f=i[3])&&Z&&t.getElementsByClassName)return S.apply(n,x.call(t.getElementsByClassName(f),0)),n}return vt(e.replace(j,"$1"),t,n,r,a)}function rt(e){return function(t){var n=t.nodeName.toLowerCase();return n==="input"&&t.type===e}}function it(e){return function(t){var n=t.nodeName.toLowerCase();return(n==="input"||n==="button")&&t.type===e}}function st(e){return N(function(t){return t=+t,N(function(n,r){var i,s=e([],n.length,t),o=s.length;while(o--)n[i=s[o]]&&(n[i]=!(r[i]=n[i]))})})}function ot(e,t,n){if(e===t)return n;var r=e.nextSibling;while(r){if(r===t)return-1;r=r.nextSibling}return 1}function ut(e,t){var n,r,s,o,u,a,f,l=L[d][e+" "];if(l)return t?0:l.slice(0);u=e,a=[],f=i.preFilter;while(u){if(!n||(r=F.exec(u)))r&&(u=u.slice(r[0].length)||u),a.push(s=[]);n=!1;if(r=I.exec(u))s.push(n=new m(r.shift())),u=u.slice(n.length),n.type=r[0].replace(j," ");for(o in i.filter)(r=J[o].exec(u))&&(!f[o]||(r=f[o](r)))&&(s.push(n=new m(r.shift())),u=u.slice(n.length),n.type=o,n.matches=r);if(!n)break}return t?u.length:u?nt.error(e):L(e,a).slice(0)}function at(e,t,r){var i=t.dir,s=r&&t.dir==="parentNode",o=w++;return t.first?function(t,n,r){while(t=t[i])if(s||t.nodeType===1)return e(t,n,r)}:function(t,r,u){if(!u){var a,f=b+" "+o+" ",l=f+n;while(t=t[i])if(s||t.nodeType===1){if((a=t[d])===l)return t.sizset;if(typeof a=="string"&&a.indexOf(f)===0){if(t.sizset)return t}else{t[d]=l;if(e(t,r,u))return t.sizset=!0,t;t.sizset=!1}}}else while(t=t[i])if(s||t.nodeType===1)if(e(t,r,u))return t}}function ft(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function lt(e,t,n,r,i){var s,o=[],u=0,a=e.length,f=t!=null;for(;u-1&&(s[f]=!(o[f]=c))}}else g=lt(g===o?g.splice(d,g.length):g),i?i(null,o,g,a):S.apply(o,g)})}function ht(e){var t,n,r,s=e.length,o=i.relative[e[0].type],u=o||i.relative[" "],a=o?1:0,f=at(function(e){return e===t},u,!0),l=at(function(e){return T.call(t,e)>-1},u,!0),h=[function(e,n,r){return!o&&(r||n!==c)||((t=n).nodeType?f(e,n,r):l(e,n,r))}];for(;a1&&ft(h),a>1&&e.slice(0,a-1).join("").replace(j,"$1"),n,a0,s=e.length>0,o=function(u,a,f,l,h){var p,d,v,m=[],y=0,w="0",x=u&&[],T=h!=null,N=c,C=u||s&&i.find.TAG("*",h&&a.parentNode||a),k=b+=N==null?1:Math.E;T&&(c=a!==g&&a,n=o.el);for(;(p=C[w])!=null;w++){if(s&&p){for(d=0;v=e[d];d++)if(v(p,a,f)){l.push(p);break}T&&(b=k,n=++o.el)}r&&((p=!v&&p)&&y--,u&&x.push(p))}y+=w;if(r&&w!==y){for(d=0;v=t[d];d++)v(x,m,a,f);if(u){if(y>0)while(w--)!x[w]&&!m[w]&&(m[w]=E.call(l));m=lt(m)}S.apply(l,m),T&&!u&&m.length>0&&y+t.length>1&&nt.uniqueSort(l)}return T&&(b=k,c=N),x};return o.el=0,r?N(o):o}function dt(e,t,n){var r=0,i=t.length;for(;r2&&(f=u[0]).type==="ID"&&t.nodeType===9&&!s&&i.relative[u[1].type]){t=i.find.ID(f.matches[0].replace($,""),t,s)[0];if(!t)return n;e=e.slice(u.shift().length)}for(o=J.POS.test(e)?-1:u.length-1;o>=0;o--){f=u[o];if(i.relative[l=f.type])break;if(c=i.find[l])if(r=c(f.matches[0].replace($,""),z.test(u[0].type)&&t.parentNode||t,s)){u.splice(o,1),e=r.length&&u.join("");if(!e)return S.apply(n,x.call(r,0)),n;break}}}return a(e,h)(r,t,s,n,z.test(e)),n}function mt(){}var n,r,i,s,o,u,a,f,l,c,h=!0,p="undefined",d=("sizcache"+Math.random()).replace(".",""),m=String,g=e.document,y=g.documentElement,b=0,w=0,E=[].pop,S=[].push,x=[].slice,T=[].indexOf||function(e){var t=0,n=this.length;for(;ti.cacheLength&&delete e[t.shift()],e[n+" "]=r},e)},k=C(),L=C(),A=C(),O="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",_=M.replace("w","w#"),D="([*^$|!~]?=)",P="\\["+O+"*("+M+")"+O+"*(?:"+D+O+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+_+")|)|)"+O+"*\\]",H=":("+M+")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:"+P+")|[^:]|\\\\.)*|.*))\\)|)",B=":(even|odd|eq|gt|lt|nth|first|last)(?:\\("+O+"*((?:-\\d)?\\d*)"+O+"*\\)|)(?=[^-]|$)",j=new RegExp("^"+O+"+|((?:^|[^\\\\])(?:\\\\.)*)"+O+"+$","g"),F=new RegExp("^"+O+"*,"+O+"*"),I=new RegExp("^"+O+"*([\\x20\\t\\r\\n\\f>+~])"+O+"*"),q=new RegExp(H),R=/^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,U=/^:not/,z=/[\x20\t\r\n\f]*[+~]/,W=/:not\($/,X=/h\d/i,V=/input|select|textarea|button/i,$=/\\(?!\\)/g,J={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),NAME:new RegExp("^\\[name=['\"]?("+M+")['\"]?\\]"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+P),PSEUDO:new RegExp("^"+H),POS:new RegExp(B,"i"),CHILD:new RegExp("^:(only|nth|first|last)-child(?:\\("+O+"*(even|odd|(([+-]|)(\\d*)n|)"+O+"*(?:([+-]|)"+O+"*(\\d+)|))"+O+"*\\)|)","i"),needsContext:new RegExp("^"+O+"*[>+~]|"+B,"i")},K=function(e){var t=g.createElement("div");try{return e(t)}catch(n){return!1}finally{t=null}},Q=K(function(e){return e.appendChild(g.createComment("")),!e.getElementsByTagName("*").length}),G=K(function(e){return e.innerHTML="",e.firstChild&&typeof e.firstChild.getAttribute!==p&&e.firstChild.getAttribute("href")==="#"}),Y=K(function(e){e.innerHTML="";var t=typeof e.lastChild.getAttribute("multiple");return t!=="boolean"&&t!=="string"}),Z=K(function(e){return e.innerHTML="",!e.getElementsByClassName||!e.getElementsByClassName("e").length?!1:(e.lastChild.className="e",e.getElementsByClassName("e").length===2)}),et=K(function(e){e.id=d+0,e.innerHTML="
",y.insertBefore(e,y.firstChild);var t=g.getElementsByName&&g.getElementsByName(d).length===2+g.getElementsByName(d+0).length;return r=!g.getElementById(d),y.removeChild(e),t});try{x.call(y.childNodes,0)[0].nodeType}catch(tt){x=function(e){var t,n=[];for(;t=this[e];e++)n.push(t);return n}}nt.matches=function(e,t){return nt(e,null,null,t)},nt.matchesSelector=function(e,t){return nt(t,null,null,[e]).length>0},s=nt.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(i===1||i===9||i===11){if(typeof e.textContent=="string")return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=s(e)}else if(i===3||i===4)return e.nodeValue}else for(;t=e[r];r++)n+=s(t);return n},o=nt.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?t.nodeName!=="HTML":!1},u=nt.contains=y.contains?function(e,t){var n=e.nodeType===9?e.documentElement:e,r=t&&t.parentNode;return e===r||!!(r&&r.nodeType===1&&n.contains&&n.contains(r))}:y.compareDocumentPosition?function(e,t){return t&&!!(e.compareDocumentPosition(t)&16)}:function(e,t){while(t=t.parentNode)if(t===e)return!0;return!1},nt.attr=function(e,t){var n,r=o(e);return r||(t=t.toLowerCase()),(n=i.attrHandle[t])?n(e):r||Y?e.getAttribute(t):(n=e.getAttributeNode(t),n?typeof e[t]=="boolean"?e[t]?t:null:n.specified?n.value:null:null)},i=nt.selectors={cacheLength:50,createPseudo:N,match:J,attrHandle:G?{}:{href:function(e){return e.getAttribute("href",2)},type:function(e){return e.getAttribute("type")}},find:{ID:r?function(e,t,n){if(typeof t.getElementById!==p&&!n){var r=t.getElementById(e);return r&&r.parentNode?[r]:[]}}:function(e,n,r){if(typeof n.getElementById!==p&&!r){var i=n.getElementById(e);return i?i.id===e||typeof i.getAttributeNode!==p&&i.getAttributeNode("id").value===e?[i]:t:[]}},TAG:Q?function(e,t){if(typeof t.getElementsByTagName!==p)return t.getElementsByTagName(e)}:function(e,t){var n=t.getElementsByTagName(e);if(e==="*"){var r,i=[],s=0;for(;r=n[s];s++)r.nodeType===1&&i.push(r);return i}return n},NAME:et&&function(e,t){if(typeof t.getElementsByName!==p)return t.getElementsByName(name)},CLASS:Z&&function(e,t,n){if(typeof t.getElementsByClassName!==p&&!n)return t.getElementsByClassName(e)}},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace($,""),e[3]=(e[4]||e[5]||"").replace($,""),e[2]==="~="&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),e[1]==="nth"?(e[2]||nt.error(e[0]),e[3]=+(e[3]?e[4]+(e[5]||1):2*(e[2]==="even"||e[2]==="odd")),e[4]=+(e[6]+e[7]||e[2]==="odd")):e[2]&&nt.error(e[0]),e},PSEUDO:function(e){var t,n;if(J.CHILD.test(e[0]))return null;if(e[3])e[2]=e[3];else if(t=e[4])q.test(t)&&(n=ut(t,!0))&&(n=t.indexOf(")",t.length-n)-t.length)&&(t=t.slice(0,n),e[0]=e[0].slice(0,n)),e[2]=t;return e.slice(0,3)}},filter:{ID:r?function(e){return e=e.replace($,""),function(t){return t.getAttribute("id")===e}}:function(e){return e=e.replace($,""),function(t){var n=typeof t.getAttributeNode!==p&&t.getAttributeNode("id");return n&&n.value===e}},TAG:function(e){return e==="*"?function(){return!0}:(e=e.replace($,"").toLowerCase(),function(t){return t.nodeName&&t.nodeName.toLowerCase()===e})},CLASS:function(e){var t=k[d][e+" "];return t||(t=new RegExp("(^|"+O+")"+e+"("+O+"|$)"))&&k(e,function(e){return t.test(e.className||typeof e.getAttribute!==p&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r,i){var s=nt.attr(r,e);return s==null?t==="!=":t?(s+="",t==="="?s===n:t==="!="?s!==n:t==="^="?n&&s.indexOf(n)===0:t==="*="?n&&s.indexOf(n)>-1:t==="$="?n&&s.substr(s.length-n.length)===n:t==="~="?(" "+s+" ").indexOf(n)>-1:t==="|="?s===n||s.substr(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r){return e==="nth"?function(e){var t,i,s=e.parentNode;if(n===1&&r===0)return!0;if(s){i=0;for(t=s.firstChild;t;t=t.nextSibling)if(t.nodeType===1){i++;if(e===t)break}}return i-=r,i===n||i%n===0&&i/n>=0}:function(t){var n=t;switch(e){case"only":case"first":while(n=n.previousSibling)if(n.nodeType===1)return!1;if(e==="first")return!0;n=t;case"last":while(n=n.nextSibling)if(n.nodeType===1)return!1;return!0}}},PSEUDO:function(e,t){var n,r=i.pseudos[e]||i.setFilters[e.toLowerCase()]||nt.error("unsupported pseudo: "+e);return r[d]?r(t):r.length>1?(n=[e,e,"",t],i.setFilters.hasOwnProperty(e.toLowerCase())?N(function(e,n){var i,s=r(e,t),o=s.length;while(o--)i=T.call(e,s[o]),e[i]=!(n[i]=s[o])}):function(e){return r(e,0,n)}):r}},pseudos:{not:N(function(e){var t=[],n=[],r=a(e.replace(j,"$1"));return r[d]?N(function(e,t,n,i){var s,o=r(e,null,i,[]),u=e.length;while(u--)if(s=o[u])e[u]=!(t[u]=s)}):function(e,i,s){return t[0]=e,r(t,null,s,n),!n.pop()}}),has:N(function(e){return function(t){return nt(e,t).length>0}}),contains:N(function(e){return function(t){return(t.textContent||t.innerText||s(t)).indexOf(e)>-1}}),enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return t==="input"&&!!e.checked||t==="option"&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},parent:function(e){return!i.pseudos.empty(e)},empty:function(e){var t;e=e.firstChild;while(e){if(e.nodeName>"@"||(t=e.nodeType)===3||t===4)return!1;e=e.nextSibling}return!0},header:function(e){return X.test(e.nodeName)},text:function(e){var t,n;return e.nodeName.toLowerCase()==="input"&&(t=e.type)==="text"&&((n=e.getAttribute("type"))==null||n.toLowerCase()===t)},radio:rt("radio"),checkbox:rt("checkbox"),file:rt("file"),password:rt("password"),image:rt("image"),submit:it("submit"),reset:it("reset"),button:function(e){var t=e.nodeName.toLowerCase();return t==="input"&&e.type==="button"||t==="button"},input:function(e){return V.test(e.nodeName)},focus:function(e){var t=e.ownerDocument;return e===t.activeElement&&(!t.hasFocus||t.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},active:function(e){return e===e.ownerDocument.activeElement},first:st(function(){return[0]}),last:st(function(e,t){return[t-1]}),eq:st(function(e,t,n){return[n<0?n+t:n]}),even:st(function(e,t){for(var n=0;n=0;)e.push(r);return e}),gt:st(function(e,t,n){for(var r=n<0?n+t:n;++r",e.querySelectorAll("[selected]").length||i.push("\\["+O+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),e.querySelectorAll(":checked").length||i.push(":checked")}),K(function(e){e.innerHTML="

",e.querySelectorAll("[test^='']").length&&i.push("[*^$]="+O+"*(?:\"\"|'')"),e.innerHTML="",e.querySelectorAll(":enabled").length||i.push(":enabled",":disabled")}),i=new RegExp(i.join("|")),vt=function(e,r,s,o,u){if(!o&&!u&&!i.test(e)){var a,f,l=!0,c=d,h=r,p=r.nodeType===9&&e;if(r.nodeType===1&&r.nodeName.toLowerCase()!=="object"){a=ut(e),(l=r.getAttribute("id"))?c=l.replace(n,"\\$&"):r.setAttribute("id",c),c="[id='"+c+"'] ",f=a.length;while(f--)a[f]=c+a[f].join("");h=z.test(e)&&r.parentNode||r,p=a.join(",")}if(p)try{return S.apply(s,x.call(h.querySelectorAll(p),0)),s}catch(v){}finally{l||r.removeAttribute("id")}}return t(e,r,s,o,u)},u&&(K(function(t){e=u.call(t,"div");try{u.call(t,"[test!='']:sizzle"),s.push("!=",H)}catch(n){}}),s=new RegExp(s.join("|")),nt.matchesSelector=function(t,n){n=n.replace(r,"='$1']");if(!o(t)&&!s.test(n)&&!i.test(n))try{var a=u.call(t,n);if(a||e||t.document&&t.document.nodeType!==11)return a}catch(f){}return nt(n,null,null,[t]).length>0})}(),i.pseudos.nth=i.pseudos.eq,i.filters=mt.prototype=i.pseudos,i.setFilters=new mt,nt.attr=v.attr,v.find=nt,v.expr=nt.selectors,v.expr[":"]=v.expr.pseudos,v.unique=nt.uniqueSort,v.text=nt.getText,v.isXMLDoc=nt.isXML,v.contains=nt.contains}(e);var nt=/Until$/,rt=/^(?:parents|prev(?:Until|All))/,it=/^.[^:#\[\.,]*$/,st=v.expr.match.needsContext,ot={children:!0,contents:!0,next:!0,prev:!0};v.fn.extend({find:function(e){var t,n,r,i,s,o,u=this;if(typeof e!="string")return v(e).filter(function(){for(t=0,n=u.length;t0)for(i=r;i=0:v.filter(e,this).length>0:this.filter(e).length>0)},closest:function(e,t){var n,r=0,i=this.length,s=[],o=st.test(e)||typeof e!="string"?v(e,t||this.context):0;for(;r-1:v.find.matchesSelector(n,e)){s.push(n);break}n=n.parentNode}}return s=s.length>1?v.unique(s):s,this.pushStack(s,"closest",e)},index:function(e){return e?typeof e=="string"?v.inArray(this[0],v(e)):v.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.prevAll().length:-1},add:function(e,t){var n=typeof e=="string"?v(e,t):v.makeArray(e&&e.nodeType?[e]:e),r=v.merge(this.get(),n);return this.pushStack(ut(n[0])||ut(r[0])?r:v.unique(r))},addBack:function(e){return this.add(e==null?this.prevObject:this.prevObject.filter(e))}}),v.fn.andSelf=v.fn.addBack,v.each({parent:function(e){var t=e.parentNode;return t&&t.nodeType!==11?t:null},parents:function(e){return v.dir(e,"parentNode")},parentsUntil:function(e,t,n){return v.dir(e,"parentNode",n)},next:function(e){return at(e,"nextSibling")},prev:function(e){return at(e,"previousSibling")},nextAll:function(e){return v.dir(e,"nextSibling")},prevAll:function(e){return v.dir(e,"previousSibling")},nextUntil:function(e,t,n){return v.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return v.dir(e,"previousSibling",n)},siblings:function(e){return v.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return v.sibling(e.firstChild)},contents:function(e){return v.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:v.merge([],e.childNodes)}},function(e,t){v.fn[e]=function(n,r){var i=v.map(this,t,n);return nt.test(e)||(r=n),r&&typeof r=="string"&&(i=v.filter(r,i)),i=this.length>1&&!ot[e]?v.unique(i):i,this.length>1&&rt.test(e)&&(i=i.reverse()),this.pushStack(i,e,l.call(arguments).join(","))}}),v.extend({filter:function(e,t,n){return n&&(e=":not("+e+")"),t.length===1?v.find.matchesSelector(t[0],e)?[t[0]]:[]:v.find.matches(e,t)},dir:function(e,n,r){var i=[],s=e[n];while(s&&s.nodeType!==9&&(r===t||s.nodeType!==1||!v(s).is(r)))s.nodeType===1&&i.push(s),s=s[n];return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)e.nodeType===1&&e!==t&&n.push(e);return n}});var ct="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",ht=/ jQuery\d+="(?:null|\d+)"/g,pt=/^\s+/,dt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,vt=/<([\w:]+)/,mt=/]","i"),Et=/^(?:checkbox|radio)$/,St=/checked\s*(?:[^=]|=\s*.checked.)/i,xt=/\/(java|ecma)script/i,Tt=/^\s*\s*$/g,Nt={option:[1,""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]},Ct=lt(i),kt=Ct.appendChild(i.createElement("div"));Nt.optgroup=Nt.option,Nt.tbody=Nt.tfoot=Nt.colgroup=Nt.caption=Nt.thead,Nt.th=Nt.td,v.support.htmlSerialize||(Nt._default=[1,"X
","
"]),v.fn.extend({text:function(e){return v.access(this,function(e){return e===t?v.text(this):this.empty().append((this[0]&&this[0].ownerDocument||i).createTextNode(e))},null,e,arguments.length)},wrapAll:function(e){if(v.isFunction(e))return this.each(function(t){v(this).wrapAll(e.call(this,t))});if(this[0]){var t=v(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&e.firstChild.nodeType===1)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return v.isFunction(e)?this.each(function(t){v(this).wrapInner(e.call(this,t))}):this.each(function(){var t=v(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=v.isFunction(e);return this.each(function(n){v(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){v.nodeName(this,"body")||v(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(e){(this.nodeType===1||this.nodeType===11)&&this.appendChild(e)})},prepend:function(){return this.domManip(arguments,!0,function(e){(this.nodeType===1||this.nodeType===11)&&this.insertBefore(e,this.firstChild)})},before:function(){if(!ut(this[0]))return this.domManip(arguments,!1,function(e){this.parentNode.insertBefore(e,this)});if(arguments.length){var e=v.clean(arguments);return this.pushStack(v.merge(e,this),"before",this.selector)}},after:function(){if(!ut(this[0]))return this.domManip(arguments,!1,function(e){this.parentNode.insertBefore(e,this.nextSibling)});if(arguments.length){var e=v.clean(arguments);return this.pushStack(v.merge(this,e),"after",this.selector)}},remove:function(e,t){var n,r=0;for(;(n=this[r])!=null;r++)if(!e||v.filter(e,[n]).length)!t&&n.nodeType===1&&(v.cleanData(n.getElementsByTagName("*")),v.cleanData([n])),n.parentNode&&n.parentNode.removeChild(n);return this},empty:function(){var e,t=0;for(;(e=this[t])!=null;t++){e.nodeType===1&&v.cleanData(e.getElementsByTagName("*"));while(e.firstChild)e.removeChild(e.firstChild)}return this},clone:function(e,t){return e=e==null?!1:e,t=t==null?e:t,this.map(function(){return v.clone(this,e,t)})},html:function(e){return v.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return n.nodeType===1?n.innerHTML.replace(ht,""):t;if(typeof e=="string"&&!yt.test(e)&&(v.support.htmlSerialize||!wt.test(e))&&(v.support.leadingWhitespace||!pt.test(e))&&!Nt[(vt.exec(e)||["",""])[1].toLowerCase()]){e=e.replace(dt,"<$1>");try{for(;r1&&typeof f=="string"&&St.test(f))return this.each(function(){v(this).domManip(e,n,r)});if(v.isFunction(f))return this.each(function(i){var s=v(this);e[0]=f.call(this,i,n?s.html():t),s.domManip(e,n,r)});if(this[0]){i=v.buildFragment(e,this,l),o=i.fragment,s=o.firstChild,o.childNodes.length===1&&(o=s);if(s){n=n&&v.nodeName(s,"tr");for(u=i.cacheable||c-1;a0?this.clone(!0):this).get(),v(o[i])[t](r),s=s.concat(r);return this.pushStack(s,e,o.selector)}}),v.extend({clone:function(e,t,n){var r,i,s,o;v.support.html5Clone||v.isXMLDoc(e)||!wt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(kt.innerHTML=e.outerHTML,kt.removeChild(o=kt.firstChild));if((!v.support.noCloneEvent||!v.support.noCloneChecked)&&(e.nodeType===1||e.nodeType===11)&&!v.isXMLDoc(e)){Ot(e,o),r=Mt(e),i=Mt(o);for(s=0;r[s];++s)i[s]&&Ot(r[s],i[s])}if(t){At(e,o);if(n){r=Mt(e),i=Mt(o);for(s=0;r[s];++s)At(r[s],i[s])}}return r=i=null,o},clean:function(e,t,n,r){var s,o,u,a,f,l,c,h,p,d,m,g,y=t===i&&Ct,b=[];if(!t||typeof t.createDocumentFragment=="undefined")t=i;for(s=0;(u=e[s])!=null;s++){typeof u=="number"&&(u+="");if(!u)continue;if(typeof u=="string")if(!gt.test(u))u=t.createTextNode(u);else{y=y||lt(t),c=t.createElement("div"),y.appendChild(c),u=u.replace(dt,"<$1>"),a=(vt.exec(u)||["",""])[1].toLowerCase(),f=Nt[a]||Nt._default,l=f[0],c.innerHTML=f[1]+u+f[2];while(l--)c=c.lastChild;if(!v.support.tbody){h=mt.test(u),p=a==="table"&&!h?c.firstChild&&c.firstChild.childNodes:f[1]===""&&!h?c.childNodes:[];for(o=p.length-1;o>=0;--o)v.nodeName(p[o],"tbody")&&!p[o].childNodes.length&&p[o].parentNode.removeChild(p[o])}!v.support.leadingWhitespace&&pt.test(u)&&c.insertBefore(t.createTextNode(pt.exec(u)[0]),c.firstChild),u=c.childNodes,c.parentNode.removeChild(c)}u.nodeType?b.push(u):v.merge(b,u)}c&&(u=c=y=null);if(!v.support.appendChecked)for(s=0;(u=b[s])!=null;s++)v.nodeName(u,"input")?_t(u):typeof u.getElementsByTagName!="undefined"&&v.grep(u.getElementsByTagName("input"),_t);if(n){m=function(e){if(!e.type||xt.test(e.type))return r?r.push(e.parentNode?e.parentNode.removeChild(e):e):n.appendChild(e)};for(s=0;(u=b[s])!=null;s++)if(!v.nodeName(u,"script")||!m(u))n.appendChild(u),typeof u.getElementsByTagName!="undefined"&&(g=v.grep(v.merge([],u.getElementsByTagName("script")),m),b.splice.apply(b,[s+1,0].concat(g)),s+=g.length)}return b},cleanData:function(e,t){var n,r,i,s,o=0,u=v.expando,a=v.cache,f=v.support.deleteExpando,l=v.event.special;for(;(i=e[o])!=null;o++)if(t||v.acceptData(i)){r=i[u],n=r&&a[r];if(n){if(n.events)for(s in n.events)l[s]?v.event.remove(i,s):v.removeEvent(i,s,n.handle);a[r]&&(delete a[r],f?delete i[u]:i.removeAttribute?i.removeAttribute(u):i[u]=null,v.deletedIds.push(r))}}}}),function(){var e,t;v.uaMatch=function(e){e=e.toLowerCase();var t=/(chrome)[ \/]([\w.]+)/.exec(e)||/(webkit)[ \/]([\w.]+)/.exec(e)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(e)||/(msie) ([\w.]+)/.exec(e)||e.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(e)||[];return{browser:t[1]||"",version:t[2]||"0"}},e=v.uaMatch(o.userAgent),t={},e.browser&&(t[e.browser]=!0,t.version=e.version),t.chrome?t.webkit=!0:t.webkit&&(t.safari=!0),v.browser=t,v.sub=function(){function e(t,n){return new e.fn.init(t,n)}v.extend(!0,e,this),e.superclass=this,e.fn=e.prototype=this(),e.fn.constructor=e,e.sub=this.sub,e.fn.init=function(r,i){return i&&i instanceof v&&!(i instanceof e)&&(i=e(i)),v.fn.init.call(this,r,i,t)},e.fn.init.prototype=e.fn;var t=e(i);return e}}();var Dt,Pt,Ht,Bt=/alpha\([^)]*\)/i,jt=/opacity=([^)]*)/,Ft=/^(top|right|bottom|left)$/,It=/^(none|table(?!-c[ea]).+)/,qt=/^margin/,Rt=new RegExp("^("+m+")(.*)$","i"),Ut=new RegExp("^("+m+")(?!px)[a-z%]+$","i"),zt=new RegExp("^([-+])=("+m+")","i"),Wt={BODY:"block"},Xt={position:"absolute",visibility:"hidden",display:"block"},Vt={letterSpacing:0,fontWeight:400},$t=["Top","Right","Bottom","Left"],Jt=["Webkit","O","Moz","ms"],Kt=v.fn.toggle;v.fn.extend({css:function(e,n){return v.access(this,function(e,n,r){return r!==t?v.style(e,n,r):v.css(e,n)},e,n,arguments.length>1)},show:function(){return Yt(this,!0)},hide:function(){return Yt(this)},toggle:function(e,t){var n=typeof e=="boolean";return v.isFunction(e)&&v.isFunction(t)?Kt.apply(this,arguments):this.each(function(){(n?e:Gt(this))?v(this).show():v(this).hide()})}}),v.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Dt(e,"opacity");return n===""?"1":n}}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":v.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(!e||e.nodeType===3||e.nodeType===8||!e.style)return;var s,o,u,a=v.camelCase(n),f=e.style;n=v.cssProps[a]||(v.cssProps[a]=Qt(f,a)),u=v.cssHooks[n]||v.cssHooks[a];if(r===t)return u&&"get"in u&&(s=u.get(e,!1,i))!==t?s:f[n];o=typeof r,o==="string"&&(s=zt.exec(r))&&(r=(s[1]+1)*s[2]+parseFloat(v.css(e,n)),o="number");if(r==null||o==="number"&&isNaN(r))return;o==="number"&&!v.cssNumber[a]&&(r+="px");if(!u||!("set"in u)||(r=u.set(e,r,i))!==t)try{f[n]=r}catch(l){}},css:function(e,n,r,i){var s,o,u,a=v.camelCase(n);return n=v.cssProps[a]||(v.cssProps[a]=Qt(e.style,a)),u=v.cssHooks[n]||v.cssHooks[a],u&&"get"in u&&(s=u.get(e,!0,i)),s===t&&(s=Dt(e,n)),s==="normal"&&n in Vt&&(s=Vt[n]),r||i!==t?(o=parseFloat(s),r||v.isNumeric(o)?o||0:s):s},swap:function(e,t,n){var r,i,s={};for(i in t)s[i]=e.style[i],e.style[i]=t[i];r=n.call(e);for(i in t)e.style[i]=s[i];return r}}),e.getComputedStyle?Dt=function(t,n){var r,i,s,o,u=e.getComputedStyle(t,null),a=t.style;return u&&(r=u.getPropertyValue(n)||u[n],r===""&&!v.contains(t.ownerDocument,t)&&(r=v.style(t,n)),Ut.test(r)&&qt.test(n)&&(i=a.width,s=a.minWidth,o=a.maxWidth,a.minWidth=a.maxWidth=a.width=r,r=u.width,a.width=i,a.minWidth=s,a.maxWidth=o)),r}:i.documentElement.currentStyle&&(Dt=function(e,t){var n,r,i=e.currentStyle&&e.currentStyle[t],s=e.style;return i==null&&s&&s[t]&&(i=s[t]),Ut.test(i)&&!Ft.test(t)&&(n=s.left,r=e.runtimeStyle&&e.runtimeStyle.left,r&&(e.runtimeStyle.left=e.currentStyle.left),s.left=t==="fontSize"?"1em":i,i=s.pixelLeft+"px",s.left=n,r&&(e.runtimeStyle.left=r)),i===""?"auto":i}),v.each(["height","width"],function(e,t){v.cssHooks[t]={get:function(e,n,r){if(n)return e.offsetWidth===0&&It.test(Dt(e,"display"))?v.swap(e,Xt,function(){return tn(e,t,r)}):tn(e,t,r)},set:function(e,n,r){return Zt(e,n,r?en(e,t,r,v.support.boxSizing&&v.css(e,"boxSizing")==="border-box"):0)}}}),v.support.opacity||(v.cssHooks.opacity={get:function(e,t){return jt.test((t&&e.currentStyle?e.currentStyle.filter:e.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":t?"1":""},set:function(e,t){var n=e.style,r=e.currentStyle,i=v.isNumeric(t)?"alpha(opacity="+t*100+")":"",s=r&&r.filter||n.filter||"";n.zoom=1;if(t>=1&&v.trim(s.replace(Bt,""))===""&&n.removeAttribute){n.removeAttribute("filter");if(r&&!r.filter)return}n.filter=Bt.test(s)?s.replace(Bt,i):s+" "+i}}),v(function(){v.support.reliableMarginRight||(v.cssHooks.marginRight={get:function(e,t){return v.swap(e,{display:"inline-block"},function(){if(t)return Dt(e,"marginRight")})}}),!v.support.pixelPosition&&v.fn.position&&v.each(["top","left"],function(e,t){v.cssHooks[t]={get:function(e,n){if(n){var r=Dt(e,t);return Ut.test(r)?v(e).position()[t]+"px":r}}}})}),v.expr&&v.expr.filters&&(v.expr.filters.hidden=function(e){return e.offsetWidth===0&&e.offsetHeight===0||!v.support.reliableHiddenOffsets&&(e.style&&e.style.display||Dt(e,"display"))==="none"},v.expr.filters.visible=function(e){return!v.expr.filters.hidden(e)}),v.each({margin:"",padding:"",border:"Width"},function(e,t){v.cssHooks[e+t]={expand:function(n){var r,i=typeof n=="string"?n.split(" "):[n],s={};for(r=0;r<4;r++)s[e+$t[r]+t]=i[r]||i[r-2]||i[0];return s}},qt.test(e)||(v.cssHooks[e+t].set=Zt)});var rn=/%20/g,sn=/\[\]$/,on=/\r?\n/g,un=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,an=/^(?:select|textarea)/i;v.fn.extend({serialize:function(){return v.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?v.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||an.test(this.nodeName)||un.test(this.type))}).map(function(e,t){var n=v(this).val();return n==null?null:v.isArray(n)?v.map(n,function(e,n){return{name:t.name,value:e.replace(on,"\r\n")}}):{name:t.name,value:n.replace(on,"\r\n")}}).get()}}),v.param=function(e,n){var r,i=[],s=function(e,t){t=v.isFunction(t)?t():t==null?"":t,i[i.length]=encodeURIComponent(e)+"="+encodeURIComponent(t)};n===t&&(n=v.ajaxSettings&&v.ajaxSettings.traditional);if(v.isArray(e)||e.jquery&&!v.isPlainObject(e))v.each(e,function(){s(this.name,this.value)});else for(r in e)fn(r,e[r],n,s);return i.join("&").replace(rn,"+")};var ln,cn,hn=/#.*$/,pn=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,dn=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,vn=/^(?:GET|HEAD)$/,mn=/^\/\//,gn=/\?/,yn=/)<[^<]*)*<\/script>/gi,bn=/([?&])_=[^&]*/,wn=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,En=v.fn.load,Sn={},xn={},Tn=["*/"]+["*"];try{cn=s.href}catch(Nn){cn=i.createElement("a"),cn.href="",cn=cn.href}ln=wn.exec(cn.toLowerCase())||[],v.fn.load=function(e,n,r){if(typeof e!="string"&&En)return En.apply(this,arguments);if(!this.length)return this;var i,s,o,u=this,a=e.indexOf(" ");return a>=0&&(i=e.slice(a,e.length),e=e.slice(0,a)),v.isFunction(n)?(r=n,n=t):n&&typeof n=="object"&&(s="POST"),v.ajax({url:e,type:s,dataType:"html",data:n,complete:function(e,t){r&&u.each(r,o||[e.responseText,t,e])}}).done(function(e){o=arguments,u.html(i?v("
").append(e.replace(yn,"")).find(i):e)}),this},v.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(e,t){v.fn[t]=function(e){return this.on(t,e)}}),v.each(["get","post"],function(e,n){v[n]=function(e,r,i,s){return v.isFunction(r)&&(s=s||i,i=r,r=t),v.ajax({type:n,url:e,data:r,success:i,dataType:s})}}),v.extend({getScript:function(e,n){return v.get(e,t,n,"script")},getJSON:function(e,t,n){return v.get(e,t,n,"json")},ajaxSetup:function(e,t){return t?Ln(e,v.ajaxSettings):(t=e,e=v.ajaxSettings),Ln(e,t),e},ajaxSettings:{url:cn,isLocal:dn.test(ln[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":Tn},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":e.String,"text html":!0,"text json":v.parseJSON,"text xml":v.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:Cn(Sn),ajaxTransport:Cn(xn),ajax:function(e,n){function T(e,n,s,a){var l,y,b,w,S,T=n;if(E===2)return;E=2,u&&clearTimeout(u),o=t,i=a||"",x.readyState=e>0?4:0,s&&(w=An(c,x,s));if(e>=200&&e<300||e===304)c.ifModified&&(S=x.getResponseHeader("Last-Modified"),S&&(v.lastModified[r]=S),S=x.getResponseHeader("Etag"),S&&(v.etag[r]=S)),e===304?(T="notmodified",l=!0):(l=On(c,w),T=l.state,y=l.data,b=l.error,l=!b);else{b=T;if(!T||e)T="error",e<0&&(e=0)}x.status=e,x.statusText=(n||T)+"",l?d.resolveWith(h,[y,T,x]):d.rejectWith(h,[x,T,b]),x.statusCode(g),g=t,f&&p.trigger("ajax"+(l?"Success":"Error"),[x,c,l?y:b]),m.fireWith(h,[x,T]),f&&(p.trigger("ajaxComplete",[x,c]),--v.active||v.event.trigger("ajaxStop"))}typeof e=="object"&&(n=e,e=t),n=n||{};var r,i,s,o,u,a,f,l,c=v.ajaxSetup({},n),h=c.context||c,p=h!==c&&(h.nodeType||h instanceof v)?v(h):v.event,d=v.Deferred(),m=v.Callbacks("once memory"),g=c.statusCode||{},b={},w={},E=0,S="canceled",x={readyState:0,setRequestHeader:function(e,t){if(!E){var n=e.toLowerCase();e=w[n]=w[n]||e,b[e]=t}return this},getAllResponseHeaders:function(){return E===2?i:null},getResponseHeader:function(e){var n;if(E===2){if(!s){s={};while(n=pn.exec(i))s[n[1].toLowerCase()]=n[2]}n=s[e.toLowerCase()]}return n===t?null:n},overrideMimeType:function(e){return E||(c.mimeType=e),this},abort:function(e){return e=e||S,o&&o.abort(e),T(0,e),this}};d.promise(x),x.success=x.done,x.error=x.fail,x.complete=m.add,x.statusCode=function(e){if(e){var t;if(E<2)for(t in e)g[t]=[g[t],e[t]];else t=e[x.status],x.always(t)}return this},c.url=((e||c.url)+"").replace(hn,"").replace(mn,ln[1]+"//"),c.dataTypes=v.trim(c.dataType||"*").toLowerCase().split(y),c.crossDomain==null&&(a=wn.exec(c.url.toLowerCase()),c.crossDomain=!(!a||a[1]===ln[1]&&a[2]===ln[2]&&(a[3]||(a[1]==="http:"?80:443))==(ln[3]||(ln[1]==="http:"?80:443)))),c.data&&c.processData&&typeof c.data!="string"&&(c.data=v.param(c.data,c.traditional)),kn(Sn,c,n,x);if(E===2)return x;f=c.global,c.type=c.type.toUpperCase(),c.hasContent=!vn.test(c.type),f&&v.active++===0&&v.event.trigger("ajaxStart");if(!c.hasContent){c.data&&(c.url+=(gn.test(c.url)?"&":"?")+c.data,delete c.data),r=c.url;if(c.cache===!1){var N=v.now(),C=c.url.replace(bn,"$1_="+N);c.url=C+(C===c.url?(gn.test(c.url)?"&":"?")+"_="+N:"")}}(c.data&&c.hasContent&&c.contentType!==!1||n.contentType)&&x.setRequestHeader("Content-Type",c.contentType),c.ifModified&&(r=r||c.url,v.lastModified[r]&&x.setRequestHeader("If-Modified-Since",v.lastModified[r]),v.etag[r]&&x.setRequestHeader("If-None-Match",v.etag[r])),x.setRequestHeader("Accept",c.dataTypes[0]&&c.accepts[c.dataTypes[0]]?c.accepts[c.dataTypes[0]]+(c.dataTypes[0]!=="*"?", "+Tn+"; q=0.01":""):c.accepts["*"]);for(l in c.headers)x.setRequestHeader(l,c.headers[l]);if(!c.beforeSend||c.beforeSend.call(h,x,c)!==!1&&E!==2){S="abort";for(l in{success:1,error:1,complete:1})x[l](c[l]);o=kn(xn,c,n,x);if(!o)T(-1,"No Transport");else{x.readyState=1,f&&p.trigger("ajaxSend",[x,c]),c.async&&c.timeout>0&&(u=setTimeout(function(){x.abort("timeout")},c.timeout));try{E=1,o.send(b,T)}catch(k){if(!(E<2))throw k;T(-1,k)}}return x}return x.abort()},active:0,lastModified:{},etag:{}});var Mn=[],_n=/\?/,Dn=/(=)\?(?=&|$)|\?\?/,Pn=v.now();v.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Mn.pop()||v.expando+"_"+Pn++;return this[e]=!0,e}}),v.ajaxPrefilter("json jsonp",function(n,r,i){var s,o,u,a=n.data,f=n.url,l=n.jsonp!==!1,c=l&&Dn.test(f),h=l&&!c&&typeof a=="string"&&!(n.contentType||"").indexOf("application/x-www-form-urlencoded")&&Dn.test(a);if(n.dataTypes[0]==="jsonp"||c||h)return s=n.jsonpCallback=v.isFunction(n.jsonpCallback)?n.jsonpCallback():n.jsonpCallback,o=e[s],c?n.url=f.replace(Dn,"$1"+s):h?n.data=a.replace(Dn,"$1"+s):l&&(n.url+=(_n.test(f)?"&":"?")+n.jsonp+"="+s),n.converters["script json"]=function(){return u||v.error(s+" was not called"),u[0]},n.dataTypes[0]="json",e[s]=function(){u=arguments},i.always(function(){e[s]=o,n[s]&&(n.jsonpCallback=r.jsonpCallback,Mn.push(s)),u&&v.isFunction(o)&&o(u[0]),u=o=t}),"script"}),v.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(e){return v.globalEval(e),e}}}),v.ajaxPrefilter("script",function(e){e.cache===t&&(e.cache=!1),e.crossDomain&&(e.type="GET",e.global=!1)}),v.ajaxTransport("script",function(e){if(e.crossDomain){var n,r=i.head||i.getElementsByTagName("head")[0]||i.documentElement;return{send:function(s,o){n=i.createElement("script"),n.async="async",e.scriptCharset&&(n.charset=e.scriptCharset),n.src=e.url,n.onload=n.onreadystatechange=function(e,i){if(i||!n.readyState||/loaded|complete/.test(n.readyState))n.onload=n.onreadystatechange=null,r&&n.parentNode&&r.removeChild(n),n=t,i||o(200,"success")},r.insertBefore(n,r.firstChild)},abort:function(){n&&n.onload(0,1)}}}});var Hn,Bn=e.ActiveXObject?function(){for(var e in Hn)Hn[e](0,1)}:!1,jn=0;v.ajaxSettings.xhr=e.ActiveXObject?function(){return!this.isLocal&&Fn()||In()}:Fn,function(e){v.extend(v.support,{ajax:!!e,cors:!!e&&"withCredentials"in e})}(v.ajaxSettings.xhr()),v.support.ajax&&v.ajaxTransport(function(n){if(!n.crossDomain||v.support.cors){var r;return{send:function(i,s){var o,u,a=n.xhr();n.username?a.open(n.type,n.url,n.async,n.username,n.password):a.open(n.type,n.url,n.async);if(n.xhrFields)for(u in n.xhrFields)a[u]=n.xhrFields[u];n.mimeType&&a.overrideMimeType&&a.overrideMimeType(n.mimeType),!n.crossDomain&&!i["X-Requested-With"]&&(i["X-Requested-With"]="XMLHttpRequest");try{for(u in i)a.setRequestHeader(u,i[u])}catch(f){}a.send(n.hasContent&&n.data||null),r=function(e,i){var u,f,l,c,h;try{if(r&&(i||a.readyState===4)){r=t,o&&(a.onreadystatechange=v.noop,Bn&&delete Hn[o]);if(i)a.readyState!==4&&a.abort();else{u=a.status,l=a.getAllResponseHeaders(),c={},h=a.responseXML,h&&h.documentElement&&(c.xml=h);try{c.text=a.responseText}catch(p){}try{f=a.statusText}catch(p){f=""}!u&&n.isLocal&&!n.crossDomain?u=c.text?200:404:u===1223&&(u=204)}}}catch(d){i||s(-1,d)}c&&s(u,f,c,l)},n.async?a.readyState===4?setTimeout(r,0):(o=++jn,Bn&&(Hn||(Hn={},v(e).unload(Bn)),Hn[o]=r),a.onreadystatechange=r):r()},abort:function(){r&&r(0,1)}}}});var qn,Rn,Un=/^(?:toggle|show|hide)$/,zn=new RegExp("^(?:([-+])=|)("+m+")([a-z%]*)$","i"),Wn=/queueHooks$/,Xn=[Gn],Vn={"*":[function(e,t){var n,r,i=this.createTween(e,t),s=zn.exec(t),o=i.cur(),u=+o||0,a=1,f=20;if(s){n=+s[2],r=s[3]||(v.cssNumber[e]?"":"px");if(r!=="px"&&u){u=v.css(i.elem,e,!0)||n||1;do a=a||".5",u/=a,v.style(i.elem,e,u+r);while(a!==(a=i.cur()/o)&&a!==1&&--f)}i.unit=r,i.start=u,i.end=s[1]?u+(s[1]+1)*n:n}return i}]};v.Animation=v.extend(Kn,{tweener:function(e,t){v.isFunction(e)?(t=e,e=["*"]):e=e.split(" ");var n,r=0,i=e.length;for(;r-1,f={},l={},c,h;a?(l=i.position(),c=l.top,h=l.left):(c=parseFloat(o)||0,h=parseFloat(u)||0),v.isFunction(t)&&(t=t.call(e,n,s)),t.top!=null&&(f.top=t.top-s.top+c),t.left!=null&&(f.left=t.left-s.left+h),"using"in t?t.using.call(e,f):i.css(f)}},v.fn.extend({position:function(){if(!this[0])return;var e=this[0],t=this.offsetParent(),n=this.offset(),r=er.test(t[0].nodeName)?{top:0,left:0}:t.offset();return n.top-=parseFloat(v.css(e,"marginTop"))||0,n.left-=parseFloat(v.css(e,"marginLeft"))||0,r.top+=parseFloat(v.css(t[0],"borderTopWidth"))||0,r.left+=parseFloat(v.css(t[0],"borderLeftWidth"))||0,{top:n.top-r.top,left:n.left-r.left}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||i.body;while(e&&!er.test(e.nodeName)&&v.css(e,"position")==="static")e=e.offsetParent;return e||i.body})}}),v.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,n){var r=/Y/.test(n);v.fn[e]=function(i){return v.access(this,function(e,i,s){var o=tr(e);if(s===t)return o?n in o?o[n]:o.document.documentElement[i]:e[i];o?o.scrollTo(r?v(o).scrollLeft():s,r?s:v(o).scrollTop()):e[i]=s},e,i,arguments.length,null)}}),v.each({Height:"height",Width:"width"},function(e,n){v.each({padding:"inner"+e,content:n,"":"outer"+e},function(r,i){v.fn[i]=function(i,s){var o=arguments.length&&(r||typeof i!="boolean"),u=r||(i===!0||s===!0?"margin":"border");return v.access(this,function(n,r,i){var s;return v.isWindow(n)?n.document.documentElement["client"+e]:n.nodeType===9?(s=n.documentElement,Math.max(n.body["scroll"+e],s["scroll"+e],n.body["offset"+e],s["offset"+e],s["client"+e])):i===t?v.css(n,r,i,u):v.style(n,r,i,u)},n,o?i:t,o,null)}})}),e.jQuery=e.$=v,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return v})})(window); +/*! jQuery v3.6.0 | (c) OpenJS Foundation and other contributors | jquery.org/license */ +!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.6.0",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace($,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||v.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||D,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,D=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",y.option=!!ce.lastChild;var ge={thead:[1,"
","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function je(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function De(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function qe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Le(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var _t,zt=[],Ut=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=zt.pop()||S.expando+"_"+wt.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Ut.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Ut.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Ut,"$1"+r):!1!==e.jsonp&&(e.url+=(Tt.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,zt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((_t=E.implementation.createHTMLDocument("").body).innerHTML="
",2===_t.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=Fe(y.pixelPosition,function(e,t){if(t)return t=We(e,n),Pe.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return $(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0 Date: Mon, 24 Jul 2023 14:36:51 -0700 Subject: [PATCH 042/235] suppress errors in `mapillary/opensfm` Differential Revision: D47734393 fbshipit-source-id: 60c404337afddf2eb20c9b0df27fb6bd009eba61 --- viewer/server.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/viewer/server.py b/viewer/server.py index bddd1ba13..536c0fc2e 100644 --- a/viewer/server.py +++ b/viewer/server.py @@ -23,6 +23,8 @@ @app.route("/") def index() -> Response: + # pyre-fixme[6]: For 1st argument expected `typing_extensions.LiteralString` but + # got `Optional[str]`. return send_file(os.path.join(app.static_folder, "index.html")) @@ -83,7 +85,6 @@ def verified_send(file) -> Response: if os.path.isfile(file): return send_file(file) else: - # pyre-fixme[7]: Expected `Response` but got implicit return value of `None`. abort(404) From 5fe4115896d994bf31e8856bd04a5063aafccfd9 Mon Sep 17 00:00:00 2001 From: generatedunixname89002005307016 Date: Mon, 24 Jul 2023 18:16:27 -0700 Subject: [PATCH 043/235] suppress errors in `mapillary/opensfm` Differential Revision: D47743328 fbshipit-source-id: 8c1f719db79817730bf0aabf03899082fcca9a6c --- viewer/server.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/viewer/server.py b/viewer/server.py index 536c0fc2e..bddd1ba13 100644 --- a/viewer/server.py +++ b/viewer/server.py @@ -23,8 +23,6 @@ @app.route("/") def index() -> Response: - # pyre-fixme[6]: For 1st argument expected `typing_extensions.LiteralString` but - # got `Optional[str]`. return send_file(os.path.join(app.static_folder, "index.html")) @@ -85,6 +83,7 @@ def verified_send(file) -> Response: if os.path.isfile(file): return send_file(file) else: + # pyre-fixme[7]: Expected `Response` but got implicit return value of `None`. abort(404) From 193818dcd274fbc5763c654b0446df0aca696544 Mon Sep 17 00:00:00 2001 From: generatedunixname89002005307016 Date: Mon, 31 Jul 2023 18:13:07 -0700 Subject: [PATCH 044/235] suppress errors in `mapillary/opensfm` Differential Revision: D47940244 fbshipit-source-id: dd8961029435e5c43816cbe63b6a01cdc1b52986 --- viewer/server.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/viewer/server.py b/viewer/server.py index bddd1ba13..536c0fc2e 100644 --- a/viewer/server.py +++ b/viewer/server.py @@ -23,6 +23,8 @@ @app.route("/") def index() -> Response: + # pyre-fixme[6]: For 1st argument expected `typing_extensions.LiteralString` but + # got `Optional[str]`. return send_file(os.path.join(app.static_folder, "index.html")) @@ -83,7 +85,6 @@ def verified_send(file) -> Response: if os.path.isfile(file): return send_file(file) else: - # pyre-fixme[7]: Expected `Response` but got implicit return value of `None`. abort(404) From 899575ae9633d24e497df52ed2eb93642d862422 Mon Sep 17 00:00:00 2001 From: Richard Barnes Date: Sun, 27 Aug 2023 22:26:08 -0700 Subject: [PATCH 045/235] Del `(object)` from 50 inc manifold/cogwheel/lib/manifold_semaphore.py Summary: Python3 makes the use of `(object)` in class inheritance unnecessary. Let's modernize our code by eliminating this. Reviewed By: palmje Differential Revision: D48718310 fbshipit-source-id: c6e6ad2889add16537c78353f3202ac924f00fae --- opensfm/dataset.py | 2 +- opensfm/feature_loading.py | 2 +- opensfm/features_processing.py | 2 +- opensfm/geo.py | 2 +- opensfm/synthetic_data/synthetic_scene.py | 2 +- opensfm/types.py | 4 ++-- opensfm/vlad.py | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/opensfm/dataset.py b/opensfm/dataset.py index 90aaf9b37..ff825a272 100644 --- a/opensfm/dataset.py +++ b/opensfm/dataset.py @@ -702,7 +702,7 @@ def undistorted_dataset(self) -> "UndistortedDataSet": ) -class UndistortedDataSet(object): +class UndistortedDataSet: """Accessors to the undistorted data of a dataset. Data include undistorted images, masks, and segmentation as well diff --git a/opensfm/feature_loading.py b/opensfm/feature_loading.py index bd8baa022..f985b6869 100644 --- a/opensfm/feature_loading.py +++ b/opensfm/feature_loading.py @@ -15,7 +15,7 @@ ) -class FeatureLoader(object): +class FeatureLoader: def clear_cache(self) -> None: self.load_mask.cache_clear() self.load_points_colors_segmentations_instances.cache_clear() diff --git a/opensfm/features_processing.py b/opensfm/features_processing.py index b48f2aac2..52ce8c29c 100644 --- a/opensfm/features_processing.py +++ b/opensfm/features_processing.py @@ -118,7 +118,7 @@ def is_high_res_panorama( return w == 2 * h or exif_pano -class Counter(object): +class Counter: """Lock-less counter from https://julien.danjou.info/atomic-lock-free-counters-in-python/ that relies on the CPython impl. of itertools.count() that is thread-safe. Used, as for some reason, joblib doesn't like a good old threading.Lock (everything is stuck) diff --git a/opensfm/geo.py b/opensfm/geo.py index a0324f9b9..90c3d3d9d 100644 --- a/opensfm/geo.py +++ b/opensfm/geo.py @@ -175,7 +175,7 @@ def gps_distance(latlon_1, latlon_2): return dis -class TopocentricConverter(object): +class TopocentricConverter: """Convert to and from a topocentric reference frame.""" def __init__(self, reflat, reflon, refalt): diff --git a/opensfm/synthetic_data/synthetic_scene.py b/opensfm/synthetic_data/synthetic_scene.py index 688717981..5a1e4f230 100644 --- a/opensfm/synthetic_data/synthetic_scene.py +++ b/opensfm/synthetic_data/synthetic_scene.py @@ -75,7 +75,7 @@ def normalized(x: np.ndarray) -> np.ndarray: return pose -class SyntheticScene(object): +class SyntheticScene: def get_reconstruction(self) -> types.Reconstruction: raise NotImplementedError() diff --git a/opensfm/types.py b/opensfm/types.py index 1d2a877d1..7e444b9c9 100644 --- a/opensfm/types.py +++ b/opensfm/types.py @@ -9,7 +9,7 @@ PANOSHOT_RIG_PREFIX = "panoshot_" -class ShotMesh(object): +class ShotMesh: """Triangular mesh of points visible in a shot Attributes: @@ -22,7 +22,7 @@ def __init__(self): self.faces = None -class Reconstruction(object): +class Reconstruction: """Defines the reconstructed scene. Attributes: diff --git a/opensfm/vlad.py b/opensfm/vlad.py index 3a472f054..5cf9b02b4 100644 --- a/opensfm/vlad.py +++ b/opensfm/vlad.py @@ -47,7 +47,7 @@ def vlad_distances( return image, distances, others -class VladCache(object): +class VladCache: def clear_cache(self) -> None: self.load_words.cache_clear() self.vlad_histogram.cache_clear() From c798da16206aa52395eaef09ea4d7746028479d3 Mon Sep 17 00:00:00 2001 From: True Price Date: Wed, 30 Aug 2023 08:46:11 -0700 Subject: [PATCH 046/235] Use ASSERT_FLOAT_EQ in TestPixelNormalizedCoordinatesConversion Reviewed By: mlopezantequera Differential Revision: D48805944 fbshipit-source-id: 1c293ca367202740fc4e96011efb66bd8df0b119 --- opensfm/src/geometry/test/camera_test.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/opensfm/src/geometry/test/camera_test.cc b/opensfm/src/geometry/test/camera_test.cc index 81d8a0032..881c19861 100644 --- a/opensfm/src/geometry/test/camera_test.cc +++ b/opensfm/src/geometry/test/camera_test.cc @@ -549,7 +549,8 @@ TEST(Camera, TestPixelNormalizedCoordinatesConversion) { ASSERT_EQ(norm_coord_comp[1], (px_coord_def[1] - (height - 1) / 2.0) * inv_normalizer); const Vec2d px_coord_comp = cam.NormalizedToPixelCoordinates(norm_coord_comp); - ASSERT_EQ(px_coord_comp, px_coord_def); + ASSERT_FLOAT_EQ(px_coord_comp[0], px_coord_def[0]); + ASSERT_FLOAT_EQ(px_coord_comp[1], px_coord_def[1]); const Vec2d norm_coord_static = geometry::Camera::PixelToNormalizedCoordinates(px_coord_def, width, From c6b5acef9376a75b87414d900c258ef876a6413a Mon Sep 17 00:00:00 2001 From: michalmachura Date: Fri, 15 Sep 2023 01:54:39 -0700 Subject: [PATCH 047/235] Image channels dimension and dtype check for feature extraction. (#1018) Summary: Pull Request resolved: https://github.com/mapillary/OpenSfM/pull/1018 Reviewed By: paulinus Differential Revision: D48945121 Pulled By: fabianschenk fbshipit-source-id: b1b1b51640dd82d9de98e59de8d09c054641a6b7 --- opensfm/features.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/opensfm/features.py b/opensfm/features.py index bf07b7973..d4dbac37d 100644 --- a/opensfm/features.py +++ b/opensfm/features.py @@ -589,10 +589,14 @@ def extract_features( else config["feature_min_frames"] ) - assert len(image.shape) == 3 or len(image.shape) == 2 + assert image.ndim == 2 or image.ndim == 3 and image.shape[2] in [1, 3] + assert image.shape[0] > 2 and image.shape[1] > 2 + assert np.issubdtype(image.dtype, np.uint8) + image = resized_image(image, extraction_size) - if len(image.shape) == 2: # convert (h, w) to (h, w, 1) + if image.ndim == 2: # convert (h, w) to (h, w, 1) image = np.expand_dims(image, axis=2) + # convert color to gray-scale if necessary if image.shape[2] == 3: image_gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY) @@ -610,9 +614,8 @@ def extract_features( elif feature_type == "ORB": points, desc = extract_features_orb(image_gray, config, features_count) else: - raise ValueError( - "Unknown feature type " "(must be SURF, SIFT, AKAZE, HAHOG or ORB)" - ) + raise ValueError("Unknown feature type " + + "(must be SURF, SIFT, AKAZE, HAHOG or ORB)") xs = points[:, 0].round().astype(int) ys = points[:, 1].round().astype(int) From fb3dc964854a08d7cd6aa1c7ef98dd5fe419c4ce Mon Sep 17 00:00:00 2001 From: Ahmed Ahmed Date: Mon, 6 Nov 2023 13:12:51 -0800 Subject: [PATCH 048/235] Add logs for number of GPS constraints in OpenSFM Summary: Loggs to test Enable/Disable GPS in OpenSFM Differential Revision: D50942543 fbshipit-source-id: ba2c001179a5d07d25917adf7b4abdb517f6d5a7 --- opensfm/align.py | 6 +++--- opensfm/src/sfm/src/ba_helpers.cc | 7 +++++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/opensfm/align.py b/opensfm/align.py index 034799c96..383109564 100644 --- a/opensfm/align.py +++ b/opensfm/align.py @@ -123,13 +123,13 @@ def alignment_constraints( """Gather alignment constraints to be used by checking bundle_use_gcp and bundle_use_gps.""" X, Xp = [], [] - + logger.info(f"Collecting alignment constraints - bundle_use_gps:{config['bundle_use_gps']} bundle_use_gcp: {config['bundle_use_gcp']}") # Get Ground Control Point correspondences if gcp and config["bundle_use_gcp"]: triangulated, measured = triangulate_all_gcp(reconstruction, gcp) X.extend(triangulated) Xp.extend(measured) - + logger.info(f"GCP constraints X ({len(X)}) - Xp ({len(Xp)})") # Get camera center correspondences if use_gps and config["bundle_use_gps"]: for rig_instance in reconstruction.rig_instances.values(): @@ -141,7 +141,7 @@ def alignment_constraints( if len(gpses) > 0: X.append(rig_instance.pose.get_origin()) Xp.append(np.average(gpses, axis=0)) - + logger.info(f"GPS constraints X ({len(X)}) - Xp ({len(Xp)})") return X, Xp diff --git a/opensfm/src/sfm/src/ba_helpers.cc b/opensfm/src/sfm/src/ba_helpers.cc index 835883eb6..01b9dc10d 100644 --- a/opensfm/src/sfm/src/ba_helpers.cc +++ b/opensfm/src/sfm/src/ba_helpers.cc @@ -205,8 +205,15 @@ py::tuple BAHelpers::BundleLocal( ba.AddRigInstance(rig_instance_id, instance.GetPose(), shot_cameras, shot_rig_cameras, fix_instance); + LOG(INFO) << "bundle_use_gps: " << config["bundle_use_gps"].cast(); // only add averaged rig position constraints to moving instances if (!fix_instance && gps_count > 0) { + LOG(INFO) << "bundle_use_gps: " << config["bundle_use_gps"].cast() + << ", adding average GPS prior to rig instance " << rig_instance_id + << ", count: " << gps_count + << ", avg pos: " << average_position.transpose() + << ", avg std: " << average_std + << ", scale group: " << gps_scale_group; average_position /= gps_count; average_std /= gps_count; ba.AddRigInstancePositionPrior(rig_instance_id, average_position, From 25c04c334001c2316d946c3c63ef5a1b4054ca90 Mon Sep 17 00:00:00 2001 From: Ruibin Ma Date: Fri, 10 Nov 2023 14:08:52 -0800 Subject: [PATCH 049/235] add gopro max fisheye to hardcoded_camera_calibration Summary: with this we no longer need to manually set calibration in UVP Differential Revision: D51165336 fbshipit-source-id: 85804043986ef9520694e9dd788efbc7223420d9 --- opensfm/src/sfm/src/ba_helpers.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/opensfm/src/sfm/src/ba_helpers.cc b/opensfm/src/sfm/src/ba_helpers.cc index 01b9dc10d..e06692840 100644 --- a/opensfm/src/sfm/src/ba_helpers.cc +++ b/opensfm/src/sfm/src/ba_helpers.cc @@ -205,7 +205,6 @@ py::tuple BAHelpers::BundleLocal( ba.AddRigInstance(rig_instance_id, instance.GetPose(), shot_cameras, shot_rig_cameras, fix_instance); - LOG(INFO) << "bundle_use_gps: " << config["bundle_use_gps"].cast(); // only add averaged rig position constraints to moving instances if (!fix_instance && gps_count > 0) { LOG(INFO) << "bundle_use_gps: " << config["bundle_use_gps"].cast() From 98939bf06a7a777415c97db380fd110cc36043b7 Mon Sep 17 00:00:00 2001 From: generatedunixname89002005287564 Date: Tue, 14 Nov 2023 06:36:42 -0800 Subject: [PATCH 050/235] mapillary Reviewed By: zsol Differential Revision: D51300169 fbshipit-source-id: 30cf2084197dbe6f30d499e06e0f09674d761bad --- annotation_gui_gcp/run_ba.py | 38 +++++++++++++++++++++++++++--------- bin/opensfm_main.py | 12 +++++++++--- bin/plot_matches.py | 21 +++++++++++++------- 3 files changed, 52 insertions(+), 19 deletions(-) diff --git a/annotation_gui_gcp/run_ba.py b/annotation_gui_gcp/run_ba.py index 5e4ad9f09..4e571f8aa 100644 --- a/annotation_gui_gcp/run_ba.py +++ b/annotation_gui_gcp/run_ba.py @@ -8,10 +8,16 @@ import numpy as np import opensfm.reconstruction as orec -from opensfm import dataset, log, multiview, pygeometry, pymap -from opensfm import reconstruction_helpers as helpers -from opensfm import transformations as tf -from opensfm import types +from opensfm import ( + dataset, + log, + multiview, + pygeometry, + pymap, + reconstruction_helpers as helpers, + transformations as tf, + types, +) from opensfm.align import apply_similarity logger = logging.getLogger(__name__) @@ -81,7 +87,9 @@ def resplit_reconstruction(merged, original_reconstructions): return split -def gcp_geopositional_error(gcps: List[pymap.GroundControlPoint], reconstruction: types.Reconstruction): +def gcp_geopositional_error( + gcps: List[pymap.GroundControlPoint], reconstruction: types.Reconstruction +): coords_reconstruction = triangulate_gcps(gcps, reconstruction) out = {} for ix, gcp in enumerate(gcps): @@ -114,7 +122,9 @@ def gcp_geopositional_error(gcps: List[pymap.GroundControlPoint], reconstruction return out -def triangulate_gcps(gcps: List[pymap.GroundControlPoint], reconstruction: types.Reconstruction): +def triangulate_gcps( + gcps: List[pymap.GroundControlPoint], reconstruction: types.Reconstruction +): coords = [] for gcp in gcps: res = multiview.triangulate_gcp( @@ -127,7 +137,11 @@ def triangulate_gcps(gcps: List[pymap.GroundControlPoint], reconstruction: types return coords -def reproject_gcps(gcps: List[pymap.GroundControlPoint], reconstruction: types.Reconstruction, reproj_threshold): +def reproject_gcps( + gcps: List[pymap.GroundControlPoint], + reconstruction: types.Reconstruction, + reproj_threshold, +): output = {} for gcp in gcps: point = multiview.triangulate_gcp( @@ -269,7 +283,9 @@ def bundle_with_fixed_images( for point in reconstruction.points.values(): ba.add_point(point.id, point.coordinates, False) - ba.add_point_prior(point.id, point.coordinates, np.array([100.0, 100.0, 100.0]), False) + ba.add_point_prior( + point.id, point.coordinates, np.array([100.0, 100.0, 100.0]), False + ) for shot_id in reconstruction.shots: shot = reconstruction.get_shot(shot_id) @@ -866,7 +882,7 @@ def align( logger.info("No annotations with large reprojection errors") -if __name__ == "__main__": +def main() -> None: log.setup() args = parse_args() sys.exit( @@ -880,3 +896,7 @@ def align( args.std_threshold, ) ) + + +if __name__ == "__main__": + main() # pragma: no cover diff --git a/bin/opensfm_main.py b/bin/opensfm_main.py index 31249e129..2041e163d 100755 --- a/bin/opensfm_main.py +++ b/bin/opensfm_main.py @@ -1,5 +1,5 @@ import sys -from os.path import abspath, join, dirname +from os.path import abspath, dirname, join sys.path.insert(0, abspath(join(dirname(__file__), ".."))) @@ -21,7 +21,13 @@ def create_default_dataset_context( dataset.clean_up() -if __name__ == "__main__": +def main() -> None: commands.command_runner( - commands.opensfm_commands, create_default_dataset_context, dataset_choices=["opensfm"] + commands.opensfm_commands, + create_default_dataset_context, + dataset_choices=["opensfm"], ) + + +if __name__ == "__main__": + main() # pragma: no cover diff --git a/bin/plot_matches.py b/bin/plot_matches.py index 94f9d7fbf..2fe59174b 100755 --- a/bin/plot_matches.py +++ b/bin/plot_matches.py @@ -3,15 +3,13 @@ import argparse import os.path from itertools import combinations +from typing import List import matplotlib.cm as cm import matplotlib.pyplot as pl import numpy as np -from opensfm import dataset -from opensfm import features -from opensfm import io from numpy import ndarray -from typing import List +from opensfm import dataset, features, io def plot_matches(im1, im2, p1: ndarray, p2: ndarray) -> None: @@ -113,7 +111,8 @@ def plot_matches_for_images(data, image, images) -> None: pl.show() -if __name__ == "__main__": +def main() -> None: + global args, images parser = argparse.ArgumentParser(description="Plot matches between images") parser.add_argument("dataset", help="path to the dataset to be processed") parser.add_argument("--image", help="show tracks for a specific") @@ -124,12 +123,20 @@ def plot_matches_for_images(data, image, images) -> None: parser.add_argument( "--save_figs", help="save figures instead of showing them", action="store_true" ) - args: argparse.Namespace = parser.parse_args() + args = parser.parse_args() data = dataset.DataSet(args.dataset) - images: List[str] = data.images() + images = data.images() if args.graph: plot_graph(data) else: plot_matches_for_images(data, args.image, args.images) + + +args: argparse.Namespace +images: List[str] + + +if __name__ == "__main__": + main() # pragma: no cover From 925d7ffe327026d4afb0eb75134090f9f8c63a8d Mon Sep 17 00:00:00 2001 From: generatedunixname89002005307016 Date: Wed, 6 Dec 2023 23:06:23 -0800 Subject: [PATCH 051/235] upgrade pyre version in `fbcode/mapillary` - batch 1 Differential Revision: D51900922 fbshipit-source-id: 4d2baa2ad4b8555fbe1ef33e2ebaedb64bdcac4b --- opensfm/report.py | 1 - 1 file changed, 1 deletion(-) diff --git a/opensfm/report.py b/opensfm/report.py index 31cb47186..b1bf5f859 100644 --- a/opensfm/report.py +++ b/opensfm/report.py @@ -39,7 +39,6 @@ def __init__(self, data: DataSet) -> None: self.stats = self._read_stats_file("stats.json") def save_report(self, filename: str) -> None: - # pyre-fixme[28]: Unexpected keyword argument `dest`. bytestring = self.pdf.output(dest="S") if isinstance(bytestring, str): bytestring = bytestring.encode("utf8") From 6a1f95ec626f63668afe09af2b0c1cccde4c9700 Mon Sep 17 00:00:00 2001 From: Michael Waechter Date: Fri, 8 Dec 2023 11:11:51 -0800 Subject: [PATCH 052/235] add progress plotting to correspondence copier and opensfm.reconstructor Summary: To make it easier to track reconstruction progress in larger jobs, this diff adds - logging to the `opensfm.reconstructor` how many shots we already have in a map - `tqdm` logging to the most expensive loops of the `copy_view_correspondences_between_pose_graph_and_component` module. Differential Revision: D51964593 fbshipit-source-id: 08a4e81f6464329da01ba78e41d5142c7db0e848 --- opensfm/reconstruction.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/opensfm/reconstruction.py b/opensfm/reconstruction.py index 3de7ebe89..eaa6a6a15 100644 --- a/opensfm/reconstruction.py +++ b/opensfm/reconstruction.py @@ -1494,6 +1494,8 @@ def grow_reconstruction( remove_outliers(reconstruction, config, bundled_points) step["local_bundle"] = brep + logger.info(f"Reconstruction now has {len(reconstruction.shots)} shots.") + break else: logger.info("Some images can not be added") From d787a1811be3eda610090af3741c4a618e73f375 Mon Sep 17 00:00:00 2001 From: Richard Barnes Date: Fri, 8 Dec 2023 15:40:48 -0800 Subject: [PATCH 053/235] Remove extra semi colon from mapillary/opensfm/opensfm/src/geo/geo.h Summary: `-Wextra-semi` or `-Wextra-semi-stmt` If the code compiles, this is safe to land. Reviewed By: palmje Differential Revision: D51995097 fbshipit-source-id: 473fa063cd47983e6e99a85c112fb51af0ea6719 --- opensfm/src/geo/geo.h | 2 +- opensfm/src/geo/src/geo.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/opensfm/src/geo/geo.h b/opensfm/src/geo/geo.h index 053249d72..cf3c7e63e 100644 --- a/opensfm/src/geo/geo.h +++ b/opensfm/src/geo/geo.h @@ -47,4 +47,4 @@ struct TopocentricConverter { Vec3d ToLla(const Vec3d& xyz) const; Vec3d GetLlaRef() const; }; -}; // namespace geo +} // namespace geo diff --git a/opensfm/src/geo/src/geo.cc b/opensfm/src/geo/src/geo.cc index 2f07b4ad2..c80118901 100644 --- a/opensfm/src/geo/src/geo.cc +++ b/opensfm/src/geo/src/geo.cc @@ -165,7 +165,7 @@ TopocentricConverter::TopocentricConverter(const double lat, : lat_(lat), long_(longitude), alt_(alt) {} TopocentricConverter::TopocentricConverter(const Vec3d& lla) - : TopocentricConverter(lla[0], lla[1], lla[2]){}; + : TopocentricConverter(lla[0], lla[1], lla[2]){} Vec3d TopocentricConverter::ToTopocentric(const double lat, const double lon, const double alt) const { From 7f170d0dc352340295ff480378e3ac37d0179f8e Mon Sep 17 00:00:00 2001 From: Richard Barnes Date: Fri, 8 Dec 2023 18:20:27 -0800 Subject: [PATCH 054/235] Remove extra semi colon from luna/common/sampling/samplers/StatsWrapper.cpp Summary: `-Wextra-semi` or `-Wextra-semi-stmt` If the code compiles, this is safe to land. Reviewed By: palmje Differential Revision: D51995049 fbshipit-source-id: 441e8695a7d4c68d715c87a7704fa54bda53f6ab --- opensfm/src/foundation/newton_raphson.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opensfm/src/foundation/newton_raphson.h b/opensfm/src/foundation/newton_raphson.h index d418905f3..47db76d5f 100644 --- a/opensfm/src/foundation/newton_raphson.h +++ b/opensfm/src/foundation/newton_raphson.h @@ -65,7 +65,7 @@ typename TypeTraits::Values SolveDecr( const typename TypeTraits::Jacobian& d, const typename TypeTraits::Values& f) { return (d.transpose() * d).inverse() * d.transpose() * f; -}; +} template <> typename TypeTraits<1, 1>::Values SolveDecr<1, 1>( From 569f6d3a287178872277d7adcae1f5cb6eba92e3 Mon Sep 17 00:00:00 2001 From: Fabian Schenk Date: Mon, 8 Jan 2024 02:59:21 -0800 Subject: [PATCH 055/235] Rename variable to avoid shadowing Summary: This is a better renaming of what was proposed in D52582811. Reviewed By: YanNoun Differential Revision: D52596501 fbshipit-source-id: 17a4b2e3b17a2040908d16c007cea3556c7302bf --- opensfm/src/bundle/src/bundle_adjuster.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/opensfm/src/bundle/src/bundle_adjuster.cc b/opensfm/src/bundle/src/bundle_adjuster.cc index dd999ac0d..18a6dd1ed 100644 --- a/opensfm/src/bundle/src/bundle_adjuster.cc +++ b/opensfm/src/bundle/src/bundle_adjuster.cc @@ -561,17 +561,17 @@ void BundleAdjuster::Run() { ceres::Problem problem; // Add cameras - for (auto &i : cameras_) { - auto &data = i.second.GetValueData(); + for (auto &[_, cam] : cameras_) { + auto &data = cam.GetValueData(); problem.AddParameterBlock(data.data(), data.size()); // Lock parameters based on bitmask of parameters : only constant for now - if (i.second.GetParametersToOptimize().empty()) { + if (cam.GetParametersToOptimize().empty()) { problem.SetParameterBlockConstant(data.data()); } // Add a barrier for constraining transition of dual to stay in [0, 1] - const auto camera = i.second.GetValue(); + const auto camera = cam.GetValue(); if (camera.GetProjectionType() == geometry::ProjectionType::DUAL) { const auto types = camera.GetParametersTypes(); int index = -1; From a848b1f47a71da6c96dee666245ed9253ec69aa0 Mon Sep 17 00:00:00 2001 From: generatedunixname89002005307016 Date: Thu, 25 Jan 2024 19:15:07 -0800 Subject: [PATCH 056/235] suppress errors in `mapillary/opensfm` Differential Revision: D53099888 fbshipit-source-id: 2dc5a3bf14b2e97958f394f87f8dc4fb8bc1a851 --- opensfm/multiview.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/opensfm/multiview.py b/opensfm/multiview.py index 65dd3ea07..10d55dcfb 100644 --- a/opensfm/multiview.py +++ b/opensfm/multiview.py @@ -165,6 +165,7 @@ def ransac(kernel: Any, threshold: float) -> TRansacSolution: try: samples = kernel.sampling() except AttributeError: + # pyre-fixme[20]: Argument `k` expected. samples = random.sample( range(kernel.num_samples()), kernel.required_samples ) @@ -238,13 +239,16 @@ def sampling(self) -> Dict[str, Any]: samples = {} if len(self.vectors) > 0: samples["points"] = self.points[ + # pyre-fixme[20]: Argument `k` expected. random.sample(range(len(self.points)), 2), : ] samples["vectors"] = [ + # pyre-fixme[20]: Argument `k` expected. self.vectors[i] for i in random.sample(range(len(self.vectors)), 1) ] else: samples["points"] = self.points[ + # pyre-fixme[20]: Argument `k` expected. :, random.sample(range(len(self.points)), 3) ] samples["vectors"] = None From bec57f3075bb3f2ef0e7c2a29ad4d877cc1bd1d3 Mon Sep 17 00:00:00 2001 From: generatedunixname89002005307016 Date: Fri, 26 Jan 2024 19:07:33 -0800 Subject: [PATCH 057/235] suppress errors in `mapillary/opensfm` Differential Revision: D53151206 fbshipit-source-id: 04c3b8f4766a2d749b2471038e3cb1cd9b877f5d --- opensfm/multiview.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/opensfm/multiview.py b/opensfm/multiview.py index 10d55dcfb..65dd3ea07 100644 --- a/opensfm/multiview.py +++ b/opensfm/multiview.py @@ -165,7 +165,6 @@ def ransac(kernel: Any, threshold: float) -> TRansacSolution: try: samples = kernel.sampling() except AttributeError: - # pyre-fixme[20]: Argument `k` expected. samples = random.sample( range(kernel.num_samples()), kernel.required_samples ) @@ -239,16 +238,13 @@ def sampling(self) -> Dict[str, Any]: samples = {} if len(self.vectors) > 0: samples["points"] = self.points[ - # pyre-fixme[20]: Argument `k` expected. random.sample(range(len(self.points)), 2), : ] samples["vectors"] = [ - # pyre-fixme[20]: Argument `k` expected. self.vectors[i] for i in random.sample(range(len(self.vectors)), 1) ] else: samples["points"] = self.points[ - # pyre-fixme[20]: Argument `k` expected. :, random.sample(range(len(self.points)), 3) ] samples["vectors"] = None From 013956c43ffb95605845ff1858e645a00ed66e98 Mon Sep 17 00:00:00 2001 From: Richard Barnes Date: Wed, 14 Feb 2024 13:29:12 -0800 Subject: [PATCH 058/235] Remove semicolon(s) from 3 files inc loki/lacis/storage/rtree/liveindex/LokiShard.h Summary: `-Wextra-semi` or `-Wextra-semi-stmt` found an extra semi If the code compiles, this is safe to land. Reviewed By: palmje, dmm-fb Differential Revision: D53776073 fbshipit-source-id: 99e769877dd17b6ddb51e82cf48d7605668cafb7 --- opensfm/src/bundle/src/bundle_adjuster.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/opensfm/src/bundle/src/bundle_adjuster.cc b/opensfm/src/bundle/src/bundle_adjuster.cc index 18a6dd1ed..b727b6b70 100644 --- a/opensfm/src/bundle/src/bundle_adjuster.cc +++ b/opensfm/src/bundle/src/bundle_adjuster.cc @@ -18,7 +18,7 @@ bool IsRigCameraUseful(bundle::RigCamera &rig_camera) { return !(rig_camera.GetParametersToOptimize().empty() && rig_camera.GetValueData().isConstant(0.)); } -}; // namespace +} // namespace namespace bundle { BundleAdjuster::BundleAdjuster() { @@ -140,7 +140,7 @@ void BundleAdjuster::AddRigInstance( &rig_camera_exists->second, &rig_instances_.at(rig_instance_id))); } -}; +} void BundleAdjuster::AddRigCamera(const std::string &rig_camera_id, const geometry::Pose &pose, @@ -161,7 +161,7 @@ void BundleAdjuster::AddRigCamera(const std::string &rig_camera_id, if (fixed) { rig_camera.SetParametersToOptimize({}); } -}; +} void BundleAdjuster::AddRigInstancePositionPrior( const std::string &instance_id, const Vec3d &position, From 2281fd434989b28ff5c7161c389c09a111956f8d Mon Sep 17 00:00:00 2001 From: Richard Barnes Date: Wed, 14 Feb 2024 13:44:22 -0800 Subject: [PATCH 059/235] Remove semicolon(s) from 3 files inc mapillary/opensfm/opensfm/src/geometry/camera.h Summary: `-Wextra-semi` or `-Wextra-semi-stmt` found an extra semi If the code compiles, this is safe to land. Reviewed By: palmje, dmm-fb Differential Revision: D53776237 fbshipit-source-id: eb4d82dc16f32e4276887e025d29b701d3333811 --- opensfm/src/geometry/camera.h | 2 +- opensfm/src/geometry/camera_instances.h | 2 +- opensfm/src/geometry/functions.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/opensfm/src/geometry/camera.h b/opensfm/src/geometry/camera.h index 348219599..e38867d99 100644 --- a/opensfm/src/geometry/camera.h +++ b/opensfm/src/geometry/camera.h @@ -118,4 +118,4 @@ class Camera { std::pair ComputeCameraMapping(const Camera& from, const Camera& to, int width, int height); -}; // namespace geometry +} // namespace geometry diff --git a/opensfm/src/geometry/camera_instances.h b/opensfm/src/geometry/camera_instances.h index e5acf475e..ba89e6407 100644 --- a/opensfm/src/geometry/camera_instances.h +++ b/opensfm/src/geometry/camera_instances.h @@ -232,5 +232,5 @@ void Dispatch(const ProjectionType& type, IN&&... args) { default: throw std::runtime_error("Invalid ProjectionType"); } -}; +} } // namespace geometry diff --git a/opensfm/src/geometry/functions.h b/opensfm/src/geometry/functions.h index 4beb40784..58c8e8db1 100644 --- a/opensfm/src/geometry/functions.h +++ b/opensfm/src/geometry/functions.h @@ -109,4 +109,4 @@ static void ComposeFunctions(const T* in, const T* parameters, T* out) { constexpr int Index = ComposeIndex(); FUNC1::template Apply(&tmp[0], parameters + Index, out); } -}; // namespace geometry +} // namespace geometry From 072abf02f58b923d74736277c1e15af4de8c0162 Mon Sep 17 00:00:00 2001 From: Richard Barnes Date: Wed, 14 Feb 2024 16:16:41 -0800 Subject: [PATCH 060/235] Remove unused variables in mapillary/opensfm/opensfm/src/geometry/pose.h Summary: LLVM-15 has a warning `-Wunused-but-set-variable` which we treat as an error because it's so often diagnostic of a code issue. Unused variables can compromise readability or, worse, performance. This diff either (a) removes an unused variable and, possibly, it's associated code, or (b) qualifies the variable with `[[maybe_unused]]`, mostly in cases where the variable _is_ used, but, eg, in an `assert` statement that isn't present in production code. - If you approve of this diff, please use the "Accept & Ship" button :-) Reviewed By: palmje Differential Revision: D53779585 fbshipit-source-id: d651d6b4cf4dbc777f924f936e9325005c80d2ba --- opensfm/src/geometry/pose.h | 1 - 1 file changed, 1 deletion(-) diff --git a/opensfm/src/geometry/pose.h b/opensfm/src/geometry/pose.h index c015e7b7f..736563b3d 100644 --- a/opensfm/src/geometry/pose.h +++ b/opensfm/src/geometry/pose.h @@ -17,7 +17,6 @@ class Pose { virtual ~Pose() = default; Pose(const Vec3d& R, const Vec3d& t = Vec3d::Zero()) { - Mat4d T_cw = Mat4d::Identity(); SetFromWorldToCamera(R, t); } Pose(const Mat3d& R, const Vec3d& t = Vec3d::Zero()) { From 68b18f309e743f8824c93616800ddaab64bba9e8 Mon Sep 17 00:00:00 2001 From: Richard Barnes Date: Wed, 14 Feb 2024 16:26:06 -0800 Subject: [PATCH 061/235] Remove unused variables in mapillary/opensfm/opensfm/src/foundation/newton_raphson.h Summary: LLVM-15 has a warning `-Wunused-but-set-variable` which we treat as an error because it's so often diagnostic of a code issue. Unused variables can compromise readability or, worse, performance. This diff either (a) removes an unused variable and, possibly, it's associated code, or (b) qualifies the variable with `[[maybe_unused]]`, mostly in cases where the variable _is_ used, but, eg, in an `assert` statement that isn't present in production code. - If you approve of this diff, please use the "Accept & Ship" button :-) Reviewed By: palmje Differential Revision: D53779594 fbshipit-source-id: a22fbbc945140165686a74c9d0c921983ca54451 --- opensfm/src/foundation/newton_raphson.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/opensfm/src/foundation/newton_raphson.h b/opensfm/src/foundation/newton_raphson.h index 47db76d5f..63b44e976 100644 --- a/opensfm/src/foundation/newton_raphson.h +++ b/opensfm/src/foundation/newton_raphson.h @@ -44,7 +44,6 @@ template struct FiniteDiff { static typename TypeTraits<1, 1>::Jacobian Derivative( const F& func, typename TypeTraits<1, 1>::Values& x) { - typename TypeTraits<1, 1>::Jacobian jacobian; constexpr auto eps = 1e-15; return (func(x + eps) - func(x)) / eps; } @@ -77,7 +76,6 @@ template > typename TypeTraits::Values NewtonRaphson( const F& func, const typename TypeTraits::Values& initial_value, int iterations, double tol = 1e-6) { - constexpr auto eps = std::numeric_limits::epsilon(); auto current_value = initial_value; for (int i = 0; i < iterations; ++i) { const auto at_current_value = func(current_value); From 21ed668ed496c5b4f7477e7985579b5112099a6a Mon Sep 17 00:00:00 2001 From: Richard Barnes Date: Wed, 14 Feb 2024 16:48:58 -0800 Subject: [PATCH 062/235] Remove semicolon(s) from 3 files inc mapillary/opensfm/opensfm/src/geometry/pose.h Summary: `-Wextra-semi` or `-Wextra-semi-stmt` found an extra semi If the code compiles, this is safe to land. Reviewed By: palmje, dmm-fb Differential Revision: D53776244 fbshipit-source-id: 83a21ed4c3a954d7389b084a68912fe229bff40e --- opensfm/src/geometry/pose.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opensfm/src/geometry/pose.h b/opensfm/src/geometry/pose.h index 736563b3d..69f95488f 100644 --- a/opensfm/src/geometry/pose.h +++ b/opensfm/src/geometry/pose.h @@ -49,7 +49,7 @@ class Pose { Vec3d TranslationCameraToWorld() const { return cam_to_world_.block<3, 1>(0, 3); - }; + } Vec3d GetOrigin() const { return TranslationCameraToWorld(); } virtual void SetOrigin(const Vec3d& origin) { From 4a74bc3b1f4043079099100e969e558d559acbfa Mon Sep 17 00:00:00 2001 From: generatedunixname89002005287564 Date: Wed, 28 Feb 2024 03:10:47 -0800 Subject: [PATCH 063/235] mapillary (463897787004193082) Reviewed By: paulinus Differential Revision: D54105414 fbshipit-source-id: a76d6dcd36c8d73a04ec93cfb8aabf2ca9eab2de --- opensfm/src/bundle/error/projection_errors.h | 6 +-- opensfm/src/bundle/reconstruction_alignment.h | 6 +-- opensfm/src/bundle/src/bundle_adjuster.cc | 10 ++-- .../bundle/test/reprojection_errors_test.cc | 18 +++---- opensfm/src/dense/depthmap_bind.h | 8 +-- opensfm/src/features/src/hahog.cc | 11 ++-- opensfm/src/features/src/matching.cc | 3 +- opensfm/src/foundation/numeric.h | 5 +- opensfm/src/foundation/python_types.h | 12 ++--- opensfm/src/geometry/covariance.h | 4 +- opensfm/src/geometry/src/covariance.cc | 4 +- opensfm/src/geometry/src/triangulation.cc | 7 +-- .../geometry/test/camera_functions_test.cc | 2 +- opensfm/src/geometry/test/covariance_test.cc | 2 +- opensfm/src/map/ground_control_points.h | 4 +- opensfm/src/map/pybind_utils.h | 20 ++++--- opensfm/src/map/src/map.cc | 6 +-- opensfm/src/sfm/retriangulation.h | 4 +- opensfm/src/sfm/src/ba_helpers.cc | 3 +- opensfm/src/sfm/src/retriangulation.cc | 4 +- opensfm/src/sfm/src/tracks_helpers.cc | 4 +- opensfm/src/sfm/test/tracks_helpers_test.cc | 8 +-- opensfm/src/sfm/tracks_helpers.h | 4 +- opensfm/src/third_party/akaze/lib/AKAZE.cpp | 52 ++++++++++++------- opensfm/src/third_party/akaze/lib/fed.cpp | 11 ++-- .../akaze/lib/nldiffusion_functions.cpp | 29 +++++++---- opensfm/src/third_party/akaze/lib/utils.cpp | 21 +++++--- 27 files changed, 148 insertions(+), 120 deletions(-) diff --git a/opensfm/src/bundle/error/projection_errors.h b/opensfm/src/bundle/error/projection_errors.h index c8bf8f239..20d6fdb87 100644 --- a/opensfm/src/bundle/error/projection_errors.h +++ b/opensfm/src/bundle/error/projection_errors.h @@ -261,10 +261,10 @@ class ReprojectionError3DAnalytic Vec3d transformed; /* Error only */ if (!jacobians) { - geometry::PoseFunctor::Forward(point, rig_instance, &transformed[0]); + geometry::PoseFunctor::Forward(point, rig_instance, transformed.data()); if (use_rig_camera_) { - geometry::PoseFunctor::Forward(&transformed[0], rig_camera, - &transformed[0]); + geometry::PoseFunctor::Forward(transformed.data(), rig_camera, + transformed.data()); } transformed.normalize(); } /* Jacobian + Error */ diff --git a/opensfm/src/bundle/reconstruction_alignment.h b/opensfm/src/bundle/reconstruction_alignment.h index 8b108401a..a27073439 100644 --- a/opensfm/src/bundle/reconstruction_alignment.h +++ b/opensfm/src/bundle/reconstruction_alignment.h @@ -375,8 +375,8 @@ struct RACommonCameraError { class ReconstructionAlignment { public: - ReconstructionAlignment() {} - virtual ~ReconstructionAlignment() {} + ReconstructionAlignment() = default; + virtual ~ReconstructionAlignment() = default; RAShot GetShot(const std::string &id) { return shots_[id]; } @@ -520,7 +520,7 @@ class ReconstructionAlignment { new ceres::AutoDiffCostFunction( new RAAbsolutePositionError(a.position, a.std_deviation)); - problem.AddResidualBlock(cost_function, NULL, a.shot->parameters); + problem.AddResidualBlock(cost_function, nullptr, a.shot->parameters); } // Add relative-absolute position errors diff --git a/opensfm/src/bundle/src/bundle_adjuster.cc b/opensfm/src/bundle/src/bundle_adjuster.cc index b727b6b70..40aac3347 100644 --- a/opensfm/src/bundle/src/bundle_adjuster.cc +++ b/opensfm/src/bundle/src/bundle_adjuster.cc @@ -424,7 +424,7 @@ ceres::LossFunction *CreateLossFunction(std::string name, double threshold) { } else if (name.compare("ArctanLoss") == 0) { return new ceres::ArctanLoss(threshold); } - return NULL; + return nullptr; } void BundleAdjuster::AddLinearMotion(const std::string &shot0_id, @@ -1094,9 +1094,8 @@ void BundleAdjuster::ComputeCovariances(ceres::Problem *problem) { std::vector> covariance_blocks; for (auto &i : shots_) { - covariance_blocks.push_back( - std::make_pair(i.second.GetRigInstance()->GetValueData().data(), - i.second.GetRigInstance()->GetValueData().data())); + covariance_blocks.emplace_back(i.second.GetRigInstance()->GetValueData().data(), + i.second.GetRigInstance()->GetValueData().data()); } bool worked = covariance.Compute(covariance_blocks, problem); @@ -1129,7 +1128,8 @@ void BundleAdjuster::ComputeCovariances(ceres::Problem *problem) { break; } // stop after first Nan value - if (!computed) break; + if (!computed) { break; +} } } diff --git a/opensfm/src/bundle/test/reprojection_errors_test.cc b/opensfm/src/bundle/test/reprojection_errors_test.cc index cfb9edb64..581296c03 100644 --- a/opensfm/src/bundle/test/reprojection_errors_test.cc +++ b/opensfm/src/bundle/test/reprojection_errors_test.cc @@ -7,7 +7,7 @@ class ReprojectionError2DFixtureBase : public ::testing::Test { public: - typedef Eigen::AutoDiffScalar AScalar; + using AScalar = Eigen::AutoDiffScalar; ReprojectionError2DFixtureBase() { observed << 0.5, 0.5; } constexpr static int size_residual = 2; @@ -118,7 +118,7 @@ TEST_F(ReprojectionError2DFixture, BrownAnalyticErrorEvaluatesOK) { // focal, ar, cx, cy, k1, k2, k3, p1, p2 constexpr std::array camera{0.3, 1.0, 0.001, -0.02, 0.1, -0.03, 0.001, -0.005, 0.001}; - RunTest(geometry::ProjectionType::BROWN, &camera[0]); + RunTest(geometry::ProjectionType::BROWN, camera.data()); } TEST_F(ReprojectionError2DFixture, PerspectiveAnalyticErrorEvaluatesOK) { @@ -126,7 +126,7 @@ TEST_F(ReprojectionError2DFixture, PerspectiveAnalyticErrorEvaluatesOK) { // focal, k1, k2 constexpr std::array camera{0.3, 0.1, -0.03}; - RunTest(geometry::ProjectionType::PERSPECTIVE, &camera[0]); + RunTest(geometry::ProjectionType::PERSPECTIVE, camera.data()); } TEST_F(ReprojectionError2DFixture, FisheyeAnalyticErrorEvaluatesOK) { @@ -134,7 +134,7 @@ TEST_F(ReprojectionError2DFixture, FisheyeAnalyticErrorEvaluatesOK) { // focal, k1, k2, k3 constexpr std::array camera{0.3, 0.1, -0.03}; - RunTest(geometry::ProjectionType::FISHEYE, &camera[0]); + RunTest(geometry::ProjectionType::FISHEYE, camera.data()); } TEST_F(ReprojectionError2DFixture, FisheyeOpencvAnalyticErrorEvaluatesOK) { @@ -143,7 +143,7 @@ TEST_F(ReprojectionError2DFixture, FisheyeOpencvAnalyticErrorEvaluatesOK) { // focal, ar, cx, cy, k1, k2, k3, k4 constexpr std::array camera{0.3, 1.0, 0.001, -0.02, 0.1, -0.03, 0.001, -0.005}; - RunTest(geometry::ProjectionType::FISHEYE_OPENCV, &camera[0]); + RunTest(geometry::ProjectionType::FISHEYE_OPENCV, camera.data()); } TEST_F(ReprojectionError2DFixture, Fisheye62AnalyticErrorEvaluatesOK) { @@ -153,7 +153,7 @@ TEST_F(ReprojectionError2DFixture, Fisheye62AnalyticErrorEvaluatesOK) { constexpr std::array camera{0.3, 1.0, 0.001, -0.02, 0.1, -0.03, 0.001, -0.005, 0.01, 0.006, 0.02, 0.003}; - RunTest(geometry::ProjectionType::FISHEYE62, &camera[0]); + RunTest(geometry::ProjectionType::FISHEYE62, camera.data()); } TEST_F(ReprojectionError2DFixture, Fisheye624AnalyticErrorEvaluatesOK) { @@ -163,7 +163,7 @@ TEST_F(ReprojectionError2DFixture, Fisheye624AnalyticErrorEvaluatesOK) { constexpr std::array camera{ 0.3, 1.0, 0.001, -0.02, 0.1, -0.03, 0.001, -0.005, 0.01, 0.006, 0.02, 0.003, 0.001, -0.009, -0.01, 0.03}; - RunTest(geometry::ProjectionType::FISHEYE624, &camera[0]); + RunTest(geometry::ProjectionType::FISHEYE624, camera.data()); } TEST_F(ReprojectionError2DFixture, DualAnalyticErrorEvaluatesOK) { @@ -171,14 +171,14 @@ TEST_F(ReprojectionError2DFixture, DualAnalyticErrorEvaluatesOK) { // transition, focal, k1, k2 constexpr std::array camera{0.5, 0.3, 0.1, -0.03}; - RunTest(geometry::ProjectionType::DUAL, &camera[0]); + RunTest(geometry::ProjectionType::DUAL, camera.data()); } class ReprojectionError3DFixture : public ::testing::Test { public: static constexpr int size = 3; - typedef Eigen::AutoDiffScalar AScalar; + using AScalar = Eigen::AutoDiffScalar; ReprojectionError3DFixture() { observed << 0.5, 0.5; } void SetupADiff() { diff --git a/opensfm/src/dense/depthmap_bind.h b/opensfm/src/dense/depthmap_bind.h index 2c62127fe..007178394 100644 --- a/opensfm/src/dense/depthmap_bind.h +++ b/opensfm/src/dense/depthmap_bind.h @@ -128,10 +128,10 @@ class DepthmapPrunerWrapper { py::list retn; int n = int(points.size()) / 3; - retn.append(py_array_from_data(&points[0], n, 3)); - retn.append(py_array_from_data(&normals[0], n, 3)); - retn.append(py_array_from_data(&colors[0], n, 3)); - retn.append(py_array_from_data(&labels[0], n)); + retn.append(py_array_from_data(points.data(), n, 3)); + retn.append(py_array_from_data(normals.data(), n, 3)); + retn.append(py_array_from_data(colors.data(), n, 3)); + retn.append(py_array_from_data(labels.data(), n)); return std::move(retn); } diff --git a/opensfm/src/features/src/hahog.cc b/opensfm/src/features/src/hahog.cc index 6f8002c64..3a6aace8f 100644 --- a/opensfm/src/features/src/hahog.cc +++ b/opensfm/src/features/src/hahog.cc @@ -49,7 +49,8 @@ vl_size run_non_maxima_suppression(VlCovDet *covdet, vl_size num_features, double dy_ = features[j].frame.y - y; double sigma_ = features[j].frame.a11; double score_ = features[j].peakScore; - if (score_ == 0) continue; + if (score_ == 0) { continue; +} if (sigma < (1 + tol) * sigma_ && sigma_ < (1 + tol) * sigma && vl_abs_d(dx_) < tol * sigma && vl_abs_d(dy_) < tol * sigma && vl_abs_d(score) > vl_abs_d(score_)) { @@ -178,15 +179,15 @@ py::tuple hahog(foundation::pyarray_f image, float peak_threshold, points[4 * i + 2] = size; points[4 * i + 3] = angle; - vl_covdet_extract_patch_for_frame(covdet, &patch[0], patchResolution, + vl_covdet_extract_patch_for_frame(covdet, patch.data(), patchResolution, patchRelativeExtent, patchRelativeSmoothing, frame); - vl_imgradient_polar_f(&patchXY[0], &patchXY[1], 2, 2 * patchSide, - &patch[0], patchSide, patchSide, patchSide); + vl_imgradient_polar_f(patchXY.data(), &patchXY[1], 2, 2 * patchSide, + patch.data(), patchSide, patchSide, patchSide); vl_sift_calc_raw_descriptor( - sift, &patchXY[0], &desc[dimension * i], (int)patchSide, + sift, patchXY.data(), &desc[dimension * i], (int)patchSide, (int)patchSide, (double)(patchSide - 1) / 2, (double)(patchSide - 1) / 2, (double)patchRelativeExtent / (3.0 * (4 + 1) / 2) / patchStep, diff --git a/opensfm/src/features/src/matching.cc b/opensfm/src/features/src/matching.cc index d759b7647..0623cd452 100644 --- a/opensfm/src/features/src/matching.cc +++ b/opensfm/src/features/src/matching.cc @@ -66,7 +66,8 @@ void MatchUsingWords(const cv::Mat &f1, const cv::Mat &w1, const cv::Mat &f2, } checks++; } - if (checks >= max_checks) break; + if (checks >= max_checks) { break; +} } if (best_distance[i] < lowes_ratio * second_best_distance[i]) { tmp_match.at(0, 0) = i; diff --git a/opensfm/src/foundation/numeric.h b/opensfm/src/foundation/numeric.h index 19cdb8bef..ba42e1c8b 100644 --- a/opensfm/src/foundation/numeric.h +++ b/opensfm/src/foundation/numeric.h @@ -35,11 +35,12 @@ bool SolveAX0(const MAT& A, VEC* solution) { // Some nullspace will make a solution const bool some_nullspace = ratio > minimum_ratio; - if (some_nullspace) + if (some_nullspace) { return true; - else + } else { return false; } +} Eigen::Matrix3d SkewMatrix(const Eigen::Vector3d& v); template diff --git a/opensfm/src/foundation/python_types.h b/opensfm/src/foundation/python_types.h index c56d71e88..35855cc28 100644 --- a/opensfm/src/foundation/python_types.h +++ b/opensfm/src/foundation/python_types.h @@ -10,12 +10,10 @@ namespace py = pybind11; namespace foundation { -typedef py::array_t pyarray_f; -typedef py::array_t - pyarray_d; -typedef py::array_t pyarray_int; -typedef py::array_t - pyarray_uint8; +using pyarray_f = py::array_t; +using pyarray_d = py::array_t; +using pyarray_int = py::array_t; +using pyarray_uint8 = py::array_t; template py::array_t py_array_from_data(const T *data, size_t shape0) { @@ -41,7 +39,7 @@ py::array_t py_array_from_data(const T *data, size_t shape0, size_t shape1, template py::array_t py_array_from_vector(const std::vector &v) { - const T *data = v.size() ? &v[0] : NULL; + const T *data = v.size() ? v.data() : NULL; return py_array_from_data(data, v.size()); } diff --git a/opensfm/src/geometry/covariance.h b/opensfm/src/geometry/covariance.h index 8c6a0b52f..af6d747b9 100644 --- a/opensfm/src/geometry/covariance.h +++ b/opensfm/src/geometry/covariance.h @@ -3,8 +3,7 @@ #include #include -namespace geometry { -namespace covariance { +namespace geometry::covariance { using PointJacobian = Eigen::Matrix; std::pair ComputeJacobianReprojectionError( const Camera& camera, const Pose& pose, const Vec2d& observation, @@ -12,5 +11,4 @@ std::pair ComputeJacobianReprojectionError( std::pair ComputePointInverseCovariance( const std::vector& cameras, const std::vector& poses, const std::vector& observations, const Vec3d& point); -} // namespace covariance } // namespace geometry diff --git a/opensfm/src/geometry/src/covariance.cc b/opensfm/src/geometry/src/covariance.cc index c88942b61..b86fabf3d 100644 --- a/opensfm/src/geometry/src/covariance.cc +++ b/opensfm/src/geometry/src/covariance.cc @@ -1,7 +1,6 @@ #include -namespace geometry { -namespace covariance { +namespace geometry::covariance { using PointJacobian = Eigen::Matrix; std::pair ComputeJacobianReprojectionError( const Camera& camera, const Pose& pose, const Vec2d& observation, @@ -39,5 +38,4 @@ std::pair ComputePointInverseCovariance( return std::make_pair(covariance, sigma2); } -} // namespace covariance } // namespace geometry diff --git a/opensfm/src/geometry/src/triangulation.cc b/opensfm/src/geometry/src/triangulation.cc index 1723731fa..470ea71dd 100644 --- a/opensfm/src/geometry/src/triangulation.cc +++ b/opensfm/src/geometry/src/triangulation.cc @@ -5,15 +5,16 @@ #include #include #include -#include +#include double AngleBetweenVectors(const Eigen::Vector3d &u, const Eigen::Vector3d &v) { double c = (u.dot(v)) / sqrt(u.dot(u) * v.dot(v)); - if (std::fabs(c) >= 1.0) + if (std::fabs(c) >= 1.0) { return 0.0; - else + } else { return acos(c); } +} Eigen::Vector4d TriangulateBearingsDLTSolve( const Eigen::Matrix &bearings, diff --git a/opensfm/src/geometry/test/camera_functions_test.cc b/opensfm/src/geometry/test/camera_functions_test.cc index d851c28dd..975ee9e9f 100644 --- a/opensfm/src/geometry/test/camera_functions_test.cc +++ b/opensfm/src/geometry/test/camera_functions_test.cc @@ -305,7 +305,7 @@ class CameraDerivativesFixture : public ::testing::Test { Vec2d principal_point; double point[3]; - typedef Eigen::AutoDiffScalar AScalar; + using AScalar = Eigen::AutoDiffScalar; AScalar point_adiff[3]; VecX camera_adiff; diff --git a/opensfm/src/geometry/test/covariance_test.cc b/opensfm/src/geometry/test/covariance_test.cc index 9a235bfac..0049e27d9 100644 --- a/opensfm/src/geometry/test/covariance_test.cc +++ b/opensfm/src/geometry/test/covariance_test.cc @@ -70,7 +70,7 @@ class CovarianceFixture : public ::testing::Test { const double focal{1.0}; double point[3]; - typedef Eigen::AutoDiffScalar AScalar; + using AScalar = Eigen::AutoDiffScalar; AScalar point_adiff[3]; AScalar projection_expected[2]; Vec2d observation; diff --git a/opensfm/src/map/ground_control_points.h b/opensfm/src/map/ground_control_points.h index bab86d74a..c14a07b6e 100644 --- a/opensfm/src/map/ground_control_points.h +++ b/opensfm/src/map/ground_control_points.h @@ -25,7 +25,7 @@ struct GroundControlPointObservation { GroundControlPointObservation() = default; GroundControlPointObservation(const ShotId& shot_id, const Vec2d& proj) : shot_id_(shot_id), projection_(proj) {} - ShotId shot_id_ = ""; + ShotId shot_id_; Vec2d projection_ = Vec2d::Zero(); LandmarkUniqueId uid_ = 0; }; @@ -42,7 +42,7 @@ struct GroundControlPoint { ground control point is used for computing map merging metrics */ GroundControlPoint() = default; - LandmarkId id_ = ""; + LandmarkId id_; LandmarkUniqueId survey_point_id_ = 0; bool has_altitude_ = false; AlignedVector observations_; diff --git a/opensfm/src/map/pybind_utils.h b/opensfm/src/map/pybind_utils.h index 817d1a16a..414d9ca74 100644 --- a/opensfm/src/map/pybind_utils.h +++ b/opensfm/src/map/pybind_utils.h @@ -68,10 +68,11 @@ iterator make_value_iterator(Iterator first, Sentinel last, Extra &&... extra) { .def("__iter__", [](state &s) -> state & { return s; }) .def("__next__", [](state &s) -> KeyType { - if (!s.first_or_done) + if (!s.first_or_done) { ++s.it; - else + } else { s.first_or_done = false; +} if (s.it == s.end) { s.first_or_done = true; throw stop_iteration(); @@ -99,10 +100,11 @@ iterator make_ref_value_iterator(Iterator first, Sentinel last, .def("__iter__", [](state &s) -> state & { return s; }) .def("__next__", [](state &s) -> KeyType { - if (!s.first_or_done) + if (!s.first_or_done) { ++s.it; - else + } else { s.first_or_done = false; +} if (s.it == s.end) { s.first_or_done = true; throw stop_iteration(); @@ -131,10 +133,11 @@ iterator make_ref_iterator(Iterator first, Sentinel last, Extra &&... extra) { .def("__iter__", [](state &s) -> state & { return s; }) .def("__next__", [](state &s) -> KeyType { - if (!s.first_or_done) + if (!s.first_or_done) { ++s.it; - else + } else { s.first_or_done = false; +} if (s.it == s.end) { s.first_or_done = true; throw stop_iteration(); @@ -160,10 +163,11 @@ iterator make_ptr_iterator(Iterator first, Sentinel last, Extra &&... extra) { .def("__iter__", [](state &s) -> state & { return s; }) .def("__next__", [](state &s) -> ValueType { - if (!s.first_or_done) + if (!s.first_or_done) { ++s.it; - else + } else { s.first_or_done = false; +} if (s.it == s.end) { s.first_or_done = true; throw stop_iteration(); diff --git a/opensfm/src/map/src/map.cc b/opensfm/src/map/src/map.cc index cce614ffc..e8773ca2c 100644 --- a/opensfm/src/map/src/map.cc +++ b/opensfm/src/map/src/map.cc @@ -320,8 +320,8 @@ void Map::RemoveLandmark(const LandmarkId& lm_id) { } geometry::Camera& Map::CreateCamera(const geometry::Camera& cam) { - auto it = cameras_.emplace(std::make_pair(cam.id, cam)); - bias_.emplace(std::make_pair(cam.id, geometry::Similarity())); + auto it = cameras_.emplace(cam.id, cam); + bias_.emplace(cam.id, geometry::Similarity()); return it.first->second; } @@ -413,7 +413,7 @@ RigCamera& Map::CreateRigCamera(const map::RigCamera& rig_camera) { throw std::runtime_error("RigCamera " + rig_camera.id + " already exists."); } - auto it = rig_cameras_.emplace(std::make_pair(rig_camera.id, rig_camera)); + auto it = rig_cameras_.emplace(rig_camera.id, rig_camera); return it.first->second; } diff --git a/opensfm/src/sfm/retriangulation.h b/opensfm/src/sfm/retriangulation.h index 100a64ca0..c1e703ca2 100644 --- a/opensfm/src/sfm/retriangulation.h +++ b/opensfm/src/sfm/retriangulation.h @@ -2,9 +2,7 @@ #include #include -namespace sfm { -namespace retriangulation { +namespace sfm::retriangulation { void RealignMaps(const map::Map& reference, map::Map& to_align, bool update_points); -} // namespace retriangulation } // namespace sfm diff --git a/opensfm/src/sfm/src/ba_helpers.cc b/opensfm/src/sfm/src/ba_helpers.cc index e06692840..d0aca260f 100644 --- a/opensfm/src/sfm/src/ba_helpers.cc +++ b/opensfm/src/sfm/src/ba_helpers.cc @@ -852,7 +852,8 @@ void BAHelpers::AlignmentConstraints( // Triangulated vs measured points if (!gcp.empty() && config["bundle_use_gcp"].cast()) { for (const auto& point : gcp) { - if (point.lla_.empty()) continue; + if (point.lla_.empty()) { continue; +} Vec3d coordinates; if (TriangulateGCP(point, shots, coordinates)) { Xp.row(idx) = topocentricConverter.ToTopocentric(point.GetLlaVec3d()); diff --git a/opensfm/src/sfm/src/retriangulation.cc b/opensfm/src/sfm/src/retriangulation.cc index 78c30c447..006189b32 100644 --- a/opensfm/src/sfm/src/retriangulation.cc +++ b/opensfm/src/sfm/src/retriangulation.cc @@ -5,8 +5,7 @@ #include #include -namespace sfm { -namespace retriangulation { +namespace sfm::retriangulation { void RealignMaps(const map::Map& map_from, map::Map& map_to, bool update_points) { const auto& map_from_shots = map_from.GetShots(); @@ -114,5 +113,4 @@ void RealignMaps(const map::Map& map_from, map::Map& map_to, map_to.RemoveShot(shot_id); } } -} // namespace retriangulation } // namespace sfm diff --git a/opensfm/src/sfm/src/tracks_helpers.cc b/opensfm/src/sfm/src/tracks_helpers.cc index 27e4ff967..2346bcc94 100644 --- a/opensfm/src/sfm/src/tracks_helpers.cc +++ b/opensfm/src/sfm/src/tracks_helpers.cc @@ -3,8 +3,7 @@ #include #include -namespace sfm { -namespace tracks_helpers { +namespace sfm::tracks_helpers { std::unordered_map CountTracksPerShot( const map::TracksManager& manager, const std::vector& shots, const std::vector& tracks) { @@ -43,5 +42,4 @@ void RemoveConnections(map::TracksManager& manager, const map::ShotId& shot_id, manager.RemoveObservation(shot_id, connection); } } -} // namespace tracks_helpers } // namespace sfm diff --git a/opensfm/src/sfm/test/tracks_helpers_test.cc b/opensfm/src/sfm/test/tracks_helpers_test.cc index 7420d08bb..baee75dd8 100644 --- a/opensfm/src/sfm/test/tracks_helpers_test.cc +++ b/opensfm/src/sfm/test/tracks_helpers_test.cc @@ -18,11 +18,11 @@ class TracksHelpersTest : public ::testing::Test { track["2"] = o2; track["3"] = o3; - connections_add.push_back("1"); - connections_add.push_back("2"); - connections_add.push_back("3"); + connections_add.emplace_back("1"); + connections_add.emplace_back("2"); + connections_add.emplace_back("3"); - connections_remove.push_back("1"); + connections_remove.emplace_back("1"); } map::TracksManager manager; diff --git a/opensfm/src/sfm/tracks_helpers.h b/opensfm/src/sfm/tracks_helpers.h index 42e7f5f00..cadc91ea0 100644 --- a/opensfm/src/sfm/tracks_helpers.h +++ b/opensfm/src/sfm/tracks_helpers.h @@ -9,8 +9,7 @@ #include -namespace sfm { -namespace tracks_helpers { +namespace sfm::tracks_helpers { std::unordered_map CountTracksPerShot( const map::TracksManager& manager, const std::vector& shots, const std::vector& tracks); @@ -18,5 +17,4 @@ void AddConnections(map::TracksManager& manager, const map::ShotId& shot_id, const std::vector& connections); void RemoveConnections(map::TracksManager& manager, const map::ShotId& shot_id, const std::vector& connections); -} // namespace tracks_helpers } // namespace sfm diff --git a/opensfm/src/third_party/akaze/lib/AKAZE.cpp b/opensfm/src/third_party/akaze/lib/AKAZE.cpp index 26472fea2..32f1b0ae8 100644 --- a/opensfm/src/third_party/akaze/lib/AKAZE.cpp +++ b/opensfm/src/third_party/akaze/lib/AKAZE.cpp @@ -165,8 +165,9 @@ int AKAZE::Create_Nonlinear_Scale_Space(const cv::Mat& img) { } // Perform FED n inner steps - for (int j = 0; j < nsteps_[i-1]; j++) + for (int j = 0; j < nsteps_[i-1]; j++) { nld_step_scalar(evolution_[i].Lt, evolution_[i].Lflow, evolution_[i].Lstep, tsteps_[i-1][j]); +} } t2 = cv::getTickCount(); @@ -241,8 +242,9 @@ void AKAZE::Compute_Determinant_Hessian_Response() { const float* lxy = evolution_[i].Lxy.ptr(ix); const float* lyy = evolution_[i].Lyy.ptr(ix); float* ldet = evolution_[i].Ldet.ptr(ix); - for (int jx = 0; jx < evolution_[i].Ldet.cols; jx++) + for (int jx = 0; jx < evolution_[i].Ldet.cols; jx++) { ldet[jx] = lxx[jx]*lyy[jx]-lxy[jx]*lxy[jx]; +} } } } @@ -391,8 +393,9 @@ void AKAZE::Find_Scale_Space_Extrema(std::vector& kpts) { } } - if (is_repeated == false) + if (is_repeated == false) { kpts.push_back(point); +} } // Keep only the k-best keypoints @@ -583,10 +586,11 @@ void AKAZE::Compute_Descriptors(std::vector& kpts, cv::Mat& desc) #pragma omp parallel for #endif for (int i = 0; i < (int)(kpts.size()); i++) { - if (options_.descriptor_size == 0) + if (options_.descriptor_size == 0) { Get_Upright_MLDB_Full_Descriptor(kpts[i], desc.ptr(i)); - else + } else { Get_Upright_MLDB_Descriptor_Subset(kpts[i], desc.ptr(i)); +} } } break; @@ -597,10 +601,11 @@ void AKAZE::Compute_Descriptors(std::vector& kpts, cv::Mat& desc) #endif for (int i = 0; i < (int)(kpts.size()); i++) { Compute_Main_Orientation(kpts[i]); - if (options_.descriptor_size == 0) + if (options_.descriptor_size == 0) { Get_MLDB_Full_Descriptor(kpts[i], desc.ptr(i)); - else + } else { Get_MLDB_Descriptor_Subset(kpts[i], desc.ptr(i)); +} } } break; @@ -843,9 +848,10 @@ void AKAZE::Get_SURF_Descriptor_64(const cv::KeyPoint& kpt, float *desc) const { // convert to unit vector len = sqrt(len); - for (int i = 0; i < dsize; i++) + for (int i = 0; i < dsize; i++) { desc[i] /= len; } +} /* ************************************************************************* */ void AKAZE::Get_MSURF_Upright_Descriptor_64(const cv::KeyPoint& kpt, float *desc) const { @@ -954,9 +960,10 @@ void AKAZE::Get_MSURF_Upright_Descriptor_64(const cv::KeyPoint& kpt, float *desc // convert to unit vector len = sqrt(len); - for (int i = 0; i < dsize; i++) + for (int i = 0; i < dsize; i++) { desc[i] /= len; } +} /* ************************************************************************* */ void AKAZE::Get_MSURF_Descriptor_64(const cv::KeyPoint& kpt, float *desc) const { @@ -1069,9 +1076,10 @@ void AKAZE::Get_MSURF_Descriptor_64(const cv::KeyPoint& kpt, float *desc) const // convert to unit vector len = sqrt(len); - for (int i = 0; i < dsize; i++) + for (int i = 0; i < dsize; i++) { desc[i] /= len; } +} /* ************************************************************************* */ void AKAZE::Get_MLDB_Full_Descriptor(const cv::KeyPoint& kpt, unsigned char* desc) const { @@ -1170,11 +1178,13 @@ void AKAZE::MLDB_Fill_Values(float* values, int sample_step, int level, values[valpos] = di; - if (nr_channels > 1) + if (nr_channels > 1) { values[valpos + 1] = dx; +} - if (nr_channels > 2) + if (nr_channels > 2) { values[valpos + 2] = dy; +} valpos += nr_channels; } @@ -1229,11 +1239,13 @@ void AKAZE::MLDB_Fill_Upright_Values(float* values, int sample_step, int level, values[valpos] = di; - if (nr_channels > 1) + if (nr_channels > 1) { values[valpos + 1] = dx; +} - if (nr_channels > 2) + if (nr_channels > 2) { values[valpos + 2] = dy; +} valpos += nr_channels; } @@ -1569,16 +1581,20 @@ void libAKAZE::generateDescriptorSubsample(cv::Mat& sampleList, cv::Mat& compari /* ************************************************************************* */ void libAKAZE::check_descriptor_limits(int &x, int &y, int width, int height) { - if (x < 0) + if (x < 0) { x = 0; +} - if (y < 0) + if (y < 0) { y = 0; +} - if (x > width-1) + if (x > width-1) { x = width-1; +} - if (y > height-1) + if (y > height-1) { y = height-1; } +} diff --git a/opensfm/src/third_party/akaze/lib/fed.cpp b/opensfm/src/third_party/akaze/lib/fed.cpp index 7973af6b8..ac67fa1c3 100644 --- a/opensfm/src/third_party/akaze/lib/fed.cpp +++ b/opensfm/src/third_party/akaze/lib/fed.cpp @@ -66,14 +66,16 @@ int fed_tau_internal(const int n, const float scale, const float tau_max, float c = 0.0, d = 0.0; // Time savers vector tauh; // Helper vector for unsorted taus - if (n <= 0) + if (n <= 0) { return 0; +} // Allocate memory for the time step size tau = vector(n); - if (reordering) + if (reordering) { tauh = vector(n); +} // Compute time saver c = 1.0f / (4.0f * (float)n + 2.0f); @@ -83,10 +85,11 @@ int fed_tau_internal(const int n, const float scale, const float tau_max, for (int k = 0; k < n; ++k) { float h = cos(M_PI * (2.0f * (float)k + 1.0f) * c); - if (reordering) + if (reordering) { tauh[k] = d / (h * h); - else + } else { tau[k] = d / (h * h); +} } // Permute list of time steps according to chosen reordering function diff --git a/opensfm/src/third_party/akaze/lib/nldiffusion_functions.cpp b/opensfm/src/third_party/akaze/lib/nldiffusion_functions.cpp index 1fdab7b95..3981d455c 100644 --- a/opensfm/src/third_party/akaze/lib/nldiffusion_functions.cpp +++ b/opensfm/src/third_party/akaze/lib/nldiffusion_functions.cpp @@ -33,11 +33,13 @@ void gaussian_2D_convolution(const cv::Mat& src, cv::Mat& dst, size_t ksize_x, } // The kernel size must be and odd number - if ((ksize_x % 2) == 0) + if ((ksize_x % 2) == 0) { ksize_x += 1; +} - if ((ksize_y % 2) == 0) + if ((ksize_y % 2) == 0) { ksize_y += 1; +} // Perform the Gaussian Smoothing with border replication cv::GaussianBlur(src, dst, cv::Size(ksize_x, ksize_y), sigma, sigma, cv::BORDER_REPLICATE); @@ -58,8 +60,9 @@ void pm_g1(const cv::Mat& Lx, const cv::Mat& Ly, cv::Mat& dst, const float k) { const float* Lx_row = Lx.ptr(y); const float* Ly_row = Ly.ptr(y); float* dst_row = dst.ptr(y); - for (int x = 0; x < sz.width; x++) + for (int x = 0; x < sz.width; x++) { dst_row[x] = (-inv_k*(Lx_row[x]*Lx_row[x] + Ly_row[x]*Ly_row[x])); +} } cv::exp(dst, dst); @@ -74,8 +77,9 @@ void pm_g2(const cv::Mat& Lx, const cv::Mat& Ly, cv::Mat& dst, const float k) { const float* Lx_row = Lx.ptr(y); const float* Ly_row = Ly.ptr(y); float* dst_row = dst.ptr(y); - for (int x = 0; x < sz.width; x++) + for (int x = 0; x < sz.width; x++) { dst_row[x] = 1.0 / (1.0+inv_k*(Lx_row[x]*Lx_row[x] + Ly_row[x]*Ly_row[x])); +} } } @@ -130,8 +134,9 @@ float compute_k_percentile(const cv::Mat& img, float perc, float gscale, cv::Mat Ly = cv::Mat::zeros(img.rows, img.cols, CV_32F); // Set the histogram to zero - for (size_t i = 0; i < nbins; i++) + for (size_t i = 0; i < nbins; i++) { hist[i] = 0.0; +} // Perform the Gaussian convolution gaussian_2D_convolution(img, gaussian, ksize_x, ksize_y, gscale); @@ -151,8 +156,9 @@ float compute_k_percentile(const cv::Mat& img, float perc, float gscale, modg = sqrt(Lx_row[x]*Lx_row[x] + Ly_row[x]*Ly_row[x]); // Get the maximum - if (modg > hmax) + if (modg > hmax) { hmax = modg; +} } } @@ -183,13 +189,15 @@ float compute_k_percentile(const cv::Mat& img, float perc, float gscale, // Now find the perc of the histogram percentile nthreshold = (size_t)(npoints*perc); - for (k = 0; nelements < nthreshold && k < nbins; k++) + for (k = 0; nelements < nthreshold && k < nbins; k++) { nelements = nelements + hist[k]; +} - if (nelements < nthreshold) + if (nelements < nthreshold) { kperc = 0.03; - else + } else { kperc = hmax*((float)(k)/(float)nbins); +} delete [] hist; return kperc; @@ -343,8 +351,9 @@ void compute_derivative_kernels(cv::OutputArray kx_, cv::OutputArray ky_, int order = k == 0 ? dx : dy; float kerI[1000]; - for (int t = 0; t(i,j) < aux) + if (src.at(i,j) < aux) { aux = src.at(i,j); +} } } value = aux; @@ -49,8 +50,9 @@ void compute_max_32F(const cv::Mat &src, float& value) { float aux = 0.0; for (int i = 0; i < src.rows; i++) { for (int j = 0; j < src.cols; j++) { - if (src.at(i,j) > aux) + if (src.at(i,j) > aux) { aux = src.at(i,j); +} } } value = aux; @@ -184,10 +186,11 @@ void compute_inliers_ransac(const std::vector& matches, } if (npoints > 8) { - if (use_fund == true) + if (use_fund == true) { H = cv::findFundamentalMat(points1,points2,cv::FM_RANSAC,error,0.99,status); - else + } else { H = cv::findHomography(points1,points2,cv::RANSAC,error,status); +} for (int i = 0; i < npoints; i++) { if (status.at(i) == 1) { @@ -326,12 +329,13 @@ void draw_inliers(const cv::Mat& img1, const cv::Mat& img2, cv::Mat& img_com, x2 = (int)(ptpairs[i+1].x*ufactor+img1.cols+.5); y2 = (int)(ptpairs[i+1].y*vfactor+.5); - if (color == 0) + if (color == 0) { cv::line(img_com, cv::Point(x1,y1), cv::Point(x2,y2), cv::Scalar(255,255,0), 2); - else if (color == 1) + } else if (color == 1) { cv::line(img_com, cv::Point(x1,y1), cv::Point(x2,y2), cv::Scalar(255,0,0), 2); - else if (color == 2) + } else if (color == 2) { cv::line(img_com, cv::Point(x1,y1), cv::Point(x2,y2), cv::Scalar(0,0,255), 2); +} } } @@ -351,8 +355,9 @@ bool read_homography(const string& hFile, cv::Mat& H1toN) { ifstream pf; pf.open(filename.c_str(), std::ifstream::in); - if (!pf.is_open()) + if (!pf.is_open()) { return false; +} pf.getline(tmp_buf,tmp_buf_size); sscanf(tmp_buf,"%f %f %f",&h11,&h12,&h13); From 8f618a2baf99589064f6eebb1c5018cda4dbfd43 Mon Sep 17 00:00:00 2001 From: Pau Gargallo Date: Wed, 28 Feb 2024 04:53:27 -0800 Subject: [PATCH 064/235] fix some indentation messed up by a codemod Summary: The previous diff failed to indent closing brackets. Reviewed By: fabianschenk Differential Revision: D54298641 fbshipit-source-id: fff4bb610fad7ee64375f7182b3e4c177556af95 --- opensfm/src/bundle/src/bundle_adjuster.cc | 5 +-- opensfm/src/features/src/hahog.cc | 5 +-- opensfm/src/features/src/matching.cc | 5 +-- opensfm/src/foundation/numeric.h | 2 +- opensfm/src/geometry/src/triangulation.cc | 2 +- opensfm/src/map/pybind_utils.h | 8 ++--- opensfm/src/sfm/src/ba_helpers.cc | 5 +-- opensfm/src/third_party/akaze/lib/AKAZE.cpp | 35 +++++++++---------- opensfm/src/third_party/akaze/lib/fed.cpp | 6 ++-- .../akaze/lib/nldiffusion_functions.cpp | 16 ++++----- opensfm/src/third_party/akaze/lib/utils.cpp | 14 ++++---- 11 files changed, 53 insertions(+), 50 deletions(-) diff --git a/opensfm/src/bundle/src/bundle_adjuster.cc b/opensfm/src/bundle/src/bundle_adjuster.cc index 40aac3347..907a6691c 100644 --- a/opensfm/src/bundle/src/bundle_adjuster.cc +++ b/opensfm/src/bundle/src/bundle_adjuster.cc @@ -1128,8 +1128,9 @@ void BundleAdjuster::ComputeCovariances(ceres::Problem *problem) { break; } // stop after first Nan value - if (!computed) { break; -} + if (!computed) { + break; + } } } diff --git a/opensfm/src/features/src/hahog.cc b/opensfm/src/features/src/hahog.cc index 3a6aace8f..691a898fb 100644 --- a/opensfm/src/features/src/hahog.cc +++ b/opensfm/src/features/src/hahog.cc @@ -49,8 +49,9 @@ vl_size run_non_maxima_suppression(VlCovDet *covdet, vl_size num_features, double dy_ = features[j].frame.y - y; double sigma_ = features[j].frame.a11; double score_ = features[j].peakScore; - if (score_ == 0) { continue; -} + if (score_ == 0) { + continue; + } if (sigma < (1 + tol) * sigma_ && sigma_ < (1 + tol) * sigma && vl_abs_d(dx_) < tol * sigma && vl_abs_d(dy_) < tol * sigma && vl_abs_d(score) > vl_abs_d(score_)) { diff --git a/opensfm/src/features/src/matching.cc b/opensfm/src/features/src/matching.cc index 0623cd452..b25ed46ca 100644 --- a/opensfm/src/features/src/matching.cc +++ b/opensfm/src/features/src/matching.cc @@ -66,8 +66,9 @@ void MatchUsingWords(const cv::Mat &f1, const cv::Mat &w1, const cv::Mat &f2, } checks++; } - if (checks >= max_checks) { break; -} + if (checks >= max_checks) { + break; + } } if (best_distance[i] < lowes_ratio * second_best_distance[i]) { tmp_match.at(0, 0) = i; diff --git a/opensfm/src/foundation/numeric.h b/opensfm/src/foundation/numeric.h index ba42e1c8b..dd1550791 100644 --- a/opensfm/src/foundation/numeric.h +++ b/opensfm/src/foundation/numeric.h @@ -39,7 +39,7 @@ bool SolveAX0(const MAT& A, VEC* solution) { return true; } else { return false; -} + } } Eigen::Matrix3d SkewMatrix(const Eigen::Vector3d& v); diff --git a/opensfm/src/geometry/src/triangulation.cc b/opensfm/src/geometry/src/triangulation.cc index 470ea71dd..be15dfd4b 100644 --- a/opensfm/src/geometry/src/triangulation.cc +++ b/opensfm/src/geometry/src/triangulation.cc @@ -13,7 +13,7 @@ double AngleBetweenVectors(const Eigen::Vector3d &u, const Eigen::Vector3d &v) { return 0.0; } else { return acos(c); -} + } } Eigen::Vector4d TriangulateBearingsDLTSolve( diff --git a/opensfm/src/map/pybind_utils.h b/opensfm/src/map/pybind_utils.h index 414d9ca74..e7f402eed 100644 --- a/opensfm/src/map/pybind_utils.h +++ b/opensfm/src/map/pybind_utils.h @@ -72,7 +72,7 @@ iterator make_value_iterator(Iterator first, Sentinel last, Extra &&... extra) { ++s.it; } else { s.first_or_done = false; -} + } if (s.it == s.end) { s.first_or_done = true; throw stop_iteration(); @@ -104,7 +104,7 @@ iterator make_ref_value_iterator(Iterator first, Sentinel last, ++s.it; } else { s.first_or_done = false; -} + } if (s.it == s.end) { s.first_or_done = true; throw stop_iteration(); @@ -137,7 +137,7 @@ iterator make_ref_iterator(Iterator first, Sentinel last, Extra &&... extra) { ++s.it; } else { s.first_or_done = false; -} + } if (s.it == s.end) { s.first_or_done = true; throw stop_iteration(); @@ -167,7 +167,7 @@ iterator make_ptr_iterator(Iterator first, Sentinel last, Extra &&... extra) { ++s.it; } else { s.first_or_done = false; -} + } if (s.it == s.end) { s.first_or_done = true; throw stop_iteration(); diff --git a/opensfm/src/sfm/src/ba_helpers.cc b/opensfm/src/sfm/src/ba_helpers.cc index d0aca260f..d0501aa84 100644 --- a/opensfm/src/sfm/src/ba_helpers.cc +++ b/opensfm/src/sfm/src/ba_helpers.cc @@ -852,8 +852,9 @@ void BAHelpers::AlignmentConstraints( // Triangulated vs measured points if (!gcp.empty() && config["bundle_use_gcp"].cast()) { for (const auto& point : gcp) { - if (point.lla_.empty()) { continue; -} + if (point.lla_.empty()) { + continue; + } Vec3d coordinates; if (TriangulateGCP(point, shots, coordinates)) { Xp.row(idx) = topocentricConverter.ToTopocentric(point.GetLlaVec3d()); diff --git a/opensfm/src/third_party/akaze/lib/AKAZE.cpp b/opensfm/src/third_party/akaze/lib/AKAZE.cpp index 32f1b0ae8..5d42f251d 100644 --- a/opensfm/src/third_party/akaze/lib/AKAZE.cpp +++ b/opensfm/src/third_party/akaze/lib/AKAZE.cpp @@ -167,7 +167,7 @@ int AKAZE::Create_Nonlinear_Scale_Space(const cv::Mat& img) { // Perform FED n inner steps for (int j = 0; j < nsteps_[i-1]; j++) { nld_step_scalar(evolution_[i].Lt, evolution_[i].Lflow, evolution_[i].Lstep, tsteps_[i-1][j]); -} + } } t2 = cv::getTickCount(); @@ -244,7 +244,7 @@ void AKAZE::Compute_Determinant_Hessian_Response() { float* ldet = evolution_[i].Ldet.ptr(ix); for (int jx = 0; jx < evolution_[i].Ldet.cols; jx++) { ldet[jx] = lxx[jx]*lyy[jx]-lxy[jx]*lxy[jx]; -} + } } } } @@ -395,7 +395,7 @@ void AKAZE::Find_Scale_Space_Extrema(std::vector& kpts) { if (is_repeated == false) { kpts.push_back(point); -} + } } // Keep only the k-best keypoints @@ -430,7 +430,7 @@ void AKAZE::Find_Scale_Space_Extrema(std::vector& kpts) { } else { // Non-adapting suppression: keep k best response. std::sort(kpts.begin(), kpts.end(), compareKeyPointResponse); - kpts.resize(options_.target_num_features); + kpts.resize(options_.target_num_features); } } std::cout << "Keeping " << kpts.size() << " out of " << num_features_before << "\n"; @@ -590,7 +590,7 @@ void AKAZE::Compute_Descriptors(std::vector& kpts, cv::Mat& desc) Get_Upright_MLDB_Full_Descriptor(kpts[i], desc.ptr(i)); } else { Get_Upright_MLDB_Descriptor_Subset(kpts[i], desc.ptr(i)); -} + } } } break; @@ -605,7 +605,7 @@ void AKAZE::Compute_Descriptors(std::vector& kpts, cv::Mat& desc) Get_MLDB_Full_Descriptor(kpts[i], desc.ptr(i)); } else { Get_MLDB_Descriptor_Subset(kpts[i], desc.ptr(i)); -} + } } } break; @@ -850,7 +850,7 @@ void AKAZE::Get_SURF_Descriptor_64(const cv::KeyPoint& kpt, float *desc) const { for (int i = 0; i < dsize; i++) { desc[i] /= len; -} + } } /* ************************************************************************* */ @@ -962,7 +962,7 @@ void AKAZE::Get_MSURF_Upright_Descriptor_64(const cv::KeyPoint& kpt, float *desc for (int i = 0; i < dsize; i++) { desc[i] /= len; -} + } } /* ************************************************************************* */ @@ -1078,7 +1078,7 @@ void AKAZE::Get_MSURF_Descriptor_64(const cv::KeyPoint& kpt, float *desc) const for (int i = 0; i < dsize; i++) { desc[i] /= len; -} + } } /* ************************************************************************* */ @@ -1180,11 +1180,11 @@ void AKAZE::MLDB_Fill_Values(float* values, int sample_step, int level, if (nr_channels > 1) { values[valpos + 1] = dx; -} + } if (nr_channels > 2) { values[valpos + 2] = dy; -} + } valpos += nr_channels; } @@ -1241,11 +1241,11 @@ void AKAZE::MLDB_Fill_Upright_Values(float* values, int sample_step, int level, if (nr_channels > 1) { values[valpos + 1] = dx; -} + } if (nr_channels > 2) { values[valpos + 2] = dy; -} + } valpos += nr_channels; } @@ -1583,18 +1583,17 @@ void libAKAZE::check_descriptor_limits(int &x, int &y, int width, int height) { if (x < 0) { x = 0; -} + } if (y < 0) { y = 0; -} + } if (x > width-1) { x = width-1; -} + } if (y > height-1) { y = height-1; + } } -} - diff --git a/opensfm/src/third_party/akaze/lib/fed.cpp b/opensfm/src/third_party/akaze/lib/fed.cpp index ac67fa1c3..8989c2463 100644 --- a/opensfm/src/third_party/akaze/lib/fed.cpp +++ b/opensfm/src/third_party/akaze/lib/fed.cpp @@ -68,14 +68,14 @@ int fed_tau_internal(const int n, const float scale, const float tau_max, if (n <= 0) { return 0; -} + } // Allocate memory for the time step size tau = vector(n); if (reordering) { tauh = vector(n); -} + } // Compute time saver c = 1.0f / (4.0f * (float)n + 2.0f); @@ -89,7 +89,7 @@ int fed_tau_internal(const int n, const float scale, const float tau_max, tauh[k] = d / (h * h); } else { tau[k] = d / (h * h); -} + } } // Permute list of time steps according to chosen reordering function diff --git a/opensfm/src/third_party/akaze/lib/nldiffusion_functions.cpp b/opensfm/src/third_party/akaze/lib/nldiffusion_functions.cpp index 3981d455c..b1e3567ef 100644 --- a/opensfm/src/third_party/akaze/lib/nldiffusion_functions.cpp +++ b/opensfm/src/third_party/akaze/lib/nldiffusion_functions.cpp @@ -35,11 +35,11 @@ void gaussian_2D_convolution(const cv::Mat& src, cv::Mat& dst, size_t ksize_x, // The kernel size must be and odd number if ((ksize_x % 2) == 0) { ksize_x += 1; -} + } if ((ksize_y % 2) == 0) { ksize_y += 1; -} + } // Perform the Gaussian Smoothing with border replication cv::GaussianBlur(src, dst, cv::Size(ksize_x, ksize_y), sigma, sigma, cv::BORDER_REPLICATE); @@ -62,7 +62,7 @@ void pm_g1(const cv::Mat& Lx, const cv::Mat& Ly, cv::Mat& dst, const float k) { float* dst_row = dst.ptr(y); for (int x = 0; x < sz.width; x++) { dst_row[x] = (-inv_k*(Lx_row[x]*Lx_row[x] + Ly_row[x]*Ly_row[x])); -} + } } cv::exp(dst, dst); @@ -79,7 +79,7 @@ void pm_g2(const cv::Mat& Lx, const cv::Mat& Ly, cv::Mat& dst, const float k) { float* dst_row = dst.ptr(y); for (int x = 0; x < sz.width; x++) { dst_row[x] = 1.0 / (1.0+inv_k*(Lx_row[x]*Lx_row[x] + Ly_row[x]*Ly_row[x])); -} + } } } @@ -158,7 +158,7 @@ float compute_k_percentile(const cv::Mat& img, float perc, float gscale, // Get the maximum if (modg > hmax) { hmax = modg; -} + } } } @@ -191,13 +191,13 @@ float compute_k_percentile(const cv::Mat& img, float perc, float gscale, for (k = 0; nelements < nthreshold && k < nbins; k++) { nelements = nelements + hist[k]; -} + } if (nelements < nthreshold) { kperc = 0.03; } else { kperc = hmax*((float)(k)/(float)nbins); -} + } delete [] hist; return kperc; @@ -353,7 +353,7 @@ void compute_derivative_kernels(cv::OutputArray kx_, cv::OutputArray ky_, for (int t = 0; t(i,j) < aux) { aux = src.at(i,j); -} + } } } value = aux; @@ -52,7 +52,7 @@ void compute_max_32F(const cv::Mat &src, float& value) { for (int j = 0; j < src.cols; j++) { if (src.at(i,j) > aux) { aux = src.at(i,j); -} + } } } value = aux; @@ -190,7 +190,7 @@ void compute_inliers_ransac(const std::vector& matches, H = cv::findFundamentalMat(points1,points2,cv::FM_RANSAC,error,0.99,status); } else { H = cv::findHomography(points1,points2,cv::RANSAC,error,status); -} + } for (int i = 0; i < npoints; i++) { if (status.at(i) == 1) { @@ -335,7 +335,7 @@ void draw_inliers(const cv::Mat& img1, const cv::Mat& img2, cv::Mat& img_com, cv::line(img_com, cv::Point(x1,y1), cv::Point(x2,y2), cv::Scalar(255,0,0), 2); } else if (color == 2) { cv::line(img_com, cv::Point(x1,y1), cv::Point(x2,y2), cv::Scalar(0,0,255), 2); -} + } } } @@ -357,7 +357,7 @@ bool read_homography(const string& hFile, cv::Mat& H1toN) { if (!pf.is_open()) { return false; -} + } pf.getline(tmp_buf,tmp_buf_size); sscanf(tmp_buf,"%f %f %f",&h11,&h12,&h13); @@ -414,12 +414,12 @@ void show_input_options_help(int example) { else if (example == 2) { cout << "./akaze_compare img1.jpg img2.pgm [homography.txt] [options]" << endl; } - + cout << endl; cout_help() << "homography.txt is optional. If the txt file is not provided a planar homography will be estimated using RANSAC" << endl; cout << endl; - cout_help() << "Options below are not mandatory. Unless specified, default arguments are used." << endl << endl; + cout_help() << "Options below are not mandatory. Unless specified, default arguments are used." << endl << endl; // Justify on the left cout << left; From 7ad733935e0c81942e03d8f994844084a925372c Mon Sep 17 00:00:00 2001 From: generatedunixname89002005287564 Date: Sat, 2 Mar 2024 10:20:41 -0800 Subject: [PATCH 065/235] Pyre Configurationless migration for] [batch:26/112] [shard:6/N] (#1041) Summary: X-link: https://github.com/facebookincubator/metalos/pull/5 X-link: https://github.com/facebookresearch/fbpcp/pull/527 Pull Request resolved: https://github.com/mapillary/OpenSfM/pull/1041 Reviewed By: connernilsen Differential Revision: D54440273 fbshipit-source-id: 0742c4b76bbef07c68a729f65bc27f1a176b919f --- annotation_gui_gcp/lib/GUI.py | 1 + annotation_gui_gcp/lib/gcp_manager.py | 1 + annotation_gui_gcp/lib/geometry.py | 1 + annotation_gui_gcp/lib/image_manager.py | 1 + annotation_gui_gcp/lib/views/cad_view.py | 1 + annotation_gui_gcp/lib/views/cp_finder_view.py | 1 + annotation_gui_gcp/lib/views/image_view.py | 1 + annotation_gui_gcp/lib/views/tools_view.py | 1 + annotation_gui_gcp/lib/views/web_view.py | 1 + annotation_gui_gcp/main.py | 1 + annotation_gui_gcp/run_ba.py | 1 + bin/import_colmap.py | 2 ++ bin/opensfm_main.py | 1 + bin/plot_matches.py | 2 ++ opensfm/__init__.py | 1 + opensfm/actions/align_submodels.py | 1 + opensfm/actions/bundle.py | 1 + opensfm/actions/compute_depthmaps.py | 1 + opensfm/actions/compute_statistics.py | 1 + opensfm/actions/create_rig.py | 1 + opensfm/actions/create_submodels.py | 1 + opensfm/actions/create_tracks.py | 1 + opensfm/actions/detect_features.py | 1 + opensfm/actions/export_bundler.py | 1 + opensfm/actions/export_colmap.py | 2 ++ opensfm/actions/export_geocoords.py | 1 + opensfm/actions/export_openmvs.py | 1 + opensfm/actions/export_ply.py | 1 + opensfm/actions/export_pmvs.py | 1 + opensfm/actions/export_report.py | 1 + opensfm/actions/export_visualsfm.py | 1 + opensfm/actions/extend_reconstruction.py | 1 + opensfm/actions/extract_metadata.py | 1 + opensfm/actions/match_features.py | 1 + opensfm/actions/mesh.py | 1 + opensfm/actions/reconstruct.py | 1 + opensfm/actions/reconstruct_from_prior.py | 1 + opensfm/actions/undistort.py | 1 + opensfm/align.py | 1 + opensfm/bow.py | 1 + opensfm/commands/__init__.py | 1 + opensfm/commands/align_submodels.py | 1 + opensfm/commands/bundle.py | 1 + opensfm/commands/command.py | 1 + opensfm/commands/command_runner.py | 1 + opensfm/commands/compute_depthmaps.py | 1 + opensfm/commands/compute_statistics.py | 1 + opensfm/commands/create_rig.py | 1 + opensfm/commands/create_submodels.py | 1 + opensfm/commands/create_tracks.py | 1 + opensfm/commands/detect_features.py | 1 + opensfm/commands/export_bundler.py | 1 + opensfm/commands/export_colmap.py | 1 + opensfm/commands/export_geocoords.py | 1 + opensfm/commands/export_openmvs.py | 1 + opensfm/commands/export_ply.py | 1 + opensfm/commands/export_pmvs.py | 1 + opensfm/commands/export_report.py | 1 + opensfm/commands/export_visualsfm.py | 1 + opensfm/commands/extend_reconstruction.py | 1 + opensfm/commands/extract_metadata.py | 1 + opensfm/commands/match_features.py | 1 + opensfm/commands/mesh.py | 1 + opensfm/commands/reconstruct.py | 1 + opensfm/commands/reconstruct_from_prior.py | 1 + opensfm/commands/undistort.py | 1 + opensfm/config.py | 1 + opensfm/context.py | 1 + opensfm/dataset.py | 1 + opensfm/dataset_base.py | 1 + opensfm/dense.py | 1 + opensfm/exif.py | 1 + opensfm/feature_loader.py | 1 + opensfm/feature_loading.py | 1 + opensfm/features.py | 1 + opensfm/features_processing.py | 1 + opensfm/geo.py | 1 + opensfm/geometry.py | 1 + opensfm/geotag_from_gpx.py | 2 ++ opensfm/io.py | 1 + opensfm/large/metadataset.py | 1 + opensfm/large/tools.py | 1 + opensfm/log.py | 1 + opensfm/masking.py | 1 + opensfm/matching.py | 1 + opensfm/mesh.py | 2 ++ opensfm/multiview.py | 1 + opensfm/pairs_selection.py | 1 + opensfm/reconstruction.py | 1 + opensfm/reconstruction_helpers.py | 1 + opensfm/report.py | 1 + opensfm/rig.py | 1 + opensfm/sensors.py | 1 + opensfm/stats.py | 1 + opensfm/synthetic_data/synthetic_dataset.py | 1 + opensfm/synthetic_data/synthetic_examples.py | 1 + opensfm/synthetic_data/synthetic_generator.py | 1 + opensfm/synthetic_data/synthetic_metrics.py | 1 + opensfm/synthetic_data/synthetic_scene.py | 1 + opensfm/test/conftest.py | 1 + opensfm/test/data_generation.py | 1 + opensfm/test/test_bundle.py | 1 + opensfm/test/test_commands.py | 1 + opensfm/test/test_dataset.py | 1 + opensfm/test/test_datastructures.py | 1 + opensfm/test/test_dense.py | 1 + opensfm/test/test_geo.py | 1 + opensfm/test/test_geometry.py | 1 + opensfm/test/test_io.py | 1 + opensfm/test/test_matching.py | 1 + opensfm/test/test_multiview.py | 1 + opensfm/test/test_pairs_selection.py | 1 + opensfm/test/test_reconstruction_alignment.py | 1 + opensfm/test/test_reconstruction_incremental.py | 1 + opensfm/test/test_reconstruction_resect.py | 1 + opensfm/test/test_reconstruction_shot_neighborhood.py | 1 + opensfm/test/test_reconstruction_triangulation.py | 1 + opensfm/test/test_rig.py | 1 + opensfm/test/test_robust.py | 1 + opensfm/test/test_stats.py | 1 + opensfm/test/test_triangulation.py | 1 + opensfm/test/test_types.py | 1 + opensfm/test/test_undistort.py | 1 + opensfm/test/test_vlad.py | 1 + opensfm/test/utils.py | 2 ++ opensfm/tracking.py | 1 + opensfm/transformations.py | 2 ++ opensfm/types.py | 1 + opensfm/undistort.py | 1 + opensfm/unionfind.py | 2 ++ opensfm/upright.py | 1 + opensfm/video.py | 1 + opensfm/vlad.py | 1 + viewer/server.py | 1 + 134 files changed, 142 insertions(+) diff --git a/annotation_gui_gcp/lib/GUI.py b/annotation_gui_gcp/lib/GUI.py index f9953f4d8..44a999ec3 100644 --- a/annotation_gui_gcp/lib/GUI.py +++ b/annotation_gui_gcp/lib/GUI.py @@ -1,3 +1,4 @@ +# pyre-unsafe import os import random import subprocess diff --git a/annotation_gui_gcp/lib/gcp_manager.py b/annotation_gui_gcp/lib/gcp_manager.py index 1a22e1ae7..f5d2858e5 100644 --- a/annotation_gui_gcp/lib/gcp_manager.py +++ b/annotation_gui_gcp/lib/gcp_manager.py @@ -1,3 +1,4 @@ +# pyre-unsafe import json import os import typing as t diff --git a/annotation_gui_gcp/lib/geometry.py b/annotation_gui_gcp/lib/geometry.py index c10b2daa5..1df053f3e 100644 --- a/annotation_gui_gcp/lib/geometry.py +++ b/annotation_gui_gcp/lib/geometry.py @@ -1,3 +1,4 @@ +# pyre-unsafe from opensfm import dataset from numpy import ndarray from typing import Dict, Tuple diff --git a/annotation_gui_gcp/lib/image_manager.py b/annotation_gui_gcp/lib/image_manager.py index bd4d63922..494eeda7a 100644 --- a/annotation_gui_gcp/lib/image_manager.py +++ b/annotation_gui_gcp/lib/image_manager.py @@ -1,3 +1,4 @@ +# pyre-unsafe import typing as t from io import BytesIO diff --git a/annotation_gui_gcp/lib/views/cad_view.py b/annotation_gui_gcp/lib/views/cad_view.py index fb3e46c79..29d1320d3 100644 --- a/annotation_gui_gcp/lib/views/cad_view.py +++ b/annotation_gui_gcp/lib/views/cad_view.py @@ -1,3 +1,4 @@ +# pyre-unsafe import json import logging from pathlib import Path diff --git a/annotation_gui_gcp/lib/views/cp_finder_view.py b/annotation_gui_gcp/lib/views/cp_finder_view.py index af6f3b0a6..b8b491402 100644 --- a/annotation_gui_gcp/lib/views/cp_finder_view.py +++ b/annotation_gui_gcp/lib/views/cp_finder_view.py @@ -1,3 +1,4 @@ +# pyre-unsafe import typing as t from annotation_gui_gcp.lib.views.image_view import ImageView diff --git a/annotation_gui_gcp/lib/views/image_view.py b/annotation_gui_gcp/lib/views/image_view.py index 16dddbed8..efc1a1bdf 100644 --- a/annotation_gui_gcp/lib/views/image_view.py +++ b/annotation_gui_gcp/lib/views/image_view.py @@ -1,3 +1,4 @@ +# pyre-unsafe from typing import Dict, Any from annotation_gui_gcp.lib.views.web_view import WebView, distinct_colors diff --git a/annotation_gui_gcp/lib/views/tools_view.py b/annotation_gui_gcp/lib/views/tools_view.py index 9a70b0482..22a5e9bca 100644 --- a/annotation_gui_gcp/lib/views/tools_view.py +++ b/annotation_gui_gcp/lib/views/tools_view.py @@ -1,3 +1,4 @@ +# pyre-unsafe from typing import Dict, Any from annotation_gui_gcp.lib.views.web_view import WebView diff --git a/annotation_gui_gcp/lib/views/web_view.py b/annotation_gui_gcp/lib/views/web_view.py index a2f93107c..b41dd41e6 100644 --- a/annotation_gui_gcp/lib/views/web_view.py +++ b/annotation_gui_gcp/lib/views/web_view.py @@ -1,3 +1,4 @@ +# pyre-unsafe import abc import json import time diff --git a/annotation_gui_gcp/main.py b/annotation_gui_gcp/main.py index aad365118..41388dbe5 100644 --- a/annotation_gui_gcp/main.py +++ b/annotation_gui_gcp/main.py @@ -1,3 +1,4 @@ +# pyre-unsafe import argparse import json import typing as t diff --git a/annotation_gui_gcp/run_ba.py b/annotation_gui_gcp/run_ba.py index 4e571f8aa..41d54ed59 100644 --- a/annotation_gui_gcp/run_ba.py +++ b/annotation_gui_gcp/run_ba.py @@ -1,3 +1,4 @@ +# pyre-unsafe import argparse import json import logging diff --git a/bin/import_colmap.py b/bin/import_colmap.py index 9388883f4..95a6a2365 100755 --- a/bin/import_colmap.py +++ b/bin/import_colmap.py @@ -1,5 +1,7 @@ #!/usr/bin/env python3 +# pyre-unsafe + # Snippets to read from the colmap database taken from: # https://github.com/colmap/colmap/blob/ad7bd93f1a27af7533121aa043a167fe1490688c / # scripts/python/export_to_bundler.py diff --git a/bin/opensfm_main.py b/bin/opensfm_main.py index 2041e163d..7709b7491 100755 --- a/bin/opensfm_main.py +++ b/bin/opensfm_main.py @@ -1,3 +1,4 @@ +# pyre-unsafe import sys from os.path import abspath, dirname, join diff --git a/bin/plot_matches.py b/bin/plot_matches.py index 2fe59174b..ab94b2e94 100755 --- a/bin/plot_matches.py +++ b/bin/plot_matches.py @@ -1,5 +1,7 @@ #!/usr/bin/env python3 +# pyre-unsafe + import argparse import os.path from itertools import combinations diff --git a/opensfm/__init__.py b/opensfm/__init__.py index 011058c79..8cd78b225 100644 --- a/opensfm/__init__.py +++ b/opensfm/__init__.py @@ -1,3 +1,4 @@ +# pyre-unsafe from opensfm import pybundle from opensfm import pydense from opensfm import pyfeatures diff --git a/opensfm/actions/align_submodels.py b/opensfm/actions/align_submodels.py index 3e70501f4..28fc2a525 100644 --- a/opensfm/actions/align_submodels.py +++ b/opensfm/actions/align_submodels.py @@ -1,3 +1,4 @@ +# pyre-unsafe from opensfm.large import metadataset from opensfm.large import tools from opensfm.dataset import DataSet diff --git a/opensfm/actions/bundle.py b/opensfm/actions/bundle.py index fa4afdc48..28c08dd14 100644 --- a/opensfm/actions/bundle.py +++ b/opensfm/actions/bundle.py @@ -1,3 +1,4 @@ +# pyre-unsafe import opensfm.reconstruction as orec from opensfm.dataset_base import DataSetBase from typing import Optional diff --git a/opensfm/actions/compute_depthmaps.py b/opensfm/actions/compute_depthmaps.py index d16f06e59..e7972c226 100644 --- a/opensfm/actions/compute_depthmaps.py +++ b/opensfm/actions/compute_depthmaps.py @@ -1,3 +1,4 @@ +# pyre-unsafe import os from opensfm import dataset diff --git a/opensfm/actions/compute_statistics.py b/opensfm/actions/compute_statistics.py index 736c11706..0b8eb057a 100644 --- a/opensfm/actions/compute_statistics.py +++ b/opensfm/actions/compute_statistics.py @@ -1,3 +1,4 @@ +# pyre-unsafe import logging import os diff --git a/opensfm/actions/create_rig.py b/opensfm/actions/create_rig.py index 823f9f019..50b1608fb 100644 --- a/opensfm/actions/create_rig.py +++ b/opensfm/actions/create_rig.py @@ -1,3 +1,4 @@ +# pyre-unsafe import logging from opensfm import pymap, rig, reconstruction_helpers as helpers, types diff --git a/opensfm/actions/create_submodels.py b/opensfm/actions/create_submodels.py index 08ef8e205..2716a0603 100644 --- a/opensfm/actions/create_submodels.py +++ b/opensfm/actions/create_submodels.py @@ -1,3 +1,4 @@ +# pyre-unsafe import logging from collections import defaultdict diff --git a/opensfm/actions/create_tracks.py b/opensfm/actions/create_tracks.py index e119eb07f..1a0db6e4f 100644 --- a/opensfm/actions/create_tracks.py +++ b/opensfm/actions/create_tracks.py @@ -1,3 +1,4 @@ +# pyre-unsafe from timeit import default_timer as timer from opensfm import io diff --git a/opensfm/actions/detect_features.py b/opensfm/actions/detect_features.py index a84f6791b..9bf47cfed 100644 --- a/opensfm/actions/detect_features.py +++ b/opensfm/actions/detect_features.py @@ -1,3 +1,4 @@ +# pyre-unsafe import logging from timeit import default_timer as timer diff --git a/opensfm/actions/export_bundler.py b/opensfm/actions/export_bundler.py index 9a6002aa3..1535ff795 100644 --- a/opensfm/actions/export_bundler.py +++ b/opensfm/actions/export_bundler.py @@ -1,3 +1,4 @@ +# pyre-unsafe import os import numpy as np diff --git a/opensfm/actions/export_colmap.py b/opensfm/actions/export_colmap.py index ab275e074..c86e38fa9 100644 --- a/opensfm/actions/export_colmap.py +++ b/opensfm/actions/export_colmap.py @@ -29,6 +29,8 @@ # # Author: Johannes L. Schoenberger (jsch at inf.ethz.ch) +# pyre-unsafe + # This script is based on an original implementation by True Price. import math diff --git a/opensfm/actions/export_geocoords.py b/opensfm/actions/export_geocoords.py index 67b1f7233..aad9d7910 100644 --- a/opensfm/actions/export_geocoords.py +++ b/opensfm/actions/export_geocoords.py @@ -1,3 +1,4 @@ +# pyre-unsafe import logging import os from opensfm import types diff --git a/opensfm/actions/export_openmvs.py b/opensfm/actions/export_openmvs.py index 7d3edc8ab..2020913d6 100644 --- a/opensfm/actions/export_openmvs.py +++ b/opensfm/actions/export_openmvs.py @@ -1,3 +1,4 @@ +# pyre-unsafe import os import numpy as np diff --git a/opensfm/actions/export_ply.py b/opensfm/actions/export_ply.py index 3e718c01b..69658ce4f 100644 --- a/opensfm/actions/export_ply.py +++ b/opensfm/actions/export_ply.py @@ -1,3 +1,4 @@ +# pyre-unsafe import os import numpy as np diff --git a/opensfm/actions/export_pmvs.py b/opensfm/actions/export_pmvs.py index 264fb2e4a..de11b4974 100644 --- a/opensfm/actions/export_pmvs.py +++ b/opensfm/actions/export_pmvs.py @@ -1,3 +1,4 @@ +# pyre-unsafe import logging import os diff --git a/opensfm/actions/export_report.py b/opensfm/actions/export_report.py index 8b50e4f49..d20ac0a3a 100644 --- a/opensfm/actions/export_report.py +++ b/opensfm/actions/export_report.py @@ -1,3 +1,4 @@ +# pyre-unsafe from opensfm import report from opensfm.dataset import DataSet diff --git a/opensfm/actions/export_visualsfm.py b/opensfm/actions/export_visualsfm.py index 1b1ce0846..1f91b0811 100644 --- a/opensfm/actions/export_visualsfm.py +++ b/opensfm/actions/export_visualsfm.py @@ -1,3 +1,4 @@ +# pyre-unsafe import logging import os import sys diff --git a/opensfm/actions/extend_reconstruction.py b/opensfm/actions/extend_reconstruction.py index 2d9bd303d..adc9ea78b 100644 --- a/opensfm/actions/extend_reconstruction.py +++ b/opensfm/actions/extend_reconstruction.py @@ -1,3 +1,4 @@ +# pyre-unsafe from opensfm import io, reconstruction from opensfm.dataset_base import DataSetBase from typing import Optional diff --git a/opensfm/actions/extract_metadata.py b/opensfm/actions/extract_metadata.py index b7f5fcbae..6d58383d3 100644 --- a/opensfm/actions/extract_metadata.py +++ b/opensfm/actions/extract_metadata.py @@ -1,3 +1,4 @@ +# pyre-unsafe import copy import logging from functools import partial diff --git a/opensfm/actions/match_features.py b/opensfm/actions/match_features.py index 84b1937a1..9cd8d8433 100644 --- a/opensfm/actions/match_features.py +++ b/opensfm/actions/match_features.py @@ -1,3 +1,4 @@ +# pyre-unsafe from timeit import default_timer as timer from opensfm import io diff --git a/opensfm/actions/mesh.py b/opensfm/actions/mesh.py index d3a952c93..203e3bf86 100644 --- a/opensfm/actions/mesh.py +++ b/opensfm/actions/mesh.py @@ -1,3 +1,4 @@ +# pyre-unsafe from opensfm import mesh from opensfm.dataset_base import DataSetBase diff --git a/opensfm/actions/reconstruct.py b/opensfm/actions/reconstruct.py index 9c952fd7d..d5b30420d 100644 --- a/opensfm/actions/reconstruct.py +++ b/opensfm/actions/reconstruct.py @@ -1,3 +1,4 @@ +# pyre-unsafe from opensfm import io from opensfm import reconstruction from opensfm.dataset_base import DataSetBase diff --git a/opensfm/actions/reconstruct_from_prior.py b/opensfm/actions/reconstruct_from_prior.py index 067be1fa2..e5d86232e 100644 --- a/opensfm/actions/reconstruct_from_prior.py +++ b/opensfm/actions/reconstruct_from_prior.py @@ -1,3 +1,4 @@ +# pyre-unsafe from opensfm import io from opensfm import reconstruction from opensfm.dataset_base import DataSetBase diff --git a/opensfm/actions/undistort.py b/opensfm/actions/undistort.py index 1f1a129de..5d9bcd220 100644 --- a/opensfm/actions/undistort.py +++ b/opensfm/actions/undistort.py @@ -1,3 +1,4 @@ +# pyre-unsafe import os from typing import Optional diff --git a/opensfm/align.py b/opensfm/align.py index 383109564..48d7d60c3 100644 --- a/opensfm/align.py +++ b/opensfm/align.py @@ -1,3 +1,4 @@ +# pyre-unsafe """Tools to align a reconstruction to GPS and GCP data.""" import logging diff --git a/opensfm/bow.py b/opensfm/bow.py index 544bcb079..f4746c469 100644 --- a/opensfm/bow.py +++ b/opensfm/bow.py @@ -1,3 +1,4 @@ +# pyre-unsafe import os.path import cv2 diff --git a/opensfm/commands/__init__.py b/opensfm/commands/__init__.py index 426afebd7..97a2f32fe 100644 --- a/opensfm/commands/__init__.py +++ b/opensfm/commands/__init__.py @@ -1,3 +1,4 @@ +# pyre-unsafe from . import ( align_submodels, bundle, diff --git a/opensfm/commands/align_submodels.py b/opensfm/commands/align_submodels.py index f3bc8c917..8055c45bd 100644 --- a/opensfm/commands/align_submodels.py +++ b/opensfm/commands/align_submodels.py @@ -1,3 +1,4 @@ +# pyre-unsafe from opensfm.actions import align_submodels from . import command diff --git a/opensfm/commands/bundle.py b/opensfm/commands/bundle.py index b7e6f668a..767d73146 100644 --- a/opensfm/commands/bundle.py +++ b/opensfm/commands/bundle.py @@ -1,3 +1,4 @@ +# pyre-unsafe from opensfm.actions import bundle from . import command diff --git a/opensfm/commands/command.py b/opensfm/commands/command.py index 077c7c811..2e7093e93 100644 --- a/opensfm/commands/command.py +++ b/opensfm/commands/command.py @@ -1,3 +1,4 @@ +# pyre-unsafe from timeit import default_timer as timer import argparse from opensfm.dataset import DataSet diff --git a/opensfm/commands/command_runner.py b/opensfm/commands/command_runner.py index 6498a7ef6..55b556903 100644 --- a/opensfm/commands/command_runner.py +++ b/opensfm/commands/command_runner.py @@ -1,3 +1,4 @@ +# pyre-unsafe from typing import Any, Callable, List import argparse diff --git a/opensfm/commands/compute_depthmaps.py b/opensfm/commands/compute_depthmaps.py index 57c647947..6265b6fd3 100644 --- a/opensfm/commands/compute_depthmaps.py +++ b/opensfm/commands/compute_depthmaps.py @@ -1,3 +1,4 @@ +# pyre-unsafe from opensfm.actions import compute_depthmaps from . import command diff --git a/opensfm/commands/compute_statistics.py b/opensfm/commands/compute_statistics.py index a445fc7c4..8b6544a30 100644 --- a/opensfm/commands/compute_statistics.py +++ b/opensfm/commands/compute_statistics.py @@ -1,3 +1,4 @@ +# pyre-unsafe from . import command import argparse from opensfm.dataset import DataSet diff --git a/opensfm/commands/create_rig.py b/opensfm/commands/create_rig.py index 120e471b9..82d191156 100644 --- a/opensfm/commands/create_rig.py +++ b/opensfm/commands/create_rig.py @@ -1,3 +1,4 @@ +# pyre-unsafe import json from opensfm.actions import create_rig diff --git a/opensfm/commands/create_submodels.py b/opensfm/commands/create_submodels.py index bc76dcba8..a6d301103 100644 --- a/opensfm/commands/create_submodels.py +++ b/opensfm/commands/create_submodels.py @@ -1,3 +1,4 @@ +# pyre-unsafe from opensfm.actions import create_submodels from . import command diff --git a/opensfm/commands/create_tracks.py b/opensfm/commands/create_tracks.py index d5ee6e6ac..408c67a53 100644 --- a/opensfm/commands/create_tracks.py +++ b/opensfm/commands/create_tracks.py @@ -1,3 +1,4 @@ +# pyre-unsafe from opensfm.actions import create_tracks from . import command diff --git a/opensfm/commands/detect_features.py b/opensfm/commands/detect_features.py index b94f83289..466826e52 100644 --- a/opensfm/commands/detect_features.py +++ b/opensfm/commands/detect_features.py @@ -1,3 +1,4 @@ +# pyre-unsafe from opensfm.actions import detect_features from . import command diff --git a/opensfm/commands/export_bundler.py b/opensfm/commands/export_bundler.py index 13bb1a241..83be840d3 100644 --- a/opensfm/commands/export_bundler.py +++ b/opensfm/commands/export_bundler.py @@ -1,3 +1,4 @@ +# pyre-unsafe from opensfm.actions import export_bundler from . import command diff --git a/opensfm/commands/export_colmap.py b/opensfm/commands/export_colmap.py index b5fab0a00..79c4b86ac 100644 --- a/opensfm/commands/export_colmap.py +++ b/opensfm/commands/export_colmap.py @@ -1,3 +1,4 @@ +# pyre-unsafe from opensfm.actions import export_colmap from . import command diff --git a/opensfm/commands/export_geocoords.py b/opensfm/commands/export_geocoords.py index 155a91bca..1f3b4e219 100644 --- a/opensfm/commands/export_geocoords.py +++ b/opensfm/commands/export_geocoords.py @@ -1,3 +1,4 @@ +# pyre-unsafe from opensfm.actions import export_geocoords from . import command diff --git a/opensfm/commands/export_openmvs.py b/opensfm/commands/export_openmvs.py index 7476c6fad..91dbb595e 100644 --- a/opensfm/commands/export_openmvs.py +++ b/opensfm/commands/export_openmvs.py @@ -1,3 +1,4 @@ +# pyre-unsafe from opensfm.actions import export_openmvs from . import command diff --git a/opensfm/commands/export_ply.py b/opensfm/commands/export_ply.py index 7e4892968..1d3be5f00 100644 --- a/opensfm/commands/export_ply.py +++ b/opensfm/commands/export_ply.py @@ -1,3 +1,4 @@ +# pyre-unsafe from opensfm.actions import export_ply from . import command diff --git a/opensfm/commands/export_pmvs.py b/opensfm/commands/export_pmvs.py index 9a39d5ccd..84d67c656 100644 --- a/opensfm/commands/export_pmvs.py +++ b/opensfm/commands/export_pmvs.py @@ -1,3 +1,4 @@ +# pyre-unsafe from opensfm.actions import export_pmvs from . import command diff --git a/opensfm/commands/export_report.py b/opensfm/commands/export_report.py index ab6722ee2..d9f084329 100644 --- a/opensfm/commands/export_report.py +++ b/opensfm/commands/export_report.py @@ -1,3 +1,4 @@ +# pyre-unsafe from . import command import argparse from opensfm.dataset import DataSet diff --git a/opensfm/commands/export_visualsfm.py b/opensfm/commands/export_visualsfm.py index c0b65eead..37080add9 100644 --- a/opensfm/commands/export_visualsfm.py +++ b/opensfm/commands/export_visualsfm.py @@ -1,3 +1,4 @@ +# pyre-unsafe from opensfm.actions import export_visualsfm from . import command diff --git a/opensfm/commands/extend_reconstruction.py b/opensfm/commands/extend_reconstruction.py index 2804c5382..6e72374e5 100644 --- a/opensfm/commands/extend_reconstruction.py +++ b/opensfm/commands/extend_reconstruction.py @@ -1,3 +1,4 @@ +# pyre-unsafe from opensfm.actions import extend_reconstruction from . import command diff --git a/opensfm/commands/extract_metadata.py b/opensfm/commands/extract_metadata.py index c51879103..5bf0d62b1 100644 --- a/opensfm/commands/extract_metadata.py +++ b/opensfm/commands/extract_metadata.py @@ -1,3 +1,4 @@ +# pyre-unsafe from opensfm.actions import extract_metadata from . import command diff --git a/opensfm/commands/match_features.py b/opensfm/commands/match_features.py index 5739c1801..74e88984f 100644 --- a/opensfm/commands/match_features.py +++ b/opensfm/commands/match_features.py @@ -1,3 +1,4 @@ +# pyre-unsafe from opensfm.actions import match_features from . import command diff --git a/opensfm/commands/mesh.py b/opensfm/commands/mesh.py index c762d97c3..6a407cab4 100644 --- a/opensfm/commands/mesh.py +++ b/opensfm/commands/mesh.py @@ -1,3 +1,4 @@ +# pyre-unsafe from opensfm.actions import mesh from . import command diff --git a/opensfm/commands/reconstruct.py b/opensfm/commands/reconstruct.py index bfccf9eba..5dcb002f2 100644 --- a/opensfm/commands/reconstruct.py +++ b/opensfm/commands/reconstruct.py @@ -1,3 +1,4 @@ +# pyre-unsafe from opensfm import reconstruction from opensfm.actions import reconstruct diff --git a/opensfm/commands/reconstruct_from_prior.py b/opensfm/commands/reconstruct_from_prior.py index f4271e98a..0aa7389ef 100644 --- a/opensfm/commands/reconstruct_from_prior.py +++ b/opensfm/commands/reconstruct_from_prior.py @@ -1,3 +1,4 @@ +# pyre-unsafe from opensfm.actions import reconstruct_from_prior from . import command diff --git a/opensfm/commands/undistort.py b/opensfm/commands/undistort.py index d9f99eb62..d7eae5d6e 100644 --- a/opensfm/commands/undistort.py +++ b/opensfm/commands/undistort.py @@ -1,3 +1,4 @@ +# pyre-unsafe from opensfm.actions import undistort from . import command diff --git a/opensfm/config.py b/opensfm/config.py index 4ef433a17..907e9c1ed 100644 --- a/opensfm/config.py +++ b/opensfm/config.py @@ -1,3 +1,4 @@ +# pyre-unsafe import os from dataclasses import dataclass, asdict from typing import Any, Dict, IO, Union diff --git a/opensfm/context.py b/opensfm/context.py index 58fa25296..00ea4074e 100644 --- a/opensfm/context.py +++ b/opensfm/context.py @@ -1,3 +1,4 @@ +# pyre-unsafe import logging import os diff --git a/opensfm/dataset.py b/opensfm/dataset.py index ff825a272..12af6a344 100644 --- a/opensfm/dataset.py +++ b/opensfm/dataset.py @@ -1,3 +1,4 @@ +# pyre-unsafe import gzip import json import logging diff --git a/opensfm/dataset_base.py b/opensfm/dataset_base.py index 9f3c64068..a049344e9 100644 --- a/opensfm/dataset_base.py +++ b/opensfm/dataset_base.py @@ -1,3 +1,4 @@ +# pyre-unsafe import logging from abc import ABC, abstractmethod from typing import Dict, List, Tuple, Optional, IO, Any diff --git a/opensfm/dense.py b/opensfm/dense.py index 49cd18365..14b4fc940 100644 --- a/opensfm/dense.py +++ b/opensfm/dense.py @@ -1,3 +1,4 @@ +# pyre-unsafe import logging import typing as t diff --git a/opensfm/exif.py b/opensfm/exif.py index d46ead2d8..6b4e76462 100644 --- a/opensfm/exif.py +++ b/opensfm/exif.py @@ -1,3 +1,4 @@ +# pyre-unsafe import datetime import logging from codecs import encode, decode diff --git a/opensfm/feature_loader.py b/opensfm/feature_loader.py index eac0cb4cc..d9a3ad086 100644 --- a/opensfm/feature_loader.py +++ b/opensfm/feature_loader.py @@ -1,3 +1,4 @@ +# pyre-unsafe from opensfm import feature_loading diff --git a/opensfm/feature_loading.py b/opensfm/feature_loading.py index f985b6869..7ff3d4934 100644 --- a/opensfm/feature_loading.py +++ b/opensfm/feature_loading.py @@ -1,3 +1,4 @@ +# pyre-unsafe import logging from functools import lru_cache from typing import Optional, Tuple, Any diff --git a/opensfm/features.py b/opensfm/features.py index d4dbac37d..622c47ae2 100644 --- a/opensfm/features.py +++ b/opensfm/features.py @@ -1,3 +1,4 @@ +# pyre-unsafe """Tools to extract features.""" import logging diff --git a/opensfm/features_processing.py b/opensfm/features_processing.py index 52ce8c29c..94889eac9 100644 --- a/opensfm/features_processing.py +++ b/opensfm/features_processing.py @@ -1,3 +1,4 @@ +# pyre-unsafe import itertools import logging import math diff --git a/opensfm/geo.py b/opensfm/geo.py index 90c3d3d9d..335dad66f 100644 --- a/opensfm/geo.py +++ b/opensfm/geo.py @@ -1,3 +1,4 @@ +# pyre-unsafe import numpy as np from numpy import ndarray from typing import Tuple diff --git a/opensfm/geometry.py b/opensfm/geometry.py index 654a17469..43cd52a12 100644 --- a/opensfm/geometry.py +++ b/opensfm/geometry.py @@ -1,3 +1,4 @@ +# pyre-unsafe from typing import Tuple import cv2 diff --git a/opensfm/geotag_from_gpx.py b/opensfm/geotag_from_gpx.py index a206f907d..9198b3398 100644 --- a/opensfm/geotag_from_gpx.py +++ b/opensfm/geotag_from_gpx.py @@ -1,5 +1,7 @@ #!/usr/bin/python3 +# pyre-unsafe + import datetime import math import os diff --git a/opensfm/io.py b/opensfm/io.py index 95eaedfa3..bf72ae9f3 100644 --- a/opensfm/io.py +++ b/opensfm/io.py @@ -1,3 +1,4 @@ +# pyre-unsafe import json import logging import os diff --git a/opensfm/large/metadataset.py b/opensfm/large/metadataset.py index 81a016f6e..df5a27a7b 100644 --- a/opensfm/large/metadataset.py +++ b/opensfm/large/metadataset.py @@ -1,3 +1,4 @@ +# pyre-unsafe import os import os.path import shutil diff --git a/opensfm/large/tools.py b/opensfm/large/tools.py index e66c0d35e..fff5b6536 100644 --- a/opensfm/large/tools.py +++ b/opensfm/large/tools.py @@ -1,3 +1,4 @@ +# pyre-unsafe import itertools import logging from collections import namedtuple diff --git a/opensfm/log.py b/opensfm/log.py index 379a3a53b..ecca50c12 100644 --- a/opensfm/log.py +++ b/opensfm/log.py @@ -1,3 +1,4 @@ +# pyre-unsafe import logging import os from typing import Optional diff --git a/opensfm/masking.py b/opensfm/masking.py index 37bfe0ec8..3a20a86f7 100644 --- a/opensfm/masking.py +++ b/opensfm/masking.py @@ -1,3 +1,4 @@ +# pyre-unsafe import logging from typing import List, Tuple, Optional diff --git a/opensfm/matching.py b/opensfm/matching.py index 068d126e9..a96eee3f0 100644 --- a/opensfm/matching.py +++ b/opensfm/matching.py @@ -1,3 +1,4 @@ +# pyre-unsafe import logging from timeit import default_timer as timer from typing import Any, Dict, Generator, List, Optional, Sized, Tuple diff --git a/opensfm/mesh.py b/opensfm/mesh.py index 47447c275..9080a0a74 100644 --- a/opensfm/mesh.py +++ b/opensfm/mesh.py @@ -1,4 +1,6 @@ #!/usr/bin/env python3 + +# pyre-unsafe import itertools import logging from typing import Any, Tuple, List diff --git a/opensfm/multiview.py b/opensfm/multiview.py index 65dd3ea07..e6f37e9c0 100644 --- a/opensfm/multiview.py +++ b/opensfm/multiview.py @@ -1,3 +1,4 @@ +# pyre-unsafe import math import random from typing import Any, Dict, List, Optional, Tuple diff --git a/opensfm/pairs_selection.py b/opensfm/pairs_selection.py index 191ab030e..214e251b3 100644 --- a/opensfm/pairs_selection.py +++ b/opensfm/pairs_selection.py @@ -1,3 +1,4 @@ +# pyre-unsafe import copy import logging import math diff --git a/opensfm/reconstruction.py b/opensfm/reconstruction.py index eaa6a6a15..ad242f9ee 100644 --- a/opensfm/reconstruction.py +++ b/opensfm/reconstruction.py @@ -1,3 +1,4 @@ +# pyre-unsafe """Incremental reconstruction pipeline""" import datetime diff --git a/opensfm/reconstruction_helpers.py b/opensfm/reconstruction_helpers.py index 0b8787801..48aa4663b 100644 --- a/opensfm/reconstruction_helpers.py +++ b/opensfm/reconstruction_helpers.py @@ -1,3 +1,4 @@ +# pyre-unsafe import logging import math from typing import Any, Dict, Iterable, List, Optional diff --git a/opensfm/report.py b/opensfm/report.py index b1bf5f859..410f0a016 100644 --- a/opensfm/report.py +++ b/opensfm/report.py @@ -1,3 +1,4 @@ +# pyre-unsafe import logging import os import subprocess diff --git a/opensfm/rig.py b/opensfm/rig.py index e20003e42..d21380228 100644 --- a/opensfm/rig.py +++ b/opensfm/rig.py @@ -1,3 +1,4 @@ +# pyre-unsafe """Tool for handling rigs""" import logging diff --git a/opensfm/sensors.py b/opensfm/sensors.py index 7ff93f13c..9e2cc8796 100644 --- a/opensfm/sensors.py +++ b/opensfm/sensors.py @@ -1,3 +1,4 @@ +# pyre-unsafe from functools import lru_cache from typing import Any, Dict, List import yaml diff --git a/opensfm/stats.py b/opensfm/stats.py index 5cc3a5151..44dc31a05 100644 --- a/opensfm/stats.py +++ b/opensfm/stats.py @@ -1,3 +1,4 @@ +# pyre-unsafe import datetime import math import os diff --git a/opensfm/synthetic_data/synthetic_dataset.py b/opensfm/synthetic_data/synthetic_dataset.py index a6023010d..b52cdfcd7 100644 --- a/opensfm/synthetic_data/synthetic_dataset.py +++ b/opensfm/synthetic_data/synthetic_dataset.py @@ -1,3 +1,4 @@ +# pyre-unsafe import collections import logging import os diff --git a/opensfm/synthetic_data/synthetic_examples.py b/opensfm/synthetic_data/synthetic_examples.py index c17589395..2632854b5 100644 --- a/opensfm/synthetic_data/synthetic_examples.py +++ b/opensfm/synthetic_data/synthetic_examples.py @@ -1,3 +1,4 @@ +# pyre-unsafe from typing import Optional import opensfm.synthetic_data.synthetic_scene as ss diff --git a/opensfm/synthetic_data/synthetic_generator.py b/opensfm/synthetic_data/synthetic_generator.py index 6037761fa..90b3fc8da 100644 --- a/opensfm/synthetic_data/synthetic_generator.py +++ b/opensfm/synthetic_data/synthetic_generator.py @@ -1,3 +1,4 @@ +# pyre-unsafe import logging import math import time diff --git a/opensfm/synthetic_data/synthetic_metrics.py b/opensfm/synthetic_data/synthetic_metrics.py index baabb3853..762060aa8 100644 --- a/opensfm/synthetic_data/synthetic_metrics.py +++ b/opensfm/synthetic_data/synthetic_metrics.py @@ -1,3 +1,4 @@ +# pyre-unsafe from typing import Tuple, List, Dict import cv2 diff --git a/opensfm/synthetic_data/synthetic_scene.py b/opensfm/synthetic_data/synthetic_scene.py index 5a1e4f230..f8fcc8140 100644 --- a/opensfm/synthetic_data/synthetic_scene.py +++ b/opensfm/synthetic_data/synthetic_scene.py @@ -1,3 +1,4 @@ +# pyre-unsafe import functools import math from typing import Dict, Optional, List, Any, Union, Tuple, Callable diff --git a/opensfm/test/conftest.py b/opensfm/test/conftest.py index b8cc2ed9a..78331cd35 100644 --- a/opensfm/test/conftest.py +++ b/opensfm/test/conftest.py @@ -1,3 +1,4 @@ +# pyre-unsafe from collections import defaultdict from distutils.version import LooseVersion from typing import Dict, List, Tuple diff --git a/opensfm/test/data_generation.py b/opensfm/test/data_generation.py index 097d53c09..821f3a8b1 100644 --- a/opensfm/test/data_generation.py +++ b/opensfm/test/data_generation.py @@ -1,3 +1,4 @@ +# pyre-unsafe import os import opensfm.dataset diff --git a/opensfm/test/test_bundle.py b/opensfm/test/test_bundle.py index a3e12afaf..54202da06 100644 --- a/opensfm/test/test_bundle.py +++ b/opensfm/test/test_bundle.py @@ -1,3 +1,4 @@ +# pyre-unsafe import copy import numpy as np diff --git a/opensfm/test/test_commands.py b/opensfm/test/test_commands.py index 2e30159b8..a5890bcd9 100644 --- a/opensfm/test/test_commands.py +++ b/opensfm/test/test_commands.py @@ -1,3 +1,4 @@ +# pyre-unsafe import argparse from os.path import join diff --git a/opensfm/test/test_dataset.py b/opensfm/test/test_dataset.py index 02202e45d..60022ae0a 100644 --- a/opensfm/test/test_dataset.py +++ b/opensfm/test/test_dataset.py @@ -1,3 +1,4 @@ +# pyre-unsafe import numpy as np from opensfm import features from opensfm.test import data_generation diff --git a/opensfm/test/test_datastructures.py b/opensfm/test/test_datastructures.py index 2e8d1a25e..5e9c5cd9a 100644 --- a/opensfm/test/test_datastructures.py +++ b/opensfm/test/test_datastructures.py @@ -1,3 +1,4 @@ +# pyre-unsafe import copy from opensfm.pymap import RigCamera, RigInstance, Shot from opensfm.types import Reconstruction diff --git a/opensfm/test/test_dense.py b/opensfm/test/test_dense.py index 5f2bb9789..2c7bdd28e 100644 --- a/opensfm/test/test_dense.py +++ b/opensfm/test/test_dense.py @@ -1,3 +1,4 @@ +# pyre-unsafe import numpy as np from opensfm import dense from opensfm import pygeometry diff --git a/opensfm/test/test_geo.py b/opensfm/test/test_geo.py index a6d534be4..65c3b12bd 100644 --- a/opensfm/test/test_geo.py +++ b/opensfm/test/test_geo.py @@ -1,3 +1,4 @@ +# pyre-unsafe import numpy as np from opensfm import geo, pygeo diff --git a/opensfm/test/test_geometry.py b/opensfm/test/test_geometry.py index ccb5ec728..4d5890198 100644 --- a/opensfm/test/test_geometry.py +++ b/opensfm/test/test_geometry.py @@ -1,3 +1,4 @@ +# pyre-unsafe import numpy as np from opensfm import geometry diff --git a/opensfm/test/test_io.py b/opensfm/test/test_io.py index 23c90c140..0b43af2c5 100644 --- a/opensfm/test/test_io.py +++ b/opensfm/test/test_io.py @@ -1,3 +1,4 @@ +# pyre-unsafe import json import os.path from io import StringIO diff --git a/opensfm/test/test_matching.py b/opensfm/test/test_matching.py index c397b7ee1..c236de723 100644 --- a/opensfm/test/test_matching.py +++ b/opensfm/test/test_matching.py @@ -1,3 +1,4 @@ +# pyre-unsafe from typing import Any, Dict, List, Set, Tuple import numpy as np diff --git a/opensfm/test/test_multiview.py b/opensfm/test/test_multiview.py index ab943fe41..a0e6f1376 100644 --- a/opensfm/test/test_multiview.py +++ b/opensfm/test/test_multiview.py @@ -1,3 +1,4 @@ +# pyre-unsafe import copy import numpy as np diff --git a/opensfm/test/test_pairs_selection.py b/opensfm/test/test_pairs_selection.py index 3fdc04145..b16a2ce69 100644 --- a/opensfm/test/test_pairs_selection.py +++ b/opensfm/test/test_pairs_selection.py @@ -1,3 +1,4 @@ +# pyre-unsafe import argparse import os.path from typing import Any, Dict, Generator diff --git a/opensfm/test/test_reconstruction_alignment.py b/opensfm/test/test_reconstruction_alignment.py index fb2f156c4..a077cca4a 100644 --- a/opensfm/test/test_reconstruction_alignment.py +++ b/opensfm/test/test_reconstruction_alignment.py @@ -1,3 +1,4 @@ +# pyre-unsafe import numpy as np from opensfm import pybundle from opensfm import pygeometry diff --git a/opensfm/test/test_reconstruction_incremental.py b/opensfm/test/test_reconstruction_incremental.py index e1513dab5..1d3320e34 100644 --- a/opensfm/test/test_reconstruction_incremental.py +++ b/opensfm/test/test_reconstruction_incremental.py @@ -1,3 +1,4 @@ +# pyre-unsafe from opensfm import reconstruction from opensfm.synthetic_data import synthetic_dataset, synthetic_scene diff --git a/opensfm/test/test_reconstruction_resect.py b/opensfm/test/test_reconstruction_resect.py index 3a5e1f4dc..f55448d1a 100644 --- a/opensfm/test/test_reconstruction_resect.py +++ b/opensfm/test/test_reconstruction_resect.py @@ -1,3 +1,4 @@ +# pyre-unsafe import numpy as np from opensfm import config, multiview, pymap, reconstruction, types from typing import Tuple diff --git a/opensfm/test/test_reconstruction_shot_neighborhood.py b/opensfm/test/test_reconstruction_shot_neighborhood.py index d302a7fa7..f42f98603 100644 --- a/opensfm/test/test_reconstruction_shot_neighborhood.py +++ b/opensfm/test/test_reconstruction_shot_neighborhood.py @@ -1,3 +1,4 @@ +# pyre-unsafe import networkx as nx from opensfm import pygeometry from opensfm import pymap diff --git a/opensfm/test/test_reconstruction_triangulation.py b/opensfm/test/test_reconstruction_triangulation.py index a05056681..9f631872a 100644 --- a/opensfm/test/test_reconstruction_triangulation.py +++ b/opensfm/test/test_reconstruction_triangulation.py @@ -1,3 +1,4 @@ +# pyre-unsafe from opensfm import reconstruction from opensfm.synthetic_data import synthetic_dataset, synthetic_scene diff --git a/opensfm/test/test_rig.py b/opensfm/test/test_rig.py index 56fd95161..50677f3cc 100644 --- a/opensfm/test/test_rig.py +++ b/opensfm/test/test_rig.py @@ -1,3 +1,4 @@ +# pyre-unsafe """Test the rig module.""" import numpy as np from opensfm import pygeometry, rig, types diff --git a/opensfm/test/test_robust.py b/opensfm/test/test_robust.py index ed296dd4c..6c02d71a9 100644 --- a/opensfm/test/test_robust.py +++ b/opensfm/test/test_robust.py @@ -1,3 +1,4 @@ +# pyre-unsafe import copy from typing import Tuple diff --git a/opensfm/test/test_stats.py b/opensfm/test/test_stats.py index b486794eb..2511fb255 100644 --- a/opensfm/test/test_stats.py +++ b/opensfm/test/test_stats.py @@ -1,3 +1,4 @@ +# pyre-unsafe from opensfm import stats, types from opensfm.synthetic_data import synthetic_dataset, synthetic_scene diff --git a/opensfm/test/test_triangulation.py b/opensfm/test/test_triangulation.py index 1620931c9..734be5d6c 100644 --- a/opensfm/test/test_triangulation.py +++ b/opensfm/test/test_triangulation.py @@ -1,3 +1,4 @@ +# pyre-unsafe import numpy as np from opensfm import io from opensfm import pygeometry diff --git a/opensfm/test/test_types.py b/opensfm/test/test_types.py index 01a27f560..679c2ab02 100644 --- a/opensfm/test/test_types.py +++ b/opensfm/test/test_types.py @@ -1,3 +1,4 @@ +# pyre-unsafe import copy import sys diff --git a/opensfm/test/test_undistort.py b/opensfm/test/test_undistort.py index 3ea656967..e5e8120f6 100644 --- a/opensfm/test/test_undistort.py +++ b/opensfm/test/test_undistort.py @@ -1,3 +1,4 @@ +# pyre-unsafe import itertools import numpy as np diff --git a/opensfm/test/test_vlad.py b/opensfm/test/test_vlad.py index c406195c0..dee12fa08 100644 --- a/opensfm/test/test_vlad.py +++ b/opensfm/test/test_vlad.py @@ -1,3 +1,4 @@ +# pyre-unsafe import numpy as np import pytest from opensfm import vlad diff --git a/opensfm/test/utils.py b/opensfm/test/utils.py index 0531458d9..562bbd1fe 100644 --- a/opensfm/test/utils.py +++ b/opensfm/test/utils.py @@ -1,4 +1,6 @@ # Test utils for python + +# pyre-unsafe import numpy as np from opensfm import pygeo, pygeometry, pymap diff --git a/opensfm/tracking.py b/opensfm/tracking.py index 4cb699ee4..c1b79798c 100644 --- a/opensfm/tracking.py +++ b/opensfm/tracking.py @@ -1,3 +1,4 @@ +# pyre-unsafe import logging import typing as t diff --git a/opensfm/transformations.py b/opensfm/transformations.py index 96bcd6bdc..071915b64 100644 --- a/opensfm/transformations.py +++ b/opensfm/transformations.py @@ -1,5 +1,7 @@ # transformations.py +# pyre-unsafe + # Copyright (c) 2006-2013, Christoph Gohlke # Copyright (c) 2006-2013, The Regents of the University of California # Produced at the Laboratory for Fluorescence Dynamics diff --git a/opensfm/types.py b/opensfm/types.py index 7e444b9c9..6492e8509 100644 --- a/opensfm/types.py +++ b/opensfm/types.py @@ -1,3 +1,4 @@ +# pyre-unsafe """Basic types for building a reconstruction.""" from typing import Dict, Optional diff --git a/opensfm/undistort.py b/opensfm/undistort.py index 63bae4de6..f7e3f0803 100644 --- a/opensfm/undistort.py +++ b/opensfm/undistort.py @@ -1,3 +1,4 @@ +# pyre-unsafe import itertools import logging from typing import Iterator, List, Dict, Optional diff --git a/opensfm/unionfind.py b/opensfm/unionfind.py index bf0345bf5..aca3e8951 100644 --- a/opensfm/unionfind.py +++ b/opensfm/unionfind.py @@ -1,6 +1,8 @@ # Source: https://www.ics.uci.edu/~eppstein/PADS/UnionFind.py # Licence: MIT +# pyre-unsafe + # This is PADS, a library of Python Algorithms and Data Structures # implemented by David Eppstein of the University of California, Irvine. diff --git a/opensfm/upright.py b/opensfm/upright.py index bfa2a3df2..c06cc409a 100644 --- a/opensfm/upright.py +++ b/opensfm/upright.py @@ -1,3 +1,4 @@ +# pyre-unsafe import numpy as np from typing import Optional diff --git a/opensfm/video.py b/opensfm/video.py index a951240c2..9e34b6e92 100644 --- a/opensfm/video.py +++ b/opensfm/video.py @@ -1,3 +1,4 @@ +# pyre-unsafe import datetime import os from subprocess import Popen, PIPE diff --git a/opensfm/vlad.py b/opensfm/vlad.py index 5cf9b02b4..5c623e0f1 100644 --- a/opensfm/vlad.py +++ b/opensfm/vlad.py @@ -1,3 +1,4 @@ +# pyre-unsafe from functools import lru_cache from typing import List, Tuple, Iterable, Dict, Optional diff --git a/viewer/server.py b/viewer/server.py index 536c0fc2e..418791c79 100644 --- a/viewer/server.py +++ b/viewer/server.py @@ -1,3 +1,4 @@ +# pyre-unsafe import argparse import os from typing import List From 938a3a169e66adb71949907fcf3ebca2089727a9 Mon Sep 17 00:00:00 2001 From: Richard Barnes Date: Wed, 6 Mar 2024 07:58:20 -0800 Subject: [PATCH 066/235] Fix `-Wimplicit-const-int-float-conversion` violation in mapillary/opensfm/opensfm/src/features/src/matching.cc Summary: # Overview LLVM has detected a bad _implicit constant integer to float conversion_ in mapillary/opensfm/opensfm/src/features/src/matching.cc. Almost all such cases lead to very subtle bugs, so we are making them a compiler error by default. # Reproducer The fix can be checked using: ``` buck2 build --config cxx.extra_cxxflags=-Wimplicit-const-int-float-conversion ``` # Description of the problem What value do you think this produces? ``` static_cast(static_cast(std::numeric_limits::max())) ``` You'd hope it would produce UINT64_MAX (18446744073709551615), but it doesn't. In debug mode it produces 9223372036854775808 (half of the above). In opt mode it produces "random" numbers such as 140726009322632 (which is 130,000x smaller than UINT64_MAX). Comparisons between floats and maximum integer values are also scary: ``` constexpr double x = std::numeric_limits::max(); constexpr auto kMax64 = std::numeric_limits::max(); std::cout << (x > kMax64 ? kMax64 : static_cast(x)) << std::endl; ``` produces garbage: 140731185888920 The reason this happens is because floating-point types can only represent integers sparsely in the regions of the maximum integers (generated with P1188399781): ``` delta = 128 2147483264 f 2147483392 f 2147483520 f 2147483647 <- Largest integer 2147483648 f 2147483904 f 2147484160 f delta = 256 4294966528 f 4294966784 f 4294967040 f 4294967295 <- Largest integer 4294967296 f 4294967808 f 4294968320 f delta = 1024 9223372036854772736 d 9223372036854773760 d 9223372036854774784 d 9223372036854775807 <- Largest integer 9223372036854775808 d 9223372036854777856 d 9223372036854779904 d delta = 2048 18446744073709545472 d 18446744073709547520 d 18446744073709549568 d 18446744073709551615 <- Largest integer 18446744073709551616 d 18446744073709555712 d 18446744073709559808 d ``` # Fixing the Problem See example fixes in D54119898, D54119901, D54119899. ## Careful Clamping The fix will be situation dependent, `folly::constexpr_clamp_cast` is _very_ useful: ``` // Include the target `//folly:constexpr_math` #include #include #include int main() { constexpr auto kMax32 = std::numeric_limits::max(); std::cout << folly::constexpr_clamp_cast(static_cast(kMax32)) << std::endl; return 0; } ``` ## Use infinity In some cases we want want something like ``` double smallest_value = BIG_NUMBER; for (const auto &x : values) { smallest_value = std::min(smallest_value, x); } ``` If `BIG_NUMBER` is an integer this code could be incorrect! Instead we use ``` double smallest_value = std::numeric_limits::infinity(); ``` ## Make the conversion explicit For situations in which we are dividing by a very large integer, we can use `static_cast(LARGE_INT)` to make the conversion from int to float explicit. The conversion is _not_ exact, but our hope is that the precision we've lost is small enough that it doesn't matter for the problem being solved. Reviewed By: YanNoun Differential Revision: D54586513 fbshipit-source-id: 87fba3097e3822eb68660e0f2ab947eaf6450698 --- opensfm/src/features/src/matching.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/opensfm/src/features/src/matching.cc b/opensfm/src/features/src/matching.cc index b25ed46ca..26e7e4339 100644 --- a/opensfm/src/features/src/matching.cc +++ b/opensfm/src/features/src/matching.cc @@ -41,8 +41,8 @@ void MatchUsingWords(const cv::Mat &f1, const cv::Mat &w1, const cv::Mat &f2, } std::vector best_match(f1.rows, -1), second_best_match(f1.rows, -1); - std::vector best_distance(f1.rows, 99999999), - second_best_distance(f1.rows, 99999999); + std::vector best_distance(f1.rows, std::numeric_limits::infinity()); + std::vector second_best_distance(f1.rows, std::numeric_limits::infinity()); *matches = cv::Mat(0, 2, CV_32S); cv::Mat tmp_match(1, 2, CV_32S); for (unsigned int i = 0; i < w1.rows; ++i) { From 424ecc210ee468c0eab46a019d484ceaf4893a21 Mon Sep 17 00:00:00 2001 From: Richard Barnes Date: Wed, 6 Mar 2024 08:05:42 -0800 Subject: [PATCH 067/235] Fix `-Wimplicit-const-int-float-conversion` violation in mapillary/opensfm/opensfm/src/dense/src/depthmap.cc Summary: # Overview LLVM has detected a bad _implicit constant integer to float conversion_ in mapillary/opensfm/opensfm/src/dense/src/depthmap.cc. Almost all such cases lead to very subtle bugs, so we are making them a compiler error by default. # Reproducer The fix can be checked using: ``` buck2 build --config cxx.extra_cxxflags=-Wimplicit-const-int-float-conversion ``` # Description of the problem What value do you think this produces? ``` static_cast(static_cast(std::numeric_limits::max())) ``` You'd hope it would produce UINT64_MAX (18446744073709551615), but it doesn't. In debug mode it produces 9223372036854775808 (half of the above). In opt mode it produces "random" numbers such as 140726009322632 (which is 130,000x smaller than UINT64_MAX). Comparisons between floats and maximum integer values are also scary: ``` constexpr double x = std::numeric_limits::max(); constexpr auto kMax64 = std::numeric_limits::max(); std::cout << (x > kMax64 ? kMax64 : static_cast(x)) << std::endl; ``` produces garbage: 140731185888920 The reason this happens is because floating-point types can only represent integers sparsely in the regions of the maximum integers (generated with P1188399781): ``` delta = 128 2147483264 f 2147483392 f 2147483520 f 2147483647 <- Largest integer 2147483648 f 2147483904 f 2147484160 f delta = 256 4294966528 f 4294966784 f 4294967040 f 4294967295 <- Largest integer 4294967296 f 4294967808 f 4294968320 f delta = 1024 9223372036854772736 d 9223372036854773760 d 9223372036854774784 d 9223372036854775807 <- Largest integer 9223372036854775808 d 9223372036854777856 d 9223372036854779904 d delta = 2048 18446744073709545472 d 18446744073709547520 d 18446744073709549568 d 18446744073709551615 <- Largest integer 18446744073709551616 d 18446744073709555712 d 18446744073709559808 d ``` # Fixing the Problem See example fixes in D54119898, D54119901, D54119899. ## Careful Clamping The fix will be situation dependent, `folly::constexpr_clamp_cast` is _very_ useful: ``` // Include the target `//folly:constexpr_math` #include #include #include int main() { constexpr auto kMax32 = std::numeric_limits::max(); std::cout << folly::constexpr_clamp_cast(static_cast(kMax32)) << std::endl; return 0; } ``` ## Use infinity In some cases we want want something like ``` double smallest_value = BIG_NUMBER; for (const auto &x : values) { smallest_value = std::min(smallest_value, x); } ``` If `BIG_NUMBER` is an integer this code could be incorrect! Instead we use ``` double smallest_value = std::numeric_limits::infinity(); ``` ## Make the conversion explicit For situations in which we are dividing by a very large integer, we can use `static_cast(LARGE_INT)` to make the conversion from int to float explicit. The conversion is _not_ exact, but our hope is that the precision we've lost is small enough that it doesn't matter for the problem being solved. Reviewed By: YanNoun Differential Revision: D54586527 fbshipit-source-id: 6ac8812158f204457e002f2c3ec15b55d8fcb538 --- opensfm/src/dense/src/depthmap.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/opensfm/src/dense/src/depthmap.cc b/opensfm/src/dense/src/depthmap.cc index a665d9296..57ef85b6d 100644 --- a/opensfm/src/dense/src/depthmap.cc +++ b/opensfm/src/dense/src/depthmap.cc @@ -126,7 +126,8 @@ cv::Vec3f PlaneFromDepthAndNormal(float x, float y, const cv::Matx33d &K, } float UniformRand(float a, float b) { - return a + (b - a) * float(rand()) / RAND_MAX; + // Note that float(RAND_MAX) cannot be exactly represented as a float. We ignore the small inaccuracy here; this is already a bad way to get random numbers. + return a + (b - a) * float(rand()) / static_cast(RAND_MAX); } DepthmapEstimator::DepthmapEstimator() From afb0c15beacbf68890c3ddcadbb33186cc03f379 Mon Sep 17 00:00:00 2001 From: Richard Barnes Date: Thu, 7 Mar 2024 08:17:38 -0800 Subject: [PATCH 068/235] Fix `-Wimplicit-const-int-float-conversion` violation in mapillary/opensfm/opensfm/src/geometry/relative_pose.h Summary: # Overview LLVM has detected a bad _implicit constant integer to float conversion_ in mapillary/opensfm/opensfm/src/geometry/relative_pose.h. Almost all such cases lead to very subtle bugs, so we are making them a compiler error by default. # Reproducer The fix can be checked using: ``` buck2 build --config cxx.extra_cxxflags=-Wimplicit-const-int-float-conversion ``` # Description of the problem What value do you think this produces? ``` static_cast(static_cast(std::numeric_limits::max())) ``` You'd hope it would produce UINT64_MAX (18446744073709551615), but it doesn't. In debug mode it produces 9223372036854775808 (half of the above). In opt mode it produces "random" numbers such as 140726009322632 (which is 130,000x smaller than UINT64_MAX). Comparisons between floats and maximum integer values are also scary: ``` constexpr double x = std::numeric_limits::max(); constexpr auto kMax64 = std::numeric_limits::max(); std::cout << (x > kMax64 ? kMax64 : static_cast(x)) << std::endl; ``` produces garbage: 140731185888920 The reason this happens is because floating-point types can only represent integers sparsely in the regions of the maximum integers (generated with P1188399781): ``` delta = 128 2147483264 f 2147483392 f 2147483520 f 2147483647 <- Largest integer 2147483648 f 2147483904 f 2147484160 f delta = 256 4294966528 f 4294966784 f 4294967040 f 4294967295 <- Largest integer 4294967296 f 4294967808 f 4294968320 f delta = 1024 9223372036854772736 d 9223372036854773760 d 9223372036854774784 d 9223372036854775807 <- Largest integer 9223372036854775808 d 9223372036854777856 d 9223372036854779904 d delta = 2048 18446744073709545472 d 18446744073709547520 d 18446744073709549568 d 18446744073709551615 <- Largest integer 18446744073709551616 d 18446744073709555712 d 18446744073709559808 d ``` # Fixing the Problem See example fixes in D54119898, D54119901, D54119899. ## Careful Clamping The fix will be situation dependent, `folly::constexpr_clamp_cast` is _very_ useful: ``` // Include the target `//folly:constexpr_math` #include #include #include int main() { constexpr auto kMax32 = std::numeric_limits::max(); std::cout << folly::constexpr_clamp_cast(static_cast(kMax32)) << std::endl; return 0; } ``` ## Use infinity In some cases we want want something like ``` double smallest_value = BIG_NUMBER; for (const auto &x : values) { smallest_value = std::min(smallest_value, x); } ``` If `BIG_NUMBER` is an integer this code could be incorrect! Instead we use ``` double smallest_value = std::numeric_limits::infinity(); ``` ## Make the conversion explicit For situations in which we are dividing by a very large integer, we can use `static_cast(LARGE_INT)` to make the conversion from int to float explicit. The conversion is _not_ exact, but our hope is that the precision we've lost is small enough that it doesn't matter for the problem being solved. Reviewed By: dmm-fb Differential Revision: D54586517 fbshipit-source-id: b03d0e05edc5dccff17811e8419548cfb72759b0 --- opensfm/src/geometry/relative_pose.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/opensfm/src/geometry/relative_pose.h b/opensfm/src/geometry/relative_pose.h index 997875764..7fb759fd9 100644 --- a/opensfm/src/geometry/relative_pose.h +++ b/opensfm/src/geometry/relative_pose.h @@ -87,7 +87,8 @@ struct RelativePoseCost { std::srand(42); const int count = end_ - begin_; for (int i = 0; i < MAX_ERRORS; ++i) { - const int index = (float(std::rand()) / RAND_MAX) * count; + // Note that float(RAND_MAX) cannot be exactly represented as a float. We ignore the small inaccuracy here; this is already a bad way to get random numbers. + const int index = (float(std::rand()) / static_cast(RAND_MAX)) * count; picked_errors_.push_back(begin_ + index); } } From 78b795c58a4684195c6c7ab5e7d531ee484f32c6 Mon Sep 17 00:00:00 2001 From: Richard Barnes Date: Thu, 7 Mar 2024 10:57:56 -0800 Subject: [PATCH 069/235] Remove unused variables in mapillary/opensfm/opensfm/src/third_party/akaze/lib/AKAZE.cpp Summary: LLVM-15 has a warning `-Wunused-but-set-variable` which we treat as an error because it's so often diagnostic of a code issue. Unused variables can compromise readability or, worse, performance. This diff either (a) removes an unused variable and, possibly, it's associated code, or (b) qualifies the variable with `[[maybe_unused]]`, mostly in cases where the variable _is_ used, but, eg, in an `assert` statement that isn't present in production code. - If you approve of this diff, please use the "Accept & Ship" button :-) Reviewed By: dmm-fb Differential Revision: D54378379 fbshipit-source-id: 0a23b525ffbe0862e32609ce45af4c2cd7794551 --- opensfm/src/third_party/akaze/lib/AKAZE.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/opensfm/src/third_party/akaze/lib/AKAZE.cpp b/opensfm/src/third_party/akaze/lib/AKAZE.cpp index 5d42f251d..e49b6f1c2 100644 --- a/opensfm/src/third_party/akaze/lib/AKAZE.cpp +++ b/opensfm/src/third_party/akaze/lib/AKAZE.cpp @@ -269,7 +269,7 @@ void AKAZE::Find_Scale_Space_Extrema(std::vector& kpts) { double t1 = 0.0, t2 = 0.0; float value = 0.0; float dist = 0.0, ratio = 0.0, smax = 0.0; - int npoints = 0, id_repeated = 0; + int id_repeated = 0; int sigma_size_ = 0, left_x = 0, right_x = 0, up_y = 0, down_y = 0; bool is_extremum = false, is_repeated = false, is_out = false; cv::KeyPoint point; @@ -357,7 +357,6 @@ void AKAZE::Find_Scale_Space_Extrema(std::vector& kpts) { point.pt.x *= ratio; point.pt.y *= ratio; kpts_aux.push_back(point); - npoints++; } else { point.pt.x *= ratio; From 4b562c6ab178b60d1f167dc2ec24d6dad8bb7aa6 Mon Sep 17 00:00:00 2001 From: oafolabi Date: Mon, 18 Mar 2024 10:02:32 -0700 Subject: [PATCH 070/235] =?UTF-8?q?returning=20norm=5Fcoords=20instead=20o?= =?UTF-8?q?f=20px=5Fcoords=20in=20pixelToNormalizedCoordi=E2=80=A6=20(#103?= =?UTF-8?q?1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: …natesMany Attempting to fix issue create here: [https://github.com/mapillary/OpenSfM/issues/1030#issue-2046628484](https://github.com/mapillary/OpenSfM/issues/1030#issue-2046628484) Pull Request resolved: https://github.com/mapillary/OpenSfM/pull/1031 Reviewed By: paulinus Differential Revision: D55006764 Pulled By: fabianschenk fbshipit-source-id: 506078187c0f2387535521f0068c3322f2465b22 --- opensfm/src/geometry/src/camera.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opensfm/src/geometry/src/camera.cc b/opensfm/src/geometry/src/camera.cc index 45619f6cf..d864fa743 100644 --- a/opensfm/src/geometry/src/camera.cc +++ b/opensfm/src/geometry/src/camera.cc @@ -366,7 +366,7 @@ MatX2d Camera::PixelToNormalizedCoordinatesMany(const MatX2d& px_coords, norm_coords.row(i) = PixelToNormalizedCoordinates(px_coords.row(i), width, height); } - return px_coords; + return norm_coords; } Vec2d Camera::NormalizedToPixelCoordinates(const Vec2d& norm_coord) const { From c72419228fb8c86f2c367989abd64f784ec684b3 Mon Sep 17 00:00:00 2001 From: generatedunixname89002005307016 Date: Thu, 21 Mar 2024 18:37:26 -0700 Subject: [PATCH 071/235] upgrade pyre version in `fbcode/mapillary` - batch 1 Differential Revision: D55201655 fbshipit-source-id: a1eb370d0b39457e3f59614a093a50022869eca9 --- opensfm/commands/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/opensfm/commands/__init__.py b/opensfm/commands/__init__.py index 97a2f32fe..da12e64dc 100644 --- a/opensfm/commands/__init__.py +++ b/opensfm/commands/__init__.py @@ -24,6 +24,7 @@ reconstruct_from_prior, undistort, ) +# pyre-fixme[21]: Could not find module `opensfm.commands.command_runner`. from .command_runner import command_runner From 5e854bb43f046ac9277dcfc7a891bab8587f070f Mon Sep 17 00:00:00 2001 From: generatedunixname89002005307016 Date: Tue, 2 Apr 2024 17:49:18 -0700 Subject: [PATCH 072/235] upgrade pyre version in `fbcode/mapillary` - batch 1 Differential Revision: D55650790 fbshipit-source-id: e7eb7d1ee3f84943d28a1f893e75f58e9b4a67e1 --- opensfm/commands/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/opensfm/commands/__init__.py b/opensfm/commands/__init__.py index da12e64dc..97a2f32fe 100644 --- a/opensfm/commands/__init__.py +++ b/opensfm/commands/__init__.py @@ -24,7 +24,6 @@ reconstruct_from_prior, undistort, ) -# pyre-fixme[21]: Could not find module `opensfm.commands.command_runner`. from .command_runner import command_runner From 5b32e380a66e095894de82291087c674e0d6d3cd Mon Sep 17 00:00:00 2001 From: True Price Date: Thu, 18 Apr 2024 12:39:11 -0700 Subject: [PATCH 073/235] Remove unused pybind11 functions Differential Revision: D56274720 fbshipit-source-id: bd23cac89ee6df6190e8b847591ba2a12d8b4c66 --- opensfm/src/map/pybind_utils.h | 154 +++++++-------------------------- 1 file changed, 32 insertions(+), 122 deletions(-) diff --git a/opensfm/src/map/pybind_utils.h b/opensfm/src/map/pybind_utils.h index e7f402eed..bcb878176 100644 --- a/opensfm/src/map/pybind_utils.h +++ b/opensfm/src/map/pybind_utils.h @@ -12,12 +12,10 @@ #define PYBIND11_NAMESPACE_END_ NAMESPACE_END #endif - PYBIND11_NAMESPACE_BEGIN_(PYBIND11_NAMESPACE) PYBIND11_NAMESPACE_BEGIN_(detail) // See https://github.com/pybind/pybind11/issues/637 -// Also fbsource/fbcode/caffe2/torch/csrc/jit/python/pybind.h using ListCasterBase = pybind11::detail::list_caster, @@ -52,45 +50,12 @@ struct sfm_iterator_state { }; PYBIND11_NAMESPACE_END_(detail) -/// Makes an python iterator over the keys (`.first`) of a iterator over pairs -/// from a first and past-the-end InputIterator. -template ()).second), - typename... Extra> -iterator make_value_iterator(Iterator first, Sentinel last, Extra &&... extra) { - typedef detail::sfm_iterator_state - state; - - if (!detail::get_type_info(typeid(state), false)) { - class_(handle(), "iterator", pybind11::module_local()) - .def("__iter__", [](state &s) -> state & { return s; }) - .def("__next__", - [](state &s) -> KeyType { - if (!s.first_or_done) { - ++s.it; - } else { - s.first_or_done = false; - } - if (s.it == s.end) { - s.first_or_done = true; - throw stop_iteration(); - } - return (*s.it).second; - }, - std::forward(extra)..., Policy); - } - - return cast(state{first, last, true}); -} - template ()).second)), typename... Extra> iterator make_ref_value_iterator(Iterator first, Sentinel last, - Extra &&... extra) { + Extra &&...extra) { typedef detail::sfm_iterator_state state; @@ -98,20 +63,21 @@ iterator make_ref_value_iterator(Iterator first, Sentinel last, if (!detail::get_type_info(typeid(state), false)) { class_(handle(), "ref_value_iterator", pybind11::module_local()) .def("__iter__", [](state &s) -> state & { return s; }) - .def("__next__", - [](state &s) -> KeyType { - if (!s.first_or_done) { - ++s.it; - } else { - s.first_or_done = false; - } - if (s.it == s.end) { - s.first_or_done = true; - throw stop_iteration(); - } - return &(s.it->second); - }, - std::forward(extra)..., Policy); + .def( + "__next__", + [](state &s) -> KeyType { + if (!s.first_or_done) { + ++s.it; + } else { + s.first_or_done = false; + } + if (s.it == s.end) { + s.first_or_done = true; + throw stop_iteration(); + } + return &(s.it->second); + }, + std::forward(extra)..., Policy); } return cast(state{first, last, true}); @@ -123,7 +89,7 @@ template < typename KeyType = pybind11::tuple, // decltype(&((*std::declval()).second)), typename... Extra> -iterator make_ref_iterator(Iterator first, Sentinel last, Extra &&... extra) { +iterator make_ref_iterator(Iterator first, Sentinel last, Extra &&...extra) { typedef detail::sfm_iterator_state state; @@ -131,80 +97,24 @@ iterator make_ref_iterator(Iterator first, Sentinel last, Extra &&... extra) { if (!detail::get_type_info(typeid(state), false)) { class_(handle(), "ref_iterator", pybind11::module_local()) .def("__iter__", [](state &s) -> state & { return s; }) - .def("__next__", - [](state &s) -> KeyType { - if (!s.first_or_done) { - ++s.it; - } else { - s.first_or_done = false; - } - if (s.it == s.end) { - s.first_or_done = true; - throw stop_iteration(); - } - return pybind11::make_tuple(s.it->first, &(s.it->second)); - }, - std::forward(extra)..., Policy); - } - - return cast(state{first, last, true}); -} - -/// Makes a python iterator from a first and past-the-end C++ InputIterator. -template ()), - typename... Extra> -iterator make_ptr_iterator(Iterator first, Sentinel last, Extra &&... extra) { - typedef detail::iterator_state state; - - if (!detail::get_type_info(typeid(state), false)) { - class_(handle(), "iterator", pybind11::module_local()) - .def("__iter__", [](state &s) -> state & { return s; }) - .def("__next__", - [](state &s) -> ValueType { - if (!s.first_or_done) { - ++s.it; - } else { - s.first_or_done = false; - } - if (s.it == s.end) { - s.first_or_done = true; - throw stop_iteration(); - } - return s.it; - }, - std::forward(extra)..., Policy); + .def( + "__next__", + [](state &s) -> KeyType { + if (!s.first_or_done) { + ++s.it; + } else { + s.first_or_done = false; + } + if (s.it == s.end) { + s.first_or_done = true; + throw stop_iteration(); + } + return pybind11::make_tuple(s.it->first, &(s.it->second)); + }, + std::forward(extra)..., Policy); } return cast(state{first, last, true}); } -/// Makes an iterator over the keys (`.first`) of a stl map-like container -/// supporting `std::begin()`/`std::end()` -template -iterator make_value_iterator(Type &value, Extra &&... extra) { - return make_value_iterator(std::begin(value), std::end(value), - extra...); -} -template -iterator make_unique_ptr_value_iterator(Type &value, Extra &&... extra) { - return make_unique_ptr_value_iterator(std::begin(value), - std::end(value), extra...); -} -template -iterator make_unique_ptr_iterator(Type &value, Extra &&... extra) { - return make_unique_ptr_iterator(std::begin(value), std::end(value), - extra...); -} - -template -iterator make_ref_value_iterator(Type &value, Extra &&... extra) { - return make_ref_value_iterator(std::begin(value), std::end(value), - extra...); -} PYBIND11_NAMESPACE_END_(PYBIND11_NAMESPACE) From 40b73c08d4a7087a6d76033284eb6c66e1efe35f Mon Sep 17 00:00:00 2001 From: Sebastian Gassner Date: Mon, 3 Jun 2024 01:02:22 -0700 Subject: [PATCH 074/235] describe how to build and use docker images (#1049) Summary: Pull Request resolved: https://github.com/mapillary/OpenSfM/pull/1049 Reviewed By: paulinus Differential Revision: D57765801 Pulled By: fabianschenk fbshipit-source-id: 6aa8c2678ac0007d42baa410b43077d4cccdd9ad --- doc/source/building.rst | 12 +++++++++++- doc/source/using.rst | 15 +++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/doc/source/building.rst b/doc/source/building.rst index 591444af4..56a76ec96 100644 --- a/doc/source/building.rst +++ b/doc/source/building.rst @@ -108,6 +108,16 @@ Once the dependencies have been installed, you can build OpenSfM by running the python3 setup.py build +Building Docker images +---------------------- + +Once dependencies have been installed, you can build OpenSfM Docker images by running the following command from the main folder:: + + docker build -t opensfm -f Dockerfile . + +To build an image using the Ceres 2 solver, use:: + + docker build -t opensfm:ceres2 -f Dockerfile.ceres2 . Building the documentation -------------------------- @@ -131,4 +141,4 @@ and browse `http://localhost:8000/ `_ .. _git: https://git-scm.com/ .. _cmake: https://cmake.org/ .. _Visual Studio 2019: https://visualstudio.microsoft.com/downloads/ -.. _Python 3.8: https://www.microsoft.com/en-us/p/python-38/9mssztt1n39l \ No newline at end of file +.. _Python 3.8: https://www.microsoft.com/en-us/p/python-38/9mssztt1n39l diff --git a/doc/source/using.rst b/doc/source/using.rst index bcd3aeee4..9cf364ead 100644 --- a/doc/source/using.rst +++ b/doc/source/using.rst @@ -14,6 +14,21 @@ An example dataset is available at ``data/berlin``. You can reconstruct it by r This will run the entire SfM pipeline and produce the file ``data/berlin/reconstruction.meshed.json`` as output. +Running in Docker +''''''''''''''''' + +First, build the OpenSfM Docker image, as described under "building". + + +Then, start a Docker container. The following command mounts the `data/` folder to `/data/` inside the Docker container:: + + docker run -it -p 8080:8080 -v ${PWD}/data/:/data/ opensfm:ceres2 + +Once inside the running Docker container, start the reconstruction process with the usual command:: + + bin/opensfm_run_all /data/berlin/ + +When done, exit the container by pressing Ctrl+d. The model generated will be available in the `data/` catalogue. Viewer setup '''''''''''' From b18e63800126844b27c9d56d2da466c6a58c6d1f Mon Sep 17 00:00:00 2001 From: kielnino Date: Mon, 3 Jun 2024 01:50:18 -0700 Subject: [PATCH 075/235] Remove dublicated SIFT-Dectector instance in feature matching (#1053) Summary: It seems to me that the SIFT detector is instantiated, but then not used, because the object is created again in the following while loop. This merge request removes the unnecessary code. I have also made the missing parameters of the OpenCV-Sift implementation configurable. Pull Request resolved: https://github.com/mapillary/OpenSfM/pull/1053 Reviewed By: paulinus Differential Revision: D57765783 Pulled By: fabianschenk fbshipit-source-id: 59a24bbbc60f55c1cb5e1f81a9896ec13f82e5d8 --- opensfm/config.py | 6 ++++++ opensfm/features.py | 48 +++++++++++++++++++-------------------------- 2 files changed, 26 insertions(+), 28 deletions(-) diff --git a/opensfm/config.py b/opensfm/config.py index 907e9c1ed..d19591333 100644 --- a/opensfm/config.py +++ b/opensfm/config.py @@ -42,6 +42,12 @@ class OpenSfMConfig: sift_peak_threshold: float = 0.1 # See OpenCV doc sift_edge_threshold: int = 10 + # See OpenCV doc + sift_nfeatures: int = 0 + # See OpenCV doc + sift_octave_layers: int = 3 + # See OpenCV doc + sift_sigma: float = 1.6 ################################## # Params for SURF diff --git a/opensfm/features.py b/opensfm/features.py index 622c47ae2..26eb0c05a 100644 --- a/opensfm/features.py +++ b/opensfm/features.py @@ -353,45 +353,36 @@ def extract_features_sift( ) -> Tuple[np.ndarray, np.ndarray]: sift_edge_threshold = config["sift_edge_threshold"] sift_peak_threshold = float(config["sift_peak_threshold"]) - # SIFT support is in cv2 main from version 4.4.0 - if context.OPENCV44 or context.OPENCV5: - # OpenCV versions concerned /** 3.4.11, >= 4.4.0 **/ ==> Sift became free since March 2020 - detector = cv2.SIFT_create( - edgeThreshold=sift_edge_threshold, contrastThreshold=sift_peak_threshold - ) - descriptor = detector - elif context.OPENCV3 or context.OPENCV4: - try: - # OpenCV versions concerned /** 3.2.x, 3.3.x, 3.4.0, 3.4.1, 3.4.2, 3.4.10, 4.3.0, 4.4.0 **/ - detector = cv2.xfeatures2d.SIFT_create( - edgeThreshold=sift_edge_threshold, contrastThreshold=sift_peak_threshold - ) - except AttributeError as ae: - # OpenCV versions concerned /** 3.4.3, 3.4.4, 3.4.5, 3.4.6, 3.4.7, 3.4.8, 3.4.9, 4.0.x, 4.1.x, 4.2.x **/ - if "no attribute 'xfeatures2d'" in str(ae): - logger.error( - "OpenCV Contrib modules are required to extract SIFT features" - ) - raise - descriptor = detector - else: - detector = cv2.FeatureDetector_create("SIFT") - descriptor = cv2.DescriptorExtractor_create("SIFT") - detector.setDouble("edgeThreshold", sift_edge_threshold) + sift_nfeatures = config["sift_nfeatures"] + sift_octave_layers = config["sift_octave_layers"] + sift_sigma = float(config["sift_sigma"]) while True: logger.debug("Computing sift with threshold {0}".format(sift_peak_threshold)) t = time.time() # SIFT support is in cv2 main from version 4.4.0 if context.OPENCV44 or context.OPENCV5: detector = cv2.SIFT_create( - edgeThreshold=sift_edge_threshold, contrastThreshold=sift_peak_threshold + nfeatures=sift_nfeatures, + nOctaveLayers=sift_octave_layers, + contrastThreshold=sift_peak_threshold, + edgeThreshold=sift_edge_threshold, + sigma=sift_sigma, ) + descriptor = detector elif context.OPENCV3: detector = cv2.xfeatures2d.SIFT_create( - edgeThreshold=sift_edge_threshold, contrastThreshold=sift_peak_threshold + nfeatures=sift_nfeatures, + nOctaveLayers=sift_octave_layers, + contrastThreshold=sift_peak_threshold, + edgeThreshold=sift_edge_threshold, + sigma=sift_sigma, ) + descriptor = detector else: - detector.setDouble("contrastThreshold", sift_peak_threshold) + detector = cv2.FeatureDetector_create("SIFT") + descriptor = cv2.DescriptorExtractor_create("SIFT") + detector.setDouble("edgeThreshold", sift_edge_threshold) + points = detector.detect(image) logger.debug("Found {0} points in {1}s".format(len(points), time.time() - t)) if len(points) < features_count and sift_peak_threshold > 0.0001: @@ -400,6 +391,7 @@ def extract_features_sift( else: logger.debug("done") break + points, desc = descriptor.compute(image, points) if desc is not None: From c9d7d98811568777d4ed35947ac040066c50782e Mon Sep 17 00:00:00 2001 From: Michael Waechter Date: Tue, 11 Jun 2024 02:18:27 -0700 Subject: [PATCH 076/235] add check to opensfm BA that GPS accuracies are positive Summary: For MLY internal we sometimes get -1 values for GPS accuracy. The new EXIF parser now prevents this from happening and sends None instead, but this diff adds an error message for this case so that we immediately notice if this ever happens again. Reviewed By: DodgySpaniard Differential Revision: D58373009 fbshipit-source-id: 526d92fbec49be7a9a8398648d722880ab138d54 --- opensfm/src/sfm/src/ba_helpers.cc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/opensfm/src/sfm/src/ba_helpers.cc b/opensfm/src/sfm/src/ba_helpers.cc index d0501aa84..82d550e9f 100644 --- a/opensfm/src/sfm/src/ba_helpers.cc +++ b/opensfm/src/sfm/src/ba_helpers.cc @@ -8,6 +8,7 @@ #include #include #include +#include #include "geo/geo.h" #include "map/defines.h" @@ -672,6 +673,11 @@ py::dict BAHelpers::Bundle( const auto pos = shot.GetShotMeasurements().gps_position_; const auto acc = shot.GetShotMeasurements().gps_accuracy_; if (pos.HasValue() && acc.HasValue()) { + if (acc.Value() <= 0) { + throw std::runtime_error("Shot " + shot.GetId() + " has an accuracy <= 0: " + + std::to_string(acc.Value()) + ". Try modifying " + "your input parser to filter such values."); + } average_position += pos.Value(); average_std += acc.Value(); ++gps_count; From 7b531aecf708472b1eed928cdea1d7d4fc70028a Mon Sep 17 00:00:00 2001 From: Richard Barnes Date: Wed, 26 Jun 2024 07:24:14 -0700 Subject: [PATCH 077/235] Fix shadowed variable in mapillary/opensfm/opensfm/src/geometry/src/camera.cc Summary: Our upcoming compiler upgrade will require us not to have shadowed variables. Such variables have a _high_ bug rate and reduce readability, so we would like to avoid them even if the compiler was not forcing us to do so. This codemod attempts to fix an instance of a shadowed variable. Please review with care: if it's failed the result will be a silent bug. **What's a shadowed variable?** Shadowed variables are variables in an inner scope with the same name as another variable in an outer scope. Having the same name for both variables might be semantically correct, but it can make the code confusing to read! It can also hide subtle bugs. This diff fixes such an issue by renaming the variable. - If you approve of this diff, please use the "Accept & Ship" button :-) Reviewed By: dmm-fb Differential Revision: D59008872 fbshipit-source-id: bd67d6396265aefb077ab37ae343e67c31a16408 --- opensfm/src/geometry/src/camera.cc | 8 ++--- opensfm/src/third_party/akaze/lib/AKAZE.cpp | 22 ++++++------- .../akaze/lib/nldiffusion_functions.cpp | 32 +++++++++---------- 3 files changed, 31 insertions(+), 31 deletions(-) diff --git a/opensfm/src/geometry/src/camera.cc b/opensfm/src/geometry/src/camera.cc index d864fa743..58b4a50e2 100644 --- a/opensfm/src/geometry/src/camera.cc +++ b/opensfm/src/geometry/src/camera.cc @@ -276,15 +276,15 @@ Mat3d Camera::GetProjectionMatrix() const { return unnormalized; } -Mat3d Camera::GetProjectionMatrixScaled(int width, int height) const { - const auto unnormalizer = std::max(width, height); +Mat3d Camera::GetProjectionMatrixScaled(int width_2, int height_2) const { + const auto unnormalizer = std::max(width_2, height_2); Mat3d unnormalized = Mat3d::Zero(); const auto projection_matrix = GetProjectionMatrix(); unnormalized.block<2, 2>(0, 0) << unnormalizer * projection_matrix.block<2, 2>(0, 0); - unnormalized.col(2) << projection_matrix(0, 2) * unnormalizer + 0.5 * width, - projection_matrix(1, 2) * unnormalizer + 0.5 * height, 1.0; + unnormalized.col(2) << projection_matrix(0, 2) * unnormalizer + 0.5 * width_2, + projection_matrix(1, 2) * unnormalizer + 0.5 * height_2, 1.0; return unnormalized; } diff --git a/opensfm/src/third_party/akaze/lib/AKAZE.cpp b/opensfm/src/third_party/akaze/lib/AKAZE.cpp index e49b6f1c2..d8356a066 100644 --- a/opensfm/src/third_party/akaze/lib/AKAZE.cpp +++ b/opensfm/src/third_party/akaze/lib/AKAZE.cpp @@ -374,17 +374,17 @@ void AKAZE::Find_Scale_Space_Extrema(std::vector& kpts) { for (size_t i = 0; i < kpts_aux.size(); i++) { is_repeated = false; - const cv::KeyPoint& point = kpts_aux[i]; + const cv::KeyPoint& point_2 = kpts_aux[i]; for (size_t j = i+1; j < kpts_aux.size(); j++) { // Compare response with the upper scale - if ((point.class_id+1) == kpts_aux[j].class_id) { + if ((point_2.class_id+1) == kpts_aux[j].class_id) { - dist = (point.pt.x-kpts_aux[j].pt.x)*(point.pt.x-kpts_aux[j].pt.x) + - (point.pt.y-kpts_aux[j].pt.y)*(point.pt.y-kpts_aux[j].pt.y); + dist = (point_2.pt.x-kpts_aux[j].pt.x)*(point_2.pt.x-kpts_aux[j].pt.x) + + (point_2.pt.y-kpts_aux[j].pt.y)*(point_2.pt.y-kpts_aux[j].pt.y); - if (dist <= point.size*point.size) { - if (point.response < kpts_aux[j].response) { + if (dist <= point_2.size*point_2.size) { + if (point_2.response < kpts_aux[j].response) { is_repeated = true; break; } @@ -393,7 +393,7 @@ void AKAZE::Find_Scale_Space_Extrema(std::vector& kpts) { } if (is_repeated == false) { - kpts.push_back(point); + kpts.push_back(point_2); } } @@ -959,8 +959,8 @@ void AKAZE::Get_MSURF_Upright_Descriptor_64(const cv::KeyPoint& kpt, float *desc // convert to unit vector len = sqrt(len); - for (int i = 0; i < dsize; i++) { - desc[i] /= len; + for (int i_2 = 0; i_2 < dsize; i_2++) { + desc[i_2] /= len; } } @@ -1075,8 +1075,8 @@ void AKAZE::Get_MSURF_Descriptor_64(const cv::KeyPoint& kpt, float *desc) const // convert to unit vector len = sqrt(len); - for (int i = 0; i < dsize; i++) { - desc[i] /= len; + for (int i_2 = 0; i_2 < dsize; i_2++) { + desc[i_2] /= len; } } diff --git a/opensfm/src/third_party/akaze/lib/nldiffusion_functions.cpp b/opensfm/src/third_party/akaze/lib/nldiffusion_functions.cpp index b1e3567ef..9f50abd5a 100644 --- a/opensfm/src/third_party/akaze/lib/nldiffusion_functions.cpp +++ b/opensfm/src/third_party/akaze/lib/nldiffusion_functions.cpp @@ -271,11 +271,11 @@ void nld_step_scalar(cv::Mat& Ld, const cv::Mat& c, cv::Mat& Lstep, const float Ld_row_p = Ld.ptr(Lstep.rows-2); Lstep_row = Lstep.ptr(Lstep.rows-1); - for (int x = 1; x < Lstep.cols-1; x++) { - float xpos = (c_row[x]+c_row[x+1])*(Ld_row[x+1]-Ld_row[x]); - float xneg = (c_row[x-1]+c_row[x])*(Ld_row[x]-Ld_row[x-1]); - float ypos = (c_row[x]+c_row_p[x])*(Ld_row_p[x]-Ld_row[x]); - Lstep_row[x] = 0.5*stepsize*(xpos-xneg + ypos); + for (int x_2 = 1; x_2 < Lstep.cols-1; x_2++) { + float xpos_2 = (c_row[x_2]+c_row[x_2+1])*(Ld_row[x_2+1]-Ld_row[x_2]); + float xneg_2 = (c_row[x_2-1]+c_row[x_2])*(Ld_row[x_2]-Ld_row[x_2-1]); + float ypos_2 = (c_row[x_2]+c_row_p[x_2])*(Ld_row_p[x_2]-Ld_row[x_2]); + Lstep_row[x_2] = 0.5*stepsize*(xpos_2-xneg_2 + ypos_2); } xpos = (c_row[0]+c_row[1])*(Ld_row[1]-Ld_row[0]); @@ -290,22 +290,22 @@ void nld_step_scalar(cv::Mat& Ld, const cv::Mat& c, cv::Mat& Lstep, const float // First and last columns for (int i = 1; i < Lstep.rows-1; i++) { - const float* c_row = c.ptr(i); + const float* c_row_2 = c.ptr(i); const float* c_row_m = c.ptr(i-1); - const float* c_row_p = c.ptr(i+1); - float* Ld_row = Ld.ptr(i); - float* Ld_row_p = Ld.ptr(i+1); + const float* c_row_p_2 = c.ptr(i+1); + float* Ld_row_2 = Ld.ptr(i); + float* Ld_row_p_2 = Ld.ptr(i+1); float* Ld_row_m = Ld.ptr(i-1); Lstep_row = Lstep.ptr(i); - float xpos = (c_row[0]+c_row[1])*(Ld_row[1]-Ld_row[0]); - float ypos = (c_row[0]+c_row_p[0])*(Ld_row_p[0]-Ld_row[0]); - float yneg = (c_row_m[0]+c_row[0])*(Ld_row[0]-Ld_row_m[0]); - Lstep_row[0] = 0.5*stepsize*(xpos+ypos-yneg); + float xpos_2 = (c_row_2[0]+c_row_2[1])*(Ld_row_2[1]-Ld_row_2[0]); + float ypos = (c_row_2[0]+c_row_p_2[0])*(Ld_row_p_2[0]-Ld_row_2[0]); + float yneg = (c_row_m[0]+c_row_2[0])*(Ld_row_2[0]-Ld_row_m[0]); + Lstep_row[0] = 0.5*stepsize*(xpos_2+ypos-yneg); - float xneg = (c_row[Lstep.cols-2]+c_row[Lstep.cols-1])*(Ld_row[Lstep.cols-1]-Ld_row[Lstep.cols-2]); - ypos = (c_row[Lstep.cols-1]+c_row_p[Lstep.cols-1])*(Ld_row_p[Lstep.cols-1]-Ld_row[Lstep.cols-1]); - yneg = (c_row_m[Lstep.cols-1]+c_row[Lstep.cols-1])*(Ld_row[Lstep.cols-1]-Ld_row_m[Lstep.cols-1]); + float xneg = (c_row_2[Lstep.cols-2]+c_row_2[Lstep.cols-1])*(Ld_row_2[Lstep.cols-1]-Ld_row_2[Lstep.cols-2]); + ypos = (c_row_2[Lstep.cols-1]+c_row_p_2[Lstep.cols-1])*(Ld_row_p_2[Lstep.cols-1]-Ld_row_2[Lstep.cols-1]); + yneg = (c_row_m[Lstep.cols-1]+c_row_2[Lstep.cols-1])*(Ld_row_2[Lstep.cols-1]-Ld_row_m[Lstep.cols-1]); Lstep_row[Lstep.cols-1] = 0.5*stepsize*(-xneg+ypos-yneg); } From da789737d4e97c2b47242742009824ba77eb853c Mon Sep 17 00:00:00 2001 From: Richard Barnes Date: Wed, 10 Jul 2024 08:41:35 -0700 Subject: [PATCH 078/235] Remove unused-variable in mapillary/opensfm/opensfm/src/geometry/absolute_pose.h Summary: LLVM-15 has a warning `-Wunused-variable` which we treat as an error because it's so often diagnostic of a code issue. Unused variables can compromise readability or, worse, performance. This diff either (a) removes an unused variable and, possibly, it's associated code or (b) qualifies the variable with `[[maybe_unused]]`. - If you approve of this diff, please use the "Accept & Ship" button :-) Reviewed By: fabianschenk Differential Revision: D59586421 fbshipit-source-id: 6a8eece4ed9e6015a73021a0ee3bba4d1a0c49b6 --- opensfm/src/geometry/absolute_pose.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/opensfm/src/geometry/absolute_pose.h b/opensfm/src/geometry/absolute_pose.h index faa7a2633..2de1894b2 100644 --- a/opensfm/src/geometry/absolute_pose.h +++ b/opensfm/src/geometry/absolute_pose.h @@ -28,7 +28,6 @@ std::vector> AbsolutePoseThreePoints(IT begin, // Compute k1, k2 and k3 const Eigen::Vector3d k1 = (p1 - p2).normalized(); const Eigen::Vector3d k3 = (b1.cross(b2)).normalized(); - const Eigen::Vector3d k2 = (k1.cross(k3)).normalized(); // Compute ui and vi for i = 1, 2 const Eigen::Vector3d u1 = p1 - p3; @@ -93,7 +92,6 @@ std::vector> AbsolutePoseThreePoints(IT begin, e1 << 1, 0, 0; e2 << 0, 1, 0; - constexpr double eps = 1e-20; for (const auto &root : roots) { const auto cos_theta_1 = root; const auto sin_theta_1 = From 1106198c79a0417fe59df68293c59ba7688533c0 Mon Sep 17 00:00:00 2001 From: Richard Barnes Date: Fri, 12 Jul 2024 07:38:50 -0700 Subject: [PATCH 079/235] Remove unused function from mapillary/opensfm/opensfm/src/third_party/akaze/lib/utils.cpp Summary: `-Wunused-function` has identified an unused function. This diff removes it. In many cases these functions have existed for years in an unused state. Reviewed By: dmm-fb Differential Revision: D59644696 fbshipit-source-id: 1e7f68d125820c9a969db26df91e0fe269fbddd5 --- opensfm/src/third_party/akaze/lib/utils.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/opensfm/src/third_party/akaze/lib/utils.cpp b/opensfm/src/third_party/akaze/lib/utils.cpp index ddd2a2f0f..d77168908 100644 --- a/opensfm/src/third_party/akaze/lib/utils.cpp +++ b/opensfm/src/third_party/akaze/lib/utils.cpp @@ -392,12 +392,6 @@ static inline std::ostream& cout_help() { return cout; } -/* ************************************************************************* */ -static inline std::string toUpper(std::string s) { - std::transform(s.begin(), s.end(), s.begin(), ::toupper); - return s; -} - /* ************************************************************************* */ void show_input_options_help(int example) { From 670d53e64ccebbdc4234d8c0be76c9bb6c71f476 Mon Sep 17 00:00:00 2001 From: Richard Barnes Date: Thu, 25 Jul 2024 13:46:04 -0700 Subject: [PATCH 080/235] Del using namespace mapillary/opensfm/opensfm/src/dense/depthmap_bind.h Summary: Removes a `using namespace` from the global namespace in pursuit of enabling `-Wheader-hygiene`. Qualifies instances that relied on the `using namespace`. Reviewed By: dmm-fb Differential Revision: D60114516 fbshipit-source-id: d8741cc8a56bf07fb9e596bd219e4ef42468451e --- opensfm/src/dense/depthmap_bind.h | 29 ++++++++++++++-------------- opensfm/src/dense/openmvs_exporter.h | 6 +++--- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/opensfm/src/dense/depthmap_bind.h b/opensfm/src/dense/depthmap_bind.h index 007178394..d24ff80a3 100644 --- a/opensfm/src/dense/depthmap_bind.h +++ b/opensfm/src/dense/depthmap_bind.h @@ -3,14 +3,13 @@ #include #include -using namespace foundation; namespace dense { class DepthmapEstimatorWrapper { public: - void AddView(pyarray_d K, pyarray_d R, pyarray_d t, pyarray_uint8 image, - pyarray_uint8 mask) { + void AddView(foundation::pyarray_d K, foundation::pyarray_d R, foundation::pyarray_d t, foundation::pyarray_uint8 image, + foundation::pyarray_uint8 mask) { if ((image.shape(0) != mask.shape(0)) || (image.shape(1) != mask.shape(1))){ throw std::invalid_argument("image and mask must have matching shapes."); } @@ -57,13 +56,13 @@ class DepthmapEstimatorWrapper { py::object ComputeReturnValues(const DepthmapEstimatorResult &result) { py::list retn; - retn.append(py_array_from_data(result.depth.ptr(0), + retn.append(foundation::py_array_from_data(result.depth.ptr(0), result.depth.rows, result.depth.cols)); - retn.append(py_array_from_data(result.plane.ptr(0), + retn.append(foundation::py_array_from_data(result.plane.ptr(0), result.plane.rows, result.plane.cols, 3)); - retn.append(py_array_from_data(result.score.ptr(0), + retn.append(foundation::py_array_from_data(result.score.ptr(0), result.score.rows, result.score.cols)); - retn.append(py_array_from_data(result.nghbr.ptr(0), result.nghbr.rows, + retn.append(foundation::py_array_from_data(result.nghbr.ptr(0), result.nghbr.rows, result.nghbr.cols)); return std::move(retn); } @@ -78,7 +77,7 @@ class DepthmapCleanerWrapper { void SetMinConsistentViews(int n) { dc_.SetMinConsistentViews(n); } - void AddView(pyarray_d K, pyarray_d R, pyarray_d t, pyarray_f depth) { + void AddView(foundation::pyarray_d K, foundation::pyarray_d R, foundation::pyarray_d t, foundation::pyarray_f depth) { dc_.AddView(K.data(), R.data(), t.data(), depth.data(), depth.shape(1), depth.shape(0)); } @@ -89,7 +88,7 @@ class DepthmapCleanerWrapper { py::gil_scoped_release release; dc_.Clean(&depth); } - return py_array_from_data(depth.ptr(0), depth.rows, depth.cols); + return foundation::py_array_from_data(depth.ptr(0), depth.rows, depth.cols); } private: @@ -100,8 +99,8 @@ class DepthmapPrunerWrapper { public: void SetSameDepthThreshold(float t) { dp_.SetSameDepthThreshold(t); } - void AddView(pyarray_d K, pyarray_d R, pyarray_d t, pyarray_f depth, - pyarray_f plane, pyarray_uint8 color, pyarray_uint8 label) { + void AddView(foundation::pyarray_d K, foundation::pyarray_d R, foundation::pyarray_d t, foundation::pyarray_f depth, + foundation::pyarray_f plane, foundation::pyarray_uint8 color, foundation::pyarray_uint8 label) { if ((depth.shape(0) != plane.shape(0)) || (depth.shape(1) != plane.shape(1))){ throw std::invalid_argument("depth and plane must have matching shapes."); } @@ -128,10 +127,10 @@ class DepthmapPrunerWrapper { py::list retn; int n = int(points.size()) / 3; - retn.append(py_array_from_data(points.data(), n, 3)); - retn.append(py_array_from_data(normals.data(), n, 3)); - retn.append(py_array_from_data(colors.data(), n, 3)); - retn.append(py_array_from_data(labels.data(), n)); + retn.append(foundation::py_array_from_data(points.data(), n, 3)); + retn.append(foundation::py_array_from_data(normals.data(), n, 3)); + retn.append(foundation::py_array_from_data(colors.data(), n, 3)); + retn.append(foundation::py_array_from_data(labels.data(), n)); return std::move(retn); } diff --git a/opensfm/src/dense/openmvs_exporter.h b/opensfm/src/dense/openmvs_exporter.h index 088223f7b..ba055f76e 100644 --- a/opensfm/src/dense/openmvs_exporter.h +++ b/opensfm/src/dense/openmvs_exporter.h @@ -6,7 +6,7 @@ namespace dense { class OpenMVSExporter { public: - void AddCamera(const std::string &camera_id, pyarray_d K, uint32_t width, uint32_t height) { + void AddCamera(const std::string &camera_id, foundation::pyarray_d K, uint32_t width, uint32_t height) { MVS::Interface::Platform platform; platform.name = camera_id; MVS::Interface::Platform::Camera camera; @@ -22,7 +22,7 @@ class OpenMVSExporter { } void AddShot(const std::string &path, const std::string &maskPath, const std::string &shot_id, - const std::string &camera_id, pyarray_d R, pyarray_d C) { + const std::string &camera_id, foundation::pyarray_d R, foundation::pyarray_d C) { const double *C_data = C.data(); int platform_id = platform_ids_[camera_id]; @@ -45,7 +45,7 @@ class OpenMVSExporter { scene_.images.push_back(image); } - void AddPoint(pyarray_d coordinates, py::list shot_ids) { + void AddPoint(foundation::pyarray_d coordinates, py::list shot_ids) { const double *x = coordinates.data(); MVS::Interface::Vertex vertex; From f953531fdea6b7ab2631e9910a5466be447107a9 Mon Sep 17 00:00:00 2001 From: Fabian Schenk Date: Tue, 6 Aug 2024 00:10:02 -0700 Subject: [PATCH 081/235] Migrate "mapillary/opensfm/PACKAGE" from LLVM-15 to LLVM-17 Differential Revision: D60359203 fbshipit-source-id: 5064b2fdb68276edd6408fd4f0fe87424be4bb4f --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index a739a68fd..8843455c0 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,5 @@ data/berlin/* # Ignore virtualenv files env/* + +PACKAGE From ef872b2399cf1cc036d91e950f210a7be33c2745 Mon Sep 17 00:00:00 2001 From: generatedunixname89002005307016 Date: Thu, 8 Aug 2024 23:08:12 -0700 Subject: [PATCH 082/235] upgrade pyre version in `fbcode/mapillary` - batch 1 Differential Revision: D60994471 fbshipit-source-id: 9fdcfea8f07fc6b2c711a03ec1c919d37623d852 --- opensfm/features.py | 1 + opensfm/io.py | 1 + opensfm/multiview.py | 1 + opensfm/synthetic_data/synthetic_generator.py | 2 ++ opensfm/test/test_bundle.py | 13 +++++++++++++ opensfm/test/test_multiview.py | 3 +++ opensfm/test/test_robust.py | 1 + 7 files changed, 22 insertions(+) diff --git a/opensfm/features.py b/opensfm/features.py index 26eb0c05a..15af8700f 100644 --- a/opensfm/features.py +++ b/opensfm/features.py @@ -516,6 +516,7 @@ def extract_features_hahog( uchar_scaling = 512 if config["hahog_normalize_to_uchar"]: + # pyre-fixme[16]: `int` has no attribute `clip`. desc = (uchar_scaling * desc).clip(0, 255).round() logger.debug("Found {0} points in {1}s".format(len(points), time.time() - t)) diff --git a/opensfm/io.py b/opensfm/io.py index bf72ae9f3..79119e892 100644 --- a/opensfm/io.py +++ b/opensfm/io.py @@ -1098,6 +1098,7 @@ def reconstruction_to_ply( for depth in np.linspace(0, 2, 10): p = o + depth * R[axis] s = "{} {} {} {} {} {}".format( + # pyre-fixme[16]: `int` has no attribute `__getitem__`. p[0], p[1], p[2], int(c[0]), int(c[1]), int(c[2]) ) if point_num_views: diff --git a/opensfm/multiview.py b/opensfm/multiview.py index e6f37e9c0..e164fd1f0 100644 --- a/opensfm/multiview.py +++ b/opensfm/multiview.py @@ -464,6 +464,7 @@ def R_from_homography( def project_to_rotation_matrix(A: np.ndarray) -> Optional[np.ndarray]: try: u, d, vt = np.linalg.svd(A) + # pyre-fixme[16]: Module `linalg` has no attribute `LinAlgError`. except np.linalg.linalg.LinAlgError: return None return u.dot(vt) diff --git a/opensfm/synthetic_data/synthetic_generator.py b/opensfm/synthetic_data/synthetic_generator.py index 90b3fc8da..0dd20c840 100644 --- a/opensfm/synthetic_data/synthetic_generator.py +++ b/opensfm/synthetic_data/synthetic_generator.py @@ -219,6 +219,8 @@ def _gps_dop(shot: pymap.Shot) -> float: origin = shot.pose.get_origin() if causal_gps_noise: + # pyre-fixme[61]: `perturbations_2d` is undefined, or not always + # defined. gps_perturbation = [perturbations_2d[j][i] for j in range(2)] + [0] else: gps_noise = _gps_dop(shot) diff --git a/opensfm/test/test_bundle.py b/opensfm/test/test_bundle.py index 54202da06..d3d499560 100644 --- a/opensfm/test/test_bundle.py +++ b/opensfm/test/test_bundle.py @@ -108,14 +108,27 @@ def test_bundle_projection_fixed_internals(scene_synthetic) -> None: color = g_obs["feature_color"] pt = g_obs["feature"] obs = pymap.Observation( + # pyre-fixme[6]: For 1st argument expected `str` but got `int`. pt[0], + # pyre-fixme[6]: For 1st argument expected `str` but got `int`. pt[1], + # pyre-fixme[6]: For 3rd argument expected `float` but got + # `Dict[str, typing.Any]`. g_obs["feature_scale"], + # pyre-fixme[6]: For 1st argument expected `str` but got `int`. color[0], + # pyre-fixme[6]: For 1st argument expected `str` but got `int`. color[1], + # pyre-fixme[6]: For 1st argument expected `str` but got `int`. color[2], + # pyre-fixme[6]: For 7th argument expected `int` but got + # `Dict[str, typing.Any]`. g_obs["feature_id"], + # pyre-fixme[6]: For 8th argument expected `int` but got + # `Dict[str, typing.Any]`. g_obs["feature_segmentation"], + # pyre-fixme[6]: For 9th argument expected `int` but got + # `Dict[str, typing.Any]`. g_obs["feature_instance"], ) reference.map.add_observation(shot_id, point_id, obs) diff --git a/opensfm/test/test_multiview.py b/opensfm/test/test_multiview.py index a0e6f1376..8edc8cc8b 100644 --- a/opensfm/test/test_multiview.py +++ b/opensfm/test/test_multiview.py @@ -13,12 +13,15 @@ def normalized(x: np.ndarray) -> np.ndarray: def test_motion_from_plane_homography() -> None: R = tf.random_rotation_matrix()[:3, :3] + # pyre-fixme[6]: For 1st argument expected `ndarray` but got `int`. t = normalized(2 * np.random.rand(3) - 1) + # pyre-fixme[6]: For 1st argument expected `ndarray` but got `int`. n = normalized(2 * np.random.rand(3) - 1) d = 2 * np.random.rand() - 1 scale = 2 * np.random.rand() - 1 H = scale * (d * R - np.outer(t, n)) + # pyre-fixme[6]: For 1st argument expected `ndarray` but got `int`. motions = multiview.motion_from_plane_homography(H) assert motions is not None goodness = [] diff --git a/opensfm/test/test_robust.py b/opensfm/test/test_robust.py index 6c02d71a9..1f4330b6f 100644 --- a/opensfm/test/test_robust.py +++ b/opensfm/test/test_robust.py @@ -261,6 +261,7 @@ def test_outliers_relative_pose_ransac(pairs_and_their_E) -> None: inliers_count = (1 - ratio_outliers) * len(points) assert np.isclose(len(result.inliers_indices), inliers_count, rtol=tolerance) + # pyre-fixme[61]: `expected` is undefined, or not always defined. assert np.linalg.norm(expected - result.lo_model, ord="fro") < 16e-2 From d1727b0673a70120ad1db8e81fac46fbd55adec5 Mon Sep 17 00:00:00 2001 From: generatedunixname89002005287564 Date: Thu, 15 Aug 2024 02:34:52 -0700 Subject: [PATCH 083/235] removing base_module] fbcode/mapillary/opensfm/opensfm/test/TARGETS Reviewed By: fabianschenk Differential Revision: D61262745 fbshipit-source-id: ecf3ab7b8e3e37e9a5bc9da01a33b2bda62882d5 --- opensfm/test/test_commands.py | 2 +- opensfm/test/test_dataset.py | 2 +- opensfm/test/test_datastructures.py | 6 +----- opensfm/test/test_io.py | 2 +- opensfm/test/test_pairs_selection.py | 2 +- 5 files changed, 5 insertions(+), 9 deletions(-) diff --git a/opensfm/test/test_commands.py b/opensfm/test/test_commands.py index a5890bcd9..ac04e8602 100644 --- a/opensfm/test/test_commands.py +++ b/opensfm/test/test_commands.py @@ -3,7 +3,7 @@ from os.path import join from opensfm import commands, dataset -from opensfm.test import data_generation, utils +from mapillary.opensfm.opensfm.test import data_generation, utils def run_command(command, args) -> None: diff --git a/opensfm/test/test_dataset.py b/opensfm/test/test_dataset.py index 60022ae0a..142887c82 100644 --- a/opensfm/test/test_dataset.py +++ b/opensfm/test/test_dataset.py @@ -1,7 +1,7 @@ # pyre-unsafe import numpy as np from opensfm import features -from opensfm.test import data_generation +from mapillary.opensfm.opensfm.test import data_generation def test_dataset_load_features_sift(tmpdir) -> None: diff --git a/opensfm/test/test_datastructures.py b/opensfm/test/test_datastructures.py index 5e9c5cd9a..cbf5116be 100644 --- a/opensfm/test/test_datastructures.py +++ b/opensfm/test/test_datastructures.py @@ -11,11 +11,7 @@ from opensfm import pygeometry from opensfm import pymap from opensfm import types -from opensfm.test.utils import ( - assert_maps_equal, assert_metadata_equal, - assert_cameras_equal, - assert_shots_equal, -) +from mapillary.opensfm.opensfm.test.utils import assert_maps_equal, assert_metadata_equal, assert_cameras_equal, assert_shots_equal def _create_reconstruction( diff --git a/opensfm/test/test_io.py b/opensfm/test/test_io.py index 0b43af2c5..39e46890d 100644 --- a/opensfm/test/test_io.py +++ b/opensfm/test/test_io.py @@ -5,7 +5,7 @@ import numpy as np from opensfm import io, pygeometry, types -from opensfm.test import data_generation, utils +from mapillary.opensfm.opensfm.test import data_generation, utils filename = os.path.join( diff --git a/opensfm/test/test_pairs_selection.py b/opensfm/test/test_pairs_selection.py index b16a2ce69..303f334ff 100644 --- a/opensfm/test/test_pairs_selection.py +++ b/opensfm/test/test_pairs_selection.py @@ -6,7 +6,7 @@ import numpy as np import pytest from opensfm import commands, dataset, feature_loader, pairs_selection, geo -from opensfm.test import data_generation +from mapillary.opensfm.opensfm.test import data_generation from opensfm.dataset_base import DataSetBase From 7514c2107fa8fe3ae757968a3ec14926ddba721f Mon Sep 17 00:00:00 2001 From: generatedunixname89002005307016 Date: Mon, 30 Sep 2024 15:54:51 -0700 Subject: [PATCH 084/235] Convert .pyre_configuration.local to fast by default architecture] [batch:44/100] [shard:2/N] [A] Reviewed By: MaggieMoss Differential Revision: D63644535 fbshipit-source-id: f4118078d10c24b1fd5c400659c5f3c70ae2c781 --- opensfm/actions/export_colmap.py | 2 ++ opensfm/actions/export_geocoords.py | 2 ++ opensfm/align.py | 4 ++++ opensfm/dataset.py | 2 ++ opensfm/feature_loading.py | 1 + opensfm/features_processing.py | 2 ++ opensfm/multiview.py | 11 ++++++++++- opensfm/pairs_selection.py | 2 ++ opensfm/reconstruction.py | 7 +++++++ opensfm/synthetic_data/synthetic_generator.py | 2 ++ opensfm/synthetic_data/synthetic_scene.py | 6 ++++++ opensfm/test/test_bundle.py | 5 ----- opensfm/test/test_dataset.py | 2 ++ opensfm/test/test_multiview.py | 1 - opensfm/test/test_triangulation.py | 1 + opensfm/tracking.py | 4 ++++ opensfm/transformations.py | 10 ++++++++++ 17 files changed, 57 insertions(+), 7 deletions(-) diff --git a/opensfm/actions/export_colmap.py b/opensfm/actions/export_colmap.py index c86e38fa9..a8b7a5ccb 100644 --- a/opensfm/actions/export_colmap.py +++ b/opensfm/actions/export_colmap.py @@ -185,11 +185,13 @@ def array_to_blob(array) -> bytes: if IS_PYTHON3: return array.tobytes() else: + # pyre-fixme[16]: Module `numpy` has no attribute `getbuffer`. return np.getbuffer(array) def blob_to_array(blob, dtype, shape: Tuple[int] = (-1,)): if IS_PYTHON3: + # pyre-fixme[20]: Argument `sep` expected. return np.fromstring(blob, dtype=dtype).reshape(*shape) else: return np.frombuffer(blob, dtype=dtype).reshape(*shape) diff --git a/opensfm/actions/export_geocoords.py b/opensfm/actions/export_geocoords.py index aad9d7910..42ab9df76 100644 --- a/opensfm/actions/export_geocoords.py +++ b/opensfm/actions/export_geocoords.py @@ -146,7 +146,9 @@ def _transform_dense_point_cloud( fout.write(line) else: x, y, z, nx, ny, nz, red, green, blue = line.split() + # pyre-fixme[6]: For 2nd argument expected `Union[Sequence[Sequen... x, y, z = np.dot(A, map(float, [x, y, z])) + b + # pyre-fixme[6]: For 2nd argument expected `Union[Sequence[Sequen... nx, ny, nz = np.dot(A, map(float, [nx, ny, nz])) fout.write( "{} {} {} {} {} {} {} {} {}\n".format( diff --git a/opensfm/align.py b/opensfm/align.py index 48d7d60c3..f07aa004f 100644 --- a/opensfm/align.py +++ b/opensfm/align.py @@ -282,7 +282,11 @@ def compute_orientation_prior_similarity( max_scale = 1000 current_scale = np.linalg.norm(b) if two_shots and current_scale > max_scale: + # pyre-fixme[58]: `/` is not supported for operand types `int` and + # `floating[typing.Any]`. b = max_scale * b / current_scale + # pyre-fixme[58]: `/` is not supported for operand types `int` and + # `floating[typing.Any]`. s = max_scale / current_scale else: try: diff --git a/opensfm/dataset.py b/opensfm/dataset.py index 12af6a344..fa96fc6fb 100644 --- a/opensfm/dataset.py +++ b/opensfm/dataset.py @@ -334,6 +334,8 @@ def load_words(self, image: str) -> np.ndarray: def save_words(self, image: str, words: np.ndarray) -> None: with self.io_handler.open(self._words_file(image), "wb") as f: + # pyre-fixme[6]: For 1st argument expected `Union[_SupportsWrite[bytes], + # PathLike[str], str]` but got `IO[typing.Any]`. np.savez_compressed(f, words=words.astype(np.uint16)) def _matches_path(self) -> str: diff --git a/opensfm/feature_loading.py b/opensfm/feature_loading.py index 7ff3d4934..1f3c63a69 100644 --- a/opensfm/feature_loading.py +++ b/opensfm/feature_loading.py @@ -133,6 +133,7 @@ def _add_segmentation_in_descriptor( return features desc_augmented = np.concatenate( + # pyre-fixme[6]: For 1st argument expected `Union[_SupportsArray[dtype[ty... ( features.descriptors, (np.array([segmentation]).T).astype(np.float32), diff --git a/opensfm/features_processing.py b/opensfm/features_processing.py index 94889eac9..671facfde 100644 --- a/opensfm/features_processing.py +++ b/opensfm/features_processing.py @@ -219,6 +219,8 @@ def bake_segmentation( new_width=new_width, new_height=new_height, ).astype(int) + # pyre-fixme[6]: For 2nd argument expected `None` but got + # `ndarray[typing.Any, typing.Any]`. panoptic_data[i] = p_data[ps[:, 1], ps[:, 0]] return tuple(panoptic_data) diff --git a/opensfm/multiview.py b/opensfm/multiview.py index e164fd1f0..97b7e2b18 100644 --- a/opensfm/multiview.py +++ b/opensfm/multiview.py @@ -182,6 +182,9 @@ def ransac(kernel: Any, threshold: float) -> TRansacSolution: max_iterations, ransac_max_iterations(kernel, best_inliers, 0.01) ) i += 1 + # pyre-fixme[7]: Expected `Tuple[ndarray[typing.Any, typing.Any], + # ndarray[typing.Any, typing.Any], float]` but got `Tuple[typing.Any, + # Union[List[typing.Any], ndarray[typing.Any, dtype[typing.Any]]], typing.Any]`. return best_model, best_inliers, best_error @@ -211,6 +214,8 @@ def num_samples(self) -> int: def fit(self, samples: np.ndarray) -> List[float]: x = self.x[samples[0]] y = self.y[samples[0]] + # pyre-fixme[7]: Expected `List[float]` but got `List[ndarray[typing.Any, + # dtype[typing.Any]]]`. return [y / x] def evaluate(self, model: np.ndarray) -> np.ndarray: @@ -416,6 +421,9 @@ def fit_similarity_transform( errors = np.sqrt(np.sum((p2h.T - np.dot(best_T, p1h.T)) ** 2, axis=0)) best_inliers = np.argwhere(errors < threshold)[:, 0] + # pyre-fixme[7]: Expected `Tuple[ndarray[typing.Any, typing.Any], + # ndarray[typing.Any, typing.Any]]` but got `Tuple[ndarray[typing.Any, + # typing.Any], Union[List[typing.Any], ndarray[typing.Any, dtype[typing.Any]]]]`. return best_T, best_inliers @@ -453,7 +461,9 @@ def focal_from_homography(H: np.ndarray) -> np.ndarray: def R_from_homography( H: np.ndarray, f1: np.ndarray, f2: np.ndarray ) -> Optional[np.ndarray]: + # pyre-fixme[6]: For 1st argument expected `Union[_SupportsArray[dtype[typing.Any... K1 = np.diag([f1, f1, 1]) + # pyre-fixme[6]: For 1st argument expected `Union[_SupportsArray[dtype[typing.Any... K2 = np.diag([f2, f2, 1]) K2inv = np.linalg.inv(K2) R = K2inv.dot(H).dot(K1) @@ -464,7 +474,6 @@ def R_from_homography( def project_to_rotation_matrix(A: np.ndarray) -> Optional[np.ndarray]: try: u, d, vt = np.linalg.svd(A) - # pyre-fixme[16]: Module `linalg` has no attribute `LinAlgError`. except np.linalg.linalg.LinAlgError: return None return u.dot(vt) diff --git a/opensfm/pairs_selection.py b/opensfm/pairs_selection.py index 214e251b3..2bae00157 100644 --- a/opensfm/pairs_selection.py +++ b/opensfm/pairs_selection.py @@ -472,6 +472,8 @@ def construct_pairs( order = np.argsort(distances) if enforce_other_cameras: pairs.update( + # pyre-fixme[6]: For 4th argument expected `List[int]` but got + # `ndarray[typing.Any, dtype[typing.Any]]`. pairs_from_neighbors(im, exifs, distances, order, other, max_neighbors) ) else: diff --git a/opensfm/reconstruction.py b/opensfm/reconstruction.py index ad242f9ee..1c07b9f62 100644 --- a/opensfm/reconstruction.py +++ b/opensfm/reconstruction.py @@ -284,6 +284,8 @@ def _two_view_reconstruction_inliers( ) -> List[int]: """Returns indices of matches that can be triangulated.""" ok = matching.compute_inliers_bearings(b1, b2, R, t, threshold) + # pyre-fixme[7]: Expected `List[int]` but got `ndarray[typing.Any, + # dtype[typing.Any]]`. return np.nonzero(ok)[0] @@ -318,6 +320,7 @@ def two_view_reconstruction_plane_based( inliers = _two_view_reconstruction_inliers(b1, b2, R.T, -R.T.dot(t), threshold) motion_inliers.append(inliers) + # pyre-fixme[6]: For 1st argument expected `Union[_SupportsArray[dtype[typing.Any... best = np.argmax(map(len, motion_inliers)) R, t, n, d = motions[best] inliers = motion_inliers[best] @@ -370,6 +373,8 @@ def _two_view_rotation_inliers( ) -> List[int]: br2 = R.dot(b2.T).T ok = np.linalg.norm(br2 - b1, axis=1) < threshold + # pyre-fixme[7]: Expected `List[int]` but got `ndarray[typing.Any, + # dtype[typing.Any]]`. return np.nonzero(ok)[0] @@ -1048,6 +1053,8 @@ def triangulate_dlt( if len(Rts) >= 2: e, X = pygeometry.triangulate_bearings_dlt( + # pyre-fixme[6]: For 1st argument expected `List[ndarray[typing.Any, + # typing.Any]]` but got `ndarray[typing.Any, dtype[typing.Any]]`. np.asarray(Rts), np.asarray(bs), reproj_threshold, diff --git a/opensfm/synthetic_data/synthetic_generator.py b/opensfm/synthetic_data/synthetic_generator.py index 0dd20c840..f856af382 100644 --- a/opensfm/synthetic_data/synthetic_generator.py +++ b/opensfm/synthetic_data/synthetic_generator.py @@ -201,6 +201,8 @@ def _gps_dop(shot: pymap.Shot) -> float: ): pose = rig_instance.pose.get_origin() if previous_pose is not None: + # pyre-fixme[58]: `+` is not supported for operand types `int` and + # `floating[typing.Any]`. previous_time += np.linalg.norm(pose - previous_pose) / speed_ms previous_pose = pose for shot_id in rig_instance.shots: diff --git a/opensfm/synthetic_data/synthetic_scene.py b/opensfm/synthetic_data/synthetic_scene.py index f8fcc8140..6dcae3206 100644 --- a/opensfm/synthetic_data/synthetic_scene.py +++ b/opensfm/synthetic_data/synthetic_scene.py @@ -177,9 +177,11 @@ def __init__( def combine(self, other_scene: "SyntheticStreetScene") -> "SyntheticStreetScene": combined_scene = SyntheticStreetScene(None) combined_scene.wall_points = np.concatenate( + # pyre-fixme[6]: For 1st argument expected `Union[_SupportsArray[dtype[ty... (self.wall_points, other_scene.wall_points) ) combined_scene.floor_points = np.concatenate( + # pyre-fixme[6]: For 1st argument expected `Union[_SupportsArray[dtype[ty... (self.floor_points, other_scene.floor_points) ) combined_scene.cameras = self.cameras + other_scene.cameras @@ -400,7 +402,11 @@ def get_reconstruction(self) -> types.Reconstruction: wall_color = [10, 90, 130] return sg.create_reconstruction( + # pyre-fixme[6]: For 1st argument expected `List[ndarray[typing.Any, + # typing.Any]]` but got `ndarray[typing.Any, dtype[typing.Any]]`. points=np.asarray([self.floor_points, self.wall_points], dtype=object), + # pyre-fixme[6]: For 2nd argument expected `List[ndarray[typing.Any, + # typing.Any]]` but got `ndarray[typing.Any, dtype[typing.Any]]`. colors=np.asarray([floor_color, wall_color]), cameras=self.cameras, shot_ids=self.shot_ids, diff --git a/opensfm/test/test_bundle.py b/opensfm/test/test_bundle.py index d3d499560..27aff4d8e 100644 --- a/opensfm/test/test_bundle.py +++ b/opensfm/test/test_bundle.py @@ -108,18 +108,13 @@ def test_bundle_projection_fixed_internals(scene_synthetic) -> None: color = g_obs["feature_color"] pt = g_obs["feature"] obs = pymap.Observation( - # pyre-fixme[6]: For 1st argument expected `str` but got `int`. pt[0], - # pyre-fixme[6]: For 1st argument expected `str` but got `int`. pt[1], # pyre-fixme[6]: For 3rd argument expected `float` but got # `Dict[str, typing.Any]`. g_obs["feature_scale"], - # pyre-fixme[6]: For 1st argument expected `str` but got `int`. color[0], - # pyre-fixme[6]: For 1st argument expected `str` but got `int`. color[1], - # pyre-fixme[6]: For 1st argument expected `str` but got `int`. color[2], # pyre-fixme[6]: For 7th argument expected `int` but got # `Dict[str, typing.Any]`. diff --git a/opensfm/test/test_dataset.py b/opensfm/test/test_dataset.py index 142887c82..17db15e38 100644 --- a/opensfm/test/test_dataset.py +++ b/opensfm/test/test_dataset.py @@ -26,6 +26,7 @@ def test_dataset_load_features_sift(tmpdir) -> None: after = data.load_features(image) assert after assert np.allclose(points, after.points) + # pyre-fixme[6]: For 2nd argument expected `Union[_SupportsArray[dtype[typing.Any... assert np.allclose(descriptors, after.descriptors) assert np.allclose(colors, after.colors) semantic = after.semantic @@ -34,4 +35,5 @@ def test_dataset_load_features_sift(tmpdir) -> None: segmentations, semantic.segmentation, ) + # pyre-fixme[6]: For 2nd argument expected `Union[_SupportsArray[dtype[typing.Any... assert np.allclose(instances, semantic.instances) diff --git a/opensfm/test/test_multiview.py b/opensfm/test/test_multiview.py index 8edc8cc8b..6911ad26c 100644 --- a/opensfm/test/test_multiview.py +++ b/opensfm/test/test_multiview.py @@ -21,7 +21,6 @@ def test_motion_from_plane_homography() -> None: scale = 2 * np.random.rand() - 1 H = scale * (d * R - np.outer(t, n)) - # pyre-fixme[6]: For 1st argument expected `ndarray` but got `int`. motions = multiview.motion_from_plane_homography(H) assert motions is not None goodness = [] diff --git a/opensfm/test/test_triangulation.py b/opensfm/test/test_triangulation.py index 734be5d6c..ee9f8ceaf 100644 --- a/opensfm/test/test_triangulation.py +++ b/opensfm/test/test_triangulation.py @@ -50,6 +50,7 @@ def test_track_triangulator_spherical() -> None: def unit_vector(x: object) -> np.ndarray: + # pyre-fixme[6]: For 1st argument expected `Union[_SupportsArray[dtype[typing.Any... return np.array(x) / np.linalg.norm(x) diff --git a/opensfm/tracking.py b/opensfm/tracking.py index c1b79798c..eb897855d 100644 --- a/opensfm/tracking.py +++ b/opensfm/tracking.py @@ -98,6 +98,10 @@ def create_tracks_manager( instances[image][featureid] if image in instances else NO_VALUE, ) obs = pymap.Observation( + # pyre-fixme[6]: For 8th argument expected `int` but got + # `Union[ndarray[typing.Any, typing.Any], int]`. + # pyre-fixme[6]: For 9th argument expected `int` but got + # `Union[ndarray[typing.Any, typing.Any], int]`. x, y, s, int(r), int(g), int(b), featureid, segmentation, instance ) tracks_manager.add_observation(image, str(track_id), obs) diff --git a/opensfm/transformations.py b/opensfm/transformations.py index 071915b64..dfd2d142d 100644 --- a/opensfm/transformations.py +++ b/opensfm/transformations.py @@ -411,6 +411,7 @@ def scale_matrix( """ if direction is None: # uniform scaling + # pyre-fixme[6]: For 1st argument expected `Union[_SupportsArray[dtype[typing... M = numpy.diag([factor, factor, factor, 1.0]) if origin is not None: M[:3, 3] = origin[:3] @@ -466,6 +467,10 @@ def scale_from_matrix( raise ValueError("no eigenvector corresponding to eigenvalue 1") origin = numpy.real(V[:, i[-1]]).squeeze() origin /= origin[3] + # pyre-fixme[7]: Expected `Tuple[ndarray[typing.Any, typing.Any], + # ndarray[typing.Any, typing.Any], ndarray[typing.Any, typing.Any]]` but got + # `Tuple[typing.Any, ndarray[typing.Any, dtype[typing.Any]], + # Optional[ndarray[typing.Any, dtype[typing.Any]]]]`. return factor, origin, direction @@ -1663,10 +1668,14 @@ def vector_norm( data *= data out = numpy.atleast_1d(numpy.sum(data, axis=axis)) numpy.sqrt(out, out) + # pyre-fixme[7]: Expected `float` but got `ndarray[typing.Any, + # dtype[typing.Any]]`. return out else: data *= data numpy.sum(data, axis=axis, out=out) + # pyre-fixme[7]: Expected `float` but got `ndarray[typing.Any, + # dtype[typing.Any]]`. return numpy.sqrt(out, out) @@ -1832,6 +1841,7 @@ def is_same_transform(matrix0: numpy.ndarray, matrix1: numpy.ndarray) -> numpy.n matrix0 /= matrix0[3, 3] matrix1 = numpy.array(matrix1, dtype=numpy.float64, copy=True) matrix1 /= matrix1[3, 3] + # pyre-fixme[7]: Expected `ndarray[typing.Any, typing.Any]` but got `bool`. return numpy.allclose(matrix0, matrix1) From 03432a8e010081f360dd260981d6a55119c44089 Mon Sep 17 00:00:00 2001 From: Richard Barnes Date: Mon, 14 Oct 2024 12:57:42 -0700 Subject: [PATCH 085/235] Remove unused-variable in mapillary/opensfm/opensfm/src/bundle/error/absolute_motion_errors.h Summary: LLVM-15 has a warning `-Wunused-variable` which we treat as an error because it's so often diagnostic of a code issue. Unused variables can compromise readability or, worse, performance. This diff either (a) removes an unused variable and, possibly, it's associated code or (b) qualifies the variable with `[[maybe_unused]]`. - If you approve of this diff, please use the "Accept & Ship" button :-) Reviewed By: meyering Differential Revision: D64279137 fbshipit-source-id: 68f17d9881c727d38065cd80d8314d28ac325f52 --- opensfm/src/bundle/error/absolute_motion_errors.h | 1 - 1 file changed, 1 deletion(-) diff --git a/opensfm/src/bundle/error/absolute_motion_errors.h b/opensfm/src/bundle/error/absolute_motion_errors.h index 407267a91..d6a072bcc 100644 --- a/opensfm/src/bundle/error/absolute_motion_errors.h +++ b/opensfm/src/bundle/error/absolute_motion_errors.h @@ -93,7 +93,6 @@ struct RollAngleError { T ex[3] = {T(1), T(0), T(0)}; // A point to the right of the camera (x=1) T ez[3] = {T(0), T(0), T(1)}; // A point in front of the camera (z=1) T Rt_ex[3], Rt_ez[3]; - T tangle_ = T(angle_); ceres::AngleAxisRotatePoint(R.data(), ex, Rt_ex); ceres::AngleAxisRotatePoint(R.data(), ez, Rt_ez); From 61c0f12c580a305ce8a016827c7a3974059538e9 Mon Sep 17 00:00:00 2001 From: Richard Barnes Date: Tue, 15 Oct 2024 13:58:42 -0700 Subject: [PATCH 086/235] Fix shadowed variable in mapillary/opensfm/opensfm/src/map/src/tracks_manager.cc Summary: Our upcoming compiler upgrade will require us not to have shadowed variables. Such variables have a _high_ bug rate and reduce readability, so we would like to avoid them even if the compiler was not forcing us to do so. This codemod attempts to fix an instance of a shadowed variable. Please review with care: if it's failed the result will be a silent bug. **What's a shadowed variable?** Shadowed variables are variables in an inner scope with the same name as another variable in an outer scope. Having the same name for both variables might be semantically correct, but it can make the code confusing to read! It can also hide subtle bugs. This diff fixes such an issue by renaming the variable. - If you approve of this diff, please use the "Accept & Ship" button :-) Reviewed By: palmje Differential Revision: D64398698 fbshipit-source-id: e70f61a9337391e8357fff7a8d07c0b927c63b4d --- opensfm/src/map/src/tracks_manager.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/opensfm/src/map/src/tracks_manager.cc b/opensfm/src/map/src/tracks_manager.cc index 93272e5dd..89dc64aa4 100644 --- a/opensfm/src/map/src/tracks_manager.cc +++ b/opensfm/src/map/src/tracks_manager.cc @@ -356,7 +356,7 @@ TracksManager::GetAllPairsConnectivity( TracksManager TracksManager::MergeTracksManager( const std::vector& tracks_managers) { // Some typedefs claryfying the aggregations - using FeatureId = std::pair; + using FeatureId_2 = std::pair; using SingleTrackId = std::pair; // Union-find main data @@ -364,7 +364,7 @@ TracksManager TracksManager::MergeTracksManager( union_find_elements; // Aggregate tracks be merged using (shot_id, feature_id) - std::unordered_map, HashPair> + std::unordered_map, HashPair> observations_per_feature_id; for (int i = 0; i < tracks_managers.size(); ++i) { const auto& manager = tracks_managers[i]; @@ -387,7 +387,7 @@ TracksManager TracksManager::MergeTracksManager( return merged; } - // Union-find any two tracks sharing a common FeatureId + // Union-find any two tracks sharing a common FeatureId_2 // For N tracks, make 0 the parent of [1, ... N-1[ for (const auto& tracks_agg : observations_per_feature_id) { if (tracks_agg.second.empty()) { From 4b19f0d8620f03d0f2e8a82c89dbc46195264b2d Mon Sep 17 00:00:00 2001 From: Richard Barnes Date: Tue, 15 Oct 2024 13:59:21 -0700 Subject: [PATCH 087/235] Fix shadowed variable in mapillary/opensfm/opensfm/src/third_party/akaze/lib/nldiffusion_functions.cpp Summary: Our upcoming compiler upgrade will require us not to have shadowed variables. Such variables have a _high_ bug rate and reduce readability, so we would like to avoid them even if the compiler was not forcing us to do so. This codemod attempts to fix an instance of a shadowed variable. Please review with care: if it's failed the result will be a silent bug. **What's a shadowed variable?** Shadowed variables are variables in an inner scope with the same name as another variable in an outer scope. Having the same name for both variables might be semantically correct, but it can make the code confusing to read! It can also hide subtle bugs. This diff fixes such an issue by renaming the variable. - If you approve of this diff, please use the "Accept & Ship" button :-) Reviewed By: palmje Differential Revision: D64398715 fbshipit-source-id: 5a49263b83945d723e9f3046fb13e260e9c6af11 --- .../akaze/lib/nldiffusion_functions.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/opensfm/src/third_party/akaze/lib/nldiffusion_functions.cpp b/opensfm/src/third_party/akaze/lib/nldiffusion_functions.cpp index 9f50abd5a..5fa764094 100644 --- a/opensfm/src/third_party/akaze/lib/nldiffusion_functions.cpp +++ b/opensfm/src/third_party/akaze/lib/nldiffusion_functions.cpp @@ -299,22 +299,22 @@ void nld_step_scalar(cv::Mat& Ld, const cv::Mat& c, cv::Mat& Lstep, const float Lstep_row = Lstep.ptr(i); float xpos_2 = (c_row_2[0]+c_row_2[1])*(Ld_row_2[1]-Ld_row_2[0]); - float ypos = (c_row_2[0]+c_row_p_2[0])*(Ld_row_p_2[0]-Ld_row_2[0]); + float ypos_2 = (c_row_2[0]+c_row_p_2[0])*(Ld_row_p_2[0]-Ld_row_2[0]); float yneg = (c_row_m[0]+c_row_2[0])*(Ld_row_2[0]-Ld_row_m[0]); - Lstep_row[0] = 0.5*stepsize*(xpos_2+ypos-yneg); + Lstep_row[0] = 0.5*stepsize*(xpos_2+ypos_2-yneg); - float xneg = (c_row_2[Lstep.cols-2]+c_row_2[Lstep.cols-1])*(Ld_row_2[Lstep.cols-1]-Ld_row_2[Lstep.cols-2]); - ypos = (c_row_2[Lstep.cols-1]+c_row_p_2[Lstep.cols-1])*(Ld_row_p_2[Lstep.cols-1]-Ld_row_2[Lstep.cols-1]); + float xneg_2 = (c_row_2[Lstep.cols-2]+c_row_2[Lstep.cols-1])*(Ld_row_2[Lstep.cols-1]-Ld_row_2[Lstep.cols-2]); + ypos_2 = (c_row_2[Lstep.cols-1]+c_row_p_2[Lstep.cols-1])*(Ld_row_p_2[Lstep.cols-1]-Ld_row_2[Lstep.cols-1]); yneg = (c_row_m[Lstep.cols-1]+c_row_2[Lstep.cols-1])*(Ld_row_2[Lstep.cols-1]-Ld_row_m[Lstep.cols-1]); - Lstep_row[Lstep.cols-1] = 0.5*stepsize*(-xneg+ypos-yneg); + Lstep_row[Lstep.cols-1] = 0.5*stepsize*(-xneg_2+ypos_2-yneg); } // Ld = Ld + Lstep for (int y = 0; y < Lstep.rows; y++) { - float* Ld_row = Ld.ptr(y); - float* Lstep_row = Lstep.ptr(y); - for (int x = 0; x < Lstep.cols; x++) { - Ld_row[x] = Ld_row[x] + Lstep_row[x]; + float* Ld_row_2 = Ld.ptr(y); + float* Lstep_row_2 = Lstep.ptr(y); + for (int x_2 = 0; x_2 < Lstep.cols; x_2++) { + Ld_row_2[x_2] = Ld_row_2[x_2] + Lstep_row_2[x_2]; } } } From afcf90bd0a48bef89c1af03b830d73cdd23edc71 Mon Sep 17 00:00:00 2001 From: generatedunixname89002005279527 Date: Wed, 16 Oct 2024 01:37:54 -0700 Subject: [PATCH 088/235] fbcode/mapillary/opensfm/opensfm/src/third_party/gtest/gmock Reviewed By: bal-a Differential Revision: D63973589 fbshipit-source-id: 93e60daee2c6d3fca353bfe03fbe2fe75b530d8d --- opensfm/src/third_party/gtest/gmock/gmock.h | 14978 ---------------- .../src/third_party/gtest/gmock/mock-log.h | 160 - 2 files changed, 15138 deletions(-) delete mode 100644 opensfm/src/third_party/gtest/gmock/gmock.h delete mode 100644 opensfm/src/third_party/gtest/gmock/mock-log.h diff --git a/opensfm/src/third_party/gtest/gmock/gmock.h b/opensfm/src/third_party/gtest/gmock/gmock.h deleted file mode 100644 index 70e227571..000000000 --- a/opensfm/src/third_party/gtest/gmock/gmock.h +++ /dev/null @@ -1,14978 +0,0 @@ -// Copyright 2007, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Author: wan@google.com (Zhanyong Wan) - -// Google Mock - a framework for writing C++ mock classes. -// -// This is the main header file a user should include. - -#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_H_ -#define GMOCK_INCLUDE_GMOCK_GMOCK_H_ - -// This file implements the following syntax: -// -// ON_CALL(mock_object.Method(...)) -// .With(...) ? -// .WillByDefault(...); -// -// where With() is optional and WillByDefault() must appear exactly -// once. -// -// EXPECT_CALL(mock_object.Method(...)) -// .With(...) ? -// .Times(...) ? -// .InSequence(...) * -// .WillOnce(...) * -// .WillRepeatedly(...) ? -// .RetiresOnSaturation() ? ; -// -// where all clauses are optional and WillOnce() can be repeated. - -// Copyright 2007, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Author: wan@google.com (Zhanyong Wan) - -// Google Mock - a framework for writing C++ mock classes. -// -// This file implements some commonly used actions. - -#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_ACTIONS_H_ -#define GMOCK_INCLUDE_GMOCK_GMOCK_ACTIONS_H_ - -#ifndef _WIN32_WCE -# include -#endif - -#include -#include - -// Copyright 2007, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Author: wan@google.com (Zhanyong Wan) - -// Google Mock - a framework for writing C++ mock classes. -// -// This file defines some utilities useful for implementing Google -// Mock. They are subject to change without notice, so please DO NOT -// USE THEM IN USER CODE. - -#ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_INTERNAL_UTILS_H_ -#define GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_INTERNAL_UTILS_H_ - -#include -#include // NOLINT -#include - -// This file was GENERATED by command: -// pump.py gmock-generated-internal-utils.h.pump -// DO NOT EDIT BY HAND!!! - -// Copyright 2007, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Author: wan@google.com (Zhanyong Wan) - -// Google Mock - a framework for writing C++ mock classes. -// -// This file contains template meta-programming utility classes needed -// for implementing Google Mock. - -#ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_GENERATED_INTERNAL_UTILS_H_ -#define GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_GENERATED_INTERNAL_UTILS_H_ - -// Copyright 2008, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Author: vadimb@google.com (Vadim Berman) -// -// Low-level types and utilities for porting Google Mock to various -// platforms. All macros ending with _ and symbols defined in an -// internal namespace are subject to change without notice. Code -// outside Google Mock MUST NOT USE THEM DIRECTLY. Macros that don't -// end with _ are part of Google Mock's public API and can be used by -// code outside Google Mock. - -#ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_PORT_H_ -#define GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_PORT_H_ - -#include -#include -#include - -// Most of the utilities needed for porting Google Mock are also -// required for Google Test and are defined in gtest-port.h. -// -// Note to maintainers: to reduce code duplication, prefer adding -// portability utilities to Google Test's gtest-port.h instead of -// here, as Google Mock depends on Google Test. Only add a utility -// here if it's truly specific to Google Mock. -#include "gtest/gtest.h" -// Copyright 2015, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Injection point for custom user configurations. -// The following macros can be defined: -// -// Flag related macros: -// GMOCK_DECLARE_bool_(name) -// GMOCK_DECLARE_int32_(name) -// GMOCK_DECLARE_string_(name) -// GMOCK_DEFINE_bool_(name, default_val, doc) -// GMOCK_DEFINE_int32_(name, default_val, doc) -// GMOCK_DEFINE_string_(name, default_val, doc) -// -// ** Custom implementation starts here ** - -#ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_PORT_H_ -#define GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_PORT_H_ - -#endif // GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_PORT_H_ - -// To avoid conditional compilation everywhere, we make it -// gmock-port.h's responsibility to #include the header implementing -// tr1/tuple. gmock-port.h does this via gtest-port.h, which is -// guaranteed to pull in the tuple header. - -// For MS Visual C++, check the compiler version. At least VS 2003 is -// required to compile Google Mock. -#if defined(_MSC_VER) && _MSC_VER < 1310 -# error "At least Visual C++ 2003 (7.1) is required to compile Google Mock." -#endif - -// Macro for referencing flags. This is public as we want the user to -// use this syntax to reference Google Mock flags. -#define GMOCK_FLAG(name) FLAGS_gmock_##name - -#if !defined(GMOCK_DECLARE_bool_) - -// Macros for declaring flags. -#define GMOCK_DECLARE_bool_(name) extern GTEST_API_ bool GMOCK_FLAG(name) -#define GMOCK_DECLARE_int32_(name) \ - extern GTEST_API_ ::testing::internal::Int32 GMOCK_FLAG(name) -#define GMOCK_DECLARE_string_(name) \ - extern GTEST_API_ ::std::string GMOCK_FLAG(name) - -// Macros for defining flags. -#define GMOCK_DEFINE_bool_(name, default_val, doc) \ - GTEST_API_ bool GMOCK_FLAG(name) = (default_val) -#define GMOCK_DEFINE_int32_(name, default_val, doc) \ - GTEST_API_ ::testing::internal::Int32 GMOCK_FLAG(name) = (default_val) -#define GMOCK_DEFINE_string_(name, default_val, doc) \ - GTEST_API_ ::std::string GMOCK_FLAG(name) = (default_val) - -#endif // !defined(GMOCK_DECLARE_bool_) - -#endif // GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_PORT_H_ - -namespace testing { - -template -class Matcher; - -namespace internal { - -// An IgnoredValue object can be implicitly constructed from ANY value. -// This is used in implementing the IgnoreResult(a) action. -class IgnoredValue { - public: - // This constructor template allows any value to be implicitly - // converted to IgnoredValue. The object has no data member and - // doesn't try to remember anything about the argument. We - // deliberately omit the 'explicit' keyword in order to allow the - // conversion to be implicit. - template - IgnoredValue(const T& /* ignored */) {} // NOLINT(runtime/explicit) -}; - -// MatcherTuple::type is a tuple type where each field is a Matcher -// for the corresponding field in tuple type T. -template -struct MatcherTuple; - -template <> -struct MatcherTuple< ::testing::tuple<> > { - typedef ::testing::tuple< > type; -}; - -template -struct MatcherTuple< ::testing::tuple > { - typedef ::testing::tuple > type; -}; - -template -struct MatcherTuple< ::testing::tuple > { - typedef ::testing::tuple, Matcher > type; -}; - -template -struct MatcherTuple< ::testing::tuple > { - typedef ::testing::tuple, Matcher, Matcher > type; -}; - -template -struct MatcherTuple< ::testing::tuple > { - typedef ::testing::tuple, Matcher, Matcher, - Matcher > type; -}; - -template -struct MatcherTuple< ::testing::tuple > { - typedef ::testing::tuple, Matcher, Matcher, Matcher, - Matcher > type; -}; - -template -struct MatcherTuple< ::testing::tuple > { - typedef ::testing::tuple, Matcher, Matcher, Matcher, - Matcher, Matcher > type; -}; - -template -struct MatcherTuple< ::testing::tuple > { - typedef ::testing::tuple, Matcher, Matcher, Matcher, - Matcher, Matcher, Matcher > type; -}; - -template -struct MatcherTuple< ::testing::tuple > { - typedef ::testing::tuple, Matcher, Matcher, Matcher, - Matcher, Matcher, Matcher, Matcher > type; -}; - -template -struct MatcherTuple< ::testing::tuple > { - typedef ::testing::tuple, Matcher, Matcher, Matcher, - Matcher, Matcher, Matcher, Matcher, Matcher > type; -}; - -template -struct MatcherTuple< ::testing::tuple > { - typedef ::testing::tuple, Matcher, Matcher, Matcher, - Matcher, Matcher, Matcher, Matcher, Matcher, - Matcher > type; -}; - -// Template struct Function, where F must be a function type, contains -// the following typedefs: -// -// Result: the function's return type. -// ArgumentN: the type of the N-th argument, where N starts with 1. -// ArgumentTuple: the tuple type consisting of all parameters of F. -// ArgumentMatcherTuple: the tuple type consisting of Matchers for all -// parameters of F. -// MakeResultVoid: the function type obtained by substituting void -// for the return type of F. -// MakeResultIgnoredValue: -// the function type obtained by substituting Something -// for the return type of F. -template -struct Function; - -template -struct Function { - typedef R Result; - typedef ::testing::tuple<> ArgumentTuple; - typedef typename MatcherTuple::type ArgumentMatcherTuple; - typedef void MakeResultVoid(); - typedef IgnoredValue MakeResultIgnoredValue(); -}; - -template -struct Function - : Function { - typedef A1 Argument1; - typedef ::testing::tuple ArgumentTuple; - typedef typename MatcherTuple::type ArgumentMatcherTuple; - typedef void MakeResultVoid(A1); - typedef IgnoredValue MakeResultIgnoredValue(A1); -}; - -template -struct Function - : Function { - typedef A2 Argument2; - typedef ::testing::tuple ArgumentTuple; - typedef typename MatcherTuple::type ArgumentMatcherTuple; - typedef void MakeResultVoid(A1, A2); - typedef IgnoredValue MakeResultIgnoredValue(A1, A2); -}; - -template -struct Function - : Function { - typedef A3 Argument3; - typedef ::testing::tuple ArgumentTuple; - typedef typename MatcherTuple::type ArgumentMatcherTuple; - typedef void MakeResultVoid(A1, A2, A3); - typedef IgnoredValue MakeResultIgnoredValue(A1, A2, A3); -}; - -template -struct Function - : Function { - typedef A4 Argument4; - typedef ::testing::tuple ArgumentTuple; - typedef typename MatcherTuple::type ArgumentMatcherTuple; - typedef void MakeResultVoid(A1, A2, A3, A4); - typedef IgnoredValue MakeResultIgnoredValue(A1, A2, A3, A4); -}; - -template -struct Function - : Function { - typedef A5 Argument5; - typedef ::testing::tuple ArgumentTuple; - typedef typename MatcherTuple::type ArgumentMatcherTuple; - typedef void MakeResultVoid(A1, A2, A3, A4, A5); - typedef IgnoredValue MakeResultIgnoredValue(A1, A2, A3, A4, A5); -}; - -template -struct Function - : Function { - typedef A6 Argument6; - typedef ::testing::tuple ArgumentTuple; - typedef typename MatcherTuple::type ArgumentMatcherTuple; - typedef void MakeResultVoid(A1, A2, A3, A4, A5, A6); - typedef IgnoredValue MakeResultIgnoredValue(A1, A2, A3, A4, A5, A6); -}; - -template -struct Function - : Function { - typedef A7 Argument7; - typedef ::testing::tuple ArgumentTuple; - typedef typename MatcherTuple::type ArgumentMatcherTuple; - typedef void MakeResultVoid(A1, A2, A3, A4, A5, A6, A7); - typedef IgnoredValue MakeResultIgnoredValue(A1, A2, A3, A4, A5, A6, A7); -}; - -template -struct Function - : Function { - typedef A8 Argument8; - typedef ::testing::tuple ArgumentTuple; - typedef typename MatcherTuple::type ArgumentMatcherTuple; - typedef void MakeResultVoid(A1, A2, A3, A4, A5, A6, A7, A8); - typedef IgnoredValue MakeResultIgnoredValue(A1, A2, A3, A4, A5, A6, A7, A8); -}; - -template -struct Function - : Function { - typedef A9 Argument9; - typedef ::testing::tuple ArgumentTuple; - typedef typename MatcherTuple::type ArgumentMatcherTuple; - typedef void MakeResultVoid(A1, A2, A3, A4, A5, A6, A7, A8, A9); - typedef IgnoredValue MakeResultIgnoredValue(A1, A2, A3, A4, A5, A6, A7, A8, - A9); -}; - -template -struct Function - : Function { - typedef A10 Argument10; - typedef ::testing::tuple ArgumentTuple; - typedef typename MatcherTuple::type ArgumentMatcherTuple; - typedef void MakeResultVoid(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10); - typedef IgnoredValue MakeResultIgnoredValue(A1, A2, A3, A4, A5, A6, A7, A8, - A9, A10); -}; - -} // namespace internal - -} // namespace testing - -#endif // GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_GENERATED_INTERNAL_UTILS_H_ - -namespace testing { -namespace internal { - -// Converts an identifier name to a space-separated list of lower-case -// words. Each maximum substring of the form [A-Za-z][a-z]*|\d+ is -// treated as one word. For example, both "FooBar123" and -// "foo_bar_123" are converted to "foo bar 123". -GTEST_API_ string ConvertIdentifierNameToWords(const char* id_name); - -// PointeeOf::type is the type of a value pointed to by a -// Pointer, which can be either a smart pointer or a raw pointer. The -// following default implementation is for the case where Pointer is a -// smart pointer. -template -struct PointeeOf { - // Smart pointer classes define type element_type as the type of - // their pointees. - typedef typename Pointer::element_type type; -}; -// This specialization is for the raw pointer case. -template -struct PointeeOf { typedef T type; }; // NOLINT - -// GetRawPointer(p) returns the raw pointer underlying p when p is a -// smart pointer, or returns p itself when p is already a raw pointer. -// The following default implementation is for the smart pointer case. -template -inline const typename Pointer::element_type* GetRawPointer(const Pointer& p) { - return p.get(); -} -// This overloaded version is for the raw pointer case. -template -inline Element* GetRawPointer(Element* p) { return p; } - -// This comparator allows linked_ptr to be stored in sets. -template -struct LinkedPtrLessThan { - bool operator()(const ::testing::internal::linked_ptr& lhs, - const ::testing::internal::linked_ptr& rhs) const { - return lhs.get() < rhs.get(); - } -}; - -// Symbian compilation can be done with wchar_t being either a native -// type or a typedef. Using Google Mock with OpenC without wchar_t -// should require the definition of _STLP_NO_WCHAR_T. -// -// MSVC treats wchar_t as a native type usually, but treats it as the -// same as unsigned short when the compiler option /Zc:wchar_t- is -// specified. It defines _NATIVE_WCHAR_T_DEFINED symbol when wchar_t -// is a native type. -#if (GTEST_OS_SYMBIAN && defined(_STLP_NO_WCHAR_T)) || \ - (defined(_MSC_VER) && !defined(_NATIVE_WCHAR_T_DEFINED)) -// wchar_t is a typedef. -#else -# define GMOCK_WCHAR_T_IS_NATIVE_ 1 -#endif - -// signed wchar_t and unsigned wchar_t are NOT in the C++ standard. -// Using them is a bad practice and not portable. So DON'T use them. -// -// Still, Google Mock is designed to work even if the user uses signed -// wchar_t or unsigned wchar_t (obviously, assuming the compiler -// supports them). -// -// To gcc, -// wchar_t == signed wchar_t != unsigned wchar_t == unsigned int -#ifdef __GNUC__ -// signed/unsigned wchar_t are valid types. -# define GMOCK_HAS_SIGNED_WCHAR_T_ 1 -#endif - -// In what follows, we use the term "kind" to indicate whether a type -// is bool, an integer type (excluding bool), a floating-point type, -// or none of them. This categorization is useful for determining -// when a matcher argument type can be safely converted to another -// type in the implementation of SafeMatcherCast. -enum TypeKind { - kBool, kInteger, kFloatingPoint, kOther -}; - -// KindOf::value is the kind of type T. -template struct KindOf { - enum { value = kOther }; // The default kind. -}; - -// This macro declares that the kind of 'type' is 'kind'. -#define GMOCK_DECLARE_KIND_(type, kind) \ - template <> struct KindOf { enum { value = kind }; } - -GMOCK_DECLARE_KIND_(bool, kBool); - -// All standard integer types. -GMOCK_DECLARE_KIND_(char, kInteger); -GMOCK_DECLARE_KIND_(signed char, kInteger); -GMOCK_DECLARE_KIND_(unsigned char, kInteger); -GMOCK_DECLARE_KIND_(short, kInteger); // NOLINT -GMOCK_DECLARE_KIND_(unsigned short, kInteger); // NOLINT -GMOCK_DECLARE_KIND_(int, kInteger); -GMOCK_DECLARE_KIND_(unsigned int, kInteger); -GMOCK_DECLARE_KIND_(long, kInteger); // NOLINT -GMOCK_DECLARE_KIND_(unsigned long, kInteger); // NOLINT - -#if GMOCK_WCHAR_T_IS_NATIVE_ -GMOCK_DECLARE_KIND_(wchar_t, kInteger); -#endif - -// Non-standard integer types. -GMOCK_DECLARE_KIND_(Int64, kInteger); -GMOCK_DECLARE_KIND_(UInt64, kInteger); - -// All standard floating-point types. -GMOCK_DECLARE_KIND_(float, kFloatingPoint); -GMOCK_DECLARE_KIND_(double, kFloatingPoint); -GMOCK_DECLARE_KIND_(long double, kFloatingPoint); - -#undef GMOCK_DECLARE_KIND_ - -// Evaluates to the kind of 'type'. -#define GMOCK_KIND_OF_(type) \ - static_cast< ::testing::internal::TypeKind>( \ - ::testing::internal::KindOf::value) - -// Evaluates to true iff integer type T is signed. -#define GMOCK_IS_SIGNED_(T) (static_cast(-1) < 0) - -// LosslessArithmeticConvertibleImpl::value -// is true iff arithmetic type From can be losslessly converted to -// arithmetic type To. -// -// It's the user's responsibility to ensure that both From and To are -// raw (i.e. has no CV modifier, is not a pointer, and is not a -// reference) built-in arithmetic types, kFromKind is the kind of -// From, and kToKind is the kind of To; the value is -// implementation-defined when the above pre-condition is violated. -template -struct LosslessArithmeticConvertibleImpl : public false_type {}; - -// Converting bool to bool is lossless. -template <> -struct LosslessArithmeticConvertibleImpl - : public true_type {}; // NOLINT - -// Converting bool to any integer type is lossless. -template -struct LosslessArithmeticConvertibleImpl - : public true_type {}; // NOLINT - -// Converting bool to any floating-point type is lossless. -template -struct LosslessArithmeticConvertibleImpl - : public true_type {}; // NOLINT - -// Converting an integer to bool is lossy. -template -struct LosslessArithmeticConvertibleImpl - : public false_type {}; // NOLINT - -// Converting an integer to another non-bool integer is lossless iff -// the target type's range encloses the source type's range. -template -struct LosslessArithmeticConvertibleImpl - : public bool_constant< - // When converting from a smaller size to a larger size, we are - // fine as long as we are not converting from signed to unsigned. - ((sizeof(From) < sizeof(To)) && - (!GMOCK_IS_SIGNED_(From) || GMOCK_IS_SIGNED_(To))) || - // When converting between the same size, the signedness must match. - ((sizeof(From) == sizeof(To)) && - (GMOCK_IS_SIGNED_(From) == GMOCK_IS_SIGNED_(To)))> {}; // NOLINT - -#undef GMOCK_IS_SIGNED_ - -// Converting an integer to a floating-point type may be lossy, since -// the format of a floating-point number is implementation-defined. -template -struct LosslessArithmeticConvertibleImpl - : public false_type {}; // NOLINT - -// Converting a floating-point to bool is lossy. -template -struct LosslessArithmeticConvertibleImpl - : public false_type {}; // NOLINT - -// Converting a floating-point to an integer is lossy. -template -struct LosslessArithmeticConvertibleImpl - : public false_type {}; // NOLINT - -// Converting a floating-point to another floating-point is lossless -// iff the target type is at least as big as the source type. -template -struct LosslessArithmeticConvertibleImpl< - kFloatingPoint, From, kFloatingPoint, To> - : public bool_constant {}; // NOLINT - -// LosslessArithmeticConvertible::value is true iff arithmetic -// type From can be losslessly converted to arithmetic type To. -// -// It's the user's responsibility to ensure that both From and To are -// raw (i.e. has no CV modifier, is not a pointer, and is not a -// reference) built-in arithmetic types; the value is -// implementation-defined when the above pre-condition is violated. -template -struct LosslessArithmeticConvertible - : public LosslessArithmeticConvertibleImpl< - GMOCK_KIND_OF_(From), From, GMOCK_KIND_OF_(To), To> {}; // NOLINT - -// This interface knows how to report a Google Mock failure (either -// non-fatal or fatal). -class FailureReporterInterface { - public: - // The type of a failure (either non-fatal or fatal). - enum FailureType { - kNonfatal, kFatal - }; - - virtual ~FailureReporterInterface() {} - - // Reports a failure that occurred at the given source file location. - virtual void ReportFailure(FailureType type, const char* file, int line, - const string& message) = 0; -}; - -// Returns the failure reporter used by Google Mock. -GTEST_API_ FailureReporterInterface* GetFailureReporter(); - -// Asserts that condition is true; aborts the process with the given -// message if condition is false. We cannot use LOG(FATAL) or CHECK() -// as Google Mock might be used to mock the log sink itself. We -// inline this function to prevent it from showing up in the stack -// trace. -inline void Assert(bool condition, const char* file, int line, - const string& msg) { - if (!condition) { - GetFailureReporter()->ReportFailure(FailureReporterInterface::kFatal, - file, line, msg); - } -} -inline void Assert(bool condition, const char* file, int line) { - Assert(condition, file, line, "Assertion failed."); -} - -// Verifies that condition is true; generates a non-fatal failure if -// condition is false. -inline void Expect(bool condition, const char* file, int line, - const string& msg) { - if (!condition) { - GetFailureReporter()->ReportFailure(FailureReporterInterface::kNonfatal, - file, line, msg); - } -} -inline void Expect(bool condition, const char* file, int line) { - Expect(condition, file, line, "Expectation failed."); -} - -// Severity level of a log. -enum LogSeverity { - kInfo = 0, - kWarning = 1 -}; - -// Valid values for the --gmock_verbose flag. - -// All logs (informational and warnings) are printed. -const char kInfoVerbosity[] = "info"; -// Only warnings are printed. -const char kWarningVerbosity[] = "warning"; -// No logs are printed. -const char kErrorVerbosity[] = "error"; - -// Returns true iff a log with the given severity is visible according -// to the --gmock_verbose flag. -GTEST_API_ bool LogIsVisible(LogSeverity severity); - -// Prints the given message to stdout iff 'severity' >= the level -// specified by the --gmock_verbose flag. If stack_frames_to_skip >= -// 0, also prints the stack trace excluding the top -// stack_frames_to_skip frames. In opt mode, any positive -// stack_frames_to_skip is treated as 0, since we don't know which -// function calls will be inlined by the compiler and need to be -// conservative. -GTEST_API_ void Log(LogSeverity severity, - const string& message, - int stack_frames_to_skip); - -// TODO(wan@google.com): group all type utilities together. - -// Type traits. - -// is_reference::value is non-zero iff T is a reference type. -template struct is_reference : public false_type {}; -template struct is_reference : public true_type {}; - -// type_equals::value is non-zero iff T1 and T2 are the same type. -template struct type_equals : public false_type {}; -template struct type_equals : public true_type {}; - -// remove_reference::type removes the reference from type T, if any. -template struct remove_reference { typedef T type; }; // NOLINT -template struct remove_reference { typedef T type; }; // NOLINT - -// DecayArray::type turns an array type U[N] to const U* and preserves -// other types. Useful for saving a copy of a function argument. -template struct DecayArray { typedef T type; }; // NOLINT -template struct DecayArray { - typedef const T* type; -}; -// Sometimes people use arrays whose size is not available at the use site -// (e.g. extern const char kNamePrefix[]). This specialization covers that -// case. -template struct DecayArray { - typedef const T* type; -}; - -// Disable MSVC warnings for infinite recursion, since in this case the -// the recursion is unreachable. -#ifdef _MSC_VER -# pragma warning(push) -# pragma warning(disable:4717) -#endif - -// Invalid() is usable as an expression of type T, but will terminate -// the program with an assertion failure if actually run. This is useful -// when a value of type T is needed for compilation, but the statement -// will not really be executed (or we don't care if the statement -// crashes). -template -inline T Invalid() { - Assert(false, "", -1, "Internal error: attempt to return invalid value"); - // This statement is unreachable, and would never terminate even if it - // could be reached. It is provided only to placate compiler warnings - // about missing return statements. - return Invalid(); -} - -#ifdef _MSC_VER -# pragma warning(pop) -#endif - -// Given a raw type (i.e. having no top-level reference or const -// modifier) RawContainer that's either an STL-style container or a -// native array, class StlContainerView has the -// following members: -// -// - type is a type that provides an STL-style container view to -// (i.e. implements the STL container concept for) RawContainer; -// - const_reference is a type that provides a reference to a const -// RawContainer; -// - ConstReference(raw_container) returns a const reference to an STL-style -// container view to raw_container, which is a RawContainer. -// - Copy(raw_container) returns an STL-style container view of a -// copy of raw_container, which is a RawContainer. -// -// This generic version is used when RawContainer itself is already an -// STL-style container. -template -class StlContainerView { - public: - typedef RawContainer type; - typedef const type& const_reference; - - static const_reference ConstReference(const RawContainer& container) { - // Ensures that RawContainer is not a const type. - testing::StaticAssertTypeEq(); - return container; - } - static type Copy(const RawContainer& container) { return container; } -}; - -// This specialization is used when RawContainer is a native array type. -template -class StlContainerView { - public: - typedef GTEST_REMOVE_CONST_(Element) RawElement; - typedef internal::NativeArray type; - // NativeArray can represent a native array either by value or by - // reference (selected by a constructor argument), so 'const type' - // can be used to reference a const native array. We cannot - // 'typedef const type& const_reference' here, as that would mean - // ConstReference() has to return a reference to a local variable. - typedef const type const_reference; - - static const_reference ConstReference(const Element (&array)[N]) { - // Ensures that Element is not a const type. - testing::StaticAssertTypeEq(); -#if GTEST_OS_SYMBIAN - // The Nokia Symbian compiler confuses itself in template instantiation - // for this call without the cast to Element*: - // function call '[testing::internal::NativeArray].NativeArray( - // {lval} const char *[4], long, testing::internal::RelationToSource)' - // does not match - // 'testing::internal::NativeArray::NativeArray( - // char *const *, unsigned int, testing::internal::RelationToSource)' - // (instantiating: 'testing::internal::ContainsMatcherImpl - // ::Matches(const char * (&)[4]) const') - // (instantiating: 'testing::internal::StlContainerView:: - // ConstReference(const char * (&)[4])') - // (and though the N parameter type is mismatched in the above explicit - // conversion of it doesn't help - only the conversion of the array). - return type(const_cast(&array[0]), N, - RelationToSourceReference()); -#else - return type(array, N, RelationToSourceReference()); -#endif // GTEST_OS_SYMBIAN - } - static type Copy(const Element (&array)[N]) { -#if GTEST_OS_SYMBIAN - return type(const_cast(&array[0]), N, RelationToSourceCopy()); -#else - return type(array, N, RelationToSourceCopy()); -#endif // GTEST_OS_SYMBIAN - } -}; - -// This specialization is used when RawContainer is a native array -// represented as a (pointer, size) tuple. -template -class StlContainerView< ::testing::tuple > { - public: - typedef GTEST_REMOVE_CONST_( - typename internal::PointeeOf::type) RawElement; - typedef internal::NativeArray type; - typedef const type const_reference; - - static const_reference ConstReference( - const ::testing::tuple& array) { - return type(get<0>(array), get<1>(array), RelationToSourceReference()); - } - static type Copy(const ::testing::tuple& array) { - return type(get<0>(array), get<1>(array), RelationToSourceCopy()); - } -}; - -// The following specialization prevents the user from instantiating -// StlContainer with a reference type. -template class StlContainerView; - -// A type transform to remove constness from the first part of a pair. -// Pairs like that are used as the value_type of associative containers, -// and this transform produces a similar but assignable pair. -template -struct RemoveConstFromKey { - typedef T type; -}; - -// Partially specialized to remove constness from std::pair. -template -struct RemoveConstFromKey > { - typedef std::pair type; -}; - -// Mapping from booleans to types. Similar to boost::bool_ and -// std::integral_constant. -template -struct BooleanConstant {}; - -} // namespace internal -} // namespace testing - -#endif // GMOCK_INCLUDE_GMOCK_INTERNAL_GMOCK_INTERNAL_UTILS_H_ - - -#if GTEST_LANG_CXX11 // Defined by gtest-port.h via gmock-port.h. -#include -#endif - -namespace testing { - -// To implement an action Foo, define: -// 1. a class FooAction that implements the ActionInterface interface, and -// 2. a factory function that creates an Action object from a -// const FooAction*. -// -// The two-level delegation design follows that of Matcher, providing -// consistency for extension developers. It also eases ownership -// management as Action objects can now be copied like plain values. - -namespace internal { - -template -class ActionAdaptor; - -// BuiltInDefaultValueGetter::Get() returns a -// default-constructed T value. BuiltInDefaultValueGetter::Get() crashes with an error. -// -// This primary template is used when kDefaultConstructible is true. -template -struct BuiltInDefaultValueGetter { - static T Get() { return T(); } -}; -template -struct BuiltInDefaultValueGetter { - static T Get() { - Assert(false, __FILE__, __LINE__, - "Default action undefined for the function return type."); - return internal::Invalid(); - // The above statement will never be reached, but is required in - // order for this function to compile. - } -}; - -// BuiltInDefaultValue::Get() returns the "built-in" default value -// for type T, which is NULL when T is a raw pointer type, 0 when T is -// a numeric type, false when T is bool, or "" when T is string or -// std::string. In addition, in C++11 and above, it turns a -// default-constructed T value if T is default constructible. For any -// other type T, the built-in default T value is undefined, and the -// function will abort the process. -template -class BuiltInDefaultValue { - public: -#if GTEST_LANG_CXX11 - // This function returns true iff type T has a built-in default value. - static bool Exists() { - return ::std::is_default_constructible::value; - } - - static T Get() { - return BuiltInDefaultValueGetter< - T, ::std::is_default_constructible::value>::Get(); - } - -#else // GTEST_LANG_CXX11 - // This function returns true iff type T has a built-in default value. - static bool Exists() { - return false; - } - - static T Get() { - return BuiltInDefaultValueGetter::Get(); - } - -#endif // GTEST_LANG_CXX11 -}; - -// This partial specialization says that we use the same built-in -// default value for T and const T. -template -class BuiltInDefaultValue { - public: - static bool Exists() { return BuiltInDefaultValue::Exists(); } - static T Get() { return BuiltInDefaultValue::Get(); } -}; - -// This partial specialization defines the default values for pointer -// types. -template -class BuiltInDefaultValue { - public: - static bool Exists() { return true; } - static T* Get() { return NULL; } -}; - -// The following specializations define the default values for -// specific types we care about. -#define GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(type, value) \ - template <> \ - class BuiltInDefaultValue { \ - public: \ - static bool Exists() { return true; } \ - static type Get() { return value; } \ - } - -GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(void, ); // NOLINT -#if GTEST_HAS_GLOBAL_STRING -GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(::string, ""); -#endif // GTEST_HAS_GLOBAL_STRING -GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(::std::string, ""); -GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(bool, false); -GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(unsigned char, '\0'); -GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(signed char, '\0'); -GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(char, '\0'); - -// There's no need for a default action for signed wchar_t, as that -// type is the same as wchar_t for gcc, and invalid for MSVC. -// -// There's also no need for a default action for unsigned wchar_t, as -// that type is the same as unsigned int for gcc, and invalid for -// MSVC. -#if GMOCK_WCHAR_T_IS_NATIVE_ -GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(wchar_t, 0U); // NOLINT -#endif - -GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(unsigned short, 0U); // NOLINT -GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(signed short, 0); // NOLINT -GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(unsigned int, 0U); -GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(signed int, 0); -GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(unsigned long, 0UL); // NOLINT -GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(signed long, 0L); // NOLINT -GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(UInt64, 0); -GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(Int64, 0); -GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(float, 0); -GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_(double, 0); - -#undef GMOCK_DEFINE_DEFAULT_ACTION_FOR_RETURN_TYPE_ - -} // namespace internal - -// When an unexpected function call is encountered, Google Mock will -// let it return a default value if the user has specified one for its -// return type, or if the return type has a built-in default value; -// otherwise Google Mock won't know what value to return and will have -// to abort the process. -// -// The DefaultValue class allows a user to specify the -// default value for a type T that is both copyable and publicly -// destructible (i.e. anything that can be used as a function return -// type). The usage is: -// -// // Sets the default value for type T to be foo. -// DefaultValue::Set(foo); -template -class DefaultValue { - public: - // Sets the default value for type T; requires T to be - // copy-constructable and have a public destructor. - static void Set(T x) { - delete producer_; - producer_ = new FixedValueProducer(x); - } - - // Provides a factory function to be called to generate the default value. - // This method can be used even if T is only move-constructible, but it is not - // limited to that case. - typedef T (*FactoryFunction)(); - static void SetFactory(FactoryFunction factory) { - delete producer_; - producer_ = new FactoryValueProducer(factory); - } - - // Unsets the default value for type T. - static void Clear() { - delete producer_; - producer_ = NULL; - } - - // Returns true iff the user has set the default value for type T. - static bool IsSet() { return producer_ != NULL; } - - // Returns true if T has a default return value set by the user or there - // exists a built-in default value. - static bool Exists() { - return IsSet() || internal::BuiltInDefaultValue::Exists(); - } - - // Returns the default value for type T if the user has set one; - // otherwise returns the built-in default value. Requires that Exists() - // is true, which ensures that the return value is well-defined. - static T Get() { - return producer_ == NULL ? - internal::BuiltInDefaultValue::Get() : producer_->Produce(); - } - - private: - class ValueProducer { - public: - virtual ~ValueProducer() {} - virtual T Produce() = 0; - }; - - class FixedValueProducer : public ValueProducer { - public: - explicit FixedValueProducer(T value) : value_(value) {} - virtual T Produce() { return value_; } - - private: - const T value_; - GTEST_DISALLOW_COPY_AND_ASSIGN_(FixedValueProducer); - }; - - class FactoryValueProducer : public ValueProducer { - public: - explicit FactoryValueProducer(FactoryFunction factory) - : factory_(factory) {} - virtual T Produce() { return factory_(); } - - private: - const FactoryFunction factory_; - GTEST_DISALLOW_COPY_AND_ASSIGN_(FactoryValueProducer); - }; - - static ValueProducer* producer_; -}; - -// This partial specialization allows a user to set default values for -// reference types. -template -class DefaultValue { - public: - // Sets the default value for type T&. - static void Set(T& x) { // NOLINT - address_ = &x; - } - - // Unsets the default value for type T&. - static void Clear() { - address_ = NULL; - } - - // Returns true iff the user has set the default value for type T&. - static bool IsSet() { return address_ != NULL; } - - // Returns true if T has a default return value set by the user or there - // exists a built-in default value. - static bool Exists() { - return IsSet() || internal::BuiltInDefaultValue::Exists(); - } - - // Returns the default value for type T& if the user has set one; - // otherwise returns the built-in default value if there is one; - // otherwise aborts the process. - static T& Get() { - return address_ == NULL ? - internal::BuiltInDefaultValue::Get() : *address_; - } - - private: - static T* address_; -}; - -// This specialization allows DefaultValue::Get() to -// compile. -template <> -class DefaultValue { - public: - static bool Exists() { return true; } - static void Get() {} -}; - -// Points to the user-set default value for type T. -template -typename DefaultValue::ValueProducer* DefaultValue::producer_ = NULL; - -// Points to the user-set default value for type T&. -template -T* DefaultValue::address_ = NULL; - -// Implement this interface to define an action for function type F. -template -class ActionInterface { - public: - typedef typename internal::Function::Result Result; - typedef typename internal::Function::ArgumentTuple ArgumentTuple; - - ActionInterface() {} - virtual ~ActionInterface() {} - - // Performs the action. This method is not const, as in general an - // action can have side effects and be stateful. For example, a - // get-the-next-element-from-the-collection action will need to - // remember the current element. - virtual Result Perform(const ArgumentTuple& args) = 0; - - private: - GTEST_DISALLOW_COPY_AND_ASSIGN_(ActionInterface); -}; - -// An Action is a copyable and IMMUTABLE (except by assignment) -// object that represents an action to be taken when a mock function -// of type F is called. The implementation of Action is just a -// linked_ptr to const ActionInterface, so copying is fairly cheap. -// Don't inherit from Action! -// -// You can view an object implementing ActionInterface as a -// concrete action (including its current state), and an Action -// object as a handle to it. -template -class Action { - public: - typedef typename internal::Function::Result Result; - typedef typename internal::Function::ArgumentTuple ArgumentTuple; - - // Constructs a null Action. Needed for storing Action objects in - // STL containers. - Action() : impl_(NULL) {} - - // Constructs an Action from its implementation. A NULL impl is - // used to represent the "do-default" action. - explicit Action(ActionInterface* impl) : impl_(impl) {} - - // Copy constructor. - Action(const Action& action) : impl_(action.impl_) {} - - // This constructor allows us to turn an Action object into an - // Action, as long as F's arguments can be implicitly converted - // to Func's and Func's return type can be implicitly converted to - // F's. - template - explicit Action(const Action& action); - - // Returns true iff this is the DoDefault() action. - bool IsDoDefault() const { return impl_.get() == NULL; } - - // Performs the action. Note that this method is const even though - // the corresponding method in ActionInterface is not. The reason - // is that a const Action means that it cannot be re-bound to - // another concrete action, not that the concrete action it binds to - // cannot change state. (Think of the difference between a const - // pointer and a pointer to const.) - Result Perform(const ArgumentTuple& args) const { - internal::Assert( - !IsDoDefault(), __FILE__, __LINE__, - "You are using DoDefault() inside a composite action like " - "DoAll() or WithArgs(). This is not supported for technical " - "reasons. Please instead spell out the default action, or " - "assign the default action to an Action variable and use " - "the variable in various places."); - return impl_->Perform(args); - } - - private: - template - friend class internal::ActionAdaptor; - - internal::linked_ptr > impl_; -}; - -// The PolymorphicAction class template makes it easy to implement a -// polymorphic action (i.e. an action that can be used in mock -// functions of than one type, e.g. Return()). -// -// To define a polymorphic action, a user first provides a COPYABLE -// implementation class that has a Perform() method template: -// -// class FooAction { -// public: -// template -// Result Perform(const ArgumentTuple& args) const { -// // Processes the arguments and returns a result, using -// // tr1::get(args) to get the N-th (0-based) argument in the tuple. -// } -// ... -// }; -// -// Then the user creates the polymorphic action using -// MakePolymorphicAction(object) where object has type FooAction. See -// the definition of Return(void) and SetArgumentPointee(value) for -// complete examples. -template -class PolymorphicAction { - public: - explicit PolymorphicAction(const Impl& impl) : impl_(impl) {} - - template - operator Action() const { - return Action(new MonomorphicImpl(impl_)); - } - - private: - template - class MonomorphicImpl : public ActionInterface { - public: - typedef typename internal::Function::Result Result; - typedef typename internal::Function::ArgumentTuple ArgumentTuple; - - explicit MonomorphicImpl(const Impl& impl) : impl_(impl) {} - - virtual Result Perform(const ArgumentTuple& args) { - return impl_.template Perform(args); - } - - private: - Impl impl_; - - GTEST_DISALLOW_ASSIGN_(MonomorphicImpl); - }; - - Impl impl_; - - GTEST_DISALLOW_ASSIGN_(PolymorphicAction); -}; - -// Creates an Action from its implementation and returns it. The -// created Action object owns the implementation. -template -Action MakeAction(ActionInterface* impl) { - return Action(impl); -} - -// Creates a polymorphic action from its implementation. This is -// easier to use than the PolymorphicAction constructor as it -// doesn't require you to explicitly write the template argument, e.g. -// -// MakePolymorphicAction(foo); -// vs -// PolymorphicAction(foo); -template -inline PolymorphicAction MakePolymorphicAction(const Impl& impl) { - return PolymorphicAction(impl); -} - -namespace internal { - -// Allows an Action object to pose as an Action, as long as F2 -// and F1 are compatible. -template -class ActionAdaptor : public ActionInterface { - public: - typedef typename internal::Function::Result Result; - typedef typename internal::Function::ArgumentTuple ArgumentTuple; - - explicit ActionAdaptor(const Action& from) : impl_(from.impl_) {} - - virtual Result Perform(const ArgumentTuple& args) { - return impl_->Perform(args); - } - - private: - const internal::linked_ptr > impl_; - - GTEST_DISALLOW_ASSIGN_(ActionAdaptor); -}; - -// Helper struct to specialize ReturnAction to execute a move instead of a copy -// on return. Useful for move-only types, but could be used on any type. -template -struct ByMoveWrapper { - explicit ByMoveWrapper(T value) : payload(internal::move(value)) {} - T payload; -}; - -// Implements the polymorphic Return(x) action, which can be used in -// any function that returns the type of x, regardless of the argument -// types. -// -// Note: The value passed into Return must be converted into -// Function::Result when this action is cast to Action rather than -// when that action is performed. This is important in scenarios like -// -// MOCK_METHOD1(Method, T(U)); -// ... -// { -// Foo foo; -// X x(&foo); -// EXPECT_CALL(mock, Method(_)).WillOnce(Return(x)); -// } -// -// In the example above the variable x holds reference to foo which leaves -// scope and gets destroyed. If copying X just copies a reference to foo, -// that copy will be left with a hanging reference. If conversion to T -// makes a copy of foo, the above code is safe. To support that scenario, we -// need to make sure that the type conversion happens inside the EXPECT_CALL -// statement, and conversion of the result of Return to Action is a -// good place for that. -// -template -class ReturnAction { - public: - // Constructs a ReturnAction object from the value to be returned. - // 'value' is passed by value instead of by const reference in order - // to allow Return("string literal") to compile. - explicit ReturnAction(R value) : value_(new R(internal::move(value))) {} - - // This template type conversion operator allows Return(x) to be - // used in ANY function that returns x's type. - template - operator Action() const { - // Assert statement belongs here because this is the best place to verify - // conditions on F. It produces the clearest error messages - // in most compilers. - // Impl really belongs in this scope as a local class but can't - // because MSVC produces duplicate symbols in different translation units - // in this case. Until MS fixes that bug we put Impl into the class scope - // and put the typedef both here (for use in assert statement) and - // in the Impl class. But both definitions must be the same. - typedef typename Function::Result Result; - GTEST_COMPILE_ASSERT_( - !is_reference::value, - use_ReturnRef_instead_of_Return_to_return_a_reference); - return Action(new Impl(value_)); - } - - private: - // Implements the Return(x) action for a particular function type F. - template - class Impl : public ActionInterface { - public: - typedef typename Function::Result Result; - typedef typename Function::ArgumentTuple ArgumentTuple; - - // The implicit cast is necessary when Result has more than one - // single-argument constructor (e.g. Result is std::vector) and R - // has a type conversion operator template. In that case, value_(value) - // won't compile as the compiler doesn't known which constructor of - // Result to call. ImplicitCast_ forces the compiler to convert R to - // Result without considering explicit constructors, thus resolving the - // ambiguity. value_ is then initialized using its copy constructor. - explicit Impl(const linked_ptr& value) - : value_before_cast_(*value), - value_(ImplicitCast_(value_before_cast_)) {} - - virtual Result Perform(const ArgumentTuple&) { return value_; } - - private: - GTEST_COMPILE_ASSERT_(!is_reference::value, - Result_cannot_be_a_reference_type); - // We save the value before casting just in case it is being cast to a - // wrapper type. - R value_before_cast_; - Result value_; - - GTEST_DISALLOW_COPY_AND_ASSIGN_(Impl); - }; - - // Partially specialize for ByMoveWrapper. This version of ReturnAction will - // move its contents instead. - template - class Impl, F> : public ActionInterface { - public: - typedef typename Function::Result Result; - typedef typename Function::ArgumentTuple ArgumentTuple; - - explicit Impl(const linked_ptr& wrapper) - : performed_(false), wrapper_(wrapper) {} - - virtual Result Perform(const ArgumentTuple&) { - GTEST_CHECK_(!performed_) - << "A ByMove() action should only be performed once."; - performed_ = true; - return internal::move(wrapper_->payload); - } - - private: - bool performed_; - const linked_ptr wrapper_; - - GTEST_DISALLOW_ASSIGN_(Impl); - }; - - const linked_ptr value_; - - GTEST_DISALLOW_ASSIGN_(ReturnAction); -}; - -// Implements the ReturnNull() action. -class ReturnNullAction { - public: - // Allows ReturnNull() to be used in any pointer-returning function. In C++11 - // this is enforced by returning nullptr, and in non-C++11 by asserting a - // pointer type on compile time. - template - static Result Perform(const ArgumentTuple&) { -#if GTEST_LANG_CXX11 - return nullptr; -#else - GTEST_COMPILE_ASSERT_(internal::is_pointer::value, - ReturnNull_can_be_used_to_return_a_pointer_only); - return NULL; -#endif // GTEST_LANG_CXX11 - } -}; - -// Implements the Return() action. -class ReturnVoidAction { - public: - // Allows Return() to be used in any void-returning function. - template - static void Perform(const ArgumentTuple&) { - CompileAssertTypesEqual(); - } -}; - -// Implements the polymorphic ReturnRef(x) action, which can be used -// in any function that returns a reference to the type of x, -// regardless of the argument types. -template -class ReturnRefAction { - public: - // Constructs a ReturnRefAction object from the reference to be returned. - explicit ReturnRefAction(T& ref) : ref_(ref) {} // NOLINT - - // This template type conversion operator allows ReturnRef(x) to be - // used in ANY function that returns a reference to x's type. - template - operator Action() const { - typedef typename Function::Result Result; - // Asserts that the function return type is a reference. This - // catches the user error of using ReturnRef(x) when Return(x) - // should be used, and generates some helpful error message. - GTEST_COMPILE_ASSERT_(internal::is_reference::value, - use_Return_instead_of_ReturnRef_to_return_a_value); - return Action(new Impl(ref_)); - } - - private: - // Implements the ReturnRef(x) action for a particular function type F. - template - class Impl : public ActionInterface { - public: - typedef typename Function::Result Result; - typedef typename Function::ArgumentTuple ArgumentTuple; - - explicit Impl(T& ref) : ref_(ref) {} // NOLINT - - virtual Result Perform(const ArgumentTuple&) { - return ref_; - } - - private: - T& ref_; - - GTEST_DISALLOW_ASSIGN_(Impl); - }; - - T& ref_; - - GTEST_DISALLOW_ASSIGN_(ReturnRefAction); -}; - -// Implements the polymorphic ReturnRefOfCopy(x) action, which can be -// used in any function that returns a reference to the type of x, -// regardless of the argument types. -template -class ReturnRefOfCopyAction { - public: - // Constructs a ReturnRefOfCopyAction object from the reference to - // be returned. - explicit ReturnRefOfCopyAction(const T& value) : value_(value) {} // NOLINT - - // This template type conversion operator allows ReturnRefOfCopy(x) to be - // used in ANY function that returns a reference to x's type. - template - operator Action() const { - typedef typename Function::Result Result; - // Asserts that the function return type is a reference. This - // catches the user error of using ReturnRefOfCopy(x) when Return(x) - // should be used, and generates some helpful error message. - GTEST_COMPILE_ASSERT_( - internal::is_reference::value, - use_Return_instead_of_ReturnRefOfCopy_to_return_a_value); - return Action(new Impl(value_)); - } - - private: - // Implements the ReturnRefOfCopy(x) action for a particular function type F. - template - class Impl : public ActionInterface { - public: - typedef typename Function::Result Result; - typedef typename Function::ArgumentTuple ArgumentTuple; - - explicit Impl(const T& value) : value_(value) {} // NOLINT - - virtual Result Perform(const ArgumentTuple&) { - return value_; - } - - private: - T value_; - - GTEST_DISALLOW_ASSIGN_(Impl); - }; - - const T value_; - - GTEST_DISALLOW_ASSIGN_(ReturnRefOfCopyAction); -}; - -// Implements the polymorphic DoDefault() action. -class DoDefaultAction { - public: - // This template type conversion operator allows DoDefault() to be - // used in any function. - template - operator Action() const { return Action(NULL); } -}; - -// Implements the Assign action to set a given pointer referent to a -// particular value. -template -class AssignAction { - public: - AssignAction(T1* ptr, T2 value) : ptr_(ptr), value_(value) {} - - template - void Perform(const ArgumentTuple& /* args */) const { - *ptr_ = value_; - } - - private: - T1* const ptr_; - const T2 value_; - - GTEST_DISALLOW_ASSIGN_(AssignAction); -}; - -#if !GTEST_OS_WINDOWS_MOBILE - -// Implements the SetErrnoAndReturn action to simulate return from -// various system calls and libc functions. -template -class SetErrnoAndReturnAction { - public: - SetErrnoAndReturnAction(int errno_value, T result) - : errno_(errno_value), - result_(result) {} - template - Result Perform(const ArgumentTuple& /* args */) const { - errno = errno_; - return result_; - } - - private: - const int errno_; - const T result_; - - GTEST_DISALLOW_ASSIGN_(SetErrnoAndReturnAction); -}; - -#endif // !GTEST_OS_WINDOWS_MOBILE - -// Implements the SetArgumentPointee(x) action for any function -// whose N-th argument (0-based) is a pointer to x's type. The -// template parameter kIsProto is true iff type A is ProtocolMessage, -// proto2::Message, or a sub-class of those. -template -class SetArgumentPointeeAction { - public: - // Constructs an action that sets the variable pointed to by the - // N-th function argument to 'value'. - explicit SetArgumentPointeeAction(const A& value) : value_(value) {} - - template - void Perform(const ArgumentTuple& args) const { - CompileAssertTypesEqual(); - *::testing::get(args) = value_; - } - - private: - const A value_; - - GTEST_DISALLOW_ASSIGN_(SetArgumentPointeeAction); -}; - -template -class SetArgumentPointeeAction { - public: - // Constructs an action that sets the variable pointed to by the - // N-th function argument to 'proto'. Both ProtocolMessage and - // proto2::Message have the CopyFrom() method, so the same - // implementation works for both. - explicit SetArgumentPointeeAction(const Proto& proto) : proto_(new Proto) { - proto_->CopyFrom(proto); - } - - template - void Perform(const ArgumentTuple& args) const { - CompileAssertTypesEqual(); - ::testing::get(args)->CopyFrom(*proto_); - } - - private: - const internal::linked_ptr proto_; - - GTEST_DISALLOW_ASSIGN_(SetArgumentPointeeAction); -}; - -// Implements the InvokeWithoutArgs(f) action. The template argument -// FunctionImpl is the implementation type of f, which can be either a -// function pointer or a functor. InvokeWithoutArgs(f) can be used as an -// Action as long as f's type is compatible with F (i.e. f can be -// assigned to a tr1::function). -template -class InvokeWithoutArgsAction { - public: - // The c'tor makes a copy of function_impl (either a function - // pointer or a functor). - explicit InvokeWithoutArgsAction(FunctionImpl function_impl) - : function_impl_(function_impl) {} - - // Allows InvokeWithoutArgs(f) to be used as any action whose type is - // compatible with f. - template - Result Perform(const ArgumentTuple&) { return function_impl_(); } - - private: - FunctionImpl function_impl_; - - GTEST_DISALLOW_ASSIGN_(InvokeWithoutArgsAction); -}; - -// Implements the InvokeWithoutArgs(object_ptr, &Class::Method) action. -template -class InvokeMethodWithoutArgsAction { - public: - InvokeMethodWithoutArgsAction(Class* obj_ptr, MethodPtr method_ptr) - : obj_ptr_(obj_ptr), method_ptr_(method_ptr) {} - - template - Result Perform(const ArgumentTuple&) const { - return (obj_ptr_->*method_ptr_)(); - } - - private: - Class* const obj_ptr_; - const MethodPtr method_ptr_; - - GTEST_DISALLOW_ASSIGN_(InvokeMethodWithoutArgsAction); -}; - -// Implements the IgnoreResult(action) action. -template -class IgnoreResultAction { - public: - explicit IgnoreResultAction(const A& action) : action_(action) {} - - template - operator Action() const { - // Assert statement belongs here because this is the best place to verify - // conditions on F. It produces the clearest error messages - // in most compilers. - // Impl really belongs in this scope as a local class but can't - // because MSVC produces duplicate symbols in different translation units - // in this case. Until MS fixes that bug we put Impl into the class scope - // and put the typedef both here (for use in assert statement) and - // in the Impl class. But both definitions must be the same. - typedef typename internal::Function::Result Result; - - // Asserts at compile time that F returns void. - CompileAssertTypesEqual(); - - return Action(new Impl(action_)); - } - - private: - template - class Impl : public ActionInterface { - public: - typedef typename internal::Function::Result Result; - typedef typename internal::Function::ArgumentTuple ArgumentTuple; - - explicit Impl(const A& action) : action_(action) {} - - virtual void Perform(const ArgumentTuple& args) { - // Performs the action and ignores its result. - action_.Perform(args); - } - - private: - // Type OriginalFunction is the same as F except that its return - // type is IgnoredValue. - typedef typename internal::Function::MakeResultIgnoredValue - OriginalFunction; - - const Action action_; - - GTEST_DISALLOW_ASSIGN_(Impl); - }; - - const A action_; - - GTEST_DISALLOW_ASSIGN_(IgnoreResultAction); -}; - -// A ReferenceWrapper object represents a reference to type T, -// which can be either const or not. It can be explicitly converted -// from, and implicitly converted to, a T&. Unlike a reference, -// ReferenceWrapper can be copied and can survive template type -// inference. This is used to support by-reference arguments in the -// InvokeArgument(...) action. The idea was from "reference -// wrappers" in tr1, which we don't have in our source tree yet. -template -class ReferenceWrapper { - public: - // Constructs a ReferenceWrapper object from a T&. - explicit ReferenceWrapper(T& l_value) : pointer_(&l_value) {} // NOLINT - - // Allows a ReferenceWrapper object to be implicitly converted to - // a T&. - operator T&() const { return *pointer_; } - private: - T* pointer_; -}; - -// Allows the expression ByRef(x) to be printed as a reference to x. -template -void PrintTo(const ReferenceWrapper& ref, ::std::ostream* os) { - T& value = ref; - UniversalPrinter::Print(value, os); -} - -// Does two actions sequentially. Used for implementing the DoAll(a1, -// a2, ...) action. -template -class DoBothAction { - public: - DoBothAction(Action1 action1, Action2 action2) - : action1_(action1), action2_(action2) {} - - // This template type conversion operator allows DoAll(a1, ..., a_n) - // to be used in ANY function of compatible type. - template - operator Action() const { - return Action(new Impl(action1_, action2_)); - } - - private: - // Implements the DoAll(...) action for a particular function type F. - template - class Impl : public ActionInterface { - public: - typedef typename Function::Result Result; - typedef typename Function::ArgumentTuple ArgumentTuple; - typedef typename Function::MakeResultVoid VoidResult; - - Impl(const Action& action1, const Action& action2) - : action1_(action1), action2_(action2) {} - - virtual Result Perform(const ArgumentTuple& args) { - action1_.Perform(args); - return action2_.Perform(args); - } - - private: - const Action action1_; - const Action action2_; - - GTEST_DISALLOW_ASSIGN_(Impl); - }; - - Action1 action1_; - Action2 action2_; - - GTEST_DISALLOW_ASSIGN_(DoBothAction); -}; - -} // namespace internal - -// An Unused object can be implicitly constructed from ANY value. -// This is handy when defining actions that ignore some or all of the -// mock function arguments. For example, given -// -// MOCK_METHOD3(Foo, double(const string& label, double x, double y)); -// MOCK_METHOD3(Bar, double(int index, double x, double y)); -// -// instead of -// -// double DistanceToOriginWithLabel(const string& label, double x, double y) { -// return sqrt(x*x + y*y); -// } -// double DistanceToOriginWithIndex(int index, double x, double y) { -// return sqrt(x*x + y*y); -// } -// ... -// EXEPCT_CALL(mock, Foo("abc", _, _)) -// .WillOnce(Invoke(DistanceToOriginWithLabel)); -// EXEPCT_CALL(mock, Bar(5, _, _)) -// .WillOnce(Invoke(DistanceToOriginWithIndex)); -// -// you could write -// -// // We can declare any uninteresting argument as Unused. -// double DistanceToOrigin(Unused, double x, double y) { -// return sqrt(x*x + y*y); -// } -// ... -// EXEPCT_CALL(mock, Foo("abc", _, _)).WillOnce(Invoke(DistanceToOrigin)); -// EXEPCT_CALL(mock, Bar(5, _, _)).WillOnce(Invoke(DistanceToOrigin)); -typedef internal::IgnoredValue Unused; - -// This constructor allows us to turn an Action object into an -// Action, as long as To's arguments can be implicitly converted -// to From's and From's return type cann be implicitly converted to -// To's. -template -template -Action::Action(const Action& from) - : impl_(new internal::ActionAdaptor(from)) {} - -// Creates an action that returns 'value'. 'value' is passed by value -// instead of const reference - otherwise Return("string literal") -// will trigger a compiler error about using array as initializer. -template -internal::ReturnAction Return(R value) { - return internal::ReturnAction(internal::move(value)); -} - -// Creates an action that returns NULL. -inline PolymorphicAction ReturnNull() { - return MakePolymorphicAction(internal::ReturnNullAction()); -} - -// Creates an action that returns from a void function. -inline PolymorphicAction Return() { - return MakePolymorphicAction(internal::ReturnVoidAction()); -} - -// Creates an action that returns the reference to a variable. -template -inline internal::ReturnRefAction ReturnRef(R& x) { // NOLINT - return internal::ReturnRefAction(x); -} - -// Creates an action that returns the reference to a copy of the -// argument. The copy is created when the action is constructed and -// lives as long as the action. -template -inline internal::ReturnRefOfCopyAction ReturnRefOfCopy(const R& x) { - return internal::ReturnRefOfCopyAction(x); -} - -// Modifies the parent action (a Return() action) to perform a move of the -// argument instead of a copy. -// Return(ByMove()) actions can only be executed once and will assert this -// invariant. -template -internal::ByMoveWrapper ByMove(R x) { - return internal::ByMoveWrapper(internal::move(x)); -} - -// Creates an action that does the default action for the give mock function. -inline internal::DoDefaultAction DoDefault() { - return internal::DoDefaultAction(); -} - -// Creates an action that sets the variable pointed by the N-th -// (0-based) function argument to 'value'. -template -PolymorphicAction< - internal::SetArgumentPointeeAction< - N, T, internal::IsAProtocolMessage::value> > -SetArgPointee(const T& x) { - return MakePolymorphicAction(internal::SetArgumentPointeeAction< - N, T, internal::IsAProtocolMessage::value>(x)); -} - -#if !((GTEST_GCC_VER_ && GTEST_GCC_VER_ < 40000) || GTEST_OS_SYMBIAN) -// This overload allows SetArgPointee() to accept a string literal. -// GCC prior to the version 4.0 and Symbian C++ compiler cannot distinguish -// this overload from the templated version and emit a compile error. -template -PolymorphicAction< - internal::SetArgumentPointeeAction > -SetArgPointee(const char* p) { - return MakePolymorphicAction(internal::SetArgumentPointeeAction< - N, const char*, false>(p)); -} - -template -PolymorphicAction< - internal::SetArgumentPointeeAction > -SetArgPointee(const wchar_t* p) { - return MakePolymorphicAction(internal::SetArgumentPointeeAction< - N, const wchar_t*, false>(p)); -} -#endif - -// The following version is DEPRECATED. -template -PolymorphicAction< - internal::SetArgumentPointeeAction< - N, T, internal::IsAProtocolMessage::value> > -SetArgumentPointee(const T& x) { - return MakePolymorphicAction(internal::SetArgumentPointeeAction< - N, T, internal::IsAProtocolMessage::value>(x)); -} - -// Creates an action that sets a pointer referent to a given value. -template -PolymorphicAction > Assign(T1* ptr, T2 val) { - return MakePolymorphicAction(internal::AssignAction(ptr, val)); -} - -#if !GTEST_OS_WINDOWS_MOBILE - -// Creates an action that sets errno and returns the appropriate error. -template -PolymorphicAction > -SetErrnoAndReturn(int errval, T result) { - return MakePolymorphicAction( - internal::SetErrnoAndReturnAction(errval, result)); -} - -#endif // !GTEST_OS_WINDOWS_MOBILE - -// Various overloads for InvokeWithoutArgs(). - -// Creates an action that invokes 'function_impl' with no argument. -template -PolymorphicAction > -InvokeWithoutArgs(FunctionImpl function_impl) { - return MakePolymorphicAction( - internal::InvokeWithoutArgsAction(function_impl)); -} - -// Creates an action that invokes the given method on the given object -// with no argument. -template -PolymorphicAction > -InvokeWithoutArgs(Class* obj_ptr, MethodPtr method_ptr) { - return MakePolymorphicAction( - internal::InvokeMethodWithoutArgsAction( - obj_ptr, method_ptr)); -} - -// Creates an action that performs an_action and throws away its -// result. In other words, it changes the return type of an_action to -// void. an_action MUST NOT return void, or the code won't compile. -template -inline internal::IgnoreResultAction IgnoreResult(const A& an_action) { - return internal::IgnoreResultAction(an_action); -} - -// Creates a reference wrapper for the given L-value. If necessary, -// you can explicitly specify the type of the reference. For example, -// suppose 'derived' is an object of type Derived, ByRef(derived) -// would wrap a Derived&. If you want to wrap a const Base& instead, -// where Base is a base class of Derived, just write: -// -// ByRef(derived) -template -inline internal::ReferenceWrapper ByRef(T& l_value) { // NOLINT - return internal::ReferenceWrapper(l_value); -} - -} // namespace testing - -#endif // GMOCK_INCLUDE_GMOCK_GMOCK_ACTIONS_H_ -// Copyright 2007, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Author: wan@google.com (Zhanyong Wan) - -// Google Mock - a framework for writing C++ mock classes. -// -// This file implements some commonly used cardinalities. More -// cardinalities can be defined by the user implementing the -// CardinalityInterface interface if necessary. - -#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_CARDINALITIES_H_ -#define GMOCK_INCLUDE_GMOCK_GMOCK_CARDINALITIES_H_ - -#include -#include // NOLINT - -namespace testing { - -// To implement a cardinality Foo, define: -// 1. a class FooCardinality that implements the -// CardinalityInterface interface, and -// 2. a factory function that creates a Cardinality object from a -// const FooCardinality*. -// -// The two-level delegation design follows that of Matcher, providing -// consistency for extension developers. It also eases ownership -// management as Cardinality objects can now be copied like plain values. - -// The implementation of a cardinality. -class CardinalityInterface { - public: - virtual ~CardinalityInterface() {} - - // Conservative estimate on the lower/upper bound of the number of - // calls allowed. - virtual int ConservativeLowerBound() const { return 0; } - virtual int ConservativeUpperBound() const { return INT_MAX; } - - // Returns true iff call_count calls will satisfy this cardinality. - virtual bool IsSatisfiedByCallCount(int call_count) const = 0; - - // Returns true iff call_count calls will saturate this cardinality. - virtual bool IsSaturatedByCallCount(int call_count) const = 0; - - // Describes self to an ostream. - virtual void DescribeTo(::std::ostream* os) const = 0; -}; - -// A Cardinality is a copyable and IMMUTABLE (except by assignment) -// object that specifies how many times a mock function is expected to -// be called. The implementation of Cardinality is just a linked_ptr -// to const CardinalityInterface, so copying is fairly cheap. -// Don't inherit from Cardinality! -class GTEST_API_ Cardinality { - public: - // Constructs a null cardinality. Needed for storing Cardinality - // objects in STL containers. - Cardinality() {} - - // Constructs a Cardinality from its implementation. - explicit Cardinality(const CardinalityInterface* impl) : impl_(impl) {} - - // Conservative estimate on the lower/upper bound of the number of - // calls allowed. - int ConservativeLowerBound() const { return impl_->ConservativeLowerBound(); } - int ConservativeUpperBound() const { return impl_->ConservativeUpperBound(); } - - // Returns true iff call_count calls will satisfy this cardinality. - bool IsSatisfiedByCallCount(int call_count) const { - return impl_->IsSatisfiedByCallCount(call_count); - } - - // Returns true iff call_count calls will saturate this cardinality. - bool IsSaturatedByCallCount(int call_count) const { - return impl_->IsSaturatedByCallCount(call_count); - } - - // Returns true iff call_count calls will over-saturate this - // cardinality, i.e. exceed the maximum number of allowed calls. - bool IsOverSaturatedByCallCount(int call_count) const { - return impl_->IsSaturatedByCallCount(call_count) && - !impl_->IsSatisfiedByCallCount(call_count); - } - - // Describes self to an ostream - void DescribeTo(::std::ostream* os) const { impl_->DescribeTo(os); } - - // Describes the given actual call count to an ostream. - static void DescribeActualCallCountTo(int actual_call_count, - ::std::ostream* os); - - private: - internal::linked_ptr impl_; -}; - -// Creates a cardinality that allows at least n calls. -GTEST_API_ Cardinality AtLeast(int n); - -// Creates a cardinality that allows at most n calls. -GTEST_API_ Cardinality AtMost(int n); - -// Creates a cardinality that allows any number of calls. -GTEST_API_ Cardinality AnyNumber(); - -// Creates a cardinality that allows between min and max calls. -GTEST_API_ Cardinality Between(int min, int max); - -// Creates a cardinality that allows exactly n calls. -GTEST_API_ Cardinality Exactly(int n); - -// Creates a cardinality from its implementation. -inline Cardinality MakeCardinality(const CardinalityInterface* c) { - return Cardinality(c); -} - -} // namespace testing - -#endif // GMOCK_INCLUDE_GMOCK_GMOCK_CARDINALITIES_H_ -// This file was GENERATED by a script. DO NOT EDIT BY HAND!!! - -// Copyright 2007, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Author: wan@google.com (Zhanyong Wan) - -// Google Mock - a framework for writing C++ mock classes. -// -// This file implements some commonly used variadic actions. - -#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_ACTIONS_H_ -#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_ACTIONS_H_ - - -namespace testing { -namespace internal { - -// InvokeHelper knows how to unpack an N-tuple and invoke an N-ary -// function or method with the unpacked values, where F is a function -// type that takes N arguments. -template -class InvokeHelper; - -template -class InvokeHelper > { - public: - template - static R Invoke(Function function, const ::testing::tuple<>&) { - return function(); - } - - template - static R InvokeMethod(Class* obj_ptr, - MethodPtr method_ptr, - const ::testing::tuple<>&) { - return (obj_ptr->*method_ptr)(); - } -}; - -template -class InvokeHelper > { - public: - template - static R Invoke(Function function, const ::testing::tuple& args) { - return function(get<0>(args)); - } - - template - static R InvokeMethod(Class* obj_ptr, - MethodPtr method_ptr, - const ::testing::tuple& args) { - return (obj_ptr->*method_ptr)(get<0>(args)); - } -}; - -template -class InvokeHelper > { - public: - template - static R Invoke(Function function, const ::testing::tuple& args) { - return function(get<0>(args), get<1>(args)); - } - - template - static R InvokeMethod(Class* obj_ptr, - MethodPtr method_ptr, - const ::testing::tuple& args) { - return (obj_ptr->*method_ptr)(get<0>(args), get<1>(args)); - } -}; - -template -class InvokeHelper > { - public: - template - static R Invoke(Function function, const ::testing::tuple& args) { - return function(get<0>(args), get<1>(args), get<2>(args)); - } - - template - static R InvokeMethod(Class* obj_ptr, - MethodPtr method_ptr, - const ::testing::tuple& args) { - return (obj_ptr->*method_ptr)(get<0>(args), get<1>(args), - get<2>(args)); - } -}; - -template -class InvokeHelper > { - public: - template - static R Invoke(Function function, const ::testing::tuple& args) { - return function(get<0>(args), get<1>(args), get<2>(args), - get<3>(args)); - } - - template - static R InvokeMethod(Class* obj_ptr, - MethodPtr method_ptr, - const ::testing::tuple& args) { - return (obj_ptr->*method_ptr)(get<0>(args), get<1>(args), - get<2>(args), get<3>(args)); - } -}; - -template -class InvokeHelper > { - public: - template - static R Invoke(Function function, const ::testing::tuple& args) { - return function(get<0>(args), get<1>(args), get<2>(args), - get<3>(args), get<4>(args)); - } - - template - static R InvokeMethod(Class* obj_ptr, - MethodPtr method_ptr, - const ::testing::tuple& args) { - return (obj_ptr->*method_ptr)(get<0>(args), get<1>(args), - get<2>(args), get<3>(args), get<4>(args)); - } -}; - -template -class InvokeHelper > { - public: - template - static R Invoke(Function function, const ::testing::tuple& args) { - return function(get<0>(args), get<1>(args), get<2>(args), - get<3>(args), get<4>(args), get<5>(args)); - } - - template - static R InvokeMethod(Class* obj_ptr, - MethodPtr method_ptr, - const ::testing::tuple& args) { - return (obj_ptr->*method_ptr)(get<0>(args), get<1>(args), - get<2>(args), get<3>(args), get<4>(args), get<5>(args)); - } -}; - -template -class InvokeHelper > { - public: - template - static R Invoke(Function function, const ::testing::tuple& args) { - return function(get<0>(args), get<1>(args), get<2>(args), - get<3>(args), get<4>(args), get<5>(args), get<6>(args)); - } - - template - static R InvokeMethod(Class* obj_ptr, - MethodPtr method_ptr, - const ::testing::tuple& args) { - return (obj_ptr->*method_ptr)(get<0>(args), get<1>(args), - get<2>(args), get<3>(args), get<4>(args), get<5>(args), - get<6>(args)); - } -}; - -template -class InvokeHelper > { - public: - template - static R Invoke(Function function, const ::testing::tuple& args) { - return function(get<0>(args), get<1>(args), get<2>(args), - get<3>(args), get<4>(args), get<5>(args), get<6>(args), - get<7>(args)); - } - - template - static R InvokeMethod(Class* obj_ptr, - MethodPtr method_ptr, - const ::testing::tuple& args) { - return (obj_ptr->*method_ptr)(get<0>(args), get<1>(args), - get<2>(args), get<3>(args), get<4>(args), get<5>(args), - get<6>(args), get<7>(args)); - } -}; - -template -class InvokeHelper > { - public: - template - static R Invoke(Function function, const ::testing::tuple& args) { - return function(get<0>(args), get<1>(args), get<2>(args), - get<3>(args), get<4>(args), get<5>(args), get<6>(args), - get<7>(args), get<8>(args)); - } - - template - static R InvokeMethod(Class* obj_ptr, - MethodPtr method_ptr, - const ::testing::tuple& args) { - return (obj_ptr->*method_ptr)(get<0>(args), get<1>(args), - get<2>(args), get<3>(args), get<4>(args), get<5>(args), - get<6>(args), get<7>(args), get<8>(args)); - } -}; - -template -class InvokeHelper > { - public: - template - static R Invoke(Function function, const ::testing::tuple& args) { - return function(get<0>(args), get<1>(args), get<2>(args), - get<3>(args), get<4>(args), get<5>(args), get<6>(args), - get<7>(args), get<8>(args), get<9>(args)); - } - - template - static R InvokeMethod(Class* obj_ptr, - MethodPtr method_ptr, - const ::testing::tuple& args) { - return (obj_ptr->*method_ptr)(get<0>(args), get<1>(args), - get<2>(args), get<3>(args), get<4>(args), get<5>(args), - get<6>(args), get<7>(args), get<8>(args), get<9>(args)); - } -}; - -// An INTERNAL macro for extracting the type of a tuple field. It's -// subject to change without notice - DO NOT USE IN USER CODE! -#define GMOCK_FIELD_(Tuple, N) \ - typename ::testing::tuple_element::type - -// SelectArgs::type is the -// type of an n-ary function whose i-th (1-based) argument type is the -// k{i}-th (0-based) field of ArgumentTuple, which must be a tuple -// type, and whose return type is Result. For example, -// SelectArgs, 0, 3>::type -// is int(bool, long). -// -// SelectArgs::Select(args) -// returns the selected fields (k1, k2, ..., k_n) of args as a tuple. -// For example, -// SelectArgs, 2, 0>::Select( -// ::testing::make_tuple(true, 'a', 2.5)) -// returns tuple (2.5, true). -// -// The numbers in list k1, k2, ..., k_n must be >= 0, where n can be -// in the range [0, 10]. Duplicates are allowed and they don't have -// to be in an ascending or descending order. - -template -class SelectArgs { - public: - typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1), - GMOCK_FIELD_(ArgumentTuple, k2), GMOCK_FIELD_(ArgumentTuple, k3), - GMOCK_FIELD_(ArgumentTuple, k4), GMOCK_FIELD_(ArgumentTuple, k5), - GMOCK_FIELD_(ArgumentTuple, k6), GMOCK_FIELD_(ArgumentTuple, k7), - GMOCK_FIELD_(ArgumentTuple, k8), GMOCK_FIELD_(ArgumentTuple, k9), - GMOCK_FIELD_(ArgumentTuple, k10)); - typedef typename Function::ArgumentTuple SelectedArgs; - static SelectedArgs Select(const ArgumentTuple& args) { - return SelectedArgs(get(args), get(args), get(args), - get(args), get(args), get(args), get(args), - get(args), get(args), get(args)); - } -}; - -template -class SelectArgs { - public: - typedef Result type(); - typedef typename Function::ArgumentTuple SelectedArgs; - static SelectedArgs Select(const ArgumentTuple& /* args */) { - return SelectedArgs(); - } -}; - -template -class SelectArgs { - public: - typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1)); - typedef typename Function::ArgumentTuple SelectedArgs; - static SelectedArgs Select(const ArgumentTuple& args) { - return SelectedArgs(get(args)); - } -}; - -template -class SelectArgs { - public: - typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1), - GMOCK_FIELD_(ArgumentTuple, k2)); - typedef typename Function::ArgumentTuple SelectedArgs; - static SelectedArgs Select(const ArgumentTuple& args) { - return SelectedArgs(get(args), get(args)); - } -}; - -template -class SelectArgs { - public: - typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1), - GMOCK_FIELD_(ArgumentTuple, k2), GMOCK_FIELD_(ArgumentTuple, k3)); - typedef typename Function::ArgumentTuple SelectedArgs; - static SelectedArgs Select(const ArgumentTuple& args) { - return SelectedArgs(get(args), get(args), get(args)); - } -}; - -template -class SelectArgs { - public: - typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1), - GMOCK_FIELD_(ArgumentTuple, k2), GMOCK_FIELD_(ArgumentTuple, k3), - GMOCK_FIELD_(ArgumentTuple, k4)); - typedef typename Function::ArgumentTuple SelectedArgs; - static SelectedArgs Select(const ArgumentTuple& args) { - return SelectedArgs(get(args), get(args), get(args), - get(args)); - } -}; - -template -class SelectArgs { - public: - typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1), - GMOCK_FIELD_(ArgumentTuple, k2), GMOCK_FIELD_(ArgumentTuple, k3), - GMOCK_FIELD_(ArgumentTuple, k4), GMOCK_FIELD_(ArgumentTuple, k5)); - typedef typename Function::ArgumentTuple SelectedArgs; - static SelectedArgs Select(const ArgumentTuple& args) { - return SelectedArgs(get(args), get(args), get(args), - get(args), get(args)); - } -}; - -template -class SelectArgs { - public: - typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1), - GMOCK_FIELD_(ArgumentTuple, k2), GMOCK_FIELD_(ArgumentTuple, k3), - GMOCK_FIELD_(ArgumentTuple, k4), GMOCK_FIELD_(ArgumentTuple, k5), - GMOCK_FIELD_(ArgumentTuple, k6)); - typedef typename Function::ArgumentTuple SelectedArgs; - static SelectedArgs Select(const ArgumentTuple& args) { - return SelectedArgs(get(args), get(args), get(args), - get(args), get(args), get(args)); - } -}; - -template -class SelectArgs { - public: - typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1), - GMOCK_FIELD_(ArgumentTuple, k2), GMOCK_FIELD_(ArgumentTuple, k3), - GMOCK_FIELD_(ArgumentTuple, k4), GMOCK_FIELD_(ArgumentTuple, k5), - GMOCK_FIELD_(ArgumentTuple, k6), GMOCK_FIELD_(ArgumentTuple, k7)); - typedef typename Function::ArgumentTuple SelectedArgs; - static SelectedArgs Select(const ArgumentTuple& args) { - return SelectedArgs(get(args), get(args), get(args), - get(args), get(args), get(args), get(args)); - } -}; - -template -class SelectArgs { - public: - typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1), - GMOCK_FIELD_(ArgumentTuple, k2), GMOCK_FIELD_(ArgumentTuple, k3), - GMOCK_FIELD_(ArgumentTuple, k4), GMOCK_FIELD_(ArgumentTuple, k5), - GMOCK_FIELD_(ArgumentTuple, k6), GMOCK_FIELD_(ArgumentTuple, k7), - GMOCK_FIELD_(ArgumentTuple, k8)); - typedef typename Function::ArgumentTuple SelectedArgs; - static SelectedArgs Select(const ArgumentTuple& args) { - return SelectedArgs(get(args), get(args), get(args), - get(args), get(args), get(args), get(args), - get(args)); - } -}; - -template -class SelectArgs { - public: - typedef Result type(GMOCK_FIELD_(ArgumentTuple, k1), - GMOCK_FIELD_(ArgumentTuple, k2), GMOCK_FIELD_(ArgumentTuple, k3), - GMOCK_FIELD_(ArgumentTuple, k4), GMOCK_FIELD_(ArgumentTuple, k5), - GMOCK_FIELD_(ArgumentTuple, k6), GMOCK_FIELD_(ArgumentTuple, k7), - GMOCK_FIELD_(ArgumentTuple, k8), GMOCK_FIELD_(ArgumentTuple, k9)); - typedef typename Function::ArgumentTuple SelectedArgs; - static SelectedArgs Select(const ArgumentTuple& args) { - return SelectedArgs(get(args), get(args), get(args), - get(args), get(args), get(args), get(args), - get(args), get(args)); - } -}; - -#undef GMOCK_FIELD_ - -// Implements the WithArgs action. -template -class WithArgsAction { - public: - explicit WithArgsAction(const InnerAction& action) : action_(action) {} - - template - operator Action() const { return MakeAction(new Impl(action_)); } - - private: - template - class Impl : public ActionInterface { - public: - typedef typename Function::Result Result; - typedef typename Function::ArgumentTuple ArgumentTuple; - - explicit Impl(const InnerAction& action) : action_(action) {} - - virtual Result Perform(const ArgumentTuple& args) { - return action_.Perform(SelectArgs::Select(args)); - } - - private: - typedef typename SelectArgs::type InnerFunctionType; - - Action action_; - }; - - const InnerAction action_; - - GTEST_DISALLOW_ASSIGN_(WithArgsAction); -}; - -// A macro from the ACTION* family (defined later in this file) -// defines an action that can be used in a mock function. Typically, -// these actions only care about a subset of the arguments of the mock -// function. For example, if such an action only uses the second -// argument, it can be used in any mock function that takes >= 2 -// arguments where the type of the second argument is compatible. -// -// Therefore, the action implementation must be prepared to take more -// arguments than it needs. The ExcessiveArg type is used to -// represent those excessive arguments. In order to keep the compiler -// error messages tractable, we define it in the testing namespace -// instead of testing::internal. However, this is an INTERNAL TYPE -// and subject to change without notice, so a user MUST NOT USE THIS -// TYPE DIRECTLY. -struct ExcessiveArg {}; - -// A helper class needed for implementing the ACTION* macros. -template -class ActionHelper { - public: - static Result Perform(Impl* impl, const ::testing::tuple<>& args) { - return impl->template gmock_PerformImpl<>(args, ExcessiveArg(), - ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), - ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), - ExcessiveArg()); - } - - template - static Result Perform(Impl* impl, const ::testing::tuple& args) { - return impl->template gmock_PerformImpl(args, get<0>(args), - ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), - ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), - ExcessiveArg()); - } - - template - static Result Perform(Impl* impl, const ::testing::tuple& args) { - return impl->template gmock_PerformImpl(args, get<0>(args), - get<1>(args), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), - ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), - ExcessiveArg()); - } - - template - static Result Perform(Impl* impl, const ::testing::tuple& args) { - return impl->template gmock_PerformImpl(args, get<0>(args), - get<1>(args), get<2>(args), ExcessiveArg(), ExcessiveArg(), - ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), - ExcessiveArg()); - } - - template - static Result Perform(Impl* impl, const ::testing::tuple& args) { - return impl->template gmock_PerformImpl(args, get<0>(args), - get<1>(args), get<2>(args), get<3>(args), ExcessiveArg(), - ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), - ExcessiveArg()); - } - - template - static Result Perform(Impl* impl, const ::testing::tuple& args) { - return impl->template gmock_PerformImpl(args, - get<0>(args), get<1>(args), get<2>(args), get<3>(args), get<4>(args), - ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), - ExcessiveArg()); - } - - template - static Result Perform(Impl* impl, const ::testing::tuple& args) { - return impl->template gmock_PerformImpl(args, - get<0>(args), get<1>(args), get<2>(args), get<3>(args), get<4>(args), - get<5>(args), ExcessiveArg(), ExcessiveArg(), ExcessiveArg(), - ExcessiveArg()); - } - - template - static Result Perform(Impl* impl, const ::testing::tuple& args) { - return impl->template gmock_PerformImpl(args, - get<0>(args), get<1>(args), get<2>(args), get<3>(args), get<4>(args), - get<5>(args), get<6>(args), ExcessiveArg(), ExcessiveArg(), - ExcessiveArg()); - } - - template - static Result Perform(Impl* impl, const ::testing::tuple& args) { - return impl->template gmock_PerformImpl(args, get<0>(args), get<1>(args), get<2>(args), get<3>(args), - get<4>(args), get<5>(args), get<6>(args), get<7>(args), ExcessiveArg(), - ExcessiveArg()); - } - - template - static Result Perform(Impl* impl, const ::testing::tuple& args) { - return impl->template gmock_PerformImpl(args, get<0>(args), get<1>(args), get<2>(args), get<3>(args), - get<4>(args), get<5>(args), get<6>(args), get<7>(args), get<8>(args), - ExcessiveArg()); - } - - template - static Result Perform(Impl* impl, const ::testing::tuple& args) { - return impl->template gmock_PerformImpl(args, get<0>(args), get<1>(args), get<2>(args), get<3>(args), - get<4>(args), get<5>(args), get<6>(args), get<7>(args), get<8>(args), - get<9>(args)); - } -}; - -} // namespace internal - -// Various overloads for Invoke(). - -// WithArgs(an_action) creates an action that passes -// the selected arguments of the mock function to an_action and -// performs it. It serves as an adaptor between actions with -// different argument lists. C++ doesn't support default arguments for -// function templates, so we have to overload it. -template -inline internal::WithArgsAction -WithArgs(const InnerAction& action) { - return internal::WithArgsAction(action); -} - -template -inline internal::WithArgsAction -WithArgs(const InnerAction& action) { - return internal::WithArgsAction(action); -} - -template -inline internal::WithArgsAction -WithArgs(const InnerAction& action) { - return internal::WithArgsAction(action); -} - -template -inline internal::WithArgsAction -WithArgs(const InnerAction& action) { - return internal::WithArgsAction(action); -} - -template -inline internal::WithArgsAction -WithArgs(const InnerAction& action) { - return internal::WithArgsAction(action); -} - -template -inline internal::WithArgsAction -WithArgs(const InnerAction& action) { - return internal::WithArgsAction(action); -} - -template -inline internal::WithArgsAction -WithArgs(const InnerAction& action) { - return internal::WithArgsAction(action); -} - -template -inline internal::WithArgsAction -WithArgs(const InnerAction& action) { - return internal::WithArgsAction(action); -} - -template -inline internal::WithArgsAction -WithArgs(const InnerAction& action) { - return internal::WithArgsAction(action); -} - -template -inline internal::WithArgsAction -WithArgs(const InnerAction& action) { - return internal::WithArgsAction(action); -} - -// Creates an action that does actions a1, a2, ..., sequentially in -// each invocation. -template -inline internal::DoBothAction -DoAll(Action1 a1, Action2 a2) { - return internal::DoBothAction(a1, a2); -} - -template -inline internal::DoBothAction > -DoAll(Action1 a1, Action2 a2, Action3 a3) { - return DoAll(a1, DoAll(a2, a3)); -} - -template -inline internal::DoBothAction > > -DoAll(Action1 a1, Action2 a2, Action3 a3, Action4 a4) { - return DoAll(a1, DoAll(a2, a3, a4)); -} - -template -inline internal::DoBothAction > > > -DoAll(Action1 a1, Action2 a2, Action3 a3, Action4 a4, Action5 a5) { - return DoAll(a1, DoAll(a2, a3, a4, a5)); -} - -template -inline internal::DoBothAction > > > > -DoAll(Action1 a1, Action2 a2, Action3 a3, Action4 a4, Action5 a5, Action6 a6) { - return DoAll(a1, DoAll(a2, a3, a4, a5, a6)); -} - -template -inline internal::DoBothAction > > > > > -DoAll(Action1 a1, Action2 a2, Action3 a3, Action4 a4, Action5 a5, Action6 a6, - Action7 a7) { - return DoAll(a1, DoAll(a2, a3, a4, a5, a6, a7)); -} - -template -inline internal::DoBothAction > > > > > > -DoAll(Action1 a1, Action2 a2, Action3 a3, Action4 a4, Action5 a5, Action6 a6, - Action7 a7, Action8 a8) { - return DoAll(a1, DoAll(a2, a3, a4, a5, a6, a7, a8)); -} - -template -inline internal::DoBothAction > > > > > > > -DoAll(Action1 a1, Action2 a2, Action3 a3, Action4 a4, Action5 a5, Action6 a6, - Action7 a7, Action8 a8, Action9 a9) { - return DoAll(a1, DoAll(a2, a3, a4, a5, a6, a7, a8, a9)); -} - -template -inline internal::DoBothAction > > > > > > > > -DoAll(Action1 a1, Action2 a2, Action3 a3, Action4 a4, Action5 a5, Action6 a6, - Action7 a7, Action8 a8, Action9 a9, Action10 a10) { - return DoAll(a1, DoAll(a2, a3, a4, a5, a6, a7, a8, a9, a10)); -} - -} // namespace testing - -// The ACTION* family of macros can be used in a namespace scope to -// define custom actions easily. The syntax: -// -// ACTION(name) { statements; } -// -// will define an action with the given name that executes the -// statements. The value returned by the statements will be used as -// the return value of the action. Inside the statements, you can -// refer to the K-th (0-based) argument of the mock function by -// 'argK', and refer to its type by 'argK_type'. For example: -// -// ACTION(IncrementArg1) { -// arg1_type temp = arg1; -// return ++(*temp); -// } -// -// allows you to write -// -// ...WillOnce(IncrementArg1()); -// -// You can also refer to the entire argument tuple and its type by -// 'args' and 'args_type', and refer to the mock function type and its -// return type by 'function_type' and 'return_type'. -// -// Note that you don't need to specify the types of the mock function -// arguments. However rest assured that your code is still type-safe: -// you'll get a compiler error if *arg1 doesn't support the ++ -// operator, or if the type of ++(*arg1) isn't compatible with the -// mock function's return type, for example. -// -// Sometimes you'll want to parameterize the action. For that you can use -// another macro: -// -// ACTION_P(name, param_name) { statements; } -// -// For example: -// -// ACTION_P(Add, n) { return arg0 + n; } -// -// will allow you to write: -// -// ...WillOnce(Add(5)); -// -// Note that you don't need to provide the type of the parameter -// either. If you need to reference the type of a parameter named -// 'foo', you can write 'foo_type'. For example, in the body of -// ACTION_P(Add, n) above, you can write 'n_type' to refer to the type -// of 'n'. -// -// We also provide ACTION_P2, ACTION_P3, ..., up to ACTION_P10 to support -// multi-parameter actions. -// -// For the purpose of typing, you can view -// -// ACTION_Pk(Foo, p1, ..., pk) { ... } -// -// as shorthand for -// -// template -// FooActionPk Foo(p1_type p1, ..., pk_type pk) { ... } -// -// In particular, you can provide the template type arguments -// explicitly when invoking Foo(), as in Foo(5, false); -// although usually you can rely on the compiler to infer the types -// for you automatically. You can assign the result of expression -// Foo(p1, ..., pk) to a variable of type FooActionPk. This can be useful when composing actions. -// -// You can also overload actions with different numbers of parameters: -// -// ACTION_P(Plus, a) { ... } -// ACTION_P2(Plus, a, b) { ... } -// -// While it's tempting to always use the ACTION* macros when defining -// a new action, you should also consider implementing ActionInterface -// or using MakePolymorphicAction() instead, especially if you need to -// use the action a lot. While these approaches require more work, -// they give you more control on the types of the mock function -// arguments and the action parameters, which in general leads to -// better compiler error messages that pay off in the long run. They -// also allow overloading actions based on parameter types (as opposed -// to just based on the number of parameters). -// -// CAVEAT: -// -// ACTION*() can only be used in a namespace scope. The reason is -// that C++ doesn't yet allow function-local types to be used to -// instantiate templates. The up-coming C++0x standard will fix this. -// Once that's done, we'll consider supporting using ACTION*() inside -// a function. -// -// MORE INFORMATION: -// -// To learn more about using these macros, please search for 'ACTION' -// on http://code.google.com/p/googlemock/wiki/CookBook. - -// An internal macro needed for implementing ACTION*(). -#define GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_\ - const args_type& args GTEST_ATTRIBUTE_UNUSED_, \ - arg0_type arg0 GTEST_ATTRIBUTE_UNUSED_, \ - arg1_type arg1 GTEST_ATTRIBUTE_UNUSED_, \ - arg2_type arg2 GTEST_ATTRIBUTE_UNUSED_, \ - arg3_type arg3 GTEST_ATTRIBUTE_UNUSED_, \ - arg4_type arg4 GTEST_ATTRIBUTE_UNUSED_, \ - arg5_type arg5 GTEST_ATTRIBUTE_UNUSED_, \ - arg6_type arg6 GTEST_ATTRIBUTE_UNUSED_, \ - arg7_type arg7 GTEST_ATTRIBUTE_UNUSED_, \ - arg8_type arg8 GTEST_ATTRIBUTE_UNUSED_, \ - arg9_type arg9 GTEST_ATTRIBUTE_UNUSED_ - -// Sometimes you want to give an action explicit template parameters -// that cannot be inferred from its value parameters. ACTION() and -// ACTION_P*() don't support that. ACTION_TEMPLATE() remedies that -// and can be viewed as an extension to ACTION() and ACTION_P*(). -// -// The syntax: -// -// ACTION_TEMPLATE(ActionName, -// HAS_m_TEMPLATE_PARAMS(kind1, name1, ..., kind_m, name_m), -// AND_n_VALUE_PARAMS(p1, ..., p_n)) { statements; } -// -// defines an action template that takes m explicit template -// parameters and n value parameters. name_i is the name of the i-th -// template parameter, and kind_i specifies whether it's a typename, -// an integral constant, or a template. p_i is the name of the i-th -// value parameter. -// -// Example: -// -// // DuplicateArg(output) converts the k-th argument of the mock -// // function to type T and copies it to *output. -// ACTION_TEMPLATE(DuplicateArg, -// HAS_2_TEMPLATE_PARAMS(int, k, typename, T), -// AND_1_VALUE_PARAMS(output)) { -// *output = T(::testing::get(args)); -// } -// ... -// int n; -// EXPECT_CALL(mock, Foo(_, _)) -// .WillOnce(DuplicateArg<1, unsigned char>(&n)); -// -// To create an instance of an action template, write: -// -// ActionName(v1, ..., v_n) -// -// where the ts are the template arguments and the vs are the value -// arguments. The value argument types are inferred by the compiler. -// If you want to explicitly specify the value argument types, you can -// provide additional template arguments: -// -// ActionName(v1, ..., v_n) -// -// where u_i is the desired type of v_i. -// -// ACTION_TEMPLATE and ACTION/ACTION_P* can be overloaded on the -// number of value parameters, but not on the number of template -// parameters. Without the restriction, the meaning of the following -// is unclear: -// -// OverloadedAction(x); -// -// Are we using a single-template-parameter action where 'bool' refers -// to the type of x, or are we using a two-template-parameter action -// where the compiler is asked to infer the type of x? -// -// Implementation notes: -// -// GMOCK_INTERNAL_*_HAS_m_TEMPLATE_PARAMS and -// GMOCK_INTERNAL_*_AND_n_VALUE_PARAMS are internal macros for -// implementing ACTION_TEMPLATE. The main trick we use is to create -// new macro invocations when expanding a macro. For example, we have -// -// #define ACTION_TEMPLATE(name, template_params, value_params) -// ... GMOCK_INTERNAL_DECL_##template_params ... -// -// which causes ACTION_TEMPLATE(..., HAS_1_TEMPLATE_PARAMS(typename, T), ...) -// to expand to -// -// ... GMOCK_INTERNAL_DECL_HAS_1_TEMPLATE_PARAMS(typename, T) ... -// -// Since GMOCK_INTERNAL_DECL_HAS_1_TEMPLATE_PARAMS is a macro, the -// preprocessor will continue to expand it to -// -// ... typename T ... -// -// This technique conforms to the C++ standard and is portable. It -// allows us to implement action templates using O(N) code, where N is -// the maximum number of template/value parameters supported. Without -// using it, we'd have to devote O(N^2) amount of code to implement all -// combinations of m and n. - -// Declares the template parameters. -#define GMOCK_INTERNAL_DECL_HAS_1_TEMPLATE_PARAMS(kind0, name0) kind0 name0 -#define GMOCK_INTERNAL_DECL_HAS_2_TEMPLATE_PARAMS(kind0, name0, kind1, \ - name1) kind0 name0, kind1 name1 -#define GMOCK_INTERNAL_DECL_HAS_3_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \ - kind2, name2) kind0 name0, kind1 name1, kind2 name2 -#define GMOCK_INTERNAL_DECL_HAS_4_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \ - kind2, name2, kind3, name3) kind0 name0, kind1 name1, kind2 name2, \ - kind3 name3 -#define GMOCK_INTERNAL_DECL_HAS_5_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \ - kind2, name2, kind3, name3, kind4, name4) kind0 name0, kind1 name1, \ - kind2 name2, kind3 name3, kind4 name4 -#define GMOCK_INTERNAL_DECL_HAS_6_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \ - kind2, name2, kind3, name3, kind4, name4, kind5, name5) kind0 name0, \ - kind1 name1, kind2 name2, kind3 name3, kind4 name4, kind5 name5 -#define GMOCK_INTERNAL_DECL_HAS_7_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \ - kind2, name2, kind3, name3, kind4, name4, kind5, name5, kind6, \ - name6) kind0 name0, kind1 name1, kind2 name2, kind3 name3, kind4 name4, \ - kind5 name5, kind6 name6 -#define GMOCK_INTERNAL_DECL_HAS_8_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \ - kind2, name2, kind3, name3, kind4, name4, kind5, name5, kind6, name6, \ - kind7, name7) kind0 name0, kind1 name1, kind2 name2, kind3 name3, \ - kind4 name4, kind5 name5, kind6 name6, kind7 name7 -#define GMOCK_INTERNAL_DECL_HAS_9_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \ - kind2, name2, kind3, name3, kind4, name4, kind5, name5, kind6, name6, \ - kind7, name7, kind8, name8) kind0 name0, kind1 name1, kind2 name2, \ - kind3 name3, kind4 name4, kind5 name5, kind6 name6, kind7 name7, \ - kind8 name8 -#define GMOCK_INTERNAL_DECL_HAS_10_TEMPLATE_PARAMS(kind0, name0, kind1, \ - name1, kind2, name2, kind3, name3, kind4, name4, kind5, name5, kind6, \ - name6, kind7, name7, kind8, name8, kind9, name9) kind0 name0, \ - kind1 name1, kind2 name2, kind3 name3, kind4 name4, kind5 name5, \ - kind6 name6, kind7 name7, kind8 name8, kind9 name9 - -// Lists the template parameters. -#define GMOCK_INTERNAL_LIST_HAS_1_TEMPLATE_PARAMS(kind0, name0) name0 -#define GMOCK_INTERNAL_LIST_HAS_2_TEMPLATE_PARAMS(kind0, name0, kind1, \ - name1) name0, name1 -#define GMOCK_INTERNAL_LIST_HAS_3_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \ - kind2, name2) name0, name1, name2 -#define GMOCK_INTERNAL_LIST_HAS_4_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \ - kind2, name2, kind3, name3) name0, name1, name2, name3 -#define GMOCK_INTERNAL_LIST_HAS_5_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \ - kind2, name2, kind3, name3, kind4, name4) name0, name1, name2, name3, \ - name4 -#define GMOCK_INTERNAL_LIST_HAS_6_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \ - kind2, name2, kind3, name3, kind4, name4, kind5, name5) name0, name1, \ - name2, name3, name4, name5 -#define GMOCK_INTERNAL_LIST_HAS_7_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \ - kind2, name2, kind3, name3, kind4, name4, kind5, name5, kind6, \ - name6) name0, name1, name2, name3, name4, name5, name6 -#define GMOCK_INTERNAL_LIST_HAS_8_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \ - kind2, name2, kind3, name3, kind4, name4, kind5, name5, kind6, name6, \ - kind7, name7) name0, name1, name2, name3, name4, name5, name6, name7 -#define GMOCK_INTERNAL_LIST_HAS_9_TEMPLATE_PARAMS(kind0, name0, kind1, name1, \ - kind2, name2, kind3, name3, kind4, name4, kind5, name5, kind6, name6, \ - kind7, name7, kind8, name8) name0, name1, name2, name3, name4, name5, \ - name6, name7, name8 -#define GMOCK_INTERNAL_LIST_HAS_10_TEMPLATE_PARAMS(kind0, name0, kind1, \ - name1, kind2, name2, kind3, name3, kind4, name4, kind5, name5, kind6, \ - name6, kind7, name7, kind8, name8, kind9, name9) name0, name1, name2, \ - name3, name4, name5, name6, name7, name8, name9 - -// Declares the types of value parameters. -#define GMOCK_INTERNAL_DECL_TYPE_AND_0_VALUE_PARAMS() -#define GMOCK_INTERNAL_DECL_TYPE_AND_1_VALUE_PARAMS(p0) , typename p0##_type -#define GMOCK_INTERNAL_DECL_TYPE_AND_2_VALUE_PARAMS(p0, p1) , \ - typename p0##_type, typename p1##_type -#define GMOCK_INTERNAL_DECL_TYPE_AND_3_VALUE_PARAMS(p0, p1, p2) , \ - typename p0##_type, typename p1##_type, typename p2##_type -#define GMOCK_INTERNAL_DECL_TYPE_AND_4_VALUE_PARAMS(p0, p1, p2, p3) , \ - typename p0##_type, typename p1##_type, typename p2##_type, \ - typename p3##_type -#define GMOCK_INTERNAL_DECL_TYPE_AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4) , \ - typename p0##_type, typename p1##_type, typename p2##_type, \ - typename p3##_type, typename p4##_type -#define GMOCK_INTERNAL_DECL_TYPE_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5) , \ - typename p0##_type, typename p1##_type, typename p2##_type, \ - typename p3##_type, typename p4##_type, typename p5##_type -#define GMOCK_INTERNAL_DECL_TYPE_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \ - p6) , typename p0##_type, typename p1##_type, typename p2##_type, \ - typename p3##_type, typename p4##_type, typename p5##_type, \ - typename p6##_type -#define GMOCK_INTERNAL_DECL_TYPE_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \ - p6, p7) , typename p0##_type, typename p1##_type, typename p2##_type, \ - typename p3##_type, typename p4##_type, typename p5##_type, \ - typename p6##_type, typename p7##_type -#define GMOCK_INTERNAL_DECL_TYPE_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \ - p6, p7, p8) , typename p0##_type, typename p1##_type, typename p2##_type, \ - typename p3##_type, typename p4##_type, typename p5##_type, \ - typename p6##_type, typename p7##_type, typename p8##_type -#define GMOCK_INTERNAL_DECL_TYPE_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \ - p6, p7, p8, p9) , typename p0##_type, typename p1##_type, \ - typename p2##_type, typename p3##_type, typename p4##_type, \ - typename p5##_type, typename p6##_type, typename p7##_type, \ - typename p8##_type, typename p9##_type - -// Initializes the value parameters. -#define GMOCK_INTERNAL_INIT_AND_0_VALUE_PARAMS()\ - () -#define GMOCK_INTERNAL_INIT_AND_1_VALUE_PARAMS(p0)\ - (p0##_type gmock_p0) : p0(gmock_p0) -#define GMOCK_INTERNAL_INIT_AND_2_VALUE_PARAMS(p0, p1)\ - (p0##_type gmock_p0, p1##_type gmock_p1) : p0(gmock_p0), p1(gmock_p1) -#define GMOCK_INTERNAL_INIT_AND_3_VALUE_PARAMS(p0, p1, p2)\ - (p0##_type gmock_p0, p1##_type gmock_p1, \ - p2##_type gmock_p2) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2) -#define GMOCK_INTERNAL_INIT_AND_4_VALUE_PARAMS(p0, p1, p2, p3)\ - (p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ - p3##_type gmock_p3) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \ - p3(gmock_p3) -#define GMOCK_INTERNAL_INIT_AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4)\ - (p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ - p3##_type gmock_p3, p4##_type gmock_p4) : p0(gmock_p0), p1(gmock_p1), \ - p2(gmock_p2), p3(gmock_p3), p4(gmock_p4) -#define GMOCK_INTERNAL_INIT_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5)\ - (p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ - p3##_type gmock_p3, p4##_type gmock_p4, \ - p5##_type gmock_p5) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \ - p3(gmock_p3), p4(gmock_p4), p5(gmock_p5) -#define GMOCK_INTERNAL_INIT_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6)\ - (p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ - p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \ - p6##_type gmock_p6) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \ - p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6) -#define GMOCK_INTERNAL_INIT_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7)\ - (p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ - p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \ - p6##_type gmock_p6, p7##_type gmock_p7) : p0(gmock_p0), p1(gmock_p1), \ - p2(gmock_p2), p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), \ - p7(gmock_p7) -#define GMOCK_INTERNAL_INIT_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \ - p7, p8)\ - (p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ - p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \ - p6##_type gmock_p6, p7##_type gmock_p7, \ - p8##_type gmock_p8) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \ - p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), p7(gmock_p7), \ - p8(gmock_p8) -#define GMOCK_INTERNAL_INIT_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \ - p7, p8, p9)\ - (p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ - p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \ - p6##_type gmock_p6, p7##_type gmock_p7, p8##_type gmock_p8, \ - p9##_type gmock_p9) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \ - p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), p7(gmock_p7), \ - p8(gmock_p8), p9(gmock_p9) - -// Declares the fields for storing the value parameters. -#define GMOCK_INTERNAL_DEFN_AND_0_VALUE_PARAMS() -#define GMOCK_INTERNAL_DEFN_AND_1_VALUE_PARAMS(p0) p0##_type p0; -#define GMOCK_INTERNAL_DEFN_AND_2_VALUE_PARAMS(p0, p1) p0##_type p0; \ - p1##_type p1; -#define GMOCK_INTERNAL_DEFN_AND_3_VALUE_PARAMS(p0, p1, p2) p0##_type p0; \ - p1##_type p1; p2##_type p2; -#define GMOCK_INTERNAL_DEFN_AND_4_VALUE_PARAMS(p0, p1, p2, p3) p0##_type p0; \ - p1##_type p1; p2##_type p2; p3##_type p3; -#define GMOCK_INTERNAL_DEFN_AND_5_VALUE_PARAMS(p0, p1, p2, p3, \ - p4) p0##_type p0; p1##_type p1; p2##_type p2; p3##_type p3; p4##_type p4; -#define GMOCK_INTERNAL_DEFN_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, \ - p5) p0##_type p0; p1##_type p1; p2##_type p2; p3##_type p3; p4##_type p4; \ - p5##_type p5; -#define GMOCK_INTERNAL_DEFN_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \ - p6) p0##_type p0; p1##_type p1; p2##_type p2; p3##_type p3; p4##_type p4; \ - p5##_type p5; p6##_type p6; -#define GMOCK_INTERNAL_DEFN_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \ - p7) p0##_type p0; p1##_type p1; p2##_type p2; p3##_type p3; p4##_type p4; \ - p5##_type p5; p6##_type p6; p7##_type p7; -#define GMOCK_INTERNAL_DEFN_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \ - p7, p8) p0##_type p0; p1##_type p1; p2##_type p2; p3##_type p3; \ - p4##_type p4; p5##_type p5; p6##_type p6; p7##_type p7; p8##_type p8; -#define GMOCK_INTERNAL_DEFN_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \ - p7, p8, p9) p0##_type p0; p1##_type p1; p2##_type p2; p3##_type p3; \ - p4##_type p4; p5##_type p5; p6##_type p6; p7##_type p7; p8##_type p8; \ - p9##_type p9; - -// Lists the value parameters. -#define GMOCK_INTERNAL_LIST_AND_0_VALUE_PARAMS() -#define GMOCK_INTERNAL_LIST_AND_1_VALUE_PARAMS(p0) p0 -#define GMOCK_INTERNAL_LIST_AND_2_VALUE_PARAMS(p0, p1) p0, p1 -#define GMOCK_INTERNAL_LIST_AND_3_VALUE_PARAMS(p0, p1, p2) p0, p1, p2 -#define GMOCK_INTERNAL_LIST_AND_4_VALUE_PARAMS(p0, p1, p2, p3) p0, p1, p2, p3 -#define GMOCK_INTERNAL_LIST_AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4) p0, p1, \ - p2, p3, p4 -#define GMOCK_INTERNAL_LIST_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5) p0, \ - p1, p2, p3, p4, p5 -#define GMOCK_INTERNAL_LIST_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \ - p6) p0, p1, p2, p3, p4, p5, p6 -#define GMOCK_INTERNAL_LIST_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \ - p7) p0, p1, p2, p3, p4, p5, p6, p7 -#define GMOCK_INTERNAL_LIST_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \ - p7, p8) p0, p1, p2, p3, p4, p5, p6, p7, p8 -#define GMOCK_INTERNAL_LIST_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \ - p7, p8, p9) p0, p1, p2, p3, p4, p5, p6, p7, p8, p9 - -// Lists the value parameter types. -#define GMOCK_INTERNAL_LIST_TYPE_AND_0_VALUE_PARAMS() -#define GMOCK_INTERNAL_LIST_TYPE_AND_1_VALUE_PARAMS(p0) , p0##_type -#define GMOCK_INTERNAL_LIST_TYPE_AND_2_VALUE_PARAMS(p0, p1) , p0##_type, \ - p1##_type -#define GMOCK_INTERNAL_LIST_TYPE_AND_3_VALUE_PARAMS(p0, p1, p2) , p0##_type, \ - p1##_type, p2##_type -#define GMOCK_INTERNAL_LIST_TYPE_AND_4_VALUE_PARAMS(p0, p1, p2, p3) , \ - p0##_type, p1##_type, p2##_type, p3##_type -#define GMOCK_INTERNAL_LIST_TYPE_AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4) , \ - p0##_type, p1##_type, p2##_type, p3##_type, p4##_type -#define GMOCK_INTERNAL_LIST_TYPE_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5) , \ - p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, p5##_type -#define GMOCK_INTERNAL_LIST_TYPE_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \ - p6) , p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, p5##_type, \ - p6##_type -#define GMOCK_INTERNAL_LIST_TYPE_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \ - p6, p7) , p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \ - p5##_type, p6##_type, p7##_type -#define GMOCK_INTERNAL_LIST_TYPE_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \ - p6, p7, p8) , p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \ - p5##_type, p6##_type, p7##_type, p8##_type -#define GMOCK_INTERNAL_LIST_TYPE_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \ - p6, p7, p8, p9) , p0##_type, p1##_type, p2##_type, p3##_type, p4##_type, \ - p5##_type, p6##_type, p7##_type, p8##_type, p9##_type - -// Declares the value parameters. -#define GMOCK_INTERNAL_DECL_AND_0_VALUE_PARAMS() -#define GMOCK_INTERNAL_DECL_AND_1_VALUE_PARAMS(p0) p0##_type p0 -#define GMOCK_INTERNAL_DECL_AND_2_VALUE_PARAMS(p0, p1) p0##_type p0, \ - p1##_type p1 -#define GMOCK_INTERNAL_DECL_AND_3_VALUE_PARAMS(p0, p1, p2) p0##_type p0, \ - p1##_type p1, p2##_type p2 -#define GMOCK_INTERNAL_DECL_AND_4_VALUE_PARAMS(p0, p1, p2, p3) p0##_type p0, \ - p1##_type p1, p2##_type p2, p3##_type p3 -#define GMOCK_INTERNAL_DECL_AND_5_VALUE_PARAMS(p0, p1, p2, p3, \ - p4) p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, p4##_type p4 -#define GMOCK_INTERNAL_DECL_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, \ - p5) p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, p4##_type p4, \ - p5##_type p5 -#define GMOCK_INTERNAL_DECL_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, \ - p6) p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, p4##_type p4, \ - p5##_type p5, p6##_type p6 -#define GMOCK_INTERNAL_DECL_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \ - p7) p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, p4##_type p4, \ - p5##_type p5, p6##_type p6, p7##_type p7 -#define GMOCK_INTERNAL_DECL_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \ - p7, p8) p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \ - p4##_type p4, p5##_type p5, p6##_type p6, p7##_type p7, p8##_type p8 -#define GMOCK_INTERNAL_DECL_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \ - p7, p8, p9) p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \ - p4##_type p4, p5##_type p5, p6##_type p6, p7##_type p7, p8##_type p8, \ - p9##_type p9 - -// The suffix of the class template implementing the action template. -#define GMOCK_INTERNAL_COUNT_AND_0_VALUE_PARAMS() -#define GMOCK_INTERNAL_COUNT_AND_1_VALUE_PARAMS(p0) P -#define GMOCK_INTERNAL_COUNT_AND_2_VALUE_PARAMS(p0, p1) P2 -#define GMOCK_INTERNAL_COUNT_AND_3_VALUE_PARAMS(p0, p1, p2) P3 -#define GMOCK_INTERNAL_COUNT_AND_4_VALUE_PARAMS(p0, p1, p2, p3) P4 -#define GMOCK_INTERNAL_COUNT_AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4) P5 -#define GMOCK_INTERNAL_COUNT_AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5) P6 -#define GMOCK_INTERNAL_COUNT_AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6) P7 -#define GMOCK_INTERNAL_COUNT_AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \ - p7) P8 -#define GMOCK_INTERNAL_COUNT_AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \ - p7, p8) P9 -#define GMOCK_INTERNAL_COUNT_AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, \ - p7, p8, p9) P10 - -// The name of the class template implementing the action template. -#define GMOCK_ACTION_CLASS_(name, value_params)\ - GTEST_CONCAT_TOKEN_(name##Action, GMOCK_INTERNAL_COUNT_##value_params) - -#define ACTION_TEMPLATE(name, template_params, value_params)\ - template \ - class GMOCK_ACTION_CLASS_(name, value_params) {\ - public:\ - explicit GMOCK_ACTION_CLASS_(name, value_params)\ - GMOCK_INTERNAL_INIT_##value_params {}\ - template \ - class gmock_Impl : public ::testing::ActionInterface {\ - public:\ - typedef F function_type;\ - typedef typename ::testing::internal::Function::Result return_type;\ - typedef typename ::testing::internal::Function::ArgumentTuple\ - args_type;\ - explicit gmock_Impl GMOCK_INTERNAL_INIT_##value_params {}\ - virtual return_type Perform(const args_type& args) {\ - return ::testing::internal::ActionHelper::\ - Perform(this, args);\ - }\ - template \ - return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \ - arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \ - arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \ - arg9_type arg9) const;\ - GMOCK_INTERNAL_DEFN_##value_params\ - private:\ - GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ - };\ - template operator ::testing::Action() const {\ - return ::testing::Action(\ - new gmock_Impl(GMOCK_INTERNAL_LIST_##value_params));\ - }\ - GMOCK_INTERNAL_DEFN_##value_params\ - private:\ - GTEST_DISALLOW_ASSIGN_(GMOCK_ACTION_CLASS_(name, value_params));\ - };\ - template \ - inline GMOCK_ACTION_CLASS_(name, value_params)<\ - GMOCK_INTERNAL_LIST_##template_params\ - GMOCK_INTERNAL_LIST_TYPE_##value_params> name(\ - GMOCK_INTERNAL_DECL_##value_params) {\ - return GMOCK_ACTION_CLASS_(name, value_params)<\ - GMOCK_INTERNAL_LIST_##template_params\ - GMOCK_INTERNAL_LIST_TYPE_##value_params>(\ - GMOCK_INTERNAL_LIST_##value_params);\ - }\ - template \ - template \ - template \ - typename ::testing::internal::Function::Result\ - GMOCK_ACTION_CLASS_(name, value_params)<\ - GMOCK_INTERNAL_LIST_##template_params\ - GMOCK_INTERNAL_LIST_TYPE_##value_params>::gmock_Impl::\ - gmock_PerformImpl(\ - GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const - -#define ACTION(name)\ - class name##Action {\ - public:\ - name##Action() {}\ - template \ - class gmock_Impl : public ::testing::ActionInterface {\ - public:\ - typedef F function_type;\ - typedef typename ::testing::internal::Function::Result return_type;\ - typedef typename ::testing::internal::Function::ArgumentTuple\ - args_type;\ - gmock_Impl() {}\ - virtual return_type Perform(const args_type& args) {\ - return ::testing::internal::ActionHelper::\ - Perform(this, args);\ - }\ - template \ - return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \ - arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \ - arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \ - arg9_type arg9) const;\ - private:\ - GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ - };\ - template operator ::testing::Action() const {\ - return ::testing::Action(new gmock_Impl());\ - }\ - private:\ - GTEST_DISALLOW_ASSIGN_(name##Action);\ - };\ - inline name##Action name() {\ - return name##Action();\ - }\ - template \ - template \ - typename ::testing::internal::Function::Result\ - name##Action::gmock_Impl::gmock_PerformImpl(\ - GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const - -#define ACTION_P(name, p0)\ - template \ - class name##ActionP {\ - public:\ - explicit name##ActionP(p0##_type gmock_p0) : p0(gmock_p0) {}\ - template \ - class gmock_Impl : public ::testing::ActionInterface {\ - public:\ - typedef F function_type;\ - typedef typename ::testing::internal::Function::Result return_type;\ - typedef typename ::testing::internal::Function::ArgumentTuple\ - args_type;\ - explicit gmock_Impl(p0##_type gmock_p0) : p0(gmock_p0) {}\ - virtual return_type Perform(const args_type& args) {\ - return ::testing::internal::ActionHelper::\ - Perform(this, args);\ - }\ - template \ - return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \ - arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \ - arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \ - arg9_type arg9) const;\ - p0##_type p0;\ - private:\ - GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ - };\ - template operator ::testing::Action() const {\ - return ::testing::Action(new gmock_Impl(p0));\ - }\ - p0##_type p0;\ - private:\ - GTEST_DISALLOW_ASSIGN_(name##ActionP);\ - };\ - template \ - inline name##ActionP name(p0##_type p0) {\ - return name##ActionP(p0);\ - }\ - template \ - template \ - template \ - typename ::testing::internal::Function::Result\ - name##ActionP::gmock_Impl::gmock_PerformImpl(\ - GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const - -#define ACTION_P2(name, p0, p1)\ - template \ - class name##ActionP2 {\ - public:\ - name##ActionP2(p0##_type gmock_p0, p1##_type gmock_p1) : p0(gmock_p0), \ - p1(gmock_p1) {}\ - template \ - class gmock_Impl : public ::testing::ActionInterface {\ - public:\ - typedef F function_type;\ - typedef typename ::testing::internal::Function::Result return_type;\ - typedef typename ::testing::internal::Function::ArgumentTuple\ - args_type;\ - gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1) : p0(gmock_p0), \ - p1(gmock_p1) {}\ - virtual return_type Perform(const args_type& args) {\ - return ::testing::internal::ActionHelper::\ - Perform(this, args);\ - }\ - template \ - return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \ - arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \ - arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \ - arg9_type arg9) const;\ - p0##_type p0;\ - p1##_type p1;\ - private:\ - GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ - };\ - template operator ::testing::Action() const {\ - return ::testing::Action(new gmock_Impl(p0, p1));\ - }\ - p0##_type p0;\ - p1##_type p1;\ - private:\ - GTEST_DISALLOW_ASSIGN_(name##ActionP2);\ - };\ - template \ - inline name##ActionP2 name(p0##_type p0, \ - p1##_type p1) {\ - return name##ActionP2(p0, p1);\ - }\ - template \ - template \ - template \ - typename ::testing::internal::Function::Result\ - name##ActionP2::gmock_Impl::gmock_PerformImpl(\ - GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const - -#define ACTION_P3(name, p0, p1, p2)\ - template \ - class name##ActionP3 {\ - public:\ - name##ActionP3(p0##_type gmock_p0, p1##_type gmock_p1, \ - p2##_type gmock_p2) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2) {}\ - template \ - class gmock_Impl : public ::testing::ActionInterface {\ - public:\ - typedef F function_type;\ - typedef typename ::testing::internal::Function::Result return_type;\ - typedef typename ::testing::internal::Function::ArgumentTuple\ - args_type;\ - gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, \ - p2##_type gmock_p2) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2) {}\ - virtual return_type Perform(const args_type& args) {\ - return ::testing::internal::ActionHelper::\ - Perform(this, args);\ - }\ - template \ - return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \ - arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \ - arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \ - arg9_type arg9) const;\ - p0##_type p0;\ - p1##_type p1;\ - p2##_type p2;\ - private:\ - GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ - };\ - template operator ::testing::Action() const {\ - return ::testing::Action(new gmock_Impl(p0, p1, p2));\ - }\ - p0##_type p0;\ - p1##_type p1;\ - p2##_type p2;\ - private:\ - GTEST_DISALLOW_ASSIGN_(name##ActionP3);\ - };\ - template \ - inline name##ActionP3 name(p0##_type p0, \ - p1##_type p1, p2##_type p2) {\ - return name##ActionP3(p0, p1, p2);\ - }\ - template \ - template \ - template \ - typename ::testing::internal::Function::Result\ - name##ActionP3::gmock_Impl::gmock_PerformImpl(\ - GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const - -#define ACTION_P4(name, p0, p1, p2, p3)\ - template \ - class name##ActionP4 {\ - public:\ - name##ActionP4(p0##_type gmock_p0, p1##_type gmock_p1, \ - p2##_type gmock_p2, p3##_type gmock_p3) : p0(gmock_p0), p1(gmock_p1), \ - p2(gmock_p2), p3(gmock_p3) {}\ - template \ - class gmock_Impl : public ::testing::ActionInterface {\ - public:\ - typedef F function_type;\ - typedef typename ::testing::internal::Function::Result return_type;\ - typedef typename ::testing::internal::Function::ArgumentTuple\ - args_type;\ - gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ - p3##_type gmock_p3) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \ - p3(gmock_p3) {}\ - virtual return_type Perform(const args_type& args) {\ - return ::testing::internal::ActionHelper::\ - Perform(this, args);\ - }\ - template \ - return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \ - arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \ - arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \ - arg9_type arg9) const;\ - p0##_type p0;\ - p1##_type p1;\ - p2##_type p2;\ - p3##_type p3;\ - private:\ - GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ - };\ - template operator ::testing::Action() const {\ - return ::testing::Action(new gmock_Impl(p0, p1, p2, p3));\ - }\ - p0##_type p0;\ - p1##_type p1;\ - p2##_type p2;\ - p3##_type p3;\ - private:\ - GTEST_DISALLOW_ASSIGN_(name##ActionP4);\ - };\ - template \ - inline name##ActionP4 name(p0##_type p0, p1##_type p1, p2##_type p2, \ - p3##_type p3) {\ - return name##ActionP4(p0, p1, \ - p2, p3);\ - }\ - template \ - template \ - template \ - typename ::testing::internal::Function::Result\ - name##ActionP4::gmock_Impl::gmock_PerformImpl(\ - GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const - -#define ACTION_P5(name, p0, p1, p2, p3, p4)\ - template \ - class name##ActionP5 {\ - public:\ - name##ActionP5(p0##_type gmock_p0, p1##_type gmock_p1, \ - p2##_type gmock_p2, p3##_type gmock_p3, \ - p4##_type gmock_p4) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \ - p3(gmock_p3), p4(gmock_p4) {}\ - template \ - class gmock_Impl : public ::testing::ActionInterface {\ - public:\ - typedef F function_type;\ - typedef typename ::testing::internal::Function::Result return_type;\ - typedef typename ::testing::internal::Function::ArgumentTuple\ - args_type;\ - gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ - p3##_type gmock_p3, p4##_type gmock_p4) : p0(gmock_p0), \ - p1(gmock_p1), p2(gmock_p2), p3(gmock_p3), p4(gmock_p4) {}\ - virtual return_type Perform(const args_type& args) {\ - return ::testing::internal::ActionHelper::\ - Perform(this, args);\ - }\ - template \ - return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \ - arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \ - arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \ - arg9_type arg9) const;\ - p0##_type p0;\ - p1##_type p1;\ - p2##_type p2;\ - p3##_type p3;\ - p4##_type p4;\ - private:\ - GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ - };\ - template operator ::testing::Action() const {\ - return ::testing::Action(new gmock_Impl(p0, p1, p2, p3, p4));\ - }\ - p0##_type p0;\ - p1##_type p1;\ - p2##_type p2;\ - p3##_type p3;\ - p4##_type p4;\ - private:\ - GTEST_DISALLOW_ASSIGN_(name##ActionP5);\ - };\ - template \ - inline name##ActionP5 name(p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \ - p4##_type p4) {\ - return name##ActionP5(p0, p1, p2, p3, p4);\ - }\ - template \ - template \ - template \ - typename ::testing::internal::Function::Result\ - name##ActionP5::gmock_Impl::gmock_PerformImpl(\ - GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const - -#define ACTION_P6(name, p0, p1, p2, p3, p4, p5)\ - template \ - class name##ActionP6 {\ - public:\ - name##ActionP6(p0##_type gmock_p0, p1##_type gmock_p1, \ - p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \ - p5##_type gmock_p5) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \ - p3(gmock_p3), p4(gmock_p4), p5(gmock_p5) {}\ - template \ - class gmock_Impl : public ::testing::ActionInterface {\ - public:\ - typedef F function_type;\ - typedef typename ::testing::internal::Function::Result return_type;\ - typedef typename ::testing::internal::Function::ArgumentTuple\ - args_type;\ - gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ - p3##_type gmock_p3, p4##_type gmock_p4, \ - p5##_type gmock_p5) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \ - p3(gmock_p3), p4(gmock_p4), p5(gmock_p5) {}\ - virtual return_type Perform(const args_type& args) {\ - return ::testing::internal::ActionHelper::\ - Perform(this, args);\ - }\ - template \ - return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \ - arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \ - arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \ - arg9_type arg9) const;\ - p0##_type p0;\ - p1##_type p1;\ - p2##_type p2;\ - p3##_type p3;\ - p4##_type p4;\ - p5##_type p5;\ - private:\ - GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ - };\ - template operator ::testing::Action() const {\ - return ::testing::Action(new gmock_Impl(p0, p1, p2, p3, p4, p5));\ - }\ - p0##_type p0;\ - p1##_type p1;\ - p2##_type p2;\ - p3##_type p3;\ - p4##_type p4;\ - p5##_type p5;\ - private:\ - GTEST_DISALLOW_ASSIGN_(name##ActionP6);\ - };\ - template \ - inline name##ActionP6 name(p0##_type p0, p1##_type p1, p2##_type p2, \ - p3##_type p3, p4##_type p4, p5##_type p5) {\ - return name##ActionP6(p0, p1, p2, p3, p4, p5);\ - }\ - template \ - template \ - template \ - typename ::testing::internal::Function::Result\ - name##ActionP6::gmock_Impl::gmock_PerformImpl(\ - GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const - -#define ACTION_P7(name, p0, p1, p2, p3, p4, p5, p6)\ - template \ - class name##ActionP7 {\ - public:\ - name##ActionP7(p0##_type gmock_p0, p1##_type gmock_p1, \ - p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \ - p5##_type gmock_p5, p6##_type gmock_p6) : p0(gmock_p0), p1(gmock_p1), \ - p2(gmock_p2), p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), \ - p6(gmock_p6) {}\ - template \ - class gmock_Impl : public ::testing::ActionInterface {\ - public:\ - typedef F function_type;\ - typedef typename ::testing::internal::Function::Result return_type;\ - typedef typename ::testing::internal::Function::ArgumentTuple\ - args_type;\ - gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ - p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \ - p6##_type gmock_p6) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \ - p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6) {}\ - virtual return_type Perform(const args_type& args) {\ - return ::testing::internal::ActionHelper::\ - Perform(this, args);\ - }\ - template \ - return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \ - arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \ - arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \ - arg9_type arg9) const;\ - p0##_type p0;\ - p1##_type p1;\ - p2##_type p2;\ - p3##_type p3;\ - p4##_type p4;\ - p5##_type p5;\ - p6##_type p6;\ - private:\ - GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ - };\ - template operator ::testing::Action() const {\ - return ::testing::Action(new gmock_Impl(p0, p1, p2, p3, p4, p5, \ - p6));\ - }\ - p0##_type p0;\ - p1##_type p1;\ - p2##_type p2;\ - p3##_type p3;\ - p4##_type p4;\ - p5##_type p5;\ - p6##_type p6;\ - private:\ - GTEST_DISALLOW_ASSIGN_(name##ActionP7);\ - };\ - template \ - inline name##ActionP7 name(p0##_type p0, p1##_type p1, \ - p2##_type p2, p3##_type p3, p4##_type p4, p5##_type p5, \ - p6##_type p6) {\ - return name##ActionP7(p0, p1, p2, p3, p4, p5, p6);\ - }\ - template \ - template \ - template \ - typename ::testing::internal::Function::Result\ - name##ActionP7::gmock_Impl::gmock_PerformImpl(\ - GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const - -#define ACTION_P8(name, p0, p1, p2, p3, p4, p5, p6, p7)\ - template \ - class name##ActionP8 {\ - public:\ - name##ActionP8(p0##_type gmock_p0, p1##_type gmock_p1, \ - p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \ - p5##_type gmock_p5, p6##_type gmock_p6, \ - p7##_type gmock_p7) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \ - p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), \ - p7(gmock_p7) {}\ - template \ - class gmock_Impl : public ::testing::ActionInterface {\ - public:\ - typedef F function_type;\ - typedef typename ::testing::internal::Function::Result return_type;\ - typedef typename ::testing::internal::Function::ArgumentTuple\ - args_type;\ - gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ - p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \ - p6##_type gmock_p6, p7##_type gmock_p7) : p0(gmock_p0), \ - p1(gmock_p1), p2(gmock_p2), p3(gmock_p3), p4(gmock_p4), \ - p5(gmock_p5), p6(gmock_p6), p7(gmock_p7) {}\ - virtual return_type Perform(const args_type& args) {\ - return ::testing::internal::ActionHelper::\ - Perform(this, args);\ - }\ - template \ - return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \ - arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \ - arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \ - arg9_type arg9) const;\ - p0##_type p0;\ - p1##_type p1;\ - p2##_type p2;\ - p3##_type p3;\ - p4##_type p4;\ - p5##_type p5;\ - p6##_type p6;\ - p7##_type p7;\ - private:\ - GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ - };\ - template operator ::testing::Action() const {\ - return ::testing::Action(new gmock_Impl(p0, p1, p2, p3, p4, p5, \ - p6, p7));\ - }\ - p0##_type p0;\ - p1##_type p1;\ - p2##_type p2;\ - p3##_type p3;\ - p4##_type p4;\ - p5##_type p5;\ - p6##_type p6;\ - p7##_type p7;\ - private:\ - GTEST_DISALLOW_ASSIGN_(name##ActionP8);\ - };\ - template \ - inline name##ActionP8 name(p0##_type p0, \ - p1##_type p1, p2##_type p2, p3##_type p3, p4##_type p4, p5##_type p5, \ - p6##_type p6, p7##_type p7) {\ - return name##ActionP8(p0, p1, p2, p3, p4, p5, \ - p6, p7);\ - }\ - template \ - template \ - template \ - typename ::testing::internal::Function::Result\ - name##ActionP8::gmock_Impl::gmock_PerformImpl(\ - GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const - -#define ACTION_P9(name, p0, p1, p2, p3, p4, p5, p6, p7, p8)\ - template \ - class name##ActionP9 {\ - public:\ - name##ActionP9(p0##_type gmock_p0, p1##_type gmock_p1, \ - p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \ - p5##_type gmock_p5, p6##_type gmock_p6, p7##_type gmock_p7, \ - p8##_type gmock_p8) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \ - p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), p7(gmock_p7), \ - p8(gmock_p8) {}\ - template \ - class gmock_Impl : public ::testing::ActionInterface {\ - public:\ - typedef F function_type;\ - typedef typename ::testing::internal::Function::Result return_type;\ - typedef typename ::testing::internal::Function::ArgumentTuple\ - args_type;\ - gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ - p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \ - p6##_type gmock_p6, p7##_type gmock_p7, \ - p8##_type gmock_p8) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \ - p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), \ - p7(gmock_p7), p8(gmock_p8) {}\ - virtual return_type Perform(const args_type& args) {\ - return ::testing::internal::ActionHelper::\ - Perform(this, args);\ - }\ - template \ - return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \ - arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \ - arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \ - arg9_type arg9) const;\ - p0##_type p0;\ - p1##_type p1;\ - p2##_type p2;\ - p3##_type p3;\ - p4##_type p4;\ - p5##_type p5;\ - p6##_type p6;\ - p7##_type p7;\ - p8##_type p8;\ - private:\ - GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ - };\ - template operator ::testing::Action() const {\ - return ::testing::Action(new gmock_Impl(p0, p1, p2, p3, p4, p5, \ - p6, p7, p8));\ - }\ - p0##_type p0;\ - p1##_type p1;\ - p2##_type p2;\ - p3##_type p3;\ - p4##_type p4;\ - p5##_type p5;\ - p6##_type p6;\ - p7##_type p7;\ - p8##_type p8;\ - private:\ - GTEST_DISALLOW_ASSIGN_(name##ActionP9);\ - };\ - template \ - inline name##ActionP9 name(p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \ - p4##_type p4, p5##_type p5, p6##_type p6, p7##_type p7, \ - p8##_type p8) {\ - return name##ActionP9(p0, p1, p2, \ - p3, p4, p5, p6, p7, p8);\ - }\ - template \ - template \ - template \ - typename ::testing::internal::Function::Result\ - name##ActionP9::gmock_Impl::gmock_PerformImpl(\ - GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const - -#define ACTION_P10(name, p0, p1, p2, p3, p4, p5, p6, p7, p8, p9)\ - template \ - class name##ActionP10 {\ - public:\ - name##ActionP10(p0##_type gmock_p0, p1##_type gmock_p1, \ - p2##_type gmock_p2, p3##_type gmock_p3, p4##_type gmock_p4, \ - p5##_type gmock_p5, p6##_type gmock_p6, p7##_type gmock_p7, \ - p8##_type gmock_p8, p9##_type gmock_p9) : p0(gmock_p0), p1(gmock_p1), \ - p2(gmock_p2), p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), \ - p7(gmock_p7), p8(gmock_p8), p9(gmock_p9) {}\ - template \ - class gmock_Impl : public ::testing::ActionInterface {\ - public:\ - typedef F function_type;\ - typedef typename ::testing::internal::Function::Result return_type;\ - typedef typename ::testing::internal::Function::ArgumentTuple\ - args_type;\ - gmock_Impl(p0##_type gmock_p0, p1##_type gmock_p1, p2##_type gmock_p2, \ - p3##_type gmock_p3, p4##_type gmock_p4, p5##_type gmock_p5, \ - p6##_type gmock_p6, p7##_type gmock_p7, p8##_type gmock_p8, \ - p9##_type gmock_p9) : p0(gmock_p0), p1(gmock_p1), p2(gmock_p2), \ - p3(gmock_p3), p4(gmock_p4), p5(gmock_p5), p6(gmock_p6), \ - p7(gmock_p7), p8(gmock_p8), p9(gmock_p9) {}\ - virtual return_type Perform(const args_type& args) {\ - return ::testing::internal::ActionHelper::\ - Perform(this, args);\ - }\ - template \ - return_type gmock_PerformImpl(const args_type& args, arg0_type arg0, \ - arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, \ - arg5_type arg5, arg6_type arg6, arg7_type arg7, arg8_type arg8, \ - arg9_type arg9) const;\ - p0##_type p0;\ - p1##_type p1;\ - p2##_type p2;\ - p3##_type p3;\ - p4##_type p4;\ - p5##_type p5;\ - p6##_type p6;\ - p7##_type p7;\ - p8##_type p8;\ - p9##_type p9;\ - private:\ - GTEST_DISALLOW_ASSIGN_(gmock_Impl);\ - };\ - template operator ::testing::Action() const {\ - return ::testing::Action(new gmock_Impl(p0, p1, p2, p3, p4, p5, \ - p6, p7, p8, p9));\ - }\ - p0##_type p0;\ - p1##_type p1;\ - p2##_type p2;\ - p3##_type p3;\ - p4##_type p4;\ - p5##_type p5;\ - p6##_type p6;\ - p7##_type p7;\ - p8##_type p8;\ - p9##_type p9;\ - private:\ - GTEST_DISALLOW_ASSIGN_(name##ActionP10);\ - };\ - template \ - inline name##ActionP10 name(p0##_type p0, p1##_type p1, p2##_type p2, p3##_type p3, \ - p4##_type p4, p5##_type p5, p6##_type p6, p7##_type p7, p8##_type p8, \ - p9##_type p9) {\ - return name##ActionP10(p0, \ - p1, p2, p3, p4, p5, p6, p7, p8, p9);\ - }\ - template \ - template \ - template \ - typename ::testing::internal::Function::Result\ - name##ActionP10::gmock_Impl::gmock_PerformImpl(\ - GMOCK_ACTION_ARG_TYPES_AND_NAMES_UNUSED_) const - -namespace testing { - - -// The ACTION*() macros trigger warning C4100 (unreferenced formal -// parameter) in MSVC with -W4. Unfortunately they cannot be fixed in -// the macro definition, as the warnings are generated when the macro -// is expanded and macro expansion cannot contain #pragma. Therefore -// we suppress them here. -#ifdef _MSC_VER -# pragma warning(push) -# pragma warning(disable:4100) -#endif - -// Various overloads for InvokeArgument(). -// -// The InvokeArgument(a1, a2, ..., a_k) action invokes the N-th -// (0-based) argument, which must be a k-ary callable, of the mock -// function, with arguments a1, a2, ..., a_k. -// -// Notes: -// -// 1. The arguments are passed by value by default. If you need to -// pass an argument by reference, wrap it inside ByRef(). For -// example, -// -// InvokeArgument<1>(5, string("Hello"), ByRef(foo)) -// -// passes 5 and string("Hello") by value, and passes foo by -// reference. -// -// 2. If the callable takes an argument by reference but ByRef() is -// not used, it will receive the reference to a copy of the value, -// instead of the original value. For example, when the 0-th -// argument of the mock function takes a const string&, the action -// -// InvokeArgument<0>(string("Hello")) -// -// makes a copy of the temporary string("Hello") object and passes a -// reference of the copy, instead of the original temporary object, -// to the callable. This makes it easy for a user to define an -// InvokeArgument action from temporary values and have it performed -// later. - -namespace internal { -namespace invoke_argument { - -// Appears in InvokeArgumentAdl's argument list to help avoid -// accidental calls to user functions of the same name. -struct AdlTag {}; - -// InvokeArgumentAdl - a helper for InvokeArgument. -// The basic overloads are provided here for generic functors. -// Overloads for other custom-callables are provided in the -// internal/custom/callback-actions.h header. - -template -R InvokeArgumentAdl(AdlTag, F f) { - return f(); -} -template -R InvokeArgumentAdl(AdlTag, F f, A1 a1) { - return f(a1); -} -template -R InvokeArgumentAdl(AdlTag, F f, A1 a1, A2 a2) { - return f(a1, a2); -} -template -R InvokeArgumentAdl(AdlTag, F f, A1 a1, A2 a2, A3 a3) { - return f(a1, a2, a3); -} -template -R InvokeArgumentAdl(AdlTag, F f, A1 a1, A2 a2, A3 a3, A4 a4) { - return f(a1, a2, a3, a4); -} -template -R InvokeArgumentAdl(AdlTag, F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) { - return f(a1, a2, a3, a4, a5); -} -template -R InvokeArgumentAdl(AdlTag, F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) { - return f(a1, a2, a3, a4, a5, a6); -} -template -R InvokeArgumentAdl(AdlTag, F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, - A7 a7) { - return f(a1, a2, a3, a4, a5, a6, a7); -} -template -R InvokeArgumentAdl(AdlTag, F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, - A7 a7, A8 a8) { - return f(a1, a2, a3, a4, a5, a6, a7, a8); -} -template -R InvokeArgumentAdl(AdlTag, F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, - A7 a7, A8 a8, A9 a9) { - return f(a1, a2, a3, a4, a5, a6, a7, a8, a9); -} -template -R InvokeArgumentAdl(AdlTag, F f, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, - A7 a7, A8 a8, A9 a9, A10 a10) { - return f(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); -} -} // namespace invoke_argument -} // namespace internal - -ACTION_TEMPLATE(InvokeArgument, - HAS_1_TEMPLATE_PARAMS(int, k), - AND_0_VALUE_PARAMS()) { - using internal::invoke_argument::InvokeArgumentAdl; - return InvokeArgumentAdl( - internal::invoke_argument::AdlTag(), - ::testing::get(args)); -} - -ACTION_TEMPLATE(InvokeArgument, - HAS_1_TEMPLATE_PARAMS(int, k), - AND_1_VALUE_PARAMS(p0)) { - using internal::invoke_argument::InvokeArgumentAdl; - return InvokeArgumentAdl( - internal::invoke_argument::AdlTag(), - ::testing::get(args), p0); -} - -ACTION_TEMPLATE(InvokeArgument, - HAS_1_TEMPLATE_PARAMS(int, k), - AND_2_VALUE_PARAMS(p0, p1)) { - using internal::invoke_argument::InvokeArgumentAdl; - return InvokeArgumentAdl( - internal::invoke_argument::AdlTag(), - ::testing::get(args), p0, p1); -} - -ACTION_TEMPLATE(InvokeArgument, - HAS_1_TEMPLATE_PARAMS(int, k), - AND_3_VALUE_PARAMS(p0, p1, p2)) { - using internal::invoke_argument::InvokeArgumentAdl; - return InvokeArgumentAdl( - internal::invoke_argument::AdlTag(), - ::testing::get(args), p0, p1, p2); -} - -ACTION_TEMPLATE(InvokeArgument, - HAS_1_TEMPLATE_PARAMS(int, k), - AND_4_VALUE_PARAMS(p0, p1, p2, p3)) { - using internal::invoke_argument::InvokeArgumentAdl; - return InvokeArgumentAdl( - internal::invoke_argument::AdlTag(), - ::testing::get(args), p0, p1, p2, p3); -} - -ACTION_TEMPLATE(InvokeArgument, - HAS_1_TEMPLATE_PARAMS(int, k), - AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4)) { - using internal::invoke_argument::InvokeArgumentAdl; - return InvokeArgumentAdl( - internal::invoke_argument::AdlTag(), - ::testing::get(args), p0, p1, p2, p3, p4); -} - -ACTION_TEMPLATE(InvokeArgument, - HAS_1_TEMPLATE_PARAMS(int, k), - AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5)) { - using internal::invoke_argument::InvokeArgumentAdl; - return InvokeArgumentAdl( - internal::invoke_argument::AdlTag(), - ::testing::get(args), p0, p1, p2, p3, p4, p5); -} - -ACTION_TEMPLATE(InvokeArgument, - HAS_1_TEMPLATE_PARAMS(int, k), - AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6)) { - using internal::invoke_argument::InvokeArgumentAdl; - return InvokeArgumentAdl( - internal::invoke_argument::AdlTag(), - ::testing::get(args), p0, p1, p2, p3, p4, p5, p6); -} - -ACTION_TEMPLATE(InvokeArgument, - HAS_1_TEMPLATE_PARAMS(int, k), - AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7)) { - using internal::invoke_argument::InvokeArgumentAdl; - return InvokeArgumentAdl( - internal::invoke_argument::AdlTag(), - ::testing::get(args), p0, p1, p2, p3, p4, p5, p6, p7); -} - -ACTION_TEMPLATE(InvokeArgument, - HAS_1_TEMPLATE_PARAMS(int, k), - AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7, p8)) { - using internal::invoke_argument::InvokeArgumentAdl; - return InvokeArgumentAdl( - internal::invoke_argument::AdlTag(), - ::testing::get(args), p0, p1, p2, p3, p4, p5, p6, p7, p8); -} - -ACTION_TEMPLATE(InvokeArgument, - HAS_1_TEMPLATE_PARAMS(int, k), - AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9)) { - using internal::invoke_argument::InvokeArgumentAdl; - return InvokeArgumentAdl( - internal::invoke_argument::AdlTag(), - ::testing::get(args), p0, p1, p2, p3, p4, p5, p6, p7, p8, p9); -} - -// Various overloads for ReturnNew(). -// -// The ReturnNew(a1, a2, ..., a_k) action returns a pointer to a new -// instance of type T, constructed on the heap with constructor arguments -// a1, a2, ..., and a_k. The caller assumes ownership of the returned value. -ACTION_TEMPLATE(ReturnNew, - HAS_1_TEMPLATE_PARAMS(typename, T), - AND_0_VALUE_PARAMS()) { - return new T(); -} - -ACTION_TEMPLATE(ReturnNew, - HAS_1_TEMPLATE_PARAMS(typename, T), - AND_1_VALUE_PARAMS(p0)) { - return new T(p0); -} - -ACTION_TEMPLATE(ReturnNew, - HAS_1_TEMPLATE_PARAMS(typename, T), - AND_2_VALUE_PARAMS(p0, p1)) { - return new T(p0, p1); -} - -ACTION_TEMPLATE(ReturnNew, - HAS_1_TEMPLATE_PARAMS(typename, T), - AND_3_VALUE_PARAMS(p0, p1, p2)) { - return new T(p0, p1, p2); -} - -ACTION_TEMPLATE(ReturnNew, - HAS_1_TEMPLATE_PARAMS(typename, T), - AND_4_VALUE_PARAMS(p0, p1, p2, p3)) { - return new T(p0, p1, p2, p3); -} - -ACTION_TEMPLATE(ReturnNew, - HAS_1_TEMPLATE_PARAMS(typename, T), - AND_5_VALUE_PARAMS(p0, p1, p2, p3, p4)) { - return new T(p0, p1, p2, p3, p4); -} - -ACTION_TEMPLATE(ReturnNew, - HAS_1_TEMPLATE_PARAMS(typename, T), - AND_6_VALUE_PARAMS(p0, p1, p2, p3, p4, p5)) { - return new T(p0, p1, p2, p3, p4, p5); -} - -ACTION_TEMPLATE(ReturnNew, - HAS_1_TEMPLATE_PARAMS(typename, T), - AND_7_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6)) { - return new T(p0, p1, p2, p3, p4, p5, p6); -} - -ACTION_TEMPLATE(ReturnNew, - HAS_1_TEMPLATE_PARAMS(typename, T), - AND_8_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7)) { - return new T(p0, p1, p2, p3, p4, p5, p6, p7); -} - -ACTION_TEMPLATE(ReturnNew, - HAS_1_TEMPLATE_PARAMS(typename, T), - AND_9_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7, p8)) { - return new T(p0, p1, p2, p3, p4, p5, p6, p7, p8); -} - -ACTION_TEMPLATE(ReturnNew, - HAS_1_TEMPLATE_PARAMS(typename, T), - AND_10_VALUE_PARAMS(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9)) { - return new T(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9); -} - -#ifdef _MSC_VER -# pragma warning(pop) -#endif - -} // namespace testing - -// Include any custom actions added by the local installation. -// We must include this header at the end to make sure it can use the -// declarations from this file. -// This file was GENERATED by command: -// pump.py gmock-generated-actions.h.pump -// DO NOT EDIT BY HAND!!! - -#ifndef GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_GENERATED_ACTIONS_H_ -#define GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_GENERATED_ACTIONS_H_ - -#endif // GMOCK_INCLUDE_GMOCK_INTERNAL_CUSTOM_GMOCK_GENERATED_ACTIONS_H_ - -#endif // GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_ACTIONS_H_ -// This file was GENERATED by command: -// pump.py gmock-generated-function-mockers.h.pump -// DO NOT EDIT BY HAND!!! - -// Copyright 2007, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Author: wan@google.com (Zhanyong Wan) - -// Google Mock - a framework for writing C++ mock classes. -// -// This file implements function mockers of various arities. - -#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_ -#define GMOCK_INCLUDE_GMOCK_GMOCK_GENERATED_FUNCTION_MOCKERS_H_ - -// Copyright 2007, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Author: wan@google.com (Zhanyong Wan) - -// Google Mock - a framework for writing C++ mock classes. -// -// This file implements the ON_CALL() and EXPECT_CALL() macros. -// -// A user can use the ON_CALL() macro to specify the default action of -// a mock method. The syntax is: -// -// ON_CALL(mock_object, Method(argument-matchers)) -// .With(multi-argument-matcher) -// .WillByDefault(action); -// -// where the .With() clause is optional. -// -// A user can use the EXPECT_CALL() macro to specify an expectation on -// a mock method. The syntax is: -// -// EXPECT_CALL(mock_object, Method(argument-matchers)) -// .With(multi-argument-matchers) -// .Times(cardinality) -// .InSequence(sequences) -// .After(expectations) -// .WillOnce(action) -// .WillRepeatedly(action) -// .RetiresOnSaturation(); -// -// where all clauses are optional, and .InSequence()/.After()/ -// .WillOnce() can appear any number of times. - -#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_SPEC_BUILDERS_H_ -#define GMOCK_INCLUDE_GMOCK_GMOCK_SPEC_BUILDERS_H_ - -#include -#include -#include -#include -#include - -#if GTEST_HAS_EXCEPTIONS -# include // NOLINT -#endif - -// Copyright 2007, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Author: wan@google.com (Zhanyong Wan) - -// Google Mock - a framework for writing C++ mock classes. -// -// This file implements some commonly used argument matchers. More -// matchers can be defined by the user implementing the -// MatcherInterface interface if necessary. - -#ifndef GMOCK_INCLUDE_GMOCK_GMOCK_MATCHERS_H_ -#define GMOCK_INCLUDE_GMOCK_GMOCK_MATCHERS_H_ - -#include -#include -#include -#include -#include // NOLINT -#include -#include -#include -#include - - -#if GTEST_HAS_STD_INITIALIZER_LIST_ -# include // NOLINT -- must be after gtest.h -#endif - -namespace testing { - -// To implement a matcher Foo for type T, define: -// 1. a class FooMatcherImpl that implements the -// MatcherInterface interface, and -// 2. a factory function that creates a Matcher object from a -// FooMatcherImpl*. -// -// The two-level delegation design makes it possible to allow a user -// to write "v" instead of "Eq(v)" where a Matcher is expected, which -// is impossible if we pass matchers by pointers. It also eases -// ownership management as Matcher objects can now be copied like -// plain values. - -// MatchResultListener is an abstract class. Its << operator can be -// used by a matcher to explain why a value matches or doesn't match. -// -// TODO(wan@google.com): add method -// bool InterestedInWhy(bool result) const; -// to indicate whether the listener is interested in why the match -// result is 'result'. -class MatchResultListener { - public: - // Creates a listener object with the given underlying ostream. The - // listener does not own the ostream, and does not dereference it - // in the constructor or destructor. - explicit MatchResultListener(::std::ostream* os) : stream_(os) {} - virtual ~MatchResultListener() = 0; // Makes this class abstract. - - // Streams x to the underlying ostream; does nothing if the ostream - // is NULL. - template - MatchResultListener& operator<<(const T& x) { - if (stream_ != NULL) - *stream_ << x; - return *this; - } - - // Returns the underlying ostream. - ::std::ostream* stream() { return stream_; } - - // Returns true iff the listener is interested in an explanation of - // the match result. A matcher's MatchAndExplain() method can use - // this information to avoid generating the explanation when no one - // intends to hear it. - bool IsInterested() const { return stream_ != NULL; } - - private: - ::std::ostream* const stream_; - - GTEST_DISALLOW_COPY_AND_ASSIGN_(MatchResultListener); -}; - -inline MatchResultListener::~MatchResultListener() { -} - -// An instance of a subclass of this knows how to describe itself as a -// matcher. -class MatcherDescriberInterface { - public: - virtual ~MatcherDescriberInterface() {} - - // Describes this matcher to an ostream. The function should print - // a verb phrase that describes the property a value matching this - // matcher should have. The subject of the verb phrase is the value - // being matched. For example, the DescribeTo() method of the Gt(7) - // matcher prints "is greater than 7". - virtual void DescribeTo(::std::ostream* os) const = 0; - - // Describes the negation of this matcher to an ostream. For - // example, if the description of this matcher is "is greater than - // 7", the negated description could be "is not greater than 7". - // You are not required to override this when implementing - // MatcherInterface, but it is highly advised so that your matcher - // can produce good error messages. - virtual void DescribeNegationTo(::std::ostream* os) const { - *os << "not ("; - DescribeTo(os); - *os << ")"; - } -}; - -// The implementation of a matcher. -template -class MatcherInterface : public MatcherDescriberInterface { - public: - // Returns true iff the matcher matches x; also explains the match - // result to 'listener' if necessary (see the next paragraph), in - // the form of a non-restrictive relative clause ("which ...", - // "whose ...", etc) that describes x. For example, the - // MatchAndExplain() method of the Pointee(...) matcher should - // generate an explanation like "which points to ...". - // - // Implementations of MatchAndExplain() should add an explanation of - // the match result *if and only if* they can provide additional - // information that's not already present (or not obvious) in the - // print-out of x and the matcher's description. Whether the match - // succeeds is not a factor in deciding whether an explanation is - // needed, as sometimes the caller needs to print a failure message - // when the match succeeds (e.g. when the matcher is used inside - // Not()). - // - // For example, a "has at least 10 elements" matcher should explain - // what the actual element count is, regardless of the match result, - // as it is useful information to the reader; on the other hand, an - // "is empty" matcher probably only needs to explain what the actual - // size is when the match fails, as it's redundant to say that the - // size is 0 when the value is already known to be empty. - // - // You should override this method when defining a new matcher. - // - // It's the responsibility of the caller (Google Mock) to guarantee - // that 'listener' is not NULL. This helps to simplify a matcher's - // implementation when it doesn't care about the performance, as it - // can talk to 'listener' without checking its validity first. - // However, in order to implement dummy listeners efficiently, - // listener->stream() may be NULL. - virtual bool MatchAndExplain(T x, MatchResultListener* listener) const = 0; - - // Inherits these methods from MatcherDescriberInterface: - // virtual void DescribeTo(::std::ostream* os) const = 0; - // virtual void DescribeNegationTo(::std::ostream* os) const; -}; - -// A match result listener that stores the explanation in a string. -class StringMatchResultListener : public MatchResultListener { - public: - StringMatchResultListener() : MatchResultListener(&ss_) {} - - // Returns the explanation accumulated so far. - internal::string str() const { return ss_.str(); } - - // Clears the explanation accumulated so far. - void Clear() { ss_.str(""); } - - private: - ::std::stringstream ss_; - - GTEST_DISALLOW_COPY_AND_ASSIGN_(StringMatchResultListener); -}; - -namespace internal { - -struct AnyEq { - template - bool operator()(const A& a, const B& b) const { return a == b; } -}; -struct AnyNe { - template - bool operator()(const A& a, const B& b) const { return a != b; } -}; -struct AnyLt { - template - bool operator()(const A& a, const B& b) const { return a < b; } -}; -struct AnyGt { - template - bool operator()(const A& a, const B& b) const { return a > b; } -}; -struct AnyLe { - template - bool operator()(const A& a, const B& b) const { return a <= b; } -}; -struct AnyGe { - template - bool operator()(const A& a, const B& b) const { return a >= b; } -}; - -// A match result listener that ignores the explanation. -class DummyMatchResultListener : public MatchResultListener { - public: - DummyMatchResultListener() : MatchResultListener(NULL) {} - - private: - GTEST_DISALLOW_COPY_AND_ASSIGN_(DummyMatchResultListener); -}; - -// A match result listener that forwards the explanation to a given -// ostream. The difference between this and MatchResultListener is -// that the former is concrete. -class StreamMatchResultListener : public MatchResultListener { - public: - explicit StreamMatchResultListener(::std::ostream* os) - : MatchResultListener(os) {} - - private: - GTEST_DISALLOW_COPY_AND_ASSIGN_(StreamMatchResultListener); -}; - -// An internal class for implementing Matcher, which will derive -// from it. We put functionalities common to all Matcher -// specializations here to avoid code duplication. -template -class MatcherBase { - public: - // Returns true iff the matcher matches x; also explains the match - // result to 'listener'. - bool MatchAndExplain(T x, MatchResultListener* listener) const { - return impl_->MatchAndExplain(x, listener); - } - - // Returns true iff this matcher matches x. - bool Matches(T x) const { - DummyMatchResultListener dummy; - return MatchAndExplain(x, &dummy); - } - - // Describes this matcher to an ostream. - void DescribeTo(::std::ostream* os) const { impl_->DescribeTo(os); } - - // Describes the negation of this matcher to an ostream. - void DescribeNegationTo(::std::ostream* os) const { - impl_->DescribeNegationTo(os); - } - - // Explains why x matches, or doesn't match, the matcher. - void ExplainMatchResultTo(T x, ::std::ostream* os) const { - StreamMatchResultListener listener(os); - MatchAndExplain(x, &listener); - } - - // Returns the describer for this matcher object; retains ownership - // of the describer, which is only guaranteed to be alive when - // this matcher object is alive. - const MatcherDescriberInterface* GetDescriber() const { - return impl_.get(); - } - - protected: - MatcherBase() {} - - // Constructs a matcher from its implementation. - explicit MatcherBase(const MatcherInterface* impl) - : impl_(impl) {} - - virtual ~MatcherBase() {} - - private: - // shared_ptr (util/gtl/shared_ptr.h) and linked_ptr have similar - // interfaces. The former dynamically allocates a chunk of memory - // to hold the reference count, while the latter tracks all - // references using a circular linked list without allocating - // memory. It has been observed that linked_ptr performs better in - // typical scenarios. However, shared_ptr can out-perform - // linked_ptr when there are many more uses of the copy constructor - // than the default constructor. - // - // If performance becomes a problem, we should see if using - // shared_ptr helps. - ::testing::internal::linked_ptr > impl_; -}; - -} // namespace internal - -// A Matcher is a copyable and IMMUTABLE (except by assignment) -// object that can check whether a value of type T matches. The -// implementation of Matcher is just a linked_ptr to const -// MatcherInterface, so copying is fairly cheap. Don't inherit -// from Matcher! -template -class Matcher : public internal::MatcherBase { - public: - // Constructs a null matcher. Needed for storing Matcher objects in STL - // containers. A default-constructed matcher is not yet initialized. You - // cannot use it until a valid value has been assigned to it. - explicit Matcher() {} // NOLINT - - // Constructs a matcher from its implementation. - explicit Matcher(const MatcherInterface* impl) - : internal::MatcherBase(impl) {} - - // Implicit constructor here allows people to write - // EXPECT_CALL(foo, Bar(5)) instead of EXPECT_CALL(foo, Bar(Eq(5))) sometimes - Matcher(T value); // NOLINT -}; - -// The following two specializations allow the user to write str -// instead of Eq(str) and "foo" instead of Eq("foo") when a string -// matcher is expected. -template <> -class GTEST_API_ Matcher - : public internal::MatcherBase { - public: - Matcher() {} - - explicit Matcher(const MatcherInterface* impl) - : internal::MatcherBase(impl) {} - - // Allows the user to write str instead of Eq(str) sometimes, where - // str is a string object. - Matcher(const internal::string& s); // NOLINT - - // Allows the user to write "foo" instead of Eq("foo") sometimes. - Matcher(const char* s); // NOLINT -}; - -template <> -class GTEST_API_ Matcher - : public internal::MatcherBase { - public: - Matcher() {} - - explicit Matcher(const MatcherInterface* impl) - : internal::MatcherBase(impl) {} - - // Allows the user to write str instead of Eq(str) sometimes, where - // str is a string object. - Matcher(const internal::string& s); // NOLINT - - // Allows the user to write "foo" instead of Eq("foo") sometimes. - Matcher(const char* s); // NOLINT -}; - -#if GTEST_HAS_STRING_PIECE_ -// The following two specializations allow the user to write str -// instead of Eq(str) and "foo" instead of Eq("foo") when a StringPiece -// matcher is expected. -template <> -class GTEST_API_ Matcher - : public internal::MatcherBase { - public: - Matcher() {} - - explicit Matcher(const MatcherInterface* impl) - : internal::MatcherBase(impl) {} - - // Allows the user to write str instead of Eq(str) sometimes, where - // str is a string object. - Matcher(const internal::string& s); // NOLINT - - // Allows the user to write "foo" instead of Eq("foo") sometimes. - Matcher(const char* s); // NOLINT - - // Allows the user to pass StringPieces directly. - Matcher(StringPiece s); // NOLINT -}; - -template <> -class GTEST_API_ Matcher - : public internal::MatcherBase { - public: - Matcher() {} - - explicit Matcher(const MatcherInterface* impl) - : internal::MatcherBase(impl) {} - - // Allows the user to write str instead of Eq(str) sometimes, where - // str is a string object. - Matcher(const internal::string& s); // NOLINT - - // Allows the user to write "foo" instead of Eq("foo") sometimes. - Matcher(const char* s); // NOLINT - - // Allows the user to pass StringPieces directly. - Matcher(StringPiece s); // NOLINT -}; -#endif // GTEST_HAS_STRING_PIECE_ - -// The PolymorphicMatcher class template makes it easy to implement a -// polymorphic matcher (i.e. a matcher that can match values of more -// than one type, e.g. Eq(n) and NotNull()). -// -// To define a polymorphic matcher, a user should provide an Impl -// class that has a DescribeTo() method and a DescribeNegationTo() -// method, and define a member function (or member function template) -// -// bool MatchAndExplain(const Value& value, -// MatchResultListener* listener) const; -// -// See the definition of NotNull() for a complete example. -template -class PolymorphicMatcher { - public: - explicit PolymorphicMatcher(const Impl& an_impl) : impl_(an_impl) {} - - // Returns a mutable reference to the underlying matcher - // implementation object. - Impl& mutable_impl() { return impl_; } - - // Returns an immutable reference to the underlying matcher - // implementation object. - const Impl& impl() const { return impl_; } - - template - operator Matcher() const { - return Matcher(new MonomorphicImpl(impl_)); - } - - private: - template - class MonomorphicImpl : public MatcherInterface { - public: - explicit MonomorphicImpl(const Impl& impl) : impl_(impl) {} - - virtual void DescribeTo(::std::ostream* os) const { - impl_.DescribeTo(os); - } - - virtual void DescribeNegationTo(::std::ostream* os) const { - impl_.DescribeNegationTo(os); - } - - virtual bool MatchAndExplain(T x, MatchResultListener* listener) const { - return impl_.MatchAndExplain(x, listener); - } - - private: - const Impl impl_; - - GTEST_DISALLOW_ASSIGN_(MonomorphicImpl); - }; - - Impl impl_; - - GTEST_DISALLOW_ASSIGN_(PolymorphicMatcher); -}; - -// Creates a matcher from its implementation. This is easier to use -// than the Matcher constructor as it doesn't require you to -// explicitly write the template argument, e.g. -// -// MakeMatcher(foo); -// vs -// Matcher(foo); -template -inline Matcher MakeMatcher(const MatcherInterface* impl) { - return Matcher(impl); -} - -// Creates a polymorphic matcher from its implementation. This is -// easier to use than the PolymorphicMatcher constructor as it -// doesn't require you to explicitly write the template argument, e.g. -// -// MakePolymorphicMatcher(foo); -// vs -// PolymorphicMatcher(foo); -template -inline PolymorphicMatcher MakePolymorphicMatcher(const Impl& impl) { - return PolymorphicMatcher(impl); -} - -// Anything inside the 'internal' namespace IS INTERNAL IMPLEMENTATION -// and MUST NOT BE USED IN USER CODE!!! -namespace internal { - -// The MatcherCastImpl class template is a helper for implementing -// MatcherCast(). We need this helper in order to partially -// specialize the implementation of MatcherCast() (C++ allows -// class/struct templates to be partially specialized, but not -// function templates.). - -// This general version is used when MatcherCast()'s argument is a -// polymorphic matcher (i.e. something that can be converted to a -// Matcher but is not one yet; for example, Eq(value)) or a value (for -// example, "hello"). -template -class MatcherCastImpl { - public: - static Matcher Cast(const M& polymorphic_matcher_or_value) { - // M can be a polymorhic matcher, in which case we want to use - // its conversion operator to create Matcher. Or it can be a value - // that should be passed to the Matcher's constructor. - // - // We can't call Matcher(polymorphic_matcher_or_value) when M is a - // polymorphic matcher because it'll be ambiguous if T has an implicit - // constructor from M (this usually happens when T has an implicit - // constructor from any type). - // - // It won't work to unconditionally implict_cast - // polymorphic_matcher_or_value to Matcher because it won't trigger - // a user-defined conversion from M to T if one exists (assuming M is - // a value). - return CastImpl( - polymorphic_matcher_or_value, - BooleanConstant< - internal::ImplicitlyConvertible >::value>()); - } - - private: - static Matcher CastImpl(const M& value, BooleanConstant) { - // M can't be implicitly converted to Matcher, so M isn't a polymorphic - // matcher. It must be a value then. Use direct initialization to create - // a matcher. - return Matcher(ImplicitCast_(value)); - } - - static Matcher CastImpl(const M& polymorphic_matcher_or_value, - BooleanConstant) { - // M is implicitly convertible to Matcher, which means that either - // M is a polymorhpic matcher or Matcher has an implicit constructor - // from M. In both cases using the implicit conversion will produce a - // matcher. - // - // Even if T has an implicit constructor from M, it won't be called because - // creating Matcher would require a chain of two user-defined conversions - // (first to create T from M and then to create Matcher from T). - return polymorphic_matcher_or_value; - } -}; - -// This more specialized version is used when MatcherCast()'s argument -// is already a Matcher. This only compiles when type T can be -// statically converted to type U. -template -class MatcherCastImpl > { - public: - static Matcher Cast(const Matcher& source_matcher) { - return Matcher(new Impl(source_matcher)); - } - - private: - class Impl : public MatcherInterface { - public: - explicit Impl(const Matcher& source_matcher) - : source_matcher_(source_matcher) {} - - // We delegate the matching logic to the source matcher. - virtual bool MatchAndExplain(T x, MatchResultListener* listener) const { - return source_matcher_.MatchAndExplain(static_cast(x), listener); - } - - virtual void DescribeTo(::std::ostream* os) const { - source_matcher_.DescribeTo(os); - } - - virtual void DescribeNegationTo(::std::ostream* os) const { - source_matcher_.DescribeNegationTo(os); - } - - private: - const Matcher source_matcher_; - - GTEST_DISALLOW_ASSIGN_(Impl); - }; -}; - -// This even more specialized version is used for efficiently casting -// a matcher to its own type. -template -class MatcherCastImpl > { - public: - static Matcher Cast(const Matcher& matcher) { return matcher; } -}; - -} // namespace internal - -// In order to be safe and clear, casting between different matcher -// types is done explicitly via MatcherCast(m), which takes a -// matcher m and returns a Matcher. It compiles only when T can be -// statically converted to the argument type of m. -template -inline Matcher MatcherCast(const M& matcher) { - return internal::MatcherCastImpl::Cast(matcher); -} - -// Implements SafeMatcherCast(). -// -// We use an intermediate class to do the actual safe casting as Nokia's -// Symbian compiler cannot decide between -// template ... (M) and -// template ... (const Matcher&) -// for function templates but can for member function templates. -template -class SafeMatcherCastImpl { - public: - // This overload handles polymorphic matchers and values only since - // monomorphic matchers are handled by the next one. - template - static inline Matcher Cast(const M& polymorphic_matcher_or_value) { - return internal::MatcherCastImpl::Cast(polymorphic_matcher_or_value); - } - - // This overload handles monomorphic matchers. - // - // In general, if type T can be implicitly converted to type U, we can - // safely convert a Matcher to a Matcher (i.e. Matcher is - // contravariant): just keep a copy of the original Matcher, convert the - // argument from type T to U, and then pass it to the underlying Matcher. - // The only exception is when U is a reference and T is not, as the - // underlying Matcher may be interested in the argument's address, which - // is not preserved in the conversion from T to U. - template - static inline Matcher Cast(const Matcher& matcher) { - // Enforce that T can be implicitly converted to U. - GTEST_COMPILE_ASSERT_((internal::ImplicitlyConvertible::value), - T_must_be_implicitly_convertible_to_U); - // Enforce that we are not converting a non-reference type T to a reference - // type U. - GTEST_COMPILE_ASSERT_( - internal::is_reference::value || !internal::is_reference::value, - cannot_convert_non_referentce_arg_to_reference); - // In case both T and U are arithmetic types, enforce that the - // conversion is not lossy. - typedef GTEST_REMOVE_REFERENCE_AND_CONST_(T) RawT; - typedef GTEST_REMOVE_REFERENCE_AND_CONST_(U) RawU; - const bool kTIsOther = GMOCK_KIND_OF_(RawT) == internal::kOther; - const bool kUIsOther = GMOCK_KIND_OF_(RawU) == internal::kOther; - GTEST_COMPILE_ASSERT_( - kTIsOther || kUIsOther || - (internal::LosslessArithmeticConvertible::value), - conversion_of_arithmetic_types_must_be_lossless); - return MatcherCast(matcher); - } -}; - -template -inline Matcher SafeMatcherCast(const M& polymorphic_matcher) { - return SafeMatcherCastImpl::Cast(polymorphic_matcher); -} - -// A() returns a matcher that matches any value of type T. -template -Matcher A(); - -// Anything inside the 'internal' namespace IS INTERNAL IMPLEMENTATION -// and MUST NOT BE USED IN USER CODE!!! -namespace internal { - -// If the explanation is not empty, prints it to the ostream. -inline void PrintIfNotEmpty(const internal::string& explanation, - ::std::ostream* os) { - if (explanation != "" && os != NULL) { - *os << ", " << explanation; - } -} - -// Returns true if the given type name is easy to read by a human. -// This is used to decide whether printing the type of a value might -// be helpful. -inline bool IsReadableTypeName(const string& type_name) { - // We consider a type name readable if it's short or doesn't contain - // a template or function type. - return (type_name.length() <= 20 || - type_name.find_first_of("<(") == string::npos); -} - -// Matches the value against the given matcher, prints the value and explains -// the match result to the listener. Returns the match result. -// 'listener' must not be NULL. -// Value cannot be passed by const reference, because some matchers take a -// non-const argument. -template -bool MatchPrintAndExplain(Value& value, const Matcher& matcher, - MatchResultListener* listener) { - if (!listener->IsInterested()) { - // If the listener is not interested, we do not need to construct the - // inner explanation. - return matcher.Matches(value); - } - - StringMatchResultListener inner_listener; - const bool match = matcher.MatchAndExplain(value, &inner_listener); - - UniversalPrint(value, listener->stream()); -#if GTEST_HAS_RTTI - const string& type_name = GetTypeName(); - if (IsReadableTypeName(type_name)) - *listener->stream() << " (of type " << type_name << ")"; -#endif - PrintIfNotEmpty(inner_listener.str(), listener->stream()); - - return match; -} - -// An internal helper class for doing compile-time loop on a tuple's -// fields. -template -class TuplePrefix { - public: - // TuplePrefix::Matches(matcher_tuple, value_tuple) returns true - // iff the first N fields of matcher_tuple matches the first N - // fields of value_tuple, respectively. - template - static bool Matches(const MatcherTuple& matcher_tuple, - const ValueTuple& value_tuple) { - return TuplePrefix::Matches(matcher_tuple, value_tuple) - && get(matcher_tuple).Matches(get(value_tuple)); - } - - // TuplePrefix::ExplainMatchFailuresTo(matchers, values, os) - // describes failures in matching the first N fields of matchers - // against the first N fields of values. If there is no failure, - // nothing will be streamed to os. - template - static void ExplainMatchFailuresTo(const MatcherTuple& matchers, - const ValueTuple& values, - ::std::ostream* os) { - // First, describes failures in the first N - 1 fields. - TuplePrefix::ExplainMatchFailuresTo(matchers, values, os); - - // Then describes the failure (if any) in the (N - 1)-th (0-based) - // field. - typename tuple_element::type matcher = - get(matchers); - typedef typename tuple_element::type Value; - Value value = get(values); - StringMatchResultListener listener; - if (!matcher.MatchAndExplain(value, &listener)) { - // TODO(wan): include in the message the name of the parameter - // as used in MOCK_METHOD*() when possible. - *os << " Expected arg #" << N - 1 << ": "; - get(matchers).DescribeTo(os); - *os << "\n Actual: "; - // We remove the reference in type Value to prevent the - // universal printer from printing the address of value, which - // isn't interesting to the user most of the time. The - // matcher's MatchAndExplain() method handles the case when - // the address is interesting. - internal::UniversalPrint(value, os); - PrintIfNotEmpty(listener.str(), os); - *os << "\n"; - } - } -}; - -// The base case. -template <> -class TuplePrefix<0> { - public: - template - static bool Matches(const MatcherTuple& /* matcher_tuple */, - const ValueTuple& /* value_tuple */) { - return true; - } - - template - static void ExplainMatchFailuresTo(const MatcherTuple& /* matchers */, - const ValueTuple& /* values */, - ::std::ostream* /* os */) {} -}; - -// TupleMatches(matcher_tuple, value_tuple) returns true iff all -// matchers in matcher_tuple match the corresponding fields in -// value_tuple. It is a compiler error if matcher_tuple and -// value_tuple have different number of fields or incompatible field -// types. -template -bool TupleMatches(const MatcherTuple& matcher_tuple, - const ValueTuple& value_tuple) { - // Makes sure that matcher_tuple and value_tuple have the same - // number of fields. - GTEST_COMPILE_ASSERT_(tuple_size::value == - tuple_size::value, - matcher_and_value_have_different_numbers_of_fields); - return TuplePrefix::value>:: - Matches(matcher_tuple, value_tuple); -} - -// Describes failures in matching matchers against values. If there -// is no failure, nothing will be streamed to os. -template -void ExplainMatchFailureTupleTo(const MatcherTuple& matchers, - const ValueTuple& values, - ::std::ostream* os) { - TuplePrefix::value>::ExplainMatchFailuresTo( - matchers, values, os); -} - -// TransformTupleValues and its helper. -// -// TransformTupleValuesHelper hides the internal machinery that -// TransformTupleValues uses to implement a tuple traversal. -template -class TransformTupleValuesHelper { - private: - typedef ::testing::tuple_size TupleSize; - - public: - // For each member of tuple 't', taken in order, evaluates '*out++ = f(t)'. - // Returns the final value of 'out' in case the caller needs it. - static OutIter Run(Func f, const Tuple& t, OutIter out) { - return IterateOverTuple()(f, t, out); - } - - private: - template - struct IterateOverTuple { - OutIter operator() (Func f, const Tup& t, OutIter out) const { - *out++ = f(::testing::get(t)); - return IterateOverTuple()(f, t, out); - } - }; - template - struct IterateOverTuple { - OutIter operator() (Func /* f */, const Tup& /* t */, OutIter out) const { - return out; - } - }; -}; - -// Successively invokes 'f(element)' on each element of the tuple 't', -// appending each result to the 'out' iterator. Returns the final value -// of 'out'. -template -OutIter TransformTupleValues(Func f, const Tuple& t, OutIter out) { - return TransformTupleValuesHelper::Run(f, t, out); -} - -// Implements A(). -template -class AnyMatcherImpl : public MatcherInterface { - public: - virtual bool MatchAndExplain( - T /* x */, MatchResultListener* /* listener */) const { return true; } - virtual void DescribeTo(::std::ostream* os) const { *os << "is anything"; } - virtual void DescribeNegationTo(::std::ostream* os) const { - // This is mostly for completeness' safe, as it's not very useful - // to write Not(A()). However we cannot completely rule out - // such a possibility, and it doesn't hurt to be prepared. - *os << "never matches"; - } -}; - -// Implements _, a matcher that matches any value of any -// type. This is a polymorphic matcher, so we need a template type -// conversion operator to make it appearing as a Matcher for any -// type T. -class AnythingMatcher { - public: - template - operator Matcher() const { return A(); } -}; - -// Implements a matcher that compares a given value with a -// pre-supplied value using one of the ==, <=, <, etc, operators. The -// two values being compared don't have to have the same type. -// -// The matcher defined here is polymorphic (for example, Eq(5) can be -// used to match an int, a short, a double, etc). Therefore we use -// a template type conversion operator in the implementation. -// -// The following template definition assumes that the Rhs parameter is -// a "bare" type (i.e. neither 'const T' nor 'T&'). -template -class ComparisonBase { - public: - explicit ComparisonBase(const Rhs& rhs) : rhs_(rhs) {} - template - operator Matcher() const { - return MakeMatcher(new Impl(rhs_)); - } - - private: - template - class Impl : public MatcherInterface { - public: - explicit Impl(const Rhs& rhs) : rhs_(rhs) {} - virtual bool MatchAndExplain( - Lhs lhs, MatchResultListener* /* listener */) const { - return Op()(lhs, rhs_); - } - virtual void DescribeTo(::std::ostream* os) const { - *os << D::Desc() << " "; - UniversalPrint(rhs_, os); - } - virtual void DescribeNegationTo(::std::ostream* os) const { - *os << D::NegatedDesc() << " "; - UniversalPrint(rhs_, os); - } - private: - Rhs rhs_; - GTEST_DISALLOW_ASSIGN_(Impl); - }; - Rhs rhs_; - GTEST_DISALLOW_ASSIGN_(ComparisonBase); -}; - -template -class EqMatcher : public ComparisonBase, Rhs, AnyEq> { - public: - explicit EqMatcher(const Rhs& rhs) - : ComparisonBase, Rhs, AnyEq>(rhs) { } - static const char* Desc() { return "is equal to"; } - static const char* NegatedDesc() { return "isn't equal to"; } -}; -template -class NeMatcher : public ComparisonBase, Rhs, AnyNe> { - public: - explicit NeMatcher(const Rhs& rhs) - : ComparisonBase, Rhs, AnyNe>(rhs) { } - static const char* Desc() { return "isn't equal to"; } - static const char* NegatedDesc() { return "is equal to"; } -}; -template -class LtMatcher : public ComparisonBase, Rhs, AnyLt> { - public: - explicit LtMatcher(const Rhs& rhs) - : ComparisonBase, Rhs, AnyLt>(rhs) { } - static const char* Desc() { return "is <"; } - static const char* NegatedDesc() { return "isn't <"; } -}; -template -class GtMatcher : public ComparisonBase, Rhs, AnyGt> { - public: - explicit GtMatcher(const Rhs& rhs) - : ComparisonBase, Rhs, AnyGt>(rhs) { } - static const char* Desc() { return "is >"; } - static const char* NegatedDesc() { return "isn't >"; } -}; -template -class LeMatcher : public ComparisonBase, Rhs, AnyLe> { - public: - explicit LeMatcher(const Rhs& rhs) - : ComparisonBase, Rhs, AnyLe>(rhs) { } - static const char* Desc() { return "is <="; } - static const char* NegatedDesc() { return "isn't <="; } -}; -template -class GeMatcher : public ComparisonBase, Rhs, AnyGe> { - public: - explicit GeMatcher(const Rhs& rhs) - : ComparisonBase, Rhs, AnyGe>(rhs) { } - static const char* Desc() { return "is >="; } - static const char* NegatedDesc() { return "isn't >="; } -}; - -// Implements the polymorphic IsNull() matcher, which matches any raw or smart -// pointer that is NULL. -class IsNullMatcher { - public: - template - bool MatchAndExplain(const Pointer& p, - MatchResultListener* /* listener */) const { -#if GTEST_LANG_CXX11 - return p == nullptr; -#else // GTEST_LANG_CXX11 - return GetRawPointer(p) == NULL; -#endif // GTEST_LANG_CXX11 - } - - void DescribeTo(::std::ostream* os) const { *os << "is NULL"; } - void DescribeNegationTo(::std::ostream* os) const { - *os << "isn't NULL"; - } -}; - -// Implements the polymorphic NotNull() matcher, which matches any raw or smart -// pointer that is not NULL. -class NotNullMatcher { - public: - template - bool MatchAndExplain(const Pointer& p, - MatchResultListener* /* listener */) const { -#if GTEST_LANG_CXX11 - return p != nullptr; -#else // GTEST_LANG_CXX11 - return GetRawPointer(p) != NULL; -#endif // GTEST_LANG_CXX11 - } - - void DescribeTo(::std::ostream* os) const { *os << "isn't NULL"; } - void DescribeNegationTo(::std::ostream* os) const { - *os << "is NULL"; - } -}; - -// Ref(variable) matches any argument that is a reference to -// 'variable'. This matcher is polymorphic as it can match any -// super type of the type of 'variable'. -// -// The RefMatcher template class implements Ref(variable). It can -// only be instantiated with a reference type. This prevents a user -// from mistakenly using Ref(x) to match a non-reference function -// argument. For example, the following will righteously cause a -// compiler error: -// -// int n; -// Matcher m1 = Ref(n); // This won't compile. -// Matcher m2 = Ref(n); // This will compile. -template -class RefMatcher; - -template -class RefMatcher { - // Google Mock is a generic framework and thus needs to support - // mocking any function types, including those that take non-const - // reference arguments. Therefore the template parameter T (and - // Super below) can be instantiated to either a const type or a - // non-const type. - public: - // RefMatcher() takes a T& instead of const T&, as we want the - // compiler to catch using Ref(const_value) as a matcher for a - // non-const reference. - explicit RefMatcher(T& x) : object_(x) {} // NOLINT - - template - operator Matcher() const { - // By passing object_ (type T&) to Impl(), which expects a Super&, - // we make sure that Super is a super type of T. In particular, - // this catches using Ref(const_value) as a matcher for a - // non-const reference, as you cannot implicitly convert a const - // reference to a non-const reference. - return MakeMatcher(new Impl(object_)); - } - - private: - template - class Impl : public MatcherInterface { - public: - explicit Impl(Super& x) : object_(x) {} // NOLINT - - // MatchAndExplain() takes a Super& (as opposed to const Super&) - // in order to match the interface MatcherInterface. - virtual bool MatchAndExplain( - Super& x, MatchResultListener* listener) const { - *listener << "which is located @" << static_cast(&x); - return &x == &object_; - } - - virtual void DescribeTo(::std::ostream* os) const { - *os << "references the variable "; - UniversalPrinter::Print(object_, os); - } - - virtual void DescribeNegationTo(::std::ostream* os) const { - *os << "does not reference the variable "; - UniversalPrinter::Print(object_, os); - } - - private: - const Super& object_; - - GTEST_DISALLOW_ASSIGN_(Impl); - }; - - T& object_; - - GTEST_DISALLOW_ASSIGN_(RefMatcher); -}; - -// Polymorphic helper functions for narrow and wide string matchers. -inline bool CaseInsensitiveCStringEquals(const char* lhs, const char* rhs) { - return String::CaseInsensitiveCStringEquals(lhs, rhs); -} - -inline bool CaseInsensitiveCStringEquals(const wchar_t* lhs, - const wchar_t* rhs) { - return String::CaseInsensitiveWideCStringEquals(lhs, rhs); -} - -// String comparison for narrow or wide strings that can have embedded NUL -// characters. -template -bool CaseInsensitiveStringEquals(const StringType& s1, - const StringType& s2) { - // Are the heads equal? - if (!CaseInsensitiveCStringEquals(s1.c_str(), s2.c_str())) { - return false; - } - - // Skip the equal heads. - const typename StringType::value_type nul = 0; - const size_t i1 = s1.find(nul), i2 = s2.find(nul); - - // Are we at the end of either s1 or s2? - if (i1 == StringType::npos || i2 == StringType::npos) { - return i1 == i2; - } - - // Are the tails equal? - return CaseInsensitiveStringEquals(s1.substr(i1 + 1), s2.substr(i2 + 1)); -} - -// String matchers. - -// Implements equality-based string matchers like StrEq, StrCaseNe, and etc. -template -class StrEqualityMatcher { - public: - StrEqualityMatcher(const StringType& str, bool expect_eq, - bool case_sensitive) - : string_(str), expect_eq_(expect_eq), case_sensitive_(case_sensitive) {} - - // Accepts pointer types, particularly: - // const char* - // char* - // const wchar_t* - // wchar_t* - template - bool MatchAndExplain(CharType* s, MatchResultListener* listener) const { - if (s == NULL) { - return !expect_eq_; - } - return MatchAndExplain(StringType(s), listener); - } - - // Matches anything that can convert to StringType. - // - // This is a template, not just a plain function with const StringType&, - // because StringPiece has some interfering non-explicit constructors. - template - bool MatchAndExplain(const MatcheeStringType& s, - MatchResultListener* /* listener */) const { - const StringType& s2(s); - const bool eq = case_sensitive_ ? s2 == string_ : - CaseInsensitiveStringEquals(s2, string_); - return expect_eq_ == eq; - } - - void DescribeTo(::std::ostream* os) const { - DescribeToHelper(expect_eq_, os); - } - - void DescribeNegationTo(::std::ostream* os) const { - DescribeToHelper(!expect_eq_, os); - } - - private: - void DescribeToHelper(bool expect_eq, ::std::ostream* os) const { - *os << (expect_eq ? "is " : "isn't "); - *os << "equal to "; - if (!case_sensitive_) { - *os << "(ignoring case) "; - } - UniversalPrint(string_, os); - } - - const StringType string_; - const bool expect_eq_; - const bool case_sensitive_; - - GTEST_DISALLOW_ASSIGN_(StrEqualityMatcher); -}; - -// Implements the polymorphic HasSubstr(substring) matcher, which -// can be used as a Matcher as long as T can be converted to a -// string. -template -class HasSubstrMatcher { - public: - explicit HasSubstrMatcher(const StringType& substring) - : substring_(substring) {} - - // Accepts pointer types, particularly: - // const char* - // char* - // const wchar_t* - // wchar_t* - template - bool MatchAndExplain(CharType* s, MatchResultListener* listener) const { - return s != NULL && MatchAndExplain(StringType(s), listener); - } - - // Matches anything that can convert to StringType. - // - // This is a template, not just a plain function with const StringType&, - // because StringPiece has some interfering non-explicit constructors. - template - bool MatchAndExplain(const MatcheeStringType& s, - MatchResultListener* /* listener */) const { - const StringType& s2(s); - return s2.find(substring_) != StringType::npos; - } - - // Describes what this matcher matches. - void DescribeTo(::std::ostream* os) const { - *os << "has substring "; - UniversalPrint(substring_, os); - } - - void DescribeNegationTo(::std::ostream* os) const { - *os << "has no substring "; - UniversalPrint(substring_, os); - } - - private: - const StringType substring_; - - GTEST_DISALLOW_ASSIGN_(HasSubstrMatcher); -}; - -// Implements the polymorphic StartsWith(substring) matcher, which -// can be used as a Matcher as long as T can be converted to a -// string. -template -class StartsWithMatcher { - public: - explicit StartsWithMatcher(const StringType& prefix) : prefix_(prefix) { - } - - // Accepts pointer types, particularly: - // const char* - // char* - // const wchar_t* - // wchar_t* - template - bool MatchAndExplain(CharType* s, MatchResultListener* listener) const { - return s != NULL && MatchAndExplain(StringType(s), listener); - } - - // Matches anything that can convert to StringType. - // - // This is a template, not just a plain function with const StringType&, - // because StringPiece has some interfering non-explicit constructors. - template - bool MatchAndExplain(const MatcheeStringType& s, - MatchResultListener* /* listener */) const { - const StringType& s2(s); - return s2.length() >= prefix_.length() && - s2.substr(0, prefix_.length()) == prefix_; - } - - void DescribeTo(::std::ostream* os) const { - *os << "starts with "; - UniversalPrint(prefix_, os); - } - - void DescribeNegationTo(::std::ostream* os) const { - *os << "doesn't start with "; - UniversalPrint(prefix_, os); - } - - private: - const StringType prefix_; - - GTEST_DISALLOW_ASSIGN_(StartsWithMatcher); -}; - -// Implements the polymorphic EndsWith(substring) matcher, which -// can be used as a Matcher as long as T can be converted to a -// string. -template -class EndsWithMatcher { - public: - explicit EndsWithMatcher(const StringType& suffix) : suffix_(suffix) {} - - // Accepts pointer types, particularly: - // const char* - // char* - // const wchar_t* - // wchar_t* - template - bool MatchAndExplain(CharType* s, MatchResultListener* listener) const { - return s != NULL && MatchAndExplain(StringType(s), listener); - } - - // Matches anything that can convert to StringType. - // - // This is a template, not just a plain function with const StringType&, - // because StringPiece has some interfering non-explicit constructors. - template - bool MatchAndExplain(const MatcheeStringType& s, - MatchResultListener* /* listener */) const { - const StringType& s2(s); - return s2.length() >= suffix_.length() && - s2.substr(s2.length() - suffix_.length()) == suffix_; - } - - void DescribeTo(::std::ostream* os) const { - *os << "ends with "; - UniversalPrint(suffix_, os); - } - - void DescribeNegationTo(::std::ostream* os) const { - *os << "doesn't end with "; - UniversalPrint(suffix_, os); - } - - private: - const StringType suffix_; - - GTEST_DISALLOW_ASSIGN_(EndsWithMatcher); -}; - -// Implements polymorphic matchers MatchesRegex(regex) and -// ContainsRegex(regex), which can be used as a Matcher as long as -// T can be converted to a string. -class MatchesRegexMatcher { - public: - MatchesRegexMatcher(const RE* regex, bool full_match) - : regex_(regex), full_match_(full_match) {} - - // Accepts pointer types, particularly: - // const char* - // char* - // const wchar_t* - // wchar_t* - template - bool MatchAndExplain(CharType* s, MatchResultListener* listener) const { - return s != NULL && MatchAndExplain(internal::string(s), listener); - } - - // Matches anything that can convert to internal::string. - // - // This is a template, not just a plain function with const internal::string&, - // because StringPiece has some interfering non-explicit constructors. - template - bool MatchAndExplain(const MatcheeStringType& s, - MatchResultListener* /* listener */) const { - const internal::string& s2(s); - return full_match_ ? RE::FullMatch(s2, *regex_) : - RE::PartialMatch(s2, *regex_); - } - - void DescribeTo(::std::ostream* os) const { - *os << (full_match_ ? "matches" : "contains") - << " regular expression "; - UniversalPrinter::Print(regex_->pattern(), os); - } - - void DescribeNegationTo(::std::ostream* os) const { - *os << "doesn't " << (full_match_ ? "match" : "contain") - << " regular expression "; - UniversalPrinter::Print(regex_->pattern(), os); - } - - private: - const internal::linked_ptr regex_; - const bool full_match_; - - GTEST_DISALLOW_ASSIGN_(MatchesRegexMatcher); -}; - -// Implements a matcher that compares the two fields of a 2-tuple -// using one of the ==, <=, <, etc, operators. The two fields being -// compared don't have to have the same type. -// -// The matcher defined here is polymorphic (for example, Eq() can be -// used to match a tuple, a tuple, -// etc). Therefore we use a template type conversion operator in the -// implementation. -template -class PairMatchBase { - public: - template - operator Matcher< ::testing::tuple >() const { - return MakeMatcher(new Impl< ::testing::tuple >); - } - template - operator Matcher&>() const { - return MakeMatcher(new Impl&>); - } - - private: - static ::std::ostream& GetDesc(::std::ostream& os) { // NOLINT - return os << D::Desc(); - } - - template - class Impl : public MatcherInterface { - public: - virtual bool MatchAndExplain( - Tuple args, - MatchResultListener* /* listener */) const { - return Op()(::testing::get<0>(args), ::testing::get<1>(args)); - } - virtual void DescribeTo(::std::ostream* os) const { - *os << "are " << GetDesc; - } - virtual void DescribeNegationTo(::std::ostream* os) const { - *os << "aren't " << GetDesc; - } - }; -}; - -class Eq2Matcher : public PairMatchBase { - public: - static const char* Desc() { return "an equal pair"; } -}; -class Ne2Matcher : public PairMatchBase { - public: - static const char* Desc() { return "an unequal pair"; } -}; -class Lt2Matcher : public PairMatchBase { - public: - static const char* Desc() { return "a pair where the first < the second"; } -}; -class Gt2Matcher : public PairMatchBase { - public: - static const char* Desc() { return "a pair where the first > the second"; } -}; -class Le2Matcher : public PairMatchBase { - public: - static const char* Desc() { return "a pair where the first <= the second"; } -}; -class Ge2Matcher : public PairMatchBase { - public: - static const char* Desc() { return "a pair where the first >= the second"; } -}; - -// Implements the Not(...) matcher for a particular argument type T. -// We do not nest it inside the NotMatcher class template, as that -// will prevent different instantiations of NotMatcher from sharing -// the same NotMatcherImpl class. -template -class NotMatcherImpl : public MatcherInterface { - public: - explicit NotMatcherImpl(const Matcher& matcher) - : matcher_(matcher) {} - - virtual bool MatchAndExplain(T x, MatchResultListener* listener) const { - return !matcher_.MatchAndExplain(x, listener); - } - - virtual void DescribeTo(::std::ostream* os) const { - matcher_.DescribeNegationTo(os); - } - - virtual void DescribeNegationTo(::std::ostream* os) const { - matcher_.DescribeTo(os); - } - - private: - const Matcher matcher_; - - GTEST_DISALLOW_ASSIGN_(NotMatcherImpl); -}; - -// Implements the Not(m) matcher, which matches a value that doesn't -// match matcher m. -template -class NotMatcher { - public: - explicit NotMatcher(InnerMatcher matcher) : matcher_(matcher) {} - - // This template type conversion operator allows Not(m) to be used - // to match any type m can match. - template - operator Matcher() const { - return Matcher(new NotMatcherImpl(SafeMatcherCast(matcher_))); - } - - private: - InnerMatcher matcher_; - - GTEST_DISALLOW_ASSIGN_(NotMatcher); -}; - -// Implements the AllOf(m1, m2) matcher for a particular argument type -// T. We do not nest it inside the BothOfMatcher class template, as -// that will prevent different instantiations of BothOfMatcher from -// sharing the same BothOfMatcherImpl class. -template -class BothOfMatcherImpl : public MatcherInterface { - public: - BothOfMatcherImpl(const Matcher& matcher1, const Matcher& matcher2) - : matcher1_(matcher1), matcher2_(matcher2) {} - - virtual void DescribeTo(::std::ostream* os) const { - *os << "("; - matcher1_.DescribeTo(os); - *os << ") and ("; - matcher2_.DescribeTo(os); - *os << ")"; - } - - virtual void DescribeNegationTo(::std::ostream* os) const { - *os << "("; - matcher1_.DescribeNegationTo(os); - *os << ") or ("; - matcher2_.DescribeNegationTo(os); - *os << ")"; - } - - virtual bool MatchAndExplain(T x, MatchResultListener* listener) const { - // If either matcher1_ or matcher2_ doesn't match x, we only need - // to explain why one of them fails. - StringMatchResultListener listener1; - if (!matcher1_.MatchAndExplain(x, &listener1)) { - *listener << listener1.str(); - return false; - } - - StringMatchResultListener listener2; - if (!matcher2_.MatchAndExplain(x, &listener2)) { - *listener << listener2.str(); - return false; - } - - // Otherwise we need to explain why *both* of them match. - const internal::string s1 = listener1.str(); - const internal::string s2 = listener2.str(); - - if (s1 == "") { - *listener << s2; - } else { - *listener << s1; - if (s2 != "") { - *listener << ", and " << s2; - } - } - return true; - } - - private: - const Matcher matcher1_; - const Matcher matcher2_; - - GTEST_DISALLOW_ASSIGN_(BothOfMatcherImpl); -}; - -#if GTEST_LANG_CXX11 -// MatcherList provides mechanisms for storing a variable number of matchers in -// a list structure (ListType) and creating a combining matcher from such a -// list. -// The template is defined recursively using the following template paramters: -// * kSize is the length of the MatcherList. -// * Head is the type of the first matcher of the list. -// * Tail denotes the types of the remaining matchers of the list. -template -struct MatcherList { - typedef MatcherList MatcherListTail; - typedef ::std::pair ListType; - - // BuildList stores variadic type values in a nested pair structure. - // Example: - // MatcherList<3, int, string, float>::BuildList(5, "foo", 2.0) will return - // the corresponding result of type pair>. - static ListType BuildList(const Head& matcher, const Tail&... tail) { - return ListType(matcher, MatcherListTail::BuildList(tail...)); - } - - // CreateMatcher creates a Matcher from a given list of matchers (built - // by BuildList()). CombiningMatcher is used to combine the matchers of the - // list. CombiningMatcher must implement MatcherInterface and have a - // constructor taking two Matchers as input. - template class CombiningMatcher> - static Matcher CreateMatcher(const ListType& matchers) { - return Matcher(new CombiningMatcher( - SafeMatcherCast(matchers.first), - MatcherListTail::template CreateMatcher( - matchers.second))); - } -}; - -// The following defines the base case for the recursive definition of -// MatcherList. -template -struct MatcherList<2, Matcher1, Matcher2> { - typedef ::std::pair ListType; - - static ListType BuildList(const Matcher1& matcher1, - const Matcher2& matcher2) { - return ::std::pair(matcher1, matcher2); - } - - template class CombiningMatcher> - static Matcher CreateMatcher(const ListType& matchers) { - return Matcher(new CombiningMatcher( - SafeMatcherCast(matchers.first), - SafeMatcherCast(matchers.second))); - } -}; - -// VariadicMatcher is used for the variadic implementation of -// AllOf(m_1, m_2, ...) and AnyOf(m_1, m_2, ...). -// CombiningMatcher is used to recursively combine the provided matchers -// (of type Args...). -template