How to resolve the algorithm Sutherland-Hodgman polygon clipping step by step in the Haskell programming language
How to resolve the algorithm Sutherland-Hodgman polygon clipping step by step in the Haskell programming language
Table of Contents
Problem Statement
The Sutherland-Hodgman clipping algorithm finds the polygon that is the intersection between an arbitrary polygon (the “subject polygon”) and a convex polygon (the “clip polygon”). It is used in computer graphics (especially 2D graphics) to reduce the complexity of a scene being displayed by eliminating parts of a polygon that do not need to be displayed.
Take the closed polygon defined by the points: and clip it by the rectangle defined by the points: Print the sequence of points that define the resulting clipped polygon.
Display all three polygons on a graphical surface, using a different color for each polygon and filling the resulting polygon. (When displaying you may use either a north-west or a south-west origin, whichever is more convenient for your display mechanism.)
Let's start with the solution:
Step by Step solution about How to resolve the algorithm Sutherland-Hodgman polygon clipping step by step in the Haskell programming language
The code snippet implements the Sutherland-Hodgman algorithm for clipping polygons.
The algorithm takes a target polygon and a clipping polygon as input and returns the intersection of the two polygons.
The clipping polygon is assumed to be convex.
The algorithm works by intersecting the target polygon with each edge of the clipping polygon in turn.
The intersection of two lines is computed using the ><
function, which uses the formula for the intersection of two lines in parametric form.
The -
operator is used to intersect a line segment with a halfspace defined by a line.
The -|
function computes the intersection of a line segment with the left halfspace of a clipping line.
The -|<
function computes the intersection of a polygon with the left halfspace of a clipping line.
The clipTo
function is the main function of the code snippet.
It takes a target polygon and a clipping polygon as input and returns the intersection of the two polygons.
The main
function sets up a window and draws the target polygon, the clipping polygon, and the intersection of the two polygons.
Source code in the haskell programming language
module SuthHodgClip (clipTo) where
import Data.List
type Pt a = (a, a)
type Ln a = (Pt a, Pt a)
type Poly a = [Pt a]
-- Return a polygon from a list of points.
polyFrom ps = last ps : ps
-- Return a list of lines from a list of points.
linesFrom pps@(_:ps) = zip pps ps
-- Return true if the point (x,y) is on or to the left of the oriented line
-- defined by (px,py) and (qx,qy).
(.|) :: (Num a, Ord a) => Pt a -> Ln a -> Bool
(x,y) .| ((px,py),(qx,qy)) = (qx-px)*(y-py) >= (qy-py)*(x-px)
-- Return the intersection of two lines.
(><) :: Fractional a => Ln a -> Ln a -> Pt a
((x1,y1),(x2,y2)) >< ((x3,y3),(x4,y4)) =
let (r,s) = (x1*y2-y1*x2, x3*y4-y3*x4)
(t,u,v,w) = (x1-x2, y3-y4, y1-y2, x3-x4)
d = t*u-v*w
in ((r*w-t*s)/d, (r*u-v*s)/d)
-- Intersect the line segment (p0,p1) with the clipping line's left halfspace,
-- returning the point closest to p1. In the special case where p0 lies outside
-- the halfspace and p1 lies inside we return both the intersection point and
-- p1. This ensures we will have the necessary segment along the clipping line.
(-|) :: (Fractional a, Ord a) => Ln a -> Ln a -> [Pt a]
ln@(p0, p1) -| clipLn =
case (p0 .| clipLn, p1 .| clipLn) of
(False, False) -> []
(False, True) -> [isect, p1]
(True, False) -> [isect]
(True, True) -> [p1]
where isect = ln >< clipLn
-- Intersect the polygon with the clipping line's left halfspace.
(<|) :: (Fractional a, Ord a) => Poly a -> Ln a -> Poly a
poly <| clipLn = polyFrom $ concatMap (-| clipLn) (linesFrom poly)
-- Intersect a target polygon with a clipping polygon. The latter is assumed to
-- be convex.
clipTo :: (Fractional a, Ord a) => [Pt a] -> [Pt a] -> [Pt a]
targPts `clipTo` clipPts =
let targPoly = polyFrom targPts
clipLines = linesFrom (polyFrom clipPts)
in foldl' (<|) targPoly clipLines
import Graphics.HGL
import SuthHodgClip
targPts = [( 50,150), (200, 50), (350,150), (350,300), (250,300),
(200,250), (150,350), (100,250), (100,200)] :: [(Float,Float)]
clipPts = [(100,100), (300,100), (300,300), (100,300)] :: [(Float,Float)]
toInts = map (\(a,b) -> (round a, round b))
complete xs = last xs : xs
drawSolid w c = drawInWindow w . withRGB c . polygon
drawLines w p = drawInWindow w . withPen p . polyline . toInts . complete
blue = RGB 0x99 0x99 0xff
green = RGB 0x99 0xff 0x99
pink = RGB 0xff 0x99 0x99
white = RGB 0xff 0xff 0xff
main = do
let resPts = targPts `clipTo` clipPts
sz = 400
win = [(0,0), (sz,0), (sz,sz), (0,sz)]
runWindow "Sutherland-Hodgman Polygon Clipping" (sz,sz) $ \w -> do
print $ toInts resPts
penB <- createPen Solid 3 blue
penP <- createPen Solid 5 pink
drawSolid w white win
drawLines w penB targPts
drawLines w penP clipPts
drawSolid w green $ toInts resPts
getKey w
You may also check:How to resolve the algorithm Entropy step by step in the Ada programming language
You may also check:How to resolve the algorithm Strip comments from a string step by step in the Red programming language
You may also check:How to resolve the algorithm Currying step by step in the TXR programming language
You may also check:How to resolve the algorithm Variable size/Get step by step in the Delphi programming language
You may also check:How to resolve the algorithm Hello world/Text step by step in the Clipper programming language