/*
* Copyright (c) 2009 Stanford University, School of Medicine All rights reserved.
*
* STANFORD ACADEMIC SOFTWARE LICENSE AGREEMENT
* FOR AngioLocalize SOURCE CODE:
*
* 1.  This is a legal agreement between you, RECIPIENT, and STANFORD UNIVERSITY.
*       By accepting, receiving, and using AngioLocalize.including any accompanying information, materials or
*       manuals (Program), you are agreeing to be bound by the terms of this Agreement.
*       If you do not agree to the terms of this Agreement, promptly return the Program to the STANFORD.

* 2.  STANFORD grants to RECIPIENT a royalty-free, nonexclusive, and nontransferable license to use the Program
*       and accompanying source code furnished hereunder, upon the terms and conditions set out below.
*       documentation and/or other materials provided with the distribution.
* 3.  RECIPIENT acknowledges that the Program is a research tool still in the development stage and that
*       it is being supplied as is, without any accompanying services, support or improvements from STANFORD.
* 4.  RECIPIENT agrees to use the Program solely for internal non-commercial purposes.
* 5.  RECIPIENT may create derivatives and further transfer the Program under the following terms and conditions:
*        A) Recipient agrees to not commercially exploit the Program and agrees all uses will be for non-commercial purposes; and,
*        B) Recipient may not mark any derivatives with the title of Program and may not to use iPad mark for any derivatives; and,
*        C) Recipient agrees to mark and acknowledge all derivatives as follows: "This is a derivative work based on AngioLocalize:
*           Frameless AVM localization with 2D Digital Subtraction Angiography (DSA) and 3D Rotational Angiography (DRA) Images developed
*           by Dimitre Hristov, Lina Liu.
*        D) Recipient agrees to make all improvements, enhancements and derivatives available under
*           similar terms and conditions to the research community.
* 6.   RECIPIENT warrants that RECIPIENT will not remove or export any part of the software or Program from the United
*       States except in full compliance with all United States and other applicable laws and regulations.
* 7.  RECIPIENT will use the Program in compliance with all applicable laws, policies and regulations including, but not
*       limited to, any approvals, informed consent and patient confidentiality principles.
* 8.   RECIPIENT will indemnify, hold harmless, and defend Stanford against any claim of any kind arising out of or
*       related to the exercise of any rights granted under this Agreement or the breach of this Agreement by RECIPIENT.
* 9.  Title and copyright to the Program and any associated documentation shall at all times remain with STANFORD,
*       and RECIPIENT agrees to preserve same.
*/


//----------------------------------------------------------------------------------
//! The ML module class AngioTransformEdit.
/*!
// \file    mlAngioTransformEdit.cpp
// \author  linaliu
// \date    2009-12-09
//
//
*/
//----------------------------------------------------------------------------------

// Local includes
#include "mlAngioTransformEdit.h"

ML_START_NAMESPACE


//! Implements code for the runtime type system of the ML
ML_BASEOP_CLASS_SOURCE(AngioTransformEdit, BaseOp);

//----------------------------------------------------------------------------------
//! Constructor
//----------------------------------------------------------------------------------
AngioTransformEdit::AngioTransformEdit ()
  : BaseOp(0, 0)
{
  ML_TRACE_IN("AngioTransformEdit::AngioTransformEdit ()");

  // Suppress calls of handleNotification on field changes to
  // avoid side effects during initialization phase.
  handleNotificationOff();

  // Get reference to always existing field container (guaranteed by BaseOp).
  FieldContainer &fields = *getFieldContainer();

  _translationFld           = fields.addVec3f  ("translation"      );
  _rotationFld              = fields.addVec3f  ("rotation"      );

  _addxtranslationFld       = fields.addNotify ("addxtranslation");
  _addytranslationFld       = fields.addNotify ("addytranslation");
  _addztranslationFld       = fields.addNotify ("addztranslation");

  _subxtranslationFld       = fields.addNotify ("subxtranslation");
  _subytranslationFld       = fields.addNotify ("subytranslation");
  _subztranslationFld       = fields.addNotify ("subztranslation");

  _transxincreFld           = fields.addDouble("transincrex");
  _transyincreFld           = fields.addDouble("transincrey");
  _transzincreFld           = fields.addDouble("transincrez");

  _transxincreFld->setDoubleValue(1);
  _transyincreFld->setDoubleValue(1);
  _transzincreFld->setDoubleValue(1);

  _addxrotationFld          = fields.addNotify ("addxrotation");
  _addyrotationFld          = fields.addNotify ("addyrotation");
  _addzrotationFld          = fields.addNotify ("addzrotation");

  _subxrotationFld          = fields.addNotify ("subxrotation");
  _subyrotationFld          = fields.addNotify ("subyrotation");
  _subzrotationFld          = fields.addNotify ("subzrotation");

  _rotationxincreFld        = fields.addDouble("rotationxincre");
  _rotationyincreFld        = fields.addDouble("rotationyincre");
  _rotationzincreFld        = fields.addDouble("rotationzincre");

  _rotationxincreFld->setDoubleValue(1);
  _rotationyincreFld->setDoubleValue(1);
  _rotationzincreFld->setDoubleValue(1);

  _matrixFld                = fields.addMatrix("matrix");
  _resetFld                 = fields.addNotify("reset");
  handleNotificationOn();

  // Activate inplace data buffers for output outIndex and input inIndex.
  // setOutImgInplace(outIndex, inIndex);

  // Activate page data bypass from input inIdx to output outIdx.
  // Note that the module must still be able to calculate the output image.
  // setBypass(outIndex, inIndex);

  // Activate parallel execution of calcOutSubImage.
  // setThreadSupport(supportMode);
  // with supportMode =
  //   NO_THREAD_SUPPORT                 //! The module is not thread safe at all.
  //   CALC_OUTSUBIMAGE_ON_STD_TYPES     //! calcOutSubImage can be called in parallel for scalar voxel types.
  //   CALC_OUTSUBIMAGE_ON_CARRIER_TYPES //! calcOutSubImage can be called in parallel for carrier voxel types.
  //   CALC_OUTSUBIMAGE_ON_ALL_TYPES     //! calcOutSubImage can be called in parallel for all voxel types.
  // Warning: You should be familiar with multithreading before activating this feature.

  // Specify whether the module can only process standard scalar voxel types or
  // also registered voxel types (vec2, mat2, complexf, Vector, etc.)
  // setVoxelDataTypeSupport(permittedTypes);
  // with permittedTypes =
  //   ONLY_STANDARD_TYPES               //! Only standard scalar voxels are supported.
  //   FULLY_OPERATIONAL                 //! Scalar and registered voxels types are supported.
  //   MINIMUM_OPERATIONAL               //! Scalar and registered voxel types are supported.
  //                                     //! Voxel operators are not used by algorithm.
  //
  // See ML Programming Guide, "Configuring Image Processing Behaviour of the BaseOp"
  // for further details.
}

//----------------------------------------------------------------------------------
//! Handle field changes of the field field.
//----------------------------------------------------------------------------------
void AngioTransformEdit::handleNotification (Field *field)
{
  ML_TRACE_IN("AngioTransformEdit::handleNotification ()");
	  if (field == _addxtranslationFld) {

		 _translationFld->setVec3fValue(_translationFld->getVec3fValue() +
			 vec3(_transxincreFld->getDoubleValue(), 0, 0));
	  } else if (field == _addytranslationFld) {
        _translationFld->setVec3fValue(_translationFld->getVec3fValue() +
			 vec3(0, _transyincreFld->getDoubleValue(), 0));
	  } else if (field == _addztranslationFld){
		  _translationFld->setVec3fValue(_translationFld->getVec3fValue() +
			 vec3(0, 0, _transzincreFld->getDoubleValue()));
	  } else if (field == _subxtranslationFld) {
		  _translationFld->setVec3fValue(_translationFld->getVec3fValue() -
			 vec3( _transxincreFld->getDoubleValue(), 0, 0));
	  } else if (field == _subytranslationFld) {
		   _translationFld->setVec3fValue(_translationFld->getVec3fValue() -
			 vec3(0, _transyincreFld->getDoubleValue(), 0));
	  } else if (field == _subztranslationFld) {
		   _translationFld->setVec3fValue(_translationFld->getVec3fValue() -
			 vec3(0, 0, _transzincreFld->getDoubleValue()));
	  } else if (field == _addxrotationFld) {
		  _rotationFld->setVec3fValue(_rotationFld->getVec3fValue()  +
			  vec3(_rotationxincreFld->getDoubleValue()/180.0 * PI, 0,0));
	  } else if (field == _addyrotationFld) {
          _rotationFld->setVec3fValue(_rotationFld->getVec3fValue() +
			  vec3(0, _rotationyincreFld->getDoubleValue()/ 180.0 * PI, 0));
	  } else if (field == _addzrotationFld) {
		   _rotationFld->setVec3fValue(_rotationFld->getVec3fValue() +
			   vec3(0,0,_rotationzincreFld->getDoubleValue()/ 180.0 * PI));
	  } else if (field == _subxrotationFld) {
           _rotationFld->setVec3fValue(_rotationFld->getVec3fValue() -
			   vec3(_rotationxincreFld->getDoubleValue()/ 180.0 * PI, 0,0));
	  } else if (field == _subyrotationFld) {
            _rotationFld->setVec3fValue(_rotationFld->getVec3fValue() -
				vec3(0, _rotationyincreFld->getDoubleValue()/ 180.0 * PI, 0));
	  } else if (field == _subzrotationFld) {
		    _rotationFld->setVec3fValue(_rotationFld->getVec3fValue() -
				vec3(0,0,_rotationzincreFld->getDoubleValue()/ 180.0 * PI));
	  } else if (field == _resetFld) {
		  _matrixFld->setStringValue("1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1");
		  _translationFld->setVec3fValue(vec3(0, 0, 0));
		  _rotationFld->setVec3fValue(vec3(0,0,0));
		  return;
	  }
      updateMatrix();
  // Handle changes of module parameters and connectors here.
}

//----------------------------------------------------------------------------------
//! Update internal module state after load or clone and enable notification handling again.
//----------------------------------------------------------------------------------
void AngioTransformEdit::activateAttachments ()
{
  ML_TRACE_IN("AngioTransformEdit::activateAttachments ()");

  // Update members to new field state here.
  // Call super class functionality to enable notification handling again.
  BaseOp::activateAttachments ();
}

void AngioTransformEdit::updateMatrix()
{
	vec3 v3 = _translationFld->getVec3fValue();
	mat4 Translations(1,0,0,v3[0], 0,1,0,v3[1], 0,0,1,v3[2], 0, 0, 0,1);
	//_affine1TempM = (_matrix1Fld->getMatrixValue()) * Translations;

	vec3 x3 = _rotationFld->getVec3fValue();
	vec3 axis(1, 0, 0); // x axis

	Rotation RotTemp(axis, x3[0]);
	axis.assign(0,1,0); // y axis
	Rotation rot(axis, x3[1]); //y axis
	rot *= RotTemp;
	axis.assign(0,0,1); // z axis
	RotTemp.setRotation(axis, x3[2]);
	rot *= RotTemp;
	mat4 RotMatrix = rot.getMatrix();
	_matrixFld->setMatrixValue(RotMatrix * Translations);

}
ML_END_NAMESPACE

