PyObject* MatrixPy::rotateZ(PyObject * args) { double angle = 0; do { PyObject *object; if (PyArg_ParseTuple(args,"O!",&(Base::QuantityPy::Type), &object)) { Quantity *q = static_cast<Base::QuantityPy*>(object)->getQuantityPtr(); if (q->getUnit() == Base::Unit::Angle) { angle = q->getValueAs(Base::Quantity::Radian); break; } } PyErr_Clear(); if (PyArg_ParseTuple(args, "d: angle to rotate (double) needed", &angle)) { break; } PyErr_SetString(PyExc_TypeError, "For angle either float or Quantity expected"); return 0; } while (false); PY_TRY { getMatrixPtr()->rotZ(angle); } PY_CATCH; Py_Return; }
QString UnitsSchemaMmMin::schemaTranslate(const Quantity &quant, double &factor, QString &unitString) { Unit unit = quant.getUnit(); if (unit == Unit::Length) { unitString = QString::fromLatin1("mm"); factor = 1.0; } else if (unit == Unit::Angle) { unitString = QString::fromUtf8("\xC2\xB0"); //unitString = QString::fromUtf8(u8"\u00B0"); //C++11 - Not supported by VS2013 factor = 1.0; } else if (unit == Unit::Velocity) { unitString = QString::fromLatin1("mm/min"); factor = 1./60.; } else { // default action for all cases without special treatment: unitString = quant.getUnit().getString(); factor = 1.0; } return toLocale(quant, factor, unitString); }
double UnitsApi::toDbl(PyObject *ArgObj, const Base::Unit &u) { if (PyString_Check(ArgObj)) { // Parse the string QString str = QString::fromLatin1(PyString_AsString(ArgObj)); Quantity q = Quantity::parse(str); if (q.getUnit() == u) return q.getValue(); throw Base::Exception("Wrong unit type!"); } else if (PyFloat_Check(ArgObj)) { return PyFloat_AsDouble(ArgObj); } else if (PyInt_Check(ArgObj)) { return static_cast<double>(PyInt_AsLong(ArgObj)); } else { throw Base::Exception("Wrong parameter type!"); } }
Expression * AggregateFunctionExpression::eval() const { switch (static_cast<Function>(f)) { case SUM: case AVERAGE: case STDDEV: case COUNT: case MIN: case MAX: { RangeExpression * v = freecad_dynamic_cast<RangeExpression>(args[0]); Quantity q; Quantity mean; Quantity M2; int n = 0; bool first = true; if (!v) throw Exception("Expected range as argument"); Range range(v->getRange()); do { Property * p = owner->getPropertyByName(range.address().c_str()); PropertyQuantity * qp; PropertyFloat * fp; Quantity value; if (!p) continue; if ((qp = freecad_dynamic_cast<PropertyQuantity>(p)) != 0) value = qp->getQuantityValue(); else if ((fp = freecad_dynamic_cast<PropertyFloat>(p)) != 0) value = fp->getValue(); else throw Exception("Invalid property type for aggregate"); if (first) { q.setUnit(value.getUnit()); mean.setUnit(value.getUnit()); M2.setUnit(value.getUnit()); } switch (static_cast<Function>(f)) { case AVERAGE: n++; case SUM: q = q + value; break; case STDDEV: { n++; const Quantity delta = value - mean; mean = mean + delta / n; M2 = M2 + delta * (value - mean); break; } case COUNT: q = q + 1; break; case MIN: if (first || value < q) q = value; break; case MAX: if (first || value > q) q = value; break; default: break; } first = false; } while (range.next()); switch (static_cast<Function>(f)) { case AVERAGE: q = q / (double)n; break; case STDDEV: if (n < 2) q = Quantity(); else q = (M2 / (n - 1.0)).pow(Quantity(0.5)); break; default: break; } return new NumberExpression(owner, q); } default: return App::FunctionExpression::eval(); } }
double UnitsApi::toDbl(PyObject *ArgObj, const Base::Unit &u) { #if PY_MAJOR_VERSION >= 3 if (PyUnicode_Check(ArgObj)) { QString str = QString::fromUtf8(PyUnicode_AsUTF8(ArgObj)); #else if (PyString_Check(ArgObj)) { QString str = QString::fromLatin1(PyString_AsString(ArgObj)); #endif // Parse the string Quantity q = Quantity::parse(str); if (q.getUnit() == u) return q.getValue(); throw Base::UnitsMismatchError("Wrong unit type!"); } else if (PyFloat_Check(ArgObj)) { return PyFloat_AsDouble(ArgObj); } #if PY_MAJOR_VERSION < 3 else if (PyInt_Check(ArgObj)) { return static_cast<double>(PyInt_AsLong(ArgObj)); #else else if (PyLong_Check(ArgObj)) { return static_cast<double>(PyLong_AsLong(ArgObj)); #endif } else { throw Base::UnitsMismatchError("Wrong parameter type!"); } } Quantity UnitsApi::toQuantity(PyObject *ArgObj, const Base::Unit &u) { double d; #if PY_MAJOR_VERSION >= 3 if (PyUnicode_Check(ArgObj)) { QString str = QString::fromUtf8(PyUnicode_AsUTF8(ArgObj)); #else if (PyString_Check(ArgObj)) { QString str = QString::fromLatin1(PyString_AsString(ArgObj)); #endif // Parse the string Quantity q = Quantity::parse(str); d = q.getValue(); } else if (PyFloat_Check(ArgObj)) { d = PyFloat_AsDouble(ArgObj); } #if PY_MAJOR_VERSION < 3 else if (PyInt_Check(ArgObj)) { d = static_cast<double>(PyInt_AsLong(ArgObj)); #else else if (PyLong_Check(ArgObj)) { d = static_cast<double>(PyLong_AsLong(ArgObj)); #endif } else { throw Base::UnitsMismatchError("Wrong parameter type!"); } return Quantity(d,u); } void UnitsApi::setDecimals(int prec) { UserPrefDecimals = prec; } int UnitsApi::getDecimals() { return UserPrefDecimals; }
QString UnitsSchemaImperial1::schemaTranslate(const Quantity &quant, double &factor, QString &unitString) { double UnitValue = std::abs(quant.getValue()); Unit unit = quant.getUnit(); // for imperial user/programmer mind; UnitValue is in internal system, that means // mm/kg/s. And all combined units have to be calculated from there! // now do special treatment on all cases seems necessary: if (unit == Unit::Length) { // Length handling ============================ if (UnitValue < 0.00000254) {// smaller then 0.001 thou -> inch and scientific notation unitString = QString::fromLatin1("in"); factor = 25.4; } else if(UnitValue < 2.54) { // smaller then 0.1 inch -> Thou (mil) unitString = QString::fromLatin1("thou"); factor = 0.0254; } else if(UnitValue < 304.8) { unitString = QString::fromLatin1("\""); factor = 25.4; } else if(UnitValue < 914.4) { unitString = QString::fromLatin1("\'"); factor = 304.8; } else if(UnitValue < 1609344.0) { unitString = QString::fromLatin1("yd"); factor = 914.4; } else if(UnitValue < 1609344000.0) { unitString = QString::fromLatin1("mi"); factor = 1609344.0; } else { // bigger then 1000 mi -> scientific notation unitString = QString::fromLatin1("in"); factor = 25.4; } } else if (unit == Unit::Area) { // TODO Cascade for the Areas // default action for all cases without special treatment: unitString = QString::fromLatin1("in^2"); factor = 645.16; } else if (unit == Unit::Volume) { // TODO Cascade for the Volume // default action for all cases without special treatment: unitString = QString::fromLatin1("in^3"); factor = 16387.064; } else if (unit == Unit::Mass) { // TODO Cascade for the weights // default action for all cases without special treatment: unitString = QString::fromLatin1("lb"); factor = 0.45359237; } else if (unit == Unit::Pressure) { if (UnitValue < 6894.744) {// psi is the smallest unitString = QString::fromLatin1("psi"); factor = 6.894744825494; } else if (UnitValue < 6894744.825) { unitString = QString::fromLatin1("ksi"); factor = 6894.744825494; } else { // bigger then 1000 ksi -> psi + scientific notation unitString = QString::fromLatin1("psi"); factor = 6.894744825494; } } else if (unit == Unit::Velocity) { unitString = QString::fromLatin1("in/min"); factor = 25.4/60; } else { // default action for all cases without special treatment: unitString = quant.getUnit().getString(); factor = 1.0; } return toLocale(quant, factor, unitString); }
QString UnitsSchemaImperialBuilding::schemaTranslate(const Quantity &quant, double &factor, QString &unitString) { // this schema expresses distances in feet + inches + fractions // ex: 3'- 4 1/4" with proper rounding Unit unit = quant.getUnit(); if (unit == Unit::Length) { unitString = QString::fromLatin1("in"); factor = 25.4; // Total number of inches to format double totalInches = std::abs(quant.getValue())/factor; // minimum denominator (8 for 1/8, 16 for 1/16, etc) int minden; // Outputs int feet; // whole feet int inches; // whole inches int num,den; // numerator and denominator of fractional val std::stringstream output; // output stream // Intermediate values int ntot; // total fractional units int a,b,d; // used to compute greatest common denominator int tmp; // temporary variable for GCD // Get the current user specified minimum denominator minden = quant.getFormat().getDenominator(); // Compute and round the total number of fractional units ntot = (int)std::round(totalInches * (double)minden); // If this is zero, nothing to do but return if( ntot==0 ) return QString::fromLatin1("0"); // Compute the whole number of feet and remaining units feet = (int)std::floor(ntot / (12*minden)); ntot = ntot - 12*minden*feet; // Compute the remaining number of whole inches inches = (int)std::floor(ntot/minden); // Lastly the fractional quantities num = ntot - inches*minden; den = minden; // If numerator is not zero, compute greatest common divisor and reduce // fraction if( num!=0 ) { // initialize a = num; b = den; while (b != 0) { tmp = a % b; a = b; b = tmp; } d = a; num /= d; den /= d; } // Process into string. Start with negative sign if quantity is less // than zero if( quant.getValue() < 0 ) output << "-"; // Print feet if we have any if( feet!=0 ) { output << feet << "'"; // if there is to be trailing numbers, add space if( inches!=0 || num!=0 ) { output << " "; } } // Three cases: // 1. Whole inches, no fraction // 2. Whole inches, fraction // 3. Fraction only if( inches>0 && num==0 ) // case 1. { output << inches << "\""; } else if( inches>0 && num!=0 ) // case 2 { output << inches << "+" << num << "/" << den << "\""; } else if( inches==0 && num!=0 ) // case 3 { output << num << "/" << den << "\""; } // Done! return QString::fromLatin1(output.str().c_str()); } else if (unit == Unit::Area) { unitString = QString::fromLatin1("sqft"); factor = 92903.04; } else if (unit == Unit::Volume) { unitString = QString::fromLatin1("cuft"); factor = 28316846.592; } else if (unit == Unit::Velocity) { unitString = QString::fromLatin1("in/min"); factor = 25.4/60; } else { unitString = quant.getUnit().getString(); factor = 1.0; } return toLocale(quant, factor, unitString); }