/*
 * @(#)PTransform.java
 *
 * Copyright 2001 by Intelligent Technology Inc. All rights reserved.
 */

package jp.co.iti.fagot.gob;

import java.awt.Shape;

import java.awt.geom.Point2D;
import java.awt.geom.AffineTransform;
import java.awt.geom.NoninvertibleTransformException;

import jp.co.iti.fagot.geom.ZPoint;

import jp.co.iti.fagot.util.ZDebug;
/**
 * P系クラスは描画部品の描画属性(プロパティ)を格納する
 *
 * http://www.w3.org/TR/2000/CR-SVG-20001102/DTD/svg-20001102.dtdにおける
 * TransformList に対応
 *
 * Transform
 *
 * 単純図形：
 *	移動・拡大は座標に反映
 *	回転・ゆがみなど特殊変形を座標変換オブジェクトに格納
 *
 * グループ化図形：
 *	自分の座標は持たずに、すべての操作を座標変換オブジェクトに格納
 *
 * @author  福島康治
 * @version 1.01 2001/01/07
 */
public class PTransform {

	/**
	 * コンストラクタ
	 */
	public PTransform() {
	m00=1;
	m11=1;
	}

	/**
	 * コンストラクタ
	 */
	public PTransform( AffineTransform at ) {
	this();
	setTransform(at);
	}

	/**
	 * コンストラクタ
	 */
	public PTransform( PTransform trans ) {
	this();
	set(trans);
	}

	/**
	 * コンストラクタ
	 */
	public PTransform( double d00, double d10,
					   double d01, double d11,
					   double d02, double d12 ) {
	this();
	setTransform(d00,d10,d01,d11,d02,d12);
	}

	/**
	 * コンストラクタ(倍率のみ指定)
	 */
	public PTransform( double scale ) {
	this();
	setTransform(scale,0,0,scale,0,0);
	}

	//## 値 ###########################################################
	/**
	 * 変換の取得
	 */
	public AffineTransform getTransform() {
	return new AffineTransform(m00,m10,
								m01,m11,
								m02,m12) ;
	}

	/**
	 * 倍率のみ変換の取得
	 * @ret AffineTransform
	 */
	public AffineTransform getScaleTransform(){
	return new AffineTransform(m00,0,0,m11,0,0);
	}

	/**
	 * 変換の設定
	 */
	public void set( PTransform trans ) {
	setTransform( trans.getTransform() );
	}

	/**
	 * 変換の設定
	 */
	public void setTransform( AffineTransform at ) {
	setTransform( at.getScaleX(), at.getShearY(),
				  at.getShearX(), at.getScaleY(),
				  at.getTranslateX(), at.getTranslateY() );
	}

	/**
	 * 変換の設定
	 */
	public void setTransform( double d00, double d10,
							  double d01, double d11,
							  double d02, double d12 ) {
		m00 = d00;
		m10 = d10;
		m01 = d01;
		m11 = d11;
		m02 = d02;
		m12 = d12;
	}

	/**
	 * 変換の追加
	 */
	public void add( PTransform trans ) {
	AffineTransform srctrans = getTransform();
	AffineTransform dsttrans = trans.getTransform();
//	srctrans.concatenate(dsttrans);
//	setTransform( srctrans );
	dsttrans.concatenate(srctrans);
	setTransform( dsttrans );
	}

	//## 変換 #########################################################
	/**
	 * 変換した座標の取得
	 * @param pt 変換対象となる座標
	 */
	public ZPoint transform( ZPoint pt ) {
	ZPoint pttrans = new ZPoint(pt);
	AffineTransform at = getTransform();
	Point2D pt2D = at.transform(pttrans,null);
	pttrans.setLocation(pt2D.getX(),pt2D.getY()) ;
	return pttrans;
	}

	/**
	 * 変換した形状の取得
	 * @param sh 変換対象となる形状
	 */
	public Shape transform( Shape sh ) {
	AffineTransform at = getTransform();
	return at.createTransformedShape(sh);
	}

	/**
	 * 逆変換した座標の取得
	 * @param pt 変換対象となる座標
	 */
	public ZPoint inverseTransform( ZPoint pt ) {
	ZPoint pttrans = new ZPoint(pt);
	AffineTransform at = getTransform();
	try {
		AffineTransform atr = at.createInverse();
		Point2D pt2D = atr.transform(pttrans,null);
		pttrans.setLocation(pt2D.getX(),pt2D.getY()) ;
	} catch ( NoninvertibleTransformException nt ) {
		ZDebug.err("at.createInverse failed:"+at.toString());
		nt.printStackTrace();
	}
	return pttrans;
	}

	/**
	 * 逆変換した形状の取得
	 * @param sh 変換対象となる形状
	 */
	public Shape inverseTransform( Shape sh ) {
	AffineTransform at = getTransform();
	try {
		AffineTransform atr = at.createInverse();
		return atr.createTransformedShape(sh);
	} catch ( NoninvertibleTransformException nt ) {
		ZDebug.err("at.createInverse failed:"+at.toString());
	}
	return null;
	}

	//## CLONE ########################################################
	/**
	 * 複製の作成
	 */
	public Object clone() {
	PTransform obj = new PTransform();
	obj.set(this);
	return obj;
	}

	public String toString() {
	return "PTransform:"+
		m00+" "+m10+" "+
		m01+" "+m11+" "+
		m02+" "+m12 ;
	}

	//## アトリビュート ###############################################
	/**
	 * 変換座標
	 */
	protected double m00;
	protected double m10;
	protected double m01;
	protected double m11;
	protected double m02;
	protected double m12;
}
