796{
797 assert(a.get_type() != SurfaceFeatureType::Undef && b.get_type() != SurfaceFeatureType::Undef);
798
799 const bool swap = int(a.get_type()) > int(b.get_type());
802
804
808 if (f1.
get_type() == SurfaceFeatureType::Point) {
809 if (f2.
get_type() == SurfaceFeatureType::Point) {
813
815 }
else if (f2.
get_type() == SurfaceFeatureType::Edge) {
818 const double dist_inf = line.distance(f1.
get_point());
819 const Vec3d proj = line.projection(f1.
get_point());
820 const double len_sq = (e-s).squaredNorm();
821 const double dist_start_sq = (proj-s).squaredNorm();
822 const double dist_end_sq = (proj-e).squaredNorm();
823 if (dist_start_sq < len_sq && dist_end_sq < len_sq) {
824
826 } else {
827 const bool s_is_closer = dist_start_sq < dist_end_sq;
828 result.
distance_strict = std::make_optional(DistAndPoints{std::sqrt(std::min(dist_start_sq, dist_end_sq) +
sqr(dist_inf)), f1.
get_point(), s_is_closer ? s : e});
829 }
832 }
else if (f2.
get_type() == SurfaceFeatureType::Circle) {
833
837 if (proj.isApprox(c)) {
839 result.
distance_strict = std::make_optional(DistAndPoints{ radius,
c, p_on_circle });
840 }
841 else {
844 const double dist = std::sqrt(std::pow((proj - c).norm() - radius, 2.) +
846
847 const Vec3d p_on_circle =
c + radius * (proj -
c).normalized();
849 }
851 }
else if (f2.
get_type() == SurfaceFeatureType::Plane) {
855
856 }
860 }
861 else if (f1.
get_type() == SurfaceFeatureType::Edge) {
862 if (f2.
get_type() == SurfaceFeatureType::Edge) {
863 std::vector<DistAndPoints> distances;
864
865 auto add_point_edge_distance = [&distances](
const Vec3d& v,
const std::pair<Vec3d, Vec3d>& e) {
866 const MeasurementResult res =
get_measurement(SurfaceFeature(v), SurfaceFeature(SurfaceFeatureType::Edge, e.first, e.second));
867 double distance = res.distance_strict->dist;
868 Vec3d v2 = res.distance_strict->to;
869
870 const Vec3d e1e2 = e.second - e.first;
871 const Vec3d e1v2 = v2 - e.first;
872 if (e1v2.dot(e1e2) >= 0.0 && e1v2.norm() < e1e2.norm())
873 distances.emplace_back(distance, v, v2);
874 };
875
876 std::pair<Vec3d, Vec3d> e1 = f1.
get_edge();
877 std::pair<Vec3d, Vec3d> e2 = f2.
get_edge();
878
879 distances.emplace_back((e2.first - e1.first).norm(), e1.first, e2.first);
880 distances.emplace_back((e2.second - e1.first).norm(), e1.first, e2.second);
881 distances.emplace_back((e2.first - e1.second).norm(), e1.second, e2.first);
882 distances.emplace_back((e2.second - e1.second).norm(), e1.second, e2.second);
883 add_point_edge_distance(e1.first, e2);
884 add_point_edge_distance(e1.second, e2);
885 add_point_edge_distance(e2.first, e1);
886 add_point_edge_distance(e2.second, e1);
887 auto it = std::min_element(distances.begin(), distances.end(),
888 [](const DistAndPoints& item1, const DistAndPoints& item2) {
889 return item1.dist < item2.dist;
890 });
892
895 }
else if (f2.
get_type() == SurfaceFeatureType::Circle) {
896 const std::pair<Vec3d, Vec3d> e = f1.
get_edge();
898 const Vec3d e1e2 = (e.second - e.first);
899 const Vec3d e1e2_unit = e1e2.normalized();
900
901 std::vector<DistAndPoints> distances;
904
908 const Vec3d e1inter = inter - e.first;
909 if (e1inter.dot(e1e2) >= 0.0 && e1inter.norm() < e1e2.norm())
910 distances.emplace_back(*
get_measurement(SurfaceFeature(inter), f2).distance_strict);
911
912 auto it = std::min_element(distances.begin(), distances.end(),
913 [](const DistAndPoints& item1, const DistAndPoints& item2) {
914 return item1.dist < item2.dist;
915 });
916 result.
distance_infinite = std::make_optional(DistAndPoints{it->dist, it->from, it->to});
918 }
else if (f2.
get_type() == SurfaceFeatureType::Plane) {
919 assert(measuring != nullptr);
920
921 const auto [from, to] = f1.
get_edge();
923
924 const Vec3d edge_unit = (to - from).normalized();
926 std::vector<DistAndPoints> distances;
928 distances.push_back(DistAndPoints{ plane.absDistance(from), from, plane.projection(from) });
929 distances.push_back(DistAndPoints{ plane.absDistance(to), to, plane.projection(to) });
930 auto it = std::min_element(distances.begin(), distances.end(),
931 [](const DistAndPoints& item1, const DistAndPoints& item2) {
932 return item1.dist < item2.dist;
933 });
934 result.
distance_infinite = std::make_optional(DistAndPoints{ it->dist, it->from, it->to });
935 }
936 else {
937 const std::vector<SurfaceFeature>& plane_features = measuring->
get_plane_features(idx);
938 std::vector<DistAndPoints> distances;
939 for (const SurfaceFeature& sf : plane_features) {
940 if (sf.get_type() == SurfaceFeatureType::Edge) {
942 if (!m.distance_infinite.has_value()) {
943 distances.clear();
944 break;
945 }
946 else
947 distances.push_back(*m.distance_infinite);
948 }
949 }
950 if (!distances.empty()) {
951 auto it = std::min_element(distances.begin(), distances.end(),
952 [](const DistAndPoints& item1, const DistAndPoints& item2) {
953 return item1.dist < item2.dist;
954 });
955 result.
distance_infinite = std::make_optional(DistAndPoints{ it->dist, it->from, it->to });
956 }
957 }
959 }
963 }
else if (f1.
get_type() == SurfaceFeatureType::Circle) {
964 if (f2.
get_type() == SurfaceFeatureType::Circle) {
967
968
969
970
971
972
973 struct ClosestInfo
974 {
975 double sqrDistance{ 0.0 };
976 Vec3d circle0Closest{ Vec3d::Zero() };
977 Vec3d circle1Closest{ Vec3d::Zero() };
978
979 inline bool operator < (const ClosestInfo& other) const { return sqrDistance < other.sqrDistance; }
980 };
981 std::array<ClosestInfo, 16> candidates{};
982
983 const double zero = 0.0;
984
985 const Vec3d D = c1 - c0;
986
988
989 const double one = 1.0;
990 const double two = 2.0;
991 const double r0sqr =
sqr(r0);
992 const double r1sqr =
sqr(r1);
993
994
996 const Vec3d U1 = basis[0];
997 const Vec3d V1 = basis[1];
998
999
1000 const Vec3d N0xD = n0.cross(D);
1001 const Vec3d N0xU1 = n0.cross(U1);
1002 const Vec3d N0xV1 = n0.cross(V1);
1003 const double a0 = r1 * D.dot(U1);
1004 const double a1 = r1 * D.dot(V1);
1005 const double a2 = N0xD.dot(N0xD);
1006 const double a3 = r1 * N0xD.dot(N0xU1);
1007 const double a4 = r1 * N0xD.dot(N0xV1);
1008 const double a5 = r1sqr * N0xU1.dot(N0xU1);
1009 const double a6 = r1sqr * N0xU1.dot(N0xV1);
1010 const double a7 = r1sqr * N0xV1.dot(N0xV1);
1011 Polynomial1 p0{ a2 + a7, two * a3, a5 - a7 };
1012 Polynomial1 p1{ two * a4, two * a6 };
1013 Polynomial1 p2{ zero, a1 };
1014 Polynomial1 p3{ -a0 };
1015 Polynomial1 p4{ -a6, a4, two * a6 };
1016 Polynomial1 p5{ -a3, a7 - a5 };
1017 Polynomial1 tmp0{ one, zero, -one };
1018 Polynomial1 tmp1 = p2 * p2 + tmp0 * p3 * p3;
1019 Polynomial1 tmp2 = two * p2 * p3;
1020 Polynomial1 tmp3 = p4 * p4 + tmp0 * p5 * p5;
1021 Polynomial1 tmp4 = two * p4 * p5;
1022 Polynomial1 p6 = p0 * tmp1 + tmp0 * p1 * tmp2 - r0sqr * tmp3;
1023 Polynomial1 p7 = p0 * tmp2 + p1 * tmp1 - r0sqr * tmp4;
1024
1025
1026
1027
1028
1029
1030
1031 const uint32_t maxIterations = 128;
1033 size_t numRoots = 0;
1034 std::array<double, 8> roots{};
1035 std::set<double> uniqueRoots{};
1036 size_t numPairs = 0;
1037 std::array<std::pair<double, double>, 16> pairs{};
1038 double temp = zero;
1039 double sn = zero;
1040
1041 if (p7.GetDegree() > 0 || p7[0] != zero) {
1042
1043 Polynomial1 phi = p6 * p6 - tmp0 * p7 * p7;
1044 degree =
static_cast<int32_t>(phi.GetDegree());
1045 assert(degree > 0);
1046 numRoots = RootsPolynomial::Find(degree, &phi[0], maxIterations, roots.data());
1047 for (size_t i = 0; i < numRoots; ++i) {
1048 uniqueRoots.insert(roots[i]);
1049 }
1050
1051 for (auto const& cs : uniqueRoots) {
1052 if (std::fabs(cs) <= one) {
1053 temp = p7(cs);
1054 if (temp != zero) {
1055 sn = -p6(cs) / temp;
1056 pairs[numPairs++] = std::make_pair(cs, sn);
1057 }
1058 else {
1059 temp = std::max(one -
sqr(cs), zero);
1060 sn = std::sqrt(temp);
1061 pairs[numPairs++] = std::make_pair(cs, sn);
1062 if (sn != zero)
1063 pairs[numPairs++] = std::make_pair(cs, -sn);
1064 }
1065 }
1066 }
1067 }
1068 else {
1069
1070 degree =
static_cast<int32_t>(p6.GetDegree());
1071 assert(degree > 0);
1072 numRoots = RootsPolynomial::Find(degree, &p6[0], maxIterations, roots.data());
1073 for (size_t i = 0; i < numRoots; ++i) {
1074 uniqueRoots.insert(roots[i]);
1075 }
1076
1077 for (auto const& cs : uniqueRoots) {
1078 if (std::fabs(cs) <= one) {
1079 temp = std::max(one -
sqr(cs), zero);
1080 sn = std::sqrt(temp);
1081 pairs[numPairs++] = std::make_pair(cs, sn);
1082 if (sn != zero)
1083 pairs[numPairs++] = std::make_pair(cs, -sn);
1084 }
1085 }
1086 }
1087
1088 for (size_t i = 0; i < numPairs; ++i) {
1089 ClosestInfo& info = candidates[i];
1090 Vec3d delta = D + r1 * (pairs[i].first * U1 + pairs[i].second * V1);
1091 info.circle1Closest = c0 + delta;
1092 const double N0dDelta = n0.dot(delta);
1093 const double lenN0xDelta = n0.cross(delta).norm();
1094 if (lenN0xDelta > 0.0) {
1095 const double diff = lenN0xDelta - r0;
1096 info.sqrDistance =
sqr(N0dDelta) +
sqr(diff);
1097 delta -= N0dDelta * n0;
1098 delta.normalize();
1099 info.circle0Closest = c0 + r0 * delta;
1100 }
1101 else {
1104 info.sqrDistance =
diff.dot(diff);
1105 info.circle0Closest = c0 + r0U0;
1106 }
1107 }
1108
1109 std::sort(candidates.begin(), candidates.begin() + numPairs);
1110 }
1111 else {
1112 ClosestInfo& info = candidates[0];
1113
1114 const double N0dD = n0.dot(D);
1115 const Vec3d normProj = N0dD * n0;
1116 const Vec3d compProj = D - normProj;
1118 const double d = U.norm();
1119 U.normalize();
1120
1121
1122
1123
1124
1125 const double dmr1 =
d - r1;
1127 if (dmr1 >= r0) {
1128
1129
1130
1132 info.circle0Closest = c0 + r0 * U;
1133 info.circle1Closest = c1 - r1 * U;
1134 }
1135 else {
1136
1137
1138 const double dpr1 =
d + r1;
1139 if (dpr1 <= r0) {
1140
1142 if (d > 0.0) {
1143 info.circle0Closest = c0 + r0 * U;
1144 info.circle1Closest = c1 + r1 * U;
1145 }
1146 else {
1147
1148
1149
1151 info.circle0Closest = c0 + r0 * U;
1152 info.circle1Closest = c1 + r1 * U;
1153 }
1154 }
1155 else if (dmr1 <= -r0) {
1156
1158 if (d > 0.0) {
1159 info.circle0Closest = c0 - r0 * U;
1160 info.circle1Closest = c1 - r1 * U;
1161 }
1162 else {
1163
1164
1165
1167 info.circle0Closest = c0 + r0 * U;
1168 info.circle1Closest = c1 + r1 * U;
1169 }
1170 }
1171 else {
1173 info.circle0Closest = c0;
1174 info.circle1Closest = c1;
1175 }
1176 }
1177
1179 }
1180
1181 result.
distance_infinite = std::make_optional(DistAndPoints{ std::sqrt(candidates[0].sqrDistance), candidates[0].circle0Closest, candidates[0].circle1Closest });
1183 }
else if (f2.
get_type() == SurfaceFeatureType::Plane) {
1184 assert(measuring != nullptr);
1185
1186 const auto [center, radius, normal1] = f1.
get_circle();
1187 const auto [idx2, normal2, origin2] = f2.
get_plane();
1188
1190 if (!coplanar) {
1191 const std::vector<SurfaceFeature>& plane_features = measuring->
get_plane_features(idx2);
1192 std::vector<DistAndPoints> distances;
1193 for (const SurfaceFeature& sf : plane_features) {
1194 if (sf.get_type() == SurfaceFeatureType::Edge) {
1196 if (!m.distance_infinite.has_value()) {
1197 distances.clear();
1198 break;
1199 }
1200 else
1201 distances.push_back(*m.distance_infinite);
1202 }
1203 }
1204 if (!distances.empty()) {
1205 auto it = std::min_element(distances.begin(), distances.end(),
1206 [](const DistAndPoints& item1, const DistAndPoints& item2) {
1207 return item1.dist < item2.dist;
1208 });
1209 result.
distance_infinite = std::make_optional(DistAndPoints{ it->dist, it->from, it->to });
1210 }
1211 }
1212 }
1216 }
else if (f1.
get_type() == SurfaceFeatureType::Plane) {
1217 const auto [idx1, normal1, pt1] = f1.
get_plane();
1218 const auto [idx2, normal2, pt2] = f2.
get_plane();
1219
1221
1223 result.
distance_infinite = std::make_optional(DistAndPoints{ plane.absDistance(pt2), pt2, plane.projection(pt2) });
1224 }
1225 else
1227 }
1228
1229 return result;
1230}
const std::vector< SurfaceFeature > & get_plane_features(unsigned int plane_id) const
Definition Measure.cpp:624
Definition Measure.hpp:29
std::tuple< Vec3d, double, Vec3d > get_circle() const
Definition Measure.hpp:47
Vec3d get_point() const
Definition Measure.hpp:41
std::tuple< int, Vec3d, Vec3d > get_plane() const
Definition Measure.hpp:50
EIGEN_DEVICE_FUNC Scalar absDistance(const VectorType &p) const
Definition Hyperplane.h:148
T dist(const boost::polygon::point_data< T > &p1, const boost::polygon::point_data< T > &p2)
Definition Geometry.cpp:280
static AngleAndEdges angle_plane_plane(const std::tuple< int, Vec3d, Vec3d > &p1, const std::tuple< int, Vec3d, Vec3d > &p2)
Definition Measure.cpp:751
static AngleAndEdges angle_edge_plane(const std::pair< Vec3d, Vec3d > &e, const std::tuple< int, Vec3d, Vec3d > &p)
Definition Measure.cpp:700
Vec3d get_orthogonal(const Vec3d &v, bool unitLength)
Definition MeasureUtils.hpp:355
static std::array< Vec3d, 3 > orthonormal_basis(const Vec3d &v)
Definition Measure.cpp:41
MeasurementResult get_measurement(const SurfaceFeature &a, const SurfaceFeature &b, const Measuring *measuring)
Definition Measure.cpp:795
constexpr T sqr(T x)
Definition libslic3r.h:258
Slic3r::Polygons diff(const Slic3r::Polygon &subject, const Slic3r::Polygon &clip, ApplySafetyOffset do_safety_offset)
Definition ClipperUtils.cpp:672
double distance(const P &p1, const P &p2)
Definition geometry_traits.hpp:329
Definition Measure.hpp:119
Definition Measure.hpp:139
std::optional< DistAndPoints > distance_infinite
Definition Measure.hpp:141
std::optional< AngleAndEdges > angle
Definition Measure.hpp:140
std::optional< Vec3d > distance_xyz
Definition Measure.hpp:143
std::optional< DistAndPoints > distance_strict
Definition Measure.hpp:142
__int32 int32_t
Definition unistd.h:75
unsigned __int32 uint32_t
Definition unistd.h:79