//---------------------------------------------------------------------------
/*
RectFitter, demonstrates how to fit rectangles within a rectangle
Copyright (C) 2008 Richel Bilderbeek
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
// From http://www.richelbilderbeek.nl
//---------------------------------------------------------------------------
// Programmed at 02-12-2008
//---------------------------------------------------------------------------
#include <cstdlib>
#include <ctime>
#include <vcl.h>
#pragma hdrstop
#include "UnitFormRectFitter.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TFormRectFitter *FormRectFitter;
//---------------------------------------------------------------------------
__fastcall TFormRectFitter::TFormRectFitter(TComponent* Owner)
: TForm(Owner), mRects(CreateRects(10))
{
RandomizeTimer();
}
//---------------------------------------------------------------------------
void __fastcall TFormRectFitter::FormResize(TObject *Sender)
{
ImageBuffer->Picture->Bitmap->Width = ClientWidth;
ImageBuffer->Picture->Bitmap->Height = ClientHeight;
}
//---------------------------------------------------------------------------
void __fastcall TFormRectFitter::TimerMainTimer(TObject *Sender)
{
const int nRects = mRects.size();
for (int i=0; i!=nRects; ++i)
{
for (int j=0; j!=i; ++j)
{
MoveAway(mRects[i],mRects[j]);
}
}
//Draw screen
ImageBuffer->Canvas->Draw(0,0,ImageBackground->Picture->Graphic);
for (int i=0; i!=nRects; ++i)
{
ImageBuffer->Canvas->Rectangle(mRects[i]);
}
this->Canvas->Draw(0,0,ImageBuffer->Picture->Graphic);
}
//---------------------------------------------------------------------------
void TFormRectFitter::MoveAway(TRect& r1, TRect& r2)
{
int dx1 = 0;
int dy1 = 0;
int dx2 = 0;
int dy2 = 0;
//No collision
if (r1.Left < 0) ++dx1;
if (r1.Top < 0) ++dy1;
if (r1.Right > ClientWidth ) --dx1;
if (r1.Bottom > ClientHeight) --dy1;
if (r2.Left < 0) ++dx2;
if (r2.Top < 0) ++dy2;
if (r2.Right > ClientWidth ) --dx2;
if (r2.Bottom > ClientHeight) --dy2;
if (!( r1.Right < r2.Left || r1.Left > r2.Right
|| r1.Bottom < r2.Top || r1.Top > r2.Bottom))
{
if (InRect(r1.Left ,r1.Top ,r2)==true) { ++dx1; ++dy1; --dx2; --dy2;}
if (InRect(r1.Right,r1.Top ,r2)==true) { --dx1; ++dy1; ++dx2; --dy2;}
if (InRect(r1.Left ,r1.Bottom,r2)==true) { ++dx1; --dy1; --dx2; ++dy2;}
if (InRect(r1.Right,r1.Bottom,r2)==true) { --dx1; --dy1; ++dx2; ++dy2;}
//If all 4 edges are collision
if (dx1 == 0 && dy1 == 0)
{
++dx1;
++dy1;
--dx2;
--dy2;
}
}
r1.Left += dx1;
r1.Right += dx1;
r1.Top += dy1;
r1.Bottom += dy1;
r2.Left += dx2;
r2.Right += dx2;
r2.Top += dy2;
r2.Bottom += dy2;
}
//---------------------------------------------------------------------------
const bool InRect(const int x, const int y, const TRect& r)
{
return (x >= r.Left && x < r.Right && y >= r.Top && y < r.Bottom);
}
//---------------------------------------------------------------------------
void __fastcall TFormRectFitter::FormKeyDown(TObject *Sender, WORD &Key,
TShiftState Shift)
{
mRects = CreateRects(5 + ((std::rand() >> 4) % 20));
}
//---------------------------------------------------------------------------
const std::vector<TRect> TFormRectFitter::CreateRects(const int n)
{
std::vector<TRect> v;
for (int i=0; i!=n; ++i)
{
TRect rect;
const int x1 = std::rand() % (ClientWidth / 2);
const int x2 = std::rand() % (ClientWidth / 2);
if (x1 == x2) { --i; continue; }
rect.Left = (x1 < x2 ? x1 : x2);
rect.Right = (x1 > x2 ? x1 : x2);
const int y1 = std::rand() % (ClientWidth / 2);
const int y2 = std::rand() % (ClientWidth / 2);
if (y1 == y2) { --i; continue; }
rect.Top = (y1 < y2 ? y1 : y2);
rect.Bottom = (y1 > y2 ? y1 : y2);
v.push_back(rect);
}
return v;
}
//---------------------------------------------------------------------------
//From http://www.richelbilderbeek.nl/CppRandomizeTimer.htm
void RandomizeTimer()
{
std::srand(std::time(0));
}
//---------------------------------------------------------------------------
|