Split C4Rect out to its own source file

Because much more depends on C4Rect than only C4Shape, and C4Shape uses
lots of other stuff.

Also move some other files which depend on C4Group to src/c4group, because
I'm editing the build files anyway.
Günther Brammer 2009-08-14 01:46:32 +02:00
parent 52fe574835
commit b46f4696e9
11 changed files with 435 additions and 372 deletions

View File

@ -18,12 +18,16 @@ set(OC_CLONK_SOURCES
src/C4GraphicsSystem.cpp
src/C4GraphicsSystem.h
src/c4group/C4Components.h
src/c4group/C4ComponentHost.cpp
src/c4group/C4ComponentHost.h
src/c4group/C4Extra.cpp
src/c4group/C4Extra.h
src/c4group/C4Group.cpp
src/c4group/C4Group.h
src/c4group/C4GroupSet.cpp
src/c4group/C4GroupSet.h
src/c4group/C4LangStringTable.cpp
src/c4group/C4LangStringTable.h
src/c4group/C4Language.cpp
src/c4group/C4Language.h
src/c4group/C4Update.cpp
@ -217,12 +221,8 @@ set(OC_CLONK_SOURCES
src/gui/C4UserMessages.h
src/gui/C4Viewport.cpp
src/gui/C4Viewport.h
src/lib/C4ComponentHost.cpp
src/lib/C4ComponentHost.h
src/lib/C4InputValidation.cpp
src/lib/C4InputValidation.h
src/lib/C4LangStringTable.cpp
src/lib/C4LangStringTable.h
src/lib/C4LogBuf.cpp
src/lib/C4LogBuf.h
src/lib/C4Log.cpp
@ -231,6 +231,8 @@ set(OC_CLONK_SOURCES
src/lib/C4NameList.h
src/lib/C4Random.cpp
src/lib/C4Random.h
src/lib/C4Rect.cpp
src/lib/C4Rect.h
src/lib/C4RTF.cpp
src/lib/C4RTF.H
src/lib/C4Stat.cpp

View File

@ -17,6 +17,8 @@ bin_PROGRAMS = clonk
EXTRA_PROGRAMS = tstc4netio puncher c4group gunzip4c4group
noinst_LIBRARIES = lib.a
# Some defines and warning options
if RECENT_GCC
GCC_FLAGS = -pipe
@ -83,7 +85,56 @@ WARNING_FLAGS += -Winvalid-pch
endif
lib_a_SOURCES = \
src/lib/C4InputValidation.cpp \
src/lib/C4InputValidation.h \
src/lib/C4LogBuf.cpp \
src/lib/C4LogBuf.h \
src/lib/C4Random.cpp \
src/lib/C4Random.h \
src/lib/C4Rect.cpp \
src/lib/C4Rect.h \
src/lib/C4RTF.cpp \
src/lib/C4RTF.H \
src/lib/C4Stat.cpp \
src/lib/C4Stat.h \
src/lib/Fixed.cpp \
src/lib/Fixed.h \
src/lib/PathFinder.cpp \
src/lib/PathFinder.h \
src/lib/Standard.cpp \
src/lib/Standard.h \
src/lib/StdAdaptors.h \
src/lib/StdBase64.cpp \
src/lib/StdBase64.h \
src/lib/StdBuf.cpp \
src/lib/StdBuf.h \
src/lib/StdColors.h \
src/lib/StdCompiler.cpp \
src/lib/StdCompiler.h \
src/lib/StdMarkup.cpp \
src/lib/StdMarkup.h \
src/lib/StdResStr2.cpp \
src/lib/StdResStr2.h \
src/lib/StdResStr.h \
src/lib/texture/C4Facet.cpp \
src/lib/texture/C4FacetEx.cpp \
src/lib/texture/C4FacetEx.h \
src/lib/texture/C4Facet.h \
src/lib/texture/C4Surface.cpp \
src/lib/texture/C4SurfaceFile.cpp \
src/lib/texture/C4SurfaceFile.h \
src/lib/texture/C4Surface.h \
src/lib/texture/StdPNG.cpp \
src/lib/texture/StdPNG.h
clonk_SOURCES = \
src/lib/C4Log.cpp \
src/lib/C4Log.h \
src/lib/C4NameList.cpp \
src/lib/C4NameList.h \
src/lib/texture/C4GraphicsResource.cpp \
src/lib/texture/C4GraphicsResource.h \
src/C4Application.cpp \
src/C4Application.h \
src/C4FullScreen.cpp \
@ -92,7 +143,11 @@ src/C4Game.cpp \
src/C4Game.h \
src/C4GraphicsSystem.cpp \
src/C4GraphicsSystem.h \
src/c4group/C4LangStringTable.cpp \
src/c4group/C4LangStringTable.h \
src/c4group/C4Components.h \
src/c4group/C4ComponentHost.cpp \
src/c4group/C4ComponentHost.h \
src/c4group/C4Extra.cpp \
src/c4group/C4Extra.h \
src/c4group/C4Group.cpp \
@ -292,55 +347,6 @@ src/gui/C4UpperBoard.h \
src/gui/C4UserMessages.h \
src/gui/C4Viewport.cpp \
src/gui/C4Viewport.h \
src/lib/C4ComponentHost.cpp \
src/lib/C4ComponentHost.h \
src/lib/C4InputValidation.cpp \
src/lib/C4InputValidation.h \
src/lib/C4LangStringTable.cpp \
src/lib/C4LangStringTable.h \
src/lib/C4LogBuf.cpp \
src/lib/C4LogBuf.h \
src/lib/C4Log.cpp \
src/lib/C4Log.h \
src/lib/C4NameList.cpp \
src/lib/C4NameList.h \
src/lib/C4Random.cpp \
src/lib/C4Random.h \
src/lib/C4RTF.cpp \
src/lib/C4RTF.H \
src/lib/C4Stat.cpp \
src/lib/C4Stat.h \
src/lib/Fixed.cpp \
src/lib/Fixed.h \
src/lib/PathFinder.cpp \
src/lib/PathFinder.h \
src/lib/Standard.cpp \
src/lib/Standard.h \
src/lib/StdAdaptors.h \
src/lib/StdBase64.cpp \
src/lib/StdBase64.h \
src/lib/StdBuf.cpp \
src/lib/StdBuf.h \
src/lib/StdColors.h \
src/lib/StdCompiler.cpp \
src/lib/StdCompiler.h \
src/lib/StdMarkup.cpp \
src/lib/StdMarkup.h \
src/lib/StdResStr2.cpp \
src/lib/StdResStr2.h \
src/lib/StdResStr.h \
src/lib/texture/C4Facet.cpp \
src/lib/texture/C4FacetEx.cpp \
src/lib/texture/C4FacetEx.h \
src/lib/texture/C4Facet.h \
src/lib/texture/C4GraphicsResource.cpp \
src/lib/texture/C4GraphicsResource.h \
src/lib/texture/C4Surface.cpp \
src/lib/texture/C4SurfaceFile.cpp \
src/lib/texture/C4SurfaceFile.h \
src/lib/texture/C4Surface.h \
src/lib/texture/StdPNG.cpp \
src/lib/texture/StdPNG.h \
src/network/C4Client.cpp \
src/network/C4Client.h \
src/network/C4GameControlNetwork.cpp \
@ -483,6 +489,7 @@ clonk_SOURCES += src/platform/StdGtkWindow.cpp src/platform/StdGtkWindow.h
endif
clonk_LDADD = \
lib.a \
$(LIBICONV) \
$(GTK_LIBS) \
$(FREETYPE_LIBS) \

View File

@ -21,6 +21,7 @@
#include "C4Include.h"
#include "C4LangStringTable.h"
#include "C4InputValidation.h"
struct C4StringTableEntry
{

View File

@ -50,152 +50,6 @@ C4Shape::C4Shape()
Default();
}
void C4Rect::Default()
{
x=y=Wdt=Hgt=0;
}
void C4Rect::CompileFunc(StdCompiler *pComp)
{
pComp->Value(mkDefaultAdapt(x, 0)); pComp->Seperator();
pComp->Value(mkDefaultAdapt(y, 0)); pComp->Seperator();
pComp->Value(mkDefaultAdapt(Wdt, 0)); pComp->Seperator();
pComp->Value(mkDefaultAdapt(Hgt, 0));
}
void C4TargetRect::Default()
{
C4Rect::Default();
tx=ty=0;
}
void C4TargetRect::Set(int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt, int32_t iTX, int32_t iTY)
{
C4Rect::Set(iX,iY,iWdt,iHgt);
tx=iTX; ty=iTY;
}
bool C4TargetRect::ClipBy(C4TargetRect &rClip)
{
int32_t d;
// clip left
if ((d = x - rClip.x) < 0) { Wdt += d; x = rClip.x; } else tx += d;
// clip top
if ((d = y - rClip.y) < 0) { Hgt += d; y = rClip.y; } else ty += d;
// clip right
if ((d = (x+Wdt - rClip.x-rClip.Wdt)) > 0) Wdt -= d;
// clip bottom
if ((d = (y+Hgt - rClip.y-rClip.Hgt)) > 0) Hgt -= d;
// check validity
if (Wdt <= 0 || Hgt <= 0) return false;
// add target pos
tx += rClip.tx;
ty += rClip.ty;
// done
return true;
}
void C4TargetRect::Set(const C4TargetFacet &rSrc)
{
// copy members
x=rSrc.X; y=rSrc.Y; Wdt=rSrc.Wdt; Hgt=rSrc.Hgt; tx=rSrc.TargetX; ty=rSrc.TargetY;
}
void C4TargetRect::CompileFunc(StdCompiler *pComp)
{
C4Rect::CompileFunc(pComp); pComp->Seperator();
pComp->Value(mkDefaultAdapt(tx,0)); pComp->Seperator();
pComp->Value(mkDefaultAdapt(ty,0));
}
void C4Rect::Set(int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt)
{
x=iX; y=iY; Wdt=iWdt; Hgt=iHgt;
}
BOOL C4Rect::Overlap(C4Rect &rTarget)
{
if (x+Wdt<=rTarget.x) return FALSE;
if (x>=rTarget.x+rTarget.Wdt) return FALSE;
if (y+Hgt<=rTarget.y) return FALSE;
if (y>=rTarget.y+rTarget.Hgt) return FALSE;
return TRUE;
}
void C4Rect::Intersect(const C4Rect &r2)
{
// Narrow bounds
if (r2.x > x)
if (r2.x + r2.Wdt < x + Wdt)
{ x = r2.x; Wdt = r2.Wdt; }
else
{ Wdt -= (r2.x - x); x = r2.x; }
else
if (r2.x + r2.Wdt < x + Wdt)
Wdt = r2.x + r2.Wdt - x;
if (r2.y > y)
if (r2.y + r2.Hgt < y + Hgt)
{ y = r2.y; Hgt = r2.Hgt; }
else
{ Hgt -= (r2.y - y); y = r2.y; }
else
if (r2.y + r2.Hgt < y + Hgt)
Hgt = r2.y + r2.Hgt - y;
// Degenerated? Will happen when the two rects don't overlap
if (Wdt < 0) Wdt = 0;
if (Hgt < 0) Hgt = 0;
}
bool C4Rect::IntersectsLine(int32_t iX, int32_t iY, int32_t iX2, int32_t iY2)
{
// Easy cases first
if(Contains(iX, iY)) return true;
if(Contains(iX2, iY2)) return true;
if(iX < x && iX2 < x) return false;
if(iY < y && iY2 < y) return false;
if(iX >= x+Wdt && iX2 >= x+Wdt) return false;
if(iY >= y+Hgt && iY2 >= y+Hgt) return false;
// check some special cases
if (iX == iX2 || iY == iY2) return true;
// Check intersection left/right
int32_t iXI, iYI;
iXI = (iX < x ? x : x+Wdt);
iYI = iY + (iY2 - iY) * (iXI - iX) / (iX2 - iX);
if(iYI >= y && iYI < y+Hgt) return true;
// Check intersection up/down
iYI = (iY < y ? y : y+Hgt);
iXI = iX + (iX2 - iX) * (iYI - iY) / (iY2 - iY);
return iXI >= x && iXI < x+Wdt;
}
void C4Rect::Add(const C4Rect &r2)
{
// Null? Don't do anything
if (!r2.Wdt || !r2.Hgt) return;
if (!Wdt || !Hgt)
{
*this = r2;
return;
}
// Expand bounds
if (r2.x < x)
if (r2.x + r2.Wdt > x + Wdt)
{ x = r2.x; Wdt = r2.Wdt; }
else
{ Wdt += (x - r2.x); x = r2.x; }
else
if (r2.x + r2.Wdt > x + Wdt)
Wdt = r2.x + r2.Wdt - x;
if (r2.y < y)
if (r2.y + r2.Hgt > y + Hgt)
{ y = r2.y; Hgt = r2.Hgt; }
else
{ Hgt += (y - r2.y); y = r2.y; }
else
if (r2.y + r2.Hgt > y + Hgt)
Hgt = r2.y + r2.Hgt - y;
}
void C4Shape::Clear()
{
ZeroMem(this, sizeof (C4Shape));
@ -679,95 +533,3 @@ void C4Shape::CompileFunc(StdCompiler *pComp, bool fRuntime)
pComp->Value(mkNamingAdapt( iAttachVtx, "AttachVtx", 0 ));
}
}
// ---- C4RectList ----
void C4RectList::ClipByRect(const C4Rect &rClip)
{
// split up all rectangles
for (int32_t i = 0; i < GetCount(); ++i)
{
C4Rect *pTarget = &Get(i);
// any overlap?
if (rClip.x+rClip.Wdt <= pTarget->x) continue;
if (rClip.y+rClip.Hgt <= pTarget->y) continue;
if (rClip.x >= pTarget->x+pTarget->Wdt) continue;
if (rClip.y >= pTarget->y+pTarget->Hgt) continue;
// okay; split up rectangle
// first split will just reduce the target rectangle size
// if more splits are done, additional rectangles need to be added
int32_t iSplitCount = 0, iOver; C4Rect rcThis(*pTarget);
// clipped by right side
if ((iOver=rcThis.x+rcThis.Wdt-rClip.x-rClip.Wdt)>0)
{
pTarget->x += pTarget->Wdt - iOver; pTarget->Wdt = iOver; rcThis.Wdt -= iOver;
++iSplitCount;
}
// clipped by obttom side
if ((iOver=rcThis.y+rcThis.Hgt-rClip.y-rClip.Hgt)>0)
{
if (iSplitCount) { AddRect(rcThis); pTarget = &Get(GetCount()-1); }
pTarget->y += pTarget->Hgt - iOver; pTarget->Hgt = iOver; rcThis.Hgt -= iOver;
++iSplitCount;
}
// clipped by left side
if ((iOver=rClip.x-rcThis.x)>0)
{
if (iSplitCount) { AddRect(rcThis); pTarget = &Get(GetCount()-1); }
pTarget->Wdt = iOver; rcThis.Wdt -= iOver; rcThis.x = rClip.x;
++iSplitCount;
}
// clipped by top side
if ((iOver=rClip.y-rcThis.y)>0)
{
if (iSplitCount) { AddRect(rcThis); pTarget = &Get(GetCount()-1); } else ++iSplitCount;
pTarget->Hgt = iOver; /* rcThis.Hgt -= iOver; rcThis.y = rClip.y; not needed, since rcThis is no longer used */
}
// nothing split? This means this rectnagle is completely contained
if (!iSplitCount)
{
// make it vanish
RemoveIndexedRect(i); --i;
}
}
// concat rectangles if possible
bool fDone = false;
while (!fDone)
{
fDone=true;
for (int32_t i = 0, cnt=GetCount(); i < cnt && fDone; ++i)
{
C4Rect &rc1 = Get(i);
for (int32_t j = i+1; j < cnt; ++j)
{
C4Rect &rc2 = Get(j);
if (rc1.y == rc2.y && rc1.Hgt == rc2.Hgt)
{
if (rc1.x + rc1.Wdt == rc2.x)
{
rc1.Wdt += rc2.Wdt; RemoveIndexedRect(j); fDone=false; break;
}
else if (rc2.x + rc2.Wdt == rc1.x)
{
rc2.Wdt += rc1.Wdt; RemoveIndexedRect(i); fDone=false; break;
}
}
else if (rc1.x == rc2.x && rc1.Wdt == rc2.Wdt)
{
if (rc1.y + rc1.Hgt == rc2.y)
{
rc1.Hgt += rc2.Hgt; RemoveIndexedRect(j); fDone=false; break;
}
else if (rc2.y + rc2.Hgt == rc1.y)
{
rc2.Hgt += rc1.Hgt; RemoveIndexedRect(i); fDone=false; break;
}
}
}
}
}
}

View File

@ -26,71 +26,10 @@
#include "C4FacetEx.h"
#include "C4Constants.h"
#include "C4Rect.h"
#define C4D_VertexCpyPos (C4D_MaxVertex/2)
class C4Rect
{
public:
int32_t x,y,Wdt,Hgt;
public:
void Set(int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt);
void Default();
BOOL Overlap(C4Rect &rTarget);
void Intersect(const C4Rect &r2);
void Add(const C4Rect &r2);
bool operator ==(const C4Rect &r2) { return !((x-r2.x) | (y-r2.y) | (Wdt-r2.Wdt) | (Hgt-r2.Hgt)); }
bool operator !=(const C4Rect &r2) { return 0 != ((x-r2.x) | (y-r2.y) | (Wdt-r2.Wdt) | (Hgt-r2.Hgt)); }
bool Contains(int32_t iX, int32_t iY)
{ return iX>=x && iX<x+Wdt && iY>=y && iY<y+Hgt; }
bool Contains(int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt)
{ return iX>=x && iX+iWdt<x+Wdt && iY>=y && iY+iHgt<y+Hgt; }
bool Contains(const C4Rect &rect)
{ return Contains(rect.x, rect.y, rect.Wdt, rect.Hgt); }
bool IntersectsLine(int32_t iX, int32_t iY, int32_t iX2, int32_t iY2);
void Normalize()
{ if(Wdt < 0) { x+=Wdt+1; Wdt=-Wdt; } if(Hgt < 0) { y+=Hgt+1; Hgt=-Hgt; } }
void Enlarge(int32_t iBy)
{ x -= iBy; y -= iBy; Wdt += 2*iBy; Hgt += 2*iBy; }
int32_t GetMiddleX() { return x+Wdt/2; }
int32_t GetMiddleY() { return y+Hgt/2; }
int32_t GetBottom() { return y+Hgt; }
C4Rect(int32_t tx, int32_t ty, int32_t twdt, int32_t thgt) // ctor
{ x=tx; y=ty; Wdt=twdt; Hgt=thgt; }
C4Rect() { } // default ctor; doesn't initialize
C4Rect(const FLOAT_RECT &rcfOuter) // set to surround floating point rectangle
{ x=static_cast<int32_t>(rcfOuter.left); y=static_cast<int32_t>(rcfOuter.top);
Wdt=static_cast<int32_t>(ceilf(rcfOuter.right)-floorf(rcfOuter.left));
Hgt=static_cast<int32_t>(ceilf(rcfOuter.bottom)-floorf(rcfOuter.top)); }
void CompileFunc(StdCompiler *pComp);
};
class C4TargetRect: public C4Rect
{
public:
int32_t tx,ty;
public:
C4TargetRect(int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt, int32_t iTX, int32_t iTY)
: C4Rect(iX, iY, iWdt, iHgt), tx(iTX), ty(iTY) { }
C4TargetRect() { } // default ctor; doesn't initialize
void Set(int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt, int32_t iTX, int32_t iTY);
void Default();
bool ClipBy(C4TargetRect &rClip); // clip this rectangle by the given one (adding target positions) - return false if they don't overlap
void Set(const C4TargetFacet &rSrc); // copy contents from facet
void CompileFunc(StdCompiler *pComp);
};
const C4Rect Rect0(0,0,0,0);
const C4TargetRect TargetRect0(0,0,0,0,0,0);
// a functional class to provide density for coordinates
class C4DensityProvider
{
@ -145,22 +84,4 @@ class C4Shape: public C4Rect
void CompileFunc(StdCompiler *pComp, bool fRuntime);
};
// a bunch of rectangles
// rects NOT including pos+size-point
class C4RectList : public std::vector<C4Rect>
{
public:
void AddRect(const C4Rect &rNewRect)
{ push_back(rNewRect); }
void RemoveIndexedRect(int32_t idx)
{ if (idx<GetCount()-1) Get(idx)=Get(GetCount()-1); pop_back(); }
void Clear() { clear(); }
int32_t GetCount() const { return size(); }
C4Rect &Get(int32_t idx) { return (*this)[idx]; } // access w/o range check
void ClipByRect(const C4Rect &rClip); // split up rectangles
};
#endif // INC_C4Shape

262
src/lib/C4Rect.cpp 100644
View File

@ -0,0 +1,262 @@
/*
* OpenClonk, http://www.openclonk.org
*
* Copyright (c) 1998-2000, 2005, 2007 Matthes Bender
* Copyright (c) 2001-2007 Sven Eberhardt
* Copyright (c) 2003, 2005-2007 Peter Wortmann
* Copyright (c) 2006-2009 Günther Brammer
* Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de
*
* Portions might be copyrighted by other authors who have contributed
* to OpenClonk.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
* See isc_license.txt for full license and disclaimer.
*
* "Clonk" is a registered trademark of Matthes Bender.
* See clonk_trademark_license.txt for full license.
*/
/* Basic classes for rectangles and vertex outlines */
#include "C4Include.h"
#include "C4Rect.h"
#include "C4FacetEx.h"
void C4Rect::Default()
{
x=y=Wdt=Hgt=0;
}
void C4Rect::CompileFunc(StdCompiler *pComp)
{
pComp->Value(mkDefaultAdapt(x, 0)); pComp->Seperator();
pComp->Value(mkDefaultAdapt(y, 0)); pComp->Seperator();
pComp->Value(mkDefaultAdapt(Wdt, 0)); pComp->Seperator();
pComp->Value(mkDefaultAdapt(Hgt, 0));
}
void C4TargetRect::Default()
{
C4Rect::Default();
tx=ty=0;
}
void C4TargetRect::Set(int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt, int32_t iTX, int32_t iTY)
{
C4Rect::Set(iX,iY,iWdt,iHgt);
tx=iTX; ty=iTY;
}
bool C4TargetRect::ClipBy(C4TargetRect &rClip)
{
int32_t d;
// clip left
if ((d = x - rClip.x) < 0) { Wdt += d; x = rClip.x; } else tx += d;
// clip top
if ((d = y - rClip.y) < 0) { Hgt += d; y = rClip.y; } else ty += d;
// clip right
if ((d = (x+Wdt - rClip.x-rClip.Wdt)) > 0) Wdt -= d;
// clip bottom
if ((d = (y+Hgt - rClip.y-rClip.Hgt)) > 0) Hgt -= d;
// check validity
if (Wdt <= 0 || Hgt <= 0) return false;
// add target pos
tx += rClip.tx;
ty += rClip.ty;
// done
return true;
}
void C4TargetRect::Set(const C4TargetFacet &rSrc)
{
// copy members
x=rSrc.X; y=rSrc.Y; Wdt=rSrc.Wdt; Hgt=rSrc.Hgt; tx=rSrc.TargetX; ty=rSrc.TargetY;
}
void C4TargetRect::CompileFunc(StdCompiler *pComp)
{
C4Rect::CompileFunc(pComp); pComp->Seperator();
pComp->Value(mkDefaultAdapt(tx,0)); pComp->Seperator();
pComp->Value(mkDefaultAdapt(ty,0));
}
void C4Rect::Set(int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt)
{
x=iX; y=iY; Wdt=iWdt; Hgt=iHgt;
}
BOOL C4Rect::Overlap(C4Rect &rTarget)
{
if (x+Wdt<=rTarget.x) return FALSE;
if (x>=rTarget.x+rTarget.Wdt) return FALSE;
if (y+Hgt<=rTarget.y) return FALSE;
if (y>=rTarget.y+rTarget.Hgt) return FALSE;
return TRUE;
}
void C4Rect::Intersect(const C4Rect &r2)
{
// Narrow bounds
if (r2.x > x)
if (r2.x + r2.Wdt < x + Wdt)
{ x = r2.x; Wdt = r2.Wdt; }
else
{ Wdt -= (r2.x - x); x = r2.x; }
else
if (r2.x + r2.Wdt < x + Wdt)
Wdt = r2.x + r2.Wdt - x;
if (r2.y > y)
if (r2.y + r2.Hgt < y + Hgt)
{ y = r2.y; Hgt = r2.Hgt; }
else
{ Hgt -= (r2.y - y); y = r2.y; }
else
if (r2.y + r2.Hgt < y + Hgt)
Hgt = r2.y + r2.Hgt - y;
// Degenerated? Will happen when the two rects don't overlap
if (Wdt < 0) Wdt = 0;
if (Hgt < 0) Hgt = 0;
}
bool C4Rect::IntersectsLine(int32_t iX, int32_t iY, int32_t iX2, int32_t iY2)
{
// Easy cases first
if(Contains(iX, iY)) return true;
if(Contains(iX2, iY2)) return true;
if(iX < x && iX2 < x) return false;
if(iY < y && iY2 < y) return false;
if(iX >= x+Wdt && iX2 >= x+Wdt) return false;
if(iY >= y+Hgt && iY2 >= y+Hgt) return false;
// check some special cases
if (iX == iX2 || iY == iY2) return true;
// Check intersection left/right
int32_t iXI, iYI;
iXI = (iX < x ? x : x+Wdt);
iYI = iY + (iY2 - iY) * (iXI - iX) / (iX2 - iX);
if(iYI >= y && iYI < y+Hgt) return true;
// Check intersection up/down
iYI = (iY < y ? y : y+Hgt);
iXI = iX + (iX2 - iX) * (iYI - iY) / (iY2 - iY);
return iXI >= x && iXI < x+Wdt;
}
void C4Rect::Add(const C4Rect &r2)
{
// Null? Don't do anything
if (!r2.Wdt || !r2.Hgt) return;
if (!Wdt || !Hgt)
{
*this = r2;
return;
}
// Expand bounds
if (r2.x < x)
if (r2.x + r2.Wdt > x + Wdt)
{ x = r2.x; Wdt = r2.Wdt; }
else
{ Wdt += (x - r2.x); x = r2.x; }
else
if (r2.x + r2.Wdt > x + Wdt)
Wdt = r2.x + r2.Wdt - x;
if (r2.y < y)
if (r2.y + r2.Hgt > y + Hgt)
{ y = r2.y; Hgt = r2.Hgt; }
else
{ Hgt += (y - r2.y); y = r2.y; }
else
if (r2.y + r2.Hgt > y + Hgt)
Hgt = r2.y + r2.Hgt - y;
}
// ---- C4RectList ----
void C4RectList::ClipByRect(const C4Rect &rClip)
{
// split up all rectangles
for (int32_t i = 0; i < GetCount(); ++i)
{
C4Rect *pTarget = &Get(i);
// any overlap?
if (rClip.x+rClip.Wdt <= pTarget->x) continue;
if (rClip.y+rClip.Hgt <= pTarget->y) continue;
if (rClip.x >= pTarget->x+pTarget->Wdt) continue;
if (rClip.y >= pTarget->y+pTarget->Hgt) continue;
// okay; split up rectangle
// first split will just reduce the target rectangle size
// if more splits are done, additional rectangles need to be added
int32_t iSplitCount = 0, iOver; C4Rect rcThis(*pTarget);
// clipped by right side
if ((iOver=rcThis.x+rcThis.Wdt-rClip.x-rClip.Wdt)>0)
{
pTarget->x += pTarget->Wdt - iOver; pTarget->Wdt = iOver; rcThis.Wdt -= iOver;
++iSplitCount;
}
// clipped by obttom side
if ((iOver=rcThis.y+rcThis.Hgt-rClip.y-rClip.Hgt)>0)
{
if (iSplitCount) { AddRect(rcThis); pTarget = &Get(GetCount()-1); }
pTarget->y += pTarget->Hgt - iOver; pTarget->Hgt = iOver; rcThis.Hgt -= iOver;
++iSplitCount;
}
// clipped by left side
if ((iOver=rClip.x-rcThis.x)>0)
{
if (iSplitCount) { AddRect(rcThis); pTarget = &Get(GetCount()-1); }
pTarget->Wdt = iOver; rcThis.Wdt -= iOver; rcThis.x = rClip.x;
++iSplitCount;
}
// clipped by top side
if ((iOver=rClip.y-rcThis.y)>0)
{
if (iSplitCount) { AddRect(rcThis); pTarget = &Get(GetCount()-1); } else ++iSplitCount;
pTarget->Hgt = iOver; /* rcThis.Hgt -= iOver; rcThis.y = rClip.y; not needed, since rcThis is no longer used */
}
// nothing split? This means this rectnagle is completely contained
if (!iSplitCount)
{
// make it vanish
RemoveIndexedRect(i); --i;
}
}
// concat rectangles if possible
bool fDone = false;
while (!fDone)
{
fDone=true;
for (int32_t i = 0, cnt=GetCount(); i < cnt && fDone; ++i)
{
C4Rect &rc1 = Get(i);
for (int32_t j = i+1; j < cnt; ++j)
{
C4Rect &rc2 = Get(j);
if (rc1.y == rc2.y && rc1.Hgt == rc2.Hgt)
{
if (rc1.x + rc1.Wdt == rc2.x)
{
rc1.Wdt += rc2.Wdt; RemoveIndexedRect(j); fDone=false; break;
}
else if (rc2.x + rc2.Wdt == rc1.x)
{
rc2.Wdt += rc1.Wdt; RemoveIndexedRect(i); fDone=false; break;
}
}
else if (rc1.x == rc2.x && rc1.Wdt == rc2.Wdt)
{
if (rc1.y + rc1.Hgt == rc2.y)
{
rc1.Hgt += rc2.Hgt; RemoveIndexedRect(j); fDone=false; break;
}
else if (rc2.y + rc2.Hgt == rc1.y)
{
rc2.Hgt += rc1.Hgt; RemoveIndexedRect(i); fDone=false; break;
}
}
}
}
}
}

108
src/lib/C4Rect.h 100644
View File

@ -0,0 +1,108 @@
/*
* OpenClonk, http://www.openclonk.org
*
* Copyright (c) 1998-2000, 2007 Matthes Bender
* Copyright (c) 2001, 2003-2006 Sven Eberhardt
* Copyright (c) 2005-2006 Peter Wortmann
* Copyright (c) 2006, 2009 Günther Brammer
* Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de
*
* Portions might be copyrighted by other authors who have contributed
* to OpenClonk.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
* See isc_license.txt for full license and disclaimer.
*
* "Clonk" is a registered trademark of Matthes Bender.
* See clonk_trademark_license.txt for full license.
*/
/* Basic classes for rectangles and vertex outlines */
#ifndef INC_C4Rect
#define INC_C4Rect
#define C4D_VertexCpyPos (C4D_MaxVertex/2)
class C4Rect
{
public:
int32_t x,y,Wdt,Hgt;
public:
void Set(int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt);
void Default();
BOOL Overlap(C4Rect &rTarget);
void Intersect(const C4Rect &r2);
void Add(const C4Rect &r2);
bool operator ==(const C4Rect &r2) { return !((x-r2.x) | (y-r2.y) | (Wdt-r2.Wdt) | (Hgt-r2.Hgt)); }
bool operator !=(const C4Rect &r2) { return 0 != ((x-r2.x) | (y-r2.y) | (Wdt-r2.Wdt) | (Hgt-r2.Hgt)); }
bool Contains(int32_t iX, int32_t iY)
{ return iX>=x && iX<x+Wdt && iY>=y && iY<y+Hgt; }
bool Contains(int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt)
{ return iX>=x && iX+iWdt<x+Wdt && iY>=y && iY+iHgt<y+Hgt; }
bool Contains(const C4Rect &rect)
{ return Contains(rect.x, rect.y, rect.Wdt, rect.Hgt); }
bool IntersectsLine(int32_t iX, int32_t iY, int32_t iX2, int32_t iY2);
void Normalize()
{ if(Wdt < 0) { x+=Wdt+1; Wdt=-Wdt; } if(Hgt < 0) { y+=Hgt+1; Hgt=-Hgt; } }
void Enlarge(int32_t iBy)
{ x -= iBy; y -= iBy; Wdt += 2*iBy; Hgt += 2*iBy; }
int32_t GetMiddleX() { return x+Wdt/2; }
int32_t GetMiddleY() { return y+Hgt/2; }
int32_t GetBottom() { return y+Hgt; }
C4Rect(int32_t tx, int32_t ty, int32_t twdt, int32_t thgt) // ctor
{ x=tx; y=ty; Wdt=twdt; Hgt=thgt; }
C4Rect() { } // default ctor; doesn't initialize
C4Rect(const FLOAT_RECT &rcfOuter) // set to surround floating point rectangle
{ x=static_cast<int32_t>(rcfOuter.left); y=static_cast<int32_t>(rcfOuter.top);
Wdt=static_cast<int32_t>(ceilf(rcfOuter.right)-floorf(rcfOuter.left));
Hgt=static_cast<int32_t>(ceilf(rcfOuter.bottom)-floorf(rcfOuter.top)); }
void CompileFunc(StdCompiler *pComp);
};
class C4TargetRect: public C4Rect
{
public:
int32_t tx,ty;
public:
C4TargetRect(int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt, int32_t iTX, int32_t iTY)
: C4Rect(iX, iY, iWdt, iHgt), tx(iTX), ty(iTY) { }
C4TargetRect() { } // default ctor; doesn't initialize
void Set(int32_t iX, int32_t iY, int32_t iWdt, int32_t iHgt, int32_t iTX, int32_t iTY);
void Default();
bool ClipBy(C4TargetRect &rClip); // clip this rectangle by the given one (adding target positions) - return false if they don't overlap
void Set(const C4TargetFacet &rSrc); // copy contents from facet
void CompileFunc(StdCompiler *pComp);
};
const C4Rect Rect0(0,0,0,0);
const C4TargetRect TargetRect0(0,0,0,0,0,0);
// a bunch of rectangles
// rects NOT including pos+size-point
class C4RectList : public std::vector<C4Rect>
{
public:
void AddRect(const C4Rect &rNewRect)
{ push_back(rNewRect); }
void RemoveIndexedRect(int32_t idx)
{ if (idx<GetCount()-1) Get(idx)=Get(GetCount()-1); pop_back(); }
void Clear() { clear(); }
int32_t GetCount() const { return size(); }
C4Rect &Get(int32_t idx) { return (*this)[idx]; } // access w/o range check
void ClipByRect(const C4Rect &rClip); // split up rectangles
};
#endif // INC_C4Rect

View File

@ -25,7 +25,7 @@
#ifndef BIG_C4INCLUDE
#include <C4Random.h>
#include <C4Shape.h>
#include <C4Rect.h>
#include <C4Group.h>
#endif