{-- 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 - -} module TerraHS.TerraLib.TeGeometryAlgorithms where import Foreign (unsafePerformIO) import Foreign.C.String import qualified Foreign.Ptr (Ptr) --locais import TerraHS.Algebras.Base.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 import TerraHS.Algebras.Base.Operations import TerraHS.Algebras.Spatial.Geometries --------------------------------------- --------- centroid operations --------- --------------------------------------- instance Centroid TePointSet TePoint where centroid ps = unsafePerformIO ( ( new ps ) >>= tepointset_tefindcentroid >>= fromPointer >>= return ) instance Centroid TeLineSet TePoint where centroid ls = unsafePerformIO ( ( new ls ) >>= telineset_tefindcentroid >>= fromPointer >>= return ) instance Centroid TePolygonSet TePoint where centroid pols = unsafePerformIO ( ( new pols ) >>= tepolygonset_tefindcentroid >>= fromPointer >>= return ) instance Centroid TePolygon TePoint where centroid pols = unsafePerformIO ( ( new pols ) >>= tepolygon_tefindcentroid >>= fromPointer >>= return ) --------------------------------------- --------- metric operations --------- --------------------------------------- instance DistanceDirection TePoint where distance p1 p2 = tedistance p1 p2 instance Numeric TePolygon where area p = tearea p length pol = telength (head (getlines pol) ) where getlines (TePolygon ls) = ls instance Numeric TeBox where area p = teareabox p instance Numeric TeLine2D where length l = telength l -- distance between two points tedistance pt1 pt2 = ( unsafePerformIO (applyf pt1 toTE pt2 toTE tepoint_tedistance)) where toTE tx = new tx -- | Returns the length of a Line 2D. telength :: TeLine2D -> Double telength l = ( unsafePerformIO (new l >>= \tl -> h_telength tl >>= \r -> delete tl >> return r )) -- | Returns the area of a TePolygon tearea :: TePolygon -> Double tearea p = ( unsafePerformIO (new p >>= \tpol -> (tegeometryarea tpol) >>= \r -> delete tpol >> return r )) teareabox :: TeBox -> Double teareabox p = ( unsafePerformIO (new p >>= \tb -> tegeometryareabox tb >>= \r -> delete tb >> return r )) makepolygon box = unsafePerformIO ( (new box ) >>= (temakepolygon) >>= fromPointer >>= return ) tepolygonrotate pol1 angle= unsafePerformIO ((new pol1) >>= \tpol1 -> (tepolygon_rotate tpol1 angle) >>= fromPointer >>= \r -> delete tpol1 >> return r) tepolygonradius pol1 = unsafePerformIO ((new pol1) >>= \tpol1 -> (tepolygon_radius tpol1 ) >>= \r -> delete tpol1 >> return r) tepolygonrectangularfit pol1 = unsafePerformIO ((new pol1) >>= \tpol1 -> (tepolygon_rectangularfit tpol1 ) >>= \r -> delete tpol1 >> return r) {-- foreign import stdcall unsafe "c_tepolygon_angle" tepolygon_angle :: TePolygonPtr -> Prelude.IO Double --} --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 <- (new pol) ptrpolset <- (h_tebufferregion ptrpol distance npoints) (polset2geoset ptrpolset) polset2geoset gs = size gs >>= (polygonset2geometryset gs 0) ----------- overlay instance Set TePolygon where union p1 p2 | (r == [] ) = error "union: return any geometry" | otherwise = head r where r = (union [p1] [p2]) difference p1 p2 = head (difference [p1] [p2]) intersection p1 p2 = head (intersection [p1] [p2]) instance Set [TeGeometry] where union gs1 gs2 = unsafePerformIO (apply1 gs1 gs2 (\ptr1 ptr2 -> teoverlay ptr1 ptr2 2)) difference gs1 gs2 = unsafePerformIO (apply1 gs1 gs2 (\ptr1 ptr2 -> teoverlay ptr1 ptr2 1)) intersection gs1 gs2 = unsafePerformIO (apply1 gs1 gs2 (\ptr1 ptr2 -> teoverlay ptr1 ptr2 4)) instance Set TePolygonSet where union gs1 gs2 = (TePolygonSet (map toPolygon (unsafePerformIO (apply gs1 gs2 (\ptr1 ptr2 -> teoverlay ptr1 ptr2 2))))) difference gs1 gs2 = (TePolygonSet (map toPolygon (unsafePerformIO (apply gs1 gs2 (\ptr1 ptr2 -> teoverlay ptr1 ptr2 1))))) difference gs1 gs2 = (TePolygonSet (map toPolygon (unsafePerformIO (apply gs1 gs2 (\ptr1 ptr2 -> teoverlay ptr1 ptr2 4))))) instance Set [TePolygon] where union p1 p2 = geos where (TePolygonSet geos) = union (TePolygonSet p1) (TePolygonSet p2) intersection a b = geos where (TePolygonSet geos) = intersection (TePolygonSet a) (TePolygonSet b) difference a b = geos where (TePolygonSet geos) = difference (TePolygonSet a) (TePolygonSet b) apply1 gs1 gs2 f = (new (TePolygonSet (map toPolygon1 gs1))) >>= \ps1 -> (new (TePolygonSet (map toPolygon1 gs2))) >>= \ps2 -> f ps1 ps2 >>= \geo -> polset2geoset geo >>= return where polset2geoset gs = size gs >>= (polygonset2geometryset gs 0) toPolygon1 (GPg pg) = pg apply gs1 gs2 f = (new gs1) >>= \ps1 -> (new gs2) >>= \ps2 -> f ps1 ps2 >>= \geo -> polset2geoset geo >>= return where polset2geoset gs = size gs >>= (polygonset2geometryset gs 0) foreign import stdcall unsafe "c_teoverlay" teoverlay :: TePolygonSetPtr -> TePolygonSetPtr -> Int -> Prelude.IO TePolygonSetPtr -- 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_tegeometryareabox" tegeometryareabox :: TeBoxPtr -> 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 foreign import stdcall unsafe "c_temakepolygon" temakepolygon :: TeBoxPtr -> Prelude.IO TePolygonPtr ------------ thales foreign import stdcall unsafe "c_tepolygon_rotate" tepolygon_rotate :: TePolygonPtr -> Double -> Prelude.IO TePolygonPtr foreign import stdcall unsafe "c_tepolygon_angle" tepolygon_angle :: TePolygonPtr -> Prelude.IO Double foreign import stdcall unsafe "c_tepolygon_radius" tepolygon_radius :: TePolygonPtr -> Prelude.IO Double foreign import stdcall unsafe "c_tepolygon_rectangularfit" tepolygon_rectangularfit :: TePolygonPtr -> Prelude.IO Double