Beispiel #1
0
std::deque<Vector> FlowMath::computeStreamlineEuler(const Flow& flow,
                                           const Vector& r0,
                                           const float length,
                                           const float stepwidth,
                                           int* const startIndex,
                                           const tgt::vec2& thresholds)
{
    // N: number of partitions
    //
    const float h = fabsf(stepwidth);
    float fn = ceilf(fabsf(length) / h);
    const unsigned int N = (length != 0.0f) ? static_cast<unsigned int>(fn) : 0;

    Vector r(r0), r_(r0);

    std::deque<Vector> points;
    points.push_back(r0);
    int indexR0 = 0;

    bool lookupPos = true;  // integrate along the streamline in positive direction?
    bool lookupNeg = true;  // integrate along the streamline in negative direction?
    bool useThresholds = (thresholds != tgt::vec2::zero);

    for (unsigned int i = 0; ((N == 0) || (i < N)) ; ++i) {
        if (lookupPos == true) {
            const Vector& v = flow.lookupFlow(r);
            if (useThresholds == true) {
                float magnitude = tgt::length(v);
                if ((magnitude < thresholds.x) || (magnitude > thresholds.y)) {
                    lookupPos = false;
                    break;
                }
            }

            if (v != Vector::zero) {
                r += normalize(v) * h;

                lookupPos = flow.isInsideBoundings(r);
                if (r == points.back()) // in case of no progress on streamline in this direction...
                    lookupPos = false;
                else if (lookupPos == true)
                    points.push_back(r);
            } else
                lookupPos = false;
        }

        if (lookupNeg == true) {
            const Vector& v = flow.lookupFlow(r_);
            if (useThresholds == true) {
                float magnitude = tgt::length(v);
                if ((magnitude < thresholds.x) || (magnitude > thresholds.y)) {
                    lookupNeg = false;
                    break;
                }
            }

            if (v != Vector::zero) {
                r_ -= normalize(v) * h;

                lookupNeg = flow.isInsideBoundings(r_);
                if (r_ == points.front()) // in case of no progress on streamline in this direction...
                    lookupNeg = false;
                else if (lookupNeg == true) {
                    points.push_front(r_);
                    ++indexR0;
                }
            } else
                lookupNeg = false;
        }

        if ((lookupPos == false) && (lookupNeg == false))
            break;
    }   // for ( ; ; ++i)

    if (startIndex != 0)
        *startIndex = indexR0;

    return points;
}
Beispiel #2
0
std::deque<Vector> FlowMath::computeStreamlineRungeKutta(const Flow& flow,
                                                const Vector& r0,
                                                const float length,
                                                const float stepwidth,
                                                int* const startIndex,
                                                const tgt::vec2& thresholds)
{
    // N: number of partitions
    //
    const float h = fabsf(stepwidth);
    float fn = ceilf(fabsf(length) / h);
    const unsigned int N = (length != 0.0f) ? static_cast<unsigned int>(fn) : 0;

    Vector r(r0), r_(r0);
    Vector k1(0.0f), k2(0.0f), k3(0.0f), k4(0.0f);
    Vector k1_(0.0f), k2_(0.0f), k3_(0.0f), k4_(0.0f);

    std::deque<Vector> points;    // points on streamline in positive direction
    points.push_back(r0);       // avoid that one of the deque is empty
    int indexR0 = 0;            // position of r0 within deque

    bool lookupPos = true;  // integrate along the streamline in positive direction?
    bool lookupNeg = true;  // integrate along the streamline in negative direction?
    bool useThresholds = (thresholds != tgt::vec2::zero);

    for (unsigned int i = 0; ((N == 0) || (i < N)); ++i) {
        if (lookupPos == true) {
            const Vector& v = flow.lookupFlow(r);
            if (useThresholds == true) {
                float magnitude = tgt::length(v);
                if ((magnitude < thresholds.x) || (magnitude > thresholds.y)) {
                    lookupPos = false;
                    break;
                }
            }

            if (v != Vector::zero) {
                k1 = normalize(v) * h;
                k2 = normalize( flow.lookupFlow(r + (k1 / 2.0f)) ) * h;
                k3 = normalize( flow.lookupFlow(r + (k2 / 2.0f)) ) * h;
                k4 = normalize( flow.lookupFlow(r + k3) ) * h;

                r += ((k1 / 6.0f) + (k2 / 3.0f) + (k3 / 3.0f) + (k4 / 6.0f));

                lookupPos = flow.isInsideBoundings(r);
                if (r == points.back()) // in case of no progress on streamline in this direction...
                    lookupPos = false;
                else if (lookupPos == true)
                    points.push_back(r);
            } else
                lookupPos = false;
        }

        if (lookupNeg == true) {
            const Vector& v = flow.lookupFlow(r_);
            if (useThresholds == true) {
                float magnitude = tgt::length(v);
                if ((magnitude < thresholds.x) || (magnitude > thresholds.y)) {
                    lookupNeg = false;
                    break;
                }
            }

            if (v != Vector::zero) {
                k1_ = normalize(v) * h;
                k2_ = normalize( flow.lookupFlow(r_ - (k1_ / 2.0f)) ) * h;
                k3_ = normalize( flow.lookupFlow(r_ - (k2_ / 2.0f)) ) * h;
                k4_ = normalize( flow.lookupFlow(r_ - k3_) ) * h;

                r_ -= ((k1_ / 6.0f) + (k2_ / 3.0f) + (k3_ / 3.0f) + (k4_ / 6.0f));

                lookupNeg = flow.isInsideBoundings(r_);
                if (r_ == points.front()) // in case of no progress on streamline in this direction...
                    lookupNeg = false;
                else if (lookupNeg == true) {
                    points.push_front(r_);
                    ++indexR0;
                }
            } else
                lookupNeg = false;
        }

        if ((lookupPos == false) && (lookupNeg == false))
            break;
    }   // for (; ; ++i)

    if (startIndex != 0)
        *startIndex = indexR0;

    return points;
}