link graphics procedure main() WOpen("size=600,600") DrawRectangle(100,100,400,400) DrawLine(75,300,125,300) DrawLine(550,480,480,550) DrawLine(550,440,480,510) DrawLine(75,400,125,550) Fg("red") clipSegment(75,300,125,300,100,100,400,400) clipSegment(550,480,480,550,100,100,400,400) clipSegment(550,440,480,510,100,100,400,400) clipSegment(75,400,125,550,100,100,400,400) Event() end record Point(x,y) # akin to Hill, Figure 3.21 procedure clipSegment(x1,y1, x2,y2, x,y,wd,ht) p1 := Point(x1,y1) p2 := Point(x2,y2) repeat { write("p1: ",p1.x,",",p1.y," p2: ",p2.x,",",p2.y) p1_inside := (x <= p1.x <= x+wd & y <= p1.y <= y+ht) | &null p2_inside := (x <= p2.x <= x+wd & y <= p2.y <= y+ht) | &null if \p1_inside & \p2_inside then { write("p1 inside,p2 inside") # draw the whole line, no clipping needed return DrawLine(p1.x,p1.y,p2.x,p2.y) } # else some clipping is actually needed. if p1.x < x & p2.x < x then return if p1.x > x+wd & p2.x > x+wd then return if p1.y < y & p2.y < y then return if p1.y > y+ht & p2.y > y+ht then return if /p1_inside then { # p1 not inside, fix p1 write("fixing p1, x=",p1.x,", y=",p1.y) fix(p1,p2,x,y,wd,ht) } else { # p2 not inside, fix p2 write("fixing p2, x=",p2.x,", y=",p2.y) fix(p2,p1,x,y,wd,ht) } } end procedure fix(p1,p2,x,y,wd,ht) if p1.x < x then { # p1 to the left, chop left edge dx := p2.x-p1.x dy := p2.y-p1.y m := real(dy)/dx p1.y := p1.y + (x-p1.x)*m p1.x := x } else if p1.x > x+wd then { # p1 to the right, chop right edge dx := p1.x-p2.x dy := p1.y-p2.y m := real(dy)/dx p1.y := p2.y + ((x+wd)-p2.x)*m p1.x := x+wd } else if p1.y < y then { # p1 above, chop against top edge dx := p2.x-p1.x dy := p2.y-p1.y m := real(dx)/dy p1.x := p1.x + (y-p1.y)*m p1.y := y } else if p1.y > y+ht then { # p1 below, chop against bottom edge dx := p1.x-p2.x dy := p1.y-p2.y m := real(dx)/dy p1.x := p1.x + ((y+ht)-p1.y)*m p1.y := y+ht } end