/***
 *** Title: DeclaredName Utility
 *** Author: Itsuki Noda
 *** Date: 2006.10.11
 ***/

package daruma.geometry;

import com.vividsolutions.jts.geom.* ;
import com.vividsolutions.jts.geom.impl.* ;

//======================================================================
/**
 * JTS が提供する OGC モデル準拠の geometry facility を利用するための
 * ツール群
 */

public class OgcGeometryFactory extends GeometryFactory {

    private static final long serialVersionUID = 0L;

    //--------------------------------------------------
    /**
     * constructor
     */
    public OgcGeometryFactory() {
	super() ;
    }

    //--------------------------------------------------
    /**
     * 2D coordinate 作成
     */
    public CoordinateSequence genCoords2D(double ... xyList) {
	return genCoords(2, xyList) ;
    }

    //--------------------------------------------------
    /**
     * 3D coordinate 作成
     */
    public CoordinateSequence genCoords3D(double ... xyzList) {
	return genCoords(3, xyzList) ;
    }
    
    //--------------------------------------------------
    /**
     * 汎用 coordinate 作成
     */
    public CoordinateSequence genCoords(int dimensionN, 
					double ... values) {
	return genCoordsBody(false, dimensionN, values) ;
    }
    
    //--------------------------------------------------
    /**
     * 2D の閉じた coordinate 作成
     */
    public CoordinateSequence genClosedCoords2D(double ... xyList) {
	return genClosedCoords(2, xyList) ;
    }

    //--------------------------------------------------
    /**
     * 3D の閉じた coordinate 作成
     */
    public CoordinateSequence genClosedCoords3D(double ... xyzList) {
	return genClosedCoords(3, xyzList) ;
    }
    
    //--------------------------------------------------
    /**
     * 汎用 の閉じた coordinate 作成
     */
    public CoordinateSequence genClosedCoords(int dimensionN, 
					      double ... values) {
	return genCoordsBody(true, dimensionN, values) ;
    }

    //--------------------------------------------------
    /**
     * coordinate 作成 (body)
     */
    private CoordinateSequence genCoordsBody(boolean isClosed, 
					     int dimensionN,
					     double ... values) {
	CoordinateSequence coord = null ;
	int valueN = values.length ;

	if(valueN % dimensionN != 0) {
	    // FIXME: should cause exception
	} else {
	    int coordN = valueN / dimensionN ;

	    if(isClosed) {
		coord = newCoords(coordN + 1, dimensionN) ;
	    } else {
		coord = newCoords(coordN, dimensionN) ;
	    }

	    for(int i = 0 ; i < coordN ; i++) {
		for(int j = 0 ; j < dimensionN ; j++) {
		    coord.setOrdinate(i,j,values[i * dimensionN + j]) ;
		}
	    }

	    if(isClosed) {
		for(int j = 0 ; j < dimensionN ; j++) {
		    coord.setOrdinate(coordN, j, values[j]) ;
		}
	    }
	}

	return coord ;
    }

    //--------------------------------------------------
    /**
     * coordinate 作成 (body)
     */
    public CoordinateSequence newCoords(int size, int dimensionN)
    {
	return this.getCoordinateSequenceFactory().create(size, dimensionN) ;
    }


    //--------------------------------------------------
    /**
     * Point (2D) の作成
     */
    public Point genPoint2D(double x, double y) {
	
	return this.createPoint(this.genCoords2D(x,y)) ;
    }

    //--------------------------------------------------
    /**
     * Point (3D) の作成
     */
    public Point genPoint3D(double x, double y, double z) {
	return this.createPoint(this.genCoords3D(x,y,z)) ;
    }

    //--------------------------------------------------
    /**
     * LineString (2D) の作成
     */
    public LineString genLineString2D(double ... xyList) {
	return this.createLineString(this.genCoords2D(xyList)) ;
    }
    
    //--------------------------------------------------
    /**
     * LineString (3D) の作成
     */
    public LineString genLineString3D(double ... xyzList) {
	return this.createLineString(this.genCoords3D(xyzList)) ;
    }

    //--------------------------------------------------
    /**
     * LinearRing(2D) の作成
     */
    public LinearRing genLinearRing2D(double ... xyList) {
	return this.createLinearRing(this.genClosedCoords2D(xyList)) ;
    }

    //--------------------------------------------------
    /**
     * LinearRing(3D) の作成
     */
    public LinearRing genLinearRing3D(double ... xyzList) {
	return this.createLinearRing(this.genClosedCoords3D(xyzList)) ;
    }

    //--------------------------------------------------
    /**
     * 単純な(innerBoundaryのない) Polygon(2D) の作成
     */
    public Polygon genSimplePolygon2D(double ... xyList) {
	return this.createPolygon(this.genLinearRing2D(xyList),null) ;
    }

    //--------------------------------------------------
    /**
     * 単純な(innerBoundaryのない) Polygon(3D) の作成
     */
    public Polygon genSimplePolygon3D(double ... xyzList) {
	return this.createPolygon(this.genLinearRing3D(xyzList),null) ;
    }

    //--------------------------------------------------
    /**
     * CoordinateSequence への設定(2D)
     */
    static public void setCoordinate2D(CoordinateSequence coords,
				       int index,
				       double x,
				       double y) 
    {
	coords.setOrdinate(index,0,x) ;
	coords.setOrdinate(index,1,y) ;
    }

    //--------------------------------------------------
    /**
     * CoordinateSequence への設定(3D)
     */
    static public void setCoordinate3D(CoordinateSequence coords,
				       int index,
				       double x,
				       double y,
				       double z) 
    {
	coords.setOrdinate(index,0,x) ;
	coords.setOrdinate(index,1,y) ;
	coords.setOrdinate(index,2,z) ;
    }
}
