{-- TerraHS - Interface between TerraLib and Haskell

    (c) Sergio Costa (INPE) - Setembro, 2005

	This program is free software; you can redistribute it 
    and/or modify it under the terms of the GNU General 
    Public License 2.1 as published by the Free Software Foundation
    (http://www.opensource.org/licenses/gpl-license.php)
--}

{- | A module for supporting the functions of TerraLib TeGeometryAlgorithms

More information - <http://www.terralib.org>
-}
module TerraHS.TerraLib.TeGeometryAlgorithms 
	(
		 tedistance, telength, tearea, TeCentroid (..), setPrecision, tebufferregion 		
	) 
	 where


import Foreign
import Foreign.C.String
import qualified Foreign.Ptr (Ptr)

--locais
import TerraHS.Misc.Object
import TerraHS.TerraLib.TeGeometry
import TerraHS.TerraLib.TePoint
import TerraHS.TerraLib.TeLine2D
import TerraHS.TerraLib.TeCell
import TerraHS.TerraLib.TeBox
import TerraHS.TerraLib.TePolygon

---------------------------------------
--------- centroid operations ---------
---------------------------------------

	
-- | Calculates the centroid of a object
class TeCentroid a where
	tecentroid :: a -> TePoint
			
instance TeCentroid TePointSet where
	tecentroid ps = unsafePerformIO ( ( TerraHS.Misc.Object.new ps ) >>= tepointset_tefindcentroid >>= fromPointer >>= return )
	

instance TeCentroid TeLineSet where
	tecentroid ls = unsafePerformIO ( ( TerraHS.Misc.Object.new ls )	>>= telineset_tefindcentroid >>= fromPointer >>= return )

instance TeCentroid TePolygonSet where
	tecentroid pols = unsafePerformIO ( ( TerraHS.Misc.Object.new pols )	>>= tepolygonset_tefindcentroid >>= fromPointer >>= return )

instance TeCentroid TePolygon where
	tecentroid pols = unsafePerformIO ( ( TerraHS.Misc.Object.new pols )	>>= tepolygon_tefindcentroid >>= fromPointer >>= return )
	
---------------------------------------
--------- metric operations ---------
---------------------------------------
	
-- distance between two points	
tedistance pt1 pt2 = ( unsafePerformIO (applyf pt1 toTE pt2 toTE tepoint_tedistance))
	where
	toTE tx = TerraHS.Misc.Object.new tx

-- | Returns the length of a Line 2D.
telength :: TeLine2D -> Double
telength l = ( unsafePerformIO (TerraHS.Misc.Object.new l >>= h_telength >>= return ))

-- | Returns the area of a TePolygon 
tearea :: TePolygon -> Double
tearea p = ( unsafePerformIO (TerraHS.Misc.Object.new p >>= tegeometryarea >>= return ))


applyf ea fab ec fcd fbde  = fab ea >>= \eb -> fcd ec >>= \ed -> fbde eb ed >>= return


tebufferregion :: TePolygon  -> Double ->  Int -> [TeGeometry]
tebufferregion pol distance npoints = unsafePerformIO (tebufferregion')
	where
	tebufferregion' = do
		ptrpol <- (TerraHS.Misc.Object.new pol)
		ptrpolset <- (h_tebufferregion ptrpol distance npoints)
		(polset2geoset ptrpolset)
	
polset2geoset gs = size gs >>= (polygonset2geometryset gs 0)
	
	
-- metrics operations -------------------------
foreign import stdcall unsafe "c_tepoint_tedistance" tepoint_tedistance :: TePointPtr -> TePointPtr -> Prelude.IO Double
foreign import stdcall unsafe "c_telength" h_telength :: TeLine2DPtr ->  Prelude.IO Double
foreign import stdcall unsafe "c_tegeometryarea" tegeometryarea :: TePolygonPtr ->  Prelude.IO Double

foreign import stdcall unsafe "c_tepointset_tefindcentroid" tepointset_tefindcentroid :: TePointSetPtr ->  Prelude.IO TePointPtr
foreign import stdcall unsafe "c_tepolygonset_tefindcentroid" tepolygonset_tefindcentroid :: TePolygonSetPtr ->  Prelude.IO TePointPtr
foreign import stdcall unsafe "c_telineset_tefindcentroid" telineset_tefindcentroid :: TeLineSetPtr ->  Prelude.IO TePointPtr
foreign import stdcall unsafe "c_tepolygon_tefindcentroid" tepolygon_tefindcentroid :: TePolygonPtr ->  Prelude.IO TePointPtr

foreign import stdcall unsafe "c_set_precision" setPrecision :: Double ->  Prelude.IO ()

foreign import stdcall unsafe "c_tebufferregion" h_tebufferregion :: TePolygonPtr -> Double ->  Int ->  Prelude.IO TePolygonSetPtr