Überlappende Rechtecke in nicht mehr überlappende zerlegen

Übersicht BlitzBasic Codearchiv

Neue Antwort erstellen

 

walski

Ehemaliger Admin

Betreff: Überlappende Rechtecke in nicht mehr überlappende zerlegen

BeitragSo, Feb 22, 2004 18:29
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich habe dafür recht lang gebraucht, was aber wahrscheinlich eher an einer gesteigerten Dummheit meinerseits, als an einem komplexen Problem ansich liegen dürfte Smile

Aber naja, da das Niveau hier ja eh nicht allzu hoch ist, poste ich es trotzdem mal.
Die Ausgangsposition war folgende:
Man hat mehrere Rechtecke die sich überschneiden und diese sollen nun in mehrere Rechtecke zerlegt werden, die sich nicht mehr überschneiden.

Das ist zum Beispiel gut, wenn man die Fläche von solch einer "Rechteck Menge" errechnen will, ohne die überlappenden Flächen eben 2,3,4 oder 5 mal zu berechnen.

Meine Lösung ist nicht sehr sauber, nicht sehr kommentier und schon gar nicht optimiert! Es entstehen VIEL zu viele Rechtecke, aber ich hatte keine Lust mehr den Schreibkram zu machen und mir langt es so.
Wenn es dennoch jemand optimeirt, wäre ich super dankbar!

Hier jetz aber der (wie gesagt, miserabel kommentierte) Code:
Code: [AUSKLAPPEN]

; just a tiny RectIntersection Demo
; (c) 2004 by walski

;Rect Type construct
Type Ground
   Field x,y
   Field width,height
End Type

;SAMPLE
Const screen_w = 800, screen_h = 600, screen_d = 32, screen_m = 2

Graphics screen_w,screen_h,screen_d,screen_m
SetBuffer BackBuffer()


timer = CreateTimer(100)
SeedRnd MilliSecs()

DragMode = 0
While Not KeyHit(1)
   Cls
   If DragMode Then
      If Not MouseDown(1)
         GroundSpace.Ground = New Ground
            mX = MouseX()
            mY = MouseY()
            If RBx < mX Then
               GroundSpace\width = mX - RBx
               GroundSpace\x = RBx
            Else
               GroundSpace\width = RBx - mX
               GroundSpace\x = mX               
            EndIf
            If RBy < mY Then
               GroundSpace\height = mY - RBy
               GroundSpace\y = RBy               
            Else
               GroundSpace\height = RBy - mY               
               GroundSpace\y = mY
            EndIf

         DragMode = 0
      Else
         Rect2 RBx,RBy,MouseX() - RBx,MouseY() - RBy,0
      EndIf
   Else
      If MouseDown(1)
         DragMode = 1
         RBx = MouseX()
         RBy = MouseY()
      EndIf
   EndIf
   DrawGround()
   DoIntersection()
   Flip()
Wend
;SAMPLE END

;Draw any Rect
Function DrawGround()
   For GroundSpace.ground = Each Ground
      Rect2 GroundSpace\x,GroundSpace\y,GroundSpace\width,GroundSpace\height,1
   Next
   Text 10,10,i
End Function

;This is detecting overlaps on any rect and then intersect the specific rect until there are no more overlaps
Function DoIntersection()
   ;Outer Loop
   OuterSpace.Ground = First Ground
   For OuterSpace.Ground = Each Ground
      ;Inner Loop
      InnerSpace.Ground = First Ground
      For InnerSpace.Ground = Each Ground
         If InnerSpace <> OuterSpace And RectsOverlap(OuterSpace\x,OuterSpace\y,OuterSpace\width,OuterSpace\height,InnerSpace\x,InnerSpace\y,InnerSpace\width,InnerSpace\height) Then
            ;Setting the point of intersection coordinates
            If OuterSpace\x > InnerSpace\x Then
               SPx = OuterSpace\x
               If InnerSpace\x + InnerSpace\width <= OuterSpace\x + OuterSpace\width Then
                  SPwidth = (InnerSpace\x + InnerSpace\width) - OuterSpace\x
               Else
                  SPwidth = InnerSpace\width
                  If SPx + SPwidth > OuterSpace\x + OuterSpace\width Then
                     SPwidth = OuterSpace\x + OuterSpace\width - SPx
                  EndIf
               EndIf
            Else
               SPx = InnerSpace\x
               If (InnerSpace\x + InnerSpace\width) >= (OuterSpace\x + OuterSpace\width) Then
                  SPwidth = (OuterSpace\x + OuterSpace\width) - InnerSpace\x
               Else
                  SPwidth = InnerSpace\width
               EndIf
            EndIf
            If OuterSpace\y > InnerSpace\y Then
               SPy = OuterSpace\y
               If (InnerSpace\y + InnerSpace\height) >= (OuterSpace\y + OuterSpace\height) Then
                  SPheight = (InnerSpace\y + InnerSpace\height) - OuterSpace\y
                  If SPy + SPheight > OuterSpace\y + OuterSpace\height Then
                     SPheight = (OuterSpace\y + OuterSpace\height) - SPy
                  EndIf
               Else
                  SPheight = InnerSpace\y + InnerSpace\height - SPy
               EndIf
            Else
               SPy = InnerSpace\y
               If (InnerSpace\y + InnerSpace\height) >= (OuterSpace\y + OuterSpace\height) Then
                  SPheight = (OuterSpace\y + OuterSpace\height) - InnerSpace\y
                  If SPy + SPheight > OuterSpace\y + OuterSpace\height Then
                     SPheight = (OuterSpace\y + OuterSpace\height) - SPy
                  EndIf
               Else
                  SPheight = InnerSpace\height
               EndIf
            EndIf
            ;Debug Mode
            If DebugMode Then
               Color 255,0,0
               Rect OuterSpace\x,OuterSpace\y,OuterSpace\width,OuterSpace\height,1
               Color 0,0,255
               Rect InnerSpace\x,InnerSpace\y,InnerSpace\width,InnerSpace\height,1
               Color 0,255,0
               Rect SPx,SPy,SPwidth,SPheight,1
               Flip()
               Repeat
               Until MouseHit(2)
               Color 255,255,255
            EndIf
            ;Intersect the current collision
            IntersectRect OuterSpace,SPx,SPy,SPwidth,SPheight
            ;Jump to the next "Outer Rect" because the current one was deleted by the Intersect Routine
            Goto Begin
         EndIf
      Next
      .Begin
   Next
End Function

;This function intersects an specific rect. R2 gives the data of the "overlapped area"
Function IntersectRect(R1.Ground,R2x,R2y,R2w,R2h)
   If (R2x > R1\x) Then
      NewSpace.Ground = New Ground
         NewSpace\x = R1\x
         NewSpace\y = R1\y
         NewSpace\width = R2x - R1\x
         NewSpace\height = R1\height
   EndIf
   If (R2x + R2w < R1\x + R1\width) Then
      NewSpace.Ground = New Ground
         NewSpace\x = R2x + R2w
         NewSpace\y = R1\y
         NewSpace\width = (R1\x + R1\width) - (R2x + R2w)
         NewSpace\height = R1\height
   EndIf
   If (R2y > R1\y) Then
      NewSpace.Ground = New Ground
         NewSpace\x = R2x
         NewSpace\y = R1\y
         NewSpace\width = R2w
         NewSpace\height = R2y - R1\y
   EndIf
   If (R2y + R2h) < (R1\y + R1\height) Then
      NewSpace.Ground = New Ground
         NewSpace\x = R2x
         NewSpace\y = R2y + R2h
         NewSpace\width = R2w
         NewSpace\height = (R1\y + R1\height) - (R2y + R2h)
   EndIf
   Delete R1
End Function

;This function corrects the problem with negative widths and heights while using rect
Function Rect2(x,y,width,height,solid=0)
   If width < 0 Then
      x = x + width
      width = Abs(width)
   EndIf
   If height < 0 Then
      y = y + height
      height = Abs(height)
   EndIf
   Rect x,y,width,height,solid
End Function


walski
buh!

Neue Antwort erstellen


Übersicht BlitzBasic Codearchiv

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group