Clip Rectangle To Rectangle
In this example, we're clipping the background rectangle to the foreground rectangle. This results in 16 possible layouts that the pair of rectangles can have in relation to each other. The goal is to output a list of areas that represent the visible portion of the background rectangle without overlapping any pixels
In this example, we're clipping the background rectangle to the foreground rectangle. This results in 16 possible layouts that the pair of rectangles can have in relation to each other. The goal is to output a list of areas that represent the visible portion of the background rectangle without overlapping any pixels
PlayBASIC Code:
; PROJECT : Clip Foreground Rectangle TO Background Rectangle ; AUTHOR : Kev Picone - https://PlayBASIC.com ; CREATED : 8/04/2023 ; EDITED : 9/04/2023 ; --------------------------------------------------------------------- loadfont "courier new",1, 40 Type tRect x1,y1 x2,y2 Colour EndType Dim Rects(16) as tRect Global RectCount =0 do Dim Back as tRect Pointer Back = new TRect w= rndrange(100,500) h= rndrange(100,500) X=rnd( getscreenwidth() * 0.60) Y=rnd(getscreenheight() * 0.60) Back.x1 = x Back.y1 = y Back.x2 = x+w Back.y2 = y+h Back.colour =rndrgb() Dim Front as tRect Pointer Front = new TRect W= 500 H= 150 // -------------------------------------------------------- Do // -------------------------------------------------------- cls $203040 Boxc Back.x1,Back.y1,Back.x2,Back.y2,true,Back.Colour Front.x1=mousex() Front.y1=mousey() Front.x2=Front.x1+W Front.y2=Front.y1+H box Front.x1,Front.y1,Front.x2,Front.y2,true inkmode 1+1024 Status =ClipRectangles(Front,Back) inkmode 1 for lp =0 to Status-1 X1=Rects(lp).x1 y1=Rects(lp).y1 x2=Rects(lp).x2 y2=Rects(lp).y2 boxc x1,y1,x2,y2,false, $00ff00 boxc x1+1,y1+1,x2-1,y2-1,false, $00ff00 s$ =" X1="+str$(X1) s$+=" Y1="+str$(Y1) s$+=" Y1="+str$(X2) s$+=" Y1="+str$(Y2) Print "#"+str$(lp)+s$ next if Status=-2 Print "Foreground covers background" endif if mousebutton()=2 w=rndrange(50,500) h=rndrange(50,350) endif sync // -------------------------------------------------------- loop spacekey() // -------------------------------------------------------- free front free back loop Function ClipRectangles(Front as tRect Pointer, Back as tRect Pointer) RectCount =0 Count = -1 if int(Front)=0 or int(Back)=0 then ExitFunction -1 // chec if the Front rect to the left or right of te back rect if Front.X2<Back.X1 then exitfunction Count if Front.X1>Back.X2 then exitfunction Count // check if the FRONT is ABOVE or BELLOW the BACK rect if Front.Y2<Back.Y1 then exitfunction Count if Front.Y1>Back.Y2 then exitfunction Count // Make bit pattern for what side each point is to its patern Layout = (Front.X1>=Back.X1 << 1)+ ( Front.X2>Back.X2) Layout =Layout<<2 Layout+= Front.Y1>=Back.Y1 << 1 Layout+= Front.Y2>Back.Y2 Filled =true static ThisRGB ThisRGB = -1 print bin$(Layout) Select LayOut // --------------------------------------------- case %0000 // --------------------------------------------- // front is covering back to left and // above and bellow back SetBox( Front.x2 ,Back.y1 ,back.x2 ,front.y2 , ThisRGB) SetBox( Back.x1 ,front.y2 ,back.x2 ,back.y2 , ThisRGB) // --------------------------------------------- case %0001 // --------------------------------------------- // front is covering back to left and // above and bellow back SetBox( Front.x2,Back.y1 ,back.x2 ,back.y2, ThisRGB ) // --------------------------------------------- case %0010 // --------------------------------------------- // top chunk SetBox( Back.x1,Back.y1 ,back.x2 , front.y1, ThisRGB ) // bottom chunk SetBox( Back.x1,front.y2 ,back.x2 , back.y2, ThisRGB ) // middle chuck to the right of the front rect SetBox( Front.x2,front.y1 ,back.x2 ,front.y2, ThisRGB ) // --------------------------------------------- case %0011 // --------------------------------------------- // The front rect is covering back rect SetBox( Back.x1,Back.y1 ,Back.x2 ,Front.y1, ThisRGB ) SetBox( front.x2,front.y1,back.x2,back.y2 ,ThisRGB ) // --------------------------------------------- case %0100 // --------------------------------------------- // visible left edge of back SetBox( Back.x1,front.y2 ,back.x2 ,back.y2, ThisRGB ) // --------------------------------------------- case %0101 // --------------------------------------------- // draw nothing// front overlaps backdrop exitfunction -2 // --------------------------------------------- case %0110 // --------------------------------------------- // Top SetBox( Back.x1,back.y1 ,back.x2 ,front.y1, ThisRGB ) // bottom SetBox( Back.x1,front.y2 ,back.x2 ,back.y2, ThisRGB ) // --------------------------------------------- case %0111 // --------------------------------------------- // visible left edge of back SetBox( Back.x1,back.y1 ,back.x2 ,front.y1, ThisRGB ) // --------------------------------------------- case %1000 // --------------------------------------------- // chunks of either side SetBox( Back.x1 ,Back.y1 ,front.x1 ,front.y2, ThisRGB ) SetBox( front.x2 ,Back.y1 ,back.x2 , front.y2, ThisRGB ) // bottom section SetBox( Back.x1 ,front.y2 ,back.x2 ,back.y2, ThisRGB ) // --------------------------------------------- case %1001 // --------------------------------------------- SetBox( Back.x1,Back.y1 ,front.x1 ,back.y2, ThisRGB ) SetBox( front.x2,Back.y1 ,back.x2 ,back.y2, ThisRGB ) // --------------------------------------------- case %1010 // --------------------------------------------- // front rect is inside the background rect // Top Chunk SetBox( Back.x1,Back.y1 ,back.x2 ,front.y1, ThisRGB ) // bottom SetBox( Back.x1,front.y2 ,back.x2 ,back.y2, ThisRGB ) // Left chunk SetBox( Back.x1,front.y1 ,front.x1 ,front.y2, ThisRGB ) // right chunk SetBox( front.x2,front.y1 ,back.x2 ,front.y2, ThisRGB ) // --------------------------------------------- case %1011 // --------------------------------------------- // top section SetBox( Back.x1,back.y1 ,back.x2 ,front.y1, ThisRGB ) // left and right blocks SetBox( Back.x1,front.y1 ,front.x1 ,back.y2, ThisRGB ) SetBox( front.x2,front.y1 ,back.x2 ,back.y2, ThisRGB ) // --------------------------------------------- case %1100 // --------------------------------------------- // visible left edge of back SetBox( Back.x1,Back.y1 ,front.x1 ,back.y2, ThisRGB ) // visible bottom strip of bacl SetBox( front.x1,front.y2 ,back.x2 ,back.y2, ThisRGB ) // --------------------------------------------- case %1101 // --------------------------------------------- // front is covering back to left and // above and bellow back SetBox( Back.x1,Back.y1 ,front.x1 ,back.y2, ThisRGB ) // --------------------------------------------- case %1110 // --------------------------------------------- // top part SetBox( Back.x1,Back.y1 ,Back.x2 ,Front.y1, ThisRGB ) // bottom part SetBox( Back.x1,front.y2 ,Back.x2 ,back.y2, ThisRGB ) // left hand box SetBox( Back.x1,front.y1 ,front.x1 ,Front.y2, ThisRGB ) // --------------------------------------------- case %1111 // --------------------------------------------- // The front rect is covering back rect SetBox( Back.x1,Back.y1 ,Back.x2 ,Front.y1, ThisRGB ) SetBox( Back.x1,front.y1,front.x1,back.y2 ,ThisRGB ) EndSelect Count=RectCount ThisRGB+=$112233 EndFunction Count function SetBox(X1,Y1,X2,Y2,Colour) if Rects(RectCount)=0 Rects(RectCount) = new tRect endif Rects(RectCount).x1=x1 Rects(RectCount).y1=y1 Rects(RectCount).x2=x2 Rects(RectCount).y2=y2 Rects(RectCount).Colour=Colour RectCount++ Boxc x1,y1,x2,y2,true,Colour EndFunction