Resolve #11825 - no automatic quantity conversion: App::anyToQuantity
This commit is contained in:
committed by
Chris Hennes
parent
d52cf81bce
commit
6a54591bac
@@ -37,6 +37,7 @@
|
||||
#include <sstream>
|
||||
#include <stack>
|
||||
#include <string>
|
||||
#include <regex>
|
||||
|
||||
#include <App/Application.h>
|
||||
#include <App/DocumentObject.h>
|
||||
@@ -517,6 +518,29 @@ Py::Object pyFromQuantity(const Quantity &quantity) {
|
||||
}
|
||||
}
|
||||
|
||||
static const std::regex REGEX_QUANTITY(
|
||||
R"(\s*)"
|
||||
R"(([-+]?[0-9]*[.]?[0-9]+([eE][-+]?[0-9]+)?))" // value
|
||||
R"(\s*)"
|
||||
R"(([^\s]+)?)" // unit
|
||||
R"(\s*)"
|
||||
);
|
||||
|
||||
// https://github.com/FreeCAD/FreeCAD/issues/11825
|
||||
Quantity parseQuantityFromText(std::string text) {
|
||||
std::smatch match;
|
||||
if (std::regex_match(text, match, REGEX_QUANTITY)) {
|
||||
std::string value_text = match[1];
|
||||
std::string unit_text = match[3];
|
||||
double value = std::stod(value_text);
|
||||
Unit unit = Unit(QString::fromStdString(unit_text));
|
||||
return Quantity(value, unit);
|
||||
} else {
|
||||
std::string error_message = "Failed to parse to Quantity: text='" + text + "'";
|
||||
PARSER_THROW(error_message);
|
||||
}
|
||||
}
|
||||
|
||||
Quantity anyToQuantity(const App::any &value, const char *msg) {
|
||||
if (is_type(value,typeid(Quantity))) {
|
||||
return cast<Quantity>(value);
|
||||
@@ -530,6 +554,10 @@ Quantity anyToQuantity(const App::any &value, const char *msg) {
|
||||
return Quantity(cast<float>(value));
|
||||
} else if (is_type(value,typeid(double))) {
|
||||
return Quantity(cast<double>(value));
|
||||
} else if (is_type(value,typeid(const char*))) {
|
||||
return parseQuantityFromText(std::string(cast<const char*>(value)));
|
||||
} else if (is_type(value,typeid(std::string))) {
|
||||
return parseQuantityFromText(cast<std::string>(value));
|
||||
}
|
||||
if(!msg)
|
||||
msg = "Failed to convert to Quantity";
|
||||
|
||||
@@ -49,6 +49,7 @@ using ExpressionPtr = std::unique_ptr<Expression>;
|
||||
|
||||
AppExport bool isAnyEqual(const App::any &v1, const App::any &v2);
|
||||
AppExport Base::Quantity anyToQuantity(const App::any &value, const char *errmsg = nullptr);
|
||||
AppExport Base::Quantity parseQuantityFromText(std::string text);
|
||||
|
||||
// Map of depending objects to a map of depending property name to the full referencing object identifier
|
||||
using ExpressionDeps = std::map<App::DocumentObject*, std::map<std::string, std::vector<ObjectIdentifier> > >;
|
||||
|
||||
@@ -49,4 +49,47 @@ TEST(Expression, test_e_rad)
|
||||
EXPECT_EQ(op->toString(), "e rad");
|
||||
op.release();
|
||||
}
|
||||
|
||||
TEST(Expression, parseQuantityFromText)
|
||||
{
|
||||
EXPECT_ANY_THROW(App::parseQuantityFromText("")) << "should not parse empty";
|
||||
EXPECT_ANY_THROW(App::parseQuantityFromText("mm")) << "should not parse missing value";
|
||||
EXPECT_NO_THROW(App::parseQuantityFromText("2")) << "ok to parse missing unit";
|
||||
EXPECT_NO_THROW(App::parseQuantityFromText("2mm"));
|
||||
EXPECT_NO_THROW(App::parseQuantityFromText("2 mm"));
|
||||
EXPECT_NO_THROW(App::parseQuantityFromText("\t \n .5e-3kg/m^3 \t"));
|
||||
EXPECT_NO_THROW(App::parseQuantityFromText("\n \t -6.7E3 \t A/m^2 \t"));
|
||||
EXPECT_EQ(App::parseQuantityFromText("2mm"), Base::Quantity(2.0, QString::fromStdString("mm"))); // exact ULP form
|
||||
EXPECT_EQ(App::parseQuantityFromText("2 mm"), Base::Quantity(2.0, QString::fromStdString("mm"))); // exact ULP form
|
||||
auto quant_one = App::parseQuantityFromText("\t \n.5e-3kg/m^3 \t");
|
||||
EXPECT_DOUBLE_EQ(quant_one.getValue(), 0.5e-3); // approximately equal, to within 4 ULPs
|
||||
EXPECT_EQ(quant_one.getUnit(), Base::Unit(QString::fromStdString("kg/m^3")));
|
||||
auto quant_two = App::parseQuantityFromText("\n \t -6.7E3 \t A/m^2 \t");
|
||||
EXPECT_DOUBLE_EQ(quant_two.getValue(), -6.7e+3); // approximately equal, to within 4 ULPs
|
||||
EXPECT_EQ(quant_two.getUnit(), Base::Unit(QString::fromStdString("A/m^2")));
|
||||
}
|
||||
|
||||
TEST(Expression, anyToQuantity)
|
||||
{
|
||||
EXPECT_EQ(App::anyToQuantity(Base::Quantity()), Base::Quantity());
|
||||
EXPECT_EQ(App::anyToQuantity(true), Base::Quantity(1.0));
|
||||
EXPECT_EQ(App::anyToQuantity(false), Base::Quantity(0.0));
|
||||
EXPECT_EQ(App::anyToQuantity(123), Base::Quantity(123.0));
|
||||
EXPECT_EQ(App::anyToQuantity(123L), Base::Quantity(123.0));
|
||||
EXPECT_EQ(App::anyToQuantity(123.0F), Base::Quantity(123.0));
|
||||
EXPECT_EQ(App::anyToQuantity(123.0), Base::Quantity(123.0));
|
||||
EXPECT_EQ(App::anyToQuantity("123"), Base::Quantity(123.0));
|
||||
EXPECT_EQ(App::anyToQuantity(std::string("123")), Base::Quantity(123.0));
|
||||
EXPECT_EQ(App::anyToQuantity("123 mm"), Base::Quantity(123.0, QString::fromStdString("mm")));
|
||||
EXPECT_EQ(App::anyToQuantity(std::string("123 mm")), Base::Quantity(123.0, QString::fromStdString("mm")));
|
||||
EXPECT_ANY_THROW(App::anyToQuantity(""));
|
||||
EXPECT_ANY_THROW(App::anyToQuantity("mm"));
|
||||
}
|
||||
|
||||
TEST(Expression, isAnyEqual)
|
||||
{
|
||||
EXPECT_TRUE(App::isAnyEqual("123 mm", "123 mm"));
|
||||
EXPECT_TRUE(App::isAnyEqual("123 mm", Base::Quantity(123.0, QString::fromStdString("mm"))));
|
||||
EXPECT_TRUE(App::isAnyEqual(Base::Quantity(123.0, QString::fromStdString("mm")), "123 mm"));
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
Reference in New Issue
Block a user