Ejemplo n.º 1
3
void WindPlot::updatePlot()
{
    clearPlottables();
    clearItems();

    // Return now if plot empty
    if (mMainWindow->dataSize() == 0) return;

    double lower = mMainWindow->rangeLower();
    double upper = mMainWindow->rangeUpper();

    QVector< double > t, x, y;

    double xMin, xMax;
    double yMin, yMax;

    int start = mMainWindow->findIndexBelowT(lower) + 1;
    int end   = mMainWindow->findIndexAboveT(upper);

    bool first = true;
    for (int i = start; i < end; ++i)
    {
        const DataPoint &dp = mMainWindow->dataPoint(i);

        t.append(dp.t);

        if (mMainWindow->units() == PlotValue::Metric)
        {
            x.append(dp.velE * MPS_TO_KMH);
            y.append(dp.velN * MPS_TO_KMH);
        }
        else
        {
            x.append(dp.velE * MPS_TO_MPH);
            y.append(dp.velN * MPS_TO_MPH);
        }

        if (first)
        {
            xMin = xMax = x.back();
            yMin = yMax = y.back();

            first = false;
        }
        else
        {
            if (x.back() < xMin) xMin = x.back();
            if (x.back() > xMax) xMax = x.back();

            if (y.back() < yMin) yMin = y.back();
            if (y.back() > yMax) yMax = y.back();
        }
    }

    QCPCurve *curve = new QCPCurve(xAxis, yAxis);
    curve->setData(t, x, y);
    curve->setPen(QPen(Qt::lightGray, mMainWindow->lineThickness()));

    setViewRange(xMin, xMax, yMin, yMax);

    if (mMainWindow->markActive())
    {
        const DataPoint &dpEnd = mMainWindow->interpolateDataT(mMainWindow->markEnd());

        t.clear();
        x.clear();
        y.clear();

        QVector< double > xMark, yMark;

        if (mMainWindow->units() == PlotValue::Metric)
        {
            xMark.append(dpEnd.velE * MPS_TO_KMH);
            yMark.append(dpEnd.velN * MPS_TO_KMH);
        }
        else
        {
            xMark.append(dpEnd.velE * MPS_TO_MPH);
            yMark.append(dpEnd.velN * MPS_TO_MPH);
        }

        QCPGraph *graph = addGraph();
        graph->setData(xMark, yMark);
        graph->setPen(QPen(Qt::black, mMainWindow->lineThickness()));
        graph->setLineStyle(QCPGraph::lsNone);
        graph->setScatterStyle(QCPScatterStyle::ssDisc);
    }

    updateWind(start, end);

    QVector< double > xMark, yMark;

    if (mMainWindow->units() == PlotValue::Metric)
    {
        xMark.append(mWindE * MPS_TO_KMH);
        yMark.append(mWindN * MPS_TO_KMH);
    }
    else
    {
        xMark.append(mWindE * MPS_TO_MPH);
        yMark.append(mWindN * MPS_TO_MPH);
    }

    QCPGraph *graph = addGraph();
    graph->setData(xMark, yMark);
    graph->setPen(QPen(Qt::red, mMainWindow->lineThickness()));
    graph->setLineStyle(QCPGraph::lsNone);
    graph->setScatterStyle(QCPScatterStyle::ssDisc);

    const double x0 = mWindE;
    const double y0 = mWindN;
    const double r = mVelAircraft;

    QVector< double > tCircle, xCircle, yCircle;

    for (int i = 0; i <= 100; ++i)
    {
        tCircle.append(i);

        const double x = x0 + r * cos((double) i / 100 * 2 * M_PI);
        const double y = y0 + r * sin((double) i / 100 * 2 * M_PI);

        if (mMainWindow->units() == PlotValue::Metric)
        {
            xCircle.append(x * MPS_TO_KMH);
            yCircle.append(y * MPS_TO_KMH);
        }
        else
        {
            xCircle.append(x * MPS_TO_MPH);
            yCircle.append(y * MPS_TO_MPH);
        }
    }

    curve = new QCPCurve(xAxis, yAxis);
    curve->setData(tCircle, xCircle, yCircle);
    curve->setPen(QPen(Qt::red, mMainWindow->lineThickness()));

    // Add label to show best fit
    QCPItemText *textLabel = new QCPItemText(this);

    const double factor = (mMainWindow->units() == PlotValue::Metric) ? MPS_TO_KMH : MPS_TO_MPH;
    const QString units = (mMainWindow->units() == PlotValue::Metric) ? "km/h" : "mph";

    double direction = atan2(-mWindE, -mWindN) / M_PI * 180.0;
    if (direction < 0) direction += 360.0;

    QPainter painter(this);
    double mmPerPix = (double) painter.device()->widthMM() / painter.device()->width();

    double xRatioPerPix = 1.0 / axisRect()->width();
    double xRatioPerMM = xRatioPerPix / mmPerPix;

    double yRatioPerPix = 1.0 / axisRect()->height();
    double yRatioPerMM = yRatioPerPix / mmPerPix;

    textLabel->setPositionAlignment(Qt::AlignBottom|Qt::AlignRight);
    textLabel->setTextAlignment(Qt::AlignRight);
    textLabel->position->setType(QCPItemPosition::ptAxisRectRatio);
    textLabel->position->setCoords(1 - 5 * xRatioPerMM,
                                   1 - 5 * yRatioPerMM);
    textLabel->setText(
                QString("Wind speed = %1 %2\nWind direction = %3 deg\nAircraft speed = %4 %5")
                    .arg(sqrt(mWindE * mWindE + mWindN * mWindN) * factor)
                    .arg(units)
                    .arg(direction)
                    .arg(mVelAircraft * factor)
                    .arg(units));

    replot();
}
Ejemplo n.º 2
0
void ForestWindAccumulator::presimulate( const VectorF &windVector, U32 ticks )
{
   PROFILE_SCOPE( ForestWindAccumulator_Presimulate );

   for ( U32 i = 0; i < ticks; i++ )
      updateWind( windVector, TickSec );
}
Ejemplo n.º 3
0
void ForestWindMgr::processTick()
{
   const F32 timeDelta = 0.032f;

   if ( mEmitters.empty() )
      return;

   PROFILE_SCOPE(ForestWindMgr_AdvanceTime);

   // Advance all ForestWinds.
   {
      PROFILE_SCOPE(ForestWindMgr_AdvanceTime_ForestWind_ProcessTick);

      ForestWindEmitterList::iterator iter = mEmitters.begin();
      for ( ; iter != mEmitters.end(); iter++ )
      {
         if (  (*iter)->getWind() &&
               (*iter)->isEnabled() )
         {
            (*iter)->updateMountPosition();

            ForestWind *wind = (*iter)->getWind();
            if ( wind )
               wind->processTick();
         }
      }
   }   

   // Assign the new global wind value used by the particle system.
   {
      ForestWindEmitter *pWindEmitter = getGlobalWind();
      if ( pWindEmitter == NULL )      
         ParticleEmitter::setWindVelocity( Point3F::Zero );
      else
      {
         ForestWind *pWind = pWindEmitter->getWind();
         ParticleEmitter::setWindVelocity( pWind->getDirection() * pWind->getStrength() );
      }
   }

   // Get the game connection and camera object
   // in order to retrieve the camera position.
   GameConnection *conn = GameConnection::getConnectionToServer();
   if ( !conn )
      return;

   GameBase *cam = conn->getCameraObject();
   if ( !cam )
      return;   

   const Point3F &camPos = cam->getPosition();

      

   // Gather TreePlacementInfo for trees near the camera.
   {
      PROFILE_SCOPE( ForestWindMgr_AdvanceTime_GatherTreePlacementInfo );
      
      smAdvanceSignal.trigger( camPos, smWindEffectRadius, &mPlacementInfo );
   }

   // Prepare to build a new local source map.
   {
      PROFILE_SCOPE( ForestWindMgr_AdvanceTime_SwapSources );
      AssertFatal( mPrevSources->isEmpty(), "prev sources not empty!" );
      
      swap( mSources, mPrevSources );      

      AssertFatal( mSources->isEmpty(), "swap failed!" );
   }

   // Update wind for each TreePlacementInfo
   {
      PROFILE_SCOPE( ForestWindMgr_AdvanceTime_UpdateWind );

      for( S32 i = 0; i < mPlacementInfo.size(); i++ )
      {
         const TreePlacementInfo &info = mPlacementInfo[i];      
         updateWind( camPos, info, timeDelta );    
      }

      mPlacementInfo.clear();
   }

   // Clean up any accumulators in the
   // previous local source map.
   {
      PROFILE_SCOPE( ForestWindMgr_AdvanceTime_Cleanup );

      IdToWindMap::Iterator sourceIter = mPrevSources->begin();
      for( ; sourceIter != mPrevSources->end(); sourceIter++ )
      {
         ForestWindAccumulator *accum = (*sourceIter).value;

         AssertFatal( accum, "Got null accumulator!" );
         delete accum;
      }

      mPrevSources->clear();
   }
}