text:
//==============================================================================
//         Copyright 2003 - 2012   LASMEA UMR 6602 CNRS/Univ. Clermont II
//         Copyright 2009 - 2012   LRI    UMR 8623 CNRS/Univ Paris Sud XI
//         Copyright 2012 - 2013   MetaScale SAS
//
//          Distributed under the Boost Software License, Version 1.0.
//                 See accompanying file LICENSE.txt or copy at
//                     http://www.boost.org/LICENSE_1_0.txt
//==============================================================================
#ifndef BOOST_SIMD_SDK_SIMD_EXTENSIONS_POWERPC_VSX_HPP_INCLUDED
#define BOOST_SIMD_SDK_SIMD_EXTENSIONS_POWERPC_VSX_HPP_INCLUDED

#if defined(__VSX__)
#  ifndef BOOST_SIMD_HAS_VSX_SUPPORT
#    define BOOST_SIMD_HAS_VSX_SUPPORT
#  endif
#elif defined(BOOST_SIMD_HAS_VSX_SUPPORT)
#  undef BOOST_SIMD_HAS_VSX_SUPPORT
#endif

#if !defined(BOOST_SIMD_DETECTED) && defined(BOOST_SIMD_HAS_VSX_SUPPORT)

////////////////////////////////////////////////////////////////////////////////
// Include the proper intrinsic include. Depending of the option used by the
// compiler (-faltivec or -maltivec), we need to include altivec.h or not.
////////////////////////////////////////////////////////////////////////////////
#if !defined(__APPLE_CC__) || __APPLE_CC__ <= 1 || __GNUC__ >= 4
#include <altivec.h>
#endif

#ifdef bool
#undef bool
#endif
#ifdef pixel
#undef pixel
#endif
#ifdef vector
#undef vector
#endif

#if defined(__IBMCPP__) || defined(__MWERKS__)
#define __bool bool
#endif

////////////////////////////////////////////////////////////////////////////////
// Altivec PPC extensions flags
////////////////////////////////////////////////////////////////////////////////
#define BOOST_SIMD_DETECTED
#define BOOST_SIMD_ALTIVEC
#define BOOST_SIMD_STRING             "VSX"
#define BOOST_SIMD_STRING_LIST        "VMX VSX"
#define BOOST_SIMD_VMX_FAMILY
#define BOOST_SIMD_BYTES              16
#define BOOST_SIMD_BITS               128
#define BOOST_SIMD_CARDINALS          (2)(4)(8)(16)
#define BOOST_SIMD_TAG_SEQ            (::boost::simd::tag::vmx_)

#ifndef BOOST_SIMD_DEFAULT_EXTENSION
#define BOOST_SIMD_DEFAULT_EXTENSION  ::boost::simd::tag::vmx_
#endif

#define BOOST_SIMD_DEFAULT_SITE       ::boost::simd::tag::vsx_
#define BOOST_SIMD_NO_DENORMALS
#define BOOST_SIMD_SIMD_HAS_ALL_TYPES

#include <boost/simd/sdk/simd/extensions/meta/vmx.hpp>

#endif
#endif


text:
/* ------------Includes---------------------- */
#include <cmath>
#include <iostream>
#include <utility>
#include <unistd.h>
#include "../include/CAN_utils.h"
#include "../include/CO_message.h"
#include "../include/vehicle.h"
#include "../include/motor.h"
#include "../include/caster.h"
#include <Eigen/Core>
#include <Eigen/QR>
#include <Eigen/Geometry>
#include <Eigen/Dense>
#include <Eigen/LU>
#include <omniveyor_common/definitions.h>

// #define VELOCITY_SATURATION
// #define SEND_ZERO_TORQUES
#define CLAMP_TORQUES

using std::cout;
using std::endl;

/* --------------------------- STATIC FUNCTION PROTOTYPES ------------------------------- */
static double casterPosXSign(int casterNum);
static double casterPosYSign(int casterNum);
static Eigen::Vector3d clampVelocity(Eigen::Vector3d xd_com_in);
static Eigen::Vector3d clampAcceleration(Eigen::Vector3d xdd_com_in);
static float saturate(float x);

/* --------------------------- PUBLIC MEMBER FUNCTIONS ------------------------------- */

/* Constructor. Caster number starts at 1 */
Vehicle::Vehicle()
{
	_initialized = false;
	_enabled = false;
	_stopped = false;
	_control = VELOCITY;

	_x_local.setZero();
	_xd_local.setZero();
	_gx.setZero();
	_gxd.setZero();
	_gxd_com.setZero();
	_gxd_des.setZero();
	_gxdd.setZero();

	_g_cf.setZero();
	_cf_des_local.setZero();

	_q_steer.setZero();
	_qd.setZero();
	_qd_des.setZero();
	_tq.setZero();
	_tq_des.setZero();
	_lambda.setZero();
	_mu.setZero();
	_C.setZero();
	_Cp.setZero();
	_Jq.setZero();
	_C_pinv.setZero();

	_heading = 0;

	_Kp.setZero(); // zero gains for torque control initially
	_Kv.setZero(); // zero gains for torque control initially

	// create casters
	for(int i = 0; i < NUM_CASTERS; i++)
	{
		casters[i] = new Caster(i+1);
	}

	/* create a socket for the control thread */
	s = create_can_socket (UNUSED_NODE_ID, 0xF);
	if (s < 0)
	{
		perror ("Unable to open control socket\n");
		exit (-1);
	}
	//CO_Set_bitrate(s, 500000);
}

/* Destructor */
Vehicle::~Vehicle()
{
	_initialized = false;
	/* quick stop to motors - wait (x amount of time)*/

	/* destroy caster objects */
	for(int i = 0; i < NUM_CASTERS; i++)
	{
		delete casters[i];
	}
	/* reset comm */
	struct CO_message msg;
	msg.type = NMT;
	msg.m.NMT.data = 0x81;
	CO_send_message (s, 0, &msg);
	shutdown(s,1);
	//close(s);
}

/* Intializes all casters */
int Vehicle::init()
{
	for(int i = 0; i < NUM_CASTERS; i++)
	{
		if(casters[i]->init())
		{
			return -1;
		}
	}
	_initialized = true;
	return 0;
}

/* Enable all casters*/
int Vehicle::enable()
{
	if(!_initialized)
	{
		return -1;
	}

	for(int i = 0; i < NUM_CASTERS; i++)
	{
		if(casters[i]->enable())
		{
			return -1;
		}
	}

	_enabled = true;
	_stopped = false;
	return 0;
}

/* Disable all casters */
int Vehicle::disable()
{
	if(!_initialized)
	{
		return -1;
	}

	for(int i = 0; i < NUM_CASTERS; i++)
	{
		if(casters[i]->disable())
		{
			return -1;
		}
	}

	_enabled = false;
	return 0;
}

/* Stop all motors */
// HAVEN'T GOTTEN THIS TO WORK YET - CAN USE WHATEVER METHOD YOU WANT
int Vehicle::stop()
{
	if (!_enabled)
	{
		return -1;
	}

	for(int i = 0; i < NUM_CASTERS; i++)
	{
		if(casters[i]->stop() == 0)
		{
			cout << "stopping caster " << i << endl;
			// return -1;
		}
	}

	_stopped = true; // wait for stop?
	return 0;
}

int Vehicle::start()
{
	if (!_enabled)
	{
		return -1;
	}

	for(int i = 0; i < NUM_CASTERS; i++)
	{
		if(casters[i]->start() == 0)
		{
			cout << "starting caster " << i << endl;
			// return -1;
		}
	}

	_stopped = false; // wait for stop?
	return 0;
}

/* Set control mode to velocity or torque control.
 * This can only be set when the motors are disabled.
 */
int Vehicle::setCtrlMode(enum ctrl_mode cm)
{
	if(_enabled && !_stopped)
	{
		return -1; // only set mode if disabled
	}

	// Set mode
	_control = cm;
	cout << "Setting vehicle control mode to : " << cm << endl;
	for(int i = 0; i < NUM_CASTERS; i++)
	{
		if(casters[i]->setCtrlMode(cm))
		{
			return -1;
		}
	}

	return 0;
}

/* Update the local and global coordinates of the
 * operational point of the mobile base
 */
void Vehicle::updateOdometry(){
	updateJointData();
	// Eigen::Matrix<double, NUM_MOTORS, 1> deltaQ = getDeltaQ();

	// Calculate C_p^+
	updateConstraintPinvMatrix();

	// Find velocity and position of the base in the frame of the base with respect to the world origin
	// _xd_local = _C_pinv * deltaQ / CONTROL_PERIOD_s;
	_xd_local = _C_pinv * _qd;
	_x_local += _xd_local * CONTROL_PERIOD_s;

	_heading = _gx(2)+ 0.5*_xd_local(2)*CONTROL_PERIOD_s;

	// Rotation matrix to convert vectors from local frame to global frame
	Eigen::Matrix3d R = Eigen::Matrix3d::Zero();
	R(0, 0) =  cos(_heading);
    R(0, 1) = -sin(_heading);
    R(1, 0) =  sin(_heading);
    R(1, 1) =  cos(_heading);
    R(2, 2) =  1.0;

    _gxd = R * _xd_local;
    _gx += _gxd * CONTROL_PERIOD_s;
}

/* Returns the change in steer and roll angle */
Eigen::Matrix<double, NUM_MOTORS, 1> Vehicle::getDeltaQ(){
	Eigen::Matrix<double, NUM_MOTORS, 1> deltaQ;
	for(int i = 0; i < NUM_CASTERS; i++)
	{
		deltaQ(2*i) = casters[i]->getSteerDeltaQ();
		deltaQ(2*i + 1) = casters[i]->getRollDeltaQ();
	}
	return deltaQ;
}

/* Set vehicle velocities in x, y, and theta. vx,vy in m/s and vth in rad/s */
// (6.1)
int Vehicle::setGlobalVelocity(Eigen::Vector3d xd_com_in)
{
	// Retrieve latest joint data
	updateJointData();

	// Calculate C
	updateConstraintMatrix();

	// Store velocity command and determine current xd_des (limit acceleration)
	_gxd_com = clampVelocity(xd_com_in);
	_gxd_des = _gxd_des + clampAcceleration(_gxd_com - _gxd_des);

	// Calculate joint velocities to command
	_qd_des = _C * _gxd_des;

	// Set velocities for each caster
	for(int i = 0; i < NUM_CASTERS; i++)
	{
		if(casters[i]->setVelocities(_qd_des(2*i),_qd_des(2*i+1)))
		{
			return -1;
		}
	}

	return 0;
}

/* Set desired vehicle position, velocity, and acceleration for torque controller */
// (6.4)
void Vehicle::setTargets(Eigen::Array3d gx_des_in, Eigen::Array3d gxd_des_in, Eigen::Array3d gxdd_des_in)
{
	// update _lambda and mu
	updateDynamics();

	_gx_des   = gx_des_in;
	_gxd_des  = gxd_des_in;
	_gxdd_des = gxdd_des_in;

	// Calculate and set control forces/torques
#ifdef VELOCITY_SATURATION
	Eigen::Array3d dxd;
	dxd = _Kp / _Kv * (gx_des_in - _gx.array());
	Eigen::Array3d nu;
	nu(0) = saturate(MAX_VEL_X/abs(dxd(0)));
	nu(1) = saturate(MAX_VEL_Y/abs(dxd(1)));
	nu(2) = saturate(MAX_VEL_TH/abs(dxd(2)));
	Eigen::Vector3d g_cf_unit = -_Kv * (_gxd.array() - nu * dxd);
#else
	Eigen::Vector3d g_cf_unit = -_Kp * (_gx.array() - gx_des_in) - _Kv * (_gxd.array() - gxd_des_in) + gxdd_des_in;

#endif

	// Rotation matrix to convert vector from global frame to local frame
	Eigen::Matrix3d R = Eigen::Matrix3d::Zero();
	R(0, 0) = cos(_heading);
    R(0, 1) = sin(_heading);
    R(1, 0) = -sin(_heading);
    R(1, 1) = cos(_heading);
    R(2, 2) = 1.0;

	// Map global command to local coordinates
	Eigen::Array3d cf_unit_local = R * g_cf_unit;

	_cf_des_local = _lambda * cf_unit_local.matrix();
	// cf_des = _lambda * cf_unit.matrix() + mu;

	setTorque(_cf_des_local);
}

/* set _Kp gains */
void Vehicle::setKp(Eigen::Array3d Kp_des){
	_Kp = Kp_des;
}

/* set Kv gains */
void Vehicle::setKv(Eigen::Array3d Kv_des){
	_Kv = Kv_des;
}

/* Get control mode (velocity/torque) */
enum ctrl_mode Vehicle::getCtrlMode() const
{
	return _control;
}

/* Get position in m for x and y and rad for theta */
Eigen::Vector3d Vehicle::getGlobalPosition() const
{
	return _gx;
}

Eigen::Vector3d Vehicle::getLocalPosition() const
{
	return  _x_local;
}

/* Get vehicle velocity in m/s for x and y and rad/s for theta */
Eigen::Vector3d Vehicle::getGlobalVelocity() const
{
	return _gxd;
}

Eigen::Vector3d Vehicle::getLocalVelocity() const
{
	return _xd_local;
}

/* Get joint steering angles in rad */
Eigen::Matrix<double, NUM_CASTERS, 1> Vehicle::getJointSteeringAngles() const
{
	// updateJointData();
	return _q_steer;
}

/* Get desired joint velocities in rad/s */
Eigen::Matrix<double, NUM_MOTORS, 1> Vehicle::getDesJointVelocities() const
{
	return _qd_des;
}

/* Get joint velocities in rad/s */
Eigen::Matrix<double, NUM_MOTORS, 1> Vehicle::getJointVelocities() const
{
	return _qd;
}

/* Get vehicle (operational space) forces in x and y in N and torque in theta in Nm */
Eigen::Vector3d Vehicle::getLocalCommandForces() const
{
	return _cf_des_local;
}

/* Get joint torques in Nm */
Eigen::Matrix<double, NUM_MOTORS, 1> Vehicle::getDesJointTorques() const
{
	return _tq_des;
}

/* Get initialization status of vehicle */
bool Vehicle::isInitialized() const
{
	return _initialized;
}

/* Get enable status of vehicle */
bool Vehicle::isEnabled() const
{
	return _enabled;
}

/* Get status of vehicle */
bool Vehicle::isStopped() const
{
	return _stopped;
}

Eigen::Matrix3d Vehicle::getLambda() const
{
	return _lambda;
}

Eigen::MatrixXd Vehicle::getCPinv() const
{
	return _C_pinv;
}

/* Returns true if at least one bumper is hit */
bool Vehicle::isBumperHit() const
{
	bool retVal = false;
	for(int i = 0; i < NUM_CASTERS; i++)
	{
		if (casters[i]->getBumperState()){
			retVal = true;
		}
	}
	return retVal;
}

/* Returns a 4D vector containing the bumper state of each bumper */
Eigen::Vector4d Vehicle::getBumperState() const
{
	Eigen::Vector4d bumper_state;
	for(int i = 0; i < NUM_CASTERS; i++)
	{
		bumper_state[i] = casters[i]->getBumperState();
	}
	return bumper_state;
}

double Vehicle::getHeading() const
{
	return _heading;
}

void Vehicle::getElectricalStatus (robotElectrical_T *status)
{
	for (int i=0; i<NUM_CASTERS; i++){
		casters[i]->getAmps(&(status->steerMotorCurrent[i]), &(status->rollMotorCurrent[i]));
		casters[i]->getVolts(&(status->steerMotorVoltage[i]), &(status->rollMotorVoltage[i]));
	}
}

bool Vehicle::reachedTarget(Eigen::Vector3d curr_pos, Eigen::Vector3d curr_target, double max_linear_dist, double max_rot_dist) const
{
	return ((fabs(curr_pos[0]-curr_target[0]) < max_linear_dist) && (fabs(curr_pos[1]-curr_target[1]) < max_linear_dist) && (fabs(curr_pos[2]-curr_target[2]) < max_rot_dist));
}

/* --------------------------- PRIVATE MEMBER FUNCTIONS ------------------------------- */

/* Input: operational space forces fx,fy (N) and torque tz (Nm), all in local frame */
/* Outputs torques to casters */
int Vehicle::setTorque(const Eigen::Vector3d& cf_command)
{
	// Retrieve latest joint data
	updateJointData();

	// Calculate C#
	//updateConstraintMatrix();

	// Calculate C_p^+
	updateConstraintPinvMatrix();

	// Calculate joint torques
	// (6.11)
	_tq_des = _C_pinv.transpose() * cf_command;

#ifdef CLAMP_TORQUES
	clampTorque();
#endif

#ifdef SEND_ZERO_TORQUES
	_tq_des.setZero();
#endif

	for(int i = 0; i < NUM_CASTERS; i++)
	{
		if(casters[i]->setTorques(_tq_des(2*i),_tq_des(2*i+1)))
		{
			return -1;
		}
	}
	return 0;
}

/* Update joint data */
void Vehicle::updateJointData()
{
	std::pair<double,double> jointVel;
	for(int i = 0; i < NUM_CASTERS; i++)
	{
		_q_steer(i) = casters[i]->getSteerPosition();
		jointVel = casters[i]->getVelocities();
		_qd(2*i) = jointVel.first;
		_qd(2*i + 1) = jointVel.second;
	}
}

/* Mass Matrix taken from pg 20 of PCV Dyanmics.pdf*/
void Vehicle::updateDynamics()
{
	_lambda = Eigen::Matrix3d::Zero();
	_mu = Eigen::Vector3d::Zero();
	for(int i = 0; i < NUM_CASTERS; i++)
	{
		// Calculate relevant matrices and vectors
		Eigen::Matrix3d C_th = calcC_thMatrix(i);
		Eigen::Matrix3d A = calcAMatrix();
		Eigen::Vector3d p = calcpVector(i);
		Eigen::Matrix3d J_dot = calcJ_dotMatrix(i);
		Eigen::Vector3d Q_dot = calcQ_dotVector(i);

		//Calculate lambda_pumpkin and mu_pumpkin
		Eigen::Matrix3d lambda_pumpkin = calcLambdaPumpkinMatrix(i);
		Eigen::Vector3d mu_pumpkin = calcMuPumpkinVector(i);

		Eigen::Matrix3d lambda_i = C_th.transpose() * A * C_th + lambda_pumpkin;
		_lambda += lambda_i;

		Eigen::Vector3d mu_i = C_th.transpose()*(p - A*C_th*J_dot*Q_dot) + mu_pumpkin;
 		_mu += mu_i;
	}
	_lambda += calcLambdaVehicleMatrix();
}

/* Update kinematic constraint matrix, C#. Assumes joint data is up to date.
   Converts from operational space (xdot) to joint space (qdot). See pg 27 PCV_Dyanmics.pdf*/
void Vehicle::updateConstraintMatrix()
{
	for(int i = 0; i < NUM_CASTERS; i++)
	{
		int steerRow = 2*i;
		int rollRow = 2*i + 1;

		// Caster position values
		double hx = casterPosXSign(i+1) * DIST_TO_CASTER_X;
		double hy = casterPosYSign(i+1) * DIST_TO_CASTER_Y;

		// Take sin/cos of steeering angle
		double steerSin = sin(_q_steer(i));
		double steerCos = cos(_q_steer(i));

		// Compute steer row
		/**************** Alternative sign convention *******************/
		// C(steerRow,0) = -steerSin / PC_b;
		// C(steerRow,1) = steerCos / PC_b;
		// C(steerRow,2) = (hx * steerCos + hy * steerSin) / PC_b - 1.0;
		/****************************************************************/
		_C(steerRow,0) = steerSin / PC_b;
		_C(steerRow,1) = -steerCos / PC_b;
		_C(steerRow,2) = -(hx * steerCos + hy * steerSin) / PC_b - 1.0;

		// Compute roll row
		_C(rollRow,0) = steerCos / PC_r;
		_C(rollRow,1) = steerSin / PC_r;
		_C(rollRow,2) = (hx * steerSin - hy * steerCos) / PC_r;
	}
}

/* Update Moore-Penrose pseudoinverse of the constraint matrix C_p. Assumes constraint matrix, C#, is up to date */
void Vehicle::updateConstraintPinvMatrix()
{
	// Update Cp matrix with current data
	updateCpMatrix();

	Eigen::MatrixXd CptCli = Eigen::MatrixXd::Zero(3, NUM_MOTORS);

	for(int i = 0; i < NUM_CASTERS; i++)
	{
		// Cli IS 2x2 BLOCK DIAGONAL, SO MULTIPLY
	    // IN PIECES TO AVOID SLOW NxN MATRIX OPERATIONS

		// Take sin/cos of steering angle
		double steerSin = sin(_q_steer(i));
		double steerCos = cos(_q_steer(i));

		// Caster position values
		double hx = casterPosXSign(i+1) * DIST_TO_CASTER_X;
		double hy = casterPosYSign(i+1) * DIST_TO_CASTER_Y;

	    int j = 2*i;

	    // Note: sign of p-dot is: wheel as viewed from ground
	    CptCli(0, j ) =  PC_b * steerSin;
	    CptCli(0,j+1) =  PC_r * steerCos;
	    CptCli(1, j ) = -PC_b * steerCos;
	    CptCli(1,j+1) =  PC_r * steerSin;
	    CptCli(2, j ) = -PC_b * ((hx * steerCos + hy * steerSin) + PC_b);
	    CptCli(2,j+1) =  PC_r * (hx * steerSin - hy * steerCos);
	}

	_C_pinv = (_Cp.transpose()*_Cp).llt().solve(CptCli);
}

Eigen::Matrix3d Vehicle::calcAMatrix(){
	Eigen::Matrix3d A;
	A(0, 0) = PC_Mf*pow(PC_e, 2) + PC_If + PC_Ii + PC_Ih + PC_Is*pow(Ns, 2) + PC_It*Nr;
	A(0, 1) = PC_Ii*Nw - PC_Ih*Nw - PC_It*pow(Nr, 2)*Nw;
	A(0, 2) = PC_Mf*pow(PC_e, 2) + PC_If + PC_Ii + PC_Ih - PC_Is*Ns - PC_It*Nr;

	A(1, 0) = A(0, 1);
	A(1, 1) = PC_Mf*pow(PC_r, 2) + PC_Ii*pow(Nw, 2) + PC_Ih*pow(Nw, 2) + PC_It*pow(Nr, 2)*pow(Nw, 2) + PC_Ij;
	A(1, 2) = PC_Ii*Nw - PC_Ih*Nw + PC_It*Nr*Nw;

	A(2, 0) = A(0, 2);
	A(2, 1) = A(1, 2);
	A(2, 2) = PC_Mf*pow(PC_e, 2) + PC_If + PC_Ii + PC_Ih + PC_Is + PC_It;
	return A;
}

// PCV Dynamics page 21
Eigen::Vector3d Vehicle::calcpVector(int caster_no){
	double steer_d = _qd(2*caster_no);
	double roll_d  = _qd(2*caster_no+1);
	double gth_d   = _gxd(2);

	Eigen::Vector3d p;
	p(0) = PC_Mf*PC_r*PC_e*roll_d*(steer_d+gth_d);
	p(1) = -PC_Mf*PC_r*PC_e*pow((steer_d+gth_d), 2);
	p(2) = PC_Mf*PC_r*PC_e*roll_d*(steer_d+gth_d);
	return p;
}

// From PCV Dynamics page 29
Eigen::Matrix3d Vehicle::calcC_thMatrix(int caster_no)
{
	// Caster position values
	double hx = casterPosXSign(caster_no+1) * DIST_TO_CASTER_X;
	double hy = casterPosYSign(caster_no+1) * DIST_TO_CASTER_Y;

	// Take sin/cos of steering angle
	double steerSin = sin(_q_steer(caster_no));
	double steerCos = cos(_q_steer(caster_no));

	Eigen::Matrix3d C_th;
	/***  Alternate sign convention ***/
	// C_th(0, 0) = -steerSin / PC_b;
	// C_th(0, 1) = steerCos / PC_b;
	// C_th(0, 2) = (hx * steerCos + hy * steerSin) / PC_b - 1.0;
	/**********************************/
	C_th(0, 0) = steerSin / PC_b;
	C_th(0, 1) = -steerCos / PC_b;
	C_th(0, 2) = -(hx * steerCos + hy * steerSin) / PC_b - 1.0;

	C_th(1, 0) = steerCos / PC_r;
	C_th(1, 1) = steerSin / PC_r;
	C_th(1, 2) = (hx * steerSin - hy * steerCos) / PC_r;

	C_th(2, 0) = 0.0;
	C_th(2, 1) = 0.0;
	C_th(2, 2) = 1.0;

	return C_th;
}

// From PCV Dynamics page 25
Eigen::Matrix3d Vehicle::calcJ_dotMatrix(int caster_no)
{
	Eigen::Matrix3d J_dot;
	double steer_d = _qd(2*caster_no);
	double gth_d = _gxd(2);

	// Caster position values
	double hx = casterPosXSign(caster_no+1) * DIST_TO_CASTER_X;
	double hy = casterPosYSign(caster_no+1) * DIST_TO_CASTER_Y;

	// Take sin/cos of steeering angle
	double steerSin = sin(_q_steer(caster_no));
	double steerCos = cos(_q_steer(caster_no));

	// Take sin/cos of steer angle velocity plus PCV angle velocity
	double Sum = steer_d + gth_d;

	J_dot(0, 0) = PC_b * steerCos * Sum;
	J_dot(0, 1) = -PC_r * steerSin * Sum;
	J_dot(0, 2) = hx * gth_d + PC_b * steerCos * Sum;

	J_dot(1, 0) = PC_b * steerSin * Sum;
	J_dot(1, 1) = PC_r * steerCos * Sum;
	J_dot(1, 2) = hy * gth_d + PC_b * steerSin * Sum;

	J_dot(2, 0) = 0.0;
	J_dot(2, 1) = 0.0;
	J_dot(2, 2) = 0.0;

	return J_dot;
}

Eigen::Matrix3d Vehicle::calcLambdaPumpkinMatrix(int caster_no)
{
	Eigen::Matrix3d lambda_pumpkin = Eigen::Matrix3d::Zero();

	// Caster position values
	double hx = casterPosXSign(caster_no+1) * DIST_TO_CASTER_X;
	double hy = casterPosYSign(caster_no+1) * DIST_TO_CASTER_Y;

	lambda_pumpkin(0, 0) = PC_Mp;
	lambda_pumpkin(0, 2) = -PC_Mp*hy;

	lambda_pumpkin(1, 1) = PC_Mp;
	lambda_pumpkin(1, 2) = PC_Mp*hx;

	lambda_pumpkin(2, 0) = lambda_pumpkin(0, 2);
	lambda_pumpkin(2, 1) = lambda_pumpkin(1, 2);
	lambda_pumpkin(2, 2) = PC_Ip + PC_Mp*pow(DIST_TO_CASTER ,2);
	return lambda_pumpkin;
}

Eigen::Matrix3d Vehicle::calcLambdaVehicleMatrix()
{
	Eigen::Matrix3d lambda_vehicle = Eigen::Matrix3d::Zero();

	lambda_vehicle(0, 0) = PC_Mv; // Effective mass along the x direction is the mass of the vehicle
	lambda_vehicle(1, 1) = PC_Mv; // Effective mass along the y direction is the mass of the vehicle
	lambda_vehicle(2, 2) = PC_Iv; // Inertia of the vehicle about the z axis

	return lambda_vehicle;
}

Eigen::Vector3d Vehicle::calcQ_dotVector(int caster_no)
{
	Eigen::Vector3d Q_dot;

	double steer_d = _qd(2*caster_no);
	double roll_d = _qd(2*caster_no+1);
	double gth_d = _gxd(2);
	Q_dot << steer_d, roll_d, gth_d;

	return Q_dot;
}

Eigen::Vector3d Vehicle::calcMuPumpkinVector(int caster_no)
{
	Eigen::Vector3d mu_pumpkin;
	double gth_d = _gxd(2);

	// Caster position values
	double hx = casterPosXSign(caster_no+1) * DIST_TO_CASTER_X;
	double hy = casterPosYSign(caster_no+1) * DIST_TO_CASTER_Y;

	mu_pumpkin << -PC_Mp * hx * pow(gth_d, 2), -PC_Mp * hy * pow(gth_d, 2), 0.0;

	return mu_pumpkin;
}

/* Update Jq matrix. Transforms q_d's into p_d's (p_d = Jq*q_d). In documentation, Jq = C_q^{-1} */
void Vehicle::updateJqMatrix()
{
	_Jq = Eigen::MatrixXd::Zero(NUM_MOTORS, NUM_MOTORS);
	for(int i = 0; i < NUM_CASTERS; i++)
	{
		// Which rows to calculate
		int steerRow = 2*i;
		int rollRow = 2*i + 1;

		// Take sin/cos of steering angle
		double steerSin = sin(_q_steer(i));
		double steerCos = cos(_q_steer(i));

		// Compute steer row
		_Jq(steerRow,steerRow) = steerSin * PC_b;
		_Jq(steerRow,rollRow) = steerCos * PC_r;

		// Compute roll row
		_Jq(rollRow,steerRow) = -steerCos * PC_b;
		_Jq(rollRow,rollRow) = steerSin * PC_r;
	}
}

/* Update Cp matrix. Transforms x_d's into p_d's (p_d = C_p*x_d) */
void Vehicle::updateCpMatrix()
{
	for(int i = 0; i < NUM_CASTERS; i++)
	{
		// Which rows to calculate
		int steerRow = 2*i;
		int rollRow = 2*i + 1;

		// Take sin/cos of steering angle
		double steerSin = sin(_q_steer(i));
		double steerCos = cos(_q_steer(i));

		// Caster position values
		double hx = casterPosXSign(i+1) * DIST_TO_CASTER_X;
		double hy = casterPosYSign(i+1) * DIST_TO_CASTER_Y;

		// Cp = Jq*C, could calculate it this way instead
		// Compute steer row
		_Cp(steerRow,0) = 1.0;
		_Cp(steerRow,1) = 0.0;
		_Cp(steerRow,2) = -PC_b * steerSin - hy;

		// Compute roll row
		_Cp(rollRow,0) = 0.0;
		_Cp(rollRow,1) = 1.0;
		_Cp(rollRow,2) = PC_b * steerCos + hx;
	}
}

// Clamp the torque command to max values
void Vehicle::clampTorque(){
	// Clamp torque values to maximum allowed
	for(int i = 0; i < NUM_CASTERS; i++)
	{
		_tq_des(2*i)   = abs(_tq_des(2*i))   < MAX_STEER_TORQUE  ? _tq_des(2*i)   : copysign(MAX_STEER_TORQUE, _tq_des(2*i));
		_tq_des(2*i+1) = abs(_tq_des(2*i+1)) < MAX_ROLL_TORQUE   ? _tq_des(2*i+1) : copysign(MAX_ROLL_TORQUE,  _tq_des(2*i+1));
	}
}

/* ------------ Static functions-------------- */
// Determine sign of x position of caster based on number
static double casterPosXSign(int casterNum)
{
	switch(casterNum)
	{
		case 1:
		case 2:
			return 1.0;
		case 3:
		case 4:
			return -1.0;
		default:
			return 0;
	}
}

// Determine sign of y position of caster based on number
static double casterPosYSign(int casterNum)
{
	switch(casterNum)
	{
		case 2:
		case 3:
			return 1.0;
		case 1:
		case 4:
			return -1.0;
		default:
			return 0;
	}
}

/*  Saturation function
	Returns the input float value if its absolute value is less than or equal to 1.
	Otherwise, it returns 1.0 or -1.0 (depending on the sign of float x) */
static float saturate(float x) {
	x = abs(x) <= 1.0 ? x : copysign(1.0, x);
	return x;
}

// Function to clamp velocity command to max values
static Eigen::Vector3d clampVelocity(Eigen::Vector3d xd_com_in){
	// Clamp velocity values to maximum allowed
	xd_com_in(0) = abs(xd_com_in(0)) < MAX_VEL_TRANS ? xd_com_in(0) : copysign(MAX_VEL_TRANS, xd_com_in(0));
	xd_com_in(1) = abs(xd_com_in(1)) < MAX_VEL_TRANS ? xd_com_in(1) : copysign(MAX_VEL_TRANS, xd_com_in(1));
	xd_com_in(2) = abs(xd_com_in(2)) < MAX_VEL_ROT ? xd_com_in(2) : copysign(MAX_VEL_ROT, xd_com_in(2));

	return xd_com_in;
}

// Function to clamp acceleration command to max values (accel is change in xd_des for one control loop here)
static Eigen::Vector3d clampAcceleration(Eigen::Vector3d xdd_com_in){

	// Clamp acceleration values to maximum allowed

	// Check accel/decel for x
	if(xdd_com_in(0) >= 0){
		// Clamp trans accel
		xdd_com_in(0) = xdd_com_in(0) < MAX_VEL_TRANS_INC ? xdd_com_in(0) : MAX_VEL_TRANS_INC;
	}
	else{
		// Clamp trans decel
		xdd_com_in(0) = xdd_com_in(0) > -MAX_VEL_TRANS_DEC ? xdd_com_in(0) : -MAX_VEL_TRANS_DEC;
	}

	// Check accel/decel for y
	if(xdd_com_in(1) >= 0){
		// Clamp trans accel
		xdd_com_in(1) = xdd_com_in(1) < MAX_VEL_TRANS_INC ? xdd_com_in(1) : MAX_VEL_TRANS_INC;
	}
	else{
		// Clamp trans decel
		xdd_com_in(1) = xdd_com_in(1) > -MAX_VEL_TRANS_DEC ? xdd_com_in(1) : -MAX_VEL_TRANS_DEC;
	}

	// Check accel/decel for theta
	if(xdd_com_in(2) >= 0){
		// Clamp trans accel
		xdd_com_in(2) = xdd_com_in(2) < MAX_VEL_ROT_INC ? xdd_com_in(2) : MAX_VEL_ROT_INC;
	}
	else{
		// Clamp trans decel
		xdd_com_in(2) = xdd_com_in(2) > -MAX_VEL_ROT_DEC ? xdd_com_in(2) : -MAX_VEL_ROT_DEC;
	}

	return xdd_com_in;
}

/*********************** TEST HARNESS *****************************************/

#ifdef TEST_VEHICLE

// Different types of tests to run
enum test_type
{
	TEST_INIT,
	TEST_CONSTRAINT_MATRIX,
	TEST_DYNAMICS
};

int main (void)
{
	cout << "Begin vehicle test harness" << endl;

	/* instantiate vehicle */
	Vehicle *vehicle = new Vehicle ();

	// Which test to run
	enum test_type thisTest = TEST_DYNAMICS;

	int s = create_can_socket (0xF, 0xF);

	// Switch on type
	switch(thisTest){

		case TEST_DYNAMICS:
		{
			cout << "Testing Vehicle Dynamics" << endl;

		}

		case TEST_INIT:
			cout << "Testing Vehicle Initialization" << endl;

			if (vehicle->init())
				cout << "Vehicle initialization failed" << endl;
			else
				cout << "Vehicle initialization success" << endl;

			getchar ();
			break;

		case TEST_CONSTRAINT_MATRIX:
			{
				cout << "Testing Vehicle constraint matrix" << endl;

				Eigen::Matrix<double, NUM_MOTORS, 3> C; 		 		// constraint matrix
				Eigen::Matrix<double, NUM_CASTERS, 5> _q_steer;
				Eigen::Vector3d xd1;
				Eigen::Vector3d xd2;
				xd1 << 1,0,0;
				xd2 << 0,1,0;

				_q_steer << 0,0,0,0,
								   M_PI/2, M_PI/2, M_PI/2, M_PI/2,
									 M_PI,M_PI,M_PI,M_PI,
									 3*M_PI/2,3*M_PI/2,3*M_PI/2,3*M_PI/2,
									 -M_PI/2, -M_PI/2, -M_PI/2, -M_PI/2;

				// Re-compute constraint matrix C
				for(int j = 0; j < 5; j++){
					cout << "q_steer = [";
					for(int i = 0; i < NUM_CASTERS; i++)
					{
						// Which rows to calculate
						int steerRow = 2*i;
						int rollRow = 2*i + 1;

						// Caster position values
						double hx = casterPosXSign(i+1) * DIST_TO_CASTER_X;
						double hy = casterPosYSign(i+1) * DIST_TO_CASTER_Y;

						// Take sin/cos of steeering angle
						double steerSin = sin(_q_steer(i,j));
						double steerCos = cos(_q_steer(i,j));

						// Compute steer row
						C(steerRow,0) = -steerSin / PC_b;
						C(steerRow,1) =  steerCos / PC_b;
						C(steerRow,2) = (hx * steerCos + hy * steerSin) / PC_b - 1.0;

								// Compute roll row
						C(rollRow,0) = steerCos / PC_r;
						C(rollRow,1) = steerSin / PC_r;
						C(rollRow,2) = (hx * steerSin - hy * steerCos) / PC_r;

						cout << _q_steer(i,j) << ", ";
					}

					cout << "]" << endl;
					cout << endl << "C = " << endl;
					cout << C << endl;
					cout << "xd1 = " << xd1.transpose() << endl;
					cout << "qd1 = " << (C*xd1).transpose() << endl;
					cout << "xd2 = " << xd2.transpose() << endl;
					cout << "qd2 = " << (C*xd2).transpose() << endl;

					getchar();
				}
			}
			break;

		default:
			break;
	}

	// Delete caster
	delete vehicle;

	getchar ();
	cout << "End vehicle test harness" << endl;
	return 0;
}

#endif

ext: cc


text:
//| Copyright Inria May 2015
//| This project has received funding from the European Research Council (ERC) under
//| the European Union's Horizon 2020 research and innovation programme (grant
//| agreement No 637972) - see http://www.resibots.eu
//|
//| Contributor(s):
//|   - Jean-Baptiste Mouret (jean-baptiste.mouret@inria.fr)
//|   - Antoine Cully (antoinecully@gmail.com)
//|   - Konstantinos Chatzilygeroudis (konstantinos.chatzilygeroudis@inria.fr)
//|   - Federico Allocati (fede.allocati@gmail.com)
//|   - Vaios Papaspyros (b.papaspyros@gmail.com)
//|   - Roberto Rama (bertoski@gmail.com)
//|
//| This software is a computer library whose purpose is to optimize continuous,
//| black-box functions. It mainly implements Gaussian processes and Bayesian
//| optimization.
//| Main repository: http://github.com/resibots/limbo
//| Documentation: http://www.resibots.eu/limbo
//|
//| This software is governed by the CeCILL-C license under French law and
//| abiding by the rules of distribution of free software.  You can  use,
//| modify and/ or redistribute the software under the terms of the CeCILL-C
//| license as circulated by CEA, CNRS and INRIA at the following URL
//| "http://www.cecill.info".
//|
//| As a counterpart to the access to the source code and  rights to copy,
//| modify and redistribute granted by the license, users are provided only
//| with a limited warranty  and the software's author,  the holder of the
//| economic rights,  and the successive licensors  have only  limited
//| liability.
//|
//| In this respect, the user's attention is drawn to the risks associated
//| with loading,  using,  modifying and/or developing or reproducing the
//| software by the user in light of its specific status of free software,
//| that may mean  that it is complicated to manipulate,  and  that  also
//| therefore means  that it is reserved for developers  and  experienced
//| professionals having in-depth computer knowledge. Users are therefore
//| encouraged to load and test the software's suitability as regards their
//| requirements in conditions enabling the security of their systems and/or
//| data to be ensured and,  more generally, to use and operate it in the
//| same conditions as regards security.
//|
//| The fact that you are presently reading this means that you have had
//| knowledge of the CeCILL-C license and that you accept its terms.
//|
#ifndef LIMBO_ACQUI_EI_HPP
#define LIMBO_ACQUI_EI_HPP

#include <Eigen/Core>
#include <cmath>
#include <vector>

#include <limbo/opt/optimizer.hpp>
#include <limbo/tools/macros.hpp>

namespace limbo {
    namespace defaults {
        struct acqui_ei {
            /// @ingroup acqui_defaults
            BO_PARAM(double, jitter, 0.0);
        };
    }
    namespace acqui {
        /** @ingroup acqui
        \rst
        Classic EI (Expected Improvement). See :cite:`brochu2010tutorial`, p. 14

          .. math::
            EI(x) = (\mu(x) - f(x^+) - \xi)\Phi(Z) + \sigma(x)\phi(Z),\\\text{with } Z = \frac{\mu(x)-f(x^+) - \xi}{\sigma(x)}.

        Parameters:
          - ``double jitter`` - :math:`\xi`
        \endrst
        */
        template <typename Params, typename Model>
        class EI {
        public:
            EI(const Model& model, int iteration = 0) : _model(model), _nb_samples(-1) {}

            size_t dim_in() const { return _model.dim_in(); }

            size_t dim_out() const { return _model.dim_out(); }

            template <typename AggregatorFunction>
            opt::eval_t operator()(const Eigen::VectorXd& v, const AggregatorFunction& afun, bool gradient)
            {
                assert(!gradient);

                Eigen::VectorXd mu;
                double sigma_sq;
                std::tie(mu, sigma_sq) = _model.query(v);
                double sigma = std::sqrt(sigma_sq);

                // If \sigma(x) = 0 or we do not have any observation yet we return 0
                if (sigma < 1e-10 || _model.samples().size() < 1)
                    return opt::no_grad(0.0);

                // Compute EI(x)
                // First find the best so far (predicted) observation -- if needed
                if (_nb_samples != _model.nb_samples()) {
                    std::vector<double> rewards;
                    for (auto s : _model.samples()) {
                        rewards.push_back(afun(_model.mu(s)));
                    }

                    _nb_samples = _model.nb_samples();
                    _f_max = *std::max_element(rewards.begin(), rewards.end());
                }
                // Calculate Z and \Phi(Z) and \phi(Z)
                double X = afun(mu) - _f_max - Params::acqui_ei::jitter();
                double Z = X / sigma;
                double phi = std::exp(-0.5 * std::pow(Z, 2.0)) / std::sqrt(2.0 * M_PI);
                double Phi = 0.5 * std::erfc(-Z / std::sqrt(2)); //0.5 * (1.0 + std::erf(Z / std::sqrt(2)));

                return opt::no_grad(X * Phi + sigma * phi);
            }

        protected:
            const Model& _model;
            int _nb_samples;
            double _f_max;
        };
    }
}

#endif

ext: hpp


text:
// Copyright Louis Dionne 2013-2016
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)

#include <boost/hana/ext/std/array.hpp>
#include <boost/hana/less.hpp>

#include <array>
namespace hana = boost::hana;

constexpr std::array<int, 4> evens = {{2, 4, 6, 8}};
constexpr std::array<int, 4> odds = {{1, 3, 5, 7}};

constexpr std::array<int, 5> up_to_5 = {{1, 2, 3, 4, 5}};

// arrays with same length
static_assert(hana::less(odds, evens), "");

// arrays with different lenghts
static_assert(hana::less(up_to_5, odds), "");

int main() { }

ext: cpp

max_stars_repo_name: nxplatform/nx-mobile

max_issues_repo_name: nxplatform/nx-mobile

max_forks_repo_name: nxplatform/nx-mobile


text:
//=========================================================================
//  Copyright (c) Kitware, Inc.
//  All rights reserved.
//  See LICENSE.txt for details.
//
//  This software is distributed WITHOUT ANY WARRANTY; without even
//  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
//  PURPOSE.  See the above copyright notice for more information.
//=========================================================================
#include "smtk/model/EntityRef.h"

#include "smtk/model/EntityRefArrangementOps.h"
#include "smtk/model/DefaultSession.h"
#include "smtk/model/Entity.h"
#include "smtk/model/Events.h"
#include "smtk/model/Group.h"
#include "smtk/model/Manager.h"
#include "smtk/model/Model.h"
#include "smtk/model/Tessellation.h"

#include <boost/functional/hash.hpp>

#include <algorithm>

using namespace smtk::common;

namespace smtk {
  namespace model {

/// Construct an invalid entityref.
EntityRef::EntityRef()
{
}

/// Construct a entityref referencing a given \a entity residing in the given \a mgr.
EntityRef::EntityRef(ManagerPtr mgr, const smtk::common::UUID& inEntity)
  : m_manager(mgr), m_entity(inEntity)
{
}

/// Change the underlying manager the entityref references.
bool EntityRef::setManager(ManagerPtr mgr)
{
  if (mgr == this->m_manager.lock())
    {
    return false;
    }
  this->m_manager = mgr;
  return true;
}

/// Return the underlying manager the entityref references.
ManagerPtr EntityRef::manager()
{
  return this->m_manager.lock();
}

/// Return the underlying manager the entityref references.
const ManagerPtr EntityRef::manager() const
{
  return this->m_manager.lock();
}

/// Change the UUID of the entity the entityref references.
bool EntityRef::setEntity(const smtk::common::UUID& inEntity)
{
  if (inEntity == this->m_entity)
    return false;

  this->m_entity = inEntity;
  return true;
}

/// Return the UUID of the entity the entityref references.
const smtk::common::UUID& EntityRef::entity() const
{
  return this->m_entity;
}

/**\brief Return the nominal parametric dimension of the entity (or -1).
  *
  * A value of -1 is returned when the entityref is invalid, or the entity
  * does not have any specified dimension, or the entity may have components
  * with multiple distinct dimensionalities.
  */
int EntityRef::dimension() const
{
  ManagerPtr mgr = this->m_manager.lock();
  if (mgr && !this->m_entity.isNull())
    {
    Entity* entRec = mgr->findEntity(this->m_entity);
    if (entRec)
      {
      return entRec->dimension();
      }
    }
  return -1;
}

/**\brief Return the nominal parametric dimension(s) of the entity as a bit vector.
  *
  * A value of 0 is returned when the entityref is invalid.
  * Multiple bits will be set if the entity may have components with
  * multiple distinct dimensionalities.
  */
int EntityRef::dimensionBits() const
{
  ManagerPtr mgr = this->m_manager.lock();
  if (mgr && !this->m_entity.isNull())
    {
    Entity* entRec = mgr->findEntity(this->m_entity);
    if (entRec)
      {
      return entRec->dimensionBits();
      }
    }
  return 0;
}

/**\brief Set the dimensionality of this entity. WARNING: Intended for internal use only.
  *
  * This method is used by some sessions to change the dimensionality of a model
  * after it has been transcribed. Do not call it.
  */
void EntityRef::setDimensionBits(BitFlags dimBits)
{
  ManagerPtr mgr = this->m_manager.lock();
  if (mgr && !this->m_entity.isNull())
    {
    Entity* entRec = mgr->findEntity(this->m_entity);
    if (entRec)
      {
      BitFlags old = entRec->entityFlags() & ~ANY_DIMENSION;
      entRec->setEntityFlags(old | dimBits);
      }
    }
}

/**\brief Return the maximum number of coordinates required to parameterize this model's point locus.
  *
  * Unlike EntityRef::dimension(), this will always return a non-negative number
  * for valid cell, use, shell and model entities.
  * It returns -1 for unpopulated groups with no members, instance entities, sessions,
  * and other entities with no dimension bits set.
  */
int EntityRef::maxParametricDimension() const
{
  int result = -1;
  BitFlags dimbits = this->dimensionBits();
  if (dimbits == 0) return result;
  BitFlags onedim = DIMENSION_0;
  while (1)
    {
    ++result;
    if (2 * onedim > dimbits)
      return result;
    onedim <<= 1;
    }
  return -1;
}

/**\brief Return the dimension of the space into which this entity is embedded.
  *
  * This is the number of actual coordinate values associated with points in
  * the underlying space of the entity (i.e., the point locus that make it up).
  * It should be equal to or greater than the maximum parametric dimension.
  *
  * All the entities in a model must have the same embedding dimension; it
  * is a property stored with the model.
  *
  * By default, the embedding dimension is 3.
  */
int EntityRef::embeddingDimension() const
{
  Model owner = this->owningModel();
  if (owner.isValid() && owner.hasIntegerProperty("embedding dimension"))
    {
    const IntegerList& prop(owner.integerProperty("embedding dimension"));
    if (!prop.empty())
      return prop[0];
    }
  return this->maxParametricDimension();
}

/// Return the bit vector describing the entity's type. \sa isVector, isEdge, ...
BitFlags EntityRef::entityFlags() const
{
  ManagerPtr mgr = this->m_manager.lock();
  if (mgr && !this->m_entity.isNull())
    {
    Entity* entRec = mgr->findEntity(this->m_entity);
    if (entRec)
      {
      return entRec->entityFlags();
      }
    }
  return 0;
}

/**\brief A string summary of the type of entity represented by this entityref.
  *
  * If \a form is non-zero, the plural form of the summary is returned.
  */
std::string EntityRef::flagSummary(int form) const
{
  ManagerPtr mgr = this->m_manager.lock();
  if (mgr)
    {
    Entity* ent = mgr->findEntity(this->m_entity);
    if (ent)
      {
      std::ostringstream summary;
      // We can embellish the entity BitFlag summary with
      // additional information for some objects.
      if (ent->entityFlags() & SESSION)
        {
        Session::Ptr brdg = mgr->sessionData(*this);
        if (brdg)
          {
          // if this is a DefaultSession and there is a remote session name, display that;
          // otherwise, show the local session name.
          DefaultSessionPtr defaultBr = smtk::dynamic_pointer_cast<DefaultSession>(brdg);
          if(defaultBr && !defaultBr->remoteName().empty())
            summary << defaultBr->remoteName() << " ";
          else
            summary << brdg->name() << " ";
          }
        }
      summary << ent->flagSummary(form);
      return summary.str();
      }
    }
  return Entity::flagSummary(INVALID, form);
}

/** Report the name associated with this entity.
  *
  * This will not assign a default name to the entity (that would
  * violate the const-ness of the method), but will report a
  * UUID-based name for the entity if it does not have a
  * user-assigned name.
  */
std::string EntityRef::name() const
{
  ManagerPtr mgr = this->m_manager.lock();
  return mgr ? mgr->name(this->m_entity) : "(null model)";
}

/** Assign a name to an entity.
  *
  * This will override any existing name.
  */
void EntityRef::setName(const std::string& n)
{
  this->setStringProperty("name", n);
}

/**\brief Assign a default name to the entity.
  *
  * This uses counters associated with the owning
  * model or model manager to name the entity.
  */
std::string EntityRef::assignDefaultName()
{
  ManagerPtr mgr = this->m_manager.lock();
  if (!mgr || !this->m_entity)
    return std::string();

  return mgr->assignDefaultName(this->m_entity);
}

/// Returns true if the "visible" integer-property exists.
bool EntityRef::hasVisibility() const
{
  return this->hasIntegerProperty("visible");
}

/** Report the visibility associated with this entity.
  *
  * If there is no "visible" property set,return false
  */
bool EntityRef::visible() const
{
  if ( !this->hasVisibility() )
    return false;

  const IntegerList& prop(this->integerProperty("visible"));
  return (!prop.empty() && (prop[0] != 0));
}

/** Assign the visible property to an entity.
  *
  * This will override any existing visibility.
  */
void EntityRef::setVisible(bool vis)
{
  this->setIntegerProperty("visible", vis ? 1 : 0);
}

/** Return a user-assigned color for the entity.
  *
  * If no color was assigned, (0,0,0,0) will be returned.
  */
FloatList EntityRef::color() const
{
  FloatList result = this->floatProperty("color");
  int ncomp = static_cast<int>(result.size());
  if (ncomp < 4)
    {
    result.resize(4);
    for (int i = ncomp; i < 3; ++i)
      result[i] = 0.;
    switch (ncomp)
      {
    default:
    case 0: // Assuming color not defined; mark alpha invalid.
      result[3] = -1.;
      break;
    case 1:
    case 3: // Assume RGB or greyscale; default alpha = 1.
      result[3] = 1.;
      break;
    case 2: // Assume greyscale+alpha; remap alpha to result[4]
      result[3] = (result[1] >= 0. && result[1] <= 0. ? result[1] : 1.);
      break;
      }
    }
  return result;
}

/// Returns true if the "color" float-property exists. No check on the size is performed.
bool EntityRef::hasColor() const
{
  return this->hasFloatProperty("color");
}

/** Assign a color to an entity.
  *
  * This will override any existing color.
  * No check on the size is performed, but you should provide 4 values per color:
  * red, green, blue, and alpha. Each should be in [0,1].
  */
void EntityRef::setColor(const smtk::model::FloatList& rgba)
{
  this->setFloatProperty("color", rgba);
}

/** Assign a color to an entity.
  *
  * This will override any existing color.
  * Each value should be in [0,1].
  */
void EntityRef::setColor(double red, double green, double blue, double alpha)
{
  FloatList rgba;
  rgba.resize(4);
  rgba[0] = red;
  rgba[1] = green;
  rgba[2] = blue;
  rgba[3] = alpha;
  this->setColor(rgba);
}

/**\brief Return whether the entityref is pointing to valid manager that contains the UUID of the entity.
  *
  * Subclasses should not override this method. It is a convenience
  * which makes the shiboken wrapper more functional.
  */
bool EntityRef::isValid() const
{
  return this->isValid(NULL);
}

/**\brief Return whether the entityref is pointing to valid manager that contains the UUID of the entity.
  *
  * Subclasses override this and additionally return whether the entity is of
  * a type that matches the EntityRef subclass. For example, it is possible to
  * create a Vertex entityref from a UUID referring to an EdgeUse. While
  * EntityRef::isValid() will return true, Vertex::isValid() will return false.
  *
  * The optional \a entityRecord will be set when a non-NULL value is passed
  * and the entity is valid.
  */
bool EntityRef::isValid(Entity** entityRecord) const
{
  ManagerPtr mgr = this->m_manager.lock();
  bool status = mgr && !this->m_entity.isNull();
  if (status)
    {
    Entity* rec = mgr->findEntity(this->m_entity, false);
    status = rec ? true : false;
    if (status && entityRecord)
      {
      *entityRecord = rec;
      }
    }
  return status;
}

/**\brief A wrapper around EntityRef::isValid() which also verifies an arrangement exists.
  *
  */
bool EntityRef::checkForArrangements(ArrangementKind k, Entity*& entRec, Arrangements*& arr) const
{
  ManagerPtr mgr = this->m_manager.lock();
  if (this->isValid(&entRec))
    {
    arr = NULL;
    if (
      (arr = mgr->hasArrangementsOfKindForEntity(this->m_entity, k)) &&
      !arr->empty())
      {
      return true;
      }
    }
  return false;
}

EntityRefs EntityRef::bordantEntities(int ofDimension) const
{
  EntityRefs result;
  ManagerPtr mgr = this->m_manager.lock();
  if (mgr && !this->m_entity.isNull())
    {
    smtk::common::UUIDs uids = mgr->bordantEntities(
      this->m_entity, ofDimension);
    EntityRefsFromUUIDs(result, mgr, uids);
    }
  return result;
}

EntityRefs EntityRef::boundaryEntities(int ofDimension) const
{
  EntityRefs result;
  ManagerPtr mgr = this->m_manager.lock();
  if (mgr && !this->m_entity.isNull())
    {
    smtk::common::UUIDs uids = mgr->boundaryEntities(
      this->m_entity, ofDimension);
    EntityRefsFromUUIDs(result, mgr, uids);
    }
  return result;
}

EntityRefs EntityRef::lowerDimensionalBoundaries(int lowerDimension)
{
  EntityRefs result;
  ManagerPtr mgr = this->m_manager.lock();
  if (mgr && !this->m_entity.isNull())
    {
    smtk::common::UUIDs uids = mgr->lowerDimensionalBoundaries(
      this->m_entity, lowerDimension);
    EntityRefsFromUUIDs(result, mgr, uids);
    }
  return result;
}

EntityRefs EntityRef::higherDimensionalBordants(int higherDimension)
{
  EntityRefs result;
  ManagerPtr mgr = this->m_manager.lock();
  if (mgr && !this->m_entity.isNull())
    {
    smtk::common::UUIDs uids = mgr->higherDimensionalBordants(
      this->m_entity, higherDimension);
    EntityRefsFromUUIDs(result, mgr, uids);
    }
  return result;
}

EntityRefs EntityRef::adjacentEntities(int ofDimension)
{
  EntityRefs result;
  ManagerPtr mgr = this->m_manager.lock();
  if (mgr && !this->m_entity.isNull())
    {
    smtk::common::UUIDs uids = mgr->adjacentEntities(
      this->m_entity, ofDimension);
    EntityRefsFromUUIDs(result, mgr, uids);
    }
  return result;
}

/// Return a set of entities related to this entity. This method is provided for Python wrapping.
EntityRefs EntityRef::relations() const
{
  return this->relationsAs<EntityRefs>();
}

/**\brief Add a relation to an entity, \a ent, without specifying the relationship's nature.
  *
  * The relation is considered "raw" because no arrangement information is added
  * describing the nature of the arrangement.
  *
  * This method adds a relation regardless of whether \a ent is already a relation;
  * \a ent may appear in the entity's list of relations multiple times after this call.
  */
EntityRef& EntityRef::addRawRelation(const EntityRef& ent)
{
  ManagerPtr mgr = this->m_manager.lock();
  if (
    mgr &&
    !this->m_entity.isNull() &&
    mgr == ent.manager() &&
    !ent.entity().isNull() &&
    ent.entity() != this->m_entity)
    {
    Entity* entRec = mgr->findEntity(this->m_entity);
    if (entRec)
      entRec->appendRelation(ent.entity());
    }
  return *this;
}

/**\brief Find or add a relation to an entity, \a ent, without specifying the relationship's nature.
  *
  * The relation is considered "raw" because no arrangement information is added
  * describing the nature of the arrangement.
  *
  * This method has no effect if \a ent is already a relation.
  */
EntityRef& EntityRef::findOrAddRawRelation(const EntityRef& ent)
{
  ManagerPtr mgr = this->m_manager.lock();
  if (
    mgr &&
    !this->m_entity.isNull() &&
    mgr == ent.manager() &&
    !ent.entity().isNull() &&
    ent.entity() != this->m_entity)
    {
    Entity* entRec = mgr->findEntity(this->m_entity);
    if (
      entRec &&
      std::find(
        entRec->relations().begin(),
        entRec->relations().end(),
        ent.entity())
      == entRec->relations().end())
      entRec->appendRelation(ent.entity());
    }
  return *this;
}

/**\brief Return the entity's tessellation if one exists or NULL otherwise.
  *
  */
const Tessellation* EntityRef::hasTessellation() const
{
  ManagerPtr mgr = this->m_manager.lock();
  if (mgr && !this->m_entity.isNull())
    {
    UUIDsToTessellations::const_iterator it = mgr->tessellations().find(this->m_entity);
    if (it != mgr->tessellations().end())
      return &it->second;
    }
  return NULL;
}

/**\brief Return the entity's analysis mesh if one exists or NULL otherwise.
  *
  */
const Tessellation* EntityRef::hasAnalysisMesh() const
{
  ManagerPtr mgr = this->m_manager.lock();
  if (mgr && !this->m_entity.isNull())
    {
    UUIDsToTessellations::const_iterator it = mgr->analysisMesh().find(this->m_entity);
    if (it != mgr->analysisMesh().end())
      return &it->second;
    }
  return NULL;
}

/**\brief Return the entity's analysis mesh if one exists,
  * otherwise return the entity's tessellation. If neither
  * exist return NULL.
  *
  */
const Tessellation* EntityRef::gotMesh() const
{
  ManagerPtr mgr = this->m_manager.lock();
  if (mgr && !this->m_entity.isNull())
    {
    UUIDsToTessellations::const_iterator am = mgr->analysisMesh().find(this->m_entity);
    if (am != mgr->analysisMesh().end())
      return &am->second;
    //don't even search for the tessellation if we have an analysis mesh
    UUIDsToTessellations::const_iterator te = mgr->tessellations().find(this->m_entity);
    if (te != mgr->tessellations().end())
      return &te->second;
    }
  return NULL;
}

/**\brief Set the tessellation of the entity, returning its
  *       generation number (or -1 on failure).
  *
  * If \a analysisMesh is non-zero (zero is the default), then
  * the tessellation is treated as an analysis mesh rather than
  * a tessellation for display purposes.
  */
int EntityRef::setTessellation(const Tessellation* tess, int analysisMesh)
{
  ManagerPtr mgr = this->m_manager.lock();
  if (mgr && !this->m_entity.isNull())
    {
    int gen;
    try {
      mgr->setTessellation(this->m_entity, *tess, analysisMesh, &gen);
    } catch (std::string& badIdMsg) {
      (void)badIdMsg;
      return -1;
    }

    return gen;
    }
  return -1;
}

/**\brief Remove the tessellation of the entity, returning true
  *       if such a tessellation existed.
  *
  * If \a removeGen is true (false is the default), then
  * also remove the generation-number property (a monotonically
  * increasing integer property used to signal that the
  * tessellation has changed).
  */
bool EntityRef::removeTessellation(bool removeGen)
{
  ManagerPtr mgr = this->m_manager.lock();
  if (mgr && !this->m_entity.isNull())
    return mgr->removeTessellation(this->m_entity, removeGen);
  return false;
}

/** @name Attribute associations
  *
  */
///@{
/**\brief Does the entityref have any attributes associated with it?
  */
bool EntityRef::hasAttributes() const
{
  ManagerPtr mgr = this->m_manager.lock();
  UUIDsToAttributeAssignments::const_iterator it =
    mgr->attributeAssignments().find(this->m_entity);
  if (it != mgr->attributeAssignments().end())
    {
    return it->second.attributes().empty() ? false : true;
    }
  return false;
}

/**\brief Does the entityref have any attributes associated with it?
 */
    bool EntityRef::hasAttribute(const smtk::common::UUID &attribId) const
{
  ManagerPtr mgr = this->m_manager.lock();
  return mgr->hasAttribute(attribId, this->m_entity);
}

/**\brief Does the entityref have any attributes associated with it?
  */
bool EntityRef::associateAttribute(smtk::attribute::System* sys,
                                   const smtk::common::UUID &attribId)
{
  ManagerPtr mgr = this->m_manager.lock();
  return mgr->associateAttribute(sys, attribId, this->m_entity);
}

/**\brief Does the entityref have any attributes associated with it?
  */
bool EntityRef::disassociateAttribute(smtk::attribute::System* sys,
                                      const smtk::common::UUID &attribId, bool reverse)
{
  ManagerPtr mgr = this->m_manager.lock();
  return mgr->disassociateAttribute(sys, attribId, this->m_entity, reverse);
}

/**\brief Remove all attribute association form this entityref
  */
bool EntityRef::disassociateAllAttributes(smtk::attribute::System* sys,
   bool reverse)
{
  AttributeSet atts = this->attributes();
  AttributeSet::const_iterator it;
  bool res = true;
  for(it = atts.begin(); it != atts.end(); ++it)
    {
    if(!this->disassociateAttribute(sys, *it, reverse))
      res = false;
    }
  return res;
}

/**\brief Does the entityref have any attributes associated with it?
  */
AttributeSet EntityRef::attributes() const
{
  ManagerPtr mgr = this->m_manager.lock();
  return mgr->attributeAssignments().find(this->m_entity)->second.attributes();
}
///@}

void EntityRef::setFloatProperty(const std::string& propName, smtk::model::Float propValue)
{
  ManagerPtr mgr = this->m_manager.lock();
  if (mgr && !this->m_entity.isNull())
    {
    mgr->setFloatProperty(this->m_entity, propName, propValue);
    }
}

void EntityRef::setFloatProperty(const std::string& propName, const smtk::model::FloatList& propValue)
{
  ManagerPtr mgr = this->m_manager.lock();
  if (mgr && !this->m_entity.isNull())
    {
    mgr->setFloatProperty(this->m_entity, propName, propValue);
    }
}

smtk::model::FloatList const& EntityRef::floatProperty(const std::string& propName) const
{
  ManagerPtr mgr = this->m_manager.lock();
  return mgr->floatProperty(this->m_entity, propName);
}

smtk::model::FloatList& EntityRef::floatProperty(const std::string& propName)
{
  ManagerPtr mgr = this->m_manager.lock();
  return mgr->floatProperty(this->m_entity, propName);
}

bool EntityRef::hasFloatProperty(const std::string& propName) const
{
  ManagerPtr mgr = this->m_manager.lock();
  if (mgr && !this->m_entity.isNull())
    {
    return mgr->hasFloatProperty(this->m_entity, propName);
    }
  return false;
}

bool EntityRef::removeFloatProperty(const std::string& propName)
{
  ManagerPtr mgr = this->m_manager.lock();
  if (mgr && !this->m_entity.isNull())
    {
    return mgr->removeFloatProperty(this->m_entity, propName);
    }
  return false;
}

/**\brief Does this entity have *any* float-valued properties?
  *
  * If not, you should call EntityRef::setFloatProperty() before
  * calling EntityRef::floatProperties().
  */
bool EntityRef::hasFloatProperties() const
{
  ManagerPtr mgr = this->m_manager.lock();
  return
    mgr->floatProperties().find(this->m_entity)
    == mgr->floatProperties().end() ?
    false : true;
}

/// Return the names of all the floating-point properties.
std::set<std::string> EntityRef::floatPropertyNames() const
{
  std::set<std::string> pnames;
  if (this->hasFloatProperties())
    {
    const FloatData& props(this->floatProperties());
    for (FloatData::const_iterator it = props.begin(); it != props.end(); ++it)
      {
      pnames.insert(it->first);
      }
    }
  return pnames;
}

FloatData& EntityRef::floatProperties()
{
  ManagerPtr mgr = this->m_manager.lock();
  return mgr->floatProperties().find(this->m_entity)->second;
}

FloatData const& EntityRef::floatProperties() const
{
  ManagerPtr mgr = this->m_manager.lock();
  return mgr->floatProperties().find(this->m_entity)->second;
}

void EntityRef::setStringProperty(const std::string& propName, const smtk::model::String& propValue)
{
  ManagerPtr mgr = this->m_manager.lock();
  if (mgr && !this->m_entity.isNull())
    {
    mgr->setStringProperty(this->m_entity, propName, propValue);
    }
}

void EntityRef::setStringProperty(const std::string& propName, const smtk::model::StringList& propValue)
{
  ManagerPtr mgr = this->m_manager.lock();
  if (mgr && !this->m_entity.isNull())
    {
    mgr->setStringProperty(this->m_entity, propName, propValue);
    }
}

smtk::model::StringList const& EntityRef::stringProperty(const std::string& propName) const
{
  ManagerPtr mgr = this->m_manager.lock();
  return mgr->stringProperty(this->m_entity, propName);
}

smtk::model::StringList& EntityRef::stringProperty(const std::string& propName)
{
  ManagerPtr mgr = this->m_manager.lock();
  return mgr->stringProperty(this->m_entity, propName);
}

bool EntityRef::hasStringProperty(const std::string& propName) const
{
  ManagerPtr mgr = this->m_manager.lock();
  if (mgr && !this->m_entity.isNull())
    {
    return mgr->hasStringProperty(this->m_entity, propName);
    }
  return false;
}

bool EntityRef::removeStringProperty(const std::string& propName)
{
  ManagerPtr mgr = this->m_manager.lock();
  if (mgr && !this->m_entity.isNull())
    {
    return mgr->removeStringProperty(this->m_entity, propName);
    }
  return false;
}

/**\brief Does this entity have *any* string-valued properties?
  *
  * If not, you should call EntityRef::setStringProperty() before
  * calling EntityRef::stringProperties().
  */
bool EntityRef::hasStringProperties() const
{
  ManagerPtr mgr = this->m_manager.lock();
  return
    mgr->stringProperties().find(this->m_entity)
    == mgr->stringProperties().end() ?
    false : true;
}

/// Return the names of all the string properties.
std::set<std::string> EntityRef::stringPropertyNames() const
{
  std::set<std::string> pnames;
  if (this->hasStringProperties())
    {
    const StringData& props(this->stringProperties());
    for (StringData::const_iterator it = props.begin(); it != props.end(); ++it)
      {
      pnames.insert(it->first);
      }
    }
  return pnames;
}

StringData& EntityRef::stringProperties()
{
  ManagerPtr mgr = this->m_manager.lock();
  return mgr->stringProperties().find(this->m_entity)->second;
}

StringData const& EntityRef::stringProperties() const
{
  ManagerPtr mgr = this->m_manager.lock();
  return mgr->stringProperties().find(this->m_entity)->second;
}

void EntityRef::setIntegerProperty(const std::string& propName, smtk::model::Integer propValue)
{
  ManagerPtr mgr = this->m_manager.lock();
  if (mgr && !this->m_entity.isNull())
    {
    mgr->setIntegerProperty(this->m_entity, propName, propValue);
    }
}

void EntityRef::setIntegerProperty(const std::string& propName, const smtk::model::IntegerList& propValue)
{
  ManagerPtr mgr = this->m_manager.lock();
  if (mgr && !this->m_entity.isNull())
    {
    mgr->setIntegerProperty(this->m_entity, propName, propValue);
    }
}

smtk::model::IntegerList const& EntityRef::integerProperty(const std::string& propName) const
{
  ManagerPtr mgr = this->m_manager.lock();
  return mgr->integerProperty(this->m_entity, propName);
}

smtk::model::IntegerList& EntityRef::integerProperty(const std::string& propName)
{
  ManagerPtr mgr = this->m_manager.lock();
  return mgr->integerProperty(this->m_entity, propName);
}

bool EntityRef::hasIntegerProperty(const std::string& propName) const
{
  ManagerPtr mgr = this->m_manager.lock();
  if (mgr && !this->m_entity.isNull())
    {
    return mgr->hasIntegerProperty(this->m_entity, propName);
    }
  return false;
}

bool EntityRef::removeIntegerProperty(const std::string& propName)
{
  ManagerPtr mgr = this->m_manager.lock();
  if (mgr && !this->m_entity.isNull())
    {
    return mgr->removeIntegerProperty(this->m_entity, propName);
    }
  return false;
}

/**\brief Does this entity have *any* integer-valued properties?
  *
  * If not, you should call EntityRef::setIntegerProperty() before
  * calling EntityRef::integerProperties().
  */
bool EntityRef::hasIntegerProperties() const
{
  ManagerPtr mgr = this->m_manager.lock();
  return
    mgr->integerProperties().find(this->m_entity)
    == mgr->integerProperties().end() ?
    false : true;
}

/// Return the names of all the integer properties.
std::set<std::string> EntityRef::integerPropertyNames() const
{
  std::set<std::string> pnames;
  if (this->hasIntegerProperties())
    {
    const IntegerData& props(this->integerProperties());
    for (IntegerData::const_iterator it = props.begin(); it != props.end(); ++it)
      {
      pnames.insert(it->first);
      }
    }
  return pnames;
}

IntegerData& EntityRef::integerProperties()
{
  ManagerPtr mgr = this->m_manager.lock();
  return mgr->integerProperties().find(this->m_entity)->second;
}

IntegerData const& EntityRef::integerProperties() const
{
  ManagerPtr mgr = this->m_manager.lock();
  return mgr->integerProperties().find(this->m_entity)->second;
}

/// Return the number of arrangements of the given kind \a k.
int EntityRef::numberOfArrangementsOfKind(ArrangementKind k) const
{
  ManagerPtr mgr = this->m_manager.lock();
  const Arrangements* arr =
    mgr->hasArrangementsOfKindForEntity(
      this->m_entity, k);
  return arr ? static_cast<int>(arr->size()) : 0;
}

/// Return the \a i-th arrangement of kind \a k (or NULL).
Arrangement* EntityRef::findArrangement(ArrangementKind k, int i)
{
  ManagerPtr mgr = this->m_manager.lock();
  return mgr->findArrangement(this->m_entity, k, i);
}

/// Return the \a i-th arrangement of kind \a k (or NULL).
const Arrangement* EntityRef::findArrangement(ArrangementKind k, int i) const
{
  ManagerPtr mgr = this->m_manager.lock();
  return mgr->findArrangement(this->m_entity, k, i);
}

/// Delete all arrangements of this entity with prejudice.
bool EntityRef::clearArrangements()
{
  ManagerPtr mgr = this->m_manager.lock();
  return mgr->clearArrangements(this->m_entity);
}

/**\brief Return the relation specified by the \a offset into the specified arrangement.
  *
  */
EntityRef EntityRef::relationFromArrangement(
  ArrangementKind k, int arrangementIndex, int offset) const
{
  ManagerPtr mgr = this->m_manager.lock();
  const Entity* ent = mgr->findEntity(this->m_entity);
  if (ent)
    {
    const Arrangement* arr = this->findArrangement(k, arrangementIndex);
    if (arr && static_cast<int>(arr->details().size()) > offset)
      {
      int idx = arr->details()[offset];
      return idx < 0 ?
        EntityRef() :
        EntityRef(mgr, ent->relations()[idx]);
      }
    }
  return EntityRef();
}

/**\brief Embed the specified \a thingToEmbed as an inclusion into this entityref's entity.
  *
  * This adds an INCLUDES relation (if necessary) to this entity and
  * an EMBEDDED_IN relation (if necessary) to the \a thingToEmbed.
  */
EntityRef& EntityRef::embedEntity(const EntityRef& thingToEmbed)
{
  ManagerPtr mgr = this->m_manager.lock();
  //ManagerEventType event = std::make_pair(ADD_EVENT, INVALID_RELATIONSHIP);
  ManagerEventType event = std::make_pair(ADD_EVENT, this->embeddingRelationType(thingToEmbed));
  if (event.second != INVALID_RELATIONSHIP)
    {
    EntityRefArrangementOps::findOrAddSimpleRelationship(*this, INCLUDES, thingToEmbed);
    EntityRefArrangementOps::findOrAddSimpleRelationship(thingToEmbed, EMBEDDED_IN, *this);
    mgr->trigger(event, *this, thingToEmbed);
    }
  return *this;
}

/**\brief Unembed the specified \a thingToUnembed as an inclusion into this entityref's entity.
  *
  * This removes an INCLUDES relation (if necessary) to this entity and
  * an EMBEDDED_IN relation (if necessary) to the \a thingToUnembed.
  */
EntityRef& EntityRef::unembedEntity(const EntityRef& thingToEmbed)
{
  ManagerPtr mgr = this->m_manager.lock();
  ManagerEventType event = std::make_pair(DEL_EVENT, this->embeddingRelationType(thingToEmbed));
  if (event.second != INVALID_RELATIONSHIP)
    {
    int aidx = EntityRefArrangementOps::findSimpleRelationship(*this, INCLUDES, thingToEmbed);
    if (aidx >= 0)
      {
      mgr->unarrangeEntity(this->m_entity, EMBEDDED_IN, aidx);
      mgr->trigger(event, *this, thingToEmbed);
      }
    }
  return *this;
}

/**\brief Return whether the specified \a entity is a direct inclusion in this entityref's entity.
  *
  */
bool EntityRef::isEmbedded(EntityRef& ent) const
{
  return EntityRefArrangementOps::findSimpleRelationship(*this, INCLUDES, ent) >= 0;
}

/**\brief Report the entity into which this entity is directly embedded.
  *
  * If the entity is not embedded into another, the result will be an invalid entityref.
  */
EntityRef EntityRef::embeddedIn() const
{
  return EntityRefArrangementOps::firstRelation<EntityRef>(*this, EMBEDDED_IN);
}

/**\brief Return the Model which owns this entity.
  *
  * A Model is analogous to a body in some kernels,
  * a lump in others, or a group of regions in yet others.
  * In SMTK, models are the objects that get associated with
  * sessions to other kernels, so determining the owning
  * model is important for discovering which modeling operations
  * (including reading and writing to/from disk) are possible.
  *
  * Note that the returned model may be invalid.
  */
Model EntityRef::owningModel() const
{
  ManagerPtr mgr = this->m_manager.lock();
  return Model(
    mgr,
    mgr->modelOwningEntity(this->m_entity));
}

/**\brief Return the Groups which contains this entity.
  *
  */
Groups EntityRef::containingGroups() const
{
  Groups result;
  EntityRefArrangementOps::appendAllRelations(*this, SUBSET_OF, result);
  return result;
}

/// A comparator provided so that entityrefs may be included in ordered sets.
bool EntityRef::operator == (const EntityRef& other) const
{
  ManagerPtr mgr = this->m_manager.lock();
  return (
    (mgr == other.manager()) &&
    (this->m_entity == other.m_entity)) ?
    true :
    false;
}

/// A comparator provided so that entityrefs may be included in ordered sets.
bool EntityRef::operator < (const EntityRef& other) const
{
  ManagerPtr mgr = this->m_manager.lock();
  ManagerPtr otherMgr = other.m_manager.lock();
  if (mgr < otherMgr)
    {
    return true;
    }
  else if (otherMgr < mgr)
    {
    return false;
    }
  return this->m_entity < other.m_entity;
}

/**\brief A hash function for entityrefs.
  *
  * This allows entityrefs to be put into sets in Python.
  */
std::size_t EntityRef::hash() const
{
  ManagerPtr mgr = this->m_manager.lock();
  std::size_t result = this->m_entity.hash();
  boost::hash_combine(result, reinterpret_cast<std::size_t>(mgr.get()));
  return result;
}

std::ostream& operator << (std::ostream& os, const EntityRef& c)
{
  os << c.name();
  return os;
}

std::size_t entityrefHash(const EntityRef& c)
{
  return c.hash();
}

/*! \fn template<typename T> T EntityRef::relationsAs() const
 *\brief Return all of the entities related to this entityref.
 *
 * The return value is a template parameter naming container type.
 * Each member is cast from a EntityRef to T::value_type and added
 * to the container only if valid. This makes it possible to
 * subset the relations by forcing them into a container of the
 * desired type.
 */

/*! \fn template<typename S, typename T> void EntityRef::EntityRefsFromUUIDs(S& result, ManagerPtr mgr, const T& uids)
 *\brief Convert a set of UUIDs into a set of entityrefs referencing the same \a mgr.
 */

/*! \fn template<typename T> EntityRef::embedEntities(const T& container)
 * \brief Embed each of the entities in the container inside this entity.
 */

/*! \fn EntityRef::instances() const
 * \brief Return all the instances this object serves as a prototype for.
 */

/*! \fn EntityRef::properties<T>()
 *  \brief Return a pointer to the properties of the entity, creating an entry as required.
 *
 * Unlike the hasProperties() method, this will return a valid pointer as long as the
 * manager and entity of the entityref are valid.
 * If the entity does not already have any properties of the given type, a new
 * StringData, FloatData, or IntegerData instance is created and added to the
 * appropriate map.
 *
 * This templated version exists for use in functions where the
 * property type is a template parameter.
 */
template<>
SMTKCORE_EXPORT
StringData* EntityRef::properties<StringData>()
{
  if (!this->hasStringProperties())
    {
    if (!this->manager() || !this->entity())
      return NULL;
    StringData blank;
    this->manager()->stringProperties().insert(
      std::pair<UUID,StringData>(this->entity(), blank));
    }
  return &(this->stringProperties());
}

template<>
SMTKCORE_EXPORT
FloatData* EntityRef::properties<FloatData>()
{
  if (!this->hasFloatProperties())
    {
    if (!this->manager() || !this->entity())
      return NULL;
    FloatData blank;
    this->manager()->floatProperties().insert(
      std::pair<UUID,FloatData>(this->entity(), blank));
    }
  return &(this->floatProperties());
}

template<>
SMTKCORE_EXPORT
IntegerData* EntityRef::properties<IntegerData>()
{
  if (!this->hasIntegerProperties())
    {
    if (!this->manager() || !this->entity())
      return NULL;
    IntegerData blank;
    this->manager()->integerProperties().insert(
      std::pair<UUID,IntegerData>(this->entity(), blank));
    }
  return &(this->integerProperties());
}

/*! \fn EntityRef::hasProperties<T>() const
 *! \fn EntityRef::hasProperties<T>()
 *  \brief Return a pointer to the properties of the entity or null if none exist.
 *
 * Unlike the properties() method, this will return a NULL pointer
 * if the entity does not already have any properties of the given type.
 *
 * This templated version exists for use in functions where the
 * property type is a template parameter.
 */
template<>
SMTKCORE_EXPORT
StringData* EntityRef::hasProperties<StringData>()
{
  if (this->hasStringProperties())
    return &(this->stringProperties());
  return NULL;
}

template<>
SMTKCORE_EXPORT
const StringData* EntityRef::hasProperties<StringData>() const
{
  if (this->hasStringProperties())
    return &(this->stringProperties());
  return NULL;
}

template<>
SMTKCORE_EXPORT
FloatData* EntityRef::hasProperties<FloatData>()
{
  if (this->hasFloatProperties())
    return &(this->floatProperties());
  return NULL;
}

template<>
SMTKCORE_EXPORT
const FloatData* EntityRef::hasProperties<FloatData>() const
{
  if (this->hasFloatProperties())
    return &(this->floatProperties());
  return NULL;
}

template<>
SMTKCORE_EXPORT
IntegerData* EntityRef::hasProperties<IntegerData>()
{
  if (this->hasIntegerProperties())
    return &(this->integerProperties());
  return NULL;
}

template<>
SMTKCORE_EXPORT
const IntegerData* EntityRef::hasProperties<IntegerData>() const
{
  if (this->hasIntegerProperties())
    return &(this->integerProperties());
  return NULL;
}

/*! \fn EntityRef::removeProperty<T>(const std::string& name)
 *  \brief Remove the property of type \a T with the given \a name, returning true on success.
 *
 * False is returned if the property did not exist for the given entity.
 *
 * This templated version exists for use in functions where the
 * property type is a template parameter.
 */
template<>
SMTKCORE_EXPORT
bool EntityRef::removeProperty<StringData>(const std::string& pname)
{ return this->removeStringProperty(pname); }

template<>
SMTKCORE_EXPORT
bool EntityRef::removeProperty<FloatData>(const std::string& pname)
{ return this->removeFloatProperty(pname); }

template<>
SMTKCORE_EXPORT
bool EntityRef::removeProperty<IntegerData>(const std::string& pname)
{ return this->removeIntegerProperty(pname); }

/**\defgroup SetMembershipMethods Methods for managing superset/subset membership.
  *\brief Primitive operations for subset/superset arrangements.
  *
  * These methods are intended to be used by subclasses such as Group and Model.
  */
///@{
/**\brief Add an entity as a member of this entity without any membership constraint checks.
  *
  */
EntityRef& EntityRef::addMemberEntity(const EntityRef& memberToAdd)
{
  ManagerPtr mgr = this->m_manager.lock();
  ManagerEventType event = std::make_pair(ADD_EVENT, this->subsetRelationType(memberToAdd));
  if (event.second != INVALID_RELATIONSHIP)
    {
    EntityRefArrangementOps::findOrAddSimpleRelationship(*this, SUPERSET_OF, memberToAdd);
    EntityRefArrangementOps::findOrAddSimpleRelationship(memberToAdd, SUBSET_OF, *this);
    mgr->trigger(event, *this, memberToAdd);
    }
  return *this;
}

/**\brief Return true when this EntityRef has a SUPERSET_OF relationship with \a ent.
  */
bool EntityRef::isMember(EntityRef& ent) const
{
  return EntityRefArrangementOps::findSimpleRelationship(*this, SUPERSET_OF, ent) >= 0;
}

/**\brief Return the first entity that this EntityRef has a SUBSET_OF relationship with.
  */
EntityRef EntityRef::memberOf() const
{
  return EntityRefArrangementOps::firstRelation<EntityRef>(*this, SUBSET_OF);
}

/**\brief Remove the \a memberToRemove from this EntityRef.
  *
  * No membership constraint checks are performed.
  */
EntityRef& EntityRef::removeMemberEntity(const EntityRef& memberToRemove)
{
  int aidx = EntityRefArrangementOps::findSimpleRelationship(*this, SUPERSET_OF, memberToRemove);
  return this->removeMemberEntity(aidx);
}

/**\brief Remove a member from this EntityRef given the index of its arrangement.
  *
  * No membership constraint checks are performed.
  *
  * Note that the \a indexOfArrangementToRemove is not an index into the Entity's
  * relations, but an index into the Arrangement vector for the SUPERSET_OF relationship.
  */
EntityRef& EntityRef::removeMemberEntity(int indexOfArrangementToRemove)
{
  if (indexOfArrangementToRemove < 0)
    return *this;

  ManagerPtr mgr = this->m_manager.lock();
  EntityRef memberToRemove = this->relationFromArrangement(SUPERSET_OF, indexOfArrangementToRemove, 0);
  ManagerEventType event = std::make_pair(DEL_EVENT, this->embeddingRelationType(memberToRemove));
  if (event.second != INVALID_RELATIONSHIP)
    {
    mgr->unarrangeEntity(this->m_entity, SUPERSET_OF, indexOfArrangementToRemove);
    mgr->trigger(event, *this, memberToRemove);
    }
  return *this;
}

/**\brief Determine the nature of a SUPERSET_OF relationship.
  *
  * Given a SUPERSET_OF arrangement, use the types of the involved
  * entities to determine the exact nature of the relationship.
  * This is used by the event framework so that observers can watch
  * for particular types of events.
  */
ManagerEventRelationType EntityRef::subsetRelationType(const EntityRef& member) const
{
  ManagerEventRelationType reln = INVALID_RELATIONSHIP;

  switch (this->entityFlags() & ENTITY_MASK)
    {
  case SESSION:
    switch (member.entityFlags() & ENTITY_MASK)
      {
    case MODEL_ENTITY: reln = SESSION_SUPERSET_OF_MODEL; break;
      }
    break;
  case MODEL_ENTITY:
    switch (member.entityFlags() & ENTITY_MASK)
      {
    case MODEL_ENTITY: reln = MODEL_SUPERSET_OF_MODEL; break;
    case GROUP_ENTITY: reln = MODEL_SUPERSET_OF_GROUP; break;
      }
    break;
  case GROUP_ENTITY:
    reln = GROUP_SUPERSET_OF_ENTITY;
    break;
  default:
    break;
    }

  return reln;
}

///@}

/**\brief Determine the nature of an EMBEDDED_IN relationship.
  *\ingroup embeddingMethods
  *
  * Given an EMBEDDED_IN arrangement, use the types of the involved
  * entities to determine the exact nature of the relationship.
  * This is used by the event framework so that observers can watch
  * for particular types of events.
  */
ManagerEventRelationType EntityRef::embeddingRelationType(const EntityRef& embedded) const
{
  ManagerEventRelationType reln = INVALID_RELATIONSHIP;

  switch (this->entityFlags() & ENTITY_MASK)
    {
  case SESSION:
    switch (embedded.entityFlags() & ENTITY_MASK)
      {
    case MODEL_ENTITY: reln = SESSION_INCLUDES_MODEL; break;
      }
    break;
  case MODEL_ENTITY:
    switch (embedded.entityFlags() & ENTITY_MASK)
      {
    case MODEL_ENTITY: reln = MODEL_INCLUDES_MODEL; break;
    case SHELL_ENTITY: reln = MODEL_INCLUDES_FREE_SHELL; break;
    case CELL_ENTITY: reln = MODEL_INCLUDES_FREE_CELL; break;
    case USE_ENTITY: reln = MODEL_INCLUDES_FREE_USE; break;
      }
    break;
  case CELL_ENTITY:
    switch (embedded.entityFlags() & ENTITY_MASK)
      {
    case CELL_ENTITY: reln = CELL_INCLUDES_CELL; break;
      }
    break;
  case SHELL_ENTITY:
    switch (embedded.entityFlags() & ENTITY_MASK)
      {
    case SHELL_ENTITY: reln = SHELL_INCLUDES_SHELL; break;
    case USE_ENTITY: reln = SHELL_HAS_USE; break;
      }
    break;
    }

  return reln;
}

  } // namespace model
} // namespace smtk

ext: cxx

max_stars_repo_name: yumin/SMTK

max_issues_repo_name: yumin/SMTK

max_forks_repo_name: yumin/SMTK


text:
/*!
@file
Forward declares `boost::hana::prefix`.

@copyright Louis Dionne 2015
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
 */

#ifndef BOOST_HANA_FWD_PREFIX_HPP
#define BOOST_HANA_FWD_PREFIX_HPP

#include <boost/hana/core/when.hpp>

namespace boost { namespace hana {
    //! Inserts a value before each element of a monadic structure.
    //! @relates MonadPlus
    //!
    //! Given a monadic structure `xs` and a value `z` called the prefix,
    //! `prefix` returns a new monadic structure. `prefix` satisfies
    //! @code
    //!     prefix(xs, z) == flatten(transform(xs, [](auto x) {
    //!         return concat(lift<M>(z), lift<M>(x));
    //!     }))
    //! @endcode
    //!
    //! For sequences, this simply corresponds to inserting the prefix before
    //! each element of the sequence. For example, given a sequence
    //! `[x1, ..., xn]`, `prefix` will return
    //! @code
    //!     [z, x1, z, x2, ..., z, xn]
    //! @endcode
    //! As explained above, this can be generalized to other MonadPlus models,
    //! with various levels of interest.
    //!
    //!
    //! Signature
    //! ---------
    //! Given a MonadPlus `M`, the signature is
    //! @f$ \mathrm{prefix} : M(T) \times T \to M(T) @f$.
    //!
    //! @param xs
    //! A monadic structure.
    //!
    //! @param pref
    //! A value (the prefix) to insert before each element of a monadic
    //! structure.
    //!
    //!
    //! Example
    //! -------
    //! @include example/prefix.cpp
#ifdef BOOST_HANA_DOXYGEN_INVOKED
    constexpr auto prefix = [](auto&& xs, auto&& pref) {
        return tag-dispatched;
    };
#else
    template <typename M, typename = void>
    struct prefix_impl : prefix_impl<M, when<true>> { };

    struct prefix_t {
        template <typename Xs, typename Pref>
        constexpr auto operator()(Xs&& xs, Pref&& pref) const;
    };

    constexpr prefix_t prefix{};
#endif
}} // end namespace boost::hana

#endif // !BOOST_HANA_FWD_PREFIX_HPP

max_stars_repo_name: qicosmos/hana

max_issues_repo_name: qicosmos/hana

max_forks_repo_name: qicosmos/hana


text:
#ifndef _IDISCRETE_CHOICE_HPP_
#define _IDISCRETE_CHOICE_HPP_
#if defined(_MSC_VER)
#pragma once
#endif

/*
* LEGAL NOTICE
* This computer software was prepared by Battelle Memorial Institute,
* hereinafter the Contractor, under Contract No. DE-AC05-76RL0 1830
* with the Department of Energy (DOE). NEITHER THE GOVERNMENT NOR THE
* CONTRACTOR MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY
* LIABILITY FOR THE USE OF THIS SOFTWARE. This notice including this
* sentence must appear on any copies of this computer software.
*
* EXPORT CONTROL
* User agrees that the Software will not be shipped, transferred or
* exported into any country or used in any manner prohibited by the
* United States Export Administration Act or any other applicable
* export laws, restrictions or regulations (collectively the "Export Laws").
* Export of the Software may require some form of license or other
* authority from the U.S. Government, and failure to obtain such
* export control license may result in criminal liability under
* U.S. laws. In addition, if the Software is identified as export controlled
* items under the Export Laws, User represents and warrants that User
* is not a citizen, or otherwise located within, an embargoed nation
* (including without limitation Iran, Syria, Sudan, Cuba, and North Korea)
*     and that User is not otherwise prohibited
* under the Export Laws from receiving the Software.
*
* Copyright 2011 Battelle Memorial Institute.  All Rights Reserved.
* Distributed as open-source under the terms of the Educational Community
* License version 2.0 (ECL 2.0). http://www.opensource.org/licenses/ecl2.php
*
* For further details, see: http://www.globalchange.umd.edu/models/gcam/
*
*/

/*!
 * \file idiscrete_choice.hpp
 * \ingroup Objects
 * \brief IDiscreteChoice class declaration file
 * \author Robert Link
 */
#include <boost/core/noncopyable.hpp>

#include "util/base/include/iparsable.h"
#include "util/base/include/iround_trippable.h"
#include "util/base/include/data_definition_util.h"

// Need to forward declare the subclasses as well.
class RelativeCostLogit;
class AbsoluteCostLogit;

/*!
 * \ingroup Objects
 * \brief Base class for discrete choice model class hierarchy
 * \details Subclasses of this class describe different formulae for
 *          imputing shares to competing options with different
 *          prices.  The classes gather in a single place the
 *          functions for calculating the discrete choice function and
 *          computing share weights.
 * \note For numerical stability purposes calculations done by the subclasses
 *       of this interface are done in log space.  Thus the return values, of
 *       calcUnnormalizedShare for instance, may be the log of the value a user
 *       would otherwise expect.  All methods will assume calculations are done
 *       in log space.
 * \note The calcAveragePrice method is currently only used in the land-allocator.
 *       The sectors and and subsectors are currently not using this and instead
 *       are calculating a straight average cost.
 */
class IDiscreteChoice : public IParsable, public IRoundTrippable, private boost::noncopyable {
public:
    /*!
     * \brief Constructor.
     * \details Inlined constructor to avoid compiler problems with abstract
     *          base classes.
     */
    inline IDiscreteChoice();

    /*!
     * \brief Destructor.
     * \details Inlined destructor to avoid compiler problems with abstract base
     *          classes and allow deletion through the base class pointer.
     */
    virtual inline ~IDiscreteChoice();

	/*!
     * \brief Write data from this object in an XML format for debugging.
	 * \param aPeriod Period for which to write data.
	 * \param aOut Filestream to which to write.
	 * \param aTabs Object responsible for writing the correct number of tabs.
     */
	virtual void toDebugXML( const int aPeriod,
                             std::ostream& aOut,
                             Tabs* aTabs ) const = 0;

    /*!
     * \brief Return the actual XML name of the object.
     */
    virtual const std::string& getXMLName() const = 0;

    /*!
     * \brief Any initializations or error checking before beginning of a model period.
     * \param aRegionName The name of the region that contains this object.
     * \param aContainerName The name of the containing object of this one.
     * \param aShouldShareIncreaseWithValue A boolean from containing objects if true
     *                                      would like to ensure share increases if the
     *                                      value of an option increases (i.e. it is a
     *                                      profit rate).  Conversely if false, the share
     *                                      should decrease if the value increases (i.e.
     *                                      it is a cost).
     * \param aPeriod The model period.
     */
    virtual void initCalc( const std::string& aRegionName, const std::string& aContainerName,
                           const bool aShouldShareIncreaseWithValue, const int aPeriod ) = 0;

    /*!
     * \brief Compute the unnormalized share given the value (e.g. cost or profit) and
     *        share weight of the given option.
     * \param aShareWeight The weighting term used in the share calculation.
     * \param aValue The value of the option.
     * \param aPeriod The current model period.
     * \return The log of the unnormalized share.
     */
    virtual double calcUnnormalizedShare( const double aShareWeight, const double aValue,
                                          const int aPeriod ) const = 0;

    /*!
     * \brief Compute the mean value according the the discrete choice function's
     *        parameterization.
     * \param aUnnormalizedShareSum The sum of all of the shares as calculated by
     *                              exp( calcUnnormalizedShare ) which will be used to
     *                              calculate the mean value.
     * \param aLogShareFac A log( unnormalized share ) factor that has been factored
     *                     out of aUnnormalizedShareSum.  Doing this allows for calculating
     *                     the average value in a numerically stable way.
     * \param aPeriod The current model period.
     * \return The average value.
     */
    virtual double calcAverageValue( const double aUnnormalizedShareSum,
                                     const double aLogShareFac,
                                     const int aPeriod ) const = 0;

    /*!
     * \brief Compute the share weight by inverting the discrete choice function
     *        given the values of the other terms in the equation.
     * \details Given the discrete choice is calculating unnormalized shares we must
     *          anchor this calculation which is done by assuming some "anchor" option
     *          receives a share weight of 1.
     * \param aShare The share the option should receive.
     * \param aValue The value of the option.
     * \param aAnchorShare The share of the anchoring option.
     * \param aAnchorValue The value of the anchoring option.
     * \param aPeriod The current model period.
     * \return The share weight.
     * \warning If users are intending to calcAverageValue then the scale of the share-weights matter.
     *          In such a case users may want to just set the anchor share to one and choose the anchor
     *          value to be in the correct range for which calcAverageValue should return a value.
     */
    virtual double calcShareWeight( const double aShare, const double aValue, const double aAnchorShare,
                                    const double aAnchorValue, const int aPeriod ) const = 0;

    /*!
     * \brief Compute the share weight by inverting the discrete choice function
     *        given the values of the other terms in the equation.
     * \details This is a convenience method for users who would like to use these
     *          share-weights with the calcAverageValue and anchor to the base value.
     * \param aShare The share the option should receive.
     * \param aValue The value of the option.
     * \param aPeriod The current model period.
     * \return The share weight.
     */
    virtual double calcShareWeight( const double aShare, const double aValue, const int aPeriod ) const = 0;

    /*!
     * \brief Sets the base value to use in the choice formulation if necessary.
     * \warning This value may be ignored if a user explicitly parsed a value to
     *          use instead.
     * \param aBaseValue The base value to set.
     */
    virtual void setBaseValue( const double aBaseValue ) = 0;

protected:

    DEFINE_DATA(
        /* Declare all subclasses of IDiscreteChoice to allow automatic traversal of the
         * hierarchy under introspection.
         */
        DEFINE_SUBCLASS_FAMILY( IDiscreteChoice, RelativeCostLogit, AbsoluteCostLogit )
    )
};

// Inline function definitions.
inline IDiscreteChoice::IDiscreteChoice(){
}

inline IDiscreteChoice::~IDiscreteChoice(){
}

#endif // _IDISCRETE_CHOICE_HPP_

max_stars_repo_name: crvernon/gcam-core

max_issues_repo_name: crvernon/gcam-core

max_forks_repo_name: crvernon/gcam-core


text:
#include <boost/python.hpp>
#include "../../def_submodule.hpp"

#include "IceRay/light/suns.hpp"
#include "IceRay/light/sung.hpp"

typedef GS_DDMRM::S_IceRay::S_type::GT_scalar             GTs_scalar;
typedef GS_DDMRM::S_IceRay::S_type::S_color::GT_scalar    GTs_color;
typedef GS_DDMRM::S_IceRay::S_type::S_coord::GT_scalar3D  GTs_coord3D;

typedef GS_DDMRM::S_IceRay::S_light::GC__pure          GTs__pure;

void expose_IceRay_light_SunGeneral()
 {
  //MAKE_SUBMODULE( IceRay );
  MAKE_SUBMODULE( core );
  MAKE_SUBMODULE( light );

  typedef GS_DDMRM::S_IceRay::S_light::GC_sung            Tf_sunG;

  typedef  bool (Tf_sunG::*Tf_setChild  )( GTs__pure * );
  Tf_setChild I_setChild = &Tf_sunG::F_child;

  boost::python::class_< Tf_sunG, boost::python::bases<GTs__pure> >( "LightSunGeneral" )
    .def( boost::python::init<>() )
    .def( boost::python::init<GTs__pure *>() )
    .def( "child", I_setChild      )
   ;

 }

void expose_IceRay_light_SunSpot()
 {
  //MAKE_SUBMODULE( IceRay );
  MAKE_SUBMODULE( core );
  MAKE_SUBMODULE( light );

  typedef GS_DDMRM::S_IceRay::S_light::S_type::GC_spot   Tf_spot;
  typedef GS_DDMRM::S_IceRay::S_light::GC_suns           Tf_suns;

  typedef  GTs_coord3D const& (Tf_suns::*Tf_getCoord  )(void) const;
  typedef  bool (Tf_suns::*Tf_setCoord  )(GTs_coord3D const&);

  Tf_getCoord I_getCenter = &Tf_suns::F_center;
  Tf_setCoord I_setCenter = &Tf_suns::F_center;

  typedef  Tf_spot const& (Tf_suns::*Tf_getSpot  )(void) const;
  Tf_getSpot I_getSpot = &Tf_suns::F_spot;
  typedef  bool (Tf_suns::*Tf_setSpot  )(Tf_spot const&);
  Tf_setSpot I_setSpot = &Tf_suns::F_spot;

  boost::python::class_< Tf_suns, boost::python::bases<GTs__pure> >( "LightSunSpot" )
      .def( boost::python::init<>() )
      .def( boost::python::init<Tf_spot const&>() )
      .def("spot",   I_getSpot, boost::python::return_value_policy<boost::python::copy_const_reference>() )
      .def("spot",   I_setSpot    )
      .def("center",      I_getCenter, boost::python::return_value_policy<boost::python::copy_const_reference>() )
      .def("center",      I_setCenter      )
      ;
 }

max_stars_repo_name: dmilos/IceRay

max_issues_repo_name: dmilos/IceRay

max_forks_repo_name: dmilos/IceRay