module Geometry.Polyhedral where import Geometry.ConvexHull3 import Data.List import Data.Maybe import Data.Function -- | Given a vertex of a convex hull, computes the facets adjacent to the vertex. adjacentFacets :: Point3D -> ConvexHull -> [Facet] adjacentFacets p c = sortFacets p $ filter (isPointInFacet p) (facets c) -- | For each vertex of a polyhedron, the facets must be ordered clockwise since we need there normals to point inside the polyhedron isPointInFacet :: Point3D -> Facet -> Bool isPointInFacet p f = p `elem` fromFacet f -- | Checks if two facets are adjacent with respect to a vertex in counterclockwise orientation. areFacetsAdjacent :: Point3D -> Facet -> Facet -> Bool areFacetsAdjacent p f1 f2 | isJust edge1 && isJust edge2 = True | otherwise = False where edge1, edge2 :: Maybe Edge edge1 = find (\e -> (coordinates.snd.vertices) e == p) (edges f1) edge2 = find (\e -> (coordinates.fst.vertices) e == p) (edges f2) -- | The facets are ordered counterclockwise with respect to a vertex. [Optimizable] sortFacets :: Point3D -> [Facet] -> [Facet] sortFacets _ [a,b] = [a,b] sortFacets p (f:g:fs) | areFacetsAdjacent p f g = f:sortFacets p (g:fs) | otherwise = sortFacets p (f:fs)++[g] -- | Computes normal vector to a facet of the polyhedron with respect to a vertex. normalVector :: Vertex -> Facet -> Point3D normalVector v f = crossProduct vector1 vector2 where (v1,v2) = vertices.fromJust $ find (\e -> (fst.vertices) e == v) (edges f) (v3,v4) = vertices.fromJust $ find (\e -> (snd.vertices) e == v) (edges f) vector1 = ((-) `on` coordinates) v2 v1 vector2 = ((-) `on` coordinates) v3 v4 crossProduct :: Point3D -> Point3D -> Point3D crossProduct (x1,y1,z1) (x2,y2,z2) = (y1*z2-y2*z1,-(x1*z2-x2*z1),x1*y2-x2*y1) normalCone :: Vertex -> [Facet] -> [Point3D] normalCone v facets@(f:fs) = computeNormalCone normals where normals = map (normalVector v) (facets++[f]) computeNormalCone [v1,v2] = [crossProduct v1 v2] computeNormalCone (v1:v2:vs) = (crossProduct v1 v2):computeNormalCone (v2:vs) normalFan :: ConvexHull -> [[Point3D]] normalFan convexHull = normalFanPointsFacets (fromConvexHull convexHull) convexHull normalFanPointsFacets :: [Point3D] -> ConvexHull -> [[Point3D]] normalFanPointsFacets [] _ = [] normalFanPointsFacets (v:vs) convexHull = (normalCone (Vertex v) properFacets):normalFanPointsFacets vs convexHull where properFacets = adjacentFacets v convexHull isLowerFace :: Facet -> Bool isLowerFace facet = trd' normal < 0 where trd' (_,_,a) = a vertex = Vertex $ head $ fromFacet facet normal = normalVector vertex facet