Beispiel #1
0
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);
}
Beispiel #3
0
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();
    }
}
Beispiel #5
0
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);
}