<commit_before>//----------------------------------------------------------------------------
//
// License:  See top level LICENSE.txt file.
//
// Author:  David Hicks
//
// Description: Evaluate geodetic functions.
//
//----------------------------------------------------------------------------

#include <ossim/base/ossimGeodeticEvaluator.h>
#include <ossim/base/ossimString.h>
#include <ossim/base/ossimTrace.h>
#include <ossim/base/ossimNotify.h>

#include <iostream>
#include <iomanip>

static ossimTrace traceDebug(ossimString("ossimGeodeticEvaluator:debug"));
static ossimTrace traceExec(ossimString("ossimGeodeticEvaluator:exec"));

//*****************************************************************************
//  METHOD: ossimGeodeticEvaluator::ossimGeodeticEvaluator()
//
//  Constructor.
//
//*****************************************************************************
ossimGeodeticEvaluator::ossimGeodeticEvaluator(const ossimEllipsoid& ell)
   :
      m_A(ell.getA()),
      m_B(ell.getB()),
      m_F(ell.getFlattening()),
      m_Ecc2(ell.eccentricitySquared())
{
   m_A2 = m_A*m_A;
   m_B2 = m_B*m_B;
   m_2ndEcc2 = (m_A2 - m_B2) / m_B2;
}

//*****************************************************************************
//  METHOD: ossimGeodeticEvaluator::ossimGeodeticEvaluator()
//
//  Destructor.
//
//*****************************************************************************
ossimGeodeticEvaluator::~ossimGeodeticEvaluator()
{
   if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG)
      << "DEBUG: ~ossimGeodeticEvaluator(): returning..." << std::endl;
}

//*****************************************************************************
//  METHOD: ossimGeodeticEvaluator::direct()
//
//  Equation numbers reference Vincenty:
//    http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf
//
//    p2   = unknown point
//    az21 = azimuth 2->1  (back azimuth)
//
//*****************************************************************************
bool ossimGeodeticEvaluator::direct(const ossimGpt& p1,
                                    const double& d,
                                    const double& az12,
                                    ossimGpt& p2,
                                    double& az21)
{
   if (traceDebug())
   {
      ossimNotify(ossimNotifyLevel_DEBUG)
         << "\nossimGeodeticEvaluator::direct DEBUG:" << std::endl;
   }

   bool computationOK = false;

   double phi1 = p1.latr();
   // double lam1 = p1.lonr();

   double cosalpha1 = cos(az12);
   double sinalpha1 = sin(az12);
   double tanU1 = (1.0 - m_F) * tan(phi1);
   double cosU1 = 1.0 / sqrt( 1.0 + tanU1 * tanU1 );
   double sinU1 = tanU1 * cosU1;

   // eq. 1
   double sigma1 = atan2(tanU1, cosalpha1);

   // eq. 2
   double sinalpha = cosU1 * sinalpha1;

   double sin2alpha = sinalpha * sinalpha;
   double cos2alpha = 1.0 - sin2alpha;

   double u2 = cos2alpha * m_2ndEcc2;

   // Eq. 3
   double A = 1 + u2 / 16384 * (4096 + u2 * (-768 + u2 * (320 - 175*u2)));

   // Eq. 4
   double B = u2 / 1024 * (256 + u2 * (-128 + u2 * (74 - 47*u2)));

   // iterate until there is a negligible change in sigma
   double dSig;
   double d_bA = d / (m_B * A);
   double sigma = d_bA;
   double sinsig;
   double cossig;
   double prevSigma = M_PI;
   double sigmaM2;
   double cos2sigm;
   double cos2sigm2;

   while (abs(sigma - prevSigma) > 1.e-12)
   {
      // eq. 5
      sigmaM2 = 2.0*sigma1 + sigma;
      cos2sigm = cos(sigmaM2);
      cos2sigm2 = cos2sigm * cos2sigm;
      sinsig = sin(sigma);
      cossig = cos(sigma);
      double sin2sig = sinsig*sinsig;

      // Eq. 6
      dSig = B * sinsig * (cos2sigm + B / 4 * (cossig * (-1 + 2*cos2sigm2) - B / 6 * cos2sigm * (-3 + 4*sin2sig) * (-3 + 4*cos2sigm2)));

      // eq. 7
      prevSigma = sigma;
      sigma = d_bA + dSig;
   }

   sigmaM2 = 2.0*sigma1 + sigma;
   cos2sigm = cos(sigmaM2);
   cos2sigm2 = cos2sigm * cos2sigm;
   cossig = cos(sigma);
   sinsig = sin(sigma);

   // eq. 8
   double tmp = sinU1*sinsig - cosU1*cossig*cosalpha1;
   double phi2 = atan2( sinU1*cossig + cosU1*sinsig*cosalpha1,
                        (1.0-m_F) * sqrt( sin2alpha + tmp*tmp));

   // eq. 9
   double lam = atan2(sinsig*sinalpha1, cosU1*cossig - sinU1*sinsig*cosalpha1);

   // eq. 10
   double C = m_F/16 * cos2alpha * (4 + m_F * (4 - 3*cos2alpha));

   // eq. 11
   double L = lam - (1-C) * m_F * sinalpha * (sigma + C * sinsig * (cos2sigm + C * cossig * (-1 + 2*cos2sigm2)));

   // eq. 12
   double alpha2 = atan2(sinalpha, -tmp);

   p2.latr(phi2);
   p2.lonr(p1.lonr() + L);
   az21 = alpha2 + M_PI;
   if (az21 < 0.0)
      az21 += 2.0*M_PI;
   if (az21 > 2.0*M_PI)
      az21 -= 2.0*M_PI;

   return computationOK;
}

//*****************************************************************************
//  METHOD: ossimGeodeticEvaluator::inverse()
//
//  Equation numbers reference Vincenty:
//    http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf
//
//    d    = distance (m)
//    az12 = azimuth 1->2
//    az21 = azimuth 2->1  (back azimuth)
//
//*****************************************************************************
bool ossimGeodeticEvaluator::inverse(const ossimGpt& p1,
                                     const ossimGpt& p2,
                                     double& d,
                                     double& az12,
                                     double& az21)
{
   if (traceDebug())
   {
      ossimNotify(ossimNotifyLevel_DEBUG)
         << "\nossimGeodeticEvaluator::inverse DEBUG:" << std::endl;
   }

   bool computationOK = false;

   double phi1 = p1.latr();
   double lam1 = p1.lonr();
   double phi2 = p2.latr();
   double lam2 = p2.lonr();

   double U1 = atan((1.0-m_F) * tan(phi1));
   double sinU1 = sin(U1);
   double cosU1 = cos(U1);

   double U2 = atan((1.0-m_F) * tan(phi2));
   double sinU2 = sin(U2);
   double cosU2 = cos(U2);

   double sinU1sinU2 = sinU1 * sinU2;
   double cosU1sinU2 = cosU1 * sinU2;
   double sinU1cosU2 = sinU1 * cosU2;
   double cosU1cosU2 = cosU1 * cosU2;

   // Eq. 13
   // 1st approximation
   double L = lam2 - lam1;
   double lam = L;

   // Auxiliaries
   double sig = 0.0;
   double dSig = 0.0;
   double lam0;
   double cos2alpha;
   double cos2sigm;
   double cos2sigm2;
   double sinsig;
   double sin2sig;
   double cossig;
   bool converged = false;

   int iter = 0;
   int iterMax = 100;
   int iterMin = 4;

   // Iterative loop
   do
   {
      iter++;

      double sinlam = sin(lam);
      double coslam = cos(lam);

      // Eq. 14
      double tmp = cosU1sinU2 - sinU1cosU2 * coslam;
      sin2sig = cosU2*sinlam * cosU2*sinlam + tmp * tmp;
      sinsig = sqrt(sin2sig);

      // Eq. 15
      cossig = sinU1sinU2 + (cosU1cosU2 * coslam);

      // Eq. 16
      sig = atan2(sinsig, cossig);

      // Eq. 17
      double sinalpha;
      if (sin2sig == 0.0)
         sinalpha = 0.0;
      else
         sinalpha = cosU1cosU2 * sinlam / sinsig;
      cos2alpha = 1.0 - sinalpha*sinalpha;

      // Eq. 18
      if (cos2alpha == 0.0)
         cos2sigm = 0.0;
      else
         cos2sigm = cossig - 2 * sinU1sinU2 / cos2alpha;
      cos2sigm2 = cos2sigm * cos2sigm;

      // Eq. 10
      double C = m_F/16 * cos2alpha * (4 + m_F * (4 - 3*cos2alpha));

      // Eq. 11
      lam0 = lam;
      lam = L + (1-C) * m_F * sinalpha * (sig + C * sinsig * (cos2sigm + C * cossig * (-1 + 2*cos2sigm2)));

      // Check delta lambda for convergence
      double delta = abs(lam - lam0);
      if (delta < 1e-13 && iter>=iterMin)
      {
        converged = true;
      }

   } while (!converged && iter<=iterMax);

   double u2 = cos2alpha * m_2ndEcc2;

   // Eq. 3
   double A = 1 + u2 / 16384 * (4096 + u2 * (-768 + u2 * (320 - 175*u2)));

   // Eq. 4
   double B = u2 / 1024 * (256 + u2 * (-128 + u2 * (74 - 47*u2)));

   // Eq. 6
   dSig = B * sinsig * (cos2sigm + B / 4 * (cossig * (-1 + 2*cos2sigm2) - B / 6 * cos2sigm * (-3 + 4*sin2sig) * (-3 + 4*cos2sigm2)));

   // Compute distance
   //  Eq. 19
   d = m_B * A * (sig - dSig);

   // Compute azimuths
   //  Diverged, same meridian or antipodal
   if (!converged)
   {
      if (phi1 > phi2)
      {
         az12 = M_PI;
         az21 = 0.0;
      }
      else if (phi1 < phi2)
      {
         az12 = 0.0;
         az21 = M_PI;
      }
      else
      {
         az12 = ossim::nan();
         az21 = ossim::nan();
      }
   }

   // Converged
   else
   {
      // Eq. 20
      az12 = atan2(cosU2 * sin(lam), (cosU1sinU2 - sinU1cosU2 * cos(lam)));
      if (az12 < 0.0) az12 += 2.0*M_PI;

      // Eq. 21
      az21 = atan2(cosU1 * sin(lam), (-sinU1cosU2 + cosU1sinU2 * cos(lam))) + M_PI;
      if (az21 < 0.0) az21 += 2.0*M_PI;

      computationOK = true;
   }

   return computationOK;
 }
<commit_msg>Added verbage to comments<commit_after>//----------------------------------------------------------------------------
//
// License:  See top level LICENSE.txt file.
//
// Author:  David Hicks
//
// Description: Evaluate geodetic functions.
//
//----------------------------------------------------------------------------

#include <ossim/base/ossimGeodeticEvaluator.h>
#include <ossim/base/ossimString.h>
#include <ossim/base/ossimTrace.h>
#include <ossim/base/ossimNotify.h>

#include <iostream>
#include <iomanip>

static ossimTrace traceDebug(ossimString("ossimGeodeticEvaluator:debug"));
static ossimTrace traceExec(ossimString("ossimGeodeticEvaluator:exec"));

//*****************************************************************************
//  METHOD: ossimGeodeticEvaluator::ossimGeodeticEvaluator()
//
//  Constructor.
//
//*****************************************************************************
ossimGeodeticEvaluator::ossimGeodeticEvaluator(const ossimEllipsoid& ell)
   :
      m_A(ell.getA()),
      m_B(ell.getB()),
      m_F(ell.getFlattening()),
      m_Ecc2(ell.eccentricitySquared())
{
   m_A2 = m_A*m_A;
   m_B2 = m_B*m_B;
   m_2ndEcc2 = (m_A2 - m_B2) / m_B2;
}

//*****************************************************************************
//  METHOD: ossimGeodeticEvaluator::ossimGeodeticEvaluator()
//
//  Destructor.
//
//*****************************************************************************
ossimGeodeticEvaluator::~ossimGeodeticEvaluator()
{
   if (traceExec())  ossimNotify(ossimNotifyLevel_DEBUG)
      << "DEBUG: ~ossimGeodeticEvaluator(): returning..." << std::endl;
}

//*****************************************************************************
//  METHOD: ossimGeodeticEvaluator::direct()
//
//  Equation numbers reference Vincenty:
//    http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf
//
//    p2   = unknown point
//    az21 = azimuth 2->1  (back azimuth)
//
//*****************************************************************************
bool ossimGeodeticEvaluator::direct(const ossimGpt& p1,
                                    const double& d,
                                    const double& az12,
                                    ossimGpt& p2,
                                    double& az21)
{
   if (traceDebug())
   {
      ossimNotify(ossimNotifyLevel_DEBUG)
         << "\nossimGeodeticEvaluator::direct DEBUG:" << std::endl;
   }

   bool computationOK = false;

   double phi1 = p1.latr();
   // double lam1 = p1.lonr();

   double cosalpha1 = cos(az12);
   double sinalpha1 = sin(az12);
   double tanU1 = (1.0 - m_F) * tan(phi1);
   double cosU1 = 1.0 / sqrt( 1.0 + tanU1 * tanU1 );
   double sinU1 = tanU1 * cosU1;

   // eq. 1
   double sigma1 = atan2(tanU1, cosalpha1);

   // eq. 2
   double sinalpha = cosU1 * sinalpha1;

   double sin2alpha = sinalpha * sinalpha;
   double cos2alpha = 1.0 - sin2alpha;

   double u2 = cos2alpha * m_2ndEcc2;

   // Eq. 3
   double A = 1 + u2 / 16384 * (4096 + u2 * (-768 + u2 * (320 - 175*u2)));

   // Eq. 4
   double B = u2 / 1024 * (256 + u2 * (-128 + u2 * (74 - 47*u2)));

   // iterate until there is a negligible change in sigma
   double dSig;
   double d_bA = d / (m_B * A);
   double sigma = d_bA;
   double sinsig;
   double cossig;
   double prevSigma = M_PI;
   double sigmaM2;
   double cos2sigm;
   double cos2sigm2;

   while (fabs(sigma - prevSigma) > 1.e-12)
   {
      // eq. 5
      sigmaM2 = 2.0*sigma1 + sigma;
      cos2sigm = cos(sigmaM2);
      cos2sigm2 = cos2sigm * cos2sigm;
      sinsig = sin(sigma);
      cossig = cos(sigma);
      double sin2sig = sinsig*sinsig;

      // Eq. 6
      dSig = B * sinsig * (cos2sigm + B / 4 * (cossig * (-1 + 2*cos2sigm2) - B / 6 * cos2sigm * (-3 + 4*sin2sig) * (-3 + 4*cos2sigm2)));

      // eq. 7
      prevSigma = sigma;
      sigma = d_bA + dSig;
   }

   sigmaM2 = 2.0*sigma1 + sigma;
   cos2sigm = cos(sigmaM2);
   cos2sigm2 = cos2sigm * cos2sigm;
   cossig = cos(sigma);
   sinsig = sin(sigma);

   // eq. 8
   double tmp = sinU1*sinsig - cosU1*cossig*cosalpha1;
   double phi2 = atan2( sinU1*cossig + cosU1*sinsig*cosalpha1,
                        (1.0-m_F) * sqrt( sin2alpha + tmp*tmp));

   // eq. 9
   double lam = atan2(sinsig*sinalpha1, cosU1*cossig - sinU1*sinsig*cosalpha1);

   // eq. 10
   double C = m_F/16 * cos2alpha * (4 + m_F * (4 - 3*cos2alpha));

   // eq. 11
   double L = lam - (1-C) * m_F * sinalpha * (sigma + C * sinsig * (cos2sigm + C * cossig * (-1 + 2*cos2sigm2)));

   // eq. 12
   double alpha2 = atan2(sinalpha, -tmp);

   p2.latr(phi2);
   p2.lonr(p1.lonr() + L);
   az21 = alpha2 + M_PI;
   if (az21 < 0.0)
      az21 += 2.0*M_PI;
   if (az21 > 2.0*M_PI)
      az21 -= 2.0*M_PI;

   return computationOK;
}

//*****************************************************************************
//  METHOD: ossimGeodeticEvaluator::inverse()
//
//  Equation numbers reference Vincenty:
//    http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf
//
//    d    = distance (m)
//    az12 = azimuth 1->2
//    az21 = azimuth 2->1  (back azimuth)
//
//*****************************************************************************
bool ossimGeodeticEvaluator::inverse(const ossimGpt& p1,
                                     const ossimGpt& p2,
                                     double& d,
                                     double& az12,
                                     double& az21)
{
   if (traceDebug())
   {
      ossimNotify(ossimNotifyLevel_DEBUG)
         << "\nossimGeodeticEvaluator::inverse DEBUG:" << std::endl;
   }

   bool computationOK = false;

   double phi1 = p1.latr();
   double lam1 = p1.lonr();
   double phi2 = p2.latr();
   double lam2 = p2.lonr();

   double U1 = atan((1.0-m_F) * tan(phi1));
   double sinU1 = sin(U1);
   double cosU1 = cos(U1);

   double U2 = atan((1.0-m_F) * tan(phi2));
   double sinU2 = sin(U2);
   double cosU2 = cos(U2);

   double sinU1sinU2 = sinU1 * sinU2;
   double cosU1sinU2 = cosU1 * sinU2;
   double sinU1cosU2 = sinU1 * cosU2;
   double cosU1cosU2 = cosU1 * cosU2;

   // Eq. 13
   // 1st approximation
   double L = lam2 - lam1;
   double lam = L;

   // Auxiliaries
   double sig = 0.0;
   double dSig = 0.0;
   double lam0;
   double cos2alpha;
   double cos2sigm;
   double cos2sigm2;
   double sinsig;
   double sin2sig;
   double cossig;
   bool converged = false;

   int iter = 0;
   int iterMax = 100;
   int iterMin = 4;

   // Iterative loop
   do
   {
      iter++;

      double sinlam = sin(lam);
      double coslam = cos(lam);

      // Eq. 14
      double tmp = cosU1sinU2 - sinU1cosU2 * coslam;
      sin2sig = cosU2*sinlam * cosU2*sinlam + tmp * tmp;
      sinsig = sqrt(sin2sig);

      // Eq. 15
      cossig = sinU1sinU2 + (cosU1cosU2 * coslam);

      // Eq. 16
      sig = atan2(sinsig, cossig);

      // Eq. 17
      double sinalpha;
      if (sin2sig == 0.0)
         sinalpha = 0.0;
      else
         sinalpha = cosU1cosU2 * sinlam / sinsig;
      cos2alpha = 1.0 - sinalpha*sinalpha;

      // Eq. 18
      if (cos2alpha == 0.0)
         cos2sigm = 0.0;
      else
         cos2sigm = cossig - 2 * sinU1sinU2 / cos2alpha;
      cos2sigm2 = cos2sigm * cos2sigm;

      // Eq. 10
      double C = m_F/16 * cos2alpha * (4 + m_F * (4 - 3*cos2alpha));

      // Eq. 11
      lam0 = lam;
      lam = L + (1-C) * m_F * sinalpha * (sig + C * sinsig * (cos2sigm + C * cossig * (-1 + 2*cos2sigm2)));

      // Check delta lambda for convergence
      double delta = fabs(lam - lam0);
      if (delta < 1e-13 && iter>=iterMin)
      {
        converged = true;
      }

   } while (!converged && iter<=iterMax);

   double u2 = cos2alpha * m_2ndEcc2;

   // Eq. 3
   double A = 1 + u2 / 16384 * (4096 + u2 * (-768 + u2 * (320 - 175*u2)));

   // Eq. 4
   double B = u2 / 1024 * (256 + u2 * (-128 + u2 * (74 - 47*u2)));

   // Eq. 6
   dSig = B * sinsig * (cos2sigm + B / 4 * (cossig * (-1 + 2*cos2sigm2) - B / 6 * cos2sigm * (-3 + 4*sin2sig) * (-3 + 4*cos2sigm2)));

   // Compute distance
   //  Eq. 19
   d = m_B * A * (sig - dSig);

   // Compute azimuths
   //  Diverged, same meridian or antipodal
   if (!converged)
   {
      if (phi1 > phi2)
      {
         az12 = M_PI;
         az21 = 0.0;
      }
      else if (phi1 < phi2)
      {
         az12 = 0.0;
         az21 = M_PI;
      }
      else
      {
         az12 = ossim::nan();
         az21 = ossim::nan();
      }
   }

   // Converged
   else
   {
      // Eq. 20
      az12 = atan2(cosU2 * sin(lam), (cosU1sinU2 - sinU1cosU2 * cos(lam)));
      if (az12 < 0.0) az12 += 2.0*M_PI;

      // Eq. 21
      az21 = atan2(cosU1 * sin(lam), (-sinU1cosU2 + cosU1sinU2 * cos(lam))) + M_PI;
      if (az21 < 0.0) az21 += 2.0*M_PI;

      computationOK = true;
   }

   return computationOK;
 }
<|endoftext|>


<commit_before>/*
   Copyright 2017 Thomas Krause <thomaskrause@posteo.de>

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

#include "dynamicbenchmark.h"
#include <annis/json/jsonqueryparser.h>

#include <humblelogging/api.h>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <string>
#include <stddef.h>

#include <cmath>

using namespace annis;

HUMBLE_LOGGER(benchLogger, "DynamicBenchmark");

std::shared_ptr<DBCache> DynamicCorpusFixture::dbCache
  = std::make_shared<DBCache>(0);

void DynamicCorpusFixture::UserBenchmark()
{
  while (q->next())
  {
    counter++;
  }
  HL_INFO(benchLogger, (boost::format("result %1%") % counter).str());
  if (expectedCount && counter != *expectedCount)
  {
    std::cerr << "FATAL ERROR: query " << benchmarkName << ":" << currentExperimentValue << " should have count " << *expectedCount << " but was " << counter << std::endl;
    std::cerr << "" << __FILE__ << ":" << __LINE__ << std::endl;
    exit(-1);
  }
}

std::vector<std::pair<int64_t, uint64_t> > DynamicCorpusFixture::getExperimentValues() const
{
  std::vector<std::pair<int64_t, uint64_t> > result;

  for (auto it : json)
  {
    result.push_back({it.first, 0});
  }

  return result;
}

void DynamicCorpusFixture::tearDown()
{
}

DynamicBenchmark::DynamicBenchmark(std::string queriesDir,
  std::string corpusPath, std::string benchmarkName, bool multipleExperimentsParam)
  : corpusPath(corpusPath), benchmarkName(benchmarkName), multipleExperiments(multipleExperimentsParam)
{
  // find all file ending with ".json" in the folder
  boost::filesystem::directory_iterator fileEndIt;

  boost::filesystem::directory_iterator itFiles(queriesDir);
  while (itFiles != fileEndIt)
  {
    const auto filePath = itFiles->path();
    if (filePath.extension().string() == ".json")
    {
      if(multipleExperiments)
      {
        // check if the file name is a valid number
        std::string name = filePath.filename().stem().string();
        try
        {
          std::stol(name);
        }
        catch(std::invalid_argument invalid)
        {
          // not a number, don't assume we have multiple experiments
          multipleExperiments = false;
        }
      }

      foundJSONFiles.push_back(filePath);
    }
    itFiles++;
  }

  if(foundJSONFiles.empty())
  {
    multipleExperiments = false;
  }

  QueryConfig baselineConfig;
  baselineConfig.forceFallback = true;
  registerFixtureInternal(true, "Baseline", baselineConfig);
}

void DynamicBenchmark::registerFixture(std::string fixtureName, const QueryConfig config)
{
  registerFixtureInternal(false, fixtureName, config);
}

void DynamicBenchmark::registerFixtureInternal(
  bool baseline,
  std::string fixtureName, const QueryConfig config)
{
  if (multipleExperiments)
  {
    std::map<int64_t, const boost::filesystem::path> paths;
    for (const auto& filePath : foundJSONFiles)
    {
      // try to get a numerical ID from the file name
      std::string name = filePath.filename().stem().string();
      auto id = std::stol(name);
      paths.insert({id, filePath});
    }
    addBenchmark(baseline, benchmarkName, paths, fixtureName, config);
  }
  else
  {
    for (const auto& filePath : foundJSONFiles)
    {
      std::map<int64_t, const boost::filesystem::path> paths;
      paths.insert({0, filePath});
      auto subBenchmarkName = benchmarkName + "_" + filePath.stem().string();
      addBenchmark(baseline, subBenchmarkName, paths, fixtureName, config);
    }
  }
}

void DynamicBenchmark::addBenchmark(bool baseline,
  std::string benchmarkName,
  std::map<int64_t, const boost::filesystem::path>& paths,
  std::string fixtureName,
  QueryConfig config)
{
  unsigned int numberOfSamples = 5;

  HL_INFO(benchLogger, (boost::format("adding benchmark %1%") % benchmarkName).str());

  std::map<int64_t, std::string> allQueries;
  std::map<int64_t, unsigned int> expectedCount;
  std::map<int64_t, uint64_t> fixedValues;

  for (auto p : paths)
  {
    auto countPath = p.second.parent_path() /= (p.second.stem().string() + ".count");

    boost::filesystem::ifstream stream;

    stream.open(countPath);
    if (stream.is_open())
    {
      unsigned int tmp;
      stream >> tmp;
      stream.close();
      expectedCount.insert({p.first, tmp});
    }

    stream.open(p.second);
    std::string queryJSON(
      (std::istreambuf_iterator<char>(stream)),
      (std::istreambuf_iterator<char>()));
    stream.close();

    allQueries.insert({p.first, queryJSON});

    if(baseline)
    {
      double timeVal = 0.0;
      auto timePath = p.second.parent_path() /= (p.second.stem().string() + ".time");
      stream.open(timePath);
      if (stream.is_open())
      {
        stream >> timeVal;
        stream.close();
      }
      if(timeVal > 0.0)
      {
        // since celero uses microseconds an ANNIS milliseconds the value needs to be converted
        fixedValues.insert({p.first, std::llround(timeVal*1000.0)});
      }
      else
      {
        // we would divide by zero later, thus use 1 micro second as smallest value
        fixedValues.insert({p.first, 1});
      }

    }
  }
  std::shared_ptr<::celero::TestFixture> fixture(
    new DynamicCorpusFixture(corpusPath, config, allQueries,
    benchmarkName + " (" + fixtureName + ")",
    expectedCount));

  if (baseline)
  {
    if(fixedValues.size() > 0)
    {
      std::shared_ptr<::celero::TestFixture> fixedFixture(new FixedValueFixture(fixedValues));
      celero::RegisterBaseline(benchmarkName.c_str(), fixtureName.c_str(), numberOfSamples, 1, 1,
        std::make_shared<DynamicCorpusFixtureFactory>(fixedFixture));

    }
    else
    {
     celero::RegisterBaseline(benchmarkName.c_str(), fixtureName.c_str(), numberOfSamples, 1, 1,
        std::make_shared<DynamicCorpusFixtureFactory>(fixture));
    }
  }
  else
  {
    celero::RegisterTest(benchmarkName.c_str(), fixtureName.c_str(), numberOfSamples, 1, 1,
      std::make_shared<DynamicCorpusFixtureFactory>(fixture));
  }
}

<commit_msg>Baseline is now always the count from the relANNIS system<commit_after>/*
   Copyright 2017 Thomas Krause <thomaskrause@posteo.de>

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

#include "dynamicbenchmark.h"
#include <annis/json/jsonqueryparser.h>

#include <humblelogging/api.h>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <string>
#include <stddef.h>

#include <cmath>

using namespace annis;

HUMBLE_LOGGER(benchLogger, "DynamicBenchmark");

std::shared_ptr<DBCache> DynamicCorpusFixture::dbCache
  = std::make_shared<DBCache>(0);

void DynamicCorpusFixture::UserBenchmark()
{
  while (q->next())
  {
    counter++;
  }
  HL_INFO(benchLogger, (boost::format("result %1%") % counter).str());
  if (expectedCount && counter != *expectedCount)
  {
    std::cerr << "FATAL ERROR: query " << benchmarkName << ":" << currentExperimentValue << " should have count " << *expectedCount << " but was " << counter << std::endl;
    std::cerr << "" << __FILE__ << ":" << __LINE__ << std::endl;
    exit(-1);
  }
}

std::vector<std::pair<int64_t, uint64_t> > DynamicCorpusFixture::getExperimentValues() const
{
  std::vector<std::pair<int64_t, uint64_t> > result;

  for (auto it : json)
  {
    result.push_back({it.first, 0});
  }

  return result;
}

void DynamicCorpusFixture::tearDown()
{
}

DynamicBenchmark::DynamicBenchmark(std::string queriesDir,
  std::string corpusPath, std::string benchmarkName, bool multipleExperimentsParam)
  : corpusPath(corpusPath), benchmarkName(benchmarkName), multipleExperiments(multipleExperimentsParam)
{
  // find all file ending with ".json" in the folder
  boost::filesystem::directory_iterator fileEndIt;

  boost::filesystem::directory_iterator itFiles(queriesDir);
  while (itFiles != fileEndIt)
  {
    const auto filePath = itFiles->path();
    if (filePath.extension().string() == ".json")
    {
      if(multipleExperiments)
      {
        // check if the file name is a valid number
        std::string name = filePath.filename().stem().string();
        try
        {
          std::stol(name);
        }
        catch(std::invalid_argument invalid)
        {
          // not a number, don't assume we have multiple experiments
          multipleExperiments = false;
        }
      }

      foundJSONFiles.push_back(filePath);
    }
    itFiles++;
  }

  if(foundJSONFiles.empty())
  {
    multipleExperiments = false;
  }

  QueryConfig baselineConfig;
  registerFixtureInternal(true, "Baseline", baselineConfig);
}

void DynamicBenchmark::registerFixture(std::string fixtureName, const QueryConfig config)
{
  registerFixtureInternal(false, fixtureName, config);
}

void DynamicBenchmark::registerFixtureInternal(
  bool baseline,
  std::string fixtureName, const QueryConfig config)
{
  if (multipleExperiments)
  {
    std::map<int64_t, const boost::filesystem::path> paths;
    for (const auto& filePath : foundJSONFiles)
    {
      // try to get a numerical ID from the file name
      std::string name = filePath.filename().stem().string();
      auto id = std::stol(name);
      paths.insert({id, filePath});
    }
    addBenchmark(baseline, benchmarkName, paths, fixtureName, config);
  }
  else
  {
    for (const auto& filePath : foundJSONFiles)
    {
      std::map<int64_t, const boost::filesystem::path> paths;
      paths.insert({0, filePath});
      auto subBenchmarkName = benchmarkName + "_" + filePath.stem().string();
      addBenchmark(baseline, subBenchmarkName, paths, fixtureName, config);
    }
  }
}

void DynamicBenchmark::addBenchmark(bool baseline,
  std::string benchmarkName,
  std::map<int64_t, const boost::filesystem::path>& paths,
  std::string fixtureName,
  QueryConfig config)
{
  unsigned int numberOfSamples = 5;

  HL_INFO(benchLogger, (boost::format("adding benchmark %1%") % benchmarkName).str());

  std::map<int64_t, std::string> allQueries;
  std::map<int64_t, unsigned int> expectedCount;
  std::map<int64_t, uint64_t> fixedValues;

  for (auto p : paths)
  {
    auto countPath = p.second.parent_path() /= (p.second.stem().string() + ".count");

    boost::filesystem::ifstream stream;

    stream.open(countPath);
    if (stream.is_open())
    {
      unsigned int tmp;
      stream >> tmp;
      stream.close();
      expectedCount.insert({p.first, tmp});
    }

    stream.open(p.second);
    std::string queryJSON(
      (std::istreambuf_iterator<char>(stream)),
      (std::istreambuf_iterator<char>()));
    stream.close();

    allQueries.insert({p.first, queryJSON});

    if(baseline)
    {
      double timeVal = 0.0;
      auto timePath = p.second.parent_path() /= (p.second.stem().string() + ".time");
      stream.open(timePath);
      if (stream.is_open())
      {
        stream >> timeVal;
        stream.close();
      }
      if(timeVal > 0.0)
      {
        // since celero uses microseconds an ANNIS milliseconds the value needs to be converted
        fixedValues.insert({p.first, std::llround(timeVal*1000.0)});
      }
      else
      {
        // we would divide by zero later, thus use 1 micro second as smallest value
        fixedValues.insert({p.first, 1});
      }

    }
  }
  std::shared_ptr<::celero::TestFixture> fixture(
    new DynamicCorpusFixture(corpusPath, config, allQueries,
    benchmarkName + " (" + fixtureName + ")",
    expectedCount));

  if (baseline)
  {
    if(fixedValues.size() > 0)
    {
      std::shared_ptr<::celero::TestFixture> fixedFixture(new FixedValueFixture(fixedValues));
      celero::RegisterBaseline(benchmarkName.c_str(), fixtureName.c_str(), numberOfSamples, 1, 1,
        std::make_shared<DynamicCorpusFixtureFactory>(fixedFixture));
    }
    else
    {
     celero::RegisterBaseline(benchmarkName.c_str(), fixtureName.c_str(), numberOfSamples, 1, 1,
        std::make_shared<DynamicCorpusFixtureFactory>(fixture));
    }
  }
  else
  {
    celero::RegisterTest(benchmarkName.c_str(), fixtureName.c_str(), numberOfSamples, 1, 1,
      std::make_shared<DynamicCorpusFixtureFactory>(fixture));
  }
}

<|endoftext|>


<commit_before>//
// PROJECT CHRONO - http://projectchrono.org
//
// Copyright (c) 2010, 2012 Alessandro Tasora
// Copyright (c) 2013 Project Chrono
// All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file at the top level of the distribution
// and at http://projectchrono.org/license-chrono.txt.
//

#include "chrono_fea/ChLinkPointFrame.h"
#include "physics/ChSystem.h"
#include "physics/ChIndexedNodes.h"

using namespace chrono;
using namespace fea;

// Register into the object factory, to enable run-time
// dynamic creation and persistence
ChClassRegister<ChLinkPointFrame> a_registration_ChLinkPointFrame;

//////////////////////////////////////
//////////////////////////////////////

ChLinkPointFrame::ChLinkPointFrame() {
	this->react= VNULL;
	this->cache_li_speed = VNULL;
	this->cache_li_pos = VNULL;
	this->attach_reference = CSYSNORM;

	SetIdentifier(GetUniqueIntID()); // mark with unique ID
}

ChLinkPointFrame::~ChLinkPointFrame() {
}

void ChLinkPointFrame::Copy(ChLinkPointFrame* source) {
		// copy the parent class data...
	ChPhysicsItem::Copy(source);

		// copy class data
	attach_reference = source->attach_reference;
	react = source->react;
	cache_li_speed = source->cache_li_speed;
	cache_li_pos = source->cache_li_pos;
}

ChCoordsys<> ChLinkPointFrame::GetLinkAbsoluteCoords() {
    if (this->body) {
		ChCoordsys<> linkcsys = attach_reference >> (*this->body);
		return linkcsys;
	}
	return CSYSNORM;
}

int ChLinkPointFrame::Initialize(ChSharedPtr<ChIndexedNodes> mnodes, ///< nodes container
						   unsigned int mnode_index, ///< index of the node to join
						   ChSharedPtr<ChBodyFrame>  mbody,   ///< body to join
                                 ChVector<>* mattach) {
	assert(!mnodes.IsNull());

	ChSharedPtr<ChNodeFEAxyz> anode(mnodes->GetNode(mnode_index).DynamicCastTo<ChNodeFEAxyz>() ); // downcasting

	if (anode.IsNull())
        return false;  // downcasting wasn't successfull (in a ChIndexedNodes, different types of nodes could be
                       // present..)

	return this->Initialize(anode, mbody, mattach);
}

int ChLinkPointFrame::Initialize(ChSharedPtr<ChNodeFEAxyz> anode,  ///< node to join
						   ChSharedPtr<ChBodyFrame>  mbody,		///< body to join
                                 ChVector<>* mattach) {
	assert(!anode.IsNull() && !mbody.IsNull());

	this->body = mbody;
	this->mnode = anode;

	this->constraint1.SetVariables(&(this->mnode->Variables()), &(this->body->Variables()));
	this->constraint2.SetVariables(&(this->mnode->Variables()), &(this->body->Variables()));
	this->constraint3.SetVariables(&(this->mnode->Variables()), &(this->body->Variables()));

	//this->SetSystem(this->body->GetSystem());

    if (mattach) {
		this->attach_reference.pos = body->TransformPointParentToLocal(*mattach);
    } else {
		// downcasting
        if (mnode.IsNull())
            return false;

		ChVector<> temp= mnode->GetPos();
		this->attach_reference.pos = body->TransformPointParentToLocal(temp);
	}

	return true;
}

void ChLinkPointFrame::Update(double mytime, bool update_assets) {
  // Inherit time changes of parent class
  ChPhysicsItem::Update(mytime, update_assets);

  // update class data
  // ...
}

ChMatrix<> ChLinkPointFrame::GetC() {
    ChMatrix33<> Arw(attach_reference.rot >> body->GetRot());
    ChVector<> res = Arw.MatrT_x_Vect(mnode->GetPos() - body->TransformPointLocalToParent(attach_reference.pos));
    ChMatrixNM<double, 3, 1> C;
    C(0, 0) = res.y;
    C(1, 0) = res.z;
    C(2, 0) = res.z;
    return C;
}

//// STATE BOOKKEEPING FUNCTIONS

void ChLinkPointFrame::IntStateGatherReactions(const unsigned int off_L, ChVectorDynamic<>& L) {
	L(off_L+0) = this->react.x;
	L(off_L+1) = this->react.y;
	L(off_L+2) = this->react.z;
}

void ChLinkPointFrame::IntStateScatterReactions(const unsigned int off_L, const ChVectorDynamic<>& L) {
	this->react.x = L(off_L+0);
	this->react.y = L(off_L+1);
	this->react.z = L(off_L+2);
}

void ChLinkPointFrame::IntLoadResidual_CqL(const unsigned int off_L,    ///< offset in L multipliers
					ChVectorDynamic<>& R,		 ///< result: the R residual, R += c*Cq'*L
					const ChVectorDynamic<>& L,  ///< the L vector
					const double c				 ///< a scaling factor
                                           ) {
	if (!IsActive())
    return;

	constraint1.MultiplyTandAdd(R, L(off_L+0) *c);
	constraint2.MultiplyTandAdd(R, L(off_L+1) *c);
	constraint3.MultiplyTandAdd(R, L(off_L+2) *c);
}

void ChLinkPointFrame::IntLoadConstraint_C(const unsigned int off_L,  ///< offset in Qc residual
					ChVectorDynamic<>& Qc,		 ///< result: the Qc residual, Qc += c*C
					const double c,				 ///< a scaling factor
					bool do_clamp,				 ///< apply clamping to c*C?
					double recovery_clamp		 ///< value for min/max clamping of c*C
                                           ) {
	if (!IsActive())
    return;

	ChMatrix33<> Arw (attach_reference.rot >> body->GetRot());

	ChVector<> res = Arw.MatrT_x_Vect(mnode->GetPos() - this->body->TransformPointLocalToParent(this->attach_reference.pos) );
	ChVector<> cres = res * c;

	if (do_clamp) {
		cres.x = ChMin(ChMax(cres.x, -recovery_clamp), recovery_clamp);
		cres.y = ChMin(ChMax(cres.y, -recovery_clamp), recovery_clamp);
		cres.z = ChMin(ChMax(cres.z, -recovery_clamp), recovery_clamp);
	}
	Qc(off_L+0) += cres.x;
	Qc(off_L+1) += cres.y;
	Qc(off_L+2) += cres.z;
}

void ChLinkPointFrame::IntToLCP(const unsigned int off_v,  ///< offset in v, R
					const ChStateDelta& v,
					const ChVectorDynamic<>& R,
					const unsigned int off_L,			///< offset in L, Qc
					const ChVectorDynamic<>& L,
                                const ChVectorDynamic<>& Qc) {
	if (!IsActive())
    return;

	constraint1.Set_l_i(L(off_L+0));
	constraint2.Set_l_i(L(off_L+1));
	constraint3.Set_l_i(L(off_L+2));

	constraint1.Set_b_i(Qc(off_L+0));
	constraint2.Set_b_i(Qc(off_L+1));
	constraint3.Set_b_i(Qc(off_L+2));
}

void ChLinkPointFrame::IntFromLCP(const unsigned int off_v,  ///< offset in v
					ChStateDelta& v,
					const unsigned int off_L,			///< offset in L
                                  ChVectorDynamic<>& L) {
	if (!IsActive())
    return;

	L(off_L+0)=constraint1.Get_l_i();
	L(off_L+1)=constraint2.Get_l_i();
	L(off_L+2)=constraint3.Get_l_i();
}

////////// LCP INTERFACES ////

void ChLinkPointFrame::InjectConstraints(ChLcpSystemDescriptor& mdescriptor) {
	//if (!this->IsActive())
	//	return;

	mdescriptor.InsertConstraint(&constraint1);
	mdescriptor.InsertConstraint(&constraint2);
	mdescriptor.InsertConstraint(&constraint3);
}

void ChLinkPointFrame::ConstraintsBiReset() {
	constraint1.Set_b_i(0.);
	constraint2.Set_b_i(0.);
	constraint3.Set_b_i(0.);
}

void ChLinkPointFrame::ConstraintsBiLoad_C(double factor, double recovery_clamp, bool do_clamp) {
	//if (!this->IsActive())
	//	return;

	if (mnode.IsNull())
		return;

	ChMatrix33<> Arw (attach_reference.rot >> body->GetRot());

	ChVector<> res = Arw.MatrT_x_Vect(mnode->GetPos() - this->body->TransformPointLocalToParent(this->attach_reference.pos) );

	this->constraint1.Set_b_i(constraint1.Get_b_i() +  factor * res.x);
	this->constraint2.Set_b_i(constraint2.Get_b_i() +  factor * res.y);
	this->constraint3.Set_b_i(constraint3.Get_b_i() +  factor * res.z);
}

void ChLinkPointFrame::ConstraintsBiLoad_Ct(double factor) {
	//if (!this->IsActive())
	//	return;

	// nothing
}

void ChLinkPointFrame::ConstraintsLoadJacobians() {
		// compute jacobians
	ChMatrix33<> Aro (attach_reference.rot);
	ChMatrix33<> Aow (body->GetRot());
	ChMatrix33<> Arw = Aow * Aro;

	ChMatrix33<> Jxn;
	Jxn.CopyFromMatrixT(Arw);

	ChMatrix33<> Jxb;
	Jxb.CopyFromMatrixT(Arw);
	Jxb.MatrNeg();

	ChMatrix33<> atilde;
	atilde.Set_X_matrix(Aow.MatrT_x_Vect(mnode->GetPos()- body->GetPos()));
	ChMatrix33<> Jrb;
	Jrb.MatrTMultiply(Aro, atilde);

	this->constraint1.Get_Cq_a()->PasteClippedMatrix(&Jxn, 0,0, 1,3, 0,0);
	this->constraint2.Get_Cq_a()->PasteClippedMatrix(&Jxn, 1,0, 1,3, 0,0);
	this->constraint3.Get_Cq_a()->PasteClippedMatrix(&Jxn, 2,0, 1,3, 0,0);

	this->constraint1.Get_Cq_b()->PasteClippedMatrix(&Jxb, 0,0, 1,3, 0,0);
	this->constraint2.Get_Cq_b()->PasteClippedMatrix(&Jxb, 1,0, 1,3, 0,0);
	this->constraint3.Get_Cq_b()->PasteClippedMatrix(&Jxb, 2,0, 1,3, 0,0);
	this->constraint1.Get_Cq_b()->PasteClippedMatrix(&Jrb, 0,0, 1,3, 0,3);
	this->constraint2.Get_Cq_b()->PasteClippedMatrix(&Jrb, 1,0, 1,3, 0,3);
	this->constraint3.Get_Cq_b()->PasteClippedMatrix(&Jrb, 2,0, 1,3, 0,3);
}

void ChLinkPointFrame::ConstraintsFetch_react(double factor) {
	// From constraints to react vector:
	this->react.x = constraint1.Get_l_i() * factor;
	this->react.y = constraint2.Get_l_i() * factor;
	this->react.z = constraint3.Get_l_i() * factor;
}

// Following functions are for exploiting the contact persistence

void ChLinkPointFrame::ConstraintsLiLoadSuggestedSpeedSolution() {
	constraint1.Set_l_i(this->cache_li_speed.x);
	constraint2.Set_l_i(this->cache_li_speed.y);
	constraint3.Set_l_i(this->cache_li_speed.z);
}

void ChLinkPointFrame::ConstraintsLiLoadSuggestedPositionSolution() {
	constraint1.Set_l_i(this->cache_li_pos.x);
	constraint2.Set_l_i(this->cache_li_pos.y);
	constraint3.Set_l_i(this->cache_li_pos.z);
}

void ChLinkPointFrame::ConstraintsLiFetchSuggestedSpeedSolution() {
	this->cache_li_speed.x = (float)constraint1.Get_l_i();
	this->cache_li_speed.y = (float)constraint2.Get_l_i();
	this->cache_li_speed.z = (float)constraint3.Get_l_i();
}

void ChLinkPointFrame::ConstraintsLiFetchSuggestedPositionSolution() {
	this->cache_li_pos.x =  (float)constraint1.Get_l_i();
	this->cache_li_pos.y =  (float)constraint2.Get_l_i();
	this->cache_li_pos.z =  (float)constraint3.Get_l_i();
}

//////// FILE I/O

void ChLinkPointFrame::StreamOUT(ChStreamOutBinary& mstream) {
    /*
			// class version number
	mstream.VersionWrite(1);

		// serialize parent class too
	ChPhysicsItem::StreamOUT(mstream);

		// stream out all member data
	//mstream << this->node_index;
	mstream < this->attach_reference;
	mstream < this->react;
    */
}

void ChLinkPointFrame::StreamIN(ChStreamInBinary& mstream) {
    /*
		// class version number
	int version = mstream.VersionRead();

		// deserialize parent class too
	ChPhysicsItem::StreamIN(mstream);

		// deserialize class
	//mstream >> this->node_index;
	mstream >> this->attach_reference;
	mstream >> this->react;
    */
}

/////////////////////
<commit_msg>Fix bug in reporting constraint violations for ChLinkPointFrame<commit_after>//
// PROJECT CHRONO - http://projectchrono.org
//
// Copyright (c) 2010, 2012 Alessandro Tasora
// Copyright (c) 2013 Project Chrono
// All rights reserved.
//
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file at the top level of the distribution
// and at http://projectchrono.org/license-chrono.txt.
//

#include "chrono_fea/ChLinkPointFrame.h"
#include "physics/ChSystem.h"
#include "physics/ChIndexedNodes.h"

using namespace chrono;
using namespace fea;

// Register into the object factory, to enable run-time
// dynamic creation and persistence
ChClassRegister<ChLinkPointFrame> a_registration_ChLinkPointFrame;

//////////////////////////////////////
//////////////////////////////////////

ChLinkPointFrame::ChLinkPointFrame() {
	this->react= VNULL;
	this->cache_li_speed = VNULL;
	this->cache_li_pos = VNULL;
	this->attach_reference = CSYSNORM;

	SetIdentifier(GetUniqueIntID()); // mark with unique ID
}

ChLinkPointFrame::~ChLinkPointFrame() {
}

void ChLinkPointFrame::Copy(ChLinkPointFrame* source) {
		// copy the parent class data...
	ChPhysicsItem::Copy(source);

		// copy class data
	attach_reference = source->attach_reference;
	react = source->react;
	cache_li_speed = source->cache_li_speed;
	cache_li_pos = source->cache_li_pos;
}

ChCoordsys<> ChLinkPointFrame::GetLinkAbsoluteCoords() {
    if (this->body) {
		ChCoordsys<> linkcsys = attach_reference >> (*this->body);
		return linkcsys;
	}
	return CSYSNORM;
}

int ChLinkPointFrame::Initialize(ChSharedPtr<ChIndexedNodes> mnodes, ///< nodes container
						   unsigned int mnode_index, ///< index of the node to join
						   ChSharedPtr<ChBodyFrame>  mbody,   ///< body to join
                                 ChVector<>* mattach) {
	assert(!mnodes.IsNull());

	ChSharedPtr<ChNodeFEAxyz> anode(mnodes->GetNode(mnode_index).DynamicCastTo<ChNodeFEAxyz>() ); // downcasting

	if (anode.IsNull())
        return false;  // downcasting wasn't successfull (in a ChIndexedNodes, different types of nodes could be
                       // present..)

	return this->Initialize(anode, mbody, mattach);
}

int ChLinkPointFrame::Initialize(ChSharedPtr<ChNodeFEAxyz> anode,  ///< node to join
						   ChSharedPtr<ChBodyFrame>  mbody,		///< body to join
                                 ChVector<>* mattach) {
	assert(!anode.IsNull() && !mbody.IsNull());

	this->body = mbody;
	this->mnode = anode;

	this->constraint1.SetVariables(&(this->mnode->Variables()), &(this->body->Variables()));
	this->constraint2.SetVariables(&(this->mnode->Variables()), &(this->body->Variables()));
	this->constraint3.SetVariables(&(this->mnode->Variables()), &(this->body->Variables()));

	//this->SetSystem(this->body->GetSystem());

    if (mattach) {
		this->attach_reference.pos = body->TransformPointParentToLocal(*mattach);
    } else {
		// downcasting
        if (mnode.IsNull())
            return false;

		ChVector<> temp= mnode->GetPos();
		this->attach_reference.pos = body->TransformPointParentToLocal(temp);
	}

	return true;
}

void ChLinkPointFrame::Update(double mytime, bool update_assets) {
  // Inherit time changes of parent class
  ChPhysicsItem::Update(mytime, update_assets);

  // update class data
  // ...
}

ChMatrix<> ChLinkPointFrame::GetC() {
    ChMatrix33<> Arw(attach_reference.rot >> body->GetRot());
    ChVector<> res = Arw.MatrT_x_Vect(mnode->GetPos() - body->TransformPointLocalToParent(attach_reference.pos));
    ChMatrixNM<double, 3, 1> C;
    C(0, 0) = res.x;
    C(1, 0) = res.y;
    C(2, 0) = res.z;
    return C;
}

//// STATE BOOKKEEPING FUNCTIONS

void ChLinkPointFrame::IntStateGatherReactions(const unsigned int off_L, ChVectorDynamic<>& L) {
	L(off_L+0) = this->react.x;
	L(off_L+1) = this->react.y;
	L(off_L+2) = this->react.z;
}

void ChLinkPointFrame::IntStateScatterReactions(const unsigned int off_L, const ChVectorDynamic<>& L) {
	this->react.x = L(off_L+0);
	this->react.y = L(off_L+1);
	this->react.z = L(off_L+2);
}

void ChLinkPointFrame::IntLoadResidual_CqL(const unsigned int off_L,    ///< offset in L multipliers
					ChVectorDynamic<>& R,		 ///< result: the R residual, R += c*Cq'*L
					const ChVectorDynamic<>& L,  ///< the L vector
					const double c				 ///< a scaling factor
                                           ) {
	if (!IsActive())
    return;

	constraint1.MultiplyTandAdd(R, L(off_L+0) *c);
	constraint2.MultiplyTandAdd(R, L(off_L+1) *c);
	constraint3.MultiplyTandAdd(R, L(off_L+2) *c);
}

void ChLinkPointFrame::IntLoadConstraint_C(const unsigned int off_L,  ///< offset in Qc residual
					ChVectorDynamic<>& Qc,		 ///< result: the Qc residual, Qc += c*C
					const double c,				 ///< a scaling factor
					bool do_clamp,				 ///< apply clamping to c*C?
					double recovery_clamp		 ///< value for min/max clamping of c*C
                                           ) {
	if (!IsActive())
    return;

	ChMatrix33<> Arw (attach_reference.rot >> body->GetRot());

	ChVector<> res = Arw.MatrT_x_Vect(mnode->GetPos() - this->body->TransformPointLocalToParent(this->attach_reference.pos) );
	ChVector<> cres = res * c;

	if (do_clamp) {
		cres.x = ChMin(ChMax(cres.x, -recovery_clamp), recovery_clamp);
		cres.y = ChMin(ChMax(cres.y, -recovery_clamp), recovery_clamp);
		cres.z = ChMin(ChMax(cres.z, -recovery_clamp), recovery_clamp);
	}
	Qc(off_L+0) += cres.x;
	Qc(off_L+1) += cres.y;
	Qc(off_L+2) += cres.z;
}

void ChLinkPointFrame::IntToLCP(const unsigned int off_v,  ///< offset in v, R
					const ChStateDelta& v,
					const ChVectorDynamic<>& R,
					const unsigned int off_L,			///< offset in L, Qc
					const ChVectorDynamic<>& L,
                                const ChVectorDynamic<>& Qc) {
	if (!IsActive())
    return;

	constraint1.Set_l_i(L(off_L+0));
	constraint2.Set_l_i(L(off_L+1));
	constraint3.Set_l_i(L(off_L+2));

	constraint1.Set_b_i(Qc(off_L+0));
	constraint2.Set_b_i(Qc(off_L+1));
	constraint3.Set_b_i(Qc(off_L+2));
}

void ChLinkPointFrame::IntFromLCP(const unsigned int off_v,  ///< offset in v
					ChStateDelta& v,
					const unsigned int off_L,			///< offset in L
                                  ChVectorDynamic<>& L) {
	if (!IsActive())
    return;

	L(off_L+0)=constraint1.Get_l_i();
	L(off_L+1)=constraint2.Get_l_i();
	L(off_L+2)=constraint3.Get_l_i();
}

////////// LCP INTERFACES ////

void ChLinkPointFrame::InjectConstraints(ChLcpSystemDescriptor& mdescriptor) {
	//if (!this->IsActive())
	//	return;

	mdescriptor.InsertConstraint(&constraint1);
	mdescriptor.InsertConstraint(&constraint2);
	mdescriptor.InsertConstraint(&constraint3);
}

void ChLinkPointFrame::ConstraintsBiReset() {
	constraint1.Set_b_i(0.);
	constraint2.Set_b_i(0.);
	constraint3.Set_b_i(0.);
}

void ChLinkPointFrame::ConstraintsBiLoad_C(double factor, double recovery_clamp, bool do_clamp) {
	//if (!this->IsActive())
	//	return;

	if (mnode.IsNull())
		return;

	ChMatrix33<> Arw (attach_reference.rot >> body->GetRot());

	ChVector<> res = Arw.MatrT_x_Vect(mnode->GetPos() - this->body->TransformPointLocalToParent(this->attach_reference.pos) );

	this->constraint1.Set_b_i(constraint1.Get_b_i() +  factor * res.x);
	this->constraint2.Set_b_i(constraint2.Get_b_i() +  factor * res.y);
	this->constraint3.Set_b_i(constraint3.Get_b_i() +  factor * res.z);
}

void ChLinkPointFrame::ConstraintsBiLoad_Ct(double factor) {
	//if (!this->IsActive())
	//	return;

	// nothing
}

void ChLinkPointFrame::ConstraintsLoadJacobians() {
		// compute jacobians
	ChMatrix33<> Aro (attach_reference.rot);
	ChMatrix33<> Aow (body->GetRot());
	ChMatrix33<> Arw = Aow * Aro;

	ChMatrix33<> Jxn;
	Jxn.CopyFromMatrixT(Arw);

	ChMatrix33<> Jxb;
	Jxb.CopyFromMatrixT(Arw);
	Jxb.MatrNeg();

	ChMatrix33<> atilde;
	atilde.Set_X_matrix(Aow.MatrT_x_Vect(mnode->GetPos()- body->GetPos()));
	ChMatrix33<> Jrb;
	Jrb.MatrTMultiply(Aro, atilde);

	this->constraint1.Get_Cq_a()->PasteClippedMatrix(&Jxn, 0,0, 1,3, 0,0);
	this->constraint2.Get_Cq_a()->PasteClippedMatrix(&Jxn, 1,0, 1,3, 0,0);
	this->constraint3.Get_Cq_a()->PasteClippedMatrix(&Jxn, 2,0, 1,3, 0,0);

	this->constraint1.Get_Cq_b()->PasteClippedMatrix(&Jxb, 0,0, 1,3, 0,0);
	this->constraint2.Get_Cq_b()->PasteClippedMatrix(&Jxb, 1,0, 1,3, 0,0);
	this->constraint3.Get_Cq_b()->PasteClippedMatrix(&Jxb, 2,0, 1,3, 0,0);
	this->constraint1.Get_Cq_b()->PasteClippedMatrix(&Jrb, 0,0, 1,3, 0,3);
	this->constraint2.Get_Cq_b()->PasteClippedMatrix(&Jrb, 1,0, 1,3, 0,3);
	this->constraint3.Get_Cq_b()->PasteClippedMatrix(&Jrb, 2,0, 1,3, 0,3);
}

void ChLinkPointFrame::ConstraintsFetch_react(double factor) {
	// From constraints to react vector:
	this->react.x = constraint1.Get_l_i() * factor;
	this->react.y = constraint2.Get_l_i() * factor;
	this->react.z = constraint3.Get_l_i() * factor;
}

// Following functions are for exploiting the contact persistence

void ChLinkPointFrame::ConstraintsLiLoadSuggestedSpeedSolution() {
	constraint1.Set_l_i(this->cache_li_speed.x);
	constraint2.Set_l_i(this->cache_li_speed.y);
	constraint3.Set_l_i(this->cache_li_speed.z);
}

void ChLinkPointFrame::ConstraintsLiLoadSuggestedPositionSolution() {
	constraint1.Set_l_i(this->cache_li_pos.x);
	constraint2.Set_l_i(this->cache_li_pos.y);
	constraint3.Set_l_i(this->cache_li_pos.z);
}

void ChLinkPointFrame::ConstraintsLiFetchSuggestedSpeedSolution() {
	this->cache_li_speed.x = (float)constraint1.Get_l_i();
	this->cache_li_speed.y = (float)constraint2.Get_l_i();
	this->cache_li_speed.z = (float)constraint3.Get_l_i();
}

void ChLinkPointFrame::ConstraintsLiFetchSuggestedPositionSolution() {
	this->cache_li_pos.x =  (float)constraint1.Get_l_i();
	this->cache_li_pos.y =  (float)constraint2.Get_l_i();
	this->cache_li_pos.z =  (float)constraint3.Get_l_i();
}

//////// FILE I/O

void ChLinkPointFrame::StreamOUT(ChStreamOutBinary& mstream) {
    /*
			// class version number
	mstream.VersionWrite(1);

		// serialize parent class too
	ChPhysicsItem::StreamOUT(mstream);

		// stream out all member data
	//mstream << this->node_index;
	mstream < this->attach_reference;
	mstream < this->react;
    */
}

void ChLinkPointFrame::StreamIN(ChStreamInBinary& mstream) {
    /*
		// class version number
	int version = mstream.VersionRead();

		// deserialize parent class too
	ChPhysicsItem::StreamIN(mstream);

		// deserialize class
	//mstream >> this->node_index;
	mstream >> this->attach_reference;
	mstream >> this->react;
    */
}

/////////////////////
<|endoftext|>


<commit_before>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome_frame/test/chrome_frame_test_utils.h"

#include <atlbase.h>
#include <atlwin.h>
#include <iepmapi.h>

#include "base/registry.h"   // to find IE and firefox
#include "base/scoped_handle.h"
#include "base/scoped_comptr_win.h"
#include "base/string_util.h"
#include "base/win_util.h"
#include "chrome/common/chrome_switches.h"

namespace chrome_frame_test {

const wchar_t kIEImageName[] = L"iexplore.exe";
const wchar_t kIEBrokerImageName[] = L"ieuser.exe";
const wchar_t kFirefoxImageName[] = L"firefox.exe";
const wchar_t kOperaImageName[] = L"opera.exe";
const wchar_t kSafariImageName[] = L"safari.exe";
const wchar_t kChromeImageName[] = L"chrome.exe";

bool IsTopLevelWindow(HWND window) {
  long style = GetWindowLong(window, GWL_STYLE);  // NOLINT
  if (!(style & WS_CHILD))
    return true;

  HWND parent = GetParent(window);
  if (!parent)
    return true;

  if (parent == GetDesktopWindow())
    return true;

  return false;
}

// Callback function for EnumThreadWindows.
BOOL CALLBACK CloseWindowsThreadCallback(HWND hwnd, LPARAM param) {
  int& count = *reinterpret_cast<int*>(param);
  if (IsWindowVisible(hwnd)) {
    if (IsWindowEnabled(hwnd)) {
      DWORD results = 0;
      if (!::SendMessageTimeout(hwnd, WM_SYSCOMMAND, SC_CLOSE, 0, SMTO_BLOCK,
                                10000, &results)) {
        DLOG(WARNING) << "Window hung: " << StringPrintf(L"%08X", hwnd);
      }
      count++;
    } else {
      DLOG(WARNING) << "Skipping disabled window: "
                  << StringPrintf(L"%08X", hwnd);
    }
  }
  return TRUE;  // continue enumeration
}

// Attempts to close all non-child, visible windows on the given thread.
// The return value is the number of visible windows a close request was
// sent to.
int CloseVisibleTopLevelWindowsOnThread(DWORD thread_id) {
  int window_close_attempts = 0;
  EnumThreadWindows(thread_id, CloseWindowsThreadCallback,
                    reinterpret_cast<LPARAM>(&window_close_attempts));
  return window_close_attempts;
}

// Enumerates the threads of a process and attempts to close visible non-child
// windows on all threads of the process.
// The return value is the number of visible windows a close request was
// sent to.
int CloseVisibleWindowsOnAllThreads(HANDLE process) {
  DWORD process_id = ::GetProcessId(process);
  if (process_id == 0) {
    NOTREACHED();
    return 0;
  }

  ScopedHandle snapshot(CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0));
  if (!snapshot.IsValid()) {
    NOTREACHED();
    return 0;
  }

  int window_close_attempts = 0;
  THREADENTRY32 te = { sizeof(THREADENTRY32) };
  if (Thread32First(snapshot, &te)) {
    do {
      if (RTL_CONTAINS_FIELD(&te, te.dwSize, th32OwnerProcessID) &&
          te.th32OwnerProcessID == process_id) {
        window_close_attempts +=
            CloseVisibleTopLevelWindowsOnThread(te.th32ThreadID);
      }
      te.dwSize = sizeof(te);
    } while (Thread32Next(snapshot, &te));
  }

  return window_close_attempts;
}

class ForegroundHelperWindow : public CWindowImpl<ForegroundHelperWindow> {
 public:
BEGIN_MSG_MAP(ForegroundHelperWindow)
  MESSAGE_HANDLER(WM_HOTKEY, OnHotKey)
END_MSG_MAP()

  HRESULT SetForeground(HWND window) {
    DCHECK(::IsWindow(window));
    if (NULL == Create(NULL, NULL, NULL, WS_POPUP))
      return AtlHresultFromLastError();

    static const int hotkey_id = 0x0000baba;

    SetWindowLongPtr(GWLP_USERDATA, reinterpret_cast<ULONG_PTR>(window));
    RegisterHotKey(m_hWnd, hotkey_id, 0, VK_F22);

    MSG msg = {0};
    PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);

    INPUT hotkey = {0};
    hotkey.type = INPUT_KEYBOARD;
    hotkey.ki.wVk =  VK_F22;
    SendInput(1, &hotkey, sizeof(hotkey));

    while (GetMessage(&msg, NULL, 0, 0)) {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
      if (WM_HOTKEY == msg.message)
        break;
    }

    UnregisterHotKey(m_hWnd, hotkey_id);
    DestroyWindow();

    return S_OK;
  }

  LRESULT OnHotKey(UINT msg, WPARAM wp, LPARAM lp, BOOL& handled) {  // NOLINT
    HWND window = reinterpret_cast<HWND>(GetWindowLongPtr(GWLP_USERDATA));
    SetForegroundWindow(window);
    return 1;
  }
};

bool ForceSetForegroundWindow(HWND window) {
  if (GetForegroundWindow() == window)
    return true;
  ForegroundHelperWindow foreground_helper_window;
  HRESULT hr = foreground_helper_window.SetForeground(window);
  return SUCCEEDED(hr);
}

struct PidAndWindow {
  base::ProcessId pid;
  HWND hwnd;
};

BOOL CALLBACK FindWindowInProcessCallback(HWND hwnd, LPARAM param) {
  PidAndWindow* paw = reinterpret_cast<PidAndWindow*>(param);
  base::ProcessId pid;
  GetWindowThreadProcessId(hwnd, &pid);
  if (pid == paw->pid && IsWindowVisible(hwnd)) {
    paw->hwnd = hwnd;
    return FALSE;
  }

  return TRUE;
}

bool EnsureProcessInForeground(base::ProcessId process_id) {
  HWND hwnd = GetForegroundWindow();
  base::ProcessId current_foreground_pid = 0;
  DWORD active_thread_id = GetWindowThreadProcessId(hwnd,
      &current_foreground_pid);
  if (current_foreground_pid == process_id)
    return true;

  PidAndWindow paw = { process_id };
  EnumWindows(FindWindowInProcessCallback, reinterpret_cast<LPARAM>(&paw));
  if (!IsWindow(paw.hwnd)) {
    DLOG(ERROR) << "failed to find process window";
    return false;
  }

  bool ret = ForceSetForegroundWindow(paw.hwnd);
  DLOG_IF(ERROR, !ret) << "ForceSetForegroundWindow: " << ret;

  return ret;
}

// Iterates through all the characters in the string and simulates
// keyboard input.  The input goes to the currently active application.
bool SendString(const wchar_t* string) {
  DCHECK(string != NULL);

  INPUT input[2] = {0};
  input[0].type = INPUT_KEYBOARD;
  input[0].ki.dwFlags = KEYEVENTF_UNICODE;  // to avoid shift, etc.
  input[1] = input[0];
  input[1].ki.dwFlags |= KEYEVENTF_KEYUP;

  for (const wchar_t* p = string; *p; p++) {
    input[0].ki.wScan = input[1].ki.wScan = *p;
    SendInput(2, input, sizeof(INPUT));
  }

  return true;
}

void SendVirtualKey(int16 key) {
  INPUT input = { INPUT_KEYBOARD };
  input.ki.wVk = key;
  SendInput(1, &input, sizeof(input));
  input.ki.dwFlags = KEYEVENTF_KEYUP;
  SendInput(1, &input, sizeof(input));
}

void SendChar(char c) {
  SendVirtualKey(VkKeyScanA(c));
}

void SendString(const char* s) {
  while (*s) {
    SendChar(*s);
    s++;
  }
}

// Sends a keystroke to the currently active application with optional
// modifiers set.
bool SendMnemonic(WORD mnemonic_char, bool shift_pressed, bool control_pressed,
                  bool alt_pressed) {
  INPUT special_keys[3] = {0};
  for (int index = 0; index < arraysize(special_keys); ++index) {
    special_keys[index].type = INPUT_KEYBOARD;
    special_keys[index].ki.dwFlags = 0;
  }

  int num_special_keys = 0;
  if (shift_pressed)  {
    special_keys[num_special_keys].ki.wVk = VK_SHIFT;
    num_special_keys++;
  }

  if (control_pressed)  {
    special_keys[num_special_keys].ki.wVk = VK_CONTROL;
    num_special_keys++;
  }

  if (alt_pressed)  {
    special_keys[num_special_keys].ki.wVk = VK_MENU;
    num_special_keys++;
  }

  // Depress the modifiers.
  SendInput(num_special_keys, special_keys, sizeof(INPUT));

  Sleep(100);

  INPUT mnemonic = {0};
  mnemonic.type = INPUT_KEYBOARD;
  mnemonic.ki.wVk = mnemonic_char;

  // Depress and release the mnemonic.
  SendInput(1, &mnemonic, sizeof(INPUT));
  Sleep(100);

  mnemonic.ki.dwFlags |= KEYEVENTF_KEYUP;
  SendInput(1, &mnemonic, sizeof(INPUT));
  Sleep(100);

  // Now release the modifiers.
  for (int index = 0;  index < num_special_keys; index++) {
    special_keys[index].ki.dwFlags |= KEYEVENTF_KEYUP;
  }

  SendInput(num_special_keys, special_keys, sizeof(INPUT));
  Sleep(100);

  return true;
}

std::wstring GetExecutableAppPath(const std::wstring& file) {
  std::wstring kAppPathsKey =
      L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\";

  std::wstring app_path;
  RegKey key(HKEY_LOCAL_MACHINE, (kAppPathsKey + file).c_str());
  if (key.Handle()) {
    key.ReadValue(NULL, &app_path);
  }

  return app_path;
}

std::wstring FormatCommandForApp(const std::wstring& exe_name,
                                 const std::wstring& argument) {
  std::wstring reg_path(StringPrintf(L"Applications\\%ls\\shell\\open\\command",
                                     exe_name.c_str()));
  RegKey key(HKEY_CLASSES_ROOT, reg_path.c_str());

  std::wstring command;
  if (key.Handle()) {
    key.ReadValue(NULL, &command);
    int found = command.find(L"%1");
    if (found >= 0) {
      command.replace(found, 2, argument);
    }
  }
  return command;
}

base::ProcessHandle LaunchExecutable(const std::wstring& executable,
                                     const std::wstring& argument) {
  base::ProcessHandle process = NULL;
  std::wstring path = GetExecutableAppPath(executable);
  if (path.empty()) {
    path = FormatCommandForApp(executable, argument);
    if (path.empty()) {
      DLOG(ERROR) << "Failed to find executable: " << executable;
    } else {
      CommandLine cmdline = CommandLine::FromString(path);
      base::LaunchApp(cmdline, false, false, &process);
    }
  } else {
    CommandLine cmdline(path);
    cmdline.AppendLooseValue(argument);
    base::LaunchApp(cmdline, false, false, &process);
  }
  return process;
}

base::ProcessHandle LaunchFirefox(const std::wstring& url) {
  return LaunchExecutable(kFirefoxImageName, url);
}

base::ProcessHandle LaunchSafari(const std::wstring& url) {
  return LaunchExecutable(kSafariImageName, url);
}

base::ProcessHandle LaunchChrome(const std::wstring& url) {
  return LaunchExecutable(kChromeImageName,
      StringPrintf(L"--%ls ", switches::kNoFirstRun) + url);
}

base::ProcessHandle LaunchOpera(const std::wstring& url) {
  // NOTE: For Opera tests to work it must be configured to start up with
  // a blank page.  There is an command line switch, -nosession, that's supposed
  // to avoid opening up the previous session, but that switch is not working.
  // TODO(tommi): Include a special ini file (opera6.ini) for opera and launch
  //  with our required settings.  This file is by default stored here:
  // "%USERPROFILE%\Application Data\Opera\Opera\profile\opera6.ini"
  return LaunchExecutable(kOperaImageName, url);
}

base::ProcessHandle LaunchIEOnVista(const std::wstring& url) {
  typedef HRESULT (WINAPI* IELaunchURLPtr)(
      const wchar_t* url,
      PROCESS_INFORMATION *pi,
      VOID *info);

  IELaunchURLPtr launch;
  PROCESS_INFORMATION pi = {0};
  IELAUNCHURLINFO  info = {sizeof info, 0};
  HMODULE h = LoadLibrary(L"ieframe.dll");
  if (!h)
    return NULL;
  launch = reinterpret_cast<IELaunchURLPtr>(GetProcAddress(h, "IELaunchURL"));
  HRESULT hr = launch(url.c_str(), &pi, &info);
  FreeLibrary(h);
  if (SUCCEEDED(hr))
    CloseHandle(pi.hThread);
  return pi.hProcess;
}

base::ProcessHandle LaunchIE(const std::wstring& url) {
  if (win_util::GetWinVersion() >= win_util::WINVERSION_VISTA) {
    return LaunchIEOnVista(url);
  } else {
    return LaunchExecutable(kIEImageName, url);
  }
}

int CloseAllIEWindows() {
  int ret = 0;

  ScopedComPtr<IShellWindows> windows;
  HRESULT hr = ::CoCreateInstance(__uuidof(ShellWindows), NULL, CLSCTX_ALL,
      IID_IShellWindows, reinterpret_cast<void**>(windows.Receive()));
  DCHECK(SUCCEEDED(hr));

  if (SUCCEEDED(hr)) {
    long count = 0;  // NOLINT
    windows->get_Count(&count);
    VARIANT i = { VT_I4 };
    for (i.lVal = 0; i.lVal < count; ++i.lVal) {
      ScopedComPtr<IDispatch> folder;
      windows->Item(i, folder.Receive());
      if (folder != NULL) {
        ScopedComPtr<IWebBrowser2> browser;
        if (SUCCEEDED(browser.QueryFrom(folder))) {
          browser->Quit();
          ++ret;
        }
      }
    }
  }

  return ret;
}

}  // namespace chrome_frame_test
<commit_msg>Blind attempt at fixing broken Chrome Frame test utils build.<commit_after>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome_frame/test/chrome_frame_test_utils.h"

#include <atlbase.h>
#include <atlwin.h>
#include <iepmapi.h>

#include "base/registry.h"   // to find IE and firefox
#include "base/scoped_handle.h"
#include "base/scoped_comptr_win.h"
#include "base/string_util.h"
#include "base/win_util.h"
#include "chrome/common/chrome_switches.h"

namespace chrome_frame_test {

const wchar_t kIEImageName[] = L"iexplore.exe";
const wchar_t kIEBrokerImageName[] = L"ieuser.exe";
const wchar_t kFirefoxImageName[] = L"firefox.exe";
const wchar_t kOperaImageName[] = L"opera.exe";
const wchar_t kSafariImageName[] = L"safari.exe";
const wchar_t kChromeImageName[] = L"chrome.exe";

bool IsTopLevelWindow(HWND window) {
  long style = GetWindowLong(window, GWL_STYLE);  // NOLINT
  if (!(style & WS_CHILD))
    return true;

  HWND parent = GetParent(window);
  if (!parent)
    return true;

  if (parent == GetDesktopWindow())
    return true;

  return false;
}

// Callback function for EnumThreadWindows.
BOOL CALLBACK CloseWindowsThreadCallback(HWND hwnd, LPARAM param) {
  int& count = *reinterpret_cast<int*>(param);
  if (IsWindowVisible(hwnd)) {
    if (IsWindowEnabled(hwnd)) {
      DWORD results = 0;
      if (!::SendMessageTimeout(hwnd, WM_SYSCOMMAND, SC_CLOSE, 0, SMTO_BLOCK,
                                10000, &results)) {
        DLOG(WARNING) << "Window hung: " << StringPrintf(L"%08X", hwnd);
      }
      count++;
    } else {
      DLOG(WARNING) << "Skipping disabled window: "
                  << StringPrintf(L"%08X", hwnd);
    }
  }
  return TRUE;  // continue enumeration
}

// Attempts to close all non-child, visible windows on the given thread.
// The return value is the number of visible windows a close request was
// sent to.
int CloseVisibleTopLevelWindowsOnThread(DWORD thread_id) {
  int window_close_attempts = 0;
  EnumThreadWindows(thread_id, CloseWindowsThreadCallback,
                    reinterpret_cast<LPARAM>(&window_close_attempts));
  return window_close_attempts;
}

// Enumerates the threads of a process and attempts to close visible non-child
// windows on all threads of the process.
// The return value is the number of visible windows a close request was
// sent to.
int CloseVisibleWindowsOnAllThreads(HANDLE process) {
  DWORD process_id = ::GetProcessId(process);
  if (process_id == 0) {
    NOTREACHED();
    return 0;
  }

  ScopedHandle snapshot(CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0));
  if (!snapshot.IsValid()) {
    NOTREACHED();
    return 0;
  }

  int window_close_attempts = 0;
  THREADENTRY32 te = { sizeof(THREADENTRY32) };
  if (Thread32First(snapshot, &te)) {
    do {
      if (RTL_CONTAINS_FIELD(&te, te.dwSize, th32OwnerProcessID) &&
          te.th32OwnerProcessID == process_id) {
        window_close_attempts +=
            CloseVisibleTopLevelWindowsOnThread(te.th32ThreadID);
      }
      te.dwSize = sizeof(te);
    } while (Thread32Next(snapshot, &te));
  }

  return window_close_attempts;
}

class ForegroundHelperWindow : public CWindowImpl<ForegroundHelperWindow> {
 public:
BEGIN_MSG_MAP(ForegroundHelperWindow)
  MESSAGE_HANDLER(WM_HOTKEY, OnHotKey)
END_MSG_MAP()

  HRESULT SetForeground(HWND window) {
    DCHECK(::IsWindow(window));
    if (NULL == Create(NULL, NULL, NULL, WS_POPUP))
      return AtlHresultFromLastError();

    static const int hotkey_id = 0x0000baba;

    SetWindowLongPtr(GWLP_USERDATA, reinterpret_cast<ULONG_PTR>(window));
    RegisterHotKey(m_hWnd, hotkey_id, 0, VK_F22);

    MSG msg = {0};
    PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);

    INPUT hotkey = {0};
    hotkey.type = INPUT_KEYBOARD;
    hotkey.ki.wVk =  VK_F22;
    SendInput(1, &hotkey, sizeof(hotkey));

    while (GetMessage(&msg, NULL, 0, 0)) {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
      if (WM_HOTKEY == msg.message)
        break;
    }

    UnregisterHotKey(m_hWnd, hotkey_id);
    DestroyWindow();

    return S_OK;
  }

  LRESULT OnHotKey(UINT msg, WPARAM wp, LPARAM lp, BOOL& handled) {  // NOLINT
    HWND window = reinterpret_cast<HWND>(GetWindowLongPtr(GWLP_USERDATA));
    SetForegroundWindow(window);
    return 1;
  }
};

bool ForceSetForegroundWindow(HWND window) {
  if (GetForegroundWindow() == window)
    return true;
  ForegroundHelperWindow foreground_helper_window;
  HRESULT hr = foreground_helper_window.SetForeground(window);
  return SUCCEEDED(hr);
}

struct PidAndWindow {
  base::ProcessId pid;
  HWND hwnd;
};

BOOL CALLBACK FindWindowInProcessCallback(HWND hwnd, LPARAM param) {
  PidAndWindow* paw = reinterpret_cast<PidAndWindow*>(param);
  base::ProcessId pid;
  GetWindowThreadProcessId(hwnd, &pid);
  if (pid == paw->pid && IsWindowVisible(hwnd)) {
    paw->hwnd = hwnd;
    return FALSE;
  }

  return TRUE;
}

bool EnsureProcessInForeground(base::ProcessId process_id) {
  HWND hwnd = GetForegroundWindow();
  base::ProcessId current_foreground_pid = 0;
  DWORD active_thread_id = GetWindowThreadProcessId(hwnd,
      &current_foreground_pid);
  if (current_foreground_pid == process_id)
    return true;

  PidAndWindow paw = { process_id };
  EnumWindows(FindWindowInProcessCallback, reinterpret_cast<LPARAM>(&paw));
  if (!IsWindow(paw.hwnd)) {
    DLOG(ERROR) << "failed to find process window";
    return false;
  }

  bool ret = ForceSetForegroundWindow(paw.hwnd);
  DLOG_IF(ERROR, !ret) << "ForceSetForegroundWindow: " << ret;

  return ret;
}

// Iterates through all the characters in the string and simulates
// keyboard input.  The input goes to the currently active application.
bool SendString(const wchar_t* string) {
  DCHECK(string != NULL);

  INPUT input[2] = {0};
  input[0].type = INPUT_KEYBOARD;
  input[0].ki.dwFlags = KEYEVENTF_UNICODE;  // to avoid shift, etc.
  input[1] = input[0];
  input[1].ki.dwFlags |= KEYEVENTF_KEYUP;

  for (const wchar_t* p = string; *p; p++) {
    input[0].ki.wScan = input[1].ki.wScan = *p;
    SendInput(2, input, sizeof(INPUT));
  }

  return true;
}

void SendVirtualKey(int16 key) {
  INPUT input = { INPUT_KEYBOARD };
  input.ki.wVk = key;
  SendInput(1, &input, sizeof(input));
  input.ki.dwFlags = KEYEVENTF_KEYUP;
  SendInput(1, &input, sizeof(input));
}

void SendChar(char c) {
  SendVirtualKey(VkKeyScanA(c));
}

void SendString(const char* s) {
  while (*s) {
    SendChar(*s);
    s++;
  }
}

// Sends a keystroke to the currently active application with optional
// modifiers set.
bool SendMnemonic(WORD mnemonic_char, bool shift_pressed, bool control_pressed,
                  bool alt_pressed) {
  INPUT special_keys[3] = {0};
  for (int index = 0; index < arraysize(special_keys); ++index) {
    special_keys[index].type = INPUT_KEYBOARD;
    special_keys[index].ki.dwFlags = 0;
  }

  int num_special_keys = 0;
  if (shift_pressed)  {
    special_keys[num_special_keys].ki.wVk = VK_SHIFT;
    num_special_keys++;
  }

  if (control_pressed)  {
    special_keys[num_special_keys].ki.wVk = VK_CONTROL;
    num_special_keys++;
  }

  if (alt_pressed)  {
    special_keys[num_special_keys].ki.wVk = VK_MENU;
    num_special_keys++;
  }

  // Depress the modifiers.
  SendInput(num_special_keys, special_keys, sizeof(INPUT));

  Sleep(100);

  INPUT mnemonic = {0};
  mnemonic.type = INPUT_KEYBOARD;
  mnemonic.ki.wVk = mnemonic_char;

  // Depress and release the mnemonic.
  SendInput(1, &mnemonic, sizeof(INPUT));
  Sleep(100);

  mnemonic.ki.dwFlags |= KEYEVENTF_KEYUP;
  SendInput(1, &mnemonic, sizeof(INPUT));
  Sleep(100);

  // Now release the modifiers.
  for (int index = 0;  index < num_special_keys; index++) {
    special_keys[index].ki.dwFlags |= KEYEVENTF_KEYUP;
  }

  SendInput(num_special_keys, special_keys, sizeof(INPUT));
  Sleep(100);

  return true;
}

std::wstring GetExecutableAppPath(const std::wstring& file) {
  std::wstring kAppPathsKey =
      L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\";

  std::wstring app_path;
  RegKey key(HKEY_LOCAL_MACHINE, (kAppPathsKey + file).c_str());
  if (key.Handle()) {
    key.ReadValue(NULL, &app_path);
  }

  return app_path;
}

std::wstring FormatCommandForApp(const std::wstring& exe_name,
                                 const std::wstring& argument) {
  std::wstring reg_path(StringPrintf(L"Applications\\%ls\\shell\\open\\command",
                                     exe_name.c_str()));
  RegKey key(HKEY_CLASSES_ROOT, reg_path.c_str());

  std::wstring command;
  if (key.Handle()) {
    key.ReadValue(NULL, &command);
    int found = command.find(L"%1");
    if (found >= 0) {
      command.replace(found, 2, argument);
    }
  }
  return command;
}

base::ProcessHandle LaunchExecutable(const std::wstring& executable,
                                     const std::wstring& argument) {
  base::ProcessHandle process = NULL;
  std::wstring path = GetExecutableAppPath(executable);
  if (path.empty()) {
    path = FormatCommandForApp(executable, argument);
    if (path.empty()) {
      DLOG(ERROR) << "Failed to find executable: " << executable;
    } else {
      CommandLine cmdline = CommandLine::FromString(path);
      base::LaunchApp(cmdline, false, false, &process);
    }
  } else {
    CommandLine cmdline(FilePath(path));
    cmdline.AppendLooseValue(argument);
    base::LaunchApp(cmdline, false, false, &process);
  }
  return process;
}

base::ProcessHandle LaunchFirefox(const std::wstring& url) {
  return LaunchExecutable(kFirefoxImageName, url);
}

base::ProcessHandle LaunchSafari(const std::wstring& url) {
  return LaunchExecutable(kSafariImageName, url);
}

base::ProcessHandle LaunchChrome(const std::wstring& url) {
  return LaunchExecutable(kChromeImageName,
      StringPrintf(L"--%ls ", switches::kNoFirstRun) + url);
}

base::ProcessHandle LaunchOpera(const std::wstring& url) {
  // NOTE: For Opera tests to work it must be configured to start up with
  // a blank page.  There is an command line switch, -nosession, that's supposed
  // to avoid opening up the previous session, but that switch is not working.
  // TODO(tommi): Include a special ini file (opera6.ini) for opera and launch
  //  with our required settings.  This file is by default stored here:
  // "%USERPROFILE%\Application Data\Opera\Opera\profile\opera6.ini"
  return LaunchExecutable(kOperaImageName, url);
}

base::ProcessHandle LaunchIEOnVista(const std::wstring& url) {
  typedef HRESULT (WINAPI* IELaunchURLPtr)(
      const wchar_t* url,
      PROCESS_INFORMATION *pi,
      VOID *info);

  IELaunchURLPtr launch;
  PROCESS_INFORMATION pi = {0};
  IELAUNCHURLINFO  info = {sizeof info, 0};
  HMODULE h = LoadLibrary(L"ieframe.dll");
  if (!h)
    return NULL;
  launch = reinterpret_cast<IELaunchURLPtr>(GetProcAddress(h, "IELaunchURL"));
  HRESULT hr = launch(url.c_str(), &pi, &info);
  FreeLibrary(h);
  if (SUCCEEDED(hr))
    CloseHandle(pi.hThread);
  return pi.hProcess;
}

base::ProcessHandle LaunchIE(const std::wstring& url) {
  if (win_util::GetWinVersion() >= win_util::WINVERSION_VISTA) {
    return LaunchIEOnVista(url);
  } else {
    return LaunchExecutable(kIEImageName, url);
  }
}

int CloseAllIEWindows() {
  int ret = 0;

  ScopedComPtr<IShellWindows> windows;
  HRESULT hr = ::CoCreateInstance(__uuidof(ShellWindows), NULL, CLSCTX_ALL,
      IID_IShellWindows, reinterpret_cast<void**>(windows.Receive()));
  DCHECK(SUCCEEDED(hr));

  if (SUCCEEDED(hr)) {
    long count = 0;  // NOLINT
    windows->get_Count(&count);
    VARIANT i = { VT_I4 };
    for (i.lVal = 0; i.lVal < count; ++i.lVal) {
      ScopedComPtr<IDispatch> folder;
      windows->Item(i, folder.Receive());
      if (folder != NULL) {
        ScopedComPtr<IWebBrowser2> browser;
        if (SUCCEEDED(browser.QueryFrom(folder))) {
          browser->Quit();
          ++ret;
        }
      }
    }
  }

  return ret;
}

}  // namespace chrome_frame_test
<|endoftext|>


<commit_before>#include "OE/Platform/OpenGL/GLStates.hpp"

#include "OE/Platform/OpenGL/OpenGL.hpp"
#include "OE/Graphics/API/FrameBuffer.hpp"

namespace OrbitEngine { namespace Graphics {

	void GLStates::setBlending(BlendState blendState)
	{
		GLEnableDisableColorMask(blendState != BlendState::NO_COLOR);

		switch (blendState)
		{
		case BlendState::NO_COLOR:
		case BlendState::DISABLED:
			GLEnableDisable(GL_BLEND, false);
			break;
		default:
			GLEnableDisable(GL_BLEND, true);
			switch (blendState)
			{
			case BlendState::SRC_ALPHA:
				OE_CHECK_GL(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
				break;
			case BlendState::ONE_ALPHA:
				OE_CHECK_GL(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
				break;
			case BlendState::ONE_ONE:
				OE_CHECK_GL(glBlendFunc(GL_ONE, GL_ONE));
				break;
			case BlendState::ONE_ZERO:
				OE_CHECK_GL(glBlendFunc(GL_ONE, GL_ZERO));
				break;
			}
			break;
		}
	}

	void GLStates::setCullMode(CullMode cullMode)
	{
#if !OE_OPENGL_ES
		// Not supported in OpenGLES
		if (cullMode == CullMode::WIREFRAME)
			glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
		else
			glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
#else
		cullMode = CullMode::NONE;
#endif

		if (cullMode == CullMode::NONE)
			GLEnableDisable(GL_CULL_FACE, false);
		else {
			GLEnableDisable(GL_CULL_FACE, true);

			if (cullMode != CullMode::WIREFRAME)
				OE_CHECK_GL(glCullFace(CullModeToGL(cullMode)));
		}
	}

	void GLStates::setDepthTest(FunctionMode depthMode)
	{
		bool enabled = depthMode != FunctionMode::DISABLED;
		GLEnableDisable(GL_DEPTH_TEST, enabled);
		if (!enabled)
			return;
		OE_CHECK_GL(glDepthFunc(FunctionModeToGL(depthMode)));
	}

	void GLStates::setStencil(FunctionMode stencilMode, StencilOperation operation)
	{
		bool enabled = stencilMode != FunctionMode::DISABLED;
		GLEnableDisable(GL_STENCIL_TEST, enabled);
		if (!enabled)
			return;

		OE_CHECK_GL(glStencilMask(0xff));
		OE_CHECK_GL(glStencilFunc(FunctionModeToGL(stencilMode), 0x0, 0xff));

		switch (operation)
		{
		case StencilOperation::ZERO:
			OE_CHECK_GL(glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO));
			break;
		case StencilOperation::KEEP:
			OE_CHECK_GL(glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP));
			break;
		case StencilOperation::SEPARATE_INCR_DECR:
			OE_CHECK_GL(glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_INCR_WRAP));
			OE_CHECK_GL(glStencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, GL_DECR_WRAP));
			break;
		}
	}

	void GLStates::setScissor(Math::Scissor* scissor)
	{
		bool enabled = scissor != nullptr;

		GLEnableDisable(GL_SCISSOR_TEST, enabled);

		if (enabled) {
			OE_CHECK_GL(glScissor(
				scissor->rect.x,
				FrameBuffer::GetCurrentSize().y - (scissor->rect.w + scissor->rect.y),
				scissor->rect.z,
				scissor->rect.w
			));
		}
	}

	GLenum GLStates::CullModeToGL(CullMode cullMode)
	{
		switch (cullMode)
		{
		case CullMode::WIREFRAME:
		case CullMode::NONE:
			return GL_FRONT_AND_BACK;
		case CullMode::FRONT:
			return GL_FRONT;
		case CullMode::BACK:
			return GL_BACK;
		}
		// TODO Assert
		return 0;
	}

	GLenum GLStates::FunctionModeToGL(FunctionMode functionMode)
	{
		switch (functionMode)
		{
		case FunctionMode::NEVER:
			return GL_NEVER;
		case FunctionMode::LESS:
			return GL_LESS;
		case FunctionMode::EQUAL:
			return GL_EQUAL;
		case FunctionMode::LESS_EQUAL:
			return GL_LEQUAL;
		case FunctionMode::GREATER:
			return GL_GREATER;
		case FunctionMode::NOT_EQUAL:
			return GL_NOTEQUAL;
		case FunctionMode::GREATER_EQUAL:
			return GL_GEQUAL;
		case FunctionMode::ALWAYS:
			return GL_ALWAYS;
		}
		// TODO Assert
		return 0;
	}

	bool GLStates::cache(GLenum key, GLuint value)
	{
		auto it = m_GLCache.find(key);
		if (it != m_GLCache.end()) {
			if ((*it).second == value)
				return true; // hit
		}
		m_GLCache[key] = value;
		return false;
	}

	void GLStates::GLEnableDisable(GLenum type, GLboolean enabled)
	{
		if (cache(type, enabled))
			return;

		if (enabled) {
			OE_CHECK_GL(glEnable(type));
		}
		else {
			OE_CHECK_GL(glDisable(type));
		}
	}

	void GLStates::GLEnableDisableColorMask(GLboolean enabled)
	{
		if (cache(0x8E52 /* GL_SAMPLE_MASK_VALUE */, enabled))
			return;

		OE_CHECK_GL(glColorMask(enabled, enabled, enabled, enabled));
	}
} }<commit_msg>GL blend func cache<commit_after>#include "OE/Platform/OpenGL/GLStates.hpp"

#include "OE/Platform/OpenGL/OpenGL.hpp"
#include "OE/Graphics/API/FrameBuffer.hpp"

namespace OrbitEngine { namespace Graphics {

	void GLStates::setBlending(BlendState blendState)
	{
		GLEnableDisableColorMask(blendState != BlendState::NO_COLOR);

		switch (blendState)
		{
		case BlendState::NO_COLOR:
		case BlendState::DISABLED:
			GLEnableDisable(GL_BLEND, false);
			break;
		default:
			GLEnableDisable(GL_BLEND, true);

			if (!cache(GL_BLEND_SRC, (int)blendState)) {
				switch (blendState)
				{
				case BlendState::SRC_ALPHA:
					OE_CHECK_GL(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
					break;
				case BlendState::ONE_ALPHA:
					OE_CHECK_GL(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
					break;
				case BlendState::ONE_ONE:
					OE_CHECK_GL(glBlendFunc(GL_ONE, GL_ONE));
					break;
				case BlendState::ONE_ZERO:
					OE_CHECK_GL(glBlendFunc(GL_ONE, GL_ZERO));
					break;
				}
				break;
			}
		}
	}

	void GLStates::setCullMode(CullMode cullMode)
	{
#if !OE_OPENGL_ES
		// Not supported in OpenGLES
		if (cullMode == CullMode::WIREFRAME)
			glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
		else
			glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
#else
		cullMode = CullMode::NONE;
#endif

		if (cullMode == CullMode::NONE)
			GLEnableDisable(GL_CULL_FACE, false);
		else {
			GLEnableDisable(GL_CULL_FACE, true);

			if (cullMode != CullMode::WIREFRAME)
				OE_CHECK_GL(glCullFace(CullModeToGL(cullMode)));
		}
	}

	void GLStates::setDepthTest(FunctionMode depthMode)
	{
		bool enabled = depthMode != FunctionMode::DISABLED;
		GLEnableDisable(GL_DEPTH_TEST, enabled);
		if (!enabled)
			return;
		OE_CHECK_GL(glDepthFunc(FunctionModeToGL(depthMode)));
	}

	void GLStates::setStencil(FunctionMode stencilMode, StencilOperation operation)
	{
		bool enabled = stencilMode != FunctionMode::DISABLED;
		GLEnableDisable(GL_STENCIL_TEST, enabled);
		if (!enabled)
			return;

		OE_CHECK_GL(glStencilMask(0xff));
		OE_CHECK_GL(glStencilFunc(FunctionModeToGL(stencilMode), 0x0, 0xff));

		switch (operation)
		{
		case StencilOperation::ZERO:
			OE_CHECK_GL(glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO));
			break;
		case StencilOperation::KEEP:
			OE_CHECK_GL(glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP));
			break;
		case StencilOperation::SEPARATE_INCR_DECR:
			OE_CHECK_GL(glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_INCR_WRAP));
			OE_CHECK_GL(glStencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, GL_DECR_WRAP));
			break;
		}
	}

	void GLStates::setScissor(Math::Scissor* scissor)
	{
		bool enabled = scissor != nullptr;

		GLEnableDisable(GL_SCISSOR_TEST, enabled);

		if (enabled) {
			OE_CHECK_GL(glScissor(
				scissor->rect.x,
				FrameBuffer::GetCurrentSize().y - (scissor->rect.w + scissor->rect.y),
				scissor->rect.z,
				scissor->rect.w
			));
		}
	}

	GLenum GLStates::CullModeToGL(CullMode cullMode)
	{
		switch (cullMode)
		{
		case CullMode::WIREFRAME:
		case CullMode::NONE:
			return GL_FRONT_AND_BACK;
		case CullMode::FRONT:
			return GL_FRONT;
		case CullMode::BACK:
			return GL_BACK;
		}
		// TODO Assert
		return 0;
	}

	GLenum GLStates::FunctionModeToGL(FunctionMode functionMode)
	{
		switch (functionMode)
		{
		case FunctionMode::NEVER:
			return GL_NEVER;
		case FunctionMode::LESS:
			return GL_LESS;
		case FunctionMode::EQUAL:
			return GL_EQUAL;
		case FunctionMode::LESS_EQUAL:
			return GL_LEQUAL;
		case FunctionMode::GREATER:
			return GL_GREATER;
		case FunctionMode::NOT_EQUAL:
			return GL_NOTEQUAL;
		case FunctionMode::GREATER_EQUAL:
			return GL_GEQUAL;
		case FunctionMode::ALWAYS:
			return GL_ALWAYS;
		}
		// TODO Assert
		return 0;
	}

	bool GLStates::cache(GLenum key, GLuint value)
	{
		auto it = m_GLCache.find(key);
		if (it != m_GLCache.end()) {
			if ((*it).second == value)
				return true; // hit
		}
		m_GLCache[key] = value;
		return false;
	}

	void GLStates::GLEnableDisable(GLenum type, GLboolean enabled)
	{
		if (cache(type, enabled))
			return;

		if (enabled) {
			OE_CHECK_GL(glEnable(type));
		}
		else {
			OE_CHECK_GL(glDisable(type));
		}
	}

	void GLStates::GLEnableDisableColorMask(GLboolean enabled)
	{
		if (cache(0x8E52 /* GL_SAMPLE_MASK_VALUE */, enabled))
			return;

		OE_CHECK_GL(glColorMask(enabled, enabled, enabled, enabled));
	}
} }<|endoftext|>


<commit_before>/*
 * THE NEW CHRONOTEXT TOOLKIT: https://github.com/arielm/new-chronotext-toolkit
 * COPYRIGHT (C) 2012-2014, ARIEL MALKA ALL RIGHTS RESERVED.
 *
 * THE FOLLOWING SOURCE-CODE IS DISTRIBUTED UNDER THE MODIFIED BSD LICENSE:
 * https://github.com/arielm/new-chronotext-toolkit/blob/master/LICENSE.md
 */

#include "chronotext/cinder/CinderApp.h"
#include "chronotext/utils/Utils.h"

using namespace std;
using namespace ci;
using namespace app;

namespace chronotext
{
    CinderApp::CinderApp()
    :
    startCount(0),
    updateCount(0),
    ticks(0)
    {}

    void CinderApp::setup()
    {
        /*
         * App::privateUpdate__ HACKING: SEE COMMENT IN CinderApp::update
         */
        io_service().post([this]{ sketch->clock().update(); });

        sketch->setIOService(io_service());
        sketch->timeline().stepTo(0);
        sketch->setup(false);

#if defined(CINDER_COCOA_TOUCH)
        getSignalDidBecomeActive().connect(bind(&CinderApp::start, this));
        getSignalWillResignActive().connect(bind(&CinderApp::stop, this));
#endif
    }

    void CinderApp::shutdown()
    {
        stop();
        sketch->stop(CinderSketch::FLAG_FOCUS_LOST);
        sketch->shutdown();
        delete sketch;
    }

    void CinderApp::resize()
    {
        sketch->resize();

        if (startCount == 0)
        {
            start();
            sketch->start(CinderSketch::FLAG_FOCUS_GAINED);
            startCount++;
        }
    }

    void CinderApp::update()
    {
        double now = getElapsedSeconds();

        if (ticks == 0)
        {
            t0 = now;
        }

        ticks++;
        elapsed = now - t0;

        // ---

        /*
         * App::privateUpdate__ HACKING:
         * WE MUST UPDATE THE CLOCK AT THE BEGINNING OF THE FRAME,
         * AND WE NEED THIS TO TAKE PLACE BEFORE THE FUNCTIONS
         * "POSTED" DURING CinderSketch::update ARE "POLLED"
         */
        io_service().post([this]{ sketch->clock().update(); });

        /*
         * MUST BE CALLED BEFORE Sketch::update
         * ANY SUBSEQUENT CALL WILL RETURN THE SAME TIME-VALUE
         *
         * NOTE THAT getTime() COULD HAVE BEEN ALREADY CALLED
         * WITHIN ONE OF THE PREVIOUSLY "POLLED" FUNCTIONS
         */
        now = sketch->clock().getTime();

        sketch->update();
        sketch->timeline().stepTo(now); // WE OBVIOUSLY CAN'T USE THE APP'S TIMELINE...
        updateCount++;
    }

    void CinderApp::draw()
    {
        if (updateCount == 0)
        {
            update(); // HANDLING CASES WHERE draw() IS INVOKED BEFORE update()
        }

        sketch->draw();
    }

    void CinderApp::mouseDown(MouseEvent event)
    {
        addTouch(0, event.getPos());
    }

    void CinderApp::mouseDrag(MouseEvent event)
    {
        updateTouch(0, event.getPos());
    }

    void CinderApp::mouseUp(MouseEvent event)
    {
        removeTouch(0, event.getPos());
    }

    void CinderApp::touchesBegan(TouchEvent event)
    {
        for (auto &touch : event.getTouches())
        {
            addTouch(touch.getId() - 1, touch.getPos());
        }
    }

    void CinderApp::touchesMoved(TouchEvent event)
    {
        for (auto &touch : event.getTouches())
        {
            updateTouch(touch.getId() - 1, touch.getPos());
        }
    }

    void CinderApp::touchesEnded(TouchEvent event)
    {
        for (auto &touch : event.getTouches())
        {
            removeTouch(touch.getId() - 1, touch.getPos());
        }
    }

    void CinderApp::accelerated(AccelEvent event)
    {
        sketch->accelerated(event);
    }

    void CinderApp::sendMessageToSketch(int what, const string &body)
    {
        sketch->sendMessage(Message(what, body));
    }

    void CinderApp::emulate(Settings *settings, const EmulatedDevice &device)
    {
        /*
         * HACK TO OVERCOME MALFUNCTION IN 0.8.5
         * OTHERWISE, WE'D USE settings->getDisplay()->getContentScale()
         */
        stringstream tmp;
        tmp << *settings->getDisplay();
        float realContentScale = (tmp.str().back() == '2') ? 2 : 1;

        settings->setWindowSize(device.size * device.contentScale / realContentScale);

        WindowInfo windowInfo;
        windowInfo.size = device.size;
        windowInfo.contentScale = device.contentScale;
        windowInfo.diagonal = device.diagonal;
        windowInfo.density = (device.diagonal == 0) ? 0: (device.size.length() / device.diagonal);

        SystemInfo::instance().setWindowInfo(windowInfo);
    }

#if defined(CINDER_ANDROID)

    void CinderApp::resume(bool renewContext)
    {
        sketch->setup(true);
        sketch->start(CinderSketch::FLAG_APP_RESUMED);
    }

    void CinderApp::pause()
    {
        sketch->event(CinderSketch::EVENT_CONTEXT_LOST);
        sketch->stop(CinderSketch::FLAG_APP_PAUSED);
    }

#endif

    void CinderApp::start()
    {
        ticks = 0;
        sketch->clock().start();
    }

    void CinderApp::stop()
    {
        sketch->clock().stop();
        LOGI << "AVERAGE FRAME-RATE: " << ticks / elapsed << " FPS" << endl;
    }

    void CinderApp::addTouch(int index, const Vec2f &position)
    {
        auto scale = sketch->getWindowInfo().contentScale / getWindowContentScale();
        sketch->addTouch(0, position.x / scale, position.y / scale);
    }

    void CinderApp::updateTouch(int index, const Vec2f &position)
    {
        auto scale = sketch->getWindowInfo().contentScale / getWindowContentScale();
        sketch->updateTouch(0, position.x / scale, position.y / scale);
    }

    void CinderApp::removeTouch(int index, const Vec2f &position)
    {
        auto scale = sketch->getWindowInfo().contentScale / getWindowContentScale();
        sketch->removeTouch(0, position.x / scale, position.y / scale);
    }
}
<commit_msg>COSMETICS<commit_after>/*
 * THE NEW CHRONOTEXT TOOLKIT: https://github.com/arielm/new-chronotext-toolkit
 * COPYRIGHT (C) 2012-2014, ARIEL MALKA ALL RIGHTS RESERVED.
 *
 * THE FOLLOWING SOURCE-CODE IS DISTRIBUTED UNDER THE MODIFIED BSD LICENSE:
 * https://github.com/arielm/new-chronotext-toolkit/blob/master/LICENSE.md
 */

#include "chronotext/cinder/CinderApp.h"
#include "chronotext/utils/Utils.h"

using namespace std;
using namespace ci;
using namespace app;

namespace chronotext
{
    CinderApp::CinderApp()
    :
    startCount(0),
    updateCount(0),
    ticks(0)
    {}

    void CinderApp::setup()
    {
        /*
         * App::privateUpdate__ HACKING: SEE COMMENT IN CinderApp::update
         */
        io_service().post([this]{ sketch->clock().update(); });

        sketch->setIOService(io_service());
        sketch->timeline().stepTo(0);
        sketch->setup(false);

#if defined(CINDER_COCOA_TOUCH)
        getSignalDidBecomeActive().connect(bind(&CinderApp::start, this));
        getSignalWillResignActive().connect(bind(&CinderApp::stop, this));
#endif
    }

    void CinderApp::shutdown()
    {
        stop();
        sketch->stop(CinderSketch::FLAG_FOCUS_LOST);
        sketch->shutdown();
        delete sketch;
    }

    void CinderApp::resize()
    {
        sketch->resize();

        if (startCount == 0)
        {
            start();
            sketch->start(CinderSketch::FLAG_FOCUS_GAINED);
            startCount++;
        }
    }

    void CinderApp::update()
    {
        double now = getElapsedSeconds();

        if (ticks == 0)
        {
            t0 = now;
        }

        ticks++;
        elapsed = now - t0;

        // ---

        /*
         * App::privateUpdate__ HACKING:
         * WE MUST UPDATE THE CLOCK AT THE BEGINNING OF THE FRAME,
         * AND WE NEED THIS TO TAKE PLACE BEFORE THE FUNCTIONS
         * "POSTED" DURING CinderSketch::update ARE "POLLED"
         */
        io_service().post([this]{ sketch->clock().update(); });

        /*
         * MUST BE CALLED BEFORE Sketch::update
         * ANY SUBSEQUENT CALL WILL RETURN THE SAME TIME-VALUE
         *
         * NOTE THAT getTime() COULD HAVE BEEN ALREADY CALLED
         * WITHIN ONE OF THE PREVIOUSLY "POLLED" FUNCTIONS
         */
        now = sketch->clock().getTime();

        sketch->update();
        sketch->timeline().stepTo(now); // WE OBVIOUSLY CAN'T USE THE APP'S TIMELINE...
        updateCount++;
    }

    void CinderApp::draw()
    {
        if (updateCount == 0)
        {
            update(); // HANDLING CASES WHERE draw() IS INVOKED BEFORE update()
        }

        sketch->draw();
    }

    void CinderApp::mouseDown(MouseEvent event)
    {
        addTouch(0, event.getPos());
    }

    void CinderApp::mouseDrag(MouseEvent event)
    {
        updateTouch(0, event.getPos());
    }

    void CinderApp::mouseUp(MouseEvent event)
    {
        removeTouch(0, event.getPos());
    }

    void CinderApp::touchesBegan(TouchEvent event)
    {
        for (auto &touch : event.getTouches())
        {
            addTouch(touch.getId() - 1, touch.getPos());
        }
    }

    void CinderApp::touchesMoved(TouchEvent event)
    {
        for (auto &touch : event.getTouches())
        {
            updateTouch(touch.getId() - 1, touch.getPos());
        }
    }

    void CinderApp::touchesEnded(TouchEvent event)
    {
        for (auto &touch : event.getTouches())
        {
            removeTouch(touch.getId() - 1, touch.getPos());
        }
    }

    void CinderApp::accelerated(AccelEvent event)
    {
        sketch->accelerated(event);
    }

    void CinderApp::sendMessageToSketch(int what, const string &body)
    {
        sketch->sendMessage(Message(what, body));
    }

    void CinderApp::emulate(Settings *settings, const EmulatedDevice &device)
    {
        /*
         * HACK TO OVERCOME MALFUNCTION IN 0.8.5
         * OTHERWISE, WE'D USE settings->getDisplay()->getContentScale()
         */
        stringstream tmp;
        tmp << *settings->getDisplay();
        float realContentScale = (tmp.str().back() == '2') ? 2 : 1;

        float scale = device.contentScale / realContentScale;
        settings->setWindowSize(device.size * scale);

        WindowInfo windowInfo;
        windowInfo.size = device.size;
        windowInfo.contentScale = device.contentScale;
        windowInfo.diagonal = device.diagonal;
        windowInfo.density = (device.diagonal == 0) ? 0: (device.size.length() / device.diagonal);

        SystemInfo::instance().setWindowInfo(windowInfo);
    }

#if defined(CINDER_ANDROID)

    void CinderApp::resume(bool renewContext)
    {
        sketch->setup(true);
        sketch->start(CinderSketch::FLAG_APP_RESUMED);
    }

    void CinderApp::pause()
    {
        sketch->event(CinderSketch::EVENT_CONTEXT_LOST);
        sketch->stop(CinderSketch::FLAG_APP_PAUSED);
    }

#endif

    void CinderApp::start()
    {
        ticks = 0;
        sketch->clock().start();
    }

    void CinderApp::stop()
    {
        sketch->clock().stop();
        LOGI << "AVERAGE FRAME-RATE: " << ticks / elapsed << " FPS" << endl;
    }

    void CinderApp::addTouch(int index, const Vec2f &position)
    {
        auto scale = sketch->getWindowContentScale() / getWindowContentScale();
        sketch->addTouch(0, position.x / scale, position.y / scale);
    }

    void CinderApp::updateTouch(int index, const Vec2f &position)
    {
        auto scale = sketch->getWindowContentScale() / getWindowContentScale();
        sketch->updateTouch(0, position.x / scale, position.y / scale);
    }

    void CinderApp::removeTouch(int index, const Vec2f &position)
    {
        auto scale = sketch->getWindowContentScale() / getWindowContentScale();
        sketch->removeTouch(0, position.x / scale, position.y / scale);
    }
}
<|endoftext|>