Beispiel #1
0
Quantity Constraint::getPresentationValue() const
{
    Quantity quantity;
    switch (Type) {
    case Distance:
    case Radius:
    case DistanceX:
    case DistanceY:
        quantity.setValue(Value);
        quantity.setUnit(Unit::Length);
        break;
    case Angle:
        quantity.setValue(toDegrees<double>(Value));
        quantity.setUnit(Unit::Angle);
        break;
    case SnellsLaw:
        quantity.setValue(Value);
        break;
    default:
        quantity.setValue(Value);
        break;
    }

    QuantityFormat format = quantity.getFormat();
    format.option = QuantityFormat::None;
    format.format = QuantityFormat::Default;
    format.precision = 6; // QString's default
    quantity.setFormat(format);
    return quantity;
}
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();
    }
}