{-- 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.Algebras.Spatial 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.TerraLib.TeCoord2D 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 ) instance Centroid TeLinearRing TePoint where centroid l = (centroid (TePolygon [l])::(TePoint)) --------------------------------------- --------- metric operations --------- --------------------------------------- instance DistanceDirection TePoint where distance p1 p2 = tedistance p1 p2 instance Numeric TePolygon where area p = tearea p perimeter pol = telength (head (getlines pol) ) where getlines (TePolygon ls) = ls instance Numeric TeBox where area p = teareabox p instance Numeric TeLine2D where perimeter l = telength l --------------------------------------- --------- landscape metrics -- polygons --------------------------------------- density :: TePolygon -> Double density p = (area p) / (tepolygonradius p) circle :: TePolygon -> Double circle p = (1- (area p) / (pi * r * r) ) where r = (tepolygonradius p) compacity :: TePolygon -> Double compacity p = (perimeterAreaRatio p) / (sqrt (area p) ) shapeindex :: TePolygon -> Double shapeindex p = (perimeter p) / (4 * (sqrt (area p) ) ) perimeterAreaRatio :: TePolygon -> Double perimeterAreaRatio p = (perimeter p) / (area p) fractal :: TePolygon -> Double fractal p= d where d = (2 * (log (0.25 * (perimeter p) ) )) / (log ( area (p))) retangular :: TePolygon -> Double retangular p= d where d = (area p) / (area br) r = polygon_rotate 90 p br = polbox r -- 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 ) --- acessa funçoes do thales 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) -------------------------------- -- nao rotacionou os buracos polygon_rotate :: Double -> TePolygon -> TePolygon polygon_rotate angle pol = (TePolygon (map (line_rotate angle ) [ls]) ) where ls = (head (getLines pol)) line_rotate :: Double -> TeLinearRing -> TeLine2D line_rotate angle line = createLine ( map (point_rotate c angle) cs ) where cs = map (uncurry createPoint)(decompToCoords line) c = centroid line point_rotate :: TePoint -> Double -> TePoint -> TeCoord2D point_rotate center ang point = (x, y) where x = (getX center) + ( (getX diff) * cos(ang_rad) - (getY diff) * (sin ang_rad) ) y = (getY center) + ( (getX diff) * sin(ang_rad) + (getY diff) * (cos ang_rad) ) diff = point - center ang_rad = ang * (pi/180) 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 ccall unsafe "c_teoverlay" teoverlay :: TePolygonSetPtr -> TePolygonSetPtr -> Int -> Prelude.IO TePolygonSetPtr -- metrics operations ------------------------- foreign import ccall unsafe "c_tepoint_tedistance" tepoint_tedistance :: TePointPtr -> TePointPtr -> Prelude.IO Double foreign import ccall unsafe "c_telength" h_telength :: TeLine2DPtr -> Prelude.IO Double foreign import ccall unsafe "c_tegeometryarea" tegeometryarea :: TePolygonPtr -> Prelude.IO Double foreign import ccall unsafe "c_tegeometryareabox" tegeometryareabox :: TeBoxPtr -> Prelude.IO Double foreign import ccall unsafe "c_tepointset_tefindcentroid" tepointset_tefindcentroid :: TePointSetPtr -> Prelude.IO TePointPtr foreign import ccall unsafe "c_tepolygonset_tefindcentroid" tepolygonset_tefindcentroid :: TePolygonSetPtr -> Prelude.IO TePointPtr foreign import ccall unsafe "c_telineset_tefindcentroid" telineset_tefindcentroid :: TeLineSetPtr -> Prelude.IO TePointPtr foreign import ccall unsafe "c_tepolygon_tefindcentroid" tepolygon_tefindcentroid :: TePolygonPtr -> Prelude.IO TePointPtr foreign import ccall unsafe "c_set_precision" setPrecision :: Double -> Prelude.IO () foreign import ccall unsafe "c_tebufferregion" h_tebufferregion :: TePolygonPtr -> Double -> Int -> Prelude.IO TePolygonSetPtr foreign import ccall unsafe "c_temakepolygon" temakepolygon :: TeBoxPtr -> Prelude.IO TePolygonPtr ------------ thales foreign import ccall unsafe "c_tepolygon_rotate" tepolygon_rotate :: TePolygonPtr -> Double -> Prelude.IO TePolygonPtr foreign import ccall unsafe "c_tepolygon_angle" tepolygon_angle :: TePolygonPtr -> Prelude.IO Double foreign import ccall unsafe "c_tepolygon_radius" tepolygon_radius :: TePolygonPtr -> Prelude.IO Double foreign import ccall unsafe "c_tepolygon_rectangularfit" tepolygon_rectangularfit :: TePolygonPtr -> Prelude.IO Double