<commit_before>// This file is a part of the OpenSurgSim project.
// Copyright 2013, SimQuest Solutions Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "SurgSim/Collision/UnitTests/ContactCalculationTestsCommon.h"

namespace SurgSim
{
namespace Collision
{

::testing::AssertionResult eigenEqual(const Vector3d& left, const Vector3d& right)
{
	if (std::abs((left - right).norm()) < SurgSim::Math::Geometry::DistanceEpsilon)
	{
		return ::testing::AssertionSuccess();
	}
	else
	{
		return ::testing::AssertionFailure() << std::endl << "Vectors not close, expected: " << left.transpose() <<
			   std::endl << " result: " << right.transpose() << std::endl;
	}
}

void checkContactInfo(std::shared_ptr<Contact> contact, double expectedDepth,
					  Vector3d &expectedNormal, Vector3d &expectedPenetrationPointFirst,
					  Vector3d &expectedPenetrationPointSecond)
{
	EXPECT_NEAR(expectedDepth, contact->depth, SurgSim::Math::Geometry::DistanceEpsilon);
	EXPECT_TRUE(eigenEqual(expectedNormal, contact->normal));
	EXPECT_TRUE(contact->penetrationPoints.first.globalPosition.hasValue());
	EXPECT_TRUE(contact->penetrationPoints.second.globalPosition.hasValue());
	EXPECT_TRUE(eigenEqual(expectedPenetrationPointFirst,
							contact->penetrationPoints.first.globalPosition.getValue()));
	EXPECT_TRUE(eigenEqual(expectedPenetrationPointSecond,
							contact->penetrationPoints.second.globalPosition.getValue()));
}

::testing::AssertionResult isContactPresentInList(std::shared_ptr<Contact> expected,
												  const std::list<std::shared_ptr<Contact>>& contactsList,
												  bool expectedHasTriangleContactObject)
{
	using SurgSim::Math::Geometry::ScalarEpsilon;

	bool contactPresent = false;
	for (auto it = contactsList.begin(); it != contactsList.end() && !contactPresent; ++it)
	{
		// Compare the normals.
		contactPresent = eigenEqual(expected->normal, it->get()->normal);
		// Compare the global position of first object.
		contactPresent &= eigenEqual(expected->penetrationPoints.first.globalPosition.getValue(),
									 it->get()->penetrationPoints.first.globalPosition.getValue());
		// Compare the global position of second object.
		contactPresent &= eigenEqual(expected->penetrationPoints.second.globalPosition.getValue(),
									 it->get()->penetrationPoints.second.globalPosition.getValue());
		// Compare the depth.
		contactPresent &= std::abs(expected->depth - it->get()->depth) <= ScalarEpsilon;
		// Check if the optional 'triangleLocalPosition' is present in expected contact.
		EXPECT_EQ(expected->penetrationPoints.first.meshLocalCoordinate.hasValue(),
				  it->get()->penetrationPoints.first.meshLocalCoordinate.hasValue());
		if (expected->penetrationPoints.first.meshLocalCoordinate.hasValue() &&
			it->get()->penetrationPoints.first.meshLocalCoordinate.hasValue())
		{
			contactPresent &= expected->penetrationPoints.first.meshLocalCoordinate.getValue().elementId ==
							  it->get()->penetrationPoints.first.meshLocalCoordinate.getValue().elementId;
			Vector3d barycentricCoordinates;
			std::shared_ptr<SurgSim::Collision::TriangleContact> triangleContact;
			if (expectedHasTriangleContactObject)
			{
				triangleContact = std::static_pointer_cast<SurgSim::Collision::TriangleContact>(expected);
				barycentricCoordinates =
					it->get()->penetrationPoints.first.meshLocalCoordinate.getValue().barycentricCoordinate;
			}
			else
			{
				triangleContact = std::static_pointer_cast<SurgSim::Collision::TriangleContact>(*it);
				barycentricCoordinates =
					expected.get()->penetrationPoints.first.meshLocalCoordinate.getValue().barycentricCoordinate;
			}
			contactPresent &= eigenEqual(expected->penetrationPoints.first.globalPosition.getValue(),
										 barycentricCoordinates[0] * triangleContact->firstVertices[0] +
										 barycentricCoordinates[1] * triangleContact->firstVertices[1] +
										 barycentricCoordinates[2] * triangleContact->firstVertices[2]);
		}
		EXPECT_EQ(expected->penetrationPoints.second.meshLocalCoordinate.hasValue(),
				  it->get()->penetrationPoints.second.meshLocalCoordinate.hasValue());
		if (expected->penetrationPoints.second.meshLocalCoordinate.hasValue() &&
			it->get()->penetrationPoints.second.meshLocalCoordinate.hasValue())
		{
			contactPresent &= expected->penetrationPoints.second.meshLocalCoordinate.getValue().elementId ==
							  it->get()->penetrationPoints.second.meshLocalCoordinate.getValue().elementId;
			Vector3d barycentricCoordinates;
			std::shared_ptr<SurgSim::Collision::TriangleContact> triangleContact;
			if (expectedHasTriangleContactObject)
			{
				triangleContact = std::static_pointer_cast<SurgSim::Collision::TriangleContact>(expected);
				barycentricCoordinates =
					it->get()->penetrationPoints.second.meshLocalCoordinate.getValue().barycentricCoordinate;
			}
			else
			{
				triangleContact = std::static_pointer_cast<SurgSim::Collision::TriangleContact>(*it);
				barycentricCoordinates =
					expected.get()->penetrationPoints.second.meshLocalCoordinate.getValue().barycentricCoordinate;
			}
			contactPresent &= eigenEqual(expected->penetrationPoints.second.globalPosition.getValue(),
										 barycentricCoordinates[0] * triangleContact->secondVertices[0] +
										 barycentricCoordinates[1] * triangleContact->secondVertices[1] +
										 barycentricCoordinates[2] * triangleContact->secondVertices[2]);
		}
	}

	if (contactPresent)
	{
		return ::testing::AssertionSuccess();
	}
	else
	{
		return ::testing::AssertionFailure() << "Expected contact not found in calculated contacts list:\n" <<
			   "Normal: " << expected->normal << "\n" <<
			   "First objects' contact point: " << expected->penetrationPoints.first.globalPosition.getValue()
			   << "\n" <<
			   "Second objects' contact point: " << expected->penetrationPoints.second.globalPosition.getValue()
			   << "\n" <<
			   "Depth of penetration: " << expected->depth << "\n";
	}
}

void contactsInfoEqualityTest(const std::list<std::shared_ptr<Contact>>& expectedContacts,
							  const std::list<std::shared_ptr<Contact>>& calculatedContacts,
							  bool expectedHasTriangleContactObject)
{
	SCOPED_TRACE("Comparing the contact info.");

	EXPECT_EQ(expectedContacts.size(), calculatedContacts.size());

	for (auto it = expectedContacts.begin(); it != expectedContacts.end(); ++it)
	{
		EXPECT_TRUE(isContactPresentInList(*it, calculatedContacts, expectedHasTriangleContactObject));
	}
}

void generateBoxPlaneContact(std::list<std::shared_ptr<Contact>>* expectedContacts,
							 const int expectedNumberOfContacts,
							 const int* expectedBoxIndicesInContacts,
							 const std::shared_ptr<BoxShape> box,
							 const Vector3d& boxTrans, const Quaterniond& boxQuat,
							 const std::shared_ptr<PlaneShape> plane,
							 const Vector3d& planeTrans, const Quaterniond& planeQuat)
{
	Vector3d vertex;
	Vector3d planeNormalGlobal = planeQuat * plane->getNormal();
	Vector3d pointOnPlane = planeTrans + (planeNormalGlobal * plane->getD());
	double depth = 0.0;
	Vector3d collisionNormal = planeNormalGlobal;
	RigidTransform3d boxTransform = SurgSim::Math::makeRigidTransform(boxQuat, boxTrans);
	for (int i = 0; i < expectedNumberOfContacts; ++i)
	{
		vertex = boxTransform * box->getVertex(expectedBoxIndicesInContacts[i]);
		std::pair<Location, Location> penetrationPoint;
		penetrationPoint.first.globalPosition.setValue(vertex);
		depth = planeNormalGlobal.dot(vertex - pointOnPlane);
		penetrationPoint.second.globalPosition.setValue(vertex - planeNormalGlobal * depth);
		expectedContacts->push_back(std::make_shared<Contact>(depth, Vector3d::Zero(),
															 collisionNormal, penetrationPoint));
	}
}

void generateBoxDoubleSidedPlaneContact(std::list<std::shared_ptr<Contact>>* expectedContacts,
										const int expectedNumberOfContacts,
										const int* expectedBoxIndicesInContacts,
										const std::shared_ptr<BoxShape> box,
										const Vector3d& boxTrans, const Quaterniond& boxQuat,
										const std::shared_ptr<DoubleSidedPlaneShape> plane,
										const Vector3d& planeTrans, const Quaterniond& planeQuat,
										const bool collisionNormalIsPlaneNormal)
{
	Vector3d vertex;
	Vector3d planeNormalGlobal = planeQuat * plane->getNormal();
	Vector3d pointOnPlane = planeTrans + (planeNormalGlobal * plane->getD());
	double depth = 0.0;
	Vector3d collisionNormal = planeNormalGlobal * (collisionNormalIsPlaneNormal ? 1.0 : -1.0);
	RigidTransform3d boxTransform = SurgSim::Math::makeRigidTransform(boxQuat, boxTrans);
	for (int i = 0; i < expectedNumberOfContacts; ++i)
	{
		vertex = boxTransform * box->getVertex(expectedBoxIndicesInContacts[i]);
		std::pair<Location, Location> penetrationPoint;
		penetrationPoint.first.globalPosition.setValue(vertex);
		depth = planeNormalGlobal.dot(vertex - pointOnPlane);
		penetrationPoint.second.globalPosition.setValue(vertex - planeNormalGlobal * depth);
		expectedContacts->push_back(std::make_shared<Contact>(std::abs(depth), Vector3d::Zero(),
															 collisionNormal, penetrationPoint));
	}
}

}; // namespace Collision
}; // namespace SurgSim
<commit_msg>Minor refactoring  in isContactPresentInList to remove code duplication.<commit_after>// This file is a part of the OpenSurgSim project.
// Copyright 2013, SimQuest Solutions Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "SurgSim/Collision/UnitTests/ContactCalculationTestsCommon.h"

namespace SurgSim
{
namespace Collision
{

::testing::AssertionResult eigenEqual(const Vector3d& left, const Vector3d& right)
{
	if (std::abs((left - right).norm()) < SurgSim::Math::Geometry::DistanceEpsilon)
	{
		return ::testing::AssertionSuccess();
	}
	else
	{
		return ::testing::AssertionFailure() << std::endl << "Vectors not close, expected: " << left.transpose() <<
			   std::endl << " result: " << right.transpose() << std::endl;
	}
}

void checkContactInfo(std::shared_ptr<Contact> contact, double expectedDepth,
					  Vector3d &expectedNormal, Vector3d &expectedPenetrationPointFirst,
					  Vector3d &expectedPenetrationPointSecond)
{
	EXPECT_NEAR(expectedDepth, contact->depth, SurgSim::Math::Geometry::DistanceEpsilon);
	EXPECT_TRUE(eigenEqual(expectedNormal, contact->normal));
	EXPECT_TRUE(contact->penetrationPoints.first.globalPosition.hasValue());
	EXPECT_TRUE(contact->penetrationPoints.second.globalPosition.hasValue());
	EXPECT_TRUE(eigenEqual(expectedPenetrationPointFirst,
							contact->penetrationPoints.first.globalPosition.getValue()));
	EXPECT_TRUE(eigenEqual(expectedPenetrationPointSecond,
							contact->penetrationPoints.second.globalPosition.getValue()));
}

::testing::AssertionResult isContactPresentInList(std::shared_ptr<Contact> expected,
												  const std::list<std::shared_ptr<Contact>>& contactsList,
												  bool expectedHasTriangleContactObject)
{
	using SurgSim::Math::Geometry::ScalarEpsilon;

	bool contactPresent = false;
	for (auto it = contactsList.begin(); it != contactsList.end() && !contactPresent; ++it)
	{
		// Compare the normals.
		contactPresent = eigenEqual(expected->normal, it->get()->normal);
		// Compare the global position of first object.
		contactPresent &= eigenEqual(expected->penetrationPoints.first.globalPosition.getValue(),
									 it->get()->penetrationPoints.first.globalPosition.getValue());
		// Compare the global position of second object.
		contactPresent &= eigenEqual(expected->penetrationPoints.second.globalPosition.getValue(),
									 it->get()->penetrationPoints.second.globalPosition.getValue());
		// Compare the depth.
		contactPresent &= std::abs(expected->depth - it->get()->depth) <= ScalarEpsilon;
		// Check if the optional 'meshLocalCoordinate' are the same.
		std::shared_ptr<SurgSim::Collision::TriangleContact> triangleContact;
		std::shared_ptr<SurgSim::Collision::Contact> contact;
		if (expectedHasTriangleContactObject)
		{
			triangleContact = std::static_pointer_cast<SurgSim::Collision::TriangleContact>(expected);
			contact = *it;
		}
		else
		{
			triangleContact = std::static_pointer_cast<SurgSim::Collision::TriangleContact>(*it);
			contact = expected;
		}
		EXPECT_EQ(triangleContact->penetrationPoints.first.meshLocalCoordinate.hasValue(),
				  contact->penetrationPoints.first.meshLocalCoordinate.hasValue());
		if (triangleContact->penetrationPoints.first.meshLocalCoordinate.hasValue() &&
			contact->penetrationPoints.first.meshLocalCoordinate.hasValue())
		{
			contactPresent &= triangleContact->penetrationPoints.first.meshLocalCoordinate.getValue().elementId ==
							  contact->penetrationPoints.first.meshLocalCoordinate.getValue().elementId;
			Vector3d barycentricCoordinates =
				contact->penetrationPoints.first.meshLocalCoordinate.getValue().barycentricCoordinate;
			contactPresent &= eigenEqual(expected->penetrationPoints.first.globalPosition.getValue(),
										 barycentricCoordinates[0] * triangleContact->firstVertices[0] +
										 barycentricCoordinates[1] * triangleContact->firstVertices[1] +
										 barycentricCoordinates[2] * triangleContact->firstVertices[2]);
		}
		EXPECT_EQ(triangleContact->penetrationPoints.second.meshLocalCoordinate.hasValue(),
				  contact->penetrationPoints.second.meshLocalCoordinate.hasValue());
		if (triangleContact->penetrationPoints.second.meshLocalCoordinate.hasValue() &&
			contact->penetrationPoints.second.meshLocalCoordinate.hasValue())
		{
			contactPresent &= triangleContact->penetrationPoints.second.meshLocalCoordinate.getValue().elementId ==
							  contact->penetrationPoints.second.meshLocalCoordinate.getValue().elementId;
			Vector3d barycentricCoordinates =
				contact->penetrationPoints.second.meshLocalCoordinate.getValue().barycentricCoordinate;
			contactPresent &= eigenEqual(expected->penetrationPoints.second.globalPosition.getValue(),
										 barycentricCoordinates[0] * triangleContact->secondVertices[0] +
										 barycentricCoordinates[1] * triangleContact->secondVertices[1] +
										 barycentricCoordinates[2] * triangleContact->secondVertices[2]);
		}
	}

	if (contactPresent)
	{
		return ::testing::AssertionSuccess();
	}
	else
	{
		return ::testing::AssertionFailure() << "Expected contact not found in calculated contacts list:\n" <<
			   "Normal: " << expected->normal << "\n" <<
			   "First objects' contact point: " << expected->penetrationPoints.first.globalPosition.getValue()
			   << "\n" <<
			   "Second objects' contact point: " << expected->penetrationPoints.second.globalPosition.getValue()
			   << "\n" <<
			   "Depth of penetration: " << expected->depth << "\n";
	}
}

void contactsInfoEqualityTest(const std::list<std::shared_ptr<Contact>>& expectedContacts,
							  const std::list<std::shared_ptr<Contact>>& calculatedContacts,
							  bool expectedHasTriangleContactObject)
{
	SCOPED_TRACE("Comparing the contact info.");

	EXPECT_EQ(expectedContacts.size(), calculatedContacts.size());

	for (auto it = expectedContacts.begin(); it != expectedContacts.end(); ++it)
	{
		EXPECT_TRUE(isContactPresentInList(*it, calculatedContacts, expectedHasTriangleContactObject));
	}
}

void generateBoxPlaneContact(std::list<std::shared_ptr<Contact>>* expectedContacts,
							 const int expectedNumberOfContacts,
							 const int* expectedBoxIndicesInContacts,
							 const std::shared_ptr<BoxShape> box,
							 const Vector3d& boxTrans, const Quaterniond& boxQuat,
							 const std::shared_ptr<PlaneShape> plane,
							 const Vector3d& planeTrans, const Quaterniond& planeQuat)
{
	Vector3d vertex;
	Vector3d planeNormalGlobal = planeQuat * plane->getNormal();
	Vector3d pointOnPlane = planeTrans + (planeNormalGlobal * plane->getD());
	double depth = 0.0;
	Vector3d collisionNormal = planeNormalGlobal;
	RigidTransform3d boxTransform = SurgSim::Math::makeRigidTransform(boxQuat, boxTrans);
	for (int i = 0; i < expectedNumberOfContacts; ++i)
	{
		vertex = boxTransform * box->getVertex(expectedBoxIndicesInContacts[i]);
		std::pair<Location, Location> penetrationPoint;
		penetrationPoint.first.globalPosition.setValue(vertex);
		depth = planeNormalGlobal.dot(vertex - pointOnPlane);
		penetrationPoint.second.globalPosition.setValue(vertex - planeNormalGlobal * depth);
		expectedContacts->push_back(std::make_shared<Contact>(depth, Vector3d::Zero(),
															 collisionNormal, penetrationPoint));
	}
}

void generateBoxDoubleSidedPlaneContact(std::list<std::shared_ptr<Contact>>* expectedContacts,
										const int expectedNumberOfContacts,
										const int* expectedBoxIndicesInContacts,
										const std::shared_ptr<BoxShape> box,
										const Vector3d& boxTrans, const Quaterniond& boxQuat,
										const std::shared_ptr<DoubleSidedPlaneShape> plane,
										const Vector3d& planeTrans, const Quaterniond& planeQuat,
										const bool collisionNormalIsPlaneNormal)
{
	Vector3d vertex;
	Vector3d planeNormalGlobal = planeQuat * plane->getNormal();
	Vector3d pointOnPlane = planeTrans + (planeNormalGlobal * plane->getD());
	double depth = 0.0;
	Vector3d collisionNormal = planeNormalGlobal * (collisionNormalIsPlaneNormal ? 1.0 : -1.0);
	RigidTransform3d boxTransform = SurgSim::Math::makeRigidTransform(boxQuat, boxTrans);
	for (int i = 0; i < expectedNumberOfContacts; ++i)
	{
		vertex = boxTransform * box->getVertex(expectedBoxIndicesInContacts[i]);
		std::pair<Location, Location> penetrationPoint;
		penetrationPoint.first.globalPosition.setValue(vertex);
		depth = planeNormalGlobal.dot(vertex - pointOnPlane);
		penetrationPoint.second.globalPosition.setValue(vertex - planeNormalGlobal * depth);
		expectedContacts->push_back(std::make_shared<Contact>(std::abs(depth), Vector3d::Zero(),
															 collisionNormal, penetrationPoint));
	}
}

}; // namespace Collision
}; // namespace SurgSim
<|endoftext|>


<commit_before>//----------------------------  symmetric_tensor_08.cc  ---------------------------
//    $Id$
//    Version: $Name$
//
//    Copyright (C) 2005 by the deal.II authors
//
//    This file is subject to QPL and may not be  distributed
//    without copyright and license information. Please refer
//    to the file deal.II/doc/license.html for the  text  and
//    further information on this license.
//
//----------------------------  symmetric_tensor_08.cc  ---------------------------

// a stress test using repeated multiplication of tensors

#include "../tests.h"
#include <base/symmetric_tensor.h>
#include <base/tensor.h>
#include <base/logstream.h>
#include <fstream>
#include <iostream>

template <int dim>
void test ()
{
  const double lambda = 1.5,
	       mu     = 1.7;
  SymmetricTensor<4,dim> t;
  for (unsigned int i=0; i<dim; ++i)
    for (unsigned int j=0; j<dim; ++j)
      for (unsigned int k=0; k<dim; ++k)
	for (unsigned int l=0; l<dim; ++l)
	  t[i][j][k][l] = (((i==k) && (j==l) ? mu : 0) +
			   ((i==l) && (j==k) ? mu : 0) +
			   ((i==j) && (k==l) ? lambda : 0));

  SymmetricTensor<2,dim> a, b;
  for (unsigned int i=0; i<dim; ++i)
    for (unsigned int j=0; j<dim; ++j)
      a[i][j] = (1. + (i+1)*(j+1));

				   // stress test the whole thing many
				   // times. normalize in each step to
				   // make sure the result remains
				   // representable in floating point
				   // arithmetic. essentially, this
				   // invokes the power method to
				   // compute the largest eigenvector
				   // (eigentensor in this case)
  for (unsigned int i=0; i<1000000; ++i)
    {
      a = t*a;
      a /= a.norm();
    }

  for (unsigned int i=0; i<dim; ++i)
    for (unsigned int j=0; j<dim; ++j)
      deallog << i << ' ' << j << ' ' << a[i][j] << std::endl;
}

int main ()
{
  std::ofstream logfile("symmetric_tensor_08.output");
  logfile.precision(3);
  deallog.attach(logfile);
  deallog.depth_console(0);
  deallog.threshold_double(1.e-10);

  test<2> ();
  test<3> ();

  deallog << "OK" << std::endl;
}
<commit_msg>Work-around due to internal compiler error of gcc3.4.3<commit_after>//----------------------------  symmetric_tensor_08.cc  ---------------------------
//    $Id$
//    Version: $Name$
//
//    Copyright (C) 2005 by the deal.II authors
//
//    This file is subject to QPL and may not be  distributed
//    without copyright and license information. Please refer
//    to the file deal.II/doc/license.html for the  text  and
//    further information on this license.
//
//----------------------------  symmetric_tensor_08.cc  ---------------------------

// a stress test using repeated multiplication of tensors

#include "../tests.h"
#include <base/symmetric_tensor.h>
#include <base/tensor.h>
#include <base/logstream.h>
#include <fstream>
#include <iostream>

inline
double value(unsigned int i,
	     unsigned int j,
	     unsigned int k,
	     unsigned int l,
	     double lambda,
	     double mu)
{
  return ((i==k) && (j==l) ? mu : 0) +
	 ((i==l) && (j==k) ? mu : 0) +
	 ((i==j) && (k==l) ? lambda : 0);
}

template <int dim>
void test ()
{
  const double lambda = 1.5,
	       mu     = 1.7;
  SymmetricTensor<4,dim> t;
  for (unsigned int i=0; i<dim; ++i)
    for (unsigned int j=0; j<dim; ++j)
      for (unsigned int k=0; k<dim; ++k)
	for (unsigned int l=0; l<dim; ++l)
	  t[i][j][k][l] = value(i,j,k,l,lambda,mu);

  SymmetricTensor<2,dim> a;
  for (unsigned int i=0; i<dim; ++i)
    for (unsigned int j=0; j<dim; ++j)
      a[i][j] = (1. + (i+1)*(j+1));

				   // stress test the whole thing many
				   // times. normalize in each step to
				   // make sure the result remains
				   // representable in floating point
				   // arithmetic. essentially, this
				   // invokes the power method to
				   // compute the largest eigenvector
				   // (eigentensor in this case)
  for (unsigned int i=0; i<1000000; ++i)
    {
      a = t*a;
      a /= a.norm();
    }

  for (unsigned int i=0; i<dim; ++i)
    for (unsigned int j=0; j<dim; ++j)
      deallog << i << ' ' << j << ' ' << a[i][j] << std::endl;
}

int main ()
{
  std::ofstream logfile("symmetric_tensor_08.output");
  logfile.precision(3);
  deallog.attach(logfile);
  deallog.depth_console(0);
  deallog.threshold_double(1.e-10);

  test<2> ();
  test<3> ();

  deallog << "OK" << std::endl;
}
<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
//
//                         PelotonDB
//
// hash_join_test.cpp
//
// Identification: tests/executor/hash_join_test.cpp
//
// Copyright (c) 2015, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include <memory>

#include "gmock/gmock.h"
#include "gtest/gtest.h"

#include "backend/common/types.h"
#include "backend/executor/logical_tile.h"
#include "backend/executor/logical_tile_factory.h"

#include "backend/executor/hash_join_executor.h"
#include "backend/executor/hash_executor.h"
#include "backend/executor/merge_join_executor.h"
#include "backend/executor/nested_loop_join_executor.h"

#include "backend/expression/abstract_expression.h"
#include "backend/expression/tuple_value_expression.h"
#include "backend/expression/expression_util.h"

#include "backend/planner/hash_join_plan.h"
#include "backend/planner/hash_plan.h"
#include "backend/planner/merge_join_plan.h"
#include "backend/planner/nested_loop_join_plan.h"

#include "backend/storage/data_table.h"

#include "mock_executor.h"
#include "executor/executor_tests_util.h"
#include "executor/join_tests_util.h"
#include "harness.h"

using ::testing::NotNull;
using ::testing::Return;

namespace peloton {
namespace test {

std::vector<planner::MergeJoinPlan::JoinClause> CreateJoinClauses() {
  std::vector<planner::MergeJoinPlan::JoinClause> join_clauses;
  auto left = expression::TupleValueFactory(0, 1);
  auto right = expression::TupleValueFactory(1, 1);
  bool reversed = false;
  join_clauses.emplace_back(left, right, reversed);
  return join_clauses;
}

std::vector<PlanNodeType> join_algorithms = {
    PLAN_NODE_TYPE_NESTLOOP,
    PLAN_NODE_TYPE_MERGEJOIN,
    PLAN_NODE_TYPE_HASHJOIN
};

std::vector<PelotonJoinType> join_types = {
    JOIN_TYPE_INNER,
    JOIN_TYPE_LEFT,
    JOIN_TYPE_RIGHT,
    JOIN_TYPE_OUTER
};

void ExecuteJoinTest(PlanNodeType join_algorithm, PelotonJoinType join_type);

oid_t CountTuplesWithNullFields(executor::LogicalTile *logical_tile);

TEST(JoinTests, JoinPredicateTest) {

  // Go over all join algorithms
  for(auto join_algorithm : join_algorithms) {
    std::cout << "JOIN ALGORITHM :: " << PlanNodeTypeToString(join_algorithm) << "\n";

    // Go over all join types
    for(auto join_type : join_types) {
      std::cout << "JOIN TYPE :: " << join_type << "\n";

      // Execute the join test
      ExecuteJoinTest(join_algorithm, join_type);

    }
  }

}

void ExecuteJoinTest(PlanNodeType join_algorithm, PelotonJoinType join_type) {

  //===--------------------------------------------------------------------===//
  // Mock table scan executors
  //===--------------------------------------------------------------------===//

  MockExecutor left_table_scan_executor, right_table_scan_executor;

  // Create a table and wrap it in logical tile
  size_t tile_group_size = TESTS_TUPLES_PER_TILEGROUP;
  size_t left_table_tile_group_count = 3;
  size_t right_table_tile_group_count = 2;

  // Left table has 3 tile groups
  std::unique_ptr<storage::DataTable> left_table(
      ExecutorTestsUtil::CreateTable(tile_group_size));
  ExecutorTestsUtil::PopulateTable(left_table.get(),
                                   tile_group_size * left_table_tile_group_count,
                                   false,
                                   false, false);

  //std::cout << (*left_table);

  // Right table has 2 tile groups
  std::unique_ptr<storage::DataTable> right_table(
      ExecutorTestsUtil::CreateTable(tile_group_size));
  ExecutorTestsUtil::PopulateTable(right_table.get(),
                                   tile_group_size * right_table_tile_group_count,
                                   false, false, false);

  //std::cout << (*right_table);

  // Wrap the input tables with logical tiles
  std::unique_ptr<executor::LogicalTile> left_table_logical_tile1(
      executor::LogicalTileFactory::WrapTileGroup(left_table->GetTileGroup(0)));
  std::unique_ptr<executor::LogicalTile> left_table_logical_tile2(
      executor::LogicalTileFactory::WrapTileGroup(left_table->GetTileGroup(1)));
  std::unique_ptr<executor::LogicalTile> left_table_logical_tile3(
      executor::LogicalTileFactory::WrapTileGroup(left_table->GetTileGroup(2)));

  std::unique_ptr<executor::LogicalTile> right_table_logical_tile1(
      executor::LogicalTileFactory::WrapTileGroup(
          right_table->GetTileGroup(0)));
  std::unique_ptr<executor::LogicalTile> right_table_logical_tile2(
      executor::LogicalTileFactory::WrapTileGroup(
          right_table->GetTileGroup(1)));

  // Left scan executor returns logical tiles from the left table

  EXPECT_CALL(left_table_scan_executor, DInit())
  .WillOnce(Return(true));

  EXPECT_CALL(left_table_scan_executor, DExecute())
  .WillOnce(Return(true))
  .WillOnce(Return(true))
  .WillOnce(Return(true))
  .WillOnce(Return(false));

  EXPECT_CALL(left_table_scan_executor, GetOutput())
  .WillOnce(Return(left_table_logical_tile1.release()))
  .WillOnce(Return(left_table_logical_tile2.release()))
  .WillOnce(Return(left_table_logical_tile3.release()));

  // Right scan executor returns logical tiles from the right table

  EXPECT_CALL(right_table_scan_executor, DInit())
  .WillOnce(Return(true));

  EXPECT_CALL(right_table_scan_executor, DExecute())
  .WillOnce(Return(true))
  .WillOnce(Return(true))
  .WillOnce(Return(false));

  EXPECT_CALL(right_table_scan_executor, GetOutput())
  .WillOnce(Return(right_table_logical_tile1.release()))
  .WillOnce(Return(right_table_logical_tile2.release()));

  //===--------------------------------------------------------------------===//
  // Setup join plan nodes and executors and run them
  //===--------------------------------------------------------------------===//

  oid_t result_tuple_count = 0;
  oid_t tuples_with_null = 0;
  auto projection = JoinTestsUtil::CreateProjection();

  // Construct predicate
  expression::AbstractExpression *predicate = JoinTestsUtil::CreateJoinPredicate();

  // Differ based on join algorithm
  switch(join_algorithm) {

    case PLAN_NODE_TYPE_NESTLOOP: {

      // Create nested loop join plan node.
      planner::NestedLoopJoinPlan nested_loop_join_node(join_type, predicate, projection);

      // Run the nested loop join executor
      executor::NestedLoopJoinExecutor nested_loop_join_executor(&nested_loop_join_node, nullptr);

      // Construct the executor tree
      nested_loop_join_executor.AddChild(&left_table_scan_executor);
      nested_loop_join_executor.AddChild(&right_table_scan_executor);

      // Run the nested loop join executor
      EXPECT_TRUE(nested_loop_join_executor.Init());
      while(nested_loop_join_executor.Execute() == true) {
        std::unique_ptr<executor::LogicalTile> result_logical_tile(nested_loop_join_executor.GetOutput());

        if(result_logical_tile != nullptr) {
          result_tuple_count += result_logical_tile->GetTupleCount();
          tuples_with_null += CountTuplesWithNullFields(result_logical_tile.get());
        }
      }

    }
    break;

    case PLAN_NODE_TYPE_MERGEJOIN: {

      // Create join clauses
      std::vector<planner::MergeJoinPlan::JoinClause> join_clauses;
      join_clauses = CreateJoinClauses();

      // Create merge join plan node
      planner::MergeJoinPlan merge_join_node(join_type, predicate, projection, join_clauses);

      // Construct the merge join executor
      executor::MergeJoinExecutor merge_join_executor(&merge_join_node, nullptr);

      // Construct the executor tree
      merge_join_executor.AddChild(&left_table_scan_executor);
      merge_join_executor.AddChild(&right_table_scan_executor);

      // Run the merge join executor
      EXPECT_TRUE(merge_join_executor.Init());
      while(merge_join_executor.Execute() == true) {
        std::unique_ptr<executor::LogicalTile> result_logical_tile(merge_join_executor.GetOutput());

        if(result_logical_tile != nullptr) {
          result_tuple_count += result_logical_tile->GetTupleCount();
          tuples_with_null += CountTuplesWithNullFields(result_logical_tile.get());
          //std::cout << (*result_logical_tile);
        }
      }

    }
    break;

    case PLAN_NODE_TYPE_HASHJOIN: {

      // Create hash plan node
      expression::AbstractExpression *right_table_attr_1 =
          new expression::TupleValueExpression(1, 1);

      std::vector<std::unique_ptr<const expression::AbstractExpression> > hash_keys;
      hash_keys.emplace_back(right_table_attr_1);

      // Create hash plan node
      planner::HashPlan hash_plan_node(hash_keys);

      // Construct the hash executor
      executor::HashExecutor hash_executor(&hash_plan_node, nullptr);

      // Create hash join plan node.
      planner::HashJoinPlan hash_join_plan_node(join_type, predicate, projection);

      // Construct the hash join executor
      executor::HashJoinExecutor hash_join_executor(&hash_join_plan_node, nullptr);

      // Construct the executor tree
      hash_join_executor.AddChild(&left_table_scan_executor);
      hash_join_executor.AddChild(&hash_executor);

      hash_executor.AddChild(&right_table_scan_executor);

      // Run the hash_join_executor
      EXPECT_TRUE(hash_join_executor.Init());
      while(hash_join_executor.Execute() == true) {
        std::unique_ptr<executor::LogicalTile> result_logical_tile(hash_join_executor.GetOutput());

        if(result_logical_tile != nullptr) {
          result_tuple_count += result_logical_tile->GetTupleCount();
          tuples_with_null += CountTuplesWithNullFields(result_logical_tile.get());
          //std::cout << (*result_logical_tile);
        }
      }

    }
    break;

    default:
      throw Exception("Unsupported join algorithm : " + std::to_string(join_algorithm));
      break;
  }

  //===--------------------------------------------------------------------===//
  // Execute test
  //===--------------------------------------------------------------------===//

  // Check output
  switch(join_type) {
    case JOIN_TYPE_INNER:
      EXPECT_EQ(result_tuple_count, 2 * tile_group_size);
      EXPECT_EQ(tuples_with_null, 0 * tile_group_size);
      break;

    case JOIN_TYPE_LEFT:
      EXPECT_EQ(result_tuple_count, 3 * tile_group_size);
      EXPECT_EQ(tuples_with_null, 1 * tile_group_size);
      break;

    case JOIN_TYPE_RIGHT:
      EXPECT_EQ(result_tuple_count, 2 * tile_group_size);
      EXPECT_EQ(tuples_with_null, 0 * tile_group_size);
      break;

    case JOIN_TYPE_OUTER:
      EXPECT_EQ(result_tuple_count, 3 * tile_group_size);
      EXPECT_EQ(tuples_with_null, 1 * tile_group_size);
      break;

    default:
      throw Exception("Unsupported join type : " + std::to_string(join_type));
      break;
  }

}

oid_t CountTuplesWithNullFields(executor::LogicalTile *logical_tile) {
  assert(logical_tile);

  // Get column count
  auto column_count = logical_tile->GetColumnCount();
  oid_t tuples_with_null = 0;

  // Go over the tile
  for (auto logical_tile_itr : *logical_tile) {
    const expression::ContainerTuple<executor::LogicalTile> left_tuple(
        logical_tile, logical_tile_itr);

      // Go over all the fields and check for null values
      for(oid_t col_itr = 0; col_itr < column_count; col_itr++) {
        auto val = left_tuple.GetValue(col_itr);
        if(val.IsNull()) {
          tuples_with_null++;
          break;
        }
      }

  }

  return tuples_with_null;
}

}  // namespace test
}  // namespace peloton
<commit_msg>Removed code<commit_after>//===----------------------------------------------------------------------===//
//
//                         PelotonDB
//
// hash_join_test.cpp
//
// Identification: tests/executor/hash_join_test.cpp
//
// Copyright (c) 2015, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include <memory>

#include "gmock/gmock.h"
#include "gtest/gtest.h"

#include "backend/common/types.h"
#include "backend/executor/logical_tile.h"
#include "backend/executor/logical_tile_factory.h"

#include "backend/executor/hash_join_executor.h"
#include "backend/executor/hash_executor.h"
#include "backend/executor/merge_join_executor.h"
#include "backend/executor/nested_loop_join_executor.h"

#include "backend/expression/abstract_expression.h"
#include "backend/expression/tuple_value_expression.h"
#include "backend/expression/expression_util.h"

#include "backend/planner/hash_join_plan.h"
#include "backend/planner/hash_plan.h"
#include "backend/planner/merge_join_plan.h"
#include "backend/planner/nested_loop_join_plan.h"

#include "backend/storage/data_table.h"

#include "mock_executor.h"
#include "executor/executor_tests_util.h"
#include "executor/join_tests_util.h"
#include "harness.h"

using ::testing::NotNull;
using ::testing::Return;

namespace peloton {
namespace test {

std::vector<planner::MergeJoinPlan::JoinClause> CreateJoinClauses() {
  std::vector<planner::MergeJoinPlan::JoinClause> join_clauses;
  auto left = expression::TupleValueFactory(0, 1);
  auto right = expression::TupleValueFactory(1, 1);
  bool reversed = false;
  join_clauses.emplace_back(left, right, reversed);
  return join_clauses;
}

std::vector<PlanNodeType> join_algorithms = {
    PLAN_NODE_TYPE_NESTLOOP,
    PLAN_NODE_TYPE_MERGEJOIN
    // TODO: Uncomment this to test hash join executor
    //  PLAN_NODE_TYPE_HASHJOIN
};

std::vector<PelotonJoinType> join_types = {
    JOIN_TYPE_INNER,
    JOIN_TYPE_LEFT,
    JOIN_TYPE_RIGHT,
    JOIN_TYPE_OUTER
};

void ExecuteJoinTest(PlanNodeType join_algorithm, PelotonJoinType join_type);

oid_t CountTuplesWithNullFields(executor::LogicalTile *logical_tile);

TEST(JoinTests, JoinPredicateTest) {

  // Go over all join algorithms
  for(auto join_algorithm : join_algorithms) {
    std::cout << "JOIN ALGORITHM :: " << PlanNodeTypeToString(join_algorithm) << "\n";

    // Go over all join types
    for(auto join_type : join_types) {
      std::cout << "JOIN TYPE :: " << join_type << "\n";

      // Execute the join test
      ExecuteJoinTest(join_algorithm, join_type);

    }
  }

}

void ExecuteJoinTest(PlanNodeType join_algorithm, PelotonJoinType join_type) {

  //===--------------------------------------------------------------------===//
  // Mock table scan executors
  //===--------------------------------------------------------------------===//

  MockExecutor left_table_scan_executor, right_table_scan_executor;

  // Create a table and wrap it in logical tile
  size_t tile_group_size = TESTS_TUPLES_PER_TILEGROUP;
  size_t left_table_tile_group_count = 3;
  size_t right_table_tile_group_count = 2;

  // Left table has 3 tile groups
  std::unique_ptr<storage::DataTable> left_table(
      ExecutorTestsUtil::CreateTable(tile_group_size));
  ExecutorTestsUtil::PopulateTable(left_table.get(),
                                   tile_group_size * left_table_tile_group_count,
                                   false,
                                   false, false);

  //std::cout << (*left_table);

  // Right table has 2 tile groups
  std::unique_ptr<storage::DataTable> right_table(
      ExecutorTestsUtil::CreateTable(tile_group_size));
  ExecutorTestsUtil::PopulateTable(right_table.get(),
                                   tile_group_size * right_table_tile_group_count,
                                   false, false, false);

  //std::cout << (*right_table);

  // Wrap the input tables with logical tiles
  std::unique_ptr<executor::LogicalTile> left_table_logical_tile1(
      executor::LogicalTileFactory::WrapTileGroup(left_table->GetTileGroup(0)));
  std::unique_ptr<executor::LogicalTile> left_table_logical_tile2(
      executor::LogicalTileFactory::WrapTileGroup(left_table->GetTileGroup(1)));
  std::unique_ptr<executor::LogicalTile> left_table_logical_tile3(
      executor::LogicalTileFactory::WrapTileGroup(left_table->GetTileGroup(2)));

  std::unique_ptr<executor::LogicalTile> right_table_logical_tile1(
      executor::LogicalTileFactory::WrapTileGroup(
          right_table->GetTileGroup(0)));
  std::unique_ptr<executor::LogicalTile> right_table_logical_tile2(
      executor::LogicalTileFactory::WrapTileGroup(
          right_table->GetTileGroup(1)));

  // Left scan executor returns logical tiles from the left table

  EXPECT_CALL(left_table_scan_executor, DInit())
  .WillOnce(Return(true));

  EXPECT_CALL(left_table_scan_executor, DExecute())
  .WillOnce(Return(true))
  .WillOnce(Return(true))
  .WillOnce(Return(true))
  .WillOnce(Return(false));

  EXPECT_CALL(left_table_scan_executor, GetOutput())
  .WillOnce(Return(left_table_logical_tile1.release()))
  .WillOnce(Return(left_table_logical_tile2.release()))
  .WillOnce(Return(left_table_logical_tile3.release()));

  // Right scan executor returns logical tiles from the right table

  EXPECT_CALL(right_table_scan_executor, DInit())
  .WillOnce(Return(true));

  EXPECT_CALL(right_table_scan_executor, DExecute())
  .WillOnce(Return(true))
  .WillOnce(Return(true))
  .WillOnce(Return(false));

  EXPECT_CALL(right_table_scan_executor, GetOutput())
  .WillOnce(Return(right_table_logical_tile1.release()))
  .WillOnce(Return(right_table_logical_tile2.release()));

  //===--------------------------------------------------------------------===//
  // Setup join plan nodes and executors and run them
  //===--------------------------------------------------------------------===//

  oid_t result_tuple_count = 0;
  oid_t tuples_with_null = 0;
  auto projection = JoinTestsUtil::CreateProjection();

  // Construct predicate
  expression::AbstractExpression *predicate = JoinTestsUtil::CreateJoinPredicate();

  // Differ based on join algorithm
  switch(join_algorithm) {

    case PLAN_NODE_TYPE_NESTLOOP: {

      // Create nested loop join plan node.
      planner::NestedLoopJoinPlan nested_loop_join_node(join_type, predicate, projection);

      // Run the nested loop join executor
      executor::NestedLoopJoinExecutor nested_loop_join_executor(&nested_loop_join_node, nullptr);

      // Construct the executor tree
      nested_loop_join_executor.AddChild(&left_table_scan_executor);
      nested_loop_join_executor.AddChild(&right_table_scan_executor);

      // Run the nested loop join executor
      EXPECT_TRUE(nested_loop_join_executor.Init());
      while(nested_loop_join_executor.Execute() == true) {
        std::unique_ptr<executor::LogicalTile> result_logical_tile(nested_loop_join_executor.GetOutput());

        if(result_logical_tile != nullptr) {
          result_tuple_count += result_logical_tile->GetTupleCount();
          tuples_with_null += CountTuplesWithNullFields(result_logical_tile.get());
        }
      }

    }
    break;

    case PLAN_NODE_TYPE_MERGEJOIN: {

      // Create join clauses
      std::vector<planner::MergeJoinPlan::JoinClause> join_clauses;
      join_clauses = CreateJoinClauses();

      // Create merge join plan node
      planner::MergeJoinPlan merge_join_node(join_type, predicate, projection, join_clauses);

      // Construct the merge join executor
      executor::MergeJoinExecutor merge_join_executor(&merge_join_node, nullptr);

      // Construct the executor tree
      merge_join_executor.AddChild(&left_table_scan_executor);
      merge_join_executor.AddChild(&right_table_scan_executor);

      // Run the merge join executor
      EXPECT_TRUE(merge_join_executor.Init());
      while(merge_join_executor.Execute() == true) {
        std::unique_ptr<executor::LogicalTile> result_logical_tile(merge_join_executor.GetOutput());

        if(result_logical_tile != nullptr) {
          result_tuple_count += result_logical_tile->GetTupleCount();
          tuples_with_null += CountTuplesWithNullFields(result_logical_tile.get());
          //std::cout << (*result_logical_tile);
        }
      }

    }
    break;

    case PLAN_NODE_TYPE_HASHJOIN: {

      // Create hash plan node
      expression::AbstractExpression *right_table_attr_1 =
          new expression::TupleValueExpression(1, 1);

      std::vector<std::unique_ptr<const expression::AbstractExpression> > hash_keys;
      hash_keys.emplace_back(right_table_attr_1);

      // Create hash plan node
      planner::HashPlan hash_plan_node(hash_keys);

      // Construct the hash executor
      executor::HashExecutor hash_executor(&hash_plan_node, nullptr);

      // Create hash join plan node.
      planner::HashJoinPlan hash_join_plan_node(join_type, predicate, projection);

      // Construct the hash join executor
      executor::HashJoinExecutor hash_join_executor(&hash_join_plan_node, nullptr);

      // Construct the executor tree
      hash_join_executor.AddChild(&left_table_scan_executor);
      hash_join_executor.AddChild(&hash_executor);

      hash_executor.AddChild(&right_table_scan_executor);

      // Run the hash_join_executor
      EXPECT_TRUE(hash_join_executor.Init());
      while(hash_join_executor.Execute() == true) {
        std::unique_ptr<executor::LogicalTile> result_logical_tile(hash_join_executor.GetOutput());

        if(result_logical_tile != nullptr) {
          result_tuple_count += result_logical_tile->GetTupleCount();
          tuples_with_null += CountTuplesWithNullFields(result_logical_tile.get());
          //std::cout << (*result_logical_tile);
        }
      }

    }
    break;

    default:
      throw Exception("Unsupported join algorithm : " + std::to_string(join_algorithm));
      break;
  }

  //===--------------------------------------------------------------------===//
  // Execute test
  //===--------------------------------------------------------------------===//

  // Check output
  switch(join_type) {
    case JOIN_TYPE_INNER:
      EXPECT_EQ(result_tuple_count, 2 * tile_group_size);
      EXPECT_EQ(tuples_with_null, 0 * tile_group_size);
      break;

    case JOIN_TYPE_LEFT:
      EXPECT_EQ(result_tuple_count, 3 * tile_group_size);
      EXPECT_EQ(tuples_with_null, 1 * tile_group_size);
      break;

    case JOIN_TYPE_RIGHT:
      EXPECT_EQ(result_tuple_count, 2 * tile_group_size);
      EXPECT_EQ(tuples_with_null, 0 * tile_group_size);
      break;

    case JOIN_TYPE_OUTER:
      EXPECT_EQ(result_tuple_count, 3 * tile_group_size);
      EXPECT_EQ(tuples_with_null, 1 * tile_group_size);
      break;

    default:
      throw Exception("Unsupported join type : " + std::to_string(join_type));
      break;
  }

}

oid_t CountTuplesWithNullFields(executor::LogicalTile *logical_tile) {
  assert(logical_tile);

  // Get column count
  auto column_count = logical_tile->GetColumnCount();
  oid_t tuples_with_null = 0;

  // Go over the tile
  for (auto logical_tile_itr : *logical_tile) {
    const expression::ContainerTuple<executor::LogicalTile> left_tuple(
        logical_tile, logical_tile_itr);

      // Go over all the fields and check for null values
      for(oid_t col_itr = 0; col_itr < column_count; col_itr++) {
        auto val = left_tuple.GetValue(col_itr);
        if(val.IsNull()) {
          tuples_with_null++;
          break;
        }
      }

  }

  return tuples_with_null;
}

}  // namespace test
}  // namespace peloton
<|endoftext|>


<commit_before>// Copyright (c) 2012 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 "ui/views/examples/text_example.h"

#include "base/utf_string_conversions.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/canvas.h"
#include "ui/views/controls/button/checkbox.h"
#include "ui/views/controls/combobox/combobox.h"
#include "ui/views/controls/label.h"
#include "ui/views/examples/example_combobox_model.h"
#include "ui/views/layout/grid_layout.h"
#include "ui/views/view.h"

namespace {

// Number of columns in the view layout.
const int kNumColumns = 10;

const char kShortText[] = "Batman";
const char kMediumText[] = "The quick brown fox jumps over the lazy dog.";
const char kLongText[] =
    "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod "
    "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
    "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
    "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
    "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
    "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
    "mollit anim id est laborum.";
const char kAmpersandText[] =
    "The quick && &brown fo&x jumps over the lazy dog.";
const char kNewlineText[] =
    "The quick \nbrown fox jumps\n\n over the lazy dog.";

const char* kTextExamples[] = {
    "Short",
    "Medium",
    "Long",
    "Ampersands",
    "Newlines",
};

const char* kElidingBehaviors[] = {
    "Ellipsis",
    "None",
#if defined(OS_WIN)
    "Fade Tail",
    "Fade Head",
    "Fade Head and Tail",
#endif
};

const char* kPrefixOptions[] = {
    "Default",
    "Show",
    "Hide",
};

const char* kHorizontalAligments[] = {
    "Default",
    "Left",
    "Center",
    "Right",
};

const char* kVerticalAlignments[] = {
    "Default",
    "Top",
    "Middle",
    "Bottom",
};

// Toggles bit |flag| on |flags| based on state of |checkbox|.
void SetFlagFromCheckbox(views::Checkbox* checkbox, int* flags, int flag) {
  if (checkbox->checked())
    *flags |= flag;
  else
    *flags &= ~flag;
}

}  // namespace

namespace views {
namespace examples {

// TextExample's content view, which is responsible for drawing a string with
// the specified style.
class TextExample::TextExampleView : public View {
 public:
  TextExampleView()
    : font_(ResourceBundle::GetSharedInstance().GetFont(
          ResourceBundle::BaseFont)),
      text_(ASCIIToUTF16(kShortText)),
      text_flags_(0),
      halo_(false),
      fade_(false),
      fade_mode_(gfx::Canvas::TruncateFadeTail) {
  }

  virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
#if defined(OS_WIN)
    if (fade_) {
      size_t characters_to_truncate_from_head =
          gfx::Canvas::TruncateFadeHeadAndTail ? 10 : 0;
      canvas->DrawFadeTruncatingString(text_, fade_mode_,
          characters_to_truncate_from_head, font_, SK_ColorDKGRAY,
          GetLocalBounds());
      return;
    }
#endif

    if (halo_) {
      canvas->DrawStringWithHalo(text_, font_, SK_ColorDKGRAY, SK_ColorWHITE, 0,
          0, width(), height(), text_flags_);
    } else {
      canvas->DrawStringInt(text_, font_, SK_ColorDKGRAY, 0, 0, width(),
          height(), text_flags_);
    }
  }

  int text_flags() const { return text_flags_; }
  void set_text_flags(int text_flags) { text_flags_ = text_flags; }

  const string16& text() const { return text_; }
  void set_text(const string16& text) { text_ = text; }

  bool halo() const { return halo_; }
  void set_halo(bool halo) { halo_ = halo; }

  bool fade() const { return fade_; }
  void set_fade(bool fade) { fade_ = fade; }

  gfx::Canvas::TruncateFadeMode fade_mode() const { return fade_mode_; }
  void set_fade_mode(gfx::Canvas::TruncateFadeMode fade_mode) {
    fade_mode_ = fade_mode;
  }

  int GetFontStyle() const {
    return font_.GetStyle();
  }
  void SetFontStyle(int style) {
    font_ = font_.DeriveFont(0, style);
  }

 private:
  // The font used for drawing the text.
  gfx::Font font_;

  // The text to draw.
  string16 text_;

  // Text flags for passing to |DrawStringInt()|.
  int text_flags_;

  // If |true|, specifies to call |DrawStringWithHalo()| instead of
  // |DrawStringInt()|.
  bool halo_;

  // If |true|, specifies to call |DrawFadeTruncatingString()| instead of
  // |DrawStringInt()|.
  bool fade_;

  // If |fade_| is |true|, fade mode parameter to |DrawFadeTruncatingString()|.
  gfx::Canvas::TruncateFadeMode fade_mode_;

  DISALLOW_COPY_AND_ASSIGN(TextExampleView);
};

TextExample::TextExample() : ExampleBase("Text Styles") {
}

TextExample::~TextExample() {
}

Checkbox* TextExample::AddCheckbox(GridLayout* layout, const char* name) {
  Checkbox* checkbox = new Checkbox(ASCIIToUTF16(name));
  checkbox->set_listener(this);
  layout->AddView(checkbox);
  return checkbox;
}

Combobox* TextExample::AddCombobox(GridLayout* layout,
                                   const char* name,
                                   const char** strings,
                                   int count) {
  layout->StartRow(0, 0);
  layout->AddView(new Label(ASCIIToUTF16(name)));
  ExampleComboboxModel* new_model = new ExampleComboboxModel(strings, count);
  example_combobox_model_.push_back(new_model);
  Combobox* combo_box = new Combobox(new_model);
  combo_box->SetSelectedItem(0);
  combo_box->set_listener(this);
  layout->AddView(combo_box, kNumColumns - 1, 1);
  return combo_box;
}

void TextExample::CreateExampleView(View* container) {
  text_view_ = new TextExampleView;

  GridLayout* layout = new GridLayout(container);
  container->SetLayoutManager(layout);

  layout->AddPaddingRow(0, 8);

  ColumnSet* column_set = layout->AddColumnSet(0);
  column_set->AddPaddingColumn(0, 8);
  column_set->AddColumn(GridLayout::LEADING, GridLayout::FILL,
                        0.1f, GridLayout::USE_PREF, 0, 0);
  for (int i = 0; i < kNumColumns - 1; i++)
    column_set->AddColumn(GridLayout::FILL, GridLayout::FILL,
                          0.1f, GridLayout::USE_PREF, 0, 0);
  column_set->AddPaddingColumn(0, 8);

  h_align_cb_ = AddCombobox(layout,
                            "H-Align",
                            kHorizontalAligments,
                            arraysize(kHorizontalAligments));
  v_align_cb_ = AddCombobox(layout,
                            "V-Align",
                            kVerticalAlignments,
                            arraysize(kVerticalAlignments));
  eliding_cb_ = AddCombobox(layout,
                            "Eliding",
                            kElidingBehaviors,
                            arraysize(kElidingBehaviors));
  prefix_cb_ = AddCombobox(layout,
                           "Prefix",
                           kPrefixOptions,
                           arraysize(kPrefixOptions));
  text_cb_ = AddCombobox(layout,
                         "Example Text",
                         kTextExamples,
                         arraysize(kTextExamples));

  layout->StartRow(0, 0);
  multiline_checkbox_ = AddCheckbox(layout, "Multiline");
  break_checkbox_ = AddCheckbox(layout, "Character Break");
  halo_checkbox_ = AddCheckbox(layout, "Text Halo");
  bold_checkbox_ = AddCheckbox(layout, "Bold");
  italic_checkbox_ = AddCheckbox(layout, "Italic");
  underline_checkbox_ = AddCheckbox(layout, "Underline");

  layout->AddPaddingRow(0, 32);

  column_set = layout->AddColumnSet(1);
  column_set->AddPaddingColumn(0, 16);
  column_set->AddColumn(GridLayout::FILL, GridLayout::FILL,
                        1, GridLayout::USE_PREF, 0, 0);
  column_set->AddPaddingColumn(0, 16);
  layout->StartRow(1, 1);
  layout->AddView(text_view_);

  layout->AddPaddingRow(0, 8);
}

void TextExample::ButtonPressed(Button* button,
                                const Event& event) {
  int flags = text_view_->text_flags();
  int style = text_view_->GetFontStyle();
  SetFlagFromCheckbox(multiline_checkbox_, &flags, gfx::Canvas::MULTI_LINE);
  SetFlagFromCheckbox(break_checkbox_, &flags, gfx::Canvas::CHARACTER_BREAK);
  SetFlagFromCheckbox(bold_checkbox_, &style, gfx::Font::BOLD);
  SetFlagFromCheckbox(italic_checkbox_, &style, gfx::Font::ITALIC);
  SetFlagFromCheckbox(underline_checkbox_, &style, gfx::Font::UNDERLINED);
  text_view_->set_halo(halo_checkbox_->checked());
  text_view_->set_text_flags(flags);
  text_view_->SetFontStyle(style);
  text_view_->SchedulePaint();
}

void TextExample::ItemChanged(Combobox* combo_box,
                              int prev_index,
                              int new_index) {
  int text_flags = text_view_->text_flags();
  if (combo_box == h_align_cb_) {
    text_flags &= ~(gfx::Canvas::TEXT_ALIGN_LEFT |
                    gfx::Canvas::TEXT_ALIGN_CENTER |
                    gfx::Canvas::TEXT_ALIGN_RIGHT);
    switch (new_index) {
      case 0:
        break;
      case 1:
        text_flags |= gfx::Canvas::TEXT_ALIGN_LEFT;
        break;
      case 2:
        text_flags |= gfx::Canvas::TEXT_ALIGN_CENTER;
        break;
      case 3:
        text_flags |= gfx::Canvas::TEXT_ALIGN_RIGHT;
        break;
    }
  } else if (combo_box == v_align_cb_) {
    text_flags &= ~(gfx::Canvas::TEXT_VALIGN_TOP |
                    gfx::Canvas::TEXT_VALIGN_MIDDLE |
                    gfx::Canvas::TEXT_VALIGN_BOTTOM);
    switch (new_index) {
      case 0:
        break;
      case 1:
        text_flags |= gfx::Canvas::TEXT_VALIGN_TOP;
        break;
      case 2:
        text_flags |= gfx::Canvas::TEXT_VALIGN_MIDDLE;
        break;
      case 3:
        text_flags |= gfx::Canvas::TEXT_VALIGN_BOTTOM;
        break;
    }
  } else if (combo_box == text_cb_) {
    switch (new_index) {
      case 0:
        text_view_->set_text(ASCIIToUTF16(kShortText));
        break;
      case 1:
        text_view_->set_text(ASCIIToUTF16(kMediumText));
        break;
      case 2:
        text_view_->set_text(ASCIIToUTF16(kLongText));
        break;
      case 3:
        text_view_->set_text(ASCIIToUTF16(kAmpersandText));
        break;
      case 4:
        text_view_->set_text(ASCIIToUTF16(kNewlineText));
        break;
    }
  } else if (combo_box == eliding_cb_) {
    switch (new_index) {
      case 0:
        text_flags &= ~gfx::Canvas::NO_ELLIPSIS;
        text_view_->set_fade(false);
        break;
      case 1:
        text_flags |= gfx::Canvas::NO_ELLIPSIS;
        text_view_->set_fade(false);
        break;
#if defined(OS_WIN)
      case 2:
        text_view_->set_fade_mode(gfx::Canvas::TruncateFadeTail);
        text_view_->set_fade(true);
        break;
      case 3:
        text_view_->set_fade_mode(gfx::Canvas::TruncateFadeHead);
        text_view_->set_fade(true);
        break;
      case 4:
        text_view_->set_fade_mode(gfx::Canvas::TruncateFadeHeadAndTail);
        text_view_->set_fade(true);
        break;
#endif
    }
  } else if (combo_box == prefix_cb_) {
    text_flags &= ~(gfx::Canvas::SHOW_PREFIX | gfx::Canvas::HIDE_PREFIX);
    switch (new_index) {
      case 0:
        break;
      case 1:
        text_flags |= gfx::Canvas::SHOW_PREFIX;
        break;
      case 2:
        text_flags |= gfx::Canvas::HIDE_PREFIX;
        break;
    }
  }
  text_view_->set_text_flags(text_flags);
  text_view_->SchedulePaint();
}

}  // namespace examples
}  // namespace views
<commit_msg>Add a border to views_examples' text styles example.<commit_after>// Copyright (c) 2012 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 "ui/views/examples/text_example.h"

#include "base/utf_string_conversions.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/canvas.h"
#include "ui/views/controls/button/checkbox.h"
#include "ui/views/controls/combobox/combobox.h"
#include "ui/views/controls/label.h"
#include "ui/views/examples/example_combobox_model.h"
#include "ui/views/layout/grid_layout.h"
#include "ui/views/view.h"

namespace {

// Number of columns in the view layout.
const int kNumColumns = 10;

const char kShortText[] = "Batman";
const char kMediumText[] = "The quick brown fox jumps over the lazy dog.";
const char kLongText[] =
    "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod "
    "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
    "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
    "commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
    "velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
    "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
    "mollit anim id est laborum.";
const char kAmpersandText[] =
    "The quick && &brown fo&x jumps over the lazy dog.";
const char kNewlineText[] =
    "The quick \nbrown fox jumps\n\n over the lazy dog.";

const char* kTextExamples[] = {
    "Short",
    "Medium",
    "Long",
    "Ampersands",
    "Newlines",
};

const char* kElidingBehaviors[] = {
    "Ellipsis",
    "None",
#if defined(OS_WIN)
    "Fade Tail",
    "Fade Head",
    "Fade Head and Tail",
#endif
};

const char* kPrefixOptions[] = {
    "Default",
    "Show",
    "Hide",
};

const char* kHorizontalAligments[] = {
    "Default",
    "Left",
    "Center",
    "Right",
};

const char* kVerticalAlignments[] = {
    "Default",
    "Top",
    "Middle",
    "Bottom",
};

// Toggles bit |flag| on |flags| based on state of |checkbox|.
void SetFlagFromCheckbox(views::Checkbox* checkbox, int* flags, int flag) {
  if (checkbox->checked())
    *flags |= flag;
  else
    *flags &= ~flag;
}

}  // namespace

namespace views {
namespace examples {

// TextExample's content view, which is responsible for drawing a string with
// the specified style.
class TextExample::TextExampleView : public View {
 public:
  TextExampleView()
    : font_(ResourceBundle::GetSharedInstance().GetFont(
          ResourceBundle::BaseFont)),
      text_(ASCIIToUTF16(kShortText)),
      text_flags_(0),
      halo_(false),
      fade_(false),
      fade_mode_(gfx::Canvas::TruncateFadeTail) {
  }

  virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
    View::OnPaint(canvas);

    const gfx::Rect bounds = GetContentsBounds();

#if defined(OS_WIN)
    if (fade_) {
      size_t characters_to_truncate_from_head =
          gfx::Canvas::TruncateFadeHeadAndTail ? 10 : 0;
      canvas->DrawFadeTruncatingString(text_, fade_mode_,
          characters_to_truncate_from_head, font_, SK_ColorDKGRAY, bounds);
      return;
    }
#endif

    if (halo_) {
      canvas->DrawStringWithHalo(text_, font_, SK_ColorDKGRAY, SK_ColorWHITE,
          bounds.x(), bounds.y(), bounds.width(), bounds.height(), text_flags_);
    } else {
      canvas->DrawStringInt(text_, font_, SK_ColorDKGRAY, bounds.x(),
          bounds.y(), bounds.width(), bounds.height(), text_flags_);
    }
  }

  int text_flags() const { return text_flags_; }
  void set_text_flags(int text_flags) { text_flags_ = text_flags; }

  const string16& text() const { return text_; }
  void set_text(const string16& text) { text_ = text; }

  bool halo() const { return halo_; }
  void set_halo(bool halo) { halo_ = halo; }

  bool fade() const { return fade_; }
  void set_fade(bool fade) { fade_ = fade; }

  gfx::Canvas::TruncateFadeMode fade_mode() const { return fade_mode_; }
  void set_fade_mode(gfx::Canvas::TruncateFadeMode fade_mode) {
    fade_mode_ = fade_mode;
  }

  int GetFontStyle() const {
    return font_.GetStyle();
  }
  void SetFontStyle(int style) {
    font_ = font_.DeriveFont(0, style);
  }

 private:
  // The font used for drawing the text.
  gfx::Font font_;

  // The text to draw.
  string16 text_;

  // Text flags for passing to |DrawStringInt()|.
  int text_flags_;

  // If |true|, specifies to call |DrawStringWithHalo()| instead of
  // |DrawStringInt()|.
  bool halo_;

  // If |true|, specifies to call |DrawFadeTruncatingString()| instead of
  // |DrawStringInt()|.
  bool fade_;

  // If |fade_| is |true|, fade mode parameter to |DrawFadeTruncatingString()|.
  gfx::Canvas::TruncateFadeMode fade_mode_;

  DISALLOW_COPY_AND_ASSIGN(TextExampleView);
};

TextExample::TextExample() : ExampleBase("Text Styles") {
}

TextExample::~TextExample() {
}

Checkbox* TextExample::AddCheckbox(GridLayout* layout, const char* name) {
  Checkbox* checkbox = new Checkbox(ASCIIToUTF16(name));
  checkbox->set_listener(this);
  layout->AddView(checkbox);
  return checkbox;
}

Combobox* TextExample::AddCombobox(GridLayout* layout,
                                   const char* name,
                                   const char** strings,
                                   int count) {
  layout->StartRow(0, 0);
  layout->AddView(new Label(ASCIIToUTF16(name)));
  ExampleComboboxModel* new_model = new ExampleComboboxModel(strings, count);
  example_combobox_model_.push_back(new_model);
  Combobox* combo_box = new Combobox(new_model);
  combo_box->SetSelectedItem(0);
  combo_box->set_listener(this);
  layout->AddView(combo_box, kNumColumns - 1, 1);
  return combo_box;
}

void TextExample::CreateExampleView(View* container) {
  text_view_ = new TextExampleView;
  text_view_->set_border(views::Border::CreateSolidBorder(1, SK_ColorGRAY));

  GridLayout* layout = new GridLayout(container);
  container->SetLayoutManager(layout);

  layout->AddPaddingRow(0, 8);

  ColumnSet* column_set = layout->AddColumnSet(0);
  column_set->AddPaddingColumn(0, 8);
  column_set->AddColumn(GridLayout::LEADING, GridLayout::FILL,
                        0.1f, GridLayout::USE_PREF, 0, 0);
  for (int i = 0; i < kNumColumns - 1; i++)
    column_set->AddColumn(GridLayout::FILL, GridLayout::FILL,
                          0.1f, GridLayout::USE_PREF, 0, 0);
  column_set->AddPaddingColumn(0, 8);

  h_align_cb_ = AddCombobox(layout,
                            "H-Align",
                            kHorizontalAligments,
                            arraysize(kHorizontalAligments));
  v_align_cb_ = AddCombobox(layout,
                            "V-Align",
                            kVerticalAlignments,
                            arraysize(kVerticalAlignments));
  eliding_cb_ = AddCombobox(layout,
                            "Eliding",
                            kElidingBehaviors,
                            arraysize(kElidingBehaviors));
  prefix_cb_ = AddCombobox(layout,
                           "Prefix",
                           kPrefixOptions,
                           arraysize(kPrefixOptions));
  text_cb_ = AddCombobox(layout,
                         "Example Text",
                         kTextExamples,
                         arraysize(kTextExamples));

  layout->StartRow(0, 0);
  multiline_checkbox_ = AddCheckbox(layout, "Multiline");
  break_checkbox_ = AddCheckbox(layout, "Character Break");
  halo_checkbox_ = AddCheckbox(layout, "Text Halo");
  bold_checkbox_ = AddCheckbox(layout, "Bold");
  italic_checkbox_ = AddCheckbox(layout, "Italic");
  underline_checkbox_ = AddCheckbox(layout, "Underline");

  layout->AddPaddingRow(0, 32);

  column_set = layout->AddColumnSet(1);
  column_set->AddPaddingColumn(0, 16);
  column_set->AddColumn(GridLayout::FILL, GridLayout::FILL,
                        1, GridLayout::USE_PREF, 0, 0);
  column_set->AddPaddingColumn(0, 16);
  layout->StartRow(1, 1);
  layout->AddView(text_view_);

  layout->AddPaddingRow(0, 8);
}

void TextExample::ButtonPressed(Button* button,
                                const Event& event) {
  int flags = text_view_->text_flags();
  int style = text_view_->GetFontStyle();
  SetFlagFromCheckbox(multiline_checkbox_, &flags, gfx::Canvas::MULTI_LINE);
  SetFlagFromCheckbox(break_checkbox_, &flags, gfx::Canvas::CHARACTER_BREAK);
  SetFlagFromCheckbox(bold_checkbox_, &style, gfx::Font::BOLD);
  SetFlagFromCheckbox(italic_checkbox_, &style, gfx::Font::ITALIC);
  SetFlagFromCheckbox(underline_checkbox_, &style, gfx::Font::UNDERLINED);
  text_view_->set_halo(halo_checkbox_->checked());
  text_view_->set_text_flags(flags);
  text_view_->SetFontStyle(style);
  text_view_->SchedulePaint();
}

void TextExample::ItemChanged(Combobox* combo_box,
                              int prev_index,
                              int new_index) {
  int text_flags = text_view_->text_flags();
  if (combo_box == h_align_cb_) {
    text_flags &= ~(gfx::Canvas::TEXT_ALIGN_LEFT |
                    gfx::Canvas::TEXT_ALIGN_CENTER |
                    gfx::Canvas::TEXT_ALIGN_RIGHT);
    switch (new_index) {
      case 0:
        break;
      case 1:
        text_flags |= gfx::Canvas::TEXT_ALIGN_LEFT;
        break;
      case 2:
        text_flags |= gfx::Canvas::TEXT_ALIGN_CENTER;
        break;
      case 3:
        text_flags |= gfx::Canvas::TEXT_ALIGN_RIGHT;
        break;
    }
  } else if (combo_box == v_align_cb_) {
    text_flags &= ~(gfx::Canvas::TEXT_VALIGN_TOP |
                    gfx::Canvas::TEXT_VALIGN_MIDDLE |
                    gfx::Canvas::TEXT_VALIGN_BOTTOM);
    switch (new_index) {
      case 0:
        break;
      case 1:
        text_flags |= gfx::Canvas::TEXT_VALIGN_TOP;
        break;
      case 2:
        text_flags |= gfx::Canvas::TEXT_VALIGN_MIDDLE;
        break;
      case 3:
        text_flags |= gfx::Canvas::TEXT_VALIGN_BOTTOM;
        break;
    }
  } else if (combo_box == text_cb_) {
    switch (new_index) {
      case 0:
        text_view_->set_text(ASCIIToUTF16(kShortText));
        break;
      case 1:
        text_view_->set_text(ASCIIToUTF16(kMediumText));
        break;
      case 2:
        text_view_->set_text(ASCIIToUTF16(kLongText));
        break;
      case 3:
        text_view_->set_text(ASCIIToUTF16(kAmpersandText));
        break;
      case 4:
        text_view_->set_text(ASCIIToUTF16(kNewlineText));
        break;
    }
  } else if (combo_box == eliding_cb_) {
    switch (new_index) {
      case 0:
        text_flags &= ~gfx::Canvas::NO_ELLIPSIS;
        text_view_->set_fade(false);
        break;
      case 1:
        text_flags |= gfx::Canvas::NO_ELLIPSIS;
        text_view_->set_fade(false);
        break;
#if defined(OS_WIN)
      case 2:
        text_view_->set_fade_mode(gfx::Canvas::TruncateFadeTail);
        text_view_->set_fade(true);
        break;
      case 3:
        text_view_->set_fade_mode(gfx::Canvas::TruncateFadeHead);
        text_view_->set_fade(true);
        break;
      case 4:
        text_view_->set_fade_mode(gfx::Canvas::TruncateFadeHeadAndTail);
        text_view_->set_fade(true);
        break;
#endif
    }
  } else if (combo_box == prefix_cb_) {
    text_flags &= ~(gfx::Canvas::SHOW_PREFIX | gfx::Canvas::HIDE_PREFIX);
    switch (new_index) {
      case 0:
        break;
      case 1:
        text_flags |= gfx::Canvas::SHOW_PREFIX;
        break;
      case 2:
        text_flags |= gfx::Canvas::HIDE_PREFIX;
        break;
    }
  }
  text_view_->set_text_flags(text_flags);
  text_view_->SchedulePaint();
}

}  // namespace examples
}  // namespace views
<|endoftext|>


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

Program:   ITK nSIFT Implemention - Command Line Wrapper
Language:  C++
Date:      $Date$
Version:   $Revision$
Copyright (c) 2005,2006,2007 Warren Cheung

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.
* The name of the Insight Consortium, nor the names of any consortium members,
nor of any contributors, may be used to endorse or promote products derived
from this software without specific prior written permission.
* Modified source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER 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 AUTHORS 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.
=========================================================================*/

#define GENERATE_KEYS
#define VERBOSE
#define CROP

#include "itkScaleInvariantFeatureImageFilter.h"
#include "itkImageSeriesReader.h"
#include "itkNumericSeriesFileNames.h"
#include "itkPointSetToImageFilter.h"
#include "itkImageFileWriter.h"
#include "otbMath.h"

int itk2DScaleInvariantFeatureImageFilterTest( int argc, char *argv[])
{
  const unsigned int Dimension = 2;

  const char* inputImage1 = argv[1];
  const char* outputImage1 = argv[2];
  const char* outputImage2 = argv[3];
  const char* outputImageKeys1 = argv[4];
  const char* outputImageKeys2 = argv[5];

  // Default parametres
  // scale is 1.0
  // rotate is 0 degrees
  // crop is 0.5
  // rotate_middle is 0 (rotating around the origin
  // mode is s (synthetic)

  double test_scale = atof(argv[6]);
  float test_rotate = atof(argv[7])* M_PI * 2.0 / 360.0;
  double test_crop = atof(argv[8]);
  int rotate_middle= atoi(argv[9]);
  int mode = 's';

  typedef float PixelType;
  typedef itk::Image<PixelType, Dimension> FixedImageType;
  typedef itk::ScaleInvariantFeatureImageFilter<FixedImageType, Dimension> SiftFilterType;
  typedef itk::Image<unsigned char, Dimension> OutputImageType;

  typedef itk::ImageSource<FixedImageType> ImageSourceType;

  ImageSourceType::Pointer fixedImageReader, fixedImageReader2;

  typedef itk::PointSetToImageFilter<SiftFilterType::PointSetType, OutputImageType> PointSetFilterType;

  std::cerr << "Dimension = " << Dimension << "\n";
  std::cerr << "Test Scale = " << test_scale << "\n";
  std::cerr << "Test Rotate = " << test_rotate << "\n";
  std::cerr << "Image Crop Ratio (first 3D) = " << test_crop << "\n";
  std::cerr << "Mode = " << (char) mode << "\n";
  std::cerr << "ImageFile1 = " << inputImage1 << "\n";
  std::cerr << "SIFT Feature\n" << std::endl;

  typedef itk::ImageFileReader< FixedImageType  > FixedImageReaderType;
  FixedImageReaderType::Pointer tmpImageReader  = FixedImageReaderType::New();
  tmpImageReader  = FixedImageReaderType::New();

  tmpImageReader->SetFileName(  inputImage1 );
  fixedImageReader=tmpImageReader;
  fixedImageReader->Update();

  typedef itk::ScalableAffineTransform< double, Dimension > ScaleType;
#ifdef CROP
  ScaleType::Pointer no_transform = ScaleType::New();
  no_transform->SetIdentity();

  SiftFilterType::ResampleFilterType::Pointer cropper = SiftFilterType::ResampleFilterType::New();
  cropper->SetInput(fixedImageReader->GetOutput());
  FixedImageType::SizeType cropsize =
    fixedImageReader->GetOutput()->GetLargestPossibleRegion().GetSize();
  for (unsigned int k = 0; k < Dimension; ++k) {
    if (k < 4)
      cropsize[k] = (int) (cropsize[k] * test_crop);
  }
  cropper->SetSize( cropsize );
  cropper->SetOutputSpacing(fixedImageReader->GetOutput()->GetSpacing());
  cropper->SetTransform(no_transform);
  cropper->Update();
  FixedImageType::Pointer fixedImage = cropper->GetOutput();
#else
  FixedImageType::Pointer fixedImage = fixedImageReader->GetOutput();
#endif

  SiftFilterType::PointSetTypePointer keypoints1, keypoints2;
  PointSetFilterType::Pointer pointSet1 = PointSetFilterType::New();
  PointSetFilterType::Pointer pointSet2 = PointSetFilterType::New();

  SiftFilterType siftFilter1, siftFilter2;

  siftFilter1.writeImage(fixedImage, outputImage1);
  std::cout << std::endl << "Starting SIFT Feature Extraction...\n";
  keypoints1 = siftFilter1.getSiftFeatures(fixedImage);

  pointSet1->SetInput(keypoints1);
  pointSet1->SetOutsideValue(0);
  pointSet1->SetInsideValue(255);
  pointSet1->SetSize(fixedImage->GetLargestPossibleRegion().GetSize());
  pointSet1->Update();

  typedef itk::ImageFileWriter<OutputImageType> WriterType;

  WriterType::Pointer writer = WriterType::New();
  writer->SetFileName(outputImageKeys1);
  writer->SetInput(pointSet1->GetOutput());
  writer->Update();

  typedef itk::ScalableAffineTransform< double, Dimension > TestTransformType;
  TestTransformType::Pointer inv_test_transform;

  // Synthetic test image
  if (mode=='s') {
    std::cerr << std::endl << "Synthetic image mode\n";
    TestTransformType::Pointer test_transform = TestTransformType::New();

    inv_test_transform = TestTransformType::New();

    TestTransformType::InputPointType translate_vector;

    test_transform->SetIdentity();
    test_transform->Scale( 1.0 / test_scale);
    if (rotate_middle) {
      std::cerr << "Rotation centred at middle of image." << std::endl;
      /* Cycle through each dimension and shift by half*/
      FixedImageType::SizeType size =
	fixedImage->GetLargestPossibleRegion().GetSize();
      for (unsigned int k = 0; k < Dimension; ++k)
	translate_vector[k] = size[k]/2.0;
      test_transform->SetCenter( translate_vector);
    } else {
      std::cerr << "Rotation centred at origin." << std::endl;
    }
#if 0
    if (rotate_middle) {
      std::cerr << "Rotation centred at middle of image." << std::endl;
      /* Cycle through each dimension and shift by half*/
      FixedImageType::SizeType size =
	fixedImage->GetLargestPossibleRegion().GetSize();
      for (unsigned int k = 0; k < Dimension; ++k)
	translate_vector[k] = size[k]/2.0;
      test_transform->Translate( translate_vector);
    } else {
      std::cerr << "Rotation centred at origin." << std::endl;
    }
#endif

    test_transform->Rotate(0,1,test_rotate);
#if 0
    if (rotate_middle) {
      /* Cycle through each dimension and shift back*/
      for (unsigned int k = 0; k < Dimension; ++k)
	translate_vector[k] = -translate_vector[k];
      test_transform->Translate( translate_vector);
    }
#endif

    test_transform->GetInverse(inv_test_transform);

    {
      FixedImageType::Pointer scaledImage;

      SiftFilterType::ResampleFilterType::Pointer scaler = SiftFilterType::ResampleFilterType::New();
      scaler->SetInput(fixedImage);
      FixedImageType::SizeType size =
	fixedImage->GetLargestPossibleRegion().GetSize();
      for (unsigned int k = 0; k < Dimension; ++k)
	size[k] = (unsigned int) floor(size[k] * test_scale);
      scaler->SetSize( size );

      scaler->SetOutputSpacing(fixedImage->GetSpacing());
      scaler->SetTransform(test_transform);
      scaler->Update();
      scaledImage = scaler->GetOutput();

      siftFilter2.writeImage(scaledImage, outputImage2);
      std::cout << std::endl;

      keypoints2 = siftFilter2.getSiftFeatures(scaledImage);

      pointSet2->SetInput(keypoints2);
      pointSet2->SetOutsideValue(0);
      pointSet2->SetInsideValue(255);
      pointSet2->SetSize(scaledImage->GetLargestPossibleRegion().GetSize());
      pointSet2->Update();

      WriterType::Pointer writer2 = WriterType::New();
      writer2->SetFileName(outputImageKeys2);
      writer2->SetInput(pointSet2->GetOutput());
      writer2->Update();
    }

    std::cerr << "Test Image Scale: " << test_scale << std::endl;
    std::cerr << "Test Image Rotate: " << test_rotate << std::endl;
    std::cerr << std::endl << "Matching Keypoints\n";

    siftFilter2.MatchKeypointsPos(keypoints1, keypoints2, inv_test_transform);
    siftFilter2.MatchKeypointsFeatures(keypoints1, keypoints2, inv_test_transform);
  }
  return 0;
}
<commit_msg>BUG: M_PI correction for Utilities testing<commit_after>/*=========================================================================

Program:   ITK nSIFT Implemention - Command Line Wrapper
Language:  C++
Date:      $Date$
Version:   $Revision$
Copyright (c) 2005,2006,2007 Warren Cheung

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.
* The name of the Insight Consortium, nor the names of any consortium members,
nor of any contributors, may be used to endorse or promote products derived
from this software without specific prior written permission.
* Modified source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER 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 AUTHORS 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.
=========================================================================*/

#define GENERATE_KEYS
#define VERBOSE
#define CROP

#include "itkScaleInvariantFeatureImageFilter.h"
#include "itkImageSeriesReader.h"
#include "itkNumericSeriesFileNames.h"
#include "itkPointSetToImageFilter.h"
#include "itkImageFileWriter.h"
#include "otbMath.h"

int itk2DScaleInvariantFeatureImageFilterTest( int argc, char *argv[])
{
  const unsigned int Dimension = 2;

  const char* inputImage1 = argv[1];
  const char* outputImage1 = argv[2];
  const char* outputImage2 = argv[3];
  const char* outputImageKeys1 = argv[4];
  const char* outputImageKeys2 = argv[5];

  // Default parametres
  // scale is 1.0
  // rotate is 0 degrees
  // crop is 0.5
  // rotate_middle is 0 (rotating around the origin
  // mode is s (synthetic)

  double test_scale = atof(argv[6]);
  float test_rotate = static_cast<float>(atof(argv[7])* otb::CONST_PI_180); //M_PI * 2.0 / 360.0;
  double test_crop = atof(argv[8]);
  int rotate_middle= atoi(argv[9]);
  int mode = 's';

  typedef float PixelType;
  typedef itk::Image<PixelType, Dimension> FixedImageType;
  typedef itk::ScaleInvariantFeatureImageFilter<FixedImageType, Dimension> SiftFilterType;
  typedef itk::Image<unsigned char, Dimension> OutputImageType;

  typedef itk::ImageSource<FixedImageType> ImageSourceType;

  ImageSourceType::Pointer fixedImageReader, fixedImageReader2;

  typedef itk::PointSetToImageFilter<SiftFilterType::PointSetType, OutputImageType> PointSetFilterType;

  std::cerr << "Dimension = " << Dimension << "\n";
  std::cerr << "Test Scale = " << test_scale << "\n";
  std::cerr << "Test Rotate = " << test_rotate << "\n";
  std::cerr << "Image Crop Ratio (first 3D) = " << test_crop << "\n";
  std::cerr << "Mode = " << (char) mode << "\n";
  std::cerr << "ImageFile1 = " << inputImage1 << "\n";
  std::cerr << "SIFT Feature\n" << std::endl;

  typedef itk::ImageFileReader< FixedImageType  > FixedImageReaderType;
  FixedImageReaderType::Pointer tmpImageReader  = FixedImageReaderType::New();
  tmpImageReader  = FixedImageReaderType::New();

  tmpImageReader->SetFileName(  inputImage1 );
  fixedImageReader=tmpImageReader;
  fixedImageReader->Update();

  typedef itk::ScalableAffineTransform< double, Dimension > ScaleType;
#ifdef CROP
  ScaleType::Pointer no_transform = ScaleType::New();
  no_transform->SetIdentity();

  SiftFilterType::ResampleFilterType::Pointer cropper = SiftFilterType::ResampleFilterType::New();
  cropper->SetInput(fixedImageReader->GetOutput());
  FixedImageType::SizeType cropsize =
    fixedImageReader->GetOutput()->GetLargestPossibleRegion().GetSize();
  for (unsigned int k = 0; k < Dimension; ++k) {
    if (k < 4)
      cropsize[k] = (int) (cropsize[k] * test_crop);
  }
  cropper->SetSize( cropsize );
  cropper->SetOutputSpacing(fixedImageReader->GetOutput()->GetSpacing());
  cropper->SetTransform(no_transform);
  cropper->Update();
  FixedImageType::Pointer fixedImage = cropper->GetOutput();
#else
  FixedImageType::Pointer fixedImage = fixedImageReader->GetOutput();
#endif

  SiftFilterType::PointSetTypePointer keypoints1, keypoints2;
  PointSetFilterType::Pointer pointSet1 = PointSetFilterType::New();
  PointSetFilterType::Pointer pointSet2 = PointSetFilterType::New();

  SiftFilterType siftFilter1, siftFilter2;

  siftFilter1.writeImage(fixedImage, outputImage1);
  std::cout << std::endl << "Starting SIFT Feature Extraction...\n";
  keypoints1 = siftFilter1.getSiftFeatures(fixedImage);

  pointSet1->SetInput(keypoints1);
  pointSet1->SetOutsideValue(0);
  pointSet1->SetInsideValue(255);
  pointSet1->SetSize(fixedImage->GetLargestPossibleRegion().GetSize());
  pointSet1->Update();

  typedef itk::ImageFileWriter<OutputImageType> WriterType;

  WriterType::Pointer writer = WriterType::New();
  writer->SetFileName(outputImageKeys1);
  writer->SetInput(pointSet1->GetOutput());
  writer->Update();

  typedef itk::ScalableAffineTransform< double, Dimension > TestTransformType;
  TestTransformType::Pointer inv_test_transform;

  // Synthetic test image
  if (mode=='s') {
    std::cerr << std::endl << "Synthetic image mode\n";
    TestTransformType::Pointer test_transform = TestTransformType::New();

    inv_test_transform = TestTransformType::New();

    TestTransformType::InputPointType translate_vector;

    test_transform->SetIdentity();
    test_transform->Scale( 1.0 / test_scale);
    if (rotate_middle) {
      std::cerr << "Rotation centred at middle of image." << std::endl;
      /* Cycle through each dimension and shift by half*/
      FixedImageType::SizeType size =
	fixedImage->GetLargestPossibleRegion().GetSize();
      for (unsigned int k = 0; k < Dimension; ++k)
	translate_vector[k] = size[k]/2.0;
      test_transform->SetCenter( translate_vector);
    } else {
      std::cerr << "Rotation centred at origin." << std::endl;
    }
#if 0
    if (rotate_middle) {
      std::cerr << "Rotation centred at middle of image." << std::endl;
      /* Cycle through each dimension and shift by half*/
      FixedImageType::SizeType size =
	fixedImage->GetLargestPossibleRegion().GetSize();
      for (unsigned int k = 0; k < Dimension; ++k)
	translate_vector[k] = size[k]/2.0;
      test_transform->Translate( translate_vector);
    } else {
      std::cerr << "Rotation centred at origin." << std::endl;
    }
#endif

    test_transform->Rotate(0,1,test_rotate);
#if 0
    if (rotate_middle) {
      /* Cycle through each dimension and shift back*/
      for (unsigned int k = 0; k < Dimension; ++k)
	translate_vector[k] = -translate_vector[k];
      test_transform->Translate( translate_vector);
    }
#endif

    test_transform->GetInverse(inv_test_transform);

    {
      FixedImageType::Pointer scaledImage;

      SiftFilterType::ResampleFilterType::Pointer scaler = SiftFilterType::ResampleFilterType::New();
      scaler->SetInput(fixedImage);
      FixedImageType::SizeType size =
	fixedImage->GetLargestPossibleRegion().GetSize();
      for (unsigned int k = 0; k < Dimension; ++k)
	size[k] = (unsigned int) floor(size[k] * test_scale);
      scaler->SetSize( size );

      scaler->SetOutputSpacing(fixedImage->GetSpacing());
      scaler->SetTransform(test_transform);
      scaler->Update();
      scaledImage = scaler->GetOutput();

      siftFilter2.writeImage(scaledImage, outputImage2);
      std::cout << std::endl;

      keypoints2 = siftFilter2.getSiftFeatures(scaledImage);

      pointSet2->SetInput(keypoints2);
      pointSet2->SetOutsideValue(0);
      pointSet2->SetInsideValue(255);
      pointSet2->SetSize(scaledImage->GetLargestPossibleRegion().GetSize());
      pointSet2->Update();

      WriterType::Pointer writer2 = WriterType::New();
      writer2->SetFileName(outputImageKeys2);
      writer2->SetInput(pointSet2->GetOutput());
      writer2->Update();
    }

    std::cerr << "Test Image Scale: " << test_scale << std::endl;
    std::cerr << "Test Image Rotate: " << test_rotate << std::endl;
    std::cerr << std::endl << "Matching Keypoints\n";

    siftFilter2.MatchKeypointsPos(keypoints1, keypoints2, inv_test_transform);
    siftFilter2.MatchKeypointsFeatures(keypoints1, keypoints2, inv_test_transform);
  }
  return 0;
}
<|endoftext|>