<commit_before>/*
 * Software License Agreement (BSD License)
 *
 *  Point Cloud Library (PCL) - www.pointclouds.org
 *  Copyright (c) 2012, Willow Garage, Inc.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of Willow Garage, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *
 * $Id$
 */

#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/console/parse.h>
#include <pcl/console/print.h>
#include <pcl/common/convolution.h>
#include <pcl/visualization/pcl_visualizer.h>

void
usage (char ** argv)
{
  pcl::console::print_info ("usage: %s <filename> <-r|-c|-s> [-p <borders policy>] [-t <number of threads>] [-d <distance>]\n\n", argv[0]);
  pcl::console::print_info ("Where options are:\n");
  pcl::console::print_info ("\t\t\t-r convolve rows\n");
  pcl::console::print_info ("\t\t\t-c convolve columns\n");
  pcl::console::print_info ("\t\t\t-s convolve separate\n");
  pcl::console::print_info ("\t\t\t-p borders policy\n");
  pcl::console::print_info ("\t\t\t\t Z zero padding, default\n");
  pcl::console::print_info ("\t\t\t\t D duplicate borders\n");
  pcl::console::print_info ("\t\t\t\t M mirror borders\n");
  pcl::console::print_info ("\t\t\t-t optional, number of threads, default 1\n");
  pcl::console::print_info ("\t\t\t-d optional, distance threshold, default 0.001\n");
}

int
main (int argc, char ** argv)
{
  int viewport_source, viewport_convolved = 0;
  int direction = -1;
  int nb_threads = 0;
  char border_policy = 'Z';
  double threshold = 0.001;
	pcl::common::Convolution<pcl::PointXYZRGB> convolution;
	Eigen::ArrayXf gaussian_kernel(5);
	gaussian_kernel << 1.f/16, 1.f/4, 3.f/8, 1.f/4, 1.f/16;
  pcl::console::print_info ("convolution kernel:");
  for (int i = 0; i < gaussian_kernel.size (); ++i)
    pcl::console::print_info (" %f", gaussian_kernel[i]);
  pcl::console::print_info ("\n");

  if (argc < 3)
  {
    usage (argv);
    return 1;
  }

  // check if user is requesting help
  std::string arg (argv[1]);

  if (arg == "--help" || arg == "-h")
  {
    usage (argv);
    return 1;
  }

  // user don't need help find convolving direction
  // convolve row
  if (pcl::console::find_switch (argc, argv, "-r"))
    direction = 0;
  else
  {
    // convolve column
    if (pcl::console::find_switch (argc, argv, "-c"))
      direction = 1;
    else
      // convolve both
      if (pcl::console::find_switch (argc, argv, "-s"))
        direction = 2;
      else
      {
        // wrong direction given print usage
        usage (argv);
        return 1;
      }
  }

  // number of threads if any
  if (pcl::console::parse_argument (argc, argv, "-t", nb_threads) != -1 )
  {
    if (nb_threads <= 0)
      nb_threads = 1;
  }
  convolution.setNumberOfThreads (nb_threads);

  // borders policy if any
  if (pcl::console::parse_argument (argc, argv, "-p", border_policy) != -1 )
  {
    switch (border_policy)
    {
      case 'Z' : convolution.setBordersPolicy (pcl::common::Convolution<pcl::PointXYZRGB>::IGNORE);
        break;
      case 'M' : convolution.setBordersPolicy (pcl::common::Convolution<pcl::PointXYZRGB>::MIRROR);
        break;
      case 'D' : convolution.setBordersPolicy (pcl::common::Convolution<pcl::PointXYZRGB>::DUPLICATE);
        break;
      default :
      {
        usage (argv);
        return (1);
      }
    }
  }
  else
    convolution.setBordersPolicy (pcl::common::Convolution<pcl::PointXYZRGB>::IGNORE);

  // distance threshold if any
  if (pcl::console::parse_argument (argc, argv, "-d", threshold) == -1 )
  {
    threshold = 0.001;
  }
  convolution.setDistanceThreshold (static_cast<float> (threshold));

  // all set
  // we have file name and convolving direction
	pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZRGB> ());
	if (pcl::io::loadPCDFile (argv[1], *cloud) == -1)
  {
    pcl::console::print_error ("Couldn't read file %s \n", argv[1]);
    return (-1);
  }
	cloud->is_dense = false;
	convolution.setInputCloud (cloud);
	convolution.setKernel (gaussian_kernel);
	pcl::PointCloud<pcl::PointXYZRGB>::Ptr convolved (new pcl::PointCloud<pcl::PointXYZRGB> ());

  double t0;
  pcl::console::print_info ("convolving %s along \n", argv[1]);
  std::ostringstream convolved_label;
  convolved_label << "convolved along ";
  switch (direction)
  {
    case 0:
    {
      convolved_label << "rows... ";
      t0 = pcl::getTime ();
      convolution.convolveRows (*convolved);
      break;
    }
    case 1:
    {
      convolved_label << "columns... ";
      t0 = pcl::getTime ();
      convolution.convolveCols (*convolved);
      break;
    }
    case 2:
    {
      convolved_label << "rows and columns... ";
      t0 = pcl::getTime ();
      convolution.convolve (*convolved);
      break;
    }
  }
  convolved_label << pcl::getTime () - t0 << "s";
  // Display
	boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer (new pcl::visualization::PCLVisualizer ("Convolution"));
  // viewport stuff
  viewer->createViewPort (0, 0, 0.5, 1, viewport_source);
  viewer->createViewPort (0.5, 0, 1, 1, viewport_convolved);
  viewer->setBackgroundColor (0, 0, 0);

  // Source
  pcl::visualization::PointCloudColorHandlerRGBField<pcl::PointXYZRGB> color_handler_source (cloud);
  viewer->addPointCloud<pcl::PointXYZRGB> (cloud, color_handler_source, "source", viewport_source);
  viewer->addText ("source", 10, 10, "source_label", viewport_source);

  // Convolved
	pcl::visualization::PointCloudColorHandlerRGBField<pcl::PointXYZRGB> color_handler_convolved (convolved);
  viewer->addPointCloud<pcl::PointXYZRGB> (convolved, color_handler_convolved, "convolved", viewport_convolved);
  viewer->addText (convolved_label.str (), 10, 10, "convolved_label", viewport_convolved);
	viewer->spin ();
}
<commit_msg>Update to fit new headers<commit_after>/*
 * Software License Agreement (BSD License)
 *
 *  Point Cloud Library (PCL) - www.pointclouds.org
 *  Copyright (c) 2012, Willow Garage, Inc.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of Willow Garage, Inc. nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *
 * $Id$
 */

#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/console/parse.h>
#include <pcl/console/print.h>
#include <pcl/filters/convolution.h>
#include <pcl/visualization/pcl_visualizer.h>

void
usage (char ** argv)
{
  pcl::console::print_info ("usage: %s <filename> <-r|-c|-s> [-p <borders policy>] [-t <number of threads>] [-d <distance>]\n\n", argv[0]);
  pcl::console::print_info ("Where options are:\n");
  pcl::console::print_info ("\t\t\t-r convolve rows\n");
  pcl::console::print_info ("\t\t\t-c convolve columns\n");
  pcl::console::print_info ("\t\t\t-s convolve separate\n");
  pcl::console::print_info ("\t\t\t-p borders policy\n");
  pcl::console::print_info ("\t\t\t\t Z zero padding, default\n");
  pcl::console::print_info ("\t\t\t\t D duplicate borders\n");
  pcl::console::print_info ("\t\t\t\t M mirror borders\n");
  pcl::console::print_info ("\t\t\t-t optional, number of threads, default 1\n");
  pcl::console::print_info ("\t\t\t-d optional, distance threshold, default 0.001\n");
}

int
main (int argc, char ** argv)
{
  int viewport_source, viewport_convolved = 0;
  int direction = -1;
  int nb_threads = 0;
  char border_policy = 'Z';
  double threshold = 0.001;
  pcl::filters::Convolution<pcl::PointXYZRGB, pcl::PointXYZRGB> convolution;
  Eigen::ArrayXf gaussian_kernel(5);
  gaussian_kernel << 1.f/16, 1.f/4, 3.f/8, 1.f/4, 1.f/16;
  pcl::console::print_info ("convolution kernel:");
  for (int i = 0; i < gaussian_kernel.size (); ++i)
    pcl::console::print_info (" %f", gaussian_kernel[i]);
  pcl::console::print_info ("\n");

  if (argc < 3)
  {
    usage (argv);
    return 1;
  }

  // check if user is requesting help
  std::string arg (argv[1]);

  if (arg == "--help" || arg == "-h")
  {
    usage (argv);
    return 1;
  }

  // user don't need help find convolving direction
  // convolve row
  if (pcl::console::find_switch (argc, argv, "-r"))
    direction = 0;
  else
  {
    // convolve column
    if (pcl::console::find_switch (argc, argv, "-c"))
      direction = 1;
    else
      // convolve both
      if (pcl::console::find_switch (argc, argv, "-s"))
        direction = 2;
      else
      {
        // wrong direction given print usage
        usage (argv);
        return 1;
      }
  }

  // number of threads if any
  if (pcl::console::parse_argument (argc, argv, "-t", nb_threads) != -1 )
  {
    if (nb_threads <= 0)
      nb_threads = 1;
  }
  convolution.setNumberOfThreads (nb_threads);

  // borders policy if any
  if (pcl::console::parse_argument (argc, argv, "-p", border_policy) != -1 )
  {
    switch (border_policy)
    {
      case 'Z' : convolution.setBordersPolicy (pcl::filters::Convolution<pcl::PointXYZRGB, pcl::PointXYZRGB>::BORDERS_POLICY_IGNORE);
        break;
      case 'M' : convolution.setBordersPolicy (pcl::filters::Convolution<pcl::PointXYZRGB, pcl::PointXYZRGB>::BORDERS_POLICY_MIRROR);
        break;
      case 'D' : convolution.setBordersPolicy (pcl::filters::Convolution<pcl::PointXYZRGB, pcl::PointXYZRGB>::BORDERS_POLICY_DUPLICATE);
        break;
      default :
      {
        usage (argv);
        return (1);
      }
    }
  }
  else
    convolution.setBordersPolicy (pcl::filters::Convolution<pcl::PointXYZRGB, pcl::PointXYZRGB>::BORDERS_POLICY_IGNORE);

  // distance threshold if any
  if (pcl::console::parse_argument (argc, argv, "-d", threshold) == -1 )
  {
    threshold = 0.01;
  }
  convolution.setDistanceThreshold (static_cast<float> (threshold));

  // all set
  // we have file name and convolving direction
  pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZRGB> ());
  if (pcl::io::loadPCDFile (argv[1], *cloud) == -1)
  {
    pcl::console::print_error ("Couldn't read file %s \n", argv[1]);
    return (-1);
  }
  cloud->is_dense = false;
  convolution.setInputCloud (cloud);
  convolution.setKernel (gaussian_kernel);
  pcl::PointCloud<pcl::PointXYZRGB>::Ptr convolved (new pcl::PointCloud<pcl::PointXYZRGB> ());
  double t0;
  pcl::console::print_info ("convolving %s along \n", argv[1]);
  std::ostringstream convolved_label;
  convolved_label << "convolved along ";
  switch (direction)
  {
    case 0:
    {
      convolved_label << "rows... ";
      t0 = pcl::getTime ();
      convolution.convolveRows (*convolved);
      break;
    }
    case 1:
    {
      convolved_label << "columns... ";
      t0 = pcl::getTime ();
      convolution.convolveCols (*convolved);
      break;
    }
    case 2:
    {
      convolved_label << "rows and columns... ";
      t0 = pcl::getTime ();
      convolution.convolve (*convolved);
      break;
    }
  }
  convolved_label << pcl::getTime () - t0 << "s";
  // Display
  boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer (new pcl::visualization::PCLVisualizer ("Convolution"));
  // viewport stuff
  viewer->createViewPort (0, 0, 0.5, 1, viewport_source);
  viewer->createViewPort (0.5, 0, 1, 1, viewport_convolved);
  viewer->setBackgroundColor (0, 0, 0);

  // Source
  pcl::visualization::PointCloudColorHandlerRGBField<pcl::PointXYZRGB> color_handler_source (cloud);
  viewer->addPointCloud<pcl::PointXYZRGB> (cloud, color_handler_source, "source", viewport_source);
  viewer->addText ("source", 10, 10, "source_label", viewport_source);

  // Convolved
  pcl::visualization::PointCloudColorHandlerRGBField<pcl::PointXYZRGB> color_handler_convolved (convolved);
  viewer->addPointCloud<pcl::PointXYZRGB> (convolved, color_handler_convolved, "convolved", viewport_convolved);
  viewer->addText (convolved_label.str (), 10, 10, "convolved_label", viewport_convolved);
  viewer->spin ();
  pcl::PCDWriter writer;
  writer.write<pcl::PointXYZRGB> ("convolved.pcd", *convolved, false);
}
<|endoftext|>


<commit_before>// Copyright (C) 2018 Elviss Strazdins
// This file is part of the Ouzel engine.

#include "MainMenu.hpp"
#include "SpritesSample.hpp"
#include "GUISample.hpp"
#include "RTSample.hpp"
#include "AnimationsSample.hpp"
#include "InputSample.hpp"
#include "SoundSample.hpp"
#include "PerspectiveSample.hpp"

std::string DEVELOPER_NAME = "org.ouzel";
std::string APPLICATION_NAME = "samples";

using namespace ouzel;

ouzel::Archive archive;
std::unique_ptr<assets::Bundle> bundle;

void ouzelMain(const std::vector<std::string>& args)
{
    bundle.reset(new assets::Bundle(*engine->getCache()));

    // disable screen saver
    engine->setScreenSaverEnabled(false);

    std::string sample;

    for (auto arg = args.begin(); arg != args.end(); ++arg)
    {
        if (arg == args.begin())
        {
            // skip the first parameter
            continue;
        }

        if (*arg == "-sample")
        {
            auto nextArg = ++arg;

            if (nextArg != args.end())
                sample = *nextArg;
            else
                ouzel::Log(ouzel::Log::Level::WARN) << "No sample specified";
        }
        else
            ouzel::Log(ouzel::Log::Level::WARN) << "Invalid argument \"" << *arg << "\"";
    }

    engine->getFileSystem()->addResourcePath("Resources");

#if !OUZEL_PLATFORM_ANDROID
    archive = ouzel::Archive("gui.zip");
    engine->getFileSystem()->addArchive(&archive);
#endif

    bundle->loadAssets("assets.json");

    engine->getRenderer()->setClearColor(ouzel::Color(64, 0, 0));

    std::unique_ptr<ouzel::scene::Scene> currentScene;

    if (!sample.empty())
    {
        if (sample == "sprites") currentScene.reset(new SpritesSample());
        else if (sample == "gui") currentScene.reset(new GUISample());
        else if (sample == "render_target") currentScene.reset(new RTSample());
        else if (sample == "animations") currentScene.reset(new AnimationsSample());
        else if (sample == "input") currentScene.reset(new InputSample());
        else if (sample == "sound") currentScene.reset(new SoundSample());
        else if (sample == "perspective") currentScene.reset(new PerspectiveSample());
    }

    if (!currentScene) currentScene.reset(new MainMenu());

    engine->getSceneManager()->setScene(std::move(currentScene));
}
<commit_msg>Fix the sample project<commit_after>// Copyright (C) 2018 Elviss Strazdins
// This file is part of the Ouzel engine.

#include "MainMenu.hpp"
#include "SpritesSample.hpp"
#include "GUISample.hpp"
#include "RTSample.hpp"
#include "AnimationsSample.hpp"
#include "InputSample.hpp"
#include "SoundSample.hpp"
#include "PerspectiveSample.hpp"

std::string DEVELOPER_NAME = "org.ouzel";
std::string APPLICATION_NAME = "samples";

using namespace ouzel;

#if !OUZEL_PLATFORM_ANDROID
std::unique_ptr<ouzel::Archive> archive;
#endif
std::unique_ptr<assets::Bundle> bundle;

void ouzelMain(const std::vector<std::string>& args)
{
    bundle.reset(new assets::Bundle(*engine->getCache()));

    // disable screen saver
    engine->setScreenSaverEnabled(false);

    std::string sample;

    for (auto arg = args.begin(); arg != args.end(); ++arg)
    {
        if (arg == args.begin())
        {
            // skip the first parameter
            continue;
        }

        if (*arg == "-sample")
        {
            auto nextArg = ++arg;

            if (nextArg != args.end())
                sample = *nextArg;
            else
                ouzel::Log(ouzel::Log::Level::WARN) << "No sample specified";
        }
        else
            ouzel::Log(ouzel::Log::Level::WARN) << "Invalid argument \"" << *arg << "\"";
    }

    engine->getFileSystem()->addResourcePath("Resources");

#if !OUZEL_PLATFORM_ANDROID
    archive.reset(new ouzel::Archive(*engine->getFileSystem(), "gui.zip"));
#endif

    bundle->loadAssets("assets.json");

    engine->getRenderer()->setClearColor(ouzel::Color(64, 0, 0));

    std::unique_ptr<ouzel::scene::Scene> currentScene;

    if (!sample.empty())
    {
        if (sample == "sprites") currentScene.reset(new SpritesSample());
        else if (sample == "gui") currentScene.reset(new GUISample());
        else if (sample == "render_target") currentScene.reset(new RTSample());
        else if (sample == "animations") currentScene.reset(new AnimationsSample());
        else if (sample == "input") currentScene.reset(new InputSample());
        else if (sample == "sound") currentScene.reset(new SoundSample());
        else if (sample == "perspective") currentScene.reset(new PerspectiveSample());
    }

    if (!currentScene) currentScene.reset(new MainMenu());

    engine->getSceneManager()->setScene(std::move(currentScene));
}
<|endoftext|>


<commit_before>#define _USE_MATH_DEFINES
#include <esn/esn.h>
#include <iomanip>
#include <iostream>
#include <math.h>

static const unsigned kNeuronCount = 100;
static const float kSineFrequency = 1.0f;
static const float kSimulationStep = 0.01f;
static const float kTrainingTime = 25.0f * 1.0f / kSineFrequency;

int main()
{
    ESN::NetworkParamsNSLI params;
    params.inputCount = 1;
    params.neuronCount = kNeuronCount;
    params.outputCount = 1;
    std::unique_ptr< ESN::Network > network = ESN::CreateNetwork( params );

    std::vector< float > output( 1 );
    std::vector< float > actualOutput( 1 );
    for ( float time = 0.0f; true; time += kSimulationStep )
    {
        output[0] = sin( 2 * static_cast< float >( M_PI ) *
            kSineFrequency * time ) + 2.0f;

        network->Step( 0.1f );
        network->CaptureOutput( actualOutput );
        float error = fabs( ( actualOutput[0] - output[0] ) / output[0] );

        if ( time < kTrainingTime )
            network->TrainOnline( output, true );

        std::cout << std::setw( 14 ) << output[0];
        std::cout << std::setw( 14 ) << actualOutput[0];
        std::cout << std::setw( 14 ) << error << std::endl;
    }

    return 0;
}
<commit_msg>samples : sine : set kLeakingRate = 0.1f<commit_after>#define _USE_MATH_DEFINES
#include <esn/esn.h>
#include <iomanip>
#include <iostream>
#include <math.h>

static const unsigned kNeuronCount = 100;
static const float kLeakingRate = 0.1f;
static const float kSineFrequency = 1.0f;
static const float kSimulationStep = 0.01f;
static const float kTrainingTime = 25.0f * 1.0f / kSineFrequency;

int main()
{
    ESN::NetworkParamsNSLI params;
    params.inputCount = 1;
    params.neuronCount = kNeuronCount;
    params.outputCount = 1;
    params.leakingRate = kLeakingRate;
    std::unique_ptr< ESN::Network > network = ESN::CreateNetwork( params );

    std::vector< float > output( 1 );
    std::vector< float > actualOutput( 1 );
    for ( float time = 0.0f; true; time += kSimulationStep )
    {
        output[0] = sin( 2 * static_cast< float >( M_PI ) *
            kSineFrequency * time ) + 2.0f;

        network->Step( 0.1f );
        network->CaptureOutput( actualOutput );
        float error = fabs( ( actualOutput[0] - output[0] ) / output[0] );

        if ( time < kTrainingTime )
            network->TrainOnline( output, true );

        std::cout << std::setw( 14 ) << output[0];
        std::cout << std::setw( 14 ) << actualOutput[0];
        std::cout << std::setw( 14 ) << error << std::endl;
    }

    return 0;
}
<|endoftext|>


<commit_before>#include "Navigation.h"
#include <fstream>
#include <queue>
// #include <iostream>
// #include <string>
// #include <cstring>
// #include <dirent.h>

using namespace std;

double Node::DNE = 1000000.0;

Navigation::Navigation(const char* filename)
{
  inputNodes(filename); //forgot what your formwat was clayton and don't want to deal with it too much
  if(allNodes.size() > 1) //keep in mind, the output path doesn't include the source
  {
    cout << "from " << allNodes[0].name << " to " << allNodes[allNodes.size()-1].name << endl;
    travelFromSourceToSink(&allNodes[0], &allNodes[allNodes.size()-1]);
  }
}

void Navigation::inputNodes(const char* filename)
{
	ifstream in;
	string inStr;
	int numNeighbors;

	in.open(filename);

	if(in.good()){ //if the file was successfully opened
		in >> inStr; //read the number of nodes
		numNodes = atoi(inStr.c_str()); //change the string we read to an int
		// cout << "num nodes: " << numNodes << endl;
		for(int i = 0; i < numNodes; i++){ //loop for each node we have
			in >> inStr; //read the name of a node
      		// cout << "Name: " << inStr << endl;
			Node n(inStr, Node::DNE); //create a new node with nonexistant g value
      		n.parent = NULL;
			allNodes.push_back(n); //put that node in the list of all nodes
		}

		for(int i = 0; i < numNodes; i++){ //loop for each node we have
			in >> inStr; //read the number of neighbors a node has
			numNeighbors = atoi(inStr.c_str());
      		// cout << "numNeighbors :: " << numNeighbors << endl; //output is wrong here
			for(int j = 0; j < numNeighbors; j++) { //loop for each neighbor of a node
				in >> inStr; //read the nodes neighbor
				// cout << "Neighbor: " << inStr << endl;
				allNodes[i].neighbors.push_back(&allNodes[atoi(inStr.c_str())]); //store the node in the list of neighbors
				in >> inStr; //read the neighbors weight
				// cout << "Weight: " << inStr << endl;
				allNodes[i].weights.push_back(atoi(inStr.c_str())); //assign the weight
			}
		}
	}
}

bool Navigation::travelFromSourceToSink(Node* source, Node* sink)
{
  vector<Node*> path;
  //while not yet there...
  bool arrived = false;
  while(!arrived)
  {
    //path from CURRENT place to sink Node                                                  FIX THIS
    path = findPath(source, sink); //should be (current, sink) with current starting at source
    #ifndef TEST
    outputPath(path);
    #endif
    arrived = walkPath(path);
  }

  return true; //or false if ???
}

bool Navigation::walkPath(const vector<Node*>& path)
{
  //walk the walk using roomba commands

  //if blocked, restart pathfinding from current spot.
  return true;
}

//this is now BFS not A*... because we don't know a heuristic and it don't matter ("doesn't matter", you sound like a hick) anyway (small graphs)
vector<Node*> Navigation::findPath(Node* source, Node* sink)
{
  //cout << "findPath" << endl;
  for(size_t i=0; i<allNodes.size(); ++i)
  {
    allNodes[i].g_score = Node::DNE;
    allNodes[i].parent = NULL;
  }

  source->g_score = 0.0;
  //The set of tentative Nodes that need to be evaluated, starting with sink
  queue<Node*> openSet;
  openSet.push(source);

  //while openset is not empty
  while(!openSet.empty())
  {
    //cout << "loop openSet.size() :: " << openSet.size() << endl;
    Node* current = openSet.front();
    // cout << current->name << endl;
    openSet.pop();

    //for each neighbor in current->neighbors
    //cout << "neighbors.size() :: " << current->neighbors.size() << endl;
    for(size_t i=0; i<current->neighbors.size(); ++i)
    {
      Node* neighbor = current->neighbors[i];
      if(neighbor == NULL)
        continue;
      double tempScore = current->g_score + current->weights[i];
      //if neighbor not yet evaluated or better score
      if(neighbor->g_score == Node::DNE || tempScore < neighbor->g_score)
      {
        //if neighbor not yet evaluated
        if(neighbor->g_score == Node::DNE)
          //add neighbor to openset
          openSet.push(neighbor);
        //came_from[neighbor] = current
        neighbor->parent = current;
        //g_score[neighbor] = tentative_g_score
        neighbor->g_score= tempScore;
      }
    }
  }

  return reconstructPath(sink);
}

vector<Node*> Navigation::reconstructPath(Node* current)
{
  vector<Node*> path;
  while(current->parent != NULL)
  {
    path.insert(path.begin(), current);
    current = current->parent;
  }
  return path;
}

void Navigation::outputPath(const vector<Node*>& path)
{
  cout << endl << "start path" << endl;
  for(size_t i=0; i<path.size(); ++i)
  {
    cout << "\t" << path[i]->name << endl;
  }
  cout << "end path\n" << endl;
}

void Navigation::outputAllNodes()
{
  for(size_t i=0; i<allNodes.size(); ++i)
  {
    cout << allNodes[i].name << " " << allNodes[i].neighbors.size() << endl;
  }
}

Node* Navigation::getNode(int index) {
	return &allNodes[index];
}

vector<Node*> Navigation::dbgReconstructPath(Node* current) {
	vector<Node*> path;

	#ifdef TEST
		return reconstructPath(current);
	#else
		cout << "This function is only for testing." << endl;
	#endif

	return path;
}

vector<Node*> Navigation::dbgFindPath(Node* source, Node* sink) {
	vector<Node*> path;

	#ifdef TEST
		return findPath(source, sink);
	#else
		cout << "This function is only for testing." << endl;
	#endif

	return path;
}
<commit_msg>Commiting to pull<commit_after>#include "Navigation.h"
#include <fstream>
#include <queue>
// #include <iostream>
// #include <string>
// #include <cstring>
// #include <dirent.h>

using namespace std;

double Node::DNE = 1000000.0;

Navigation::Navigation(const char* filename)
{
  inputNodes(filename); //forgot what your format was clayton and don't want to deal with it too much
  if(allNodes.size() > 1) //keep in mind, the output path doesn't include the source
  {
    cout << "from " << allNodes[0].name << " to " << allNodes[allNodes.size()-1].name << endl;
    travelFromSourceToSink(&allNodes[0], &allNodes[allNodes.size()-1]);
  }
}

void Navigation::inputNodes(const char* filename)
{
	ifstream in;
	string inStr;
	int numNeighbors;

	in.open(filename);

	if(in.good()){ //if the file was successfully opened
		in >> inStr; //read the number of nodes
		numNodes = atoi(inStr.c_str()); //change the string we read to an int
		// cout << "num nodes: " << numNodes << endl;
		for(int i = 0; i < numNodes; i++){ //loop for each node we have
			in >> inStr; //read the name of a node
      		// cout << "Name: " << inStr << endl;
			Node n(inStr, Node::DNE); //create a new node with nonexistant g value
      		n.parent = NULL;
			allNodes.push_back(n); //put that node in the list of all nodes
		}

		for(int i = 0; i < numNodes; i++){ //loop for each node we have
			in >> inStr; //read the number of neighbors a node has
			numNeighbors = atoi(inStr.c_str());
      		// cout << "numNeighbors :: " << numNeighbors << endl; //output is wrong here
			for(int j = 0; j < numNeighbors; j++) { //loop for each neighbor of a node
				in >> inStr; //read the nodes neighbor
				// cout << "Neighbor: " << inStr << endl;
				allNodes[i].neighbors.push_back(&allNodes[atoi(inStr.c_str())]); //store the node in the list of neighbors
				in >> inStr; //read the neighbors weight
				// cout << "Weight: " << inStr << endl;
				allNodes[i].weights.push_back(atoi(inStr.c_str())); //assign the weight
			}
		}
	}
}

bool Navigation::travelFromSourceToSink(Node* source, Node* sink)
{
  vector<Node*> path;
  //while not yet there...
  bool arrived = false;
  while(!arrived)
  {
    //path from CURRENT place to sink Node                                                  FIX THIS
    path = findPath(source, sink); //should be (current, sink) with current starting at source
    #ifndef TEST
    outputPath(path);
    #endif
    arrived = walkPath(path);
  }

  return true; //or false if ???
}

bool Navigation::walkPath(const vector<Node*>& path)
{
  //walk the walk using roomba commands

  //if blocked, restart pathfinding from current spot.
  return true;
}

//this is now BFS not A*... because we don't know a heuristic and it don't matter ("doesn't matter", you sound like a hick) anyway (small graphs)
vector<Node*> Navigation::findPath(Node* source, Node* sink)
{
  //cout << "findPath" << endl;
  for(size_t i=0; i<allNodes.size(); ++i)
  {
    allNodes[i].g_score = Node::DNE;
    allNodes[i].parent = NULL;
  }

  source->g_score = 0.0;
  //The set of tentative Nodes that need to be evaluated, starting with sink
  queue<Node*> openSet;
  openSet.push(source);

  //while openset is not empty
  while(!openSet.empty())
  {
    //cout << "loop openSet.size() :: " << openSet.size() << endl;
    Node* current = openSet.front();
    // cout << current->name << endl;
    openSet.pop();

    //for each neighbor in current->neighbors
    //cout << "neighbors.size() :: " << current->neighbors.size() << endl;
    for(size_t i=0; i<current->neighbors.size(); ++i)
    {
      Node* neighbor = current->neighbors[i];
      if(neighbor == NULL)
        continue;
      double tempScore = current->g_score + current->weights[i];
      //if neighbor not yet evaluated or better score
      if(neighbor->g_score == Node::DNE || tempScore < neighbor->g_score)
      {
        //if neighbor not yet evaluated
        if(neighbor->g_score == Node::DNE)
          //add neighbor to openset
          openSet.push(neighbor);
        //came_from[neighbor] = current
        neighbor->parent = current;
        //g_score[neighbor] = tentative_g_score
        neighbor->g_score= tempScore;
      }
    }
  }

  return reconstructPath(sink);
}

vector<Node*> Navigation::reconstructPath(Node* current)
{
  vector<Node*> path;
  while(current->parent != NULL)
  {
    path.insert(path.begin(), current);
    current = current->parent;
  }
  return path;
}

void Navigation::outputPath(const vector<Node*>& path)
{
  cout << endl << "start path" << endl;
  for(size_t i=0; i<path.size(); ++i)
  {
    cout << "\t" << path[i]->name << endl;
  }
  cout << "end path\n" << endl;
}

void Navigation::outputAllNodes()
{
  for(size_t i=0; i<allNodes.size(); ++i)
  {
    cout << allNodes[i].name << " " << allNodes[i].neighbors.size() << endl;
  }
}

Node* Navigation::getNode(int index) {
	return &allNodes[index];
}

vector<Node*> Navigation::dbgReconstructPath(Node* current) {
	vector<Node*> path;

	#ifdef TEST
		return reconstructPath(current);
	#else
		cout << "This function is only for testing." << endl;
	#endif

	return path;
}

vector<Node*> Navigation::dbgFindPath(Node* source, Node* sink) {
	vector<Node*> path;

	#ifdef TEST
		return findPath(source, sink);
	#else
		cout << "This function is only for testing." << endl;
	#endif

	return path;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2012, Willow Garage, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the Willow Garage, Inc. nor the names of its
 *       contributors may be used to endorse or promote products derived from
 *       this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include <stdio.h>

#include <gtest/gtest.h>

#include <rviz/properties/property.h>
#include <rviz/properties/color_property.h>
#include <rviz/properties/vector_property.h>
#include <rviz/properties/quaternion_property.h>
#include <rviz/properties/enum_property.h>

#include "mock_property_change_receiver.h"

using namespace rviz;

TEST(Property, name)
{
  Property p;
  p.setName("chub");
  EXPECT_EQ("chub", p.getName().toStdString());
}

TEST(Property, description)
{
  Property p;
  p.setDescription("chub");
  EXPECT_EQ("chub", p.getDescription().toStdString());
}

TEST(Property, value)
{
  Property p;
  p.setValue(199);
  EXPECT_EQ(199, p.getValue().toInt());
}

TEST(Property, set_value_events)
{
  Property p;
  p.setValue(0);

  MockPropertyChangeReceiver r(&p);
  p.connect(&p, SIGNAL(aboutToChange()), &r, SLOT(aboutToChange()));
  p.connect(&p, SIGNAL(changed()), &r, SLOT(changed()));

  p.setValue(17);
  EXPECT_EQ(" aboutToChange, v=0 changed, v=17", r.result().toStdString());
}

TEST(Property, children)
{
  Property* display = new Property("Test");
  new Property("Alpha", 0.5, "The amount of transparency to apply to the grid lines.", display);
  Property* beta =
      new Property("Beta Band", 10, "The number of betas to apply to the grid lines.", display);
  new Property("Gamma Topic", "chubby", "The topic on which to listen for Gamma messages.", display);
  Property* position = new Property("Position", QVariant(), "Position of the chub.", display);
  new Property("X", 1.1f, "X component of the position of the chub.", position);
  new Property("Y", 0.717f, "Y component of the position of the chub.", position);

  // Sample usage inside the Display which owns the property.
  int b = beta->getValue().toInt();
  EXPECT_EQ(10, b);

  // Sample usage outside the Display
  beta->setValue(12);
  EXPECT_EQ(12, display->subProp("Beta Band")->getValue().toInt());

  // Compound property
  float y = display->subProp("Position")->subProp("Y")->getValue().toFloat();
  EXPECT_EQ(0.717f, y);

  // Accessing a missing property should not crash.
  printf("Next line should say 'ERROR' but not crash.\n");
  display->subProp("Position")->subProp("Z")->getValue().toFloat();
}

TEST(VectorProperty, default_value)
{
  VectorProperty* vp = new VectorProperty();
  Ogre::Vector3 vec = vp->getVector();
  EXPECT_EQ(0, vec.x);
  EXPECT_EQ(0, vec.y);
  EXPECT_EQ(0, vec.z);
}

TEST(VectorProperty, set_and_get)
{
  VectorProperty* vp = new VectorProperty();
  Ogre::Vector3 vec(1, 2, 3);
  vp->setVector(vec);

  Ogre::Vector3 vec2 = vp->getVector();
  EXPECT_EQ(1, vec2.x);
  EXPECT_EQ(2, vec2.y);
  EXPECT_EQ(3, vec2.z);
}

TEST(VectorProperty, set_string)
{
  VectorProperty* vp = new VectorProperty();
  vp->setValue(QString("1;2;3"));

  Ogre::Vector3 vec = vp->getVector();
  EXPECT_EQ(1, vec.x);
  EXPECT_EQ(2, vec.y);
  EXPECT_EQ(3, vec.z);

  vp->setValue(QString("chubby!"));

  vec = vp->getVector();
  EXPECT_EQ(1, vec.x);
  EXPECT_EQ(2, vec.y);
  EXPECT_EQ(3, vec.z);
}

TEST(VectorProperty, set_child)
{
  VectorProperty* vp = new VectorProperty();
  vp->subProp("X")->setValue(0.9);
  vp->subProp("Y")->setValue(1.1);
  vp->subProp("Z")->setValue(1.3);

  Ogre::Vector3 vec = vp->getVector();
  EXPECT_EQ(0.9f, vec.x);
  EXPECT_EQ(1.1f, vec.y);
  EXPECT_EQ(1.3f, vec.z);
}

TEST(VectorProperty, get_child)
{
  VectorProperty* vp = new VectorProperty("v", Ogre::Vector3(1, 2, 3));
  EXPECT_EQ(1, vp->subProp("X")->getValue().toFloat());
  EXPECT_EQ(2, vp->subProp("Y")->getValue().toFloat());
  EXPECT_EQ(3, vp->subProp("Z")->getValue().toFloat());
}

TEST(VectorProperty, set_value_events)
{
  VectorProperty p;

  MockPropertyChangeReceiver r(&p);
  p.connect(&p, SIGNAL(aboutToChange()), &r, SLOT(aboutToChange()));
  p.connect(&p, SIGNAL(changed()), &r, SLOT(changed()));

  p.setVector(Ogre::Vector3(.1, .0001, 1000));
  EXPECT_EQ(" aboutToChange, v=0; 0; 0 changed, v=0.1; 0.0001; 1000", r.result().toStdString());
  r.reset();

  p.subProp("Z")->setValue(2.1);
  EXPECT_EQ(" aboutToChange, v=0.1; 0.0001; 1000 changed, v=0.1; 0.0001; 2.1", r.result().toStdString());
}

TEST(QuaternionProperty, default_value)
{
  QuaternionProperty* qp = new QuaternionProperty();
  Ogre::Quaternion quat = qp->getQuaternion();
  EXPECT_EQ(0, quat.x);
  EXPECT_EQ(0, quat.y);
  EXPECT_EQ(0, quat.z);
  EXPECT_EQ(1, quat.w);
}

TEST(QuaternionProperty, set_and_get)
{
  QuaternionProperty* qp = new QuaternionProperty();
  Ogre::Quaternion quat(4, 1, 2, 3);
  qp->setQuaternion(quat);

  Ogre::Quaternion quat2 = qp->getQuaternion();
  EXPECT_EQ(1, quat2.x);
  EXPECT_EQ(2, quat2.y);
  EXPECT_EQ(3, quat2.z);
  EXPECT_EQ(4, quat2.w);
}

TEST(QuaternionProperty, set_string)
{
  QuaternionProperty* qp = new QuaternionProperty();
  qp->setValue(QString("1;2;3;4"));

  Ogre::Quaternion quat = qp->getQuaternion();
  EXPECT_EQ(1, quat.x);
  EXPECT_EQ(2, quat.y);
  EXPECT_EQ(3, quat.z);
  EXPECT_EQ(4, quat.w);

  qp->setValue(QString("chubby!"));

  quat = qp->getQuaternion();
  EXPECT_EQ(1, quat.x);
  EXPECT_EQ(2, quat.y);
  EXPECT_EQ(3, quat.z);
  EXPECT_EQ(4, quat.w);
}

TEST(QuaternionProperty, set_child)
{
  QuaternionProperty* qp = new QuaternionProperty();
  qp->subProp("X")->setValue(0.9);
  qp->subProp("Y")->setValue(1.1);
  qp->subProp("Z")->setValue(1.3);
  qp->subProp("W")->setValue(1.5);

  Ogre::Quaternion quat = qp->getQuaternion();
  EXPECT_EQ(0.9f, quat.x);
  EXPECT_EQ(1.1f, quat.y);
  EXPECT_EQ(1.3f, quat.z);
  EXPECT_EQ(1.5f, quat.w);
}

TEST(QuaternionProperty, get_child)
{
  QuaternionProperty* qp = new QuaternionProperty("v", Ogre::Quaternion(4, 1, 2, 3));
  EXPECT_EQ(1, qp->subProp("X")->getValue().toFloat());
  EXPECT_EQ(2, qp->subProp("Y")->getValue().toFloat());
  EXPECT_EQ(3, qp->subProp("Z")->getValue().toFloat());
  EXPECT_EQ(4, qp->subProp("W")->getValue().toFloat());
}

TEST(QuaternionProperty, set_value_events)
{
  QuaternionProperty p;

  MockPropertyChangeReceiver r(&p);
  p.connect(&p, SIGNAL(aboutToChange()), &r, SLOT(aboutToChange()));
  p.connect(&p, SIGNAL(changed()), &r, SLOT(changed()));

  p.setQuaternion(Ogre::Quaternion(1, .1, .0001, 1000));
  EXPECT_EQ(" aboutToChange, v=0; 0; 0; 1 changed, v=0.1; 0.0001; 1000; 1", r.result().toStdString());
  r.reset();

  p.subProp("Z")->setValue(2.1);
  EXPECT_EQ(" aboutToChange, v=0.1; 0.0001; 1000; 1 changed, v=0.1; 0.0001; 2.1; 1",
            r.result().toStdString());
}

TEST(ColorProperty, default_value)
{
  ColorProperty* qp = new ColorProperty();
  QColor color = qp->getColor();
  EXPECT_EQ(0, color.red());
  EXPECT_EQ(0, color.green());
  EXPECT_EQ(0, color.blue());
}

TEST(ColorProperty, set_and_get)
{
  ColorProperty* qp = new ColorProperty();
  QColor color(1, 2, 3);
  qp->setColor(color);

  QColor color2 = qp->getColor();
  EXPECT_EQ(1, color2.red());
  EXPECT_EQ(2, color2.green());
  EXPECT_EQ(3, color2.blue());
}

TEST(ColorProperty, set_string)
{
  ColorProperty* qp = new ColorProperty();
  qp->setValue(QString("1;2;3"));

  QColor color = qp->getColor();
  EXPECT_EQ(1, color.red());
  EXPECT_EQ(2, color.green());
  EXPECT_EQ(3, color.blue());

  qp->setValue(QString("chubby!"));

  color = qp->getColor();
  EXPECT_EQ(1, color.red());
  EXPECT_EQ(2, color.green());
  EXPECT_EQ(3, color.blue());
}

TEST(ColorProperty, set_string_limits)
{
  ColorProperty* qp = new ColorProperty();
  qp->setValue(QString("-1;2000;3"));

  QColor color = qp->getColor();
  EXPECT_EQ(0, color.red());
  EXPECT_EQ(255, color.green());
  EXPECT_EQ(3, color.blue());
}

TEST(ColorProperty, set_value_events)
{
  ColorProperty p;

  MockPropertyChangeReceiver r(&p);
  p.connect(&p, SIGNAL(aboutToChange()), &r, SLOT(aboutToChange()));
  p.connect(&p, SIGNAL(changed()), &r, SLOT(changed()));

  p.setColor(QColor(1, 2, 3));
  EXPECT_EQ(" aboutToChange, v=0; 0; 0 changed, v=1; 2; 3", r.result().toStdString());
}

TEST(EnumProperty, basic)
{
  EnumProperty p;

  EXPECT_EQ(0, p.getOptionInt());

  p.addOption("chub", 10);
  EXPECT_EQ(0, p.getOptionInt());

  p.addOption("foo", 3);
  p.addOption("bar", 999);

  p.setValue("chub");
  EXPECT_EQ(10, p.getOptionInt());

  p.clearOptions();
  EXPECT_EQ(0, p.getOptionInt());
}

int main(int argc, char** argv)
{
  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<commit_msg>Fix memory leaks<commit_after>/*
 * Copyright (c) 2012, Willow Garage, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the Willow Garage, Inc. nor the names of its
 *       contributors may be used to endorse or promote products derived from
 *       this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include <stdio.h>

#include <gtest/gtest.h>

#include <rviz/properties/property.h>
#include <rviz/properties/color_property.h>
#include <rviz/properties/vector_property.h>
#include <rviz/properties/quaternion_property.h>
#include <rviz/properties/enum_property.h>

#include "mock_property_change_receiver.h"

using namespace rviz;

TEST(Property, name)
{
  Property p;
  p.setName("chub");
  EXPECT_EQ("chub", p.getName().toStdString());
}

TEST(Property, description)
{
  Property p;
  p.setDescription("chub");
  EXPECT_EQ("chub", p.getDescription().toStdString());
}

TEST(Property, value)
{
  Property p;
  p.setValue(199);
  EXPECT_EQ(199, p.getValue().toInt());
}

TEST(Property, set_value_events)
{
  Property p;
  p.setValue(0);

  MockPropertyChangeReceiver r(&p);
  p.connect(&p, SIGNAL(aboutToChange()), &r, SLOT(aboutToChange()));
  p.connect(&p, SIGNAL(changed()), &r, SLOT(changed()));

  p.setValue(17);
  EXPECT_EQ(" aboutToChange, v=0 changed, v=17", r.result().toStdString());
}

TEST(Property, children)
{
  Property* display = new Property("Test");
  new Property("Alpha", 0.5, "The amount of transparency to apply to the grid lines.", display);
  Property* beta =
      new Property("Beta Band", 10, "The number of betas to apply to the grid lines.", display);
  new Property("Gamma Topic", "chubby", "The topic on which to listen for Gamma messages.", display);
  Property* position = new Property("Position", QVariant(), "Position of the chub.", display);
  new Property("X", 1.1f, "X component of the position of the chub.", position);
  new Property("Y", 0.717f, "Y component of the position of the chub.", position);

  // Sample usage inside the Display which owns the property.
  int b = beta->getValue().toInt();
  EXPECT_EQ(10, b);

  // Sample usage outside the Display
  beta->setValue(12);
  EXPECT_EQ(12, display->subProp("Beta Band")->getValue().toInt());

  // Compound property
  float y = display->subProp("Position")->subProp("Y")->getValue().toFloat();
  EXPECT_EQ(0.717f, y);

  // Accessing a missing property should not crash.
  printf("Next line should say 'ERROR' but not crash.\n");
  display->subProp("Position")->subProp("Z")->getValue().toFloat();
}

TEST(VectorProperty, default_value)
{
  VectorProperty vp;
  Ogre::Vector3 vec = vp.getVector();
  EXPECT_EQ(0, vec.x);
  EXPECT_EQ(0, vec.y);
  EXPECT_EQ(0, vec.z);
}

TEST(VectorProperty, set_and_get)
{
  VectorProperty vp;
  Ogre::Vector3 vec(1, 2, 3);
  vp.setVector(vec);

  Ogre::Vector3 vec2 = vp.getVector();
  EXPECT_EQ(1, vec2.x);
  EXPECT_EQ(2, vec2.y);
  EXPECT_EQ(3, vec2.z);
}

TEST(VectorProperty, set_string)
{
  VectorProperty vp;
  vp.setValue(QString("1;2;3"));

  Ogre::Vector3 vec = vp.getVector();
  EXPECT_EQ(1, vec.x);
  EXPECT_EQ(2, vec.y);
  EXPECT_EQ(3, vec.z);

  vp.setValue(QString("chubby!"));

  vec = vp.getVector();
  EXPECT_EQ(1, vec.x);
  EXPECT_EQ(2, vec.y);
  EXPECT_EQ(3, vec.z);
}

TEST(VectorProperty, set_child)
{
  VectorProperty vp;
  vp.subProp("X")->setValue(0.9);
  vp.subProp("Y")->setValue(1.1);
  vp.subProp("Z")->setValue(1.3);

  Ogre::Vector3 vec = vp.getVector();
  EXPECT_EQ(0.9f, vec.x);
  EXPECT_EQ(1.1f, vec.y);
  EXPECT_EQ(1.3f, vec.z);
}

TEST(VectorProperty, get_child)
{
  VectorProperty vp("v", Ogre::Vector3(1, 2, 3));
  EXPECT_EQ(1, vp.subProp("X")->getValue().toFloat());
  EXPECT_EQ(2, vp.subProp("Y")->getValue().toFloat());
  EXPECT_EQ(3, vp.subProp("Z")->getValue().toFloat());
}

TEST(VectorProperty, set_value_events)
{
  VectorProperty p;

  MockPropertyChangeReceiver r(&p);
  p.connect(&p, SIGNAL(aboutToChange()), &r, SLOT(aboutToChange()));
  p.connect(&p, SIGNAL(changed()), &r, SLOT(changed()));

  p.setVector(Ogre::Vector3(.1, .0001, 1000));
  EXPECT_EQ(" aboutToChange, v=0; 0; 0 changed, v=0.1; 0.0001; 1000", r.result().toStdString());
  r.reset();

  p.subProp("Z")->setValue(2.1);
  EXPECT_EQ(" aboutToChange, v=0.1; 0.0001; 1000 changed, v=0.1; 0.0001; 2.1", r.result().toStdString());
}

TEST(QuaternionProperty, default_value)
{
  QuaternionProperty qp;
  Ogre::Quaternion quat = qp.getQuaternion();
  EXPECT_EQ(0, quat.x);
  EXPECT_EQ(0, quat.y);
  EXPECT_EQ(0, quat.z);
  EXPECT_EQ(1, quat.w);
}

TEST(QuaternionProperty, set_and_get)
{
  QuaternionProperty qp;
  Ogre::Quaternion quat(4, 1, 2, 3);
  qp.setQuaternion(quat);

  Ogre::Quaternion quat2 = qp.getQuaternion();
  EXPECT_EQ(1, quat2.x);
  EXPECT_EQ(2, quat2.y);
  EXPECT_EQ(3, quat2.z);
  EXPECT_EQ(4, quat2.w);
}

TEST(QuaternionProperty, set_string)
{
  QuaternionProperty qp;
  qp.setValue(QString("1;2;3;4"));

  Ogre::Quaternion quat = qp.getQuaternion();
  EXPECT_EQ(1, quat.x);
  EXPECT_EQ(2, quat.y);
  EXPECT_EQ(3, quat.z);
  EXPECT_EQ(4, quat.w);

  qp.setValue(QString("chubby!"));

  quat = qp.getQuaternion();
  EXPECT_EQ(1, quat.x);
  EXPECT_EQ(2, quat.y);
  EXPECT_EQ(3, quat.z);
  EXPECT_EQ(4, quat.w);
}

TEST(QuaternionProperty, set_child)
{
  QuaternionProperty qp;
  qp.subProp("X")->setValue(0.9);
  qp.subProp("Y")->setValue(1.1);
  qp.subProp("Z")->setValue(1.3);
  qp.subProp("W")->setValue(1.5);

  Ogre::Quaternion quat = qp.getQuaternion();
  EXPECT_EQ(0.9f, quat.x);
  EXPECT_EQ(1.1f, quat.y);
  EXPECT_EQ(1.3f, quat.z);
  EXPECT_EQ(1.5f, quat.w);
}

TEST(QuaternionProperty, get_child)
{
  QuaternionProperty qp("v", Ogre::Quaternion(4, 1, 2, 3));
  EXPECT_EQ(1, qp.subProp("X")->getValue().toFloat());
  EXPECT_EQ(2, qp.subProp("Y")->getValue().toFloat());
  EXPECT_EQ(3, qp.subProp("Z")->getValue().toFloat());
  EXPECT_EQ(4, qp.subProp("W")->getValue().toFloat());
}

TEST(QuaternionProperty, set_value_events)
{
  QuaternionProperty p;

  MockPropertyChangeReceiver r(&p);
  p.connect(&p, SIGNAL(aboutToChange()), &r, SLOT(aboutToChange()));
  p.connect(&p, SIGNAL(changed()), &r, SLOT(changed()));

  p.setQuaternion(Ogre::Quaternion(1, .1, .0001, 1000));
  EXPECT_EQ(" aboutToChange, v=0; 0; 0; 1 changed, v=0.1; 0.0001; 1000; 1", r.result().toStdString());
  r.reset();

  p.subProp("Z")->setValue(2.1);
  EXPECT_EQ(" aboutToChange, v=0.1; 0.0001; 1000; 1 changed, v=0.1; 0.0001; 2.1; 1",
            r.result().toStdString());
}

TEST(ColorProperty, default_value)
{
  ColorProperty qp;
  QColor color = qp.getColor();
  EXPECT_EQ(0, color.red());
  EXPECT_EQ(0, color.green());
  EXPECT_EQ(0, color.blue());
}

TEST(ColorProperty, set_and_get)
{
  ColorProperty qp;
  QColor color(1, 2, 3);
  qp.setColor(color);

  QColor color2 = qp.getColor();
  EXPECT_EQ(1, color2.red());
  EXPECT_EQ(2, color2.green());
  EXPECT_EQ(3, color2.blue());
}

TEST(ColorProperty, set_string)
{
  ColorProperty qp;
  qp.setValue(QString("1;2;3"));

  QColor color = qp.getColor();
  EXPECT_EQ(1, color.red());
  EXPECT_EQ(2, color.green());
  EXPECT_EQ(3, color.blue());

  qp.setValue(QString("chubby!"));

  color = qp.getColor();
  EXPECT_EQ(1, color.red());
  EXPECT_EQ(2, color.green());
  EXPECT_EQ(3, color.blue());
}

TEST(ColorProperty, set_string_limits)
{
  ColorProperty qp;
  qp.setValue(QString("-1;2000;3"));

  QColor color = qp.getColor();
  EXPECT_EQ(0, color.red());
  EXPECT_EQ(255, color.green());
  EXPECT_EQ(3, color.blue());
}

TEST(ColorProperty, set_value_events)
{
  ColorProperty p;

  MockPropertyChangeReceiver r(&p);
  p.connect(&p, SIGNAL(aboutToChange()), &r, SLOT(aboutToChange()));
  p.connect(&p, SIGNAL(changed()), &r, SLOT(changed()));

  p.setColor(QColor(1, 2, 3));
  EXPECT_EQ(" aboutToChange, v=0; 0; 0 changed, v=1; 2; 3", r.result().toStdString());
}

TEST(EnumProperty, basic)
{
  EnumProperty p;

  EXPECT_EQ(0, p.getOptionInt());

  p.addOption("chub", 10);
  EXPECT_EQ(0, p.getOptionInt());

  p.addOption("foo", 3);
  p.addOption("bar", 999);

  p.setValue("chub");
  EXPECT_EQ(10, p.getOptionInt());

  p.clearOptions();
  EXPECT_EQ(0, p.getOptionInt());
}

int main(int argc, char** argv)
{
  testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>/*

    Copyright Eli Dupree and Isaac Dupree, 2011, 2012

    This file is part of Lasercake.

    Lasercake is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as
    published by the Free Software Foundation, either version 3 of the
    License, or (at your option) any later version.

    Lasercake 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 Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with Lasercake.  If not, see <http://www.gnu.org/licenses/>.

*/

#include <climits>
#include "world.hpp"
#include "worldgen.hpp"

world::world(shared_ptr<worldgen_type> gen)
  : current_game_time_(0),
    tile_physics_state_(*this),
    next_object_identifier_(1),
    worldgen_(gen) {}

void world::update(unordered_map<object_identifier, input_representation::input_news_t> input) {
  laser_sfxes_.clear();
  update_fluids();
  const input_representation::input_news_t no_input;
  for (auto& obj : autonomously_active_objects_) {
    input_representation::input_news_t const* input_for_obj = find_as_pointer(input, obj.first);
    if (input_for_obj == nullptr) { input_for_obj = &no_input; }
    obj.second->update(*this, *input_for_obj, obj.first);
  }
  update_moving_objects();
  //TODO update_light(vector3<distance>(3,10,-999), 3);
  for(the_decomposition_of_the_world_into_blocks_impl::worldblock* wb : worldblocks_suggested_to_delete_) {
    if(wb->is_deletable()) {
      //blocks_.erase(wb->global_position_);
    }
  }
  current_game_time_ += 1*fixed_frame_lengths * identity(time_units / fixed_frame_lengths);
}

object_identifier world::try_create_object(shared_ptr<object> obj) {
    // fail (and return NO_OBJECT) if there's something in the way
    const shape obj_shape = obj->get_initial_personal_space_shape();
    vector<object_identifier> objects_this_could_collide_with;
    objects_exposed_to_collision_.get_objects_overlapping(objects_this_could_collide_with, obj_shape.bounds());
    for (auto oid : objects_this_could_collide_with) {
      // We use volume_intersects so that tile aligned objects can be placed next to each other.
      if (object_personal_space_shapes_.find(oid)->second.volume_intersects(obj_shape)){
        return NO_OBJECT;
      }
    }

    object_identifier id = next_object_identifier_++;
    objects_.insert(make_pair(id, obj));
    bounding_box b; // TODO: in mobile_objects.cpp, include detail_shape in at least the final box left in the ztree
    object_personal_space_shapes_[id] = obj_shape;
    b.combine_with(object_personal_space_shapes_[id].bounds());
    object_detail_shapes_[id] = obj->get_initial_detail_shape();
    b.combine_with(object_detail_shapes_[id].bounds());
    objects_exposed_to_collision_.insert(id, b);
    if(shared_ptr<mobile_object> m = boost::dynamic_pointer_cast<mobile_object>(obj)) {
      moving_objects_.insert(make_pair(id, m));
    }
    // TODO: don't do this if you're in the middle of updating autonomous objects
    if(shared_ptr<autonomous_object> m = boost::dynamic_pointer_cast<autonomous_object>(obj)) {
      autonomously_active_objects_.insert(make_pair(id, m));
    }
    return id;
  }

bounding_box world::get_bounding_box_of_object_or_tile(object_or_tile_identifier id)const {
  if (tile_location const* tlocp = id.get_tile_location()) {
    return fine_bounding_box_of_tile(tlocp->coords());
  }
  if (object_identifier const* oidp = id.get_object_identifier()) {
    //TODO is this impl a hack? and what about non-mobile objects?
    auto const* result = objects_exposed_to_collision_.find_bounding_box(*oidp);
    assert(result != nullptr);
    return *result;
  }
  assert(false);
}
shape world::get_personal_space_shape_of_object_or_tile(object_or_tile_identifier id)const {
  if (tile_location const* tlocp = id.get_tile_location()) {
    return tile_shape(tlocp->coords());
  }
  if (object_identifier const* oidp = id.get_object_identifier()) {
    return object_personal_space_shapes_.find(*oidp)->second;
  }
  assert(false);
}
shape world::get_detail_shape_of_object_or_tile(object_or_tile_identifier id)const {
  if (tile_location const* tlocp = id.get_tile_location()) {
    return tile_shape(tlocp->coords());
  }
  if (object_identifier const* oidp = id.get_object_identifier()) {
    return object_personal_space_shapes_.find(*oidp)->second;
  }
  assert(false);
}

bool literally_random_access_removable_tiles_by_height::erase(tile_location const& loc) {
  auto j = data_.find(loc.coords().z);
  if (j != data_.end()) {
    if (j->second.erase(loc)) {
      if (j->second.empty()) {
        data_.erase(j);
      }
      return true;
    }
  }
  return false;
}
void literally_random_access_removable_tiles_by_height::insert(tile_location const& loc) {
  // Note: operator[] default-constructs an empty structure if there wasn't one
  data_[loc.coords().z].insert(loc);
}

bool literally_random_access_removable_tiles_by_height::any_above(tile_coordinate height)const {
  return data_.upper_bound(height) != data_.end();
}
bool literally_random_access_removable_tiles_by_height::any_below(tile_coordinate height)const {
  return (!data_.empty()) && (data_.begin()->first < height);
}

bool tile_compare_xyz::operator()(tile_location const& i, tile_location const& j)const {
  vector3<tile_coordinate> c1 = i.coords();
  vector3<tile_coordinate> c2 = j.coords();
  return (c1.x < c2.x) || ((c1.x == c2.x) && ((c1.y < c2.y) || ((c1.y == c2.y) && (c1.z < c2.z))));
}
bool tile_compare_yzx::operator()(tile_location const& i, tile_location const& j)const {
  vector3<tile_coordinate> c1 = i.coords();
  vector3<tile_coordinate> c2 = j.coords();
  return (c1.y < c2.y) || ((c1.y == c2.y) && ((c1.z < c2.z) || ((c1.z == c2.z) && (c1.x < c2.x))));
}
bool tile_compare_zxy::operator()(tile_location const& i, tile_location const& j)const {
  vector3<tile_coordinate> c1 = i.coords();
  vector3<tile_coordinate> c2 = j.coords();
  return (c1.z < c2.z) || ((c1.z == c2.z) && ((c1.x < c2.x) || ((c1.x == c2.x) && (c1.y < c2.y))));
}

// Double-check (not thoroughly) that the compilers aren't lying about word sizes
// and use 8-bit bytes and two's complement arithmetic.
// Hopefully this means that integer variations won't cause two people's compiles
// of this program to behave differently.
static_assert(CHAR_BIT == 8, "8 bits in a byte (claims limits.h)");
static_assert(uint8_t(254) < uint8_t(255) && uint8_t(255) > uint8_t(256),
              "8 bits in a byte (observed at compile-time)");
static_assert(sizeof(uint64_t)*8 == 64, "uint64_t is 64 bit");
static_assert(sizeof(int64_t)*8 == 64, "int64_t is 64 bit");
static_assert(sizeof(uint32_t)*8 == 32, "uint32_t is 32 bit");
static_assert(sizeof(int32_t)*8 == 32, "int32_t is 32 bit");
static_assert(sizeof(uint16_t)*8 == 16, "uint16_t is 16 bit");
static_assert(sizeof(int16_t)*8 == 16, "int16_t is 16 bit");
static_assert(sizeof(uint8_t)*8 == 8, "uint8_t is 8 bit");
static_assert(sizeof(int8_t)*8 == 8, "int8_t is 8 bit");
static_assert((uint32_t)0xffffffffUL == 0xffffffffUL, "max uint32_t fits");
static_assert((uint32_t)0xffffffffUL + (uint32_t)1 == (uint32_t)0, "max uint32_t + 1 doesn't fit");
static_assert((int32_t)(uint32_t)0x80000000UL < 0, "min int32_t < 0");
static_assert((int32_t)(uint32_t)0x7fffffffUL > 0, "max int32_t > 0");
<commit_msg>added obvious missing clear()<commit_after>/*

    Copyright Eli Dupree and Isaac Dupree, 2011, 2012

    This file is part of Lasercake.

    Lasercake is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as
    published by the Free Software Foundation, either version 3 of the
    License, or (at your option) any later version.

    Lasercake 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 Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with Lasercake.  If not, see <http://www.gnu.org/licenses/>.

*/

#include <climits>
#include "world.hpp"
#include "worldgen.hpp"

world::world(shared_ptr<worldgen_type> gen)
  : current_game_time_(0),
    tile_physics_state_(*this),
    next_object_identifier_(1),
    worldgen_(gen) {}

void world::update(unordered_map<object_identifier, input_representation::input_news_t> input) {
  laser_sfxes_.clear();
  update_fluids();
  const input_representation::input_news_t no_input;
  for (auto& obj : autonomously_active_objects_) {
    input_representation::input_news_t const* input_for_obj = find_as_pointer(input, obj.first);
    if (input_for_obj == nullptr) { input_for_obj = &no_input; }
    obj.second->update(*this, *input_for_obj, obj.first);
  }
  update_moving_objects();
  //TODO update_light(vector3<distance>(3,10,-999), 3);
  for(the_decomposition_of_the_world_into_blocks_impl::worldblock* wb : worldblocks_suggested_to_delete_) {
    if(wb->is_deletable()) {
      //blocks_.erase(wb->global_position_);
    }
  }
  worldblocks_suggested_to_delete_.clear();
  current_game_time_ += 1*fixed_frame_lengths * identity(time_units / fixed_frame_lengths);
}

object_identifier world::try_create_object(shared_ptr<object> obj) {
    // fail (and return NO_OBJECT) if there's something in the way
    const shape obj_shape = obj->get_initial_personal_space_shape();
    vector<object_identifier> objects_this_could_collide_with;
    objects_exposed_to_collision_.get_objects_overlapping(objects_this_could_collide_with, obj_shape.bounds());
    for (auto oid : objects_this_could_collide_with) {
      // We use volume_intersects so that tile aligned objects can be placed next to each other.
      if (object_personal_space_shapes_.find(oid)->second.volume_intersects(obj_shape)){
        return NO_OBJECT;
      }
    }

    object_identifier id = next_object_identifier_++;
    objects_.insert(make_pair(id, obj));
    bounding_box b; // TODO: in mobile_objects.cpp, include detail_shape in at least the final box left in the ztree
    object_personal_space_shapes_[id] = obj_shape;
    b.combine_with(object_personal_space_shapes_[id].bounds());
    object_detail_shapes_[id] = obj->get_initial_detail_shape();
    b.combine_with(object_detail_shapes_[id].bounds());
    objects_exposed_to_collision_.insert(id, b);
    if(shared_ptr<mobile_object> m = boost::dynamic_pointer_cast<mobile_object>(obj)) {
      moving_objects_.insert(make_pair(id, m));
    }
    // TODO: don't do this if you're in the middle of updating autonomous objects
    if(shared_ptr<autonomous_object> m = boost::dynamic_pointer_cast<autonomous_object>(obj)) {
      autonomously_active_objects_.insert(make_pair(id, m));
    }
    return id;
  }

bounding_box world::get_bounding_box_of_object_or_tile(object_or_tile_identifier id)const {
  if (tile_location const* tlocp = id.get_tile_location()) {
    return fine_bounding_box_of_tile(tlocp->coords());
  }
  if (object_identifier const* oidp = id.get_object_identifier()) {
    //TODO is this impl a hack? and what about non-mobile objects?
    auto const* result = objects_exposed_to_collision_.find_bounding_box(*oidp);
    assert(result != nullptr);
    return *result;
  }
  assert(false);
}
shape world::get_personal_space_shape_of_object_or_tile(object_or_tile_identifier id)const {
  if (tile_location const* tlocp = id.get_tile_location()) {
    return tile_shape(tlocp->coords());
  }
  if (object_identifier const* oidp = id.get_object_identifier()) {
    return object_personal_space_shapes_.find(*oidp)->second;
  }
  assert(false);
}
shape world::get_detail_shape_of_object_or_tile(object_or_tile_identifier id)const {
  if (tile_location const* tlocp = id.get_tile_location()) {
    return tile_shape(tlocp->coords());
  }
  if (object_identifier const* oidp = id.get_object_identifier()) {
    return object_personal_space_shapes_.find(*oidp)->second;
  }
  assert(false);
}

bool literally_random_access_removable_tiles_by_height::erase(tile_location const& loc) {
  auto j = data_.find(loc.coords().z);
  if (j != data_.end()) {
    if (j->second.erase(loc)) {
      if (j->second.empty()) {
        data_.erase(j);
      }
      return true;
    }
  }
  return false;
}
void literally_random_access_removable_tiles_by_height::insert(tile_location const& loc) {
  // Note: operator[] default-constructs an empty structure if there wasn't one
  data_[loc.coords().z].insert(loc);
}

bool literally_random_access_removable_tiles_by_height::any_above(tile_coordinate height)const {
  return data_.upper_bound(height) != data_.end();
}
bool literally_random_access_removable_tiles_by_height::any_below(tile_coordinate height)const {
  return (!data_.empty()) && (data_.begin()->first < height);
}

bool tile_compare_xyz::operator()(tile_location const& i, tile_location const& j)const {
  vector3<tile_coordinate> c1 = i.coords();
  vector3<tile_coordinate> c2 = j.coords();
  return (c1.x < c2.x) || ((c1.x == c2.x) && ((c1.y < c2.y) || ((c1.y == c2.y) && (c1.z < c2.z))));
}
bool tile_compare_yzx::operator()(tile_location const& i, tile_location const& j)const {
  vector3<tile_coordinate> c1 = i.coords();
  vector3<tile_coordinate> c2 = j.coords();
  return (c1.y < c2.y) || ((c1.y == c2.y) && ((c1.z < c2.z) || ((c1.z == c2.z) && (c1.x < c2.x))));
}
bool tile_compare_zxy::operator()(tile_location const& i, tile_location const& j)const {
  vector3<tile_coordinate> c1 = i.coords();
  vector3<tile_coordinate> c2 = j.coords();
  return (c1.z < c2.z) || ((c1.z == c2.z) && ((c1.x < c2.x) || ((c1.x == c2.x) && (c1.y < c2.y))));
}

// Double-check (not thoroughly) that the compilers aren't lying about word sizes
// and use 8-bit bytes and two's complement arithmetic.
// Hopefully this means that integer variations won't cause two people's compiles
// of this program to behave differently.
static_assert(CHAR_BIT == 8, "8 bits in a byte (claims limits.h)");
static_assert(uint8_t(254) < uint8_t(255) && uint8_t(255) > uint8_t(256),
              "8 bits in a byte (observed at compile-time)");
static_assert(sizeof(uint64_t)*8 == 64, "uint64_t is 64 bit");
static_assert(sizeof(int64_t)*8 == 64, "int64_t is 64 bit");
static_assert(sizeof(uint32_t)*8 == 32, "uint32_t is 32 bit");
static_assert(sizeof(int32_t)*8 == 32, "int32_t is 32 bit");
static_assert(sizeof(uint16_t)*8 == 16, "uint16_t is 16 bit");
static_assert(sizeof(int16_t)*8 == 16, "int16_t is 16 bit");
static_assert(sizeof(uint8_t)*8 == 8, "uint8_t is 8 bit");
static_assert(sizeof(int8_t)*8 == 8, "int8_t is 8 bit");
static_assert((uint32_t)0xffffffffUL == 0xffffffffUL, "max uint32_t fits");
static_assert((uint32_t)0xffffffffUL + (uint32_t)1 == (uint32_t)0, "max uint32_t + 1 doesn't fit");
static_assert((int32_t)(uint32_t)0x80000000UL < 0, "min int32_t < 0");
static_assert((int32_t)(uint32_t)0x7fffffffUL > 0, "max int32_t > 0");
<|endoftext|>


<commit_before>/*
 * Copyright 2018 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "include/core/SkCanvas.h"
#include "include/core/SkGraphics.h"
#include "include/core/SkPictureRecorder.h"
#include "include/core/SkStream.h"
#include "include/core/SkSurface.h"
#include "include/encode/SkPngEncoder.h"
#include "modules/skottie/include/Skottie.h"
#include "modules/skottie/utils/SkottieUtils.h"
#include "src/core/SkMakeUnique.h"
#include "src/core/SkOSFile.h"
#include "src/core/SkTaskGroup.h"
#include "src/utils/SkOSPath.h"
#include "tools/flags/CommandLineFlags.h"

#include <vector>

static DEFINE_string2(input    , i, nullptr, "Input .json file.");
static DEFINE_string2(writePath, w, nullptr, "Output directory.  Frames are names [0-9]{6}.png.");
static DEFINE_string2(format   , f, "png"  , "Output format (png or skp)");

static DEFINE_double(t0,   0, "Timeline start [0..1].");
static DEFINE_double(t1,   1, "Timeline stop [0..1].");
static DEFINE_double(fps, 30, "Decode frames per second.");

static DEFINE_int(width , 800, "Render width.");
static DEFINE_int(height, 600, "Render height.");
static DEFINE_int(threads,  0, "Number of worker threads (0 -> cores count).");

namespace {

class Sink {
public:
    virtual ~Sink() = default;
    Sink(const Sink&) = delete;
    Sink& operator=(const Sink&) = delete;

    bool handleFrame(const skottie::Animation* anim, size_t idx) const {
        const auto frame_file = SkStringPrintf("0%06d.%s", idx, fExtension.c_str());
        SkFILEWStream stream (SkOSPath::Join(FLAGS_writePath[0], frame_file.c_str()).c_str());

        if (!stream.isValid()) {
            SkDebugf("Could not open '%s/%s' for writing.\n",
                     FLAGS_writePath[0], frame_file.c_str());
            return false;
        }

        return this->saveFrame(anim, &stream);
    }

protected:
    Sink(const char* ext) : fExtension(ext) {}

    virtual bool saveFrame(const skottie::Animation* anim, SkFILEWStream*) const = 0;

private:
    const SkString fExtension;
};

class PNGSink final : public Sink {
public:
    PNGSink()
        : INHERITED("png")
        , fSurface(SkSurface::MakeRasterN32Premul(FLAGS_width, FLAGS_height)) {
        if (!fSurface) {
            SkDebugf("Could not allocate a %d x %d surface.\n", FLAGS_width, FLAGS_height);
        }
    }

    bool saveFrame(const skottie::Animation* anim, SkFILEWStream* stream) const override {
        if (!fSurface) return false;

        auto* canvas = fSurface->getCanvas();
        SkAutoCanvasRestore acr(canvas, true);

        canvas->concat(SkMatrix::MakeRectToRect(SkRect::MakeSize(anim->size()),
                                                SkRect::MakeIWH(FLAGS_width, FLAGS_height),
                                                SkMatrix::kCenter_ScaleToFit));

        canvas->clear(SK_ColorTRANSPARENT);
        anim->render(canvas);

        // Set encoding options to favor speed over size.
        SkPngEncoder::Options options;
        options.fZLibLevel   = 1;
        options.fFilterFlags = SkPngEncoder::FilterFlag::kNone;

        sk_sp<SkImage> img = fSurface->makeImageSnapshot();
        SkPixmap pixmap;
        return img->peekPixels(&pixmap)
            && SkPngEncoder::Encode(stream, pixmap, options);
    }

private:
    const sk_sp<SkSurface> fSurface;

    using INHERITED = Sink;
};

class SKPSink final : public Sink {
public:
    SKPSink() : INHERITED("skp") {}

    bool saveFrame(const skottie::Animation* anim, SkFILEWStream* stream) const override {
        SkPictureRecorder recorder;

        auto canvas = recorder.beginRecording(FLAGS_width, FLAGS_height);
        canvas->concat(SkMatrix::MakeRectToRect(SkRect::MakeSize(anim->size()),
                                                SkRect::MakeIWH(FLAGS_width, FLAGS_height),
                                                SkMatrix::kCenter_ScaleToFit));
        anim->render(canvas);
        recorder.finishRecordingAsPicture()->serialize(stream);

        return true;
    }

private:
    const sk_sp<SkSurface> fSurface;

    using INHERITED = Sink;
};

class Logger final : public skottie::Logger {
public:
    struct LogEntry {
        SkString fMessage,
                 fJSON;
    };

    void log(skottie::Logger::Level lvl, const char message[], const char json[]) override {
        auto& log = lvl == skottie::Logger::Level::kError ? fErrors : fWarnings;
        log.push_back({ SkString(message), json ? SkString(json) : SkString() });
    }

    void report() const {
        SkDebugf("Animation loaded with %lu error%s, %lu warning%s.\n",
                 fErrors.size(), fErrors.size() == 1 ? "" : "s",
                 fWarnings.size(), fWarnings.size() == 1 ? "" : "s");

        const auto& show = [](const LogEntry& log, const char prefix[]) {
            SkDebugf("%s%s", prefix, log.fMessage.c_str());
            if (!log.fJSON.isEmpty())
                SkDebugf(" : %s", log.fJSON.c_str());
            SkDebugf("\n");
        };

        for (const auto& err : fErrors)   show(err, "  !! ");
        for (const auto& wrn : fWarnings) show(wrn, "  ?? ");
    }

private:
    std::vector<LogEntry> fErrors,
                          fWarnings;
};

std::unique_ptr<Sink> MakeSink(const char* fmt) {
    if (0 == strcmp(fmt, "png")) {
        return skstd::make_unique<PNGSink>();
    }
    if (0 == strcmp(fmt, "skp")) {
        return skstd::make_unique<SKPSink>();
    }

    SkDebugf("Unknown format: %s\n", FLAGS_format[0]);
    return nullptr;
}

} // namespace

int main(int argc, char** argv) {
    CommandLineFlags::Parse(argc, argv);
    SkAutoGraphics ag;

    if (FLAGS_input.isEmpty() || FLAGS_writePath.isEmpty()) {
        SkDebugf("Missing required 'input' and 'writePath' args.\n");
        return 1;
    }

    if (FLAGS_fps <= 0) {
        SkDebugf("Invalid fps: %f.\n", FLAGS_fps);
        return 1;
    }

    if (!sk_mkdir(FLAGS_writePath[0])) {
        return 1;
    }

    auto logger = sk_make_sp<Logger>();
    auto     rp = skottie_utils::CachingResourceProvider::Make(
                      skottie_utils::FileResourceProvider::Make(SkOSPath::Dirname(FLAGS_input[0]),
                                                                /*predecode=*/true));
    auto data   = SkData::MakeFromFileName(FLAGS_input[0]);

    if (!data) {
        SkDebugf("Could not load %s.\n", FLAGS_input[0]);
        return 1;
    }

    // Instantiate an animation on the main thread for two reasons:
    //   - we need to know its duration upfront
    //   - we want to only report parsing errors once
    auto anim = skottie::Animation::Builder()
            .setLogger(logger)
            .setResourceProvider(rp)
            .make(static_cast<const char*>(data->data()), data->size());
    if (!anim) {
        SkDebugf("Could not parse animation: '%s'.\n", FLAGS_input[0]);
        return 1;
    }

    logger->report();

    static constexpr double kMaxFrames = 10000;
    const auto t0 = SkTPin(FLAGS_t0, 0.0, 1.0),
               t1 = SkTPin(FLAGS_t1,  t0, 1.0),
               dt = 1 / std::min(anim->duration() * FLAGS_fps, kMaxFrames);

    const auto frame_count = static_cast<int>((t1 - t0) / dt);

    SkTaskGroup::Enabler enabler(FLAGS_threads - 1);
    SkTaskGroup{}.batch(frame_count, [&](int i) {
        thread_local static auto* tl_sink = MakeSink(FLAGS_format[0]).release();
        thread_local static auto* tl_anim =
                skottie::Animation::Builder()
                    .setResourceProvider(rp)
                    .make(static_cast<const char*>(data->data()), data->size())
                    .release();

        if (tl_sink && tl_anim) {
            tl_anim->seek(t0 + dt * i);
            tl_sink->handleFrame(tl_anim, i);
        }
    });

    return 0;
}
<commit_msg>[skottie] Disable skottie_tool on iOS<commit_after>/*
 * Copyright 2018 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "include/core/SkCanvas.h"
#include "include/core/SkGraphics.h"
#include "include/core/SkPictureRecorder.h"
#include "include/core/SkStream.h"
#include "include/core/SkSurface.h"
#include "include/encode/SkPngEncoder.h"
#include "modules/skottie/include/Skottie.h"
#include "modules/skottie/utils/SkottieUtils.h"
#include "src/core/SkMakeUnique.h"
#include "src/core/SkOSFile.h"
#include "src/core/SkTaskGroup.h"
#include "src/utils/SkOSPath.h"
#include "tools/flags/CommandLineFlags.h"

#include <vector>

static DEFINE_string2(input    , i, nullptr, "Input .json file.");
static DEFINE_string2(writePath, w, nullptr, "Output directory.  Frames are names [0-9]{6}.png.");
static DEFINE_string2(format   , f, "png"  , "Output format (png or skp)");

static DEFINE_double(t0,   0, "Timeline start [0..1].");
static DEFINE_double(t1,   1, "Timeline stop [0..1].");
static DEFINE_double(fps, 30, "Decode frames per second.");

static DEFINE_int(width , 800, "Render width.");
static DEFINE_int(height, 600, "Render height.");
static DEFINE_int(threads,  0, "Number of worker threads (0 -> cores count).");

namespace {

class Sink {
public:
    virtual ~Sink() = default;
    Sink(const Sink&) = delete;
    Sink& operator=(const Sink&) = delete;

    bool handleFrame(const skottie::Animation* anim, size_t idx) const {
        const auto frame_file = SkStringPrintf("0%06d.%s", idx, fExtension.c_str());
        SkFILEWStream stream (SkOSPath::Join(FLAGS_writePath[0], frame_file.c_str()).c_str());

        if (!stream.isValid()) {
            SkDebugf("Could not open '%s/%s' for writing.\n",
                     FLAGS_writePath[0], frame_file.c_str());
            return false;
        }

        return this->saveFrame(anim, &stream);
    }

protected:
    Sink(const char* ext) : fExtension(ext) {}

    virtual bool saveFrame(const skottie::Animation* anim, SkFILEWStream*) const = 0;

private:
    const SkString fExtension;
};

class PNGSink final : public Sink {
public:
    PNGSink()
        : INHERITED("png")
        , fSurface(SkSurface::MakeRasterN32Premul(FLAGS_width, FLAGS_height)) {
        if (!fSurface) {
            SkDebugf("Could not allocate a %d x %d surface.\n", FLAGS_width, FLAGS_height);
        }
    }

    bool saveFrame(const skottie::Animation* anim, SkFILEWStream* stream) const override {
        if (!fSurface) return false;

        auto* canvas = fSurface->getCanvas();
        SkAutoCanvasRestore acr(canvas, true);

        canvas->concat(SkMatrix::MakeRectToRect(SkRect::MakeSize(anim->size()),
                                                SkRect::MakeIWH(FLAGS_width, FLAGS_height),
                                                SkMatrix::kCenter_ScaleToFit));

        canvas->clear(SK_ColorTRANSPARENT);
        anim->render(canvas);

        // Set encoding options to favor speed over size.
        SkPngEncoder::Options options;
        options.fZLibLevel   = 1;
        options.fFilterFlags = SkPngEncoder::FilterFlag::kNone;

        sk_sp<SkImage> img = fSurface->makeImageSnapshot();
        SkPixmap pixmap;
        return img->peekPixels(&pixmap)
            && SkPngEncoder::Encode(stream, pixmap, options);
    }

private:
    const sk_sp<SkSurface> fSurface;

    using INHERITED = Sink;
};

class SKPSink final : public Sink {
public:
    SKPSink() : INHERITED("skp") {}

    bool saveFrame(const skottie::Animation* anim, SkFILEWStream* stream) const override {
        SkPictureRecorder recorder;

        auto canvas = recorder.beginRecording(FLAGS_width, FLAGS_height);
        canvas->concat(SkMatrix::MakeRectToRect(SkRect::MakeSize(anim->size()),
                                                SkRect::MakeIWH(FLAGS_width, FLAGS_height),
                                                SkMatrix::kCenter_ScaleToFit));
        anim->render(canvas);
        recorder.finishRecordingAsPicture()->serialize(stream);

        return true;
    }

private:
    const sk_sp<SkSurface> fSurface;

    using INHERITED = Sink;
};

class Logger final : public skottie::Logger {
public:
    struct LogEntry {
        SkString fMessage,
                 fJSON;
    };

    void log(skottie::Logger::Level lvl, const char message[], const char json[]) override {
        auto& log = lvl == skottie::Logger::Level::kError ? fErrors : fWarnings;
        log.push_back({ SkString(message), json ? SkString(json) : SkString() });
    }

    void report() const {
        SkDebugf("Animation loaded with %lu error%s, %lu warning%s.\n",
                 fErrors.size(), fErrors.size() == 1 ? "" : "s",
                 fWarnings.size(), fWarnings.size() == 1 ? "" : "s");

        const auto& show = [](const LogEntry& log, const char prefix[]) {
            SkDebugf("%s%s", prefix, log.fMessage.c_str());
            if (!log.fJSON.isEmpty())
                SkDebugf(" : %s", log.fJSON.c_str());
            SkDebugf("\n");
        };

        for (const auto& err : fErrors)   show(err, "  !! ");
        for (const auto& wrn : fWarnings) show(wrn, "  ?? ");
    }

private:
    std::vector<LogEntry> fErrors,
                          fWarnings;
};

std::unique_ptr<Sink> MakeSink(const char* fmt) {
    if (0 == strcmp(fmt, "png")) {
        return skstd::make_unique<PNGSink>();
    }
    if (0 == strcmp(fmt, "skp")) {
        return skstd::make_unique<SKPSink>();
    }

    SkDebugf("Unknown format: %s\n", FLAGS_format[0]);
    return nullptr;
}

} // namespace

int main(int argc, char** argv) {
    CommandLineFlags::Parse(argc, argv);
    SkAutoGraphics ag;

    if (FLAGS_input.isEmpty() || FLAGS_writePath.isEmpty()) {
        SkDebugf("Missing required 'input' and 'writePath' args.\n");
        return 1;
    }

    if (FLAGS_fps <= 0) {
        SkDebugf("Invalid fps: %f.\n", FLAGS_fps);
        return 1;
    }

    if (!sk_mkdir(FLAGS_writePath[0])) {
        return 1;
    }

    auto logger = sk_make_sp<Logger>();
    auto     rp = skottie_utils::CachingResourceProvider::Make(
                      skottie_utils::FileResourceProvider::Make(SkOSPath::Dirname(FLAGS_input[0]),
                                                                /*predecode=*/true));
    auto data   = SkData::MakeFromFileName(FLAGS_input[0]);

    if (!data) {
        SkDebugf("Could not load %s.\n", FLAGS_input[0]);
        return 1;
    }

    // Instantiate an animation on the main thread for two reasons:
    //   - we need to know its duration upfront
    //   - we want to only report parsing errors once
    auto anim = skottie::Animation::Builder()
            .setLogger(logger)
            .setResourceProvider(rp)
            .make(static_cast<const char*>(data->data()), data->size());
    if (!anim) {
        SkDebugf("Could not parse animation: '%s'.\n", FLAGS_input[0]);
        return 1;
    }

    logger->report();

    static constexpr double kMaxFrames = 10000;
    const auto t0 = SkTPin(FLAGS_t0, 0.0, 1.0),
               t1 = SkTPin(FLAGS_t1,  t0, 1.0),
               dt = 1 / std::min(anim->duration() * FLAGS_fps, kMaxFrames);

    const auto frame_count = static_cast<int>((t1 - t0) / dt);

    SkTaskGroup::Enabler enabler(FLAGS_threads - 1);
    SkTaskGroup{}.batch(frame_count, [&](int i) {
#if defined(SK_BUILD_FOR_IOS)
        // iOS doesn't support thread_local on versions less than 9.0.
        auto tl_sink = MakeSink(FLAGS_format[0]);
        auto    anim = skottie::Animation::Builder()
                            .setResourceProvider(rp)
                            .make(static_cast<const char*>(data->data()), data->size());
        auto* tl_anim = anim.get();
#else
        thread_local static auto* tl_sink = MakeSink(FLAGS_format[0]).release();
        thread_local static auto* tl_anim =
                skottie::Animation::Builder()
                    .setResourceProvider(rp)
                    .make(static_cast<const char*>(data->data()), data->size())
                    .release();
#endif

        if (tl_sink && tl_anim) {
            tl_anim->seek(t0 + dt * i);
            tl_sink->handleFrame(tl_anim, i);
        }
    });

    return 0;
}
<|endoftext|>


<commit_before>// Copyright (c) 2011 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/chromeos/login/helper.h"

#include "base/file_util.h"
#include "chrome/browser/chromeos/cros/network_library.h"
#include "chrome/browser/chromeos/system_access.h"
#include "chrome/browser/google/google_util.h"
#include "googleurl/src/gurl.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "third_party/skia/include/effects/SkGradientShader.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/canvas_skia.h"
#include "views/controls/button/menu_button.h"
#include "views/controls/button/native_button.h"
#include "views/controls/label.h"
#include "views/controls/textfield/textfield.h"
#include "views/controls/throbber.h"
#include "views/painter.h"
#include "views/screen.h"
#include "views/widget/widget.h"
#include "views/widget/widget_gtk.h"

namespace chromeos {

namespace {

// Time in ms per throbber frame.
const int kThrobberFrameMs = 60;

// Time in ms before smoothed throbber is shown.
const int kThrobberStartDelayMs = 500;

const SkColor kBackgroundCenterColor = SkColorSetRGB(41, 50, 67);
const SkColor kBackgroundEdgeColor = SK_ColorBLACK;

const char kAccountRecoveryHelpUrl[] =
    "https://www.google.com/support/accounts/bin/answer.py?answer=48598";

class BackgroundPainter : public views::Painter {
 public:
  BackgroundPainter() {}

  virtual void Paint(int w, int h, gfx::Canvas* canvas) {
    SkRect rect;
    rect.set(SkIntToScalar(0),
             SkIntToScalar(0),
             SkIntToScalar(w),
             SkIntToScalar(h));
    SkPaint paint;
    paint.setStyle(SkPaint::kFill_Style);
    paint.setFlags(SkPaint::kAntiAlias_Flag);
    SkColor colors[2] = { kBackgroundCenterColor, kBackgroundEdgeColor };
    SkShader* s = SkGradientShader::CreateRadial(
        SkPoint::Make(SkIntToScalar(w / 2), SkIntToScalar(h / 2)),
        SkIntToScalar(w / 2),
        colors,
        NULL,
        2,
        SkShader::kClamp_TileMode,
        NULL);
    paint.setShader(s);
    s->unref();
    canvas->AsCanvasSkia()->drawRect(rect, paint);
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(BackgroundPainter);
};

}  // namespace

ThrobberHostView::ThrobberHostView()
    : host_view_(this),
      throbber_widget_(NULL) {
}

ThrobberHostView::~ThrobberHostView() {
  StopThrobber();
}

void ThrobberHostView::StartThrobber() {
  StopThrobber();

  views::Widget* host_widget = host_view_->GetWidget();
  if (!host_widget) {
    LOG(WARNING) << "Failed to start the throbber: no Widget";
    return;
  }

  GtkWidget* host_gtk_window = host_widget->GetNativeView();
  while (host_gtk_window && !GTK_IS_WINDOW(host_gtk_window))
    host_gtk_window = gtk_widget_get_parent(host_gtk_window);
  if (!host_gtk_window) {
    LOG(WARNING) << "Failed to start the throbber: no GtkWindow";
    return;
  }

  views::SmoothedThrobber* throbber = CreateDefaultSmoothedThrobber();
  throbber->set_stop_delay_ms(0);
  gfx::Rect throbber_bounds = CalculateThrobberBounds(throbber);

  throbber_widget_ = views::Widget::CreateWidget();
  static_cast<views::WidgetGtk*>(throbber_widget_->native_widget())->
      make_transient_to_parent();

  throbber_bounds.Offset(host_view_->GetScreenBounds().origin());
  views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
  params.transparent = true;
  params.bounds = throbber_bounds;
  params.parent = host_gtk_window;
  throbber_widget_->Init(params);
  throbber_widget_->SetContentsView(throbber);
  // This keeps the window from flashing at startup.
  gdk_window_set_back_pixmap(
      throbber_widget_->GetNativeView()->window, NULL, false);
  throbber_widget_->Show();
  // WM can ignore bounds before widget is shown.
  throbber_widget_->SetBounds(throbber_bounds);
  throbber->Start();
}

void ThrobberHostView::StopThrobber() {
  if (throbber_widget_) {
    throbber_widget_->Close();
    throbber_widget_ = NULL;
  }
}

gfx::Rect ThrobberHostView::CalculateThrobberBounds(views::Throbber* throbber) {
  gfx::Rect bounds(throbber->GetPreferredSize());
  bounds.set_x(
      host_view_->width() - login::kThrobberRightMargin - bounds.width());
  bounds.set_y((host_view_->height() - bounds.height()) / 2);
  return bounds;
}

views::SmoothedThrobber* CreateDefaultSmoothedThrobber() {
  views::SmoothedThrobber* throbber =
      new views::SmoothedThrobber(kThrobberFrameMs);
  throbber->SetFrames(
      ResourceBundle::GetSharedInstance().GetBitmapNamed(IDR_SPINNER));
  throbber->set_start_delay_ms(kThrobberStartDelayMs);
  return throbber;
}

views::Throbber* CreateDefaultThrobber() {
  views::Throbber* throbber = new views::Throbber(kThrobberFrameMs, false);
  throbber->SetFrames(
      ResourceBundle::GetSharedInstance().GetBitmapNamed(IDR_SPINNER));
  return throbber;
}

views::Painter* CreateBackgroundPainter() {
  return new BackgroundPainter();
}

gfx::Rect CalculateScreenBounds(const gfx::Size& size) {
  gfx::Rect bounds(views::Screen::GetMonitorWorkAreaNearestWindow(NULL));
  if (!size.IsEmpty()) {
    int horizontal_diff = bounds.width() - size.width();
    int vertical_diff = bounds.height() - size.height();
    bounds.Inset(horizontal_diff / 2, vertical_diff / 2);
  }
  return bounds;
}

void CorrectLabelFontSize(views::Label* label) {
  if (label)
    label->SetFont(label->font().DeriveFont(kFontSizeCorrectionDelta));
}

void CorrectMenuButtonFontSize(views::MenuButton* button) {
  if (button)
    button->SetFont(button->font().DeriveFont(kFontSizeCorrectionDelta));
}

void CorrectNativeButtonFontSize(views::NativeButton* button) {
  if (button)
    button->set_font(button->font().DeriveFont(kFontSizeCorrectionDelta));
}

void CorrectTextfieldFontSize(views::Textfield* textfield) {
  if (textfield)
    textfield->SetFont(textfield->font().DeriveFont(kFontSizeCorrectionDelta));
}

void SetAndCorrectTextfieldFont(views::Textfield* textfield,
                                const gfx::Font& font) {
  if (textfield)
    textfield->SetFont(font.DeriveFont(kFontSizeCorrectionDelta));
}

GURL GetAccountRecoveryHelpUrl() {
  return google_util::AppendGoogleLocaleParam(GURL(kAccountRecoveryHelpUrl));
}

string16 GetCurrentNetworkName(NetworkLibrary* network_library) {
  if (!network_library)
    return string16();

  if (network_library->ethernet_connected()) {
    return l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET);
  } else if (network_library->wifi_connected()) {
    return ASCIIToUTF16(network_library->wifi_network()->name());
  } else if (network_library->cellular_connected()) {
    return ASCIIToUTF16(network_library->cellular_network()->name());
  } else if (network_library->ethernet_connecting()) {
    return l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET);
  } else if (network_library->wifi_connecting()) {
    return ASCIIToUTF16(network_library->wifi_network()->name());
  } else if (network_library->cellular_connecting()) {
    return ASCIIToUTF16(network_library->cellular_network()->name());
  } else {
    return string16();
  }
}

namespace login {

gfx::Size WideButton::GetPreferredSize() {
  gfx::Size preferred_size = NativeButton::GetPreferredSize();
  // Set minimal width.
  if (preferred_size.width() < kButtonMinWidth)
    preferred_size.set_width(kButtonMinWidth);
  return preferred_size;
}

}  // namespace login

}  // namespace chromeos
<commit_msg>Set POPUP type for throbber window.<commit_after>// Copyright (c) 2011 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/chromeos/login/helper.h"

#include "base/file_util.h"
#include "chrome/browser/chromeos/cros/network_library.h"
#include "chrome/browser/chromeos/system_access.h"
#include "chrome/browser/google/google_util.h"
#include "googleurl/src/gurl.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "third_party/skia/include/effects/SkGradientShader.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/canvas_skia.h"
#include "views/controls/button/menu_button.h"
#include "views/controls/button/native_button.h"
#include "views/controls/label.h"
#include "views/controls/textfield/textfield.h"
#include "views/controls/throbber.h"
#include "views/painter.h"
#include "views/screen.h"
#include "views/widget/widget.h"
#include "views/widget/widget_gtk.h"

namespace chromeos {

namespace {

// Time in ms per throbber frame.
const int kThrobberFrameMs = 60;

// Time in ms before smoothed throbber is shown.
const int kThrobberStartDelayMs = 500;

const SkColor kBackgroundCenterColor = SkColorSetRGB(41, 50, 67);
const SkColor kBackgroundEdgeColor = SK_ColorBLACK;

const char kAccountRecoveryHelpUrl[] =
    "https://www.google.com/support/accounts/bin/answer.py?answer=48598";

class BackgroundPainter : public views::Painter {
 public:
  BackgroundPainter() {}

  virtual void Paint(int w, int h, gfx::Canvas* canvas) {
    SkRect rect;
    rect.set(SkIntToScalar(0),
             SkIntToScalar(0),
             SkIntToScalar(w),
             SkIntToScalar(h));
    SkPaint paint;
    paint.setStyle(SkPaint::kFill_Style);
    paint.setFlags(SkPaint::kAntiAlias_Flag);
    SkColor colors[2] = { kBackgroundCenterColor, kBackgroundEdgeColor };
    SkShader* s = SkGradientShader::CreateRadial(
        SkPoint::Make(SkIntToScalar(w / 2), SkIntToScalar(h / 2)),
        SkIntToScalar(w / 2),
        colors,
        NULL,
        2,
        SkShader::kClamp_TileMode,
        NULL);
    paint.setShader(s);
    s->unref();
    canvas->AsCanvasSkia()->drawRect(rect, paint);
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(BackgroundPainter);
};

}  // namespace

ThrobberHostView::ThrobberHostView()
    : host_view_(this),
      throbber_widget_(NULL) {
}

ThrobberHostView::~ThrobberHostView() {
  StopThrobber();
}

void ThrobberHostView::StartThrobber() {
  StopThrobber();

  views::Widget* host_widget = host_view_->GetWidget();
  if (!host_widget) {
    LOG(WARNING) << "Failed to start the throbber: no Widget";
    return;
  }

  GtkWidget* host_gtk_window = host_widget->GetNativeView();
  while (host_gtk_window && !GTK_IS_WINDOW(host_gtk_window))
    host_gtk_window = gtk_widget_get_parent(host_gtk_window);
  if (!host_gtk_window) {
    LOG(WARNING) << "Failed to start the throbber: no GtkWindow";
    return;
  }

  views::SmoothedThrobber* throbber = CreateDefaultSmoothedThrobber();
  throbber->set_stop_delay_ms(0);
  gfx::Rect throbber_bounds = CalculateThrobberBounds(throbber);

  throbber_widget_ = views::Widget::CreateWidget();
  static_cast<views::WidgetGtk*>(throbber_widget_->native_widget())->
      make_transient_to_parent();

  throbber_bounds.Offset(host_view_->GetScreenBounds().origin());
  views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
  params.transparent = true;
  params.bounds = throbber_bounds;
  params.parent = host_gtk_window;
  throbber_widget_->Init(params);
  throbber_widget_->SetContentsView(throbber);
  // This keeps the window from flashing at startup.
  gdk_window_set_back_pixmap(
      throbber_widget_->GetNativeView()->window, NULL, false);
  throbber_widget_->Show();
  // WM can ignore bounds before widget is shown.
  throbber_widget_->SetBounds(throbber_bounds);
  throbber->Start();
}

void ThrobberHostView::StopThrobber() {
  if (throbber_widget_) {
    throbber_widget_->Close();
    throbber_widget_ = NULL;
  }
}

gfx::Rect ThrobberHostView::CalculateThrobberBounds(views::Throbber* throbber) {
  gfx::Rect bounds(throbber->GetPreferredSize());
  bounds.set_x(
      host_view_->width() - login::kThrobberRightMargin - bounds.width());
  bounds.set_y((host_view_->height() - bounds.height()) / 2);
  return bounds;
}

views::SmoothedThrobber* CreateDefaultSmoothedThrobber() {
  views::SmoothedThrobber* throbber =
      new views::SmoothedThrobber(kThrobberFrameMs);
  throbber->SetFrames(
      ResourceBundle::GetSharedInstance().GetBitmapNamed(IDR_SPINNER));
  throbber->set_start_delay_ms(kThrobberStartDelayMs);
  return throbber;
}

views::Throbber* CreateDefaultThrobber() {
  views::Throbber* throbber = new views::Throbber(kThrobberFrameMs, false);
  throbber->SetFrames(
      ResourceBundle::GetSharedInstance().GetBitmapNamed(IDR_SPINNER));
  return throbber;
}

views::Painter* CreateBackgroundPainter() {
  return new BackgroundPainter();
}

gfx::Rect CalculateScreenBounds(const gfx::Size& size) {
  gfx::Rect bounds(views::Screen::GetMonitorWorkAreaNearestWindow(NULL));
  if (!size.IsEmpty()) {
    int horizontal_diff = bounds.width() - size.width();
    int vertical_diff = bounds.height() - size.height();
    bounds.Inset(horizontal_diff / 2, vertical_diff / 2);
  }
  return bounds;
}

void CorrectLabelFontSize(views::Label* label) {
  if (label)
    label->SetFont(label->font().DeriveFont(kFontSizeCorrectionDelta));
}

void CorrectMenuButtonFontSize(views::MenuButton* button) {
  if (button)
    button->SetFont(button->font().DeriveFont(kFontSizeCorrectionDelta));
}

void CorrectNativeButtonFontSize(views::NativeButton* button) {
  if (button)
    button->set_font(button->font().DeriveFont(kFontSizeCorrectionDelta));
}

void CorrectTextfieldFontSize(views::Textfield* textfield) {
  if (textfield)
    textfield->SetFont(textfield->font().DeriveFont(kFontSizeCorrectionDelta));
}

void SetAndCorrectTextfieldFont(views::Textfield* textfield,
                                const gfx::Font& font) {
  if (textfield)
    textfield->SetFont(font.DeriveFont(kFontSizeCorrectionDelta));
}

GURL GetAccountRecoveryHelpUrl() {
  return google_util::AppendGoogleLocaleParam(GURL(kAccountRecoveryHelpUrl));
}

string16 GetCurrentNetworkName(NetworkLibrary* network_library) {
  if (!network_library)
    return string16();

  if (network_library->ethernet_connected()) {
    return l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET);
  } else if (network_library->wifi_connected()) {
    return ASCIIToUTF16(network_library->wifi_network()->name());
  } else if (network_library->cellular_connected()) {
    return ASCIIToUTF16(network_library->cellular_network()->name());
  } else if (network_library->ethernet_connecting()) {
    return l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET);
  } else if (network_library->wifi_connecting()) {
    return ASCIIToUTF16(network_library->wifi_network()->name());
  } else if (network_library->cellular_connecting()) {
    return ASCIIToUTF16(network_library->cellular_network()->name());
  } else {
    return string16();
  }
}

namespace login {

gfx::Size WideButton::GetPreferredSize() {
  gfx::Size preferred_size = NativeButton::GetPreferredSize();
  // Set minimal width.
  if (preferred_size.width() < kButtonMinWidth)
    preferred_size.set_width(kButtonMinWidth);
  return preferred_size;
}

}  // namespace login

}  // namespace chromeos
<|endoftext|>