How to resolve the algorithm Sutherland-Hodgman polygon clipping step by step in the Haskell programming language

Published on 7 June 2024 03:52 AM

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