OrcaSlicer latest
OrcaSlicer
Loading...
Searching...
No Matches
Slic3r::Measure Namespace Reference

Classes

class  MeasuringImpl
class  SurfaceFeature
class  Measuring
struct  DistAndPoints
struct  AngleAndEdges
struct  MeasurementResult
struct  AssemblyAction
class  Polynomial1
class  RootsPolynomial

Enumerations

enum class  SurfaceFeatureType : int {
  Undef = 0 , Point = 1 << 0 , Edge = 1 << 1 , Circle = 1 << 2 ,
  Plane = 1 << 3
}

Functions

bool get_point_projection_to_plane (const Vec3d &pt, const Vec3d &plane_origin, const Vec3d &plane_normal, Vec3d &intersection_pt)
Vec3d get_one_point_in_plane (const Vec3d &plane_origin, const Vec3d &plane_normal)
static std::tuple< Vec3d, double, double > get_center_and_radius (const std::vector< Vec3d > &points, const Transform3d &trafo, const Transform3d &trafo_inv)
static std::array< Vec3d, 3 > orthonormal_basis (const Vec3d &v)
static AngleAndEdges angle_edge_edge (const std::pair< Vec3d, Vec3d > &e1, const std::pair< Vec3d, Vec3d > &e2)
static AngleAndEdges angle_edge_plane (const std::pair< Vec3d, Vec3d > &e, const std::tuple< int, Vec3d, Vec3d > &p)
static AngleAndEdges angle_plane_plane (const std::tuple< int, Vec3d, Vec3d > &p1, const std::tuple< int, Vec3d, Vec3d > &p2)
MeasurementResult get_measurement (const SurfaceFeature &a, const SurfaceFeature &b, bool deal_circle_result)
bool can_set_xyz_distance (const SurfaceFeature &a, const SurfaceFeature &b)
AssemblyAction get_assembly_action (const SurfaceFeature &a, const SurfaceFeature &b)
Vec3d edge_direction (const Vec3d &from, const Vec3d &to)
Vec3d edge_direction (const std::pair< Vec3d, Vec3d > &e)
Vec3d edge_direction (const SurfaceFeature &edge)
Vec3d plane_normal (const SurfaceFeature &plane)
bool are_parallel (const Vec3d &v1, const Vec3d &v2)
bool are_perpendicular (const Vec3d &v1, const Vec3d &v2)
bool are_parallel (const std::pair< Vec3d, Vec3d > &e1, const std::pair< Vec3d, Vec3d > &e2)
bool are_parallel (const SurfaceFeature &f1, const SurfaceFeature &f2)
bool are_perpendicular (const SurfaceFeature &f1, const SurfaceFeature &f2)
Polynomial1 operator* (const Polynomial1 &p0, const Polynomial1 &p1)
Polynomial1 operator+ (const Polynomial1 &p0, const Polynomial1 &p1)
Polynomial1 operator- (const Polynomial1 &p0, const Polynomial1 &p1)
Polynomial1 operator* (double scalar, const Polynomial1 &p)
Vec3d get_orthogonal (const Vec3d &v, bool unitLength)

Variables

constexpr double feature_hover_limit = 0.5

Class Documentation

◆ Slic3r::Measure::AssemblyAction

struct Slic3r::Measure::AssemblyAction
Class Members
float angle_radian {0}
bool can_around_center_of_faces {false}
bool can_set_feature_1_reverse_rotation {false}
bool can_set_feature_2_reverse_rotation {false}
bool can_set_to_center_coincidence {false}
bool can_set_to_parallel {false}
bool has_parallel_distance {false}
float parallel_distance
Transform3d tran_for_center_coincidence
Transform3d tran_for_parallel
Transform3d tran_for_reverse_rotation

Enumeration Type Documentation

◆ SurfaceFeatureType

enum class Slic3r::Measure::SurfaceFeatureType : int
strong
Enumerator
Undef 
Point 
Edge 
Circle 
Plane 
23 : int {
24 Undef = 0,
25 Point = 1 << 0,
26 Edge = 1 << 1,
27 Circle = 1 << 2,
28 Plane = 1 << 3
29};
@ Circle
Definition Button.hpp:37
@ Undef
Definition CustomGCode.hpp:55
@ Edge
Definition Measure.hpp:26
Kernel::Point_3 Point
Definition MeshRepair.cpp:81
@ Plane
Definition CadDocument.hpp:26

Function Documentation

◆ angle_edge_edge()

AngleAndEdges Slic3r::Measure::angle_edge_edge ( const std::pair< Vec3d, Vec3d > & e1,
const std::pair< Vec3d, Vec3d > & e2 )
static
704{
705 if (are_parallel(e1, e2))
707
708 Vec3d e1_unit = edge_direction(e1.first, e1.second);
709 Vec3d e2_unit = edge_direction(e2.first, e2.second);
710
711 // project edges on the plane defined by them
712 Vec3d normal = e1_unit.cross(e2_unit).normalized();
713 const Eigen::Hyperplane<double, 3> plane(normal, e1.first);
714 Vec3d e11_proj = plane.projection(e1.first);
715 Vec3d e12_proj = plane.projection(e1.second);
716 Vec3d e21_proj = plane.projection(e2.first);
717 Vec3d e22_proj = plane.projection(e2.second);
718
719 const bool coplanar = (e2.first - e21_proj).norm() < EPSILON && (e2.second - e22_proj).norm() < EPSILON;
720
721 // rotate the plane to become the XY plane
722 auto qp = Eigen::Quaternion<double>::FromTwoVectors(normal, Vec3d::UnitZ());
723 auto qp_inverse = qp.inverse();
724 const Vec3d e11_rot = qp * e11_proj;
725 const Vec3d e12_rot = qp * e12_proj;
726 const Vec3d e21_rot = qp * e21_proj;
727 const Vec3d e22_rot = qp * e22_proj;
728
729 // discard Z
730 const Vec2d e11_rot_2d = Vec2d(e11_rot.x(), e11_rot.y());
731 const Vec2d e12_rot_2d = Vec2d(e12_rot.x(), e12_rot.y());
732 const Vec2d e21_rot_2d = Vec2d(e21_rot.x(), e21_rot.y());
733 const Vec2d e22_rot_2d = Vec2d(e22_rot.x(), e22_rot.y());
734
735 // find intersection (arc center) of edges in XY plane
736 const Eigen::Hyperplane<double, 2> e1_rot_2d_line = Eigen::Hyperplane<double, 2>::Through(e11_rot_2d, e12_rot_2d);
737 const Eigen::Hyperplane<double, 2> e2_rot_2d_line = Eigen::Hyperplane<double, 2>::Through(e21_rot_2d, e22_rot_2d);
738 const Vec2d center_rot_2d = e1_rot_2d_line.intersection(e2_rot_2d_line);
739
740 // arc center in original coordinate
741 const Vec3d center = qp_inverse * Vec3d(center_rot_2d.x(), center_rot_2d.y(), e11_rot.z());
742
743 // ensure the edges are pointing away from the center
744 std::pair<Vec3d, Vec3d> out_e1 = e1;
745 std::pair<Vec3d, Vec3d> out_e2 = e2;
746 if ((center_rot_2d - e11_rot_2d).squaredNorm() > (center_rot_2d - e12_rot_2d).squaredNorm()) {
747 std::swap(e11_proj, e12_proj);
748 std::swap(out_e1.first, out_e1.second);
749 e1_unit = -e1_unit;
750 }
751 if ((center_rot_2d - e21_rot_2d).squaredNorm() > (center_rot_2d - e22_rot_2d).squaredNorm()) {
752 std::swap(e21_proj, e22_proj);
753 std::swap(out_e2.first, out_e2.second);
754 e2_unit = -e2_unit;
755 }
756
757 // arc angle
758 const double angle = std::acos(std::clamp(e1_unit.dot(e2_unit), -1.0, 1.0));
759 // arc radius
760 const Vec3d e1_proj_mid = 0.5 * (e11_proj + e12_proj);
761 const Vec3d e2_proj_mid = 0.5 * (e21_proj + e22_proj);
762 const double radius = std::min((center - e1_proj_mid).norm(), (center - e2_proj_mid).norm());
763
764 return { angle, center, out_e1, out_e2, radius, coplanar };
765}
#define EPSILON
Definition ColorUtils.cpp:64
bool are_parallel(const Vec3d &v1, const Vec3d &v2)
Definition Measure.hpp:212
Vec3d edge_direction(const Vec3d &from, const Vec3d &to)
Definition Measure.hpp:200
Eigen::Matrix< double, 3, 1, Eigen::DontAlign > Vec3d
Definition Point.hpp:68
void center(ExPolygonsWithIds &e)
Definition Emboss.cpp:1382
double angle(const Eigen::MatrixBase< Derived > &v1, const Eigen::MatrixBase< Derived2 > &v2)
Definition Point.hpp:138
Point normal(Point pt, double scale)
Definition TreeSupport.cpp:112
Eigen::Matrix< double, 2, 1, Eigen::DontAlign > Vec2d
Definition Point.hpp:67
static const AngleAndEdges Dummy
Definition Measure.hpp:162

References Slic3r::angle(), are_parallel(), Slic3r::center(), Slic3r::Measure::AngleAndEdges::Dummy, edge_direction(), EPSILON, and Slic3r::normal().

Referenced by angle_edge_plane(), angle_plane_plane(), and get_measurement().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ angle_edge_plane()

AngleAndEdges Slic3r::Measure::angle_edge_plane ( const std::pair< Vec3d, Vec3d > & e,
const std::tuple< int, Vec3d, Vec3d > & p )
static
768{
769 const auto& [idx, normal, origin] = p;
770 Vec3d e1e2_unit = edge_direction(e);
771 if (are_perpendicular(e1e2_unit, normal))
773
774 // ensure the edge is pointing away from the intersection
775 // 1st calculate instersection between edge and plane
776 const Eigen::Hyperplane<double, 3> plane(normal, origin);
777 const Eigen::ParametrizedLine<double, 3> line = Eigen::ParametrizedLine<double, 3>::Through(e.first, e.second);
778 const Vec3d inters = line.intersectionPoint(plane);
779
780 // then verify edge direction and revert it, if needed
781 Vec3d e1 = e.first;
782 Vec3d e2 = e.second;
783 if ((e1 - inters).squaredNorm() > (e2 - inters).squaredNorm()) {
784 std::swap(e1, e2);
785 e1e2_unit = -e1e2_unit;
786 }
787
788 if (are_parallel(e1e2_unit, normal)) {
789 const std::array<Vec3d, 3> basis = orthonormal_basis(e1e2_unit);
790 const double radius = (0.5 * (e1 + e2) - inters).norm();
791 const Vec3d edge_on_plane_dir = (basis[1].dot(origin - inters) >= 0.0) ? basis[1] : -basis[1];
792 std::pair<Vec3d, Vec3d> edge_on_plane = std::make_pair(inters, inters + radius * edge_on_plane_dir);
793 if (!inters.isApprox(e1)) {
794 edge_on_plane.first += radius * edge_on_plane_dir;
795 edge_on_plane.second += radius * edge_on_plane_dir;
796 }
797 return AngleAndEdges(0.5 * double(PI), inters, std::make_pair(e1, e2), edge_on_plane, radius, inters.isApprox(e1));
798 }
799
800 const Vec3d e1e2 = e2 - e1;
801 const double e1e2_len = e1e2.norm();
802
803 // calculate 2nd edge (on the plane)
804 const Vec3d temp = normal.cross(e1e2);
805 const Vec3d edge_on_plane_unit = normal.cross(temp).normalized();
806 std::pair<Vec3d, Vec3d> edge_on_plane = { origin, origin + e1e2_len * edge_on_plane_unit };
807
808 // ensure the 2nd edge is pointing in the correct direction
809 const Vec3d test_edge = (edge_on_plane.second - edge_on_plane.first).cross(e1e2);
810 if (test_edge.dot(temp) < 0.0)
811 edge_on_plane = { origin, origin - e1e2_len * edge_on_plane_unit };
812
813 AngleAndEdges ret = angle_edge_edge({ e1, e2 }, edge_on_plane);
814 ret.radius = (inters - 0.5 * (e1 + e2)).norm();
815 return ret;
816}
static constexpr double PI
Definition libslic3r.h:81
static AngleAndEdges angle_edge_edge(const std::pair< Vec3d, Vec3d > &e1, const std::pair< Vec3d, Vec3d > &e2)
Definition Measure.cpp:703
bool are_perpendicular(const Vec3d &v1, const Vec3d &v2)
Definition Measure.hpp:213
static std::array< Vec3d, 3 > orthonormal_basis(const Vec3d &v)
Definition Measure.cpp:86
T cross(const boost::geometry::model::d2::point_xy< T > &v1, const boost::geometry::model::d2::point_xy< T > &v2)
Definition ExtrusionSimulator.cpp:168
Definition Measure.hpp:152
double radius
Definition Measure.hpp:159

References angle_edge_edge(), are_parallel(), are_perpendicular(), Slic3r::cross(), Slic3r::Measure::AngleAndEdges::Dummy, edge_direction(), Slic3r::normal(), orthonormal_basis(), PI, and Slic3r::Measure::AngleAndEdges::radius.

Referenced by get_measurement().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ angle_plane_plane()

AngleAndEdges Slic3r::Measure::angle_plane_plane ( const std::tuple< int, Vec3d, Vec3d > & p1,
const std::tuple< int, Vec3d, Vec3d > & p2 )
static
819{
820 const auto& [idx1, normal1, origin1] = p1;
821 const auto& [idx2, normal2, origin2] = p2;
822
823 // are planes parallel ?
824 if (are_parallel(normal1, normal2))
826
827 auto intersection_plane_plane = [](const Vec3d& n1, const Vec3d& o1, const Vec3d& n2, const Vec3d& o2) {
828 Eigen::MatrixXd m(2, 3);
829 m << n1.x(), n1.y(), n1.z(), n2.x(), n2.y(), n2.z();
830 Eigen::VectorXd b(2);
831 b << o1.dot(n1), o2.dot(n2);
832 Eigen::VectorXd x = m.colPivHouseholderQr().solve(b);
833 return std::make_pair(n1.cross(n2).normalized(), Vec3d(x(0), x(1), x(2)));
834 };
835
836 // Calculate intersection line between planes
837 const auto [intersection_line_direction, intersection_line_origin] = intersection_plane_plane(normal1, origin1, normal2, origin2);
838
839 // Project planes' origin on intersection line
840 const Eigen::ParametrizedLine<double, 3> intersection_line = Eigen::ParametrizedLine<double, 3>(intersection_line_origin, intersection_line_direction);
841 const Vec3d origin1_proj = intersection_line.projection(origin1);
842 const Vec3d origin2_proj = intersection_line.projection(origin2);
843
844 // Calculate edges on planes
845 const Vec3d edge_on_plane1_unit = (origin1 - origin1_proj).normalized();
846 const Vec3d edge_on_plane2_unit = (origin2 - origin2_proj).normalized();
847 const double radius = std::max(10.0, std::max((origin1 - origin1_proj).norm(), (origin2 - origin2_proj).norm()));
848 const std::pair<Vec3d, Vec3d> edge_on_plane1 = { origin1_proj + radius * edge_on_plane1_unit, origin1_proj + 2.0 * radius * edge_on_plane1_unit };
849 const std::pair<Vec3d, Vec3d> edge_on_plane2 = { origin2_proj + radius * edge_on_plane2_unit, origin2_proj + 2.0 * radius * edge_on_plane2_unit };
850
851 AngleAndEdges ret = angle_edge_edge(edge_on_plane1, edge_on_plane2);
852 ret.radius = radius;
853 return ret;
854}

References angle_edge_edge(), are_parallel(), Slic3r::Measure::AngleAndEdges::Dummy, and Slic3r::Measure::AngleAndEdges::radius.

Referenced by get_measurement().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ are_parallel() [1/3]

bool Slic3r::Measure::are_parallel ( const std::pair< Vec3d, Vec3d > & e1,
const std::pair< Vec3d, Vec3d > & e2 )
inline
215 {
216 return are_parallel(e1.second - e1.first, e2.second - e2.first);
217}

References are_parallel().

Here is the call graph for this function:

◆ are_parallel() [2/3]

bool Slic3r::Measure::are_parallel ( const SurfaceFeature & f1,
const SurfaceFeature & f2 )
inline
218 {
223 else
224 return false;
225}
SurfaceFeatureType get_type() const
Definition Measure.hpp:54
Vec3d plane_normal(const SurfaceFeature &plane)
Definition Measure.hpp:207
@ Plane
Definition Measure.hpp:28

References are_parallel(), are_perpendicular(), Edge, edge_direction(), Slic3r::Measure::SurfaceFeature::get_type(), Plane, and plane_normal().

Here is the call graph for this function:

◆ are_parallel() [3/3]

bool Slic3r::Measure::are_parallel ( const Vec3d & v1,
const Vec3d & v2 )
inline
212{ return std::abs(std::abs(v1.dot(v2)) - 1.0) < EPSILON; }

References EPSILON.

Referenced by angle_edge_edge(), angle_edge_plane(), angle_plane_plane(), are_parallel(), are_parallel(), are_perpendicular(), get_assembly_action(), and get_measurement().

Here is the caller graph for this function:

◆ are_perpendicular() [1/2]

bool Slic3r::Measure::are_perpendicular ( const SurfaceFeature & f1,
const SurfaceFeature & f2 )
inline
227 {
232 else
233 return false;
234}

References are_parallel(), are_perpendicular(), Edge, edge_direction(), Slic3r::Measure::SurfaceFeature::get_type(), Plane, and plane_normal().

Here is the call graph for this function:

◆ are_perpendicular() [2/2]

bool Slic3r::Measure::are_perpendicular ( const Vec3d & v1,
const Vec3d & v2 )
inline
213{ return std::abs(v1.dot(v2)) < EPSILON; }

References EPSILON.

Referenced by angle_edge_plane(), are_parallel(), are_perpendicular(), and get_measurement().

Here is the caller graph for this function:

◆ can_set_xyz_distance()

bool Slic3r::Measure::can_set_xyz_distance ( const SurfaceFeature & a,
const SurfaceFeature & b )
1322 {
1323 const bool swap = int(a.get_type()) > int(b.get_type());
1324 const SurfaceFeature &f1 = swap ? b : a;
1325 const SurfaceFeature &f2 = swap ? a : b;
1327 if (f2.get_type() == SurfaceFeatureType::Point) {
1328 return true;
1329 }
1330 }
1331 else if (f1.get_type() == SurfaceFeatureType::Circle) {
1333 return true;
1334 }
1335 }
1336 return false;
1337}
Definition Measure.hpp:35
@ Point
Definition Measure.hpp:25
@ Circle
Definition Measure.hpp:27

References Circle, Slic3r::Measure::SurfaceFeature::get_type(), and Point.

Referenced by Slic3r::GUI::GLGizmoMeasure::update_measurement_result().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ edge_direction() [1/3]

Vec3d Slic3r::Measure::edge_direction ( const std::pair< Vec3d, Vec3d > & e)
inline
201{ return edge_direction(e.first, e.second); }

References edge_direction().

Here is the call graph for this function:

◆ edge_direction() [2/3]

Vec3d Slic3r::Measure::edge_direction ( const SurfaceFeature & edge)
inline
202 {
203 assert(edge.get_type() == SurfaceFeatureType::Edge);
204 return edge_direction(edge.get_edge());
205}
std::pair< Vec3d, Vec3d > get_edge() const
Definition Measure.hpp:59

References Edge, edge_direction(), Slic3r::Measure::SurfaceFeature::get_edge(), and Slic3r::Measure::SurfaceFeature::get_type().

Here is the call graph for this function:

◆ edge_direction() [3/3]

Vec3d Slic3r::Measure::edge_direction ( const Vec3d & from,
const Vec3d & to )
inline
200{ return (to - from).normalized(); }

Referenced by angle_edge_edge(), angle_edge_plane(), are_parallel(), are_perpendicular(), edge_direction(), edge_direction(), and Slic3r::GUI::GLGizmoMeasure::render_dimensioning().

Here is the caller graph for this function:

◆ get_assembly_action()

AssemblyAction Slic3r::Measure::get_assembly_action ( const SurfaceFeature & a,
const SurfaceFeature & b )
1340{
1341 AssemblyAction action;
1342 const SurfaceFeature &f1 = a;
1343 const SurfaceFeature &f2 = b;
1344 if (f1.get_type() == SurfaceFeatureType::Plane) {
1346 if (f2.get_type() == SurfaceFeatureType::Plane) {
1347 const auto [idx1, normal1, pt1] = f1.get_plane();
1348 const auto [idx2, normal2, pt2] = f2.get_plane();
1349 action.can_set_to_center_coincidence = true;
1351 if (are_parallel(normal1, normal2)) {
1352 action.can_set_to_parallel = false;
1353 action.has_parallel_distance = true;
1354 action.can_around_center_of_faces = true;
1355 Vec3d proj_pt2;
1356 Measure::get_point_projection_to_plane(pt2, pt1, normal1, proj_pt2);
1357 action.parallel_distance = (pt2 - proj_pt2).norm();
1358 if ((pt2 - proj_pt2).dot(normal1) < 0) {
1359 action.parallel_distance = -action.parallel_distance;
1360 }
1361 action.angle_radian = 0;
1362
1363 } else {
1364 action.can_set_to_parallel = true;
1365 action.has_parallel_distance = false;
1366 action.can_around_center_of_faces = false;
1367 action.parallel_distance = 0;
1368 action.angle_radian = std::acos(std::clamp(normal2.dot(-normal1), -1.0, 1.0));
1369 }
1370 }
1371 }
1372 return action;
1373}
std::tuple< int, Vec3d, Vec3d > get_plane() const
Definition Measure.hpp:65
bool can_set_to_center_coincidence
Definition Measure.hpp:187
bool can_set_feature_2_reverse_rotation
Definition Measure.hpp:189
bool can_set_feature_1_reverse_rotation
Definition Measure.hpp:188
bool has_parallel_distance
Definition Measure.hpp:191
float parallel_distance
Definition Measure.hpp:192
bool can_around_center_of_faces
Definition Measure.hpp:190
bool get_point_projection_to_plane(const Vec3d &pt, const Vec3d &plane_origin, const Vec3d &plane_normal, Vec3d &intersection_pt)
Definition Measure.cpp:40
bool can_set_to_parallel
Definition Measure.hpp:186
float angle_radian
Definition Measure.hpp:193
Definition Measure.hpp:185
T dot(const boost::geometry::model::d2::point_xy< T > &v1, const boost::geometry::model::d2::point_xy< T > &v2)
Definition ExtrusionSimulator.cpp:154

References Slic3r::Measure::AssemblyAction::angle_radian, are_parallel(), Slic3r::Measure::AssemblyAction::can_around_center_of_faces, Slic3r::Measure::AssemblyAction::can_set_feature_1_reverse_rotation, Slic3r::Measure::AssemblyAction::can_set_feature_2_reverse_rotation, Slic3r::Measure::AssemblyAction::can_set_to_center_coincidence, Slic3r::Measure::AssemblyAction::can_set_to_parallel, Slic3r::dot(), Slic3r::Measure::SurfaceFeature::get_plane(), get_point_projection_to_plane(), Slic3r::Measure::SurfaceFeature::get_type(), Slic3r::Measure::AssemblyAction::has_parallel_distance, Slic3r::Measure::AssemblyAction::parallel_distance, and Plane.

Referenced by Slic3r::GUI::GLGizmoMeasure::update_measurement_result().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_center_and_radius()

std::tuple< Vec3d, double, double > Slic3r::Measure::get_center_and_radius ( const std::vector< Vec3d > & points,
const Transform3d & trafo,
const Transform3d & trafo_inv )
static
65{
66 Vec2ds out;
67 double z = 0.;
68 for (const Vec3d& pt : points) {
69 Vec3d pt_transformed = trafo * pt;
70 z = pt_transformed.z();
71 out.emplace_back(pt_transformed.x(), pt_transformed.y());
72 }
73
74 const int iter = points.size() < 10 ? 2 :
75 points.size() < 100 ? 4 :
76 6;
77
78 double error = std::numeric_limits<double>::max();
79 auto circle = Geometry::circle_ransac(out, iter, &error);
80
81 return std::make_tuple(trafo.inverse() * Vec3d(circle.center.x(), circle.center.y(), z), circle.radius, error);
82}
Circled circle_ransac(const Vec2ds &input, size_t iterations, double *min_error)
Definition Circle.cpp:119
std::vector< Vec2d > Vec2ds
Definition Point.hpp:78

References Slic3r::Geometry::circle_ransac().

Referenced by Slic3r::Measure::MeasuringImpl::extract_features().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_measurement()

MeasurementResult Slic3r::Measure::get_measurement ( const SurfaceFeature & a,
const SurfaceFeature & b,
bool deal_circle_result )
857{
859
860 const bool swap = int(a.get_type()) > int(b.get_type());
861 const SurfaceFeature& f1 = swap ? b : a;
862 const SurfaceFeature& f2 = swap ? a : b;
863
864 MeasurementResult result;
865
871 Vec3d diff = (f2.get_point() - f1.get_point());
872 result.distance_strict = std::make_optional(DistAndPoints{diff.norm(), f1.get_point(), f2.get_point()});
873 result.distance_xyz = diff;
874
876 } else if (f2.get_type() == SurfaceFeatureType::Edge) {
877 const auto [s,e] = f2.get_edge();
878 const Eigen::ParametrizedLine<double, 3> line(s, (e-s).normalized());
879 const double dist_inf = line.distance(f1.get_point());
880 const Vec3d proj = line.projection(f1.get_point());
881 const double len_sq = (e-s).squaredNorm();
882 const double dist_start_sq = (proj-s).squaredNorm();
883 const double dist_end_sq = (proj-e).squaredNorm();
884 if (dist_start_sq < len_sq && dist_end_sq < len_sq) {
885 // projection falls on the line - the strict distance is the same as infinite
886 result.distance_strict = std::make_optional(DistAndPoints{dist_inf, f1.get_point(), proj});
887 } else { // the result is the closer of the endpoints
888 const bool s_is_closer = dist_start_sq < dist_end_sq;
889 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});
890 }
891 result.distance_infinite = std::make_optional(DistAndPoints{dist_inf, f1.get_point(), proj});
893 } else if (f2.get_type() == SurfaceFeatureType::Circle) {
894 // Find a plane containing normal, center and the point.
895 const auto [c, radius, n] = f2.get_circle();
896 const Eigen::Hyperplane<double, 3> circle_plane(n, c);
897 const Vec3d proj = circle_plane.projection(f1.get_point());
898 if (proj.isApprox(c)) {
899 const Vec3d p_on_circle = c + radius * get_orthogonal(n, true);
900 result.distance_strict = std::make_optional(DistAndPoints{ radius, c, p_on_circle });
901 }
902 else {
903 if (deal_circle_result == false) {
904 const Eigen::Hyperplane<double, 3> circle_plane(n, c);
905 const Vec3d proj = circle_plane.projection(f1.get_point());
906 const double dist = std::sqrt(std::pow((proj - c).norm() - radius, 2.) + (f1.get_point() - proj).squaredNorm());
907
908 const Vec3d p_on_circle = c + radius * (proj - c).normalized();
909 result.distance_strict = std::make_optional(DistAndPoints{dist, f1.get_point(), p_on_circle});
910 }
911 else {
912 const double dist = (f1.get_point() - c).norm();
913 result.distance_strict = std::make_optional(DistAndPoints{dist, f1.get_point(), c});
914 }
915 }
917 } else if (f2.get_type() == SurfaceFeatureType::Plane) {
918 const auto [idx, normal, pt] = f2.get_plane();
919 Eigen::Hyperplane<double, 3> plane(normal, pt);
920 result.distance_infinite = std::make_optional(DistAndPoints{plane.absDistance(f1.get_point()), f1.get_point(), plane.projection(f1.get_point())}); // TODO
921 // TODO: result.distance_strict =
922 }
926 }
927 else if (f1.get_type() == SurfaceFeatureType::Edge) {
929 std::vector<DistAndPoints> distances;
930
931 auto add_point_edge_distance = [&distances](const Vec3d& v, const std::pair<Vec3d, Vec3d>& e) {
933 double distance = res.distance_strict->dist;
934 Vec3d v2 = res.distance_strict->to;
935
936 const Vec3d e1e2 = e.second - e.first;
937 const Vec3d e1v2 = v2 - e.first;
938 if (e1v2.dot(e1e2) >= 0.0 && e1v2.norm() < e1e2.norm())
939 distances.emplace_back(distance, v, v2);
940 };
941
942 std::pair<Vec3d, Vec3d> e1 = f1.get_edge();
943 std::pair<Vec3d, Vec3d> e2 = f2.get_edge();
944
945 distances.emplace_back((e2.first - e1.first).norm(), e1.first, e2.first);
946 distances.emplace_back((e2.second - e1.first).norm(), e1.first, e2.second);
947 distances.emplace_back((e2.first - e1.second).norm(), e1.second, e2.first);
948 distances.emplace_back((e2.second - e1.second).norm(), e1.second, e2.second);
949 add_point_edge_distance(e1.first, e2);
950 add_point_edge_distance(e1.second, e2);
951 add_point_edge_distance(e2.first, e1);
952 add_point_edge_distance(e2.second, e1);
953 auto it = std::min_element(distances.begin(), distances.end(),
954 [](const DistAndPoints& item1, const DistAndPoints& item2) {
955 return item1.dist < item2.dist;
956 });
957 result.distance_infinite = std::make_optional(*it);
958
959 result.angle = angle_edge_edge(f1.get_edge(), f2.get_edge());
961 } else if (f2.get_type() == SurfaceFeatureType::Circle) {
962 const std::pair<Vec3d, Vec3d> e = f1.get_edge();
963 const auto &[center, radius, normal] = f2.get_circle();
964 const Vec3d e1e2 = (e.second - e.first);
965 const Vec3d e1e2_unit = e1e2.normalized();
966
967 std::vector<DistAndPoints> distances;
968 distances.emplace_back(*get_measurement(SurfaceFeature(e.first), f2).distance_strict);
969 distances.emplace_back(*get_measurement(SurfaceFeature(e.second), f2).distance_strict);
970
971 const Eigen::Hyperplane<double, 3> plane(e1e2_unit, center);
972 const Eigen::ParametrizedLine<double, 3> line = Eigen::ParametrizedLine<double, 3>::Through(e.first, e.second);
973 const Vec3d inter = line.intersectionPoint(plane);
974 const Vec3d e1inter = inter - e.first;
975 if (e1inter.dot(e1e2) >= 0.0 && e1inter.norm() < e1e2.norm()) distances.emplace_back(*get_measurement(SurfaceFeature(inter), f2).distance_strict);
976
977 auto it = std::min_element(distances.begin(), distances.end(), [](const DistAndPoints &item1, const DistAndPoints &item2) { return item1.dist < item2.dist; });
978 if (deal_circle_result == false) {
979 result.distance_infinite = std::make_optional(DistAndPoints{it->dist, it->from, it->to});
980 }
981 else{
982 const double dist = (it->from - center).norm();
983 result.distance_infinite = std::make_optional(DistAndPoints{dist, it->from, center});
984 }
986 } else if (f2.get_type() == SurfaceFeatureType::Plane) {
987 const auto [from, to] = f1.get_edge();
988 const auto [idx, normal, origin] = f2.get_plane();
989
990 const Vec3d edge_unit = (to - from).normalized();
991 if (are_perpendicular(edge_unit, normal)) {
992 std::vector<DistAndPoints> distances;
993 const Eigen::Hyperplane<double, 3> plane(normal, origin);
994 distances.push_back(DistAndPoints{ plane.absDistance(from), from, plane.projection(from) });
995 distances.push_back(DistAndPoints{ plane.absDistance(to), to, plane.projection(to) });
996 auto it = std::min_element(distances.begin(), distances.end(),
997 [](const DistAndPoints& item1, const DistAndPoints& item2) {
998 return item1.dist < item2.dist;
999 });
1000 result.distance_infinite = std::make_optional(DistAndPoints{ it->dist, it->from, it->to });
1001 }
1002 else {
1003 auto plane_features = f2.world_plane_features;
1004 std::vector<DistAndPoints> distances;
1005 for (const SurfaceFeature& sf : *plane_features) {
1006 if (sf.get_type() == SurfaceFeatureType::Edge) {
1007 const auto m = get_measurement(sf, f1);
1008 if (!m.distance_infinite.has_value()) {
1009 distances.clear();
1010 break;
1011 }
1012 else
1013 distances.push_back(*m.distance_infinite);
1014 }
1015 }
1016 if (!distances.empty()) {
1017 auto it = std::min_element(distances.begin(), distances.end(),
1018 [](const DistAndPoints& item1, const DistAndPoints& item2) {
1019 return item1.dist < item2.dist;
1020 });
1021 result.distance_infinite = std::make_optional(DistAndPoints{ it->dist, it->from, it->to });
1022 }
1023 }
1024 result.angle = angle_edge_plane(f1.get_edge(), f2.get_plane());
1025 }
1029 } else if (f1.get_type() == SurfaceFeatureType::Circle) {
1031 const auto [c0, r0, n0] = f1.get_circle();
1032 const auto [c1, r1, n1] = f2.get_circle();
1033
1034 // The following code is an adaptation of the algorithm found in:
1035 // https://github.com/davideberly/GeometricTools/blob/master/GTE/Mathematics/DistCircle3Circle3.h
1036 // and described in:
1037 // https://www.geometrictools.com/Documentation/DistanceToCircle3.pdf
1038
1039 struct ClosestInfo
1040 {
1041 double sqrDistance{ 0.0 };
1042 Vec3d circle0Closest{ Vec3d::Zero() };
1043 Vec3d circle1Closest{ Vec3d::Zero() };
1044
1045 inline bool operator < (const ClosestInfo& other) const { return sqrDistance < other.sqrDistance; }
1046 };
1047 std::array<ClosestInfo, 16> candidates{};
1048
1049 const double zero = 0.0;
1050
1051 const Vec3d D = c1 - c0;
1052
1053 if (!are_parallel(n0, n1)) {
1054 // Get parameters for constructing the degree-8 polynomial phi.
1055 const double one = 1.0;
1056 const double two = 2.0;
1057 const double r0sqr = sqr(r0);
1058 const double r1sqr = sqr(r1);
1059
1060 // Compute U1 and V1 for the plane of circle1.
1061 const std::array<Vec3d, 3> basis = orthonormal_basis(n1);
1062 const Vec3d U1 = basis[0];
1063 const Vec3d V1 = basis[1];
1064
1065 // Construct the polynomial phi(cos(theta)).
1066 const Vec3d N0xD = n0.cross(D);
1067 const Vec3d N0xU1 = n0.cross(U1);
1068 const Vec3d N0xV1 = n0.cross(V1);
1069 const double a0 = r1 * D.dot(U1);
1070 const double a1 = r1 * D.dot(V1);
1071 const double a2 = N0xD.dot(N0xD);
1072 const double a3 = r1 * N0xD.dot(N0xU1);
1073 const double a4 = r1 * N0xD.dot(N0xV1);
1074 const double a5 = r1sqr * N0xU1.dot(N0xU1);
1075 const double a6 = r1sqr * N0xU1.dot(N0xV1);
1076 const double a7 = r1sqr * N0xV1.dot(N0xV1);
1077 Polynomial1 p0{ a2 + a7, two * a3, a5 - a7 };
1078 Polynomial1 p1{ two * a4, two * a6 };
1079 Polynomial1 p2{ zero, a1 };
1080 Polynomial1 p3{ -a0 };
1081 Polynomial1 p4{ -a6, a4, two * a6 };
1082 Polynomial1 p5{ -a3, a7 - a5 };
1083 Polynomial1 tmp0{ one, zero, -one };
1084 Polynomial1 tmp1 = p2 * p2 + tmp0 * p3 * p3;
1085 Polynomial1 tmp2 = two * p2 * p3;
1086 Polynomial1 tmp3 = p4 * p4 + tmp0 * p5 * p5;
1087 Polynomial1 tmp4 = two * p4 * p5;
1088 Polynomial1 p6 = p0 * tmp1 + tmp0 * p1 * tmp2 - r0sqr * tmp3;
1089 Polynomial1 p7 = p0 * tmp2 + p1 * tmp1 - r0sqr * tmp4;
1090
1091 // Parameters for polynomial root finding. The roots[] array
1092 // stores the roots. We need only the unique ones, which is
1093 // the responsibility of the set uniqueRoots. The pairs[]
1094 // array stores the (cosine,sine) information mentioned in the
1095 // PDF. TODO: Choose the maximum number of iterations for root
1096 // finding based on specific polynomial data?
1097 const uint32_t maxIterations = 128;
1098 int32_t degree = 0;
1099 size_t numRoots = 0;
1100 std::array<double, 8> roots{};
1101 std::set<double> uniqueRoots{};
1102 size_t numPairs = 0;
1103 std::array<std::pair<double, double>, 16> pairs{};
1104 double temp = zero;
1105 double sn = zero;
1106
1107 if (p7.GetDegree() > 0 || p7[0] != zero) {
1108 // H(cs,sn) = p6(cs) + sn * p7(cs)
1109 Polynomial1 phi = p6 * p6 - tmp0 * p7 * p7;
1110 degree = static_cast<int32_t>(phi.GetDegree());
1111 assert(degree > 0);
1112 numRoots = RootsPolynomial::Find(degree, &phi[0], maxIterations, roots.data());
1113 for (size_t i = 0; i < numRoots; ++i) {
1114 uniqueRoots.insert(roots[i]);
1115 }
1116
1117 for (auto const& cs : uniqueRoots) {
1118 if (std::fabs(cs) <= one) {
1119 temp = p7(cs);
1120 if (temp != zero) {
1121 sn = -p6(cs) / temp;
1122 pairs[numPairs++] = std::make_pair(cs, sn);
1123 }
1124 else {
1125 temp = std::max(one - sqr(cs), zero);
1126 sn = std::sqrt(temp);
1127 pairs[numPairs++] = std::make_pair(cs, sn);
1128 if (sn != zero)
1129 pairs[numPairs++] = std::make_pair(cs, -sn);
1130 }
1131 }
1132 }
1133 }
1134 else {
1135 // H(cs,sn) = p6(cs)
1136 degree = static_cast<int32_t>(p6.GetDegree());
1137 assert(degree > 0);
1138 numRoots = RootsPolynomial::Find(degree, &p6[0], maxIterations, roots.data());
1139 for (size_t i = 0; i < numRoots; ++i) {
1140 uniqueRoots.insert(roots[i]);
1141 }
1142
1143 for (auto const& cs : uniqueRoots) {
1144 if (std::fabs(cs) <= one) {
1145 temp = std::max(one - sqr(cs), zero);
1146 sn = std::sqrt(temp);
1147 pairs[numPairs++] = std::make_pair(cs, sn);
1148 if (sn != zero)
1149 pairs[numPairs++] = std::make_pair(cs, -sn);
1150 }
1151 }
1152 }
1153
1154 for (size_t i = 0; i < numPairs; ++i) {
1155 ClosestInfo& info = candidates[i];
1156 Vec3d delta = D + r1 * (pairs[i].first * U1 + pairs[i].second * V1);
1157 info.circle1Closest = c0 + delta;
1158 const double N0dDelta = n0.dot(delta);
1159 const double lenN0xDelta = n0.cross(delta).norm();
1160 if (lenN0xDelta > 0.0) {
1161 const double diff = lenN0xDelta - r0;
1162 info.sqrDistance = sqr(N0dDelta) + sqr(diff);
1163 delta -= N0dDelta * n0;
1164 delta.normalize();
1165 info.circle0Closest = c0 + r0 * delta;
1166 }
1167 else {
1168 const Vec3d r0U0 = r0 * get_orthogonal(n0, true);
1169 const Vec3d diff = delta - r0U0;
1170 info.sqrDistance = diff.dot(diff);
1171 info.circle0Closest = c0 + r0U0;
1172 }
1173 }
1174
1175 std::sort(candidates.begin(), candidates.begin() + numPairs);
1176 }
1177 else {
1178 ClosestInfo& info = candidates[0];
1179
1180 const double N0dD = n0.dot(D);
1181 const Vec3d normProj = N0dD * n0;
1182 const Vec3d compProj = D - normProj;
1183 Vec3d U = compProj;
1184 const double d = U.norm();
1185 U.normalize();
1186
1187 // The configuration is determined by the relative location of the
1188 // intervals of projection of the circles on to the D-line.
1189 // Circle0 projects to [-r0,r0] and circle1 projects to
1190 // [d-r1,d+r1].
1191 const double dmr1 = d - r1;
1192 double distance;
1193 if (dmr1 >= r0) {
1194 // d >= r0 + r1
1195 // The circles are separated (d > r0 + r1) or tangent with one
1196 // outside the other (d = r0 + r1).
1197 distance = dmr1 - r0;
1198 info.circle0Closest = c0 + r0 * U;
1199 info.circle1Closest = c1 - r1 * U;
1200 }
1201 else {
1202 // d < r0 + r1
1203 // The cases implicitly use the knowledge that d >= 0.
1204 const double dpr1 = d + r1;
1205 if (dpr1 <= r0) {
1206 // Circle1 is inside circle0.
1207 distance = r0 - dpr1;
1208 if (d > 0.0) {
1209 info.circle0Closest = c0 + r0 * U;
1210 info.circle1Closest = c1 + r1 * U;
1211 }
1212 else {
1213 // The circles are concentric, so U = (0,0,0).
1214 // Construct a vector perpendicular to N0 to use for
1215 // closest points.
1216 U = get_orthogonal(n0, true);
1217 info.circle0Closest = c0 + r0 * U;
1218 info.circle1Closest = c1 + r1 * U;
1219 }
1220 }
1221 else if (dmr1 <= -r0) {
1222 // Circle0 is inside circle1.
1223 distance = -r0 - dmr1;
1224 if (d > 0.0) {
1225 info.circle0Closest = c0 - r0 * U;
1226 info.circle1Closest = c1 - r1 * U;
1227 }
1228 else {
1229 // The circles are concentric, so U = (0,0,0).
1230 // Construct a vector perpendicular to N0 to use for
1231 // closest points.
1232 U = get_orthogonal(n0, true);
1233 info.circle0Closest = c0 + r0 * U;
1234 info.circle1Closest = c1 + r1 * U;
1235 }
1236 }
1237 else {
1238 distance = (c1 - c0).norm();
1239 info.circle0Closest = c0;
1240 info.circle1Closest = c1;
1241 }
1242 }
1243
1244 info.sqrDistance = distance * distance;
1245 }
1246 if (deal_circle_result == false) {
1247 result.distance_infinite = std::make_optional(
1248 DistAndPoints{std::sqrt(candidates[0].sqrDistance), candidates[0].circle0Closest, candidates[0].circle1Closest}); // TODO
1249 } else {
1250 const double dist = (c0 - c1).norm();
1251 result.distance_strict = std::make_optional(DistAndPoints{dist, c0, c1});
1252 }
1253
1255 } else if (f2.get_type() == SurfaceFeatureType::Plane) {
1256 const auto [center, radius, normal1] = f1.get_circle();
1257 const auto [idx2, normal2, origin2] = f2.get_plane();
1258
1259 const bool coplanar = are_parallel(normal1, normal2) && Eigen::Hyperplane<double, 3>(normal1, center).absDistance(origin2) < EPSILON;
1260 if (!coplanar) {
1261 auto plane_features = f2.world_plane_features;
1262 std::vector<DistAndPoints> distances;
1263 for (const SurfaceFeature& sf : *plane_features) {
1264 if (sf.get_type() == SurfaceFeatureType::Edge) {
1265 const auto m = get_measurement(sf, f1);
1266 if (!m.distance_infinite.has_value()) {
1267 distances.clear();
1268 break;
1269 }
1270 else
1271 distances.push_back(*m.distance_infinite);
1272 }
1273 }
1274 if (!distances.empty()) {
1275 auto it = std::min_element(distances.begin(), distances.end(),
1276 [](const DistAndPoints& item1, const DistAndPoints& item2) {
1277 return item1.dist < item2.dist;
1278 });
1279 result.distance_infinite = std::make_optional(DistAndPoints{ it->dist, it->from, it->to });
1280 }
1281 else {
1282 const Eigen::Hyperplane<double, 3> plane(normal2, origin2);
1283 result.distance_infinite = std::make_optional(DistAndPoints{plane.absDistance(center), center, plane.projection(center)});
1284 }
1285 }
1286 else {
1287 result.distance_strict = std::make_optional(DistAndPoints{0, center, origin2});
1288 }
1289 }
1293 } else if (f1.get_type() == SurfaceFeatureType::Plane) {
1294 const auto [idx1, normal1, pt1] = f1.get_plane();
1295 const auto [idx2, normal2, pt2] = f2.get_plane();
1296
1297 if (are_parallel(normal1, normal2)) {
1298 // The planes are parallel, calculate distance.
1299 const Eigen::Hyperplane<double, 3> plane(normal2, pt2);
1300 result.distance_infinite = std::make_optional(DistAndPoints{ plane.absDistance(pt1), pt1, plane.projection(pt1) });
1301 }
1302 else
1303 result.angle = angle_plane_plane(f1.get_plane(), f2.get_plane());
1304 }
1305
1306 if (swap) {
1307 auto swap_dist_and_points = [](DistAndPoints& dp) {
1308 auto back = dp.to;
1309 dp.to = dp.from;
1310 dp.from = back;
1311 };
1312 if (result.distance_infinite.has_value()) {
1313 swap_dist_and_points(*result.distance_infinite);
1314 }
1315 if (result.distance_strict.has_value()) {
1316 swap_dist_and_points(*result.distance_strict);
1317 }
1318 }
1319 return result;
1320}
static bool operator<(wxColour const &l, wxColour const &r)
Definition StateColor.cpp:11
Definition MeasureUtils.hpp:21
static int32_t Find(int32_t degree, const double *c, uint32_t maxIterations, double *roots)
Definition MeasureUtils.hpp:195
std::tuple< Vec3d, double, Vec3d > get_circle() const
Definition Measure.hpp:62
std::shared_ptr< std::vector< SurfaceFeature > > world_plane_features
Definition Measure.hpp:96
Vec3d get_point() const
Definition Measure.hpp:57
T dist(const boost::polygon::point_data< T > &p1, const boost::polygon::point_data< T > &p2)
Definition Geometry.cpp:298
static AngleAndEdges angle_plane_plane(const std::tuple< int, Vec3d, Vec3d > &p1, const std::tuple< int, Vec3d, Vec3d > &p2)
Definition Measure.cpp:818
static AngleAndEdges angle_edge_plane(const std::pair< Vec3d, Vec3d > &e, const std::tuple< int, Vec3d, Vec3d > &p)
Definition Measure.cpp:767
MeasurementResult get_measurement(const SurfaceFeature &a, const SurfaceFeature &b, bool deal_circle_result)
Definition Measure.cpp:856
Vec3d get_orthogonal(const Vec3d &v, bool unitLength)
Definition MeasureUtils.hpp:362
@ Undef
Definition Measure.hpp:24
float distance(SpiralVase::SpiralPoint a, SpiralVase::SpiralPoint b)
Definition SpiralVase.cpp:19
constexpr T sqr(T x)
Definition libslic3r.h:301
Slic3r::Polygons diff(const Slic3r::Polygon &subject, const Slic3r::Polygon &clip, ApplySafetyOffset do_safety_offset)
Definition ClipperUtils.cpp:731
Definition Measure.hpp:145
Definition Measure.hpp:165
std::optional< DistAndPoints > distance_infinite
Definition Measure.hpp:167
std::optional< AngleAndEdges > angle
Definition Measure.hpp:166
std::optional< Vec3d > distance_xyz
Definition Measure.hpp:169
std::optional< DistAndPoints > distance_strict
Definition Measure.hpp:168

References Slic3r::Measure::MeasurementResult::angle, angle_edge_edge(), angle_edge_plane(), angle_plane_plane(), are_parallel(), are_perpendicular(), Slic3r::center(), Circle, Slic3r::diff(), Slic3r::Geometry::dist(), Slic3r::Measure::MeasurementResult::distance_infinite, Slic3r::Measure::MeasurementResult::distance_strict, Slic3r::Measure::MeasurementResult::distance_xyz, Edge, EPSILON, Slic3r::Measure::RootsPolynomial::Find(), Slic3r::Measure::SurfaceFeature::get_circle(), Slic3r::Measure::SurfaceFeature::get_edge(), get_measurement(), get_orthogonal(), Slic3r::Measure::SurfaceFeature::get_plane(), Slic3r::Measure::SurfaceFeature::get_point(), Slic3r::Measure::SurfaceFeature::get_type(), Slic3r::Measure::Polynomial1::GetDegree(), Slic3r::normal(), operator<(), orthonormal_basis(), Plane, Point, Slic3r::sqr(), Undef, and Slic3r::Measure::SurfaceFeature::world_plane_features.

Referenced by Slic3r::Measure::MeasuringImpl::get_feature(), get_measurement(), and Slic3r::GUI::GLGizmoMeasure::update_measurement_result().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_one_point_in_plane()

Vec3d Slic3r::Measure::get_one_point_in_plane ( const Vec3d & plane_origin,
const Vec3d & plane_normal )
50{
51 Vec3d dir(1, 0, 0);
52 float eps = 1e-3;
53 if (abs(plane_normal.dot(dir)) > 1 - eps) {
54 dir = Vec3d(0, 1, 0);
55 }
56 Vec3d new_pt = plane_origin + dir;
57 Vec3d retult;
58 get_point_projection_to_plane(new_pt, plane_origin, plane_normal, retult);
59 return retult;
60}

References get_point_projection_to_plane(), and plane_normal().

Referenced by Slic3r::GUI::GLGizmoMeasure::set_to_reverse_rotation(), and Slic3r::Measure::SurfaceFeature::translate().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_orthogonal()

Vec3d Slic3r::Measure::get_orthogonal ( const Vec3d & v,
bool unitLength )
inline
363{
364 double cmax = std::fabs(v[0]);
365 int32_t imax = 0;
366 for (int32_t i = 1; i < 3; ++i) {
367 double c = std::fabs(v[i]);
368 if (c > cmax) {
369 cmax = c;
370 imax = i;
371 }
372 }
373
374 Vec3d result = Vec3d::Zero();
375 int32_t inext = imax + 1;
376 if (inext == 3)
377 inext = 0;
378
379 result[imax] = v[inext];
380 result[inext] = -v[imax];
381 if (unitLength) {
382 const double sqrDistance = result[imax] * result[imax] + result[inext] * result[inext];
383 const double invLength = 1.0 / std::sqrt(sqrDistance);
384 result[imax] *= invLength;
385 result[inext] *= invLength;
386 }
387 return result;
388}

Referenced by get_measurement(), and Slic3r::GUI::GLGizmoMeasure::show_selection_ui().

Here is the caller graph for this function:

◆ get_point_projection_to_plane()

bool Slic3r::Measure::get_point_projection_to_plane ( const Vec3d & pt,
const Vec3d & plane_origin,
const Vec3d & plane_normal,
Vec3d & intersection_pt )
41{
42 Vec3d normal = plane_normal.normalized();
43 Vec3d BA = plane_origin - pt;
44 auto length = BA.dot(normal);
45 intersection_pt = pt + length * normal;
46 return true;
47}
double length(const Points &pts)
Definition MultiPoint.hpp:181

References Slic3r::length(), Slic3r::normal(), and plane_normal().

Referenced by get_assembly_action(), get_one_point_in_plane(), Slic3r::GUI::GLGizmoMeasure::set_parallel_distance(), and Slic3r::Measure::SurfaceFeature::translate().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ operator*() [1/2]

Polynomial1 Slic3r::Measure::operator* ( const Polynomial1 & p0,
const Polynomial1 & p1 )
inline
102{
103 const uint32_t p0Degree = p0.GetDegree();
104 const uint32_t p1Degree = p1.GetDegree();
105 Polynomial1 result(p0Degree + p1Degree);
106 result.SetCoefficients(0.0);
107 for (uint32_t i0 = 0; i0 <= p0Degree; ++i0) {
108 for (uint32_t i1 = 0; i1 <= p1Degree; ++i1) {
109 result[i0 + i1] += p0[i0] * p1[i1];
110 }
111 }
112 return result;
113}
uint32_t GetDegree() const
Definition MeasureUtils.hpp:74

References Slic3r::Measure::Polynomial1::GetDegree(), and Slic3r::Measure::Polynomial1::SetCoefficients().

Here is the call graph for this function:

◆ operator*() [2/2]

Polynomial1 Slic3r::Measure::operator* ( double scalar,
const Polynomial1 & p )
inline
174{
175 const uint32_t degree = p.GetDegree();
176 Polynomial1 result(degree);
177 for (uint32_t i = 0; i <= degree; ++i) {
178 result[i] = scalar * p[i];
179 }
180 return result;
181}

References Slic3r::Measure::Polynomial1::GetDegree().

Here is the call graph for this function:

◆ operator+()

Polynomial1 Slic3r::Measure::operator+ ( const Polynomial1 & p0,
const Polynomial1 & p1 )
inline
116{
117 const uint32_t p0Degree = p0.GetDegree();
118 const uint32_t p1Degree = p1.GetDegree();
119 uint32_t i;
120 if (p0Degree >= p1Degree) {
121 Polynomial1 result(p0Degree);
122 for (i = 0; i <= p1Degree; ++i) {
123 result[i] = p0[i] + p1[i];
124 }
125 for (/**/; i <= p0Degree; ++i) {
126 result[i] = p0[i];
127 }
128 result.EliminateLeadingZeros();
129 return result;
130 }
131 else {
132 Polynomial1 result(p1Degree);
133 for (i = 0; i <= p0Degree; ++i) {
134 result[i] = p0[i] + p1[i];
135 }
136 for (/**/; i <= p1Degree; ++i) {
137 result[i] = p1[i];
138 }
139 result.EliminateLeadingZeros();
140 return result;
141 }
142}

References Slic3r::Measure::Polynomial1::EliminateLeadingZeros(), and Slic3r::Measure::Polynomial1::GetDegree().

Here is the call graph for this function:

◆ operator-()

Polynomial1 Slic3r::Measure::operator- ( const Polynomial1 & p0,
const Polynomial1 & p1 )
inline
145{
146 const uint32_t p0Degree = p0.GetDegree();
147 const uint32_t p1Degree = p1.GetDegree();
148 uint32_t i;
149 if (p0Degree >= p1Degree) {
150 Polynomial1 result(p0Degree);
151 for (i = 0; i <= p1Degree; ++i) {
152 result[i] = p0[i] - p1[i];
153 }
154 for (/**/; i <= p0Degree; ++i) {
155 result[i] = p0[i];
156 }
157 result.EliminateLeadingZeros();
158 return result;
159 }
160 else {
161 Polynomial1 result(p1Degree);
162 for (i = 0; i <= p0Degree; ++i) {
163 result[i] = p0[i] - p1[i];
164 }
165 for (/**/; i <= p1Degree; ++i) {
166 result[i] = -p1[i];
167 }
168 result.EliminateLeadingZeros();
169 return result;
170 }
171}

References Slic3r::Measure::Polynomial1::EliminateLeadingZeros(), and Slic3r::Measure::Polynomial1::GetDegree().

Here is the call graph for this function:

◆ orthonormal_basis()

std::array< Vec3d, 3 > Slic3r::Measure::orthonormal_basis ( const Vec3d & v)
static
87{
88 std::array<Vec3d, 3> ret;
89 ret[2] = v.normalized();
90 int index;
91 ret[2].cwiseAbs().maxCoeff(&index);
92 switch (index)
93 {
94 case 0: { ret[0] = Vec3d(ret[2].y(), -ret[2].x(), 0.0).normalized(); break; }
95 case 1: { ret[0] = Vec3d(0.0, ret[2].z(), -ret[2].y()).normalized(); break; }
96 case 2: { ret[0] = Vec3d(-ret[2].z(), 0.0, ret[2].x()).normalized(); break; }
97 }
98 ret[1] = ret[2].cross(ret[0]).normalized();
99 return ret;
100}

Referenced by angle_edge_plane(), and get_measurement().

Here is the caller graph for this function:

◆ plane_normal()

Vec3d Slic3r::Measure::plane_normal ( const SurfaceFeature & plane)
inline
207 {
208 assert(plane.get_type() == SurfaceFeatureType::Plane);
209 return std::get<1>(plane.get_plane());
210}

References Slic3r::Measure::SurfaceFeature::get_plane(), Slic3r::Measure::SurfaceFeature::get_type(), and Plane.

Referenced by are_parallel(), are_perpendicular(), get_one_point_in_plane(), and get_point_projection_to_plane().

Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ feature_hover_limit

double Slic3r::Measure::feature_hover_limit = 0.5
constexpr