text: /*
   * Copyright (c) 2008, Laminar Research.
   *
   * Permission is hereby granted, free of charge, to any person obtaining a
   * copy of this software and associated documentation files (the "Software"),
   * to deal in the Software without restriction, including without limitation
   * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   * and/or sell copies of the Software, and to permit persons to whom the
   * Software is furnished to do so, subject to the following conditions:
   *
   * The above copyright notice and this permission notice shall be included in
   * all copies or substantial portions of the Software.
   *
   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   * THE SOFTWARE.
   *
   */
  
  #include "WED_TextureBezierNode.h"
  #include "GISUtils.h"
  
  DEFINE_PERSISTENT(WED_TextureBezierNode)
  TRIVIAL_COPY(WED_TextureBezierNode, WED_GISPoint_Bezier)
  
  WED_TextureBezierNode::WED_TextureBezierNode(WED_Archive * a, int i) : WED_GISPoint_Bezier(a,i),
  	mS(  this,PROP_Name("S",			XML_Name("texture_node","s")),	  0.0,5,4),
  	mT  (this,PROP_Name("T",			XML_Name("texture_node","t")),	  0.0,5,4),
  	mScL(this,PROP_Name("S (Ctrl Low)",	XML_Name("texture_node","sc_lo")), 0.0,5,4),
  	mTcL(this,PROP_Name("T (Ctrl Low)",	XML_Name("texture_node","tc_lo")), 0.0,5,4),
  	mScH(this,PROP_Name("S (Ctrl Hi)",	XML_Name("texture_node","sc_hi")), 0.0,5,4),
  	mTcH(this,PROP_Name("T (Ctrl Hi)",	XML_Name("texture_node","tc_hi")), 0.0,5,4)
  {
  }
  
  WED_TextureBezierNode::~WED_TextureBezierNode()
  {
  }
  
  
  bool		WED_TextureBezierNode::HasLayer(GISLayer_t l) const
  {
  	if(l == gis_UV) return true;
  	return WED_GISPoint_Bezier::HasLayer(l);
  }
  
  void		WED_TextureBezierNode::SetLocation(GISLayer_t l,const Point2& st)
  {
  	if(l == gis_UV)
  	{
  		if (st.x() != mS.value || st.y() != mT.value)
  		{
  			StateChanged();
  			mS = st.x();
  			mT = st.y();
  			CacheInval(cache_Spatial);
  			CacheBuild(cache_Spatial);
  		}
  	}
  	else 
  		WED_GISPoint_Bezier::SetLocation(l,st);
  }
  
  void		WED_TextureBezierNode::GetLocation(GISLayer_t l,	   Point2& st) const
  {
  	if(l == gis_UV)
  	{
  		st.x_ = mS.value;
  		st.y_ = mT.value;
  	} else 
  		WED_GISPoint_Bezier::GetLocation(l,st);
  }
  
  bool	WED_TextureBezierNode::GetControlHandleLo (GISLayer_t layer,      Point2& p) const
  {
  	if(!WED_GISPoint_Bezier::GetControlHandleLo(gis_Geo,p)) return false;
  	if(layer == gis_UV) 
  	{
  		p.x_ = mScL.value + mS.value;
  		p.y_ = mTcL.value + mT.value;	
  	}
  	return true;
  }
  
  bool	WED_TextureBezierNode::GetControlHandleHi (GISLayer_t layer,      Point2& p) const
  {
  	if(!WED_GISPoint_Bezier::GetControlHandleHi(gis_Geo,p)) return false;
  	if(layer == gis_UV) 
  	{
  		p.x_ = mScH.value + mS.value;
  		p.y_ = mTcH.value + mT.value;	
  	}
  	return true;
  }
  
  void	WED_TextureBezierNode::SetControlHandleLo (GISLayer_t layer,const Point2& p)
  {
  	if(layer == gis_UV)
  	{
  		if(p.x() != mScL.value + mS.value ||
  		   p.y() != mTcL.value + mT.value)
  		{
  			StateChanged();
  			mScL = p.x() - mS.value;
  			mTcL = p.y() - mT.value;
  			CacheInval(cache_Spatial);
  			CacheBuild(cache_Spatial);
  		}
  	} else
  		WED_GISPoint_Bezier::SetControlHandleLo(layer,p);
  }
  
  void	WED_TextureBezierNode::SetControlHandleHi (GISLayer_t layer,const Point2& p)
  {
  	if(layer == gis_UV)
  	{
  		if(p.x() != mScH.value + mS.value ||
  		   p.y() != mTcH.value + mT.value)
  		{
  			StateChanged();
  			mScH = p.x() - mS.value;
  			mTcH = p.y() - mT.value;
  			CacheInval(cache_Spatial);
  			CacheBuild(cache_Spatial);
  		}
  	} else
  		WED_GISPoint_Bezier::SetControlHandleHi(layer,p);
  }
  
  
  void			WED_TextureBezierNode::Rescale			(GISLayer_t l, const Bbox2& old_bounds, const Bbox2& new_bounds)
  {
  	if(l == gis_Geo)	WED_GISPoint_Bezier::Rescale(l,old_bounds,new_bounds);
  	else
  	{
  		Point2 p;
  		GetLocation(l,p);
  		
  		StateChanged();
  
  		mS.value = old_bounds.rescale_to_x(new_bounds,mS.value);
  		mT.value = old_bounds.rescale_to_y(new_bounds,mT.value);
  		
  		mScL.value = old_bounds.rescale_to_xv(new_bounds,mScL.value);
  		mTcL.value = old_bounds.rescale_to_yv(new_bounds,mTcL.value );
  		mScH.value = old_bounds.rescale_to_xv(new_bounds,mScH.value);
  		mTcH.value = old_bounds.rescale_to_yv(new_bounds,mTcH.value );
  
  		CacheInval(cache_Spatial);
  		CacheBuild(cache_Spatial);
  	}
  }
  
  void			WED_TextureBezierNode::Rotate			(GISLayer_t l, const Point2& ctr, double a)
  {
  	if(l == gis_Geo)	WED_GISPoint_Bezier::Rotate(l,ctr,a);
  	else
  	if (a != 0.0)
  	{
  		Point2 p;
  		GetLocation(l,p);
  		StateChanged();
  
  		Point2	pt_old_lo(p.x() + mScL.value, p.y() + mTcL.value);
  		Point2	pt_old_hi(p.x() + mScH.value, p.y() + mTcH.value);
  		Vector2	v_old_lo = VectorLLToMeters(ctr, Vector2(ctr,pt_old_lo));
  		Vector2	v_old_hi = VectorLLToMeters(ctr, Vector2(ctr,pt_old_hi));
  		double old_len_lo = sqrt(v_old_lo.squared_length());
  		double old_len_hi = sqrt(v_old_hi.squared_length());
  
  		double old_ang_lo = VectorMeters2NorthHeading(ctr,ctr,v_old_lo);
  		double old_ang_hi = VectorMeters2NorthHeading(ctr,ctr,v_old_hi);
  		Vector2	v_new_lo;
  		Vector2	v_new_hi;
  
  		NorthHeading2VectorMeters(ctr, ctr, old_ang_lo + a, v_new_lo);
  		NorthHeading2VectorMeters(ctr, ctr, old_ang_hi + a, v_new_hi);
  		v_new_lo.normalize();
  		v_new_hi.normalize();
  		v_new_lo *= old_len_lo;
  		v_new_hi *= old_len_hi;
  
  		v_new_lo = VectorMetersToLL(ctr,v_new_lo);
  		v_new_hi = VectorMetersToLL(ctr,v_new_hi);
  
  		WED_GISPoint::Rotate(l,ctr,a);
  		GetLocation(l,p);
  
  		mScL.value = ctr.x() + v_new_lo.dx - p.x();
  		mScH.value = ctr.x() + v_new_hi.dx - p.x();
  		mTcL.value = ctr.y() + v_new_lo.dy - p.y();
  		mTcH.value = ctr.y() + v_new_hi.dy - p.y();
  		CacheInval(cache_Spatial);
  		CacheBuild(cache_Spatial);
  
  	}
  	
  }
  
  