<commit_before>// -----------------------------------------------------------------------------
//
// Copyright (C) 2021 CERN & University of Surrey for the benefit of the
// BioDynaMo collaboration. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
//
// See the LICENSE file distributed with this work for details.
// See the NOTICE file distributed with this work for additional information
// regarding copyright ownership.
//
// -----------------------------------------------------------------------------

#include "core/util/plot_memory_layout.h"

#include <algorithm>
#include <limits>
#include <string>
// ROOT
#include <TAxis.h>
#include <TCanvas.h>
#include <TFrame.h>
#include <TGraph.h>
#include <TGraphAsymmErrors.h>
#include <TGraphErrors.h>
#include <TH1F.h>
#include <TLegend.h>
#include <TMath.h>
#include <TMultiGraph.h>
#include <TPad.h>
#include <TStyle.h>
// BioDynaMo
#include "core/agent/agent.h"
#include "core/environment/environment.h"
#include "core/scheduler.h"
#include "core/simulation.h"

namespace bdm {

// -----------------------------------------------------------------------------
void PlotMemoryLayout(const std::vector<Agent*>& agents, int numa_node) {
  TCanvas c;
  c.SetCanvasSize(1920, 1200);
  std::vector<double> x(agents.size());
  std::vector<double> y(agents.size());

  uint64_t min = std::numeric_limits<uint64_t>::max();
  for (uint64_t i = 0; i < agents.size(); ++i) {
    auto val = reinterpret_cast<uint64_t>(agents[i]);
    if (val < min) {
      min = val;
    }
  }
  for (uint64_t i = 1; i < agents.size(); ++i) {
    x[i] = i;
    y[i] = reinterpret_cast<uint64_t>(agents[i]) - min;
  }
  TGraph graph(agents.size(), x.data(), y.data());
  graph.SetTitle(";Agent element index; Virtual memory address");
  graph.Draw("ap");

  c.Update();
  gPad->Modified();
  gPad->Update();
  c.Modified();
  c.cd(0);
  auto steps = Simulation::GetActive()->GetScheduler()->GetSimulatedSteps();
  auto dir = Simulation::GetActive()->GetOutputDir();
  c.SaveAs(Concat(dir, "/mem-layout-", steps, "-", numa_node, ".png").c_str());
}

// -----------------------------------------------------------------------------
void PlotMemoryHistogram(const std::vector<Agent*>& agents, int numa_node) {
  TCanvas c;
  c.SetCanvasSize(1920, 1200);

  TH1F hist("", "", 100, 1, 10000);
  hist.SetTitle(";#Delta bytes; Count");
  for (uint64_t i = 1; i < agents.size(); ++i) {
    float val = 0;
    auto t = reinterpret_cast<uint64_t>(agents[i]);
    auto l = reinterpret_cast<uint64_t>(agents[i - 1]);
    if (t > l) {
      val = t - l;
    } else {
      val = l - t;
    }
    val = std::min(val, 10000.f - 1);
    hist.Fill(val);
  }
  hist.Draw();

  c.Update();
  gPad->SetLogy();
  gPad->Modified();
  gPad->Update();
  c.Modified();
  c.cd(0);
  auto steps = Simulation::GetActive()->GetScheduler()->GetSimulatedSteps();
  auto dir = Simulation::GetActive()->GetOutputDir();
  c.SaveAs(
      Concat(dir, "/mem-layout-hist-", steps, "-", numa_node, ".png").c_str());
}

// -----------------------------------------------------------------------------
struct Fen : public Functor<void, Agent*, double> {
  std::vector<int64_t>& diffs;
  Agent* query;
  Fen(std::vector<int64_t>& diffs, Agent* query) : diffs(diffs), query(query) {}

  void operator()(Agent* neighbor, double) {
    if (neighbor == query) {
      return;
    }
    auto t = reinterpret_cast<int64_t>(query);
    auto l = reinterpret_cast<int64_t>(neighbor);
    diffs.push_back(t - l);
  }
};

// -----------------------------------------------------------------------------
struct Fea : public Functor<void, Agent*, AgentHandle> {
  std::vector<int64_t>& diffs;
  explicit Fea(std::vector<int64_t>& diffs) : diffs(diffs) {}

  void operator()(Agent* agent, AgentHandle) {
    Fen fen(diffs, agent);
    auto* sim = Simulation::GetActive();
    auto* env = sim->GetEnvironment();
    auto squared_radius = env->GetLargestAgentSizeSquared();
    sim->GetExecutionContext()->ForEachNeighbor(fen, *agent, squared_radius);
  }
};

// -----------------------------------------------------------------------------
void PlotNeighborMemoryHistogram(bool before) {
  TCanvas c;
  c.SetCanvasSize(1920, 1200);
  auto* rm = Simulation::GetActive()->GetResourceManager();
  std::vector<int64_t> diffs;
  diffs.reserve(rm->GetNumAgents() * 3);
  if (!before) {
    Simulation::GetActive()->GetEnvironment()->Update();
  }
  Fea fea(diffs);
  rm->ForEachAgent(fea);
  auto min = std::numeric_limits<float>::max();
  auto max = std::numeric_limits<float>::min();
  for (uint64_t i = 0; i < diffs.size(); ++i) {
    if (diffs[i] < min) {
      min = diffs[i];
    }
    if (diffs[i] > max) {
      max = diffs[i];
    }
  }
  min--;
  max++;
  uint64_t nbins = std::max(static_cast<uint64_t>(100u),
                            static_cast<uint64_t>((max - min) / 20000));
  TH1F hist("", "", nbins, min, max);
  hist.SetTitle(";#Delta bytes; Count");
  for (uint64_t i = 0; i < diffs.size(); ++i) {
    hist.Fill(diffs[i]);
  }
  hist.Draw();

  c.Update();
  gPad->SetLogy();
  gPad->Modified();
  gPad->Update();
  c.Modified();
  c.cd(0);
  auto steps = Simulation::GetActive()->GetScheduler()->GetSimulatedSteps();
  auto dir = Simulation::GetActive()->GetOutputDir();
  std::string suffix = "-end";
  if (before) {
    suffix = "-begin";
  }
  c.SaveAs(
      Concat(dir, "/mem-layout-neighbor-hist-", steps, suffix, ".png").c_str());
  c.SaveAs(
      Concat(dir, "/mem-layout-neighbor-hist-", steps, suffix, ".C").c_str());
}

}  // namespace bdm
<commit_msg>Add safety check in function PlotNeighborMemoryHistogram<commit_after>// -----------------------------------------------------------------------------
//
// Copyright (C) 2021 CERN & University of Surrey for the benefit of the
// BioDynaMo collaboration. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
//
// See the LICENSE file distributed with this work for details.
// See the NOTICE file distributed with this work for additional information
// regarding copyright ownership.
//
// -----------------------------------------------------------------------------

#include "core/util/plot_memory_layout.h"

#include <algorithm>
#include <limits>
#include <string>
// ROOT
#include <TAxis.h>
#include <TCanvas.h>
#include <TFrame.h>
#include <TGraph.h>
#include <TGraphAsymmErrors.h>
#include <TGraphErrors.h>
#include <TH1F.h>
#include <TLegend.h>
#include <TMath.h>
#include <TMultiGraph.h>
#include <TPad.h>
#include <TStyle.h>
// BioDynaMo
#include "core/agent/agent.h"
#include "core/environment/environment.h"
#include "core/scheduler.h"
#include "core/simulation.h"

namespace bdm {

// -----------------------------------------------------------------------------
void PlotMemoryLayout(const std::vector<Agent*>& agents, int numa_node) {
  TCanvas c;
  c.SetCanvasSize(1920, 1200);
  std::vector<double> x(agents.size());
  std::vector<double> y(agents.size());

  uint64_t min = std::numeric_limits<uint64_t>::max();
  for (uint64_t i = 0; i < agents.size(); ++i) {
    auto val = reinterpret_cast<uint64_t>(agents[i]);
    if (val < min) {
      min = val;
    }
  }
  for (uint64_t i = 1; i < agents.size(); ++i) {
    x[i] = i;
    y[i] = reinterpret_cast<uint64_t>(agents[i]) - min;
  }
  TGraph graph(agents.size(), x.data(), y.data());
  graph.SetTitle(";Agent element index; Virtual memory address");
  graph.Draw("ap");

  c.Update();
  gPad->Modified();
  gPad->Update();
  c.Modified();
  c.cd(0);
  auto steps = Simulation::GetActive()->GetScheduler()->GetSimulatedSteps();
  auto dir = Simulation::GetActive()->GetOutputDir();
  c.SaveAs(Concat(dir, "/mem-layout-", steps, "-", numa_node, ".png").c_str());
}

// -----------------------------------------------------------------------------
void PlotMemoryHistogram(const std::vector<Agent*>& agents, int numa_node) {
  TCanvas c;
  c.SetCanvasSize(1920, 1200);

  TH1F hist("", "", 100, 1, 10000);
  hist.SetTitle(";#Delta bytes; Count");
  for (uint64_t i = 1; i < agents.size(); ++i) {
    float val = 0;
    auto t = reinterpret_cast<uint64_t>(agents[i]);
    auto l = reinterpret_cast<uint64_t>(agents[i - 1]);
    if (t > l) {
      val = t - l;
    } else {
      val = l - t;
    }
    val = std::min(val, 10000.f - 1);
    hist.Fill(val);
  }
  hist.Draw();

  c.Update();
  gPad->SetLogy();
  gPad->Modified();
  gPad->Update();
  c.Modified();
  c.cd(0);
  auto steps = Simulation::GetActive()->GetScheduler()->GetSimulatedSteps();
  auto dir = Simulation::GetActive()->GetOutputDir();
  c.SaveAs(
      Concat(dir, "/mem-layout-hist-", steps, "-", numa_node, ".png").c_str());
}

// -----------------------------------------------------------------------------
struct Fen : public Functor<void, Agent*, double> {
  std::vector<int64_t>& diffs;
  Agent* query;
  Fen(std::vector<int64_t>& diffs, Agent* query) : diffs(diffs), query(query) {}

  void operator()(Agent* neighbor, double) {
    if (neighbor == query) {
      return;
    }
    auto t = reinterpret_cast<int64_t>(query);
    auto l = reinterpret_cast<int64_t>(neighbor);
    diffs.push_back(t - l);
  }
};

// -----------------------------------------------------------------------------
struct Fea : public Functor<void, Agent*, AgentHandle> {
  std::vector<int64_t>& diffs;
  explicit Fea(std::vector<int64_t>& diffs) : diffs(diffs) {}

  void operator()(Agent* agent, AgentHandle) {
    Fen fen(diffs, agent);
    auto* sim = Simulation::GetActive();
    auto* env = sim->GetEnvironment();
    auto squared_radius = env->GetLargestAgentSizeSquared();
    sim->GetExecutionContext()->ForEachNeighbor(fen, *agent, squared_radius);
  }
};

// -----------------------------------------------------------------------------
void PlotNeighborMemoryHistogram(bool before) {
  TCanvas c;
  c.SetCanvasSize(1920, 1200);
  auto* rm = Simulation::GetActive()->GetResourceManager();
  if (rm->GetNumAgents() == 0) {
    return;
  }
  std::vector<int64_t> diffs;
  diffs.reserve(rm->GetNumAgents() * 3);
  if (!before) {
    Simulation::GetActive()->GetEnvironment()->Update();
  }
  Fea fea(diffs);
  rm->ForEachAgent(fea);
  auto min = std::numeric_limits<float>::max();
  auto max = std::numeric_limits<float>::min();
  for (uint64_t i = 0; i < diffs.size(); ++i) {
    if (diffs[i] < min) {
      min = diffs[i];
    }
    if (diffs[i] > max) {
      max = diffs[i];
    }
  }
  min--;
  max++;
  uint64_t nbins = std::max(static_cast<uint64_t>(100u),
                            static_cast<uint64_t>((max - min) / 20000));
  TH1F hist("", "", nbins, min, max);
  hist.SetTitle(";#Delta bytes; Count");
  for (uint64_t i = 0; i < diffs.size(); ++i) {
    hist.Fill(diffs[i]);
  }
  hist.Draw();

  c.Update();
  gPad->SetLogy();
  gPad->Modified();
  gPad->Update();
  c.Modified();
  c.cd(0);
  auto steps = Simulation::GetActive()->GetScheduler()->GetSimulatedSteps();
  auto dir = Simulation::GetActive()->GetOutputDir();
  std::string suffix = "-end";
  if (before) {
    suffix = "-begin";
  }
  c.SaveAs(
      Concat(dir, "/mem-layout-neighbor-hist-", steps, suffix, ".png").c_str());
  c.SaveAs(
      Concat(dir, "/mem-layout-neighbor-hist-", steps, suffix, ".C").c_str());
}

}  // namespace bdm
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: tustring.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: th $ $Date: 2001-03-16 15:25:57 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#include <string.h>

#ifndef _OSL_INTERLCK_H
#include <osl/interlck.h>
#endif
#ifndef _RTL_ALLOC_H
#include <rtl/alloc.h>
#endif
#ifndef _RTL_MEMORY_H
#include <rtl/memory.h>
#endif
#ifndef _RTL_TENCINFO_H
#include <rtl/tencinfo.h>
#endif

#define private public
#include <string.hxx>
#undef private
#include <impstrg.hxx>

#include <debug.hxx>

// =======================================================================

DBG_NAME( UniString );
DBG_NAMEEX( ByteString );

// -----------------------------------------------------------------------

#define STRCODE         sal_Unicode
#define STRING          UniString
#define STRINGDATA      UniStringData
#define DBGCHECKSTRING  DbgCheckUniString

// -----------------------------------------------------------------------

#include <strimp.cxx>
#include <strucvt.cxx>
#include <strascii.cxx>

// -----------------------------------------------------------------------

UniString UniString::CreateFromInt32( sal_Int32 n, sal_Int16 nRadix )
{
    sal_Unicode aBuf[RTL_USTR_MAX_VALUEOFINT32];
    return UniString( aBuf, rtl_ustr_valueOfInt32( aBuf, n, nRadix ) );
}

// -----------------------------------------------------------------------

UniString UniString::CreateFromInt64( sal_Int64 n, sal_Int16 nRadix )
{
    sal_Unicode aBuf[RTL_USTR_MAX_VALUEOFINT64];
    return UniString( aBuf, rtl_ustr_valueOfInt64( aBuf, n, nRadix ) );
}

// -----------------------------------------------------------------------

UniString UniString::CreateFromFloat( float f )
{
    sal_Unicode aBuf[RTL_USTR_MAX_VALUEOFFLOAT];
    return UniString( aBuf, rtl_ustr_valueOfFloat( aBuf, f ) );
}

// -----------------------------------------------------------------------

UniString UniString::CreateFromDouble( double d )
{
    sal_Unicode aBuf[RTL_USTR_MAX_VALUEOFDOUBLE];
    return UniString( aBuf, rtl_ustr_valueOfDouble( aBuf, d ) );
}

// -----------------------------------------------------------------------

sal_Int32 UniString::ToInt32() const
{
    DBG_CHKTHIS( UniString, DbgCheckUniString );

    return rtl_ustr_toInt32( mpData->maStr, 10 );
}

// -----------------------------------------------------------------------

sal_Int64 UniString::ToInt64() const
{
    DBG_CHKTHIS( UniString, DbgCheckUniString );

    return rtl_ustr_toInt64( mpData->maStr, 10 );
}

// -----------------------------------------------------------------------

float UniString::ToFloat() const
{
    DBG_CHKTHIS( UniString, DbgCheckUniString );

    return rtl_ustr_toFloat( mpData->maStr );
}

// -----------------------------------------------------------------------

double UniString::ToDouble() const
{
    DBG_CHKTHIS( UniString, DbgCheckUniString );

    return rtl_ustr_toDouble( mpData->maStr );
}

<commit_msg>INTEGRATION: CWS sb13 (1.2.210); FILE MERGED 2004/02/06 08:57:17 sb 1.2.210.1: #i19699# Tightened tools/string.hxx so that arithmetic/enumeration type arguments are not silently converted to char/sal_Unicode.<commit_after>/*************************************************************************
 *
 *  $RCSfile: tustring.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: kz $ $Date: 2004-02-26 13:21:30 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#include <string.h>

#ifndef _OSL_INTERLCK_H
#include <osl/interlck.h>
#endif
#ifndef _RTL_ALLOC_H
#include <rtl/alloc.h>
#endif
#ifndef _RTL_MEMORY_H
#include <rtl/memory.h>
#endif
#ifndef _RTL_TENCINFO_H
#include <rtl/tencinfo.h>
#endif

#define private public
#include <string.hxx>
#undef private
#include <impstrg.hxx>

#include <debug.hxx>

// =======================================================================

DBG_NAME( UniString );
DBG_NAMEEX( ByteString );

// -----------------------------------------------------------------------

#define STRCODE         sal_Unicode
#define STRING          UniString
#define STRINGDATA      UniStringData
#define DBGCHECKSTRING  DbgCheckUniString

// -----------------------------------------------------------------------

#include <strimp.cxx>
#include <strucvt.cxx>
#include <strascii.cxx>

UniString::UniString(char c): mpData(ImplAllocData(1)) { mpData->maStr[0] = c; }

// -----------------------------------------------------------------------

UniString UniString::CreateFromInt32( sal_Int32 n, sal_Int16 nRadix )
{
    sal_Unicode aBuf[RTL_USTR_MAX_VALUEOFINT32];
    return UniString( aBuf, rtl_ustr_valueOfInt32( aBuf, n, nRadix ) );
}

// -----------------------------------------------------------------------

UniString UniString::CreateFromInt64( sal_Int64 n, sal_Int16 nRadix )
{
    sal_Unicode aBuf[RTL_USTR_MAX_VALUEOFINT64];
    return UniString( aBuf, rtl_ustr_valueOfInt64( aBuf, n, nRadix ) );
}

// -----------------------------------------------------------------------

UniString UniString::CreateFromFloat( float f )
{
    sal_Unicode aBuf[RTL_USTR_MAX_VALUEOFFLOAT];
    return UniString( aBuf, rtl_ustr_valueOfFloat( aBuf, f ) );
}

// -----------------------------------------------------------------------

UniString UniString::CreateFromDouble( double d )
{
    sal_Unicode aBuf[RTL_USTR_MAX_VALUEOFDOUBLE];
    return UniString( aBuf, rtl_ustr_valueOfDouble( aBuf, d ) );
}

// -----------------------------------------------------------------------

sal_Int32 UniString::ToInt32() const
{
    DBG_CHKTHIS( UniString, DbgCheckUniString );

    return rtl_ustr_toInt32( mpData->maStr, 10 );
}

// -----------------------------------------------------------------------

sal_Int64 UniString::ToInt64() const
{
    DBG_CHKTHIS( UniString, DbgCheckUniString );

    return rtl_ustr_toInt64( mpData->maStr, 10 );
}

// -----------------------------------------------------------------------

float UniString::ToFloat() const
{
    DBG_CHKTHIS( UniString, DbgCheckUniString );

    return rtl_ustr_toFloat( mpData->maStr );
}

// -----------------------------------------------------------------------

double UniString::ToDouble() const
{
    DBG_CHKTHIS( UniString, DbgCheckUniString );

    return rtl_ustr_toDouble( mpData->maStr );
}

<|endoftext|>


<commit_before>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "mitkContourModelSetGLMapper2D.h"

#include "mitkPlaneGeometry.h"
#include "mitkColorProperty.h"
#include "mitkProperties.h"
#include "mitkContourModelSet.h"
#include <vtkLinearTransform.h>

#include "mitkContourModel.h"
#include "mitkBaseRenderer.h"
#include "mitkOverlayManager.h"
#include "mitkTextOverlay2D.h"

#include "mitkGL.h"

mitk::ContourModelGLMapper2DBase::ContourModelGLMapper2DBase()
{
  m_PointNumbersOverlay = mitk::TextOverlay2D::New();
  m_ControlPointNumbersOverlay = mitk::TextOverlay2D::New();

}

mitk::ContourModelGLMapper2DBase::~ContourModelGLMapper2DBase()
{
  RendererListType::const_iterator iter;
  for ( iter=m_RendererList.begin(); iter != m_RendererList.end(); ++iter)
  {
    (*iter)->GetOverlayManager()->RemoveOverlay( m_PointNumbersOverlay.GetPointer() );
    (*iter)->GetOverlayManager()->RemoveOverlay( m_ControlPointNumbersOverlay.GetPointer() );
  }
  m_RendererList.clear();
}

void mitk::ContourModelGLMapper2DBase::DrawContour(mitk::ContourModel* renderingContour, mitk::BaseRenderer* renderer)
{
  if ( std::find( m_RendererList.begin(), m_RendererList.end(), renderer ) == m_RendererList.end() )
  {
    m_RendererList.push_back( renderer );
  }

  renderer->GetOverlayManager()->AddOverlay( m_PointNumbersOverlay.GetPointer(), renderer );
  m_PointNumbersOverlay->SetVisibility( false, renderer );

  renderer->GetOverlayManager()->AddOverlay( m_ControlPointNumbersOverlay.GetPointer(), renderer );
  m_ControlPointNumbersOverlay->SetVisibility( false, renderer );

  InternalDrawContour( renderingContour, renderer );
}

void mitk::ContourModelGLMapper2DBase::InternalDrawContour(mitk::ContourModel* renderingContour, mitk::BaseRenderer* renderer)
{

  if(!renderingContour) return;

  mitk::DataNode* dataNode = this->GetDataNode();

  renderingContour->UpdateOutputInformation();

  unsigned int timestep = renderer->GetTimeStep();

  if ( !renderingContour->IsEmptyTimeStep(timestep) )
  {

    mitk::DisplayGeometry::Pointer displayGeometry = renderer->GetDisplayGeometry();
    assert(displayGeometry.IsNotNull());

    //apply color and opacity read from the PropertyList
    ApplyColorAndOpacityProperties(renderer);

    mitk::ColorProperty::Pointer colorprop = dynamic_cast<mitk::ColorProperty*>(dataNode->GetProperty("contour.color", renderer));
    float opacity = 0.5;
    dataNode->GetFloatProperty("opacity", opacity, renderer);

    if(colorprop)
    {
      //set the color of the contour
      double red = colorprop->GetColor().GetRed();
      double green = colorprop->GetColor().GetGreen();
      double blue = colorprop->GetColor().GetBlue();
      glColor4f(red, green, blue, opacity);
    }

    mitk::ColorProperty::Pointer selectedcolor = dynamic_cast<mitk::ColorProperty*>(dataNode->GetProperty("contour.points.color", renderer));
    if(!selectedcolor)
    {
      selectedcolor = mitk::ColorProperty::New(1.0,0.0,0.1);
    }

    vtkLinearTransform* transform = dataNode->GetVtkTransform();

    //    ContourModel::OutputType point;
    mitk::Point3D point;

    mitk::Point3D p, projected_p;
    float vtkp[3];
    float lineWidth = 3.0;

    bool drawit=false;

    bool isHovering = false;
    dataNode->GetBoolProperty("contour.hovering", isHovering);

    if (isHovering)
        dataNode->GetFloatProperty("contour.hovering.width", lineWidth);
    else
        dataNode->GetFloatProperty("contour.width", lineWidth);

    bool showSegments = false;
    dataNode->GetBoolProperty("contour.segments.show", showSegments);

    bool showControlPoints = false;
    dataNode->GetBoolProperty("contour.controlpoints.show", showControlPoints);

    bool showPoints = false;
    dataNode->GetBoolProperty("contour.points.show", showPoints);

    bool showPointsNumbers = false;
    dataNode->GetBoolProperty("contour.points.text", showPointsNumbers);

    bool showControlPointsNumbers = false;
    dataNode->GetBoolProperty("contour.controlpoints.text", showControlPointsNumbers);

    bool projectmode=false;
    dataNode->GetVisibility(projectmode, renderer, "contour.project-onto-plane");

    mitk::ContourModel::VertexIterator pointsIt = renderingContour->IteratorBegin(timestep);

    Point2D pt2d;       // projected_p in display coordinates
    Point2D lastPt2d;

    int index = 0;

    mitk::ScalarType maxDiff = 0.25;

    while ( pointsIt != renderingContour->IteratorEnd(timestep) )
    {
      lastPt2d = pt2d;

      point = (*pointsIt)->Coordinates;

      itk2vtk(point, vtkp);
      transform->TransformPoint(vtkp, vtkp);
      vtk2itk(vtkp,p);

      displayGeometry->Project(p, projected_p);

      displayGeometry->Map(projected_p, pt2d);
      displayGeometry->WorldToDisplay(pt2d, pt2d);

      Vector3D diff=p-projected_p;
      ScalarType scalardiff = diff.GetNorm();

      //project to plane
      if(projectmode)
      {
        drawit=true;
      }
      else if(scalardiff<maxDiff)//point is close enough to be drawn
      {
        drawit=true;
      }
      else
      {
        drawit = false;
      }

      //draw line
      if(drawit)
      {

         if (showSegments)
         {
            //lastPt2d is not valid in first step
            if( !(pointsIt == renderingContour->IteratorBegin(timestep)) )
            {
              glLineWidth(lineWidth);
              glBegin (GL_LINES);
              glVertex2f(pt2d[0], pt2d[1]);
              glVertex2f(lastPt2d[0], lastPt2d[1]);
              glEnd();
              glLineWidth(1);
            }
         }

        if (showControlPoints)
        {
            //draw ontrol points
            if ((*pointsIt)->IsControlPoint)
            {
              float pointsize = 4;
              Point2D  tmp;

              Vector2D horz,vert;
              horz[1]=0;
              vert[0]=0;
              horz[0]=pointsize;
              vert[1]=pointsize;
              glColor3f(selectedcolor->GetColor().GetRed(), selectedcolor->GetColor().GetBlue(), selectedcolor->GetColor().GetGreen());
              glLineWidth(1);
              //a rectangle around the point with the selected color
              glBegin (GL_LINE_LOOP);
              tmp=pt2d-horz;      glVertex2dv(&tmp[0]);
              tmp=pt2d+vert;      glVertex2dv(&tmp[0]);
              tmp=pt2d+horz;      glVertex2dv(&tmp[0]);
              tmp=pt2d-vert;      glVertex2dv(&tmp[0]);
              glEnd();
              glLineWidth(1);
              //the actual point in the specified color to see the usual color of the point
              glColor3f(colorprop->GetColor().GetRed(),colorprop->GetColor().GetGreen(),colorprop->GetColor().GetBlue());
              glPointSize(1);
              glBegin (GL_POINTS);
              tmp=pt2d;             glVertex2dv(&tmp[0]);
              glEnd ();
            }
        }

        if (showPoints)
        {
          float pointsize = 3;
          Point2D  tmp;

          Vector2D horz,vert;
          horz[1]=0;
          vert[0]=0;
          horz[0]=pointsize;
          vert[1]=pointsize;
          glColor3f(0.0, 0.0, 0.0);
          glLineWidth(1);
          //a rectangle around the point with the selected color
          glBegin (GL_LINE_LOOP);
          tmp=pt2d-horz;      glVertex2dv(&tmp[0]);
          tmp=pt2d+vert;      glVertex2dv(&tmp[0]);
          tmp=pt2d+horz;      glVertex2dv(&tmp[0]);
          tmp=pt2d-vert;      glVertex2dv(&tmp[0]);
          glEnd();
          glLineWidth(1);
          //the actual point in the specified color to see the usual color of the point
          glColor3f(colorprop->GetColor().GetRed(),colorprop->GetColor().GetGreen(),colorprop->GetColor().GetBlue());
          glPointSize(1);
          glBegin (GL_POINTS);
          tmp=pt2d;             glVertex2dv(&tmp[0]);
          glEnd ();
        }

        if (showPointsNumbers)
        {
            std::string l;
            std::stringstream ss;
            ss << index;
            l.append(ss.str());

            float rgb[3];
            rgb[0] = 0.0; rgb[1] = 0.0; rgb[2] = 0.0;

            WriteTextWithOverlay( m_PointNumbersOverlay, l.c_str(), rgb, pt2d, renderer );
        }

        if (showControlPointsNumbers && (*pointsIt)->IsControlPoint)
        {
            std::string l;
            std::stringstream ss;
            ss << index;
            l.append(ss.str());

            float rgb[3];
            rgb[0] = 1.0; rgb[1] = 1.0; rgb[2] = 0.0;

            WriteTextWithOverlay( m_ControlPointNumbersOverlay, l.c_str(), rgb, pt2d, renderer );
        }

        index++;
      }

      pointsIt++;
    }//end while iterate over controlpoints

    //close contour if necessary
    if(renderingContour->IsClosed(timestep) && drawit && showSegments)
    {
      lastPt2d = pt2d;
      point = renderingContour->GetVertexAt(0,timestep)->Coordinates;
      itk2vtk(point, vtkp);
      transform->TransformPoint(vtkp, vtkp);
      vtk2itk(vtkp,p);
      displayGeometry->Project(p, projected_p);
      displayGeometry->Map(projected_p, pt2d);
      displayGeometry->WorldToDisplay(pt2d, pt2d);

      glLineWidth(lineWidth);
      glBegin (GL_LINES);
      glVertex2f(lastPt2d[0], lastPt2d[1]);
      glVertex2f( pt2d[0], pt2d[1] );
      glEnd();
      glLineWidth(1);
    }

    //draw selected vertex if exists
    if(renderingContour->GetSelectedVertex())
    {
      //transform selected vertex
      point = renderingContour->GetSelectedVertex()->Coordinates;

      itk2vtk(point, vtkp);
      transform->TransformPoint(vtkp, vtkp);
      vtk2itk(vtkp,p);

      displayGeometry->Project(p, projected_p);

      displayGeometry->Map(projected_p, pt2d);
      displayGeometry->WorldToDisplay(pt2d, pt2d);

      Vector3D diff=p-projected_p;
      ScalarType scalardiff = diff.GetNorm();
      //----------------------------------

      //draw point if close to plane
      if(scalardiff<maxDiff)
      {

        float pointsize = 5;
        Point2D  tmp;
        glColor3f(0.0, 1.0, 0.0);
        glLineWidth(1);
        //a diamond around the point
        glBegin (GL_LINE_LOOP);
        //begin from upper left corner and paint clockwise
        tmp[0]=pt2d[0]-pointsize;    tmp[1]=pt2d[1]+pointsize;    glVertex2dv(&tmp[0]);
        tmp[0]=pt2d[0]+pointsize;    tmp[1]=pt2d[1]+pointsize;    glVertex2dv(&tmp[0]);
        tmp[0]=pt2d[0]+pointsize;    tmp[1]=pt2d[1]-pointsize;    glVertex2dv(&tmp[0]);
        tmp[0]=pt2d[0]-pointsize;    tmp[1]=pt2d[1]-pointsize;    glVertex2dv(&tmp[0]);
        glEnd ();
      }
      //------------------------------------
    }
  }
}

void mitk::ContourModelGLMapper2DBase::WriteTextWithOverlay( TextOverlayPointerType textOverlay,
                                                             const char* text,
                                                             float rgb[3],
                                                             Point2D pt2d,
                                                             mitk::BaseRenderer* renderer )
{

  textOverlay->SetText( text );
  textOverlay->SetColor( rgb );
  textOverlay->SetOpacity( 1 );
  textOverlay->SetFontSize( 16 );
  textOverlay->SetBoolProperty( "drawShadow", false );
  textOverlay->SetVisibility( true, renderer );

}
<commit_msg>commented code that causes crashes when closing the application<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "mitkContourModelSetGLMapper2D.h"

#include "mitkPlaneGeometry.h"
#include "mitkColorProperty.h"
#include "mitkProperties.h"
#include "mitkContourModelSet.h"
#include <vtkLinearTransform.h>

#include "mitkContourModel.h"
#include "mitkBaseRenderer.h"
#include "mitkOverlayManager.h"
#include "mitkTextOverlay2D.h"

#include "mitkGL.h"

mitk::ContourModelGLMapper2DBase::ContourModelGLMapper2DBase()
{
  m_PointNumbersOverlay = mitk::TextOverlay2D::New();
  m_ControlPointNumbersOverlay = mitk::TextOverlay2D::New();

}

mitk::ContourModelGLMapper2DBase::~ContourModelGLMapper2DBase()
{
//   RendererListType::const_iterator iter;
//   for ( iter=m_RendererList.begin(); iter != m_RendererList.end(); ++iter)
//   {
//     (*iter)->GetOverlayManager()->RemoveOverlay( m_PointNumbersOverlay.GetPointer() );
//     (*iter)->GetOverlayManager()->RemoveOverlay( m_ControlPointNumbersOverlay.GetPointer() );
//   }
//   m_RendererList.clear();
}

void mitk::ContourModelGLMapper2DBase::DrawContour(mitk::ContourModel* renderingContour, mitk::BaseRenderer* renderer)
{
  if ( std::find( m_RendererList.begin(), m_RendererList.end(), renderer ) == m_RendererList.end() )
  {
    m_RendererList.push_back( renderer );
  }

  renderer->GetOverlayManager()->AddOverlay( m_PointNumbersOverlay.GetPointer(), renderer );
  m_PointNumbersOverlay->SetVisibility( false, renderer );

  renderer->GetOverlayManager()->AddOverlay( m_ControlPointNumbersOverlay.GetPointer(), renderer );
  m_ControlPointNumbersOverlay->SetVisibility( false, renderer );

  InternalDrawContour( renderingContour, renderer );
}

void mitk::ContourModelGLMapper2DBase::InternalDrawContour(mitk::ContourModel* renderingContour, mitk::BaseRenderer* renderer)
{

  if(!renderingContour) return;

  mitk::DataNode* dataNode = this->GetDataNode();

  renderingContour->UpdateOutputInformation();

  unsigned int timestep = renderer->GetTimeStep();

  if ( !renderingContour->IsEmptyTimeStep(timestep) )
  {

    mitk::DisplayGeometry::Pointer displayGeometry = renderer->GetDisplayGeometry();
    assert(displayGeometry.IsNotNull());

    //apply color and opacity read from the PropertyList
    ApplyColorAndOpacityProperties(renderer);

    mitk::ColorProperty::Pointer colorprop = dynamic_cast<mitk::ColorProperty*>(dataNode->GetProperty("contour.color", renderer));
    float opacity = 0.5;
    dataNode->GetFloatProperty("opacity", opacity, renderer);

    if(colorprop)
    {
      //set the color of the contour
      double red = colorprop->GetColor().GetRed();
      double green = colorprop->GetColor().GetGreen();
      double blue = colorprop->GetColor().GetBlue();
      glColor4f(red, green, blue, opacity);
    }

    mitk::ColorProperty::Pointer selectedcolor = dynamic_cast<mitk::ColorProperty*>(dataNode->GetProperty("contour.points.color", renderer));
    if(!selectedcolor)
    {
      selectedcolor = mitk::ColorProperty::New(1.0,0.0,0.1);
    }

    vtkLinearTransform* transform = dataNode->GetVtkTransform();

    //    ContourModel::OutputType point;
    mitk::Point3D point;

    mitk::Point3D p, projected_p;
    float vtkp[3];
    float lineWidth = 3.0;

    bool drawit=false;

    bool isHovering = false;
    dataNode->GetBoolProperty("contour.hovering", isHovering);

    if (isHovering)
        dataNode->GetFloatProperty("contour.hovering.width", lineWidth);
    else
        dataNode->GetFloatProperty("contour.width", lineWidth);

    bool showSegments = false;
    dataNode->GetBoolProperty("contour.segments.show", showSegments);

    bool showControlPoints = false;
    dataNode->GetBoolProperty("contour.controlpoints.show", showControlPoints);

    bool showPoints = false;
    dataNode->GetBoolProperty("contour.points.show", showPoints);

    bool showPointsNumbers = false;
    dataNode->GetBoolProperty("contour.points.text", showPointsNumbers);

    bool showControlPointsNumbers = false;
    dataNode->GetBoolProperty("contour.controlpoints.text", showControlPointsNumbers);

    bool projectmode=false;
    dataNode->GetVisibility(projectmode, renderer, "contour.project-onto-plane");

    mitk::ContourModel::VertexIterator pointsIt = renderingContour->IteratorBegin(timestep);

    Point2D pt2d;       // projected_p in display coordinates
    Point2D lastPt2d;

    int index = 0;

    mitk::ScalarType maxDiff = 0.25;

    while ( pointsIt != renderingContour->IteratorEnd(timestep) )
    {
      lastPt2d = pt2d;

      point = (*pointsIt)->Coordinates;

      itk2vtk(point, vtkp);
      transform->TransformPoint(vtkp, vtkp);
      vtk2itk(vtkp,p);

      displayGeometry->Project(p, projected_p);

      displayGeometry->Map(projected_p, pt2d);
      displayGeometry->WorldToDisplay(pt2d, pt2d);

      Vector3D diff=p-projected_p;
      ScalarType scalardiff = diff.GetNorm();

      //project to plane
      if(projectmode)
      {
        drawit=true;
      }
      else if(scalardiff<maxDiff)//point is close enough to be drawn
      {
        drawit=true;
      }
      else
      {
        drawit = false;
      }

      //draw line
      if(drawit)
      {

         if (showSegments)
         {
            //lastPt2d is not valid in first step
            if( !(pointsIt == renderingContour->IteratorBegin(timestep)) )
            {
              glLineWidth(lineWidth);
              glBegin (GL_LINES);
              glVertex2f(pt2d[0], pt2d[1]);
              glVertex2f(lastPt2d[0], lastPt2d[1]);
              glEnd();
              glLineWidth(1);
            }
         }

        if (showControlPoints)
        {
            //draw ontrol points
            if ((*pointsIt)->IsControlPoint)
            {
              float pointsize = 4;
              Point2D  tmp;

              Vector2D horz,vert;
              horz[1]=0;
              vert[0]=0;
              horz[0]=pointsize;
              vert[1]=pointsize;
              glColor3f(selectedcolor->GetColor().GetRed(), selectedcolor->GetColor().GetBlue(), selectedcolor->GetColor().GetGreen());
              glLineWidth(1);
              //a rectangle around the point with the selected color
              glBegin (GL_LINE_LOOP);
              tmp=pt2d-horz;      glVertex2dv(&tmp[0]);
              tmp=pt2d+vert;      glVertex2dv(&tmp[0]);
              tmp=pt2d+horz;      glVertex2dv(&tmp[0]);
              tmp=pt2d-vert;      glVertex2dv(&tmp[0]);
              glEnd();
              glLineWidth(1);
              //the actual point in the specified color to see the usual color of the point
              glColor3f(colorprop->GetColor().GetRed(),colorprop->GetColor().GetGreen(),colorprop->GetColor().GetBlue());
              glPointSize(1);
              glBegin (GL_POINTS);
              tmp=pt2d;             glVertex2dv(&tmp[0]);
              glEnd ();
            }
        }

        if (showPoints)
        {
          float pointsize = 3;
          Point2D  tmp;

          Vector2D horz,vert;
          horz[1]=0;
          vert[0]=0;
          horz[0]=pointsize;
          vert[1]=pointsize;
          glColor3f(0.0, 0.0, 0.0);
          glLineWidth(1);
          //a rectangle around the point with the selected color
          glBegin (GL_LINE_LOOP);
          tmp=pt2d-horz;      glVertex2dv(&tmp[0]);
          tmp=pt2d+vert;      glVertex2dv(&tmp[0]);
          tmp=pt2d+horz;      glVertex2dv(&tmp[0]);
          tmp=pt2d-vert;      glVertex2dv(&tmp[0]);
          glEnd();
          glLineWidth(1);
          //the actual point in the specified color to see the usual color of the point
          glColor3f(colorprop->GetColor().GetRed(),colorprop->GetColor().GetGreen(),colorprop->GetColor().GetBlue());
          glPointSize(1);
          glBegin (GL_POINTS);
          tmp=pt2d;             glVertex2dv(&tmp[0]);
          glEnd ();
        }

        if (showPointsNumbers)
        {
            std::string l;
            std::stringstream ss;
            ss << index;
            l.append(ss.str());

            float rgb[3];
            rgb[0] = 0.0; rgb[1] = 0.0; rgb[2] = 0.0;

            WriteTextWithOverlay( m_PointNumbersOverlay, l.c_str(), rgb, pt2d, renderer );
        }

        if (showControlPointsNumbers && (*pointsIt)->IsControlPoint)
        {
            std::string l;
            std::stringstream ss;
            ss << index;
            l.append(ss.str());

            float rgb[3];
            rgb[0] = 1.0; rgb[1] = 1.0; rgb[2] = 0.0;

            WriteTextWithOverlay( m_ControlPointNumbersOverlay, l.c_str(), rgb, pt2d, renderer );
        }

        index++;
      }

      pointsIt++;
    }//end while iterate over controlpoints

    //close contour if necessary
    if(renderingContour->IsClosed(timestep) && drawit && showSegments)
    {
      lastPt2d = pt2d;
      point = renderingContour->GetVertexAt(0,timestep)->Coordinates;
      itk2vtk(point, vtkp);
      transform->TransformPoint(vtkp, vtkp);
      vtk2itk(vtkp,p);
      displayGeometry->Project(p, projected_p);
      displayGeometry->Map(projected_p, pt2d);
      displayGeometry->WorldToDisplay(pt2d, pt2d);

      glLineWidth(lineWidth);
      glBegin (GL_LINES);
      glVertex2f(lastPt2d[0], lastPt2d[1]);
      glVertex2f( pt2d[0], pt2d[1] );
      glEnd();
      glLineWidth(1);
    }

    //draw selected vertex if exists
    if(renderingContour->GetSelectedVertex())
    {
      //transform selected vertex
      point = renderingContour->GetSelectedVertex()->Coordinates;

      itk2vtk(point, vtkp);
      transform->TransformPoint(vtkp, vtkp);
      vtk2itk(vtkp,p);

      displayGeometry->Project(p, projected_p);

      displayGeometry->Map(projected_p, pt2d);
      displayGeometry->WorldToDisplay(pt2d, pt2d);

      Vector3D diff=p-projected_p;
      ScalarType scalardiff = diff.GetNorm();
      //----------------------------------

      //draw point if close to plane
      if(scalardiff<maxDiff)
      {

        float pointsize = 5;
        Point2D  tmp;
        glColor3f(0.0, 1.0, 0.0);
        glLineWidth(1);
        //a diamond around the point
        glBegin (GL_LINE_LOOP);
        //begin from upper left corner and paint clockwise
        tmp[0]=pt2d[0]-pointsize;    tmp[1]=pt2d[1]+pointsize;    glVertex2dv(&tmp[0]);
        tmp[0]=pt2d[0]+pointsize;    tmp[1]=pt2d[1]+pointsize;    glVertex2dv(&tmp[0]);
        tmp[0]=pt2d[0]+pointsize;    tmp[1]=pt2d[1]-pointsize;    glVertex2dv(&tmp[0]);
        tmp[0]=pt2d[0]-pointsize;    tmp[1]=pt2d[1]-pointsize;    glVertex2dv(&tmp[0]);
        glEnd ();
      }
      //------------------------------------
    }
  }
}

void mitk::ContourModelGLMapper2DBase::WriteTextWithOverlay( TextOverlayPointerType textOverlay,
                                                             const char* text,
                                                             float rgb[3],
                                                             Point2D pt2d,
                                                             mitk::BaseRenderer* renderer )
{

  textOverlay->SetText( text );
  textOverlay->SetColor( rgb );
  textOverlay->SetOpacity( 1 );
  textOverlay->SetFontSize( 16 );
  textOverlay->SetBoolProperty( "drawShadow", false );
  textOverlay->SetVisibility( true, renderer );

}
<|endoftext|>


<commit_before>// Copyright (c) 2009 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/browser/net/websocket_experiment/websocket_experiment_runner.h"

#include "base/compiler_specific.h"
#include "base/histogram.h"
#include "base/message_loop.h"
#include "base/task.h"
#include "chrome/browser/chrome_thread.h"
#include "net/base/net_errors.h"

namespace chrome_browser_net_websocket_experiment {

static const char *kExperimentHost = "websocket-experiment.chromium.org";
static const int kAlternativePort = 61985;

static const int kUrlFetchDeadlineSec = 10;
static const int kWebSocketConnectDeadlineSec = 10;
static const int kWebSocketEchoDeadlineSec = 5;
static const int kWebSocketIdleSec = 1;
static const int kWebSocketPushDeadlineSec = 1;
static const int kWebSocketByeDeadlineSec = 10;
static const int kWebSocketCloseDeadlineSec = 5;
static const int kWebSocketTimeSec = 10;
static const int kTimeBucketCount = 50;

// TODO(ukai): Use new thread-safe-reference-counted Histograms.
#define UPDATE_HISTOGRAM(name, sample, min, max, bucket_count) do { \
    switch (task_state_) {                                          \
      case STATE_RUN_WS:                                            \
        {                                                           \
          static LinearHistogram counter(                               \
              "WebSocketExperiment.Basic." name, min, max, bucket_count); \
          counter.SetFlags(kUmaTargetedHistogramFlag);                  \
          counter.Add(sample);                                          \
        }                                                               \
        break;                                                          \
      case STATE_RUN_WSS:                                               \
        {                                                               \
          static LinearHistogram counter(                               \
              "WebSocketExperiment.Secure." name, min, max, bucket_count); \
          counter.SetFlags(kUmaTargetedHistogramFlag);                  \
          counter.Add(sample);                                          \
        }                                                               \
        break;                                                          \
      case STATE_RUN_WS_NODEFAULT_PORT:                                 \
        {                                                               \
          static LinearHistogram counter(                               \
              "WebSocketExperiment.NoDefaultPort." name,                \
              min, max, bucket_count);                                  \
          counter.SetFlags(kUmaTargetedHistogramFlag);                  \
          counter.Add(sample);                                          \
        }                                                               \
        break;                                                          \
      default:                                                          \
        NOTREACHED();                                                   \
        break;                                                          \
    }                                                                   \
  } while (0)

#define UPDATE_HISTOGRAM_TIMES(name, sample, min, max, bucket_count) do {    \
    switch (task_state_) {                                              \
      case STATE_RUN_WS:                                                \
        {                                                               \
          static Histogram counter(                                     \
              "WebSocketExperiment.Basic." name, min, max, bucket_count); \
          counter.SetFlags(kUmaTargetedHistogramFlag);                  \
          counter.AddTime(sample);                                      \
        }                                                               \
        break;                                                          \
      case STATE_RUN_WSS:                                               \
        {                                                               \
          static Histogram counter(                                     \
              "WebSocketExperiment.Secure." name, min, max, bucket_count); \
          counter.SetFlags(kUmaTargetedHistogramFlag);                  \
          counter.AddTime(sample);                                      \
        }                                                               \
        break;                                                          \
      case STATE_RUN_WS_NODEFAULT_PORT:                                 \
        {                                                               \
          static Histogram counter(                                     \
              "WebSocketExperiment.NoDefaultPort." name,                \
              min, max, bucket_count);                                  \
          counter.SetFlags(kUmaTargetedHistogramFlag);                  \
          counter.AddTime(sample);                                      \
        }                                                               \
        break;                                                          \
      default:                                                          \
        NOTREACHED();                                                   \
        break;                                                          \
    }                                                                   \
  } while (0);

// Hold reference while experiment is running.
static scoped_refptr<WebSocketExperimentRunner> runner;

/* static */
void WebSocketExperimentRunner::Start() {
  DCHECK(!runner.get());
  runner = new WebSocketExperimentRunner;
  runner->Run();
}

/* static */
void WebSocketExperimentRunner::Stop() {
  if (runner.get())
    runner->Cancel();
  runner = NULL;
}

WebSocketExperimentRunner::WebSocketExperimentRunner()
    : next_state_(STATE_NONE),
      task_state_(STATE_NONE),
      ALLOW_THIS_IN_INITIALIZER_LIST(
          task_callback_(this, &WebSocketExperimentRunner::OnTaskCompleted)) {
  InitConfig();
}

WebSocketExperimentRunner::~WebSocketExperimentRunner() {
  DCHECK(!task_.get());
}

void WebSocketExperimentRunner::Run() {
  DCHECK_EQ(next_state_, STATE_NONE);
  next_state_ = STATE_RUN_WS;
  ChromeThread::PostDelayedTask(
      ChromeThread::IO,
      FROM_HERE,
      NewRunnableMethod(this, &WebSocketExperimentRunner::DoLoop),
      config_.initial_delay_ms);
}

void WebSocketExperimentRunner::Cancel() {
  next_state_ = STATE_NONE;
  ChromeThread::PostTask(
      ChromeThread::IO,
      FROM_HERE,
      NewRunnableMethod(this, &WebSocketExperimentRunner::DoLoop));
}

void WebSocketExperimentRunner::InitConfig() {
  config_.initial_delay_ms = 5 * 60 * 1000;  // 5 mins
  config_.next_delay_ms = 12 * 60 * 60 * 1000;  // 12 hours

  WebSocketExperimentTask::Config task_config;
  task_config.ws_protocol = "google-websocket-liveexperiment";
  task_config.ws_origin = "http://dev.chromium.org/";
  task_config.url_fetch_deadline_ms = kUrlFetchDeadlineSec * 1000;
  task_config.websocket_onopen_deadline_ms =
      kWebSocketConnectDeadlineSec * 1000;
  task_config.websocket_hello_message = "Hello";
  task_config.websocket_hello_echoback_deadline_ms =
      kWebSocketEchoDeadlineSec * 1000;
  // Note: wait 1.5 sec in websocket_experiment_def.txt
  task_config.websocket_idle_ms = kWebSocketIdleSec * 1000;
  task_config.websocket_receive_push_message_deadline_ms =
      kWebSocketPushDeadlineSec * 1000;
  task_config.websocket_bye_message = "Bye";
  task_config.websocket_bye_deadline_ms =
      kWebSocketByeDeadlineSec * 1000;
  task_config.websocket_close_deadline_ms =
      kWebSocketCloseDeadlineSec * 1000;

  config_.ws_config = task_config;
  config_.ws_config.url =
      GURL(StringPrintf("ws://%s/live_exp", kExperimentHost));
  config_.ws_config.ws_location =
      StringPrintf("ws://%s/live_exp", kExperimentHost);
  config_.ws_config.http_url =
      GURL(StringPrintf("http://%s/", kExperimentHost));

  config_.wss_config = task_config;
  config_.wss_config.url =
      GURL(StringPrintf("wss://%s/live_exp", kExperimentHost));
  config_.wss_config.ws_location =
      StringPrintf("wss://%s/live_exp", kExperimentHost);
  config_.wss_config.http_url =
      GURL(StringPrintf("https://%s/", kExperimentHost));

  config_.ws_nondefault_config = task_config;
  config_.ws_nondefault_config.url =
      GURL(StringPrintf("ws://%s:%d/live_exp",
                        kExperimentHost, kAlternativePort));
  config_.ws_nondefault_config.ws_location =
      StringPrintf("ws://%s:%d/live_exp",
                   kExperimentHost, kAlternativePort);
  config_.ws_nondefault_config.http_url =
      GURL(StringPrintf("http://%s:%d/",
                        kExperimentHost, kAlternativePort));
}

void WebSocketExperimentRunner::DoLoop() {
  if (next_state_ == STATE_NONE) {
    if (task_.get()) {
      AddRef();  // Release in OnTaskCompleted.
      task_->Cancel();
    }
    return;
  }

  State state = next_state_;
  task_state_ = STATE_NONE;
  next_state_ = STATE_NONE;

  switch (state) {
    case STATE_IDLE:
      task_.reset();
      next_state_ = STATE_RUN_WS;
      ChromeThread::PostDelayedTask(
          ChromeThread::IO,
          FROM_HERE,
          NewRunnableMethod(this, &WebSocketExperimentRunner::DoLoop),
          config_.next_delay_ms);
      break;
    case STATE_RUN_WS:
      task_.reset(new WebSocketExperimentTask(config_.ws_config,
                                              &task_callback_));
      task_state_ = STATE_RUN_WS;
      next_state_ = STATE_RUN_WSS;
      break;
    case STATE_RUN_WSS:
      task_.reset(new WebSocketExperimentTask(config_.wss_config,
                                              &task_callback_));
      task_state_ = STATE_RUN_WSS;
      next_state_ = STATE_RUN_WS_NODEFAULT_PORT;
      break;
    case STATE_RUN_WS_NODEFAULT_PORT:
      task_.reset(new WebSocketExperimentTask(config_.ws_nondefault_config,
                                              &task_callback_));
      task_state_ = STATE_RUN_WS_NODEFAULT_PORT;
      next_state_ = STATE_IDLE;
      break;
    default:
      NOTREACHED();
      break;
  }
  if (task_.get())
    task_->Run();
}

void WebSocketExperimentRunner::OnTaskCompleted(int result) {
  if (result == net::ERR_ABORTED) {
    task_.reset();
    // Task is Canceled.
    DLOG(INFO) << "WebSocketExperiment Task is canceled.";
    Release();
    return;
  }
  UpdateTaskResultHistogram(task_.get());
  task_.reset();

  DoLoop();
}

void WebSocketExperimentRunner::UpdateTaskResultHistogram(
    const WebSocketExperimentTask* task) {
  DCHECK(task);
  const WebSocketExperimentTask::Result& task_result = task->result();

  UPDATE_HISTOGRAM("LastState", task_result.last_state,
                   1, WebSocketExperimentTask::NUM_STATES,
                   WebSocketExperimentTask::NUM_STATES + 1);

  UPDATE_HISTOGRAM_TIMES("UrlFetch", task_result.url_fetch,
                         base::TimeDelta::FromMilliseconds(1),
                         base::TimeDelta::FromSeconds(kUrlFetchDeadlineSec),
                         kTimeBucketCount);

  if (task_result.last_state <
      WebSocketExperimentTask::STATE_WEBSOCKET_CONNECT_COMPLETE)
    return;

  UPDATE_HISTOGRAM_TIMES("WebSocketConnect", task_result.websocket_connect,
                         base::TimeDelta::FromMilliseconds(1),
                         base::TimeDelta::FromSeconds(
                             kWebSocketConnectDeadlineSec),
                         kTimeBucketCount);

  if (task_result.last_state <
      WebSocketExperimentTask::STATE_WEBSOCKET_RECV_HELLO)
    return;

  UPDATE_HISTOGRAM_TIMES("WebSocketEcho", task_result.websocket_echo,
                         base::TimeDelta::FromMilliseconds(1),
                         base::TimeDelta::FromSeconds(
                             kWebSocketEchoDeadlineSec),
                         kTimeBucketCount);

  if (task_result.last_state <
      WebSocketExperimentTask::STATE_WEBSOCKET_KEEP_IDLE)
    return;

  UPDATE_HISTOGRAM_TIMES("WebSocketIdle", task_result.websocket_idle,
                         base::TimeDelta::FromMilliseconds(1),
                         base::TimeDelta::FromSeconds(
                             kWebSocketIdleSec + kWebSocketPushDeadlineSec),
                         kTimeBucketCount);

  if (task_result.last_state <
      WebSocketExperimentTask::STATE_WEBSOCKET_CLOSE_COMPLETE)
    return;

  UPDATE_HISTOGRAM_TIMES("WebSocketTotal", task_result.websocket_total,
                         base::TimeDelta::FromMilliseconds(1),
                         base::TimeDelta::FromSeconds(kWebSocketTimeSec),
                         kTimeBucketCount);
}

}  // namespace chrome_browser_net_websocket_experiment
<commit_msg>Throttle websocket live experiment<commit_after>// Copyright (c) 2009 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/browser/net/websocket_experiment/websocket_experiment_runner.h"

#include "base/compiler_specific.h"
#include "base/field_trial.h"
#include "base/histogram.h"
#include "base/message_loop.h"
#include "base/task.h"
#include "chrome/browser/chrome_thread.h"
#include "net/base/net_errors.h"

namespace chrome_browser_net_websocket_experiment {

static const char *kExperimentHost = "websocket-experiment.chromium.org";
static const int kAlternativePort = 61985;

static const int kUrlFetchDeadlineSec = 10;
static const int kWebSocketConnectDeadlineSec = 10;
static const int kWebSocketEchoDeadlineSec = 5;
static const int kWebSocketIdleSec = 1;
static const int kWebSocketPushDeadlineSec = 1;
static const int kWebSocketByeDeadlineSec = 10;
static const int kWebSocketCloseDeadlineSec = 5;
static const int kWebSocketTimeSec = 10;
static const int kTimeBucketCount = 50;

// TODO(ukai): Use new thread-safe-reference-counted Histograms.
#define UPDATE_HISTOGRAM(name, sample, min, max, bucket_count) do { \
    switch (task_state_) {                                          \
      case STATE_RUN_WS:                                            \
        {                                                           \
          static LinearHistogram counter(                               \
              "WebSocketExperiment.Basic." name, min, max, bucket_count); \
          counter.SetFlags(kUmaTargetedHistogramFlag);                  \
          counter.Add(sample);                                          \
        }                                                               \
        break;                                                          \
      case STATE_RUN_WSS:                                               \
        {                                                               \
          static LinearHistogram counter(                               \
              "WebSocketExperiment.Secure." name, min, max, bucket_count); \
          counter.SetFlags(kUmaTargetedHistogramFlag);                  \
          counter.Add(sample);                                          \
        }                                                               \
        break;                                                          \
      case STATE_RUN_WS_NODEFAULT_PORT:                                 \
        {                                                               \
          static LinearHistogram counter(                               \
              "WebSocketExperiment.NoDefaultPort." name,                \
              min, max, bucket_count);                                  \
          counter.SetFlags(kUmaTargetedHistogramFlag);                  \
          counter.Add(sample);                                          \
        }                                                               \
        break;                                                          \
      default:                                                          \
        NOTREACHED();                                                   \
        break;                                                          \
    }                                                                   \
  } while (0)

#define UPDATE_HISTOGRAM_TIMES(name, sample, min, max, bucket_count) do {    \
    switch (task_state_) {                                              \
      case STATE_RUN_WS:                                                \
        {                                                               \
          static Histogram counter(                                     \
              "WebSocketExperiment.Basic." name, min, max, bucket_count); \
          counter.SetFlags(kUmaTargetedHistogramFlag);                  \
          counter.AddTime(sample);                                      \
        }                                                               \
        break;                                                          \
      case STATE_RUN_WSS:                                               \
        {                                                               \
          static Histogram counter(                                     \
              "WebSocketExperiment.Secure." name, min, max, bucket_count); \
          counter.SetFlags(kUmaTargetedHistogramFlag);                  \
          counter.AddTime(sample);                                      \
        }                                                               \
        break;                                                          \
      case STATE_RUN_WS_NODEFAULT_PORT:                                 \
        {                                                               \
          static Histogram counter(                                     \
              "WebSocketExperiment.NoDefaultPort." name,                \
              min, max, bucket_count);                                  \
          counter.SetFlags(kUmaTargetedHistogramFlag);                  \
          counter.AddTime(sample);                                      \
        }                                                               \
        break;                                                          \
      default:                                                          \
        NOTREACHED();                                                   \
        break;                                                          \
    }                                                                   \
  } while (0);

// Hold reference while experiment is running.
static scoped_refptr<WebSocketExperimentRunner> runner;

/* static */
void WebSocketExperimentRunner::Start() {
  DCHECK(!runner.get());

  scoped_refptr<FieldTrial> trial = new FieldTrial("WebSocketExperiment", 1000);
  trial->AppendGroup("_active", 5);  // 0.5% in _active group.

  if (trial->group() == FieldTrial::kNotParticipating)
    return;

  runner = new WebSocketExperimentRunner;
  runner->Run();
}

/* static */
void WebSocketExperimentRunner::Stop() {
  if (runner.get())
    runner->Cancel();
  runner = NULL;
}

WebSocketExperimentRunner::WebSocketExperimentRunner()
    : next_state_(STATE_NONE),
      task_state_(STATE_NONE),
      ALLOW_THIS_IN_INITIALIZER_LIST(
          task_callback_(this, &WebSocketExperimentRunner::OnTaskCompleted)) {
  InitConfig();
}

WebSocketExperimentRunner::~WebSocketExperimentRunner() {
  DCHECK(!task_.get());
}

void WebSocketExperimentRunner::Run() {
  DCHECK_EQ(next_state_, STATE_NONE);
  next_state_ = STATE_RUN_WS;
  ChromeThread::PostDelayedTask(
      ChromeThread::IO,
      FROM_HERE,
      NewRunnableMethod(this, &WebSocketExperimentRunner::DoLoop),
      config_.initial_delay_ms);
}

void WebSocketExperimentRunner::Cancel() {
  next_state_ = STATE_NONE;
  ChromeThread::PostTask(
      ChromeThread::IO,
      FROM_HERE,
      NewRunnableMethod(this, &WebSocketExperimentRunner::DoLoop));
}

void WebSocketExperimentRunner::InitConfig() {
  config_.initial_delay_ms = 5 * 60 * 1000;  // 5 mins
  config_.next_delay_ms = 12 * 60 * 60 * 1000;  // 12 hours

  WebSocketExperimentTask::Config task_config;
  task_config.ws_protocol = "google-websocket-liveexperiment";
  task_config.ws_origin = "http://dev.chromium.org/";
  task_config.url_fetch_deadline_ms = kUrlFetchDeadlineSec * 1000;
  task_config.websocket_onopen_deadline_ms =
      kWebSocketConnectDeadlineSec * 1000;
  task_config.websocket_hello_message = "Hello";
  task_config.websocket_hello_echoback_deadline_ms =
      kWebSocketEchoDeadlineSec * 1000;
  // Note: wait 1.5 sec in websocket_experiment_def.txt
  task_config.websocket_idle_ms = kWebSocketIdleSec * 1000;
  task_config.websocket_receive_push_message_deadline_ms =
      kWebSocketPushDeadlineSec * 1000;
  task_config.websocket_bye_message = "Bye";
  task_config.websocket_bye_deadline_ms =
      kWebSocketByeDeadlineSec * 1000;
  task_config.websocket_close_deadline_ms =
      kWebSocketCloseDeadlineSec * 1000;

  config_.ws_config = task_config;
  config_.ws_config.url =
      GURL(StringPrintf("ws://%s/live_exp", kExperimentHost));
  config_.ws_config.ws_location =
      StringPrintf("ws://%s/live_exp", kExperimentHost);
  config_.ws_config.http_url =
      GURL(StringPrintf("http://%s/", kExperimentHost));

  config_.wss_config = task_config;
  config_.wss_config.url =
      GURL(StringPrintf("wss://%s/live_exp", kExperimentHost));
  config_.wss_config.ws_location =
      StringPrintf("wss://%s/live_exp", kExperimentHost);
  config_.wss_config.http_url =
      GURL(StringPrintf("https://%s/", kExperimentHost));

  config_.ws_nondefault_config = task_config;
  config_.ws_nondefault_config.url =
      GURL(StringPrintf("ws://%s:%d/live_exp",
                        kExperimentHost, kAlternativePort));
  config_.ws_nondefault_config.ws_location =
      StringPrintf("ws://%s:%d/live_exp",
                   kExperimentHost, kAlternativePort);
  config_.ws_nondefault_config.http_url =
      GURL(StringPrintf("http://%s:%d/",
                        kExperimentHost, kAlternativePort));
}

void WebSocketExperimentRunner::DoLoop() {
  if (next_state_ == STATE_NONE) {
    if (task_.get()) {
      AddRef();  // Release in OnTaskCompleted.
      task_->Cancel();
    }
    return;
  }

  State state = next_state_;
  task_state_ = STATE_NONE;
  next_state_ = STATE_NONE;

  switch (state) {
    case STATE_IDLE:
      task_.reset();
      next_state_ = STATE_RUN_WS;
      ChromeThread::PostDelayedTask(
          ChromeThread::IO,
          FROM_HERE,
          NewRunnableMethod(this, &WebSocketExperimentRunner::DoLoop),
          config_.next_delay_ms);
      break;
    case STATE_RUN_WS:
      task_.reset(new WebSocketExperimentTask(config_.ws_config,
                                              &task_callback_));
      task_state_ = STATE_RUN_WS;
      next_state_ = STATE_RUN_WSS;
      break;
    case STATE_RUN_WSS:
      task_.reset(new WebSocketExperimentTask(config_.wss_config,
                                              &task_callback_));
      task_state_ = STATE_RUN_WSS;
      next_state_ = STATE_RUN_WS_NODEFAULT_PORT;
      break;
    case STATE_RUN_WS_NODEFAULT_PORT:
      task_.reset(new WebSocketExperimentTask(config_.ws_nondefault_config,
                                              &task_callback_));
      task_state_ = STATE_RUN_WS_NODEFAULT_PORT;
      next_state_ = STATE_IDLE;
      break;
    default:
      NOTREACHED();
      break;
  }
  if (task_.get())
    task_->Run();
}

void WebSocketExperimentRunner::OnTaskCompleted(int result) {
  if (result == net::ERR_ABORTED) {
    task_.reset();
    // Task is Canceled.
    DLOG(INFO) << "WebSocketExperiment Task is canceled.";
    Release();
    return;
  }
  UpdateTaskResultHistogram(task_.get());
  task_.reset();

  DoLoop();
}

void WebSocketExperimentRunner::UpdateTaskResultHistogram(
    const WebSocketExperimentTask* task) {
  DCHECK(task);
  const WebSocketExperimentTask::Result& task_result = task->result();

  UPDATE_HISTOGRAM("LastState", task_result.last_state,
                   1, WebSocketExperimentTask::NUM_STATES,
                   WebSocketExperimentTask::NUM_STATES + 1);

  UPDATE_HISTOGRAM_TIMES("UrlFetch", task_result.url_fetch,
                         base::TimeDelta::FromMilliseconds(1),
                         base::TimeDelta::FromSeconds(kUrlFetchDeadlineSec),
                         kTimeBucketCount);

  if (task_result.last_state <
      WebSocketExperimentTask::STATE_WEBSOCKET_CONNECT_COMPLETE)
    return;

  UPDATE_HISTOGRAM_TIMES("WebSocketConnect", task_result.websocket_connect,
                         base::TimeDelta::FromMilliseconds(1),
                         base::TimeDelta::FromSeconds(
                             kWebSocketConnectDeadlineSec),
                         kTimeBucketCount);

  if (task_result.last_state <
      WebSocketExperimentTask::STATE_WEBSOCKET_RECV_HELLO)
    return;

  UPDATE_HISTOGRAM_TIMES("WebSocketEcho", task_result.websocket_echo,
                         base::TimeDelta::FromMilliseconds(1),
                         base::TimeDelta::FromSeconds(
                             kWebSocketEchoDeadlineSec),
                         kTimeBucketCount);

  if (task_result.last_state <
      WebSocketExperimentTask::STATE_WEBSOCKET_KEEP_IDLE)
    return;

  UPDATE_HISTOGRAM_TIMES("WebSocketIdle", task_result.websocket_idle,
                         base::TimeDelta::FromMilliseconds(1),
                         base::TimeDelta::FromSeconds(
                             kWebSocketIdleSec + kWebSocketPushDeadlineSec),
                         kTimeBucketCount);

  if (task_result.last_state <
      WebSocketExperimentTask::STATE_WEBSOCKET_CLOSE_COMPLETE)
    return;

  UPDATE_HISTOGRAM_TIMES("WebSocketTotal", task_result.websocket_total,
                         base::TimeDelta::FromMilliseconds(1),
                         base::TimeDelta::FromSeconds(kWebSocketTimeSec),
                         kTimeBucketCount);
}

}  // namespace chrome_browser_net_websocket_experiment
<|endoftext|>


<commit_before>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include "main.h"
#include <Eigen/QR>

template<typename MatrixType> void qr(const MatrixType& m)
{
  typedef typename MatrixType::Index Index;

  Index rows = m.rows();
  Index cols = m.cols();

  typedef typename MatrixType::Scalar Scalar;
  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> MatrixQType;

  MatrixType a = MatrixType::Random(rows,cols);
  HouseholderQR<MatrixType> qrOfA(a);

  MatrixQType q = qrOfA.householderQ();
  VERIFY_IS_UNITARY(q);

  MatrixType r = qrOfA.matrixQR().template triangularView<Upper>();
  VERIFY_IS_APPROX(a, qrOfA.householderQ() * r);
}

template<typename MatrixType, int Cols2> void qr_fixedsize()
{
  enum { Rows = MatrixType::RowsAtCompileTime, Cols = MatrixType::ColsAtCompileTime };
  typedef typename MatrixType::Scalar Scalar;
  Matrix<Scalar,Rows,Cols> m1 = Matrix<Scalar,Rows,Cols>::Random();
  HouseholderQR<Matrix<Scalar,Rows,Cols> > qr(m1);

  Matrix<Scalar,Rows,Cols> r = qr.matrixQR();
  // FIXME need better way to construct trapezoid
  for(int i = 0; i < Rows; i++) for(int j = 0; j < Cols; j++) if(i>j) r(i,j) = Scalar(0);

  VERIFY_IS_APPROX(m1, qr.householderQ() * r);

  Matrix<Scalar,Cols,Cols2> m2 = Matrix<Scalar,Cols,Cols2>::Random(Cols,Cols2);
  Matrix<Scalar,Rows,Cols2> m3 = m1*m2;
  m2 = Matrix<Scalar,Cols,Cols2>::Random(Cols,Cols2);
  m2 = qr.solve(m3);
  VERIFY_IS_APPROX(m3, m1*m2);
}

template<typename MatrixType> void qr_invertible()
{
  using std::log;
  using std::abs;
  typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
  typedef typename MatrixType::Scalar Scalar;

  int size = internal::random<int>(10,50);

  MatrixType m1(size, size), m2(size, size), m3(size, size);
  m1 = MatrixType::Random(size,size);

  if (internal::is_same<RealScalar,float>::value)
  {
    // let's build a matrix more stable to inverse
    MatrixType a = MatrixType::Random(size,size*2);
    m1 += a * a.adjoint();
  }

  HouseholderQR<MatrixType> qr(m1);
  m3 = MatrixType::Random(size,size);
  m2 = qr.solve(m3);
  VERIFY_IS_APPROX(m3, m1*m2);

  // now construct a matrix with prescribed determinant
  m1.setZero();
  for(int i = 0; i < size; i++) m1(i,i) = internal::random<Scalar>();
  RealScalar absdet = abs(m1.diagonal().prod());
  m3 = qr.householderQ(); // get a unitary
  m1 = m3 * m1 * m3;
  qr.compute(m1);
  VERIFY_IS_APPROX(absdet, qr.absDeterminant());
  VERIFY_IS_APPROX(log(absdet), qr.logAbsDeterminant());
}

template<typename MatrixType> void qr_verify_assert()
{
  MatrixType tmp;

  HouseholderQR<MatrixType> qr;
  VERIFY_RAISES_ASSERT(qr.matrixQR())
  VERIFY_RAISES_ASSERT(qr.solve(tmp))
  VERIFY_RAISES_ASSERT(qr.householderQ())
  VERIFY_RAISES_ASSERT(qr.absDeterminant())
  VERIFY_RAISES_ASSERT(qr.logAbsDeterminant())
}

void test_qr()
{
  for(int i = 0; i < g_repeat; i++) {
   CALL_SUBTEST_1( qr(MatrixXf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE),internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
   CALL_SUBTEST_2( qr(MatrixXcd(internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2),internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2))) );
   CALL_SUBTEST_3(( qr_fixedsize<Matrix<float,3,4>, 2 >() ));
   CALL_SUBTEST_4(( qr_fixedsize<Matrix<double,6,2>, 4 >() ));
   CALL_SUBTEST_5(( qr_fixedsize<Matrix<double,2,5>, 7 >() ));
   CALL_SUBTEST_11( qr(Matrix<float,1,1>()) );
  }

  for(int i = 0; i < g_repeat; i++) {
    CALL_SUBTEST_1( qr_invertible<MatrixXf>() );
    CALL_SUBTEST_6( qr_invertible<MatrixXd>() );
    CALL_SUBTEST_7( qr_invertible<MatrixXcf>() );
    CALL_SUBTEST_8( qr_invertible<MatrixXcd>() );
  }

  CALL_SUBTEST_9(qr_verify_assert<Matrix3f>());
  CALL_SUBTEST_10(qr_verify_assert<Matrix3d>());
  CALL_SUBTEST_1(qr_verify_assert<MatrixXf>());
  CALL_SUBTEST_6(qr_verify_assert<MatrixXd>());
  CALL_SUBTEST_7(qr_verify_assert<MatrixXcf>());
  CALL_SUBTEST_8(qr_verify_assert<MatrixXcd>());

  // Test problem size constructors
  CALL_SUBTEST_12(HouseholderQR<MatrixXf>(10, 20));
}
<commit_msg>reduce false negative in the qr unit test<commit_after>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include "main.h"
#include <Eigen/QR>

template<typename MatrixType> void qr(const MatrixType& m)
{
  typedef typename MatrixType::Index Index;

  Index rows = m.rows();
  Index cols = m.cols();

  typedef typename MatrixType::Scalar Scalar;
  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> MatrixQType;

  MatrixType a = MatrixType::Random(rows,cols);
  HouseholderQR<MatrixType> qrOfA(a);

  MatrixQType q = qrOfA.householderQ();
  VERIFY_IS_UNITARY(q);

  MatrixType r = qrOfA.matrixQR().template triangularView<Upper>();
  VERIFY_IS_APPROX(a, qrOfA.householderQ() * r);
}

template<typename MatrixType, int Cols2> void qr_fixedsize()
{
  enum { Rows = MatrixType::RowsAtCompileTime, Cols = MatrixType::ColsAtCompileTime };
  typedef typename MatrixType::Scalar Scalar;
  Matrix<Scalar,Rows,Cols> m1 = Matrix<Scalar,Rows,Cols>::Random();
  HouseholderQR<Matrix<Scalar,Rows,Cols> > qr(m1);

  Matrix<Scalar,Rows,Cols> r = qr.matrixQR();
  // FIXME need better way to construct trapezoid
  for(int i = 0; i < Rows; i++) for(int j = 0; j < Cols; j++) if(i>j) r(i,j) = Scalar(0);

  VERIFY_IS_APPROX(m1, qr.householderQ() * r);

  Matrix<Scalar,Cols,Cols2> m2 = Matrix<Scalar,Cols,Cols2>::Random(Cols,Cols2);
  Matrix<Scalar,Rows,Cols2> m3 = m1*m2;
  m2 = Matrix<Scalar,Cols,Cols2>::Random(Cols,Cols2);
  m2 = qr.solve(m3);
  VERIFY_IS_APPROX(m3, m1*m2);
}

template<typename MatrixType> void qr_invertible()
{
  using std::log;
  using std::abs;
  using std::pow;
  using std::max;
  typedef typename NumTraits<typename MatrixType::Scalar>::Real RealScalar;
  typedef typename MatrixType::Scalar Scalar;

  int size = internal::random<int>(10,50);

  MatrixType m1(size, size), m2(size, size), m3(size, size);
  m1 = MatrixType::Random(size,size);

  if (internal::is_same<RealScalar,float>::value)
  {
    // let's build a matrix more stable to inverse
    MatrixType a = MatrixType::Random(size,size*4);
    m1 += a * a.adjoint();
  }

  HouseholderQR<MatrixType> qr(m1);
  m3 = MatrixType::Random(size,size);
  m2 = qr.solve(m3);
  VERIFY_IS_APPROX(m3, m1*m2);

  // now construct a matrix with prescribed determinant
  m1.setZero();
  for(int i = 0; i < size; i++) m1(i,i) = internal::random<Scalar>();
  RealScalar absdet = abs(m1.diagonal().prod());
  m3 = qr.householderQ(); // get a unitary
  m1 = m3 * m1 * m3;
  qr.compute(m1);
  VERIFY_IS_APPROX(log(absdet), qr.logAbsDeterminant());
  // This test is tricky if the determinant becomes too small.
  // Since we generate random numbers with magnitude rrange [0,1], the average determinant is 0.5^size
  VERIFY_IS_MUCH_SMALLER_THAN( abs(absdet-qr.absDeterminant()), (max)(RealScalar(pow(0.5,size)),(max)(abs(absdet),abs(qr.absDeterminant()))) );

}

template<typename MatrixType> void qr_verify_assert()
{
  MatrixType tmp;

  HouseholderQR<MatrixType> qr;
  VERIFY_RAISES_ASSERT(qr.matrixQR())
  VERIFY_RAISES_ASSERT(qr.solve(tmp))
  VERIFY_RAISES_ASSERT(qr.householderQ())
  VERIFY_RAISES_ASSERT(qr.absDeterminant())
  VERIFY_RAISES_ASSERT(qr.logAbsDeterminant())
}

void test_qr()
{
  for(int i = 0; i < g_repeat; i++) {
   CALL_SUBTEST_1( qr(MatrixXf(internal::random<int>(1,EIGEN_TEST_MAX_SIZE),internal::random<int>(1,EIGEN_TEST_MAX_SIZE))) );
   CALL_SUBTEST_2( qr(MatrixXcd(internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2),internal::random<int>(1,EIGEN_TEST_MAX_SIZE/2))) );
   CALL_SUBTEST_3(( qr_fixedsize<Matrix<float,3,4>, 2 >() ));
   CALL_SUBTEST_4(( qr_fixedsize<Matrix<double,6,2>, 4 >() ));
   CALL_SUBTEST_5(( qr_fixedsize<Matrix<double,2,5>, 7 >() ));
   CALL_SUBTEST_11( qr(Matrix<float,1,1>()) );
  }

  for(int i = 0; i < g_repeat; i++) {
    CALL_SUBTEST_1( qr_invertible<MatrixXf>() );
    CALL_SUBTEST_6( qr_invertible<MatrixXd>() );
    CALL_SUBTEST_7( qr_invertible<MatrixXcf>() );
    CALL_SUBTEST_8( qr_invertible<MatrixXcd>() );
  }

  CALL_SUBTEST_9(qr_verify_assert<Matrix3f>());
  CALL_SUBTEST_10(qr_verify_assert<Matrix3d>());
  CALL_SUBTEST_1(qr_verify_assert<MatrixXf>());
  CALL_SUBTEST_6(qr_verify_assert<MatrixXd>());
  CALL_SUBTEST_7(qr_verify_assert<MatrixXcf>());
  CALL_SUBTEST_8(qr_verify_assert<MatrixXcd>());

  // Test problem size constructors
  CALL_SUBTEST_12(HouseholderQR<MatrixXf>(10, 20));
}
<|endoftext|>


<commit_before>#include "testApp.h"

//--------------------------------------------------------------
void testApp::setup()
{
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_LIGHTING);

    ofBackground(10, 10, 10);

    camera.setDistance(10);
    light.setPosition(10,30,-25);

    objectLoader = new waveFrontLoader();
    objectLoader->loadFile("test.obj");
    mesh = objectLoader->generateMesh();
    delete objectLoader;
}

//--------------------------------------------------------------
void testApp::update()
{

}

//--------------------------------------------------------------
void testApp::draw()
{
    camera.begin();
    light.enable();
    mesh.draw();
    light.disable();
    camera.end();
}
<commit_msg>Update testApp.cpp<commit_after>#include "testApp.h"

//--------------------------------------------------------------
void testApp::setup()
{
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_LIGHTING);

    ofBackground(10, 10, 10);

    camera.setDistance(10);
    light.setPosition(10,30,-25);

    objectLoader = new waveFrontLoader();
    objectLoader->loadMaterial(true); //true or false depending on if a .mtl file exists
    objectLoader->loadFile("test.obj");
    mesh = objectLoader->generateMesh();
    delete objectLoader;
}

//--------------------------------------------------------------
void testApp::update()
{

}

//--------------------------------------------------------------
void testApp::draw()
{
    camera.begin();
    light.enable();
    mesh.draw();
    light.disable();
    camera.end();
}
<|endoftext|>


<commit_before>// Copyright 2014 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 "config.h"
#include "modules/screen_orientation/ScreenOrientationController.h"

#include "core/events/Event.h"
#include "core/frame/FrameView.h"
#include "core/frame/LocalFrame.h"
#include "core/page/Page.h"
#include "modules/screen_orientation/ScreenOrientation.h"
#include "platform/LayoutTestSupport.h"
#include "platform/PlatformScreen.h"
#include "public/platform/WebScreenOrientationClient.h"

namespace blink {

ScreenOrientationController::~ScreenOrientationController()
{
}

void ScreenOrientationController::persistentHostHasBeenDestroyed()
{
    // Unregister lifecycle observation once page is being torn down.
    observeContext(0);
}

void ScreenOrientationController::provideTo(LocalFrame& frame, blink::WebScreenOrientationClient* client)
{
    ASSERT(RuntimeEnabledFeatures::screenOrientationEnabled());

    ScreenOrientationController* controller = new ScreenOrientationController(frame, client);
    WillBeHeapSupplement<LocalFrame>::provideTo(frame, supplementName(), adoptPtrWillBeNoop(controller));
}

ScreenOrientationController* ScreenOrientationController::from(LocalFrame& frame)
{
    return static_cast<ScreenOrientationController*>(WillBeHeapSupplement<LocalFrame>::from(frame, supplementName()));
}

ScreenOrientationController::ScreenOrientationController(LocalFrame& frame, blink::WebScreenOrientationClient* client)
    : PageLifecycleObserver(frame.page())
    , m_client(client)
    , m_frame(frame)
    , m_dispatchEventTimer(this, &ScreenOrientationController::dispatchEventTimerFired)
{
}

const char* ScreenOrientationController::supplementName()
{
    return "ScreenOrientationController";
}

// Compute the screen orientation using the orientation angle and the screen width / height.
blink::WebScreenOrientationType ScreenOrientationController::computeOrientation(FrameView* view)
{
    // Bypass orientation detection in layout tests to get consistent results.
    // FIXME: The screen dimension should be fixed when running the layout tests to avoid such
    // issues.
    if (LayoutTestSupport::isRunningLayoutTest())
        return blink::WebScreenOrientationPortraitPrimary;

    FloatRect rect = screenRect(view);
    uint16_t rotation = screenOrientationAngle(view);
    bool isTallDisplay = rotation % 180 ? rect.height() < rect.width() : rect.height() > rect.width();
    switch (rotation) {
    case 0:
        return isTallDisplay ? blink::WebScreenOrientationPortraitPrimary : blink::WebScreenOrientationLandscapePrimary;
    case 90:
        return isTallDisplay ? blink::WebScreenOrientationLandscapePrimary : blink::WebScreenOrientationPortraitSecondary;
    case 180:
        return isTallDisplay ? blink::WebScreenOrientationPortraitSecondary : blink::WebScreenOrientationLandscapeSecondary;
    case 270:
        return isTallDisplay ? blink::WebScreenOrientationLandscapeSecondary : blink::WebScreenOrientationPortraitPrimary;
    default:
        ASSERT_NOT_REACHED();
        return blink::WebScreenOrientationPortraitPrimary;
    }
}

void ScreenOrientationController::updateOrientation()
{
    ASSERT(m_orientation);

    blink::WebScreenOrientationType orientationType = screenOrientationType(m_frame.view());
    if (orientationType == blink::WebScreenOrientationUndefined) {
        // The embedder could not provide us with an orientation, deduce it ourselves.
        orientationType = computeOrientation(m_frame.view());
    }
    ASSERT(orientationType != blink::WebScreenOrientationUndefined);

    m_orientation->setType(orientationType);
    m_orientation->setAngle(screenOrientationAngle(m_frame.view()));
}

void ScreenOrientationController::pageVisibilityChanged()
{
    if (!m_orientation || !page() || page()->visibilityState() != PageVisibilityStateVisible)
        return;

    // The orientation type and angle are tied in a way that if the angle has
    // changed, the type must have changed.
    unsigned short currentAngle = screenOrientationAngle(m_frame.view());

    // FIXME: sendOrientationChangeEvent() currently send an event all the
    // children of the frame, so it should only be called on the frame on
    // top of the tree. We would need the embedder to call
    // sendOrientationChangeEvent on every WebFrame part of a WebView to be
    // able to remove this.
    if (m_frame == m_frame.localFrameRoot() && m_orientation->angle() != currentAngle)
        notifyOrientationChanged();
}

void ScreenOrientationController::notifyOrientationChanged()
{
    ASSERT(RuntimeEnabledFeatures::screenOrientationEnabled());

    if (!m_orientation || !page() || page()->visibilityState() != PageVisibilityStateVisible)
        return;

    updateOrientation();

    // Keep track of the frames that need to be notified before notifying the
    // current frame as it will prevent side effects from the change event
    // handlers.
    Vector<RefPtr<LocalFrame> > childFrames;
    for (Frame* child = m_frame.tree().firstChild(); child; child = child->tree().nextSibling()) {
        if (child->isLocalFrame())
            childFrames.append(toLocalFrame(child));
    }

    // Notify current orientation object.
    if (!m_dispatchEventTimer.isActive())
        m_dispatchEventTimer.startOneShot(0, FROM_HERE);

    // ... and child frames, if they have a ScreenOrientationController.
    for (size_t i = 0; i < childFrames.size(); ++i) {
        ScreenOrientationController* controller = ScreenOrientationController::from(*childFrames[i]);
        if (controller)
            controller->notifyOrientationChanged();
    }
}

void ScreenOrientationController::setOrientation(ScreenOrientation* orientation)
{
    m_orientation = orientation;
    if (m_orientation)
        updateOrientation();
}

void ScreenOrientationController::lock(blink::WebScreenOrientationLockType orientation, blink::WebLockOrientationCallback* callback)
{
    if (!m_client) {
        return;
    }

    m_client->lockOrientation(orientation, callback);
}

void ScreenOrientationController::unlock()
{
    if (!m_client) {
        return;
    }

    m_client->unlockOrientation();
}

const LocalFrame& ScreenOrientationController::frame() const
{
    return m_frame;
}

void ScreenOrientationController::dispatchEventTimerFired(Timer<ScreenOrientationController>*)
{
    if (!m_orientation)
        return;
    m_orientation->dispatchEvent(Event::create(EventTypeNames::change));
}

void ScreenOrientationController::trace(Visitor* visitor)
{
    visitor->trace(m_orientation);
    WillBeHeapSupplement<LocalFrame>::trace(visitor);
}

} // namespace blink
<commit_msg>ASSERT in ScreenOrientationController::{un,}lock() if no m_client.<commit_after>// Copyright 2014 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 "config.h"
#include "modules/screen_orientation/ScreenOrientationController.h"

#include "core/events/Event.h"
#include "core/frame/FrameView.h"
#include "core/frame/LocalFrame.h"
#include "core/page/Page.h"
#include "modules/screen_orientation/ScreenOrientation.h"
#include "platform/LayoutTestSupport.h"
#include "platform/PlatformScreen.h"
#include "public/platform/WebScreenOrientationClient.h"

namespace blink {

ScreenOrientationController::~ScreenOrientationController()
{
}

void ScreenOrientationController::persistentHostHasBeenDestroyed()
{
    // Unregister lifecycle observation once page is being torn down.
    observeContext(0);
}

void ScreenOrientationController::provideTo(LocalFrame& frame, blink::WebScreenOrientationClient* client)
{
    ASSERT(RuntimeEnabledFeatures::screenOrientationEnabled());

    ScreenOrientationController* controller = new ScreenOrientationController(frame, client);
    WillBeHeapSupplement<LocalFrame>::provideTo(frame, supplementName(), adoptPtrWillBeNoop(controller));
}

ScreenOrientationController* ScreenOrientationController::from(LocalFrame& frame)
{
    return static_cast<ScreenOrientationController*>(WillBeHeapSupplement<LocalFrame>::from(frame, supplementName()));
}

ScreenOrientationController::ScreenOrientationController(LocalFrame& frame, blink::WebScreenOrientationClient* client)
    : PageLifecycleObserver(frame.page())
    , m_client(client)
    , m_frame(frame)
    , m_dispatchEventTimer(this, &ScreenOrientationController::dispatchEventTimerFired)
{
}

const char* ScreenOrientationController::supplementName()
{
    return "ScreenOrientationController";
}

// Compute the screen orientation using the orientation angle and the screen width / height.
blink::WebScreenOrientationType ScreenOrientationController::computeOrientation(FrameView* view)
{
    // Bypass orientation detection in layout tests to get consistent results.
    // FIXME: The screen dimension should be fixed when running the layout tests to avoid such
    // issues.
    if (LayoutTestSupport::isRunningLayoutTest())
        return blink::WebScreenOrientationPortraitPrimary;

    FloatRect rect = screenRect(view);
    uint16_t rotation = screenOrientationAngle(view);
    bool isTallDisplay = rotation % 180 ? rect.height() < rect.width() : rect.height() > rect.width();
    switch (rotation) {
    case 0:
        return isTallDisplay ? blink::WebScreenOrientationPortraitPrimary : blink::WebScreenOrientationLandscapePrimary;
    case 90:
        return isTallDisplay ? blink::WebScreenOrientationLandscapePrimary : blink::WebScreenOrientationPortraitSecondary;
    case 180:
        return isTallDisplay ? blink::WebScreenOrientationPortraitSecondary : blink::WebScreenOrientationLandscapeSecondary;
    case 270:
        return isTallDisplay ? blink::WebScreenOrientationLandscapeSecondary : blink::WebScreenOrientationPortraitPrimary;
    default:
        ASSERT_NOT_REACHED();
        return blink::WebScreenOrientationPortraitPrimary;
    }
}

void ScreenOrientationController::updateOrientation()
{
    ASSERT(m_orientation);

    blink::WebScreenOrientationType orientationType = screenOrientationType(m_frame.view());
    if (orientationType == blink::WebScreenOrientationUndefined) {
        // The embedder could not provide us with an orientation, deduce it ourselves.
        orientationType = computeOrientation(m_frame.view());
    }
    ASSERT(orientationType != blink::WebScreenOrientationUndefined);

    m_orientation->setType(orientationType);
    m_orientation->setAngle(screenOrientationAngle(m_frame.view()));
}

void ScreenOrientationController::pageVisibilityChanged()
{
    if (!m_orientation || !page() || page()->visibilityState() != PageVisibilityStateVisible)
        return;

    // The orientation type and angle are tied in a way that if the angle has
    // changed, the type must have changed.
    unsigned short currentAngle = screenOrientationAngle(m_frame.view());

    // FIXME: sendOrientationChangeEvent() currently send an event all the
    // children of the frame, so it should only be called on the frame on
    // top of the tree. We would need the embedder to call
    // sendOrientationChangeEvent on every WebFrame part of a WebView to be
    // able to remove this.
    if (m_frame == m_frame.localFrameRoot() && m_orientation->angle() != currentAngle)
        notifyOrientationChanged();
}

void ScreenOrientationController::notifyOrientationChanged()
{
    ASSERT(RuntimeEnabledFeatures::screenOrientationEnabled());

    if (!m_orientation || !page() || page()->visibilityState() != PageVisibilityStateVisible)
        return;

    updateOrientation();

    // Keep track of the frames that need to be notified before notifying the
    // current frame as it will prevent side effects from the change event
    // handlers.
    Vector<RefPtr<LocalFrame> > childFrames;
    for (Frame* child = m_frame.tree().firstChild(); child; child = child->tree().nextSibling()) {
        if (child->isLocalFrame())
            childFrames.append(toLocalFrame(child));
    }

    // Notify current orientation object.
    if (!m_dispatchEventTimer.isActive())
        m_dispatchEventTimer.startOneShot(0, FROM_HERE);

    // ... and child frames, if they have a ScreenOrientationController.
    for (size_t i = 0; i < childFrames.size(); ++i) {
        ScreenOrientationController* controller = ScreenOrientationController::from(*childFrames[i]);
        if (controller)
            controller->notifyOrientationChanged();
    }
}

void ScreenOrientationController::setOrientation(ScreenOrientation* orientation)
{
    m_orientation = orientation;
    if (m_orientation)
        updateOrientation();
}

void ScreenOrientationController::lock(blink::WebScreenOrientationLockType orientation, blink::WebLockOrientationCallback* callback)
{
    ASSERT(m_client);
    m_client->lockOrientation(orientation, callback);
}

void ScreenOrientationController::unlock()
{
    ASSERT(m_client);
    m_client->unlockOrientation();
}

const LocalFrame& ScreenOrientationController::frame() const
{
    return m_frame;
}

void ScreenOrientationController::dispatchEventTimerFired(Timer<ScreenOrientationController>*)
{
    if (!m_orientation)
        return;
    m_orientation->dispatchEvent(Event::create(EventTypeNames::change));
}

void ScreenOrientationController::trace(Visitor* visitor)
{
    visitor->trace(m_orientation);
    WillBeHeapSupplement<LocalFrame>::trace(visitor);
}

} // namespace blink
<|endoftext|>