24 const std::vector<double>& p1,
25 const std::vector<double>&
p2,
26 const std::vector<double>& p3) {
27 for (
size_t i = 0; i < 3; ++i) {
28 if (!std::isfinite(
p2[i] - p1[i]) ||
29 !std::isfinite(p3[i] - p1[i])) {
37 const std::vector<double>& p1,
38 const std::vector<double>&
p2,
39 const std::vector<double>& p3,
41 std::vector<std::shared_ptr<SymbolicExpr>>& v1,
42 std::vector<std::shared_ptr<SymbolicExpr>>& v2) {
43 for (
size_t i = 0; i < 3; ++i) {
44 v1.push_back(SymbolicExpr::number(
45 p2[i] / point_scale - p1[i] / point_scale));
46 v2.push_back(SymbolicExpr::number(
47 p3[i] / point_scale - p1[i] / point_scale));
52 const std::vector<std::shared_ptr<SymbolicExpr>>& p1,
53 const std::vector<std::shared_ptr<SymbolicExpr>>&
p2,
54 const std::vector<std::shared_ptr<SymbolicExpr>>& p3,
55 std::vector<std::shared_ptr<SymbolicExpr>>& v1,
56 std::vector<std::shared_ptr<SymbolicExpr>>& v2,
58 for (
size_t i = 0; i < 3; ++i) {
62 SymbolicExpr::multiply(SymbolicExpr::number(-1), p1[i])),
64 "plane edge vector is outside the supported domain",
context);
69 SymbolicExpr::multiply(SymbolicExpr::number(-1), p1[i])),
71 "plane edge vector is outside the supported domain",
context);
73 v1.push_back(std::move(left.value()));
74 v2.push_back(std::move(
right.value()));
80 const std::vector<std::shared_ptr<SymbolicExpr>>& p1,
81 const std::vector<std::shared_ptr<SymbolicExpr>>&
p2,
82 const std::vector<std::shared_ptr<SymbolicExpr>>& p3,
83 std::vector<std::shared_ptr<SymbolicExpr>>& v1,
84 std::vector<std::shared_ptr<SymbolicExpr>>& v2,
86 const std::string& operation) {
87 std::vector<double> p1_values;
88 std::vector<double> p2_values;
89 std::vector<double> p3_values;
91 p1,
context, operation, &p1_values);
95 p3,
context, operation, &p3_values);
106 const bool numeric_points =
107 p1_scale.has_value() && p2_scale.has_value() && p3_scale.has_value();
108 bool scale_differences =
false;
109 double point_scale = 0.0;
110 if (numeric_points) {
111 point_scale = std::max(
112 p1_scale.value(), std::max(p2_scale.value(), p3_scale.value()));
114 p1_values, p2_values, p3_values);
118 if (scale_differences) {
120 p1_values, p2_values, p3_values, point_scale, v1, v2);
127 std::vector<std::shared_ptr<SymbolicExpr>>& v1,
128 std::vector<std::shared_ptr<SymbolicExpr>>& v2,
130 const std::string& operation) {
131 std::vector<double> v1_values;
132 std::vector<double> v2_values;
134 v1,
context, operation, &v1_values);
136 v2,
context, operation, &v2_values);
137 const bool numeric_edges = v1_scale.has_value() && v2_scale.has_value();
138 if (!numeric_edges) {
141 !v1_scale ? v1_scale.error() : v2_scale.error());
143 }
else if (v1_scale.value() != 0.0 && v2_scale.value() != 0.0) {
144 const double safe_high =
145 std::sqrt(std::numeric_limits<double>::max() / 12.0);
146 const double safe_low =
147 std::sqrt(std::numeric_limits<double>::min());
148 const bool scale_cross =
149 v1_scale.value() > safe_high / v2_scale.value() ||
150 v1_scale.value() < safe_low / v2_scale.value();
152 for (
size_t i = 0; i < 3; ++i) {
153 v1[i] = SymbolicExpr::number(
154 v1_values[i] / v1_scale.value());
155 v2[i] = SymbolicExpr::number(
156 v2_values[i] / v2_scale.value());
164 const std::vector<std::shared_ptr<SymbolicExpr>>& normal,
167 const std::string& operation) {
171 "three points are collinear, so no unique plane exists",
172 "plane normal nonzero condition cannot be verified")
175 "plane normal nonzero condition cannot be verified",
177 if (!numeric_edges) {
181 norm_sq.value(),
context, operation,
182 "three points are collinear, so no unique plane exists",
183 "plane normal nonzero condition cannot be verified");
189 std::vector<std::shared_ptr<SymbolicExpr>>&& normal,
190 const std::vector<std::shared_ptr<SymbolicExpr>>&
point,
192 const std::string& operation) {
196 d.value(), operation,
197 "plane constant is outside the supported domain",
context);
204 component, operation,
205 "plane normal component is outside the supported domain",
context);
207 component = std::move(simplified.value());
209 plane.
d = std::move(d_simplified.value());
216 const std::vector<std::shared_ptr<SymbolicExpr>>& p1,
217 const std::vector<std::shared_ptr<SymbolicExpr>>&
p2,
218 const std::vector<std::shared_ptr<SymbolicExpr>>& p3,
220 const std::string operation =
"plane_from_three_points";
230 if (p1.size() != 3) {
233 "plane construction requires 3-dimensional points",
236 auto step =
context.consume_steps(8, operation);
241 std::vector<std::shared_ptr<SymbolicExpr>> v1, v2;
242 auto edges = build_plane_edges(p1,
p2, p3, v1, v2,
context, operation);
246 auto numeric_edges = scale_plane_edges_for_cross(v1, v2,
context, operation);
247 if (!numeric_edges) {
255 auto nonzero = check_plane_normal_nonzero(
256 normal.value(), numeric_edges.value(),
context, operation);
260 return assemble_plane(std::move(normal.value()), p1,
context, operation);
261 }
catch (
const std::bad_alloc&) {
263 "vector geometry allocation failed",
265 }
catch (
const std::exception&
e) {
267 e.what(), operation);
272 const std::vector<std::shared_ptr<SymbolicExpr>>& p1,
273 const std::vector<std::shared_ptr<SymbolicExpr>>&
p2,
274 const std::vector<std::shared_ptr<SymbolicExpr>>& p3) {
284 const std::string operation =
"dihedral_angle";
293 const double pi = std::acos(-1.0);
294 const double acute_angle =
295 std::min(angle.value(),
pi - angle.
value());
297 SymbolicExpr::number(acute_angle));
298 }
catch (
const std::bad_alloc&) {
300 "vector geometry allocation failed",
302 }
catch (
const std::exception&
e) {
304 e.what(), operation);
static Result failure(CasErrc code, std::string message, std::string operation={})
static Result success(T value)
Result< void > build_plane_edges(const std::vector< std::shared_ptr< SymbolicExpr > > &p1, const std::vector< std::shared_ptr< SymbolicExpr > > &p2, const std::vector< std::shared_ptr< SymbolicExpr > > &p3, std::vector< std::shared_ptr< SymbolicExpr > > &v1, std::vector< std::shared_ptr< SymbolicExpr > > &v2, ComputationContext &context, const std::string &operation)
Result< bool > scale_plane_edges_for_cross(std::vector< std::shared_ptr< SymbolicExpr > > &v1, std::vector< std::shared_ptr< SymbolicExpr > > &v2, ComputationContext &context, const std::string &operation)
bool is_plane_budget_error(const Result< double > &result)
PlaneSymbolicResult assemble_plane(std::vector< std::shared_ptr< SymbolicExpr > > &&normal, const std::vector< std::shared_ptr< SymbolicExpr > > &point, ComputationContext &context, const std::string &operation)
Result< void > check_plane_normal_nonzero(const std::vector< std::shared_ptr< SymbolicExpr > > &normal, bool numeric_edges, ComputationContext &context, const std::string &operation)
Result< void > append_symbolic_plane_edges(const std::vector< std::shared_ptr< SymbolicExpr > > &p1, const std::vector< std::shared_ptr< SymbolicExpr > > &p2, const std::vector< std::shared_ptr< SymbolicExpr > > &p3, std::vector< std::shared_ptr< SymbolicExpr > > &v1, std::vector< std::shared_ptr< SymbolicExpr > > &v2, const std::string &operation, ComputationContext &context)
void append_scaled_plane_edges(const std::vector< double > &p1, const std::vector< double > &p2, const std::vector< double > &p3, double point_scale, std::vector< std::shared_ptr< SymbolicExpr > > &v1, std::vector< std::shared_ptr< SymbolicExpr > > &v2)
bool plane_point_differences_overflow(const std::vector< double > &p1, const std::vector< double > &p2, const std::vector< double > &p3)
Result< double > numeric_vector_scale_checked(const std::vector< std::shared_ptr< SymbolicExpr > > &expressions, ComputationContext &context, const std::string &operation, std::vector< double > *values=nullptr)
Result< void > validate_plane_checked(const PlaneSymbolic &plane, ComputationContext &context, const std::string &operation)
ExpressionResult simplify_checked(const std::shared_ptr< SymbolicExpr > &expr, const std::string &operation, const std::string &message, ComputationContext &context)
Result< void > checked_nonzero_numeric_or_exact(const std::shared_ptr< SymbolicExpr > &expr, ComputationContext &context, const std::string &operation, const std::string &domain_message, const std::string &inconclusive_message)
Result< void > validate_same_dimension_vectors(const std::vector< std::shared_ptr< SymbolicExpr > > &a, const std::vector< std::shared_ptr< SymbolicExpr > > &b, ComputationContext &context, const std::string &operation)
Result< void > checked_nonzero_numeric_vector(const std::vector< std::shared_ptr< SymbolicExpr > > &expressions, ComputationContext &context, const std::string &operation, const std::string &domain_message, const std::string &inconclusive_message)
const std::string const LimitExprPtr & point
VectorExprListResult vector_cross_checked(const std::vector< std::shared_ptr< SymbolicExpr > > &a, const std::vector< std::shared_ptr< SymbolicExpr > > &b, ComputationContext &context)
const PlaneSymbolic & plane
const std::vector< Polynomial< BigInt > > const BigInt ComputationContext & context
Result< PlaneSymbolic > PlaneSymbolicResult
Result< std::shared_ptr< SymbolicExpr > > ExpressionResult
Result of an operation that produces a symbolic expression.
PlaneSymbolicResult plane_from_three_points_checked(const std::vector< std::shared_ptr< SymbolicExpr > > &p1, const std::vector< std::shared_ptr< SymbolicExpr > > &p2, const std::vector< std::shared_ptr< SymbolicExpr > > &p3, ComputationContext &context)
std::vector< std::shared_ptr< SymbolicExpr > > normal
法向量。
ExpressionResult dihedral_angle_checked(const PlaneSymbolic &p1, const PlaneSymbolic &p2, ComputationContext &context)
__attribute__((visibility("default"))) LineSymbolicResult line_from_two_points_checked(const std __attribute__((visibility("default"))) LineSymbolicResult line_from_two_points_checked(const std __attribute__((visibility("default"))) PlaneSymbolicResult plane_from_three_points_checked(const std __attribute__((visibility("default"))) PlaneSymbolicResult plane_from_three_points_checked(const std const PlaneSymbolic & p2
VectorAngleResult vector_angle_checked(const std::vector< std::shared_ptr< SymbolicExpr > > &a, const std::vector< std::shared_ptr< SymbolicExpr > > &b, ComputationContext &context)
ExpressionResult vector_dot_checked(const std::vector< std::shared_ptr< SymbolicExpr > > &a, const std::vector< std::shared_ptr< SymbolicExpr > > &b, ComputationContext &context)
std::shared_ptr< SymbolicExpr > d
常数项。
由法向量和常数 d 定义的符号平面 ax + by + cz = d。